summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore92
-rw-r--r--Makefile79
-rwxr-xr-xclient/dailylogin.py86
-rwxr-xr-xclient/minimap-dyecmd.py18
-rwxr-xr-xclient/minimap-dyecmd.sh261
-rw-r--r--client/minimap-override/008-3-0.pngbin0 -> 10671 bytes
-rwxr-xr-xclient/minimap-render.py165
-rwxr-xr-xclient/weapons.py89
-rw-r--r--hercules/.gitignore12
-rw-r--r--hercules/code/__init__.py0
-rw-r--r--hercules/code/clienttoserver/__init__.py0
-rw-r--r--hercules/code/clienttoserver/maps.py190
-rw-r--r--hercules/code/configutils.py51
-rw-r--r--hercules/code/fileutils.py86
-rw-r--r--hercules/code/server/__init__.py0
-rw-r--r--hercules/code/server/account.py63
-rw-r--r--hercules/code/server/accreg.py52
-rw-r--r--hercules/code/server/db/__init__.py0
-rw-r--r--hercules/code/server/db/char.py187
-rw-r--r--hercules/code/server/db/charregnumdb.py34
-rw-r--r--hercules/code/server/db/inventory.py44
-rw-r--r--hercules/code/server/db/skill.py31
-rw-r--r--hercules/code/server/dbitem.py7
-rw-r--r--hercules/code/server/dbskill.py7
-rw-r--r--hercules/code/server/dbuser.py7
-rw-r--r--hercules/code/server/evol/__init__.py0
-rw-r--r--hercules/code/server/evol/athena.py207
-rw-r--r--hercules/code/server/evol/consts.py49
-rw-r--r--hercules/code/server/evol/itemdb.py104
-rw-r--r--hercules/code/server/evol/main.py43
-rw-r--r--hercules/code/server/evol/mobdb.py89
-rw-r--r--hercules/code/server/evol/mobskilldb.py50
-rw-r--r--hercules/code/server/evol/npcs.py281
-rw-r--r--hercules/code/server/maps.py43
-rw-r--r--hercules/code/server/party.py80
-rw-r--r--hercules/code/server/questsdb.py33
-rw-r--r--hercules/code/server/storage.py81
-rw-r--r--hercules/code/server/tmw/__init__.py0
-rw-r--r--hercules/code/server/tmw/athena.py207
-rw-r--r--hercules/code/server/tmw/consts.py129
-rw-r--r--hercules/code/server/tmw/itemdb.py291
-rw-r--r--hercules/code/server/tmw/main.py49
-rw-r--r--hercules/code/server/tmw/mobdb.py173
-rw-r--r--hercules/code/server/tmw/mobskilldb.py55
-rw-r--r--hercules/code/server/tmw/npcs.py878
-rw-r--r--hercules/code/server/utils.py12
-rw-r--r--hercules/code/servertoclient/__init__.py0
-rw-r--r--hercules/code/servertoclient/groups.py185
-rw-r--r--hercules/code/servertoclient/homunculuses.py31
-rw-r--r--hercules/code/servertoclient/items.py138
-rw-r--r--hercules/code/servertoclient/luas.py51
-rw-r--r--hercules/code/servertoclient/maps.py48
-rw-r--r--hercules/code/servertoclient/mercenaries.py31
-rw-r--r--hercules/code/servertoclient/monsters.py43
-rw-r--r--hercules/code/servertoclient/npcs.py29
-rw-r--r--hercules/code/servertoclient/pets.py31
-rw-r--r--hercules/code/servertoclient/quests.py39
-rw-r--r--hercules/code/servertoclient/skills.py33
-rw-r--r--hercules/code/servertoclient/sprites.py467
-rw-r--r--hercules/code/serverutils.py12
-rw-r--r--hercules/code/stringutils.py62
-rw-r--r--hercules/code/tileutils.py48
-rwxr-xr-xhercules/convert_db.py25
-rwxr-xr-xhercules/convert_groups.py9
-rwxr-xr-xhercules/convert_mapcache_to_tmx.py24
-rwxr-xr-xhercules/convert_server.py30
-rwxr-xr-xhercules/convert_server_to_client.py29
-rwxr-xr-xhercules/convert_tmx_to_mapcache.py9
-rwxr-xr-xhercules/extract_mapcache.py24
-rwxr-xr-xhercules/import_newdb.sh24
-rwxr-xr-xhercules/list_mapcache.py24
-rw-r--r--hercules/templates/acc_reg_num_db.sql11
-rw-r--r--hercules/templates/char.sql72
-rw-r--r--hercules/templates/char_reg_num_db.sql11
-rw-r--r--hercules/templates/collision.pngbin0 -> 275 bytes
-rw-r--r--hercules/templates/constants.tpl45
-rw-r--r--hercules/templates/group.tpl10
-rw-r--r--hercules/templates/groups.xml7
-rw-r--r--hercules/templates/homunculus.tpl3
-rw-r--r--hercules/templates/homunculuses.xml6
-rw-r--r--hercules/templates/inventory.sql23
-rw-r--r--hercules/templates/item.tpl7
-rw-r--r--hercules/templates/item_db.tpl63
-rw-r--r--hercules/templates/items.xml148
-rw-r--r--hercules/templates/login.sql25
-rw-r--r--hercules/templates/mercenaries.xml6
-rw-r--r--hercules/templates/mercenary.tpl3
-rw-r--r--hercules/templates/mob_db.tpl101
-rw-r--r--hercules/templates/mob_skill_db.tpl56
-rw-r--r--hercules/templates/monster.tpl3
-rw-r--r--hercules/templates/monsters.xml11
-rw-r--r--hercules/templates/npc.tpl3
-rw-r--r--hercules/templates/npcs.xml11
-rw-r--r--hercules/templates/party.sql12
-rw-r--r--hercules/templates/pet.tpl3
-rw-r--r--hercules/templates/pets.xml6
-rw-r--r--hercules/templates/quest.tpl5
-rw-r--r--hercules/templates/quest_db.tpl5
-rw-r--r--hercules/templates/quests.xml6
-rw-r--r--hercules/templates/skill.sql10
-rw-r--r--hercules/templates/skill.tpl1
-rw-r--r--hercules/templates/skills.xml15
-rw-r--r--hercules/templates/sprite.xml21
-rw-r--r--hercules/templates/storage.sql22
-rw-r--r--hercules/templates/template.tmx25
-rw-r--r--hercules/templates/tileset.pngbin0 -> 3550 bytes
-rwxr-xr-xhercules/tmx_converter.py550
-rwxr-xr-xherculeswrapper/char.sh7
-rw-r--r--herculeswrapper/herc-map-wrapper-config.example77
-rw-r--r--herculeswrapper/include.sh287
-rwxr-xr-xherculeswrapper/login.sh7
-rwxr-xr-xherculeswrapper/map.sh102
-rwxr-xr-xlang/fetch.py48
-rw-r--r--lang/in/.gitignore1
-rw-r--r--lang/out/.gitignore1
-rw-r--r--lang/serverdata.pot9906
-rwxr-xr-xlang/updatelang.py399
-rw-r--r--lang_client/clientdata-beta.pot13
-rw-r--r--lang_client/clientdata-dict.pot0
-rw-r--r--lang_client/clientdata.pot1687
-rwxr-xr-xlang_client/createpots.sh50
-rwxr-xr-xlang_client/fetch.py58
-rw-r--r--lang_client/its/avatars.xml8
-rw-r--r--lang_client/its/clans.xml8
-rw-r--r--lang_client/its/deadmessages.xml6
-rw-r--r--lang_client/its/emotes.xml8
-rw-r--r--lang_client/its/groups.xml9
-rw-r--r--lang_client/its/homunculuses.xml8
-rw-r--r--lang_client/its/itemcolors.xml7
-rw-r--r--lang_client/its/itemfields.xml8
-rw-r--r--lang_client/its/items.xml18
-rw-r--r--lang_client/its/mercenaries.xml8
-rw-r--r--lang_client/its/monsters.xml8
-rw-r--r--lang_client/its/npcdialogs.xml8
-rw-r--r--lang_client/its/npcs.xml8
-rw-r--r--lang_client/its/pets.xml8
-rw-r--r--lang_client/its/skills.xml10
-rw-r--r--lang_client/its/skillunits.xml8
-rw-r--r--lang_client/its/stats.xml11
-rw-r--r--lang_client/its/status-effects.xml8
-rw-r--r--lang_client/its/texts.xml7
-rw-r--r--lang_client/its/tmx.xml8
-rwxr-xr-xlang_client/processtmx.sh6
-rw-r--r--localserver/.gitignore1
-rw-r--r--localserver/README14
-rwxr-xr-xlocalserver/build.sh6
-rwxr-xr-xlocalserver/buildasan.sh5
-rwxr-xr-xlocalserver/checktime.sh9
-rwxr-xr-xlocalserver/clean.sh6
-rw-r--r--localserver/conf/battle.conf32
-rw-r--r--localserver/conf/char-server.conf31
-rw-r--r--localserver/conf/constants.conf34
-rw-r--r--localserver/conf/inter-server.conf32
-rw-r--r--localserver/conf/login-server.conf32
-rw-r--r--localserver/conf/logs.conf32
-rw-r--r--localserver/conf/map-server.conf32
-rw-r--r--localserver/conf/msg_conf.txt0
-rw-r--r--localserver/conf/ports.conf8
-rw-r--r--localserver/conf/script.conf32
-rw-r--r--localserver/conf/socket.conf32
-rw-r--r--localserver/conf/sql_connection.conf52
-rwxr-xr-xlocalserver/givegm.sh8
-rwxr-xr-xlocalserver/initdb.sh26
-rwxr-xr-xlocalserver/installconfigs.sh12
-rw-r--r--localserver/npc/motd-debug-text.txt4
-rwxr-xr-xlocalserver/updateconfigs.sh36
-rwxr-xr-xlocalserver/updatedb.sh112
-rwxr-xr-xupdate/addmods.sh32
-rw-r--r--update/adler32.c79
-rw-r--r--update/commit.txt1
-rw-r--r--update/commit_old.txt1
-rwxr-xr-xupdate/createnew.sh36
-rw-r--r--update/evol_news.txt324
-rw-r--r--update/musiccommit.txt1
-rwxr-xr-xupdate/musicnew.sh31
-rw-r--r--update/news.txt30
-rwxr-xr-xupdate/update.sh39
-rwxr-xr-xupdate/update_music.sh40
178 files changed, 21190 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..afc3351
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,92 @@
+# temp files
+*.xml~
+*.py~
+*.txt~
+*.conf~
+*deploy.sh
+*~
+._*
+
+# updates
+update/files
+update/upload
+!update/adler32.c
+update/adler32
+update/files/Bugfix-*
+update/save*
+
+hercules_update/files
+hercules_update/upload
+!hercules_update/adler32.c
+hercules_update/adler32
+
+# saedit
+saedit/saedit
+saedit/make.log
+
+# langs
+lang/tx
+lang/new
+login.txt
+password.txt
+
+# lang client
+lang_client/tmp
+lang_client/pot
+lang_client/dict
+
+# tx
+tx
+
+# temp files
+*.o
+localserver/.~*
+
+# dyecmd
+dyecmd/dyecmd
+dyecmd/src/dyecmd
+dyecmd/src/CMakeFiles/
+dyecmd/src/Makefile
+dyecmd/src/cmake_install.cmake
+
+# testxml
+testxml/errors.txt
+
+# gitlab merger
+herculeswrapper/herc-map-wrapper-config
+
+# license check
+licensecheck/npcs.txt
+
+# wiki
+wiki/Items.md
+wiki/Monsters.md
+wiki/*.html
+wiki/*.txt
+
+# web
+1index.bin
+backup.bin
+web/po/*
+
+# Proccessed other server data
+hercules/data*
+hercules/osd*
+hercules/old*
+
+# Diffs and Patches related files
+*.diff
+*.patch
+*.orig
+*.rej
+
+# Jesusalva's personal stuff
+misc/*
+update/*back*
+lang/in/JSave
+
+# Beta Server
+localserver/beta.patch
+localserver/beta.patch2
+manaplus/*
+
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..4e9e5a8
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,79 @@
+XSLTPROC = xsltproc
+
+all:
+ @echo "Current makes:"
+ @echo "contrib - makes contributors list for wiki and client-data"
+ @echo "testxml - performs a minimal XML test"
+ @echo "wiki - makes wiki automated databases"
+ @echo "maps - makes server-data information"
+ @echo "update - makes update and propagate web information (untested)"
+ @echo "news - propagate web information"
+ @echo "translation - fetches Transifex translations for server, and updates both."
+ @echo "client - generate weapons.xml and daily.xml"
+ @echo "full - make contrib + wiki + translation + client + update + news"
+
+contrib:
+ cd contrib_xsl ; make
+ @echo "Please commit the result on wiki and clientdata."
+
+.PHONY: testxml
+testxml:
+ cd testxml ; ./testxml.py silent |grep -v "Checking"
+
+.PHONY: wiki
+wiki:
+ cd wiki ; ./wikigen.py
+ cd wiki ; mv *.md ../../wiki/
+ @echo "Wiki files updated, please commit the result on wiki."
+
+.PHONY: maps
+maps:
+ cd hercules ; ./tmx_converter.py ../../client-data/ ../../server-data
+ cd hercules ; ./convert_tmx_to_mapcache.py
+ @echo "Please commit the result on serverdata."
+
+.PHONY: update
+update:
+ @cd ../web ; echo "Checking for web/ folder..." # check if web directory exists
+ cd update ; ./update.sh
+ cd wiki ; ./elegen.py ; mv EleMonsters.html ../../web/Monsters.html
+ cd web ; ./deploy.sh
+ @echo "Update deployed, please move upload/ and commit result on web."
+ @echo "Don't forget to make translations, client, news and wiki too!"
+
+translation:
+ @echo "Fetching server translations, ensure lang/login.txt and lang/password.txt exists..."
+ cd lang/ ; ./fetch.py
+ @echo "Updating server translations and preparing for pull..."
+ cd lang/ ; ./updatelang.py
+ @echo "Fetching client translations, ensure lang/login.txt and lang/password.txt exists..."
+ cd lang_client/ ; ./fetch.py
+ @echo "Updating client translations and preparing for pull..."
+ cd lang_client/ ; ./createpots.sh
+ @echo "Translations updated, please commit result on server-data, client-data and tools."
+
+.PHONY: news
+news:
+ @cd ../web ; echo "Checking for web/ folder..." # check if web directory exists
+ cd web ; ./deploy.sh
+ @echo "News updated, please commit result on web."
+
+.PHONY: client
+client:
+ @cd client ; ./weapons.py
+ @cd client ; mv weapons.tmp ../../client-data/weapons.xml
+ @cd client ; ./minimap-render.py all
+ @cd client ; ./minimap-dyecmd.py ; ./minimap-dyecmd.sh
+ cp client/minimap-override/* ../client-data/graphics/minimaps/
+ @echo "XML files and minimaps updated, please commit result on client-data."
+
+.PHONY: full
+full:
+ @echo "full - make contrib + wiki + translation + client + update + news"
+ make contrib
+ make wiki
+ make translation
+ make client
+ make update
+ make news
+
diff --git a/client/dailylogin.py b/client/dailylogin.py
new file mode 100755
index 0000000..fc9296f
--- /dev/null
+++ b/client/dailylogin.py
@@ -0,0 +1,86 @@
+#!/usr/bin/python2.7
+
+# Setup
+x=y=0
+i=j=0
+
+# Functions
+def headers(val):
+ return '\n\t<dialog name="daily_%d" hideText="true">\n\t\t<menu>\n\t\t\t<text x="45" y="0" width="310" height="30" text="##BDaily Login Rewards##b" />\n <button x="157" y="280" name="Claim" value="Ok" />\n\n' % val
+
+def tail():
+ return '\n\t\t</menu>\n\t</dialog>\n'
+
+def override_check(vl, over, text1, text2):
+ global j
+ if not over:
+ j=0
+ return '\t\t\t<image %s image="graphics/images/%s.png" />\n' % (text1, text2)
+ else:
+ j+=1
+ if (j == vl):
+ return '\t\t\t<image %s image="graphics/images/done.png" />\n' % (text1)
+ elif (j < vl):
+ return '\t\t\t<image %s image="graphics/images/ok.png" />\n' % (text1)
+ else:
+ return ""
+
+def spammer(val, override=False):
+ bf=""
+
+ bf+=override_check(val, override, 'x="35" y="35"', 'jexp')
+ bf+=override_check(val, override, 'x="70" y="35"', 'bexp')
+ bf+=override_check(val, override, 'x="105" y="35"', 'sc')
+ bf+=override_check(val, override, 'x="140" y="35"', 'jexp')
+ bf+=override_check(val, override, 'x="175" y="35"', 'bexp')
+
+ bf+=override_check(val, override, 'x="35" y="70"', 'gp')
+ bf+=override_check(val, override, 'x="70" y="70"', 'sc')
+ bf+=override_check(val, override, 'x="105" y="70"', 'bexp')
+ bf+=override_check(val, override, 'x="140" y="70"', 'gp')
+ bf+=override_check(val, override, 'x="175" y="70"', 'jexp')
+
+ bf+=override_check(val, override, 'x="35" y="105"', 'bexp')
+ bf+=override_check(val, override, 'x="70" y="105"', 'gp')
+ bf+=override_check(val, override, 'x="105" y="105"', 'jexp')
+ bf+=override_check(val, override, 'x="140" y="105"', 'gift')
+ bf+=override_check(val, override, 'x="175" y="105"', 'gp')
+
+ bf+=override_check(val, override, 'x="35" y="140"', 'jexp')
+ bf+=override_check(val, override, 'x="70" y="140"', 'bexp')
+ bf+=override_check(val, override, 'x="105" y="140"', 'gp')
+ bf+=override_check(val, override, 'x="140" y="140"', 'jexp')
+ bf+=override_check(val, override, 'x="175" y="140"', 'bexp')
+
+ bf+=override_check(val, override, 'x="35" y="175"', 'gift')
+ bf+=override_check(val, override, 'x="70" y="175"', 'jexp')
+ bf+=override_check(val, override, 'x="105" y="175"', 'bexp')
+ bf+=override_check(val, override, 'x="140" y="175"', 'gp')
+ bf+=override_check(val, override, 'x="175" y="175"', 'jexp')
+
+ bf+=override_check(val, override, 'x="35" y="210"', 'bexp')
+ bf+=override_check(val, override, 'x="70" y="210"', 'gp')
+ bf+=override_check(val, override, 'x="105" y="210"', 'last')
+ bf+=override_check(val, override, 'x="140" y="210"', 'sc')
+ bf+=override_check(val, override, 'x="175" y="210"', 'sc')
+
+ bf+=override_check(val, override, 'x="35" y="245"', 'sc')
+
+ return bf
+
+# Begin
+f=open("daily.tmp", "w")
+
+f.write('<?xml version="1.0" encoding="utf-8"?>\n<!-- This file is generated automatically, editing it will have no effect.\n (C) Jesusalva, 2019 -->\n<dialogs>')
+
+while (i < 31):
+ i+=1
+ f.write(headers(i))
+ f.write(spammer(i, False))
+ f.write('\n\t\t\t<image x="245" y="52" image="graphics/images/final.png" />\n\n\t\t\t<!-- Complete -->\n')
+ f.write(spammer(i, True))
+ f.write(tail())
+
+f.write('\n</dialogs>')
+f.close()
+
diff --git a/client/minimap-dyecmd.py b/client/minimap-dyecmd.py
new file mode 100755
index 0000000..8f3e0c7
--- /dev/null
+++ b/client/minimap-dyecmd.py
@@ -0,0 +1,18 @@
+#!/usr/bin/env python
+#-*- coding:utf-8 -*-
+
+import os
+f=open("minimap-dyecmd.sh", "w");
+CLIENT_DATA_ROOT="../../client-data"
+
+map_names = sorted([os.path.splitext(p)[0] for p in os.listdir(os.path.join(CLIENT_DATA_ROOT, u'graphics', u'minimaps'))])
+
+f.write('cd '+os.path.join(CLIENT_DATA_ROOT, u'graphics', u'minimaps')+'\n')
+for c in map_names:
+ if os.path.exists(os.path.join(CLIENT_DATA_ROOT, u'graphics', u'minimaps', c+u'.png')):
+ i=c+u'.png'
+ f.write("dyecmd %s tmp ; mv tmp %s\n" % (i, i))
+ f.write("echo \"Converted "+i+" successfully.\"\n")
+
+#f.write("git checkout -- minimap-dyecmd.sh")
+f.close()
diff --git a/client/minimap-dyecmd.sh b/client/minimap-dyecmd.sh
new file mode 100755
index 0000000..4c3f1e0
--- /dev/null
+++ b/client/minimap-dyecmd.sh
@@ -0,0 +1,261 @@
+cd ../../client-data/graphics/minimaps
+dyecmd 000-1.png tmp ; mv tmp 000-1.png
+echo "Converted 000-1.png successfully."
+dyecmd 001-1.png tmp ; mv tmp 001-1.png
+echo "Converted 001-1.png successfully."
+dyecmd 001-2.png tmp ; mv tmp 001-2.png
+echo "Converted 001-2.png successfully."
+dyecmd 001-3.png tmp ; mv tmp 001-3.png
+echo "Converted 001-3.png successfully."
+dyecmd 002-1.png tmp ; mv tmp 002-1.png
+echo "Converted 002-1.png successfully."
+dyecmd 002-2.png tmp ; mv tmp 002-2.png
+echo "Converted 002-2.png successfully."
+dyecmd 002-3.png tmp ; mv tmp 002-3.png
+echo "Converted 002-3.png successfully."
+dyecmd 002-4.png tmp ; mv tmp 002-4.png
+echo "Converted 002-4.png successfully."
+dyecmd 002-5.png tmp ; mv tmp 002-5.png
+echo "Converted 002-5.png successfully."
+dyecmd 003-1.png tmp ; mv tmp 003-1.png
+echo "Converted 003-1.png successfully."
+dyecmd 003-4.png tmp ; mv tmp 003-4.png
+echo "Converted 003-4.png successfully."
+dyecmd 004-1.png tmp ; mv tmp 004-1.png
+echo "Converted 004-1.png successfully."
+dyecmd 004-3.png tmp ; mv tmp 004-3.png
+echo "Converted 004-3.png successfully."
+dyecmd 004-4.png tmp ; mv tmp 004-4.png
+echo "Converted 004-4.png successfully."
+dyecmd 004-5.png tmp ; mv tmp 004-5.png
+echo "Converted 004-5.png successfully."
+dyecmd 005-3.png tmp ; mv tmp 005-3.png
+echo "Converted 005-3.png successfully."
+dyecmd 006-1.png tmp ; mv tmp 006-1.png
+echo "Converted 006-1.png successfully."
+dyecmd 006-2.png tmp ; mv tmp 006-2.png
+echo "Converted 006-2.png successfully."
+dyecmd 006-3.png tmp ; mv tmp 006-3.png
+echo "Converted 006-3.png successfully."
+dyecmd 007-1.png tmp ; mv tmp 007-1.png
+echo "Converted 007-1.png successfully."
+dyecmd 007-2.png tmp ; mv tmp 007-2.png
+echo "Converted 007-2.png successfully."
+dyecmd 008-1.png tmp ; mv tmp 008-1.png
+echo "Converted 008-1.png successfully."
+dyecmd 009-1.png tmp ; mv tmp 009-1.png
+echo "Converted 009-1.png successfully."
+dyecmd 009-2.png tmp ; mv tmp 009-2.png
+echo "Converted 009-2.png successfully."
+dyecmd 009-3.png tmp ; mv tmp 009-3.png
+echo "Converted 009-3.png successfully."
+dyecmd 009-4.png tmp ; mv tmp 009-4.png
+echo "Converted 009-4.png successfully."
+dyecmd 009-5.png tmp ; mv tmp 009-5.png
+echo "Converted 009-5.png successfully."
+dyecmd 009-6.png tmp ; mv tmp 009-6.png
+echo "Converted 009-6.png successfully."
+dyecmd 009-7.png tmp ; mv tmp 009-7.png
+echo "Converted 009-7.png successfully."
+dyecmd 009-8.png tmp ; mv tmp 009-8.png
+echo "Converted 009-8.png successfully."
+dyecmd 010-1.png tmp ; mv tmp 010-1.png
+echo "Converted 010-1.png successfully."
+dyecmd 010-2.png tmp ; mv tmp 010-2.png
+echo "Converted 010-2.png successfully."
+dyecmd 011-1.png tmp ; mv tmp 011-1.png
+echo "Converted 011-1.png successfully."
+dyecmd 011-3.png tmp ; mv tmp 011-3.png
+echo "Converted 011-3.png successfully."
+dyecmd 011-4.png tmp ; mv tmp 011-4.png
+echo "Converted 011-4.png successfully."
+dyecmd 011-6.png tmp ; mv tmp 011-6.png
+echo "Converted 011-6.png successfully."
+dyecmd 012-1.png tmp ; mv tmp 012-1.png
+echo "Converted 012-1.png successfully."
+dyecmd 012-3.png tmp ; mv tmp 012-3.png
+echo "Converted 012-3.png successfully."
+dyecmd 012-4.png tmp ; mv tmp 012-4.png
+echo "Converted 012-4.png successfully."
+dyecmd 013-1.png tmp ; mv tmp 013-1.png
+echo "Converted 013-1.png successfully."
+dyecmd 013-2.png tmp ; mv tmp 013-2.png
+echo "Converted 013-2.png successfully."
+dyecmd 013-3.png tmp ; mv tmp 013-3.png
+echo "Converted 013-3.png successfully."
+dyecmd 014-1.png tmp ; mv tmp 014-1.png
+echo "Converted 014-1.png successfully."
+dyecmd 014-3.png tmp ; mv tmp 014-3.png
+echo "Converted 014-3.png successfully."
+dyecmd 015-1.png tmp ; mv tmp 015-1.png
+echo "Converted 015-1.png successfully."
+dyecmd 015-3.png tmp ; mv tmp 015-3.png
+echo "Converted 015-3.png successfully."
+dyecmd 016-1.png tmp ; mv tmp 016-1.png
+echo "Converted 016-1.png successfully."
+dyecmd 016-2.png tmp ; mv tmp 016-2.png
+echo "Converted 016-2.png successfully."
+dyecmd 017-1.png tmp ; mv tmp 017-1.png
+echo "Converted 017-1.png successfully."
+dyecmd 017-2.png tmp ; mv tmp 017-2.png
+echo "Converted 017-2.png successfully."
+dyecmd 017-3.png tmp ; mv tmp 017-3.png
+echo "Converted 017-3.png successfully."
+dyecmd 017-4.png tmp ; mv tmp 017-4.png
+echo "Converted 017-4.png successfully."
+dyecmd 017-9.png tmp ; mv tmp 017-9.png
+echo "Converted 017-9.png successfully."
+dyecmd 018-1.png tmp ; mv tmp 018-1.png
+echo "Converted 018-1.png successfully."
+dyecmd 018-2.png tmp ; mv tmp 018-2.png
+echo "Converted 018-2.png successfully."
+dyecmd 018-3.png tmp ; mv tmp 018-3.png
+echo "Converted 018-3.png successfully."
+dyecmd 019-1.png tmp ; mv tmp 019-1.png
+echo "Converted 019-1.png successfully."
+dyecmd 019-3.png tmp ; mv tmp 019-3.png
+echo "Converted 019-3.png successfully."
+dyecmd 019-4.png tmp ; mv tmp 019-4.png
+echo "Converted 019-4.png successfully."
+dyecmd 020-1.png tmp ; mv tmp 020-1.png
+echo "Converted 020-1.png successfully."
+dyecmd 020-2.png tmp ; mv tmp 020-2.png
+echo "Converted 020-2.png successfully."
+dyecmd 020-3.png tmp ; mv tmp 020-3.png
+echo "Converted 020-3.png successfully."
+dyecmd 021-3.png tmp ; mv tmp 021-3.png
+echo "Converted 021-3.png successfully."
+dyecmd 023-1.png tmp ; mv tmp 023-1.png
+echo "Converted 023-1.png successfully."
+dyecmd 023-2.png tmp ; mv tmp 023-2.png
+echo "Converted 023-2.png successfully."
+dyecmd 023-3.png tmp ; mv tmp 023-3.png
+echo "Converted 023-3.png successfully."
+dyecmd 025-1.png tmp ; mv tmp 025-1.png
+echo "Converted 025-1.png successfully."
+dyecmd 025-3.png tmp ; mv tmp 025-3.png
+echo "Converted 025-3.png successfully."
+dyecmd 025-4.png tmp ; mv tmp 025-4.png
+echo "Converted 025-4.png successfully."
+dyecmd 026-1.png tmp ; mv tmp 026-1.png
+echo "Converted 026-1.png successfully."
+dyecmd 026-2.png tmp ; mv tmp 026-2.png
+echo "Converted 026-2.png successfully."
+dyecmd 027-1.png tmp ; mv tmp 027-1.png
+echo "Converted 027-1.png successfully."
+dyecmd 027-2.png tmp ; mv tmp 027-2.png
+echo "Converted 027-2.png successfully."
+dyecmd 027-3.png tmp ; mv tmp 027-3.png
+echo "Converted 027-3.png successfully."
+dyecmd 027-4.png tmp ; mv tmp 027-4.png
+echo "Converted 027-4.png successfully."
+dyecmd 027-5.png tmp ; mv tmp 027-5.png
+echo "Converted 027-5.png successfully."
+dyecmd 027-6.png tmp ; mv tmp 027-6.png
+echo "Converted 027-6.png successfully."
+dyecmd 027-7.png tmp ; mv tmp 027-7.png
+echo "Converted 027-7.png successfully."
+dyecmd 027-8.png tmp ; mv tmp 027-8.png
+echo "Converted 027-8.png successfully."
+dyecmd 028-1.png tmp ; mv tmp 028-1.png
+echo "Converted 028-1.png successfully."
+dyecmd 028-3.png tmp ; mv tmp 028-3.png
+echo "Converted 028-3.png successfully."
+dyecmd 029-1.png tmp ; mv tmp 029-1.png
+echo "Converted 029-1.png successfully."
+dyecmd 029-2.png tmp ; mv tmp 029-2.png
+echo "Converted 029-2.png successfully."
+dyecmd 029-3.png tmp ; mv tmp 029-3.png
+echo "Converted 029-3.png successfully."
+dyecmd 029-4.png tmp ; mv tmp 029-4.png
+echo "Converted 029-4.png successfully."
+dyecmd 030-1.png tmp ; mv tmp 030-1.png
+echo "Converted 030-1.png successfully."
+dyecmd 030-2.png tmp ; mv tmp 030-2.png
+echo "Converted 030-2.png successfully."
+dyecmd 030-3.png tmp ; mv tmp 030-3.png
+echo "Converted 030-3.png successfully."
+dyecmd 030-4.png tmp ; mv tmp 030-4.png
+echo "Converted 030-4.png successfully."
+dyecmd 031-1.png tmp ; mv tmp 031-1.png
+echo "Converted 031-1.png successfully."
+dyecmd 031-2.png tmp ; mv tmp 031-2.png
+echo "Converted 031-2.png successfully."
+dyecmd 031-3.png tmp ; mv tmp 031-3.png
+echo "Converted 031-3.png successfully."
+dyecmd 031-4.png tmp ; mv tmp 031-4.png
+echo "Converted 031-4.png successfully."
+dyecmd 032-3.png tmp ; mv tmp 032-3.png
+echo "Converted 032-3.png successfully."
+dyecmd 033-1.png tmp ; mv tmp 033-1.png
+echo "Converted 033-1.png successfully."
+dyecmd 034-1.png tmp ; mv tmp 034-1.png
+echo "Converted 034-1.png successfully."
+dyecmd 034-2.png tmp ; mv tmp 034-2.png
+echo "Converted 034-2.png successfully."
+dyecmd 035-2.png tmp ; mv tmp 035-2.png
+echo "Converted 035-2.png successfully."
+dyecmd 036-2.png tmp ; mv tmp 036-2.png
+echo "Converted 036-2.png successfully."
+dyecmd 041-1.png tmp ; mv tmp 041-1.png
+echo "Converted 041-1.png successfully."
+dyecmd 042-1.png tmp ; mv tmp 042-1.png
+echo "Converted 042-1.png successfully."
+dyecmd 043-1.png tmp ; mv tmp 043-1.png
+echo "Converted 043-1.png successfully."
+dyecmd 043-3.png tmp ; mv tmp 043-3.png
+echo "Converted 043-3.png successfully."
+dyecmd 043-4.png tmp ; mv tmp 043-4.png
+echo "Converted 043-4.png successfully."
+dyecmd 045-1.png tmp ; mv tmp 045-1.png
+echo "Converted 045-1.png successfully."
+dyecmd 046-1.png tmp ; mv tmp 046-1.png
+echo "Converted 046-1.png successfully."
+dyecmd 046-3.png tmp ; mv tmp 046-3.png
+echo "Converted 046-3.png successfully."
+dyecmd 047-1.png tmp ; mv tmp 047-1.png
+echo "Converted 047-1.png successfully."
+dyecmd 047-3.png tmp ; mv tmp 047-3.png
+echo "Converted 047-3.png successfully."
+dyecmd 048-2.png tmp ; mv tmp 048-2.png
+echo "Converted 048-2.png successfully."
+dyecmd 051-1.png tmp ; mv tmp 051-1.png
+echo "Converted 051-1.png successfully."
+dyecmd 051-3.png tmp ; mv tmp 051-3.png
+echo "Converted 051-3.png successfully."
+dyecmd 052-1.png tmp ; mv tmp 052-1.png
+echo "Converted 052-1.png successfully."
+dyecmd 052-2.png tmp ; mv tmp 052-2.png
+echo "Converted 052-2.png successfully."
+dyecmd 055-1.png tmp ; mv tmp 055-1.png
+echo "Converted 055-1.png successfully."
+dyecmd 055-3.png tmp ; mv tmp 055-3.png
+echo "Converted 055-3.png successfully."
+dyecmd 056-2.png tmp ; mv tmp 056-2.png
+echo "Converted 056-2.png successfully."
+dyecmd 057-1.png tmp ; mv tmp 057-1.png
+echo "Converted 057-1.png successfully."
+dyecmd 069-2.png tmp ; mv tmp 069-2.png
+echo "Converted 069-2.png successfully."
+dyecmd 070-1.png tmp ; mv tmp 070-1.png
+echo "Converted 070-1.png successfully."
+dyecmd 070-3.png tmp ; mv tmp 070-3.png
+echo "Converted 070-3.png successfully."
+dyecmd 099-1.png tmp ; mv tmp 099-1.png
+echo "Converted 099-1.png successfully."
+dyecmd 099-2.png tmp ; mv tmp 099-2.png
+echo "Converted 099-2.png successfully."
+dyecmd 099-3.png tmp ; mv tmp 099-3.png
+echo "Converted 099-3.png successfully."
+dyecmd 099-4.png tmp ; mv tmp 099-4.png
+echo "Converted 099-4.png successfully."
+dyecmd 099-5.png tmp ; mv tmp 099-5.png
+echo "Converted 099-5.png successfully."
+dyecmd 099-6.png tmp ; mv tmp 099-6.png
+echo "Converted 099-6.png successfully."
+dyecmd 099-7.png tmp ; mv tmp 099-7.png
+echo "Converted 099-7.png successfully."
+dyecmd 099-8.png tmp ; mv tmp 099-8.png
+echo "Converted 099-8.png successfully."
+dyecmd botcheck.png tmp ; mv tmp botcheck.png
+echo "Converted botcheck.png successfully."
diff --git a/client/minimap-override/008-3-0.png b/client/minimap-override/008-3-0.png
new file mode 100644
index 0000000..fa94222
--- /dev/null
+++ b/client/minimap-override/008-3-0.png
Binary files differ
diff --git a/client/minimap-render.py b/client/minimap-render.py
new file mode 100755
index 0000000..716e9e3
--- /dev/null
+++ b/client/minimap-render.py
@@ -0,0 +1,165 @@
+#!/usr/bin/env python
+#-*- coding:utf-8 -*-
+
+import sys
+import os
+import subprocess
+import tempfile
+
+CLIENT_DATA_ROOT = os.path.realpath(
+ os.path.join(
+ os.path.dirname(__file__),
+ u'../../client-data',
+ )
+)
+
+class MinimapRenderer(object):
+
+ PROGRAMS = {
+ 'default': {
+ 'tmxrasterizer': 'tmxrasterizer',
+ 'im_convert': 'convert',
+ },
+ 'win32': {
+ 'tmxrasterizer': 'tmxrasterizer.exe',
+ 'im_convert': 'convert.exe',
+ },
+ }
+
+ def __init__(self, map_name, tilesize, useAntiAliasing):
+ self.map_name = map_name
+ self.tilesize = tilesize
+ self.useAntiAliasing = useAntiAliasing
+
+ def render(self):
+ """
+ Processes a map
+ """
+ if not os.path.exists(os.path.join(CLIENT_DATA_ROOT, u'maps', self.map_name+u'.tmx')):
+ sys.stderr.write(u'Invalid map name: %s. Skipping.\n' % self.map_name)
+ return 1
+ if not self.map_name.endswith(u'.tmx'):
+ self.map_name = self.map_name+u'.tmx'
+
+ map_number = os.path.splitext(os.path.basename(self.map_name))[0]
+ tmx_file = os.path.join(CLIENT_DATA_ROOT, u'maps', self.map_name)
+ minimap_file = os.path.join(CLIENT_DATA_ROOT, u'graphics', u'minimaps', map_number+u'.png')
+
+ prefix = os.path.commonprefix((tmx_file, minimap_file))
+ sys.stdout.write(u'%s -> %s\n' % (os.path.relpath(tmx_file, prefix), os.path.relpath(minimap_file, prefix)))
+
+ try:
+ self.do_render(tmx_file, minimap_file)
+ except Exception as e:
+ sys.stderr.write(u'\x1b[31m\x1b[1mError while rendering %s: %s\x1b[0m\n' % (self.map_name, e))
+ return 1
+ else:
+ return 0
+
+ def do_render(self, tmx_file, bitmap_file):
+ """
+ The map rendering implementation
+ """
+ platform_programs = MinimapRenderer.PROGRAMS.get(sys.platform, MinimapRenderer.PROGRAMS.get('default'))
+ # tmx rasterize
+ mrf, map_raster = tempfile.mkstemp(suffix='.png')
+ tmxrasterizer_cmd = [
+ platform_programs.get('tmxrasterizer'),
+ '--tilesize', str(self.tilesize), '--hide-layer', 'Collision','--hide-layer', 'Height','--hide-layer', 'Collisions','--hide-layer', 'collision','--hide-layer', 'height','--hide-layer', 'Heights', '--hide-layer', 'height', '--ignore-visibility',
+ ]
+ if self.useAntiAliasing:
+ tmxrasterizer_cmd.append('--anti-aliasing')
+ tmxrasterizer_cmd += [tmx_file, map_raster]
+ subprocess.check_call(tmxrasterizer_cmd)
+ if os.stat(map_raster).st_size == 0:
+ raise Exception('A problem was encountered when rendering a map')
+ # add cell-shading to the minimap to improve readability
+ ebf, edges_bitmap = tempfile.mkstemp(suffix='.png')
+ subprocess.check_call([
+ platform_programs.get('im_convert'), map_raster,
+ '-set', 'option:convolve:scale', '-1!',
+ '-morphology', 'Convolve', 'Laplacian:0',
+ '-colorspace', 'gray',
+ '-auto-level',
+ '-threshold', '2.8%',
+ '-negate',
+ '-transparent', 'white',
+ edges_bitmap
+ ])
+ subprocess.check_call([
+ platform_programs.get('im_convert'), map_raster, edges_bitmap,
+ '-compose', 'Dissolve',
+ '-define', 'compose:args=35',
+ '-composite',
+ bitmap_file
+ ])
+ os.unlink(map_raster)
+ os.unlink(edges_bitmap)
+
+ @staticmethod
+ def check_programs():
+ """
+ Checks the require programs are available
+ """
+ def which(program):
+ import os
+ def is_exe(fpath):
+ return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
+ fpath, fname = os.path.split(program)
+ if fpath:
+ if is_exe(program):
+ return program
+ else:
+ for path in os.environ["PATH"].split(os.pathsep):
+ exe_file = os.path.join(path, program)
+ if is_exe(exe_file):
+ return exe_file
+ return None
+
+ platform_programs = MinimapRenderer.PROGRAMS.get(sys.platform, MinimapRenderer.PROGRAMS.get('default'))
+ for program in platform_programs.values():
+ if not which(program):
+ raise Exception('The required "%s" program is missing from your PATH.' % program)
+
+def usage():
+ sys.stderr.write(u'''Usage: %s MAP_NAME...
+
+ Example:
+ $ ./minimap-render.py 007-1
+ will render the map at maps/007-1.tmx in the graphics/minimaps directory.
+ $ ./minimap-render.py all
+ will render all existing maps found in the maps directory.
+ $ ./minimap-render.py update
+ will update all existing minimaps found in the graphics/minimaps directory.
+
+ For convenience,
+ $ ./minimap-render.py 007-1.tmx
+ is also accepted.
+ \n''' % sys.argv[0])
+
+def main():
+ if not len(sys.argv) > 1:
+ usage()
+ return 127
+ try:
+ MinimapRenderer.check_programs()
+ except Exception as e:
+ sys.stderr.write(u'%s\n' % e)
+ return 126
+
+ status = 0
+ if sys.argv[1].lower() == 'all':
+ map_names = sorted([os.path.splitext(p)[0] for p in os.listdir(os.path.join(CLIENT_DATA_ROOT, u'maps'))])
+ elif sys.argv[1].lower() == 'update':
+ map_names = sorted([os.path.splitext(p)[0] for p in os.listdir(os.path.join(CLIENT_DATA_ROOT, u'graphics', u'minimaps'))])
+ else:
+ map_names = sys.argv[1:]
+
+ for map_name in map_names:
+ # Render tiles at 1 pixel size
+ map_renderer = MinimapRenderer(map_name, 1, True)
+ status += map_renderer.render()
+ return 0
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/client/weapons.py b/client/weapons.py
new file mode 100755
index 0000000..be2f60e
--- /dev/null
+++ b/client/weapons.py
@@ -0,0 +1,89 @@
+#!/usr/bin/python2.7
+
+class Item:
+ def __init__(self, xid):
+ self.id=xid
+ self.lvl=0
+
+a=open("../../client-data/items.xml", "r")
+
+swords=[]
+bows=[]
+shields=[]
+
+gid="0"
+rid=0
+ctx=Item(0)
+mem=[]
+
+for l in a:
+ if "<item id=" in l:
+ if ctx.id > 0:
+ mem.append(ctx)
+
+ gid=l.replace('\t', '').replace(' ','').replace('<itemid=', '').replace('"', '').replace("'", "")
+ rid=0
+ if "-" in gid:
+ gid="0"
+ continue
+ try:
+ rid=int(gid)
+ except:
+ print "[CRITICAL] Invalid item ID format: " + l
+ exit(1)
+
+ ctx=Item(rid)
+
+ if "\tlevel=" in l or " level=" in l:
+ gid=l.replace('\t', '').replace(' ','').replace('level=', '').replace('"', '').replace("'", "")
+ try:
+ rid=int(gid)
+ except:
+ print "[CRITICAL] Invalid item level format: " + l
+ rid=0
+ ctx.lvl=0+rid
+
+mem=sorted(mem, key=lambda xcv: xcv.lvl, reverse=True)
+
+for r in mem:
+ rid=r.id
+ if rid >= 2700 and rid <= 2899:
+ shields.append(rid)
+ elif rid >= 3500 and rid <= 3999:
+ swords.append(rid)
+ elif rid >= 6000 and rid <= 6499:
+ bows.append(rid)
+
+a.close()
+
+#shields=sorted(shields, reverse=True)
+#bows=sorted(bows, reverse=True)
+#swords=sorted(swords, reverse=True)
+
+b=open("weapons.tmp", "w")
+
+b.write('<?xml version="1.0" encoding="utf-8"?>\n\
+<!-- Author: 4144, Jesusalva\n\
+Copyright (C) 2015 Evol Online\n\
+Copyright (C) 2019-2020 The Mana World\n -->\n\
+\n\
+<weapons>\n')
+
+b.write(' <swords>\n')
+
+for i in swords:
+ b.write(' <item id="%d"/>\n' % i)
+
+b.write(' </swords>\n <bows>\n')
+
+for i in bows:
+ b.write(' <item id="%d"/>\n' % i)
+
+b.write(' </bows>\n <shields>\n')
+
+for i in shields:
+ b.write(' <item id="%d"/>\n' % i)
+
+b.write(' </shields>\n</weapons>')
+
+b.close()
diff --git a/hercules/.gitignore b/hercules/.gitignore
new file mode 100644
index 0000000..7eeffc2
--- /dev/null
+++ b/hercules/.gitignore
@@ -0,0 +1,12 @@
+clientdata
+maps
+serverdata
+oldserverdata
+newserverdata
+mapcache
+olddb
+newdb
+rodata
+tools/luadec
+
+*.pyc
diff --git a/hercules/code/__init__.py b/hercules/code/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/hercules/code/__init__.py
diff --git a/hercules/code/clienttoserver/__init__.py b/hercules/code/clienttoserver/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/hercules/code/clienttoserver/__init__.py
diff --git a/hercules/code/clienttoserver/maps.py b/hercules/code/clienttoserver/maps.py
new file mode 100644
index 0000000..b9a1626
--- /dev/null
+++ b/hercules/code/clienttoserver/maps.py
@@ -0,0 +1,190 @@
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2014 Evol Online
+# Author: Andrei Karas (4144)
+
+import array
+import csv
+import hashlib
+import os
+import zlib
+import struct
+import StringIO
+from xml.dom import minidom
+
+from code.fileutils import makeDir, writeInt16, writeInt32, writeData, removeDir
+
+def getTmxFiles(srcDir):
+ names = []
+ for name in os.listdir(srcDir):
+ names.append(name)
+ names.sort()
+ for name in names:
+ fileName = srcDir + name
+ if os.path.isfile(fileName) == False:
+ continue
+ if name.endswith(".tmx") == False:
+ continue
+ yield (fileName, name)
+
+def findFirstGid(tilesets, tile):
+ found = -1
+ for t in tilesets:
+ if t <= tile:
+ found = t
+ break
+ return found
+
+# client
+# 0 - walkable ground
+# 1 - non walkable wall
+# 2 - air allowed shootable too
+# 3 - water allowed water, shootable too
+# 4 - sit, walkable ground
+# 5 - player walk not allowed
+# 6 - monster walk not allowed
+
+# server
+# 0 - walkable ground
+# 1 - non walkable wall
+# 2 - air allowed shootable too
+# 3 - water allowed water, shootable too
+# 4 - sit, walkable ground
+# 5 - none
+# 6 - monster walk not allowed
+def convertTileType(tile, idx, width, height):
+ if tile == 5:
+ tile = 0;
+ if tile > 6 or tile < 0:
+ y = int(idx / width)
+ x = idx - y * width
+ print "Error: wrong tile: ({0}, {1}) = {2}".format(x, y, tile)
+ tile = 1
+ return tile
+
+# map file format
+#
+# int16 version;
+# uint8 md5_checksum[16];
+# int16 xs;
+# int16 ys;
+# int32 len;
+# ...data...
+
+def recreateMap(names):
+ collisionLayerName = "collision"
+ destDir = "../../server-data/maps/pre-re/"
+ tmxName = names[0]
+ mCaheName = destDir + names[1][:-3] + "mcache"
+ with open(mCaheName, "wb") as w:
+ print tmxName
+ dom = minidom.parse(tmxName)
+ root = dom.documentElement
+ tilesets = []
+ for tileset in root.getElementsByTagName("tileset"):
+ tilesets.append(int(tileset.attributes["firstgid"].value))
+ tilesets.sort(reverse = True)
+ found = False
+ for layer in root.getElementsByTagName("layer"):
+ if layer.attributes["name"].value.lower() == collisionLayerName:
+ data = layer.getElementsByTagName("data")
+ if data is None or len(data) != 1:
+ continue
+ data = data[0]
+ width = int(layer.attributes["width"].value)
+ height = int(layer.attributes["height"].value)
+ encoding = data.attributes["encoding"].value
+ try:
+ compression = data.attributes["compression"].value
+ except:
+ compression = ""
+
+ tiles = []
+ if encoding == "base64":
+ binData = data.childNodes[0].data.strip()
+ binData = binData.decode('base64')
+ if compression == "gzip":
+ dc = zlib.decompressobj(16 + zlib.MAX_WBITS)
+ else:
+ dc = zlib.decompressobj()
+ layerData = dc.decompress(binData)
+ arr = array.array("I")
+ arr.fromstring(layerData)
+ idx = 0
+ for tile in arr:
+ if tile == 0:
+ tileType = 0
+ else:
+ firstgid = findFirstGid(tilesets, tile)
+ tileType = convertTileType(tile - firstgid, idx, width, height);
+ tiles.append(tileType)
+ idx = idx + 1
+ elif encoding == "csv":
+ binData = data.childNodes[0].data.strip()
+ f = StringIO.StringIO(binData)
+ arr = list(csv.reader(f, delimiter=',', quotechar='|'))
+ idx = 0
+ for row in arr:
+ for item in row:
+ if item != "":
+ tile = int(item)
+ if tile == 0:
+ tileType = 0
+ else:
+ firstgid = findFirstGid(tilesets, tile)
+ tileType = convertTileType(tile - firstgid, idx, width, height);
+ # tmx collision format
+ # 0 - walkable ground
+ # 1 - non walkable wall
+ # 2 - air allowed shootable too
+ # 3 - water allowed water, shootable too
+ # 4 - sit, walkable ground
+ # 5 - none
+
+ # server collision format
+ # 000 0 - walkable, shootable
+ # 001 1 - wall
+ # 010 2 - same with 0
+ # 011 3 - walkable, shootable, water
+ # 100 4 - same with 0
+ # 101 5 - shootable
+ # 110 6 - same with 0
+ # 111 7 - none
+ if tileType > 128 or tileType < 0:
+ tileType = 1
+ tiles.append(tileType)
+ idx = idx + 1
+ f.close()
+ else:
+ print "map format not supported: " + tmxName
+ continue
+
+ #comp = zlib.compressobj()
+ binData = struct.pack(str(len(tiles))+"B", *tiles)
+ binData = zlib.compress(binData)
+ writeInt16(w, 1)
+ writeData(w, hashlib.md5(binData).digest()) # 16 bytes
+ writeInt16(w, width)
+ writeInt16(w, height)
+ writeInt32(w, len(binData))
+ writeData(w, binData)
+ #print tmxName
+ found = True
+ break
+ if found == False:
+ print "Error: missing collision layer in file: {0}".format(tmxName)
+ return
+ return
+ with open(mCaheName + ".debug", "wb") as w:
+ writeInt16(w, width)
+ writeInt16(w, height)
+ writeData(w, struct.pack(str(len(tiles))+"B", *tiles))
+
+
+def recreateMapCache():
+ destDir = "../../server-data/maps/pre-re/"
+ srcDir = "../../client-data/maps/"
+ removeDir(destDir)
+ makeDir(destDir)
+ for names in getTmxFiles(srcDir):
+ recreateMap(names)
diff --git a/hercules/code/configutils.py b/hercules/code/configutils.py
new file mode 100644
index 0000000..6d9ddb2
--- /dev/null
+++ b/hercules/code/configutils.py
@@ -0,0 +1,51 @@
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2014 Evol Online
+# Author: Andrei Karas (4144)
+
+def writeIntField(w, name, value):
+ if value == "":
+ value = "0"
+ w.write(" {0}: {1}\n".format(name, value))
+
+def writeIntField2(w, name, value):
+ if value == "":
+ value = "0"
+ w.write(" {0}: {1}\n".format(name, value))
+
+def writeStrField(w, name, value):
+ w.write(" {0}: \"{1}\"\n".format(name, value))
+
+def writeCondField2(w, cond, name):
+ if cond != 0:
+ w.write(" {0}: true\n".format(name))
+
+def writeSubField(w, name, value):
+ w.write(" {0}: {1}\n".format(name, value))
+
+def writeFieldArr(w, name, value, value2):
+ w.write(" {0}: [{1}, {2}]\n".format(name, value, value2))
+
+def writeFieldList(w, name, value, value2):
+ w.write(" {0}: ({1}, {2})\n".format(name, value, value2))
+
+def writeStartBlock(w, text):
+ w.write(" {0}: {{\n".format(text))
+
+def writeEndBlock(w):
+ w.write(" }\n")
+
+def writeStartScript(w, name):
+ w.write(" {0}: <\"\n".format(name))
+
+def writeEndScript(w):
+ w.write(" \">\n")
+
+def isHaveData(fields, start, cnt):
+ for f in range(0, cnt):
+ value = fields[start + f * 2]
+ chance = fields[start + f * 2]
+ if value == "" or value == "0" or chance == "" or chance == "0":
+ continue
+ return True
+ return False
diff --git a/hercules/code/fileutils.py b/hercules/code/fileutils.py
new file mode 100644
index 0000000..a0635d4
--- /dev/null
+++ b/hercules/code/fileutils.py
@@ -0,0 +1,86 @@
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2014 Evol Online
+# Author: Andrei Karas (4144)
+
+import array
+import os
+import struct
+import shutil
+
+def readInt32(f):
+ data = f.read(4)
+ arr = array.array("I")
+ arr.fromstring(data)
+ return arr[0]
+
+def readInt16(f):
+ data = f.read(2)
+ arr = array.array("H")
+ arr.fromstring(data)
+ return arr[0]
+
+def readInt8(f):
+ data = f.read(1)
+ arr = array.array("B")
+ arr.fromstring(data)
+ return arr[0]
+
+def readMapName(f):
+ data = f.read(12)
+ data = str(data)
+ while data[-1] == '\x00':
+ data = data[:-1]
+ return data
+
+def skipData(f, sz):
+ f.read(sz)
+
+def readData(f, sz):
+ return f.read(sz)
+
+def readFile(path):
+ with open(path, "r") as f:
+ return f.read()
+
+def writeInt32(f, i):
+ f.write(struct.pack("I", i))
+
+def writeInt16(f, i):
+ f.write(struct.pack("H", i))
+
+def writeMapName(f, name):
+ if len(name) > 12:
+ name = name[:12]
+ while len(name) < 12:
+ name = name + '\x00'
+ f.write(struct.pack("12s", name))
+
+def writeData(f, data):
+ f.write(data)
+
+def copyFile(src, dst, name):
+ shutil.copyfile(src + name, dst + name)
+
+def saveFile(fileName, data):
+ with open(fileName, "w") as w:
+ w.write(data)
+
+def makeDir(path):
+ if not os.path.exists(path):
+ os.makedirs(path)
+
+def removeDir(path):
+ if os.path.exists(path):
+ shutil.rmtree(path)
+
+def removeAllFiles(path):
+ if os.path.exists(path):
+ shutil.rmtree(path)
+
+def findFileIn(names, dirs):
+ for name in names:
+ for path in dirs:
+ if os.path.exists(path + name):
+ return path
+ return None
diff --git a/hercules/code/server/__init__.py b/hercules/code/server/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/hercules/code/server/__init__.py
diff --git a/hercules/code/server/account.py b/hercules/code/server/account.py
new file mode 100644
index 0000000..7763766
--- /dev/null
+++ b/hercules/code/server/account.py
@@ -0,0 +1,63 @@
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2014 Evol Online
+# Author: Andrei Karas (4144)
+
+import re
+
+from code.fileutils import readFile
+from code.stringutils import stripNewLine, escapeSqlStr
+
+def convertSex(sex):
+ if sex == "M" or sex == "F" or sex == "S":
+ return sex
+ return "M"
+
+def convertAccount():
+ srcFile = "olddb/account.txt"
+ dstFile = "newdb/login.sql"
+ fieldsSplit = re.compile("\t")
+ tpl = readFile("templates/login.sql")
+ firstLine = True
+ with open(dstFile, "w") as w:
+ w.write(tpl)
+ w.write("INSERT INTO `login` VALUES ")
+ with open(srcFile, "r") as r:
+ for line in r:
+ if line[:2] == "//":
+ continue
+ rows = fieldsSplit.split(line)
+ if len(rows) == 2:
+ continue
+ if len(rows) != 14:
+ print "wrong account.txt line: " + stripNewLine(line)
+ continue
+
+ if firstLine == False:
+ w.write(",\n")
+ else:
+ firstLine = False
+
+ w.write(("({account_id},'{userid}','{user_pass}','{sex}'," +
+ "'{email}',{group_id},{state},{unban_time}," +
+ "{expiration_time},{logincount},'{lastlogin}'," +
+ "'{last_ip}','{birthdate}',{character_slots}," +
+ "'{pincode}',{pincode_change})").format(
+ account_id = rows[0],
+ userid = escapeSqlStr(rows[1]),
+ user_pass = escapeSqlStr(rows[2]),
+ sex = convertSex(rows[4]),
+ email = escapeSqlStr(rows[7]),
+ group_id = 0,
+ state = 0,
+ unban_time = rows[12],
+ expiration_time = rows[9],
+ logincount = rows[5],
+ lastlogin = rows[3],
+ last_ip = rows[10],
+ birthdate = '0000-00-00',
+ character_slots = 0,
+ pincode = '',
+ pincode_change = 0
+ ))
+ w.write("\n")
diff --git a/hercules/code/server/accreg.py b/hercules/code/server/accreg.py
new file mode 100644
index 0000000..b69910f
--- /dev/null
+++ b/hercules/code/server/accreg.py
@@ -0,0 +1,52 @@
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2014 Evol Online
+# Author: Andrei Karas (4144)
+
+import re
+
+from code.fileutils import readFile
+from code.stringutils import stripNewLine
+
+def convertAccReg():
+ srcFile = "olddb/accreg.txt"
+ dstFile = "newdb/acc_reg_num_db.sql"
+ fieldsSplit = re.compile("\t")
+ comaSplit = re.compile(",")
+ spaceSplit = re.compile(" ")
+ tpl = readFile("templates/acc_reg_num_db.sql")
+ firstLine = True
+ with open(dstFile, "w") as w:
+ w.write(tpl)
+ w.write("INSERT INTO `acc_reg_num_db` VALUES ")
+ with open(srcFile, "r") as r:
+ for line in r:
+ if line[:2] == "//":
+ continue
+ line = stripNewLine(line)
+ rows = fieldsSplit.split(line)
+ if len(rows) != 2:
+ print "wrong accreg.txt line: " + line
+ continue
+
+ accountId = rows[0]
+
+ data = spaceSplit.split(rows[1])
+ for varStr in data:
+ if varStr == "":
+ continue
+
+ tmp = comaSplit.split(varStr)
+
+ if firstLine == False:
+ w.write(",\n")
+ else:
+ firstLine = False
+
+ w.write(("({account_id},'{key}',{index},{value})").format(
+ account_id = accountId,
+ key = tmp[0],
+ index = "0",
+ value = tmp[1]
+ ))
+ w.write("\n")
diff --git a/hercules/code/server/db/__init__.py b/hercules/code/server/db/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/hercules/code/server/db/__init__.py
diff --git a/hercules/code/server/db/char.py b/hercules/code/server/db/char.py
new file mode 100644
index 0000000..cd8e0cc
--- /dev/null
+++ b/hercules/code/server/db/char.py
@@ -0,0 +1,187 @@
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2015 Evol Online
+# Author: Andrei Karas (4144)
+
+from code.fileutils import readFile
+from code.stringutils import escapeSqlStr
+
+def saveCharTable(users):
+ dstFile = "newdb/char.sql"
+ firstLine = True
+ tpl = readFile("templates/char.sql")
+ with open(dstFile, "w") as w:
+ w.write(tpl)
+ w.write("INSERT INTO `char` VALUES ")
+ for userId in users:
+ user = users[userId]
+
+ if firstLine == False:
+ w.write(",\n")
+ else:
+ firstLine = False
+
+ w.write(("({char_id},{account_id},{char_num},'{name}',{CLASS}," +
+ "{base_level},{job_level},{base_exp},{job_exp},{zeny}," +
+ "{str},{agi},{vit},{INT},{dex},{luk},{max_hp},{hp},{max_sp}," +
+ "{sp},{status_point},{skill_point},{option},{karma},{manner}," +
+ "{party_id},{guild_id},{pet_id},{homun_id},{elemental_id}," +
+ "{hair},{hair_color},{clothes_color},{body},{weapon},{shield}," +
+ "{head_top},{head_mid},{head_bottom},{robe}," +
+ "'{last_map}',{last_x},{last_y},'{save_map}',{save_x},{save_y}," +
+ "{partner_id},{online},{father},{mother},{child},{fame}," +
+ "{rename},{delete_date},{slotchange},{char_opt},{font}," +
+ "{unban_time},{uniqueitem_counter},'{sex}',{hotkey_rowshift})").format(
+ char_id = user.char_id,
+ account_id = user.account_id,
+ char_num = user.char_num,
+ name = escapeSqlStr(user.char_name),
+ CLASS = user.char_class,
+ base_level = user.base_level,
+ job_level = user.job_level,
+ base_exp = user.base_exp,
+ job_exp = user.job_exp,
+ zeny = user.zeny,
+ str = user.stat_str,
+ agi = user.stat_agi,
+ vit = user.stat_vit,
+ INT = user.stat_int,
+ dex = user.stat_dex,
+ luk = user.stat_luk,
+ max_hp = user.max_hp,
+ hp = user.hp,
+ max_sp = user.max_sp,
+ sp = user.sp,
+ status_point = user.status_point,
+ skill_point = user.skill_point,
+ option = user.option,
+ karma = user.karma,
+ manner = user.manner,
+ party_id = user.party_id,
+ guild_id = user.guild_id,
+ pet_id = user.pet_id,
+ homun_id = "0",
+ elemental_id = "0",
+ hair = user.hair,
+ hair_color = user.hair_color,
+ clothes_color = user.clothes_color,
+ body = 0,
+ weapon = user.weapon,
+ shield = user.shield,
+ head_top = user.head_top,
+ head_mid = user.head_mid,
+ head_bottom = user.head_bottom,
+ robe = "0",
+ last_map = escapeSqlStr(user.last_map),
+ last_x = user.last_x,
+ last_y = user.last_y,
+ save_map = escapeSqlStr(user.save_map),
+ save_x = user.save_x,
+ save_y = user.save_y,
+ partner_id = user.partner_id,
+ online = "0",
+ father = "0",
+ mother = "0",
+ child = "0",
+ fame = "0",
+ rename = "0",
+ delete_date = "0",
+ slotchange = "0",
+ char_opt = "0",
+ font = "0",
+ unban_time = "0",
+ uniqueitem_counter = len(user.inventory),
+ sex = "U",
+ hotkey_rowshift = 0
+ ))
+ w.write("\n")
+
+def saveCharTableCustom(users):
+ dstFile = "newdb/char.sql"
+ firstLine = True
+ tpl = readFile("templates/char.sql")
+ with open(dstFile, "w") as w:
+ w.write(tpl)
+ w.write("INSERT INTO `char` VALUES ")
+ for userId in users:
+ user = users[userId]
+
+ if firstLine == False:
+ w.write(",\n")
+ else:
+ firstLine = False
+
+ w.write(("({char_id},{account_id},{char_num},'{name}',{CLASS}," +
+ "{base_level},{job_level},{base_exp},{job_exp},{zeny}," +
+ "{str},{agi},{vit},{INT},{dex},{luk},{max_hp},{hp},{max_sp}," +
+ "{sp},{status_point},{skill_point},{option},{karma},{manner}," +
+ "{party_id},{guild_id},{pet_id},{homun_id},{elemental_id}," +
+ "{hair},{hair_color},{clothes_color},{body},{weapon},{shield}," +
+ "{head_top},{head_mid},{head_bottom},{robe}," +
+ "'{last_map}',{last_x},{last_y},'{save_map}',{save_x},{save_y}," +
+ "{partner_id},{online},{father},{mother},{child},{fame}," +
+ "{rename},{delete_date},{slotchange},{char_opt},{font}," +
+ "{unban_time},{uniqueitem_counter},'{sex}',{hotkey_rowshift})").format(
+ char_id = user.char_id,
+ account_id = user.account_id,
+ char_num = user.char_num,
+ name = escapeSqlStr(user.char_name),
+ CLASS = 0,
+ base_level = user.base_level,
+ job_level = user.job_level,
+ base_exp = user.base_exp,
+ job_exp = user.job_exp,
+ zeny = user.zeny,
+ str = user.stat_str,
+ agi = user.stat_agi,
+ vit = user.stat_vit,
+ INT = user.stat_int,
+ dex = user.stat_dex,
+ luk = user.stat_luk,
+ max_hp = user.max_hp,
+ hp = user.hp,
+ max_sp = user.max_sp,
+ sp = user.sp,
+ status_point = user.status_point,
+ skill_point = user.skill_point,
+ option = user.option,
+ karma = user.karma,
+ manner = user.manner,
+ party_id = 0,
+ guild_id = 0,
+ pet_id = 0,
+ homun_id = "0",
+ elemental_id = "0",
+ hair = user.hair,
+ hair_color = user.hair_color,
+ clothes_color = user.clothes_color,
+ body = 0,
+ weapon = 0,
+ shield = 0,
+ head_top = 0,
+ head_mid = 0,
+ head_bottom = 0,
+ robe = "0",
+ last_map = "000-2-1",
+ last_x = 50,
+ last_y = 37,
+ save_map = "00-2-1",
+ save_x = 50,
+ save_y = 37,
+ partner_id = user.partner_id,
+ online = "0",
+ father = "0",
+ mother = "0",
+ child = "0",
+ fame = "0",
+ rename = "0",
+ delete_date = "0",
+ slotchange = "0",
+ char_opt = "0",
+ font = "0",
+ unban_time = "0",
+ uniqueitem_counter = len(user.inventory),
+ sex = "U",
+ hotkey_rowshift = 0
+ ))
+ w.write("\n")
diff --git a/hercules/code/server/db/charregnumdb.py b/hercules/code/server/db/charregnumdb.py
new file mode 100644
index 0000000..1617c13
--- /dev/null
+++ b/hercules/code/server/db/charregnumdb.py
@@ -0,0 +1,34 @@
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2015 Evol Online
+# Author: Andrei Karas (4144)
+
+from code.fileutils import readFile
+
+def saveCharRegNumDbTable(users):
+ dstFile = "newdb/char_reg_num_db.sql"
+ firstLine = True
+ tpl = readFile("templates/char_reg_num_db.sql")
+ with open(dstFile, "w") as w:
+ w.write(tpl)
+ w.write("INSERT INTO `char_reg_num_db` VALUES ")
+ for userId in users:
+ user = users[userId]
+ for varKey in user.variables:
+ if varKey == "ShipQuests":
+ continue
+
+ varValue = user.variables[varKey]
+
+ if firstLine == False:
+ w.write(",\n")
+ else:
+ firstLine = False
+
+ w.write(("({char_id},'{key}',{index},{value})").format(
+ char_id = user.char_id,
+ key = varKey,
+ index = "0",
+ value = varValue
+ ))
+ w.write("\n")
diff --git a/hercules/code/server/db/inventory.py b/hercules/code/server/db/inventory.py
new file mode 100644
index 0000000..e5c1e6a
--- /dev/null
+++ b/hercules/code/server/db/inventory.py
@@ -0,0 +1,44 @@
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2015 Evol Online
+# Author: Andrei Karas (4144)
+
+from code.fileutils import readFile
+
+def saveInventoryTable(users):
+ dstFile = "newdb/inventory.sql"
+ firstLine = True
+ tpl = readFile("templates/inventory.sql")
+ with open(dstFile, "w") as w:
+ w.write(tpl)
+ w.write("INSERT INTO `inventory` VALUES ")
+ for userId in users:
+ user = users[userId]
+ for item in user.inventory:
+
+ if firstLine == False:
+ w.write(",\n")
+ else:
+ firstLine = False
+
+ w.write(("({id},{char_id},{nameid},{amount},{equip},{identify}," +
+ "{refine},{attribute},{card0},{card1},{card2},{card3}," +
+ "{expire_time},{favorite},{bound},{unique_id})").format(
+ id = 0,
+ char_id = user.char_id,
+ nameid = item.itemId,
+ amount = item.amount,
+ equip = item.equip,
+ identify = "1",
+ refine = item.refine,
+ attribute = item.attribute,
+ card0 = "0",
+ card1 = "0",
+ card2 = "0",
+ card3 = "0",
+ expire_time = "0",
+ favorite = "0",
+ bound = "0",
+ unique_id = "0"
+ ))
+ w.write("\n")
diff --git a/hercules/code/server/db/skill.py b/hercules/code/server/db/skill.py
new file mode 100644
index 0000000..d21eb3d
--- /dev/null
+++ b/hercules/code/server/db/skill.py
@@ -0,0 +1,31 @@
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2015 Evol Online
+# Author: Andrei Karas (4144)
+
+from code.fileutils import readFile
+
+def saveSkillTable(users):
+ dstFile = "newdb/skill.sql"
+ firstLine = True
+ tpl = readFile("templates/skill.sql")
+ with open(dstFile, "w") as w:
+ w.write(tpl)
+ w.write("INSERT INTO `skill` VALUES ")
+ for userId in users:
+ user = users[userId]
+ for skill in user.skills:
+
+ if firstLine == False:
+ w.write(",\n")
+ else:
+ firstLine = False
+
+ w.write(("({char_id},{id},{lv},{flag})").format(
+ char_id = user.char_id,
+ id = skill.skillId,
+ lv = skill.level,
+ flag = 0
+# flag = skill.flags
+ ))
+ w.write("\n")
diff --git a/hercules/code/server/dbitem.py b/hercules/code/server/dbitem.py
new file mode 100644
index 0000000..8534ad4
--- /dev/null
+++ b/hercules/code/server/dbitem.py
@@ -0,0 +1,7 @@
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2015 Evol Online
+# Author: Andrei Karas (4144)
+
+class Item:
+ pass
diff --git a/hercules/code/server/dbskill.py b/hercules/code/server/dbskill.py
new file mode 100644
index 0000000..343f3af
--- /dev/null
+++ b/hercules/code/server/dbskill.py
@@ -0,0 +1,7 @@
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2015 Evol Online
+# Author: Andrei Karas (4144)
+
+class Skill:
+ pass
diff --git a/hercules/code/server/dbuser.py b/hercules/code/server/dbuser.py
new file mode 100644
index 0000000..95ad55d
--- /dev/null
+++ b/hercules/code/server/dbuser.py
@@ -0,0 +1,7 @@
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2015 Evol Online
+# Author: Andrei Karas (4144)
+
+class User:
+ pass
diff --git a/hercules/code/server/evol/__init__.py b/hercules/code/server/evol/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/hercules/code/server/evol/__init__.py
diff --git a/hercules/code/server/evol/athena.py b/hercules/code/server/evol/athena.py
new file mode 100644
index 0000000..bad35da
--- /dev/null
+++ b/hercules/code/server/evol/athena.py
@@ -0,0 +1,207 @@
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2015 Evol Online
+# Author: Andrei Karas (4144)
+
+import re
+
+from code.stringutils import stripNewLine, removeGat
+from code.server.dbitem import Item
+from code.server.dbskill import Skill
+from code.server.dbuser import User
+
+comaSplit = re.compile(",")
+spaceSplit = re.compile(" ")
+
+def parseInventory(line, data):
+ items = []
+
+ if data == "":
+ return items
+
+ rows = spaceSplit.split(data)
+ if len(rows) < 1:
+ return items
+
+ for data2 in rows:
+ if data2 == "":
+ continue
+
+ rows2 = comaSplit.split(data2)
+
+ if len(rows2) != 12:
+ print "wrong inventory in account.txt line: " + stripNewLine(line)
+ continue
+
+ item = Item()
+
+ item.uknownId = rows2[0]
+ item.itemId = rows2[1]
+ item.amount = rows2[2]
+ item.equip = rows2[3]
+ item.color = rows2[4]
+ item.refine = rows2[5]
+ item.attribute = rows2[6]
+ item.card0 = rows2[7]
+ item.card1 = rows2[8]
+ item.card2 = rows2[9]
+ item.card3 = rows2[10]
+ item.broken = rows2[11]
+
+ items.append(item)
+
+ return items
+
+def parseSkills(line, data):
+ skills = []
+
+ if data == "":
+ return skills
+
+ rows = spaceSplit.split(data)
+ if len(rows) < 1:
+ return skills
+
+ for data2 in rows:
+ if data2 == "":
+ continue
+
+ rows2 = comaSplit.split(data2)
+
+ if len(rows2) != 2:
+ print "wrong skills in account.txt line: " + stripNewLine(line)
+ continue
+
+ skill = Skill()
+ skill.skillId = rows2[0]
+ skill.level = int(rows2[1]) & 0xffff
+ skill.flags = (int(rows2[1]) * 0xffff) & 0xffff
+
+ skills.append(skill)
+
+ return skills
+
+def parseVars(line, data):
+ variables = {}
+
+ if data == "":
+ return variables
+
+ rows = spaceSplit.split(data)
+ if len(rows) < 1:
+ return variables
+
+ for data2 in rows:
+ if data2 == "":
+ continue
+
+ rows2 = comaSplit.split(data2)
+
+ if len(rows2) != 2:
+ print "wrong variables in account.txt line: " + stripNewLine(line)
+ continue
+
+ variables[rows2[0]] = rows2[1]
+
+ return variables
+
+def readAthena():
+ srcFile = "olddb/athena.txt"
+ fieldsSplit = re.compile("\t")
+
+ users = {}
+ with open(srcFile, "r") as r:
+ for line in r:
+ if line[:2] == "//":
+ continue
+ rows = fieldsSplit.split(line)
+ if len(rows) == 2:
+ continue
+ if len(rows) != 20:
+ print "wrong account.txt line: " + stripNewLine(line)
+ continue
+
+ user = User()
+
+ user.char_id = rows[0]
+ tmp = comaSplit.split(rows[1])
+ user.account_id = tmp[0]
+ user.char_num = tmp[1]
+ user.char_name = rows[2]
+
+ tmp = comaSplit.split(rows[3])
+ user.char_class = tmp[0]
+ user.base_level = tmp[1]
+ user.job_level = tmp[2]
+
+ tmp = comaSplit.split(rows[4])
+ user.base_exp = tmp[0]
+ user.job_exp = tmp[1]
+ user.zeny = tmp[2]
+
+ tmp = comaSplit.split(rows[5])
+ user.hp = tmp[0]
+ user.max_hp = tmp[1]
+ user.sp = tmp[2]
+ user.max_sp = tmp[3]
+
+ tmp = comaSplit.split(rows[6])
+ user.stat_str = tmp[0]
+ user.stat_agi = tmp[1]
+ user.stat_vit = tmp[2]
+ user.stat_int = tmp[3]
+ user.stat_dex = tmp[4]
+ user.stat_luk = tmp[5]
+
+ tmp = comaSplit.split(rows[7])
+ user.status_point = tmp[0]
+ user.skill_point = tmp[1]
+
+ tmp = comaSplit.split(rows[8])
+ user.option = tmp[0]
+ user.karma = tmp[1]
+ user.manner = tmp[2]
+
+ tmp = comaSplit.split(rows[9])
+ user.party_id = tmp[0]
+ user.guild_id = tmp[1]
+ user.pet_id = tmp[2]
+
+ tmp = comaSplit.split(rows[10])
+ user.hair = tmp[0]
+ user.hair_color = tmp[1]
+ user.clothes_color = tmp[2]
+
+ tmp = comaSplit.split(rows[11])
+ user.weapon = tmp[0]
+ user.shield = tmp[1]
+ user.head_top = tmp[2]
+ user.head_mid = tmp[3]
+ user.head_bottom = tmp[4]
+
+ tmp = comaSplit.split(rows[12])
+ user.last_map = removeGat(tmp[0])
+ user.last_x = tmp[1]
+ user.last_y = tmp[2]
+
+ tmp = comaSplit.split(rows[13])
+ user.save_map = removeGat(tmp[0])
+ user.save_x = tmp[1]
+ user.save_y = tmp[2]
+ user.partner_id = tmp[3]
+ user.language_id = tmp[4]
+
+ # skip 14
+
+ user.inventory = parseInventory(line, rows[15])
+
+ # skip 16
+
+ user.skills = parseSkills(line, rows[17])
+
+ user.variables = parseVars(line, rows[18])
+ user.variables["Lang"] = user.language_id
+
+ users[user.char_id] = user
+
+ return users
diff --git a/hercules/code/server/evol/consts.py b/hercules/code/server/evol/consts.py
new file mode 100644
index 0000000..c63f559
--- /dev/null
+++ b/hercules/code/server/evol/consts.py
@@ -0,0 +1,49 @@
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2014 Evol Online
+# Author: Andrei Karas (4144)
+
+import re
+
+def convertConsts(quests):
+ dstFile = "newserverdata/db/const.txt"
+ fieldsSplit = re.compile("\t+")
+ fields = dict()
+ with open(dstFile, "w") as w:
+ srcFile = "serverdata/db/const.txt"
+ with open(srcFile, "r") as r:
+ for line in r:
+ if len(line) < 2 or line[0:2] == "//":
+ continue
+ line = line.replace(" ", "\t")
+ rows = fieldsSplit.split(line)
+ sz = len(rows)
+ if sz < 2 or sz > 3:
+ continue
+
+ fields[rows[0]] = rows[1][:-1]
+ if sz == 2:
+ w.write("{0}\t{1}".format(rows[0], rows[1]))
+ else:
+ w.write("{0}\t{1}\t{2}".format(rows[0], rows[1], rows[2]))
+ # build in parameters
+ w.write("ClientVersion\t10000\t1\n");
+
+ srcFile = "oldserverdata/db/const.txt"
+ w.write("// evol constants\n")
+ with open(srcFile, "r") as r:
+ for line in r:
+ if len(line) < 2 or line[0:2] == "//":
+ continue
+ line = line.replace(" ", "\t")
+ rows = fieldsSplit.split(line)
+ if len(rows) != 2:
+ continue
+
+ if rows[0] in quests:
+ rows[1] = str(quests[rows[0]]) + "\n"
+ if rows[0] in fields:
+ if fields[rows[0]] != rows[1][:-1]:
+ print "warning: different const values for {0} ({1}, {2})".format(rows[0], rows[1][:-1], fields[rows[0]])
+ else:
+ w.write("{0}\t{1}".format(rows[0], rows[1]))
diff --git a/hercules/code/server/evol/itemdb.py b/hercules/code/server/evol/itemdb.py
new file mode 100644
index 0000000..a60e57d
--- /dev/null
+++ b/hercules/code/server/evol/itemdb.py
@@ -0,0 +1,104 @@
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2014 Evol Online
+# Author: Andrei Karas (4144)
+
+import re
+
+from code.configutils import writeIntField, writeStartBlock, writeEndBlock, writeStartScript, writeEndScript, writeStrField, writeSubField
+from code.fileutils import readFile
+
+def convertItemDb():
+ srcFile = "oldserverdata/db/item_db.txt"
+ dstFile = "newserverdata/db/re/item_db.conf"
+ constsFile = "newserverdata/db/const.txt"
+ fieldsSplit = re.compile(",")
+ scriptsSplit = re.compile("{")
+ items = dict()
+ with open(srcFile, "r") as r:
+ with open(dstFile, "w") as w:
+ with open(constsFile, "a") as c:
+ c.write("// items\n");
+ tpl = readFile("templates/item_db.tpl")
+ w.write(tpl)
+ for line in r:
+ if len(line) < 2 or line[0] == "#" or line[0:2] == "//":
+ continue
+ rows = fieldsSplit.split(line)
+ if len(rows) < 5 or rows[0] == "0":
+ continue
+
+ sz = len(rows)
+ if sz > 19:
+ sz = 19
+ for f in xrange(0, sz):
+ rows[f] = rows[f].strip()
+ if rows[4] == "2":
+ rows[4] = "0"
+ rows[3] = str(int(rows[3]) | 4)
+
+ items[rows[1]] = rows[0]
+ w.write("{\n")
+ c.write("{0}\t{1}\n".format(rows[1], rows[0]))
+ writeIntField(w, "Id", rows[0])
+ writeStrField(w, "AegisName", rows[1])
+ writeStrField(w, "Name", rows[2])
+ writeIntField(w, "Type", rows[4])
+ writeIntField(w, "Buy", rows[5])
+ writeIntField(w, "Sell", rows[6])
+ writeIntField(w, "Weight", rows[7])
+ writeIntField(w, "Atk", rows[8])
+ writeIntField(w, "Matk", "0")
+ writeIntField(w, "Def", rows[9])
+ writeIntField(w, "Range", rows[10])
+ writeIntField(w, "Slots", "0")
+ writeIntField(w, "Job", "0xFFFFFFFF")
+ writeIntField(w, "Upper", "0x3F")
+ writeIntField(w, "Gender", rows[13])
+ writeIntField(w, "Loc", rows[14])
+ writeIntField(w, "WeaponLv", rows[15])
+ writeIntField(w, "EquipLv", rows[16])
+ writeIntField(w, "Refine", "false")
+ if rows[14] == "2":
+ writeIntField(w, "View", "1")
+ else:
+ writeIntField(w, "View", rows[0])
+ writeIntField(w, "BindOnEquip", "false")
+ writeIntField(w, "BuyingStore", "false")
+ writeIntField(w, "Delay", "0")
+ trade = int(rows[3])
+ if trade != 0:
+ writeStartBlock(w, "Trade")
+ if trade & 1 == 1:
+ writeSubField(w, "nodrop", "true")
+ if trade & 2 == 2:
+ writeSubField(w, "notrade", "true")
+ if trade & 4 == 4:
+ writeSubField(w, "nodelonuse", "true")
+ if trade & 8 == 8:
+ writeSubField(w, "nostorage", "true")
+ if trade & 256 == 256:
+ writeSubField(w, "nogstorage", "true")
+ if trade & 512 == 512:
+ writeSubField(w, "noselltonpc", "true")
+ if trade != 0:
+ writeEndBlock(w)
+ writeIntField(w, "Sprite", "0")
+
+ scripts = ""
+ for f in xrange(sz, len(rows)):
+ scripts = scripts + ", " + rows[f]
+ rows = scriptsSplit.split(scripts)
+ cnt = len(rows)
+ if cnt > 1:
+ text = rows[1].strip()
+ if len(text) > 1:
+ text = text[:-2]
+ if text != "":
+ writeStartScript(w, "Script")
+ w.write(" {0}\n".format(text))
+ writeEndScript(w)
+
+ w.write("},\n")
+ w.write(")\n")
+ return items
diff --git a/hercules/code/server/evol/main.py b/hercules/code/server/evol/main.py
new file mode 100644
index 0000000..be9f0ab
--- /dev/null
+++ b/hercules/code/server/evol/main.py
@@ -0,0 +1,43 @@
+#! /usr/bin/env python
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2014 Evol Online
+# Author: Andrei Karas (4144)
+
+from code.server.account import convertAccount
+from code.server.accreg import convertAccReg
+from code.server.party import convertParty
+from code.server.storage import convertStorage
+from code.server.db.char import saveCharTable
+from code.server.db.charregnumdb import saveCharRegNumDbTable
+from code.server.db.inventory import saveInventoryTable
+from code.server.db.skill import saveSkillTable
+from code.server.evol.athena import readAthena
+from code.server.evol.consts import convertConsts
+from code.server.evol.itemdb import convertItemDb
+from code.server.evol.mobdb import convertMobDb
+from code.server.evol.mobskilldb import convertMobSkillDb
+from code.server.evol.npcs import createMainScript, convertNpcs
+from code.server.questsdb import convertQuestsDb
+from code.server.utils import cleanServerData
+
+def serverEvolMain():
+ cleanServerData()
+ createMainScript()
+ items = convertItemDb()
+ convertNpcs(items)
+ convertMobDb()
+ quests = convertQuestsDb()
+ convertConsts(quests)
+ convertMobSkillDb()
+
+def dbEvolMain():
+ convertAccount()
+ users = readAthena()
+ saveCharTable(users)
+ saveCharRegNumDbTable(users)
+ saveSkillTable(users)
+ saveInventoryTable(users)
+ convertStorage()
+ convertAccReg()
+ convertParty(users) \ No newline at end of file
diff --git a/hercules/code/server/evol/mobdb.py b/hercules/code/server/evol/mobdb.py
new file mode 100644
index 0000000..74eda04
--- /dev/null
+++ b/hercules/code/server/evol/mobdb.py
@@ -0,0 +1,89 @@
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2014 Evol Online
+# Author: Andrei Karas (4144)
+
+import re
+
+def convertMobDb():
+ srcFile = "oldserverdata/db/mob_db.txt"
+ dstFile = "newserverdata/db/re/mob_db.txt"
+ fieldsSplit = re.compile(",")
+ with open(srcFile, "r") as r:
+ with open(dstFile, "w") as w:
+ for line in r:
+# if len(line) < 2 or line[0] == "#":
+ if len(line) < 2:
+ w.write(line)
+ continue
+ rows = fieldsSplit.split(line)
+ for f in xrange(0, len(rows)):
+ rows[f] = rows[f].strip()
+ w.write("{0:<5} {1:<15} {2:<16} {3:<16} {4:<5} {5:<5} {6:<5} "
+ "{7:<5} {8:<5} {9:<7} {10:<5} {11:<5} {12:<5} {13:<5} "
+ "{14:<5} {15:<5} {16:<5} {17:<5} {18:<5} {19:<5} {20:<7}"
+ " {21:<7} {22:<6} {23:<5} {24:<8} {25:<8} {26:<6} "
+ "{27:<8} {28:<9} {29:<8} {30:<5} {31:<7} {32:<8} {33:<7}"
+ " {34:<8} {35:<7} {36:<8} {37:<8} {38:<9} {39:<8} "
+ "{40:<9} {41:<8} {42:<9} {43:<8} {44:<9} {45:<8} {46:<9}"
+ " {47:<8} {48:<9} {49:<8} {50:<9} {51:<8} {52:<9} "
+ "{53:<8} {54:<9} {55:<8} {56:<8} \n".format(
+ rows[0] + ",",
+ rows[1] + ",",
+ rows[2] + ",",
+ rows[2] + ",",
+ rows[3] + ",",
+ rows[4] + ",",
+ rows[5] + ",",
+ rows[6] + ",",
+ rows[7] + ",",
+ rows[8] + ",",
+ rows[9] + ",",
+ rows[10] + ",",
+ rows[11] + ",",
+ rows[12] + ",",
+ rows[13] + ",",
+ rows[14] + ",",
+ rows[15] + ",",
+ rows[16] + ",",
+ rows[17] + ",",
+ rows[18] + ",",
+ rows[19] + ",",
+ rows[20] + ",",
+ rows[21] + ",",
+ rows[22] + ",",
+ rows[23] + ",",
+ rows[24] + ",",
+ rows[25] + ",",
+ rows[26] + ",",
+ rows[27] + ",",
+ rows[28] + ",",
+ rows[45] + ",",
+ rows[47] + ",",
+ rows[48] + ",",
+ rows[49] + ",",
+ rows[50] + ",",
+ rows[51] + ",",
+ rows[52] + ",",
+ rows[29] + ",",
+ rows[30] + ",",
+ rows[31] + ",",
+ rows[32] + ",",
+ rows[33] + ",",
+ rows[34] + ",",
+ rows[35] + ",",
+ rows[36] + ",",
+ rows[37] + ",",
+ rows[38] + ",",
+ rows[39] + ",",
+ rows[40] + ",",
+ rows[41] + ",",
+ rows[42] + ",",
+ rows[43] + ",",
+ rows[44] + ",",
+ "0,",
+ "0,",
+ "0,",
+ "0"
+ ))
+
diff --git a/hercules/code/server/evol/mobskilldb.py b/hercules/code/server/evol/mobskilldb.py
new file mode 100644
index 0000000..a5a7d5f
--- /dev/null
+++ b/hercules/code/server/evol/mobskilldb.py
@@ -0,0 +1,50 @@
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2014 Evol Online
+# Author: Andrei Karas (4144)
+
+import re
+
+from code.fileutils import readFile
+
+def convertMobSkillDb():
+ srcFile = "oldserverdata/db/mob_skill_db.txt"
+ dstFile = "newserverdata/db/re/mob_skill_db.txt"
+ fieldsSplit = re.compile(",")
+ with open(srcFile, "r") as r:
+ with open(dstFile, "w") as w:
+ tpl = readFile("templates/mob_skill_db.tpl")
+ w.write(tpl)
+ for line in r:
+ if len(line) < 2:
+ w.write(line)
+ continue
+ rows = fieldsSplit.split(line)
+ if len(rows) < 10:
+ w.write(line)
+ continue
+
+ for f in xrange(0, len(rows)):
+ rows[f] = rows[f].strip()
+
+ w.write("{0},{1},{2},{3},{4},{5},{6},"
+ "{7},{8},{9},{10},{11},{12},{13},"
+ "{14},{15},,,\n".format(
+ rows[0],
+ rows[1],
+ rows[2],
+ rows[3],
+ rows[4],
+ rows[5],
+ rows[6],
+ rows[7],
+ rows[8],
+ rows[9],
+ rows[10],
+ rows[11],
+ rows[13],
+ rows[14],
+ rows[15],
+ rows[16]
+ ))
+
diff --git a/hercules/code/server/evol/npcs.py b/hercules/code/server/evol/npcs.py
new file mode 100644
index 0000000..6efe811
--- /dev/null
+++ b/hercules/code/server/evol/npcs.py
@@ -0,0 +1,281 @@
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2014 Evol Online
+# Author: Andrei Karas (4144)
+
+import os
+import re
+
+from code.fileutils import makeDir
+from code.stringutils import stripWindows, stripNewLine
+
+mapsConfFile = "newserverdata/conf/maps.conf"
+mapsIndexFile = "newserverdata/db/map_index.txt"
+npcMainScript = "newserverdata/npc/re/scripts_main.conf"
+mapsIndex = 1
+scriptRe = re.compile("^(?P<map>[^/](.+))[.]gat,([ ]*)(?P<x>[\d]+),([ ]*)(?P<y>[\d]+),([ ]*)(?P<dir>[\d]+)(|,(?P<gender>[\d]+))" +
+ "[\t](?P<tag>script)[\t](?P<name>[\w#' ]+)[\t]"
+ "(?P<class>[\d]+)((,((?P<xs>[\d]+),(?P<ys>[\d]+)))|)(|;(?P<size>[\d]+))(|,|;){$")
+
+shopRe = re.compile("^(?P<map>[^/](.+))[.]gat,([ ]*)(?P<x>[\d]+),([ ]*)(?P<y>[\d]+),([ ]*)(?P<dir>[\d]+)(|,(?P<gender>[\d]+))" +
+ "[\t](?P<tag>shop)[\t](?P<name>[\w#' ]+)[\t]"
+ "(?P<class>[\d]+),(?P<items>(.+))$")
+
+mapFlagRe = re.compile("^(?P<map>[^/](.+))[.]gat" +
+ "[ ](?P<tag>mapflag)[ ](?P<name>[\w#']+)(|[ ](?P<flag>.*))$")
+
+warpRe = re.compile("^(?P<map>[^/](.+))[.]gat,([ ]*)(?P<x>[\d]+),([ ]*)(?P<y>[\d]+)[\t]"
+ "(?P<tag>warp)[\t](?P<name>[^\t]+)[\t](?P<xs>[\d-]+),(?P<ys>[\d-]+),(?P<targetmap>[^/](.+))[.]gat,([ ]*)(?P<targetx>[\d]+),([ ]*)(?P<targety>[\d]+)$")
+
+monsterRe = re.compile("^(?P<map>[^/](.+))[.]gat,([ ]*)(?P<x>[\d]+),([ ]*)(?P<y>[\d]+),([ ]*)(?P<xs>[\d-]+),(?P<ys>[\d-]+)\t"
+ "(?P<tag>monster)[\t](?P<name>[\w#' ]+)[\t]"
+ "(?P<class>[\d]+),(?P<num>[\d]+),(?P<look>[\d-]+),(?P<delay1>[\d]+),(?P<delay2>[\d]+)$")
+
+setRe = re.compile("^(?P<space>[ ]+)set[ ](?P<var>[^,]+),([ ]*)(?P<val>[^;]+);$");
+
+class ScriptTracker:
+ pass
+
+def createMainScript():
+ with open(npcMainScript, "w") as w:
+ w.write("npc: npc/functions/main.txt\n")
+ w.write("import: npc/scripts.conf\n")
+
+def convertNpcs(items):
+ processNpcDir("oldserverdata/npc/", "newserverdata/npc/", items)
+
+def processNpcDir(srcDir, dstDir, items):
+ makeDir(dstDir)
+ files = os.listdir(srcDir)
+ for file1 in files:
+ if file1[0] == '.':
+ continue
+ srcPath = os.path.abspath(srcDir + os.path.sep + file1)
+ dstPath = os.path.abspath(dstDir + os.path.sep + file1)
+ if not os.path.isfile(srcPath):
+ processNpcDir(srcPath, dstPath, items)
+ else:
+ if file1[-5:] == ".conf" or file1[-4:] == ".txt":
+ processNpcFile(srcPath, dstPath, items)
+
+def processNpcFile(srcFile, dstFile, items):
+# print "file: " + srcFile
+ tracker = ScriptTracker()
+ tracker.insideScript = False
+ tracker.items = items
+ with open(srcFile, "r") as r:
+ with open(dstFile, "w") as w:
+ tracker.w = w
+ for line in r:
+ tracker.line = stripWindows(line)
+ res = convertTextLine(tracker)
+ if res:
+ w.write(tracker.line)
+
+def convertTextLine(tracker):
+ line = tracker.line
+ if line[:5] == "map: ":
+ processScriptMapLine(line)
+ return False
+
+ idx = line.find("\tscript\t")
+ if idx >= 0:
+ processScript(tracker)
+ return False
+ idx = line.find("\tshop\t")
+ if idx >= 0:
+ processShop(tracker)
+ return False
+ idx = line.find("\tmonster\t")
+ if idx >= 0:
+ processMonster(tracker)
+ return False
+ idx = line.find("\twarp\t")
+ if idx >= 0:
+ processWarp(tracker)
+ return False
+ idx = line.find(".gat mapflag ")
+ if idx >= 0:
+ processMapFlag(tracker)
+ return False
+ processStrReplace(tracker)
+ return False
+
+def processScriptMapLine(line):
+ global mapsIndex
+ line = stripNewLine(line)
+ if line[-4:] == ".gat":
+ line = line[:-4]
+ with open(mapsConfFile, "a") as w:
+ w.write(line + "\n")
+
+ with open(mapsIndexFile, "a") as w:
+ w.write("{0} {1}\n".format(line[5:], mapsIndex))
+ mapsIndex = mapsIndex + 1
+
+def writeScript(w, m):
+ if m.group("gender") != None:
+ w.write("// Gender = {0}\n".format(m.group("gender")));
+
+ if m.group("x") == 0 and m.group("y") == 0: # float npc
+ w.write("-")
+ else:
+ w.write("{0},{1},{2},{3}".format(m.group("map"), m.group("x"), m.group("y"), m.group("dir")))
+ class_ = m.group("class")
+ if class_ == "0": # hidden npc
+ class_ = "32767"
+ else:
+ class_ = int(class_)
+ if class_ > 125 and class_ <= 400:
+ class_ = class_ + 100
+ w.write("\t{0}\t{1}\t{2}".format(m.group("tag"), m.group("name"), class_));
+
+def processScript(tracker):
+ line = tracker.line
+ w = tracker.w
+ if line[:9] == "function\t":
+ tracker.w.write(line)
+ return
+
+ m = scriptRe.search(line)
+ if m == None:
+ print "error in parsing: " + line
+ w.write("!!!error parsing line")
+ w.write(line)
+ return
+# print "source=" + line[:-1]
+# print "map={0} x={1} y={2} dir={3} gender={4} tag={5} name={6} class={7}, xs={8}, ys={9}, size={10}".format(
+# m.group("map"), m.group("x"), m.group("y"), m.group("dir"), m.group("gender"),
+# m.group("tag"), m.group("name"), m.group("class"), m.group("xs"), m.group("ys"), m.group("size"))
+
+ if m.group("size") != None:
+ w.write("// Size = {0}\n".format(m.group("size")));
+ writeScript(w, m)
+ if m.group("xs") != None:
+ w.write(",{0},{1}".format(m.group("xs"), m.group("ys")));
+ w.write(",{\n");
+
+
+def itemsToShop(tracker, itemsStr):
+ itemsSplit = re.compile(",")
+ itemsSplit2 = re.compile(":")
+ itemsDict = tracker.items
+ outStr = ""
+ items = itemsSplit.split(itemsStr)
+ for str2 in items:
+ parts = itemsSplit2.split(str2)
+ if outStr != "":
+ outStr = outStr + ","
+ outStr = outStr + itemsDict[parts[0].strip()] + ":" + parts[1]
+ return outStr
+
+def processShop(tracker):
+ line = tracker.line
+ w = tracker.w
+
+ m = shopRe.search(line)
+ if m == None:
+ print "error in parsing: " + line
+ w.write("!!!error parsing line")
+ w.write(line)
+ return
+# print "source=" + line[:-1]
+# print "map={0} x={1} y={2} dir={3} gender={4} tag={5} name={6} class={7} items={8}".format(
+# m.group("map"), m.group("x"), m.group("y"), m.group("dir"), m.group("gender"),
+# m.group("tag"), m.group("name"), m.group("class"), m.group("items"))
+
+ writeScript(w, m)
+ w.write("," + itemsToShop(tracker, m.group("items")) + "\n")
+
+def processMapFlag(tracker):
+ line = tracker.line
+ w = tracker.w
+
+ m = mapFlagRe.search(line)
+ if m == None:
+ print "error in parsing: " + line
+ w.write("!!!error parsing line")
+ w.write(line)
+ return
+# print "source=" + line[:-1]
+# print "map={0} tag={1} name={2} flag={3}".format(
+# m.group("map"), m.group("tag"), m.group("name"), m.group("flag"))
+
+ w.write("{0}\t{1}\t{2}".format(m.group("map"), m.group("tag"), m.group("name")))
+ if m.group("flag") == None:
+ w.write("\n")
+ else:
+ w.write("\t{0}\n".format(m.group("flag")))
+
+def processWarp(tracker):
+ line = tracker.line
+ w = tracker.w
+ m = warpRe.search(line)
+ if m == None:
+ print "error in parsing: " + line
+ w.write("!!!error parsing line")
+ w.write(line)
+ return
+
+# print "source=" + line[:-1]
+# print "map={0} xy={1},{2} tag={3} name={4} xs={5} ys={6} target: map={7} xy={8},{9}".format(
+# m.group("map"), m.group("x"), m.group("y"), m.group("tag"), m.group("name"), m.group("xs"), m.group("ys"), m.group("targetmap"), m.group("targetx"), m.group("targety"))
+
+ xs = int(m.group("xs"))
+ ys = int(m.group("ys"))
+ if xs < 0:
+ xs = 0
+ if ys < 0:
+ ys = 0
+ w.write("{0},{1},{2},{3}\t{4}\t{5}\t{6},{7},{8},{9},{10}\n".format(
+ m.group("map"), m.group("x"), m.group("y"), "0", m.group("tag"), m.group("name"),
+ xs, ys, m.group("targetmap"), m.group("targetx"), m.group("targety")))
+
+
+def processMonster(tracker):
+ line = tracker.line
+ w = tracker.w
+ m = monsterRe.search(line)
+ if m == None:
+ print "error in parsing: " + line
+ w.write("!!!error parsing line")
+ w.write(line)
+ return
+
+# print "source=" + line[:-1]
+# print ("map={0} xy={1},{2} xs={3} ys={4} tag={5} name={6} class={7} " +
+# "num={8} look={9} delays={10},{11}").format(
+# m.group("map"), m.group("x"), m.group("y"), m.group("xs"), m.group("ys"),
+# m.group("tag"), m.group("name"), m.group("class"),
+# m.group("num"), m.group("look"), m.group("delay1"), m.group("delay2"))
+ w.write("{0},{1},{2},{3},{4}\t{5}\t{6}\t{7},{8},{9},{10}\n".format(m.group("map"),
+ m.group("x"), m.group("y"), m.group("xs"), m.group("ys"),
+ m.group("tag"), m.group("name"),
+ m.group("class"), m.group("num"), m.group("delay1"), m.group("delay2")))
+
+
+def processStrReplace(tracker):
+ line = tracker.line
+ w = tracker.w
+ line = line.replace("setskill ", "addtoskill ")
+ line = line.replace("zeny", "Zeny")
+ line = line.replace("getclientversion(\"\")", "ClientVersion")
+ line = line.replace("getclientversion()", "ClientVersion")
+ line = line.replace("setlang @", "Lang = @")
+ line = re.sub("([^@^$])@([^@])", "\\1.@\\2", line)
+ line = line.replace(".@menu", "@menu")
+ idx = line.find("getmapmobs(")
+ if idx >= 0:
+ idx2 = line.find("\"", idx + len("getmapmobs(") + 1)
+ idx3 = line.find(")", idx + len("getmapmobs(") + 1)
+ if idx2 + 1 == idx3:
+ line = line[:idx2 + 1] + ",\"all\"" + line[idx2 + 1:]
+
+ line = line.replace("getmapmobs(", "mobcount(")
+
+ m = setRe.search(line);
+ if m != None:
+ line = "{0}{1} = {2};\n".format(m.group("space"), m.group("var"), m.group("val"))
+
+ w.write(line)
+
diff --git a/hercules/code/server/maps.py b/hercules/code/server/maps.py
new file mode 100644
index 0000000..2ef0173
--- /dev/null
+++ b/hercules/code/server/maps.py
@@ -0,0 +1,43 @@
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2014 Evol Online
+# Author: Andrei Karas (4144)
+
+import array
+import struct
+import zlib
+
+from code.fileutils import readMapName, readInt16, readInt32, readData, makeDir
+
+def listMapCache(f, mapsCount):
+ print "Known maps:"
+ print "{0:12} {1:<4}x {2:<4} {3:<10}".format("Map name", "sx", "sy", "compressed size")
+ for i in xrange(0, mapsCount):
+ name = readMapName(f)
+ sx = readInt16(f)
+ sy = readInt16(f)
+ sz = readInt32(f)
+ print "{0:12} {1:<4}x {2:<4} {3:<10}".format(name, sx, sy, sz)
+ f.seek(sz, 1)
+
+def extractMaps(f, mapsCount):
+ destDir = "maps/"
+ makeDir(destDir)
+ for i in xrange(0, mapsCount):
+ name = readMapName(f)
+ sx = readInt16(f)
+ sy = readInt16(f)
+ sz = readInt32(f)
+ data = readData(f, sz)
+ dc = zlib.decompressobj()
+ data = dc.decompress(data)
+ with open(destDir + name, "wb") as w:
+ w.write(struct.pack("H", sx))
+ w.write(struct.pack("H", sy))
+ w.write(data)
+ with open(destDir + name + ".txt", "wb") as w:
+ arr = array.array("B")
+ arr.fromstring(data)
+ for x in xrange(0, sx):
+ for y in xrange(0, sy):
+ w.write("{0},{1}:{2}\n".format(x, y, arr[x + y * sx]))
diff --git a/hercules/code/server/party.py b/hercules/code/server/party.py
new file mode 100644
index 0000000..c75a541
--- /dev/null
+++ b/hercules/code/server/party.py
@@ -0,0 +1,80 @@
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2014 Evol Online
+# Author: Andrei Karas (4144)
+
+import re
+
+from code.fileutils import readFile
+from code.stringutils import stripNewLine, escapeSqlStr
+
+def findLeaderId(name, users):
+ for userId in users:
+ user = users[userId]
+ if user.char_name == name:
+ return user.char_id
+ return 0
+
+def convertParty(users):
+ srcFile = "olddb/party.txt"
+ dstFile = "newdb/party.sql"
+ fieldsSplit = re.compile("\t")
+ comaSplit = re.compile(",")
+ tpl = readFile("templates/party.sql")
+ firstLine = True
+ with open(dstFile, "w") as w:
+ w.write(tpl)
+ w.write("INSERT INTO `party` VALUES ")
+ with open(srcFile, "r") as r:
+ for line in r:
+ if line[:2] == "//":
+ continue
+ line = stripNewLine(line)
+ rows = fieldsSplit.split(line)
+ if len(rows) == 2:
+ continue
+ if len(rows) < 3:
+ print "wrong party.txt line: " + line
+ continue
+
+ partyId = rows[0]
+ partyName = rows[1]
+
+ tmp = comaSplit.split(rows[2])
+ partyExp = tmp[0]
+ partyItem = tmp[1]
+
+ leaderId = 0
+ leaderName = ""
+ accountId = ""
+
+ for f in xrange(3, len(rows), 2):
+
+ if rows[f] == "0,0" or rows[f] == "":
+ continue
+
+ tmp = comaSplit.split(rows[f])
+ accountId = tmp[0]
+ leader = tmp[1]
+ charName = rows[f + 1]
+ if leader == "1":
+ leaderId = accountId
+ leaderName = charName
+
+ if firstLine == False:
+ w.write(",\n")
+ else:
+ firstLine = False
+
+ leaderCharId = findLeaderId(leaderName, users)
+
+ w.write(("({party_id},'{name}',{exp},{item}," +
+ "{leader_id},{leader_char})").format(
+ party_id = partyId,
+ name = escapeSqlStr(partyName),
+ exp = partyExp,
+ item = partyItem,
+ leader_id = leaderId,
+ leader_char = leaderCharId
+ ))
+ w.write("\n")
diff --git a/hercules/code/server/questsdb.py b/hercules/code/server/questsdb.py
new file mode 100644
index 0000000..880a7f9
--- /dev/null
+++ b/hercules/code/server/questsdb.py
@@ -0,0 +1,33 @@
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2014 Evol Online
+# Author: Andrei Karas (4144)
+
+from code.fileutils import readFile
+
+def convertQuestsDb():
+ srcFile = "oldserverdata/db/questvars.txt"
+ dstFile = "newserverdata/db/quest_db.txt"
+ quests = dict()
+ with open(srcFile, "r") as r:
+ with open(dstFile, "w") as w:
+ tpl = readFile("templates/quest_db.tpl")
+ w.write(tpl)
+ cnt = 0
+ for line in r:
+ if len(line) < 2 or line[0:2] == "//":
+ continue
+
+ idx = line.find("// ")
+ if idx < 3:
+ continue
+ line = line[idx + 3:]
+ idx = line.find(" ")
+ if idx < 3:
+ continue
+ line = line[:idx]
+
+ w.write("{0},0,0,0,0,0,0,0,\"{1}\"\n".format(cnt, line))
+ quests[line] = cnt
+ cnt = cnt + 1
+ return quests
diff --git a/hercules/code/server/storage.py b/hercules/code/server/storage.py
new file mode 100644
index 0000000..6bddb52
--- /dev/null
+++ b/hercules/code/server/storage.py
@@ -0,0 +1,81 @@
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2014 Evol Online
+# Author: Andrei Karas (4144)
+
+import re
+
+from code.fileutils import readFile
+from code.stringutils import stripNewLine
+from code.server.dbitem import Item
+
+def convertStorage():
+ srcFile = "olddb/storage.txt"
+ dstFile = "newdb/storage.sql"
+ fieldsSplit = re.compile("\t")
+ comaSplit = re.compile(",")
+ spaceSplit = re.compile(" ")
+ tpl = readFile("templates/storage.sql")
+ firstLine = True
+ with open(dstFile, "w") as w:
+ w.write(tpl)
+ w.write("INSERT INTO `storage` VALUES ")
+ with open(srcFile, "r") as r:
+ for line in r:
+ if line[:2] == "//":
+ continue
+ rows = fieldsSplit.split(line)
+ if len(rows) == 2:
+ continue
+ if len(rows) != 3:
+ print "wrong storage.txt line: " + stripNewLine(line)
+ continue
+
+ tmp = comaSplit.split(rows[0])
+ accountId = tmp[0]
+# storage_amount = tmp[1]
+
+ data = spaceSplit.split(rows[1])
+ for itemStr in data:
+ if itemStr == "":
+ continue
+
+ tmp = comaSplit.split(itemStr)
+ item = Item()
+ item.unknownId = tmp[0]
+ item.itemId = tmp[1]
+ item.amount = tmp[2]
+ item.equip = tmp[3]
+ item.color = tmp[4]
+ item.refine = tmp[5]
+ item.attribute = tmp[6]
+ item.card0 = tmp[7]
+ item.card1 = tmp[8]
+ item.card2 = tmp[9]
+ item.card3 = "0"
+
+ if firstLine == False:
+ w.write(",\n")
+ else:
+ firstLine = False
+
+ w.write(("({id},{account_id},{nameid},{amount},{equip},{identify}," +
+ "{refine},{attribute},{card0},{card1},{card2},{card3}," +
+ "{expire_time},{bound},{unique_id})").format(
+ id = 0,
+ account_id = accountId,
+ nameid = item.itemId,
+ amount = item.amount,
+ equip = item.equip,
+ identify = "1",
+ refine = item.refine,
+ attribute = item.attribute,
+ card0 = "0",
+ card1 = "0",
+ card2 = "0",
+ card3 = "0",
+ expire_time = "0",
+ bound = "0",
+ unique_id = "0"
+ ))
+ w.write("\n")
diff --git a/hercules/code/server/tmw/__init__.py b/hercules/code/server/tmw/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/hercules/code/server/tmw/__init__.py
diff --git a/hercules/code/server/tmw/athena.py b/hercules/code/server/tmw/athena.py
new file mode 100644
index 0000000..6548b2e
--- /dev/null
+++ b/hercules/code/server/tmw/athena.py
@@ -0,0 +1,207 @@
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2015 Evol Online
+# Author: Andrei Karas (4144)
+
+import re
+
+from code.stringutils import stripNewLine
+from code.server.dbitem import Item
+from code.server.dbskill import Skill
+from code.server.dbuser import User
+
+comaSplit = re.compile(",")
+spaceSplit = re.compile(" ")
+
+def parseInventory(line, data):
+ items = []
+
+ if data == "":
+ return items
+
+ rows = spaceSplit.split(data)
+ if len(rows) < 1:
+ return items
+
+ for data2 in rows:
+ if data2 == "":
+ continue
+
+ rows2 = comaSplit.split(data2)
+
+ if len(rows2) != 12:
+ print "wrong inventory in account.txt line: " + stripNewLine(line)
+ continue
+
+ item = Item()
+
+ item.uknownId = rows2[0]
+ item.itemId = rows2[1]
+ item.amount = rows2[2]
+ item.equip = rows2[3]
+ item.color = rows2[4]
+ item.refine = rows2[5]
+ item.attribute = rows2[6]
+ item.card0 = rows2[7]
+ item.card1 = rows2[8]
+ item.card2 = rows2[9]
+ item.card3 = rows2[10]
+ item.broken = rows2[11]
+
+ items.append(item)
+
+ return items
+
+def parseSkills(line, data):
+ skills = []
+
+ if data == "":
+ return skills
+
+ rows = spaceSplit.split(data)
+ if len(rows) < 1:
+ return skills
+
+ for data2 in rows:
+ if data2 == "":
+ continue
+
+ rows2 = comaSplit.split(data2)
+
+ if len(rows2) != 2:
+ print "wrong skills in account.txt line: " + stripNewLine(line)
+ continue
+
+ skill = Skill()
+ skill.skillId = rows2[0]
+ skill.level = int(rows2[1]) & 0xffff
+ skill.flags = (int(rows2[1]) * 0xffff) & 0xffff
+
+ skills.append(skill)
+
+ return skills
+
+def parseVars(line, data):
+ variables = {}
+
+ if data == "":
+ return variables
+
+ rows = spaceSplit.split(data)
+ if len(rows) < 1:
+ return variables
+
+ for data2 in rows:
+ if data2 == "":
+ continue
+
+ rows2 = comaSplit.split(data2)
+
+ if len(rows2) != 2:
+ print "wrong variables in account.txt line: " + stripNewLine(line)
+ continue
+
+ variables[rows2[0]] = rows2[1]
+
+ return variables
+
+def readAthena():
+ srcFile = "olddb/athena.txt"
+ fieldsSplit = re.compile("\t")
+
+ users = {}
+ with open(srcFile, "r") as r:
+ for line in r:
+ if line[:2] == "//":
+ continue
+ rows = fieldsSplit.split(line)
+ if len(rows) == 2:
+ continue
+ if len(rows) != 20:
+ print "wrong account.txt line: " + stripNewLine(line)
+ continue
+
+ user = User()
+
+ user.char_id = rows[0]
+ tmp = comaSplit.split(rows[1])
+ user.account_id = tmp[0]
+ user.char_num = tmp[1]
+ user.char_name = rows[2]
+
+ tmp = comaSplit.split(rows[3])
+ user.char_class = tmp[0]
+ user.base_level = tmp[1]
+ user.job_level = tmp[2]
+
+ tmp = comaSplit.split(rows[4])
+ user.base_exp = tmp[0]
+ user.job_exp = tmp[1]
+ user.zeny = tmp[2]
+
+ tmp = comaSplit.split(rows[5])
+ user.hp = tmp[0]
+ user.max_hp = tmp[1]
+ user.sp = tmp[2]
+ user.max_sp = tmp[3]
+
+ tmp = comaSplit.split(rows[6])
+ user.stat_str = tmp[0]
+ user.stat_agi = tmp[1]
+ user.stat_vit = tmp[2]
+ user.stat_int = tmp[3]
+ user.stat_dex = tmp[4]
+ user.stat_luk = tmp[5]
+
+ tmp = comaSplit.split(rows[7])
+ user.status_point = tmp[0]
+ user.skill_point = tmp[1]
+
+ tmp = comaSplit.split(rows[8])
+ user.option = tmp[0]
+ user.karma = tmp[1]
+ user.manner = tmp[2]
+
+ tmp = comaSplit.split(rows[9])
+ user.party_id = tmp[0]
+ user.guild_id = tmp[1]
+ user.pet_id = tmp[2]
+
+ tmp = comaSplit.split(rows[10])
+ user.hair = tmp[0]
+ user.hair_color = tmp[1]
+ user.clothes_color = tmp[2]
+
+ tmp = comaSplit.split(rows[11])
+ user.weapon = tmp[0]
+ user.shield = tmp[1]
+ user.head_top = tmp[2]
+ user.head_mid = tmp[3]
+ user.head_bottom = tmp[4]
+
+ tmp = comaSplit.split(rows[12])
+ user.last_map = tmp[0]
+ user.last_x = tmp[1]
+ user.last_y = tmp[2]
+
+ tmp = comaSplit.split(rows[13])
+ user.save_map = tmp[0]
+ user.save_x = tmp[1]
+ user.save_y = tmp[2]
+
+ user.partner_id = "0"
+ user.language_id = "0"
+
+ # skip 14
+
+ user.inventory = parseInventory(line, rows[15])
+
+ # skip 16
+
+ user.skills = parseSkills(line, rows[17])
+
+ user.variables = parseVars(line, rows[18])
+
+ users[user.char_id] = user
+
+ return users
diff --git a/hercules/code/server/tmw/consts.py b/hercules/code/server/tmw/consts.py
new file mode 100644
index 0000000..5b8403e
--- /dev/null
+++ b/hercules/code/server/tmw/consts.py
@@ -0,0 +1,129 @@
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2014 Evol Online
+# Author: Andrei Karas (4144)
+
+import os
+import re
+
+from code.fileutils import readFile
+from code.stringutils import stripNewLine
+
+fieldsSplit = re.compile(":")
+
+def getConstsFile(srcDir):
+ files = os.listdir(srcDir)
+ for srcFile in files:
+ if srcFile.find("const") == 0 and srcFile[-4:] == ".txt":
+ yield srcDir + srcFile
+
+def readOneConst(r, line):
+ key = ""
+ val = ""
+ depr = 0
+ if line.find(": {") > 0:
+ rows = fieldsSplit.split(line)
+ key = rows[0].strip()
+ line = r.next().strip()
+ rows = fieldsSplit.split(line)
+ if len(rows) != 2:
+ print "error"
+ return ("", "", 0)
+ if rows[0] == "Value":
+ val = rows[1]
+ line = r.next().strip()
+ rows = fieldsSplit.split(line)
+ if len(rows) != 2:
+ print "error"
+ return ("", "", 0)
+ rows[1] = rows[1].strip()
+ if rows[0] == "Deprecated" and rows[1].find("true") == 0:
+ depr = 1
+ else:
+ rows = fieldsSplit.split(line)
+ if len(rows) != 2:
+ return ("", "", 0)
+ key = rows[0];
+ val = rows[1]
+ return (key, val, depr)
+
+def writeConst(w, const):
+ if const[2] == 1:
+ w.write("\t{0}: {{\n\t\tValue:{1}\n\t\tDeprecated: true\n\t}}\n".format(const[0], const[1]))
+ else:
+ w.write("\t{0}:{1}\n".format(const[0], const[1]))
+
+def convertConsts(quests, npcIds):
+ dstFile = "newserverdata/db/constants.conf"
+ fields = dict()
+ vals = [("MF_NOTELEPORT", "mf_noteleport"),
+ ("MF_NORETURN", "mf_noreturn"),
+ ("MF_MONSTER_NOTELEPORT", "mf_monster_noteleport"),
+ ("MF_NOSAVE", "mf_nosave"),
+ ("MF_NOPENALTY", "mf_nopenalty"),
+ ("MF_PVP", "mf_pvp"),
+ ("MF_PVP_NOPARTY", "mf_pvp_noparty"),
+ ("MF_PVP_NOCALCRANK", "mf_pvp_nocalcrank"),
+ ("MF_NOWARP", "mf_nowarp"),
+ ("MF_NOWARPTO", "mf_nowarpto"),
+ ("MF_SNOW", "mf_snow"),
+ ("MF_FOG", "mf_fog"),
+ ("MF_SAKURA", "mf_sakura"),
+ ("MF_LEAVES", "mf_leaves"),
+ ("MF_TOWN", "mf_town"),
+ ("sc_poison", "SC_POISON"),
+ ("sc_slowpoison", "SC_SLOWPOISON"),
+ ("sc_adrenaline", "SC_ADRENALINE"),
+ ]
+ with open(dstFile, "w") as w:
+ tpl = readFile("templates/constants.tpl")
+ w.write(tpl);
+ srcFile = "serverdata/db/constants.conf"
+ with open(srcFile, "r") as r:
+ for line in r:
+ if line.find("**************************************************************************/") >= 0:
+ break
+
+ for line in r:
+ line = line.strip()
+ if len(line) < 2 or line[0:2] == "//" or line[0:2] == "/*":
+ continue
+ const = readOneConst(r, line)
+ if const[0] == "comment__":
+ continue
+ fields[const[0]] = const[1].strip()
+ writeConst(w, const)
+
+ srcDir = "oldserverdata/world/map/db/"
+ w.write("// tmw constants\n")
+
+ fieldsSplit = re.compile("\t+")
+
+ for srcFile in getConstsFile(srcDir):
+ with open(srcFile, "r") as r:
+ for line in r:
+ if len(line) < 2 or line[0:2] == "//":
+ continue
+ line = line.replace(" ", "\t")
+ rows = fieldsSplit.split(line)
+ if len(rows) != 2:
+ continue
+
+ for val in vals:
+ if rows[0] == val[0]:
+ rows[0] = val[1]
+ if rows[0] in quests:
+ rows[1] = str(quests[rows[0]]) + "\n"
+ if rows[0] in fields:
+ if fields[rows[0]] != rows[1][:-1]:
+ print "warning: different const values for {0} ({1}, {2})".format(rows[0], rows[1][:-1], fields[rows[0]])
+ else:
+ writeConst(w, (rows[0], stripNewLine(rows[1]), 0))
+ w.write("// tmw npcs\n")
+ for npc in npcIds:
+ if npc == -1:
+ key = "MINUS1"
+ else:
+ key = str(npc)
+ writeConst(w, ("NPC" + key, npc, 0))
+ w.write("}")
diff --git a/hercules/code/server/tmw/itemdb.py b/hercules/code/server/tmw/itemdb.py
new file mode 100644
index 0000000..dde9aaa
--- /dev/null
+++ b/hercules/code/server/tmw/itemdb.py
@@ -0,0 +1,291 @@
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2014 Evol Online
+# Author: Andrei Karas (4144)
+
+import os
+import re
+
+from code.configutils import writeStartScript, writeEndScript, writeIntField, writeStrField
+from code.fileutils import readFile
+
+def getItemDbFile(srcDir):
+ files = os.listdir(srcDir)
+ for srcFile in files:
+ if srcFile.find("item_db") >= 0:
+ yield srcFile
+
+def replaceStr(line):
+ vals = [
+ ("setskill ", "addtoskill "),
+ ("zeny", "Zeny"),
+ ("sc_poison", "SC_POISON"),
+ ("sc_slowpoison", "SC_SLOWPOISON"),
+ ("sex", "Sex"),
+ ("SEX", "Sex"),
+
+ (".gat", ""),
+ ("Bugleg", "BugLeg"),
+ ("set BugLeg, 0;", "//set BugLeg, 0;"),
+ ("set CaveSnakeLamp, 0;", "//set CaveSnakeLamp, 0;"),
+ ("set Class, @BaseClass;", "//set Class, @BaseClass;"),
+ ("goto_Exit;", "goto L_Exit;"),
+ ("if @spants_state < 7 goto", "if(@spants_state < 7) goto"),
+ ("isdead()", "ispcdead()"),
+ ("changeSex", "changecharsex()"),
+ ("getpartnerid2()", "getpartnerid()"),
+
+ ("getmap()", "getmapname()"),
+ ("L_end", "L_End"),
+ ("gmcommand", "atcommand"),
+ ("MF_NOSAVE", "mf_nosave"),
+ ("S_update_var", "S_Update_Var"),
+ ("L_teach", "L_Teach"),
+ ("L_focus", "L_Focus"),
+ ("L_unfocus", "L_Unfocus"),
+ ("L_main", "L_Main"),
+ ("L_next", "L_Next"),
+ ("L_close", "L_Close"),
+ ("@NpcName$", "@npcname$"),
+ ("@cost", "@Cost"),
+ ("@TEMP", "@temp"),
+ ("L_Menuitems", "L_MenuItems"),
+ ("L_no_item", "L_No_Item"),
+ ("L_no_water", "L_No_Water"),
+ ("L_NOT_ENOUGH", "L_No_Water"),
+ ("L_bye", "L_Bye"),
+ ("L_NOHELP", "L_NoHelp"),
+ ("L_Eyepatch", "L_EyePatch"),
+ ("@PC_STAMINA", "@pc_stamina"),
+ ("L_magic", "L_Magic"),
+ ("L_cont", "L_Cont"),
+ ("L_accept", "L_Accept"),
+ ("L_no_event", "L_No_Event"),
+ ("L_event_done", "L_Event_Done"),
+ ("L_nobeer", "L_NoBeer"),
+ ("L_iron", "L_Iron"),
+ ("L_sulphur", "L_Sulphur"),
+ ("L_red", "L_Red"),
+ ("L_yellow", "L_Yellow"),
+ ("L_green", "L_Green"),
+ ("L_orange", "L_Orange"),
+ ("L_pink", "L_Pink"),
+ ("L_purple", "L_Purple"),
+ ("L_question", "L_Question"),
+ ("L_quest", "L_Quest"),
+ ("L_dead", "L_Dead"),
+ ("L_menu", "L_Menu"),
+ ("L_give", "L_Give"),
+ ("@Items$", "@items$"),
+ ("@menuItems$", "@menuitems$"),
+ ("L_Teach_initial", "L_Teach_Initial"),
+ ("L_finish", "L_Finish"),
+ ("L_No_ash", "L_No_Ash"),
+ ("L_No_water", "L_No_Water"),
+ ("L_cave", "L_Cave"),
+ ("L_farewell", "L_Farewell"),
+ ("@Q_forestbow_", "@Q_Forestbow_"),
+ ("L_game", "L_Game"),
+ ("L_good", "L_Good"),
+ ("L_abort", "L_Abort"),
+ ("@menuID", "@menuid"),
+ ("L_NO_ITEM", "L_No_Item"),
+ ("L_HELP", "L_Help"),
+ ("L_Noitem", "L_NoItem"),
+ ("L_No_fur", "L_No_Fur"),
+ ("@EXP", "@Exp"),
+ ("L_water", "L_Water"),
+ ("L_get", "L_Get"),
+ ("L_happy", "L_Happy"),
+ ("L_cheat", "L_Cheat"),
+ ("@Reward_EXP", "@Reward_Exp"),
+ ("@REWARD_EXP", "@Reward_Exp"),
+ ("L_no_money", "L_No_Money"),
+ ("@MinLevel", "@minLevel"),
+ ("L_return", "L_Return"),
+ ("L_intro", "L_Intro"),
+ ("L_full", "L_Full"),
+ ("@minlevel", "@minLevel"),
+ ("@MinLevel", "@minLevel"),
+ ("L_Cleanup", "L_CleanUp"),
+ ("L_Alreadystarted", "L_AlreadyStarted"),
+ ("@amount", "@Amount"),
+ ("L_again", "L_Again"),
+ ("L_no_potion", "L_No_Potion"),
+ ("L_wizard_hat", "L_Wizard_Hat"),
+ ("L_notenough", "L_NotEnough"),
+ ("L_offer", "L_Offer"),
+ ("L_giveup", "L_GiveUp"),
+ ("L_not_ready", "L_Not_Ready"),
+ ("@MobID", "@mobId"),
+ ("@mobID", "@mobId"),
+ ("L_naked", "L_Naked"),
+ ("L_shortcut", "L_Shortcut"),
+ ("L_shirt", "L_Shirt"),
+ ("L_goodjob", "L_GoodJob"),
+ ("L_kill", "L_Kill"),
+ ("L_nothing", "L_Nothing"),
+ ("L_lowlevel", "L_LowLevel"),
+ ("@mask", "@Mask"),
+ ("Foice", "FoiceItem"),
+ ("LanternaJack", "LanternaJackItem"),
+ # fix at same time usage with same name function and variable
+ ("\"DailyQuestPoints\"", "\"DailyQuestPointsFunc\""),
+ ("sc_adrenaline", "SC_ADRENALINE"),
+ ];
+
+ for val in vals:
+ line = line.replace(val[0], val[1]);
+ return line
+
+def getItType(it):
+ try:
+ i=int(it)
+ except:
+ i=None
+ if i == 0:
+ return '"IT_HEALING"'
+ elif i == 2:
+ return '"IT_USABLE"'
+ elif i == 3:
+ return '"IT_ETC"'
+ elif i == 4:
+ return '"IT_WEAPON"'
+ elif i == 5:
+ return '"IT_ARMOR"'
+ elif i == 6:
+ return '"IT_CARD"'
+ elif i == 7:
+ return '"IT_HEALING"'
+ elif i == 2:
+ return '"IT_HEALING"'
+ elif i == 2:
+ return '"IT_HEALING"'
+ elif i == 2:
+ return '"IT_HEALING"'
+ else:
+ print("Unrecognized item type: %s" % it)
+ return '"IT_ETC"'
+
+def convertItemDb(isNew):
+ srcDir = "oldserverdata/world/map/db/"
+ dstFile = "newserverdata/db/re/item_db.conf"
+ if os.path.isfile(dstFile):
+ os.remove(dstFile)
+ constsFile = "newserverdata/db/const.txt"
+ if os.path.isfile(constsFile):
+ os.remove(constsFile)
+ fieldsSplit = re.compile(",")
+ scriptsSplit = re.compile("},")
+ scriptsTextClean = re.compile('([{}])')
+ scriptsTextComma = re.compile('^,')
+ scriptsTextColon = re.compile('; ')
+ items = dict()
+
+ tpl = readFile("templates/item_db.tpl")
+ with open(dstFile, "w") as w:
+ w.write(tpl)
+ with open(constsFile, "a") as c:
+ c.write("// items\n");
+ for srcFile in getItemDbFile(srcDir):
+ with open(srcDir + srcFile, "r") as r:
+ for line in r:
+ if len(line) < 2 or line[0] == "#" or line[0:2] == "//":
+ continue
+ line = replaceStr(line)
+ rows = fieldsSplit.split(line)
+ if len(rows) < 5 or rows[0] == "0":
+ continue
+
+ sz = len(rows)
+ if sz > 19:
+ sz = 19
+ for f in xrange(0, sz):
+ rows[f] = rows[f].strip()
+
+ items[rows[1]] = {'id':rows[0],'buy':rows[4],'name':rows[1]}
+ items[rows[0]] = {'id':rows[0],'buy':rows[4],'name':rows[1]}
+ items[int(rows[0])] = {'id':rows[0],'buy':rows[4],'name':rows[1]}
+ # set all values then write
+ w.write("{\n")
+ c.write("{0}\t{1}\n".format(rows[1], rows[0]))
+ writeIntField(w, "Id", rows[0])
+ writeStrField(w, "AegisName", rows[1])
+ if isNew == True:
+ offset = -1
+ else:
+ offset = 0
+ writeStrField(w, "Name", rows[offset + 2])
+ if rows[offset + 3] == "0":
+ itemType = "2"
+ else:
+ itemType = rows[offset + 3]
+ writeIntField(w, "Type", itemType)
+
+ writeIntField(w, "Buy", rows[offset + 4])
+ if int(rows[offset + 4])*.75 <= int(rows[offset + 5])*1.24:
+ writeIntField(w, "Sell", str(int(int(rows[offset + 4])*.50)))
+ else:
+ writeIntField(w, "Sell", rows[offset + 5])
+ writeIntField(w, "Weight", rows[offset + 6])
+ writeIntField(w, "Atk", rows[offset + 7])
+ writeIntField(w, "Matk", "0")
+ writeIntField(w, "Def", rows[offset + 8])
+ writeIntField(w, "Range", rows[offset + 9])
+ writeIntField(w, "Slots", "0")
+ writeIntField(w, "Gender", rows[offset + 12])
+ writeIntField(w, "Loc", rows[offset + 13])
+ writeIntField(w, "WeaponLv", rows[offset + 14])
+ writeIntField(w, "EquipLv", rows[offset + 15])
+ writeIntField(w, "Refine", "false")
+ if isNew == True:
+ offset = 2
+ else:
+ offset = 0
+ if rows[offset + 13] == "2":
+ writeIntField(w, "ViewSprite", "1")
+ elif rows[offset + 13] == "34":
+ writeIntField(w, "ViewSprite", "11")
+ elif rows[offset + 13] == "32768":
+ writeIntField(w, "ViewSprite", "1")
+ elif itemType == "4": # weapon
+ writeIntField(w, "ViewSprite", "1")
+ else:
+ writeIntField(w, "View", rows[0])
+ writeIntField(w, "BindOnEquip", "false")
+ writeIntField(w, "BuyingStore", "false")
+ writeIntField(w, "Delay", "0")
+ writeIntField(w, "Sprite", "0")
+
+ scripts = ""
+ if isNew == True:
+ offset = -1
+ else:
+ offset = 0
+ for f in xrange(offset + 17, len(rows)):
+ scripts = scripts + ", " + rows[f]
+ rows = scriptsSplit.split(scripts)
+ # Needs .split(';') and \n each
+ if len(rows) > 1:
+ UseScript = scriptsTextColon.sub(';',scriptsTextComma.sub('', scriptsTextClean.sub('', rows[0]))).strip().split(';')
+ EquipScript = scriptsTextColon.sub(';',scriptsTextComma.sub('', scriptsTextClean.sub('', rows[1]))).strip().split(';')
+ else:
+ UseScript = ""
+ EquipScript = ""
+ # move to for stmt
+ if len(UseScript) > 1:
+ writeStartScript(w, "Script")
+ for uline in UseScript:
+ if len(uline) > 0:
+ w.write(" {0};\n".format(uline))
+ writeEndScript(w)
+ if len(EquipScript) > 1:
+ writeStartScript(w, "OnEquipScript")
+ for eline in EquipScript:
+ if len(eline) > 0:
+ w.write(" {0};\n".format(eline))
+ writeEndScript(w)
+
+ w.write("},\n")
+ w.write(")\n")
+ return items
diff --git a/hercules/code/server/tmw/main.py b/hercules/code/server/tmw/main.py
new file mode 100644
index 0000000..bfbf5ef
--- /dev/null
+++ b/hercules/code/server/tmw/main.py
@@ -0,0 +1,49 @@
+#! /usr/bin/env python
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2014 Evol Online
+# Author: Andrei Karas (4144)
+
+from sets import Set
+
+from code.server.account import convertAccount
+from code.server.accreg import convertAccReg
+from code.server.party import convertParty
+from code.server.storage import convertStorage
+from code.server.db.char import saveCharTableCustom
+from code.server.db.charregnumdb import saveCharRegNumDbTable
+from code.server.db.inventory import saveInventoryTable
+from code.server.db.skill import saveSkillTable
+from code.server.tmw.athena import readAthena
+from code.server.tmw.consts import convertConsts
+from code.server.tmw.itemdb import convertItemDb
+from code.server.tmw.mobdb import convertMobDb
+from code.server.tmw.mobskilldb import convertMobSkillDb
+from code.server.tmw.npcs import createMainScript, convertNpcs
+from code.server.utils import cleanServerData
+
+def serverTmwMain(isNew):
+ try:
+ cleanServerData()
+ except:
+ print "Updating server"
+ createMainScript()
+ items = convertItemDb(isNew)
+ npcIds = Set()
+ convertNpcs(items, npcIds)
+ convertMobDb(items)
+ quests = dict()
+ convertConsts(quests, npcIds)
+ convertMobSkillDb()
+
+def dbTmwMain():
+ convertAccount()
+ users = readAthena()
+# saveCharTable(users)
+ saveCharTableCustom(users)
+ saveCharRegNumDbTable(users)
+ saveSkillTable(users)
+ saveInventoryTable(users)
+ convertStorage()
+ convertAccReg()
+ convertParty(users)
diff --git a/hercules/code/server/tmw/mobdb.py b/hercules/code/server/tmw/mobdb.py
new file mode 100644
index 0000000..10edfd1
--- /dev/null
+++ b/hercules/code/server/tmw/mobdb.py
@@ -0,0 +1,173 @@
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2014 Evol Online
+# Author: Andrei Karas (4144)
+
+import math
+import os
+import re
+
+from code.configutils import isHaveData, writeCondField2, writeStartBlock, writeEndBlock, writeIntField, writeStrField, writeFieldArr, writeIntField2, writeFieldList, writeSubField
+from code.fileutils import readFile
+
+def getMobDbFile(srcDir):
+ files = os.listdir(srcDir)
+ for srcFile in files:
+ if srcFile.find("mob_db") >= 0:
+ yield srcFile
+
+def replaceStr(line):
+ vals = [
+ ("lanternaJack", "LanternaJack"),
+ ("foice", "Foice"),
+ ("BlueFairy", "BlueFairyMob"),
+ ("RedFairy", "RedFairyMob"),
+ ("GreenFairy", "GreenFairyMob"),
+ ("Scorpion", "ScorpionMob"),
+ ("Tritan", "TritanMob"),
+ ("Ukar", "UkarMob"),
+ ];
+
+ for val in vals:
+ line = line.replace(val[0], val[1]);
+ return line
+
+def convertMobDb(items):
+ srcDir = "oldserverdata/world/map/db/"
+ dstFile = "newserverdata/db/re/mob_db.conf"
+ fieldsSplit = re.compile(",")
+ tpl = readFile("templates/mob_db.tpl")
+ with open(dstFile, "w") as w:
+ w.write(tpl)
+ for srcFile in getMobDbFile(srcDir):
+ with open(srcDir + srcFile, "r") as r:
+ for line in r:
+ if len(line) < 2 or line[:2] == "//" or line[:1] == "#":
+ w.write(line)
+ continue
+ line = replaceStr(line)
+ rows = fieldsSplit.split(line)
+ for f in xrange(0, len(rows)):
+ rows[f] = rows[f].strip()
+ try:
+ val = int(rows[23])
+ if val < 20:
+ rows[23] = "20"
+ except:
+ None
+
+ # Experience and Job experience, following *tmw-eathena*/src/map/mob.c
+ calc_exp = 0
+
+ if rows[6] == "0":
+ if int(rows[4]) <= 1:
+ calc_exp = 1
+
+ mod_def = 100 - int(rows[11])
+
+ if mod_def == 0:
+ mod_def = 1
+
+ effective_hp = ((50 - int(rows[18])) * int(rows[4]) / 50) + (2 * int(rows[18]) * int(rows[4]) / mod_def)
+ attack_factor = (int(rows[9]) + int(rows[10]) + int(rows[13]) / 3 + int(rows[17]) / 2 + int(rows[18])) * (1872 / int(rows[26])) / 4
+ dodge_factor = (int(rows[3]) + int(rows[14]) + int(rows[18]) / 2)**(4 / 3)
+ persuit_factor = (3 + int(rows[8])) * (int(rows[24]) % 2) * 1000 / int(rows[25])
+ aggression_factor = 1
+
+ if False:
+ aggression_factor = 10 / 9
+
+ base_exp_rate = 100 # From *tmw-eathena-data*/conf/battle_athena.conf
+
+ calc_exp = int(math.floor(effective_hp * (math.sqrt(attack_factor) + math.sqrt(dodge_factor) + math.sqrt(persuit_factor) + 55)**3 * aggression_factor / 2000000 * base_exp_rate / 100))
+
+ if calc_exp < 1:
+ calc_exp = 1
+ else:
+ calc_exp = rows[6]
+
+ w.write("{\n")
+ writeIntField(w, "Id", rows[0])
+ writeStrField(w, "SpriteName", rows[1])
+ if (rows[2] != rows[1]):
+ writeStrField(w, "Name", rows[2])
+ else:
+ writeStrField(w, "Name", "The %s" % rows[2])
+ writeIntField(w, "Lv", rows[3])
+ writeIntField(w, "Hp", rows[4])
+ writeIntField(w, "Sp", rows[5])
+ writeIntField(w, "Exp", calc_exp)
+ writeIntField(w, "JExp", rows[7])
+ writeIntField(w, "AttackRange", rows[8])
+ writeFieldArr(w, "Attack", rows[9], rows[10])
+ writeIntField(w, "Def", rows[11])
+ writeIntField(w, "Mdef", rows[12])
+ writeStartBlock(w, "Stats")
+ writeIntField2(w, "Str", rows[13])
+ writeIntField2(w, "Agi", rows[14])
+ writeIntField2(w, "Vit", rows[15])
+ writeIntField2(w, "Int", rows[16])
+ writeIntField2(w, "Dex", rows[17])
+ writeIntField2(w, "Luk", rows[18])
+ writeEndBlock(w)
+ writeIntField(w, "ViewRange", rows[19])
+ writeIntField(w, "ChaseRange", 10)
+ writeIntField(w, "Size", rows[21])
+ writeIntField(w, "Race", rows[22])
+ writeFieldList(w, "Element", int(rows[23]) % 10, int(rows[23]) / 20)
+ mode = int(rows[24], 0)
+ if mode != 0:
+ writeStartBlock(w, "Mode")
+ writeCondField2(w, mode & 0x0001, "CanMove")
+ writeCondField2(w, mode & 0x0002, "Looter")
+ writeCondField2(w, mode & 0x0004, "Aggressive")
+ writeCondField2(w, mode & 0x0008, "Assist")
+ writeCondField2(w, mode & 0x0010, "CastSensorIdle")
+ writeCondField2(w, mode & 0x0020, "Boss")
+ writeCondField2(w, mode & 0x0040, "Plant")
+ writeCondField2(w, mode & 0x0080, "CanAttack")
+ writeCondField2(w, mode & 0x0100, "Detector")
+ writeCondField2(w, mode & 0x0200, "CastSensorChase")
+ writeCondField2(w, mode & 0x0400, "ChangeChase")
+ writeCondField2(w, mode & 0x0800, "Angry")
+ writeCondField2(w, mode & 0x1000, "ChangeTargetMelee")
+ writeCondField2(w, mode & 0x2000, "ChangeTargetChase")
+ writeCondField2(w, mode & 0x4000, "TargetWeak")
+ writeCondField2(w, mode & 0x8000, "LiveWithoutMaster")
+ writeEndBlock(w)
+ writeIntField(w, "MoveSpeed", rows[25])
+ writeIntField(w, "AttackDelay", rows[26])
+ writeIntField(w, "AttackMotion", rows[27])
+ writeIntField(w, "DamageMotion", rows[28])
+ writeIntField(w, "MvpExp", rows[45])
+
+ if isHaveData(rows, 47, 3):
+ writeStartBlock(w, "MvpDrops")
+ for f in range(0, 3):
+ value = rows[47 + f * 2]
+ chance = rows[47 + f * 2]
+ if value == "" or value == "0" or chance == "" or chance == "0":
+ continue
+ value = int(value)
+ if value not in items:
+ w.write("// Error: mvp drop with id {0} not found in item db\n".format(value))
+ print("Error: mvp drop with id {0} not found in item db".format(value))
+ else:
+ writeSubField(w, items[value]["name"], chance)
+ writeEndBlock(w)
+ if isHaveData(rows, 29, 10):
+ writeStartBlock(w, "Drops")
+ for f in range(0, 10):
+ value = rows[29 + f * 2]
+ chance = rows[30 + f * 2]
+ if value == "" or value == "0" or chance == "" or chance == "0":
+ continue
+ value = int(value)
+ if value not in items:
+ w.write("// Error: drop with id {0} not found in item db\n".format(value))
+ print("Error: drop with id {0} not found in item db".format(value))
+ else:
+ writeSubField(w, items[value]["name"], chance)
+ writeEndBlock(w)
+ w.write("},\n")
+ w.write(")\n")
diff --git a/hercules/code/server/tmw/mobskilldb.py b/hercules/code/server/tmw/mobskilldb.py
new file mode 100644
index 0000000..7188824
--- /dev/null
+++ b/hercules/code/server/tmw/mobskilldb.py
@@ -0,0 +1,55 @@
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2014 Evol Online
+# Author: Andrei Karas (4144)
+
+import re
+
+from code.fileutils import readFile
+
+def convertMobSkillDb():
+ srcFile = "oldserverdata/world/map/db/mob_skill_db.txt"
+ dstFile = "newserverdata/db/re/mob_skill_db.txt"
+ fieldsSplit = re.compile(",")
+ notintown = re.compile("notintown")
+ notintownSub = re.compile("notintown,0")
+ with open(srcFile, "r") as r:
+ with open(dstFile, "w") as w:
+ tpl = readFile("templates/mob_skill_db.tpl")
+ w.write(tpl)
+ for line in r:
+ if notintown.search(line):
+ if line[0:2] == "//":
+ line = ''
+ line = notintownSub.sub("myhpltmaxrate,20",line)
+ if len(line) < 2 or line[0:2] == "//":
+ w.write(line)
+ continue
+ rows = fieldsSplit.split(line)
+ if len(rows) < 10:
+ w.write(line)
+ continue
+
+ for f in xrange(0, len(rows)):
+ rows[f] = rows[f].strip()
+
+ w.write("{0},{1},{2},{3},{4},{5},{6},"
+ "{7},{8},{9},{10},{11},{12},{13},"
+ "{14},,,,\n".format(
+ rows[0],
+ rows[1],
+ rows[2],
+ rows[3],
+ rows[4],
+ rows[5],
+ rows[6],
+ rows[7],
+ rows[8],
+ rows[9],
+ rows[10],
+ rows[11],
+ rows[12],
+ rows[13],
+ rows[14]
+ ))
+
diff --git a/hercules/code/server/tmw/npcs.py b/hercules/code/server/tmw/npcs.py
new file mode 100644
index 0000000..c51da78
--- /dev/null
+++ b/hercules/code/server/tmw/npcs.py
@@ -0,0 +1,878 @@
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2014 Evol Online
+# Author: Andrei Karas (4144)
+
+import os
+import re
+
+from code.fileutils import makeDir
+from code.stringutils import stripWindows, stripNewLine
+
+mapsConfFile = "newserverdata/conf/maps.conf"
+if os.path.isfile(mapsConfFile):
+ os.remove(mapsConfFile)
+mapsIndexFile = "newserverdata/db/map_index.txt"
+if os.path.isfile(mapsIndexFile):
+ os.remove(mapsIndexFile)
+npcMainScript = "newserverdata/npc/re/scripts_main.conf"
+mapsIndex = 1
+scriptRe = re.compile("^(((?P<map>[^/](.+)),([ ]*)(?P<x>[\d]+),([ ]*)(?P<y>[\d]+),([ ]*)(?P<dir>[\d]+))|(?P<function>function)|-)" +
+ "[|](?P<tag>script)[|](?P<name>[^|]+)([|]"
+ "(?P<class>[\d-]+)((,((?P<xs>[\d]+),(?P<ys>[\d]+)))|)|)$")
+
+scriptRe2 = re.compile("^(((?P<map>[^/](.+))[.]gat,([ ]*)(?P<x>[\d]+),([ ]*)(?P<y>[\d]+),([ ]*)(?P<dir>[\d]+))|(?P<function>function)|-)" +
+ "[\t](?P<tag>script)[\t](?P<name>[\w#'\\[\\]_ äü.-]+)[\t]"
+ "(((?P<class>[\d-]+)((,((?P<xs>[\d-]+),(?P<ys>[\d-]+)))|)(|,)(|[ \t]))|){(|[ ])$")
+
+shopRe = re.compile("^(?P<map>[^/](.+)),([ ]*)(?P<x>[\d]+),([ ]*)(?P<y>[\d]+),([ ]*)(?P<dir>[\d]+)(|,(?P<gender>[\d]+))" +
+ "[|](?P<tag>shop)[|](?P<name>[^|]+)[|]"
+ "(?P<class>[\d-]+),(?P<items>(.+))$")
+
+shopRe2 = re.compile("^(?P<map>[^/](.+))[.]gat,([ ]*)(?P<x>[\d]+),([ ]*)(?P<y>[\d]+),([ ]*)(?P<dir>[\d]+)" +
+ "[\t](?P<tag>shop)[\t](?P<name>[^\t]+)[\t]"
+ "(?P<class>[\d]+),(?P<items>(.+))$")
+
+mapFlagRe = re.compile("^(?P<map>[^/](.+))" +
+ "[|](?P<tag>mapflag)[|](?P<name>[\w#']+)(|[|](?P<flag>.*))$")
+
+mapFlagRe2 = re.compile("^(?P<map>[^/](.+))[.]gat" +
+ "[ ](?P<tag>mapflag)[ ](?P<name>[\w#']+)(|[ ](?P<flag>.*))$")
+
+warpRe = re.compile("^(?P<map>[^/](.+)),([ ]*)(?P<x>[\d]+),([ ]*)(?P<y>[\d]+)[|]"
+ "(?P<tag>warp)[|](?P<name>[^|]+)[|](?P<xs>[\d-]+),(?P<ys>[\d-]+),(?P<targetmap>[^/](.+)),([ ]*)(?P<targetx>[\d]+),([ ]*)(?P<targety>[\d]+)$")
+warpRe2 = re.compile("^(?P<map>[^/](.+))[.]gat,([ ]*)(?P<x>[\d]+),([ ]*)(?P<y>[\d]+)([\t]+)"
+ "(?P<tag>warp)[\t](?P<name>[^\t]+)([\t]+)(?P<xs>[\d-]+),(?P<ys>[\d-]+),(?P<targetmap>[^/](.+))[.]gat,([ ]*)(?P<targetx>[\d]+),([ ]*)(?P<targety>[\d]+)$")
+warpRe3 = re.compile("^(?P<map>[^/](.+)),([ ]*)(?P<x>[\d]+),([ ]*)(?P<y>[\d]+)[|]"
+ "(?P<tag>warp)[|](?P<xs>[\d-]+),(?P<ys>[\d-]+),(?P<targetmap>[^/](.+)),([ ]*)(?P<targetx>[\d]+),([ ]*)(?P<targety>[\d]+)$")
+
+monsterRe = re.compile("^(?P<map>[^/](.+)),([ ]*)(?P<x>[\d]+),([ ]*)(?P<y>[\d]+),([ ]*)(?P<xs>[\d-]+),(?P<ys>[\d-]+)[|]"
+ "(?P<tag>monster)[|](?P<name>[^|]+)[|]"
+ "(?P<class>[\d]+),(?P<num>[\d]+),(?P<delay1>[\d]+)ms,(?P<delay2>[\d]+)ms(|,(?P<label>[\w+-:#]+))$")
+
+monsterRe2 = re.compile("^(?P<map>[^/](.+))[.]gat,([ ]*)(?P<x>[\d]+),([ ]*)(?P<y>[\d]+),([ ]*)(?P<xs>[\d-]+),(?P<ys>[\d-]+)\t"
+ "(?P<tag>monster)[\t](?P<name>[\w#' ]+)([\t]+)"
+ "(?P<class>[\d]+),(?P<num>[\d]+),(?P<delay1>[\d]+),(?P<delay2>[\d]+)(|,(?P<label>[\w+-:#]+))$")
+
+setRe = re.compile("^(?P<space>[ ]+)set[ ](?P<var>[^,]+),([ ]*)(?P<val>[^;]+);$");
+
+class ScriptTracker:
+ pass
+
+def createMainScript():
+ with open(npcMainScript, "w") as w:
+ w.write("npc: npc/functions/main.txt\n")
+ w.write("import: npc/scripts.conf\n")
+
+def convertNpcs(items, npcIds):
+ processNpcDir("oldserverdata/world/map/npc/", "newserverdata/npc/", items, npcIds)
+
+def processNpcDir(srcDir, dstDir, items, npcIds):
+ makeDir(dstDir)
+ files = os.listdir(srcDir)
+ for file1 in files:
+ if file1[0] == '.':
+ continue
+ srcPath = os.path.abspath(srcDir + os.path.sep + file1)
+ dstPath = os.path.abspath(dstDir + os.path.sep + file1)
+ if not os.path.isfile(srcPath):
+ processNpcDir(srcPath, dstPath, items, npcIds)
+ else:
+ if file1[-5:] == ".conf" or file1[-4:] == ".txt":
+ processNpcFile(srcPath, dstPath, items, npcIds)
+
+def processNpcFile(srcFile, dstFile, items, npcIds):
+# print "file: " + srcFile
+ tracker = ScriptTracker()
+ tracker.insideScript = False
+ tracker.items = items
+ tracker.npcIds = npcIds
+ with open(srcFile, "r") as r:
+ with open(dstFile, "w") as w:
+ tracker.w = w
+ for line in r:
+ line = stripWindows(line)
+ tracker.line = line
+ res = convertTextLine(tracker)
+ if res:
+ w.write(tracker.line)
+
+def convertTextLine(tracker):
+ line = tracker.line
+ if line[:5] == "map: ":
+ processScriptMapLine(line)
+ return False
+
+ if len(line) >= 2 and line[0:2] == "//":
+ return False
+
+ if line == "};\n":
+ tracker.w.write("}\n");
+ return False
+
+ idx = line.find("|script|")
+ if idx <= 0:
+ idx = line.find("\tscript\t")
+ if idx >= 0:
+ processScript(tracker)
+ return False
+ idx = line.find("|shop|")
+ if idx <= 0:
+ idx = line.find("\tshop\t")
+ if idx >= 0:
+ processShop(tracker)
+ return False
+ idx = line.find("|monster|")
+ if idx <= 0:
+ idx = line.find("\tmonster\t")
+ if idx >= 0:
+ processMonster(tracker)
+ return False
+ idx = line.find("|warp|")
+ if idx <= 0:
+ idx = line.find("\twarp\t")
+ if idx >= 0:
+ processWarp(tracker)
+ return False
+ idx = line.find("|mapflag|")
+ if idx <= 0:
+ idx = line.find(".gat mapflag ")
+ if idx >= 0:
+ processMapFlag(tracker)
+ return False
+ processStrReplace(tracker)
+ return False
+
+def processScriptMapLine(line):
+ global mapsIndex
+ line = stripNewLine(line)
+ if line[-4:] == ".gat":
+ line = line[:-4]
+ with open(mapsConfFile, "a") as w:
+ w.write(line + "\n")
+
+ with open(mapsIndexFile, "a") as w:
+ w.write("{0} {1}\n".format(line[5:], mapsIndex))
+ mapsIndex = mapsIndex + 1
+
+def writeScript(w, m, npcIds):
+ try:
+ if m.group("function") != None:
+ isFunction = True
+ else:
+ isFunction = False
+ except:
+ isFunction = False
+
+ if isFunction:
+ w.write("function");
+ elif m.group("x") == None or (m.group("x") == 0 and m.group("y") == 0): # float npc
+ w.write("-")
+ else:
+ w.write("{0},{1},{2},{3}".format(m.group("map"), m.group("x"), m.group("y"), m.group("dir")))
+ if isFunction:
+ funcName = m.group("name")
+ if funcName == "DailyQuestPoints":
+ funcName = "DailyQuestPointsFunc"
+ w.write("\t{0}\t{1}\t".format(m.group("tag"), funcName));
+ else:
+ class_ = m.group("class")
+ if class_ == "0": # hidden npc
+ class_ = 32767
+ elif class_ == None:
+ class_ = -1;
+ else:
+ class_ = int(class_)
+# if class_ > 125 and class_ <= 400:
+# class_ = class_ + 100
+ npcIds.add(int(class_))
+ if class_ == -1:
+ class_ = "MINUS1"
+ w.write("\t{0}\t{1}\tNPC{2}".format(m.group("tag"), m.group("name"), class_));
+
+def processScript(tracker):
+ line = tracker.line[:-1]
+ w = tracker.w
+
+ m = scriptRe.search(line)
+ if m == None:
+ m = scriptRe2.search(line)
+ if m == None:
+ print "error in parsing: " + line
+ w.write("!!!error parsing line")
+ w.write(line)
+ return
+# print "source=" + line
+# print "map={0} x={1} y={2} dir={3} tag={4} name={5} class={6}, xs={7}, ys={8}".format(
+# m.group("map"), m.group("x"), m.group("y"), m.group("dir"),
+# m.group("tag"), m.group("name"), m.group("class"), m.group("xs"), m.group("ys"))
+ # debug
+
+ try:
+ if m.group("function") != None:
+ isFunction = True
+ else:
+ isFunction = False
+ except:
+ isFunction = False
+
+ writeScript(w, m, tracker.npcIds)
+
+ if m.group("xs") != None:
+ w.write(",{0},{1}".format(m.group("xs"), m.group("ys")));
+
+ if isFunction == False:
+ w.write(",{\n");
+ else:
+ w.write("{\n");
+
+def itemsToShop(tracker, itemsStr):
+ itemsSplit = re.compile(",")
+ itemsSplit2 = re.compile(":")
+ itemsDict = tracker.items
+ outStr = ""
+ items = itemsSplit.split(itemsStr)
+ for str2 in items:
+ parts = itemsSplit2.split(str2)
+ if len(parts) != 2:
+ print "Wrong shop item name {0}: {1}".format(str2, itemsStr)
+ continue
+ if parts[1][0] == "*":
+ parts[1] = str((int(parts[1][1:]) * int(itemsDict[parts[0].strip()]['buy'])))
+ if outStr != "":
+ outStr = outStr + ","
+ itemName = parts[0].strip()
+ if itemName in itemsDict:
+ outStr = outStr + itemsDict[itemName]['id'] + ":" + parts[1]
+ else:
+ print "Wrong item name in shop: {0}".format(itemName)
+ return outStr
+
+def processShop(tracker):
+ line = tracker.line
+ w = tracker.w
+
+ m = shopRe.search(line)
+ if m == None:
+ m = shopRe2.search(line)
+ if m == None:
+ print "error in parsing: " + line
+ w.write("!!!error parsing line")
+ w.write(line)
+ return
+
+# print "source=" + line[:-1]
+# print "map={0} x={1} y={2} dir={3} tag={4} name={5} class={6} items={7}".format(
+# m.group("map"), m.group("x"), m.group("y"), m.group("dir"),
+# m.group("tag"), m.group("name"), m.group("class"), m.group("items"))
+
+ writeScript(w, m, tracker.npcIds)
+ w.write("," + itemsToShop(tracker, m.group("items")) + "\n")
+
+def processMapFlag(tracker):
+ line = tracker.line
+ w = tracker.w
+
+ m = mapFlagRe.search(line)
+ if m == None:
+ m = mapFlagRe2.search(line)
+ if m == None:
+ print "error in parsing: " + line
+ w.write("!!!error parsing line")
+ w.write(line)
+ return
+# print "source=" + line[:-1]
+# print "map={0} tag={1} name={2} flag={3}".format(
+# m.group("map"), m.group("tag"), m.group("name"), m.group("flag"))
+
+ if m.group("name") == "town" or m.group("name") == "resave":
+ w.write("//")
+ w.write("{0}\t{1}\t{2}".format(m.group("map"), m.group("tag"), m.group("name")))
+ if m.group("flag") == None:
+ w.write("\n")
+ else:
+ w.write("\t{0}\n".format(m.group("flag")))
+
+def processWarp(tracker):
+ line = tracker.line
+ w = tracker.w
+ m = warpRe.search(line)
+ noName = False
+ if m == None:
+ m = warpRe2.search(line)
+ if m == None:
+ m = warpRe3.search(line)
+ noName = True
+ if m == None:
+ print "error in parsing: " + line
+ w.write("!!!error parsing line")
+ w.write(line)
+ return
+
+ if noName == True:
+ warpName = "{0}_{1}_{2}".format(m.group("map"), m.group("x"), m.group("y"))
+ else:
+ warpName = m.group("name")
+
+# print "source=" + line[:-1]
+# print "map={0} xy={1},{2} tag={3} name={4} xs={5} ys={6} target: map={7} xy={8},{9}".format(
+# m.group("map"), m.group("x"), m.group("y"), m.group("tag"), warpName, m.group("xs"), m.group("ys"), m.group("targetmap"), m.group("targetx"), m.group("targety"))
+
+ xs = int(m.group("xs"))
+ ys = int(m.group("ys"))
+ if xs < 0:
+ xs = 0
+ if ys < 0:
+ ys = 0
+ w.write("{0},{1},{2},{3}\t{4}\t{5}\t{6},{7},{8},{9},{10}\n".format(
+ m.group("map"), m.group("x"), m.group("y"), "0", m.group("tag"), warpName,
+ xs, ys, m.group("targetmap"), m.group("targetx"), m.group("targety")))
+
+
+def processMonster(tracker):
+ line = tracker.line
+ w = tracker.w
+ m = monsterRe.search(line)
+ if m == None:
+ m = monsterRe2.search(line)
+ if m == None:
+ print "error in parsing: " + line
+ w.write("!!!error parsing line")
+ w.write(line)
+ return
+
+# print "source=" + line[:-1]
+# print ("map={0} xy={1},{2} xs={3} ys={4} tag={5} name={6} class={7} " +
+# "num={8} delays={9},{10}, label={11}").format(
+# m.group("map"), m.group("x"), m.group("y"), m.group("xs"), m.group("ys"),
+# m.group("tag"), m.group("name"), m.group("class"),
+# m.group("num"), m.group("delay1"), m.group("delay2"), m.group("label"))
+
+ if m.group("label") != None:
+ label = "," + m.group("label")
+ else:
+ label = ""
+ w.write("{0},{1},{2},{3},{4}\t{5}\t{6}\t{7},{8},{9},{10}{11}\n".format(m.group("map"),
+ m.group("x"), m.group("y"), m.group("xs"), m.group("ys"),
+ m.group("tag"), m.group("name"),
+ m.group("class"), m.group("num"), m.group("delay1"), m.group("delay2"), label))
+
+
+def processStrReplace(tracker):
+ line = tracker.line
+ w = tracker.w
+ if line == "{\n":
+ return
+ vals = [
+ ("setskill ", "addtoskill "),
+ ("zeny", "Zeny"),
+ ("sc_poison", "SC_POISON"),
+ ("sc_slowpoison", "SC_SLOWPOISON"),
+ ("sex", "Sex"),
+ ("SEX", "Sex"),
+
+ (".gat", ""),
+ ("Bugleg", "BugLeg"),
+ ("set BugLeg, 0;", "//set BugLeg, 0;"),
+ ("set CaveSnakeLamp, 0;", "//set CaveSnakeLamp, 0;"),
+ ("set Class, @BaseClass;", "//set Class, @BaseClass;"),
+ ("goto_Exit;", "goto L_Exit;"),
+ ("if @spants_state < 7 goto", "if(@spants_state < 7) goto"),
+ ("isdead()", "ispcdead()"),
+ ("changeSex", "changecharsex()"),
+ ("getpartnerid2()", "getpartnerid()"),
+ ("getpartnerid2(0)", "getpartnerid()"),
+ ("getgmlevel(0)", "getgmlevel()"),
+ ("if @beer_count > 4", "if (@beer_count > 4)"),
+ ("if !(@Q_status)", "if (!(@Q_status))"),
+ ("if isin(\"021-1\", 130, 120, 140, 125) ", "if (isin(\"021-1\", 130, 120, 140, 125)) "),
+ ("if divorce(0) goto L_", "if (divorce()) goto L_"),
+
+ ("getmap()", "getmapname()"),
+ ("L_end", "L_End"),
+ ("gmcommand", "atcommand"),
+ ("MF_NOSAVE", "mf_nosave"),
+ ("S_update_var", "S_Update_Var"),
+ ("L_teach", "L_Teach"),
+ ("L_focus", "L_Focus"),
+ ("L_unfocus", "L_Unfocus"),
+ ("L_main", "L_Main"),
+ ("L_next", "L_Next"),
+ ("L_close", "L_Close"),
+ ("@NpcName$", "@npcname$"),
+ ("@npcName$", "@npcname$"),
+ ("@cost", "@Cost"),
+ ("@TEMP", "@temp"),
+ ("L_Menuitems", "L_MenuItems"),
+ ("L_no_item", "L_No_Item"),
+ ("L_no_water", "L_No_Water"),
+ ("L_NOT_ENOUGH", "L_No_Water"),
+ ("L_bye", "L_Bye"),
+ ("L_NOHELP", "L_NoHelp"),
+ ("L_Eyepatch", "L_EyePatch"),
+ ("@PC_STAMINA", "@pc_stamina"),
+ ("L_magic", "L_Magic"),
+ ("L_cont", "L_Cont"),
+ ("L_accept", "L_Accept"),
+ ("L_no_event", "L_No_Event"),
+ ("L_event_done", "L_Event_Done"),
+ ("L_nobeer", "L_NoBeer"),
+ ("L_iron", "L_Iron"),
+ ("L_sulphur", "L_Sulphur"),
+ ("L_red", "L_Red"),
+ ("L_yellow", "L_Yellow"),
+ ("L_green", "L_Green"),
+ ("L_orange", "L_Orange"),
+ ("L_pink", "L_Pink"),
+ ("L_purple", "L_Purple"),
+ ("L_question", "L_Question"),
+ ("L_quest", "L_Quest"),
+ ("L_dead", "L_Dead"),
+ ("L_menu", "L_Menu"),
+ ("L_give", "L_Give"),
+ ("@Items$", "@items$"),
+ ("@menuItems$", "@menuitems$"),
+ ("L_Teach_initial", "L_Teach_Initial"),
+ ("L_finish", "L_Finish"),
+ ("L_No_ash", "L_No_Ash"),
+ ("L_no_ash", "L_No_Ash"),
+ ("L_No_water", "L_No_Water"),
+ ("L_cave", "L_Cave"),
+ ("L_farewell", "L_Farewell2"),
+ ("@Q_forestbow_", "@Q_Forestbow_"),
+ ("L_game", "L_Game"),
+ ("L_good", "L_Good"),
+ ("L_abort", "L_Abort"),
+ ("@menuID", "@menuid"),
+ ("L_NO_ITEM", "L_No_Item"),
+ ("L_HELP", "L_Help"),
+ ("L_Noitem", "L_NoItem"),
+ ("L_No_fur", "L_No_Fur"),
+ ("@EXP", "@Exp"),
+ ("L_water", "L_Water"),
+ ("L_get", "L_Get"),
+ ("L_happy", "L_Happy"),
+ ("L_cheat", "L_Cheat"),
+ ("@Reward_EXP", "@Reward_Exp"),
+ ("@REWARD_EXP", "@Reward_Exp"),
+ ("L_no_money", "L_No_Money"),
+ ("@MinLevel", "@minLevel"),
+ ("L_return", "L_Return"),
+ ("L_intro", "L_Intro"),
+ ("L_full", "L_Full"),
+ ("@minlevel", "@minLevel"),
+ ("@MinLevel", "@minLevel"),
+ ("L_Cleanup", "L_CleanUp"),
+ ("L_Alreadystarted", "L_AlreadyStarted"),
+ ("@amount", "@Amount"),
+ ("L_again", "L_Again"),
+ ("L_no_potion", "L_No_Potion"),
+ ("L_wizard_hat", "L_Wizard_Hat"),
+ ("L_notenough", "L_NotEnough"),
+ ("L_offer", "L_Offer"),
+ ("L_giveup", "L_GiveUp"),
+ ("L_not_ready", "L_Not_Ready"),
+ ("@MobID", "@mobId"),
+ ("@mobID", "@mobId"),
+ ("L_naked", "L_Naked"),
+ ("L_shortcut", "L_Shortcut"),
+ ("L_shirt", "L_Shirt"),
+ ("L_goodjob", "L_GoodJob"),
+ ("L_kill", "L_Kill"),
+ ("L_nothing", "L_Nothing"),
+ ("L_lowlevel", "L_LowLevel"),
+ ("L_MENU", "L_Menu"),
+ ("L_potion", "L_Potion"),
+ ("L_fertig", "L_Fertig"),
+ ("L_exit", "L_Exit"),
+ ("L_fight", "L_Fight"),
+ ("L_start", "L_Start"),
+ ("L_unvollst", "L_Unvollst"),
+ ("L_no_room_for_rings", "L_No_Room_For_Rings"),
+ ("@mask", "@Mask"),
+ ("@MAP$", "@map$"),
+ ("baselevel", "BaseLevel"),
+ ("L_Lifestones_Trade_Missing", "L_Lifestones_TM"),
+ ("L_Caretaker_first_reward", "L_Caretaker_fr"),
+ ("L_NohMask_TravelingTroupe", "L_NohMask_TravT"),
+ ("L_listen_to_a_story_first", "L_listen_to_sf"),
+ ("L_post_ironpowder_option", "L_post_ip_op"),
+ ("L_Sulphur_teach_spell_no", "L_Sulphur_tspell"),
+ ("L_Lifestones_MakeSelf_yes", "L_Lifestones_MSy"),
+ ("L_Lifestones_MakeSelf_no", "L_Lifestones_MSn"),
+ ("L_Caretaker_later_rewards", "L_Caretaker_lr"),
+ ("L_boneknife_quest_completed", "L_boneknife_qc"),
+ ("L_boneknife_quest_tooweak", "L_boneknife_qtw"),
+ ("L_tanktop_insufficient_cloth", "L_tanktop_ic"),
+ ("L_dark_green_q_toolittle", "L_dark_greenqtit"),
+ ("L_about_schools_minimenu", "L_about_sch_mm"),
+ ("L_insufficient_BaseLevel", "L_insuf_BL"),
+ ("L_Teach_Initial_nonature", "L_Teach_Ininn"),
+ ("L_Teach_CheckAdvanceTo2_fail", "L_Teach_CATo2f"),
+ ("L_Levelup2_must_practice", "L_Levelup2_mpr"),
+ ("L_Airlia_intro_mana_loss", "L_Airlia_iml"),
+ ("L_knife_quest_completecheck", "L_knife_q_cc"),
+ ("L_Magic_purify_explained", "L_Magic_pur_exp"),
+ ("L_tanktop_insufficient_Zeny", "L_tanktop_ins_Z"),
+ ("L_monster_oil_knows_recipe", "L_monsteroil_kn_r"),
+ ("L_Teach_CheckAdvanceToLOH", "L_TeachChATLOH"),
+ ("L_knife_quest_missing_stingers", "L_knife_qm_sti"),
+ ("L_Magic_train_tree_backgd", "L_Mag_tr_tr_ba"),
+ ("SUB_pick_one_of_many_items", "SUB_pick_1_m_it"),
+ ("L_about_other_prerequisites", "L_a_o_prereq"),
+ ("L_monster_oil_why_dangerous", "L_monstero_w_dang"),
+ ("L_Teach_LOH_advance_abort0", "L_Teach_LOH_a_a0"),
+ ("L_Teach_LOH_advance_abort1", "L_Teach_LOH_a_a1"),
+ ("L_knife_quest_missing_mushrooms", "L_knife_q_m_mushr"),
+ ("L_Magic_train_sagatha_fail", "L_Magic_tsag_f"),
+ ("L_Q_manaseed_touched_short", "L_Q_manas_tou_sh"),
+ ("L_monster_oil_ingredients", "L_monsoil_ingr"),
+ ("L_snakeskins_completecheck", "L_snakes_comc"),
+ ("L_Magic_train_sagatha_lvl1", "L_Mag_tr_sag_lvl1"),
+ ("L_make_mana_potion_missing", "L_make_m_p_mis"),
+ ("L_monster_oil_where_gold", "L_monoil_wg"),
+ ("L_golden_scorpion_wrestle_intro", "L_gold_scor_wr_i"),
+ ("L_component_quest_missing", "L_comp_q_mis"),
+ ("L_monster_oil_start_brew", "L_monsto_st_br"),
+ ("L_golden_requires_knife_quest_done", "L_gold_req_kn_q_d"),
+ ("LL_student_4_wrong_potion", "L_stud_4_wrong_p"),
+ ("L_monster_oil_missing_gold", "L_monsto_mis_g"),
+ ("L_golden_requires_knife_quest", "L_gold_req_kn_q"),
+ ("LL_Magic_skill_insufficient", "L_Mag_sk_insuf"),
+ ("L_monster_oil_out_of_leaves", "L_monso_oo_lea"),
+ ("L_too_lowlevel_for_stinger", "L_too_lol_f_sti"),
+ ("L_monster_oil_leaf_color", "L_monso_le_co"),
+ ("L_golden_scorpion_over_ask", "L_gold_scor_ov_a"),
+ ("S_monster_oil_random_move", "L_monso_rand_mo"),
+ ("L_golden_scorpion_ask_again", "L_gold_scor_as_ag"),
+ ("L_monster_oil_random_0_lighten", "L_monso_rand_0_li"),
+ ("L_golden_scorpion_wrestle_again", "L_gold_scorp_wre_ag"),
+ ("L_monster_oil_explode_dodge", "L_monso_expl_dod"),
+ ("L_golden_scorpion_wrestle", "L_gold_scorp_wre"),
+ ("L_monster_oil_no_gold_end", "L_monso_no_go_e"),
+ ("L_mopox_cure_", "L_moc_"),
+ ("L_mopox_failed_", "L_mof_"),
+ # fix at same time usage with same name function and variable
+ ("\"DailyQuestPoints\"", "\"DailyQuestPointsFunc\""),
+ # TMW-BR errors
+ ("@cerveja", "@Cerveja"),
+ ("@custo", "@Custo"),
+ ("@genero", "@Genero"),
+ ("@gosmaVerme", "@GosmaVerme"),
+ ("@I", "@i"),
+ ("@valor", "@Valor"),
+
+ ("@peloBranco", "@PeloBranco"),
+ ("@pelobranco", "@PeloBranco"),
+ ("@raiz", "@Raiz"),
+ ("@senha", "@Senha"),
+ ("@garrafaVazia", "@GarrafaVazia"),
+ ("@GAMBOGE", "@Gamboge"),
+ ("@FM$", "@fm$"),
+ ("L_abrir", "L_Abrir"),
+ ("L_Abrir", "L_Abrir"),
+ ("L_acabou", "L_Acabou"),
+ ("L_ACABOU", "L_Acabou"),
+ ("L_Aceita", "L_Aceita"),
+ ("L_aceita", "L_Aceita"),
+ ("L_AceitaCapaceteDeMineiro", "L_AceitaCapMineiro"),
+ ("L_AceitaShortDeAlgodao", "L_AceitaShortAlgodao"),
+ ("L_AceitoFlechasDeFerro", "L_AceitaFlechaFerro"),
+ ("L_AceitoFlechasNormais", "L_AceitaFlechaNormal"),
+ ("L_Aceitou", "L_Aceitou"),
+ ("L_aceitou", "L_Aceitou"),
+ ("L_adicionar_registro_AGE", "L_addreg_AGE"),
+ ("L_adicionar_registro_GP", "L_addreg_GP"),
+ ("L_adicionar_registro_LVL", "L_addreg_LVL"),
+ ("L_Ajuda", "L_Ajuda"),
+ ("L_ajuda", "L_Ajuda"),
+ ("L_ajudaComMaisPresentes2", "L_AjudaMaisPresentes2"),
+ ("L_ajudaComMaisPresentes", "L_AjudaMaisPresentes"),
+ ("L_Apresentacao", "L_Apresentacao"),
+ ("L_apresentacao", "L_Apresentacao"),
+ ("L_Arco", "L_Arco"),
+ ("L_arco", "L_Arco"),
+ ("L_Azul", "L_Azul"),
+ ("L_azul", "L_Azul"),
+ ("L_boneknife_quest_completed", "L_BoneKnife_Completo"),
+ ("L_boneknife_quest_tooweak", "L_BoneKnife_Fraco"),
+ ("L_buscar_e_adicionar_AGE", "L_seekadd_AGE"),
+ ("L_buscar_e_adicionar_GP", "L_seekadd_GP"),
+ ("L_buscar_e_adicionar_LVL", "L_seekadd_LVL"),
+ ("L_buscar_e_selecionar_AGE", "L_seeksel_AGE"),
+ ("L_buscar_e_selecionar_GP", "L_seeksel_GP"),
+ ("L_buscar_e_selecionar_LVL", "L_seeksel_LVL"),
+ ("L_Check", "L_Check"),
+ ("L_CHECK", "L_Check"),
+ ("L_cheio", "L_Cheio"),
+ ("L_CHEIO", "L_Cheio"),
+ ("L_Close", "L_close"),
+ ("L_close", "L_close"),
+ ("L_coelhoProcurandoOvos", "L_CoelhoProcuraOvos"),
+ ("L_ComGrana", "L_ComGrana"),
+ ("L_comgrana", "L_ComGrana"),
+ ("L_comprimenta_conhecendo", "L_CumprimentaSabe"),
+ ("L_Concluida", "L_Concluida"),
+ ("L_concluida", "L_Concluida"),
+ ("L_confirmacao_invalida", "L_Inv_Conf"),
+ ("L_Congratulacoes", "L_Congratulacao"),
+ ("L_congratulacoes", "L_Congratulacao"),
+ ("L_Continua", "L_Continua"),
+ ("L_continua", "L_Continua"),
+ ("L_continua_destransformar", "L_Continua_destransf"),
+ ("L_Continua_destransformar", "L_Continua_destransf"),
+ ("L_continuacao", "L_Continuacao"),
+ ("L_Continuacao", "L_Continuacao"),
+ ("L_controlarNacionalidade", "L_ControlaNacao"),
+ ("L_ControlarNacionalidade", "L_ControlaNacao"),
+ ("L_conversa_com_garotas", "L_ConvesaGarota"),
+ ("L_conversa_com_garotos", "L_ConversaGaroto"),
+ ("L_cor", "L_Cor"),
+ ("L_Cor", "L_Cor"),
+ ("L_Curar", "L_Curar"),
+ ("L_curar", "L_Curar"),
+ ("L_dark_green_q_explain2", "L_VerdeEscuro_qexp2"),
+ ("L_dark_green_q_explain", "L_VerdeEscuro_qexp"),
+ ("L_dark_green_q_guess_0", "L_VerdeEscuro_qguess"),
+ ("L_dark_green_q_noslime", "L_VerdeEscuro_noslim"),
+ ("L_dark_green_q_toolittle", "L_VerdeEscuro_pouco"),
+ ("L_dark_green_q_toomuch", "L_VerdeEscuro_muito"),
+ ("L_dep_tudo", "L_Dep_Tudo"),
+ ("L_dep_Tudo", "L_Dep_Tudo"),
+ ("L_DesistenteSelecionado", "L_DesistSel"),
+ ("L_Desistir", "L_Desistir"),
+ ("L_desistir", "L_Desistir"),
+ ("L_desistir_de_assinar2", "L_DesistirAssinar2"),
+ ("L_DICA", "L_Dica"),
+ ("L_Dica", "L_Dica"),
+ ("L_dica", "L_Dica"),
+ ("L_Encontrei", "L_Encontrei"),
+ ("L_encontrei", "L_Encontrei"),
+ ("L_End", "L_End"),
+ ("L_end", "L_end"),
+ ("L_engana_player_novamente", "L_Engana2"),
+ ("L_EQUIP", "L_Equip"),
+ ("L_Equip", "L_Equip"),
+ ("L_ErrouPalavrasMagicas", "L_ErrouMagia2"),
+ ("L_explicacao", "L_Explicacao"),
+ ("L_Explicacao", "L_Explicacao"),
+ ("L_ExplicacaoCausaCrise", "L_ExplicacaoCrise"),
+ ("L_Explicar", "L_Explicar"),
+ ("L_explicar", "L_Explicar"),
+ ("L_fala2", "L_Fala2"),
+ ("L_Fala2", "L_Fala2"),
+ ("L_Fala", "L_Fala"),
+ ("L_fala", "L_Fala"),
+ ("L_falasRestauracaoErro", "L_FalaRestauraErro"),
+ ("L_Falta", "L_Falta"),
+ ("L_falta", "L_Falta"),
+ ("L_falta_ovos_novamente", "L_FaltaOvos2"),
+ ("L_Fechar", "L_Fechar"),
+ ("L_fechar", "L_Fechar"),
+ ("L_Fim", "L_Fim"),
+ ("L_fim", "L_Fim"),
+ ("L_FIM", "L_Fim"),
+ ("L_FimListaDesconectados", "L_FimListaOff"),
+ ("L_Fraco", "L_Fraco"),
+ ("L_fraco", "L_Fraco"),
+ ("L_FRACO", "L_Fraco"),
+ ("L_GanhaPartyParticipar", "L_GanhaPartyP"),
+ ("L_golden_requires_knife_quest", "L_Ouroreq_Knife_q"),
+ ("L_golden_requires_knife_quest_done", "L_Ouroreq_Kinfe_ok"),
+ ("L_golden_scorpion_ask_again", "L_EscorpOuro_again"),
+ ("L_golden_scorpion_over_ask", "L_EscorpOuro_overask"),
+ ("L_golden_scorpion_wrestle", "L_EscorpOuro_Wrest"),
+ ("L_golden_scorpion_wrestle_again", "L_EscorpOuro_Wrest2"),
+ ("L_golden_scorpion_wrestle_intro", "L_EscorpOuro_WerestI"),
+ ("L_HistoriaAdagaBoneClaide", "L_HistoriaAdagaBC"),
+ ("L_Info", "L_Info"),
+ ("L_info", "L_Info"),
+ ("L_iniciaQuest", "L_IniciaQuest"),
+ ("L_IniciaQuest", "L_IniciaQuest"),
+ ("L_Inicio", "L_Inicio"),
+ ("L_inicio", "L_Inicio"),
+ ("L_Inicio_Segunda_Parte", "L_Inicio_P2"),
+ ("L_INSUF", "L_Insuf"),
+ ("L_insuf", "L_Insuf"),
+ ("L_Introfloresta", "L_IntroFloresta"),
+ ("L_introFloresta", "L_IntroFloresta"),
+ ("L_introfloresta", "L_IntroFloresta"),
+ ("L_itens", "L_Itens"),
+ ("L_Itens", "L_Itens"),
+ ("L_jaParticipandoPartida", "L_JaPartPart"),
+ ("L_knife_quest_completecheck", "L_Knife_CompCheck"),
+ ("L_knife_quest_missing_mushrooms", "L_Knife_MissMush"),
+ ("L_knife_quest_missing_mushrooms_2", "L_Knife_MissMush2"),
+ ("L_knife_quest_missing_stingers", "L_Knife_MissSting"),
+ ("L_knife_quest_missing_stingers_2", "L_Knife_MissSting2"),
+ ("L_limpar", "L_Limpar"),
+ ("L_Limpar", "L_Limpar"),
+ ("L_lista", "L_Lista2"),
+ ("L_listen_to_a_story_first", "L_ListenStory"),
+ ("L_longe", "L_Longe"),
+ ("L_LONGE", "L_Longe"),
+ ("L_loop_buscar_desconectados", "L_LoopOff"),
+ ("L_loop_buscar_lutadores2", "L_LoopLutador2"),
+ ("L_loop_buscar_lutadores", "L_LoopLutador"),
+ ("L_main_menu_post_setzer", "L_MM_PostSetzer"),
+ ("L_maisDoces //< pede o dobro de itens e dá o dobro de XP.", "L_MaisDoces //< pede o dobro de itens e dá o dobro de XP."),
+ ("L_Menu", "L_Menu"),
+ ("L_menu", "L_Menu"),
+ ("L_menuGM", "L_MenuGM"),
+ ("L_menugm", "L_MenuGM"),
+ ("L_MenuGM", "L_MenuGM"),
+ ("L_Menugm", "L_MenuGM"),
+ ("L_MenuItens", "L_MenuItens"),
+ ("L_menuItens", "L_MenuItens"),
+ ("L_missaoCogumeloCompleta", "L_MissCog_Ok"),
+ ("L_missaoCordaPescador1", "L_MissCorda_1"),
+ ("L_missaoCordaPescador2", "L_MissCorda_2"),
+ ("L_missaoEscudoMadeira1", "L_MissEscudMad_1"),
+ ("L_missaoEscudoMadeira2", "L_MissEscudMad_2"),
+ ("L_missaoMadeiraResistente", "L_MissMadeiraR"),
+ ("L_missaoMadeiraResistenteCompleta", "L_MissMadeiraR_Ok"),
+ ("L_missaoMaisPresentesCompleta", "L_MissMaisPresenteOK"),
+ ("L_missaoPocaoQueimadura", "L_MissPotQueim"),
+ ("L_missaoPresentesCompleta", "L_MissPresenteOk"),
+ ("L_MOBS_queimaduraEscorpiao", "L_MOB_QueimEscorp"),
+ ("L_nada", "L_Nada2"),
+ ("L_nao", "L_Nao2"),
+ ("L_naoPode", "L_NaoPode"),
+ ("L_naoSei", "L_NaoSei"),
+ ("L_naotenho", "L_NaoTenho"),
+ ("L_Naotenho", "L_NaoTenho"),
+ ("L_naoTrouxe", "L_NaoTrouxe"),
+ ("L_naotrouxe", "L_NaoTrouxe"),
+ ("L_Naotrouxe", "L_NaoTrouxe"),
+ ("L_novaPartida", "L_NovaPartida2"),
+ ("L_NovaPartida", "L_NovaPartida"),
+ ("L_novorecordindividual", "L_NovoRecordSeu"),
+ ("L_obrigado", "L_Obrigado2"),
+ ("L_obsidian_spork_intro", "L_ObsidianSporkIntro"),
+ ("L_OK", "L_Ok2"),
+ ("L_ok", "L_Ok3"),
+ ("L_onde", "L_Onde"),
+ ("L_opcaoFinalizarPartida", "L_opFimPart"),
+ ("L_opcaoIniciaPartidaErro", "L_opIniPartErro"),
+ ("L_opcaoParticipaJogoErro", "L_opPartJogoErro"),
+ ("L_Participante_Invalido", "L_Partc_Invalido"),
+ ("L_Participante_Perdedor", "L_Partc_Perde"),
+ ("L_Participante_Vencedor", "L_partc_Vence"),
+ ("L_pobre", "L_Pobre"),
+ ("L_porque", "L_Porque"),
+ ("L_possuiFragmento", "L_PossuiFragmento"),
+ ("L_preciso", "L_Preciso"),
+ ("L_PrecoPartyParticipar", "L_PrecoPartyPart"),
+ ("L_presente", "L_Presente"),
+ ("L_PrometeVoltarComGRana", "L_VoltoComGp"),
+ ("L_pronto", "L_Pronto"),
+ ("L_quem", "L_Quem"),
+ ("L_QueroArcoDeCurtoAlcance", "L_ArcoCurto"),
+ ("L_ReexplicaApostaParaCobrir", "L_ExpApostaCobrir"),
+ ("L_ReexplicaApostaParaIniciar", "L_ExpApostaIniciar"),
+ ("L_ret_tudo", "L_Ret_Tudo"),
+ ("L_ret_Tudo", "L_Ret_Tudo"),
+ ("L_retirar", "L_Retirar"),
+ ("L_retorno", "L_Retorno"),
+ ("L_retorno_Doces_Escondidos", "L_Retorno_DoceHid"),
+ ("L_Retorno_Segunda_Parte", "L_Retorno_Part2"),
+ ("L_return", "L_Return"),
+ ("L_rever", "L_Rever"),
+ ("L_rico", "L_Rico"),
+ ("L_saia", "L_Saia"),
+ ("L_salvar", "L_Salvar"),
+ ("L_Segunda_Parte_MaisPirulitos", "L_P2_MaisPirulito"),
+ ("L_Segunda_Parte_NaoPirulito", "L_P2_NaoPirulito"),
+ ("L_Segunda_Parte_Pirulito", "L_P2_Pirulito"),
+ ("L_Segunda_Parte_Satisfeito", "L_P2_Satisfeito"),
+ ("L_selecionar_registro_AGE", "L_selreg_AGE"),
+ ("L_selecionar_registro_GP", "L_selreg_GP"),
+ ("L_selecionar_registro_LVL", "L_selreg_LVL"),
+ ("L_semEspaco", "L_SemEspaco"),
+ ("L_semGrana", "L_SemGrana"),
+ ("L_semgrana", "L_SemGrana"),
+ ("L_semItem", "L_SemItem"),
+ ("L_semItens", "L_SemItens"),
+ ("L_semLevel", "L_SemLevel"),
+ ("L_semlevel", "L_SemLevel"),
+ ("L_semlugar", "L_SemLugar"),
+ ("L_semLugar", "L_SemLugar"),
+ ("L_semLvl", "L_SemLvl"),
+ ("L_semLVL", "L_SemLvl"),
+ ("L_SemLVL", "L_SemLvl"),
+ ("L_set", "L_Set"),
+ ("L_SET", "L_Set"),
+ ("L_ShieldNoLeatherPatch", "L_ShdNoLeathPatch"),
+ ("L_sim2", "L_Sim2"),
+ ("L_sim3", "L_Sim3"),
+ ("L_sim", "L_Sim"),
+ ("L_Nao2trouxe", "L_Nao2Trouxe"),
+ ("L_snakeskins_completecheck", "L_snakeskin_okcheck"),
+ ("L_SugerePesquisaDePreco", "L_PesquisePreco"),
+ ("L_tchau2", "L_Tchau2"),
+ ("L_tchau", "L_Tchau"),
+ ("L_This_shouldn_t_happen", "L_NaoDeviaAcontecer"),
+ ("L_too_lowlevel_for_stinger", "L_Stinger_LvlBaixo"),
+ ("L_verde", "L_Verde"),
+ ("L_verificaMaisPresentes", "L_MaisPresenteCheck"),
+ ("L_VOLTA", "L_Volta"),
+ ("L_voltaCheckIngredientes", "L_VoltaCheckItens"),
+ ("L_voltaComIngredientes", "L_VoltaComItens"),
+ ("L_warp", "L_Warp2"),
+ ("L_minissaia", "L_Minissaia"),
+ ("L_preMenu", "L_PreMenu"),
+ ("L_Regras", "L_regras"),
+ ("S_MOBS_queimaduraEscorpiao", "S_MOBS_QueimEscorp"),
+ ("S_MOBS_queimaduraTartaruga", "S_MOBS_QueimTartaruga"),
+ ("Refinamento \\+\" + (@menu", "Refinamento \" + (@menu"),
+ ("Bom! \Aqui vou eu...", "Bom! Aqui vou eu..."),
+ ("\\:\";", ":\";"),
+ ("if BaseLevel <= 10, set", "if (BaseLevel <= 10) set"),
+ ("\\: Passando", ": Passando"),
+ ("\\o/", "o/"),
+ ("(getgmlevel ==", "(getgmlevel() =="),
+ ("foice", "Foice"),
+ ("lanternaJack", "LanternaJack"),
+ ("0), set @preco, ", "0) set @preco, "),
+ ("255), set @preco, ", "255) set @preco, "),
+ ("L_pass", "L_Pass"),
+ ("Quest_threepwood1", "QUEST_threepwood1"),
+ ("L_no", "L_No"),
+ ("L_askHelp", "L_AskHelp"),
+ ("L_ask", "L_Ask"),
+ ("L_notEnough", "L_NotEnough"),
+ ("L_done", "L_Done"),
+ ("L_toomany", "L_TooMany"),
+ ("L_not_enough_money", "L_Not_enough_money"),
+ ("L_island", "L_Island"),
+ ("if @colorID == 2 ", "if (@colorID == 2) "),
+ ("L_help", "L_Help"),
+ ("L_yes", "L_Yes"),
+ ("if @opacityID == 2 ", "if (@opacityID == 2) "),
+ ("L_NohMask_Accuse_Respond", "L_NohMask_AResp"),
+ ("if @opacityID > 4 ", "if (@opacityID > 4) "),
+ ("if @tmpHairStyle > 0 ", "if (@tmpHairStyle > 0) "),
+ ("if @colorID > 6 ", "if (@colorID > 6) "),
+ ("if @opacityID < 0 ", "if (@opacityID < 0) "),
+ ("if countitem(\"MaggotSlime\") >= 10 goto", "if (countitem(\"MaggotSlime\") >= 10) goto"),
+ ("if @colorID < 0 set", "if (@colorID < 0) set"),
+ ];
+
+ for val in vals:
+ line = line.replace(val[0], val[1]);
+
+ idx = line.find("getmapmobs(")
+ if idx >= 0:
+ idx2 = line.find("\"", idx + len("getmapmobs(") + 1)
+ idx3 = line.find(")", idx + len("getmapmobs(") + 1)
+ if idx2 + 1 == idx3:
+ line = line[:idx2 + 1] + ",\"all\"" + line[idx2 + 1:]
+
+ line = line.replace("getmapmobs(", "mobcount(")
+
+ m = setRe.search(line);
+ if m != None:
+ line = "{0}{1} = {2};\n".format(m.group("space"), m.group("var"), m.group("val"))
+
+ w.write(line)
+
diff --git a/hercules/code/server/utils.py b/hercules/code/server/utils.py
new file mode 100644
index 0000000..ebbddf3
--- /dev/null
+++ b/hercules/code/server/utils.py
@@ -0,0 +1,12 @@
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2014 Evol Online
+# Author: Andrei Karas (4144)
+
+from code.fileutils import removeAllFiles, makeDir
+
+def cleanServerData():
+ removeAllFiles("newserverdata")
+ makeDir("newserverdata/conf")
+ makeDir("newserverdata/db/re/")
+ makeDir("newserverdata/npc/re/")
diff --git a/hercules/code/servertoclient/__init__.py b/hercules/code/servertoclient/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/hercules/code/servertoclient/__init__.py
diff --git a/hercules/code/servertoclient/groups.py b/hercules/code/servertoclient/groups.py
new file mode 100644
index 0000000..99424e5
--- /dev/null
+++ b/hercules/code/servertoclient/groups.py
@@ -0,0 +1,185 @@
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2017 Evol Online
+# Author: Andrei Karas (4144)
+
+import re
+
+from code.fileutils import makeDir, readFile, saveFile
+
+nameSplit = re.compile(":")
+comaSplit = re.compile(",")
+
+class Groups:
+ pass
+
+def readLine(f):
+ for line in f:
+ if len(line) == 0:
+ continue
+ if line[-1:] == "\n":
+ line = line[:-1]
+ idx = line.find("/*")
+ if idx >= 0:
+ line = line[:idx]
+ line = line.strip()
+ yield line
+
+def skipFor(data, f):
+ for line in readLine(f):
+ if line == data or line == data + "\n":
+ return True
+ return False
+
+def readCommands(f):
+ commands = dict()
+ for line in readLine(f):
+ if line == "}":
+ return commands
+ parts = nameSplit.split(line)
+ if len(parts) != 2:
+ continue
+ name = parts[0].strip()
+ value = parts[1].strip()
+ idx1 = value.find("[")
+ if idx1 < 0:
+ commands[name] = (value, "false")
+ else:
+ idx2 = value.find("]")
+ value = value[idx1 + 1: idx2 - idx1]
+ parts = comaSplit.split(value)
+ commands[name] = (parts[0].strip(), parts[1].strip())
+ print "command: {0}, {1}".format(name, commands[name])
+ return commands
+
+def readPermissions(f):
+ permissions = dict()
+ for line in readLine(f):
+ if line == "}":
+ return permissions
+ parts = nameSplit.split(line)
+ if len(parts) != 2:
+ continue
+ name = parts[0].strip()
+ value = parts[1].strip()
+ permissions[name] = value
+ print "permission: {0}, {1}".format(name, value)
+ return permissions
+
+def readInherit(data):
+ inherit = set()
+ idx1 = data.find("(")
+ idx2 = data.find(")")
+ data = data[idx1 + 1: idx2 - idx1]
+ parts = comaSplit.split(data)
+ for field in parts:
+ field = field.strip()
+ if field == "":
+ continue
+ inherit.add(field)
+ return inherit
+
+def readGroup(groups, f):
+ fields = dict()
+ commands = dict()
+ permissions = dict()
+ inherit = set()
+ for line in readLine(f):
+ if line == "}" or line == "},":
+ groups.nameToId[fields["name"]] = fields["id"]
+ groups.idToFields[fields["id"]] = fields
+ groups.idToCommands[fields["id"]] = commands
+ groups.idToPermissions[fields["id"]] = permissions
+ groups.idToInherit[fields["id"]] = inherit
+ groups.idToNames[fields["id"]] = fields["name"]
+ return
+ parts = nameSplit.split(line)
+ if len(parts) != 2:
+ continue
+ name = parts[0].strip()
+ value = parts[1].strip()
+ print "line: {0}, {1}".format(name, value)
+ if name == "id":
+ fields["id"] = value
+ elif name == "name":
+ fields["name"] = value
+ elif name == "commands":
+ commands = readCommands(f)
+ print "Commands: {0}".format(commands)
+ elif name == "permissions":
+ permissions = readPermissions(f)
+ print "Permissions: {0}".format(permissions)
+ elif name == "inherit":
+ inherit = readInherit(value)
+ print "Inherit: {0}".format(inherit)
+
+def getCommandType(data):
+ if data[0] == "false" and data[1] == "false":
+ return "false"
+ elif data[0] == "false" and data[1] == "true":
+ return "other";
+ elif data[0] == "true" and data[1] == "false":
+ return "self"
+ elif data[0] == "true" and data[1] == "true":
+ return "both"
+
+def getCommandsStr(commands):
+ data = ""
+ commandFormat = "\n <command name=\"{0}\" use=\"{1}\" />"
+ for command in commands:
+ data = data + commandFormat.format(
+ command,
+ getCommandType(commands[command])
+ )
+ return data
+
+def getPermissionsStr(permissions):
+ data = ""
+ permissionFormat = "\n <permission name=\"{0}\" />"
+ for permission in permissions:
+ data = data + permissionFormat.format(
+ permission
+ )
+ return data
+
+def getInheritStr(inherits, names):
+ data = ""
+ if len(inherits) == 0:
+ return ""
+ for name in inherits:
+ if data != "":
+ data = data + ","
+ data += names[name]
+ return "\n inherit=\"{0}\"".format(data)
+
+def convertGroups():
+ destDir = "clientdata/"
+ templatesDir = "templates/"
+ groupsConfFile = "serverdata/conf/groups.conf"
+ makeDir(destDir)
+ tpl = readFile(templatesDir + "group.tpl")
+ groupsTpl = readFile(templatesDir + "groups.xml")
+ groups = Groups()
+ groups.nameToId = dict()
+ groups.idToFields = dict()
+ groups.idToCommands = dict()
+ groups.idToPermissions = dict()
+ groups.idToNames = dict()
+ groups.idToInherit = dict()
+
+ with open(groupsConfFile, "r") as f:
+ skipFor("groups: (", f)
+ while (skipFor("{", f) == True):
+ readGroup(groups, f)
+
+ data = ""
+ for ids in sorted(groups.idToFields):
+ data = data + tpl.format(
+ id = ids,
+ name = groups.idToNames[ids],
+ inherit = getInheritStr(groups.idToInherit[ids], groups.nameToId),
+ commands = getCommandsStr(groups.idToCommands[ids]),
+ permissions = getPermissionsStr(groups.idToPermissions[ids]),
+ )
+
+ saveFile(destDir + "groups.xml", groupsTpl.format(data))
diff --git a/hercules/code/servertoclient/homunculuses.py b/hercules/code/servertoclient/homunculuses.py
new file mode 100644
index 0000000..678a96c
--- /dev/null
+++ b/hercules/code/servertoclient/homunculuses.py
@@ -0,0 +1,31 @@
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2014 Evol Online
+# Author: Andrei Karas (4144)
+
+import re
+
+from code.fileutils import makeDir, readFile, saveFile
+
+def convertHomunculuses():
+ destDir = "clientdata/"
+ templatesDir = "templates/"
+ homunculusesDbFile = "serverdata/db/re/homunculus_db.txt"
+ fieldsSplit = re.compile(",")
+ makeDir(destDir)
+ tpl = readFile(templatesDir + "homunculus.tpl")
+ homunculuses = readFile(templatesDir + "homunculuses.xml")
+ data = ""
+ homunculusSprite = "<sprite>monsters/tortuga.xml</sprite>";
+ with open(homunculusesDbFile, "r") as f:
+ for line in f:
+ if line == "" or line[0:2] == "//":
+ continue
+ rows = fieldsSplit.split(line)
+ if len(rows) < 9:
+ continue
+ data = data + tpl.format(
+ id = rows[0],
+ sprite = homunculusSprite,
+ name = rows[2])
+ saveFile(destDir + "homunculuses.xml", homunculuses.format(data))
diff --git a/hercules/code/servertoclient/items.py b/hercules/code/servertoclient/items.py
new file mode 100644
index 0000000..3fdb531
--- /dev/null
+++ b/hercules/code/servertoclient/items.py
@@ -0,0 +1,138 @@
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2014 Evol Online
+# Author: Andrei Karas (4144)
+
+import re
+from sets import Set
+
+from code.fileutils import makeDir, readFile, saveFile
+from code.stringutils import stripQuotes2, strToXml
+
+def prepStat(val, text):
+ if val != "0" and val != "":
+ return " {0}=\"{1}\"\n".format(text, val)
+ return ""
+
+def convertItems():
+ destDir = "clientdata/"
+ templatesDir = "templates/"
+ itemsDbFile = "serverdata/sql-files/item_db_re.sql"
+ fieldsSplit = re.compile(",")
+ bracketsSplit = re.compile("[(]|[)]")
+ makeDir(destDir)
+ tpl = readFile(templatesDir + "item.tpl")
+ items = readFile(templatesDir + "items.xml")
+ data = ""
+ ids = Set()
+ with open(itemsDbFile, "r") as f:
+ for line in f:
+ if len(line) < 10 or line[0:2] == "//" or line[0:12] != "REPLACE INTO":
+ continue
+ rows = bracketsSplit.split(line)
+ if len(rows) < 2:
+ continue
+ rows = fieldsSplit.split(rows[1])
+ if len(rows) < 31:
+ continue
+ rows = stripQuotes2(rows)
+ itemId = rows[0]
+ name = rows[1]
+# name2 = rows[2]
+ itemType = rows[3]
+# priceBuy = rows[4]
+# priceSell = rows[5]
+ weight = rows[6]
+ atk = rows[7]
+ matk = rows[8]
+ defense = rows[9]
+ attackRange = rows[10]
+# slots = rows[11]
+# equipJobs = rows[12]
+# equipUpper = rows[12]
+# equipGender = rows[14]
+ equipLocations = rows[15]
+# weaponLevel = rows[16]
+# equipLevelMin = rows[17]
+# equipLevelMax = rows[18]
+# refinable = rows[19]
+ view = rows[20]
+# bindOnEquip = rows[21]
+# buyInStore = rows[22]
+ delay = rows[23]
+# tradeFlag = rows[24]
+# tradeGroup = rows[25]
+# nouseFlag = rows[26]
+# nouseGroup = rows[27]
+# stackAmount = rows[28]
+# stackFlag = rows[29]
+# sprite = rows[30]
+
+ name = name.replace("\\'", "'")
+ image = ""
+
+ statStr = prepStat(atk, "attack")
+ statStr = statStr + prepStat(matk, "mattack")
+ statStr = statStr + prepStat(defense, "defense")
+ statStr = statStr + prepStat(weight, "weight")
+ statStr = statStr + prepStat(attackRange, "range")
+ statStr = statStr + prepStat(delay, "speed")
+# print itemId + "," + equipLocations
+# typeStr = "other"
+ typeStr = "equip-legs"
+ spriteStr = "equipment/legs/trousers-male.xml"
+ image = "generic/box-fish.png"
+ if itemType == 0 or itemType == 2 or itemType == 18: # usable
+ image = "usable/bread.png"
+ typeStr = "usable"
+ spriteStr = "";
+ elif equipLocations == "0":
+ image = "usable/bread.png"
+ typeStr = "usable"
+ spriteStr = "";
+ elif equipLocations == "1":
+ image = "equipment/legs/shorts.png|S:#4d4d4d,514d47,686868,706662,919191,99917b,b6b6b6,c0b698,dfdfdf,e4dfca"
+ typeStr = "equip-legs"
+ spriteStr = "equipment/legs/shorts-male.xml|#4d4d4d,514d47,686868,706662,919191,99917b,b6b6b6,c0b698,dfdfdf,e0d5bf";
+ elif equipLocations == "2":
+ image = "equipment/weapons/knife.png"
+ typeStr = "equip-1hand"
+ spriteStr = "equipment/weapons/knife.xml";
+ elif equipLocations == "4":
+ image = "equipment/hands/armbands.png"
+ typeStr = "equip-arms"
+ spriteStr = "equipment/hands/armbands-male.xml";
+ elif equipLocations == "16":
+ image = "equipment/chest/cottonshirt.png|S:#3c3c3c,3e3c38,4d4d4d,514d47,686868,706662,919191,99917b,b6b6b6,c0b698,dfdfdf,e4dfca"
+ typeStr = "equip-torso"
+ spriteStr = "equipment/chest/cottonshirt-male.xml|#43413d,59544f,7a706c,8a8176,a69e88,d1c7a7,e0d5bf";
+ elif equipLocations == "64":
+ image = "equipment/feet/boots.png|S:#3c3c3c,40332d,4d4d4d,5e4a3d,686868,705740,919191,a1825d,b6b6b6,b59767,dfdfdf,dbbf88"
+ typeStr = "equip-feet"
+ spriteStr = "equipment/feet/boots-male.xml|#40332d,5e4a3d,705740,a1825d,b59767,dbbf88";
+ elif equipLocations == "136":
+ image = "equipment/chest/cottonshirt.png|S:#3c3c3c,3e3c38,4d4d4d,514d47,686868,706662,919191,99917b,b6b6b6,c0b698,dfdfdf,e4dfca"
+ typeStr = "equip-torso"
+ spriteStr = "equipment/chest/cottonshirt-male.xml|#43413d,59544f,7a706c,8a8176,a69e88,d1c7a7,e0d5bf";
+ elif equipLocations == "256":
+ image = "equipment/head/bandana.png"
+ typeStr = "equip-head"
+ spriteStr = "equipment/head/bandana-male.xml";
+ elif equipLocations == "512":
+ # no sprites in evol
+ image = "equipment/chest/sailorshirt.png"
+ typeStr = "equip-torso"
+ spriteStr = "equipment/chest/shirt-male.xml|#131913,1b231d,233129,35433e,4e6059,6c8279;#72571e,836737,a5854d,b18f45";
+
+ name = strToXml(name);
+
+ if itemId not in ids:
+ ids.add(itemId)
+ data = data + tpl.format(itemId, name, 0,
+ statStr, image, typeStr, spriteStr)
+ if view != "0" and view not in ids:
+ ids.add(view)
+ data = data + tpl.format(view, name, 0,
+ statStr, image, typeStr, spriteStr)
+
+ saveFile(destDir + "items.xml", items.format(data))
diff --git a/hercules/code/servertoclient/luas.py b/hercules/code/servertoclient/luas.py
new file mode 100644
index 0000000..8b401b7
--- /dev/null
+++ b/hercules/code/servertoclient/luas.py
@@ -0,0 +1,51 @@
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2015 Evol Online
+# Author: Andrei Karas (4144)
+
+import re
+
+comaSplit = re.compile(",")
+equalSplit = re.compile("=")
+
+def extractLuaArray(fileName, arrName):
+ with open(fileName, "r") as f:
+ for line in f:
+ if line.find(arrName) == 0:
+ line = line[line.find("{") + 1:]
+ line = line[:line.find("}")]
+ return line
+ return ""
+
+def convertJobName():
+ jobs = dict()
+ jobNameFile = "rodata/decompiled/jobname.lua"
+ line = extractLuaArray(jobNameFile, "JobNameTable")
+ arr = comaSplit.split(line)
+ for itemStr in arr:
+ parts = equalSplit.split(itemStr.strip())
+ if parts[0].find("[jobtbl.") == 0:
+ key = parts[0].strip()
+ key = key[8:-1].strip()
+ val = parts[1].strip()
+ val = val[1:-1].strip()
+ jobs[key] = val
+ return jobs
+
+def convertIdentity(jobs):
+ idents = dict()
+ npcIdentityFile = "rodata/decompiled/npcidentity.lua"
+ line = extractLuaArray(npcIdentityFile, "jobtbl = ")
+ arr = comaSplit.split(line)
+ for itemStr in arr:
+ parts = equalSplit.split(itemStr.strip())
+ key = parts[0].strip()
+ val = parts[1].strip()
+ if key in jobs:
+ idents[val] = jobs[key].lower()
+ return idents
+
+def convertLuas():
+ jobs = convertJobName()
+ idtofile = convertIdentity(jobs)
+ return idtofile
diff --git a/hercules/code/servertoclient/maps.py b/hercules/code/servertoclient/maps.py
new file mode 100644
index 0000000..0f1ca5b
--- /dev/null
+++ b/hercules/code/servertoclient/maps.py
@@ -0,0 +1,48 @@
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2014 Evol Online
+# Author: Andrei Karas (4144)
+
+import zlib
+
+from code.fileutils import readInt16, readInt32, makeDir, copyFile, readFile, readMapName, saveFile, readData
+from code.tileutils import getTileData, getTile
+
+def covertToTmx(f, mapsCount):
+ destDir = "clientdata/"
+ mapsDir = destDir + "maps/"
+ tilesetsDir = destDir + "graphics/tilesets/"
+ templatesDir = "templates/"
+ makeDir(mapsDir)
+ makeDir(tilesetsDir)
+ copyFile(templatesDir, tilesetsDir, "collision.png")
+ copyFile(templatesDir, tilesetsDir, "tileset.png")
+ tmx = readFile("templates/template.tmx")
+ for i in xrange(0, mapsCount):
+ name = readMapName(f)
+ print "converting map [{0:4}/{1:4}]: {2}".format(i, mapsCount + 1, name)
+ sx = readInt16(f)
+ sy = readInt16(f)
+ sz = readInt32(f)
+ mapData = readData(f, sz)
+ dc = zlib.decompressobj()
+ mapData = dc.decompress(mapData)
+ ground = ""
+ collision = ""
+ fringe = ""
+ for y in xrange(0, sy):
+ for x in xrange(0, sx):
+ tileData = getTileData(mapData, x, y, sx)
+ tile = getTile(tileData)
+ if x + 1 == sx and y + 1 == sy:
+ ground = ground + tile[0]
+ collision = collision + tile[1]
+ fringe = fringe + "0";
+ else:
+ ground = ground + tile[0] + ","
+ collision = collision + tile[1] + ","
+ fringe = fringe + "0,";
+ ground = ground + "\n"
+ collision = collision + "\n"
+ fringe = fringe + "\n"
+ saveFile(mapsDir + name + ".tmx", tmx.format(sx, sy, ground, collision, fringe))
diff --git a/hercules/code/servertoclient/mercenaries.py b/hercules/code/servertoclient/mercenaries.py
new file mode 100644
index 0000000..481f66c
--- /dev/null
+++ b/hercules/code/servertoclient/mercenaries.py
@@ -0,0 +1,31 @@
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2014 Evol Online
+# Author: Andrei Karas (4144)
+
+import re
+
+from code.fileutils import makeDir, readFile, saveFile
+
+def convertMercenaries():
+ destDir = "clientdata/"
+ templatesDir = "templates/"
+ mercenariesDbFile = "serverdata/db/mercenary_db.txt"
+ fieldsSplit = re.compile(",")
+ makeDir(destDir)
+ tpl = readFile(templatesDir + "mercenary.tpl")
+ mercenaries = readFile(templatesDir + "mercenaries.xml")
+ data = ""
+ mercenarySprite = "<sprite>monsters/croc.xml</sprite>";
+ with open(mercenariesDbFile, "r") as f:
+ for line in f:
+ if line == "" or line[0:2] == "//":
+ continue
+ rows = fieldsSplit.split(line)
+ if len(rows) < 9:
+ continue
+ data = data + tpl.format(
+ id = rows[0],
+ sprite = mercenarySprite,
+ name = rows[2])
+ saveFile(destDir + "mercenaries.xml", mercenaries.format(data))
diff --git a/hercules/code/servertoclient/monsters.py b/hercules/code/servertoclient/monsters.py
new file mode 100644
index 0000000..969795d
--- /dev/null
+++ b/hercules/code/servertoclient/monsters.py
@@ -0,0 +1,43 @@
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2014 Evol Online
+# Author: Andrei Karas (4144)
+
+import re
+
+from code.fileutils import makeDir, readFile, saveFile
+from code.stringutils import strToXml, stripQuotes
+
+def convertMonsters(isNonFree = False, idtofile = None):
+ destDir = "clientdata/"
+ templatesDir = "templates/"
+ monstersDbFile = "serverdata/sql-files/mob_db_re.sql"
+ fieldsSplit = re.compile(",")
+ bracketsSplit = re.compile("[(]|[)]")
+ makeDir(destDir)
+ tpl = readFile(templatesDir + "monster.tpl")
+ monsters = readFile(templatesDir + "monsters.xml")
+ data = ""
+
+ with open(monstersDbFile, "r") as f:
+ for line in f:
+ if len(line) < 10 or line[0:2] == "//" or line[0:12] != "REPLACE INTO":
+ continue
+ rows = bracketsSplit.split(line)
+ if len(rows) < 2:
+ continue
+ rows = fieldsSplit.split(rows[1])
+ if len(rows) < 5:
+ continue
+ monsterId = rows[0]
+ if isNonFree == True and monsterId in idtofile:
+ #convertSprite("rodata/data/sprite/ёуЅєЕН/", idtofile[monsterId])
+ monsterSprite = "<sprite>sprites/{0}.xml</sprite>".format(idtofile[monsterId])
+ else:
+ monsterSprite = """<sprite>monsters/blub.xml</sprite>
+ <sprite>accessories/blub-tentacle.xml|#3e4164,3a3968,544a82,64437a,7d6db4,a26392,8f99c4,d294ab,b3cdcd,e7b8b8,d9ecd1,f0e8c5</sprite>""";
+
+ name = strToXml(stripQuotes(rows[2]))
+ data = data + tpl.format(monsterId, name, monsterSprite)
+
+ saveFile(destDir + "monsters.xml", monsters.format(data))
diff --git a/hercules/code/servertoclient/npcs.py b/hercules/code/servertoclient/npcs.py
new file mode 100644
index 0000000..5e49ffd
--- /dev/null
+++ b/hercules/code/servertoclient/npcs.py
@@ -0,0 +1,29 @@
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2015 Evol Online
+# Author: Andrei Karas (4144)
+
+from code.fileutils import makeDir, readFile, saveFile
+
+
+def getNpcIds(idtofile):
+ for key1 in idtofile:
+ key = int(key1)
+ if 45 <= key <= 125 or 400 < key < 1000 or 10001 <= key < 10100:
+ yield key1
+
+
+def convertNpcsNonFree(idtofile):
+ destDir = "clientdata/"
+ templatesDir = "templates/"
+ makeDir(destDir)
+ tpl = readFile(templatesDir + "npc.tpl")
+ npcs = readFile(templatesDir + "npcs.xml")
+ data = ""
+
+ for key in getNpcIds(idtofile):
+ npcSprite = "<sprite>sprites/{0}.xml</sprite>".format(idtofile[key])
+ data = data + tpl.format(
+ id = key,
+ sprite = npcSprite)
+ saveFile(destDir + "npcs.xml", npcs.format(data))
diff --git a/hercules/code/servertoclient/pets.py b/hercules/code/servertoclient/pets.py
new file mode 100644
index 0000000..bc6deef
--- /dev/null
+++ b/hercules/code/servertoclient/pets.py
@@ -0,0 +1,31 @@
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2014 Evol Online
+# Author: Andrei Karas (4144)
+
+import re
+
+from code.fileutils import makeDir, readFile, saveFile
+
+def convertPets():
+ destDir = "clientdata/"
+ templatesDir = "templates/"
+ petsDbFile = "serverdata/db/re/pet_db.txt"
+ fieldsSplit = re.compile(",")
+ makeDir(destDir)
+ tpl = readFile(templatesDir + "pet.tpl")
+ pets = readFile(templatesDir + "pets.xml")
+ data = ""
+ petSprite = "<sprite>monsters/tortuga.xml</sprite>";
+ with open(petsDbFile, "r") as f:
+ for line in f:
+ if line == "" or line[0:2] == "//":
+ continue
+ rows = fieldsSplit.split(line)
+ if len(rows) < 9:
+ continue
+ data = data + tpl.format(
+ id = rows[0],
+ sprite = petSprite,
+ name = rows[2])
+ saveFile(destDir + "pets.xml", pets.format(data))
diff --git a/hercules/code/servertoclient/quests.py b/hercules/code/servertoclient/quests.py
new file mode 100644
index 0000000..df47fd5
--- /dev/null
+++ b/hercules/code/servertoclient/quests.py
@@ -0,0 +1,39 @@
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2014 Evol Online
+# Author: Andrei Karas (4144)
+
+import re
+
+from code.fileutils import makeDir, readFile, saveFile
+from code.stringutils import strToXml, stripQuotes
+
+def convertQuests():
+ print "quests disabled for now"
+ return
+ destDir = "clientdata/"
+ templatesDir = "templates/"
+ questsDbFile = "serverdata/db/quest_db.txt"
+ fieldsSplit = re.compile(",")
+ makeDir(destDir)
+ tpl = readFile(templatesDir + "quest.tpl")
+ quests = readFile(templatesDir + "quests.xml")
+ data = ""
+ with open(questsDbFile, "r") as f:
+ for line in f:
+ if line == "" or line[0:2] == "//":
+ continue
+ rows = fieldsSplit.split(line)
+ if len(rows) < 9:
+ continue
+ questId = rows[0]
+ text = rows[8]
+ if text[-1] == "\n":
+ text = text[:-1]
+ text = strToXml(stripQuotes(text))
+ name = text
+ if len(name) > 20:
+ name = name[:19]
+
+ data = data + tpl.format(questId, name, text + ": " + str(questId))
+ saveFile(destDir + "quests.xml", quests.format(data))
diff --git a/hercules/code/servertoclient/skills.py b/hercules/code/servertoclient/skills.py
new file mode 100644
index 0000000..6affb72
--- /dev/null
+++ b/hercules/code/servertoclient/skills.py
@@ -0,0 +1,33 @@
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2014 Evol Online
+# Author: Andrei Karas (4144)
+
+import re
+
+from code.fileutils import makeDir, readFile, saveFile
+
+def convertSkillsToXml():
+ destDir = "clientdata/"
+ templatesDir = "templates/"
+ skillsDbFile = "serverdata/db/re/skill_db.txt"
+ fieldsSplit = re.compile(",")
+ makeDir(destDir)
+ tpl = readFile(templatesDir + "skill.tpl")
+ skills = readFile(templatesDir + "skills.xml")
+ data = ""
+ with open(skillsDbFile, "r") as f:
+ for line in f:
+ if line == "" or line[0:2] == "//":
+ continue
+ rows = fieldsSplit.split(line)
+ if len(rows) < 9:
+ continue
+ skillId = rows[0]
+ name = rows[15].strip()
+ description = rows[16].strip()
+ idx = description.find ("//")
+ if idx > 1:
+ description = description[:idx]
+ data = data + tpl.format(skillId, name, description)
+ saveFile(destDir + "skills.xml", skills.format(data))
diff --git a/hercules/code/servertoclient/sprites.py b/hercules/code/servertoclient/sprites.py
new file mode 100644
index 0000000..5dad9d1
--- /dev/null
+++ b/hercules/code/servertoclient/sprites.py
@@ -0,0 +1,467 @@
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2015 Evol Online
+# Author: Andrei Karas (4144)
+
+import array
+import os
+from PIL import Image
+
+from code.fileutils import readInt8, readInt16, readInt32, makeDir, readFile, saveFile, skipData, readData, findFileIn
+
+class ActClass:
+ pass
+
+class ActAnimationClass:
+ pass
+
+class ActSpriteClass:
+ pass
+
+class ActFrameClass:
+ pass
+
+class ActPivotClass:
+ pass
+
+class ActEventClass:
+ pass
+
+class SprClass:
+ pass
+
+class SprImageClass:
+ pass
+
+def readIndexedRLEImage(f, spr):
+ spr.nimages = spr.indexedSpritesCount
+ spr.images = dict()
+ for imageN in range(0, spr.indexedSpritesCount):
+ image = SprImageClass()
+ spr.images[imageN] = image
+ image.width = readInt16(f)
+ image.height = readInt16(f)
+ image.compressed = True
+ data = array.array('B', (0 for _ in xrange(image.width * image.height)))
+ image.data = data
+
+ compressSize = readInt16(f)
+ #uncompressedSize = image.width * image.height
+ #print "uncompressed size=" + str(uncompressedSize)
+ #print "compressed size=" + str(compressSize)
+
+ idx = 0
+ readCnt = 0
+ while readCnt < compressSize:
+ c = readInt8(f)
+ readCnt = readCnt + 1
+ data[idx] = c;
+ #print "{0:4}: {1}".format(idx, c)
+ idx = idx + 1
+ if c == 0:
+ cnt = readInt8(f)
+ readCnt = readCnt + 1
+ if cnt == 0:
+ data[idx] = cnt
+ #print "{0:4}: {1}".format(idx, cnt)
+ idx = idx + 1
+ else:
+ for j in range(1, cnt):
+ data[idx] = c
+ #print "{0:4} ({1} to {2}): {3}".format(idx, j, cnt - 1, c)
+ idx = idx + 1
+ #print "read bytes: " + str(readCnt)
+
+def readIndexedImage(f, spr):
+ pass
+
+def readRgbaImage(f, spr):
+ for imageN in range(0, spr.rgbaSpritesCount):
+ image = SprImageClass()
+ spr.images[imageN + spr.indexedSpritesCount] = image
+ image.width = readInt16(f)
+ image.height = readInt16(f)
+ data = array.array('I', (0 for _ in xrange(image.width * image.height)))
+ image.compressed = False
+ image.data = data
+ for idx in range(0, image.width * image.height):
+ data[idx] = readInt32(f)
+
+
+def readPalette(f, spr):
+ palette = array.array('I', (0 for _ in xrange(256)))
+ spr.palette = palette
+ for col in range(0, 256):
+ palette[col] = readInt32(f)
+
+def getSignedNumber(number, bitLength):
+ mask = (2 ** bitLength) - 1
+ if number & (1 << (bitLength - 1)):
+ return number | ~mask
+ else:
+ return number & mask
+
+def decodeSprite(spr):
+ palette = spr.palette
+ spr.maxwidth = 0
+ spr.maxheight = 0
+ alpha = False
+ for imageN in range(0, spr.indexedSpritesCount):
+ image = spr.images[imageN]
+ indexed = image.data
+ data = array.array('I', (0 for _ in xrange(image.width * image.height)))
+ for idx in range(0, image.width * image.height):
+ col = indexed[idx]
+ if col == 0:
+ data[idx] = 0
+ else:
+ if palette[col] > 0x00ffffff:
+ data[idx] = palette[col]
+ alpha = True
+ else:
+ data[idx] = palette[col] + 0xff000000
+ image.data = data
+ if image.width > spr.maxwidth:
+ spr.maxwidth = image.width
+ if image.height > spr.maxheight:
+ spr.maxheight = image.height
+
+ # for debug
+# png = Image.new('RGBA', (image.width, image.height))
+# png.putdata(image.data)
+# png.save("test{0}.png".format(imageN))
+
+ if alpha:
+ print "detected alpha"
+
+ for imageN in range(0, spr.rgbaSpritesCount):
+ image = spr.images[imageN + spr.indexedSpritesCount]
+ if image.width > spr.maxwidth:
+ spr.maxwidth = image.width
+ if image.height > spr.maxheight:
+ spr.maxheight = image.height
+
+
+
+def saveSpriteImage(act, spr, spriteDir, spriteName):
+# for imageN in range(0, spr.rgbaSpritesCount):
+# image = spr.images[imageN + spr.indexedSpritesCount]
+# print "{0} x {1}".format(image.width, image.height)
+# png = Image.new('RGBA', (image.width, image.height))
+# png.putdata(image.data)
+# png.save("test{0}.png".format(imageN + spr.indexedSpritesCount))
+
+# numTiles = spr.indexedSpritesCount + spr.rgbaSpritesCount
+
+ counted = 0
+ for animN in range(0, act.nanimations):
+ anim = act.animations[animN]
+ for spriteN in range(0, anim.nsprites):
+ sprite = anim.sprites[spriteN]
+# key = []
+# for frameN in range(0, sprite.nframes):
+# frame = sprite.frames[frameN]
+# idf = frame.frameIndex
+# if frame.mirror > 0:
+# idf = - idf
+# key.append(idf)
+ counted = counted + 1
+
+ numTiles = counted
+ #print "max: {0}x{1}".format(spr.maxwidth, spr.maxheight)
+
+ # in row
+ rowTiles = int(2048 / spr.maxwidth)
+ colTiles = int(numTiles / rowTiles)
+ if colTiles * rowTiles < numTiles:
+ colTiles = colTiles + 1
+ tilesetWidth = 2048
+ tilesetHeight = colTiles * spr.maxheight
+# print "num {0} row {1}, col {2}".format(numTiles, rowTiles, colTiles)
+# print "size {0}x{1}".format(2048, colTiles * spr.maxheight)
+
+# tileset = array.array('I', (0 for _ in xrange(tilesetWidth * tilesetHeight)))
+ tileset = Image.new('RGBA', (tilesetWidth, tilesetHeight))
+# png.putdata(tileset)
+ #draw = ImageDraw.Draw(png)
+
+ x = 0
+ y = 0
+
+ frameToIdx = dict()
+
+ tile = 0
+ for animN in range(0, act.nanimations):
+ anim = act.animations[animN]
+ for spriteN in range(0, anim.nsprites):
+ sprite = anim.sprites[spriteN]
+ frameToIdx[str(animN) + "_" + str(spriteN)] = tile
+ for frameN in range(0, sprite.nframes):
+ frame = sprite.frames[frameN]
+ frm = frame.frameIndex
+ if frame.mirror > 0:
+ frm = - frm
+
+ if frm in frameToIdx:
+ continue
+
+ if frame.frameIndex not in spr.images:
+ print "wrong frame index: {0}".format(frame.frameIndex)
+ continue
+ image = spr.images[frame.frameIndex]
+ png = Image.new('RGBA', (image.width, image.height))
+ png.putdata(image.data)
+ if frame.mirror > 0:
+ png = png.transpose(Image.FLIP_LEFT_RIGHT)
+ offsetX = (spr.maxwidth - image.width) / 2
+ offsetY = spr.maxheight - image.height
+# offsetX = (spr.maxwidth - image.width) / 2 + getSignedNumber(frame.offsetX, 32)
+# offsetY = spr.maxheight - image.height + getSignedNumber(frame.offsetY, 32)
+ tileset.paste(png, (x + offsetX, y + offsetY))
+ tile = tile + 1
+ x = x + spr.maxwidth
+ if x + spr.maxwidth > 2048:
+ x = 0
+ y = y + spr.maxheight
+
+# for imageN in range(0, spr.rgbaSpritesCount + spr.indexedSpritesCount):
+# image = spr.images[imageN]
+# png = Image.new('RGBA', (image.width, image.height))
+# png.putdata(image.data)
+# tileset.paste(png, (x, y))
+# x = x + spr.maxwidth
+# if x + spr.maxwidth > 2048:
+# x = 0
+# y = y + spr.maxheight
+
+ spr.frameToIdx = frameToIdx
+ spr.tilesetWidth = tilesetWidth
+ spr.tilesetHeight = tilesetHeight
+ makeDir(spriteDir)
+ tileset.save(spriteDir + spriteName + ".png")
+
+def extractSpriteAnimData(act, spr, actIndex, direction):
+# delay = anim.delay
+ delay = 100
+ data = " <animation direction=\"" + direction + "\">\n"
+ if actIndex not in act.animations:
+ data = data + " <frame index=\"{0}\" delay=\"{1}\" offsetX=\"{2}\" offsetY=\"{3}\"/>\n".format(
+ 0, delay, 0, 0)
+ data = data + " </animation>\n"
+ return data
+
+ anim = act.animations[actIndex]
+ for spriteN in range(0, anim.nsprites):
+ #sprite = anim.sprites[spriteN]
+ #for frameN in range(0, sprite.nframes):
+ #frame = sprite.frames[frameN]
+ #frm = frame.frameIndex
+ #if frame.mirror > 0:
+ # frm = -frm
+ #if frm not in spr.frameToIdx:
+ # continue
+
+ idx = spr.frameToIdx[str(actIndex) + "_" + str(spriteN)]
+ offsetX = 0
+ offsetY = 0
+# offsetX = frame.offsetX
+# offsetY = frame.offsetY
+# if offsetX > 4294900000:
+# offsetX = - (4294967296 - offsetX)
+# if offsetY > 4294000000:
+# offsetY = -(4294967296 - offsetY)
+
+ data = data + " <frame index=\"{0}\" delay=\"{1}\" offsetX=\"{2}\" offsetY=\"{3}\"/>\n".format(
+ idx, delay, offsetX, offsetY)
+
+ data = data + " </animation>\n"
+ return data
+
+def extractSpriteDataAll(act, spr, actIndex, name):
+ data = extractSpriteAnimData(act, spr, actIndex, "down")
+ data = data + extractSpriteAnimData(act, spr, actIndex + 1, "downleft")
+ data = data + extractSpriteAnimData(act, spr, actIndex + 2, "left")
+ data = data + extractSpriteAnimData(act, spr, actIndex + 3, "upleft")
+ data = data + extractSpriteAnimData(act, spr, actIndex + 4, "up")
+ data = data + extractSpriteAnimData(act, spr, actIndex + 5, "upright")
+ data = data + extractSpriteAnimData(act, spr, actIndex + 6, "right")
+ data = data + extractSpriteAnimData(act, spr, actIndex + 6, "downright")
+ return data
+
+def saveSpriteXml(act, spr, spriteDir, spriteName):
+ templatesDir = "templates/"
+ dstFile = spriteDir + spriteName + ".xml"
+ tpl = readFile(templatesDir + "sprite.xml")
+ # 0, 8, 16, 24, 32, 40, 48
+ # 0 - walk or attack or ?
+ # 8 - walk
+ # 16 - attack
+ # 24 - dead
+ # 32 - dead2 ?
+ # no more
+ standData = extractSpriteDataAll(act, spr, 0, "stand")
+ walkData = extractSpriteDataAll(act, spr, 8, "walk")
+ attackData = extractSpriteDataAll(act, spr, 16, "attack")
+ deadData = extractSpriteDataAll(act, spr, 32, "dead")
+
+ data = tpl.format(
+ src = "graphics/sprites/sprites/" + spriteName + ".png",
+ width = spr.maxwidth,
+ height = spr.maxheight,
+ stand = standData,
+ walk = walkData,
+ attack = attackData,
+ dead = deadData
+ )
+ saveFile(dstFile, data)
+
+
+def readAct(actFile):
+ act = ActClass()
+ with open(actFile, "r") as f:
+ act.header = readInt16(f)
+ if act.header != 17217:
+ #print "Wrong header in file {0}".format(actFile)
+ return None
+ act.minorVersion = readInt8(f)
+ act.majorVersion = readInt8(f)
+ act.nanimations = readInt16(f)
+ print "{0}, {1}.{2}, {3}".format(actFile, act.majorVersion, act.minorVersion, act.nanimations)
+ #print " animations: " + str(act.nanimations)
+ act.animations = dict()
+ skipData(f, 10)
+ for animN in range(0, act.nanimations):
+ anim = ActAnimationClass()
+ anim.delay = 30
+ act.animations[animN] = anim
+ anim.nsprites = readInt32(f)
+ #print " sprites: " + str(anim.nsprites)
+ anim.sprites = dict()
+ for spriteN in range(0, anim.nsprites):
+ sprite = ActSpriteClass()
+ anim.sprites[spriteN] = sprite
+ sprite.left1 = readInt32(f)
+ sprite.top1 = readInt32(f)
+ sprite.right1 = readInt32(f)
+ sprite.buttom1 = readInt32(f)
+ sprite.left2 = readInt32(f)
+ sprite.top2 = readInt32(f)
+ sprite.right2 = readInt32(f)
+ sprite.buttom2 = readInt32(f)
+ sprite.nframes = readInt32(f)
+ #print "sprite {0}, frames: {1}".format(spriteN, sprite.nframes)
+ sprite.frames = dict()
+ for frameN in range(0, sprite.nframes):
+ frame = ActFrameClass()
+ sprite.frames[frameN] = frame
+ frame.offsetX = readInt32(f)
+ frame.offsetY = readInt32(f)
+ frame.frameIndex = readInt32(f)
+ #print " index: " + str(frame.frameIndex)
+ frame.mirror = readInt32(f)
+ if act.majorVersion >= 2:
+ frame.color = readInt32(f)
+ frame.scaleX = readInt32(f)
+ if act.majorVersion > 2 or (act.majorVersion == 2 and act.minorVersion >= 4):
+ frame.scaleY = readInt32(f)
+ else:
+ frame.scaleY = frame.scaleX
+ frame.angle = readInt32(f)
+ frame.spriteType = readInt32(f)
+ if act.majorVersion > 2 or (act.majorVersion == 2 and act.minorVersion >= 5):
+ frame.width = readInt32(f)
+ frame.height = readInt32(f)
+ #print "{0} x {1}".format(frame.width, frame.height)
+ if act.majorVersion >= 2:
+ sprite.eventIndex = readInt32(f)
+ if act.majorVersion > 2 or (act.majorVersion == 2 and act.minorVersion >= 3):
+ sprite.npivots = readInt32(f)
+ sprite.pivots = dict()
+ #if sprite.npivots > 0:
+ #print " pivotes: " + str(sprite.npivots)
+ for pivotN in range(0, sprite.npivots):
+ pivot = ActPivotClass()
+ sprite.pivots[pivotN] = pivot
+ pivot.unknown = readInt32(f)
+ pivot.centerX = readInt32(f)
+ pivot.centerY = readInt32(f)
+ pivot.nAttribute = readInt32(f)
+ if act.majorVersion > 2 or (act.majorVersion == 2 and act.minorVersion >= 1):
+ act.nevents = readInt32(f)
+ act.events = dict()
+ for eventN in range(0, act.nevents):
+ event = ActEventClass()
+ act.events[eventN] = event;
+ event.name = readData(f, 40)
+ if act.majorVersion > 2 or (act.majorVersion == 2 and act.minorVersion >= 2):
+ for animN in range(0, act.nanimations):
+ anim = act.animations[animN]
+ anim.delay = readInt32(f)
+ return act
+
+def readSpr(sprFile):
+ spr = SprClass()
+ with open(sprFile, "r") as f:
+ spr.header1 = readInt8(f)
+ spr.header2 = readInt8(f)
+ if spr.header1 != 0x53 or spr.header2 != 0x50:
+ return None
+ spr.minorVersion = readInt8(f)
+ spr.majorVersion = readInt8(f)
+ spr.indexedSpritesCount = readInt16(f)
+ if spr.majorVersion > 1 or (spr.majorVersion == 1 and spr.minorVersion >= 1):
+ spr.rgbaSpritesCount = readInt16(f)
+ else:
+ spr.rgbaSpritesCount = 0
+ print "{0}, {1}.{2}, {3}, {4}".format(sprFile, spr.majorVersion, spr.minorVersion, spr.indexedSpritesCount, spr.rgbaSpritesCount)
+ spr.frames = spr.indexedSpritesCount + spr.rgbaSpritesCount
+
+ if spr.majorVersion > 2 or (spr.majorVersion == 2 and spr.minorVersion >= 1):
+ readIndexedRLEImage(f, spr)
+ else:
+ readIndexedImage(f, spr)
+ readRgbaImage(f, spr)
+
+ if spr.majorVersion > 1 or (spr.majorVersion == 1 and spr.minorVersion >= 1):
+ readPalette(f, spr)
+
+ return spr
+
+def convertSprite(spritePath, spriteName):
+ actFile = "{0}.act".format(spritePath + spriteName)
+ sprFile = "{0}.spr".format(spritePath + spriteName)
+ if os.path.exists(actFile) == False or os.path.exists(sprFile) == False:
+ return None
+ act = readAct(actFile)
+ spr = readSpr(sprFile)
+ decodeSprite(spr)
+ saveSpriteImage(act, spr, "clientdata/graphics/sprites/sprites/", spriteName)
+ saveSpriteXml(act, spr, "clientdata/graphics/sprites/sprites/", spriteName)
+# if actFile.find("wolf") > 0:
+# exit(0)
+# exit(0)
+
+def findSpritePath(spriteName):
+ testName = spriteName + ".act"
+ testName2 = spriteName.upper() + ".act"
+ path = findFileIn((testName, testName2),
+ ("rodata/data/sprite/ёуЅєЕН/",
+ "rodata/data/sprite/npc/",
+ "rodata/data/sprite/homun/"))
+ return path
+
+def convertSpritesNonFree(idtofile):
+ processed = []
+ for spriteid in idtofile:
+ spriteName = idtofile[spriteid]
+ if spriteName in processed:
+ print "skipping " + spriteName
+ continue
+
+ path = findSpritePath(spriteName)
+ if path is None:
+ print "not found " + spriteName
+ continue
+ print spriteName
+ convertSprite(path, spriteName)
+ processed.append(spriteName)
diff --git a/hercules/code/serverutils.py b/hercules/code/serverutils.py
new file mode 100644
index 0000000..39a283e
--- /dev/null
+++ b/hercules/code/serverutils.py
@@ -0,0 +1,12 @@
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2014 Evol Online
+# Author: Andrei Karas (4144)
+
+import os
+
+def detectServerType():
+ if os.path.exists("oldserverdata/world/map/news.d"):
+ return "tmw"
+ else:
+ return "evol"
diff --git a/hercules/code/stringutils.py b/hercules/code/stringutils.py
new file mode 100644
index 0000000..73db611
--- /dev/null
+++ b/hercules/code/stringutils.py
@@ -0,0 +1,62 @@
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2014 Evol Online
+# Author: Andrei Karas (4144)
+
+import codecs
+
+def stripQuotes(data):
+ if len(data) == 0:
+ return data
+ if data[-1] == "\"":
+ data = data[:-1]
+ if data[0] == "\"":
+ data = data[1:]
+ if data[-1] == "'":
+ data = data[:-1]
+ if data[0] == "'":
+ data = data[1:]
+ return data
+
+def stripQuotes2(data):
+ for idx in xrange(0, len(data)):
+ data[idx] = stripQuotes(data[idx])
+ return data
+
+def strToXml(data):
+ data = data.replace("&", "&amp;");
+ data = data.replace("<", "&lt;");
+ data = data.replace(">", "&gt;");
+ return data
+
+def stripNewLine(data):
+ if len(data) == 0:
+ return data
+ if data[-1] == "\r":
+ data = data[:-1]
+ if len(data) > 0 and data[-1] == "\n":
+ data = data[:-1]
+ return data
+
+def stripWindows(data):
+ if len(data) == 0:
+ return data
+ if data[-1] == "\r":
+ data = data[:-1]
+ if len(data) > 1 and data[-2] == "\r":
+ data = data[:-2] + data[-1]
+ data = data.replace(codecs.BOM_UTF8, "", 1)
+ return data
+
+def escapeSqlStr(data):
+ data = data.replace("\\", "\\\\");
+ data = data.replace("'", "\\'");
+ data = data.replace("`", "\\`");
+ data = data.replace("{", "\\{");
+ data = data.replace("}", "\\}");
+ return data
+
+def removeGat(data):
+ if len(data) >= 4 and data[-4:] == ".gat":
+ data = data[:-4]
+ return data
diff --git a/hercules/code/tileutils.py b/hercules/code/tileutils.py
new file mode 100644
index 0000000..42e7a84
--- /dev/null
+++ b/hercules/code/tileutils.py
@@ -0,0 +1,48 @@
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2014 Evol Online
+# Author: Andrei Karas (4144)
+
+import array
+
+def getTileData(mapData, x, y, sx):
+ data = mapData[y * sx + x]
+ arr = array.array("B")
+ arr.fromstring(data)
+ data = arr[0]
+ return data
+
+def getTile(data):
+ normal = 0
+ collision = 0
+ if data == 0: # 000 normal walkable
+ normal = 1
+ collision = 5
+ elif data == 1: # 001 non walkable
+ normal = 2
+ collision = 6
+ elif data == 2: # 010 same with 0
+ normal = 1
+ collision = 5
+ elif data == 3: # 011 same with 0, but water
+ normal = 3
+ collision = 5
+ elif data == 4: # 100 same with 0
+ normal = 1
+ collision = 5
+ elif data == 5: # 101 same with 1, but shootable (for now not supported!!!)
+ normal = 4
+ collision = 6
+ elif data == 6: # 110 same with 0
+ normal = 1
+ collision = 5
+ return (str(normal), str(collision))
+
+def getGroundTile(flag):
+ return str(flag + 1)
+
+def getCollisionTile(flag):
+ if flag == 0:
+ return "0"
+ return "4"
+
diff --git a/hercules/convert_db.py b/hercules/convert_db.py
new file mode 100755
index 0000000..e10ad8a
--- /dev/null
+++ b/hercules/convert_db.py
@@ -0,0 +1,25 @@
+#! /usr/bin/env python
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2015 Evol Online
+# Author: Andrei Karas (4144)
+
+import sys
+
+from code.server.evol.main import dbEvolMain
+from code.server.tmw.main import dbTmwMain
+
+def showHelp():
+ print "Usage: ./convert_db.py evol"
+ print " ./convert_db.py tmw"
+ exit(1)
+
+if len(sys.argv) != 2:
+ showHelp()
+
+if sys.argv[1] == "evol":
+ dbEvolMain()
+elif sys.argv[1] == "tmw":
+ dbTmwMain()
+else:
+ showHelp()
diff --git a/hercules/convert_groups.py b/hercules/convert_groups.py
new file mode 100755
index 0000000..cbb3988
--- /dev/null
+++ b/hercules/convert_groups.py
@@ -0,0 +1,9 @@
+#! /usr/bin/env python
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2017 Evol Online
+# Author: Andrei Karas (4144)
+
+from code.servertoclient.groups import convertGroups
+
+convertGroups()
diff --git a/hercules/convert_mapcache_to_tmx.py b/hercules/convert_mapcache_to_tmx.py
new file mode 100755
index 0000000..e6e6bc9
--- /dev/null
+++ b/hercules/convert_mapcache_to_tmx.py
@@ -0,0 +1,24 @@
+#! /usr/bin/env python
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2014 Evol Online
+# Author: Andrei Karas (4144)
+
+import os
+
+from code.fileutils import readInt32, readInt16
+from code.servertoclient.maps import covertToTmx
+
+def runFunction(path):
+ with open(path, "rb") as f:
+ size = readInt32(f)
+ if os.path.getsize(path) != size:
+ print "Map cache corrupted, wrong file size."
+ exit(1)
+ mapsCount = readInt16(f)
+ print "Maps count: " + str(mapsCount)
+ readInt16(f) # padding
+ covertToTmx(f, mapsCount)
+
+
+runFunction("serverdata/db/re/map_cache.dat")
diff --git a/hercules/convert_server.py b/hercules/convert_server.py
new file mode 100755
index 0000000..83e9149
--- /dev/null
+++ b/hercules/convert_server.py
@@ -0,0 +1,30 @@
+#! /usr/bin/env python
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2014 Evol Online
+# Author: Andrei Karas (4144)
+
+import sys
+
+from code.server.evol.main import serverEvolMain
+from code.server.tmw.main import serverTmwMain
+
+def showHelp():
+ print "Usage: ./convert_server.py evol"
+ print " ./convert_server.py tmwold"
+ print " ./convert_server.py tmwnew"
+ exit(1)
+
+if len(sys.argv) != 2:
+ showHelp()
+ exit(1)
+
+serverType = sys.argv[1]
+if serverType == "evol":
+ serverEvolMain();
+elif serverType == "tmwold":
+ serverTmwMain(False);
+elif serverType == "tmwnew":
+ serverTmwMain(True);
+else:
+ print "Wrong parameter" \ No newline at end of file
diff --git a/hercules/convert_server_to_client.py b/hercules/convert_server_to_client.py
new file mode 100755
index 0000000..f98ead3
--- /dev/null
+++ b/hercules/convert_server_to_client.py
@@ -0,0 +1,29 @@
+#! /usr/bin/env python
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2014 Evol Online
+# Author: Andrei Karas (4144)
+
+from code.servertoclient.homunculuses import convertHomunculuses
+from code.servertoclient.items import convertItems
+from code.servertoclient.luas import convertLuas
+from code.servertoclient.mercenaries import convertMercenaries
+from code.servertoclient.monsters import convertMonsters
+from code.servertoclient.npcs import convertNpcsNonFree
+from code.servertoclient.pets import convertPets
+from code.servertoclient.quests import convertQuests
+from code.servertoclient.skills import convertSkillsToXml
+from code.servertoclient.sprites import convertSpritesNonFree
+
+# non free data
+idtofile = convertLuas()
+convertSpritesNonFree(idtofile)
+convertNpcsNonFree(idtofile)
+
+convertHomunculuses()
+convertItems()
+convertMercenaries()
+convertMonsters(True, idtofile)
+convertPets()
+convertSkillsToXml()
+convertQuests()
diff --git a/hercules/convert_tmx_to_mapcache.py b/hercules/convert_tmx_to_mapcache.py
new file mode 100755
index 0000000..62d0d18
--- /dev/null
+++ b/hercules/convert_tmx_to_mapcache.py
@@ -0,0 +1,9 @@
+#! /usr/bin/env python
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2014 Evol Online
+# Author: Andrei Karas (4144)
+
+from code.clienttoserver.maps import recreateMapCache
+
+recreateMapCache();
diff --git a/hercules/extract_mapcache.py b/hercules/extract_mapcache.py
new file mode 100755
index 0000000..39a63c3
--- /dev/null
+++ b/hercules/extract_mapcache.py
@@ -0,0 +1,24 @@
+#! /usr/bin/env python
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2014 Evol Online
+# Author: Andrei Karas (4144)
+
+import os
+
+from code.fileutils import readInt16, readInt32
+from code.server.maps import extractMaps
+
+
+def runFunction(path):
+ with open(path, "rb") as f:
+ size = readInt32(f)
+ if os.path.getsize(path) != size:
+ print "Map cache corrupted, wrong file size."
+ exit(1)
+ mapsCount = readInt16(f)
+ print "Maps count: " + str(mapsCount)
+ readInt16(f) # padding
+ extractMaps(f, mapsCount)
+
+runFunction("serverdata/db/re/map_cache.dat")
diff --git a/hercules/import_newdb.sh b/hercules/import_newdb.sh
new file mode 100755
index 0000000..ba81d4f
--- /dev/null
+++ b/hercules/import_newdb.sh
@@ -0,0 +1,24 @@
+#!/usr/bin/env bash
+
+export CMD="$*"
+
+if [[ -z "${CMD}" ]]; then
+ echo "Usage example: ./import_newsb.sh -u evol -pevol evol"
+ exit
+fi
+
+cd newdb
+
+function import {
+echo Importing $1
+mysql $CMD <$1
+}
+
+import acc_reg_num_db.sql
+import char.sql
+import char_reg_num_db.sql
+import inventory.sql
+import login.sql
+import party.sql
+import skill.sql
+import storage.sql
diff --git a/hercules/list_mapcache.py b/hercules/list_mapcache.py
new file mode 100755
index 0000000..2a83f53
--- /dev/null
+++ b/hercules/list_mapcache.py
@@ -0,0 +1,24 @@
+#! /usr/bin/env python
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2014 Evol Online
+# Author: Andrei Karas (4144)
+
+import os
+
+from code.fileutils import readInt16, readInt32
+from code.server.maps import listMapCache
+
+def runFunction(path):
+ with open(path, "rb") as f:
+ size = readInt32(f)
+ if os.path.getsize(path) != size:
+ print "Map cache corrupted, wrong file size."
+ exit(1)
+ mapsCount = readInt16(f)
+ print "Maps count: " + str(mapsCount)
+ readInt16(f) # padding
+ listMapCache(f, mapsCount)
+
+
+runFunction("serverdata/db/re/map_cache.dat")
diff --git a/hercules/templates/acc_reg_num_db.sql b/hercules/templates/acc_reg_num_db.sql
new file mode 100644
index 0000000..da8b061
--- /dev/null
+++ b/hercules/templates/acc_reg_num_db.sql
@@ -0,0 +1,11 @@
+DROP TABLE IF EXISTS `acc_reg_num_db`;
+
+CREATE TABLE IF NOT EXISTS `acc_reg_num_db` (
+ `account_id` INT(11) UNSIGNED NOT NULL DEFAULT '0',
+ `key` VARCHAR(32) BINARY NOT NULL DEFAULT '',
+ `index` INT(11) UNSIGNED NOT NULL DEFAULT '0',
+ `value` INT(11) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`account_id`,`key`,`index`),
+ KEY `account_id` (`account_id`)
+) ENGINE=InnoDB;
+
diff --git a/hercules/templates/char.sql b/hercules/templates/char.sql
new file mode 100644
index 0000000..0f75eb5
--- /dev/null
+++ b/hercules/templates/char.sql
@@ -0,0 +1,72 @@
+DROP TABLE IF EXISTS `char`;
+
+CREATE TABLE IF NOT EXISTS `char` (
+ `char_id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
+ `account_id` INT(11) UNSIGNED NOT NULL DEFAULT '0',
+ `char_num` TINYINT(1) NOT NULL DEFAULT '0',
+ `name` VARCHAR(30) NOT NULL DEFAULT '',
+ `class` SMALLINT(6) UNSIGNED NOT NULL DEFAULT '0',
+ `base_level` SMALLINT(6) UNSIGNED NOT NULL DEFAULT '1',
+ `job_level` SMALLINT(6) UNSIGNED NOT NULL DEFAULT '1',
+ `base_exp` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0',
+ `job_exp` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0',
+ `zeny` INT(11) UNSIGNED NOT NULL DEFAULT '0',
+ `str` SMALLINT(4) UNSIGNED NOT NULL DEFAULT '0',
+ `agi` SMALLINT(4) UNSIGNED NOT NULL DEFAULT '0',
+ `vit` SMALLINT(4) UNSIGNED NOT NULL DEFAULT '0',
+ `int` SMALLINT(4) UNSIGNED NOT NULL DEFAULT '0',
+ `dex` SMALLINT(4) UNSIGNED NOT NULL DEFAULT '0',
+ `luk` SMALLINT(4) UNSIGNED NOT NULL DEFAULT '0',
+ `max_hp` INT(9) UNSIGNED NOT NULL DEFAULT '0',
+ `hp` INT(9) UNSIGNED NOT NULL DEFAULT '0',
+ `max_sp` INT(9) UNSIGNED NOT NULL DEFAULT '0',
+ `sp` INT(9) UNSIGNED NOT NULL DEFAULT '0',
+ `status_point` INT(11) UNSIGNED NOT NULL DEFAULT '0',
+ `skill_point` INT(11) UNSIGNED NOT NULL DEFAULT '0',
+ `option` INT(11) NOT NULL DEFAULT '0',
+ `karma` TINYINT(3) NOT NULL DEFAULT '0',
+ `manner` SMALLINT(6) NOT NULL DEFAULT '0',
+ `party_id` INT(11) UNSIGNED NOT NULL DEFAULT '0',
+ `guild_id` INT(11) UNSIGNED NOT NULL DEFAULT '0',
+ `pet_id` INT(11) UNSIGNED NOT NULL DEFAULT '0',
+ `homun_id` INT(11) UNSIGNED NOT NULL DEFAULT '0',
+ `elemental_id` INT(11) UNSIGNED NOT NULL DEFAULT '0',
+ `hair` TINYINT(4) UNSIGNED NOT NULL DEFAULT '0',
+ `hair_color` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0',
+ `clothes_color` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0',
+ `body` SMALLINT(5) unsigned NOT NULL default '0',
+ `weapon` SMALLINT(6) UNSIGNED NOT NULL DEFAULT '0',
+ `shield` SMALLINT(6) UNSIGNED NOT NULL DEFAULT '0',
+ `head_top` SMALLINT(6) UNSIGNED NOT NULL DEFAULT '0',
+ `head_mid` SMALLINT(6) UNSIGNED NOT NULL DEFAULT '0',
+ `head_bottom` SMALLINT(6) UNSIGNED NOT NULL DEFAULT '0',
+ `robe` SMALLINT(6) UNSIGNED NOT NULL DEFAULT '0',
+ `last_map` VARCHAR(11) NOT NULL DEFAULT '',
+ `last_x` SMALLINT(4) UNSIGNED NOT NULL DEFAULT '53',
+ `last_y` SMALLINT(4) UNSIGNED NOT NULL DEFAULT '111',
+ `save_map` VARCHAR(11) NOT NULL DEFAULT '',
+ `save_x` SMALLINT(4) UNSIGNED NOT NULL DEFAULT '53',
+ `save_y` SMALLINT(4) UNSIGNED NOT NULL DEFAULT '111',
+ `partner_id` INT(11) UNSIGNED NOT NULL DEFAULT '0',
+ `online` TINYINT(2) NOT NULL DEFAULT '0',
+ `father` INT(11) UNSIGNED NOT NULL DEFAULT '0',
+ `mother` INT(11) UNSIGNED NOT NULL DEFAULT '0',
+ `child` INT(11) UNSIGNED NOT NULL DEFAULT '0',
+ `fame` INT(11) UNSIGNED NOT NULL DEFAULT '0',
+ `rename` SMALLINT(3) UNSIGNED NOT NULL DEFAULT '0',
+ `delete_date` INT(11) UNSIGNED NOT NULL DEFAULT '0',
+ `slotchange` SMALLINT(3) UNSIGNED NOT NULL DEFAULT '0',
+ `char_opt` INT(11) UNSIGNED NOT NULL DEFAULT '0',
+ `font` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0',
+ `unban_time` INT(11) UNSIGNED NOT NULL DEFAULT '0',
+ `uniqueitem_counter` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0',
+ `sex` ENUM('M','F','U') NOT NULL DEFAULT 'U',
+ `hotkey_rowshift` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0',
+ PRIMARY KEY (`char_id`),
+ UNIQUE KEY `name_key` (`name`),
+ KEY `account_id` (`account_id`),
+ KEY `party_id` (`party_id`),
+ KEY `guild_id` (`guild_id`),
+ KEY `online` (`online`)
+) ENGINE=InnoDB AUTO_INCREMENT=150000;
+
diff --git a/hercules/templates/char_reg_num_db.sql b/hercules/templates/char_reg_num_db.sql
new file mode 100644
index 0000000..ea9429f
--- /dev/null
+++ b/hercules/templates/char_reg_num_db.sql
@@ -0,0 +1,11 @@
+DROP TABLE IF EXISTS `char_reg_num_db`;
+
+CREATE TABLE IF NOT EXISTS `char_reg_num_db` (
+ `char_id` INT(11) UNSIGNED NOT NULL DEFAULT '0',
+ `key` VARCHAR(32) BINARY NOT NULL DEFAULT '',
+ `index` INT(11) UNSIGNED NOT NULL DEFAULT '0',
+ `value` INT(11) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`char_id`,`key`,`index`),
+ KEY `char_id` (`char_id`)
+) ENGINE=InnoDB;
+
diff --git a/hercules/templates/collision.png b/hercules/templates/collision.png
new file mode 100644
index 0000000..f360c63
--- /dev/null
+++ b/hercules/templates/collision.png
Binary files differ
diff --git a/hercules/templates/constants.tpl b/hercules/templates/constants.tpl
new file mode 100644
index 0000000..b42bb18
--- /dev/null
+++ b/hercules/templates/constants.tpl
@@ -0,0 +1,45 @@
+//================= Hercules Database =====================================
+//= _ _ _
+//= | | | | | |
+//= | |_| | ___ _ __ ___ _ _| | ___ ___
+//= | _ |/ _ \ '__/ __| | | | |/ _ \/ __|
+//= | | | | __/ | | (__| |_| | | __/\__ \
+//= \_| |_/\___|_| \___|\__,_|_|\___||___/
+//================= License ===============================================
+//= This file is part of Hercules.
+//= http://herc.ws - http://github.com/HerculesWS/Hercules
+//=
+//= Copyright (C) 2016 Hercules Dev Team
+//=
+//= Hercules is free software: you can redistribute it and/or modify
+//= it under the terms of the GNU General Public License as published by
+//= the Free Software Foundation, either version 3 of the License, or
+//= (at your option) any later version.
+//=
+//= This program is distributed in the hope that it will be useful,
+//= but WITHOUT ANY WARRANTY; without even the implied warranty of
+//= MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//= GNU General Public License for more details.
+//=
+//= You should have received a copy of the GNU General Public License
+//= along with this program. If not, see <http://www.gnu.org/licenses/>.
+//=========================================================================
+//= Script Constants Database
+//=========================================================================
+
+constants_db: {
+/************* Entry structure (short) ************************************
+ Identifier: value // (int)
+ ************* Entry structure (full) *************************************
+ Identifier: {
+ Value: value // (int)
+ Parameter: true // (boolean) Defaults to false.
+ Deprecated: true // (boolean) Defaults to false.
+ }
+**************************************************************************/
+// NOTE:
+// Parameters are special in that they retrieve certain runtime values
+// depending on the specified ID in field Value. Depending on the
+// implementation values assigned by scripts to parameters will affect
+// runtime values, such as Zeny, as well (see pc_readparam/pc_setparam).
+
diff --git a/hercules/templates/group.tpl b/hercules/templates/group.tpl
new file mode 100644
index 0000000..99868d3
--- /dev/null
+++ b/hercules/templates/group.tpl
@@ -0,0 +1,10 @@
+ <group
+ id="{id}"
+ name={name}
+ longName={name}{inherit}
+ >
+ <commands>{commands}
+ </commands>
+ <permissions>{permissions}
+ </permissions>
+ </group>
diff --git a/hercules/templates/groups.xml b/hercules/templates/groups.xml
new file mode 100644
index 0000000..bc14631
--- /dev/null
+++ b/hercules/templates/groups.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Author: 4144
+Copyright (C) 2017 Evol Online -->
+
+<groups>
+{0}
+</groups>
diff --git a/hercules/templates/homunculus.tpl b/hercules/templates/homunculus.tpl
new file mode 100644
index 0000000..67a76bc
--- /dev/null
+++ b/hercules/templates/homunculus.tpl
@@ -0,0 +1,3 @@
+ <homunculus id="{id}" name="{name}">
+ {sprite}
+ </homunculus>
diff --git a/hercules/templates/homunculuses.xml b/hercules/templates/homunculuses.xml
new file mode 100644
index 0000000..3737d8b
--- /dev/null
+++ b/hercules/templates/homunculuses.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Authors: 4144
+Copyright (C) 2014 Evol Online -->
+<homunculuses>
+{0}
+</homunculuses>
diff --git a/hercules/templates/inventory.sql b/hercules/templates/inventory.sql
new file mode 100644
index 0000000..9fabd54
--- /dev/null
+++ b/hercules/templates/inventory.sql
@@ -0,0 +1,23 @@
+DROP TABLE IF EXISTS `inventory`;
+
+CREATE TABLE IF NOT EXISTS `inventory` (
+ `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
+ `char_id` INT(11) UNSIGNED NOT NULL DEFAULT '0',
+ `nameid` INT(11) UNSIGNED NOT NULL DEFAULT '0',
+ `amount` INT(11) UNSIGNED NOT NULL DEFAULT '0',
+ `equip` INT(11) UNSIGNED NOT NULL DEFAULT '0',
+ `identify` SMALLINT(6) NOT NULL DEFAULT '0',
+ `refine` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0',
+ `attribute` TINYINT(4) UNSIGNED NOT NULL DEFAULT '0',
+ `card0` SMALLINT(11) NOT NULL DEFAULT '0',
+ `card1` SMALLINT(11) NOT NULL DEFAULT '0',
+ `card2` SMALLINT(11) NOT NULL DEFAULT '0',
+ `card3` SMALLINT(11) NOT NULL DEFAULT '0',
+ `expire_time` INT(11) UNSIGNED NOT NULL DEFAULT '0',
+ `favorite` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0',
+ `bound` TINYINT(1) UNSIGNED NOT NULL DEFAULT '0',
+ `unique_id` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0',
+ PRIMARY KEY (`id`),
+ KEY `char_id` (`char_id`)
+) ENGINE=InnoDB;
+
diff --git a/hercules/templates/item.tpl b/hercules/templates/item.tpl
new file mode 100644
index 0000000..a7f28a9
--- /dev/null
+++ b/hercules/templates/item.tpl
@@ -0,0 +1,7 @@
+ <item id="{0}"
+ name="{1}"
+ description="{1}"
+{3} image="{4}"
+ type="{5}">
+ <sprite>{6}</sprite>
+ </item>
diff --git a/hercules/templates/item_db.tpl b/hercules/templates/item_db.tpl
new file mode 100644
index 0000000..198343d
--- /dev/null
+++ b/hercules/templates/item_db.tpl
@@ -0,0 +1,63 @@
+item_db: (
+// Items Database
+//
+/******************************************************************************
+ ************* Entry structure ************************************************
+ ******************************************************************************
+{
+ // =================== Mandatory fields ===============================
+ Id: ID (int)
+ AegisName: "Aegis_Name" (string)
+ Name: "Item Name" (string)
+ // =================== Optional fields ================================
+ Type: Item Type (int, defaults to 3 = etc item)
+ Buy: Buy Price (int, defaults to Sell * 2)
+ Sell: Sell Price (int, defaults to Buy / 2)
+ Weight: Item Weight (int, defaults to 0)
+ Atk: Attack (int, defaults to 0)
+ Matk: Magical Attack (int, defaults to 0, ignored in pre-re)
+ Def: Defense (int, defaults to 0)
+ Range: Attack Range (int, defaults to 0)
+ Slots: Slots (int, defaults to 0)
+ Job: Job mask (int, defaults to all jobs = 0xFFFFFFFF)
+ Upper: Upper mask (int, defaults to any = 0x3f)
+ Gender: Gender (int, defaults to both = 2)
+ Loc: Equip location (int, required value for equipment)
+ WeaponLv: Weapon Level (int, defaults to 0)
+ EquipLv: Equip required level (int, defaults to 0)
+ EquipLv: [min, max] (alternative syntax with min / max level)
+ Refine: Refineable (boolean, defaults to true)
+ View: View ID (int, defaults to 0)
+ BindOnEquip: true/false (boolean, defaults to false)
+ BuyingStore: true/false (boolean, defaults to false)
+ Delay: Delay to use item (int, defaults to 0)
+ FloorLifeTime: Delay to remove item from ground (int, default flooritem_lifetime)
+ KeepAfterUse: true/false (boolean, defaults to false)
+ Trade: { (defaults to no restrictions)
+ override: GroupID (int, defaults to 100)
+ nodrop: true/false (boolean, defaults to false)
+ notrade: true/false (boolean, defaults to false)
+ partneroverride: true/false (boolean, defaults to false)
+ noselltonpc: true/false (boolean, defaults to false)
+ nocart: true/false (boolean, defaults to false)
+ nostorage: true/false (boolean, defaults to false)
+ nogstorage: true/false (boolean, defaults to false)
+ nomail: true/false (boolean, defaults to false)
+ noauction: true/false (boolean, defaults to false)
+ nodelonuse: true/false (boolean, defaults to false)
+ }
+ Nouse: { (defaults to no restrictions)
+ override: GroupID (int, defaults to 100)
+ sitting: true/false (boolean, defaults to false)
+ }
+ Stack: [amount, type] (int, defaults to 0)
+ Sprite: SpriteID (int, defaults to 0)
+ Script: <"
+ Script
+ (it can be multi-line)
+ ">
+ OnEquipScript: <" OnEquip Script (can also be multi-line) ">
+ OnUnequipScript: <" OnUnequip Script (can also be multi-line) ">
+},
+******************************************************************************/
+
diff --git a/hercules/templates/items.xml b/hercules/templates/items.xml
new file mode 100644
index 0000000..07d1cb7
--- /dev/null
+++ b/hercules/templates/items.xml
@@ -0,0 +1,148 @@
+<?xml version="1.0" encoding="utf-8"?>
+<?xml-stylesheet type="text/xsl" href="items.xsl"?>
+<!-- Authors: 4144, Piman, Reid
+Copyright (C) 2010-2013 Evol Online -->
+
+<items>
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="1.0">
+ <its:translateRule selector="//item/@name" translate="yes"/>
+ <its:translateRule selector="//item/@description" translate="yes"/>
+ <its:translateRule selector="//item/@useButton" translate="yes"/>
+ <its:translateRule selector="//item/@useButton2" translate="yes"/>
+ <its:translateRule selector="//item/@effect" translate="yes"/>
+ <its:translateRule selector="//*" translate="no"/>
+ </its:rules>
+
+ <!-- Hairstyles -->
+ <item id="-1" type="hairsprite" name="Bald">
+ <sprite>hairstyles/hairstyle01.xml</sprite>
+ </item>
+ <item id="-2" type="hairsprite" name="Bowl Cut" colors="hairS">
+ <sprite>hairstyles/hairstyle02.xml</sprite>
+ </item>
+ <item id="-3" type="hairsprite" name="Combed Back" colors="hairS">
+ <sprite>hairstyles/hairstyle03.xml</sprite>
+ </item>
+ <item id="-4" type="hairsprite" name="Emo" colors="hairS">
+ <sprite>hairstyles/hairstyle04.xml</sprite>
+ </item>
+ <item id="-5" type="hairsprite" name="Mohawk" colors="hairS">
+ <sprite>hairstyles/hairstyle05.xml</sprite>
+ </item>
+ <item id="-6" type="hairsprite" name="Pompadour" colors="hairS">
+ <sprite>hairstyles/hairstyle06.xml</sprite>
+ </item>
+ <item id="-7" type="hairsprite" name="Center Parting" colors="hairS">
+ <sprite>hairstyles/hairstyle07.xml</sprite>
+ </item>
+ <item id="-8" type="hairsprite" name="Long and Slick" colors="hair">
+ <sprite>hairstyles/hairstyle08.xml</sprite>
+ </item>
+ <item id="-9" type="hairsprite" name="Short and Curly" colors="hair">
+ <sprite>hairstyles/hairstyle09.xml</sprite>
+ </item>
+ <item id="-10" type="hairsprite" name="Pigtails" colors="hair">
+ <sprite>hairstyles/hairstyle10.xml</sprite>
+ </item>
+ <item id="-11" type="hairsprite" name="Long and Curly" colors="hair">
+ <sprite>hairstyles/hairstyle11.xml</sprite>
+ </item>
+ <item id="-12" type="hairsprite" name="Parted" colors="hair">
+ <sprite>hairstyles/hairstyle12.xml</sprite>
+ </item>
+ <item id="-13" type="hairsprite" name="Perky Ponytail" colors="hairS">
+ <sprite>hairstyles/hairstyle13.xml</sprite>
+ </item>
+ <item id="-14" type="hairsprite" name="Wave" colors="hairS">
+ <sprite>hairstyles/hairstyle14.xml</sprite>
+ </item>
+ <item id="-15" type="hairsprite" name="Mane" colors="hairS">
+ <sprite>hairstyles/hairstyle15.xml</sprite>
+ </item>
+ <item id="-16" type="hairsprite" name="Bun" colors="hairS">
+ <sprite>hairstyles/hairstyle16.xml</sprite>
+ </item>
+ <item id="-17" type="hairsprite" name="Wavy" colors="hairS">
+ <sprite>hairstyles/hairstyle17.xml</sprite>
+ </item>
+ <item id="-18" type="hairsprite" name="Bunches" colors="hairS">
+ <sprite>hairstyles/hairstyle18.xml</sprite>
+ </item>
+ <item id="-19" type="hairsprite" name="Long Ponytail" colors="hairS">
+ <sprite>hairstyles/hairstyle19.xml</sprite>
+ </item>
+ <item id="-20" type="hairsprite" name="Infinitely Long" colors="hair">
+ <sprite>hairstyles/hairstyle20.xml</sprite>
+ </item>
+ <item id="-21" type="hairsprite" name="Choppy" colors="hair">
+ <sprite>hairstyles/hairstyle21.xml</sprite>
+ </item>
+ <item id="-22" type="hairsprite" name="Wild" colors="hair">
+ <sprite>hairstyles/hairstyle22.xml</sprite>
+ </item>
+ <item id="-23" type="hairsprite" name="Punk" colors="hairS">
+ <sprite>hairstyles/hairstyle23.xml</sprite>
+ </item>
+ <item id="-24" type="hairsprite" name="Imperial" colors="hairS">
+ <sprite>hairstyles/hairstyle24.xml</sprite>
+ </item>
+ <item id="-25" type="hairsprite" name="Side Strand" colors="hairS">
+ <sprite>hairstyles/hairstyle25.xml</sprite>
+ </item>
+ <item id="-26" type="hairsprite" name="Messy" colors="hairS">
+ <sprite>hairstyles/hairstyle26.xml</sprite>
+ </item>
+ <item id="-27" type="hairsprite" name="Flat Ponytail" colors="hairS">
+ <sprite>hairstyles/hairstyle27.xml</sprite>
+ </item>
+ <item id="-28" type="hairsprite" name="Tapered Nape" colors="hairS">
+ <sprite>hairstyles/hairstyle28.xml</sprite>
+ </item>
+
+ <!-- Races -->
+ <item id="-100" type="racesprite" name="Human">
+ <sprite gender="unisex">races/human-male.xml</sprite>
+ <sprite gender="female">races/human-female.xml</sprite>
+ <sound event="hit">weapons/barehands/hit1.ogg</sound>
+ <sound event="miss">weapons/barehands/miss1.ogg</sound>
+ </item>
+ <item id="-101" type="racesprite" name="Ukar">
+ <sprite gender="unisex">races/ukar-male.xml</sprite>
+ <sprite gender="female">races/ukar-female.xml</sprite>
+ <sound event="hit">weapons/barehands/hit1.ogg</sound>
+ <sound event="miss">weapons/barehands/miss1.ogg</sound>
+ </item>
+ <item id="-102" type="racesprite" name="Demon">
+ <sprite gender="unisex">races/demon-male.xml</sprite>
+ <sprite gender="female">races/demon-female.xml</sprite>
+ <sound event="hit">weapons/barehands/hit1.ogg</sound>
+ <sound event="miss">weapons/barehands/miss1.ogg</sound>
+ </item>
+ <item id="-103" type="racesprite" name="Elven">
+ <sprite gender="unisex">races/elven-male.xml</sprite>
+ <sprite gender="female">races/elven-female.xml</sprite>
+ <sound event="hit">weapons/barehands/hit1.ogg</sound>
+ <sound event="miss">weapons/barehands/miss1.ogg</sound>
+ </item>
+ <item id="-104" type="racesprite" name="Orc">
+ <sprite gender="unisex">races/orc-male.xml</sprite>
+ <sprite gender="female">races/orc-female.xml</sprite>
+ <sound event="hit">weapons/barehands/hit1.ogg</sound>
+ <sound event="miss">weapons/barehands/miss1.ogg</sound>
+ </item>
+ <item id="-105" type="racesprite" name="Raijin">
+ <sprite gender="unisex">races/raijin-male.xml</sprite>
+ <sprite gender="female">races/raijin-female.xml</sprite>
+ <sound event="hit">weapons/barehands/hit1.ogg</sound>
+ <sound event="miss">weapons/barehands/miss1.ogg</sound>
+ </item>
+ <item id="-106" type="racesprite" name="Tritan">
+ <sprite gender="unisex">races/tritan-male.xml</sprite>
+ <sprite gender="female">races/tritan-female.xml</sprite>
+ <sound event="hit">weapons/barehands/hit1.ogg</sound>
+ <sound event="miss">weapons/barehands/miss1.ogg</sound>
+ </item>
+
+ <!-- Items -->
+{0}
+</items>
diff --git a/hercules/templates/login.sql b/hercules/templates/login.sql
new file mode 100644
index 0000000..e64de4a
--- /dev/null
+++ b/hercules/templates/login.sql
@@ -0,0 +1,25 @@
+DROP TABLE IF EXISTS `login`;
+
+CREATE TABLE IF NOT EXISTS `login` (
+ `account_id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
+ `userid` VARCHAR(23) NOT NULL DEFAULT '',
+ `user_pass` VARCHAR(32) NOT NULL DEFAULT '',
+ `sex` ENUM('M','F','S') NOT NULL DEFAULT 'M',
+ `email` VARCHAR(39) NOT NULL DEFAULT '',
+ `group_id` TINYINT(3) NOT NULL DEFAULT '0',
+ `state` INT(11) UNSIGNED NOT NULL DEFAULT '0',
+ `unban_time` INT(11) UNSIGNED NOT NULL DEFAULT '0',
+ `expiration_time` INT(11) UNSIGNED NOT NULL DEFAULT '0',
+ `logincount` MEDIUMINT(9) UNSIGNED NOT NULL DEFAULT '0',
+ `lastlogin` DATETIME NULL,
+ `last_ip` VARCHAR(100) NOT NULL DEFAULT '',
+ `birthdate` DATE NULL,
+ `character_slots` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0',
+ `pincode` VARCHAR(4) NOT NULL DEFAULT '',
+ `pincode_change` INT(11) UNSIGNED NOT NULL DEFAULT '0',
+ PRIMARY KEY (`account_id`),
+ KEY `name` (`userid`)
+) ENGINE=InnoDB AUTO_INCREMENT=2000000;
+
+INSERT INTO `login` (`account_id`, `userid`, `user_pass`, `sex`, `email`) VALUES ('1', 's1', 'p1', 'S','athena@athena.com');
+
diff --git a/hercules/templates/mercenaries.xml b/hercules/templates/mercenaries.xml
new file mode 100644
index 0000000..cfc801c
--- /dev/null
+++ b/hercules/templates/mercenaries.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Authors: 4144
+Copyright (C) 2014 Evol Online -->
+<mercenaries>
+{0}
+</mercenaries>
diff --git a/hercules/templates/mercenary.tpl b/hercules/templates/mercenary.tpl
new file mode 100644
index 0000000..c371659
--- /dev/null
+++ b/hercules/templates/mercenary.tpl
@@ -0,0 +1,3 @@
+ <mercenary id="{id}" name="{name}">
+ {sprite}
+ </mercenary>
diff --git a/hercules/templates/mob_db.tpl b/hercules/templates/mob_db.tpl
new file mode 100644
index 0000000..ecf4a27
--- /dev/null
+++ b/hercules/templates/mob_db.tpl
@@ -0,0 +1,101 @@
+//================= Hercules Database =====================================
+//= _ _ _
+//= | | | | | |
+//= | |_| | ___ _ __ ___ _ _| | ___ ___
+//= | _ |/ _ \ '__/ __| | | | |/ _ \/ __|
+//= | | | | __/ | | (__| |_| | | __/\__ \
+//= \_| |_/\___|_| \___|\__,_|_|\___||___/
+//================= License ===============================================
+//= This file is part of Hercules.
+//= http://herc.ws - http://github.com/HerculesWS/Hercules
+//=
+//= Copyright (C) 2015 Hercules Dev Team
+//=
+//= Hercules is free software: you can redistribute it and/or modify
+//= it under the terms of the GNU General Public License as published by
+//= the Free Software Foundation, either version 3 of the License, or
+//= (at your option) any later version.
+//=
+//= This program is distributed in the hope that it will be useful,
+//= but WITHOUT ANY WARRANTY; without even the implied warranty of
+//= MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//= GNU General Public License for more details.
+//=
+//= You should have received a copy of the GNU General Public License
+//= along with this program. If not, see <http://www.gnu.org/licenses/>.
+//=========================================================================
+//= Mobs Database
+//=========================================================================
+
+mob_db: (
+// Mobs Database
+//
+/******************************************************************************
+ ************* Entry structure ************************************************
+ ******************************************************************************
+{
+ // =================== Mandatory fields ===============================
+ Id: ID (int)
+ SpriteName: "SPRITE_NAME" (string)
+ Name: "Mob name" (string)
+ // =================== Optional fields ================================
+ JName: "Mob name" (string)
+ Lv: level (int, defaults to 1)
+ Hp: health (int, defaults to 1)
+ Sp: mana (int, defaults to 0)
+ Exp: basic experience (int, defaults to 0)
+ JExp: job experience (int, defaults to 0)
+ AttackRange: attack range (int, defaults to 1)
+ Attack: [attack1, attack2] (int, defaults to 0)
+ Def: defence (int, defaults to 0)
+ Mdef: magic defence (int, defaults to 0)
+ Stats: {
+ Str: strength (int, defaults to 0)
+ Agi: agility (int, defaults to 0)
+ Vit: vitality (int, defaults to 0)
+ Int: intelligence (int, defaults to 0)
+ Dex: dexterity (int, defaults to 0)
+ Luk: luck (int, defaults to 0)
+ }
+ ViewRange: view range (int, defaults to 1)
+ ChaseRange: chase range (int, defaults to 1)
+ Size: size (int, defaults to 1)
+ Race: race (int, defaults to 0)
+ Element: (type, level)
+ Mode: {
+ CanMove: true/false (bool, defaults to false)
+ Looter: true/false (bool, defaults to false)
+ Aggressive: true/false (bool, defaults to false)
+ Assist: true/false (bool, defaults to false)
+ CastSensorIdle:true/false (bool, defaults to false)
+ Boss: true/false (bool, defaults to false)
+ Plant: true/false (bool, defaults to false)
+ CanAttack: true/false (bool, defaults to false)
+ Detector: true/false (bool, defaults to false)
+ CastSensorChase: true/false (bool, defaults to false)
+ ChangeChase: true/false (bool, defaults to false)
+ Angry: true/false (bool, defaults to false)
+ ChangeTargetMelee: true/false (bool, defaults to false)
+ ChangeTargetChase: true/false (bool, defaults to false)
+ TargetWeak: true/false (bool, defaults to false)
+ NoKnockback: true/false (bool, defaults to false)
+ SurviveWithoutMaster: true/false (bool, defaults to false)
+ }
+ MoveSpeed: move speed (int, defaults to 0)
+ WalkMask: walk mask (int, defaults to 0)
+ AttackDelay: attack delay (int, defaults to 4000)
+ AttackMotion: attack motion (int, defaults to 2000)
+ DamageMotion: damage motion (int, defaults to 0)
+ MvpExp: mvp experience (int, defaults to 0)
+ MvpDrops: {
+ AegisName: chance (string: int)
+ ...
+ }
+ Drops: {
+ AegisName: chance (string: int)
+ ...
+ }
+
+},
+******************************************************************************/
+
diff --git a/hercules/templates/mob_skill_db.tpl b/hercules/templates/mob_skill_db.tpl
new file mode 100644
index 0000000..d8cc0a4
--- /dev/null
+++ b/hercules/templates/mob_skill_db.tpl
@@ -0,0 +1,56 @@
+// Mob Skill Database
+// Based on Aegis Episode 14.2
+//
+// Structure of Database:
+// MobID,Dummy value (info only),State,SkillID,SkillLv,Rate,CastTime,Delay,Cancelable,Target,Condition type,Condition value,val1,val2,val3,val4,val5,Emotion,Chat
+//
+// RATE: the chance of the skill being casted when the condition is fulfilled (10000 = 100%).
+// DELAY: the time (in milliseconds) before attempting to recast the same skill.
+//
+// STATE:
+// any (except dead) / idle (in standby) / walk (in movement) / dead (on killed) /
+// loot /attack / angry (like attack, except player has not attacked mob yet) /
+// chase (following target, after being attacked) / follow (following target,
+// without being attacked) / anytarget (attack+angry+chase+follow)
+//
+// TARGET:
+// target (current target) / self / friend / master / randomtarget (any enemy within skill's range)
+//
+// The following are for ground-skills, a random target tile is selected from the specified area:
+// around1 (3x3 area around self) / around2 (5x5 area around self) /
+// around3 (7x7 area around self) / around4 (9x9 area around self) /
+// around5 (3x3 area around target) / around6 (5x5 area around target) /
+// around7 (7x7 area around target) / around8 (9x9 area around target) /
+// around = around4
+//
+// CONDITION:
+// always Unconditional (no condition value).
+// onspawn When mob spawns/respawns (no condition value).
+// myhpltmaxrate When mob's HP drops to the specified %.
+// myhpinrate When mob's HP is in a certain % range (condition value = lower bound, val1 = upper bound).
+// mystatuson If mob has the specified abnormality in status.
+// mystatusoff If mob has ended the specified abnormality in status.
+// friendhpltmaxrate When mob's friend's HP drops to the specified %.
+// friendhpinrate When mob's friend's HP is in a certain % range (condition value = lower bound, val1 = upper bound).
+// friendstatuson If friend has the specified abnormality in status.
+// friendstatusoff If friend has ended the specified abnormality in status.
+// attackpcgt When attack PCs become greater than specified number.
+// attackpcge When attack PCs become greater than or equal to the specified number.
+// slavelt When number of slaves is less than the original specified number.
+// slavele When number of slaves is less than or equal to the original specified number.
+// closedattacked When close range melee attacked (no condition value).
+// longrangeattacked When long range attacked, ex. bows, guns, ranged skills (no condition value).
+// skillused When the specified skill is used on the mob.
+// afterskill After mob casts the specified skill.
+// casttargeted When a target is in cast range (no condition value).
+// rudeattacked When mob is rude attacked (no condition value).
+//
+// Status abnormalities specified through the statuson/statusoff system:
+// anybad (any type of state change) / stone / freeze / stun / sleep /
+// poison / curse / silence / confusion / blind / hiding / sight (unhidden)
+//
+// Note: if a negative MobID is provided, the skill will be treated as 'global':
+// -1: added for all boss types.
+// -2: added for all normal types.
+// -4: added for all mobs.
+
diff --git a/hercules/templates/monster.tpl b/hercules/templates/monster.tpl
new file mode 100644
index 0000000..3b6bf4d
--- /dev/null
+++ b/hercules/templates/monster.tpl
@@ -0,0 +1,3 @@
+ <monster id="{0}" name="{1}">
+ {2}
+ </monster>
diff --git a/hercules/templates/monsters.xml b/hercules/templates/monsters.xml
new file mode 100644
index 0000000..9f8ffa0
--- /dev/null
+++ b/hercules/templates/monsters.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010-2014 Evol Online -->
+
+<monsters>
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="1.0">
+ <its:translateRule selector="//monster/@name" translate="yes"/>
+ <its:translateRule selector="//*" translate="no"/>
+ </its:rules>
+
+{0}
+</monsters>
diff --git a/hercules/templates/npc.tpl b/hercules/templates/npc.tpl
new file mode 100644
index 0000000..a201d64
--- /dev/null
+++ b/hercules/templates/npc.tpl
@@ -0,0 +1,3 @@
+ <npc id="{id}">
+ {sprite}
+ </npc>
diff --git a/hercules/templates/npcs.xml b/hercules/templates/npcs.xml
new file mode 100644
index 0000000..72a0a4f
--- /dev/null
+++ b/hercules/templates/npcs.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010-2014 Evol Online -->
+
+<npcs>
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="1.0">
+ <its:translateRule selector="//monster/@name" translate="yes"/>
+ <its:translateRule selector="//*" translate="no"/>
+ </its:rules>
+
+{0}
+</npcs>
diff --git a/hercules/templates/party.sql b/hercules/templates/party.sql
new file mode 100644
index 0000000..0beb439
--- /dev/null
+++ b/hercules/templates/party.sql
@@ -0,0 +1,12 @@
+DROP TABLE IF EXISTS `party`;
+
+CREATE TABLE IF NOT EXISTS `party` (
+ `party_id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
+ `name` VARCHAR(24) NOT NULL DEFAULT '',
+ `exp` TINYINT(11) UNSIGNED NOT NULL DEFAULT '0',
+ `item` TINYINT(11) UNSIGNED NOT NULL DEFAULT '0',
+ `leader_id` INT(11) UNSIGNED NOT NULL DEFAULT '0',
+ `leader_char` INT(11) UNSIGNED NOT NULL DEFAULT '0',
+ PRIMARY KEY (`party_id`)
+) ENGINE=InnoDB;
+
diff --git a/hercules/templates/pet.tpl b/hercules/templates/pet.tpl
new file mode 100644
index 0000000..08d489c
--- /dev/null
+++ b/hercules/templates/pet.tpl
@@ -0,0 +1,3 @@
+ <pet id="{id}" name="{name}">
+ {sprite}
+ </pet>
diff --git a/hercules/templates/pets.xml b/hercules/templates/pets.xml
new file mode 100644
index 0000000..6f838cf
--- /dev/null
+++ b/hercules/templates/pets.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Authors: 4144
+Copyright (C) 2014 Evol Online -->
+<pets>
+{0}
+</pets>
diff --git a/hercules/templates/quest.tpl b/hercules/templates/quest.tpl
new file mode 100644
index 0000000..25615f9
--- /dev/null
+++ b/hercules/templates/quest.tpl
@@ -0,0 +1,5 @@
+ <var id="{0}">
+ <quest name="{1}" group="hercules" incomplete="1" complete="2">
+ <name>{2}</name>
+ </quest>
+ </var>
diff --git a/hercules/templates/quest_db.tpl b/hercules/templates/quest_db.tpl
new file mode 100644
index 0000000..e67b40f
--- /dev/null
+++ b/hercules/templates/quest_db.tpl
@@ -0,0 +1,5 @@
+// Quest Database
+//
+// Structure of Database:
+// Quest ID,Time Limit,Target1,Val1,Target2,Val2,Target3,Val3,Quest Title
+
diff --git a/hercules/templates/quests.xml b/hercules/templates/quests.xml
new file mode 100644
index 0000000..c2828f9
--- /dev/null
+++ b/hercules/templates/quests.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Authors: 4144
+Copyright (C) 2014 Evol Online -->
+<quests>
+{0}
+</quests>
diff --git a/hercules/templates/skill.sql b/hercules/templates/skill.sql
new file mode 100644
index 0000000..2ee3002
--- /dev/null
+++ b/hercules/templates/skill.sql
@@ -0,0 +1,10 @@
+DROP TABLE IF EXISTS `skill`;
+
+CREATE TABLE IF NOT EXISTS `skill` (
+ `char_id` INT(11) UNSIGNED NOT NULL DEFAULT '0',
+ `id` SMALLINT(11) UNSIGNED NOT NULL DEFAULT '0',
+ `lv` TINYINT(4) UNSIGNED NOT NULL DEFAULT '0',
+ `flag` TINYINT(1) UNSIGNED NOT NULL DEFAULT 0,
+ PRIMARY KEY (`char_id`,`id`)
+) ENGINE=InnoDB;
+
diff --git a/hercules/templates/skill.tpl b/hercules/templates/skill.tpl
new file mode 100644
index 0000000..53dc952
--- /dev/null
+++ b/hercules/templates/skill.tpl
@@ -0,0 +1 @@
+ <skill id="{0}" name="{1}" description="{2}"/>
diff --git a/hercules/templates/skills.xml b/hercules/templates/skills.xml
new file mode 100644
index 0000000..c747ed7
--- /dev/null
+++ b/hercules/templates/skills.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Authors: 4144
+Copyright (C) 2014 Evol Online -->
+<skills>
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="1.0">
+ <its:translateRule selector="//set/@name" translate="yes"/>
+ <its:translateRule selector="//set/skill/@name" translate="yes"/>
+ <its:translateRule selector="//set/skill/@description" translate="yes"/>
+ <its:translateRule selector="//*" translate="no"/>
+ </its:rules>
+
+ <set name="Basic">
+{0}
+ </set>
+</skills>
diff --git a/hercules/templates/sprite.xml b/hercules/templates/sprite.xml
new file mode 100644
index 0000000..7443ba7
--- /dev/null
+++ b/hercules/templates/sprite.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Author: 4144
+Copyright (C) 2015 Evol Online -->
+<sprite>
+ <imageset name="sprite"
+ src="{src}"
+ width="{width}"
+ height="{height}"/>
+
+ <action name="stand" imageset="sprite">
+{stand}</action>
+
+ <action name="walk" imageset="sprite">
+{walk}</action>
+
+ <action name="attack" imageset="sprite">
+{attack}</action>
+
+ <action name="dead" imageset="sprite">
+{dead}</action>
+</sprite>
diff --git a/hercules/templates/storage.sql b/hercules/templates/storage.sql
new file mode 100644
index 0000000..027d291
--- /dev/null
+++ b/hercules/templates/storage.sql
@@ -0,0 +1,22 @@
+DROP TABLE IF EXISTS `storage`;
+
+CREATE TABLE IF NOT EXISTS `storage` (
+ `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
+ `account_id` INT(11) UNSIGNED NOT NULL DEFAULT '0',
+ `nameid` INT(11) UNSIGNED NOT NULL DEFAULT '0',
+ `amount` SMALLINT(11) UNSIGNED NOT NULL DEFAULT '0',
+ `equip` INT(11) UNSIGNED NOT NULL DEFAULT '0',
+ `identify` SMALLINT(6) UNSIGNED NOT NULL DEFAULT '0',
+ `refine` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0',
+ `attribute` TINYINT(4) UNSIGNED NOT NULL DEFAULT '0',
+ `card0` SMALLINT(11) NOT NULL DEFAULT '0',
+ `card1` SMALLINT(11) NOT NULL DEFAULT '0',
+ `card2` SMALLINT(11) NOT NULL DEFAULT '0',
+ `card3` SMALLINT(11) NOT NULL DEFAULT '0',
+ `expire_time` INT(11) UNSIGNED NOT NULL DEFAULT '0',
+ `bound` TINYINT(1) UNSIGNED NOT NULL DEFAULT '0',
+ `unique_id` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0',
+ PRIMARY KEY (`id`),
+ KEY `account_id` (`account_id`)
+) ENGINE=InnoDB;
+
diff --git a/hercules/templates/template.tmx b/hercules/templates/template.tmx
new file mode 100644
index 0000000..ec9b214
--- /dev/null
+++ b/hercules/templates/template.tmx
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE map SYSTEM "http://mapeditor.org/dtd/1.0/map.dtd">
+<map version="1.0" orientation="orthogonal" width="{0}" height="{1}" tilewidth="32" tileheight="32">
+ <tileset firstgid="1" name="tiles" tilewidth="32" tileheight="32">
+ <image source="../graphics/tilesets/tileset.png" width="64" height="32"/>
+ </tileset>
+ <tileset firstgid="5" name="Collision" tilewidth="32" tileheight="32">
+ <image source="../graphics/tilesets/collision.png" width="64" height="32"/>
+ </tileset>
+ <layer name="ground" width="{0}" height="{1}">
+ <data encoding="csv">
+{2}
+</data>
+ </layer>
+ <layer name="Fringe" width="{0}" height="{1}">
+ <data encoding="csv">
+{4}
+</data>
+ </layer>
+ <layer name="Collision" width="{0}" height="{1}">
+ <data encoding="csv">
+{3}
+</data>
+ </layer>
+</map>
diff --git a/hercules/templates/tileset.png b/hercules/templates/tileset.png
new file mode 100644
index 0000000..f36ccbb
--- /dev/null
+++ b/hercules/templates/tileset.png
Binary files differ
diff --git a/hercules/tmx_converter.py b/hercules/tmx_converter.py
new file mode 100755
index 0000000..5e864de
--- /dev/null
+++ b/hercules/tmx_converter.py
@@ -0,0 +1,550 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+
+## tmx_converter.py - Extract walkmap, warp, and spawn information from maps.
+##
+## Copyright © 2012 Ben Longbons <b.r.longbons@gmail.com>
+## Copyright © 2016-2018 The Mana World Developers
+##
+## This file is part of The Mana World
+##
+## 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.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+
+from __future__ import print_function
+
+import sys
+import os
+import posixpath
+import xml.sax
+import traceback
+
+dump_all = False # wall of text
+check_mobs = True # mob_db.txt
+
+# lower case versions of everything except 'spawn' and 'warp'
+other_object_types = set([
+ 'particle_effect',
+ 'music',
+ 'node',
+ 'switch',
+ 'npc',
+])
+
+other_spawn_fields = (
+ 'monster_id',
+)
+other_warp_fields = (
+)
+
+TILESIZE = 32
+WIDESCREEN=1920
+SEPARATOR = ''
+MESSAGE = 'This file is generated automatically. All manually added changes will be removed when running the Converter.'
+CLIENT_MAPS = 'maps'
+SERVER_WLK = 'data'
+SERVER_NPCS = 'npc'
+MOB_DB_CONF = 'db/pre-re/mob_db.conf'
+MAP_CONF = 'conf/map/maps.conf'
+MAP_DB_CONF = 'db/map_index.txt'
+NPC_MOBS = '_mobs.txt'
+NPC_SAVES = '_savepoints.txt'
+NPC_WARPS = '_warps.txt'
+NPC_IMPORTS = '_import.txt'
+NPC_MASTER_IMPORTS = NPC_IMPORTS
+NPC_MASTER_ANCHORS = '_anchors.txt'
+
+class State(object):
+ pass
+State.INITIAL = State()
+State.LAYER = State()
+State.DATA = State()
+State.FINAL = State()
+
+class Object(object):
+ __slots__ = (
+ 'name',
+ 'x', 'y',
+ 'w', 'h',
+ 'ignore',
+ )
+class Mob(Object):
+ __slots__ = (
+ 'max_beings',
+ 'spawn',
+ 'death',
+ 'ea_death',
+ 'ea_spawn',
+ 'script',
+ ) + other_spawn_fields
+ def __init__(self):
+ self.max_beings = 1
+ self.spawn = 0
+ self.death = 0
+ self.script = ''
+
+class Save(Object):
+ __slots__ = (
+ 'inn',
+ )
+
+class Anchor(Object):
+ __slots__ = (
+ )
+
+class Warp(Object):
+ __slots__ = (
+ 'dest_map',
+ 'dest_x',
+ 'dest_y',
+ 'dest_tile_x',
+ 'dest_tile_y',
+ 'npc_id',
+ 'trigger_x',
+ 'trigger_y',
+ ) + other_warp_fields
+ def __init__(self):
+ self.npc_id = 'WARP'
+
+class ContentHandler(xml.sax.ContentHandler):
+ __slots__ = (
+ 'locator', # keeps track of location in document
+ 'state', # state of height info
+ 'tilesets', # first gid of each tileset
+ 'buffer', # characters within a section
+ 'width', # width of the height layer
+ 'height', # height of the height layer
+ 'firstgid', # first gid of height layer
+ 'heightmap', # height map
+ 'base', # base name of current map
+ 'npc_dir', # world/map/npc/<base>
+ 'mobs', # open file to _mobs.txt
+ 'warps', # open file to _warps.txt
+ 'imports', # open file to _import.txt
+ 'name', # name property of the current map
+ 'object', # stores properties of the latest <object> tag
+ 'mob_ids', # set of all mob types that spawn here
+ 'anchor_master', # list of all anchors
+ )
+ def __init__(self, npc_dir, mobs, saves, warps, imports, anchor_master):
+ xml.sax.ContentHandler.__init__(self)
+ self.locator = None
+ self.state = State.INITIAL
+ self.tilesets = set([0]) # consider the null tile as its own tileset
+ self.buffer = bytearray()
+ self.width = None
+ self.height = None
+ self.firstgid = 0
+ self.heightmap = ''
+ self.base = posixpath.basename(npc_dir)
+ self.npc_dir = npc_dir
+ self.mobs = mobs
+ self.saves = saves
+ self.warps = warps
+ self.imports = imports
+ self.anchor_master = anchor_master
+ self.object = None
+ self.mob_ids = set()
+ self.mob_cnt = False
+ self.save_cnt = False
+ self.warp_cnt = False
+ self.name = None
+ self.layer_name = u''
+ self.layers = set()
+
+ def setDocumentLocator(self, loc):
+ self.locator = loc
+
+ # this method randomly cuts in the middle of a line; thus funky logic
+ def characters(self, s):
+ if not s.strip():
+ return
+ if self.state is State.DATA:
+ self.buffer += s.encode('ascii')
+
+ def startDocument(self):
+ pass
+
+ def startElement(self, name, attr):
+ if dump_all:
+ attrs = ' '.join('%s="%s"' % (k,v) for k,v in attr.items())
+ if attrs:
+ print('<%s %s>' % (name, attrs))
+ else:
+ print('<%s>' % name)
+
+ if self.state is State.INITIAL:
+ if name == u'property':
+ if (attr[u'name'] == u'name'):
+ self.name = attr[u'value']
+ self.mobs.write('// %s\n' % MESSAGE)
+ self.mobs.write('// Map %s: %s mobs\n' % (self.base, self.name))
+ self.saves.write('// %s\n' % MESSAGE)
+ self.saves.write('// Map %s: %s saves\n' % (self.base, self.name))
+ self.warps.write('// %s\n' % MESSAGE)
+ self.warps.write('// Map %s: %s warps\n' % (self.base, self.name))
+ elif attr[u'name'] == u'ignore':
+ print("\n\nIgnore flag detected on map %s. Skipping..." % self.base)
+ raise Exception('ignore')
+
+ if name == u'tileset':
+ self.tilesets.add(int(attr[u'firstgid']))
+ if 'name' in attr.__dict__['_attrs'].keys():
+ if attr[u'name'] == u'Height Numbers':
+ self.firstgid = int(attr[u'firstgid'])
+
+ if name == u'layer':
+ self.width = int(attr[u'width'])
+ self.height = int(attr[u'height'])
+ self.layers.add(attr[u'name'].lower())
+ self.layer_name = attr[u'name'].lower()
+ self.state = State.LAYER
+ # Map width must be enough to fill the largest widescreen on market
+ if (self.width < WIDESCREEN/TILESIZE):
+ print('\n\n\033[21;1mERROR:\033[0m invalid map width: %d (min. %d)' % (self.width, WIDESCREEN/TILESIZE))
+ #raise SyntaxError('width')
+ elif self.state is State.LAYER:
+ if name == u'layer':
+ self.layers.add(attr[u'name'].lower())
+ self.layer_name = attr[u'name'].lower()
+ elif name == u'data':
+ if self.layer_name.startswith(u'height'):
+ if attr.get(u'encoding','') not in (u'', u'csv'):
+ print("\n\n\033[21;1mERROR:\033[0m bad encoding on map %s: encoding must be CSV, but %s was used." % (self.base, attr.get(u'encoding','')))
+ raise SyntaxError('encoding')
+ if attr.get(u'compression','') not in (u'', u'none'):
+ print("\n\n\033[21;1mERROR:\033[0m bad compression on map %s: compression must be disabled, but %s was used." % (self.base, attr.get(u'compression','')))
+ raise SyntaxError('compression')
+ self.state = State.DATA
+ elif name == u'properties' or name == u'property':
+ pass
+ else:
+ self.state = State.FINAL
+ if not u'collision' in self.layers:
+ print("\n\n\033[21;1mERROR:\033[0m missing Collision layer on map %s." % (self.base))
+ raise AttributeError('collision')
+ if not u'fringe' in self.layers:
+ print("\n\n\033[21;1mERROR:\033[0m missing Fringe layer on map %s." % (self.base))
+ raise AttributeError('fringe')
+ for layer in self.layers:
+ if layer.startswith(u'height'):
+ return
+ print("\n\nERROR: missing Heights layer on map %s." % (self.base))
+ #raise AttributeError('heights')
+ self.heightmap=''
+ elif self.state is State.FINAL:
+ if self.name is None:
+ print("\n\n\033[21;1mERROR:\033[0m missing property on map %s: name is mandatory on a map." % (self.base))
+ self.name="ERROR"
+ #raise AttributeError('name')
+
+ if name == u'object':
+ if not attr.has_key('type'):
+ self.object = Object()
+ self.object.name = attr[u'name']
+ self.object.ignore = 'auto=>type' # no type: implicitly ignored
+ return
+
+ obj_type = attr[u'type'].lower()
+ x = int(float(attr[u'x']) / TILESIZE)
+ y = int(float(attr[u'y']) / TILESIZE)
+ w = int(float(attr.get(u'width', 0)) / TILESIZE)
+ h = int(float(attr.get(u'height', 0)) / TILESIZE)
+ # I'm not sure exactly what the w/h shrinking is for,
+ # I just copied it out of the old converter.
+ # I know that the x += w/2 is to get centers, though.
+ if obj_type == 'spawn':
+ self.object = Mob()
+ w = int((w - 1) / 2)
+ h = int((h - 1) / 2)
+ if w < 0:
+ w = 0
+ else:
+ x += w
+ if h < 0:
+ h = 0
+ else:
+ y += h
+ elif obj_type == 'save':
+ self.object = Save()
+ x += w/2
+ y += h/2
+ w -= 2
+ h -= 2
+ elif obj_type == 'anchor':
+ self.object = Anchor()
+ x += w/2
+ y += h/2
+ w -= 2
+ h -= 2
+ elif obj_type == 'warp':
+ self.object = Warp()
+ x += w/2
+ y += h/2
+ w -= 1
+ h -= 1
+ else:
+ if obj_type not in other_object_types:
+ print('\n\nWarning: unknown object type \"%s\" on map %s.' % (obj_type, self.base), file=sys.stderr)
+ self.object = None
+ return
+ obj = self.object
+ obj.x = x
+ obj.y = y
+ obj.w = w
+ obj.h = h
+ obj.name = attr[u'name']
+ elif name == u'property':
+ obj = self.object
+ if obj is None:
+ return
+ key = attr[u'name'].lower()
+ value = attr[u'value']
+ # Not true due to defaulting
+ #assert not hasattr(obj, key)
+ try:
+ value = int(value)
+ except ValueError:
+ pass
+ try:
+ setattr(obj, key, value)
+ except AttributeError:
+ print("\n\nERROR: extraneous property on object \"%s\": %s is not allowed on a %s object." % (obj.name, key, obj.__class__.__name__.lower()))
+ raise
+
+ def add_warp_line(self, line):
+ self.warps.write(line)
+
+ def endElement(self, name):
+ if dump_all:
+ print('</%s>' % name)
+
+ if name == u'object':
+ if hasattr(self.object, 'ignore'):
+ if (self.object.ignore == 'auto=>type'):
+ print("\n\nwarning: object \"%s\" has no type and will be ignored.\nTo silence this warning, add an \"ignore\" property to the object." % self.object.name)
+ return
+ obj = self.object
+ try:
+ if isinstance(obj, Mob):
+ if not hasattr(obj, 'monster_id'):
+ obj.monster_id = 0
+ mob_id = obj.monster_id
+ if mob_id < 1002:
+ mob_id+=1002
+ print("Legacy offset mobid, applied +1002")
+ if check_mobs:
+ try:
+ name = mob_names[mob_id]
+ except KeyError:
+ for mid, mn in mob_names.iteritems():
+ if mn == obj.name:
+ mob_id = mid
+ name = obj.name
+ if mob_id == obj.monster_id:
+ print('\n\nWarning: unknown mob ID %d (%s) on map %s.' % (mob_id, obj.name, self.base))
+ return
+ else:
+ if name != obj.name:
+ print('\n\nWarning: wrong mob name on map %s: %s (!= %s)' % (self.base, obj.name, name))
+ obj.name = name
+ self.mob_ids.add(mob_id)
+ if obj.script:
+ obj.script = ",%s" % (obj.script)
+ try:
+ if (obj.ea_death):
+ obj.death=obj.ea_death
+ print('Legacy eA monster')
+ if (obj.ea_spawn):
+ obj.spawn=obj.ea_spawn
+ print('Legacy eA monster')
+ except:
+ pass
+ self.mobs.write(
+ SEPARATOR.join([
+ '%s,%d,%d,%d,%d\t' % (self.base, obj.x, obj.y, obj.w, obj.h),
+ 'monster\t',
+ obj.name,
+ '\t%d,%d,%d,%d%s\n' % (mob_id, obj.max_beings, obj.spawn, obj.death, obj.script),
+ ])
+ )
+ self.mob_cnt = True
+ elif isinstance(obj, Save):
+ obj_name = "%s_%s_%s" % (self.base, obj.x, obj.y)
+ self.saves.write(
+ SEPARATOR.join([
+ '%s,%d,%d,0\tscript\t#save_%s\tNPC_SAVE_POINT,0,0,{\n' % (self.base, obj.x, obj.y, obj_name),
+ ' savepointparticle .map$, .x, .y, %s;\n close;\n\nOnInit:\n .distance = 2;\n .sex = G_OTHER;\n end;\n\nOnTouch:\n bedTouch();\n end;\n}\n' % (obj.inn),
+ ])
+ )
+ self.save_cnt = True
+ elif isinstance(obj, Anchor):
+ self.anchor_master.append(' htput(.ht, "%s", "%s %d %d");\n' % (obj.name.upper(), self.base, obj.x, obj.y))
+ elif isinstance(obj, Warp):
+ try:
+ if obj.dest_tile_x:
+ obj.dest_x=obj.dest_tile_x
+ obj.dest_y=obj.dest_tile_y
+ print("Legacy warp object")
+ except:
+ pass
+ if (obj.npc_id == u'WARP'):
+ obj_name = "#%s_%s_%s" % (self.base, obj.x, obj.y)
+ if (obj.dest_map.lower() in ["slide", "self"]):
+ self.warps.write(
+ SEPARATOR.join([
+ '%s,%d,%d,0\t' % (self.base, obj.x, (obj.y)),
+ 'script\t',
+ '%s\tNPC_HIDDEN,%d,%d,{\n\tend;\nOnTouch:\n\tslide %d,%d; end;\n}\n' % (obj_name, obj.w, obj.h, obj.dest_x, obj.dest_y),
+ ])
+ )
+ else:
+ self.warps.write(
+ SEPARATOR.join([
+ '%s,%d,%d,0\t' % (self.base, obj.x, obj.y),
+ 'warp\t',
+ '%s\t%s,%s,%s,%d,%d\n' % (obj_name, obj.w, obj.h, obj.dest_map, obj.dest_x, obj.dest_y),
+ ])
+ )
+ self.warp_cnt = True
+ elif (not obj.npc_id == u'SCRIPT'):
+ obj_name = "#%s_%s_%s" % (self.base, obj.x, obj.y)
+ self.warps.write(
+ SEPARATOR.join([
+ '%s,%d,%d,0\tscript\t%s_h\tNPC_HIDDEN,0,0,{\n' % (self.base, obj.x, obj.y, obj_name),
+ 'OnTouch:\n warp "%s", %d, %d;\nclose;\n\nOnUnTouch:\n doevent "%s::OnUnTouch";\n}\n' % (obj.dest_map, obj.dest_x, obj.dest_y, obj_name),
+ '%s,%d,%d,0\tscript\t%s\t%s,%d,%d,{\n close;\nOnTouch:\n doorTouch;\n\nOnUnTouch:\n doorUnTouch;\n\nOnTimer340:\n doorTimer;\n\nOnInit:\n doorInit;\n}\n\n' % (self.base, obj.x, obj.y, obj_name, obj.npc_id, obj.trigger_x, obj.trigger_y),
+ ])
+ )
+ self.warp_cnt = True
+ except AttributeError, prop:
+ print("\n\nERROR: missing property on object \"%s\": %s is mandatory on a %s object." % (obj.name, prop, obj.__class__.__name__.lower()));
+ raise
+
+ if name == u'data':
+ if self.state is State.DATA:
+ for x in self.buffer.split(','):
+ if int(x) > 0:
+ self.heightmap += str((int(x) - int(self.firstgid)) + 1)
+ else:
+ self.heightmap += str(x)
+ self.state = State.LAYER
+
+ def endDocument(self):
+ if not self.mob_cnt:
+ os.remove(posixpath.join(main.this_map_npc_dir, NPC_MOBS))
+ if not self.save_cnt:
+ os.remove(posixpath.join(main.this_map_npc_dir, NPC_SAVES))
+ if not self.warp_cnt:
+ os.remove(posixpath.join(main.this_map_npc_dir, NPC_WARPS))
+
+ imp_cnt = (len(os.walk(self.npc_dir).next()[2]))
+
+ if imp_cnt > 0:
+ self.imports.write('// Map %s: %s\n' % (self.base, self.name))
+ self.imports.write('// %s\n' % MESSAGE)
+
+ npcs = os.listdir(self.npc_dir)
+ npcs.sort()
+ for x in npcs:
+ if x == NPC_IMPORTS:
+ continue
+ if x.startswith('.'):
+ continue
+ if x.endswith('.txt'):
+ self.imports.write('"%s",\n' % posixpath.join(SERVER_NPCS, self.base, x))
+ else:
+ os.remove(posixpath.join(main.this_map_npc_dir, NPC_IMPORTS))
+
+def main(argv):
+ _, client_data, server_data = argv
+ tmx_dir = posixpath.join(client_data, CLIENT_MAPS)
+ npc_dir = posixpath.join(server_data, SERVER_NPCS)
+ if check_mobs:
+ global mob_names
+ mob_names = {}
+ with open(posixpath.join(server_data, MOB_DB_CONF)) as mob_db:
+ for line in mob_db:
+ line = line.strip()
+ if not line:
+ continue
+ elif line.startswith('//'):
+ continue
+ elif line.endswith(')'):
+ continue # the template on top of the file
+ elif line.startswith('Id:'):
+ current_id = int(line[4:].strip())
+ elif line.startswith('Name:'):
+ mob_names[current_id] = line[7:-1].strip()
+
+ npc_master = []
+ anchor_master = []
+ map_basenames = []
+
+ map_conf = open(posixpath.join(server_data,MAP_CONF), 'w')
+ map_db = open(posixpath.join(server_data,MAP_DB_CONF), 'w')
+ map_conf.write("map_removed: (\n)\nmap_list: (\n")
+ map_count = 1
+ for arg in sorted(os.listdir(tmx_dir)):
+ base, ext = posixpath.splitext(arg)
+
+ if ext == '.tmx':
+ map_basenames.append(base)
+ tmx = posixpath.join(tmx_dir, arg)
+ main.this_map_npc_dir = posixpath.join(npc_dir, base)
+ os.path.isdir(main.this_map_npc_dir) or os.mkdir(main.this_map_npc_dir)
+ sys.stdout.write('\033[2K\rConverting: %s' % (tmx))
+ sys.stdout.flush()
+ try:
+ with open(posixpath.join(main.this_map_npc_dir, NPC_MOBS), 'w') as mobs:
+ with open(posixpath.join(main.this_map_npc_dir, NPC_SAVES), 'w') as saves:
+ with open(posixpath.join(main.this_map_npc_dir, NPC_WARPS), 'w') as warps:
+ with open(posixpath.join(main.this_map_npc_dir, NPC_IMPORTS), 'w') as imports:
+ xml.sax.parse(tmx, ContentHandler(main.this_map_npc_dir, mobs, saves, warps, imports, anchor_master))
+ if os.path.isfile(posixpath.join(main.this_map_npc_dir, NPC_IMPORTS)):
+ npc_master.append('@include "%s"\n' % posixpath.join(SERVER_NPCS, base, NPC_IMPORTS))
+
+ map_db.write('%s %d\n' % (arg.split('.')[0], map_count))
+ map_conf.write(' "%s",\n' % (arg.split('.')[0]))
+ map_count += 1
+ except Exception, e:
+ if 'CI' in os.environ and str(e) != 'ignore':
+ raise # re-raise to make CI jobs fail
+ elif str(e) == 'ignore':
+ print("map %s has been ignored." % base)
+ pass
+ else:
+ print("\n\nUnexpected error in map %s.\n" % base)
+ traceback.print_exc()
+ map_conf.write(")\n")
+ sys.stdout.write('\033[2K\nDone: %i maps converted.\n' % map_count)
+ sys.stdout.flush()
+ with open(posixpath.join(npc_dir, NPC_MASTER_ANCHORS), 'w') as out:
+ out.write('// %s\n\n' % MESSAGE)
+ out.write('-\tscript\t__anchors__\t32767,{\n')
+ out.write('OnInit:\n')
+ out.write(' .ht = htnew();\n')
+ anchor_master.sort()
+ for line in anchor_master:
+ out.write(line)
+ out.write('}\n')
+ with open(posixpath.join(npc_dir, NPC_MASTER_IMPORTS), 'w') as out:
+ out.write('// %s\n\n' % MESSAGE)
+ npc_master.sort()
+ for line in npc_master:
+ out.write(line)
+ out.write('"%s",\n' % posixpath.join(SERVER_NPCS, NPC_MASTER_ANCHORS))
+
+if __name__ == '__main__':
+ main(sys.argv)
diff --git a/herculeswrapper/char.sh b/herculeswrapper/char.sh
new file mode 100755
index 0000000..2b794d9
--- /dev/null
+++ b/herculeswrapper/char.sh
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+
+export PIPE=./log/charpipe.tmp
+
+source ${dir}/include.sh
+
+server_logic ./char-server 2s
diff --git a/herculeswrapper/herc-map-wrapper-config.example b/herculeswrapper/herc-map-wrapper-config.example
new file mode 100644
index 0000000..00bfe8b
--- /dev/null
+++ b/herculeswrapper/herc-map-wrapper-config.example
@@ -0,0 +1,77 @@
+## config for herc-map-wrapper
+
+echo "Copy this file to herc-map-wrapper-config" >&2
+echo "Then You need to either set the oauth secret" >&2
+echo "or use a hard-coded list instead of list_issues" >&2
+echo "Both github and gitlab methods are included.">&2
+echo "Make sure to comment out the method that isn't used" >&2
+echo "Update the <repo ids> with the ID number for gitlab" >&2
+echo "or the repo name if github i.e. themanaworld/server-data" >&2
+echo "Then, delete these lines" >&2
+exit 1
+
+server_data=../../server-data
+client_data=../client-data
+evol_music=../music
+tmw_tools=../tools
+
+#gitlab
+list_issues()
+{
+python -c '
+
+# replace this with one of your oauth keys from github (no permissions needed)
+oauth = "01234567890123456789"
+
+import requests
+issues = requests.get("https://gitlab.com/api/v4/projects/%d/merge_requests" % '$1', params={"state": "opened"}, headers={"PRIVATE-TOKEN": "%s" % oauth, "Accept": "application/vnd.gitlab.v4+json"})
+issues.raise_for_status()
+for issue in issues.json():
+ if "test" in issue["labels"]:
+ print(issue["iid"])
+' | sort -n
+}
+
+#github
+list_issues()
+{
+python -c '
+
+# replace this with one of your oauth keys from github (no permissions needed)
+oauth = "0123456789abcdef0123456789abcdef01234567"
+
+import requests
+issues = requests.get("https://api.github.com/search/issues", params={"q": "repo:'$1' type:pr state:open label:test"}, headers={"Authorization": "token %s" % oauth, "Accept": "application/vnd.github.v3+json"})
+issues.raise_for_status()
+for issue in issues.json["items"]:
+ print(issue["number"])
+' | sort -n
+}
+
+
+server_main_branch=origin/master
+
+server_extra_branches=(
+ $(list_issues <repo id> | sed 's|^|origin/merge-requests/|;')
+)
+
+client_main_branch=origin/master
+
+client_extra_branches=(
+ $(list_issues <repo id> | sed 's|^|origin/merge-requests/|;')
+)
+
+music_main_branch=origin/master
+
+music_extra_branches=(
+ $(list_issues <repo id> | sed 's|^|origin/merge-requests/|;')
+)
+unset list_issues
+
+motd=../server-data/npc/commands/motd-debug-text.txt
+
+expected_life=60
+trouble_sleep=60
+normal_sleep=5
+
+ulimit -c unlimited
diff --git a/herculeswrapper/include.sh b/herculeswrapper/include.sh
new file mode 100644
index 0000000..17c8c0a
--- /dev/null
+++ b/herculeswrapper/include.sh
@@ -0,0 +1,287 @@
+#!/usr/bin/env bash
+
+function create_pipe {
+ trap "rm -f $PIPE" EXIT
+ if [[ ! -p $PIPE ]]; then
+ echo "Making pipe $PIPE"
+ rm -f $PIPE
+ mkfifo $PIPE
+ fi
+}
+
+# $1 - text
+function send_all_pipes {
+ echo $1 >$LOGIN_PIPE
+ echo $1 >$CHAR_PIPE
+}
+
+# $1 - text
+function send_char_pipe {
+ echo $1 >$CHAR_PIPE
+}
+
+# $1 - server binary name
+# $2 - sleep time
+function server_logic {
+ create_pipe
+ $1
+
+ while true
+ do
+ if read line <$PIPE; then
+ echo pipe: $line
+ if [[ "$line" == 'exit' ]]; then
+ exit
+ fi
+ if [[ "$line" == 'restart' ]]; then
+ sleep $2
+ $1
+ fi
+ fi
+ done
+}
+
+function hard_reset {
+ echo ${1}: hard reset
+ git fetch upstream
+ git reset --hard upstream/master
+ git clean -fd
+ # the following should be unnecessary, but just in case:
+ git checkout --detach
+ git branch -D master
+ git checkout upstream/master -b master
+}
+
+function pull_all {
+ hard_reset "data"
+ cd ../client-data
+ hard_reset "client"
+ cd ../music
+ hard_reset "music"
+ cd ../server-code
+ hard_reset "code"
+ cd src/evol
+ hard_reset "plugin"
+ cd ../../../tools
+ hard_reset "tools"
+ cd ..
+ ./pull.sh
+ cd server-data
+ git_merge
+ cd ../
+ ./status.sh
+ cd server-data
+ make maps
+}
+
+function build_all {
+ cd ../server-code
+ ./build.sh $BUILD_MAP 2>err.txt
+ cat err.txt
+ cd ../server-data
+ make updatedb
+}
+
+function build_clean {
+ cd ../tools/localserver
+ ./clean.sh
+ cd ../../server-data
+}
+
+function build_plugin {
+ cd ../server-plugin
+ ./build.sh 2>err.txt
+ cat err.txt
+ cd ../server-data
+}
+
+function git_merge {
+ if [ -f ../tools/herculeswrapper/herc-map-wrapper-config ]
+ then
+ # prevent interaction
+ export GIT_EDITOR=:
+ # force commits to have predictable hashes
+ export GIT_AUTHOR_DATE='1970-01-01 00:00 +0000'
+ export GIT_COMMITTER_DATE='1970-01-01 00:00 +0000'
+
+ reset=$'\e[m'
+ black_fg=$'\e[30m'
+ red_fg=$'\e[31m'
+ green_fg=$'\e[32m'
+ yellow_fg=$'\e[33m'
+ blue_fg=$'\e[34m'
+ magenta_fg=$'\e[35m'
+ cyan_fg=$'\e[36m'
+ gray_fg=$'\e[37m'
+
+ reset2='##0'
+ black_fg2='##0'
+ red_fg2='##1'
+ green_fg2='##2'
+ blue_fg2='##3'
+ orange_fg2='##4'
+ yellow_fg2='##5'
+ pink_fg2='##6'
+ purple_fg2='##7'
+ gray_fg2='##8'
+ brown_fg2='##9'
+
+
+ now()
+ {
+ date -u +'%F %T'
+ }
+
+ good()
+ {
+ echo "$(now)$green_fg" "$@" "$reset" >&2
+ }
+
+ info()
+ {
+ echo "$(now)$cyan_fg" "$@" "$reset" >&2
+ }
+
+ warning()
+ {
+ echo "$(now)$yellow_fg" "$@" "$reset" >&2
+ }
+
+ error()
+ {
+ echo "$(now)$red_fg" "$@" "$reset" >&2
+ }
+
+ good2()
+ {
+ echo \""$green_fg2" "$@" "$reset2"\",
+ }
+
+ info2()
+ {
+ echo \""$brown_fg2" "$@" "$reset2"\",
+ }
+
+ warning2()
+ {
+ echo \""$yellow_fg2" "$@" "$reset2"\",
+ }
+
+ error2()
+ {
+ echo \""$red_fg2" "$@" "$reset2"\",
+ }
+
+ run()
+ {
+ info '$' "$@"
+ "$@"
+ }
+
+ wipe_logs()
+ {
+ echo -e "$(now)\n===\n" > $merge_log
+ chmod +r $merge_log
+ }
+
+ do_git()
+ {
+ info '$' "git $@"
+ echo -e "${PWD##*/} $ git $@" >> $merge_log
+ git "$@" 2> >(tee -a $merge_log >&2)
+ ec=$?
+
+ # print a newline to logs on error
+ if [[ $ec != 0 ]]; then echo "" >> $merge_log; fi
+ return $ec
+ }
+
+ try_merge()
+ {
+ test -n "$1"
+ local branch=$1 commit
+ info 'commit=$(' git rev-parse --verify -q $branch ')'
+ if ! commit=$(git rev-parse --verify -q $branch)
+ then
+ error2 bogus $branch >> $motd
+ error bogus $branch
+ return
+ fi
+ info commit=$commit
+ if run bash -c 'set -o pipefail; git branch --contains '$commit' | grep -qw master'
+ then
+ warning2 already $branch $commit >> $motd
+ warning already $branch
+ return
+ fi
+ if git merge-base --is-ancestor $branch $commit && do_git merge --ff-only $branch $commit
+ then
+ good2 fast $branch $commit >> $motd
+ good fast $branch $commit
+ return
+ fi
+ if do_git merge $branch $commit
+ then
+ good2 merge $branch $commit >> $motd
+ good merge $branch $commit
+ return
+ fi
+ git merge --abort
+ error2 abort $branch $commit >> $motd
+ error abort $branch $commit
+ return
+ }
+
+ start_time=$(date +%s)
+ source ../tools/herculeswrapper/herc-map-wrapper-config
+
+ run test -f $motd
+ echo -e 'function\tscript\tMOTD_debug_text\t{\n setarray $@Debug_Messages$[0],' > $motd
+ merge_log=${tmw_tools}/herculeswrapper/stderr.log
+ wipe_logs
+ do_git fetch --all
+ do_git reset --hard $server_main_branch
+ info 'commit=$(' git rev-parse --verify -q $server_main_branch ')'
+ commit=$(git rev-parse --verify -q $server_main_branch)
+ info2 server base $server_main_branch $commit >> $motd
+ for branch in ${server_extra_branches[@]}
+ do
+ try_merge $branch
+ done
+
+ run cd $client_data
+
+ # force new master and back up for future restoration
+ do_git fetch --all
+ do_git reset --hard $client_main_branch
+
+ info 'commit=$(' git rev-parse --verify -q $client_main_branch ')'
+ commit=$(git rev-parse --verify -q $client_main_branch)
+ info2 client base $client_main_branch $commit >> $motd
+ for branch in ${client_extra_branches[@]}
+ do
+ try_merge $branch
+ done
+
+ run cd $evol_music
+
+ do_git fetch --all
+ do_git reset --hard $music_main_branch
+ info 'commit=$(' git rev-parse --verify -q $music_main_branch ')'
+ commit=$(git rev-parse --verify -q $music_main_branch)
+ info2 music base $music_main_branch $commit >> $motd
+ for branch in ${music_extra_branches[@]}
+ do
+ try_merge $branch
+ done
+
+ echo '"End of Commits";' >> $motd
+ echo -e ' return;\n}' >> $motd
+
+ # generate the transient updates
+ run cd $tmw_tools/update/
+ run ./createnew.sh
+ run ./create_music.sh
+ run cd ../../server-data/
+ fi
+}
diff --git a/herculeswrapper/login.sh b/herculeswrapper/login.sh
new file mode 100755
index 0000000..32085dd
--- /dev/null
+++ b/herculeswrapper/login.sh
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+
+export PIPE=./log/loginpipe.tmp
+
+source ${dir}/include.sh
+
+server_logic ./login-server 0s
diff --git a/herculeswrapper/map.sh b/herculeswrapper/map.sh
new file mode 100755
index 0000000..d0cd929
--- /dev/null
+++ b/herculeswrapper/map.sh
@@ -0,0 +1,102 @@
+#!/usr/bin/env bash
+
+export PIPE=./log/mappipe.tmp
+export LOGIN_PIPE=./log/loginpipe.tmp
+export CHAR_PIPE=./log/charpipe.tmp
+
+source ${dir}/include.sh
+
+create_pipe
+
+while [ 1 ] ; do
+ $DEBUG_MAP ./map-server
+ export ret=$?
+ case "${ret}" in
+ 0)
+ echo "Returned 0. Probably ctrl+c"
+ break
+ ;;
+ 1)
+ echo "Returned 1. Probably error in server"
+ [ ! -z "$DEBUG_MAP" ] || break
+ ;;
+ 100)
+ echo "Terminating server"
+ send_all_pipes "exit"
+ break
+ ;;
+ 101)
+ echo "Restarting all servers..."
+ send_all_pipes "restart"
+ sleep 5s
+ ;;
+ 102)
+ echo "Restarting chat and map servers..."
+ send_char_pipe "restart"
+ sleep 3s
+ ;;
+ 103)
+ echo "Restarting map server..."
+ ;;
+ 104)
+ echo "git pull..."
+ pull_all
+ echo "Restarting all servers..."
+ send_all_pipes "restart"
+ sleep 5s
+ ;;
+ 105)
+ echo "Build all servers"
+ sleep 5s
+ build_all
+ echo "Restarting all servers..."
+ send_all_pipes "restart"
+ sleep 5s
+ ;;
+ 106)
+ echo "Rebuild all servers"
+ sleep 5s
+ build_clean
+ build_all
+ echo "Restarting all servers..."
+ send_all_pipes "restart"
+ sleep 5s
+ ;;
+ 107)
+ echo "git pull..."
+ pull_all
+ echo "Build all servers"
+ build_all
+ echo "Restarting all servers..."
+ send_all_pipes "restart"
+ sleep 5s
+ ;;
+ 108)
+ echo "git pull..."
+ pull_all
+ echo "Rebuild all servers"
+ build_clean
+ build_all
+ echo "Restarting all servers..."
+ send_all_pipes "restart"
+ sleep 5s
+ ;;
+ 109)
+ echo "Build plugin"
+ sleep 5s
+ build_plugin
+ echo "Restarting all servers..."
+ send_all_pipes "restart"
+ sleep 5s
+ ;;
+ 110)
+ echo "git pull..."
+ pull_all
+ echo "Build plugin"
+ build_plugin
+ echo "Restarting all servers..."
+ send_all_pipes "restart"
+ sleep 5s
+ ;;
+ esac
+done
diff --git a/lang/fetch.py b/lang/fetch.py
new file mode 100755
index 0000000..67c667f
--- /dev/null
+++ b/lang/fetch.py
@@ -0,0 +1,48 @@
+#! /usr/bin/env python2.7
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2018 TMW-2
+# Author: Jesusalva
+
+from transifex.api import TransifexAPI
+
+project='tmw'
+
+# Load credentials from login.txt and password.txt
+login=open('login.txt', 'r')
+for i in login:
+ username=i.replace('\n', '').replace('\r', '')
+
+login.close()
+
+passw=open('password.txt', 'r')
+for i in passw:
+ password=i.replace('\n', '').replace('\r', '')
+
+passw.close()
+
+t=TransifexAPI(username, password, 'https://www.transifex.com')
+
+if (not t.ping):
+ print("ERROR: Ping failed, this may be due incorrect username/password in login.txt and password.txt. Ensure there is NO newline at the end of file.")
+ exit(1)
+
+if (not t.project_exists(project)):
+ print("ERROR: Invalid project name")
+ exit(1)
+
+# Load languages
+langs=[]
+vcx=open("../../server-data/langs/langs.txt", "r")
+for i in vcx:
+ if i != "en":
+ langs.append(i.replace('\n', ''))
+vcx.close()
+
+# Fetch all translations and record them at in/
+for i in langs:
+ if i not in ['en']:
+ print("Fetching %s..." %(i))
+ t.get_translation(project, 'serverdata', i, 'in/'+str(i)+'.po')
+
+
diff --git a/lang/in/.gitignore b/lang/in/.gitignore
new file mode 100644
index 0000000..6d609ce
--- /dev/null
+++ b/lang/in/.gitignore
@@ -0,0 +1 @@
+*.po
diff --git a/lang/out/.gitignore b/lang/out/.gitignore
new file mode 100644
index 0000000..6d609ce
--- /dev/null
+++ b/lang/out/.gitignore
@@ -0,0 +1 @@
+*.po
diff --git a/lang/serverdata.pot b/lang/serverdata.pot
new file mode 100644
index 0000000..a3015de
--- /dev/null
+++ b/lang/serverdata.pot
@@ -0,0 +1,9906 @@
+# Copyright (C) 2010-2015 Evol Online
+#
+
+msgid ""
+msgstr ""
+"Project-Id-Version: EvolOnline\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. code: mes l("1) Do not abuse other players. Insults, swearing, and the like are not to be directed towards a particular person or group.");
+#: npc/functions/game_rules.txt:6
+#, no-c-format
+msgid "1) Do not abuse other players. Insults, swearing, and the like are not to be directed towards a particular person or group."
+msgstr ""
+
+#. code: mes l("2) No bots – including ##Bany##b AFK activity or automated actions of any sort.");
+#: npc/functions/game_rules.txt:7
+#, no-c-format
+msgid "2) No bots – including ##Bany##b AFK activity or automated actions of any sort."
+msgstr ""
+
+#. code: mes l("3) No spamming or flooding (including messages, whispers, and trade requests).");
+#: npc/functions/game_rules.txt:8
+#, no-c-format
+msgid "3) No spamming or flooding (including messages, whispers, and trade requests)."
+msgstr ""
+
+#. code: mes l("4) No begging.");
+#: npc/functions/game_rules.txt:9
+#, no-c-format
+msgid "4) No begging."
+msgstr ""
+
+#. code: mes l("5) Speak ##Bonly##b English in the public chat.");
+#: npc/functions/game_rules.txt:10
+#, no-c-format
+msgid "5) Speak ##Bonly##b English in the public chat."
+msgstr ""
+
+#. code: mes l("6) Treat others how you would like to be treated.");
+#: npc/functions/game_rules.txt:11
+#, no-c-format
+msgid "6) Treat others how you would like to be treated."
+msgstr ""
+
+#. code: 052-2,1,1,0 script ? NPC127,{
+#: npc/052-2/lobby.txt:127
+#, no-c-format
+msgid "?"
+msgstr ""
+
+#. code: mes l("AFK botting will be determined by talking to players who are moving and/or attacking.");
+#: npc/functions/game_rules.txt:12
+#, no-c-format
+msgid "AFK botting will be determined by talking to players who are moving and/or attacking."
+msgstr ""
+
+#. code: Name: "AFKCap"
+#: item_db.conf:-1
+#, no-c-format
+msgid "AFKCap"
+msgstr ""
+
+#. code: 029-1,71,52,0 script Aahna NPC404,{
+#: npc/029-1/aahna.txt:0
+#, no-c-format
+msgid "Aahna"
+msgstr ""
+
+#. code: 030-2,78,34,0 script Aaron NPC328,{
+#: npc/030-2/basic_npcs.txt:59
+#, no-c-format
+msgid "Aaron"
+msgstr ""
+
+#. code: Name: "Acorn"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Acorn"
+msgstr ""
+
+#. code: Name: "ActivatedSulphur"
+#: item_db.conf:-1
+#, no-c-format
+msgid "ActivatedSulphur"
+msgstr ""
+
+#. code: 001-1,113,64,0 script Adrian NPC213,{
+#: npc/001-1/adrian.txt:0
+#, no-c-format
+msgid "Adrian"
+msgstr ""
+
+#. code: 020-2,27,26,0 script Agostine NPC137,{
+#: npc/020-2/furquest.txt:36
+#, no-c-format
+msgid "Agostine"
+msgstr ""
+
+#. code: 020-2,24,26,0 script Agostine Debug NPC137,{
+#: npc/020-2/furquest.txt:1
+#, no-c-format
+msgid "Agostine Debug"
+msgstr ""
+
+#. code: 029-1,45,97,0 script Aidan NPC102,{
+#: npc/029-1/monster_guide.txt:1
+#, no-c-format
+msgid "Aidan"
+msgstr ""
+
+#. code: 009-2,123,71,0 script Airlia NPC108,{
+#: npc/009-2/airlia.txt:3
+#, no-c-format
+msgid "Airlia"
+msgstr ""
+
+#. code: 001-1,102,27,0 script Aisha NPC108,{
+#: npc/001-1/children.txt:1
+#, no-c-format
+msgid "Aisha"
+msgstr ""
+
+#. code: 030-2,31,85,0 script Akseli NPC329,{
+#: npc/030-2/basic_npcs.txt:31
+#, no-c-format
+msgid "Akseli"
+msgstr ""
+
+#. code: 027-2,45,105,0 script Alacrius NPC313,{
+#: npc/027-2/alacrius.txt:1
+#, no-c-format
+msgid "Alacrius"
+msgstr ""
+
+#. code: 009-2,99,23,0 script Alan NPC125,{
+#: npc/009-2/alan.txt:1
+#, no-c-format
+msgid "Alan"
+msgstr ""
+
+#. code: 026-2,67,86,0 script Aldred NPC314,{
+#: npc/026-2/crying_child.txt:1
+#, no-c-format
+msgid "Aldred"
+msgstr ""
+
+#. code: 015-1,52,53,0 script Alice NPC106,{
+#: npc/015-1/alice.txt:1
+#, no-c-format
+msgid "Alice"
+msgstr ""
+
+#. code: Name: "AlizarinHerb"
+#: item_db.conf:-1
+#, no-c-format
+msgid "AlizarinHerb"
+msgstr ""
+
+#. code: Name: "AmberChristmasSweater"
+#: item_db.conf:-1
+#, no-c-format
+msgid "AmberChristmasSweater"
+msgstr ""
+
+#. code: Name: "Amethyst"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Amethyst"
+msgstr ""
+
+#. code: Name: "AmethystPowder"
+#: item_db.conf:-1
+#, no-c-format
+msgid "AmethystPowder"
+msgstr ""
+
+#. code: Name: "AmethystRing"
+#: item_db.conf:-1
+#, no-c-format
+msgid "AmethystRing"
+msgstr ""
+
+#. code: 012-1,137,104,0 script Amrak NPC103,{
+#: npc/012-1/amrak.txt:1
+#, no-c-format
+msgid "Amrak"
+msgstr ""
+
+#. code: 008-1,36,26,0 script Andra NPC201,{
+#: npc/008-1/andra.txt:1
+#, no-c-format
+msgid "Andra"
+msgstr ""
+
+#. code: 031-1,79,24,0 script Angela NPC195,15,15,{
+#: npc/031-1/angelaOutside.txt:30
+#, no-c-format
+msgid "Angela"
+msgstr ""
+
+#. code: 031-2,29,28,0 script Angela#house NPC196,{
+#: npc/031-2/angelaHouse.txt:1
+#, no-c-format
+msgid "Angela#house"
+msgstr ""
+
+#. code: Name: "AngryScorpionStinger"
+#: item_db.conf:-1
+#, no-c-format
+msgid "AngryScorpionStinger"
+msgstr ""
+
+#. code: 018-2,31,39,0 script Angus NPC147,{
+#: npc/018-2/angus.txt:1
+#, no-c-format
+msgid "Angus"
+msgstr ""
+
+#. code: 030-4,32,21,0 script AniManOMat NPC400,{
+#: npc/030-4/mana_battery.txt:4
+#, no-c-format
+msgid "AniManOMat"
+msgstr ""
+
+#. code: Name: "AnimalBones"
+#: item_db.conf:-1
+#, no-c-format
+msgid "AnimalBones"
+msgstr ""
+
+#. code: Name: "AnniversaryHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "AnniversaryHat"
+msgstr ""
+
+#. code: 051-3,33,95,0 script Another Sneaky Bandit NPC32767,{
+#: npc/051-3/ambush.txt:147
+#, no-c-format
+msgid "Another Sneaky Bandit"
+msgstr ""
+
+#. code: Name: "AntlerHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "AntlerHat"
+msgstr ""
+
+#. code: Name: "Antlers"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Antlers"
+msgstr ""
+
+#. code: 002-1,95,67,0 script Anwar NPC156,{
+#: npc/002-1/anwar.txt~:0
+#: npc/002-1/anwar.txt:0
+#, no-c-format
+msgid "Anwar"
+msgstr ""
+
+#. code: Name: "AppleCake"
+#: item_db.conf:-1
+#, no-c-format
+msgid "AppleCake"
+msgstr ""
+
+#. code: 009-2,97,24,0 shop Apprentice NPC120,904:0,1199:2,529:2,1200:500,530:4000
+#: npc/009-2/shops.txt:9
+#, no-c-format
+msgid "Apprentice"
+msgstr ""
+
+#. code: Name: "ApprenticeRobe"
+#: item_db.conf:-1
+#, no-c-format
+msgid "ApprenticeRobe"
+msgstr ""
+
+#. code: Name: "AquaHint"
+#: item_db.conf:-1
+#, no-c-format
+msgid "AquaHint"
+msgstr ""
+
+#. code: Name: "AquaOrnament"
+#: item_db.conf:-1
+#, no-c-format
+msgid "AquaOrnament"
+msgstr ""
+
+#. code: Name: "AquaTicket"
+#: item_db.conf:-1
+#, no-c-format
+msgid "AquaTicket"
+msgstr ""
+
+#. code: 001-3,69,37,0 script Aradin NPC126,{
+#: npc/001-3/guards.txt:26
+#, no-c-format
+msgid "Aradin"
+msgstr ""
+
+#. code: 026-2,34,59,0 script Archibald NPC306,{
+#: npc/026-2/testnpcs.txt:12
+#, no-c-format
+msgid "Archibald"
+msgstr ""
+
+#. code: 006-2,30,35,0 shop Ardra NPC179,501:25,502:35,541:100,533:55
+#: npc/006-2/shops.txt:2
+#, no-c-format
+msgid "Ardra"
+msgstr ""
+
+#. code: 011-3,30,23,0 script Arkim NPC116,{
+#: npc/011-3/hermit.txt:1
+#, no-c-format
+msgid "Arkim"
+msgstr ""
+
+#. code: Name: "Arrow"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Arrow"
+msgstr ""
+
+#. code: 048-2,139,99,0 script Arvo NPC366,{
+#: npc/048-2/helperCleaning3.txt:1
+#, no-c-format
+msgid "Arvo"
+msgstr ""
+
+#. code: Name: "AssassinBoots"
+#: item_db.conf:-1
+#, no-c-format
+msgid "AssassinBoots"
+msgstr ""
+
+#. code: Name: "AssassinGloves"
+#: item_db.conf:-1
+#, no-c-format
+msgid "AssassinGloves"
+msgstr ""
+
+#. code: Name: "AssassinPants"
+#: item_db.conf:-1
+#, no-c-format
+msgid "AssassinPants"
+msgstr ""
+
+#. code: Name: "AssassinShirt"
+#: item_db.conf:-1
+#, no-c-format
+msgid "AssassinShirt"
+msgstr ""
+
+#. code: Name: "AstralCube"
+#: item_db.conf:-1
+#, no-c-format
+msgid "AstralCube"
+msgstr ""
+
+#. code: 011-1,50,68,0 script Auldsbel#_M NPC168,{
+#: npc/011-1/auldsbel.txt:1
+#, no-c-format
+msgid "Auldsbel#_M"
+msgstr ""
+
+#. code: Name: "Aureole"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Aureole"
+msgstr ""
+
+#. code: mes l("Automated following will be determined by observation.");
+#: npc/functions/game_rules.txt:13
+#, no-c-format
+msgid "Automated following will be determined by observation."
+msgstr ""
+
+#. code: Name: "AutumnMask"
+#: item_db.conf:-1
+#, no-c-format
+msgid "AutumnMask"
+msgstr ""
+
+#. code: 030-2,198,61,0 script Avalia NPC356,{
+#: npc/030-2/avalia.txt:1
+#, no-c-format
+msgid "Avalia"
+msgstr ""
+
+#. code: Name: "Axe"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Axe"
+msgstr ""
+
+#. code: Name: "AxeHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "AxeHat"
+msgstr ""
+
+#. code: 029-1,62,90,0 script Ayasha NPC258,{
+#: npc/029-1/hideandseek.txt:65
+#, no-c-format
+msgid "Ayasha"
+msgstr ""
+
+#. code: 029-1,64,90,0 script AyashaDebug NPC258,{
+#: npc/029-1/hideandseek.txt:28
+#, no-c-format
+msgid "AyashaDebug"
+msgstr ""
+
+#. code: 020-2,70,61,0 script Baktar NPC191,{
+#: npc/020-2/baktar.txt:0
+#, no-c-format
+msgid "Baktar"
+msgstr ""
+
+#. code: Name: "Bandana"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Bandana"
+msgstr ""
+
+#. code: Name: "BanditHood"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BanditHood"
+msgstr ""
+
+#. code: Name: "BansheeBow"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BansheeBow"
+msgstr ""
+
+#. code: 008-1,70,42,0 script Banu NPC154,{
+#: npc/008-1/banu.txt:0
+#, no-c-format
+msgid "Banu"
+msgstr ""
+
+#. code: 010-2,27,30,0 script Bar Rules NPC400,{
+#: npc/010-2/dimonds.txt:457
+#, no-c-format
+msgid "Bar Rules"
+msgstr ""
+
+#. code: 026-2,75,23,0 script Barbara Grey NPC320,{
+#: npc/026-2/gy_inn_shops.txt:14
+#, no-c-format
+msgid "Barbara Grey"
+msgstr ""
+
+#. code: 002-1,91,33,0 script Bard NPC152,{
+#: npc/002-1/bard.txt:1
+#, no-c-format
+msgid "Bard"
+msgstr ""
+
+#. code: Name: "Bardiche"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Bardiche"
+msgstr ""
+
+#. code: 009-2,65,49,0 shop Barkeeper NPC112,539:87,513:15,676:100
+#: npc/009-2/shops.txt:0
+#, no-c-format
+msgid "Barkeeper"
+msgstr ""
+
+#. code: 029-2,23,86,0 script Barrel#0 NPC400,{
+#: npc/029-2/barrels.txt:0
+#, no-c-format
+msgid "Barrel#0"
+msgstr ""
+
+#. code: 029-2,28,86,0 script Barrel#1 NPC400,{
+#: npc/029-2/barrels.txt:10
+#, no-c-format
+msgid "Barrel#1"
+msgstr ""
+
+#. code: 029-2,31,91,0 script Barrel#2 NPC400,{
+#: npc/029-2/barrels.txt:15
+#, no-c-format
+msgid "Barrel#2"
+msgstr ""
+
+#. code: 029-2,36,85,0 script Barrel#3 NPC400,{
+#: npc/029-2/barrels.txt:20
+#, no-c-format
+msgid "Barrel#3"
+msgstr ""
+
+#. code: 029-2,40,89,0 script Barrel#4 NPC400,{
+#: npc/029-2/barrels.txt:25
+#, no-c-format
+msgid "Barrel#4"
+msgstr ""
+
+#. code: 029-2,38,91,0 script Barrel#5 NPC400,{
+#: npc/029-2/barrels.txt:30
+#, no-c-format
+msgid "Barrel#5"
+msgstr ""
+
+#. code: 029-2,29,92,0 script Barrel#6 NPC400,{
+#: npc/029-2/barrels.txt:35
+#, no-c-format
+msgid "Barrel#6"
+msgstr ""
+
+#. code: 029-2,24,91,0 script Barrel#7 NPC400,{
+#: npc/029-2/barrels.txt:40
+#, no-c-format
+msgid "Barrel#7"
+msgstr ""
+
+#. code: 010-2,24,27,0 shop Bartender NPC112,539:87,567:250,568:250
+#: npc/010-2/dimonds.txt:528
+#, no-c-format
+msgid "Bartender"
+msgstr ""
+
+#. code: 002-2,68,25,0 shop Bartender#Casino NPC112,539:87,513:15,519:50
+#: npc/002-2/shops.txt:1
+#, no-c-format
+msgid "Bartender#Casino"
+msgstr ""
+
+#. code: 009-7,34,23,0 shop Bartender#Duels NPC177,539:87,567:250,568:250,541:100,527:150
+#: npc/009-7/shops.txt:0
+#, no-c-format
+msgid "Bartender#Duels"
+msgstr ""
+
+#. code: 010-2,75,68,0 script Basil NPC107,{
+#: npc/010-2/dimonds.txt:536
+#, no-c-format
+msgid "Basil"
+msgstr ""
+
+#. code: Name: "BastardSword"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BastardSword"
+msgstr ""
+
+#. code: Name: "BatTeeth"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BatTeeth"
+msgstr ""
+
+#. code: Name: "BatWing"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BatWing"
+msgstr ""
+
+#. code: 009-7,40,35,0 script Battle Master#Duels NPC322,{
+#: npc/009-7/battlemaster.txt:0
+#, no-c-format
+msgid "Battle Master#Duels"
+msgstr ""
+
+#. code: Name: "BeanieCopter"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BeanieCopter"
+msgstr ""
+
+#. code: Name: "Beer"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Beer"
+msgstr ""
+
+#. code: Name: "BeetleJuice"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BeetleJuice"
+msgstr ""
+
+#. code: Name: "Beheader"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Beheader"
+msgstr ""
+
+#. code: 020-2,122,64,0 script Ben NPC193,{
+#: npc/020-2/banker.txt:0
+#, no-c-format
+msgid "Ben"
+msgstr ""
+
+#. code: 026-2,37,24,0 script Bennet NPC310,{
+#: npc/026-2/barman.txt:0
+#, no-c-format
+msgid "Bennet"
+msgstr ""
+
+#. code: Name: "BentNeedle"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BentNeedle"
+msgstr ""
+
+#. code: Name: "Beret"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Beret"
+msgstr ""
+
+#. code: 009-2,67,79,0 script Bernard NPC117,{
+#: npc/009-2/bernard.txt:0
+#, no-c-format
+msgid "Bernard"
+msgstr ""
+
+#. code: 033-1,72,27,0 script Birrod NPC217,{
+#: npc/033-1/birrod.txt:0
+#, no-c-format
+msgid "Birrod"
+msgstr ""
+
+#. code: Name: "BlackBeret"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlackBeret"
+msgstr ""
+
+#. code: Name: "BlackBoots"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlackBoots"
+msgstr ""
+
+#. code: Name: "BlackBowlerHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlackBowlerHat"
+msgstr ""
+
+#. code: Name: "BlackBowlerHatBrown"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlackBowlerHatBrown"
+msgstr ""
+
+#. code: Name: "BlackContributor"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlackContributor"
+msgstr ""
+
+#. code: Name: "BlackCottonBoots"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlackCottonBoots"
+msgstr ""
+
+#. code: Name: "BlackCottonCloth"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlackCottonCloth"
+msgstr ""
+
+#. code: Name: "BlackCottonGloves"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlackCottonGloves"
+msgstr ""
+
+#. code: Name: "BlackCottonHeadband"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlackCottonHeadband"
+msgstr ""
+
+#. code: Name: "BlackCottonShirt"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlackCottonShirt"
+msgstr ""
+
+#. code: Name: "BlackCottonShorts"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlackCottonShorts"
+msgstr ""
+
+#. code: Name: "BlackCottonSkirt"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlackCottonSkirt"
+msgstr ""
+
+#. code: Name: "BlackCottonTrousers"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlackCottonTrousers"
+msgstr ""
+
+#. code: Name: "BlackCowboyHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlackCowboyHat"
+msgstr ""
+
+#. code: Name: "BlackDesertHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlackDesertHat"
+msgstr ""
+
+#. code: Name: "BlackDye"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlackDye"
+msgstr ""
+
+#. code: Name: "BlackEvokersRobeBlue"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlackEvokersRobeBlue"
+msgstr ""
+
+#. code: Name: "BlackFineDress"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlackFineDress"
+msgstr ""
+
+#. code: 002-2,75,60,0 script BlackJack NPC107,{
+#: npc/002-2/casino.txt:34
+#, no-c-format
+msgid "BlackJack"
+msgstr ""
+
+#. code: Name: "BlackMiniskirt"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlackMiniskirt"
+msgstr ""
+
+#. code: Name: "BlackPearl"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlackPearl"
+msgstr ""
+
+#. code: Name: "BlackRabbitEars"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlackRabbitEars"
+msgstr ""
+
+#. code: Name: "BlackRose"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlackRose"
+msgstr ""
+
+#. code: Name: "BlackScorpionStinger"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlackScorpionStinger"
+msgstr ""
+
+#. code: Name: "BlackShades"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlackShades"
+msgstr ""
+
+#. code: Name: "BlackShortTankTop"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlackShortTankTop"
+msgstr ""
+
+#. code: Name: "BlackSilkRobe"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlackSilkRobe"
+msgstr ""
+
+#. code: Name: "BlackSorcererBlack"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlackSorcererBlack"
+msgstr ""
+
+#. code: Name: "BlackSorcererDBlue"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlackSorcererDBlue"
+msgstr ""
+
+#. code: Name: "BlackSorcererDGreen"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlackSorcererDGreen"
+msgstr ""
+
+#. code: Name: "BlackSorcererGreen"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlackSorcererGreen"
+msgstr ""
+
+#. code: Name: "BlackSorcererLBlue"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlackSorcererLBlue"
+msgstr ""
+
+#. code: Name: "BlackSorcererOrange"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlackSorcererOrange"
+msgstr ""
+
+#. code: Name: "BlackSorcererPink"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlackSorcererPink"
+msgstr ""
+
+#. code: Name: "BlackSorcererPurple"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlackSorcererPurple"
+msgstr ""
+
+#. code: Name: "BlackSorcererRed"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlackSorcererRed"
+msgstr ""
+
+#. code: Name: "BlackSorcererWhite"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlackSorcererWhite"
+msgstr ""
+
+#. code: Name: "BlackSorcererYellow"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlackSorcererYellow"
+msgstr ""
+
+#. code: Name: "BlackTankTop"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlackTankTop"
+msgstr ""
+
+#. code: Name: "BlackTurtleneck"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlackTurtleneck"
+msgstr ""
+
+#. code: Name: "BlackVNeckSweater"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlackVNeckSweater"
+msgstr ""
+
+#. code: Name: "BlackWizardHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlackWizardHat"
+msgstr ""
+
+#. code: Name: "BlackWizardRobe"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlackWizardRobe"
+msgstr ""
+
+#. code: 010-2,85,41,0 shop Blacksmith NPC146,545:5000,529:2,603:1000
+#: npc/010-2/dimonds.txt:532
+#, no-c-format
+msgid "Blacksmith"
+msgstr ""
+
+#. code: Name: "BlacksmithsAxe"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlacksmithsAxe"
+msgstr ""
+
+#. code: 026-1,50,32,0 script Blackwin NPC316,{
+#: npc/026-1/evil_guard.txt:0
+#, no-c-format
+msgid "Blackwin"
+msgstr ""
+
+#. code: Name: "BlinkingEvil"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlinkingEvil"
+msgstr ""
+
+#. code: Name: "BlinkingEvilBlue"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlinkingEvilBlue"
+msgstr ""
+
+#. code: Name: "BlinkingEvilHalloween"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlinkingEvilHalloween"
+msgstr ""
+
+#. code: Name: "BlinkingEvilPink"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlinkingEvilPink"
+msgstr ""
+
+#. code: Name: "BlinkingEvilRed"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlinkingEvilRed"
+msgstr ""
+
+#. code: Name: "BlinkingEvilYellow"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlinkingEvilYellow"
+msgstr ""
+
+#. code: Name: "BlinkingHocus"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlinkingHocus"
+msgstr ""
+
+#. code: Name: "BloodInk"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BloodInk"
+msgstr ""
+
+#. code: Name: "BloodWine"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BloodWine"
+msgstr ""
+
+#. code: Name: "Bloodstone"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Bloodstone"
+msgstr ""
+
+#. code: 012-1,36,99,0 script Blossom NPC163,{
+#: npc/012-1/shops.txt:3
+#, no-c-format
+msgid "Blossom"
+msgstr ""
+
+#. code: Name: "BlueChristmasSweater"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlueChristmasSweater"
+msgstr ""
+
+#. code: Name: "BlueDottedWrap"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlueDottedWrap"
+msgstr ""
+
+#. code: Name: "BlueEasterEgg"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlueEasterEgg"
+msgstr ""
+
+#. code: Name: "BlueEggshellHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlueEggshellHat"
+msgstr ""
+
+#. code: Name: "BlueHint"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlueHint"
+msgstr ""
+
+#. code: Name: "BlueHitchhikersTowel"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlueHitchhikersTowel"
+msgstr ""
+
+#. code: Name: "BlueOrnament"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlueOrnament"
+msgstr ""
+
+#. code: Name: "BluePowder"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BluePowder"
+msgstr ""
+
+#. code: Name: "BluePresentBox"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BluePresentBox"
+msgstr ""
+
+#. code: Name: "BluePresentHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BluePresentHat"
+msgstr ""
+
+#. code: Name: "BlueRose"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlueRose"
+msgstr ""
+
+#. code: Name: "BlueRoseHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlueRoseHat"
+msgstr ""
+
+#. code: Name: "BlueTicket"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlueTicket"
+msgstr ""
+
+#. code: Name: "BlueWolfHelmet"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlueWolfHelmet"
+msgstr ""
+
+#. code: Name: "BlueWrap"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BlueWrap"
+msgstr ""
+
+#. code: Name: "Blueberries"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Blueberries"
+msgstr ""
+
+#. code: Name: "Bone"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Bone"
+msgstr ""
+
+#. code: Name: "BoneArrows"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BoneArrows"
+msgstr ""
+
+#. code: Name: "BoneDarts"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BoneDarts"
+msgstr ""
+
+#. code: Name: "BoneKnife"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BoneKnife"
+msgstr ""
+
+#. code: 051-1,142,39,0 script Bones NPC367,{
+#: npc/051-1/desert.txt:1
+#, no-c-format
+msgid "Bones"
+msgstr ""
+
+#. code: Name: "BookPage"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BookPage"
+msgstr ""
+
+#. code: Name: "Boots"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Boots"
+msgstr ""
+
+#. code: Name: "BottleOfSand"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BottleOfSand"
+msgstr ""
+
+#. code: Name: "BottleOfWater"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BottleOfWater"
+msgstr ""
+
+#. code: Name: "Bow"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Bow"
+msgstr ""
+
+#. code: Name: "BowlerHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BowlerHat"
+msgstr ""
+
+#. code: Name: "BowlerHatBrown"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BowlerHatBrown"
+msgstr ""
+
+#. code: 020-2,25,65,0 shop Bracco NPC135,529:2,530:8000,521:500,603:1000
+#: npc/020-2/shops.txt:12
+#, no-c-format
+msgid "Bracco"
+msgstr ""
+
+#. code: Name: "BrainStem"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BrainStem"
+msgstr ""
+
+#. code: 009-6,36,40,0 script Brodomir NPC116,{
+#: npc/009-6/brodomir.txt:4
+#, no-c-format
+msgid "Brodomir"
+msgstr ""
+
+#. code: Name: "BrokenDoll"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BrokenDoll"
+msgstr ""
+
+#. code: Name: "BrokenFourLeafAmulet"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BrokenFourLeafAmulet"
+msgstr ""
+
+#. code: Name: "BromenalBoots"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BromenalBoots"
+msgstr ""
+
+#. code: Name: "BromenalChest"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BromenalChest"
+msgstr ""
+
+#. code: Name: "BromenalFourLeafAmulet"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BromenalFourLeafAmulet"
+msgstr ""
+
+#. code: Name: "BromenalGloves"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BromenalGloves"
+msgstr ""
+
+#. code: Name: "BromenalHelmet"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BromenalHelmet"
+msgstr ""
+
+#. code: Name: "BromenalLegs"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BromenalLegs"
+msgstr ""
+
+#. code: Name: "BromenalShield"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BromenalShield"
+msgstr ""
+
+#. code: 011-6,27,200,0 script Bryant NPC126,{
+#: npc/011-6/bryant.txt:1
+#, no-c-format
+msgid "Bryant"
+msgstr ""
+
+#. code: Name: "BucketHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BucketHat"
+msgstr ""
+
+#. code: Name: "BugLeg"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BugLeg"
+msgstr ""
+
+#. code: Name: "BullHelmet"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BullHelmet"
+msgstr ""
+
+#. code: Name: "BunchOfParsley"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BunchOfParsley"
+msgstr ""
+
+#. code: 036-2,23,35,0 script Bunkmaster Daban NPC212,{
+#: npc/036-2/shops.txt:4
+#, no-c-format
+msgid "Bunkmaster Daban"
+msgstr ""
+
+#. code: 035-2,23,35,0 script Bunkmaster Phict NPC212,{
+#: npc/035-2/shops.txt:3
+#, no-c-format
+msgid "Bunkmaster Phict"
+msgstr ""
+
+#. code: Name: "BunnyEars"
+#: item_db.conf:-1
+#, no-c-format
+msgid "BunnyEars"
+msgstr ""
+
+#. code: 002-4,30,47,0 script Button#mine-1 NPC400,0,0,{
+#: npc/002-4/mine_triggerone.txt:0
+#, no-c-format
+msgid "Button#mine-1"
+msgstr ""
+
+#. code: 002-4,100,37,0 script Button#mine-2 NPC400,0,0,{
+#: npc/002-4/mine_triggertwo.txt:0
+#, no-c-format
+msgid "Button#mine-2"
+msgstr ""
+
+#. code: 002-4,91,99,0 script Button#mine-3 NPC400,0,0,{
+#: npc/002-4/mine_triggerthree.txt:0
+#, no-c-format
+msgid "Button#mine-3"
+msgstr ""
+
+#. code: Name: "CactusDrink"
+#: item_db.conf:-1
+#, no-c-format
+msgid "CactusDrink"
+msgstr ""
+
+#. code: Name: "CactusPotion"
+#: item_db.conf:-1
+#, no-c-format
+msgid "CactusPotion"
+msgstr ""
+
+#. code: Name: "Cake"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Cake"
+msgstr ""
+
+#. code: 002-2,72,92,0 script Candide NPC156,{
+#: npc/002-2/bleacher.txt:1
+#, no-c-format
+msgid "Candide"
+msgstr ""
+
+#. code: Name: "CandleHelmet"
+#: item_db.conf:-1
+#, no-c-format
+msgid "CandleHelmet"
+msgstr ""
+
+#. code: 029-1,46,111,0 script Candor Dock NPC400,1,0,{
+#: npc/029-1/dock.txt:1
+#, no-c-format
+msgid "Candor Dock"
+msgstr ""
+
+#. code: 029-1,51,118,0 script Candor Koga NPC395,8,7,{
+#: npc/029-1/dock.txt:9
+#, no-c-format
+msgid "Candor Koga"
+msgstr ""
+
+#. code: Name: "Candy"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Candy"
+msgstr ""
+
+#. code: Name: "CandyCane"
+#: item_db.conf:-1
+#, no-c-format
+msgid "CandyCane"
+msgstr ""
+
+#. code: Name: "CandyPumpkin"
+#: item_db.conf:-1
+#, no-c-format
+msgid "CandyPumpkin"
+msgstr ""
+
+#. code: Name: "Cap"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Cap"
+msgstr ""
+
+#. code: 002-5,79,23,0 script Capitão Mirc NPC303,{
+#: npc/functions/jesusalvatr.txt:31
+#, no-c-format
+msgid "Capitão Mirc"
+msgstr ""
+
+#. code: Name: "CaptainsHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "CaptainsHat"
+msgstr ""
+
+#. code: Name: "CaramelApple"
+#: item_db.conf:-1
+#, no-c-format
+msgid "CaramelApple"
+msgstr ""
+
+#. code: Name: "CaramelCandy"
+#: item_db.conf:-1
+#, no-c-format
+msgid "CaramelCandy"
+msgstr ""
+
+#. code: Name: "CarbonGasMask"
+#: item_db.conf:-1
+#, no-c-format
+msgid "CarbonGasMask"
+msgstr ""
+
+#. code: 027-2,44,25,0 script Caretaker NPC159,{
+#: npc/027-2/caretaker.txt:1
+#, no-c-format
+msgid "Caretaker"
+msgstr ""
+
+#. code: Name: "CashiersShade"
+#: item_db.conf:-1
+#, no-c-format
+msgid "CashiersShade"
+msgstr ""
+
+#. code: Name: "CasinoCoins"
+#: item_db.conf:-1
+#, no-c-format
+msgid "CasinoCoins"
+msgstr ""
+
+#. code: Name: "CatEars"
+#: item_db.conf:-1
+#, no-c-format
+msgid "CatEars"
+msgstr ""
+
+#. code: 018-2,37,22,0 script Caul NPC107,{
+#: npc/018-2/caul.txt:1
+#: npc/018-2/caul.txt~:1
+#, no-c-format
+msgid "Caul"
+msgstr ""
+
+#. code: Name: "CaveSnakeEgg"
+#: item_db.conf:-1
+#, no-c-format
+msgid "CaveSnakeEgg"
+msgstr ""
+
+#. code: Name: "CaveSnakeLamp"
+#: item_db.conf:-1
+#, no-c-format
+msgid "CaveSnakeLamp"
+msgstr ""
+
+#. code: Name: "CaveSnakeTongue"
+#: item_db.conf:-1
+#, no-c-format
+msgid "CaveSnakeTongue"
+msgstr ""
+
+#. code: 009-8,31,23,0 script Celestia NPC144,{
+#: npc/009-8/celestia.txt:1
+#, no-c-format
+msgid "Celestia"
+msgstr ""
+
+#. code: 009-1,72,54,0 script Celestia BackDoor NPC32767,0,0,{
+#: npc/009-8/celestia.txt:279
+#, no-c-format
+msgid "Celestia BackDoor"
+msgstr ""
+
+#. code: 009-1,74,50,0 script Celestia Door NPC32767,0,0,{
+#: npc/009-8/celestia.txt:274
+#, no-c-format
+msgid "Celestia Door"
+msgstr ""
+
+#. code: 026-2,38,118,0 script Cerhan NPC311,{
+#: npc/026-2/cerhan.txt:1
+#, no-c-format
+msgid "Cerhan"
+msgstr ""
+
+#. code: Name: "ChainmailShirt"
+#: item_db.conf:-1
+#, no-c-format
+msgid "ChainmailShirt"
+msgstr ""
+
+#. code: 029-1,48,67,0 script Charda NPC260,{
+#: npc/029-1/hideandseek.txt:190
+#, no-c-format
+msgid "Charda"
+msgstr ""
+
+#. code: 001-1,43,48,0 script Ched NPC113,{
+#: npc/001-1/ched.txt:1
+#, no-c-format
+msgid "Ched"
+msgstr ""
+
+#. code: 036-2,23,38,0 shop Chef Armand NPC211,539:87,676:200,503:10
+#: npc/036-2/shops.txt:1
+#, no-c-format
+msgid "Chef Armand"
+msgstr ""
+
+#. code: 010-2,33,25,0 script Chef#dimond NPC148,{
+#: npc/010-2/chef.txt:0
+#, no-c-format
+msgid "Chef#dimond"
+msgstr ""
+
+#. code: 026-2,30,56,0 shop Chef#graveyard NPC300,784:30,785:25,786:30,787:55
+#: npc/026-2/gy_inn_shops.txt:1
+#, no-c-format
+msgid "Chef#graveyard"
+msgstr ""
+
+#. code: Name: "ChefHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "ChefHat"
+msgstr ""
+
+#. code: Name: "Cherry"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Cherry"
+msgstr ""
+
+#. code: Name: "CherryCake"
+#: item_db.conf:-1
+#, no-c-format
+msgid "CherryCake"
+msgstr ""
+
+#. code: 013-3,28,27,0 script Chest#DemonMask NPC111,{
+#: npc/013-3/mask_chest.txt:1
+#, no-c-format
+msgid "Chest#DemonMask"
+msgstr ""
+
+#. code: 013-3,127,68,0 script Chest#boring NPC111,{
+#: npc/013-3/misc.txt:1
+#, no-c-format
+msgid "Chest#boring"
+msgstr ""
+
+#. code: 052-2,136,73,0 script Chest#illia NPC111,{
+#: npc/052-2/chest.txt:1
+#, no-c-format
+msgid "Chest#illia"
+msgstr ""
+
+#. code: 013-3,177,22,0 script Chest#sword NPC111,{
+#: npc/013-3/sword_chest.txt:1
+#, no-c-format
+msgid "Chest#sword"
+msgstr ""
+
+#. code: Name: "ChicSantaHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "ChicSantaHat"
+msgstr ""
+
+#. code: Name: "ChickenLeg"
+#: item_db.conf:-1
+#, no-c-format
+msgid "ChickenLeg"
+msgstr ""
+
+#. code: 030-2,127,42,0 script Chief Warrick NPC329,{
+#: npc/030-2/chief_helper.txt:1
+#, no-c-format
+msgid "Chief Warrick"
+msgstr ""
+
+#. code: Name: "ChocolateBar"
+#: item_db.conf:-1
+#, no-c-format
+msgid "ChocolateBar"
+msgstr ""
+
+#. code: Name: "ChocolateCake"
+#: item_db.conf:-1
+#, no-c-format
+msgid "ChocolateCake"
+msgstr ""
+
+#. code: Name: "ChocolateMouboo"
+#: item_db.conf:-1
+#, no-c-format
+msgid "ChocolateMouboo"
+msgstr ""
+
+#. code: Name: "ChristmasElfHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "ChristmasElfHat"
+msgstr ""
+
+#. code: Name: "ChristmasTreeHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "ChristmasTreeHat"
+msgstr ""
+
+#. code: 031-4,42,42,0 script Cindy NPC198,{
+#: npc/031-4/cindyCave.txt:1
+#, no-c-format
+msgid "Cindy"
+msgstr ""
+
+#. code: 031-2,27,26,0 script Cindy#house NPC197,{
+#: npc/031-2/cindyHouse.txt:1
+#, no-c-format
+msgid "Cindy#house"
+msgstr ""
+
+#. code: Name: "Circlet"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Circlet"
+msgstr ""
+
+#. code: 025-4,30,30,0 script Clauquer NPC169,{
+#: npc/025-4/clauquer.txt:1
+#, no-c-format
+msgid "Clauquer"
+msgstr ""
+
+#. code: Name: "ClosedChristmasBox"
+#: item_db.conf:-1
+#, no-c-format
+msgid "ClosedChristmasBox"
+msgstr ""
+
+#. code: Name: "CloverHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "CloverHat"
+msgstr ""
+
+#. code: Name: "Coal"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Coal"
+msgstr ""
+
+#. code: Name: "CobaltHerb"
+#: item_db.conf:-1
+#, no-c-format
+msgid "CobaltHerb"
+msgstr ""
+
+#. code: Name: "CoinBag"
+#: item_db.conf:-1
+#, no-c-format
+msgid "CoinBag"
+msgstr ""
+
+#. code: Name: "ConcentrationPotion"
+#: item_db.conf:-1
+#, no-c-format
+msgid "ConcentrationPotion"
+msgstr ""
+
+#. code: 048-2,46,44,0 script Connor NPC150,{
+#: npc/048-2/visitors.txt:1
+#, no-c-format
+msgid "Connor"
+msgstr ""
+
+#. code: 009-1,52,33,0 script Constable Bob NPC419,{
+#: npc/009-1/constable.txt:1
+#, no-c-format
+msgid "Constable Bob"
+msgstr ""
+
+#. code: 001-1,50,74,0 script Constable Perry Graf NPC150,{
+#: npc/001-1/constable.txt:1
+#, no-c-format
+msgid "Constable Perry Graf"
+msgstr ""
+
+#. code: Name: "Contributor"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Contributor"
+msgstr ""
+
+#. code: 035-2,23,38,0 shop Cooky NPC213,539:87,657:10,503:10
+#: npc/035-2/shops.txt:1
+#, no-c-format
+msgid "Cooky"
+msgstr ""
+
+#. code: Name: "CottonBoots"
+#: item_db.conf:-1
+#, no-c-format
+msgid "CottonBoots"
+msgstr ""
+
+#. code: Name: "CottonCloth"
+#: item_db.conf:-1
+#, no-c-format
+msgid "CottonCloth"
+msgstr ""
+
+#. code: Name: "CottonGloves"
+#: item_db.conf:-1
+#, no-c-format
+msgid "CottonGloves"
+msgstr ""
+
+#. code: Name: "CottonHeadband"
+#: item_db.conf:-1
+#, no-c-format
+msgid "CottonHeadband"
+msgstr ""
+
+#. code: Name: "CottonShirt"
+#: item_db.conf:-1
+#, no-c-format
+msgid "CottonShirt"
+msgstr ""
+
+#. code: Name: "CottonShorts"
+#: item_db.conf:-1
+#, no-c-format
+msgid "CottonShorts"
+msgstr ""
+
+#. code: Name: "CottonSkirt"
+#: item_db.conf:-1
+#, no-c-format
+msgid "CottonSkirt"
+msgstr ""
+
+#. code: Name: "CottonTrousers"
+#: item_db.conf:-1
+#, no-c-format
+msgid "CottonTrousers"
+msgstr ""
+
+#. code: Name: "CranberryLollipop"
+#: item_db.conf:-1
+#, no-c-format
+msgid "CranberryLollipop"
+msgstr ""
+
+#. code: 011-6,172,250,0 script Crastur the Ugly NPC418,{
+#: npc/011-6/crastur.txt:0
+#, no-c-format
+msgid "Crastur the Ugly"
+msgstr ""
+
+#. code: Name: "CrescentRod"
+#: item_db.conf:-1
+#, no-c-format
+msgid "CrescentRod"
+msgstr ""
+
+#. code: Name: "CrimsonBra"
+#: item_db.conf:-1
+#, no-c-format
+msgid "CrimsonBra"
+msgstr ""
+
+#. code: Name: "Crown"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Crown"
+msgstr ""
+
+#. code: Name: "CrozeniteFourLeafAmulet"
+#: item_db.conf:-1
+#, no-c-format
+msgid "CrozeniteFourLeafAmulet"
+msgstr ""
+
+#. code: Name: "CrusadeHelmet"
+#: item_db.conf:-1
+#, no-c-format
+msgid "CrusadeHelmet"
+msgstr ""
+
+#. code: Name: "CryptKey"
+#: item_db.conf:-1
+#, no-c-format
+msgid "CryptKey"
+msgstr ""
+
+#. code: 030-2,37,88,0 script Curlee NPC329,{
+#: npc/030-2/shipping_helper.txt:13
+#, no-c-format
+msgid "Curlee"
+msgstr ""
+
+#. code: 051-1,170,24,0 script Cursed Waterfall NPC400,{
+#: npc/051-1/desert.txt:14
+#, no-c-format
+msgid "Cursed Waterfall"
+msgstr ""
+
+#. code: 001-1,49,82,0 script Cyndala NPC210,{
+#: npc/001-1/npcs.txt:0
+#, no-c-format
+msgid "Cyndala"
+msgstr ""
+
+#. code: 029-2,30,118,0 script Cynric NPC161,{
+#: npc/029-2/cynric.txt:1
+#, no-c-format
+msgid "Cynric"
+msgstr ""
+
+#. code: Name: "Dagger"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Dagger"
+msgstr ""
+
+#. code: Name: "DarkBlueBeret"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkBlueBeret"
+msgstr ""
+
+#. code: Name: "DarkBlueBowlerHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkBlueBowlerHat"
+msgstr ""
+
+#. code: Name: "DarkBlueBowlerHatBrown"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkBlueBowlerHatBrown"
+msgstr ""
+
+#. code: Name: "DarkBlueContributor"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkBlueContributor"
+msgstr ""
+
+#. code: Name: "DarkBlueCottonBoots"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkBlueCottonBoots"
+msgstr ""
+
+#. code: Name: "DarkBlueCottonCloth"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkBlueCottonCloth"
+msgstr ""
+
+#. code: Name: "DarkBlueCottonGloves"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkBlueCottonGloves"
+msgstr ""
+
+#. code: Name: "DarkBlueCottonHeadband"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkBlueCottonHeadband"
+msgstr ""
+
+#. code: Name: "DarkBlueCottonShirt"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkBlueCottonShirt"
+msgstr ""
+
+#. code: Name: "DarkBlueCottonShorts"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkBlueCottonShorts"
+msgstr ""
+
+#. code: Name: "DarkBlueCottonSkirt"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkBlueCottonSkirt"
+msgstr ""
+
+#. code: Name: "DarkBlueCottonTrousers"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkBlueCottonTrousers"
+msgstr ""
+
+#. code: Name: "DarkBlueDesertHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkBlueDesertHat"
+msgstr ""
+
+#. code: Name: "DarkBlueDye"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkBlueDye"
+msgstr ""
+
+#. code: Name: "DarkBlueFineDress"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkBlueFineDress"
+msgstr ""
+
+#. code: Name: "DarkBlueMiniskirt"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkBlueMiniskirt"
+msgstr ""
+
+#. code: Name: "DarkBlueRabbitEars"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkBlueRabbitEars"
+msgstr ""
+
+#. code: Name: "DarkBlueShades"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkBlueShades"
+msgstr ""
+
+#. code: Name: "DarkBlueShortTankTop"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkBlueShortTankTop"
+msgstr ""
+
+#. code: Name: "DarkBlueSilkRobe"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkBlueSilkRobe"
+msgstr ""
+
+#. code: Name: "DarkBlueSorcererBlack"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkBlueSorcererBlack"
+msgstr ""
+
+#. code: Name: "DarkBlueSorcererDBlue"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkBlueSorcererDBlue"
+msgstr ""
+
+#. code: Name: "DarkBlueSorcererDGreen"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkBlueSorcererDGreen"
+msgstr ""
+
+#. code: Name: "DarkBlueSorcererGreen"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkBlueSorcererGreen"
+msgstr ""
+
+#. code: Name: "DarkBlueSorcererLBlue"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkBlueSorcererLBlue"
+msgstr ""
+
+#. code: Name: "DarkBlueSorcererOrange"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkBlueSorcererOrange"
+msgstr ""
+
+#. code: Name: "DarkBlueSorcererPink"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkBlueSorcererPink"
+msgstr ""
+
+#. code: Name: "DarkBlueSorcererPurple"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkBlueSorcererPurple"
+msgstr ""
+
+#. code: Name: "DarkBlueSorcererRed"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkBlueSorcererRed"
+msgstr ""
+
+#. code: Name: "DarkBlueSorcererWhite"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkBlueSorcererWhite"
+msgstr ""
+
+#. code: Name: "DarkBlueSorcererYellow"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkBlueSorcererYellow"
+msgstr ""
+
+#. code: Name: "DarkBlueTankTop"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkBlueTankTop"
+msgstr ""
+
+#. code: Name: "DarkBlueTurtleneck"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkBlueTurtleneck"
+msgstr ""
+
+#. code: Name: "DarkBlueVNeckSweater"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkBlueVNeckSweater"
+msgstr ""
+
+#. code: Name: "DarkBlueWizardHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkBlueWizardHat"
+msgstr ""
+
+#. code: Name: "DarkChristmasSweater"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkChristmasSweater"
+msgstr ""
+
+#. code: Name: "DarkConcentrationPotion"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkConcentrationPotion"
+msgstr ""
+
+#. code: Name: "DarkCrystal"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkCrystal"
+msgstr ""
+
+#. code: Name: "DarkEasterEgg"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkEasterEgg"
+msgstr ""
+
+#. code: Name: "DarkEggshellHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkEggshellHat"
+msgstr ""
+
+#. code: Name: "DarkGreenBeret"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkGreenBeret"
+msgstr ""
+
+#. code: Name: "DarkGreenBowlerHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkGreenBowlerHat"
+msgstr ""
+
+#. code: Name: "DarkGreenBowlerHatBrown"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkGreenBowlerHatBrown"
+msgstr ""
+
+#. code: Name: "DarkGreenContributor"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkGreenContributor"
+msgstr ""
+
+#. code: Name: "DarkGreenCottonBoots"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkGreenCottonBoots"
+msgstr ""
+
+#. code: Name: "DarkGreenCottonCloth"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkGreenCottonCloth"
+msgstr ""
+
+#. code: Name: "DarkGreenCottonGloves"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkGreenCottonGloves"
+msgstr ""
+
+#. code: Name: "DarkGreenCottonHeadband"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkGreenCottonHeadband"
+msgstr ""
+
+#. code: Name: "DarkGreenCottonShirt"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkGreenCottonShirt"
+msgstr ""
+
+#. code: Name: "DarkGreenCottonShorts"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkGreenCottonShorts"
+msgstr ""
+
+#. code: Name: "DarkGreenCottonSkirt"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkGreenCottonSkirt"
+msgstr ""
+
+#. code: Name: "DarkGreenCottonTrousers"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkGreenCottonTrousers"
+msgstr ""
+
+#. code: Name: "DarkGreenDesertHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkGreenDesertHat"
+msgstr ""
+
+#. code: Name: "DarkGreenDye"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkGreenDye"
+msgstr ""
+
+#. code: Name: "DarkGreenFineDress"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkGreenFineDress"
+msgstr ""
+
+#. code: Name: "DarkGreenMiniskirt"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkGreenMiniskirt"
+msgstr ""
+
+#. code: Name: "DarkGreenRabbitEars"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkGreenRabbitEars"
+msgstr ""
+
+#. code: Name: "DarkGreenShades"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkGreenShades"
+msgstr ""
+
+#. code: Name: "DarkGreenShortTankTop"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkGreenShortTankTop"
+msgstr ""
+
+#. code: Name: "DarkGreenSilkRobe"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkGreenSilkRobe"
+msgstr ""
+
+#. code: Name: "DarkGreenSorcererBlack"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkGreenSorcererBlack"
+msgstr ""
+
+#. code: Name: "DarkGreenSorcererDBlue"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkGreenSorcererDBlue"
+msgstr ""
+
+#. code: Name: "DarkGreenSorcererDGreen"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkGreenSorcererDGreen"
+msgstr ""
+
+#. code: Name: "DarkGreenSorcererGreen"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkGreenSorcererGreen"
+msgstr ""
+
+#. code: Name: "DarkGreenSorcererLBlue"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkGreenSorcererLBlue"
+msgstr ""
+
+#. code: Name: "DarkGreenSorcererOrange"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkGreenSorcererOrange"
+msgstr ""
+
+#. code: Name: "DarkGreenSorcererPink"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkGreenSorcererPink"
+msgstr ""
+
+#. code: Name: "DarkGreenSorcererPurple"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkGreenSorcererPurple"
+msgstr ""
+
+#. code: Name: "DarkGreenSorcererRed"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkGreenSorcererRed"
+msgstr ""
+
+#. code: Name: "DarkGreenSorcererWhite"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkGreenSorcererWhite"
+msgstr ""
+
+#. code: Name: "DarkGreenSorcererYellow"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkGreenSorcererYellow"
+msgstr ""
+
+#. code: Name: "DarkGreenTankTop"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkGreenTankTop"
+msgstr ""
+
+#. code: Name: "DarkGreenTurtleneck"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkGreenTurtleneck"
+msgstr ""
+
+#. code: Name: "DarkGreenVNeckSweater"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkGreenVNeckSweater"
+msgstr ""
+
+#. code: Name: "DarkGreenWizardHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkGreenWizardHat"
+msgstr ""
+
+#. code: Name: "DarkHelm"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkHelm"
+msgstr ""
+
+#. code: Name: "DarkPetal"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkPetal"
+msgstr ""
+
+#. code: Name: "DarkRedRose"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkRedRose"
+msgstr ""
+
+#. code: Name: "DarkTalisman"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DarkTalisman"
+msgstr ""
+
+#. code: 026-2,41,30,0 script Darnel NPC308,{
+#: npc/026-2/testnpcs.txt:20
+#, no-c-format
+msgid "Darnel"
+msgstr ""
+
+#. code: 006-2,80,25,0 script Darug NPC178,{
+#: npc/006-2/npcs.txt:43
+#, no-c-format
+msgid "Darug"
+msgstr ""
+
+#. code: 001-2,92,88,0 script David NPC120,{
+#: npc/001-2/david.txt:0
+#, no-c-format
+msgid "David"
+msgstr ""
+
+#. code: 029-2,30,26,0 script Debug#0 NPC154,{
+#: npc/commands/debug.txt:935
+#, no-c-format
+msgid "Debug#0"
+msgstr ""
+
+#. code: 001-1,53,47,0 script Debug#1 NPC154,{
+#: npc/commands/debug.txt:945
+#, no-c-format
+msgid "Debug#1"
+msgstr ""
+
+#. code: 009-1,45,33,0 script Debug#2 NPC154,{
+#: npc/commands/debug.txt:955
+#, no-c-format
+msgid "Debug#2"
+msgstr ""
+
+#. code: 020-1,75,85,0 script Debug#3 NPC154,{
+#: npc/commands/debug.txt:965
+#, no-c-format
+msgid "Debug#3"
+msgstr ""
+
+#. code: 027-2,125,103,0 script Debug#5 NPC154,{
+#: npc/commands/debug.txt:975
+#, no-c-format
+msgid "Debug#5"
+msgstr ""
+
+#. code: 031-1,81,24,0 script Debug#Angela NPC195,{
+#: npc/031-1/angelaOutside.txt:1
+#, no-c-format
+msgid "Debug#Angela"
+msgstr ""
+
+#. code: 048-2,36,44,0 script Debug#BlueSage NPC110,{
+#: npc/048-2/helperJanitor.txt:1
+#, no-c-format
+msgid "Debug#BlueSage"
+msgstr ""
+
+#. code: 009-7,41,45,0 script Debug#Duels NPC181,{
+#: npc/009-7/debug.txt~:141
+#: npc/009-7/debug.txt:132
+#, no-c-format
+msgid "Debug#Duels"
+msgstr ""
+
+#. code: 017-1,74,32,0 script DebugFlowerP NPC153,{
+#: npc/017-4/waric.txt:364
+#, no-c-format
+msgid "DebugFlowerP"
+msgstr ""
+
+#. code: Name: "DecorCandy"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DecorCandy"
+msgstr ""
+
+#. code: Name: "DemonMask"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DemonMask"
+msgstr ""
+
+#. code: Name: "DesertBow"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DesertBow"
+msgstr ""
+
+#. code: Name: "DesertHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DesertHat"
+msgstr ""
+
+#. code: Name: "DesertHelmet"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DesertHelmet"
+msgstr ""
+
+#. code: Name: "DesertShirt"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DesertShirt"
+msgstr ""
+
+#. code: Name: "DevelopersCap"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DevelopersCap"
+msgstr ""
+
+#. code: Name: "Diamond"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Diamond"
+msgstr ""
+
+#. code: Name: "DiamondPowder"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DiamondPowder"
+msgstr ""
+
+#. code: Name: "DiamondRing"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DiamondRing"
+msgstr ""
+
+#. code: Name: "DilutedConcentrationPot"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DilutedConcentrationPot"
+msgstr ""
+
+#. code: 010-2,34,38,0 script Dimond NPC165,{
+#: npc/010-2/dimonds.txt:1
+#, no-c-format
+msgid "Dimond"
+msgstr ""
+
+#. code: 010-2,80,32,0 script Dimonds Cove 1 NPC400,{
+#: npc/010-2/dimonds.txt:494
+#, no-c-format
+msgid "Dimonds Cove 1"
+msgstr ""
+
+#. code: 010-2,85,32,0 script Dimonds Cove 2 NPC400,{
+#: npc/010-2/dimonds.txt:513
+#, no-c-format
+msgid "Dimonds Cove 2"
+msgstr ""
+
+#. code: 010-2,36,30,0 script Directions NPC400,{
+#: npc/010-2/dimonds.txt:488
+#, no-c-format
+msgid "Directions"
+msgstr ""
+
+#. code: 008-1,81,82,0 script Diryn the Traveler NPC103,{
+#: npc/008-1/diryn.txt:1
+#, no-c-format
+msgid "Diryn the Traveler"
+msgstr ""
+
+#. code: Name: "DiseasedHeart"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DiseasedHeart"
+msgstr ""
+
+#. code: 009-2,148,25,0 script Doctor NPC107,{
+#: npc/009-2/doctor.txt:1
+#, no-c-format
+msgid "Doctor"
+msgstr ""
+
+#. code: Name: "Doll"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Doll"
+msgstr ""
+
+#. code: 051-3,37,24,0 script Door NPC400,{
+#: npc/051-3/reinforcements.txt:15
+#, no-c-format
+msgid "Door"
+msgstr ""
+
+#. code: 010-2,68,87,0 script Doug NPC113,{
+#: npc/010-2/doug.txt:1
+#, no-c-format
+msgid "Doug"
+msgstr ""
+
+#. code: 002-2,25,22,0 shop Drabur NPC112,736:100,737:125,738:150,739:150,513:15,519:50,534:45,527:150,508:10
+#: npc/002-2/bakery.txt:126
+#, no-c-format
+msgid "Drabur"
+msgstr ""
+
+#. code: 048-2,23,46,0 script Drake the Traveler NPC103,{
+#: npc/048-2/traveler.txt:1
+#, no-c-format
+msgid "Drake the Traveler"
+msgstr ""
+
+#. code: 029-2,29,23,0 script Dresser#tutorial NPC400,{
+#: npc/029-2/sorfina.txt~:300
+#: npc/029-2/sorfina.txt:300
+#, no-c-format
+msgid "Dresser#tutorial"
+msgstr ""
+
+#. code: 009-2,65,55,0 script Drinker#1 NPC121,{
+#: npc/009-2/drunks.txt:1
+#, no-c-format
+msgid "Drinker#1"
+msgstr ""
+
+#. code: 009-2,68,55,0 script Drinker#2 NPC121,{
+#: npc/009-2/drunks.txt:8
+#, no-c-format
+msgid "Drinker#2"
+msgstr ""
+
+#. code: Name: "DruidTreeBranch"
+#: item_db.conf:-1
+#, no-c-format
+msgid "DruidTreeBranch"
+msgstr ""
+
+#. code: mesc l("ERROR: You must set a PinCode to make use of this function."), 1;
+#: npc/functions/main.txt~:399
+#: npc/functions/main.txt:399
+#, no-c-format
+msgid "ERROR: You must set a PinCode to make use of this function."
+msgstr ""
+
+#. code: Name: "Earmuffs"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Earmuffs"
+msgstr ""
+
+#. code: 008-1,0,0,0 script Easter Eggs NPC32767,{
+#: npc/008-1/annualeaster.txt:4
+#: npc/008-1/annualeaster.txt~:4
+#, no-c-format
+msgid "Easter Eggs"
+msgstr ""
+
+#. code: Name: "EasterBasket"
+#: item_db.conf:-1
+#, no-c-format
+msgid "EasterBasket"
+msgstr ""
+
+#. code: Name: "EasterEgg"
+#: item_db.conf:-1
+#, no-c-format
+msgid "EasterEgg"
+msgstr ""
+
+#. code: Name: "Ectoplasm"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Ectoplasm"
+msgstr ""
+
+#. code: 026-2,40,24,0 script Edwin NPC309,{
+#: npc/026-2/gy_inn_shops.txt:4
+#, no-c-format
+msgid "Edwin"
+msgstr ""
+
+#. code: 048-2,95,103,0 script Eevert NPC365,{
+#: npc/048-2/helperMInk.txt:1
+#, no-c-format
+msgid "Eevert"
+msgstr ""
+
+#. code: Name: "EggshellHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "EggshellHat"
+msgstr ""
+
+#. code: 001-1,103,99,0 script Ekinu NPC104,{
+#: npc/001-1/guards.txt:1
+#, no-c-format
+msgid "Ekinu"
+msgstr ""
+
+#. code: 002-1,75,62,0 script Elanore#_M NPC108,{
+#: npc/002-1/elanore.txt:35
+#, no-c-format
+msgid "Elanore#_M"
+msgstr ""
+
+#. code: Name: "ElfNightcap"
+#: item_db.conf:-1
+#, no-c-format
+msgid "ElfNightcap"
+msgstr ""
+
+#. code: 048-2,40,41,0 script Elias NPC110,7,6,{
+#: npc/048-2/helperJanitor.txt:19
+#, no-c-format
+msgid "Elias"
+msgstr ""
+
+#. code: 002-1,105,114,0 script Elijah NPC128,{
+#: npc/002-1/nomads.txt:8
+#, no-c-format
+msgid "Elijah"
+msgstr ""
+
+#. code: 030-2,87,41,0 script Eljas NPC328,5,1,{
+#: npc/030-2/eljas.txt:1
+#, no-c-format
+msgid "Eljas"
+msgstr ""
+
+#. code: Name: "Emerald"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Emerald"
+msgstr ""
+
+#. code: Name: "EmeraldPowder"
+#: item_db.conf:-1
+#, no-c-format
+msgid "EmeraldPowder"
+msgstr ""
+
+#. code: Name: "EmeraldRing"
+#: item_db.conf:-1
+#, no-c-format
+msgid "EmeraldRing"
+msgstr ""
+
+#. code: 000-1,22,22,0 script Emergency Exit NPC_NO_SPRITE,2,2,{
+#: npc/000-1/exit.txt:6
+#: npc/000-1/exit.txt~:6
+#, no-c-format
+msgid "Emergency Exit"
+msgstr ""
+
+#. code: Name: "EmptyBottle"
+#: item_db.conf:-1
+#, no-c-format
+msgid "EmptyBottle"
+msgstr ""
+
+#. code: Name: "EnchantersAmulet"
+#: item_db.conf:-1
+#, no-c-format
+msgid "EnchantersAmulet"
+msgstr ""
+
+#. code: 052-1,51,38,0 script Engravings NPC400,{
+#: npc/052-1/channelling.txt:54
+#, no-c-format
+msgid "Engravings"
+msgstr ""
+
+#. code: 048-2,104,86,0 script Ensio NPC365,{
+#: npc/048-2/helperBookpages1.txt:1
+#, no-c-format
+msgid "Ensio"
+msgstr ""
+
+#. code: 009-2,61,49,0 script Entertainer NPC165,{
+#: npc/009-2/entertainer.txt:1
+#, no-c-format
+msgid "Entertainer"
+msgstr ""
+
+#. code: 001-1,71,23,0 script Eomie NPC164,{
+#: npc/001-1/eomie.txt~:0
+#: npc/001-1/eomie.txt:0
+#, no-c-format
+msgid "Eomie"
+msgstr ""
+
+#. code: Name: "EskimoHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "EskimoHat"
+msgstr ""
+
+#. code: 001-2,25,21,0 script Estard NPC107,{
+#: npc/001-2/government_building.txt~:1
+#: npc/001-2/government_building.txt:1
+#, no-c-format
+msgid "Estard"
+msgstr ""
+
+#. code: 026-2,38,30,0 shop Estrilda NPC301,788:30,789:30,790:50
+#: npc/026-2/gy_inn_shops.txt:2
+#, no-c-format
+msgid "Estrilda"
+msgstr ""
+
+#. code: 026-2,20,124,0 script Eurni NPC136,{
+#: npc/026-2/eurni.txt:1
+#, no-c-format
+msgid "Eurni"
+msgstr ""
+
+#. code: 018-3,67,28,0 script Evil Obelisk NPC185,{
+#: npc/018-3/evil-obelisk.txt:1
+#, no-c-format
+msgid "Evil Obelisk"
+msgstr ""
+
+#. code: 028-1,98,37,0 script Exit NPC400,0,0,{
+#: npc/028-1/portal.txt:0
+#, no-c-format
+msgid "Exit"
+msgstr ""
+
+#. code: Name: "Eyepatch"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Eyepatch"
+msgstr ""
+
+#. code: 013-2,25,37,0 script Fabius NPC115,{
+#: npc/013-2/apprentice.txt:0
+#, no-c-format
+msgid "Fabius"
+msgstr ""
+
+#. code: Name: "FaceMask"
+#: item_db.conf:-1
+#, no-c-format
+msgid "FaceMask"
+msgstr ""
+
+#. code: Name: "FairTradeSoil"
+#: item_db.conf:-1
+#, no-c-format
+msgid "FairTradeSoil"
+msgstr ""
+
+#. code: Name: "FairyHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "FairyHat"
+msgstr ""
+
+#. code: Name: "FakeFangs"
+#: item_db.conf:-1
+#, no-c-format
+msgid "FakeFangs"
+msgstr ""
+
+#. code: Name: "Falchion"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Falchion"
+msgstr ""
+
+#. code: 006-2,49,25,0 script Falkurn NPC178,{
+#: npc/006-2/npcs.txt:1
+#, no-c-format
+msgid "Falkurn"
+msgstr ""
+
+#. code: Name: "FancyHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "FancyHat"
+msgstr ""
+
+#. code: 029-1,100,36,0 script Faris NPC259,{
+#: npc/029-1/hideandseek.txt:237
+#, no-c-format
+msgid "Faris"
+msgstr ""
+
+#. code: 013-1,120,90,0 script Faris the Traveler NPC103,{
+#: npc/013-1/traveler.txt:0
+#, no-c-format
+msgid "Faris the Traveler"
+msgstr ""
+
+#. code: 029-1,45,107,0 script Ferry Master#candor NPC138,{
+#: npc/029-1/ferry_master.txt:1
+#, no-c-format
+msgid "Ferry Master#candor"
+msgstr ""
+
+#. code: 001-1,64,75,0 script Ferry Master#tulimshar NPC138,{
+#: npc/001-1/ferry_master.txt:1
+#, no-c-format
+msgid "Ferry Master#tulimshar"
+msgstr ""
+
+#. code: 001-2,114,89,0 script Fieri NPC117,{
+#: npc/001-2/fieri.txt:0
+#, no-c-format
+msgid "Fieri"
+msgstr ""
+
+#. code: Name: "FineDress"
+#: item_db.conf:-1
+#, no-c-format
+msgid "FineDress"
+msgstr ""
+
+#. code: Name: "FlawedLens"
+#: item_db.conf:-1
+#, no-c-format
+msgid "FlawedLens"
+msgstr ""
+
+#. code: Name: "FlightTalisman"
+#: item_db.conf:-1
+#, no-c-format
+msgid "FlightTalisman"
+msgstr ""
+
+#. code: Name: "FluffyHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "FluffyHat"
+msgstr ""
+
+#. code: 012-3,62,130,0 script Forest Mana Seed#_M NPC166,{
+#: npc/012-3/mana-seed.txt~:0
+#: npc/012-3/mana-seed.txt:0
+#, no-c-format
+msgid "Forest Mana Seed#_M"
+msgstr ""
+
+#. code: Name: "ForestArmor"
+#: item_db.conf:-1
+#, no-c-format
+msgid "ForestArmor"
+msgstr ""
+
+#. code: Name: "ForestBow"
+#: item_db.conf:-1
+#, no-c-format
+msgid "ForestBow"
+msgstr ""
+
+#. code: 026-1,29,28,0 script Forwin NPC316,{
+#: npc/026-1/evil_guard.txt:13
+#, no-c-format
+msgid "Forwin"
+msgstr ""
+
+#. code: Name: "FourLeafClover"
+#: item_db.conf:-1
+#, no-c-format
+msgid "FourLeafClover"
+msgstr ""
+
+#. code: Name: "FreeRangeMoss"
+#: item_db.conf:-1
+#, no-c-format
+msgid "FreeRangeMoss"
+msgstr ""
+
+#. code: Name: "FrozenYetiTear"
+#: item_db.conf:-1
+#, no-c-format
+msgid "FrozenYetiTear"
+msgstr ""
+
+#. code: 031-1,96,113,0 script Frozenbeard NPC138,{
+#: npc/031-1/frozenbeard.txt:1
+#, no-c-format
+msgid "Frozenbeard"
+msgstr ""
+
+#. code: 011-1,80,33,0 shop Fruit Store NPC400,719:5,535:6,657:10
+#: npc/011-1/shops.txt:1
+#, no-c-format
+msgid "Fruit Store"
+msgstr ""
+
+#. code: Name: "FunkyChristmasSweater"
+#: item_db.conf:-1
+#, no-c-format
+msgid "FunkyChristmasSweater"
+msgstr ""
+
+#. code: Name: "FunkyHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "FunkyHat"
+msgstr ""
+
+#. code: Name: "FurBoots"
+#: item_db.conf:-1
+#, no-c-format
+msgid "FurBoots"
+msgstr ""
+
+#. code: Name: "GMCap"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GMCap"
+msgstr ""
+
+#. code: Name: "GMRobe"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GMRobe"
+msgstr ""
+
+#. code: Name: "GambogeHerb"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GambogeHerb"
+msgstr ""
+
+#. code: 009-7,27,26,0 shop Garcon#Duels NPC180,533:55,4035:1500,562:125,676:100,539:87
+#: npc/009-7/shops.txt:2
+#, no-c-format
+msgid "Garcon#Duels"
+msgstr ""
+
+#. code: 027-6,39,25,0 script General Krukan NPC400,{
+#: npc/027-6/general_krukan.txt:1
+#, no-c-format
+msgid "General Krukan"
+msgstr ""
+
+#. code: 027-7,39,25,0 script General Razha NPC400,{
+#: npc/027-7/general_razha.txt:1
+#, no-c-format
+msgid "General Razha"
+msgstr ""
+
+#. code: 010-2,65,41,0 shop General Store#dimond NPC137,586:500,524:800,544:2000,632:500,528:500,735:500
+#: npc/010-2/dimonds.txt:534
+#, no-c-format
+msgid "General Store#dimond"
+msgstr ""
+
+#. code: 009-2,32,99,0 shop General Store#hurnscald NPC112,527:150,541:100,1202:5,586:500,528:500,656:100,724:500,741:500
+#: npc/009-2/shops.txt:13
+#, no-c-format
+msgid "General Store#hurnscald"
+msgstr ""
+
+#. code: 027-8,27,41,0 script General Terogan#Exit1 NPC400,{
+#: npc/027-8/general_terogan.txt:295
+#, no-c-format
+msgid "General Terogan#Exit1"
+msgstr ""
+
+#. code: 027-8,51,41,0 script General Terogan#Exit2 NPC400,{
+#: npc/027-8/general_terogan.txt:305
+#, no-c-format
+msgid "General Terogan#Exit2"
+msgstr ""
+
+#. code: 027-8,39,24,0 script General Terogan#Main NPC400,{
+#: npc/027-8/general_terogan.txt:1
+#, no-c-format
+msgid "General Terogan#Main"
+msgstr ""
+
+#. code: 008-1,135,62,0 script George#pirate NPC138,{
+#: npc/008-1/george.txt:1
+#, no-c-format
+msgid "George#pirate"
+msgstr ""
+
+#. code: 029-1,79,99,0 script Ghada NPC265,{
+#: npc/029-1/hideandseek.txt:325
+#, no-c-format
+msgid "Ghada"
+msgstr ""
+
+#. code: Name: "GiantCaveMaggot"
+#: mob_db.conf:4394
+#, no-c-format
+msgid "GiantCaveMaggot"
+msgstr ""
+
+#. code: Name: "GingerBreadMan"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GingerBreadMan"
+msgstr ""
+
+#. code: 001-2,118,39,0 script Gispaan#Female NPC406,{
+#: npc/001-2/manakins.txt:35
+#, no-c-format
+msgid "Gispaan#Female"
+msgstr ""
+
+#. code: 001-2,118,44,0 script Gispaan#Male NPC407,{
+#: npc/001-2/manakins.txt:40
+#, no-c-format
+msgid "Gispaan#Male"
+msgstr ""
+
+#. code: 001-1,66,104,0 script Gladys NPC154,{
+#: npc/001-1/gossip.txt:1
+#, no-c-format
+msgid "Gladys"
+msgstr ""
+
+#. code: 001-1,49,68,0 script Gm Event#1 NPC368,0,0,{
+#: npc/functions/gm_island.txt:59
+#, no-c-format
+msgid "Gm Event#1"
+msgstr ""
+
+#. code: 009-1,46,30,0 script Gm Event#2 NPC368,0,0,{
+#: npc/functions/gm_island.txt:63
+#, no-c-format
+msgid "Gm Event#2"
+msgstr ""
+
+#. code: 020-1,67,89,0 script Gm Event#3 NPC368,0,0,{
+#: npc/functions/gm_island.txt:67
+#, no-c-format
+msgid "Gm Event#3"
+msgstr ""
+
+#. code: Name: "GoblinMask"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GoblinMask"
+msgstr ""
+
+#. code: Name: "Goggles"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Goggles"
+msgstr ""
+
+#. code: 026-2,60,57,0 script Golbenez NPC307,{
+#: npc/026-2/golbenez.txt:1
+#, no-c-format
+msgid "Golbenez"
+msgstr ""
+
+#. code: Name: "GoldTicket"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GoldTicket"
+msgstr ""
+
+#. code: Name: "GoldenDeliciousApple"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GoldenDeliciousApple"
+msgstr ""
+
+#. code: Name: "GoldenFourLeafAmulet"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GoldenFourLeafAmulet"
+msgstr ""
+
+#. code: Name: "GoldenPVPCap"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GoldenPVPCap"
+msgstr ""
+
+#. code: Name: "GoldenPlatemail"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GoldenPlatemail"
+msgstr ""
+
+#. code: Name: "GoldenScorpionStinger"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GoldenScorpionStinger"
+msgstr ""
+
+#. code: Name: "GoldenWarlordPlate"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GoldenWarlordPlate"
+msgstr ""
+
+#. code: Name: "GraduationCap"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GraduationCap"
+msgstr ""
+
+#. code: Name: "GrapeLollipop"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GrapeLollipop"
+msgstr ""
+
+#. code: Name: "GrassFedTofu"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GrassFedTofu"
+msgstr ""
+
+#. code: Name: "GrassLiner"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GrassLiner"
+msgstr ""
+
+#. code: Name: "GrassSeed"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GrassSeed"
+msgstr ""
+
+#. code: Name: "GrassSnakeEgg"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GrassSnakeEgg"
+msgstr ""
+
+#. code: Name: "GrassSnakeTongue"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GrassSnakeTongue"
+msgstr ""
+
+#. code: 027-1,89,62,0 script Grave#1 NPC400,{
+#: npc/027-1/graves.txt:1
+#, no-c-format
+msgid "Grave#1"
+msgstr ""
+
+#. code: 027-1,122,64,0 script Grave#10 NPC400,{
+#: npc/027-1/graves.txt:82
+#, no-c-format
+msgid "Grave#10"
+msgstr ""
+
+#. code: 027-1,102,62,0 script Grave#11 NPC400,{
+#: npc/027-1/graves.txt:91
+#, no-c-format
+msgid "Grave#11"
+msgstr ""
+
+#. code: 027-1,104,76,0 script Grave#12 NPC400,{
+#: npc/027-1/graves.txt:100
+#, no-c-format
+msgid "Grave#12"
+msgstr ""
+
+#. code: 027-1,118,54,0 script Grave#2 NPC400,{
+#: npc/027-1/graves.txt:10
+#, no-c-format
+msgid "Grave#2"
+msgstr ""
+
+#. code: 027-1,111,62,0 script Grave#3 NPC400,{
+#: npc/027-1/graves.txt:19
+#, no-c-format
+msgid "Grave#3"
+msgstr ""
+
+#. code: 027-1,112,76,0 script Grave#4 NPC400,{
+#: npc/027-1/graves.txt:28
+#, no-c-format
+msgid "Grave#4"
+msgstr ""
+
+#. code: 027-1,120,76,0 script Grave#5 NPC400,{
+#: npc/027-1/graves.txt:37
+#, no-c-format
+msgid "Grave#5"
+msgstr ""
+
+#. code: 027-1,100,68,0 script Grave#6 NPC400,{
+#: npc/027-1/graves.txt:46
+#, no-c-format
+msgid "Grave#6"
+msgstr ""
+
+#. code: 027-1,94,70,0 script Grave#7 NPC400,{
+#: npc/027-1/graves.txt:55
+#, no-c-format
+msgid "Grave#7"
+msgstr ""
+
+#. code: 027-1,106,60,0 script Grave#8 NPC400,{
+#: npc/027-1/graves.txt:64
+#, no-c-format
+msgid "Grave#8"
+msgstr ""
+
+#. code: 027-1,92,54,0 script Grave#9 NPC400,{
+#: npc/027-1/graves.txt:73
+#, no-c-format
+msgid "Grave#9"
+msgstr ""
+
+#. code: Name: "GrayHint"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GrayHint"
+msgstr ""
+
+#. code: Name: "GreatDragon"
+#: mob_db.conf:3328
+#, no-c-format
+msgid "GreatDragon"
+msgstr ""
+
+#. code: Name: "GreenApple"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GreenApple"
+msgstr ""
+
+#. code: Name: "GreenBeret"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GreenBeret"
+msgstr ""
+
+#. code: Name: "GreenBowlerHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GreenBowlerHat"
+msgstr ""
+
+#. code: Name: "GreenBowlerHatBrown"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GreenBowlerHatBrown"
+msgstr ""
+
+#. code: Name: "GreenContributor"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GreenContributor"
+msgstr ""
+
+#. code: Name: "GreenCottonBoots"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GreenCottonBoots"
+msgstr ""
+
+#. code: Name: "GreenCottonCloth"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GreenCottonCloth"
+msgstr ""
+
+#. code: Name: "GreenCottonGloves"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GreenCottonGloves"
+msgstr ""
+
+#. code: Name: "GreenCottonHeadband"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GreenCottonHeadband"
+msgstr ""
+
+#. code: Name: "GreenCottonShirt"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GreenCottonShirt"
+msgstr ""
+
+#. code: Name: "GreenCottonShorts"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GreenCottonShorts"
+msgstr ""
+
+#. code: Name: "GreenCottonSkirt"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GreenCottonSkirt"
+msgstr ""
+
+#. code: Name: "GreenCottonTrousers"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GreenCottonTrousers"
+msgstr ""
+
+#. code: Name: "GreenDesertHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GreenDesertHat"
+msgstr ""
+
+#. code: Name: "GreenDye"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GreenDye"
+msgstr ""
+
+#. code: Name: "GreenEasterEgg"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GreenEasterEgg"
+msgstr ""
+
+#. code: Name: "GreenEggshellHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GreenEggshellHat"
+msgstr ""
+
+#. code: Name: "GreenFineDress"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GreenFineDress"
+msgstr ""
+
+#. code: Name: "GreenHint"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GreenHint"
+msgstr ""
+
+#. code: Name: "GreenHitchhikersTowel"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GreenHitchhikersTowel"
+msgstr ""
+
+#. code: Name: "GreenMiniskirt"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GreenMiniskirt"
+msgstr ""
+
+#. code: Name: "GreenOrnament"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GreenOrnament"
+msgstr ""
+
+#. code: Name: "GreenPresentBox"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GreenPresentBox"
+msgstr ""
+
+#. code: Name: "GreenPresentHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GreenPresentHat"
+msgstr ""
+
+#. code: Name: "GreenRabbitEars"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GreenRabbitEars"
+msgstr ""
+
+#. code: Name: "GreenRedStripedWrap"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GreenRedStripedWrap"
+msgstr ""
+
+#. code: Name: "GreenShades"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GreenShades"
+msgstr ""
+
+#. code: Name: "GreenShortTankTop"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GreenShortTankTop"
+msgstr ""
+
+#. code: Name: "GreenSilkRobe"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GreenSilkRobe"
+msgstr ""
+
+#. code: Name: "GreenSorcererBlack"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GreenSorcererBlack"
+msgstr ""
+
+#. code: Name: "GreenSorcererDBlue"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GreenSorcererDBlue"
+msgstr ""
+
+#. code: Name: "GreenSorcererDGreen"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GreenSorcererDGreen"
+msgstr ""
+
+#. code: Name: "GreenSorcererGreen"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GreenSorcererGreen"
+msgstr ""
+
+#. code: Name: "GreenSorcererLBlue"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GreenSorcererLBlue"
+msgstr ""
+
+#. code: Name: "GreenSorcererOrange"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GreenSorcererOrange"
+msgstr ""
+
+#. code: Name: "GreenSorcererPink"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GreenSorcererPink"
+msgstr ""
+
+#. code: Name: "GreenSorcererPurple"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GreenSorcererPurple"
+msgstr ""
+
+#. code: Name: "GreenSorcererRed"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GreenSorcererRed"
+msgstr ""
+
+#. code: Name: "GreenSorcererWhite"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GreenSorcererWhite"
+msgstr ""
+
+#. code: Name: "GreenSorcererYellow"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GreenSorcererYellow"
+msgstr ""
+
+#. code: Name: "GreenTankTop"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GreenTankTop"
+msgstr ""
+
+#. code: Name: "GreenTicket"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GreenTicket"
+msgstr ""
+
+#. code: Name: "GreenTurtleneck"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GreenTurtleneck"
+msgstr ""
+
+#. code: Name: "GreenVNeckSweater"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GreenVNeckSweater"
+msgstr ""
+
+#. code: Name: "GreenWizardHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GreenWizardHat"
+msgstr ""
+
+#. code: Name: "GreenWrap"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GreenWrap"
+msgstr ""
+
+#. code: Name: "GrimaceOfDementia"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GrimaceOfDementia"
+msgstr ""
+
+#. code: Name: "Grimoire"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Grimoire"
+msgstr ""
+
+#. code: Name: "GroovyHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GroovyHat"
+msgstr ""
+
+#. code: Name: "GrubSlime"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GrubSlime"
+msgstr ""
+
+#. code: 001-1,56,47,0 script Guard#castle NPC104,{
+#: npc/001-1/gate_guards.txt:5
+#, no-c-format
+msgid "Guard#castle"
+msgstr ""
+
+#. code: 002-1,83,48,0 script Guard#east1 NPC104,{
+#: npc/002-1/gaurds.txt:10
+#, no-c-format
+msgid "Guard#east1"
+msgstr ""
+
+#. code: 001-1,61,99,0 script Guard#east3 NPC104,{
+#: npc/001-1/gate_guards.txt:11
+#, no-c-format
+msgid "Guard#east3"
+msgstr ""
+
+#. code: 001-2,22,21,0 script Guard#govt_in NPC123,{
+#: npc/001-2/government_building.txt~:149
+#: npc/001-2/government_building.txt:149
+#, no-c-format
+msgid "Guard#govt_in"
+msgstr ""
+
+#. code: 001-1,53,72,0 script Guard#govt_out NPC123,{
+#: npc/001-1/gate_guards.txt:16
+#, no-c-format
+msgid "Guard#govt_out"
+msgstr ""
+
+#. code: 002-1,100,21,0 script Guard#port1 NPC104,{
+#: npc/002-1/gaurds.txt:0
+#, no-c-format
+msgid "Guard#port1"
+msgstr ""
+
+#. code: 002-1,61,27,0 script Guard#port2 NPC104,{
+#: npc/002-1/gaurds.txt:5
+#, no-c-format
+msgid "Guard#port2"
+msgstr ""
+
+#. code: 001-1,39,33,0 script Guard#school NPC104,{
+#: npc/001-1/gate_guards.txt:0
+#, no-c-format
+msgid "Guard#school"
+msgstr ""
+
+#. code: Name: "GuardianWings"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GuardianWings"
+msgstr ""
+
+#. code: Name: "GumiCandy"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GumiCandy"
+msgstr ""
+
+#. code: 001-2,30,60,0 shop Gungnir NPC311,903:50,904:0,530:8000,1199:1,529:2
+#: npc/001-2/forge_shops.txt:1
+#, no-c-format
+msgid "Gungnir"
+msgstr ""
+
+#. code: 036-2,35,22,0 shop Gunney NPC138,1199:4,529:4
+#: npc/036-2/shops.txt:2
+#, no-c-format
+msgid "Gunney"
+msgstr ""
+
+#. code: Name: "GutBuster"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GutBuster"
+msgstr ""
+
+#. code: Name: "GuyFawkesMask"
+#: item_db.conf:-1
+#, no-c-format
+msgid "GuyFawkesMask"
+msgstr ""
+
+#. code: 016-1,91,54,0 script Gwendolyn NPC182,{
+#: npc/016-1/gwendolyn.txt:8
+#: npc/016-1/gwendolyn.txt~:8
+#, no-c-format
+msgid "Gwendolyn"
+msgstr ""
+
+#. code: mesn "Gwendolyn Bowmaker";
+#: npc/016-1/gwendolyn.txt~:28
+#: npc/016-1/gwendolyn.txt:236
+#: npc/016-1/gwendolyn.txt:230
+#: npc/016-1/gwendolyn.txt~:388
+#: npc/016-1/gwendolyn.txt:123
+#: npc/016-1/gwendolyn.txt:224
+#: npc/016-1/gwendolyn.txt~:224
+#: npc/016-1/gwendolyn.txt:42
+#: npc/016-1/gwendolyn.txt~:57
+#: npc/016-1/gwendolyn.txt~:138
+#: npc/016-1/gwendolyn.txt:144
+#: npc/016-1/gwendolyn.txt~:67
+#: npc/016-1/gwendolyn.txt~:123
+#: npc/016-1/gwendolyn.txt~:84
+#: npc/016-1/gwendolyn.txt~:236
+#: npc/016-1/gwendolyn.txt~:378
+#: npc/016-1/gwendolyn.txt~:409
+#: npc/016-1/gwendolyn.txt~:230
+#: npc/016-1/gwendolyn.txt:409
+#: npc/016-1/gwendolyn.txt:167
+#: npc/016-1/gwendolyn.txt~:437
+#: npc/016-1/gwendolyn.txt~:78
+#: npc/016-1/gwendolyn.txt:28
+#: npc/016-1/gwendolyn.txt:242
+#: npc/016-1/gwendolyn.txt:218
+#: npc/016-1/gwendolyn.txt:67
+#: npc/016-1/gwendolyn.txt~:42
+#: npc/016-1/gwendolyn.txt~:98
+#: npc/016-1/gwendolyn.txt~:144
+#: npc/016-1/gwendolyn.txt~:167
+#: npc/016-1/gwendolyn.txt:84
+#: npc/016-1/gwendolyn.txt:388
+#: npc/016-1/gwendolyn.txt:437
+#: npc/016-1/gwendolyn.txt:98
+#: npc/016-1/gwendolyn.txt:396
+#: npc/016-1/gwendolyn.txt~:242
+#: npc/016-1/gwendolyn.txt~:396
+#: npc/016-1/gwendolyn.txt:57
+#: npc/016-1/gwendolyn.txt:138
+#: npc/016-1/gwendolyn.txt:78
+#: npc/016-1/gwendolyn.txt:378
+#: npc/016-1/gwendolyn.txt~:218
+#, no-c-format
+msgid "Gwendolyn Bowmaker"
+msgstr ""
+
+#. code: 030-2,89,43,0 script Halas NPC330,{
+#: npc/030-2/guards.txt:10
+#, no-c-format
+msgid "Halas"
+msgstr ""
+
+#. code: Name: "Halberd"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Halberd"
+msgstr ""
+
+#. code: 026-1,40,41,0 script Hamond NPC319,{
+#: npc/026-1/husband.txt:1
+#, no-c-format
+msgid "Hamond"
+msgstr ""
+
+#. code: Name: "HardSpike"
+#: item_db.conf:-1
+#, no-c-format
+msgid "HardSpike"
+msgstr ""
+
+#. code: 001-1,107,53,0 script Harper NPC213,{
+#: npc/001-1/npcs.txt:46
+#, no-c-format
+msgid "Harper"
+msgstr ""
+
+#. code: 029-1,33,33,0 script Hasan NPC189,3,3,{
+#: npc/029-1/hasan.txt:17
+#, no-c-format
+msgid "Hasan"
+msgstr ""
+
+#. code: Name: "HeartGlasses"
+#: item_db.conf:-1
+#, no-c-format
+msgid "HeartGlasses"
+msgstr ""
+
+#. code: Name: "HeartNecklace"
+#: item_db.conf:-1
+#, no-c-format
+msgid "HeartNecklace"
+msgstr ""
+
+#. code: Name: "HeartOfIsis"
+#: item_db.conf:-1
+#, no-c-format
+msgid "HeartOfIsis"
+msgstr ""
+
+#. code: Name: "HeartOfLazurite"
+#: item_db.conf:-1
+#, no-c-format
+msgid "HeartOfLazurite"
+msgstr ""
+
+#. code: 001-2,23,55,0 script Heathin NPC147,{
+#: npc/001-2/heathin.txt:0
+#, no-c-format
+msgid "Heathin"
+msgstr ""
+
+#. code: 001-2,25,55,0 script HeathinDebug NPC147,{
+#: npc/001-2/heathin.txt:315
+#, no-c-format
+msgid "HeathinDebug"
+msgstr ""
+
+#. code: 048-2,94,86,0 script Henriikka NPC363,{
+#: npc/048-2/helperBookpages2.txt:1
+#, no-c-format
+msgid "Henriikka"
+msgstr ""
+
+#. code: 002-2,76,92,0 script Hetchel NPC376,{
+#: npc/002-2/hetchel.txt:1
+#, no-c-format
+msgid "Hetchel"
+msgstr ""
+
+#. code: 002-2,73,95,0 script HetchelDebug NPC376,{
+#: npc/002-2/hetchel.txt:383
+#, no-c-format
+msgid "HetchelDebug"
+msgstr ""
+
+#. code: Name: "HighPriestCrown"
+#: item_db.conf:-1
+#, no-c-format
+msgid "HighPriestCrown"
+msgstr ""
+
+#. code: 008-1,101,30,0 script Hinnak NPC142,{
+#: npc/008-1/hinnak.txt:1
+#, no-c-format
+msgid "Hinnak"
+msgstr ""
+
+#. code: Name: "HitchhikersTowel"
+#: item_db.conf:-1
+#, no-c-format
+msgid "HitchhikersTowel"
+msgstr ""
+
+#. code: Name: "Honey"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Honey"
+msgstr ""
+
+#. code: 008-1,139,65,0 script Hurnscald North Dock NPC400,2,1,{
+#: npc/008-1/dock.txt:17
+#: npc/008-1/dock.txt~:17
+#, no-c-format
+msgid "Hurnscald North Dock"
+msgstr ""
+
+#. code: 008-1,147,64,0 script Hurnscald North Koga NPC395,10,3,{
+#: npc/008-1/dock.txt~:1
+#: npc/008-1/dock.txt:1
+#, no-c-format
+msgid "Hurnscald North Koga"
+msgstr ""
+
+#. code: 008-1,139,76,0 script Hurnscald South Dock NPC400,2,1,{
+#: npc/008-1/dock.txt:59
+#: npc/008-1/dock.txt~:59
+#, no-c-format
+msgid "Hurnscald South Dock"
+msgstr ""
+
+#. code: 008-1,147,75,0 script Hurnscald South Koga NPC395,10,3,{
+#: npc/008-1/dock.txt:43
+#: npc/008-1/dock.txt~:43
+#, no-c-format
+msgid "Hurnscald South Koga"
+msgstr ""
+
+#. code: 001-2,63,17,0 script Hydusun NPC149,{
+#: npc/001-2/bank.txt:0
+#, no-c-format
+msgid "Hydusun"
+msgstr ""
+
+#. code: Name: "HyvernStinger"
+#: item_db.conf:-1
+#, no-c-format
+msgid "HyvernStinger"
+msgstr ""
+
+#. code: 009-1,92,29,0 script Ian NPC102,{
+#: npc/009-1/guide.txt:1
+#, no-c-format
+msgid "Ian"
+msgstr ""
+
+#. code: Name: "IceCube"
+#: item_db.conf:-1
+#, no-c-format
+msgid "IceCube"
+msgstr ""
+
+#. code: Name: "IceGladius"
+#: item_db.conf:-1
+#, no-c-format
+msgid "IceGladius"
+msgstr ""
+
+#. code: Name: "IcedWater"
+#: item_db.conf:-1
+#, no-c-format
+msgid "IcedWater"
+msgstr ""
+
+#. code: 030-2,154,33,0 script Iivo NPC329,{
+#: npc/030-2/basic_npcs.txt:67
+#, no-c-format
+msgid "Iivo"
+msgstr ""
+
+#. code: 051-3,0,0,0 script IlliaCMobs051-3 NPC32767,{
+#: npc/051-3/jailslimes.txt:5
+#, no-c-format
+msgid "IlliaCMobs051-3"
+msgstr ""
+
+#. code: 051-1,0,0,0 script IlliaDMobs051-1 NPC32767,{
+#: npc/051-1/desertmonsters.txt:2
+#, no-c-format
+msgid "IlliaDMobs051-1"
+msgstr ""
+
+#. code: 051-1,0,0,0 script IlliaFMobs051-1 NPC32767,{
+#: npc/051-1/forestmonsters.txt:2
+#, no-c-format
+msgid "IlliaFMobs051-1"
+msgstr ""
+
+#. code: 002-2,36,75,0 script Imec NPC162,{
+#: npc/002-2/imec.txt:0
+#, no-c-format
+msgid "Imec"
+msgstr ""
+
+#. code: 001-1,58,81,0 script Inac NPC156,{
+#: npc/001-1/inac.txt:1
+#, no-c-format
+msgid "Inac"
+msgstr ""
+
+#. code: 001-1,111,108,0 shop Inar NPC108,1202:5,656:100,586:500,735:500,546:1000,724:500,723:2400
+#: npc/001-1/north_shops.txt:1
+#, no-c-format
+msgid "Inar"
+msgstr ""
+
+#. code: Name: "InfantryHelmet"
+#: item_db.conf:-1
+#, no-c-format
+msgid "InfantryHelmet"
+msgstr ""
+
+#. code: 010-2,71,30,0 script Inn NPC400,{
+#: npc/010-2/dimonds.txt:520
+#, no-c-format
+msgid "Inn"
+msgstr ""
+
+#. code: 009-2,24,99,0 script Inspector#Hurnscald NPC150,{
+#: npc/009-2/inspector.txt:1
+#, no-c-format
+msgid "Inspector#Hurnscald"
+msgstr ""
+
+#. code: 002-2,116,61,0 script Inya NPC106,{
+#: npc/002-2/inya.txt:3
+#, no-c-format
+msgid "Inya"
+msgstr ""
+
+#. code: 002-2,21,28,0 script Iormo NPC160,{
+#: npc/002-2/bakery.txt:128
+#, no-c-format
+msgid "Iormo"
+msgstr ""
+
+#. code: Name: "IronArrow"
+#: item_db.conf:-1
+#, no-c-format
+msgid "IronArrow"
+msgstr ""
+
+#. code: Name: "IronIngot"
+#: item_db.conf:-1
+#, no-c-format
+msgid "IronIngot"
+msgstr ""
+
+#. code: Name: "IronOre"
+#: item_db.conf:-1
+#, no-c-format
+msgid "IronOre"
+msgstr ""
+
+#. code: Name: "IronPotion"
+#: item_db.conf:-1
+#, no-c-format
+msgid "IronPotion"
+msgstr ""
+
+#. code: Name: "IronPowder"
+#: item_db.conf:-1
+#, no-c-format
+msgid "IronPowder"
+msgstr ""
+
+#. code: 029-1,47,97,0 script Ishi NPC106,{
+#: npc/029-1/rewards_master.txt:1
+#, no-c-format
+msgid "Ishi"
+msgstr ""
+
+#. code: 002-3,60,47,0 shop Ishyah NPC109,525:400,531:1000,530:8000,1199:2,603:1000
+#: npc/002-3/merchant.txt:1
+#, no-c-format
+msgid "Ishyah"
+msgstr ""
+
+#. code: 030-2,33,29,0 script Ismo NPC329,{
+#: npc/030-2/storage_helper.txt:49
+#, no-c-format
+msgid "Ismo"
+msgstr ""
+
+#. code: 002-2,22,77,0 script Issay NPC156,{
+#: npc/002-2/barber.txt:0
+#, no-c-format
+msgid "Issay"
+msgstr ""
+
+#. code: Name: "Iten"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Iten"
+msgstr ""
+
+#. code: 002-1,66,39,0 script Itka NPC114,{
+#: npc/002-1/itka.txt:0
+#, no-c-format
+msgid "Itka"
+msgstr ""
+
+#. code: 026-2,25,120,0 script J.P. Morbid NPC321,{
+#: npc/026-2/gy_inn_shops.txt:29
+#, no-c-format
+msgid "J.P. Morbid"
+msgstr ""
+
+#. code: 009-1,40,45,0 script Jack NPC141,{
+#: npc/009-1/jack.txt:1
+#, no-c-format
+msgid "Jack"
+msgstr ""
+
+#. code: Name: "JackOLantern"
+#: item_db.conf:-1
+#, no-c-format
+msgid "JackOLantern"
+msgstr ""
+
+#. code: Name: "Jackal"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Jackal"
+msgstr ""
+
+#. code: Name: "JadeEgg"
+#: item_db.conf:-1
+#, no-c-format
+msgid "JadeEgg"
+msgstr ""
+
+#. code: 051-3,69,107,0 script Jail Lock 1 NPC400,{
+#: npc/051-3/locks.txt:0
+#, no-c-format
+msgid "Jail Lock 1"
+msgstr ""
+
+#. code: 051-3,64,100,0 script Jail Lock 2 NPC400,{
+#: npc/051-3/locks.txt:18
+#, no-c-format
+msgid "Jail Lock 2"
+msgstr ""
+
+#. code: 051-3,62,100,0 script Jail Lock 3 NPC400,{
+#: npc/051-3/locks.txt:34
+#, no-c-format
+msgid "Jail Lock 3"
+msgstr ""
+
+#. code: 051-3,58,100,0 script Jail Lock 4 NPC400,{
+#: npc/051-3/locks.txt:50
+#, no-c-format
+msgid "Jail Lock 4"
+msgstr ""
+
+#. code: 048-2,104,103,0 script Janika NPC363,{
+#: npc/048-2/helperMSilk.txt:1
+#, no-c-format
+msgid "Janika"
+msgstr ""
+
+#. code: Name: "JarofBlood"
+#: item_db.conf:-1
+#, no-c-format
+msgid "JarofBlood"
+msgstr ""
+
+#. code: Name: "JarofOwnBlood"
+#: item_db.conf:-1
+#, no-c-format
+msgid "JarofOwnBlood"
+msgstr ""
+
+#. code: Name: "JazzyHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "JazzyHat"
+msgstr ""
+
+#. code: Name: "JeansChaps"
+#: item_db.conf:-1
+#, no-c-format
+msgid "JeansChaps"
+msgstr ""
+
+#. code: Name: "JeansShorts"
+#: item_db.conf:-1
+#, no-c-format
+msgid "JeansShorts"
+msgstr ""
+
+#. code: Name: "JellAhh"
+#: item_db.conf:-1
+#, no-c-format
+msgid "JellAhh"
+msgstr ""
+
+#. code: Name: "JellyBeans"
+#: item_db.conf:-1
+#, no-c-format
+msgid "JellyBeans"
+msgstr ""
+
+#. code: Name: "JellySkull"
+#: item_db.conf:-1
+#, no-c-format
+msgid "JellySkull"
+msgstr ""
+
+#. code: 002-3,25,28,0 script Jena the Traveler NPC103,{
+#: npc/002-3/traveler.txt:1
+#, no-c-format
+msgid "Jena the Traveler"
+msgstr ""
+
+#. code: 002-1,96,23,0 script Jeric NPC214,{
+#: npc/002-1/npcs.txt:0
+#, no-c-format
+msgid "Jeric"
+msgstr ""
+
+#. code: 010-2,40,37,0 script Jerry NPC160,{
+#: npc/010-2/band.txt:5
+#, no-c-format
+msgid "Jerry"
+msgstr ""
+
+#. code: 029-2,98,92,0 script Jessie NPC159,{
+#: npc/029-2/stat_reset.txt:1
+#, no-c-format
+msgid "Jessie"
+msgstr ""
+
+#. code: Name: "JesterMask"
+#: item_db.conf:-1
+#, no-c-format
+msgid "JesterMask"
+msgstr ""
+
+#. code: 001-2,23,50,0 script Jhedia NPC160,{
+#: npc/001-2/jhedia.txt:1
+#, no-c-format
+msgid "Jhedia"
+msgstr ""
+
+#. code: 027-2,48,22,0 script Joan NPC409,{
+#: npc/027-2/caretaker.txt:107
+#, no-c-format
+msgid "Joan"
+msgstr ""
+
+#. code: 001-1,105,53,0 script Joelin NPC212,{
+#: npc/001-1/npcs.txt:36
+#, no-c-format
+msgid "Joelin"
+msgstr ""
+
+#. code: 030-2,47,82,0 script Jonathan NPC328,{
+#: npc/030-2/present_helper.txt:1
+#, no-c-format
+msgid "Jonathan"
+msgstr ""
+
+#. code: 010-2,23,70,0 script Josh NPC155,{
+#: npc/010-2/workers.txt:1
+#, no-c-format
+msgid "Josh"
+msgstr ""
+
+#. code: 025-4,89,21,0 script Julia NPC114,{
+#: npc/025-4/julia.txt:1
+#, no-c-format
+msgid "Julia"
+msgstr ""
+
+#. code: 002-2,120,89,0 script KPS Manager NPC191,{
+#: npc/002-2/kps.txt:0
+#, no-c-format
+msgid "KPS Manager"
+msgstr ""
+
+#. code: 029-1,46,95,0 script Kaan NPC160,{
+#: npc/029-1/kaan.txt:1
+#, no-c-format
+msgid "Kaan"
+msgstr ""
+
+#. code: 002-2,124,124,0 script Kadiya NPC174,{
+#: npc/002-2/omar.txt:177
+#, no-c-format
+msgid "Kadiya"
+msgstr ""
+
+#. code: 020-2,111,23,0 script Kane NPC120,{
+#: npc/020-2/shops.txt:15
+#, no-c-format
+msgid "Kane"
+msgstr ""
+
+#. code: 015-3,32,25,0 script Katze NPC172,{
+#: npc/015-3/katze.txt:1
+#, no-c-format
+msgid "Katze"
+msgstr ""
+
+#. code: 009-2,67,57,0 script Kfahr NPC125,{
+#: npc/009-2/kfahr.txt:1
+#, no-c-format
+msgid "Kfahr"
+msgstr ""
+
+#. code: 033-1,63,30,0 script Khoenan the Traveler NPC103,{
+#: npc/033-1/traveler.txt:1
+#, no-c-format
+msgid "Khoenan the Traveler"
+msgstr ""
+
+#. code: Name: "KidBook"
+#: item_db.conf:-1
+#, no-c-format
+msgid "KidBook"
+msgstr ""
+
+#. code: 030-2,89,84,0 script Kilis NPC330,5,2,{
+#: npc/030-2/guards.txt:19
+#, no-c-format
+msgid "Kilis"
+msgstr ""
+
+#. code: 033-1,74,32,0 script Kimarr NPC218,{
+#: npc/033-1/kimarr.txt:5
+#, no-c-format
+msgid "Kimarr"
+msgstr ""
+
+#. code: Name: "Knife"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Knife"
+msgstr ""
+
+#. code: Name: "KnightsHelmet"
+#: item_db.conf:-1
+#, no-c-format
+msgid "KnightsHelmet"
+msgstr ""
+
+#. code: Name: "KnitCap"
+#: item_db.conf:-1
+#, no-c-format
+msgid "KnitCap"
+msgstr ""
+
+#. code: 029-1,69,68,0 script Knitra the Traveler NPC103,{
+#: npc/029-1/traveler.txt:1
+#, no-c-format
+msgid "Knitra the Traveler"
+msgstr ""
+
+#. code: 020-1,57,123,0 script Knox the Traveler NPC103,{
+#: npc/020-1/traveler.txt:0
+#, no-c-format
+msgid "Knox the Traveler"
+msgstr ""
+
+#. code: 048-2,131,119,0 script Kristian NPC366,{
+#: npc/048-2/helperCleaning4.txt:1
+#, no-c-format
+msgid "Kristian"
+msgstr ""
+
+#. code: 048-2,104,78,0 script Kullervo NPC366,{
+#: npc/048-2/helperMReed.txt:1
+#, no-c-format
+msgid "Kullervo"
+msgstr ""
+
+#. code: 002-2,43,101,0 script Kylian NPC193,{
+#: npc/002-2/kylian.txt:27
+#, no-c-format
+msgid "Kylian"
+msgstr ""
+
+#. code: 002-2,40,101,0 script KylianDebug#1 NPC193,{
+#: npc/002-2/kylian.txt:344
+#, no-c-format
+msgid "KylianDebug#1"
+msgstr ""
+
+#. code: 002-2,118,89,0 script KylianDebug#2 NPC193,{
+#: npc/002-2/kylian.txt:352
+#, no-c-format
+msgid "KylianDebug#2"
+msgstr ""
+
+#. code: Name: "LacedChocolateCake"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LacedChocolateCake"
+msgstr ""
+
+#. code: Name: "LacedOrangeCupcake"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LacedOrangeCupcake"
+msgstr ""
+
+#. code: Name: "LactoseFreeAcorn"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LactoseFreeAcorn"
+msgstr ""
+
+#. code: Name: "LadyFingers"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LadyFingers"
+msgstr ""
+
+#. code: Name: "LargeHealingPotion"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LargeHealingPotion"
+msgstr ""
+
+#. code: Name: "LargeManaElixir"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LargeManaElixir"
+msgstr ""
+
+#. code: 029-1,50,105,0 script Latif NPC262,{
+#: npc/029-1/hideandseek.txt:131
+#, no-c-format
+msgid "Latif"
+msgstr ""
+
+#. code: 002-2,86,93,0 script Latoy NPC106,{
+#: npc/002-2/latoy.txt:1
+#, no-c-format
+msgid "Latoy"
+msgstr ""
+
+#. code: Name: "LazuriteCrystal"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LazuriteCrystal"
+msgstr ""
+
+#. code: Name: "LazuriteRobe"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LazuriteRobe"
+msgstr ""
+
+#. code: Name: "LazuriteShard"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LazuriteShard"
+msgstr ""
+
+#. code: Name: "LeatherBall"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LeatherBall"
+msgstr ""
+
+#. code: Name: "LeatherGloves"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LeatherGloves"
+msgstr ""
+
+#. code: Name: "LeatherGoggles"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LeatherGoggles"
+msgstr ""
+
+#. code: Name: "LeatherPatch"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LeatherPatch"
+msgstr ""
+
+#. code: Name: "LeatherShield"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LeatherShield"
+msgstr ""
+
+#. code: Name: "LeatherShirt"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LeatherShirt"
+msgstr ""
+
+#. code: Name: "LeatherSuitcase"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LeatherSuitcase"
+msgstr ""
+
+#. code: Name: "LeatherTrousers"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LeatherTrousers"
+msgstr ""
+
+#. code: 009-2,146,43,0 script Lena NPC182,{
+#: npc/009-2/lena.txt:1
+#: npc/009-2/lena.txt~:1
+#, no-c-format
+msgid "Lena"
+msgstr ""
+
+#. code: 048-2,36,26,0 script Lenita NPC363,{
+#: npc/048-2/helperResting1.txt:1
+#, no-c-format
+msgid "Lenita"
+msgstr ""
+
+#. code: 026-2,31,119,0 shop Leofwin NPC304,501:25,502:35,518:25,566:50,567:250,568:250,613:10,631:250,740:200,772:350,773:350,774:350
+#: npc/026-2/gy_inn_shops.txt:26
+#, no-c-format
+msgid "Leofwin"
+msgstr ""
+
+#. code: 029-1,62,96,0 script Liana NPC205,{
+#: npc/029-1/liana.txt:1
+#, no-c-format
+msgid "Liana"
+msgstr ""
+
+#. code: 002-1,63,67,0 script Lieutenant Dausen NPC122,{
+#: npc/002-1/lieutenant_dausen.txt:0
+#, no-c-format
+msgid "Lieutenant Dausen"
+msgstr ""
+
+#. code: Name: "Lifestone"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Lifestone"
+msgstr ""
+
+#. code: Name: "LightBlueBeret"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LightBlueBeret"
+msgstr ""
+
+#. code: Name: "LightBlueBowlerHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LightBlueBowlerHat"
+msgstr ""
+
+#. code: Name: "LightBlueBowlerHatBrown"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LightBlueBowlerHatBrown"
+msgstr ""
+
+#. code: Name: "LightBlueContributor"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LightBlueContributor"
+msgstr ""
+
+#. code: Name: "LightBlueCottonBoots"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LightBlueCottonBoots"
+msgstr ""
+
+#. code: Name: "LightBlueCottonCloth"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LightBlueCottonCloth"
+msgstr ""
+
+#. code: Name: "LightBlueCottonGloves"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LightBlueCottonGloves"
+msgstr ""
+
+#. code: Name: "LightBlueCottonHeadband"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LightBlueCottonHeadband"
+msgstr ""
+
+#. code: Name: "LightBlueCottonShirt"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LightBlueCottonShirt"
+msgstr ""
+
+#. code: Name: "LightBlueCottonShorts"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LightBlueCottonShorts"
+msgstr ""
+
+#. code: Name: "LightBlueCottonSkirt"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LightBlueCottonSkirt"
+msgstr ""
+
+#. code: Name: "LightBlueCottonTrousers"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LightBlueCottonTrousers"
+msgstr ""
+
+#. code: Name: "LightBlueDesertHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LightBlueDesertHat"
+msgstr ""
+
+#. code: Name: "LightBlueDye"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LightBlueDye"
+msgstr ""
+
+#. code: Name: "LightBlueFineDress"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LightBlueFineDress"
+msgstr ""
+
+#. code: Name: "LightBlueMiniskirt"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LightBlueMiniskirt"
+msgstr ""
+
+#. code: Name: "LightBlueRabbitEars"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LightBlueRabbitEars"
+msgstr ""
+
+#. code: Name: "LightBlueShades"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LightBlueShades"
+msgstr ""
+
+#. code: Name: "LightBlueShortTankTop"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LightBlueShortTankTop"
+msgstr ""
+
+#. code: Name: "LightBlueSilkRobe"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LightBlueSilkRobe"
+msgstr ""
+
+#. code: Name: "LightBlueSorcererBlack"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LightBlueSorcererBlack"
+msgstr ""
+
+#. code: Name: "LightBlueSorcererDBlue"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LightBlueSorcererDBlue"
+msgstr ""
+
+#. code: Name: "LightBlueSorcererDGreen"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LightBlueSorcererDGreen"
+msgstr ""
+
+#. code: Name: "LightBlueSorcererGreen"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LightBlueSorcererGreen"
+msgstr ""
+
+#. code: Name: "LightBlueSorcererLBlue"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LightBlueSorcererLBlue"
+msgstr ""
+
+#. code: Name: "LightBlueSorcererOrange"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LightBlueSorcererOrange"
+msgstr ""
+
+#. code: Name: "LightBlueSorcererPink"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LightBlueSorcererPink"
+msgstr ""
+
+#. code: Name: "LightBlueSorcererPurple"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LightBlueSorcererPurple"
+msgstr ""
+
+#. code: Name: "LightBlueSorcererRed"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LightBlueSorcererRed"
+msgstr ""
+
+#. code: Name: "LightBlueSorcererWhite"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LightBlueSorcererWhite"
+msgstr ""
+
+#. code: Name: "LightBlueSorcererYellow"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LightBlueSorcererYellow"
+msgstr ""
+
+#. code: Name: "LightBlueTankTop"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LightBlueTankTop"
+msgstr ""
+
+#. code: Name: "LightBlueTurtleneck"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LightBlueTurtleneck"
+msgstr ""
+
+#. code: Name: "LightBlueVNeckSweater"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LightBlueVNeckSweater"
+msgstr ""
+
+#. code: Name: "LightBlueWizardHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LightBlueWizardHat"
+msgstr ""
+
+#. code: Name: "LightCrystal"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LightCrystal"
+msgstr ""
+
+#. code: Name: "LightPlatemail"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LightPlatemail"
+msgstr ""
+
+#. code: Name: "LimeHitchhikersTowel"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LimeHitchhikersTowel"
+msgstr ""
+
+#. code: Name: "LockPicks"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LockPicks"
+msgstr ""
+
+#. code: Name: "LollipopColor1"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LollipopColor1"
+msgstr ""
+
+#. code: Name: "LollipopColor2"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LollipopColor2"
+msgstr ""
+
+#. code: Name: "LollipopColor3"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LollipopColor3"
+msgstr ""
+
+#. code: Name: "LongSword"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LongSword"
+msgstr ""
+
+#. code: 010-2,85,85,0 script Lora Tay NPC151,{
+#: npc/010-2/loratay.txt:35
+#, no-c-format
+msgid "Lora Tay"
+msgstr ""
+
+#. code: 010-2,83,85,0 script Lora Tay Debug NPC151,{
+#: npc/010-2/loratay.txt:0
+#, no-c-format
+msgid "Lora Tay Debug"
+msgstr ""
+
+#. code: 030-2,33,88,0 script Lorrie NPC329,{
+#: npc/030-2/shipping_helper.txt:7
+#, no-c-format
+msgid "Lorrie"
+msgstr ""
+
+#. code: Name: "LoveLetter"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LoveLetter"
+msgstr ""
+
+#. code: Name: "LovePotion"
+#: item_db.conf:-1
+#, no-c-format
+msgid "LovePotion"
+msgstr ""
+
+#. code: 026-2,64,32,0 script Lovers NPC303,{
+#: npc/026-2/testnpcs.txt:1
+#, no-c-format
+msgid "Lovers"
+msgstr ""
+
+#. code: 002-1,112,26,0 script Luca NPC102,{
+#: npc/002-1/luca.txt:1
+#, no-c-format
+msgid "Luca"
+msgstr ""
+
+#. code: 052-2,88,15,0 script Luvia NPC371,{
+#: npc/052-2/partyroom.txt:30
+#, no-c-format
+msgid "Luvia"
+msgstr ""
+
+#. code: 052-2,1,1,0 script Luvia? NPC371,2,2,{
+#: npc/052-2/lobby.txt:136
+#, no-c-format
+msgid "Luvia?"
+msgstr ""
+
+#. code: Name: "MTJarofOwnBlood"
+#: item_db.conf:-1
+#, no-c-format
+msgid "MTJarofOwnBlood"
+msgstr ""
+
+#. code: Name: "MageRing"
+#: item_db.conf:-1
+#, no-c-format
+msgid "MageRing"
+msgstr ""
+
+#. code: Name: "MagentaHint"
+#: item_db.conf:-1
+#, no-c-format
+msgid "MagentaHint"
+msgstr ""
+
+#. code: Name: "MagentaOrnament"
+#: item_db.conf:-1
+#, no-c-format
+msgid "MagentaOrnament"
+msgstr ""
+
+#. code: Name: "MaggotSlime"
+#: item_db.conf:-1
+#, no-c-format
+msgid "MaggotSlime"
+msgstr ""
+
+#. code: Name: "MagicGMTopHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "MagicGMTopHat"
+msgstr ""
+
+#. code: 018-2,85,23,0 script Malek NPC109,{
+#: npc/018-2/miners.txt:1
+#, no-c-format
+msgid "Malek"
+msgstr ""
+
+#. code: 001-1,117,105,0 script Malivox NPC103,{
+#: npc/001-1/stat_reset.txt:1
+#, no-c-format
+msgid "Malivox"
+msgstr ""
+
+#. code: Name: "ManaGuardian"
+#: mob_db.conf:3085
+#, no-c-format
+msgid "ManaGuardian"
+msgstr ""
+
+#. code: Name: "ManaPotion"
+#: item_db.conf:-1
+#, no-c-format
+msgid "ManaPotion"
+msgstr ""
+
+#. code: 020-2,127,63,0 script Maria NPC190,{
+#: npc/020-2/banker.txt:6
+#, no-c-format
+msgid "Maria"
+msgstr ""
+
+#. code: 001-1,100,79,0 script Marikel NPC211,{
+#: npc/001-1/npcs.txt:10
+#, no-c-format
+msgid "Marikel"
+msgstr ""
+
+#. code: Name: "Marshmallow"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Marshmallow"
+msgstr ""
+
+#. code: Name: "MauveHerb"
+#: item_db.conf:-1
+#, no-c-format
+msgid "MauveHerb"
+msgstr ""
+
+#. code: 020-2,75,24,0 shop Mede NPC103,501:25,502:35,567:250,568:250,826:120,827:240,828:480
+#: npc/020-2/shops.txt:13
+#, no-c-format
+msgid "Mede"
+msgstr ""
+
+#. code: Name: "MediumHealingPotion"
+#: item_db.conf:-1
+#, no-c-format
+msgid "MediumHealingPotion"
+msgstr ""
+
+#. code: Name: "MediumManaElixir"
+#: item_db.conf:-1
+#, no-c-format
+msgid "MediumManaElixir"
+msgstr ""
+
+#. code: 009-2,60,52,0 script Melinda NPC140,{
+#: npc/009-2/waitress.txt:1
+#, no-c-format
+msgid "Melinda"
+msgstr ""
+
+#. code: 006-2,34,64,0 script Meluna NPC179,{
+#: npc/006-2/npcs.txt:62
+#, no-c-format
+msgid "Meluna"
+msgstr ""
+
+#. code: 012-3,439,62,0 script Meridith the Traveler NPC103,{
+#: npc/012-3/traveler.txt:1
+#, no-c-format
+msgid "Meridith the Traveler"
+msgstr ""
+
+#. code: 001-1,92,107,0 script Michel NPC215,{
+#: npc/001-1/npcs.txt:60
+#, no-c-format
+msgid "Michel"
+msgstr ""
+
+#. code: 006-1,39,22,0 script Mika NPC114,{
+#: npc/006-1/mika.txt:0
+#, no-c-format
+msgid "Mika"
+msgstr ""
+
+#. code: 018-1,77,60,0 script Mike NPC113,{
+#: npc/018-1/mike.txt:0
+#, no-c-format
+msgid "Mike"
+msgstr ""
+
+#. code: 008-1,135,25,0 script Mikhail NPC120,{
+#: npc/008-1/mikhail.txt:0
+#, no-c-format
+msgid "Mikhail"
+msgstr ""
+
+#. code: 020-2,100,28,0 script Miler NPC100,{
+#: npc/020-1/well.txt:79
+#, no-c-format
+msgid "Miler"
+msgstr ""
+
+#. code: 030-2,190,64,0 script Milis NPC330,{
+#: npc/030-2/avalia.txt:188
+#, no-c-format
+msgid "Milis"
+msgstr ""
+
+#. code: Name: "Milk"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Milk"
+msgstr ""
+
+#. code: 009-1,81,41,0 script Milly NPC114,{
+#: npc/009-1/milly.txt:1
+#, no-c-format
+msgid "Milly"
+msgstr ""
+
+#. code: 009-1,82,41,0 script MillyDebugHelper NPC114,{
+#: npc/009-1/milly.txt:377
+#, no-c-format
+msgid "MillyDebugHelper"
+msgstr ""
+
+#. code: 002-1,61,69,0 script Mine Debug#1 NPC122,{
+#: npc/002-1/mine_debug.txt:32
+#, no-c-format
+msgid "Mine Debug#1"
+msgstr ""
+
+#. code: 002-3,45,49,6 script Mine Debug#2 NPC109,{
+#: npc/002-1/mine_debug.txt:41
+#, no-c-format
+msgid "Mine Debug#2"
+msgstr ""
+
+#. code: 002-4,88,99,6 script Mine Debug#3 NPC109,{
+#: npc/002-1/mine_debug.txt:50
+#, no-c-format
+msgid "Mine Debug#3"
+msgstr ""
+
+#. code: 002-5,43,96,6 script Mine Debug#4 NPC340,{
+#: npc/002-1/mine_debug.txt:59
+#, no-c-format
+msgid "Mine Debug#4"
+msgstr ""
+
+#. code: 018-1,80,61,0 script Miner NPC109,{
+#: npc/018-1/miners.txt:0
+#, no-c-format
+msgid "Miner"
+msgstr ""
+
+#. code: Name: "MinerGloves"
+#: item_db.conf:-1
+#, no-c-format
+msgid "MinerGloves"
+msgstr ""
+
+#. code: Name: "MinersHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "MinersHat"
+msgstr ""
+
+#. code: Name: "Miniskirt"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Miniskirt"
+msgstr ""
+
+#. code: 056-2,67,24,0 script Mirak NPC372,{
+#: npc/056-2/mirak.txt:0
+#, no-c-format
+msgid "Mirak"
+msgstr ""
+
+#. code: 006-1,115,111,0 script Miriam NPC175,{
+#: npc/006-1/miriam.txt:1
+#, no-c-format
+msgid "Miriam"
+msgstr ""
+
+#. code: 048-2,100,125,0 script Mirjami NPC363,{
+#: npc/048-2/helperCleaning5.txt:1
+#, no-c-format
+msgid "Mirjami"
+msgstr ""
+
+#. code: 048-2,35,27,0 script Miro NPC366,{
+#: npc/048-2/helperResting2.txt:1
+#, no-c-format
+msgid "Miro"
+msgstr ""
+
+#. code: 013-2,27,21,0 script Mirror#wiz NPC400,{
+#: npc/013-2/notes.txt:17
+#, no-c-format
+msgid "Mirror#wiz"
+msgstr ""
+
+#. code: 001-2,25,59,0 shop Mjolnir NPC377,1201:25,522:50,521:500,523:1000,603:1000
+#: npc/001-2/forge_shops.txt:2
+#, no-c-format
+msgid "Mjolnir"
+msgstr ""
+
+#. code: 030-2,30,88,0 script Mo NPC328,{
+#: npc/030-2/shipping_helper.txt:1
+#, no-c-format
+msgid "Mo"
+msgstr ""
+
+#. code: 002-2,78,56,0 shop MoneyChanger NPC124,503:10
+#: npc/002-2/casino.txt:32
+#, no-c-format
+msgid "MoneyChanger"
+msgstr ""
+
+#. code: Name: "Monocle"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Monocle"
+msgstr ""
+
+#. code: Name: "MonsterOilPotion"
+#: item_db.conf:-1
+#, no-c-format
+msgid "MonsterOilPotion"
+msgstr ""
+
+#. code: Name: "MonsterSkullHelmet"
+#: item_db.conf:-1
+#, no-c-format
+msgid "MonsterSkullHelmet"
+msgstr ""
+
+#. code: Name: "MoonshroomHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "MoonshroomHat"
+msgstr ""
+
+#. code: Name: "MopoxCurePotion"
+#: item_db.conf:-1
+#, no-c-format
+msgid "MopoxCurePotion"
+msgstr ""
+
+#. code: 029-2,101,57,0 script Morgan#_M NPC355,{
+#: npc/029-2/morgan.txt:19
+#, no-c-format
+msgid "Morgan#_M"
+msgstr ""
+
+#. code: 029-2,105,57,0 script MorganDebug NPC355,{
+#: npc/029-2/morgan.txt:0
+#, no-c-format
+msgid "MorganDebug"
+msgstr ""
+
+#. code: 013-2,23,32,0 script Motto#wiz NPC400,{
+#: npc/013-2/notes.txt:1
+#, no-c-format
+msgid "Motto#wiz"
+msgstr ""
+
+#. code: 012-1,57,153,0 script Mouboo NPC171,{
+#: npc/012-1/injured-mouboo.txt:45
+#, no-c-format
+msgid "Mouboo"
+msgstr ""
+
+#. code: Name: "MoubooFigurine"
+#: item_db.conf:-1
+#, no-c-format
+msgid "MoubooFigurine"
+msgstr ""
+
+#. code: Name: "MoubooHead"
+#: item_db.conf:-1
+#, no-c-format
+msgid "MoubooHead"
+msgstr ""
+
+#. code: Name: "MoubootaurHead"
+#: item_db.conf:-1
+#, no-c-format
+msgid "MoubootaurHead"
+msgstr ""
+
+#. code: Name: "MountainSnakeEgg"
+#: item_db.conf:-1
+#, no-c-format
+msgid "MountainSnakeEgg"
+msgstr ""
+
+#. code: Name: "MountainSnakeTongue"
+#: item_db.conf:-1
+#, no-c-format
+msgid "MountainSnakeTongue"
+msgstr ""
+
+#. code: Name: "MovieCap"
+#: item_db.conf:-1
+#, no-c-format
+msgid "MovieCap"
+msgstr ""
+
+#. code: 026-1,24,37,0 script Munro NPC183,{
+#: npc/annuals/halloween/munro.txt:0
+#, no-c-format
+msgid "Munro"
+msgstr ""
+
+#. code: Name: "MurdererCrown"
+#: item_db.conf:-1
+#, no-c-format
+msgid "MurdererCrown"
+msgstr ""
+
+#. code: Name: "MushHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "MushHat"
+msgstr ""
+
+#. code: Name: "MylarinDust"
+#: item_db.conf:-1
+#, no-c-format
+msgid "MylarinDust"
+msgstr ""
+
+#. code: 002-4,91,96,6 script Naem NPC109,{
+#: npc/002-4/naem.txt:0
+#, no-c-format
+msgid "Naem"
+msgstr ""
+
+#. code: mesn l("Narrator");
+#: npc/functions/main.txt:150
+#: npc/functions/main.txt~:150
+#, no-c-format
+msgid "Narrator"
+msgstr ""
+
+#. code: 002-3,42,45,6 script Nathan NPC109,{
+#: npc/002-3/nathan.txt:0
+#, no-c-format
+msgid "Nathan"
+msgstr ""
+
+#. code: 048-2,123,87,0 script Nea NPC363,{
+#: npc/048-2/helperCleaning2.txt:1
+#, no-c-format
+msgid "Nea"
+msgstr ""
+
+#. code: 001-1,106,105,0 shop Neko NPC101,3006:10,501:25,502:35,533:55,539:87,562:250
+#: npc/001-1/north_shops.txt:0
+#, no-c-format
+msgid "Neko"
+msgstr ""
+
+#. code: 009-2,185,55,0 script Nicholas NPC135,{
+#: npc/009-2/nicholas.txt:1
+#, no-c-format
+msgid "Nicholas"
+msgstr ""
+
+#. code: 002-1,46,108,0 script Nickos NPC123,{
+#: npc/002-1/nickos.txt:0
+#, no-c-format
+msgid "Nickos"
+msgstr ""
+
+#. code: 026-2,33,29,0 script Nigel NPC312,{
+#: npc/026-2/testnpcs.txt:49
+#, no-c-format
+msgid "Nigel"
+msgstr ""
+
+#. code: 048-2,98,106,0 script Nikolai NPC362,{
+#: npc/048-2/sageNikolai.txt:1
+#, no-c-format
+msgid "Nikolai"
+msgstr ""
+
+#. code: 002-1,60,41,0 script Nina the Traveler NPC103,{
+#: npc/002-1/traveler.txt:1
+#, no-c-format
+msgid "Nina the Traveler"
+msgstr ""
+
+#. code: 031-1,99,109,0 script Nivalis Dock NPC400,2,1,{
+#: npc/031-1/dock.txt:14
+#, no-c-format
+msgid "Nivalis Dock"
+msgstr ""
+
+#. code: 031-1,110,108,0 script Nivalis Koga NPC395,12,2,{
+#: npc/031-1/dock.txt:1
+#, no-c-format
+msgid "Nivalis Koga"
+msgstr ""
+
+#. code: menuaction(l("No")));
+#: npc/functions/main.txt~:216
+#: npc/functions/main.txt:216
+#, no-c-format
+msgid "No"
+msgstr ""
+
+#. code: Name: "NohMask"
+#: item_db.conf:-1
+#, no-c-format
+msgid "NohMask"
+msgstr ""
+
+#. code: 009-2,54,49,0 script Note#bar NPC400,{
+#: npc/009-2/misc.txt:1
+#, no-c-format
+msgid "Note#bar"
+msgstr ""
+
+#. code: 056-2,29,30,0 script Note#mirak NPC400,{
+#: npc/056-2/notes.txt:7
+#, no-c-format
+msgid "Note#mirak"
+msgstr ""
+
+#. code: 013-2,30,32,0 script Note#wiz NPC400,{
+#: npc/013-2/notes.txt:7
+#, no-c-format
+msgid "Note#wiz"
+msgstr ""
+
+#. code: 009-2,147,65,0 script Nurse NPC119,{
+#: npc/009-2/nurse.txt:2
+#, no-c-format
+msgid "Nurse"
+msgstr ""
+
+#. code: Name: "NutcrackerHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "NutcrackerHat"
+msgstr ""
+
+#. code: 029-2,26,120,6 script Nyle NPC101,{
+#: npc/029-2/nyle.txt:1
+#, no-c-format
+msgid "Nyle"
+msgstr ""
+
+#. code: 009-2,63,79,0 script Olana NPC190,{
+#: npc/009-2/olana.txt:1
+#, no-c-format
+msgid "Olana"
+msgstr ""
+
+#. code: 004-5,89,67,0 script Old Chest#crastur NPC111,{
+#: npc/004-5/chest.txt:0
+#, no-c-format
+msgid "Old Chest#crastur"
+msgstr ""
+
+#. code: 009-1,85,51,0 script Old Man NPC159,{
+#: npc/009-1/old_man.txt:1
+#, no-c-format
+msgid "Old Man"
+msgstr ""
+
+#. code: 013-2,66,39,0 script Old Wizard#_W NPC116,{
+#: npc/013-2/wizard.txt:0
+#, no-c-format
+msgid "Old Wizard#_W"
+msgstr ""
+
+#. code: 009-1,29,43,0 script Old Woman NPC154,{
+#: npc/009-1/old_woman.txt:1
+#, no-c-format
+msgid "Old Woman"
+msgstr ""
+
+#. code: 002-2,117,126,0 script Omar NPC162,{
+#: npc/002-2/omar.txt:21
+#, no-c-format
+msgid "Omar"
+msgstr ""
+
+#. code: 002-2,26,27,0 script Ontas NPC154,{
+#: npc/002-2/bakery.txt:142
+#, no-c-format
+msgid "Ontas"
+msgstr ""
+
+#. code: Name: "OpenPresentBox"
+#: item_db.conf:-1
+#, no-c-format
+msgid "OpenPresentBox"
+msgstr ""
+
+#. code: Name: "OperaMask"
+#: item_db.conf:-1
+#, no-c-format
+msgid "OperaMask"
+msgstr ""
+
+#. code: Name: "Orange"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Orange"
+msgstr ""
+
+#. code: Name: "OrangeBeret"
+#: item_db.conf:-1
+#, no-c-format
+msgid "OrangeBeret"
+msgstr ""
+
+#. code: Name: "OrangeBowlerHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "OrangeBowlerHat"
+msgstr ""
+
+#. code: Name: "OrangeBowlerHatBrown"
+#: item_db.conf:-1
+#, no-c-format
+msgid "OrangeBowlerHatBrown"
+msgstr ""
+
+#. code: Name: "OrangeCake"
+#: item_db.conf:-1
+#, no-c-format
+msgid "OrangeCake"
+msgstr ""
+
+#. code: Name: "OrangeContributor"
+#: item_db.conf:-1
+#, no-c-format
+msgid "OrangeContributor"
+msgstr ""
+
+#. code: Name: "OrangeCottonBoots"
+#: item_db.conf:-1
+#, no-c-format
+msgid "OrangeCottonBoots"
+msgstr ""
+
+#. code: Name: "OrangeCottonCloth"
+#: item_db.conf:-1
+#, no-c-format
+msgid "OrangeCottonCloth"
+msgstr ""
+
+#. code: Name: "OrangeCottonGloves"
+#: item_db.conf:-1
+#, no-c-format
+msgid "OrangeCottonGloves"
+msgstr ""
+
+#. code: Name: "OrangeCottonHeadband"
+#: item_db.conf:-1
+#, no-c-format
+msgid "OrangeCottonHeadband"
+msgstr ""
+
+#. code: Name: "OrangeCottonShirt"
+#: item_db.conf:-1
+#, no-c-format
+msgid "OrangeCottonShirt"
+msgstr ""
+
+#. code: Name: "OrangeCottonShorts"
+#: item_db.conf:-1
+#, no-c-format
+msgid "OrangeCottonShorts"
+msgstr ""
+
+#. code: Name: "OrangeCottonSkirt"
+#: item_db.conf:-1
+#, no-c-format
+msgid "OrangeCottonSkirt"
+msgstr ""
+
+#. code: Name: "OrangeCottonTrousers"
+#: item_db.conf:-1
+#, no-c-format
+msgid "OrangeCottonTrousers"
+msgstr ""
+
+#. code: Name: "OrangeCupcake"
+#: item_db.conf:-1
+#, no-c-format
+msgid "OrangeCupcake"
+msgstr ""
+
+#. code: Name: "OrangeDesertHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "OrangeDesertHat"
+msgstr ""
+
+#. code: Name: "OrangeDye"
+#: item_db.conf:-1
+#, no-c-format
+msgid "OrangeDye"
+msgstr ""
+
+#. code: Name: "OrangeEggshellHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "OrangeEggshellHat"
+msgstr ""
+
+#. code: Name: "OrangeFineDress"
+#: item_db.conf:-1
+#, no-c-format
+msgid "OrangeFineDress"
+msgstr ""
+
+#. code: Name: "OrangeHint"
+#: item_db.conf:-1
+#, no-c-format
+msgid "OrangeHint"
+msgstr ""
+
+#. code: Name: "OrangeHitchhikersTowel"
+#: item_db.conf:-1
+#, no-c-format
+msgid "OrangeHitchhikersTowel"
+msgstr ""
+
+#. code: Name: "OrangeLollipop"
+#: item_db.conf:-1
+#, no-c-format
+msgid "OrangeLollipop"
+msgstr ""
+
+#. code: Name: "OrangeMiniskirt"
+#: item_db.conf:-1
+#, no-c-format
+msgid "OrangeMiniskirt"
+msgstr ""
+
+#. code: Name: "OrangeRabbitEars"
+#: item_db.conf:-1
+#, no-c-format
+msgid "OrangeRabbitEars"
+msgstr ""
+
+#. code: Name: "OrangeRose"
+#: item_db.conf:-1
+#, no-c-format
+msgid "OrangeRose"
+msgstr ""
+
+#. code: Name: "OrangeRoseHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "OrangeRoseHat"
+msgstr ""
+
+#. code: Name: "OrangeShades"
+#: item_db.conf:-1
+#, no-c-format
+msgid "OrangeShades"
+msgstr ""
+
+#. code: Name: "OrangeShortTankTop"
+#: item_db.conf:-1
+#, no-c-format
+msgid "OrangeShortTankTop"
+msgstr ""
+
+#. code: Name: "OrangeSilkRobe"
+#: item_db.conf:-1
+#, no-c-format
+msgid "OrangeSilkRobe"
+msgstr ""
+
+#. code: Name: "OrangeSorcererBlack"
+#: item_db.conf:-1
+#, no-c-format
+msgid "OrangeSorcererBlack"
+msgstr ""
+
+#. code: Name: "OrangeSorcererDBlue"
+#: item_db.conf:-1
+#, no-c-format
+msgid "OrangeSorcererDBlue"
+msgstr ""
+
+#. code: Name: "OrangeSorcererDGreen"
+#: item_db.conf:-1
+#, no-c-format
+msgid "OrangeSorcererDGreen"
+msgstr ""
+
+#. code: Name: "OrangeSorcererGreen"
+#: item_db.conf:-1
+#, no-c-format
+msgid "OrangeSorcererGreen"
+msgstr ""
+
+#. code: Name: "OrangeSorcererLBlue"
+#: item_db.conf:-1
+#, no-c-format
+msgid "OrangeSorcererLBlue"
+msgstr ""
+
+#. code: Name: "OrangeSorcererOrange"
+#: item_db.conf:-1
+#, no-c-format
+msgid "OrangeSorcererOrange"
+msgstr ""
+
+#. code: Name: "OrangeSorcererPink"
+#: item_db.conf:-1
+#, no-c-format
+msgid "OrangeSorcererPink"
+msgstr ""
+
+#. code: Name: "OrangeSorcererPurple"
+#: item_db.conf:-1
+#, no-c-format
+msgid "OrangeSorcererPurple"
+msgstr ""
+
+#. code: Name: "OrangeSorcererRed"
+#: item_db.conf:-1
+#, no-c-format
+msgid "OrangeSorcererRed"
+msgstr ""
+
+#. code: Name: "OrangeSorcererWhite"
+#: item_db.conf:-1
+#, no-c-format
+msgid "OrangeSorcererWhite"
+msgstr ""
+
+#. code: Name: "OrangeSorcererYellow"
+#: item_db.conf:-1
+#, no-c-format
+msgid "OrangeSorcererYellow"
+msgstr ""
+
+#. code: Name: "OrangeSummonFlower"
+#: item_db.conf:-1
+#, no-c-format
+msgid "OrangeSummonFlower"
+msgstr ""
+
+#. code: Name: "OrangeTankTop"
+#: item_db.conf:-1
+#, no-c-format
+msgid "OrangeTankTop"
+msgstr ""
+
+#. code: Name: "OrangeTulip"
+#: item_db.conf:-1
+#, no-c-format
+msgid "OrangeTulip"
+msgstr ""
+
+#. code: Name: "OrangeTurtleneck"
+#: item_db.conf:-1
+#, no-c-format
+msgid "OrangeTurtleneck"
+msgstr ""
+
+#. code: Name: "OrangeVNeckSweater"
+#: item_db.conf:-1
+#, no-c-format
+msgid "OrangeVNeckSweater"
+msgstr ""
+
+#. code: Name: "OrangeWizardHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "OrangeWizardHat"
+msgstr ""
+
+#. code: Name: "OrchidBra"
+#: item_db.conf:-1
+#, no-c-format
+msgid "OrchidBra"
+msgstr ""
+
+#. code: 017-4,211,32,0 script Orum NPC158,{
+#: npc/017-4/orum.txt:1
+#, no-c-format
+msgid "Orum"
+msgstr ""
+
+#. code: 009-4,37,115,0 script Orum#barrier NPC158,{
+#: npc/009-4/orum.txt:31
+#, no-c-format
+msgid "Orum#barrier"
+msgstr ""
+
+#. code: 009-4,120,43,0 script Orum#trap NPC158,{
+#: npc/009-4/waric.txt:12
+#, no-c-format
+msgid "Orum#trap"
+msgstr ""
+
+#. code: 030-3,100,49,0 script Orum's Homunculus NPC385,{
+#: npc/030-3/orum_homunculus.txt:155
+#, no-c-format
+msgid "Orum's Homunculus"
+msgstr ""
+
+#. code: 009-4,35,115,0 script OrumDebug NPC158,{
+#: npc/009-4/orum.txt:1
+#, no-c-format
+msgid "OrumDebug"
+msgstr ""
+
+#. code: 011-1,94,38,0 script Oscar NPC142,{
+#: npc/011-1/oscar.txt:15
+#, no-c-format
+msgid "Oscar"
+msgstr ""
+
+#. code: 048-2,146,26,0 script Oskari NPC134,{
+#: npc/048-2/helperChief.txt:1
+#, no-c-format
+msgid "Oskari"
+msgstr ""
+
+#. code: 030-2,37,77,0 script Osmo NPC328,{
+#: npc/030-2/bedding_helper.txt:1
+#, no-c-format
+msgid "Osmo"
+msgstr ""
+
+#. code: 030-2,37,81,0 script Oswal NPC328,{
+#: npc/030-2/basic_npcs.txt:2
+#, no-c-format
+msgid "Oswal"
+msgstr ""
+
+#. code: Name: "OverlordsHelmet"
+#: item_db.conf:-1
+#, no-c-format
+msgid "OverlordsHelmet"
+msgstr ""
+
+#. code: Name: "PVPCap"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PVPCap"
+msgstr ""
+
+#. code: Name: "PVPCoin"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PVPCoin"
+msgstr ""
+
+#. code: 006-1,24,113,0 script Pachua NPC143,{
+#: npc/006-1/pachua.txt:0
+#, no-c-format
+msgid "Pachua"
+msgstr ""
+
+#. code: Name: "PaladinsHelmet"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PaladinsHelmet"
+msgstr ""
+
+#. code: Name: "PanHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PanHat"
+msgstr ""
+
+#. code: Name: "PaperBag"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PaperBag"
+msgstr ""
+
+#. code: 048-2,28,30,0 script Parcival NPC153,{
+#: npc/048-2/visitors.txt:12
+#, no-c-format
+msgid "Parcival"
+msgstr ""
+
+#. code: 029-3,50,25,0 script Parua NPC183,{
+#: npc/029-3/parua.txt~:0
+#: npc/029-3/parua.txt:0
+#, no-c-format
+msgid "Parua"
+msgstr ""
+
+#. code: 001-2,77,78,0 script Pauline NPC208,{
+#: npc/001-2/pauline.txt:1
+#, no-c-format
+msgid "Pauline"
+msgstr ""
+
+#. code: 001-2,79,74,0 script PaulineDebug NPC208,{
+#: npc/001-2/pauline.txt:267
+#, no-c-format
+msgid "PaulineDebug"
+msgstr ""
+
+#. code: Name: "Pear"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Pear"
+msgstr ""
+
+#. code: Name: "Pearl"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Pearl"
+msgstr ""
+
+#. code: 048-2,25,135,0 script Peetu NPC130,{
+#: npc/048-2/helperAccused.txt:1
+#, no-c-format
+msgid "Peetu"
+msgstr ""
+
+#. code: 009-2,183,57,0 script Peter NPC157,{
+#: npc/009-2/peter.txt:2
+#, no-c-format
+msgid "Peter"
+msgstr ""
+
+#. code: 002-2,75,56,0 script Phaet NPC125,0,0,{
+#: npc/002-2/phaet.txt:1
+#, no-c-format
+msgid "Phaet"
+msgstr ""
+
+#. code: 001-3,77,37,0 script Phaet#arena NPC125,{
+#: npc/001-3/guards.txt:0
+#, no-c-format
+msgid "Phaet#arena"
+msgstr ""
+
+#. code: 010-2,40,35,0 script Phil NPC157,{
+#: npc/010-2/band.txt:0
+#, no-c-format
+msgid "Phil"
+msgstr ""
+
+#. code: Name: "Phylactery"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Phylactery"
+msgstr ""
+
+#. code: Name: "PickledBeets"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PickledBeets"
+msgstr ""
+
+#. code: Name: "PileOfAsh"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PileOfAsh"
+msgstr ""
+
+#. code: Name: "PilotHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PilotHat"
+msgstr ""
+
+#. code: Name: "PinkAntenna"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PinkAntenna"
+msgstr ""
+
+#. code: Name: "PinkBeret"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PinkBeret"
+msgstr ""
+
+#. code: Name: "PinkBowlerHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PinkBowlerHat"
+msgstr ""
+
+#. code: Name: "PinkBowlerHatBrown"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PinkBowlerHatBrown"
+msgstr ""
+
+#. code: Name: "PinkChristmasSweater"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PinkChristmasSweater"
+msgstr ""
+
+#. code: Name: "PinkContributor"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PinkContributor"
+msgstr ""
+
+#. code: Name: "PinkCottonBoots"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PinkCottonBoots"
+msgstr ""
+
+#. code: Name: "PinkCottonCloth"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PinkCottonCloth"
+msgstr ""
+
+#. code: Name: "PinkCottonGloves"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PinkCottonGloves"
+msgstr ""
+
+#. code: Name: "PinkCottonHeadband"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PinkCottonHeadband"
+msgstr ""
+
+#. code: Name: "PinkCottonShirt"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PinkCottonShirt"
+msgstr ""
+
+#. code: Name: "PinkCottonShorts"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PinkCottonShorts"
+msgstr ""
+
+#. code: Name: "PinkCottonSkirt"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PinkCottonSkirt"
+msgstr ""
+
+#. code: Name: "PinkCottonTrousers"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PinkCottonTrousers"
+msgstr ""
+
+#. code: Name: "PinkDesertHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PinkDesertHat"
+msgstr ""
+
+#. code: Name: "PinkDye"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PinkDye"
+msgstr ""
+
+#. code: Name: "PinkEasterEgg"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PinkEasterEgg"
+msgstr ""
+
+#. code: Name: "PinkFineDress"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PinkFineDress"
+msgstr ""
+
+#. code: Name: "PinkHitchhikersTowel"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PinkHitchhikersTowel"
+msgstr ""
+
+#. code: Name: "PinkMiniskirt"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PinkMiniskirt"
+msgstr ""
+
+#. code: Name: "PinkPetal"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PinkPetal"
+msgstr ""
+
+#. code: Name: "PinkRabbitEars"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PinkRabbitEars"
+msgstr ""
+
+#. code: Name: "PinkRose"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PinkRose"
+msgstr ""
+
+#. code: Name: "PinkRoseHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PinkRoseHat"
+msgstr ""
+
+#. code: Name: "PinkShades"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PinkShades"
+msgstr ""
+
+#. code: Name: "PinkShortTankTop"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PinkShortTankTop"
+msgstr ""
+
+#. code: Name: "PinkSilkRobe"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PinkSilkRobe"
+msgstr ""
+
+#. code: Name: "PinkSorcererBlack"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PinkSorcererBlack"
+msgstr ""
+
+#. code: Name: "PinkSorcererDBlue"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PinkSorcererDBlue"
+msgstr ""
+
+#. code: Name: "PinkSorcererDGreen"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PinkSorcererDGreen"
+msgstr ""
+
+#. code: Name: "PinkSorcererGreen"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PinkSorcererGreen"
+msgstr ""
+
+#. code: Name: "PinkSorcererLBlue"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PinkSorcererLBlue"
+msgstr ""
+
+#. code: Name: "PinkSorcererOrange"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PinkSorcererOrange"
+msgstr ""
+
+#. code: Name: "PinkSorcererPink"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PinkSorcererPink"
+msgstr ""
+
+#. code: Name: "PinkSorcererPurple"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PinkSorcererPurple"
+msgstr ""
+
+#. code: Name: "PinkSorcererRed"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PinkSorcererRed"
+msgstr ""
+
+#. code: Name: "PinkSorcererWhite"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PinkSorcererWhite"
+msgstr ""
+
+#. code: Name: "PinkSorcererYellow"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PinkSorcererYellow"
+msgstr ""
+
+#. code: Name: "PinkTankTop"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PinkTankTop"
+msgstr ""
+
+#. code: Name: "PinkTicket"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PinkTicket"
+msgstr ""
+
+#. code: Name: "PinkTulip"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PinkTulip"
+msgstr ""
+
+#. code: Name: "PinkTurtleneck"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PinkTurtleneck"
+msgstr ""
+
+#. code: Name: "PinkVNeckSweater"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PinkVNeckSweater"
+msgstr ""
+
+#. code: Name: "PinkWizardHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PinkWizardHat"
+msgstr ""
+
+#. code: Name: "PinkieHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PinkieHat"
+msgstr ""
+
+#. code: Name: "PinkieHelmet"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PinkieHelmet"
+msgstr ""
+
+#. code: Name: "Piou Egg"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Piou Egg"
+msgstr ""
+
+#. code: Name: "Pipe"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Pipe"
+msgstr ""
+
+#. code: Name: "PirateHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PirateHat"
+msgstr ""
+
+#. code: Name: "PlatynaRedDress"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PlatynaRedDress"
+msgstr ""
+
+#. code: mes l("Players breaking the following rules may be banned for any length of time (even permanently) or have their characters reset at a GM's discretion:");
+#: npc/functions/game_rules.txt:5
+#, no-c-format
+msgid "Players breaking the following rules may be banned for any length of time (even permanently) or have their characters reset at a GM's discretion:"
+msgstr ""
+
+#. code: mesc l("Please insert your pincode."), 1;
+#: npc/functions/main.txt~:402
+#: npc/functions/main.txt:402
+#, no-c-format
+msgid "Please insert your pincode."
+msgstr ""
+
+#. code: Name: "Plum"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Plum"
+msgstr ""
+
+#. code: Name: "PlushMouboo"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PlushMouboo"
+msgstr ""
+
+#. code: Name: "PointyWitchHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PointyWitchHat"
+msgstr ""
+
+#. code: Name: "PollettEgg"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PollettEgg"
+msgstr ""
+
+#. code: Name: "PoltergeistPowder"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PoltergeistPowder"
+msgstr ""
+
+#. code: 015-3,37,29,0 script Pot NPC400,{
+#: npc/015-3/pot.txt:1
+#, no-c-format
+msgid "Pot"
+msgstr ""
+
+#. code: 009-2,123,22,0 shop Potions#_M NPC400,501:25,502:35,567:250,568:250,750:200
+#: npc/009-2/shops.txt:11
+#, no-c-format
+msgid "Potions#_M"
+msgstr ""
+
+#. code: 020-1,90,79,0 script Present#1 NPC386,{
+#: npc/annuals/tree_beard.txt:13
+#, no-c-format
+msgid "Present#1"
+msgstr ""
+
+#. code: 009-1,54,39,0 script Present#2 NPC386,{
+#: npc/annuals/tree_beard.txt:32
+#, no-c-format
+msgid "Present#2"
+msgstr ""
+
+#. code: 001-1,58,76,0 script Present#3 NPC386,{
+#: npc/annuals/tree_beard.txt:47
+#, no-c-format
+msgid "Present#3"
+msgstr ""
+
+#. code: Name: "PumpkinHelmet"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PumpkinHelmet"
+msgstr ""
+
+#. code: Name: "PumpkinSeeds"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PumpkinSeeds"
+msgstr ""
+
+#. code: Name: "PurificationPotion"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PurificationPotion"
+msgstr ""
+
+#. code: Name: "PurpleBeret"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PurpleBeret"
+msgstr ""
+
+#. code: Name: "PurpleBowlerHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PurpleBowlerHat"
+msgstr ""
+
+#. code: Name: "PurpleBowlerHatBrown"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PurpleBowlerHatBrown"
+msgstr ""
+
+#. code: Name: "PurpleContributor"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PurpleContributor"
+msgstr ""
+
+#. code: Name: "PurpleCottonBoots"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PurpleCottonBoots"
+msgstr ""
+
+#. code: Name: "PurpleCottonCloth"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PurpleCottonCloth"
+msgstr ""
+
+#. code: Name: "PurpleCottonGloves"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PurpleCottonGloves"
+msgstr ""
+
+#. code: Name: "PurpleCottonHeadband"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PurpleCottonHeadband"
+msgstr ""
+
+#. code: Name: "PurpleCottonShirt"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PurpleCottonShirt"
+msgstr ""
+
+#. code: Name: "PurpleCottonShorts"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PurpleCottonShorts"
+msgstr ""
+
+#. code: Name: "PurpleCottonSkirt"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PurpleCottonSkirt"
+msgstr ""
+
+#. code: Name: "PurpleCottonTrousers"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PurpleCottonTrousers"
+msgstr ""
+
+#. code: Name: "PurpleDesertHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PurpleDesertHat"
+msgstr ""
+
+#. code: Name: "PurpleDye"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PurpleDye"
+msgstr ""
+
+#. code: Name: "PurpleFineDress"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PurpleFineDress"
+msgstr ""
+
+#. code: Name: "PurpleHint"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PurpleHint"
+msgstr ""
+
+#. code: Name: "PurpleHitchhikersTowel"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PurpleHitchhikersTowel"
+msgstr ""
+
+#. code: Name: "PurpleMiniskirt"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PurpleMiniskirt"
+msgstr ""
+
+#. code: Name: "PurplePresentBox"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PurplePresentBox"
+msgstr ""
+
+#. code: Name: "PurpleRabbitEars"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PurpleRabbitEars"
+msgstr ""
+
+#. code: Name: "PurpleShades"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PurpleShades"
+msgstr ""
+
+#. code: Name: "PurpleShortTankTop"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PurpleShortTankTop"
+msgstr ""
+
+#. code: Name: "PurpleSilkRobe"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PurpleSilkRobe"
+msgstr ""
+
+#. code: Name: "PurpleSorcererBlack"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PurpleSorcererBlack"
+msgstr ""
+
+#. code: Name: "PurpleSorcererDBlue"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PurpleSorcererDBlue"
+msgstr ""
+
+#. code: Name: "PurpleSorcererDGreen"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PurpleSorcererDGreen"
+msgstr ""
+
+#. code: Name: "PurpleSorcererGreen"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PurpleSorcererGreen"
+msgstr ""
+
+#. code: Name: "PurpleSorcererLBlue"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PurpleSorcererLBlue"
+msgstr ""
+
+#. code: Name: "PurpleSorcererOrange"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PurpleSorcererOrange"
+msgstr ""
+
+#. code: Name: "PurpleSorcererPink"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PurpleSorcererPink"
+msgstr ""
+
+#. code: Name: "PurpleSorcererPurple"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PurpleSorcererPurple"
+msgstr ""
+
+#. code: Name: "PurpleSorcererRed"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PurpleSorcererRed"
+msgstr ""
+
+#. code: Name: "PurpleSorcererWhite"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PurpleSorcererWhite"
+msgstr ""
+
+#. code: Name: "PurpleSorcererYellow"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PurpleSorcererYellow"
+msgstr ""
+
+#. code: Name: "PurpleStripedWrap"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PurpleStripedWrap"
+msgstr ""
+
+#. code: Name: "PurpleSummonFlower"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PurpleSummonFlower"
+msgstr ""
+
+#. code: Name: "PurpleTankTop"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PurpleTankTop"
+msgstr ""
+
+#. code: Name: "PurpleTicket"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PurpleTicket"
+msgstr ""
+
+#. code: Name: "PurpleTulip"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PurpleTulip"
+msgstr ""
+
+#. code: Name: "PurpleTurtleneck"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PurpleTurtleneck"
+msgstr ""
+
+#. code: Name: "PurpleVNeckSweater"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PurpleVNeckSweater"
+msgstr ""
+
+#. code: Name: "PurpleWizardHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PurpleWizardHat"
+msgstr ""
+
+#. code: Name: "PurpleWrap"
+#: item_db.conf:-1
+#, no-c-format
+msgid "PurpleWrap"
+msgstr ""
+
+#. code: 048-2,117,106,0 script Pyry NPC365,{
+#: npc/048-2/helperCleaning1.txt:1
+#, no-c-format
+msgid "Pyry"
+msgstr ""
+
+#. code: Name: "QuillOfBinding"
+#: item_db.conf:-1
+#, no-c-format
+msgid "QuillOfBinding"
+msgstr ""
+
+#. code: 001-1,56,103,0 script RIP#1 NPC400,{
+#: npc/001-1/tombstones.txt:1
+#, no-c-format
+msgid "RIP#1"
+msgstr ""
+
+#. code: 001-1,60,106,0 script RIP#10 NPC400,{
+#: npc/001-1/tombstones.txt:60
+#, no-c-format
+msgid "RIP#10"
+msgstr ""
+
+#. code: 001-1,57,103,0 script RIP#2 NPC400,{
+#: npc/001-1/tombstones.txt:8
+#, no-c-format
+msgid "RIP#2"
+msgstr ""
+
+#. code: 001-1,58,103,0 script RIP#3 NPC400,{
+#: npc/001-1/tombstones.txt:15
+#, no-c-format
+msgid "RIP#3"
+msgstr ""
+
+#. code: 001-1,59,103,0 script RIP#4 NPC400,{
+#: npc/001-1/tombstones.txt:22
+#, no-c-format
+msgid "RIP#4"
+msgstr ""
+
+#. code: 001-1,60,103,0 script RIP#5 NPC400,{
+#: npc/001-1/tombstones.txt:29
+#, no-c-format
+msgid "RIP#5"
+msgstr ""
+
+#. code: 001-1,56,106,0 script RIP#6 NPC400,{
+#: npc/001-1/tombstones.txt:35
+#, no-c-format
+msgid "RIP#6"
+msgstr ""
+
+#. code: 001-1,57,106,0 script RIP#7 NPC400,{
+#: npc/001-1/tombstones.txt:42
+#, no-c-format
+msgid "RIP#7"
+msgstr ""
+
+#. code: 001-1,58,106,0 script RIP#8 NPC400,{
+#: npc/001-1/tombstones.txt:48
+#, no-c-format
+msgid "RIP#8"
+msgstr ""
+
+#. code: 001-1,59,106,0 script RIP#9 NPC400,{
+#: npc/001-1/tombstones.txt:54
+#, no-c-format
+msgid "RIP#9"
+msgstr ""
+
+#. code: Name: "RabbitEars"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RabbitEars"
+msgstr ""
+
+#. code: Name: "RaggedShorts"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RaggedShorts"
+msgstr ""
+
+#. code: Name: "RangerHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RangerHat"
+msgstr ""
+
+#. code: 029-1,28,52,0 script Rasin NPC263,{
+#: npc/029-1/hideandseek.txt:285
+#, no-c-format
+msgid "Rasin"
+msgstr ""
+
+#. code: 011-1,117,77,0 script Rauk NPC103,{
+#: npc/011-1/alchemist.txt:0
+#, no-c-format
+msgid "Rauk"
+msgstr ""
+
+#. code: Name: "RawAir"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RawAir"
+msgstr ""
+
+#. code: Name: "RawLog"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RawLog"
+msgstr ""
+
+#. code: Name: "RawTalisman"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RawTalisman"
+msgstr ""
+
+#. code: Name: "ReadingGlasses"
+#: item_db.conf:-1
+#, no-c-format
+msgid "ReadingGlasses"
+msgstr ""
+
+#. code: Name: "RealisticBrain"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RealisticBrain"
+msgstr ""
+
+#. code: 006-2,81,36,0 shop Reathe NPC179,1215:125,654:2500,721:25000,722:15000
+#: npc/006-2/shops.txt:0
+#, no-c-format
+msgid "Reathe"
+msgstr ""
+
+#. code: 002-2,44,27,0 script Rebecca NPC118,{
+#: npc/002-2/rebecca.txt:1
+#, no-c-format
+msgid "Rebecca"
+msgstr ""
+
+#. code: 009-2,50,48,0 script Receptionist#inn NPC108,{
+#: npc/009-2/shops.txt:2
+#, no-c-format
+msgid "Receptionist#inn"
+msgstr ""
+
+#. code: 018-2,50,24,0 script Receptionist#mine NPC108,{
+#: npc/018-2/receptionist.txt:1
+#, no-c-format
+msgid "Receptionist#mine"
+msgstr ""
+
+#. code: Name: "RedApple"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RedApple"
+msgstr ""
+
+#. code: Name: "RedBeret"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RedBeret"
+msgstr ""
+
+#. code: Name: "RedBowlerHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RedBowlerHat"
+msgstr ""
+
+#. code: Name: "RedBowlerHatBrown"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RedBowlerHatBrown"
+msgstr ""
+
+#. code: Name: "RedChristmasStocking"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RedChristmasStocking"
+msgstr ""
+
+#. code: Name: "RedContributor"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RedContributor"
+msgstr ""
+
+#. code: Name: "RedCottonBoots"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RedCottonBoots"
+msgstr ""
+
+#. code: Name: "RedCottonCloth"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RedCottonCloth"
+msgstr ""
+
+#. code: Name: "RedCottonGloves"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RedCottonGloves"
+msgstr ""
+
+#. code: Name: "RedCottonHeadband"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RedCottonHeadband"
+msgstr ""
+
+#. code: Name: "RedCottonShirt"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RedCottonShirt"
+msgstr ""
+
+#. code: Name: "RedCottonShorts"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RedCottonShorts"
+msgstr ""
+
+#. code: Name: "RedCottonSkirt"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RedCottonSkirt"
+msgstr ""
+
+#. code: Name: "RedCottonTrousers"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RedCottonTrousers"
+msgstr ""
+
+#. code: Name: "RedDesertHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RedDesertHat"
+msgstr ""
+
+#. code: Name: "RedDottedWrap"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RedDottedWrap"
+msgstr ""
+
+#. code: Name: "RedDye"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RedDye"
+msgstr ""
+
+#. code: Name: "RedEasterEgg"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RedEasterEgg"
+msgstr ""
+
+#. code: Name: "RedEggshellHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RedEggshellHat"
+msgstr ""
+
+#. code: Name: "RedFineDress"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RedFineDress"
+msgstr ""
+
+#. code: Name: "RedGoldenStripedWrap"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RedGoldenStripedWrap"
+msgstr ""
+
+#. code: Name: "RedHint"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RedHint"
+msgstr ""
+
+#. code: Name: "RedHitchhikersTowel"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RedHitchhikersTowel"
+msgstr ""
+
+#. code: Name: "RedMiniskirt"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RedMiniskirt"
+msgstr ""
+
+#. code: Name: "RedNose"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RedNose"
+msgstr ""
+
+#. code: Name: "RedOrnament"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RedOrnament"
+msgstr ""
+
+#. code: Name: "RedPowder"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RedPowder"
+msgstr ""
+
+#. code: Name: "RedPresentHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RedPresentHat"
+msgstr ""
+
+#. code: Name: "RedRabbitEars"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RedRabbitEars"
+msgstr ""
+
+#. code: Name: "RedRose"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RedRose"
+msgstr ""
+
+#. code: Name: "RedRoseHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RedRoseHat"
+msgstr ""
+
+#. code: Name: "RedSaddleRug"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RedSaddleRug"
+msgstr ""
+
+#. code: Name: "RedScorpionStinger"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RedScorpionStinger"
+msgstr ""
+
+#. code: Name: "RedShades"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RedShades"
+msgstr ""
+
+#. code: Name: "RedShortTankTop"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RedShortTankTop"
+msgstr ""
+
+#. code: Name: "RedSilkRobe"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RedSilkRobe"
+msgstr ""
+
+#. code: Name: "RedSorcererBlack"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RedSorcererBlack"
+msgstr ""
+
+#. code: Name: "RedSorcererDBlue"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RedSorcererDBlue"
+msgstr ""
+
+#. code: Name: "RedSorcererDGreen"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RedSorcererDGreen"
+msgstr ""
+
+#. code: Name: "RedSorcererGreen"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RedSorcererGreen"
+msgstr ""
+
+#. code: Name: "RedSorcererLBlue"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RedSorcererLBlue"
+msgstr ""
+
+#. code: Name: "RedSorcererOrange"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RedSorcererOrange"
+msgstr ""
+
+#. code: Name: "RedSorcererPink"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RedSorcererPink"
+msgstr ""
+
+#. code: Name: "RedSorcererPurple"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RedSorcererPurple"
+msgstr ""
+
+#. code: Name: "RedSorcererRed"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RedSorcererRed"
+msgstr ""
+
+#. code: Name: "RedSorcererWhite"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RedSorcererWhite"
+msgstr ""
+
+#. code: Name: "RedSorcererYellow"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RedSorcererYellow"
+msgstr ""
+
+#. code: Name: "RedStockings"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RedStockings"
+msgstr ""
+
+#. code: Name: "RedSummonFlower"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RedSummonFlower"
+msgstr ""
+
+#. code: Name: "RedTankTop"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RedTankTop"
+msgstr ""
+
+#. code: Name: "RedTicket"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RedTicket"
+msgstr ""
+
+#. code: Name: "RedTulip"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RedTulip"
+msgstr ""
+
+#. code: Name: "RedTurtleneck"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RedTurtleneck"
+msgstr ""
+
+#. code: Name: "RedVNeckSweater"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RedVNeckSweater"
+msgstr ""
+
+#. code: Name: "RedWizardHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RedWizardHat"
+msgstr ""
+
+#. code: Name: "ReedBundle"
+#: item_db.conf:-1
+#, no-c-format
+msgid "ReedBundle"
+msgstr ""
+
+#. code: 026-2,35,84,0 script Reid's Ghost NPC315,{
+#: npc/026-2/innkeeper.txt:1
+#, no-c-format
+msgid "Reid's Ghost"
+msgstr ""
+
+#. code: 030-2,140,31,0 script Reino NPC328,{
+#: npc/030-2/wrapping_paper_helper.txt:1
+#, no-c-format
+msgid "Reino"
+msgstr ""
+
+#. code: 006-1,25,95,0 script Rhutan the Traveler NPC103,{
+#: npc/006-1/traveler.txt:1
+#, no-c-format
+msgid "Rhutan the Traveler"
+msgstr ""
+
+#. code: 009-2,20,99,0 script Richard NPC161,{
+#: npc/009-2/richard.txt:1
+#, no-c-format
+msgid "Richard"
+msgstr ""
+
+#. code: 030-2,31,77,0 script Rikhard NPC329,{
+#: npc/030-2/basic_npcs.txt:17
+#, no-c-format
+msgid "Rikhard"
+msgstr ""
+
+#. code: 002-2,21,22,0 script Riskim NPC148,{
+#: npc/002-2/bakery.txt:1
+#, no-c-format
+msgid "Riskim"
+msgstr ""
+
+#. code: Name: "RoastedAcorn"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RoastedAcorn"
+msgstr ""
+
+#. code: Name: "RoastedMaggot"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RoastedMaggot"
+msgstr ""
+
+#. code: 010-2,42,36,0 script Robert NPC162,{
+#: npc/010-2/band.txt:10
+#, no-c-format
+msgid "Robert"
+msgstr ""
+
+#. code: Name: "RockKnife"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RockKnife"
+msgstr ""
+
+#. code: Name: "Root"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Root"
+msgstr ""
+
+#. code: 029-2,99,25,0 shop Rosen NPC311,903:50,904:0,530:8000,1199:2,529:2
+#: npc/029-2/two_arms.txt:1
+#, no-c-format
+msgid "Rosen"
+msgstr ""
+
+#. code: 016-1,32,44,0 script Rossy NPC114,{
+#: npc/016-1/rossy.txt:1
+#, no-c-format
+msgid "Rossy"
+msgstr ""
+
+#. code: Name: "RottenRags"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RottenRags"
+msgstr ""
+
+#. code: 009-7,32,45,0 script Rouge#Duels NPC181,{
+#: npc/009-7/rouge.txt:0
+#, no-c-format
+msgid "Rouge#Duels"
+msgstr ""
+
+#. code: 002-2,69,67,0 script Roulette NPC107,{
+#: npc/002-2/casino.txt:106
+#, no-c-format
+msgid "Roulette"
+msgstr ""
+
+#. code: Name: "RubberBat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RubberBat"
+msgstr ""
+
+#. code: Name: "Ruby"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Ruby"
+msgstr ""
+
+#. code: Name: "RubyPowder"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RubyPowder"
+msgstr ""
+
+#. code: Name: "RubyRing"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RubyRing"
+msgstr ""
+
+#. code: Name: "RunestoneA"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RunestoneA"
+msgstr ""
+
+#. code: Name: "RunestoneL"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RunestoneL"
+msgstr ""
+
+#. code: Name: "RunestoneN"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RunestoneN"
+msgstr ""
+
+#. code: Name: "RunestoneT"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RunestoneT"
+msgstr ""
+
+#. code: Name: "RunestoneW"
+#: item_db.conf:-1
+#, no-c-format
+msgid "RunestoneW"
+msgstr ""
+
+#. code: 001-1,107,42,0 script Ryan NPC104,{
+#: npc/001-1/guards.txt:75
+#, no-c-format
+msgid "Ryan"
+msgstr ""
+
+#. code: 002-2,24,27,0 script Rynoh NPC159,{
+#: npc/002-2/bakery.txt:135
+#, no-c-format
+msgid "Rynoh"
+msgstr ""
+
+#. code: 009-1,88,27,0 script Sabine NPC106,{
+#: npc/009-1/sabine.txt:1
+#, no-c-format
+msgid "Sabine"
+msgstr ""
+
+#. code: Name: "Sabre"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Sabre"
+msgstr ""
+
+#. code: 013-1,131,24,0 script Sagatha#_M NPC167,{
+#: npc/013-1/sagatha.txt~:66
+#: npc/013-1/sagatha.txt:66
+#, no-c-format
+msgid "Sagatha#_M"
+msgstr ""
+
+#. code: Name: "SailorHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "SailorHat"
+msgstr ""
+
+#. code: 002-1,101,114,0 script Samuel NPC132,{
+#: npc/002-1/nomads.txt:1
+#, no-c-format
+msgid "Samuel"
+msgstr ""
+
+#. code: Name: "SandCutter"
+#: item_db.conf:-1
+#, no-c-format
+msgid "SandCutter"
+msgstr ""
+
+#. code: 001-2,98,88,0 script Sandra NPC114,{
+#: npc/001-2/sandra.txt:0
+#, no-c-format
+msgid "Sandra"
+msgstr ""
+
+#. code: 019-1,74,75,0 script Santa's Helper NPC105,{
+#: npc/019-1/santa_helper.txt:1
+#, no-c-format
+msgid "Santa's Helper"
+msgstr ""
+
+#. code: Name: "SantaBeardHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "SantaBeardHat"
+msgstr ""
+
+#. code: Name: "SantaCookie"
+#: item_db.conf:-1
+#, no-c-format
+msgid "SantaCookie"
+msgstr ""
+
+#. code: Name: "SantaHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "SantaHat"
+msgstr ""
+
+#. code: Name: "SantaSnowGlobe"
+#: item_db.conf:-1
+#, no-c-format
+msgid "SantaSnowGlobe"
+msgstr ""
+
+#. code: 048-2,97,78,0 script Santeri NPC366,{
+#: npc/048-2/helperMYetiClaw.txt:1
+#, no-c-format
+msgid "Santeri"
+msgstr ""
+
+#. code: Name: "Sapphire"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Sapphire"
+msgstr ""
+
+#. code: Name: "SapphirePowder"
+#: item_db.conf:-1
+#, no-c-format
+msgid "SapphirePowder"
+msgstr ""
+
+#. code: Name: "SapphireRing"
+#: item_db.conf:-1
+#, no-c-format
+msgid "SapphireRing"
+msgstr ""
+
+#. code: 002-2,28,31,0 script Sara NPC108,{
+#: npc/002-2/bakery.txt:117
+#, no-c-format
+msgid "Sara"
+msgstr ""
+
+#. code: 002-1,93,43,0 script Sarah NPC106,{
+#: npc/002-1/sarah.txt:0
+#, no-c-format
+msgid "Sarah"
+msgstr ""
+
+#. code: 026-2,80,31,0 script Savaric NPC317,{
+#: npc/026-2/lover.txt:1
+#, no-c-format
+msgid "Savaric"
+msgstr ""
+
+#. code: Name: "SaviorArmor"
+#: item_db.conf:-1
+#, no-c-format
+msgid "SaviorArmor"
+msgstr ""
+
+#. code: 013-2,38,20,0 script Saying#wiz NPC400,{
+#: npc/013-2/notes.txt:12
+#, no-c-format
+msgid "Saying#wiz"
+msgstr ""
+
+#. code: Name: "ScarabArmlet"
+#: item_db.conf:-1
+#, no-c-format
+msgid "ScarabArmlet"
+msgstr ""
+
+#. code: 029-1,35,33,0 script Scared Man NPC160,{
+#: npc/029-1/hasan.txt:1
+#, no-c-format
+msgid "Scared Man"
+msgstr ""
+
+#. code: Name: "ScentedCandleHelmet"
+#: item_db.conf:-1
+#, no-c-format
+msgid "ScentedCandleHelmet"
+msgstr ""
+
+#. code: Name: "Scimitar"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Scimitar"
+msgstr ""
+
+#. code: Name: "Scissors"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Scissors"
+msgstr ""
+
+#. code: Name: "Scorpion King"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Scorpion King"
+msgstr ""
+
+#. code: Name: "ScorpionStinger"
+#: item_db.conf:-1
+#, no-c-format
+msgid "ScorpionStinger"
+msgstr ""
+
+#. code: Name: "Scythe"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Scythe"
+msgstr ""
+
+#. code: Name: "SealedSoul"
+#: item_db.conf:-1
+#, no-c-format
+msgid "SealedSoul"
+msgstr ""
+
+#. code: 009-2,32,104,0 script Selim NPC326,{
+#: npc/009-2/selim.txt~:0
+#: npc/009-2/selim.txt:0
+#, no-c-format
+msgid "Selim"
+msgstr ""
+
+#. code: 002-5,43,91,6 script Sema NPC340,{
+#: npc/002-5/sema.txt:0
+#, no-c-format
+msgid "Sema"
+msgstr ""
+
+#. code: Name: "SerfHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "SerfHat"
+msgstr ""
+
+#. code: Name: "Setzer"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Setzer"
+msgstr ""
+
+#. code: 010-2,35,35,0 script Shannon NPC193,{
+#: npc/010-2/dimonds.txt:12
+#, no-c-format
+msgid "Shannon"
+msgstr ""
+
+#. code: Name: "SharpKnife"
+#: item_db.conf:-1
+#, no-c-format
+msgid "SharpKnife"
+msgstr ""
+
+#. code: 055-1,135,60,0 script Sherman the Traveler NPC103,{
+#: npc/055-1/traveler.txt:1
+#, no-c-format
+msgid "Sherman the Traveler"
+msgstr ""
+
+#. code: Name: "ShockSweet"
+#: item_db.conf:-1
+#, no-c-format
+msgid "ShockSweet"
+msgstr ""
+
+#. code: Name: "ShortBow"
+#: item_db.conf:-1
+#, no-c-format
+msgid "ShortBow"
+msgstr ""
+
+#. code: Name: "ShortSword"
+#: item_db.conf:-1
+#, no-c-format
+msgid "ShortSword"
+msgstr ""
+
+#. code: Name: "ShortTankTop"
+#: item_db.conf:-1
+#, no-c-format
+msgid "ShortTankTop"
+msgstr ""
+
+#. code: Name: "ShroomHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "ShroomHat"
+msgstr ""
+
+#. code: 026-1,64,16,0 script Sign NPC400,{
+#: npc/026-1/sign.txt:1
+#, no-c-format
+msgid "Sign"
+msgstr ""
+
+#. code: Name: "SilkCocoon"
+#: item_db.conf:-1
+#, no-c-format
+msgid "SilkCocoon"
+msgstr ""
+
+#. code: Name: "SilkGloves"
+#: item_db.conf:-1
+#, no-c-format
+msgid "SilkGloves"
+msgstr ""
+
+#. code: Name: "SilkHeadband"
+#: item_db.conf:-1
+#, no-c-format
+msgid "SilkHeadband"
+msgstr ""
+
+#. code: Name: "SilkPants"
+#: item_db.conf:-1
+#, no-c-format
+msgid "SilkPants"
+msgstr ""
+
+#. code: Name: "SilkRobe"
+#: item_db.conf:-1
+#, no-c-format
+msgid "SilkRobe"
+msgstr ""
+
+#. code: Name: "SilkSheet"
+#: item_db.conf:-1
+#, no-c-format
+msgid "SilkSheet"
+msgstr ""
+
+#. code: Name: "SilverFourLeafAmulet"
+#: item_db.conf:-1
+#, no-c-format
+msgid "SilverFourLeafAmulet"
+msgstr ""
+
+#. code: Name: "SilverMirror"
+#: item_db.conf:-1
+#, no-c-format
+msgid "SilverMirror"
+msgstr ""
+
+#. code: 002-1,112,48,0 script Silvia NPC207,{
+#: npc/002-1/npcs.txt:10
+#, no-c-format
+msgid "Silvia"
+msgstr ""
+
+#. code: Name: "SimpleRing"
+#: item_db.conf:-1
+#, no-c-format
+msgid "SimpleRing"
+msgstr ""
+
+#. code: Name: "SkeletonCharm"
+#: item_db.conf:-1
+#, no-c-format
+msgid "SkeletonCharm"
+msgstr ""
+
+#. code: Name: "Skull"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Skull"
+msgstr ""
+
+#. code: Name: "SkullMask"
+#: item_db.conf:-1
+#, no-c-format
+msgid "SkullMask"
+msgstr ""
+
+#. code: Name: "SlingBullet"
+#: item_db.conf:-1
+#, no-c-format
+msgid "SlingBullet"
+msgstr ""
+
+#. code: Name: "SlingShot"
+#: item_db.conf:-1
+#, no-c-format
+msgid "SlingShot"
+msgstr ""
+
+#. code: 002-2,84,62,0 script Slots#1 NPC400,{
+#: npc/002-2/casino.txt:17
+#, no-c-format
+msgid "Slots#1"
+msgstr ""
+
+#. code: 002-2,86,62,0 script Slots#2 NPC400,{
+#: npc/002-2/casino.txt:22
+#, no-c-format
+msgid "Slots#2"
+msgstr ""
+
+#. code: 002-2,88,62,0 script Slots#3 NPC400,{
+#: npc/002-2/casino.txt:27
+#, no-c-format
+msgid "Slots#3"
+msgstr ""
+
+#. code: 035-2,34,37,0 script Slots#4 NPC400,{
+#: npc/035-2/casino.txt:0
+#, no-c-format
+msgid "Slots#4"
+msgstr ""
+
+#. code: 035-2,36,37,0 script Slots#5 NPC400,{
+#: npc/035-2/casino.txt:5
+#, no-c-format
+msgid "Slots#5"
+msgstr ""
+
+#. code: 036-2,34,37,0 script Slots#6 NPC400,{
+#: npc/036-2/casino.txt:0
+#, no-c-format
+msgid "Slots#6"
+msgstr ""
+
+#. code: 036-2,36,37,0 script Slots#7 NPC400,{
+#: npc/036-2/casino.txt:5
+#, no-c-format
+msgid "Slots#7"
+msgstr ""
+
+#. code: Name: "SlowPoisonPotion"
+#: item_db.conf:-1
+#, no-c-format
+msgid "SlowPoisonPotion"
+msgstr ""
+
+#. code: 030-3,27,24,0 script SmallCrack#XmasPassage NPC400,0,1,{
+#: npc/annuals/xmas/barriers.txt:66
+#, no-c-format
+msgid "SmallCrack#XmasPassage"
+msgstr ""
+
+#. code: Name: "SmallHealingPotion"
+#: item_db.conf:-1
+#, no-c-format
+msgid "SmallHealingPotion"
+msgstr ""
+
+#. code: Name: "SmallManaElixir"
+#: item_db.conf:-1
+#, no-c-format
+msgid "SmallManaElixir"
+msgstr ""
+
+#. code: Name: "SmallMushroom"
+#: item_db.conf:-1
+#, no-c-format
+msgid "SmallMushroom"
+msgstr ""
+
+#. code: Name: "SmileyCap"
+#: item_db.conf:-1
+#, no-c-format
+msgid "SmileyCap"
+msgstr ""
+
+#. code: Name: "SnakeEgg"
+#: item_db.conf:-1
+#, no-c-format
+msgid "SnakeEgg"
+msgstr ""
+
+#. code: Name: "SnakeSkin"
+#: item_db.conf:-1
+#, no-c-format
+msgid "SnakeSkin"
+msgstr ""
+
+#. code: Name: "SnakeTongue"
+#: item_db.conf:-1
+#, no-c-format
+msgid "SnakeTongue"
+msgstr ""
+
+#. code: Name: "Snapple"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Snapple"
+msgstr ""
+
+#. code: 051-3,29,94,0 script Sneaky Bandit NPC32767,{
+#: npc/051-3/ambush.txt:128
+#, no-c-format
+msgid "Sneaky Bandit"
+msgstr ""
+
+#. code: Name: "SnowGoggles"
+#: item_db.conf:-1
+#, no-c-format
+msgid "SnowGoggles"
+msgstr ""
+
+#. code: Name: "SnowLauncher"
+#: item_db.conf:-1
+#, no-c-format
+msgid "SnowLauncher"
+msgstr ""
+
+#. code: Name: "Snowball"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Snowball"
+msgstr ""
+
+#. code: 019-1,77,44,0 script Snowman NPC129,{
+#: npc/019-1/snowman.txt:1
+#, no-c-format
+msgid "Snowman"
+msgstr ""
+
+#. code: Name: "SnowmanSnowGlobe"
+#: item_db.conf:-1
+#, no-c-format
+msgid "SnowmanSnowGlobe"
+msgstr ""
+
+#. code: Name: "SorcererBlack"
+#: item_db.conf:-1
+#, no-c-format
+msgid "SorcererBlack"
+msgstr ""
+
+#. code: Name: "SorcererDBlue"
+#: item_db.conf:-1
+#, no-c-format
+msgid "SorcererDBlue"
+msgstr ""
+
+#. code: Name: "SorcererDGreen"
+#: item_db.conf:-1
+#, no-c-format
+msgid "SorcererDGreen"
+msgstr ""
+
+#. code: Name: "SorcererGreen"
+#: item_db.conf:-1
+#, no-c-format
+msgid "SorcererGreen"
+msgstr ""
+
+#. code: Name: "SorcererLBlue"
+#: item_db.conf:-1
+#, no-c-format
+msgid "SorcererLBlue"
+msgstr ""
+
+#. code: Name: "SorcererOrange"
+#: item_db.conf:-1
+#, no-c-format
+msgid "SorcererOrange"
+msgstr ""
+
+#. code: Name: "SorcererPink"
+#: item_db.conf:-1
+#, no-c-format
+msgid "SorcererPink"
+msgstr ""
+
+#. code: Name: "SorcererPurple"
+#: item_db.conf:-1
+#, no-c-format
+msgid "SorcererPurple"
+msgstr ""
+
+#. code: Name: "SorcererRed"
+#: item_db.conf:-1
+#, no-c-format
+msgid "SorcererRed"
+msgstr ""
+
+#. code: Name: "SorcererWhite"
+#: item_db.conf:-1
+#, no-c-format
+msgid "SorcererWhite"
+msgstr ""
+
+#. code: Name: "SorcererYellow"
+#: item_db.conf:-1
+#, no-c-format
+msgid "SorcererYellow"
+msgstr ""
+
+#. code: 029-2,27,27,0 script Sorfina NPC154,0,1,{
+#: npc/029-2/sorfina.txt~:0
+#: npc/029-2/sorfina.txt:0
+#, no-c-format
+msgid "Sorfina"
+msgstr ""
+
+#. code: Name: "Soul"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Soul"
+msgstr ""
+
+#. code: 029-1,39,101,0 script Soul Menhir#candor NPC344,{
+#: npc/029-1/soul-menhir.txt:1
+#, no-c-format
+msgid "Soul Menhir#candor"
+msgstr ""
+
+#. code: 026-1,29,34,0 script Soul Menhir#deadmire NPC351,{
+#: npc/026-1/soul-menhir.txt:1
+#, no-c-format
+msgid "Soul Menhir#deadmire"
+msgstr ""
+
+#. code: 009-1,53,40,0 script Soul Menhir#hurnscald NPC344,{
+#: npc/009-1/soul-menhir.txt:1
+#, no-c-format
+msgid "Soul Menhir#hurnscald"
+msgstr ""
+
+#. code: 020-1,63,89,0 script Soul Menhir#nivalis NPC346,{
+#: npc/020-1/soul-menhir.txt:1
+#, no-c-format
+msgid "Soul Menhir#nivalis"
+msgstr ""
+
+#. code: 002-1,58,60,0 script Soul Menhir#tulimshar NPC345,{
+#: npc/002-1/soul-menhir.txt:1
+#, no-c-format
+msgid "Soul Menhir#tulimshar"
+msgstr ""
+
+#. code: Name: "Spear"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Spear"
+msgstr ""
+
+#. code: Name: "SpectrePowder"
+#: item_db.conf:-1
+#, no-c-format
+msgid "SpectrePowder"
+msgstr ""
+
+#. code: 013-2,25,23,0 script Spell#wiz1 NPC400,{
+#: npc/013-2/notes.txt:29
+#, no-c-format
+msgid "Spell#wiz1"
+msgstr ""
+
+#. code: 013-2,27,24,0 script Spell#wiz2 NPC400,{
+#: npc/013-2/notes.txt:60
+#, no-c-format
+msgid "Spell#wiz2"
+msgstr ""
+
+#. code: 013-2,25,27,0 script Spell#wiz3 NPC400,{
+#: npc/013-2/notes.txt:101
+#, no-c-format
+msgid "Spell#wiz3"
+msgstr ""
+
+#. code: 013-2,27,27,0 script Spell#wiz4 NPC400,{
+#: npc/013-2/notes.txt:130
+#, no-c-format
+msgid "Spell#wiz4"
+msgstr ""
+
+#. code: 013-2,26,28,0 script Spell#wiz5 NPC400,{
+#: npc/013-2/notes.txt:159
+#, no-c-format
+msgid "Spell#wiz5"
+msgstr ""
+
+#. code: 013-2,21,29,0 script Spell#wiz6 NPC400,{
+#: npc/013-2/notes.txt:188
+#, no-c-format
+msgid "Spell#wiz6"
+msgstr ""
+
+#. code: 013-2,28,29,0 script Spell#wiz7 NPC400,{
+#: npc/013-2/notes.txt:197
+#, no-c-format
+msgid "Spell#wiz7"
+msgstr ""
+
+#. code: Name: "SquirrelPelt"
+#: item_db.conf:-1
+#, no-c-format
+msgid "SquirrelPelt"
+msgstr ""
+
+#. code: Name: "StaffOfFire"
+#: item_db.conf:-1
+#, no-c-format
+msgid "StaffOfFire"
+msgstr ""
+
+#. code: Name: "StaffOfIce"
+#: item_db.conf:-1
+#, no-c-format
+msgid "StaffOfIce"
+msgstr ""
+
+#. code: Name: "StaffOfLife"
+#: item_db.conf:-1
+#, no-c-format
+msgid "StaffOfLife"
+msgstr ""
+
+#. code: Name: "StandardHeadband"
+#: item_db.conf:-1
+#, no-c-format
+msgid "StandardHeadband"
+msgstr ""
+
+#. code: Name: "Steak"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Steak"
+msgstr ""
+
+#. code: Name: "SteelShield"
+#: item_db.conf:-1
+#, no-c-format
+msgid "SteelShield"
+msgstr ""
+
+#. code: 002-1,116,93,0 script Stewen NPC123,{
+#: npc/002-1/stewen.txt:0
+#, no-c-format
+msgid "Stewen"
+msgstr ""
+
+#. code: Name: "StickReinboo"
+#: item_db.conf:-1
+#, no-c-format
+msgid "StickReinboo"
+msgstr ""
+
+#. code: 017-9,26,28,0 script Stone Board NPC32767,{
+#: npc/functions/announcements.txt:130
+#, no-c-format
+msgid "Stone Board"
+msgstr ""
+
+#. code: 010-2,71,38,0 script Store Policy#1 NPC400,{
+#: npc/010-2/dimonds.txt:476
+#, no-c-format
+msgid "Store Policy#1"
+msgstr ""
+
+#. code: 010-2,77,38,0 script Store Policy#2 NPC400,{
+#: npc/010-2/dimonds.txt:482
+#, no-c-format
+msgid "Store Policy#2"
+msgstr ""
+
+#. code: 051-1,64,46,0 script Strange Stone NPC400,{
+#: npc/051-1/forest.txt:1
+#, no-c-format
+msgid "Strange Stone"
+msgstr ""
+
+#. code: Name: "StrangeCoin"
+#: item_db.conf:-1
+#, no-c-format
+msgid "StrangeCoin"
+msgstr ""
+
+#. code: 002-2,38,57,0 script Stranger NPC192,{
+#: npc/002-2/stranger.txt:0
+#: npc/002-2/stranger.txt~:0
+#, no-c-format
+msgid "Stranger"
+msgstr ""
+
+#. code: 026-1,49,46,0 script Styx the Traveler NPC103,{
+#: npc/026-1/traveler.txt:1
+#, no-c-format
+msgid "Styx the Traveler"
+msgstr ""
+
+#. code: Name: "SulphurPowder"
+#: item_db.conf:-1
+#, no-c-format
+msgid "SulphurPowder"
+msgstr ""
+
+#. code: Name: "Sunglasses"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Sunglasses"
+msgstr ""
+
+#. code: 002-5,93,37,0 script Supply Chest NPC378,{
+#: npc/002-5/chest.txt:0
+#, no-c-format
+msgid "Supply Chest"
+msgstr ""
+
+#. code: 001-1,75,99,0 script Swezanne NPC206,{
+#: npc/001-1/npcs.txt:53
+#, no-c-format
+msgid "Swezanne"
+msgstr ""
+
+#. code: Name: "Sword"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Sword"
+msgstr ""
+
+#. code: Name: "TMWBirthdayGift"
+#: item_db.conf:-1
+#, no-c-format
+msgid "TMWBirthdayGift"
+msgstr ""
+
+#. code: .@header$=getarg(1, l("TUTORIAL"));
+#: npc/functions/main.txt:112
+#: npc/functions/main.txt~:112
+#, no-c-format
+msgid "TUTORIAL"
+msgstr ""
+
+#. code: 030-2,37,85,0 script Taito NPC328,{
+#: npc/030-2/basic_npcs.txt:11
+#, no-c-format
+msgid "Taito"
+msgstr ""
+
+#. code: 001-2,91,39,0 script Talponian#Female NPC404,{
+#: npc/001-2/manakins.txt:25
+#, no-c-format
+msgid "Talponian#Female"
+msgstr ""
+
+#. code: 001-2,91,44,0 script Talponian#Male NPC405,{
+#: npc/001-2/manakins.txt:30
+#, no-c-format
+msgid "Talponian#Male"
+msgstr ""
+
+#. code: Name: "TamOShanter"
+#: item_db.conf:-1
+#, no-c-format
+msgid "TamOShanter"
+msgstr ""
+
+#. code: 029-2,110,88,0 script Tanisha NPC114,{
+#: npc/029-2/tanisha.txt:1
+#, no-c-format
+msgid "Tanisha"
+msgstr ""
+
+#. code: Name: "TankTop"
+#: item_db.conf:-1
+#, no-c-format
+msgid "TankTop"
+msgstr ""
+
+#. code: 001-2,28,21,0 script Tathin NPC107,{
+#: npc/001-2/tathin.txt:0
+#, no-c-format
+msgid "Tathin"
+msgstr ""
+
+#. code: 020-2,75,28,0 script Taylor NPC137,{
+#: npc/020-2/shops.txt:1
+#, no-c-format
+msgid "Taylor"
+msgstr ""
+
+#. code: Name: "TealEasterEgg"
+#: item_db.conf:-1
+#, no-c-format
+msgid "TealEasterEgg"
+msgstr ""
+
+#. code: Name: "TealHint"
+#: item_db.conf:-1
+#, no-c-format
+msgid "TealHint"
+msgstr ""
+
+#. code: Name: "TealHitchhikersTowel"
+#: item_db.conf:-1
+#, no-c-format
+msgid "TealHitchhikersTowel"
+msgstr ""
+
+#. code: 001-2,34,62,0 script Terranite NPC403,{
+#: npc/001-2/manakins.txt:15
+#, no-c-format
+msgid "Terranite"
+msgstr ""
+
+#. code: 001-2,29,57,0 script Terranite Armor#Female NPC401,{
+#: npc/001-2/manakins.txt:1
+#, no-c-format
+msgid "Terranite Armor#Female"
+msgstr ""
+
+#. code: 001-2,34,57,0 script Terranite Armor#Male NPC402,{
+#: npc/001-2/manakins.txt:8
+#, no-c-format
+msgid "Terranite Armor#Male"
+msgstr ""
+
+#. code: Name: "TerraniteArrow"
+#: item_db.conf:-1
+#, no-c-format
+msgid "TerraniteArrow"
+msgstr ""
+
+#. code: Name: "TerraniteChestArmor"
+#: item_db.conf:-1
+#, no-c-format
+msgid "TerraniteChestArmor"
+msgstr ""
+
+#. code: Name: "TerraniteHead"
+#: item_db.conf:-1
+#, no-c-format
+msgid "TerraniteHead"
+msgstr ""
+
+#. code: Name: "TerraniteHelmet"
+#: item_db.conf:-1
+#, no-c-format
+msgid "TerraniteHelmet"
+msgstr ""
+
+#. code: Name: "TerraniteLegs"
+#: item_db.conf:-1
+#, no-c-format
+msgid "TerraniteLegs"
+msgstr ""
+
+#. code: Name: "TerraniteOre"
+#: item_db.conf:-1
+#, no-c-format
+msgid "TerraniteOre"
+msgstr ""
+
+#. code: 048-2,99,87,0 script Teuvo NPC366,{
+#: npc/048-2/helperBookpages3.txt:1
+#, no-c-format
+msgid "Teuvo"
+msgstr ""
+
+#. code: mesc l("Thanks, @@. We just wanted to be sure it was you.", .@value$[0]);
+#: npc/functions/main.txt~:416
+#: npc/functions/main.txt:416
+#, no-c-format
+msgid "Thanks, @@. We just wanted to be sure it was you."
+msgstr ""
+
+#. code: Name: "The AlizarinPlant"
+#: mob_db.conf:5892
+#, no-c-format
+msgid "The AlizarinPlant"
+msgstr ""
+
+#. code: Name: "The AngryFireGoblin"
+#: mob_db.conf:1211
+#, no-c-format
+msgid "The AngryFireGoblin"
+msgstr ""
+
+#. code: Name: "The AngryGreenSlime"
+#: mob_db.conf:5511
+#, no-c-format
+msgid "The AngryGreenSlime"
+msgstr ""
+
+#. code: Name: "The AngryScorpionMob"
+#: mob_db.conf:651
+#, no-c-format
+msgid "The AngryScorpionMob"
+msgstr ""
+
+#. code: Name: "The AngrySeaSlime"
+#: mob_db.conf:4912
+#, no-c-format
+msgid "The AngrySeaSlime"
+msgstr ""
+
+#. code: Name: "The Anne"
+#: mob_db.conf:2870
+#, no-c-format
+msgid "The Anne"
+msgstr ""
+
+#. code: Name: "The Archant"
+#: mob_db.conf:740
+#, no-c-format
+msgid "The Archant"
+msgstr ""
+
+#. code: Name: "The AzulSlime"
+#: mob_db.conf:1132
+#, no-c-format
+msgid "The AzulSlime"
+msgstr ""
+
+#. code: Name: "The BallLightning"
+#: mob_db.conf:4516
+#, no-c-format
+msgid "The BallLightning"
+msgstr ""
+
+#. code: Name: "The Bandit"
+#: mob_db.conf:783
+#, no-c-format
+msgid "The Bandit"
+msgstr ""
+
+#. code: Name: "The BanditLord"
+#: mob_db.conf:6400
+#, no-c-format
+msgid "The BanditLord"
+msgstr ""
+
+#. code: Name: "The Bat"
+#: mob_db.conf:150
+#, no-c-format
+msgid "The Bat"
+msgstr ""
+
+#. code: Name: "The Bee"
+#: mob_db.conf:575
+#, no-c-format
+msgid "The Bee"
+msgstr ""
+
+#. code: Name: "The BlackScorpionMob"
+#: mob_db.conf:1304
+#, no-c-format
+msgid "The BlackScorpionMob"
+msgstr ""
+
+#. code: Name: "The BlueSlime"
+#: mob_db.conf:6644
+#, no-c-format
+msgid "The BlueSlime"
+msgstr ""
+
+#. code: Name: "The BlueSpark"
+#: mob_db.conf:6438
+#, no-c-format
+msgid "The BlueSpark"
+msgstr ""
+
+#. code: Name: "The Bluepar"
+#: mob_db.conf:1169
+#, no-c-format
+msgid "The Bluepar"
+msgstr ""
+
+#. code: Name: "The Butterfly"
+#: mob_db.conf:612
+#, no-c-format
+msgid "The Butterfly"
+msgstr ""
+
+#. code: Name: "The CandiedSlime"
+#: mob_db.conf:6731
+#, no-c-format
+msgid "The CandiedSlime"
+msgstr ""
+
+#. code: Name: "The CaveMaggot"
+#: mob_db.conf:6009
+#, no-c-format
+msgid "The CaveMaggot"
+msgstr ""
+
+#. code: Name: "The CaveSnake"
+#: mob_db.conf:362
+#, no-c-format
+msgid "The CaveSnake"
+msgstr ""
+
+#. code: Name: "The CloverPatch"
+#: mob_db.conf:5929
+#, no-c-format
+msgid "The CloverPatch"
+msgstr ""
+
+#. code: Name: "The CobaltPlant"
+#: mob_db.conf:5818
+#, no-c-format
+msgid "The CobaltPlant"
+msgstr ""
+
+#. code: Name: "The CopperSlime"
+#: mob_db.conf:6689
+#, no-c-format
+msgid "The CopperSlime"
+msgstr ""
+
+#. code: Name: "The CrotcherScorpionMob"
+#: mob_db.conf:875
+#, no-c-format
+msgid "The CrotcherScorpionMob"
+msgstr ""
+
+#. code: Name: "The DemonicMouboo"
+#: mob_db.conf:4868
+#, no-c-format
+msgid "The DemonicMouboo"
+msgstr ""
+
+#. code: Name: "The DemonicSpirit"
+#: mob_db.conf:5471
+#, no-c-format
+msgid "The DemonicSpirit"
+msgstr ""
+
+#. code: Name: "The DoomGolem"
+#: mob_db.conf:3490
+#, no-c-format
+msgid "The DoomGolem"
+msgstr ""
+
+#. code: Name: "The DreadPirateMarley"
+#: mob_db.conf:2505
+#, no-c-format
+msgid "The DreadPirateMarley"
+msgstr ""
+
+#. code: Name: "The DreadPirateMarleyClone"
+#: mob_db.conf:2545
+#, no-c-format
+msgid "The DreadPirateMarleyClone"
+msgstr ""
+
+#. code: Name: "The DrunkenLadySkeleton"
+#: mob_db.conf:4737
+#, no-c-format
+msgid "The DrunkenLadySkeleton"
+msgstr ""
+
+#. code: Name: "The DrunkenSkeleton"
+#: mob_db.conf:4645
+#, no-c-format
+msgid "The DrunkenSkeleton"
+msgstr ""
+
+#. code: Name: "The EasterFluffy"
+#: mob_db.conf:448
+#, no-c-format
+msgid "The EasterFluffy"
+msgstr ""
+
+#. code: Name: "The Enchanter"
+#: mob_db.conf:3539
+#, no-c-format
+msgid "The Enchanter"
+msgstr ""
+
+#. code: Name: "The EvilMushroom"
+#: mob_db.conf:1436
+#, no-c-format
+msgid "The EvilMushroom"
+msgstr ""
+
+#. code: Name: "The Fallen"
+#: mob_db.conf:1877
+#, no-c-format
+msgid "The Fallen"
+msgstr ""
+
+#. code: Name: "The FeyElement"
+#: mob_db.conf:6510
+#, no-c-format
+msgid "The FeyElement"
+msgstr ""
+
+#. code: Name: "The FireGoblin"
+#: mob_db.conf:105
+#, no-c-format
+msgid "The FireGoblin"
+msgstr ""
+
+#. code: Name: "The FireSkull"
+#: mob_db.conf:1614
+#, no-c-format
+msgid "The FireSkull"
+msgstr ""
+
+#. code: Name: "The Flashmob"
+#: mob_db.conf:3412
+#, no-c-format
+msgid "The Flashmob"
+msgstr ""
+
+#. code: Name: "The Fluffy"
+#: mob_db.conf:320
+#, no-c-format
+msgid "The Fluffy"
+msgstr ""
+
+#. code: Name: "The GambogePlant"
+#: mob_db.conf:5855
+#, no-c-format
+msgid "The GambogePlant"
+msgstr ""
+
+#. code: Name: "The GeneralKrukan"
+#: mob_db.conf:2632
+#, no-c-format
+msgid "The GeneralKrukan"
+msgstr ""
+
+#. code: Name: "The GeneralRazha"
+#: mob_db.conf:2684
+#, no-c-format
+msgid "The GeneralRazha"
+msgstr ""
+
+#. code: Name: "The GeneralTerogan"
+#: mob_db.conf:2732
+#, no-c-format
+msgid "The GeneralTerogan"
+msgstr ""
+
+#. code: Name: "The GiantMaggot"
+#: mob_db.conf:4170
+#, no-c-format
+msgid "The GiantMaggot"
+msgstr ""
+
+#. code: Name: "The GrassSnake"
+#: mob_db.conf:1745
+#, no-c-format
+msgid "The GrassSnake"
+msgstr ""
+
+#. code: Name: "The GreenSlime"
+#: mob_db.conf:6304
+#, no-c-format
+msgid "The GreenSlime"
+msgstr ""
+
+#. code: Name: "The GreenSlimeMother"
+#: mob_db.conf:5056
+#, no-c-format
+msgid "The GreenSlimeMother"
+msgstr ""
+
+#. code: Name: "The Grenadier"
+#: mob_db.conf:2457
+#, no-c-format
+msgid "The Grenadier"
+msgstr ""
+
+#. code: Name: "The Grinchboo"
+#: mob_db.conf:6260
+#, no-c-format
+msgid "The Grinchboo"
+msgstr ""
+
+#. code: Name: "The HouseMaggot"
+#: mob_db.conf:5694
+#, no-c-format
+msgid "The HouseMaggot"
+msgstr ""
+
+#. code: Name: "The HungryFluffy"
+#: mob_db.conf:963
+#, no-c-format
+msgid "The HungryFluffy"
+msgstr ""
+
+#. code: Name: "The HuntsmanSpider"
+#: mob_db.conf:827
+#, no-c-format
+msgid "The HuntsmanSpider"
+msgstr ""
+
+#. code: Name: "The Hyvern"
+#: mob_db.conf:6558
+#, no-c-format
+msgid "The Hyvern"
+msgstr ""
+
+#. code: Name: "The IceElement"
+#: mob_db.conf:2014
+#, no-c-format
+msgid "The IceElement"
+msgstr ""
+
+#. code: Name: "The IceGoblin"
+#: mob_db.conf:694
+#, no-c-format
+msgid "The IceGoblin"
+msgstr ""
+
+#. code: Name: "The IceSkull"
+#: mob_db.conf:2153
+#, no-c-format
+msgid "The IceSkull"
+msgstr ""
+
+#. code: Name: "The JackO"
+#: mob_db.conf:1567
+#, no-c-format
+msgid "The JackO"
+msgstr ""
+
+#. code: Name: "The KageGolem"
+#: mob_db.conf:3370
+#, no-c-format
+msgid "The KageGolem"
+msgstr ""
+
+#. code: Name: "The Koyntety"
+#: mob_db.conf:3451
+#, no-c-format
+msgid "The Koyntety"
+msgstr ""
+
+#. code: Name: "The LadySkeleton"
+#: mob_db.conf:4305
+#, no-c-format
+msgid "The LadySkeleton"
+msgstr ""
+
+#. code: Name: "The Larvern"
+#: mob_db.conf:919
+#, no-c-format
+msgid "The Larvern"
+msgstr ""
+
+#. code: Name: "The LavaSlime"
+#: mob_db.conf:2824
+#, no-c-format
+msgid "The LavaSlime"
+msgstr ""
+
+#. code: Name: "The LesserGhost"
+#: mob_db.conf:3008
+#, no-c-format
+msgid "The LesserGhost"
+msgstr ""
+
+#. code: Name: "The LogHead"
+#: mob_db.conf:406
+#, no-c-format
+msgid "The LogHead"
+msgstr ""
+
+#. code: Name: "The LovelyMaggot"
+#: mob_db.conf:2964
+#, no-c-format
+msgid "The LovelyMaggot"
+msgstr ""
+
+#. code: Name: "The Luvia"
+#: mob_db.conf:2232
+#, no-c-format
+msgid "The Luvia"
+msgstr ""
+
+#. code: Name: "The Maggot"
+#: mob_db.conf:5608
+#, no-c-format
+msgid "The Maggot"
+msgstr ""
+
+#. code: Name: "The ManaBug"
+#: mob_db.conf:196
+#, no-c-format
+msgid "The ManaBug"
+msgstr ""
+
+#. code: Name: "The ManaGhost"
+#: mob_db.conf:5154
+#, no-c-format
+msgid "The ManaGhost"
+msgstr ""
+
+#. code: Name: "The ManaSlayer"
+#: mob_db.conf:3289
+#, no-c-format
+msgid "The ManaSlayer"
+msgstr ""
+
+#. code: Name: "The ManaTyrant"
+#: mob_db.conf:3587
+#, no-c-format
+msgid "The ManaTyrant"
+msgstr ""
+
+#. code: Name: "The MauvePlant"
+#: mob_db.conf:5781
+#, no-c-format
+msgid "The MauvePlant"
+msgstr ""
+
+#. code: Name: "The Moggun"
+#: mob_db.conf:5429
+#, no-c-format
+msgid "The Moggun"
+msgstr ""
+
+#. code: Name: "The Moonshroom"
+#: mob_db.conf:2780
+#, no-c-format
+msgid "The Moonshroom"
+msgstr ""
+
+#. code: Name: "The Mouboo"
+#: mob_db.conf:4215
+#, no-c-format
+msgid "The Mouboo"
+msgstr ""
+
+#. code: Name: "The MountainSnake"
+#: mob_db.conf:1701
+#, no-c-format
+msgid "The MountainSnake"
+msgstr ""
+
+#. code: Name: "The Nutcracker"
+#: mob_db.conf:2315
+#, no-c-format
+msgid "The Nutcracker"
+msgstr ""
+
+#. code: Name: "The PinkFlower"
+#: mob_db.conf:1479
+#, no-c-format
+msgid "The PinkFlower"
+msgstr ""
+
+#. code: Name: "The Pinkie"
+#: mob_db.conf:238
+#, no-c-format
+msgid "The Pinkie"
+msgstr ""
+
+#. code: Name: "The PoisonSkull"
+#: mob_db.conf:1658
+#, no-c-format
+msgid "The PoisonSkull"
+msgstr ""
+
+#. code: Name: "The Pollett"
+#: mob_db.conf:1257
+#, no-c-format
+msgid "The Pollett"
+msgstr ""
+
+#. code: Name: "The Poltergeist"
+#: mob_db.conf:4352
+#, no-c-format
+msgid "The Poltergeist"
+msgstr ""
+
+#. code: Name: "The PsiBrain"
+#: mob_db.conf:2585
+#, no-c-format
+msgid "The PsiBrain"
+msgstr ""
+
+#. code: Name: "The Pumpkin"
+#: mob_db.conf:6054
+#, no-c-format
+msgid "The Pumpkin"
+msgstr ""
+
+#. code: Name: "The Reaper"
+#: mob_db.conf:1970
+#, no-c-format
+msgid "The Reaper"
+msgstr ""
+
+#. code: Name: "The RedBone"
+#: mob_db.conf:4598
+#, no-c-format
+msgid "The RedBone"
+msgstr ""
+
+#. code: Name: "The RedScorpionMob"
+#: mob_db.conf:4125
+#, no-c-format
+msgid "The RedScorpionMob"
+msgstr ""
+
+#. code: Name: "The RedSlime"
+#: mob_db.conf:5247
+#, no-c-format
+msgid "The RedSlime"
+msgstr ""
+
+#. code: Name: "The RedSpark"
+#: mob_db.conf:6474
+#, no-c-format
+msgid "The RedSpark"
+msgstr ""
+
+#. code: Name: "The Reinboo"
+#: mob_db.conf:1049
+#, no-c-format
+msgid "The Reinboo"
+msgstr ""
+
+#. code: Name: "The RudolphSlime"
+#: mob_db.conf:6354
+#, no-c-format
+msgid "The RudolphSlime"
+msgstr ""
+
+#. code: Name: "The SUSAN"
+#: mob_db.conf:2917
+#, no-c-format
+msgid "The SUSAN"
+msgstr ""
+
+#. code: Name: "The SantaSlime"
+#: mob_db.conf:1522
+#, no-c-format
+msgid "The SantaSlime"
+msgstr ""
+
+#. code: Name: "The Santaboo"
+#: mob_db.conf:6781
+#, no-c-format
+msgid "The Santaboo"
+msgstr ""
+
+#. code: Name: "The Sasquatch"
+#: mob_db.conf:3208
+#, no-c-format
+msgid "The Sasquatch"
+msgstr ""
+
+#. code: Name: "The ScorpionMob"
+#: mob_db.conf:5739
+#, no-c-format
+msgid "The ScorpionMob"
+msgstr ""
+
+#. code: Name: "The Scythe"
+#: mob_db.conf:4479
+#, no-c-format
+msgid "The Scythe"
+msgstr ""
+
+#. code: Name: "The SeaSlime"
+#: mob_db.conf:5295
+#, no-c-format
+msgid "The SeaSlime"
+msgstr ""
+
+#. code: Name: "The SeaSlimeMother"
+#: mob_db.conf:4960
+#, no-c-format
+msgid "The SeaSlimeMother"
+msgstr ""
+
+#. code: Name: "The Serqet"
+#: mob_db.conf:6096
+#, no-c-format
+msgid "The Serqet"
+msgstr ""
+
+#. code: Name: "The Silkworm"
+#: mob_db.conf:492
+#, no-c-format
+msgid "The Silkworm"
+msgstr ""
+
+#. code: Name: "The Skeleton"
+#: mob_db.conf:4258
+#, no-c-format
+msgid "The Skeleton"
+msgstr ""
+
+#. code: Name: "The SleepingBandit"
+#: mob_db.conf:1094
+#, no-c-format
+msgid "The SleepingBandit"
+msgstr ""
+
+#. code: Name: "The SlimeBlast"
+#: mob_db.conf:6132
+#, no-c-format
+msgid "The SlimeBlast"
+msgstr ""
+
+#. code: Name: "The Snail"
+#: mob_db.conf:531
+#, no-c-format
+msgid "The Snail"
+msgstr ""
+
+#. code: Name: "The Snake"
+#: mob_db.conf:1347
+#, no-c-format
+msgid "The Snake"
+msgstr ""
+
+#. code: Name: "The SoulEater"
+#: mob_db.conf:4783
+#, no-c-format
+msgid "The SoulEater"
+msgstr ""
+
+#. code: Name: "The SoulSnake"
+#: mob_db.conf:2195
+#, no-c-format
+msgid "The SoulSnake"
+msgstr ""
+
+#. code: Name: "The Spectre"
+#: mob_db.conf:1835
+#, no-c-format
+msgid "The Spectre"
+msgstr ""
+
+#. code: Name: "The Spider"
+#: mob_db.conf:1390
+#, no-c-format
+msgid "The Spider"
+msgstr ""
+
+#. code: Name: "The SpikyMushroom"
+#: mob_db.conf:278
+#, no-c-format
+msgid "The SpikyMushroom"
+msgstr ""
+
+#. code: Name: "The Squirrel"
+#: mob_db.conf:5964
+#, no-c-format
+msgid "The Squirrel"
+msgstr ""
+
+#. code: Name: "The Stalker"
+#: mob_db.conf:2105
+#, no-c-format
+msgid "The Stalker"
+msgstr ""
+
+#. code: Name: "The Swashbuckler"
+#: mob_db.conf:2409
+#, no-c-format
+msgid "The Swashbuckler"
+msgstr ""
+
+#. code: Name: "The TameScorpionMob"
+#: mob_db.conf:5652
+#, no-c-format
+msgid "The TameScorpionMob"
+msgstr ""
+
+#. code: Name: "The Tengu"
+#: mob_db.conf:3169
+#, no-c-format
+msgid "The Tengu"
+msgstr ""
+
+#. code: Name: "The Terranite"
+#: mob_db.conf:1925
+#, no-c-format
+msgid "The Terranite"
+msgstr ""
+
+#. code: Name: "The TheLost"
+#: mob_db.conf:4553
+#, no-c-format
+msgid "The TheLost"
+msgstr ""
+
+#. code: Name: "The Thug"
+#: mob_db.conf:2361
+#, no-c-format
+msgid "The Thug"
+msgstr ""
+
+#. code: Name: "The TipsySkeleton"
+#: mob_db.conf:4691
+#, no-c-format
+msgid "The TipsySkeleton"
+msgstr ""
+
+#. code: Name: "The Tormenta"
+#: mob_db.conf:3045
+#, no-c-format
+msgid "The Tormenta"
+msgstr ""
+
+#. code: Name: "The Troll"
+#: mob_db.conf:5384
+#, no-c-format
+msgid "The Troll"
+msgstr ""
+
+#. code: Name: "The UndeadTroll"
+#: mob_db.conf:5561
+#, no-c-format
+msgid "The UndeadTroll"
+msgstr ""
+
+#. code: Name: "The UndeadWitch"
+#: mob_db.conf:5010
+#, no-c-format
+msgid "The UndeadWitch"
+msgstr ""
+
+#. code: Name: "The VampireBat"
+#: mob_db.conf:4434
+#, no-c-format
+msgid "The VampireBat"
+msgstr ""
+
+#. code: Name: "The ViciousSquirrel"
+#: mob_db.conf:6214
+#, no-c-format
+msgid "The ViciousSquirrel"
+msgstr ""
+
+#. code: Name: "The Virus"
+#: mob_db.conf:3124
+#, no-c-format
+msgid "The Virus"
+msgstr ""
+
+#. code: Name: "The VoidArchant"
+#: mob_db.conf:3679
+#, no-c-format
+msgid "The VoidArchant"
+msgstr ""
+
+#. code: Name: "The VoidBat"
+#: mob_db.conf:3812
+#, no-c-format
+msgid "The VoidBat"
+msgstr ""
+
+#. code: Name: "The VoidFlower"
+#: mob_db.conf:3636
+#, no-c-format
+msgid "The VoidFlower"
+msgstr ""
+
+#. code: Name: "The VoidMaggot"
+#: mob_db.conf:3859
+#, no-c-format
+msgid "The VoidMaggot"
+msgstr ""
+
+#. code: Name: "The VoidMouboo"
+#: mob_db.conf:3952
+#, no-c-format
+msgid "The VoidMouboo"
+msgstr ""
+
+#. code: Name: "The VoidScorpionMob"
+#: mob_db.conf:3995
+#, no-c-format
+msgid "The VoidScorpionMob"
+msgstr ""
+
+#. code: Name: "The VoidShroom"
+#: mob_db.conf:4038
+#, no-c-format
+msgid "The VoidShroom"
+msgstr ""
+
+#. code: Name: "The VoidSlime"
+#: mob_db.conf:3722
+#, no-c-format
+msgid "The VoidSlime"
+msgstr ""
+
+#. code: Name: "The VoidSnake"
+#: mob_db.conf:3768
+#, no-c-format
+msgid "The VoidSnake"
+msgstr ""
+
+#. code: Name: "The VoidSoldier"
+#: mob_db.conf:3904
+#, no-c-format
+msgid "The VoidSoldier"
+msgstr ""
+
+#. code: Name: "The WhiteBell"
+#: mob_db.conf:6172
+#, no-c-format
+msgid "The WhiteBell"
+msgstr ""
+
+#. code: Name: "The WhiteSlime"
+#: mob_db.conf:1005
+#, no-c-format
+msgid "The WhiteSlime"
+msgstr ""
+
+#. code: Name: "The WickedMushroom"
+#: mob_db.conf:2271
+#, no-c-format
+msgid "The WickedMushroom"
+msgstr ""
+
+#. code: Name: "The Wight"
+#: mob_db.conf:5106
+#, no-c-format
+msgid "The Wight"
+msgstr ""
+
+#. code: Name: "The Wisp"
+#: mob_db.conf:5342
+#, no-c-format
+msgid "The Wisp"
+msgstr ""
+
+#. code: Name: "The WitchGuard"
+#: mob_db.conf:4826
+#, no-c-format
+msgid "The WitchGuard"
+msgstr ""
+
+#. code: Name: "The Wolvern"
+#: mob_db.conf:6601
+#, no-c-format
+msgid "The Wolvern"
+msgstr ""
+
+#. code: Name: "The Xakelbael"
+#: mob_db.conf:4081
+#, no-c-format
+msgid "The Xakelbael"
+msgstr ""
+
+#. code: Name: "The YellowSlime"
+#: mob_db.conf:5200
+#, no-c-format
+msgid "The YellowSlime"
+msgstr ""
+
+#. code: Name: "The Yeti"
+#: mob_db.conf:2059
+#, no-c-format
+msgid "The Yeti"
+msgstr ""
+
+#. code: Name: "The Zombie"
+#: mob_db.conf:1790
+#, no-c-format
+msgid "The Zombie"
+msgstr ""
+
+#. code: mesc l("This error is fatal, we stop execution."), 1;
+#: npc/functions/main.txt~:459
+#: npc/functions/main.txt:459
+#, no-c-format
+msgid "This error is fatal, we stop execution."
+msgstr ""
+
+#. code: 026-1,34,30,0 script Thurstan NPC318,{
+#: npc/026-1/headless_man.txt:1
+#, no-c-format
+msgid "Thurstan"
+msgstr ""
+
+#. code: 027-2,23,105,0 script Thurston NPC302,{
+#: npc/027-2/thurston.txt:1
+#, no-c-format
+msgid "Thurston"
+msgstr ""
+
+#. code: 001-1,69,29,0 script Tinris NPC160,{
+#: npc/001-1/tinris.txt~:0
+#: npc/001-1/tinris.txt:0
+#, no-c-format
+msgid "Tinris"
+msgstr ""
+
+#. code: Name: "TinyHealingPotion"
+#: item_db.conf:-1
+#, no-c-format
+msgid "TinyHealingPotion"
+msgstr ""
+
+#. code: Name: "TinyManaElixir"
+#: item_db.conf:-1
+#, no-c-format
+msgid "TinyManaElixir"
+msgstr ""
+
+#. code: 029-2,112,24,0 shop Toichi NPC377,1201:25,522:50,521:500,523:1000,603:1000
+#: npc/029-2/two_arms.txt:2
+#, no-c-format
+msgid "Toichi"
+msgstr ""
+
+#. code: 001-2,95,79,0 script Tondar NPC168,{
+#: npc/001-2/tondar.txt:1
+#, no-c-format
+msgid "Tondar"
+msgstr ""
+
+#. code: Name: "Tongue"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Tongue"
+msgstr ""
+
+#. code: Name: "TonoriDelight"
+#: item_db.conf:-1
+#, no-c-format
+msgid "TonoriDelight"
+msgstr ""
+
+#. code: Name: "Toothbrush"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Toothbrush"
+msgstr ""
+
+#. code: Name: "TopHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "TopHat"
+msgstr ""
+
+#. code: Name: "Topaz"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Topaz"
+msgstr ""
+
+#. code: Name: "TopazPowder"
+#: item_db.conf:-1
+#, no-c-format
+msgid "TopazPowder"
+msgstr ""
+
+#. code: Name: "TopazRing"
+#: item_db.conf:-1
+#, no-c-format
+msgid "TopazRing"
+msgstr ""
+
+#. code: 009-4,68,21,0 script Torch#1 NPC400,{
+#: npc/009-4/torches.txt:254
+#, no-c-format
+msgid "Torch#1"
+msgstr ""
+
+#. code: 009-4,67,42,0 script Torch#2 NPC400,{
+#: npc/009-4/torches.txt:265
+#, no-c-format
+msgid "Torch#2"
+msgstr ""
+
+#. code: 009-4,33,86,0 script Torch#3 NPC400,{
+#: npc/009-4/torches.txt:276
+#, no-c-format
+msgid "Torch#3"
+msgstr ""
+
+#. code: Name: "Towel"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Towel"
+msgstr ""
+
+#. code: Name: "ToySabre"
+#: item_db.conf:-1
+#, no-c-format
+msgid "ToySabre"
+msgstr ""
+
+#. code: 009-2,29,98,0 script Trader NPC115,{
+#: npc/009-2/trader.txt:1
+#, no-c-format
+msgid "Trader"
+msgstr ""
+
+#. code: Name: "TreasureKey"
+#: item_db.conf:-1
+#, no-c-format
+msgid "TreasureKey"
+msgstr ""
+
+#. code: 002-2,81,21,0 script Troupe Leader NPC165,{
+#: npc/002-2/troupe_leader.txt:1
+#, no-c-format
+msgid "Troupe Leader"
+msgstr ""
+
+#. code: 001-1,68,72,0 script Tulimshar Dock NPC400,2,2,{
+#: npc/001-1/dock.txt:17
+#, no-c-format
+msgid "Tulimshar Dock"
+msgstr ""
+
+#. code: 001-1,75,70,0 script Tulimshar Koga NPC395,9,4,{
+#: npc/001-1/dock.txt:1
+#, no-c-format
+msgid "Tulimshar Koga"
+msgstr ""
+
+#. code: Name: "TurquoiseBra"
+#: item_db.conf:-1
+#, no-c-format
+msgid "TurquoiseBra"
+msgstr ""
+
+#. code: Name: "Turtleneck"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Turtleneck"
+msgstr ""
+
+#. code: 029-2,21,26,0 script TutDebug NPC154,{
+#: npc/029-1/tutorial.txt:10
+#, no-c-format
+msgid "TutDebug"
+msgstr ""
+
+#. code: 026-2,22,120,0 shop Umfrey NPC302,1282:20,1281:500
+#: npc/026-2/gy_inn_shops.txt:28
+#, no-c-format
+msgid "Umfrey"
+msgstr ""
+
+#. code: 027-3,84,89,0 script UndeadDebug3 NPC155,{
+#: npc/functions/undead_debug.txt:82
+#, no-c-format
+msgid "UndeadDebug3"
+msgstr ""
+
+#. code: 027-4,76,79,0 script UndeadDebug4 NPC155,{
+#: npc/functions/undead_debug.txt:92
+#, no-c-format
+msgid "UndeadDebug4"
+msgstr ""
+
+#. code: 027-5,72,26,0 script UndeadDebug5 NPC155,{
+#: npc/functions/undead_debug.txt:102
+#, no-c-format
+msgid "UndeadDebug5"
+msgstr ""
+
+#. code: Name: "UndeadEar"
+#: item_db.conf:-1
+#, no-c-format
+msgid "UndeadEar"
+msgstr ""
+
+#. code: Name: "UndeadEye"
+#: item_db.conf:-1
+#, no-c-format
+msgid "UndeadEye"
+msgstr ""
+
+#. code: Name: "UnderworldKey"
+#: item_db.conf:-1
+#, no-c-format
+msgid "UnderworldKey"
+msgstr ""
+
+#. code: Name: "UnderworldMask"
+#: item_db.conf:-1
+#, no-c-format
+msgid "UnderworldMask"
+msgstr ""
+
+#. code: 030-2,140,41,0 script Urmas NPC328,{
+#: npc/030-2/empty_boxes_helper.txt:1
+#, no-c-format
+msgid "Urmas"
+msgstr ""
+
+#. code: Name: "Urn"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Urn"
+msgstr ""
+
+#. code: mesc l("Use @@ to cancel.", "##B-1##b");
+#: npc/functions/main.txt~:404
+#: npc/functions/main.txt:404
+#, no-c-format
+msgid "Use @@ to cancel."
+msgstr ""
+
+#. code: Name: "VNeckSweater"
+#: item_db.conf:-1
+#, no-c-format
+msgid "VNeckSweater"
+msgstr ""
+
+#. code: 002-2,86,29,0 script Valdo NPC117,{
+#: npc/002-2/casino.txt:11
+#, no-c-format
+msgid "Valdo"
+msgstr ""
+
+#. code: 007-2,36,23,0 script Valia NPC370,{
+#: npc/007-2/witch.txt:2
+#, no-c-format
+msgid "Valia"
+msgstr ""
+
+#. code: 030-2,85,43,0 script Valjas NPC330,{
+#: npc/030-2/guards.txt:1
+#, no-c-format
+msgid "Valjas"
+msgstr ""
+
+#. code: 029-1,72,86,0 script Valon NPC156,{
+#: npc/029-1/valon.txt:56
+#, no-c-format
+msgid "Valon"
+msgstr ""
+
+#. code: 029-1,74,86,0 script ValonDebug NPC156,{
+#: npc/029-1/valon.txt:35
+#, no-c-format
+msgid "ValonDebug"
+msgstr ""
+
+#. code: Name: "VampireBatWing"
+#: item_db.conf:-1
+#, no-c-format
+msgid "VampireBatWing"
+msgstr ""
+
+#. code: Name: "VeganWater"
+#: item_db.conf:-1
+#, no-c-format
+msgid "VeganWater"
+msgstr ""
+
+#. code: 030-2,25,35,0 script Vellamo NPC328,{
+#: npc/030-2/storage_helper.txt:1
+#, no-c-format
+msgid "Vellamo"
+msgstr ""
+
+#. code: 030-2,31,81,0 script Veneri NPC328,{
+#: npc/030-2/glitter_helper.txt:1
+#, no-c-format
+msgid "Veneri"
+msgstr ""
+
+#. code: 030-2,89,23,0 script Verneri NPC334,{
+#: npc/030-2/roasted_acorns_helper.txt:1
+#, no-c-format
+msgid "Verneri"
+msgstr ""
+
+#. code: 029-1,107,110,0 script Vincent NPC113,{
+#: npc/029-1/vincent.txt:20
+#, no-c-format
+msgid "Vincent"
+msgstr ""
+
+#. code: 029-1,108,108,0 script Vincent Debug NPC113,{
+#: npc/029-1/vincent.txt:0
+#, no-c-format
+msgid "Vincent Debug"
+msgstr ""
+
+#. code: 007-1,37,21,0 script Voltain NPC103,{
+#: npc/007-1/voltain.txt:1
+#, no-c-format
+msgid "Voltain"
+msgstr ""
+
+#. code: mesc l("WARNING: If you insert wrong pincode, you'll be disconnected.");
+#: npc/functions/main.txt:403
+#: npc/functions/main.txt~:403
+#, no-c-format
+msgid "WARNING: If you insert wrong pincode, you'll be disconnected."
+msgstr ""
+
+#. code: 010-2,32,34,0 shop Waitress NPC139,519:50,533:55,534:45,562:125,676:100
+#: npc/010-2/dimonds.txt:530
+#, no-c-format
+msgid "Waitress"
+msgstr ""
+
+#. code: Name: "Wand"
+#: item_db.conf:-1
+#, no-c-format
+msgid "Wand"
+msgstr ""
+
+#. code: 017-4,216,36,0 script Waric NPC153,{
+#: npc/017-4/waric.txt:1
+#, no-c-format
+msgid "Waric"
+msgstr ""
+
+#. code: 009-4,118,42,0 script Waric#trap NPC153,{
+#: npc/009-4/waric.txt:20
+#, no-c-format
+msgid "Waric#trap"
+msgstr ""
+
+#. code: Name: "WarlordBoots"
+#: item_db.conf:-1
+#, no-c-format
+msgid "WarlordBoots"
+msgstr ""
+
+#. code: Name: "WarlordHelmet"
+#: item_db.conf:-1
+#, no-c-format
+msgid "WarlordHelmet"
+msgstr ""
+
+#. code: Name: "WarlordPlate"
+#: item_db.conf:-1
+#, no-c-format
+msgid "WarlordPlate"
+msgstr ""
+
+#. code: 056-2,77,34,0 script Warning#mirak NPC400,{
+#: npc/056-2/notes.txt:0
+#, no-c-format
+msgid "Warning#mirak"
+msgstr ""
+
+#. code: Name: "WarpedLog"
+#: item_db.conf:-1
+#, no-c-format
+msgid "WarpedLog"
+msgstr ""
+
+#. code: 009-1,76,33,0 script Water Pump NPC400,{
+#: npc/009-1/water_pump.txt:1
+#, no-c-format
+msgid "Water Pump"
+msgstr ""
+
+#. code: 014-1,31,31,0 script Wedding Officiator NPC164,{
+#: npc/014-1/wedding-officiator.txt~:1
+#: npc/014-1/wedding-officiator.txt:1
+#, no-c-format
+msgid "Wedding Officiator"
+msgstr ""
+
+#. code: Name: "WeddingRing"
+#: item_db.conf:-1
+#, no-c-format
+msgid "WeddingRing"
+msgstr ""
+
+#. code: 001-1,55,25,0 script Weellos NPC103,{
+#: npc/001-1/weellos.txt:0
+#, no-c-format
+msgid "Weellos"
+msgstr ""
+
+#. code: 001-1,48,79,0 script Well NPC400,{
+#: npc/001-1/north_shops.txt:2
+#, no-c-format
+msgid "Well"
+msgstr ""
+
+#. code: Name: "WhiteBellTuber"
+#: item_db.conf:-1
+#, no-c-format
+msgid "WhiteBellTuber"
+msgstr ""
+
+#. code: Name: "WhiteBlanket"
+#: item_db.conf:-1
+#, no-c-format
+msgid "WhiteBlanket"
+msgstr ""
+
+#. code: Name: "WhiteCake"
+#: item_db.conf:-1
+#, no-c-format
+msgid "WhiteCake"
+msgstr ""
+
+#. code: Name: "WhiteCowboyHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "WhiteCowboyHat"
+msgstr ""
+
+#. code: Name: "WhiteEvokersRobeBlue"
+#: item_db.conf:-1
+#, no-c-format
+msgid "WhiteEvokersRobeBlue"
+msgstr ""
+
+#. code: Name: "WhiteFur"
+#: item_db.conf:-1
+#, no-c-format
+msgid "WhiteFur"
+msgstr ""
+
+#. code: Name: "WhiteHitchhikersTowel"
+#: item_db.conf:-1
+#, no-c-format
+msgid "WhiteHitchhikersTowel"
+msgstr ""
+
+#. code: Name: "WhitePresentBox"
+#: item_db.conf:-1
+#, no-c-format
+msgid "WhitePresentBox"
+msgstr ""
+
+#. code: Name: "WhiteRose"
+#: item_db.conf:-1
+#, no-c-format
+msgid "WhiteRose"
+msgstr ""
+
+#. code: Name: "WhiteRoseHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "WhiteRoseHat"
+msgstr ""
+
+#. code: Name: "WhiteSaddleRug"
+#: item_db.conf:-1
+#, no-c-format
+msgid "WhiteSaddleRug"
+msgstr ""
+
+#. code: Name: "WhiteSummonFlower"
+#: item_db.conf:-1
+#, no-c-format
+msgid "WhiteSummonFlower"
+msgstr ""
+
+#. code: Name: "WhiteTulip"
+#: item_db.conf:-1
+#, no-c-format
+msgid "WhiteTulip"
+msgstr ""
+
+#. code: Name: "WhiteWizardRobe"
+#: item_db.conf:-1
+#, no-c-format
+msgid "WhiteWizardRobe"
+msgstr ""
+
+#. code: Name: "WhiteWrap"
+#: item_db.conf:-1
+#, no-c-format
+msgid "WhiteWrap"
+msgstr ""
+
+#. code: Name: "WinterGloves"
+#: item_db.conf:-1
+#, no-c-format
+msgid "WinterGloves"
+msgstr ""
+
+#. code: Name: "WispPowder"
+#: item_db.conf:-1
+#, no-c-format
+msgid "WispPowder"
+msgstr ""
+
+#. code: Name: "WitchDoctorsMask"
+#: item_db.conf:-1
+#, no-c-format
+msgid "WitchDoctorsMask"
+msgstr ""
+
+#. code: Name: "WitchHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "WitchHat"
+msgstr ""
+
+#. code: Name: "WizardHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "WizardHat"
+msgstr ""
+
+#. code: 026-2,30,23,0 script Wolfgang NPC305,{
+#: npc/026-2/werewolf.txt:1
+#, no-c-format
+msgid "Wolfgang"
+msgstr ""
+
+#. code: Name: "WolvernPelt"
+#: item_db.conf:-1
+#, no-c-format
+msgid "WolvernPelt"
+msgstr ""
+
+#. code: Name: "WolvernTooth"
+#: item_db.conf:-1
+#, no-c-format
+msgid "WolvernTooth"
+msgstr ""
+
+#. code: Name: "WoodenShield"
+#: item_db.conf:-1
+#, no-c-format
+msgid "WoodenShield"
+msgstr ""
+
+#. code: Name: "WoodenStaff"
+#: item_db.conf:-1
+#, no-c-format
+msgid "WoodenStaff"
+msgstr ""
+
+#. code: Name: "WraithHorn"
+#: item_db.conf:-1
+#, no-c-format
+msgid "WraithHorn"
+msgstr ""
+
+#. code: Name: "WumpusEgg"
+#: item_db.conf:-1
+#, no-c-format
+msgid "WumpusEgg"
+msgstr ""
+
+#. code: 009-2,121,26,0 script Wyara#_M NPC103,{
+#: npc/009-2/wyara.txt:0
+#, no-c-format
+msgid "Wyara#_M"
+msgstr ""
+
+#. code: Name: "XmasCake"
+#: item_db.conf:-1
+#, no-c-format
+msgid "XmasCake"
+msgstr ""
+
+#. code: Name: "XmasCandyCane"
+#: item_db.conf:-1
+#, no-c-format
+msgid "XmasCandyCane"
+msgstr ""
+
+#. code: 020-1,86,76,0 script XmasDebug#1 NPC105,{
+#: npc/annuals/xmas/debug.txt:169
+#, no-c-format
+msgid "XmasDebug#1"
+msgstr ""
+
+#. code: 030-2,193,62,0 script XmasDebug#2 NPC105,{
+#: npc/annuals/xmas/debug.txt:182
+#, no-c-format
+msgid "XmasDebug#2"
+msgstr ""
+
+#. code: 030-3,26,26,0 script XmasDebug#3 NPC105,{
+#: npc/annuals/xmas/debug.txt:195
+#, no-c-format
+msgid "XmasDebug#3"
+msgstr ""
+
+#. code: 030-4,30,30,0 script XmasDebug#4 NPC111,{
+#: npc/annuals/xmas/debug.txt:208
+#, no-c-format
+msgid "XmasDebug#4"
+msgstr ""
+
+#. code: 019-1,0,0,0 script XmasSpawnCounter#0 NPC400,{
+#: npc/annuals/xmas/mobmanager.txt:54
+#, no-c-format
+msgid "XmasSpawnCounter#0"
+msgstr ""
+
+#. code: 019-3,0,0,0 script XmasSpawnCounter#1 NPC400,{
+#: npc/annuals/xmas/mobmanager.txt:62
+#, no-c-format
+msgid "XmasSpawnCounter#1"
+msgstr ""
+
+#. code: 030-3,0,0,0 script XmasSpawnCounter#2 NPC400,{
+#: npc/annuals/xmas/mobmanager.txt:70
+#, no-c-format
+msgid "XmasSpawnCounter#2"
+msgstr ""
+
+#. code: 019-1,0,0,0 script XmasSpawnManager NPC400,{
+#: npc/annuals/xmas/mobmanager.txt:1
+#, no-c-format
+msgid "XmasSpawnManager"
+msgstr ""
+
+#. code: 009-2,148,47,0 script Yalina NPC209,{
+#: npc/009-2/yalina.txt:0
+#, no-c-format
+msgid "Yalina"
+msgstr ""
+
+#. code: 001-2,31,21,0 script Yanis NPC107,{
+#: npc/001-2/yanis.txt:1
+#, no-c-format
+msgid "Yanis"
+msgstr ""
+
+#. code: Name: "YellowBeret"
+#: item_db.conf:-1
+#, no-c-format
+msgid "YellowBeret"
+msgstr ""
+
+#. code: Name: "YellowBowlerHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "YellowBowlerHat"
+msgstr ""
+
+#. code: Name: "YellowBowlerHatBrown"
+#: item_db.conf:-1
+#, no-c-format
+msgid "YellowBowlerHatBrown"
+msgstr ""
+
+#. code: Name: "YellowContributor"
+#: item_db.conf:-1
+#, no-c-format
+msgid "YellowContributor"
+msgstr ""
+
+#. code: Name: "YellowCottonBoots"
+#: item_db.conf:-1
+#, no-c-format
+msgid "YellowCottonBoots"
+msgstr ""
+
+#. code: Name: "YellowCottonCloth"
+#: item_db.conf:-1
+#, no-c-format
+msgid "YellowCottonCloth"
+msgstr ""
+
+#. code: Name: "YellowCottonGloves"
+#: item_db.conf:-1
+#, no-c-format
+msgid "YellowCottonGloves"
+msgstr ""
+
+#. code: Name: "YellowCottonHeadband"
+#: item_db.conf:-1
+#, no-c-format
+msgid "YellowCottonHeadband"
+msgstr ""
+
+#. code: Name: "YellowCottonShirt"
+#: item_db.conf:-1
+#, no-c-format
+msgid "YellowCottonShirt"
+msgstr ""
+
+#. code: Name: "YellowCottonShorts"
+#: item_db.conf:-1
+#, no-c-format
+msgid "YellowCottonShorts"
+msgstr ""
+
+#. code: Name: "YellowCottonSkirt"
+#: item_db.conf:-1
+#, no-c-format
+msgid "YellowCottonSkirt"
+msgstr ""
+
+#. code: Name: "YellowCottonTrousers"
+#: item_db.conf:-1
+#, no-c-format
+msgid "YellowCottonTrousers"
+msgstr ""
+
+#. code: Name: "YellowDesertHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "YellowDesertHat"
+msgstr ""
+
+#. code: Name: "YellowDottedWrap"
+#: item_db.conf:-1
+#, no-c-format
+msgid "YellowDottedWrap"
+msgstr ""
+
+#. code: Name: "YellowDye"
+#: item_db.conf:-1
+#, no-c-format
+msgid "YellowDye"
+msgstr ""
+
+#. code: Name: "YellowEasterEgg"
+#: item_db.conf:-1
+#, no-c-format
+msgid "YellowEasterEgg"
+msgstr ""
+
+#. code: Name: "YellowEggshellHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "YellowEggshellHat"
+msgstr ""
+
+#. code: Name: "YellowFineDress"
+#: item_db.conf:-1
+#, no-c-format
+msgid "YellowFineDress"
+msgstr ""
+
+#. code: Name: "YellowHint"
+#: item_db.conf:-1
+#, no-c-format
+msgid "YellowHint"
+msgstr ""
+
+#. code: Name: "YellowHitchhikersTowel"
+#: item_db.conf:-1
+#, no-c-format
+msgid "YellowHitchhikersTowel"
+msgstr ""
+
+#. code: Name: "YellowMiniskirt"
+#: item_db.conf:-1
+#, no-c-format
+msgid "YellowMiniskirt"
+msgstr ""
+
+#. code: Name: "YellowOrnament"
+#: item_db.conf:-1
+#, no-c-format
+msgid "YellowOrnament"
+msgstr ""
+
+#. code: Name: "YellowPowder"
+#: item_db.conf:-1
+#, no-c-format
+msgid "YellowPowder"
+msgstr ""
+
+#. code: Name: "YellowPresentBox"
+#: item_db.conf:-1
+#, no-c-format
+msgid "YellowPresentBox"
+msgstr ""
+
+#. code: Name: "YellowPresentHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "YellowPresentHat"
+msgstr ""
+
+#. code: Name: "YellowRabbitEars"
+#: item_db.conf:-1
+#, no-c-format
+msgid "YellowRabbitEars"
+msgstr ""
+
+#. code: Name: "YellowRose"
+#: item_db.conf:-1
+#, no-c-format
+msgid "YellowRose"
+msgstr ""
+
+#. code: Name: "YellowRoseHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "YellowRoseHat"
+msgstr ""
+
+#. code: Name: "YellowShades"
+#: item_db.conf:-1
+#, no-c-format
+msgid "YellowShades"
+msgstr ""
+
+#. code: Name: "YellowShortTankTop"
+#: item_db.conf:-1
+#, no-c-format
+msgid "YellowShortTankTop"
+msgstr ""
+
+#. code: Name: "YellowSilkRobe"
+#: item_db.conf:-1
+#, no-c-format
+msgid "YellowSilkRobe"
+msgstr ""
+
+#. code: Name: "YellowSorcererBlack"
+#: item_db.conf:-1
+#, no-c-format
+msgid "YellowSorcererBlack"
+msgstr ""
+
+#. code: Name: "YellowSorcererDBlue"
+#: item_db.conf:-1
+#, no-c-format
+msgid "YellowSorcererDBlue"
+msgstr ""
+
+#. code: Name: "YellowSorcererDGreen"
+#: item_db.conf:-1
+#, no-c-format
+msgid "YellowSorcererDGreen"
+msgstr ""
+
+#. code: Name: "YellowSorcererGreen"
+#: item_db.conf:-1
+#, no-c-format
+msgid "YellowSorcererGreen"
+msgstr ""
+
+#. code: Name: "YellowSorcererLBlue"
+#: item_db.conf:-1
+#, no-c-format
+msgid "YellowSorcererLBlue"
+msgstr ""
+
+#. code: Name: "YellowSorcererOrange"
+#: item_db.conf:-1
+#, no-c-format
+msgid "YellowSorcererOrange"
+msgstr ""
+
+#. code: Name: "YellowSorcererPink"
+#: item_db.conf:-1
+#, no-c-format
+msgid "YellowSorcererPink"
+msgstr ""
+
+#. code: Name: "YellowSorcererPurple"
+#: item_db.conf:-1
+#, no-c-format
+msgid "YellowSorcererPurple"
+msgstr ""
+
+#. code: Name: "YellowSorcererRed"
+#: item_db.conf:-1
+#, no-c-format
+msgid "YellowSorcererRed"
+msgstr ""
+
+#. code: Name: "YellowSorcererWhite"
+#: item_db.conf:-1
+#, no-c-format
+msgid "YellowSorcererWhite"
+msgstr ""
+
+#. code: Name: "YellowSorcererYellow"
+#: item_db.conf:-1
+#, no-c-format
+msgid "YellowSorcererYellow"
+msgstr ""
+
+#. code: Name: "YellowSummonFlower"
+#: item_db.conf:-1
+#, no-c-format
+msgid "YellowSummonFlower"
+msgstr ""
+
+#. code: Name: "YellowTankTop"
+#: item_db.conf:-1
+#, no-c-format
+msgid "YellowTankTop"
+msgstr ""
+
+#. code: Name: "YellowTicket"
+#: item_db.conf:-1
+#, no-c-format
+msgid "YellowTicket"
+msgstr ""
+
+#. code: Name: "YellowTulip"
+#: item_db.conf:-1
+#, no-c-format
+msgid "YellowTulip"
+msgstr ""
+
+#. code: Name: "YellowTurtleneck"
+#: item_db.conf:-1
+#, no-c-format
+msgid "YellowTurtleneck"
+msgstr ""
+
+#. code: Name: "YellowVNeckSweater"
+#: item_db.conf:-1
+#, no-c-format
+msgid "YellowVNeckSweater"
+msgstr ""
+
+#. code: Name: "YellowWizardHat"
+#: item_db.conf:-1
+#, no-c-format
+msgid "YellowWizardHat"
+msgstr ""
+
+#. code: Name: "YellowWrap"
+#: item_db.conf:-1
+#, no-c-format
+msgid "YellowWrap"
+msgstr ""
+
+#. code: 033-1,66,28,0 script Yerrnk NPC216,{
+#: npc/033-1/yerrnk.txt:0
+#, no-c-format
+msgid "Yerrnk"
+msgstr ""
+
+#. code: return select(menuaction(l("Yes")),
+#: npc/functions/main.txt:215
+#: npc/functions/main.txt~:215
+#, no-c-format
+msgid "Yes"
+msgstr ""
+
+#. code: Name: "YetiClaw"
+#: item_db.conf:-1
+#, no-c-format
+msgid "YetiClaw"
+msgstr ""
+
+#. code: Name: "YetiMask"
+#: item_db.conf:-1
+#, no-c-format
+msgid "YetiMask"
+msgstr ""
+
+#. code: Name: "YetiSkinShirt"
+#: item_db.conf:-1
+#, no-c-format
+msgid "YetiSkinShirt"
+msgstr ""
+
+#. code: 010-2,39,75,0 script Zack NPC155,{
+#: npc/010-2/workers.txt:7
+#, no-c-format
+msgid "Zack"
+msgstr ""
+
+#. code: Name: "ZaxDeKagen"
+#: mob_db.conf:3247
+#, no-c-format
+msgid "ZaxDeKagen"
+msgstr ""
+
+#. code: 029-1,45,85,0 script Zegas NPC165,{
+#: npc/029-1/zegas.txt:0
+#, no-c-format
+msgid "Zegas"
+msgstr ""
+
+#. code: 029-1,47,86,0 script ZegasDebug NPC165,{
+#: npc/029-1/zegas.txt:66
+#, no-c-format
+msgid "ZegasDebug"
+msgstr ""
+
+#. code: 029-2,113,59,0 shop Zitoni NPC103,501:25,502:35,825:50,826:100
+#: npc/029-2/morgan.txt:112
+#, no-c-format
+msgid "Zitoni"
+msgstr ""
+
+#. code: Name: "ZombieNachos"
+#: item_db.conf:-1
+#, no-c-format
+msgid "ZombieNachos"
+msgstr ""
+
+#. code: 055-1,0,0,0 script _N-Pumpkin NPC32767,{
+#: npc/055-1/pumpkins.txt:0
+#, no-c-format
+msgid "_N-Pumpkin"
+msgstr ""
+
+#. code: 012-3,445,61,0 script sign#pvp-1 NPC187,{
+#: npc/012-3/warningsigns.txt:1
+#, no-c-format
+msgid "sign#pvp-1"
+msgstr ""
+
+#. code: 012-3,451,61,0 script sign#pvp-2 NPC186,{
+#: npc/012-3/warningsigns.txt:9
+#, no-c-format
+msgid "sign#pvp-2"
+msgstr ""
+
+#. code: 027-3,0,0,0 script specialMob027-3 NPC32767,{
+#: npc/027-3/monsters.txt:6
+#, no-c-format
+msgid "specialMob027-3"
+msgstr ""
+
+#. code: 027-4,0,0,0 script specialMob027-4 NPC32767,{
+#: npc/027-4/monsters.txt:7
+#, no-c-format
+msgid "specialMob027-4"
+msgstr ""
+
diff --git a/lang/updatelang.py b/lang/updatelang.py
new file mode 100755
index 0000000..aa36823
--- /dev/null
+++ b/lang/updatelang.py
@@ -0,0 +1,399 @@
+#! /usr/bin/env python2.7
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2010-2015 Evol Online
+# Author: Andrei Karas (4144)
+
+import os
+import re
+
+defaultLang = "en"
+filt = re.compile(".+[.]txt", re.IGNORECASE)
+
+allStrings = set()
+strComments = dict()
+strre1 = re.compile("[\t +(]l[(][\"](?P<str>[^\"]+)[\"]")
+strre3 = re.compile("[\t +(]getitemlink[(][\"](?P<str>[^\"]+)[\"][)]")
+strre2 = re.compile("^[^/](.+)([^\t]+)[\t](script|shop|trader|cashshop)[\t](?P<str>[^\t]+)[\t]([\w\d]+),")
+strre4 = re.compile("[\t +(]lg[(][\"](?P<str>[^\"]+)[\"][)]")
+strre5 = re.compile("[\t +(]getitemname[(][\"](?P<str>[^\"]+)[\"][)]")
+strre6 = re.compile("[\t ]mesn[ ][\"](?P<str>[^\"]+)[\"]")
+strre7 = re.compile("[\t +(]lg[(][\"](?P<str1>[^\"]+)[\"],([ ]*)[\"](?P<str2>[^\"]+)[\"]")
+itemsplit = re.compile(",")
+
+langFiles = dict()
+oldLangFiles = dict()
+langs = set()
+itemNamesByName = dict()
+
+def addStr(text, comment, fileName, lineNum, addNoC):
+ text = text.replace("\a", "\"");
+ allStrings.add(text)
+ if comment[-1:] == "\n":
+ comment = comment[:-1]
+ if text not in strComments:
+ strComments[text] = set()
+
+ strComments[text].add("#. code: " + comment.strip() + "\n")
+ strComments[text].add("#: " + fileName + ":" + str(lineNum) + "\n")
+ if addNoC == True:
+ strComments[text].add("#, no-c-format\n")
+
+def collectScriptFileStrings(codeFile, file2):
+ global itemNamesByName
+ with open(file2, "r") as f:
+ cnt = -1
+ for line in f:
+ cnt = cnt + 1
+ line = line.replace("\\\"", "\a");
+ m = strre1.findall(line)
+ if len(m) > 0:
+ for str in m:
+ addStr(str, line, codeFile, cnt, True)
+ m = strre4.findall(line)
+ if len(m) > 0:
+ for str in m:
+ addStr(str + "#0", line, codeFile, cnt, True)
+ addStr(str + "#1", line, codeFile, cnt, True)
+ m = strre2.search(line)
+ if m is not None and m.group("str")[0] != "#":
+ addStr(m.group("str"), line, codeFile, cnt, True)
+ m = strre3.findall(line)
+ if len(m) > 0:
+ for str in m:
+ if str.lower() in itemNamesByName:
+ addStr(itemNamesByName[str.lower()], line, codeFile, cnt, True)
+ m = strre5.findall(line)
+ if len(m) > 0:
+ for str in m:
+ if str.lower() in itemNamesByName:
+ addStr(itemNamesByName[str.lower()], line, codeFile, cnt, True)
+ m = strre6.findall(line)
+ if len(m) > 0:
+ for str in m:
+ addStr(str, line, codeFile, cnt, True)
+ m = strre7.findall(line)
+ if len(m) > 0:
+ for str in m:
+ addStr(str[0] + "#0", line, codeFile, cnt, True)
+ addStr(str[2] + "#1", line, codeFile, cnt, True)
+
+
+def collectScriptStrings(parentDir, relativeDir):
+ files = os.listdir(parentDir)
+ for file1 in files:
+ if file1[0] == ".":
+ continue
+ file2 = os.path.abspath(parentDir + os.path.sep + file1)
+ relativeDir2 = relativeDir + os.path.sep + file1
+ if not os.path.isfile(file2):
+ collectScriptStrings(file2, relativeDir2)
+ elif filt.search(file1):
+ codeFile = relativeDir + os.path.sep + file1
+ collectScriptFileStrings(codeFile, file2)
+
+
+def collectMessages(messagesDir):
+ with open(messagesDir, "r") as r:
+ cnt = -1
+ for line in r:
+ cnt = cnt + 1
+ if line[:2] == "//":
+ continue
+ idx = line.find(": ")
+ if idx < 1:
+ continue
+# msgId = line[:idx]
+ msgStr = line[idx + 2:]
+ if msgStr[-1:] == "\n":
+ msgStr = msgStr[:-1]
+ addStr(msgStr, line, "conf/messages.conf", cnt, False)
+
+def loadFiles(dir):
+ with open(dir + "/langs.txt", "r") as f:
+ for line in f:
+ langs.add(line[:-1])
+
+ for file in langs:
+ langFiles[file] = parseFile(dir + "/lang_" + file + ".txt", True)
+ oldLangFiles[file] = parseFile(dir + "/lang_" + file + ".old", False)
+
+def parseFile(name, readFirstLine):
+ trans = dict()
+ firstLine = None
+ if os.path.exists(name):
+ with open(name, "r") as f:
+ line1 = "";
+ line2 = "";
+ for line in f:
+ if readFirstLine is True and firstLine is None:
+ firstLine = line
+ continue
+
+ if (line == ""):
+ line1 = ""
+ line2 = ""
+ continue
+ elif (line1 == ""):
+ line1 = line[:-1]
+ continue
+
+ line2 = line[:-1]
+ trans[line1] = line2
+ line1 = ""
+ line2 = ""
+ elif readFirstLine:
+ firstLine = "Copyright (C) 2010-2015 Evol Online\n"
+ return (trans, firstLine)
+
+
+def loadPoFiles(podir):
+ files = os.listdir(podir)
+ for name in files:
+ if name[-3:] == ".po":
+ parsePoFile(name[:-3], podir + "/" + name)
+
+
+def parsePoFile(name, path):
+ langFile = langFiles[name][0]
+ with open(path, "r") as f:
+ flag = 0
+ line1 = ""
+ line2 = ""
+ for line in f:
+ if flag == 0:
+ idx = line.find ("msgid ")
+ if idx == 0:
+ line2 = ""
+ line1 = line[len("msgid "):]
+ line1 = line1[1:len(line1) - 2]
+ flag = 1
+ elif flag == 1:
+ idx = line.find ("msgstr ")
+ if idx == 0:
+ line2 = line[len("msgstr "):]
+ line2 = line2[1:len(line2) - 2]
+ flag = 2
+ if line == "\n":
+ if flag == 2:
+ if line1 != "":
+ if line1 in langFile and line2 != "":
+ langFile[line1] = line2.replace("\\\"", "\"");
+ flag = 0
+
+ idx = line.find ("\"")
+ if idx == 0:
+ line = line[1:len(line) - 2]
+ if flag == 1:
+ line1 = line1 + line
+ elif flag == 2:
+ line2 = line2 + line
+
+
+
+def addMissingLines():
+ for trans in langFiles:
+ newFile = langFiles[trans][0]
+ oldFile = oldLangFiles[trans][0]
+ for str in newFile:
+ if str not in allStrings:
+# if newFile[str] != "":
+ oldFile[str] = newFile[str]
+ for str in oldFile:
+ if str in newFile:
+ del newFile[str]
+# print trans + ":moved to old: " + str
+
+ for str in allStrings:
+ for trans in langFiles:
+ newFile = langFiles[trans][0]
+ oldFile = oldLangFiles[trans][0]
+ if str not in newFile:
+# print "lang: " + trans + ", str: " + str
+ if trans == defaultLang:
+# print "newFile[str] = str"
+ newFile[str] = str
+ elif str in oldFile:
+ newFile[str] = oldFile[str]
+# print "newFile[str] = oldFile[str]: " + newFile[str]
+ else:
+# print "newFile[str] = """
+ newFile[str] = ""
+# print trans + ":new string: " + str
+
+
+def sorting():
+ for trans in langFiles:
+ newFile = langFiles[trans]
+ newFile = sortDict (newFile)
+ langFiles[trans] = newFile
+ oldFile = oldLangFiles[trans]
+ oldFile = sortDict (oldFile)
+ oldLangFiles[trans] = oldFile
+
+def sortDict(adict):
+ d2 = []
+ keys = adict[0].keys()
+ keys.sort()
+
+ for key in keys:
+ d2.append ((key, adict[0][key]))
+ return (d2, adict[1])
+
+def saveFiles(langDir, poDir):
+ for trans in langFiles:
+ writeLangFile (langDir + "/lang_" + trans + ".txt", langFiles[trans], trans, False)
+ writeLangFile (langDir + "/lang_" + trans + ".old", oldLangFiles[trans], trans, True)
+ writePoFile (poDir, langFiles[trans], trans)
+
+def removeGenderStr(trLine):
+ if trLine in ("test#0", "test#1", "test1#0", "test1#1", "test2#0", "test2#1",
+ "test1 %s#0", "test1 %s#1", "test2 %s#0", "test2 %s#1",
+ "test1 @@#0", "test1 @@#1", "test2 @@#0", "test2 @@#1"):
+ return trLine
+ return trLine[:-2]
+
+def writeLangFile(langDir, texts, trans, isold):
+ with open (langDir, "w") as f:
+ if texts[1] is not None:
+ f.write(texts[1])
+ for line in texts[0]:
+ if not isold or (line[1] is not None and len(line[1]) > 0):
+ f.write (line[0] + "\n")
+ trLine = line[1]
+ if trans == "en":
+ if len(trLine) > 2 and (trLine[-2:] == "#0" or trLine[-2:] == "#1"):
+ trLine = removeGenderStr(trLine)
+ f.write (trLine + "\n\n")
+
+def writePoComments(w, comments):
+ for line in comments:
+ if line[:3] == "#. ":
+ w.write (line)
+ for line in comments:
+ if line[:3] == "#: ":
+ w.write (line)
+
+ for line in comments:
+ if line[:3] == "#, ":
+ w.write (line)
+ break
+
+def writePoFile(poDir, texts, trans):
+ if trans == "en":
+ langDir = poDir + "/" + trans + ".pot"
+ else:
+ langDir = poDir + "/" + trans + ".po"
+
+ print langDir
+ with open (langDir, "w") as w:
+ w.write ("# " + texts[1] + "")
+ w.write ("#\n\n")
+ w.write ("msgid \"\"\n")
+ w.write ("msgstr \"\"\n")
+ w.write ("\"Project-Id-Version: EvolOnline\\n\"\n")
+ w.write ("\"MIME-Version: 1.0\\n\"\n")
+ w.write ("\"Content-Type: text/plain; charset=UTF-8\\n\"\n")
+ w.write ("\"Content-Transfer-Encoding: 8bit\\n\"\n")
+ w.write ("\n")
+ for line in texts[0]:
+ if line[0] in strComments.keys():
+ writePoComments(w, strComments[line[0]])
+
+ srcLine = line[0]
+ srcLine = srcLine.replace("\\", "\\\\");
+ srcLine = srcLine.replace("\"", "\\\"")
+ w.write ("msgid \"" + srcLine + "\"\n")
+ trLine = line[1]
+ if trans == "en":
+ trLine = ""
+ trLine = trLine.replace("\\", "\\\\");
+ trLine = trLine.replace("\"", "\\\"")
+ w.write ("msgstr \"" + trLine + "\"\n\n")
+
+def stripQuotes(data):
+ if len(data) == 0:
+ return data
+ if data[-1] == "\"":
+ data = data[:-1]
+ if data[0] == "\"":
+ data = data[1:]
+ if data[-1] == "'":
+ data = data[:-1]
+ if data[0] == "'":
+ data = data[1:]
+ return data
+
+def loadItemDb(dir):
+ global itemNamesByName
+ with open(dir + "/item_db.conf", "r") as f:
+ cnt = -1
+ for line in f:
+ line = line.strip()
+
+ idx = line.find("Name: \"")
+ if idx != 0 or line[len(line) - 1] != "\"":
+ continue
+ addStr(line[idx + 7: len(line) - 1], line, "item_db.conf", cnt, True)
+ if line == "{":
+ itemId = ""
+ itemName = ""
+ for line in f:
+ line = line.strip()
+ if len(line) < 1:
+ continue
+ if line[0] == "}":
+ if itemId != "" and itemName != "":
+ itemNamesByName[itemName.lower()] = itemName
+ break
+ if len(line) > 6 and line[:5] == "Name:":
+ itemName = stripQuotes(line[5:].strip())
+ if len(line) > 4 and line[:3] == "Id:":
+ itemId = stripQuotes(line[3:].strip())
+
+def dumpTranslations():
+ for trans in oldLangFiles:
+ print "old lang: " + trans
+ newFile = oldLangFiles[trans][0]
+ for line in newFile:
+ print line
+ if line in newFile:
+ print newFile[line]
+ print "\n"
+ for trans in langFiles:
+ print "new lang: " + trans
+ newFile = langFiles[trans][0]
+ for line in newFile:
+ print line
+ if line in newFile:
+ print newFile[line]
+ print "\n"
+
+
+def loadMobNames(dir):
+ with open(dir + "/mob_db.conf", "r") as r:
+ cnt = -1
+ for line in r:
+ cnt = cnt + 1
+ if len(line) < 1 or line[0:2] == "//":
+ continue
+ line = line.strip()
+ idx = line.find("Name: \"")
+ if idx != 0 or line[len(line) - 1] != "\"":
+ continue
+ addStr(line[idx + 7: len(line) - 1], line, "mob_db.conf", cnt, True)
+
+rootPath = "../../server-data/"
+
+loadItemDb(rootPath + "db/pre-re")
+loadMobNames(rootPath + "db/pre-re")
+collectScriptStrings(rootPath + "/npc", "npc")
+collectScriptFileStrings("db/pre-re/item_db.conf", rootPath + "/db/pre-re/item_db.conf")
+#collectMessages(rootPath + "/conf/messages.conf")
+loadFiles(rootPath + "/langs")
+addMissingLines()
+loadPoFiles("in");
+#dumpTranslations();
+sorting()
+saveFiles(rootPath + "/langs", "out")
+os.rename("out/"+defaultLang+".pot", "serverdata.pot")
diff --git a/lang_client/clientdata-beta.pot b/lang_client/clientdata-beta.pot
new file mode 100644
index 0000000..3448e49
--- /dev/null
+++ b/lang_client/clientdata-beta.pot
@@ -0,0 +1,13 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 2020-12-12 14:45-0300\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+msgid "Translations were moved to transifex.com/arctic-games/tmw/"
+msgstr ""
diff --git a/lang_client/clientdata-dict.pot b/lang_client/clientdata-dict.pot
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/lang_client/clientdata-dict.pot
diff --git a/lang_client/clientdata.pot b/lang_client/clientdata.pot
new file mode 100644
index 0000000..e3da591
--- /dev/null
+++ b/lang_client/clientdata.pot
@@ -0,0 +1,1687 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 2021-04-09 23:21-0300\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. (itstool) path: messages/message
+#: tmp/deadmessages.xml:6 deadmessages.xml:7
+msgid "You are dead."
+msgstr ""
+
+#. (itstool) path: messages/message
+#: tmp/deadmessages.xml:7 deadmessages.xml:8
+msgid "We regret to inform you that your character was killed in battle."
+msgstr ""
+
+#. (itstool) path: messages/message
+#: tmp/deadmessages.xml:8 deadmessages.xml:9
+msgid "You are not that alive anymore."
+msgstr ""
+
+#. (itstool) path: messages/message
+#: tmp/deadmessages.xml:9 deadmessages.xml:10
+msgid "The cold hands of the grim reaper are grabbing for your soul."
+msgstr ""
+
+#. (itstool) path: messages/message
+#: tmp/deadmessages.xml:10 deadmessages.xml:11
+msgid "Game Over!"
+msgstr ""
+
+#. (itstool) path: messages/message
+#: tmp/deadmessages.xml:11 deadmessages.xml:12
+msgid "Insert coin to continue."
+msgstr ""
+
+#. (itstool) path: messages/message
+#: tmp/deadmessages.xml:12 deadmessages.xml:13
+msgid ""
+"No, kids. Your character did not really die. It... err... went to a better "
+"place."
+msgstr ""
+
+#. (itstool) path: messages/message
+#: tmp/deadmessages.xml:13 deadmessages.xml:14
+msgid ""
+"Your plan of breaking your enemies weapon by bashing it with your throat "
+"failed."
+msgstr ""
+
+#. (itstool) path: messages/message
+#: tmp/deadmessages.xml:14 deadmessages.xml:15
+msgid "I guess this did not run too well."
+msgstr ""
+
+#. (itstool) path: messages/message
+#: tmp/deadmessages.xml:15 deadmessages.xml:16
+msgid "Do you want your possessions identified?"
+msgstr ""
+
+#. (itstool) path: messages/message
+#: tmp/deadmessages.xml:16 deadmessages.xml:17
+msgid "Sadly, no trace of you was ever found..."
+msgstr ""
+
+#. (itstool) path: messages/message
+#: tmp/deadmessages.xml:17 deadmessages.xml:18
+msgid "Annihilated."
+msgstr ""
+
+#. (itstool) path: messages/message
+#: tmp/deadmessages.xml:18 deadmessages.xml:19
+msgid "Looks like you got your head handed to you."
+msgstr ""
+
+#. (itstool) path: messages/message
+#: tmp/deadmessages.xml:19 deadmessages.xml:20
+msgid ""
+"You screwed up again, dump your body down the tubes and get you another one."
+msgstr ""
+
+#. (itstool) path: messages/message
+#: tmp/deadmessages.xml:20 deadmessages.xml:21
+msgid "You're not dead yet. You're just resting."
+msgstr ""
+
+#. (itstool) path: messages/message
+#: tmp/deadmessages.xml:21 deadmessages.xml:22
+msgid "You are no more."
+msgstr ""
+
+#. (itstool) path: messages/message
+#: tmp/deadmessages.xml:22 deadmessages.xml:23
+msgid "You have ceased to be."
+msgstr ""
+
+#. (itstool) path: messages/message
+#: tmp/deadmessages.xml:23 deadmessages.xml:24
+msgid "You've expired and gone to meet your maker."
+msgstr ""
+
+#. (itstool) path: messages/message
+#: tmp/deadmessages.xml:24 deadmessages.xml:25
+msgid "You're a stiff."
+msgstr ""
+
+#. (itstool) path: messages/message
+#: tmp/deadmessages.xml:25 deadmessages.xml:26
+msgid "Bereft of life, you rest in peace."
+msgstr ""
+
+#. (itstool) path: messages/message
+#: tmp/deadmessages.xml:26 deadmessages.xml:27
+msgid "If you weren't so animated, you'd be pushing up the daisies."
+msgstr ""
+
+#. (itstool) path: messages/message
+#: tmp/deadmessages.xml:27 deadmessages.xml:28
+msgid "Your metabolic processes are now history."
+msgstr ""
+
+#. (itstool) path: messages/message
+#: tmp/deadmessages.xml:28 deadmessages.xml:29
+msgid "You're off the twig."
+msgstr ""
+
+#. (itstool) path: messages/message
+#: tmp/deadmessages.xml:29 deadmessages.xml:30
+msgid "You've kicked the bucket."
+msgstr ""
+
+#. (itstool) path: messages/message
+#: tmp/deadmessages.xml:30
+msgid ""
+"You've shuffled off your mortal coil, rung down the curtain and joined the "
+"choir invisible."
+msgstr ""
+
+#. (itstool) path: messages/message
+#: tmp/deadmessages.xml:31 deadmessages.xml:32
+msgid "You are an ex-player."
+msgstr ""
+
+#. (itstool) path: messages/message
+#: tmp/deadmessages.xml:32 deadmessages.xml:33
+msgid "You're pining for the fjords."
+msgstr ""
+
+#. (itstool) path: messages/message
+#: tmp/deadmessages.xml:33
+msgid "Right now, you would just love to be resurrected."
+msgstr ""
+
+#. (itstool) path: messages/message
+#: tmp/deadmessages.xml:34
+msgid "Wait, did I just die?"
+msgstr ""
+
+#. (itstool) path: messages/message
+#: tmp/deadmessages.xml:35
+msgid "What just happened?"
+msgstr ""
+
+#. (itstool) path: messages/message
+#: tmp/deadmessages.xml:36
+msgid "I guess you're not the One."
+msgstr ""
+
+#. (itstool) path: messages/message
+#: tmp/deadmessages.xml:37
+msgid "See you in the underworld."
+msgstr ""
+
+#. (itstool) path: messages/message
+#: tmp/deadmessages.xml:38
+msgid "Try again."
+msgstr ""
+
+#. (itstool) path: messages/message
+#: tmp/deadmessages.xml:39
+msgid "Don't panic, you're just a bit dead."
+msgstr ""
+
+#. (itstool) path: messages/message
+#: tmp/deadmessages.xml:40
+msgid "It's a bit late to start digging your grave, don't you think?"
+msgstr ""
+
+#. (itstool) path: messages/message
+#: tmp/deadmessages.xml:41
+msgid "Program terminated."
+msgstr ""
+
+#. (itstool) path: messages/message
+#: tmp/deadmessages.xml:42
+msgid "Mission failed."
+msgstr ""
+
+#. (itstool) path: messages/message
+#: tmp/deadmessages.xml:43
+msgid "Welcome to the Matrix, Neo."
+msgstr ""
+
+#. (itstool) path: messages/message
+#: tmp/deadmessages.xml:44
+msgid "Everybody falls the first time."
+msgstr ""
+
+#. (itstool) path: messages/message
+#: tmp/deadmessages.xml:45
+msgid "Welcome... to the real world."
+msgstr ""
+
+#. (itstool) path: messages/message
+#: tmp/deadmessages.xml:46
+msgid "Fate, it seems, is not without a sense of irony."
+msgstr ""
+
+#. (itstool) path: messages/message
+#: tmp/deadmessages.xml:47
+msgid "There is no spoon."
+msgstr ""
+
+#. (itstool) path: messages/message
+#: tmp/deadmessages.xml:48
+msgid "One shot, one kill."
+msgstr ""
+
+#. (itstool) path: messages/message
+#: tmp/deadmessages.xml:49
+msgid "Some men just want to watch the world burn."
+msgstr ""
+
+#. (itstool) path: messages/message
+#: tmp/deadmessages.xml:50
+msgid "You are fulfilling your destiny."
+msgstr ""
+
+#. (itstool) path: messages/message
+#: tmp/deadmessages.xml:51
+msgid "Rule #8: Do not die."
+msgstr ""
+
+#. (itstool) path: messages/message
+#: tmp/deadmessages.xml:52
+msgid "There will be no order, only chaos."
+msgstr ""
+
+#. (itstool) path: messages/message
+#: tmp/deadmessages.xml:53
+msgid "Too bad, get over it."
+msgstr ""
+
+#. (itstool) path: messages/message
+#: tmp/deadmessages.xml:54
+msgid "There's no hope for us here, only death."
+msgstr ""
+
+#. (itstool) path: messages/message
+#: tmp/deadmessages.xml:55
+msgid "Death is the road to awe."
+msgstr ""
+
+#. (itstool) path: messages/message
+#: tmp/deadmessages.xml:56
+msgid ""
+"Our bodies are prisons for our souls. Our skin and blood, the iron bars of "
+"confinement. But fear not. All flesh decays. Death turns all to ash. And "
+"thus, death frees every soul."
+msgstr ""
+
+#. (itstool) path: messages/message
+#: tmp/deadmessages.xml:57
+msgid "Stop... Stop it!"
+msgstr ""
+
+#. (itstool) path: messages/message
+#: tmp/deadmessages.xml:58
+msgid "Today is a good day to die."
+msgstr ""
+
+#. (itstool) path: messages/message
+#: tmp/deadmessages.xml:59
+msgid "Any last words? Oops, too late!"
+msgstr ""
+
+#. (itstool) path: messages/message
+#: tmp/deadmessages.xml:60
+msgid "Confusion will be my epitaph."
+msgstr ""
+
+#. (itstool) path: messages/message
+#: deadmessages.xml:31
+msgid ""
+"You've shuffled off your mortal coil, run down the curtain and joined the "
+"bleedin' choir invisibile."
+msgstr ""
+
+#. (itstool) path: messages/message
+#: deadmessages.xml:34
+msgid ""
+"When you've told someone that you've left them a legacy the only decent "
+"thing to do is to die at once."
+msgstr ""
+
+#. (itstool) path: messages/message
+#: deadmessages.xml:35
+msgid ""
+"The trouble with heart disease is that the first symptom is often hard to "
+"deal with – sudden death."
+msgstr ""
+
+#. (itstool) path: messages/message
+#: deadmessages.xml:36
+msgid ""
+"There are worse things in life than death. Have you ever spent an evening "
+"with an insurance salesman?"
+msgstr ""
+
+#. (itstool) path: messages/message
+#: deadmessages.xml:37
+msgid "There is a remedy for everything; it is called death."
+msgstr ""
+
+#. (itstool) path: messages/message
+#: deadmessages.xml:38
+msgid "If you die in an elevator, be sure to push the up button."
+msgstr ""
+
+#. (itstool) path: messages/message
+#: deadmessages.xml:39
+msgid "Death - To stop sinning suddenly."
+msgstr ""
+
+#. (itstool) path: messages/message
+#: deadmessages.xml:40
+msgid ""
+"For three days after death, hair and fingernails continue to grow but phone "
+"calls taper off."
+msgstr ""
+
+#. (itstool) path: emote/sprite@name
+#: emotes.xml:9
+msgid "Disgust"
+msgstr ""
+
+#. (itstool) path: emote/sprite@name
+#: emotes.xml:12
+msgid "Surprise"
+msgstr ""
+
+#. (itstool) path: emote/sprite@name
+#: emotes.xml:15
+msgid "Happy"
+msgstr ""
+
+#. (itstool) path: emote/sprite@name
+#: emotes.xml:18
+msgid "Sad"
+msgstr ""
+
+#. (itstool) path: emote/sprite@name
+#: emotes.xml:21
+msgid "Evil"
+msgstr ""
+
+#. (itstool) path: emote/sprite@name
+#: emotes.xml:24
+msgid "Wink"
+msgstr ""
+
+#. (itstool) path: emote/sprite@name
+#: emotes.xml:27
+msgid "Angel"
+msgstr ""
+
+#. (itstool) path: emote/sprite@name
+#: emotes.xml:30
+msgid "Blush"
+msgstr ""
+
+#. (itstool) path: emote/sprite@name
+#: emotes.xml:33
+msgid "Tongue"
+msgstr ""
+
+#. (itstool) path: emote/sprite@name
+#: emotes.xml:36
+msgid "Grin"
+msgstr ""
+
+#. (itstool) path: emote/sprite@name
+#: emotes.xml:39
+msgid "Upset"
+msgstr ""
+
+#. (itstool) path: emote/sprite@name
+#: emotes.xml:42
+msgid "Perturbed"
+msgstr ""
+
+#. (itstool) path: emote/sprite@name
+#: emotes.xml:45
+msgid "Speech"
+msgstr ""
+
+#. (itstool) path: emote/sprite@name
+#: emotes.xml:48
+msgid "Blah"
+msgstr ""
+
+#. (itstool) path: groups/group@name
+#. (itstool) path: groups/group@longName
+#: groups.xml:5
+msgid "Player"
+msgstr ""
+
+#. (itstool) path: groups/group@name
+#. (itstool) path: groups/group@longName
+#: groups.xml:21
+msgid "Bot"
+msgstr ""
+
+#. (itstool) path: groups/group@name
+#: groups.xml:22 groups.xml:63 groups.xml:134 groups.xml:156
+msgid "Dev"
+msgstr ""
+
+#. (itstool) path: groups/group@longName
+#: groups.xml:22
+msgid "Developer"
+msgstr ""
+
+#. (itstool) path: groups/group@longName
+#: groups.xml:63
+msgid "Developer (hidden)"
+msgstr ""
+
+#. (itstool) path: groups/group@name
+#: groups.xml:64 groups.xml:73
+msgid "Event"
+msgstr ""
+
+#. (itstool) path: groups/group@longName
+#: groups.xml:64
+msgid "Event coordinator"
+msgstr ""
+
+#. (itstool) path: groups/group@longName
+#: groups.xml:73
+msgid "Event coordinator (hidden)"
+msgstr ""
+
+#. (itstool) path: groups/group@name
+#: groups.xml:74 groups.xml:133
+msgid "GM"
+msgstr ""
+
+#. (itstool) path: groups/group@longName
+#: groups.xml:74
+msgid "Game master"
+msgstr ""
+
+#. (itstool) path: groups/group@longName
+#: groups.xml:133
+msgid "Game master (hidden)"
+msgstr ""
+
+#. (itstool) path: groups/group@longName
+#: groups.xml:134
+msgid "Core developer"
+msgstr ""
+
+#. (itstool) path: groups/group@longName
+#: groups.xml:156
+msgid "Core developer (hidden)"
+msgstr ""
+
+#. (itstool) path: groups/group@name
+#: groups.xml:157 groups.xml:184
+msgid "Admin"
+msgstr ""
+
+#. (itstool) path: groups/group@longName
+#: groups.xml:157
+msgid "Administrator (hidden)"
+msgstr ""
+
+#. (itstool) path: groups/group@longName
+#: groups.xml:184
+msgid "Administrator"
+msgstr ""
+
+#. (itstool) path: list/color@name
+#: itemcolors.xml:5 itemcolors.xml:37 itemcolors.xml:85
+msgid "light brown"
+msgstr ""
+
+#. (itstool) path: list/color@name
+#: itemcolors.xml:6 itemcolors.xml:21 itemcolors.xml:86
+msgid "green"
+msgstr ""
+
+#. (itstool) path: list/color@name
+#: itemcolors.xml:7 itemcolors.xml:38 itemcolors.xml:87
+msgid "red"
+msgstr ""
+
+#. (itstool) path: list/color@name
+#: itemcolors.xml:8 itemcolors.xml:88
+msgid "purple"
+msgstr ""
+
+#. (itstool) path: list/color@name
+#: itemcolors.xml:9 itemcolors.xml:39 itemcolors.xml:89
+msgid "gray"
+msgstr ""
+
+#. (itstool) path: list/color@name
+#: itemcolors.xml:10 itemcolors.xml:40 itemcolors.xml:90
+msgid "yellow"
+msgstr ""
+
+#. (itstool) path: list/color@name
+#: itemcolors.xml:11 itemcolors.xml:22 itemcolors.xml:91
+msgid "blue"
+msgstr ""
+
+#. (itstool) path: list/color@name
+#: itemcolors.xml:12 itemcolors.xml:41 itemcolors.xml:92
+msgid "light red"
+msgstr ""
+
+#. (itstool) path: list/color@name
+#: itemcolors.xml:13 itemcolors.xml:23 itemcolors.xml:93
+msgid "light blue"
+msgstr ""
+
+#. (itstool) path: list/color@name
+#: itemcolors.xml:14 itemcolors.xml:24 itemcolors.xml:94
+msgid "dark purple"
+msgstr ""
+
+#. (itstool) path: list/color@name
+#: itemcolors.xml:15 itemcolors.xml:25 itemcolors.xml:95
+msgid "black"
+msgstr ""
+
+#. (itstool) path: list/color@name
+#: itemcolors.xml:16 itemcolors.xml:96
+msgid "pink"
+msgstr ""
+
+#. (itstool) path: list/color@name
+#: itemcolors.xml:17 itemcolors.xml:97
+msgid "brown"
+msgstr ""
+
+#. (itstool) path: list/color@name
+#: itemcolors.xml:18 itemcolors.xml:19 itemcolors.xml:26 itemcolors.xml:27
+#: itemcolors.xml:28 itemcolors.xml:29 itemcolors.xml:30 itemcolors.xml:31
+#: itemcolors.xml:32 itemcolors.xml:33 itemcolors.xml:34 itemcolors.xml:35
+#: itemcolors.xml:43 itemcolors.xml:44 itemcolors.xml:45 itemcolors.xml:46
+#: itemcolors.xml:47 itemcolors.xml:48 itemcolors.xml:49 itemcolors.xml:50
+#: itemcolors.xml:51 itemcolors.xml:53 itemcolors.xml:54 itemcolors.xml:55
+#: itemcolors.xml:56 itemcolors.xml:57 itemcolors.xml:58 itemcolors.xml:59
+#: itemcolors.xml:60 itemcolors.xml:61 itemcolors.xml:62 itemcolors.xml:63
+#: itemcolors.xml:64 itemcolors.xml:65 itemcolors.xml:66 itemcolors.xml:67
+#: itemcolors.xml:69 itemcolors.xml:70 itemcolors.xml:71 itemcolors.xml:72
+#: itemcolors.xml:73 itemcolors.xml:74 itemcolors.xml:75 itemcolors.xml:76
+#: itemcolors.xml:77 itemcolors.xml:78 itemcolors.xml:79 itemcolors.xml:80
+#: itemcolors.xml:81 itemcolors.xml:82 itemcolors.xml:83 itemcolors.xml:98
+#: itemcolors.xml:99 itemcolors.xml:101 itemcolors.xml:102 itemcolors.xml:103
+#: itemcolors.xml:104 itemcolors.xml:105 itemcolors.xml:106 itemcolors.xml:107
+#: itemcolors.xml:108 itemcolors.xml:109 itemcolors.xml:110 itemcolors.xml:111
+#: itemcolors.xml:112 itemcolors.xml:113 itemcolors.xml:114 itemcolors.xml:115
+#: itemcolors.xml:117 itemcolors.xml:118 itemcolors.xml:119 itemcolors.xml:120
+#: itemcolors.xml:121 itemcolors.xml:122 itemcolors.xml:123 itemcolors.xml:124
+#: itemcolors.xml:125 itemcolors.xml:126 itemcolors.xml:127 itemcolors.xml:128
+#: itemcolors.xml:129 itemcolors.xml:130 itemcolors.xml:131 itemcolors.xml:132
+#: itemcolors.xml:133 itemcolors.xml:135 itemcolors.xml:136
+msgid "(free slot)"
+msgstr ""
+
+#. (itstool) path: list/color@name
+#: itemcolors.xml:42
+msgid "dark"
+msgstr ""
+
+#. (itstool) path: list/color@name
+#: itemcolors.xml:134 itemcolors.xml:137 itemcolors.xml:138 itemcolors.xml:139
+msgid "shock white"
+msgstr ""
+
+#. (itstool) path: required/field@description
+#: itemfields.xml:6
+msgid "Req. level %s"
+msgstr ""
+
+#. (itstool) path: required/field@description
+#: itemfields.xml:7
+msgid "Req. intelligence %s"
+msgstr ""
+
+#. (itstool) path: required/field@description
+#: itemfields.xml:8
+msgid "Req. dexterity %s"
+msgstr ""
+
+#. (itstool) path: required/field@description
+#: itemfields.xml:9
+msgid "Req. strength %s"
+msgstr ""
+
+#. (itstool) path: required/field@description
+#: itemfields.xml:10
+msgid "Req. vitality %s"
+msgstr ""
+
+#. (itstool) path: required/field@description
+#: itemfields.xml:11
+msgid "Req. luck %s"
+msgstr ""
+
+#. (itstool) path: emote/sprite
+#: tmp/manaplus_emotes.xml:6 tmp/manaplus_emotes.xml:7
+#: tmp/manaplus_emotes.xml:8 tmp/manaplus_emotes.xml:9
+#: tmp/manaplus_emotes.xml:10 tmp/manaplus_emotes.xml:11
+#: tmp/manaplus_emotes.xml:12 tmp/manaplus_emotes.xml:13
+#: tmp/manaplus_emotes.xml:14 tmp/manaplus_emotes.xml:15
+#: tmp/manaplus_emotes.xml:16 tmp/manaplus_emotes.xml:17
+#: tmp/manaplus_emotes.xml:18 tmp/manaplus_emotes.xml:19
+msgid "emote.xml"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/000-1.tmx:11
+msgid "Jesusalva's Trap"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/001-1.tmx:6
+msgid "Tulimshar Port"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/001-2.tmx:5
+msgid "South Tulimshar Indoor"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/001-3.tmx:5
+msgid "Tulimshar Arena"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/002-1.tmx:6
+msgid "Tulimshar South"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/002-2.tmx:6
+msgid "Sandstorm Desert Indoors"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/002-3.tmx:6
+msgid "Tulimshar Mining Camp"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/002-4.tmx:6
+msgid "Desert Mines"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/002-5.tmx:6
+msgid "Deep Desert Mines"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/003-1.tmx:6
+msgid "2006 Tulimshar"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/003-4.tmx:6 ../../client-data/maps/004-1.tmx:6
+#: ../../client-data/maps/041-1.tmx:5 ../../client-data/maps/043-1.tmx:6
+msgid "Beach"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/004-3.tmx:6
+msgid "Pirate Caves First Floor"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/004-4.tmx:6
+msgid "Pirate Caves Second Floor"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/004-5.tmx:6
+msgid "Pirate Den"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/005-3.tmx:6
+msgid "Snake Pit"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/006-1.tmx:6
+msgid "Desert Mountains"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/006-2.tmx:6
+msgid "Pachua's Village"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/006-3.tmx:6
+msgid "Desert Mountain Cave"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/007-1.tmx:6 ../../client-data/maps/010-1.tmx:6
+#: ../../client-data/maps/011-1.tmx:6 ../../client-data/maps/014-1.tmx:6
+#: ../../client-data/maps/015-1.tmx:6 ../../client-data/maps/016-1.tmx:6
+#: ../../client-data/maps/057-1.tmx:6
+msgid "Woodland"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/007-2.tmx:5 ../../client-data/maps/052-2.tmx:5
+msgid "Illia forsaken inn"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/008-1.tmx:6
+msgid "Hurnscald Outskirts"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/009-1.tmx:6
+msgid "Hurnscald"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/009-2.tmx:5
+msgid "Hurnscald Indoor"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/009-3.tmx:6
+msgid "Hurnscald Cave"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/009-4.tmx:4
+msgid "Orum Caves"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/009-5.tmx:5
+msgid "Last man standing"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/009-6.tmx:5 ../../client-data/maps/055-3.tmx:6
+msgid "Cave"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/009-7.tmx:6
+msgid "The Sanguine Vault"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/009-8.tmx:6
+msgid "Chez Celestia"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/010-2.tmx:5
+msgid "Dimond's Cove"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/011-3.tmx:6
+msgid "Hermit's Cave"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/011-4.tmx:6
+msgid "Lake Cave"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/011-6.tmx:5
+msgid "Bandit Cave"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/012-1.tmx:6 ../../client-data/maps/013-1.tmx:6
+#: ../../client-data/maps/017-1.tmx:6 ../../client-data/maps/055-1.tmx:6
+msgid "Woodland Hills"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/012-3.tmx:6
+msgid "Moggun Cave"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/012-4.tmx:5
+msgid "Terranite Cave"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/013-2.tmx:5
+msgid "Magic House"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/013-3.tmx:6
+msgid "Woodland Hills Cave"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/014-3.tmx:6 ../../client-data/maps/017-3.tmx:6
+msgid "Woodland Cave"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/015-3.tmx:4
+msgid "Cat's Cave"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/016-2.tmx:6
+msgid "Gwendolyn's"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/017-2.tmx:4
+msgid "Theater"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/017-4.tmx:6
+msgid "Hideout"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/017-9.tmx:4
+msgid "GM Lounge"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/018-1.tmx:6
+msgid "Woodland Mining Camp"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/018-2.tmx:5
+msgid "Woodland Mining Camp Indoor"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/018-3.tmx:6
+msgid "Northern Mines"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/019-1.tmx:6
+msgid "snow Field"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/019-3.tmx:5 ../../client-data/maps/019-4.tmx:5
+msgid "Snow Cave"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/020-1.tmx:6
+msgid "Nivalis"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/020-2.tmx:5
+msgid "Nivalis Indoor"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/020-3.tmx:6
+msgid "Ice cave"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/021-3.tmx:6
+msgid "Central Tulimshar Sewers"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/023-1.tmx:5
+msgid "Tulimshar Lighthouse Beach"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/023-3.tmx:5
+msgid "Tulimshar Beach Caves"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/025-1.tmx:6
+msgid "Woodland Swamp"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/025-3.tmx:5
+msgid "Rossy Main Hall"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/025-4.tmx:5
+msgid "Rossy Battle Caves"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/026-1.tmx:6
+msgid "Asphodel Moor"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/026-2.tmx:5
+msgid "Swamp Indoors"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/027-1.tmx:6
+msgid "Graveyard"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/027-2.tmx:5
+msgid "Graveyard Indoor"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/027-3.tmx:5
+msgid "Crypt Basement"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/027-4.tmx:5
+msgid "Crypt Sub-Basement One"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/027-5.tmx:5 ../../client-data/maps/027-6.tmx:5
+#: ../../client-data/maps/027-7.tmx:5 ../../client-data/maps/027-8.tmx:5
+msgid "Crypt Sub-Basement Two"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/028-1.tmx:5
+msgid "GM Island"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/028-3.tmx:5
+msgid "GM Island Cave"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/029-1.tmx:6
+msgid "Candor Island"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/029-2.tmx:5
+msgid "Candor Island Indoor"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/029-3.tmx:6
+msgid "Candor Cave"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/029-4.tmx:6
+msgid "2014 Candor"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/030-1.tmx:5
+msgid "Romantic Place"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/030-2.tmx:5
+msgid "Christmas Inn"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/030-3.tmx:5
+msgid "The Frozen Lake"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/030-4.tmx:5
+msgid "Christmas Inn Warehouse"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/031-1.tmx:5
+msgid "Nivalis Port"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/031-2.tmx:5
+msgid "Angela's House"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/031-3.tmx:5
+msgid "Ice Labyrinth"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/031-4.tmx:5
+msgid "Cindy Cave"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/032-3.tmx:5
+msgid "Outback Cave"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/033-1.tmx:5
+msgid "snow Path"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/034-1.tmx:5
+msgid "Snow Forest"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/034-2.tmx:6
+msgid "Trappers Huts"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/042-1.tmx:5
+msgid "Tulimshar Suburbs"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/043-3.tmx:5
+msgid "Sandy Dungeon Level 1"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/043-4.tmx:5
+msgid "Troll Cave"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/045-1.tmx:5
+msgid "Deep Snow Forest"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/046-1.tmx:5
+msgid "Rock Plateau"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/046-3.tmx:4
+msgid "Frosty Underground"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/047-1.tmx:5
+msgid "snow Hills"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/047-3.tmx:5
+msgid "Snow Hills Cave"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/048-2.tmx:5
+msgid "Blue Sages' Mansion"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/051-1.tmx:5
+msgid "Illia outskirts"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/051-3.tmx:5
+msgid "Illia Bandit Cave"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/052-1.tmx:6
+msgid "Illia archipelago"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/056-2.tmx:5
+msgid "Mirak's House"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/069-2.tmx:6
+msgid "Celestia's Hideout"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/070-1.tmx:5
+msgid "Underworld"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/070-3.tmx:5
+msgid "The Abyss"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/099-1.tmx:5
+msgid "Keshlam's Adventurer's Guild"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/099-2.tmx:5 ../../client-data/maps/099-6.tmx:5
+msgid "Keshlam's Adventurer's Guild Quarters"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/099-3.tmx:5
+msgid "Keshlam's Adventurer's Guild Basement"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/099-4.tmx:5 ../../client-data/maps/099-5.tmx:5
+msgid "?????"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/099-7.tmx:5
+msgid "Ruined Swamps"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/099-8.tmx:5
+msgid "Keshlam's Maze"
+msgstr ""
+
+#. (itstool) path: properties/property@value
+#: ../../client-data/maps/botcheck.tmx:5
+msgid "Botcheck Area"
+msgstr ""
+
+#. (itstool) path: skills/set@name
+#: skills.xml:12
+msgid "Basic"
+msgstr ""
+
+#. (itstool) path: set/skill@name
+#: skills.xml:14
+msgid "Emote"
+msgstr ""
+
+#. (itstool) path: set/skill@description
+#: skills.xml:14
+msgid "Allows you to use emotes."
+msgstr ""
+
+#. (itstool) path: set/skill@name
+#: skills.xml:15
+msgid "Trade"
+msgstr ""
+
+#. (itstool) path: set/skill@description
+#: skills.xml:15
+msgid "You can trade with others."
+msgstr ""
+
+#. (itstool) path: set/skill@name
+#: skills.xml:16 skills.xml:17
+msgid "Party"
+msgstr ""
+
+#. (itstool) path: set/skill@description
+#: skills.xml:16
+msgid "Join a Party."
+msgstr ""
+
+#. (itstool) path: set/skill@description
+#: skills.xml:17
+msgid "Join or create a Party."
+msgstr ""
+
+#. (itstool) path: skills/set@name
+#. (itstool) path: set/skill@name
+#: skills.xml:19 skills.xml:22 skills.xml:23 skills.xml:24 skills.xml:25
+#: skills.xml:26
+msgid "Magic"
+msgstr ""
+
+#. (itstool) path: set/skill@description
+#: skills.xml:22
+msgid "Cast Lvl 1 magic spells."
+msgstr ""
+
+#. (itstool) path: set/skill@description
+#: skills.xml:23
+msgid "Cast Lvl 2 magic spells."
+msgstr ""
+
+#. (itstool) path: set/skill@description
+#: skills.xml:24
+msgid "Cast Lvl 3 magic spells."
+msgstr ""
+
+#. (itstool) path: set/skill@description
+#: skills.xml:25
+msgid "Cast Lvl 4 magic spells."
+msgstr ""
+
+#. (itstool) path: set/skill@description
+#: skills.xml:26
+msgid "Cast Lvl 5 magic spells."
+msgstr ""
+
+#. (itstool) path: set/skill@name
+#: skills.xml:27 skills.xml:28 skills.xml:29 skills.xml:30 skills.xml:31
+msgid "Life Magic"
+msgstr ""
+
+#. (itstool) path: set/skill@description
+#: skills.xml:27
+msgid "Cast Lvl 1 Life Magic spells."
+msgstr ""
+
+#. (itstool) path: set/skill@description
+#: skills.xml:28
+msgid "Cast Lvl 2 Life Magic spells."
+msgstr ""
+
+#. (itstool) path: set/skill@description
+#: skills.xml:29
+msgid "Cast Lvl 3 Life Magic spells."
+msgstr ""
+
+#. (itstool) path: set/skill@description
+#: skills.xml:30
+msgid "Cast Lvl 4 Life Magic spells."
+msgstr ""
+
+#. (itstool) path: set/skill@description
+#: skills.xml:31
+msgid "Cast Lvl 5 Life Magic spells."
+msgstr ""
+
+#. (itstool) path: set/skill@name
+#: skills.xml:32 skills.xml:33 skills.xml:34 skills.xml:35 skills.xml:36
+msgid "War Magic"
+msgstr ""
+
+#. (itstool) path: set/skill@description
+#: skills.xml:32
+msgid "Cast Lvl 1 War Magic spells."
+msgstr ""
+
+#. (itstool) path: set/skill@description
+#: skills.xml:33
+msgid "Cast Lvl 2 War Magic spells."
+msgstr ""
+
+#. (itstool) path: set/skill@description
+#: skills.xml:34
+msgid "Cast Lvl 3 War Magic spells."
+msgstr ""
+
+#. (itstool) path: set/skill@description
+#: skills.xml:35
+msgid "Cast Lvl 4 War Magic spells."
+msgstr ""
+
+#. (itstool) path: set/skill@description
+#: skills.xml:36
+msgid "Cast Lvl 5 War Magic spells."
+msgstr ""
+
+#. (itstool) path: set/skill@name
+#: skills.xml:37 skills.xml:38 skills.xml:39 skills.xml:40 skills.xml:41
+msgid "Transmutation Magic"
+msgstr ""
+
+#. (itstool) path: set/skill@description
+#: skills.xml:37
+msgid "Cast Lvl 1 Transmut. Magic spells."
+msgstr ""
+
+#. (itstool) path: set/skill@description
+#: skills.xml:38
+msgid "Cast Lvl 2 Transmut. Magic spells."
+msgstr ""
+
+#. (itstool) path: set/skill@description
+#: skills.xml:39
+msgid "Cast Lvl 3 Transmut. Magic spells."
+msgstr ""
+
+#. (itstool) path: set/skill@description
+#: skills.xml:40
+msgid "Cast Lvl 4 Transmut. Magic spells."
+msgstr ""
+
+#. (itstool) path: set/skill@description
+#: skills.xml:41
+msgid "Cast Lvl 5 Transmut. Magic spells."
+msgstr ""
+
+#. (itstool) path: set/skill@name
+#: skills.xml:42 skills.xml:43 skills.xml:44 skills.xml:45 skills.xml:46
+msgid "Nature Magic"
+msgstr ""
+
+#. (itstool) path: set/skill@description
+#: skills.xml:42
+msgid "Cast Lvl 1 Nature Magic spells."
+msgstr ""
+
+#. (itstool) path: set/skill@description
+#: skills.xml:43
+msgid "Cast Lvl 2 Nature Magic spells."
+msgstr ""
+
+#. (itstool) path: set/skill@description
+#: skills.xml:44
+msgid "Cast Lvl 3 Nature Magic spells."
+msgstr ""
+
+#. (itstool) path: set/skill@description
+#: skills.xml:45
+msgid "Cast Lvl 4 Nature Magic spells."
+msgstr ""
+
+#. (itstool) path: set/skill@description
+#: skills.xml:46
+msgid "Cast Lvl 5 Nature Magic spells."
+msgstr ""
+
+#. (itstool) path: set/skill@name
+#: skills.xml:47 skills.xml:48 skills.xml:49 skills.xml:50 skills.xml:51
+msgid "Astral Magic"
+msgstr ""
+
+#. (itstool) path: set/skill@description
+#: skills.xml:47
+msgid "Cast Lvl 1 Astral Magic spells."
+msgstr ""
+
+#. (itstool) path: set/skill@description
+#: skills.xml:48
+msgid "Cast Lvl 2 Astral Magic spells."
+msgstr ""
+
+#. (itstool) path: set/skill@description
+#: skills.xml:49
+msgid "Cast Lvl 3 Astral Magic spells."
+msgstr ""
+
+#. (itstool) path: set/skill@description
+#: skills.xml:50
+msgid "Cast Lvl 4 Astral Magic spells."
+msgstr ""
+
+#. (itstool) path: set/skill@description
+#: skills.xml:51
+msgid "Cast Lvl 5 Astral Magic spells."
+msgstr ""
+
+#. (itstool) path: set/skill@name
+#: skills.xml:52 skills.xml:53 skills.xml:54 skills.xml:55 skills.xml:56
+msgid "Dark Magic"
+msgstr ""
+
+#. (itstool) path: set/skill@description
+#: skills.xml:52
+msgid "Cast Lvl 1 Dark Magic spells."
+msgstr ""
+
+#. (itstool) path: set/skill@description
+#: skills.xml:53
+msgid "Cast Lvl 2 Dark Magic spells."
+msgstr ""
+
+#. (itstool) path: set/skill@description
+#: skills.xml:54
+msgid "Cast Lvl 3 Dark Magic spells."
+msgstr ""
+
+#. (itstool) path: set/skill@description
+#: skills.xml:55
+msgid "Cast Lvl 4 Dark Magic spells."
+msgstr ""
+
+#. (itstool) path: set/skill@description
+#: skills.xml:56
+msgid "Cast Lvl 5 Dark Magic spells."
+msgstr ""
+
+#. (itstool) path: skills/set@name
+#: skills.xml:58
+msgid "Focus"
+msgstr ""
+
+#. (itstool) path: set/skill@name
+#: skills.xml:59
+msgid "Focusing"
+msgstr ""
+
+#. (itstool) path: set/skill@description
+#: skills.xml:59
+msgid "Luca can activate one Focus Skill."
+msgstr ""
+
+#. (itstool) path: set/skill@name
+#: skills.xml:60
+msgid "Mallards Eye"
+msgstr ""
+
+#. (itstool) path: set/skill@description
+#: skills.xml:60
+msgid "Increases accuracy and range."
+msgstr ""
+
+#. (itstool) path: set/skill@name
+#: skills.xml:61
+msgid "Brawling"
+msgstr ""
+
+#. (itstool) path: set/skill@description
+#: skills.xml:61
+msgid "Your fists hit harder."
+msgstr ""
+
+#. (itstool) path: set/skill@name
+#: skills.xml:62
+msgid "Lucky Counter"
+msgstr ""
+
+#. (itstool) path: set/skill@description
+#: skills.xml:62
+msgid "???"
+msgstr ""
+
+#. (itstool) path: set/skill@name
+#: skills.xml:63
+msgid "Speed"
+msgstr ""
+
+#. (itstool) path: set/skill@description
+#: skills.xml:63
+msgid "Faster walking and attacking."
+msgstr ""
+
+#. (itstool) path: set/skill@name
+#: skills.xml:64
+msgid "Resist Poison"
+msgstr ""
+
+#. (itstool) path: set/skill@description
+#: skills.xml:64
+msgid "Lower chance to get poisoned."
+msgstr ""
+
+#. (itstool) path: set/skill@name
+#: skills.xml:65
+msgid "Astral Soul"
+msgstr ""
+
+#. (itstool) path: set/skill@description
+#: skills.xml:65
+msgid "Increases your Magic Attack."
+msgstr ""
+
+#. (itstool) path: set/skill@name
+#: skills.xml:66
+msgid "Raging"
+msgstr ""
+
+#. (itstool) path: set/skill@description
+#: skills.xml:66
+msgid "Higher chance for critical hits."
+msgstr ""
+
+#. (itstool) path: basic/stat@name
+#: stats.xml:6
+msgid "Strength"
+msgstr ""
+
+#. (itstool) path: basic/stat@name
+#: stats.xml:7
+msgid "Agility"
+msgstr ""
+
+#. (itstool) path: basic/stat@name
+#: stats.xml:8
+msgid "Vitality"
+msgstr ""
+
+#. (itstool) path: basic/stat@name
+#: stats.xml:9
+msgid "Intelligence"
+msgstr ""
+
+#. (itstool) path: basic/stat@name
+#: stats.xml:10
+msgid "Dexterity"
+msgstr ""
+
+#. (itstool) path: basic/stat@name
+#: stats.xml:11
+msgid "Luck"
+msgstr ""
+
+#. (itstool) path: extended/stat@name
+#: stats.xml:14
+msgid "Attack"
+msgstr ""
+
+#. (itstool) path: extended/stat@name
+#: stats.xml:15
+msgid "Defense"
+msgstr ""
+
+#. (itstool) path: extended/stat@name
+#: stats.xml:16
+msgid "M.Attack"
+msgstr ""
+
+#. (itstool) path: extended/stat@name
+#: stats.xml:17
+msgid "M.Defense"
+msgstr ""
+
+#. (itstool) path: extended/stat@name
+#: stats.xml:18
+msgid "% Accuracy"
+msgstr ""
+
+#. (itstool) path: extended/stat@name
+#: stats.xml:19
+msgid "% Evade"
+msgstr ""
+
+#. (itstool) path: extended/stat@name
+#: stats.xml:20
+msgid "% Critical"
+msgstr ""
+
+#. (itstool) path: extended/stat@name
+#: stats.xml:21
+msgid "Attack Delay"
+msgstr ""
+
+#. (itstool) path: extended/stat@name
+#: stats.xml:22
+msgid "Walk Delay"
+msgstr ""
+
+#. (itstool) path: extended/stat@name
+#: stats.xml:23
+msgid "Attack Range"
+msgstr ""
+
+#. (itstool) path: extended/stat@name
+#: stats.xml:24
+msgid "Damage per sec."
+msgstr ""
+
+#. (itstool) path: status-effects/status-effect@name
+#: status-effects.xml:3
+msgid "item-healing"
+msgstr ""
+
+#. (itstool) path: status-effects/status-effect@name
+#: status-effects.xml:4
+msgid "speed"
+msgstr ""
+
+#. (itstool) path: status-effects/status-effect@name
+#: status-effects.xml:5
+msgid "strength"
+msgstr ""
+
+#. (itstool) path: status-effects/status-effect@name
+#: status-effects.xml:6
+msgid "invisibility"
+msgstr ""
+
+#. (itstool) path: status-effects/status-effect@name
+#: status-effects.xml:7
+msgid "poison"
+msgstr ""
+
+#. (itstool) path: status-effects/status-effect@name
+#: status-effects.xml:8
+msgid "slow-poison"
+msgstr ""
+
+#. (itstool) path: status-effects/status-effect@name
+#: status-effects.xml:9
+msgid "weight 50%"
+msgstr ""
+
+#. (itstool) path: status-effects/status-effect@name
+#: status-effects.xml:10
+msgid "weight 90%"
+msgstr ""
+
+#. (itstool) path: status-effects/status-effect@name
+#: status-effects.xml:11
+msgid "hide"
+msgstr ""
+
+#. (itstool) path: status-effects/status-effect@name
+#: status-effects.xml:12
+msgid "halt-regenerate"
+msgstr ""
+
+#. (itstool) path: status-effects/status-effect@name
+#: status-effects.xml:13
+msgid "flying-backpack"
+msgstr ""
+
+#. (itstool) path: status-effects/status-effect@name
+#: status-effects.xml:14
+msgid "barrier"
+msgstr ""
+
+#. (itstool) path: status-effects/status-effect@name
+#: status-effects.xml:15
+msgid "haste"
+msgstr ""
+
+#. (itstool) path: status-effects/status-effect@name
+#: status-effects.xml:16
+msgid "phys-shield"
+msgstr ""
+
+#. (itstool) path: status-effects/status-effect@name
+#: status-effects.xml:17
+msgid "spell-attack-generic"
+msgstr ""
+
+#. (itstool) path: status-effects/status-effect@name
+#: status-effects.xml:18
+msgid "spell-shearing"
+msgstr ""
+
+#. (itstool) path: status-effects/status-effect@name
+#: status-effects.xml:19
+msgid "spell-protection-generic"
+msgstr ""
+
+#. (itstool) path: status-effects/status-effect@name
+#: status-effects.xml:20
+msgid "spell-haste"
+msgstr ""
diff --git a/lang_client/createpots.sh b/lang_client/createpots.sh
new file mode 100755
index 0000000..04d6722
--- /dev/null
+++ b/lang_client/createpots.sh
@@ -0,0 +1,50 @@
+#!/usr/bin/env bash
+
+function its {
+ itstool -o ../tools/lang_client/pot/$1.pot $1.xml
+}
+
+function its2 {
+ itstool -o ../tools/lang_client/pot/$1.pot -i ../tools/lang_client/its/$1.xml $1.xml
+}
+
+function its2dict {
+ itstool -o ../tools/lang_client/dict/$1.pot -i ../tools/lang_client/its/$1.xml $1.xml
+}
+
+DIR=`pwd`
+cd ../../client-data
+
+#its2 avatars
+its2 clans
+its2 deadmessages
+its2 emotes
+its2 groups
+its2 homunculuses
+its2 itemcolors
+its2 itemfields
+its2 items
+its2 mercenaries
+its2 monsters
+# disabled for now because here testing strings only
+#its2 npcdialogs
+its2 npcs
+its2 pets
+its quests
+its2 skills
+its2 skillunits
+its2 stats
+its2 status-effects
+its2dict texts
+
+cd $DIR
+
+rm pot/map*.pot
+
+itstool -o pot/manaplus_emotes1.pot tmp/manaplus_emotes.xml
+itstool -o pot/deadmessages1.pot tmp/deadmessages.xml
+
+find ../../client-data/maps -type f -name "*.tmx" -exec ./processtmx.sh {} \;
+
+msgcat pot/*.pot > clientdata.pot
+msgcat dict/*.pot > clientdata-dict.pot
diff --git a/lang_client/fetch.py b/lang_client/fetch.py
new file mode 100755
index 0000000..2fb7d4f
--- /dev/null
+++ b/lang_client/fetch.py
@@ -0,0 +1,58 @@
+#! /usr/bin/env python2.7
+# -*- coding: utf8 -*-
+#
+# Copyright (C) 2018 TMW-2
+# Author: Jesusalva
+
+from transifex.api import TransifexAPI
+
+project='tmw'
+
+# Load credentials from login.txt and password.txt
+login=open('../lang/login.txt', 'r')
+for i in login:
+ username=i.replace('\n', '').replace('\r', '')
+
+login.close()
+
+passw=open('../lang/password.txt', 'r')
+for i in passw:
+ password=i.replace('\n', '').replace('\r', '')
+
+passw.close()
+
+t=TransifexAPI(username, password, 'https://www.transifex.com')
+
+if (not t.ping):
+ print("ERROR: Ping failed, this may be due incorrect username/password in login.txt and password.txt. Ensure there is NO newline at the end of file. At lang/ folder.")
+ exit(1)
+
+if (not t.project_exists(project)):
+ print("ERROR: Invalid project name")
+ exit(1)
+
+# Load languages
+langs=[]
+vcx=open("../../server-data/langs/langs.txt", "r")
+for i in vcx:
+ if i != "en":
+ langs.append(i.replace('\n', ''))
+vcx.close()
+
+# Fetch all translations and record them at in/
+for i in langs:
+ # Disregarded languages
+ if i in ['en', 'vls']:
+ continue
+
+ # People translated so we cannot override stuff
+ #if i in ['pt_BR', 'vls']:
+ # print("Overriding %s..." %(i))
+ # t.new_translation(project, 'clientdata', i,'../../client-data/translations/'+str(i)+'.po')
+
+ print("Fetching %s..." %(i))
+ t.get_translation(project, 'clientdata', i, '../../client-data/translations/'+str(i)+'.po')
+
+ print("Fetching %s dict..." %(i))
+ t.get_translation(project, 'clientdata-dict', i, '../../client-data/translations/dict/'+str(i)+'.po')
+
diff --git a/lang_client/its/avatars.xml b/lang_client/its/avatars.xml
new file mode 100644
index 0000000..403c685
--- /dev/null
+++ b/lang_client/its/avatars.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Authors: 4144
+Copyright (C) 2010-2016 Evol Online -->
+
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="1.0">
+ <its:translateRule selector="//avatar/@name" translate="yes"/>
+ <its:translateRule selector="//*" translate="no"/>
+</its:rules>
diff --git a/lang_client/its/clans.xml b/lang_client/its/clans.xml
new file mode 100644
index 0000000..f35a462
--- /dev/null
+++ b/lang_client/its/clans.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Authors: 4144
+Copyright (C) 2016 Evol Online -->
+
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="1.0">
+ <its:translateRule selector="//clan/@name" translate="yes"/>
+ <its:translateRule selector="//*" translate="no"/>
+</its:rules>
diff --git a/lang_client/its/deadmessages.xml b/lang_client/its/deadmessages.xml
new file mode 100644
index 0000000..46e9dea
--- /dev/null
+++ b/lang_client/its/deadmessages.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Authors: 4144
+Copyright (C) 2013 ManaPlus -->
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="1.0">
+ <its:translateRule selector="//message" translate="yes"/>
+</its:rules>
diff --git a/lang_client/its/emotes.xml b/lang_client/its/emotes.xml
new file mode 100644
index 0000000..dbe44f2
--- /dev/null
+++ b/lang_client/its/emotes.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Authors: 4144
+Copyright (C) 2010-2013 Evol Online -->
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="1.0">
+ <its:translateRule selector="//emote/@name" translate="yes"/>
+ <its:translateRule selector="//emote/sprite/@name" translate="yes"/>
+ <its:translateRule selector="//*" translate="no"/>
+</its:rules>
diff --git a/lang_client/its/groups.xml b/lang_client/its/groups.xml
new file mode 100644
index 0000000..620c0ee
--- /dev/null
+++ b/lang_client/its/groups.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Authors: 4144
+Copyright (C) 2010-2016 Evol Online -->
+
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="1.0">
+ <its:translateRule selector="//group/@name" translate="yes"/>
+ <its:translateRule selector="//group/@longName" translate="yes"/>
+ <its:translateRule selector="//*" translate="no"/>
+</its:rules>
diff --git a/lang_client/its/homunculuses.xml b/lang_client/its/homunculuses.xml
new file mode 100644
index 0000000..a130fa9
--- /dev/null
+++ b/lang_client/its/homunculuses.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Authors: 4144
+Copyright (C) 2016 Evol Online -->
+
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="1.0">
+ <its:translateRule selector="//homunculus/@name" translate="yes"/>
+ <its:translateRule selector="//*" translate="no"/>
+</its:rules>
diff --git a/lang_client/its/itemcolors.xml b/lang_client/its/itemcolors.xml
new file mode 100644
index 0000000..f14eebd
--- /dev/null
+++ b/lang_client/its/itemcolors.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Authors: 4144
+Copyright (C) 2010-2015 Evol Online -->
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="1.0">
+ <its:translateRule selector="//list/color/@name" translate="yes"/>
+ <its:translateRule selector="//*" translate="no"/>
+</its:rules>
diff --git a/lang_client/its/itemfields.xml b/lang_client/its/itemfields.xml
new file mode 100644
index 0000000..c2edfa3
--- /dev/null
+++ b/lang_client/its/itemfields.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Author: 4144
+Copyright (C) 2016 Evol Online -->
+
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="1.0">
+ <its:translateRule selector="//required/field/@description" translate="yes"/>
+ <its:translateRule selector="//*" translate="no"/>
+</its:rules>
diff --git a/lang_client/its/items.xml b/lang_client/its/items.xml
new file mode 100644
index 0000000..3df823b
--- /dev/null
+++ b/lang_client/its/items.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Authors: 4144
+Copyright (C) 2010-2016 Evol Online -->
+
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="1.0">
+ <its:translateRule selector="//item/@name" translate="yes"/>
+ <its:translateRule selector="//item/@description" translate="yes"/>
+ <its:translateRule selector="//item/@useButton" translate="yes"/>
+ <its:translateRule selector="//item/@useButton2" translate="yes"/>
+ <its:translateRule selector="//item/@effect" translate="yes"/>
+ <its:translateRule selector="//item/inventory/menu/@name1" translate="yes"/>
+ <its:translateRule selector="//item/inventory/menu/@name2" translate="yes"/>
+ <its:translateRule selector="//item/storage/menu/@name1" translate="yes"/>
+ <its:translateRule selector="//item/storage/menu/@name2" translate="yes"/>
+ <its:translateRule selector="//item/cart/menu/@name1" translate="yes"/>
+ <its:translateRule selector="//item/cart/menu/@name2" translate="yes"/>
+ <its:translateRule selector="//*" translate="no"/>
+</its:rules>
diff --git a/lang_client/its/mercenaries.xml b/lang_client/its/mercenaries.xml
new file mode 100644
index 0000000..a6b66f9
--- /dev/null
+++ b/lang_client/its/mercenaries.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Authors: 4144
+Copyright (C) 2016 Evol Online -->
+
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="1.0">
+ <its:translateRule selector="//mercenary/@name" translate="yes"/>
+ <its:translateRule selector="//*" translate="no"/>
+</its:rules>
diff --git a/lang_client/its/monsters.xml b/lang_client/its/monsters.xml
new file mode 100644
index 0000000..ed269d0
--- /dev/null
+++ b/lang_client/its/monsters.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Author: 4144
+Copyright (C) 2010-2016 Evol Online -->
+
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="1.0">
+ <its:translateRule selector="//monster/@name" translate="yes"/>
+ <its:translateRule selector="//*" translate="no"/>
+</its:rules>
diff --git a/lang_client/its/npcdialogs.xml b/lang_client/its/npcdialogs.xml
new file mode 100644
index 0000000..37c1a8b
--- /dev/null
+++ b/lang_client/its/npcdialogs.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Authors: 4144
+Copyright (C) 2010-2016 Evol Online -->
+
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="1.0">
+ <its:translateRule selector="//dialog/menu/text/@text" translate="yes"/>
+ <its:translateRule selector="//*" translate="no"/>
+</its:rules>
diff --git a/lang_client/its/npcs.xml b/lang_client/its/npcs.xml
new file mode 100644
index 0000000..fd295b4
--- /dev/null
+++ b/lang_client/its/npcs.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Authors: 4144
+Copyright (C) 2010-2016 Evol Online -->
+
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="1.0">
+ <its:translateRule selector="//npc/menu/@name" translate="yes"/>
+ <its:translateRule selector="//*" translate="no"/>
+</its:rules>
diff --git a/lang_client/its/pets.xml b/lang_client/its/pets.xml
new file mode 100644
index 0000000..cfa8f6b
--- /dev/null
+++ b/lang_client/its/pets.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Authors: 4144
+Copyright (C) 2013-2016 Evol Online -->
+
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="1.0">
+ <its:translateRule selector="//pet/@name" translate="yes"/>
+ <its:translateRule selector="//*" translate="no"/>
+</its:rules>
diff --git a/lang_client/its/skills.xml b/lang_client/its/skills.xml
new file mode 100644
index 0000000..e27840e
--- /dev/null
+++ b/lang_client/its/skills.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Authors: 4144
+Copyright (C) 2010-2016 Evol Online -->
+
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="1.0">
+ <its:translateRule selector="//set/@name" translate="yes"/>
+ <its:translateRule selector="//set/skill/@name" translate="yes"/>
+ <its:translateRule selector="//set/skill/@description" translate="yes"/>
+ <its:translateRule selector="//*" translate="no"/>
+</its:rules>
diff --git a/lang_client/its/skillunits.xml b/lang_client/its/skillunits.xml
new file mode 100644
index 0000000..5ed05c0
--- /dev/null
+++ b/lang_client/its/skillunits.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Authors: 4144
+Copyright (C) 2010-2016 Evol Online -->
+
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="1.0">
+ <its:translateRule selector="//skillunit/@name" translate="yes"/>
+ <its:translateRule selector="//*" translate="no"/>
+</its:rules>
diff --git a/lang_client/its/stats.xml b/lang_client/its/stats.xml
new file mode 100644
index 0000000..48846ec
--- /dev/null
+++ b/lang_client/its/stats.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Authors: 4144
+Copyright (C) 2010-2016 Evol Online -->
+
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="1.0">
+ <its:translateRule selector="//basic/stat/@name" translate="yes"/>
+ <its:translateRule selector="//extended/stat/@name" translate="yes"/>
+ <its:translateRule selector="//page/@name" translate="yes"/>
+ <its:translateRule selector="//page/stat/@name" translate="yes"/>
+ <its:translateRule selector="//*" translate="no"/>
+</its:rules>
diff --git a/lang_client/its/status-effects.xml b/lang_client/its/status-effects.xml
new file mode 100644
index 0000000..56e1301
--- /dev/null
+++ b/lang_client/its/status-effects.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Authors: 4144
+Copyright (C) 2010-2016 Evol Online -->
+
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="1.0">
+ <its:translateRule selector="//status-effect/@name" translate="yes"/>
+ <its:translateRule selector="//*" translate="no"/>
+</its:rules>
diff --git a/lang_client/its/texts.xml b/lang_client/its/texts.xml
new file mode 100644
index 0000000..79d4212
--- /dev/null
+++ b/lang_client/its/texts.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Authors: 4144
+Copyright (C) 2010-2017 Evol Online -->
+
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="1.0">
+ <its:translateRule selector="//*" translate="yes"/>
+</its:rules>
diff --git a/lang_client/its/tmx.xml b/lang_client/its/tmx.xml
new file mode 100644
index 0000000..e90a1d4
--- /dev/null
+++ b/lang_client/its/tmx.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Authors: 4144
+Copyright (C) 2010-2016 Evol Online -->
+
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="1.0">
+ <its:translateRule selector="//properties/property[@name='name']/@value" translate="yes"/>
+ <its:translateRule selector="//*" translate="no"/>
+</its:rules>
diff --git a/lang_client/processtmx.sh b/lang_client/processtmx.sh
new file mode 100755
index 0000000..5fc80aa
--- /dev/null
+++ b/lang_client/processtmx.sh
@@ -0,0 +1,6 @@
+#!/usr/bin/env bash
+
+export name=$1
+export name=${name##*/}
+
+itstool -o pot/map${name}.pot -i its/tmx.xml $1
diff --git a/localserver/.gitignore b/localserver/.gitignore
new file mode 100644
index 0000000..ff3de76
--- /dev/null
+++ b/localserver/.gitignore
@@ -0,0 +1 @@
+versions
diff --git a/localserver/README b/localserver/README
new file mode 100644
index 0000000..8d1e2a3
--- /dev/null
+++ b/localserver/README
@@ -0,0 +1,14 @@
+Here located for LOCAL server usage ONLY.
+Can be unsecure to use this files in public or production server.
+
+build.sh - build server from sources with most compilers.
+buildasan.sh - build server from sources with asan flags enabled.
+clean.sh - remove all built and temp files.
+givegm.sh - give gm rights to first account created on server.
+initdb.sh - initialize mariadb database.
+installconfigs.sh - install configurations into server data directory.
+updatedb.sh - update if need sql database
+updateconfigs.sh - update if need server data configuration
+
+See also http://wiki.evolonline.org/guidelines/installmariadb
+ http://wiki.evolonline.org/guidelines/localserver
diff --git a/localserver/build.sh b/localserver/build.sh
new file mode 100755
index 0000000..c19d10b
--- /dev/null
+++ b/localserver/build.sh
@@ -0,0 +1,6 @@
+#!/usr/bin/env bash
+
+export DIR=`pwd`
+./checktime.sh
+source ./clean.sh
+./build.sh old > /dev/null
diff --git a/localserver/buildasan.sh b/localserver/buildasan.sh
new file mode 100755
index 0000000..5c6d9f7
--- /dev/null
+++ b/localserver/buildasan.sh
@@ -0,0 +1,5 @@
+#!/usr/bin/env bash
+
+export DIR=`pwd`
+source ./clean.sh
+./build.sh
diff --git a/localserver/checktime.sh b/localserver/checktime.sh
new file mode 100755
index 0000000..9ca0c95
--- /dev/null
+++ b/localserver/checktime.sh
@@ -0,0 +1,9 @@
+#!/usr/bin/env bash
+
+year=$(date "+%Y")
+
+if [[ $year -lt 2017 ]]; then
+ date
+ echo "Error: Date time is wrong. Please fix time. See man date"
+ exit 1
+fi \ No newline at end of file
diff --git a/localserver/clean.sh b/localserver/clean.sh
new file mode 100755
index 0000000..134f5cb
--- /dev/null
+++ b/localserver/clean.sh
@@ -0,0 +1,6 @@
+#!/usr/bin/env bash
+
+rm -rf ../../server-code/src/evol/build/
+mkdir ../../server-code/src/evol/build/
+cd ../../server-code/
+make clean
diff --git a/localserver/conf/battle.conf b/localserver/conf/battle.conf
new file mode 100644
index 0000000..ff05022
--- /dev/null
+++ b/localserver/conf/battle.conf
@@ -0,0 +1,32 @@
+//================= Hercules Configuration ================================
+//= _ _ _
+//= | | | | | |
+//= | |_| | ___ _ __ ___ _ _| | ___ ___
+//= | _ |/ _ \ '__/ __| | | | |/ _ \/ __|
+//= | | | | __/ | | (__| |_| | | __/\__ \
+//= \_| |_/\___|_| \___|\__,_|_|\___||___/
+//================= License ===============================================
+//= This file is part of Hercules.
+//= http://herc.ws - http://github.com/HerculesWS/Hercules
+//=
+//= Copyright (C) 2014-2019 Hercules Dev Team
+//=
+//= Hercules is free software: you can redistribute it and/or modify
+//= it under the terms of the GNU General Public License as published by
+//= the Free Software Foundation, either version 3 of the License, or
+//= (at your option) any later version.
+//=
+//= This program is distributed in the hope that it will be useful,
+//= but WITHOUT ANY WARRANTY; without even the implied warranty of
+//= MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//= GNU General Public License for more details.
+//=
+//= You should have received a copy of the GNU General Public License
+//= along with this program. If not, see <http://www.gnu.org/licenses/>.
+//=========================================================================
+//= Battle local configuration file.
+//=========================================================================
+
+battle_configuration: {
+ // See conf/map/battle.conf for details
+}
diff --git a/localserver/conf/char-server.conf b/localserver/conf/char-server.conf
new file mode 100644
index 0000000..448b8d1
--- /dev/null
+++ b/localserver/conf/char-server.conf
@@ -0,0 +1,31 @@
+//================= Hercules Configuration ================================
+//= _ _ _
+//= | | | | | |
+//= | |_| | ___ _ __ ___ _ _| | ___ ___
+//= | _ |/ _ \ '__/ __| | | | |/ _ \/ __|
+//= | | | | __/ | | (__| |_| | | __/\__ \
+//= \_| |_/\___|_| \___|\__,_|_|\___||___/
+//================= License ===============================================
+//= This file is part of Hercules.
+//= http://herc.ws - http://github.com/HerculesWS/Hercules
+//=
+//= Copyright (C) 2014-2019 Hercules Dev Team
+//=
+//= Hercules is free software: you can redistribute it and/or modify
+//= it under the terms of the GNU General Public License as published by
+//= the Free Software Foundation, either version 3 of the License, or
+//= (at your option) any later version.
+//=
+//= This program is distributed in the hope that it will be useful,
+//= but WITHOUT ANY WARRANTY; without even the implied warranty of
+//= MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//= GNU General Public License for more details.
+//=
+//= You should have received a copy of the GNU General Public License
+//= along with this program. If not, see <http://www.gnu.org/licenses/>.
+//=========================================================================
+//= Character Server local configuration file.
+//=========================================================================
+
+min_char_class: 0
+max_char_class: 6
diff --git a/localserver/conf/constants.conf b/localserver/conf/constants.conf
new file mode 100644
index 0000000..d2f4046
--- /dev/null
+++ b/localserver/conf/constants.conf
@@ -0,0 +1,34 @@
+//================= Hercules Configuration ================================
+//= _ _ _
+//= | | | | | |
+//= | |_| | ___ _ __ ___ _ _| | ___ ___
+//= | _ |/ _ \ '__/ __| | | | |/ _ \/ __|
+//= | | | | __/ | | (__| |_| | | __/\__ \
+//= \_| |_/\___|_| \___|\__,_|_|\___||___/
+//================= License ===============================================
+//= This file is part of Hercules.
+//= http://herc.ws - http://github.com/HerculesWS/Hercules
+//=
+//= Copyright (C) 2014-2016 Hercules Dev Team
+//=
+//= Hercules is free software: you can redistribute it and/or modify
+//= it under the terms of the GNU General Public License as published by
+//= the Free Software Foundation, either version 3 of the License, or
+//= (at your option) any later version.
+//=
+//= This program is distributed in the hope that it will be useful,
+//= but WITHOUT ANY WARRANTY; without even the implied warranty of
+//= MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//= GNU General Public License for more details.
+//=
+//= You should have received a copy of the GNU General Public License
+//= along with this program. If not, see <http://www.gnu.org/licenses/>.
+//=========================================================================
+//= Battle local configuration file.
+//=========================================================================
+
+// set to 0 for production, 1 for development
+debug: 0
+
+// set to 1 if the server uses tmw-vault
+SERVER_USES_VAULT: 0
diff --git a/localserver/conf/inter-server.conf b/localserver/conf/inter-server.conf
new file mode 100644
index 0000000..9cd3932
--- /dev/null
+++ b/localserver/conf/inter-server.conf
@@ -0,0 +1,32 @@
+//================= Hercules Configuration ================================
+//= _ _ _
+//= | | | | | |
+//= | |_| | ___ _ __ ___ _ _| | ___ ___
+//= | _ |/ _ \ '__/ __| | | | |/ _ \/ __|
+//= | | | | __/ | | (__| |_| | | __/\__ \
+//= \_| |_/\___|_| \___|\__,_|_|\___||___/
+//================= License ===============================================
+//= This file is part of Hercules.
+//= http://herc.ws - http://github.com/HerculesWS/Hercules
+//=
+//= Copyright (C) 2014-2019 Hercules Dev Team
+//=
+//= Hercules is free software: you can redistribute it and/or modify
+//= it under the terms of the GNU General Public License as published by
+//= the Free Software Foundation, either version 3 of the License, or
+//= (at your option) any later version.
+//=
+//= This program is distributed in the hope that it will be useful,
+//= but WITHOUT ANY WARRANTY; without even the implied warranty of
+//= MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//= GNU General Public License for more details.
+//=
+//= You should have received a copy of the GNU General Public License
+//= along with this program. If not, see <http://www.gnu.org/licenses/>.
+//=========================================================================
+//= Hercules Inter Server local configuration file.
+//=========================================================================
+
+inter_configuration: {
+ // See conf/common/inter-server.conf
+}
diff --git a/localserver/conf/login-server.conf b/localserver/conf/login-server.conf
new file mode 100644
index 0000000..c8f1f85
--- /dev/null
+++ b/localserver/conf/login-server.conf
@@ -0,0 +1,32 @@
+//================= Hercules Configuration ================================
+//= _ _ _
+//= | | | | | |
+//= | |_| | ___ _ __ ___ _ _| | ___ ___
+//= | _ |/ _ \ '__/ __| | | | |/ _ \/ __|
+//= | | | | __/ | | (__| |_| | | __/\__ \
+//= \_| |_/\___|_| \___|\__,_|_|\___||___/
+//================= License ===============================================
+//= This file is part of Hercules.
+//= http://herc.ws - http://github.com/HerculesWS/Hercules
+//=
+//= Copyright (C) 2014-2019 Hercules Dev Team
+//=
+//= Hercules is free software: you can redistribute it and/or modify
+//= it under the terms of the GNU General Public License as published by
+//= the Free Software Foundation, either version 3 of the License, or
+//= (at your option) any later version.
+//=
+//= This program is distributed in the hope that it will be useful,
+//= but WITHOUT ANY WARRANTY; without even the implied warranty of
+//= MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//= GNU General Public License for more details.
+//=
+//= You should have received a copy of the GNU General Public License
+//= along with this program. If not, see <http://www.gnu.org/licenses/>.
+//=========================================================================
+//= Login Server local configuration file.
+//=========================================================================
+
+login_configuration: {
+ // See conf/login/login-server.conf for details
+}
diff --git a/localserver/conf/logs.conf b/localserver/conf/logs.conf
new file mode 100644
index 0000000..47e5a66
--- /dev/null
+++ b/localserver/conf/logs.conf
@@ -0,0 +1,32 @@
+//================= Hercules Configuration ================================
+//= _ _ _
+//= | | | | | |
+//= | |_| | ___ _ __ ___ _ _| | ___ ___
+//= | _ |/ _ \ '__/ __| | | | |/ _ \/ __|
+//= | | | | __/ | | (__| |_| | | __/\__ \
+//= \_| |_/\___|_| \___|\__,_|_|\___||___/
+//================= License ===============================================
+//= This file is part of Hercules.
+//= http://herc.ws - http://github.com/HerculesWS/Hercules
+//=
+//= Copyright (C) 2014-2019 Hercules Dev Team
+//=
+//= Hercules is free software: you can redistribute it and/or modify
+//= it under the terms of the GNU General Public License as published by
+//= the Free Software Foundation, either version 3 of the License, or
+//= (at your option) any later version.
+//=
+//= This program is distributed in the hope that it will be useful,
+//= but WITHOUT ANY WARRANTY; without even the implied warranty of
+//= MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//= GNU General Public License for more details.
+//=
+//= You should have received a copy of the GNU General Public License
+//= along with this program. If not, see <http://www.gnu.org/licenses/>.
+//=========================================================================
+//= Hercules Log local configuration file.
+//=========================================================================
+
+map_log: {
+ // See conf/map/logs.conf for details
+}
diff --git a/localserver/conf/map-server.conf b/localserver/conf/map-server.conf
new file mode 100644
index 0000000..11e4356
--- /dev/null
+++ b/localserver/conf/map-server.conf
@@ -0,0 +1,32 @@
+//================= Hercules Configuration ================================
+//= _ _ _
+//= | | | | | |
+//= | |_| | ___ _ __ ___ _ _| | ___ ___
+//= | _ |/ _ \ '__/ __| | | | |/ _ \/ __|
+//= | | | | __/ | | (__| |_| | | __/\__ \
+//= \_| |_/\___|_| \___|\__,_|_|\___||___/
+//================= License ===============================================
+//= This file is part of Hercules.
+//= http://herc.ws - http://github.com/HerculesWS/Hercules
+//=
+//= Copyright (C) 2014-2019 Hercules Dev Team
+//=
+//= Hercules is free software: you can redistribute it and/or modify
+//= it under the terms of the GNU General Public License as published by
+//= the Free Software Foundation, either version 3 of the License, or
+//= (at your option) any later version.
+//=
+//= This program is distributed in the hope that it will be useful,
+//= but WITHOUT ANY WARRANTY; without even the implied warranty of
+//= MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//= GNU General Public License for more details.
+//=
+//= You should have received a copy of the GNU General Public License
+//= along with this program. If not, see <http://www.gnu.org/licenses/>.
+//=========================================================================
+//= Map Server local configuration file.
+//=========================================================================
+
+map_configuration: {
+ // See conf/map/map-server.conf for details
+}
diff --git a/localserver/conf/msg_conf.txt b/localserver/conf/msg_conf.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/localserver/conf/msg_conf.txt
diff --git a/localserver/conf/ports.conf b/localserver/conf/ports.conf
new file mode 100644
index 0000000..7d5481e
--- /dev/null
+++ b/localserver/conf/ports.conf
@@ -0,0 +1,8 @@
+// Login server port
+login_port: 6901
+
+// Character server port
+char_port: 6122
+
+// Map server port
+map_port: 5122
diff --git a/localserver/conf/script.conf b/localserver/conf/script.conf
new file mode 100644
index 0000000..042644f
--- /dev/null
+++ b/localserver/conf/script.conf
@@ -0,0 +1,32 @@
+//================= Hercules Configuration ================================
+//= _ _ _
+//= | | | | | |
+//= | |_| | ___ _ __ ___ _ _| | ___ ___
+//= | _ |/ _ \ '__/ __| | | | |/ _ \/ __|
+//= | | | | __/ | | (__| |_| | | __/\__ \
+//= \_| |_/\___|_| \___|\__,_|_|\___||___/
+//================= License ===============================================
+//= This file is part of Hercules.
+//= http://herc.ws - http://github.com/HerculesWS/Hercules
+//=
+//= Copyright (C) 2014-2019 Hercules Dev Team
+//=
+//= Hercules is free software: you can redistribute it and/or modify
+//= it under the terms of the GNU General Public License as published by
+//= the Free Software Foundation, either version 3 of the License, or
+//= (at your option) any later version.
+//=
+//= This program is distributed in the hope that it will be useful,
+//= but WITHOUT ANY WARRANTY; without even the implied warranty of
+//= MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//= GNU General Public License for more details.
+//=
+//= You should have received a copy of the GNU General Public License
+//= along with this program. If not, see <http://www.gnu.org/licenses/>.
+//=========================================================================
+//= Hercules Script local configuration file.
+//=========================================================================
+
+script_configuration: {
+ // See conf/map/script.conf for details
+}
diff --git a/localserver/conf/socket.conf b/localserver/conf/socket.conf
new file mode 100644
index 0000000..57806f2
--- /dev/null
+++ b/localserver/conf/socket.conf
@@ -0,0 +1,32 @@
+//================= Hercules Configuration ================================
+//= _ _ _
+//= | | | | | |
+//= | |_| | ___ _ __ ___ _ _| | ___ ___
+//= | _ |/ _ \ '__/ __| | | | |/ _ \/ __|
+//= | | | | __/ | | (__| |_| | | __/\__ \
+//= \_| |_/\___|_| \___|\__,_|_|\___||___/
+//================= License ===============================================
+//= This file is part of Hercules.
+//= http://herc.ws - http://github.com/HerculesWS/Hercules
+//=
+//= Copyright (C) 2014-2019 Hercules Dev Team
+//=
+//= Hercules is free software: you can redistribute it and/or modify
+//= it under the terms of the GNU General Public License as published by
+//= the Free Software Foundation, either version 3 of the License, or
+//= (at your option) any later version.
+//=
+//= This program is distributed in the hope that it will be useful,
+//= but WITHOUT ANY WARRANTY; without even the implied warranty of
+//= MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//= GNU General Public License for more details.
+//=
+//= You should have received a copy of the GNU General Public License
+//= along with this program. If not, see <http://www.gnu.org/licenses/>.
+//=========================================================================
+//= Hercules Sockets local configuration file
+//=========================================================================
+
+socket_configuration: {
+ // See conf/common/socket.conf for details.
+}
diff --git a/localserver/conf/sql_connection.conf b/localserver/conf/sql_connection.conf
new file mode 100644
index 0000000..00edfc0
--- /dev/null
+++ b/localserver/conf/sql_connection.conf
@@ -0,0 +1,52 @@
+//================= Hercules Configuration ================================
+//= _ _ _
+//= | | | | | |
+//= | |_| | ___ _ __ ___ _ _| | ___ ___
+//= | _ |/ _ \ '__/ __| | | | |/ _ \/ __|
+//= | | | | __/ | | (__| |_| | | __/\__ \
+//= \_| |_/\___|_| \___|\__,_|_|\___||___/
+//================= License ===============================================
+//= This file is part of Hercules.
+//= http://herc.ws - http://github.com/HerculesWS/Hercules
+//=
+//= Copyright (C) 2014-2019 Hercules Dev Team
+//=
+//= Hercules is free software: you can redistribute it and/or modify
+//= it under the terms of the GNU General Public License as published by
+//= the Free Software Foundation, either version 3 of the License, or
+//= (at your option) any later version.
+//=
+//= This program is distributed in the hope that it will be useful,
+//= but WITHOUT ANY WARRANTY; without even the implied warranty of
+//= MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//= GNU General Public License for more details.
+//=
+//= You should have received a copy of the GNU General Public License
+//= along with this program. If not, see <http://www.gnu.org/licenses/>.
+//=========================================================================
+//= SQL connection configuration file.
+//=========================================================================
+// This file affects how ALL server sql connections work, unless explictly
+// defined so in the server configuration file (See
+// doc/global_configuration.txt for more information).
+//=========================================================================
+
+sql_connection: {
+ // [INTER] You can specify the codepage to use in your mySQL tables here.
+ // (Note that this feature requires MySQL 4.1+)
+ //default_codepage: ""
+
+ // [LOGIN] Is `userid` in account_db case sensitive?
+ //case_sensitive: false
+
+ // For IPs, ideally under linux, you want to use localhost instead of 127.0.0.1.
+ // Under windows, you want to use 127.0.0.1. If you see a message like
+ // "Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)"
+ // and you have localhost, switch it to 127.0.0.1
+ db_hostname: "127.0.0.1"
+ db_port: 3306
+ db_username: "evol"
+ db_password: "evol"
+ db_database: "evol"
+ //codepage:""
+}
diff --git a/localserver/givegm.sh b/localserver/givegm.sh
new file mode 100755
index 0000000..ac9d301
--- /dev/null
+++ b/localserver/givegm.sh
@@ -0,0 +1,8 @@
+#!/usr/bin/env bash
+
+ID="$1"
+if [[ -z "${ID}" ]]; then
+ mysql -u evol -pevol evol -e "update login set group_id=99 where account_id=2000000;"
+else
+ mysql -u evol -pevol evol -e "update login set group_id=99 where account_id=${ID} or userid='${ID}';"
+fi
diff --git a/localserver/initdb.sh b/localserver/initdb.sh
new file mode 100755
index 0000000..074f8c5
--- /dev/null
+++ b/localserver/initdb.sh
@@ -0,0 +1,26 @@
+#!/usr/bin/env bash
+
+export DIR="$(pwd)"
+export VER=$(cat versions/sqlver 2>/dev/null)
+
+cd ../../server-data/sql-files
+
+echo Creating db and user...
+echo Enter mysql root password:
+mysql --force -u root -p <./init.sql
+result=$?
+if [ "$result" != 0 ]; then
+ echo Password failed. Trying with sudo...
+ sudo mysql --force -u root <./init.sql
+fi
+
+export CMD="mysql -u evol -pevol evol"
+
+echo Creating tables...
+$CMD <main.sql
+$CMD <logs.sql
+
+if [[ -z "${VER}" ]]; then
+ mkdir ${DIR}/versions
+ echo "20" >${DIR}/versions/sqlver
+fi
diff --git a/localserver/installconfigs.sh b/localserver/installconfigs.sh
new file mode 100755
index 0000000..398c02a
--- /dev/null
+++ b/localserver/installconfigs.sh
@@ -0,0 +1,12 @@
+#!/usr/bin/env bash
+
+export SD="../../server-data"
+export CONF="$SD/conf/import"
+export NPC="$SD/npc"
+
+mkdir $CONF
+cp conf/* $CONF
+cp -f ${SD}/conf/channels.conf.base ${SD}/conf/channels.conf
+cp -f npc/motd-* ${NPC}/commands/
+mkdir versions
+echo "5" >versions/confver
diff --git a/localserver/npc/motd-debug-text.txt b/localserver/npc/motd-debug-text.txt
new file mode 100644
index 0000000..60537fb
--- /dev/null
+++ b/localserver/npc/motd-debug-text.txt
@@ -0,0 +1,4 @@
+function script MOTD_debug_text {
+ setarray $@Debug_Messages$[0],"";
+ return;
+}
diff --git a/localserver/updateconfigs.sh b/localserver/updateconfigs.sh
new file mode 100755
index 0000000..8c2688c
--- /dev/null
+++ b/localserver/updateconfigs.sh
@@ -0,0 +1,36 @@
+#!/usr/bin/env bash
+
+export VER=$(cat versions/confver 2>/dev/null)
+export CONFDIR="../../server-data/"
+
+if [[ -z "${VER}" ]]; then
+ export VER="0"
+ mkdir versions
+fi
+
+if [ "${VER}" -lt "1" ]; then
+ cp -f ${CONFDIR}/conf/channels.conf ${CONFDIR}/conf/channels.conf.bak
+ cp -f ${CONFDIR}/conf/channels.conf.base ${CONFDIR}/conf/channels.conf
+fi
+
+if [ "${VER}" -lt "2" ]; then
+ rm ${CONFDIR}/conf/import/*.txt
+ cp conf/* ${CONFDIR}/conf/import
+ echo "2" >versions/confver
+fi
+
+if [ "${VER}" -lt "3" ]; then
+ cp conf/constants.conf ${CONFDIR}/conf/import/
+ echo "3" >versions/confver
+fi
+
+if [ "${VER}" -lt "4" ]; then
+ cp -f npc/motd-* ${CONFDIR}/npc/commands/
+ echo "4" >versions/confver
+fi
+
+if [ "${VER}" -lt "5" ]; then
+ cp -f ${CONFDIR}/conf/channels.conf ${CONFDIR}/conf/channels.conf.bak
+ cp -f ${CONFDIR}/conf/channels.conf.base ${CONFDIR}/conf/channels.conf
+ echo "5" >versions/confver
+fi
diff --git a/localserver/updatedb.sh b/localserver/updatedb.sh
new file mode 100755
index 0000000..8278326
--- /dev/null
+++ b/localserver/updatedb.sh
@@ -0,0 +1,112 @@
+#!/usr/bin/env bash
+
+export VER=$(cat versions/sqlver 2>/dev/null)
+export SQLDIR="../../server-data/sql-files/upgrades"
+export CMD="mysql -u evol -pevol evol"
+
+function run {
+ echo "Running $1"
+ $CMD <${SQLDIR}/$1
+}
+
+if [[ -z "${VER}" ]]; then
+ export VER="1"
+ mkdir versions
+fi
+
+if [ "${VER}" -lt "2" ]; then
+ run "2015-07-08--13-08.sql"
+ run "2015-08-27--20-42.sql"
+fi
+
+if [ "${VER}" -lt "3" ]; then
+ run "2015-12-16--12-57.sql"
+ run "2015-12-17--15-58.sql"
+fi
+
+if [ "${VER}" -lt "4" ]; then
+ run "2016-03-10--22-18.sql"
+fi
+
+if [ "${VER}" -lt "5" ]; then
+ run "2016-07-08--02-42.sql"
+ run "2016-07-08--02-51.sql"
+fi
+
+if [ "${VER}" -lt "6" ]; then
+ run "2016-10-03--20-27.sql"
+fi
+
+if [ "${VER}" -lt "7" ]; then
+ run "2016-10-26--10-29.sql"
+fi
+
+if [ "${VER}" -lt "8" ]; then
+ run "2017-03-02--11-40.sql"
+ run "2017-03-05--08-09.sql"
+fi
+
+if [ "${VER}" -lt "9" ]; then
+ run "2017-03-15--14-29.sql"
+fi
+
+if [ "${VER}" -lt "10" ]; then
+ run "2017-11-04--10-39.sql"
+fi
+
+if [ "${VER}" -lt "11" ]; then
+ run "2017-06-04--15-04.sql"
+ run "2017-06-04--15-05.sql"
+fi
+
+if [ "${VER}" -lt "12" ]; then
+ run "2018-02-26--15-57.sql"
+fi
+
+if [ "${VER}" -lt "13" ]; then
+ run "2018-03-10--04-06.sql"
+fi
+
+if [ "${VER}" -lt "14" ]; then
+ run "2018-06-05--12-02.sql"
+fi
+
+if [ "${VER}" -lt "15" ]; then
+ run "2018-07-24--03-23.sql"
+fi
+
+if [ "${VER}" -lt "16" ]; then
+ run "2018-06-03--00-10.sql"
+ run "2018-06-03--17-16.sql"
+ run "2018-09-01--05-22.sql"
+fi
+
+if [ "${VER}" -lt "17" ]; then
+ run "2018-12-14--01-02.sql"
+ run "2018-12-29--07-51.sql"
+fi
+
+if [ "${VER}" -lt "18" ]; then
+ run "2019-04-08--21-52.sql"
+ run "2019-04-25--02-12.sql"
+fi
+
+if [ "${VER}" -lt "19" ]; then
+ run "2019-05-09--18-07.sql"
+fi
+
+if [ "${VER}" -lt "20" ]; then
+ run "2019-08-08--19-43.sql"
+ run "2019-10-05--19-01.sql"
+ run "2019-10-12--14-21.sql"
+ run "2019-11-22--23-58.sql"
+ run "2020-01-24--01-09.sql"
+ run "2020-03-22--01-56.sql"
+ run "2020-03-22--03-09.sql"
+ run "2020-05-01--04-44.sql"
+ run "2020-05-10--23-11.sql"
+fi
+
+if [ "${VER}" -lt "20" ]; then
+ echo "20" >versions/sqlver
+fi
diff --git a/update/addmods.sh b/update/addmods.sh
new file mode 100755
index 0000000..a45f9ed
--- /dev/null
+++ b/update/addmods.sh
@@ -0,0 +1,32 @@
+#!/usr/bin/env bash
+
+# Copyright (C) 2010-2012 Evol Online
+# Author: Andrei Karas (4144)
+
+dir=`pwd`
+CC=${CC:=gcc}
+
+rm adler32
+$CC -lz adler32.c -o adler32
+
+mkdir files
+mkdir upload
+
+previous=`cat commit.txt`
+
+cd ../../client-data/mods
+
+FILES=`ls`
+
+for file in $FILES; do
+ cd $file
+ find . -type f | xargs zip -9 -r ../../../../evol-tools/update/files/mod-$file.zip
+ cd $dir/files
+ sum=`../adler32 1 mod-$file.zip`
+ echo " <update type=\"data\" group=\"$file\" file=\"mod-$file.zip\" hash=\"${sum}\" />" >> xml_header.txt
+ cp xml_header.txt resources.xml
+ cat xml_footer.txt >>resources.xml
+ cp mod-$file.zip ../upload/
+ cp resources2.txt ../upload/
+ cp resources.xml ../upload/
+done
diff --git a/update/adler32.c b/update/adler32.c
new file mode 100644
index 0000000..606c739
--- /dev/null
+++ b/update/adler32.c
@@ -0,0 +1,79 @@
+/*
+ * adler32.c (c) 2006 Bjorn Lindeijer
+ * License: GPL, v2 or later
+ *
+ * Calculates Adler-32 checksums for all files passed as argument.
+ *
+ * Usage: adler32 [file]...
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <zlib.h>
+
+/**
+ * Calculates the Adler-32 checksum for the given file.
+ */
+unsigned long fadler32(FILE *file)
+{
+ // Obtain file size
+ fseek(file, 0, SEEK_END);
+ long fileSize = ftell(file);
+ rewind(file);
+
+ // Calculate Adler-32 checksum
+ char *buffer = (char*) malloc(fileSize);
+ fread(buffer, 1, fileSize, file);
+ unsigned long adler = adler32(0L, Z_NULL, 0);
+ adler = adler32(adler, (Bytef*) buffer, fileSize);
+ free(buffer);
+
+ return adler;
+}
+
+/**
+ * Prints out usage and exists.
+ */
+void print_usage()
+{
+ printf("Usage: adler32 mode [file]...\n");
+ exit(0);
+}
+
+int main(int argc, char *argv[])
+{
+ int i; /**< Loops through arguments. */
+
+ if (argc < 2)
+ {
+ print_usage();
+ }
+
+ int mode = atoi(argv[1]);
+
+ for (i = 2; i < argc; ++i)
+ {
+ FILE *file = fopen(argv[i], "r");
+
+ if (!file)
+ {
+ printf("Error while opening '%s' for reading!\n", argv[i]);
+ exit(1);
+ }
+
+ unsigned long adler = fadler32(file);
+ switch (mode)
+ {
+ case 0:
+ default:
+ printf("%s %lx\n", argv[i], adler);
+ break;
+ case 1:
+ printf("%lx", adler);
+ break;
+ }
+ fclose(file);
+ }
+
+ return 0;
+}
diff --git a/update/commit.txt b/update/commit.txt
new file mode 100644
index 0000000..ab9dd1d
--- /dev/null
+++ b/update/commit.txt
@@ -0,0 +1 @@
+c7eaf530e07572c69cb31e112d615a4bd0eef443
diff --git a/update/commit_old.txt b/update/commit_old.txt
new file mode 100644
index 0000000..98b6b40
--- /dev/null
+++ b/update/commit_old.txt
@@ -0,0 +1 @@
+1cf6ff982c76e5ab116d8ed953ef8ff5005d1dde
diff --git a/update/createnew.sh b/update/createnew.sh
new file mode 100755
index 0000000..0c28040
--- /dev/null
+++ b/update/createnew.sh
@@ -0,0 +1,36 @@
+#!/usr/bin/env bash
+
+# Copyright (C) 2011-2012 Evol Online
+# Author: Andrei Karas (4144)
+
+dir=`pwd`
+#CC=${CC:=gcc}
+
+#rm adler32
+#$CC -lz adler32.c -o adler32
+
+mkdir files
+mkdir upload
+
+rm files/revolt.zip
+cd ../../client-data
+find -iregex ".+[.]\(xml\|png\|tmx\|ogg\|txt\|po\|tsx\)" -exec touch --date=2015-01-01 {} \;
+find -iregex ".+[.]\(xml\|png\|tmx\|ogg\|txt\|po\|tsx\)" -printf "%P\n" | zip -X -@ ../tools/update/files/revolt.zip
+git log --pretty=oneline -n 1 | awk '{print $1}' >../tools/update/commit.txt
+
+cd $dir/files
+sum=`adler32 revolt.zip`
+echo "revolt.zip ${sum}" >resources2.txt
+
+echo '<?xml version="1.0"?>
+<updates>' >xml_header.txt
+echo '</updates>' >xml_footer.txt
+
+echo " <update type=\"data\" file=\"revolt.zip\" hash=\"${sum}\" />" >> xml_header.txt
+cp xml_header.txt resources.xml
+cat xml_footer.txt >>resources.xml
+
+cp revolt.zip ../upload/
+cp resources2.txt ../upload/
+cp resources.xml ../upload/
+cp ../news.txt ../upload/
diff --git a/update/evol_news.txt b/update/evol_news.txt
new file mode 100644
index 0000000..3f8acc9
--- /dev/null
+++ b/update/evol_news.txt
@@ -0,0 +1,324 @@
+##9 Latest client version: ##6ManaPlus 1.8.9.1
+##0 Actual Release: ##1Beta3-H2
+##0 Welcome to ##BEvol Online##b!
+##0 You can find every ##1rules##0 of ##BEvol Online##b here:
+##1 [@@http://www.evolonline.org/guide_rules.html|http://www.evolonline.org/guide_rules.html@@]
+
+##7 Update from master branch
+
+##7 ##BThe adventure begins!##b
+
+##7 Season 2, Episode 1!
+
+##0 The long awaited Aurora1 release is finally online.
+##0 You can now fully explore Artis, the principale port city of Aurora,
+##0 and benefit of the latest fishing and digging support!
+
+##0 A lot of quests will help you to explore the city and will show off
+##0 the historical and political aspect of the Archipelagos of Andorra.
+
+##0 Welcome our new support, such as walking NPCs, pets, and various
+##0 interactive map elements!
+
+##0 Have fun, the adventure starts now!
+
+##9 -- Crocs, Reid
+##9 February 2016
+
+
+##7 Hallowe'en Event
+
+##0 Our special Hallowe'en update is out!
+
+##0 This event brings back some old monsters from the beta releases, but
+##0 it also introduces an angry bat monster named "Crafty".
+##0 We have also reworked many graphics and music from the previous
+##0 Hallowe'en theme with the help of Aeonchild and Eric Matyas.
+
+##0 The event will stay online for 3 weeks, it should be enough time to
+##0 re-visit the island and, who knows... Maybe you'll find a new
+##0 place to explore... ;)
+
+##0 We all wish you a happy Hallowe'en and we hope to see you around!
+
+##9 -- Cheers, Reid and WildX
+##9 October 2015
+
+
+##7 Season 1, Episode 4
+
+##0 The Evol Online Project is pleased to announce you the release of
+##0 the new server software!
+##0 First of all, remember to update your server list.
+
+##0 This server includes better support for all the main features of
+##0 Evol. You won't actually see much difference from other Beta
+##0 releases, but we still need your help to assure that the current
+##0 server build works with our little world while we work on the first
+##0 release.
+
+##0 we will also release most of our current changes on the island and
+##0 some bug fixes which were waiting in queue since the end of the Beta
+##0 Session.
+##0 And yet much more work in progress which should be soon available
+##0 through the Aurora1 release this year!
+
+##9 -- Cheers, Reid and WildX
+##9 March 2015
+
+
+##7 Season 1, Episode 3!
+
+##0 Greetings to you all, fellow players! Welcome to this new version of
+##0 Evol Online! This third Beta release will maybe be followed by a
+##0 Beta3.1 if bugs are to be discovered, so don't hesitate to tell us
+##0 about anything you dislike in game. Then you may deserve a cookie...
+
+##0 Thanks to Kenny690, we made great progress on sound effects and more
+##0 will come! We also worked very hard on art, we for example added a
+##0 a new hairstyle, weapons are now visible, lots of icons were remade,
+##0 etc... Furthermore, new unit names got introduced such as Esperin
+##0 for the in-game currency or Florin as weight value.
+
+##0 Last but not least, we did an incredible work on balancing the game,
+##0 this took us most of our time thus we think it'll bring a new game
+##0 experience to this adventure. We hope you'll enjoy this new version
+##0 of Evol Online, and remember, cookies are a source of life.
+
+##9 -- Regards, Alige.
+##9 July 2013
+
+
+##7 Get ready for summer!
+
+##0 Fellow players, we are pleased to inform you that during this year,
+##0 all of us worked hard on this project and also in real life, thus
+##0 most of our developers and contributors graduated! Congratulations
+##0 to all of them!
+
+##0 The change of license from GPLv2 to CC BY-SA 3.0 has made great
+##0 progress too! There are very few graphics left that are still GPLv2
+##0 and we're doing our best to get rid of these as soon as possible.
+
+##0 On top of that, we also continued working on our new website, we
+##0 hope you'll enjoy it as much as we do. Don't forget to register on
+##0 our forums too!
+
+##0 The Beta3 is coming very soon, so if you want a very special cookie,
+##0 please come and help us translate the last few sentences left.
+
+##0 On the ManaPlus development side, we are proud to announce the
+##0 release of that client on Debian and Ubuntu 13.10. Note that
+##0 http://manaplus.org/ is finally out too!
+
+##9 -- Regards, Alige.
+##9 June 2013
+
+
+##7 Spring time everybody!
+
+##0 Beta2.1 was a great success, more than what we thought it would be.
+##0 We are proud of this release and of the players too! Your bug
+##0 reports helped us a lot, as well as your feedbacks. Thank you!
+
+##0 We started working on Beta3 even before the launch of Beta2.1
+##0 because much needs to be done. We fixed all known in-game issues
+##0 and improved a lot of old content.
+
+##0 To sump up, Beta3 can be compared as a full balancing release, it'll
+##0 bring new weight and currency measures, which will offer a new game
+##0 experience to you all! We'll let you discover all of the other new
+##0 features and modifications by yourself!
+
+##0 Lastly, we think it is important for you to know that we spend a lot
+##0 of time trying to change our game art's license from GPLv2 to
+##0 CC BY-SA 3.0. This will help us develop much faster in the future.
+
+##0 Beta3 will soon be released, such as its news post!
+
+##9 -- Cheers, Reid.
+##9 March 2013
+
+
+##7 Finally, Beta2.1 is out!
+
+##0 We are proud to announce the launch of Beta2.1 tonight. This
+##0 update brings a lot of bug fixes. We also did a lot of dialogues and
+##0 quest fixes. Translators greatly helped too! Thanks to everyone
+##0 who contributed.
+
+##0 As Evol developers already started working on future releases,
+##0 some improvements, that were not supposed to come in so soon, were
+##0 implemented in this release. We improved and added graphics,
+##0 cleaned databases, added a new indoor sunlight effect. We hope
+##0 you'll like it!
+
+##0 ManaPlus also got improved along with its awesome new Jewelry
+##0 Theme! You can now play Evol Online on Android and Mac OS X,
+##0 enjoy! Special thanks to Socapex for his wonderful work, creating
+##0 the ManaPlus Mac OS X application.
+
+##0 Check out our Facebook and Google+ pages regularly so that you
+##0 don't miss anything. Note that we're already working on the Beta3
+##0 and Aurora1 releases, meaning which releases will come much sooner
+##0 than you think!
+
+##9 -- Regards, Alige.
+##9 February 2013
+
+
+##7 End of the World, Epic Fail!
+
+##0 We just released Beta2 and we hope you enjoyed all of the cool new
+##0 features it brang! This took us a lot of time to put in place but
+##0 sadly, we will soon need to release a small update to fix several
+##0 bugs.
+
+##0 Some of us also started working on future releases, that is why
+##0 this bug fixing release, called Beta2.1, will be release in a
+##0 month. In addition, we need to let translators do their job, and
+##0 that takes time!
+
+##0 Moreover, ManaPlus never stops getting better, as well as the
+##0 brand new Jewelry Theme, thanks to 4144 and Hal9000! Check it out!
+
+##0 Stay tuned for the Beta2.1 release!
+
+##9 -- Regards, Alige.
+##9 January 2013
+
+
+##7 Season 1, Episode 2!
+
+##0 After over 10 months of intense work, here is the new version of
+##0 Evol Online! A whole new dynamic has been added to the game,
+##0 everything has been rewritten, rethought and redrew.
+##0 We are proud to present you this Beta2 release!
+
+##0 Along with the story comes new game and client features, and new
+##0 interactions with the environment. This is in fact an entirely new
+##0 gaming experience.
+
+##0 Developers modified the whole game and here are some major
+##0 additions: savepoints, quest window, maps, graphics, etc...
+
+##0 You can check the full list of changes at
+##0 http://wiki.evolonline.org/changelog
+##0 And all of the new contributors at
+##0 http://wiki.evolonline.org/contributors
+
+##0 Enough said, check out everything by yourself!
+
+##9 -- Regards, Alige.
+##9 December 2012
+
+
+##7 What a scary... I mean... weird development team!
+
+##0 Hey, why did the ship stop?! Was that under Nard's orders? Lets
+##0 find out! Oh no, giant pumpkins overran all of the boat! It seems
+##0 you must get ready for battle. You can sense something very
+##0 powerful and evil at the far bottom of the ship. You should check
+##0 it out. Maybe Bachus, the party spirit, could help you throughout
+##0 this. We hope you'll enjoy this Halloween event.
+
+##0 Once again, Evol Online developers are in a rush. Beta2 takes a
+##0 whole lot longer than they thought but this is of course to avoid
+##0 any kind of issue. Again, a numerous amount of bugs were fixed and
+##0 scripts were mostly all rewritten for a better game experience.
+
+##0 As a lot of dialogues were added and improved for Beta2,
+##0 translations are needed more than ever. Even though some developers
+##0 also work on these, they cannot afford working on all of them.
+
+##0 If you feel like you can help developers in any way, especially for
+##0 translations if you speak english fluently, feel free to contact
+##0 them using Evol Online's IRC developer channel.
+
+##9 -- Regards, Alige.
+##9 November 2012
+
+
+##7 End of summer, beginning of Beta2!
+
+##0 Summer holidays are now over for the Evol Online developers. We are
+##0 proud to announce the arrival of Beta2 soon, even though we
+##0 unfortunately find ourselves currently behind schedule.
+
+##0 However, a lot of efforts were made to create a lot of new content
+##0 and great new tilesets which took for ever to create and fix.
+##0 We are currently fixing bugs and preparing the release. Final
+##0 modifications are being made to give you the best release ever made
+##0 for this project.
+
+##0 Among the new features is a Quest Window that has been added to the
+##0 client. It will help you see your progress in game.
+
+##0 When the Beta2 release will be out, we would like you to promote it
+##0 by simply spreading the word around you. Players will then be aware
+##0 of the news and this may help us expand our community.
+
+##0 As you already now, new contributors are always welcome!
+##0 Translators, artists and even writers are free to contact us for
+##0 more information.
+
+##9 -- Regards, Alige.
+##9 August 2012
+
+
+##7 Some people just never stop working!
+
+##0 Once more, a lot of work has been done, recently on the consistency
+##0 and quality of the game. A lot of new graphics will be part of the
+##0 next release, Beta2. Interactivity between the player and the game
+##0 was our main goal the past weeks.
+
+##0 This new dynamic and gaming experience will be revealed throughout
+##0 animations full of mysteries. Treasure chests, coconuts and new
+##0 have appeared on a brand new map!
+
+##0 The work on the translations, the repository reorganizations and
+##0 on top of all, the client, were one of our main concerns lately.
+##0 The developers still need a bit of time in order to finish this
+##0 release, thus we thank you for waiting.
+
+##9 -- Regards, Alige.
+##9 July 2012
+
+
+##7 Season 1, Episode 1!
+
+##0 After a mysterious past, you find yourself adrift on the waves in
+##0 the middle of Oceania. A noble-minded crew, sails by your body
+##0 decides to rescue and take care of you.
+
+##0 You now wake up about seven days later in their wooden ship.
+##0 Take some time to know the crew who saved you and try to
+##0 discover what happened to you before this terrible event!
+
+##9 -- Cheers, Reid.
+##9 January 2012
+
+
+##7 Evol Online Beta releases!
+
+##0 After several months of work, the world of ##BEvol Online##b is
+##0 finally opened to everyone for its first Beta release!
+
+##0 This Beta will be the first among two other ones which will help
+##0 the developers finding out the qualities and problems of the
+##0 chosen gameplay.
+
+##0 We welcome you to give us your thoughts about this, but we also
+##0 hope you will have fun being part of this amazing adventure.
+
+##0 We also need to warn you that at the end of the third release,
+##0 all characters will be wiped out as we are trying to have a
+##0 perfect balance for this game and start it over with it.
+##0 We kindly ask you to accept this.
+
+##9 -- Cheers, Reid.
+##9 January 2012
+
+##0 You can check out this page for older news entries:
+##1 [@@http://wiki.evolonline.org/news|http://wiki.evolonline.org/news@@]
diff --git a/update/musiccommit.txt b/update/musiccommit.txt
new file mode 100644
index 0000000..e5352e1
--- /dev/null
+++ b/update/musiccommit.txt
@@ -0,0 +1 @@
+663e049146ec1c2637338f7834cee445ab653ebb
diff --git a/update/musicnew.sh b/update/musicnew.sh
new file mode 100755
index 0000000..91a9f5e
--- /dev/null
+++ b/update/musicnew.sh
@@ -0,0 +1,31 @@
+#!/usr/bin/env bash
+
+# Copyright (C) 2011-2012 Evol Online
+# Author: Andrei Karas (4144)
+
+dir=`pwd`
+CC=${CC:=gcc}
+
+rm adler32
+$CC -lz adler32.c -o adler32
+
+mkdir files
+mkdir upload
+
+rm files/music.zip
+cd ../../music
+find -iregex ".+[.]\(ogg\)" -exec touch --date=2015-01-01 {} \;
+find -iregex ".+[.]\(ogg\)" -printf "%P\n" | zip -X -@ ../tools/update/files/music.zip
+git log --pretty=oneline -n 1 | awk '{print $1}' >../tools/update/musiccommit.txt
+
+cd $dir/files
+sum=`../adler32 1 music.zip`
+
+echo " <update type=\"music\" required=\"no\" file=\"music.zip\" hash=\"${sum}\" description=\"TMW music\" />" >> xml_header.txt
+
+cp xml_header.txt resources.xml
+cat xml_footer.txt >>resources.xml
+
+cp music.zip ../upload/
+cp resources.xml ../upload/
+cp ../news.txt ../upload/
diff --git a/update/news.txt b/update/news.txt
new file mode 100644
index 0000000..a35d7d0
--- /dev/null
+++ b/update/news.txt
@@ -0,0 +1,30 @@
+##0 Actual Release: ##1Unreleased
+##0 Welcome to ##BThe Mana World##b!
+##0 You can find every ##1rules##0 of ##BThe Mana World: rEvolt##b here:
+##1 [@@https://wiki.themanaworld.org/index.php/Game_Rules|https://wiki.themanaworld.org/index.php/Game_Rules@@]
+
+##7 Update from master branch
+
+##7 ##BThere is no release title yet##b
+
+##7 Insert here version number
+
+##0 I wish I could show you the news, but it is too troublesome updating
+##0 this file every time we add something new to the game.
+##0 So why don't you explore around, and find out all exciting things
+##0 we already add? Please report every bug you find, as well.
+
+##0 We would also like to show you our bright new ##BWallpaper##b.
+##0 Thanks for testing in advance, we'll add something more serious
+##0 to this file at release date.
+
+##0 Have fun, the adventure starts now!
+
+##9 -- Crocs, Author Name
+##9 Insert here date
+
+##0 You can check out this page for Evol Online news entries:
+##1 [@@http://wiki.evolonline.org/news|http://wiki.evolonline.org/news@@]
+
+##0 You can check out this page for The Mana World Legacy news entries:
+##1 [@@https://www.themanaworld.org/news|https://www.themanaworld.org/news@@]
diff --git a/update/update.sh b/update/update.sh
new file mode 100755
index 0000000..37882d3
--- /dev/null
+++ b/update/update.sh
@@ -0,0 +1,39 @@
+#!/usr/bin/env bash
+
+# Copyright (C) 2010-2012 Evol Online
+# Author: Andrei Karas (4144)
+
+dir=`pwd`
+CC=${CC:=gcc}
+
+rm adler32
+$CC -lz adler32.c -o adler32
+
+mkdir files
+mkdir upload
+
+previous=`cat commit.txt`
+
+cd ../../client-data
+head=`git log --pretty=oneline -n 1 | awk '{print $1}'`
+u1=`echo ${previous} | cut -c 1-7`
+u2=`echo ${head} | cut -c 1-7`
+git log --name-status ${previous}..${head} | awk '/^(A|M)\t/ {print $2}' | \
+ grep -e "[.]\(xml\|png\|tmx\|ogg\|txt\|po\|tsx\)" | sort | uniq | \
+ xargs zip -X -9 -r ../tools/update/files/revolt-${u1}..${u2}.zip
+
+cd $dir/files
+if [ -f revolt-${u1}..${u2}.zip ]; then
+ mv ../commit.txt ../commit_old.txt
+ echo ${head} >../commit.txt
+ sum=`../adler32 1 revolt-${u1}..${u2}.zip`
+ echo "revolt-${u1}..${u2}.zip ${sum}" >>resources2.txt
+ echo " <update type=\"data\" file=\"revolt-${u1}..${u2}.zip\" hash=\"${sum}\" />" >> xml_header.txt
+ cp xml_header.txt resources.xml
+ cat xml_footer.txt >>resources.xml
+
+ cp revolt-${u1}..${u2}.zip ../upload/
+ cp resources2.txt ../upload/
+ cp resources.xml ../upload/
+ cp ../news.txt ../upload
+fi
diff --git a/update/update_music.sh b/update/update_music.sh
new file mode 100755
index 0000000..7954b45
--- /dev/null
+++ b/update/update_music.sh
@@ -0,0 +1,40 @@
+#!/usr/bin/env bash
+
+# Copyright (C) 2010-2012 Evol Online
+# Author: Andrei Karas (4144)
+
+dir=`pwd`
+CC=${CC:=gcc}
+
+rm adler32
+$CC -lz adler32.c -o adler32
+
+mkdir files
+mkdir upload
+
+previous=`cat musiccommit.txt`
+
+cd ../../music
+head=`git log --pretty=oneline -n 1 | awk '{print $1}'`
+u1=`echo ${previous} | cut -c 1-7`
+u2=`echo ${head} | cut -c 1-7`
+git log --name-status ${previous}..${head} \
+| awk '/^(A|M)\t/ {print $2}'
+# grep -e "[.]\(ogg\)" | sort | uniq | \
+# xargs zip -X -9 -r ../../evol-tools/update/files/music-${u1}..${u2}.zip
+exit
+
+cd $dir/files
+if [ -f evol-${u1}..${u2}.zip ]; then
+ mv ../muciscommit.txt ../muciscommit_old.txt
+ echo ${head} >../muciscommit.txt
+ sum=`../adler32 1 music-${u1}..${u2}.zip`
+ echo " <update type=\"music\" required=\"no\" file=\"music-${u1}..${u2}.zip\" hash=\"${sum}\" description=\"TMW music\" />" >> xml_header.txt
+ cp xml_header.txt resources.xml
+ cat xml_footer.txt >>resources.xml
+
+ cp music-${u1}..${u2}.zip ../upload/
+ cp resources2.txt ../upload/
+ cp resources.xml ../upload/
+ cp ../news.txt ../upload
+fi