diff options
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 Binary files differnew file mode 100644 index 0000000..fa94222 --- /dev/null +++ b/client/minimap-override/008-3-0.png 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("&", "&"); + data = data.replace("<", "<"); + data = data.replace(">", ">"); + 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 Binary files differnew file mode 100644 index 0000000..f360c63 --- /dev/null +++ b/hercules/templates/collision.png 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 Binary files differnew file mode 100644 index 0000000..f36ccbb --- /dev/null +++ b/hercules/templates/tileset.png 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 |