summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/HPMHookGen/HPMDataCheckGen.pl12
-rwxr-xr-xtools/HPMHookGen/HPMHookGen.pl281
-rwxr-xr-xtools/ci/retry.sh33
-rwxr-xr-xtools/ci/travis.sh202
-rwxr-xr-xtools/configconverter.pl968
-rw-r--r--tools/doxygen/Hercules128.pngbin0 -> 19237 bytes
-rw-r--r--tools/doxygen/Hercules48.pngbin0 -> 4954 bytes
-rw-r--r--tools/doxygen/Makefile.in70
-rw-r--r--tools/doxygen/doxygen.conf505
-rw-r--r--tools/doxygen/footer.html21
-rw-r--r--tools/doxygen/header.html55
-rw-r--r--tools/doxygen/layoutFile.xml194
-rw-r--r--tools/doxygen/pages_index.html39
-rw-r--r--tools/doxygen/style.css1440
-rw-r--r--tools/item_merge.lua2
-rw-r--r--tools/itemdb_jobmask_converter.pl100
-rw-r--r--tools/skilldbconverter.php1201
17 files changed, 4958 insertions, 165 deletions
diff --git a/tools/HPMHookGen/HPMDataCheckGen.pl b/tools/HPMHookGen/HPMDataCheckGen.pl
index 3965668d9..e78a7bd93 100644
--- a/tools/HPMHookGen/HPMDataCheckGen.pl
+++ b/tools/HPMHookGen/HPMDataCheckGen.pl
@@ -3,7 +3,7 @@
# This file is part of Hercules.
# http://herc.ws - http://github.com/HerculesWS/Hercules
#
-# Copyright (C) 2014-2015 Hercules Dev Team
+# 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
@@ -42,11 +42,13 @@ foreach my $file (@files) {
my @filepath = split(/[\/\\]/, $data->{compounddef}->{$filekey}->{location}->[0]->{file});
my $foldername = uc($filepath[-2]);
next if $filepath[-1] eq "HPM.h"; # Skip the HPM core, plugins don't need it
- my $filename = uc($filepath[-1]); $filename =~ s/-/_/g; $filename =~ s/\.[^.]*$//;
+ my $filename = uc($filepath[-1]); $filename =~ s/[.-]/_/g; $filename =~ s/\.[^.]*$//;
my $plugintypes = 'SERVER_TYPE_UNKNOWN';
if ($foldername eq 'COMMON') {
- if ($filename eq 'MAPINDEX') {
+ if ($filename eq 'MAPINDEX_H') {
$plugintypes = 'SERVER_TYPE_CHAR|SERVER_TYPE_MAP';
+ } elsif ($filename eq 'GRFIO_H') {
+ $plugintypes = 'SERVER_TYPE_MAP';
} else {
$plugintypes = 'SERVER_TYPE_ALL';
}
@@ -57,7 +59,7 @@ foreach my $file (@files) {
name => $data->{compounddef}->{$filekey}->{compoundname}->[0],
type => $plugintypes,
};
- my $name = "${foldername}_${filename}_H";
+ my $name = "${foldername}_${filename}";
push @{ $out{$name} }, $symboldata;
}
@@ -91,6 +93,8 @@ print FH <<"EOF";
* as it will get overwritten.
*/
+/* GENERATED FILE DO NOT EDIT */
+
#ifndef HPM_DATA_CHECK_H
#define HPM_DATA_CHECK_H
diff --git a/tools/HPMHookGen/HPMHookGen.pl b/tools/HPMHookGen/HPMHookGen.pl
index 6f7f9e0a4..35c531ea8 100755
--- a/tools/HPMHookGen/HPMHookGen.pl
+++ b/tools/HPMHookGen/HPMHookGen.pl
@@ -3,7 +3,7 @@
# This file is part of Hercules.
# http://herc.ws - http://github.com/HerculesWS/Hercules
#
-# Copyright (C) 2013-2015 Hercules Dev Team
+# Copyright (C) 2013-2017 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
@@ -40,7 +40,7 @@ sub parse($$) {
$p =~ s/^.*?\)\((.*)\).*$/$1/; # Clean up extra parentheses )(around the arglist)
# Retrieve return type
- unless ($d =~ /^(.+)\(\*\s*[a-zA-Z0-9_]+_interface::([^\)]+)\s*\)\s*\(.*\)$/) {
+ unless ($d =~ /^(.+)\(\*\s*[a-zA-Z0-9_]+_interface(?:_private)?::([^\)]+)\s*\)\s*\(.*\)$/) {
print "Error: unable to parse '$d'\n";
return {};
}
@@ -148,7 +148,7 @@ sub parse($$) {
$type1 .= "$1 ";
next;
}
- if ($current =~ /^(struct|enum)\s+(.*)$/) { # enum and struct names
+ if ($current =~ /^(struct|enum|union)\s+(.*)$/) { # union, enum and struct names
$current = $2 // '';
$type1 .= "$1 ";
}
@@ -187,28 +187,29 @@ sub parse($$) {
$post_code = "va_end(${callvar});";
$var = '';
$variadic = 1;
- } elsif (!$indirectionlvl) { # Increase indirection level when necessary
+ } else { # Increase indirection level when necessary
$dereference = '*';
$addressof = '&';
}
$indirectionlvl++ if ($array); # Arrays are pointer, no matter how cute you write them
push(@args, {
- var => $var,
- callvar => $callvar,
- type => $type1.$array.$type2,
- orig => $type1 eq '...' ? '...' : trim("$type1 $indir$var$array $type2"),
- indir => $indirectionlvl,
- hookf => $type1 eq '...' ? "va_list ${var}" : trim("$type1 $dereference$indir$var$array $type2"),
- hookc => trim("$addressof$callvar"),
- origc => trim($callvar),
- pre => $pre_code,
- post => $post_code,
+ var => $var,
+ callvar => $callvar,
+ type => $type1.$array.$type2,
+ orig => $type1 eq '...' ? '...' : trim("$type1 $indir$var$array $type2"),
+ indir => $indirectionlvl,
+ hookpref => $type1 eq '...' ? "va_list ${var}" : trim("$type1 $dereference$indir$var$array $type2"),
+ hookpostf => $type1 eq '...' ? "va_list ${var}" : trim("$type1 $indir$var$array $type2"),
+ hookprec => trim("$addressof$callvar"),
+ hookpostc => trim("$callvar"),
+ origc => trim($callvar),
+ pre => $pre_code,
+ post => $post_code,
});
$lastvar = $var;
}
- my $rtmemset = 0;
my $rtinit = '';
foreach ($rt) { # Decide initialization for the return value
my $x = $_;
@@ -237,13 +238,16 @@ sub parse($$) {
$rtinit = ' = HCS_STATUS_FAIL';
} elsif ($x =~ /^enum\s+bg_queue_types$/) { # Known enum bg_queue_types
$rtinit = ' = BGQT_INVALID';
- } elsif ($x =~ /^(?:enum\s+)?DBOptions$/) { # Known enum DBOptions
+ } elsif ($x =~ /^enum\s+parsefunc_rcode$/) { # Known enum parsefunc_rcode
+ $rtinit = ' = PACKET_UNKNOWN';
+ } elsif ($x =~ /^enum\s+DBOptions$/) { # Known enum DBOptions
$rtinit = ' = DB_OPT_BASE';
+ } elsif ($x =~ /^enum\s+thread_priority$/) { # Known enum thread_priority
+ $rtinit = ' = THREADPRIO_NORMAL';
} elsif ($x eq 'DBComparator' or $x eq 'DBHasher' or $x eq 'DBReleaser') { # DB function pointers
$rtinit = ' = NULL';
- } elsif ($x =~ /^struct\s+.*$/ or $x eq 'DBData' or $x eq 'DBKey') { # Structs and unions
- $rtinit = '';
- $rtmemset = 1;
+ } elsif ($x =~ /^(?:struct|union)\s+.*$/) { # Structs and unions
+ $rtinit = ' = { 0 }';
} elsif ($x =~ /^float|double$/) { # Floating point variables
$rtinit = ' = 0.';
} elsif ($x =~ /^(?:(?:un)?signed\s+)?(?:char|int|long|short)$/
@@ -265,7 +269,6 @@ sub parse($$) {
vname => $variadic ? "v$name" : $name,
type => $rt,
typeinit => $rtinit,
- memset => $rtmemset,
variadic => $variadic,
args => \@args,
notes => $notes,
@@ -273,6 +276,7 @@ sub parse($$) {
}
my %key2original;
+my %key2pointer;
my @files = grep { -f } glob 'doxyoutput/xml/*interface*.xml';
my %ifs;
my %keys = (
@@ -291,6 +295,7 @@ foreach my $file (@files) { # Loop through the xml files
my $loc = $data->{compounddef}->{$filekey}->{location}->[0];
next unless $loc->{file} =~ /src\/(map|char|login|common)\//;
next if $loc->{file} =~ /\/HPM.*\.h/; # Don't allow hooking into the HPM itself
+ next if $loc->{file} =~ /\/memmgr\.h/; # Don't allow hooking into the memory manager
my $servertype = $1;
my $key = $data->{compounddef}->{$filekey}->{compoundname}->[0];
my $original = $key;
@@ -302,14 +307,18 @@ foreach my $file (@files) { # Loop through the xml files
} elsif ($key eq "mapindex_interface") {
push @servertypes, ("map", "char"); # Currently not used by the login server
$servermask = 'SERVER_TYPE_MAP|SERVER_TYPE_CHAR';
+ } elsif ($key eq "grfio_interface") {
+ push @servertypes, ("map"); # Currently not used by the login and char servers
+ $servermask = 'SERVER_TYPE_MAP';
} else {
push @servertypes, ("map", "char", "login");
$servermask = 'SERVER_TYPE_ALL';
}
my @filepath = split(/[\/\\]/, $loc->{file});
my $foldername = uc($filepath[-2]);
- my $filename = uc($filepath[-1]); $filename =~ s/-/_/g; $filename =~ s/\.[^.]*$//;
- my $guardname = "${foldername}_${filename}_H";
+ my $filename = uc($filepath[-1]); $filename =~ s/[.-]/_/g; $filename =~ s/\.[^.]*$//;
+ my $guardname = "${foldername}_${filename}";
+ my $private = $key =~ /_interface_private$/ ? 1 : 0;
# Some known interfaces with different names
if ($key =~ /battleground/) {
@@ -330,8 +339,6 @@ foreach my $file (@files) { # Loop through the xml files
$key = "chr";
} elsif ($key eq "db_interface") {
$key = "DB";
- } elsif ($key eq "malloc_interface") {
- $key = "iMalloc";
} elsif ($key eq "socket_interface") {
$key = "sockt";
} elsif ($key eq "sql_interface") {
@@ -344,6 +351,9 @@ foreach my $file (@files) { # Loop through the xml files
} else {
$key =~ s/_interface//;
}
+ $key =~ s/^(.*)_private$/PRIV__$1/ if $private;
+ my $pointername = $key;
+ $pointername =~ s/^PRIV__(.*)$/$1->p/ if $private;
my $sectiondef = $data->{compounddef}->{$filekey}->{sectiondef};
foreach my $v (@$sectiondef) { # Loop through the sections
@@ -353,10 +363,16 @@ foreach my $file (@files) { # Loop through the xml files
my $bstart = $b->{location}->[0]->{bodystart} || $b->{location}->[0]->{line};
$astart <=> $bstart
} @$memberdef) { # Loop through the members
+ next unless $f->{kind} eq 'variable'; # Skip macros
my $t = $f->{argsstring}->[0];
+ my $def = $f->{definition}->[0];
+ if ($f->{type}->[0] =~ /^\s*LoginParseFunc\s*\*\s*$/) {
+ $t = ')(int fd, struct login_session_data *sd)'; # typedef LoginParseFunc
+ $def =~ s/^LoginParseFunc\s*\*\s*(.*)$/enum parsefunc_rcode(* $1) (int fd, struct login_session_data *sd)/;
+ }
next unless ref $t ne 'HASH' and $t =~ /^[^\[]/; # If it's not a string, or if it starts with an array subscript, we can skip it
- my $if = parse($t, $f->{definition}->[0]);
+ my $if = parse($t, $def);
next unless scalar keys %$if; # If it returns an empty hash reference, an error must've occurred
# Skip variadic functions, we only allow hooks on their arglist equivalents.
@@ -407,10 +423,10 @@ foreach my $file (@files) { # Loop through the xml files
$if->{postcall} .= ', ';
}
$if->{handlerdef} .= $arg->{orig};
- $if->{predef} .= $arg->{hookf};
- $if->{precall} .= $arg->{hookc};
- $if->{postdef} .= $arg->{hookf};
- $if->{postcall} .= $arg->{hookc};
+ $if->{predef} .= $arg->{hookpref};
+ $if->{precall} .= $arg->{hookprec};
+ $if->{postdef} .= $arg->{hookpostf};
+ $if->{postcall} .= $arg->{hookpostc};
$if->{origcall} .= $arg->{origc};
$i++; $j++;
}
@@ -431,6 +447,7 @@ foreach my $file (@files) { # Loop through the xml files
$if->{origcall} .= ");";
$key2original{$key} = $original;
+ $key2pointer{$key} = $pointername;
$ifs{$key} = [] unless $ifs{$key};
push(@{ $ifs{$key} }, $if);
}
@@ -442,35 +459,18 @@ foreach my $file (@files) { # Loop through the xml files
$fileguards{$key} = {
guard => $guardname,
type => $servermask,
+ private => $private,
};
}
my $year = (localtime)[5] + 1900;
-foreach my $servertype (keys %keys) {
- my $keysref = $keys{$servertype};
- # Some interfaces use different names
- my %exportsymbols = map {
- $_ => &{ sub ($) {
- return 'battlegrounds' if $_ =~ /^bg$/;
- return 'pc_groups' if $_ =~ /^pcg$/;
- return $_;
- }}($_);
- } @$keysref;
-
- my ($maxlen, $idx) = (0, 0);
- my $fname;
-
- if ($servertype eq 'all') {
- $fname = "../../src/common/HPMSymbols.inc.h";
- open(FH, ">", $fname)
- or die "cannot open > $fname: $!";
- print FH <<"EOF";
+my $fileheader = <<"EOF";
/**
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2015-$year Hercules Dev Team
+ * Copyright (C) 2013-$year 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
@@ -491,10 +491,35 @@ foreach my $servertype (keys %keys) {
* as it will get overwritten.
*/
+/* GENERATED FILE DO NOT EDIT */
+EOF
+
+foreach my $servertype (keys %keys) {
+ my $keysref = $keys{$servertype};
+ # Some interfaces use different names
+ my %exportsymbols = map {
+ $_ => &{ sub ($) {
+ return 'battlegrounds' if $_ =~ /^bg$/;
+ return 'pc_groups' if $_ =~ /^pcg$/;
+ return $_;
+ }}($_);
+ } @$keysref;
+
+ my ($maxlen, $idx) = (0, 0);
+ my $fname;
+
+ if ($servertype eq 'all') {
+ $fname = "../../src/common/HPMSymbols.inc.h";
+ open(FH, ">", $fname)
+ or die "cannot open > $fname: $!";
+
+ print FH <<"EOF";
+$fileheader
#if !defined(HERCULES_CORE)
EOF
foreach my $key (@$keysref) {
+ next if $fileguards{$key}->{private};
print FH <<"EOF";
#ifdef $fileguards{$key}->{guard} /* $key */
struct $key2original{$key} *$key;
@@ -510,9 +535,11 @@ HPExport const char *HPM_shared_symbols(int server_type)
EOF
foreach my $key (@$keysref) {
+ next if $fileguards{$key}->{private};
print FH <<"EOF";
#ifdef $fileguards{$key}->{guard} /* $key */
-if ((server_type&($fileguards{$key}->{type})) && !HPM_SYMBOL("$exportsymbols{$key}", $key)) return "$exportsymbols{$key}";
+ if ((server_type&($fileguards{$key}->{type})) != 0 && !HPM_SYMBOL("$exportsymbols{$key}", $key))
+ return "$exportsymbols{$key}";
#endif // $fileguards{$key}->{guard}
EOF
}
@@ -522,6 +549,36 @@ EOF
}
EOF
close FH;
+
+ $fname = "../../src/plugins/HPMHooking/HPMHooking.Defs.inc";
+ open(FH, ">", $fname)
+ or die "cannot open > $fname: $!";
+
+ print FH <<"EOF";
+$fileheader
+EOF
+
+ foreach my $key (@$keysref) {
+ print FH <<"EOF";
+#ifdef $fileguards{$key}->{guard} /* $key */
+EOF
+
+ foreach my $if (@{ $ifs{$key} }) {
+ my ($predef, $postdef) = ($if->{predef}, $if->{postdef});
+ $predef =~ s/preHookFunc/HPMHOOK_pre_${key}_$if->{name}/;
+ $postdef =~ s/postHookFunc/HPMHOOK_post_${key}_$if->{name}/;
+
+ print FH <<"EOF";
+typedef $predef
+typedef $postdef
+EOF
+ }
+ print FH <<"EOF";
+#endif // $fileguards{$key}->{guard}
+EOF
+ }
+ close FH;
+
next;
}
@@ -530,43 +587,20 @@ EOF
or die "cannot open > $fname: $!";
print FH <<"EOF";
-/**
- * This file is part of Hercules.
- *
- * Copyright (C) 2013-$year 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/>.
- */
-
-/*
- * NOTE: This file was auto-generated and should never be manually edited,
- * as it will get overwritten.
- */
-
+$fileheader
struct HookingPointData HookingPoints[] = {
EOF
foreach my $key (@$keysref) {
- print FH "/* ".$key." */\n";
+ print FH "/* $key2original{$key} */\n";
foreach my $if (@{ $ifs{$key} }) {
print FH <<"EOF";
- { HP_POP($key\->$if->{name}, $if->{hname}) },
+ { HP_POP($key2pointer{$key}\->$if->{name}, $if->{hname}) },
EOF
$idx += 2;
- $maxlen = length($key."->".$if->{name}) if( length($key."->".$if->{name}) > $maxlen );
+ $maxlen = length($key."->".$if->{name}) if (length($key."->".$if->{name}) > $maxlen);
}
}
print FH <<"EOF";
@@ -581,36 +615,12 @@ EOF
or die "cannot open > $fname: $!";
print FH <<"EOF";
-/**
- * This file is part of Hercules.
- * http://herc.ws - http://github.com/HerculesWS/Hercules
- *
- * Copyright (C) 2013-$year 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/>.
- */
-
-/*
- * NOTE: This file was auto-generated and should never be manually edited,
- * as it will get overwritten.
- */
-
+$fileheader
EOF
foreach my $key (@$keysref) {
print FH <<"EOF";
-memcpy(&HPMHooks.source.$key, $key, sizeof(struct $key2original{$key}));
+HPMHooks.source.$key = *$key2pointer{$key};
EOF
}
close FH;
@@ -620,31 +630,7 @@ EOF
or die "cannot open > $fname: $!";
print FH <<"EOF";
-/**
- * This file is part of Hercules.
- * http://herc.ws - http://github.com/HerculesWS/Hercules
- *
- * Copyright (C) 2013-$year 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/>.
- */
-
-/*
- * NOTE: This file was auto-generated and should never be manually edited,
- * as it will get overwritten.
- */
-
+$fileheader
struct {
EOF
@@ -695,36 +681,12 @@ EOF
or die "cannot open > $fname: $!";
print FH <<"EOF";
-/**
- * This file is part of Hercules.
- * http://herc.ws - http://github.com/HerculesWS/Hercules
- *
- * Copyright (C) 2013-$year 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/>.
- */
-
-/*
- * NOTE: This file was auto-generated and should never be manually edited,
- * as it will get overwritten.
- */
-
+$fileheader
EOF
foreach my $key (@$keysref) {
print FH <<"EOF";
-/* $key */
+/* $key2original{$key} */
EOF
foreach my $if (@{ $ifs{$key} }) {
@@ -732,7 +694,6 @@ EOF
unless ($if->{type} eq 'void') {
$initialization = "\n\t$if->{type} retVal___$if->{typeinit};";
- $initialization .= "\n\tmemset(&retVal___, '\\0', sizeof($if->{type}));" if $if->{memset};
}
$beforeblock3 .= "\n\t\t\t$_" foreach (@{ $if->{before} });
@@ -744,14 +705,14 @@ EOF
print FH <<"EOF";
$if->{handlerdef} {$if->{notes}
int hIndex = 0;${initialization}
- if( HPMHooks.count.$if->{hname}_pre ) {
+ if (HPMHooks.count.$if->{hname}_pre > 0) {
$if->{predef}
*HPMforce_return = false;
- for(hIndex = 0; hIndex < HPMHooks.count.$if->{hname}_pre; hIndex++ ) {$beforeblock3
+ for (hIndex = 0; hIndex < HPMHooks.count.$if->{hname}_pre; hIndex++) {$beforeblock3
preHookFunc = HPMHooks.list.$if->{hname}_pre[hIndex].func;
$if->{precall}$afterblock3
}
- if( *HPMforce_return ) {
+ if (*HPMforce_return) {
*HPMforce_return = false;
return$retval;
}
@@ -759,9 +720,9 @@ $if->{handlerdef} {$if->{notes}
{$beforeblock2
$if->{origcall}$afterblock2
}
- if( HPMHooks.count.$if->{hname}_post ) {
+ if (HPMHooks.count.$if->{hname}_post > 0) {
$if->{postdef}
- for(hIndex = 0; hIndex < HPMHooks.count.$if->{hname}_post; hIndex++ ) {$beforeblock3
+ for (hIndex = 0; hIndex < HPMHooks.count.$if->{hname}_post; hIndex++) {$beforeblock3
postHookFunc = HPMHooks.list.$if->{hname}_post[hIndex].func;
$if->{postcall}$afterblock3
}
diff --git a/tools/ci/retry.sh b/tools/ci/retry.sh
new file mode 100755
index 000000000..6e79af1d5
--- /dev/null
+++ b/tools/ci/retry.sh
@@ -0,0 +1,33 @@
+#!/bin/bash
+
+# This file is part of Hercules.
+# http://herc.ws - http://github.com/HerculesWS/Hercules
+#
+# Copyright (C) 2016 Hercules Dev Team
+# Copyright (C) 2016 Haru <haru@herc.ws>
+#
+# 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/>.
+
+n=0
+
+while true; do
+ $@ && break
+ if [[ $n -ge 5 ]]; then
+ exit -1
+ fi
+ WAITTIME=$((2**n))
+ echo "Execution of $@ failed. Retrying in $WAITTIME seconds..."
+ sleep $WAITTIME
+ n=$((n+1))
+done
diff --git a/tools/ci/travis.sh b/tools/ci/travis.sh
new file mode 100755
index 000000000..9a6322df6
--- /dev/null
+++ b/tools/ci/travis.sh
@@ -0,0 +1,202 @@
+#!/bin/bash
+
+# This file is part of Hercules.
+# http://herc.ws - http://github.com/HerculesWS/Hercules
+#
+# Copyright (C) 2014-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/>.
+
+# Base Author: Haru @ http://herc.ws
+
+MODE="$1"
+shift
+
+function foo {
+ for i in "$@"; do
+ echo "> $i"
+ done
+}
+
+function usage {
+ echo "usage:"
+ echo " $0 createdb <dbname> [dbuser] [dbpassword] [dbhost]"
+ echo " $0 importdb <dbname> [dbuser] [dbpassword] [dbhost]"
+ echo " $0 build [configure args]"
+ echo " $0 test <dbname> [dbuser] [dbpassword] [dbhost]"
+ echo " $0 getplugins"
+ exit 1
+}
+
+function aborterror {
+ echo $@
+ exit 1
+}
+
+function run_server {
+ echo "Running: $1 --run-once $2"
+ $1 --run-once $2 2>runlog.txt
+ export errcode=$?
+ export teststr=$(cat runlog.txt)
+ if [[ -n "${teststr}" ]]; then
+ echo "Errors found in running server $1."
+ cat runlog.txt
+ aborterror "Errors found in running server $1."
+ else
+ echo "No errors found for server $1."
+ fi
+ if [ ${errcode} -ne 0 ]; then
+ echo "server $1 terminated with exit code ${errcode}"
+ aborterror "Test failed"
+ fi
+}
+
+function run_test {
+ echo "Running: test_$1"
+ ./test_$1 2>runlog.txt
+ export errcode=$?
+ export teststr=$(cat runlog.txt)
+ if [[ -n "${teststr}" ]]; then
+ echo "Errors found in running test $1."
+ cat runlog.txt
+ aborterror "Errors found in running test $1."
+ else
+ echo "No errors found for test $1."
+ fi
+ if [ ${errcode} -ne 0 ]; then
+ echo "test $1 terminated with exit code ${errcode}"
+ aborterror "Test failed"
+ fi
+}
+
+# Defaults
+DBNAME=ragnarok
+DBUSER=ragnarok
+DBPASS=ragnarok
+DBHOST=localhost
+
+case "$MODE" in
+ createdb|importdb|test)
+ if [ -z "$1" ]; then
+ usage
+ fi
+ DBNAME="$1"
+ if [ -n "$2" ]; then
+ DBUSER_ARG="-u $2"
+ DBUSER="$2"
+ fi
+ if [ -n "$3" ]; then
+ DBPASS_ARG="-p$3"
+ DBPASS="$3"
+ fi
+ if [ -n "$4" ]; then
+ DBHOST_ARG="-h $4"
+ DBHOST="$4"
+ fi
+ ;;
+esac
+
+case "$MODE" in
+ createdb)
+ echo "Creating database $DBNAME..."
+ mysql $DBUSER_ARG $DBPASS_ARG $DBHOST_ARG -e "create database $DBNAME;" || aborterror "Unable to create database."
+ ;;
+ importdb)
+ echo "Importing tables into $DBNAME..."
+ mysql $DBUSER_ARG $DBPASS_ARG $DBHOST_ARG $DBNAME < sql-files/main.sql || aborterror "Unable to import main database."
+ mysql $DBUSER_ARG $DBPASS_ARG $DBHOST_ARG $DBNAME < sql-files/logs.sql || aborterror "Unable to import logs database."
+ ;;
+ build)
+ (cd tools && ./validateinterfaces.py silent) || aborterror "Interface validation error."
+ ./configure $@ || (cat config.log && aborterror "Configure error, aborting build.")
+ make -j3 || aborterror "Build failed."
+ make plugins -j3 || aborterror "Build failed."
+ make plugin.script_mapquit -j3 || aborterror "Build failed."
+ make test || aborterror "Build failed."
+ ;;
+ test)
+ cat > conf/travis_sql_connection.conf << EOF
+sql_connection: {
+ //default_codepage: ""
+ //case_sensitive: false
+ db_hostname: "$DBHOST"
+ db_username: "$DBUSER"
+ db_password: "$DBPASS"
+ db_database: "$DBNAME"
+ //codepage:""
+}
+EOF
+ [ $? -eq 0 ] || aborterror "Unable to write database configuration, aborting tests."
+ cat > conf/import/login-server.conf << EOF
+login_configuration: {
+ account: {
+ @include "conf/travis_sql_connection.conf"
+ ipban: {
+ @include "conf/travis_sql_connection.conf"
+ }
+ }
+}
+EOF
+ [ $? -eq 0 ] || aborterror "Unable to override login-server configuration, aborting tests."
+ cat > conf/import/char-server.conf << EOF
+char_configuration: {
+ @include "conf/travis_sql_connection.conf"
+}
+EOF
+ [ $? -eq 0 ] || aborterror "Unable to override char-server configuration, aborting tests."
+ cat > conf/import/map-server.conf << EOF
+map_configuration: {
+ @include "conf/travis_sql_connection.conf"
+}
+EOF
+ [ $? -eq 0 ] || aborterror "Unable to override map-server configuration, aborting tests."
+ cat > conf/import/inter-server.conf << EOF
+inter_configuration: {
+ log: {
+ @include "conf/travis_sql_connection.conf"
+ }
+}
+EOF
+ [ $? -eq 0 ] || aborterror "Unable to override inter-server configuration, aborting tests."
+ ARGS="--load-script npc/dev/test.txt "
+ ARGS="--load-plugin script_mapquit $ARGS --load-script npc/dev/ci_test.txt"
+ PLUGINS="--load-plugin HPMHooking --load-plugin sample"
+ echo "run tests"
+ # run_test spinlock # Not running the spinlock test for the time being (too time consuming)
+ run_test libconfig
+ echo "run all servers without HPM"
+ run_server ./login-server
+ run_server ./char-server
+ run_server ./map-server "$ARGS"
+ echo "run all servers wit HPM"
+ run_server ./login-server "$PLUGINS"
+ run_server ./char-server "$PLUGINS"
+ run_server ./map-server "$ARGS $PLUGINS"
+ ;;
+ getplugins)
+ echo "Cloning plugins repository..."
+ # Nothing to clone right now, all relevant plugins are part of the repository.
+ #git clone http://github.com/HerculesWS/StaffPlugins.git || aborterror "Unable to fetch plugin repository"
+ #if [ -f StaffPlugins/Haru/script_mapquit/script_mapquit.c -a -f StaffPlugins/Haru/script_mapquit/examples/ci_test.txt ]; then
+ # pushd src/plugins || aborterror "Unable to enter plugins directory."
+ # ln -s ../../StaffPlugins/Haru/script_mapquit/script_mapquit.c ./
+ # popd
+ #else
+ # echo "Plugin not found, skipping advanced tests."
+ #fi
+ ;;
+ *)
+ usage
+ ;;
+esac
diff --git a/tools/configconverter.pl b/tools/configconverter.pl
new file mode 100755
index 000000000..dc511aaef
--- /dev/null
+++ b/tools/configconverter.pl
@@ -0,0 +1,968 @@
+#!/usr/bin/perl
+#
+# This file is part of Hercules.
+# http://herc.ws - http://github.com/HerculesWS/Hercules
+#
+# Copyright (C) 2016 Hercules Dev Team
+# Copyright (C) 2016 Haru
+#
+# 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/>.
+
+use strict;
+use warnings;
+
+my $silent = 0;
+my $confpath = 'conf';
+
+sub parse_config($$) {
+ my ($input, $defaults) = @_;
+
+ my %output = ();
+
+ for my $line (<$input>) {
+ chomp $line;
+ $line =~ s/^\s*//; $line =~ s/\s*$//;
+ if ($line =~ /^([a-z0-9A-Z_.]+)\s*:\s*(.*)$/) {
+ my ($variable, $value) = ($1, $2);
+ if ($defaults->{$variable}) {
+ next if $defaults->{$variable}->{parse}->($variable, $value, $defaults->{$variable}, \%output);
+ print "Error: Invalid value for setting '$variable: $value'\n";
+ next;
+ } else {
+ print "Found unhandled configuration setting: '$variable: $value'\n";
+ next;
+ }
+ } elsif ($line =~ m{^\s*(?://.*)?$}) {
+ next;
+ } else {
+ print "Error: Unable to parse line '$line'\n";
+ }
+ }
+ return \%output;
+}
+
+sub cfg_add($$$$) {
+ my ($variable, $value, $default, $output) = @_;
+ $output->{$variable} = {value => $value, print => $default->{print}, path => $default->{path}} unless $value eq $default->{default};
+}
+
+sub cfg_append($$$$) {
+ my ($variable, $value, $default, $output) = @_;
+ for my $default_value (@{$default->{default}}) {
+ return if $value eq $default_value;
+ }
+ $output->{$variable} = {value => [], print => $default->{print}, path => $default->{path}} unless $output->{$variable};
+ push(@{$output->{$variable}->{value}}, $value);
+}
+
+sub parsecfg_string_sub($$$$$) {
+ my ($variable, $value, $default, $output, $func) = @_;
+ if ($value =~ m{\s*"((?:\\"|.)*)"\s*(?://.*)?$}i) {
+ $func->($variable, $1, $default, $output);
+ return 1;
+ } elsif ($value =~ m{\s*((?:\\"|.)*)\s*(?://.*)?$}i) {
+ $func->($variable, $1, $default, $output);
+ return 1;
+ }
+ return 0;
+}
+
+sub parsecfg_string($$$$) {
+ my ($variable, $value, $default, $output) = @_;
+ return parsecfg_string_sub($variable, $value, $default, $output, \&cfg_add);
+}
+
+sub parsecfg_stringarr($$$$) {
+ my ($variable, $value, $default, $output) = @_;
+ return parsecfg_string_sub($variable, $value, $default, $output, \&cfg_append);
+}
+
+sub parsecfg_int($$$$) {
+ my ($variable, $value, $default, $output) = @_;
+ if ($value =~ m{\s*(-?[0-9]+)\s*(?://.*)?$}) {
+ cfg_add($variable, int $1, $default, $output);
+ return 1;
+ } elsif ($value =~ m{\s*(0x[0-9A-F]+)\s*(?://.*)?$}) {
+ cfg_add($variable, hex $1, $default, $output);
+ return 1;
+ } elsif ($value =~ m{\s*(no|false|off)\s*(?://.*)?$}) {
+ cfg_add($variable, 0, $default, $output);
+ return 1;
+ }
+ return 0;
+}
+
+sub parsecfg_bool($$$$) {
+ my ($variable, $value, $default, $output) = @_;
+ if ($value =~ m{\s*(yes|true|1|on)\s*(?://.*)?$}i) {
+ cfg_add($variable, "true", $default, $output);
+ return 1;
+ } elsif ($value =~ m{\s*(no|false|0|off)\s*(?://.*)?$}i) {
+ cfg_add($variable, "false", $default, $output);
+ return 1;
+ }
+ return 0;
+}
+
+sub print_config($) {
+ my ($config) = @_;
+
+ for my $variable (keys %$config) {
+ my $fullpath = $config->{$variable}->{path};
+ $fullpath .= $variable if $fullpath =~ m{[:/]$};
+ my ($filename, $configpath) = split(/:/, $fullpath, 2);
+ next unless $filename and $configpath;
+ my @path = split(/\//, $configpath);
+ next unless @path;
+
+ my %output = ();
+
+ my $setting = \%output;
+ while (scalar @path > 1) {
+ my $nodename = shift @path;
+ $setting->{$nodename} = {print => \&printcfg_tree, value => {}} unless $setting->{$nodename};
+ $setting = $setting->{$nodename}->{value};
+ }
+ $setting->{$path[0]} = {print => $config->{$variable}->{print}, value => $config->{$variable}->{value}};
+ verbose("- Found setting: '$variable'.\n Please manually move the setting to '$filename.conf' as in the following example:\n",
+ "- '$filename.conf': (from $variable)\n");
+ $output{$_}->{print}->($_, $output{$_}->{value}, 0) for keys %output;
+ }
+}
+
+sub indent($$) {
+ my ($message, $nestlevel) = @_;
+ return print "\t" x ($nestlevel + 1) . $message;
+}
+
+sub printcfg_tree($$$) {
+ my ($variable, $value, $nestlevel) = @_;
+
+ indent("$variable: {\n", $nestlevel);
+ $value->{$_}{print}->($_, $value->{$_}{value}, $nestlevel + 1) for keys %$value;
+ indent("}\n", $nestlevel);
+}
+
+sub printcfg_nil($$$) {
+}
+
+sub printcfg_string($$$) {
+ my ($variable, $value, $nestlevel) = @_;
+
+ indent("$variable: \"$value\"\n", $nestlevel);
+}
+
+sub printcfg_int($$$) {
+ my ($variable, $value, $nestlevel) = @_;
+
+ indent("$variable: $value\n", $nestlevel);
+}
+
+sub printcfg_hexint($$$) {
+ my ($variable, $value, $nestlevel) = @_;
+
+ indent(sprintf("%s: 0x%x\n", $variable, $value), $nestlevel);
+}
+
+sub printcfg_bool($$$) {
+ my ($variable, $value, $nestlevel) = @_;
+
+ indent("$variable: $value\n", $nestlevel);
+}
+
+sub printcfg_point($$$) {
+ my ($variable, $value, $nestlevel) = @_;
+
+ indent("$variable: {\n", $nestlevel);
+
+ my @point = split(/,/, $value, 3);
+ indent("map: \"$point[0]\"\n", $nestlevel + 1);
+ indent("x: $point[1]\n", $nestlevel + 1);
+ indent("y: $point[2]\n", $nestlevel + 1);
+
+ indent("}\n", $nestlevel);
+}
+
+sub printcfg_items($$$) {
+ my ($variable, $value, $nestlevel) = @_;
+
+ indent("$variable: (\n", $nestlevel);
+
+ my @items = split(/,/, $value);
+ while (scalar @items >= 3) {
+ my $id = shift @items;
+ my $amount = shift @items;
+ my $stackable = (shift @items) ? "true" : "false";
+ indent("{\n", $nestlevel);
+ indent("id: $id\n", $nestlevel + 1);
+ indent("amount: $amount\n", $nestlevel + 1);
+ indent("stackable: $stackable\n", $nestlevel + 1);
+ indent("},\n", $nestlevel);
+ }
+
+ indent(")\n", $nestlevel);
+}
+
+sub printcfg_md5hash($$$) {
+ my ($variable, $value, $nestlevel) = @_;
+
+ indent("$variable: (\n", $nestlevel);
+
+ for (@$value) {
+ my ($group_id, $hash) = split(/,/, $_, 2);
+ $group_id =~ s/\s*$//; $group_id =~ s/^\s*//;
+ $hash =~ s/\s*$//; $hash =~ s/^\s*//;
+
+ indent("{\n", $nestlevel);
+ indent("group_id: $group_id\n", $nestlevel + 1);
+ indent("hash: \"$hash\"\n", $nestlevel + 1);
+ indent("},\n", $nestlevel);
+ }
+
+ indent(")\n", $nestlevel);
+}
+
+sub printcfg_strlist($$$) {
+ my ($variable, $value, $nestlevel) = @_;
+
+ indent("$variable: (\n", $nestlevel);
+
+ for my $string (split(/,/, $value)) {
+ $string =~ s/\s*$//; $string =~ s/^\s*//;
+
+ indent("\"$string\",\n", $nestlevel + 1);
+ }
+
+ indent(")\n", $nestlevel);
+}
+
+sub process_conf($$) {
+ my ($files, $defaults) = @_;
+ my $found = 0;
+ for my $file (@$files) {
+ print "\nChecking $file...";
+ print " Ok\n" and next unless open my $FH, '<', $file; # File not found or already converted
+ print " Old file is still present\n";
+ my $output = parse_config($FH, $defaults);
+ close($FH);
+ my $count = scalar keys %$output;
+ print "$count non-default settings found.";
+ verbose(" The file '$file' is no longer used by Hercules and can be deleted.\n", "\n") and next unless $count;
+ verbose(" Please review and migrate the settings as described, then delete the file '$file', as it is no longer used by Hercules.\n", "\n");
+ print_config($output);
+ $found = 1;
+ }
+ return $found;
+}
+
+sub verbose($;$) {
+ my ($verbose_message, $silent_message) = @_;
+ return print $verbose_message unless $silent;
+ return print $silent_message if defined $silent_message;
+ return 1;
+}
+
+my @defaults = (
+ {
+ files => ['char-server.conf', 'import/char_conf.txt'],
+ settings => {
+ autosave_time => {parse => \&parsecfg_int, print => \&printcfg_int, path => "char-server:char_configuration/database/", default => 60},
+ bind_ip => {parse => \&parsecfg_string, print => \&printcfg_string, path => "char-server:char_configuration/inter/", default => "127.0.0.1"},
+ char_aegis_delete => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "char-server:char_configuration/player/deletion/use_aegis_delete", default => "false"},
+ char_del_delay => {parse => \&parsecfg_int, print => \&printcfg_int, path => "char-server:char_configuration/player/deletion/delay", default => 86400},
+ char_del_level => {parse => \&parsecfg_int, print => \&printcfg_int, path => "char-server:char_configuration/player/deletion/level", default => 0},
+ char_ip => {parse => \&parsecfg_string, print => \&printcfg_string, path => "char-server:char_configuration/inter/", default => "127.0.0.1"},
+ char_maintenance_min_group_id => {parse => \&parsecfg_int, print => \&printcfg_int, path => "char-server:char_configuration/permission/maintenance_min_group_id", default => 99},
+ char_name_letters => {parse => \&parsecfg_string, print => \&printcfg_string, path => "char-server:char_configuration/player/name/name_letters", default => "abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"},
+ char_name_option => {parse => \&parsecfg_int, print => \&printcfg_int, path => "char-server:char_configuration/player/name/name_option", default => 1},
+ char_new => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "char-server:char_configuration/permission/enable_char_creation", default => "true"},
+ char_new_display => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "char-server:char_configuration/permission/display_new", default => "false"},
+ char_port => {parse => \&parsecfg_int, print => \&printcfg_int, path => "char-server:char_configuration/inter/", default => 6121},
+ char_server_type => {parse => \&parsecfg_int, print => \&printcfg_int, path => "char-server:char_configuration/permission/server_type", default => 0},
+ console_silent => {parse => \&parsecfg_int, print => \&printcfg_int, path => "console:console/", default => 0},
+ db_path => {parse => \&parsecfg_string, print => \&printcfg_string, path => "char-server:char_configuration/database/", default => "db"},
+ fame_list_alchemist => {parse => \&parsecfg_int, print => \&printcfg_int, path => "char-server:char_configuration/fame/alchemist", default => 10},
+ fame_list_blacksmith => {parse => \&parsecfg_int, print => \&printcfg_int, path => "char-server:char_configuration/fame/blacksmith", default => 10},
+ fame_list_taekwon => {parse => \&parsecfg_int, print => \&printcfg_int, path => "char-server:char_configuration/fame/taekwon", default => 10},
+ gm_allow_group => {parse => \&parsecfg_int, print => \&printcfg_int, path => "char-server:char_configuration/permission/", default => -1},
+ guild_exp_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "char-server:char_configuration/", default => 100},
+ log_char => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "char-server:char_configuration/database/", default => "true"},
+ login_ip => {parse => \&parsecfg_string, print => \&printcfg_string, path => "char-server:char_configuration/inter/", default => "127.0.0.1"},
+ login_port => {parse => \&parsecfg_int, print => \&printcfg_int, path => "char-server:char_configuration/inter/", default => 6900},
+ max_connect_user => {parse => \&parsecfg_int, print => \&printcfg_int, path => "char-server:char_configuration/permission/", default => -1},
+ name_ignoring_case => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "char-server:char_configuration/player/name/", default => "false"},
+ passwd => {parse => \&parsecfg_string, print => \&printcfg_string, path => "char-server:char_configuration/inter/", default => "p1"},
+ pincode_changetime => {parse => \&parsecfg_int, print => \&printcfg_int, path => "char-server:char_configuration/pincode/change_time", default => 0},
+ pincode_charselect => {parse => \&parsecfg_int, print => \&printcfg_int, path => "char-server:char_configuration/pincode/request", default => 0},
+ pincode_enabled => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "char-server:char_configuration/pincode/enabled", default => "true"},
+ pincode_maxtry => {parse => \&parsecfg_int, print => \&printcfg_int, path => "char-server:char_configuration/pincode/max_tries", default => 3},
+ save_log => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "console:console/", default => "true"},
+ server_name => {parse => \&parsecfg_string, print => \&printcfg_string, path => "char-server:char_configuration/", default => "Hercules"},
+ start_items => {parse => \&parsecfg_string, print => \&printcfg_items, path => "char-server:char_configuration/player/new/", default => "1201,1,0,2301,1,0"},
+ start_point_pre => {parse => \&parsecfg_string, print => \&printcfg_point, path => "char-server:char_configuration/player/new/", default => "new_1-1,53,111"},
+ start_point_re => {parse => \&parsecfg_string, print => \&printcfg_point, path => "char-server:char_configuration/player/new/", default => "iz_int,97,90"},
+ start_zeny => {parse => \&parsecfg_int, print => \&printcfg_int, path => "char-server:char_configuration/player/new/zeny", default => 0},
+ stdout_with_ansisequence => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "console:console/", default => "false"},
+ timestamp_format => {parse => \&parsecfg_string, print => \&printcfg_string, path => "console:console/", default => "[%d/%b %H:%M]"},
+ unknown_char_name => {parse => \&parsecfg_string, print => \&printcfg_string, path => "char-server:char_configuration/player/name/", default => "Unknown"},
+ userid => {parse => \&parsecfg_string, print => \&printcfg_string, path => "char-server:char_configuration/inter/", default => "s1"},
+ wisp_server_name => {parse => \&parsecfg_string, print => \&printcfg_string, path => "char-server:char_configuration/", default => "Server"},
+ import => {parse => \&parsecfg_string, print => \&printcfg_nil, path => "", default => "conf/import/char_conf.txt"},
+ }
+ },
+ {
+ files => ['inter-server.conf', 'import/inter_conf.txt'],
+ settings => {
+ party_share_level => {parse => \&parsecfg_int, print => \&printcfg_int, path => "inter-server:inter_configuration/", default => 15},
+ log_inter => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "inter-server:inter_configuration/log/", default => "true"},
+ inter_log_filename => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/log/", default => "log/inter.log"},
+ mysql_reconnect_type => {parse => \&parsecfg_int, print => \&printcfg_int, path => "inter-server:inter_configuration/mysql_reconnect/type", default => 2},
+ mysql_reconnect_count => {parse => \&parsecfg_int, print => \&printcfg_int, path => "inter-server:inter_configuration/mysql_reconnect/count", default => 1},
+ log_login_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/login_db", default => "loginlog"},
+ char_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/", default => "char"},
+ interlog_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/", default => "interlog"},
+ ragsrvinfo_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/", default => "ragsrvinfo"},
+ acc_reg_num_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/registry/", default => "acc_reg_num_db"},
+ acc_reg_str_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/registry/", default => "acc_reg_str_db"},
+ char_reg_num_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/registry/", default => "char_reg_num_db"},
+ char_reg_str_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/registry/", default => "char_reg_str_db"},
+ global_acc_reg_num_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/registry/", default => "global_acc_reg_num_db"},
+ global_acc_reg_str_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/registry/", default => "global_acc_reg_str_db"},
+ hotkey_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "hotkey"},
+ scdata_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "sc_data"},
+ cart_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "cart_inventory"},
+ inventory_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "inventory"},
+ charlog_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "charlog"},
+ storage_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "storage"},
+ skill_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "skill"},
+ memo_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "memo"},
+ party_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "party"},
+ pet_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "pet"},
+ friend_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "friends"},
+ mail_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "mail"},
+ auction_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "auction"},
+ quest_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "quest"},
+ homunculus_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "homunculus"},
+ skill_homunculus_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "skill_homunculus"},
+ mercenary_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "mercenary"},
+ mercenary_owner_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "mercenary_owner"},
+ elemental_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "elemental"},
+ account_data_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "account_data"},
+ guild_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/guild/main_db", default => "guild"},
+ guild_alliance_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/guild/alliance_db", default => "guild_alliance"},
+ guild_castle_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/guild/castle_db", default => "guild_castle"},
+ guild_expulsion_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/guild/expulsion_db", default => "guild_expulsion"},
+ guild_member_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/guild/member_db", default => "guild_member"},
+ guild_skill_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/guild/skill_db", default => "guild_skill"},
+ guild_position_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/guild/position_db", default => "guild_position"},
+ guild_storage_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/guild/storage_db", default => "guild_storage"},
+ mapreg_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/", default => "mapreg"},
+ autotrade_merchants_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/", default => "autotrade_merchants"},
+ autotrade_data_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/", default => "autotrade_data"},
+ npc_market_data_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/", default => "npc_market_data"},
+ default_codepage => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/", default => ""},
+ 'sql.db_hostname' => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_hostname", default => "127.0.0.1"},
+ char_server_ip => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_hostname", default => "127.0.0.1"},
+ map_server_ip => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_hostname", default => "127.0.0.1"},
+ log_db_ip => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_hostname", default => "127.0.0.1"},
+ 'sql.db_port' => {parse => \&parsecfg_int, print => \&printcfg_int, path => "sql_connection:sql_connection/db_port", default => 3306},
+ char_server_port => {parse => \&parsecfg_int, print => \&printcfg_int, path => "sql_connection:sql_connection/db_port", default => 3306},
+ map_server_port => {parse => \&parsecfg_int, print => \&printcfg_int, path => "sql_connection:sql_connection/db_port", default => 3306},
+ log_db_port => {parse => \&parsecfg_int, print => \&printcfg_int, path => "sql_connection:sql_connection/db_port", default => 3306},
+ 'sql.db_username' => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_username", default => "ragnarok"},
+ char_server_id => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_username", default => "ragnarok"},
+ map_server_id => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_username", default => "ragnarok"},
+ log_db_id => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_username", default => "ragnarok"},
+ 'sql.db_password' => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_password", default => "ragnarok"},
+ char_server_pw => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_password", default => "ragnarok"},
+ map_server_pw => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_password", default => "ragnarok"},
+ log_db_pw => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_password", default => "ragnarok"},
+ 'sql.db_database' => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_database", default => "ragnarok"},
+ char_server_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_database", default => "ragnarok"},
+ map_server_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_database", default => "ragnarok"},
+ log_db_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_database", default => "ragnarok"},
+ 'sql.codepage' => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/codepage", default => ""},
+ log_codepage => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/codepage", default => ""},
+ interreg_db => {parse => \&parsecfg_string, print => \&printcfg_nil, path => "", default => "interreg"},
+ import => {parse => \&parsecfg_string, print => \&printcfg_nil, path => "", default => "conf/import/inter_conf.txt"},
+ }
+ },
+ {
+ files => ['login-server.conf', 'import/login_conf.txt'],
+ settings => {
+ bind_ip => {parse => \&parsecfg_string, print => \&printcfg_string, path => "login-server:login_configuration/inter/", default => "127.0.0.1"},
+ login_port => {parse => \&parsecfg_int, print => \&printcfg_int, path => "login-server:login_configuration/inter/", default => 6900},
+ timestamp_format => {parse => \&parsecfg_string, print => \&printcfg_string, path => "console:console/", default => "[%d/%b %H:%M]"},
+ stdout_with_ansisequence => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "console:console/", default => "false"},
+ console_silent => {parse => \&parsecfg_int, print => \&printcfg_int, path => "console:console/", default => 0},
+ new_account => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "login-server:login_configuration/account/", default => "true"},
+ new_acc_length_limit => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "login-server:login_configuration/account/", default => "true"},
+ allowed_regs => {parse => \&parsecfg_int, print => \&printcfg_int, path => "login-server:login_configuration/account/", default => 1},
+ time_allowed => {parse => \&parsecfg_int, print => \&printcfg_int, path => "login-server:login_configuration/account/", default => 10},
+ log_login => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "login-server:login_configuration/log/", default => "true"},
+ date_format => {parse => \&parsecfg_string, print => \&printcfg_string, path => "login-server:login_configuration/log/", default => "%Y-%m-%d %H:%M:%S"},
+ group_id_to_connect => {parse => \&parsecfg_int, print => \&printcfg_int, path => "login-server:login_configuration/permission/", default => -1},
+ min_group_id_to_connect => {parse => \&parsecfg_int, print => \&printcfg_int, path => "login-server:login_configuration/permission/", default => -1},
+ start_limited_time => {parse => \&parsecfg_int, print => \&printcfg_int, path => "login-server:login_configuration/account/", default => -1},
+ check_client_version => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "login-server:login_configuration/permission/", default => "false"},
+ client_version_to_connect => {parse => \&parsecfg_int, print => \&printcfg_int, path => "login-server:login_configuration/permission/", default => 20},
+ use_MD5_passwords => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "login-server:login_configuration/account/", default => "false"},
+ 'ipban.enable' => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "login-server:login_configuration/account/ipban/enabled", default => "true"},
+ 'ipban.sql.db_hostname' => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_hostname", default => "127.0.0.1"},
+ 'ipban.sql.db_port' => {parse => \&parsecfg_int, print => \&printcfg_int, path => "sql_connection:sql_connection/db_port", default => 3306},
+ 'ipban.sql.db_username' => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_username", default => "ragnarok"},
+ 'ipban.sql.db_password' => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_password", default => "ragnarok"},
+ 'ipban.sql.db_database' => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_database", default => "ragnarok"},
+ 'ipban.sql.codepage' => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/codepage", default => ""},
+ 'ipban.sql.ipban_table' => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/ipban_table", default => "ipbanlist"},
+ 'ipban.dynamic_pass_failure_ban' => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "login-server:login_configuration/account/ipban/dynamic_pass_failure/enabled", default => "true"},
+ 'ipban.dynamic_pass_failure_ban_interval' => {parse => \&parsecfg_int, print => \&printcfg_int, path => "login-server:login_configuration/account/ipban/dynamic_pass_failure/ban_interval", default => 5},
+ 'ipban.dynamic_pass_failure_ban_limit' => {parse => \&parsecfg_int, print => \&printcfg_int, path => "login-server:login_configuration/account/ipban/dynamic_pass_failure/ban_limit", default => 7},
+ 'ipban.dynamic_pass_failure_ban_duration' => {parse => \&parsecfg_int, print => \&printcfg_int, path => "login-server:login_configuration/account/ipban/dynamic_pass_failure/ban_duration", default => 5},
+ ipban_cleanup_interval => {parse => \&parsecfg_int, print => \&printcfg_int, path => "login-server:login_configuration/account/ipban/cleanup_interval", default => 60},
+ ip_sync_interval => {parse => \&parsecfg_int, print => \&printcfg_int, path => "login-server:login_configuration/inter/ip_sync_interval", default => 10},
+ use_dnsbl => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "login-server:login_configuration/permission/DNS_blacklist/enabled", default => "false"},
+ dnsbl_servers => {parse => \&parsecfg_string, print => \&printcfg_strlist, path => "login-server:login_configuration/permission/DNS_blacklist/dnsbl_servers", default => "bl.blocklist.de, socks.dnsbl.sorbs.net"},
+ 'account.sql.db_hostname' => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_hostname", default => "127.0.0.1"},
+ 'account.sql.db_port' => {parse => \&parsecfg_int, print => \&printcfg_int, path => "sql_connection:sql_connection/db_port", default => 3306},
+ 'account.sql.db_username' => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_username", default => "ragnarok"},
+ 'account.sql.db_password' => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_password", default => "ragnarok"},
+ 'account.sql.db_database' => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_database", default => "ragnarok"},
+ 'account.sql.codepage' => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/codepage", default => ""},
+ 'account.sql.case_sensitive' => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "sql_connection:sql_connection/case_sensitive", default => "false"},
+ 'account.sql.account_db' => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/account_db", default => "login"},
+ client_hash_check => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "login-server:login_configuration/permission/hash/enabled", default => "false"},
+ client_hash => {parse => \&parsecfg_stringarr, print => \&printcfg_md5hash, path => "login-server:login_configuration/permission/hash/MD5_hashes", default => []},
+ 'account.sql.accreg_db' => {parse => \&parsecfg_string, print => \&printcfg_nil, path => "", default => "global_reg_value"},
+ import => {parse => \&parsecfg_stringarr, print => \&printcfg_nil, path => "", default => ["conf/inter-server.conf", "conf/import/login_conf.txt"]},
+ }
+ },
+ {
+ files => ['map-server.conf', 'import/map_conf.txt'],
+ settings => {
+ userid => {parse => \&parsecfg_string, print => \&printcfg_string, path => "map-server:map_configuration/inter/", default => "s1"},
+ passwd => {parse => \&parsecfg_string, print => \&printcfg_string, path => "map-server:map_configuration/inter/", default => "p1"},
+ char_ip => {parse => \&parsecfg_string, print => \&printcfg_string, path => "map-server:map_configuration/inter/", default => "127.0.0.1"},
+ bind_ip => {parse => \&parsecfg_string, print => \&printcfg_string, path => "map-server:map_configuration/inter/", default => "127.0.0.1"},
+ char_port => {parse => \&parsecfg_int, print => \&printcfg_int, path => "map-server:map_configuration/inter/", default => 6121},
+ map_ip => {parse => \&parsecfg_string, print => \&printcfg_string, path => "map-server:map_configuration/inter/", default => "127.0.0.1"},
+ map_port => {parse => \&parsecfg_int, print => \&printcfg_int, path => "map-server:map_configuration/inter/", default => 5121},
+ timestamp_format => {parse => \&parsecfg_string, print => \&printcfg_string, path => "console:console/", default => "[%d/%b %H:%M]"},
+ stdout_with_ansisequence => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "console:console/", default => "false"},
+ console_msg_log => {parse => \&parsecfg_int, print => \&printcfg_int, path => "console:console/", default => 0},
+ console_silent => {parse => \&parsecfg_int, print => \&printcfg_int, path => "console:console/", default => 0},
+ db_path => {parse => \&parsecfg_string, print => \&printcfg_string, path => "map-server:map_configuration/database/", default => "db"},
+ enable_spy => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "map-server:map_configuration/", default => "false"},
+ use_grf => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "map-server:map_configuration/", default => "false"},
+ autosave_time => {parse => \&parsecfg_int, print => \&printcfg_int, path => "map-server:map_configuration/database/", default => 300},
+ minsave_time => {parse => \&parsecfg_int, print => \&printcfg_int, path => "map-server:map_configuration/database/", default => 100},
+ save_settings => {parse => \&parsecfg_int, print => \&printcfg_hexint, path => "map-server:map_configuration/database/", default => 511},
+ default_language => {parse => \&parsecfg_string, print => \&printcfg_string, path => "map-server:map_configuration/", default => "English"},
+ help_txt => {parse => \&parsecfg_string, print => \&printcfg_string, path => "map-server:map_configuration/", default => "conf/help.txt"},
+ charhelp_txt => {parse => \&parsecfg_string, print => \&printcfg_string, path => "map-server:map_configuration/", default => "conf/charhelp.txt"},
+ help2_txt => {parse => \&parsecfg_string, print => \&printcfg_nil, path => "", default => "conf/help2.txt"},
+ import => {parse => \&parsecfg_stringarr, print => \&printcfg_nil, path => "", default => ["conf/maps.conf", "conf/import/map_conf.txt"]},
+ }
+ },
+ {
+ files => ['logs.conf', 'import/log_conf.txt'],
+ settings => {
+ enable_logs => {parse => \&parsecfg_int, print => \&printcfg_hexint, path => "logs:map_log/enable", default => 0xFFFFF},
+ sql_logs => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "logs:map_log/database/use_sql", default => "true"},
+ log_filter => {parse => \&parsecfg_int, print => \&printcfg_int, path => "logs:map_log/filter/item/", default => 1},
+ refine_items_log => {parse => \&parsecfg_int, print => \&printcfg_int, path => "logs:map_log/filter/item/", default => 5},
+ rare_items_log => {parse => \&parsecfg_int, print => \&printcfg_int, path => "logs:map_log/filter/item/", default => 100},
+ price_items_log => {parse => \&parsecfg_int, print => \&printcfg_int, path => "logs:map_log/filter/item/", default => 1000},
+ amount_items_log => {parse => \&parsecfg_int, print => \&printcfg_int, path => "logs:map_log/filter/item/", default => 100},
+ log_branch => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "logs:map_log/", default => "false"},
+ log_zeny => {parse => \&parsecfg_int, print => \&printcfg_int, path => "logs:map_log/", default => 0},
+ log_mvpdrop => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "logs:map_log/", default => "false"},
+ log_commands => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "logs:map_log/", default => "true"},
+ log_npc => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "logs:map_log/", default => "false"},
+ log_chat => {parse => \&parsecfg_int, print => \&printcfg_int, path => "logs:map_log/filter/chat/", default => 0},
+ log_chat_woe_disable => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "logs:map_log/filter/chat/", default => "false"},
+ log_gm_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "logs:map_log/database/", default => "atcommandlog"},
+ log_branch_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "logs:map_log/database/", default => "branchlog"},
+ log_chat_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "logs:map_log/database/", default => "chatlog"},
+ log_mvpdrop_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "logs:map_log/database/", default => "mvplog"},
+ log_npc_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "logs:map_log/database/", default => "npclog"},
+ log_pick_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "logs:map_log/database/", default => "picklog"},
+ log_zeny_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "logs:map_log/database/", default => "zenylog"},
+ import => {parse => \&parsecfg_string, print => \&printcfg_nil, path => "", default => "conf/import/log_conf.txt"},
+ }
+ },
+ {
+ files => ['script.conf', 'import/script_conf.txt'],
+ settings => {
+ warn_func_mismatch_paramnum => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "script:script_configuration/", default => "true"},
+ check_cmdcount => {parse => \&parsecfg_int, print => \&printcfg_int, path => "script:script_configuration/", default => 655360},
+ check_gotocount => {parse => \&parsecfg_int, print => \&printcfg_int, path => "script:script_configuration/", default => 2048},
+ input_min_value => {parse => \&parsecfg_int, print => \&printcfg_int, path => "script:script_configuration/", default => 0},
+ input_max_value => {parse => \&parsecfg_int, print => \&printcfg_int, path => "script:script_configuration/", default => 10000000},
+ warn_func_mismatch_argtypes => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "script:script_configuration/", default => "true"},
+ import => {parse => \&parsecfg_string, print => \&printcfg_nil, path => "", default => "conf/import/script_conf.txt"},
+ }
+ },
+ {
+ files => ['packet.conf', 'import/packet_conf.txt'],
+ settings => {
+ debug => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "socket:socket_configuration/", default => "false"},
+ stall_time => {parse => \&parsecfg_int, print => \&printcfg_int, path => "socket:socket_configuration/", default => 60},
+ epoll_maxevents => {parse => \&parsecfg_int, print => \&printcfg_int, path => "socket:socket_configuration/", default => 1024},
+ socket_max_client_packet => {parse => \&parsecfg_int, print => \&printcfg_int, path => "socket:socket_configuration/", default => 65535},
+ enable_ip_rules => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "socket:socket_configuration/ip_rules/enable", default => "true"},
+ order => {parse => \&parsecfg_string, print => \&printcfg_string, path => "socket:socket_configuration/ip_rules/", default => "deny,allow"},
+ allow => {parse => \&parsecfg_stringarr, print => \&printcfg_strlist, path => "socket:socket_configuration/ip_rules/allow_list", default => []},
+ deny => {parse => \&parsecfg_stringarr, print => \&printcfg_strlist, path => "socket:socket_configuration/ip_rules/deny_list", default => []},
+ ddos_interval => {parse => \&parsecfg_int, print => \&printcfg_int, path => "socket:socket_configuration/ddos/interval", default => 3000},
+ ddos_count => {parse => \&parsecfg_int, print => \&printcfg_int, path => "socket:socket_configuration/ddos/count", default => 5},
+ ddos_autoreset => {parse => \&parsecfg_int, print => \&printcfg_int, path => "socket:socket_configuration/ddos/autoreset", default => 600000},
+ import => {parse => \&parsecfg_string, print => \&printcfg_nil, path => "", default => "conf/import/packet_conf.txt"},
+ }
+ },
+ {
+ files => ['battle.conf', 'battle/battle.conf', 'battle/client.conf', 'battle/drops.conf', 'battle/exp.conf', 'battle/gm.conf', 'battle/guild.conf', 'battle/battleground.conf', 'battle/items.conf', 'battle/monster.conf', 'battle/party.conf', 'battle/pet.conf', 'battle/homunc.conf', 'battle/player.conf', 'battle/skill.conf', 'battle/status.conf', 'battle/feature.conf', 'battle/misc.conf', 'import/battle_conf.txt'],
+ settings => {
+ bg_flee_penalty => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battleground:", default => 20},
+ bg_update_interval => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battleground:", default => 1000},
+ 'feature.buying_store' => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "feature:features/buying_store", default => "true"},
+ 'feature.search_stores' => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "feature:features/search_stores", default => "true"},
+ 'feature.atcommand_suggestions' => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "feature:features/atcommand_suggestions", default => "false"},
+ 'feature.banking' => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "feature:features/banking", default => "true"},
+ 'feature.auction' => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "feature:features/auction", default => "false"},
+ 'feature.roulette' => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "feature:features/roulette", default => "false"},
+ atcommand_spawn_quantity_limit => {parse => \&parsecfg_int, print => \&printcfg_int, path => "gm:", default => 100},
+ atcommand_slave_clone_limit => {parse => \&parsecfg_int, print => \&printcfg_int, path => "gm:", default => 25},
+ partial_name_scan => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "gm:", default => "true"},
+ atcommand_max_stat_bypass => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "gm:", default => "false"},
+ ban_hack_trade => {parse => \&parsecfg_int, print => \&printcfg_int, path => "gm:", default => 5},
+ atcommand_mobinfo_type => {parse => \&parsecfg_int, print => \&printcfg_int, path => "gm:", default => 0},
+ gm_ignore_warpable_area => {parse => \&parsecfg_int, print => \&printcfg_int, path => "gm:", default => 2},
+ atcommand_levelup_events => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "gm:", default => "false"},
+ guild_emperium_check => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "guild:", default => "true"},
+ guild_exp_limit => {parse => \&parsecfg_int, print => \&printcfg_int, path => "guild:", default => 50},
+ guild_max_castles => {parse => \&parsecfg_int, print => \&printcfg_int, path => "guild:", default => 0},
+ guild_skill_relog_delay => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "guild:", default => "false"},
+ castle_defense_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "guild:", default => 100},
+ gvg_flee_penalty => {parse => \&parsecfg_int, print => \&printcfg_int, path => "guild:", default => 20},
+ require_glory_guild => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "guild:", default => "false"},
+ max_guild_alliance => {parse => \&parsecfg_int, print => \&printcfg_int, path => "guild:", default => 3},
+ guild_notice_changemap => {parse => \&parsecfg_int, print => \&printcfg_int, path => "guild:", default => 2},
+ guild_castle_invite => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "guild:", default => "false"},
+ guild_castle_expulsion => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "guild:", default => "false"},
+ hom_setting => {parse => \&parsecfg_int, print => \&printcfg_hexint, path => "homunc:", default => 0x1D},
+ homunculus_friendly_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "homunc:", default => 100},
+ hom_rename => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "homunc:", default => "false"},
+ hvan_explosion_intimate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "homunc:", default => 45000},
+ homunculus_show_growth => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "homunc:", default => "true"},
+ homunculus_autoloot => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "homunc:", default => "true"},
+ homunculus_auto_vapor => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "homunc:", default => "true"},
+ homunculus_max_level => {parse => \&parsecfg_int, print => \&printcfg_int, path => "homunc:", default => 99},
+ homunculus_S_max_level => {parse => \&parsecfg_int, print => \&printcfg_int, path => "homunc:", default => 150},
+ enable_baseatk => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battle:", default => 9},
+ enable_perfect_flee => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battle:", default => 1},
+ enable_critical => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battle:", default => 17},
+ mob_critical_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battle:", default => 100},
+ critical_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battle:", default => 100},
+ attack_walk_delay => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battle:", default => 15},
+ pc_damage_walk_delay_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battle:", default => 20},
+ damage_walk_delay_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battle:", default => 100},
+ multihit_delay => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battle:", default => 80},
+ player_damage_delay_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battle:", default => 100},
+ undead_detect_type => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battle:", default => 0},
+ attribute_recover => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "battle:", default => "false"},
+ min_hitrate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battle:", default => 5},
+ max_hitrate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battle:", default => 100},
+ agi_penalty_type => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battle:", default => 1},
+ agi_penalty_target => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battle:", default => 1},
+ agi_penalty_count => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battle:", default => 3},
+ agi_penalty_num => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battle:", default => 10},
+ vit_penalty_type => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battle:", default => 1},
+ vit_penalty_target => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battle:", default => 1},
+ vit_penalty_count => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battle:", default => 3},
+ vit_penalty_num => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battle:", default => 5},
+ weapon_defense_type => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battle:", default => 0},
+ magic_defense_type => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battle:", default => 0},
+ attack_direction_change => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battle:", default => 0},
+ attack_attr_none => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battle:", default => 14},
+ equip_natural_break_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battle:", default => 0},
+ equip_self_break_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battle:", default => 100},
+ equip_skill_break_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battle:", default => 100},
+ delay_battle_damage => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "battle:", default => "true"},
+ arrow_decrement => {parse => \&parsecfg_int, print => \&printcfg_int, path => "battle:", default => 1},
+ autospell_check_range => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "battle:", default => "false"},
+ knockback_left => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "battle:", default => "true"},
+ snap_dodge => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "battle:", default => "false"},
+ packet_obfuscation => {parse => \&parsecfg_int, print => \&printcfg_int, path => "client:", default => 1},
+ min_chat_delay => {parse => \&parsecfg_int, print => \&printcfg_int, path => "client:", default => 0},
+ min_hair_style => {parse => \&parsecfg_int, print => \&printcfg_int, path => "client:", default => 0},
+ max_hair_style => {parse => \&parsecfg_int, print => \&printcfg_int, path => "client:", default => 29},
+ min_hair_color => {parse => \&parsecfg_int, print => \&printcfg_int, path => "client:", default => 0},
+ max_hair_color => {parse => \&parsecfg_int, print => \&printcfg_int, path => "client:", default => 8},
+ min_cloth_color => {parse => \&parsecfg_int, print => \&printcfg_int, path => "client:", default => 0},
+ max_cloth_color => {parse => \&parsecfg_int, print => \&printcfg_int, path => "client:", default => 4},
+ min_body_style => {parse => \&parsecfg_int, print => \&printcfg_int, path => "client:", default => 0},
+ max_body_style => {parse => \&parsecfg_int, print => \&printcfg_int, path => "client:", default => 4},
+ hide_woe_damage => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "client:", default => "true"},
+ pet_hair_style => {parse => \&parsecfg_int, print => \&printcfg_int, path => "client:", default => 100},
+ area_size => {parse => \&parsecfg_int, print => \&printcfg_int, path => "client:", default => 14},
+ max_walk_path => {parse => \&parsecfg_int, print => \&printcfg_int, path => "client:", default => 17},
+ max_lv => {parse => \&parsecfg_int, print => \&printcfg_int, path => "client:", default => 99},
+ aura_lv => {parse => \&parsecfg_int, print => \&printcfg_int, path => "client:", default => 99},
+ client_limit_unit_lv => {parse => \&parsecfg_int, print => \&printcfg_int, path => "client:", default => 0},
+ wedding_modifydisplay => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "client:", default => "false"},
+ save_clothcolor => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "client:", default => "true"},
+ save_body_style => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "client:", default => "false"},
+ wedding_ignorepalette => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "client:", default => "false"},
+ xmas_ignorepalette => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "client:", default => "false"},
+ summer_ignorepalette => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "client:", default => "false"},
+ hanbok_ignorepalette => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "client:", default => "false"},
+ display_version => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "client:", default => "false"},
+ display_hallucination => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "client:", default => "true"},
+ display_status_timers => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "client:", default => "true"},
+ client_reshuffle_dice => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "client:", default => "true"},
+ client_sort_storage => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "client:", default => "false"},
+ client_accept_chatdori => {parse => \&parsecfg_int, print => \&printcfg_int, path => "client:", default => 0},
+ client_emblem_max_blank_percent => {parse => \&parsecfg_int, print => \&printcfg_int, path => "client:", default => 100},
+ item_auto_get => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "drops:", default => "false"},
+ flooritem_lifetime => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 60000},
+ item_first_get_time => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 3000},
+ item_second_get_time => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 1000},
+ item_third_get_time => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 1000},
+ mvp_item_first_get_time => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 10000},
+ mvp_item_second_get_time => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 10000},
+ mvp_item_third_get_time => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 2000},
+ item_rate_common => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 100},
+ item_rate_common_boss => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 100},
+ item_drop_common_min => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 1},
+ item_drop_common_max => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 10000},
+ item_rate_heal => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 100},
+ item_rate_heal_boss => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 100},
+ item_drop_heal_min => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 1},
+ item_drop_heal_max => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 10000},
+ item_rate_use => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 100},
+ item_rate_use_boss => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 100},
+ item_drop_use_min => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 1},
+ item_drop_use_max => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 10000},
+ item_rate_equip => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 100},
+ item_rate_equip_boss => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 100},
+ item_drop_equip_min => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 1},
+ item_drop_equip_max => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 10000},
+ item_rate_card => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 100},
+ item_rate_card_boss => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 100},
+ item_drop_card_min => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 1},
+ item_drop_card_max => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 10000},
+ item_rate_mvp => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 100},
+ item_drop_mvp_min => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 1},
+ item_drop_mvp_max => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 10000},
+ item_rate_adddrop => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 100},
+ item_drop_add_min => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 1},
+ item_drop_add_max => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 10000},
+ item_rate_treasure => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 100},
+ item_drop_treasure_min => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 1},
+ item_drop_treasure_max => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 10000},
+ item_logarithmic_drops => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "drops:", default => "false"},
+ drop_rate0item => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "drops:", default => "false"},
+ drops_by_luk => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 0},
+ drops_by_luk2 => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 0},
+ alchemist_summon_reward => {parse => \&parsecfg_int, print => \&printcfg_int, path => "drops:", default => 1},
+ base_exp_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "exp:", default => 100},
+ job_exp_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "exp:", default => 100},
+ multi_level_up => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "exp:", default => "false"},
+ max_exp_gain_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "exp:", default => 0},
+ exp_calc_type => {parse => \&parsecfg_int, print => \&printcfg_int, path => "exp:", default => 0},
+ exp_bonus_attacker => {parse => \&parsecfg_int, print => \&printcfg_int, path => "exp:", default => 25},
+ exp_bonus_max_attacker => {parse => \&parsecfg_int, print => \&printcfg_int, path => "exp:", default => 12},
+ mvp_exp_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "exp:", default => 100},
+ quest_exp_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "exp:", default => 100},
+ heal_exp => {parse => \&parsecfg_int, print => \&printcfg_int, path => "exp:", default => 0},
+ resurrection_exp => {parse => \&parsecfg_int, print => \&printcfg_int, path => "exp:", default => 0},
+ shop_exp => {parse => \&parsecfg_int, print => \&printcfg_int, path => "exp:", default => 0},
+ pvp_exp => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "exp:", default => "true"},
+ death_penalty_type => {parse => \&parsecfg_int, print => \&printcfg_int, path => "exp:", default => 1},
+ death_penalty_base => {parse => \&parsecfg_int, print => \&printcfg_int, path => "exp:", default => 100},
+ death_penalty_job => {parse => \&parsecfg_int, print => \&printcfg_int, path => "exp:", default => 100},
+ zeny_penalty => {parse => \&parsecfg_int, print => \&printcfg_int, path => "exp:", default => 0},
+ disp_experience => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "exp:", default => "false"},
+ disp_zeny => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "exp:", default => "false"},
+ use_statpoint_table => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "exp:", default => "true"},
+ vending_max_value => {parse => \&parsecfg_int, print => \&printcfg_int, path => "items:", default => 1000000000},
+ vending_over_max => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "items:", default => "true"},
+ vending_tax => {parse => \&parsecfg_int, print => \&printcfg_int, path => "items:", default => 200},
+ buyer_name => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "items:", default => "true"},
+ weapon_produce_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "items:", default => 100},
+ potion_produce_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "items:", default => 100},
+ produce_item_name_input => {parse => \&parsecfg_int, print => \&printcfg_hexint, path => "items:", default => 0x03},
+ dead_branch_active => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "items:", default => "true"},
+ random_monster_checklv => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "items:", default => "false"},
+ ignore_items_gender => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "items:", default => "true"},
+ item_check => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "items:", default => "false"},
+ item_use_interval => {parse => \&parsecfg_int, print => \&printcfg_int, path => "items:", default => 100},
+ cashfood_use_interval => {parse => \&parsecfg_int, print => \&printcfg_int, path => "items:", default => 60000},
+ gtb_sc_immunity => {parse => \&parsecfg_int, print => \&printcfg_int, path => "items:", default => 50},
+ autospell_stacking => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "items:", default => "false"},
+ item_restricted_consumption_type => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "items:", default => "true"},
+ item_enabled_npc => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "items:", default => "true"},
+ unequip_restricted_equipment => {parse => \&parsecfg_int, print => \&printcfg_int, path => "items:", default => 0},
+ pk_mode => {parse => \&parsecfg_int, print => \&printcfg_int, path => "misc:", default => 0},
+ manner_system => {parse => \&parsecfg_int, print => \&printcfg_int, path => "misc:", default => 31},
+ pk_min_level => {parse => \&parsecfg_int, print => \&printcfg_int, path => "misc:", default => 55},
+ pk_level_range => {parse => \&parsecfg_int, print => \&printcfg_int, path => "misc:", default => 0},
+ skill_log => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "misc:", default => "false"},
+ battle_log => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "misc:", default => "false"},
+ etc_log => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "misc:", default => "false"},
+ warp_point_debug => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "misc:", default => "false"},
+ night_at_start => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "misc:", default => "false"},
+ day_duration => {parse => \&parsecfg_int, print => \&printcfg_int, path => "misc:", default => 0},
+ night_duration => {parse => \&parsecfg_int, print => \&printcfg_int, path => "misc:", default => 0},
+ duel_allow_pvp => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "misc:", default => "false"},
+ duel_allow_gvg => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "misc:", default => "false"},
+ duel_allow_teleport => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "misc:", default => "false"},
+ duel_autoleave_when_die => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "misc:", default => "true"},
+ duel_time_interval => {parse => \&parsecfg_int, print => \&printcfg_int, path => "misc:", default => 60},
+ duel_only_on_same_map => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "misc:", default => "false"},
+ official_cell_stack_limit => {parse => \&parsecfg_int, print => \&printcfg_int, path => "misc:", default => 1},
+ custom_cell_stack_limit => {parse => \&parsecfg_int, print => \&printcfg_int, path => "misc:", default => 1},
+ check_occupied_cells => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "misc:", default => "true"},
+ at_mapflag => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "misc:", default => "false"},
+ at_timeout => {parse => \&parsecfg_int, print => \&printcfg_int, path => "misc:", default => 0},
+ auction_feeperhour => {parse => \&parsecfg_int, print => \&printcfg_int, path => "misc:", default => 12000},
+ auction_maximumprice => {parse => \&parsecfg_int, print => \&printcfg_int, path => "misc:", default => 500000000},
+ searchstore_querydelay => {parse => \&parsecfg_int, print => \&printcfg_int, path => "misc:", default => 10},
+ searchstore_maxresults => {parse => \&parsecfg_int, print => \&printcfg_int, path => "misc:", default => 30},
+ cashshop_show_points => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "misc:", default => "false"},
+ mail_show_status => {parse => \&parsecfg_int, print => \&printcfg_int, path => "misc:", default => 0},
+ mon_trans_disable_in_gvg => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "misc:", default => "false"},
+ case_sensitive_aegisnames => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "misc:", default => "true"},
+ mvp_hp_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "monster:", default => 100},
+ monster_hp_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "monster:", default => 100},
+ monster_max_aspd => {parse => \&parsecfg_int, print => \&printcfg_int, path => "monster:", default => 199},
+ monster_ai => {parse => \&parsecfg_int, print => \&printcfg_int, path => "monster:", default => 0},
+ monster_chase_refresh => {parse => \&parsecfg_int, print => \&printcfg_int, path => "monster:", default => 3},
+ mob_warp => {parse => \&parsecfg_int, print => \&printcfg_int, path => "monster:", default => 0},
+ mob_active_time => {parse => \&parsecfg_int, print => \&printcfg_int, path => "monster:", default => 0},
+ boss_active_time => {parse => \&parsecfg_int, print => \&printcfg_int, path => "monster:", default => 0},
+ view_range_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "monster:", default => 100},
+ chase_range_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "monster:", default => 100},
+ monster_active_enable => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "monster:", default => "true"},
+ override_mob_names => {parse => \&parsecfg_int, print => \&printcfg_int, path => "monster:", default => 0},
+ monster_damage_delay_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "monster:", default => 100},
+ monster_loot_type => {parse => \&parsecfg_int, print => \&printcfg_int, path => "monster:", default => 0},
+ mob_skill_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "monster:", default => 100},
+ mob_skill_delay => {parse => \&parsecfg_int, print => \&printcfg_int, path => "monster:", default => 100},
+ mob_count_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "monster:", default => 100},
+ mob_spawn_delay => {parse => \&parsecfg_int, print => \&printcfg_int, path => "monster:", default => 100},
+ plant_spawn_delay => {parse => \&parsecfg_int, print => \&printcfg_int, path => "monster:", default => 100},
+ boss_spawn_delay => {parse => \&parsecfg_int, print => \&printcfg_int, path => "monster:", default => 100},
+ no_spawn_on_player => {parse => \&parsecfg_int, print => \&printcfg_int, path => "monster:", default => 0},
+ force_random_spawn => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "monster:", default => "false"},
+ slaves_inherit_mode => {parse => \&parsecfg_int, print => \&printcfg_int, path => "monster:", default => 2},
+ slaves_inherit_speed => {parse => \&parsecfg_int, print => \&printcfg_int, path => "monster:", default => 3},
+ summons_trigger_autospells => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "monster:", default => "true"},
+ retaliate_to_master => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "monster:", default => "true"},
+ mob_changetarget_byskill => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "monster:", default => "false"},
+ monster_class_change_full_recover => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "monster:", default => "true"},
+ show_mob_info => {parse => \&parsecfg_int, print => \&printcfg_int, path => "monster:", default => 0},
+ zeny_from_mobs => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "monster:", default => "false"},
+ mobs_level_up => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "monster:", default => "false"},
+ mobs_level_up_exp_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "monster:", default => 1},
+ dynamic_mobs => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "monster:", default => "true"},
+ mob_remove_damaged => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "monster:", default => "true"},
+ mob_remove_delay => {parse => \&parsecfg_int, print => \&printcfg_int, path => "monster:", default => 300000},
+ mob_npc_event_type => {parse => \&parsecfg_int, print => \&printcfg_int, path => "monster:", default => 1},
+ ksprotection => {parse => \&parsecfg_int, print => \&printcfg_int, path => "monster:", default => 0},
+ mob_slave_keep_target => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "monster:", default => "true"},
+ mvp_tomb_enabled => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "monster:", default => "true"},
+ show_monster_hp_bar => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "monster:", default => "true"},
+ mob_size_influence => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "monster:", default => "false"},
+ mob_icewall_walk_block => {parse => \&parsecfg_int, print => \&printcfg_int, path => "monster:", default => 220},
+ boss_icewall_walk_block => {parse => \&parsecfg_int, print => \&printcfg_int, path => "monster:", default => 1},
+ show_steal_in_same_party => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "party:", default => "false"},
+ party_update_interval => {parse => \&parsecfg_int, print => \&printcfg_int, path => "party:", default => 1000},
+ party_hp_mode => {parse => \&parsecfg_int, print => \&printcfg_int, path => "party:", default => 0},
+ show_party_share_picker => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "party:", default => "true"},
+ 'show_picker.item_type' => {parse => \&parsecfg_int, print => \&printcfg_int, path => "party:show_picker_item_type", default => 112},
+ party_item_share_type => {parse => \&parsecfg_int, print => \&printcfg_int, path => "party:", default => 0},
+ idle_no_share => {parse => \&parsecfg_int, print => \&printcfg_int, path => "party:", default => 0},
+ party_even_share_bonus => {parse => \&parsecfg_int, print => \&printcfg_int, path => "party:", default => 0},
+ display_party_name => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "party:", default => "false"},
+ pet_catch_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "pet:", default => 100},
+ pet_rename => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "pet:", default => "false"},
+ pet_friendly_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "pet:", default => 100},
+ pet_hungry_delay_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "pet:", default => 100},
+ pet_hungry_friendly_decrease => {parse => \&parsecfg_int, print => \&printcfg_int, path => "pet:", default => 5},
+ pet_equip_required => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "pet:", default => "true"},
+ pet_attack_support => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "pet:", default => "false"},
+ pet_damage_support => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "pet:", default => "false"},
+ pet_support_min_friendly => {parse => \&parsecfg_int, print => \&printcfg_int, path => "pet:", default => 900},
+ pet_equip_min_friendly => {parse => \&parsecfg_int, print => \&printcfg_int, path => "pet:", default => 900},
+ pet_status_support => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "pet:", default => "false"},
+ pet_support_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "pet:", default => 100},
+ pet_attack_exp_to_master => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "pet:", default => "false"},
+ pet_attack_exp_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "pet:", default => 100},
+ pet_lv_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "pet:", default => 0},
+ pet_max_stats => {parse => \&parsecfg_int, print => \&printcfg_int, path => "pet:", default => 99},
+ pet_max_atk1 => {parse => \&parsecfg_int, print => \&printcfg_int, path => "pet:", default => 500},
+ pet_max_atk2 => {parse => \&parsecfg_int, print => \&printcfg_int, path => "pet:", default => 1000},
+ pet_disable_in_gvg => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "pet:", default => "false"},
+ hp_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "player:", default => 100},
+ sp_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "player:", default => 100},
+ left_cardfix_to_right => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "player:", default => "true"},
+ restart_hp_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "player:", default => 0},
+ restart_sp_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "player:", default => 0},
+ player_skillfree => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "player:", default => "false"},
+ player_skillup_limit => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "player:", default => "true"},
+ quest_skill_learn => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "player:", default => "false"},
+ quest_skill_reset => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "player:", default => "false"},
+ basic_skill_check => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "player:", default => "true"},
+ player_invincible_time => {parse => \&parsecfg_int, print => \&printcfg_int, path => "player:", default => 5000},
+ fix_warp_hit_delay_abuse => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "player:", default => "false"},
+ natural_healhp_interval => {parse => \&parsecfg_int, print => \&printcfg_int, path => "player:", default => 6000},
+ natural_healsp_interval => {parse => \&parsecfg_int, print => \&printcfg_int, path => "player:", default => 8000},
+ natural_heal_skill_interval => {parse => \&parsecfg_int, print => \&printcfg_int, path => "player:", default => 10000},
+ natural_heal_weight_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "player:", default => 50},
+ max_aspd => {parse => \&parsecfg_int, print => \&printcfg_int, path => "player:", default => 190},
+ max_third_aspd => {parse => \&parsecfg_int, print => \&printcfg_int, path => "player:", default => 193},
+ max_walk_speed => {parse => \&parsecfg_int, print => \&printcfg_int, path => "player:", default => 300},
+ max_hp => {parse => \&parsecfg_int, print => \&printcfg_int, path => "player:", default => 1000000},
+ max_sp => {parse => \&parsecfg_int, print => \&printcfg_int, path => "player:", default => 1000000},
+ max_parameter => {parse => \&parsecfg_int, print => \&printcfg_int, path => "player:", default => 99},
+ max_third_parameter => {parse => \&parsecfg_int, print => \&printcfg_int, path => "player:", default => 130},
+ max_extended_parameter => {parse => \&parsecfg_int, print => \&printcfg_int, path => "player:", default => 125},
+ max_baby_parameter => {parse => \&parsecfg_int, print => \&printcfg_int, path => "player:", default => 80},
+ max_baby_third_parameter => {parse => \&parsecfg_int, print => \&printcfg_int, path => "player:", default => 117},
+ max_def => {parse => \&parsecfg_int, print => \&printcfg_int, path => "player:", default => 99},
+ over_def_bonus => {parse => \&parsecfg_int, print => \&printcfg_int, path => "player:", default => 0},
+ max_cart_weight => {parse => \&parsecfg_int, print => \&printcfg_int, path => "player:", default => 8000},
+ prevent_logout => {parse => \&parsecfg_int, print => \&printcfg_int, path => "player:", default => 10000},
+ show_hp_sp_drain => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "player:", default => "false"},
+ show_hp_sp_gain => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "player:", default => "true"},
+ show_katar_crit_bonus => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "player:", default => "false"},
+ friend_auto_add => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "player:", default => "true"},
+ invite_request_check => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "player:", default => "true"},
+ bone_drop => {parse => \&parsecfg_int, print => \&printcfg_int, path => "player:", default => 0},
+ character_size => {parse => \&parsecfg_int, print => \&printcfg_int, path => "player:", default => 0},
+ idle_no_autoloot => {parse => \&parsecfg_int, print => \&printcfg_int, path => "player:", default => 0},
+ min_npc_vendchat_distance => {parse => \&parsecfg_int, print => \&printcfg_int, path => "player:", default => 3},
+ vendchat_near_hiddennpc => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "player:", default => "false"},
+ snovice_call_type => {parse => \&parsecfg_int, print => \&printcfg_int, path => "player:", default => 0},
+ idletime_criteria => {parse => \&parsecfg_int, print => \&printcfg_hexint, path => "player:", default => 0x1F},
+ costume_refine_def => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "player:", default => "true"},
+ shadow_refine_def => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "player:", default => "true"},
+ shadow_refine_atk => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "player:", default => "true"},
+ player_warp_keep_direction => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "player:", default => "true"},
+ casting_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 100},
+ delay_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 100},
+ delay_dependon_dex => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "skill:", default => "false"},
+ delay_dependon_agi => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "skill:", default => "false"},
+ min_skill_delay_limit => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 100},
+ default_walk_delay => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 300},
+ no_skill_delay => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 2},
+ castrate_dex_scale => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 150},
+ vcast_stat_scale => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 530},
+ skill_amotion_leniency => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 90},
+ skill_delay_attack_enable => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "skill:", default => "true"},
+ skill_add_range => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 0},
+ skill_out_range_consume => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "skill:", default => "false"},
+ skillrange_by_distance => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 14},
+ skillrange_from_weapon => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 0},
+ skill_caster_check => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "skill:", default => "true"},
+ clear_skills_on_death => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 0},
+ clear_skills_on_warp => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 15},
+ defunit_not_enemy => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "skill:", default => "false"},
+ skill_min_damage => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 6},
+ combo_delay_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 100},
+ auto_counter_type => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 15},
+ skill_reiteration => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 0},
+ skill_nofootset => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 1},
+ gvg_traps_target_all => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 1},
+ traps_setting => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 0},
+ summon_flora_setting => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 3},
+ song_timer_reset => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 0},
+ skill_wall_check => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "skill:", default => "true"},
+ player_cloak_check_type => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 1},
+ monster_cloak_check_type => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 4},
+ land_skill_limit => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 9},
+ display_skill_fail => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 0},
+ chat_warpportal => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "skill:", default => "false"},
+ sense_type => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 1},
+ finger_offensive_type => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 0},
+ gx_allhit => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "skill:", default => "false"},
+ gx_disptype => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 1},
+ devotion_level_difference => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 10},
+ player_skill_partner_check => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "skill:", default => "true"},
+ skill_removetrap_type => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 0},
+ backstab_bow_penalty => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "skill:", default => "true"},
+ skill_steal_max_tries => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 0},
+ copyskill_restrict => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 2},
+ berserk_cancels_buffs => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "skill:", default => "false"},
+ max_heal => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 9999},
+ max_heal_lv => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 11},
+ emergency_call => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 11},
+ guild_aura => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 31},
+ skip_teleport_lv1_menu => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "skill:", default => "false"},
+ allow_skill_without_day => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "skill:", default => "false"},
+ allow_es_magic_player => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "skill:", default => "false"},
+ sg_miracle_skill_ratio => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 2},
+ sg_miracle_skill_duration => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 3600000},
+ sg_angel_skill_ratio => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 10},
+ skill_add_heal_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 7},
+ eq_single_target_reflectable => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "skill:", default => "true"},
+ 'invincible.nodamage' => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "skill:", default => "false"},
+ dancing_weaponswitch_fix => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "skill:", default => "true"},
+ skill_trap_type => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 0},
+ mob_max_skilllvl => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 100},
+ bowling_bash_area => {parse => \&parsecfg_int, print => \&printcfg_int, path => "skill:", default => 0},
+ stormgust_knockback => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "skill:", default => "true"},
+ status_cast_cancel => {parse => \&parsecfg_int, print => \&printcfg_int, path => "status:", default => 0},
+ pc_status_def_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "status:", default => 100},
+ mob_status_def_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "status:", default => 100},
+ pc_max_status_def => {parse => \&parsecfg_int, print => \&printcfg_int, path => "status:", default => 100},
+ mob_max_status_def => {parse => \&parsecfg_int, print => \&printcfg_int, path => "status:", default => 100},
+ import => {parse => \&parsecfg_stringarr, print => \&printcfg_nil, path => "", default => ['conf/battle/battle.conf', 'conf/battle/client.conf', 'conf/battle/drops.conf', 'conf/battle/exp.conf', 'conf/battle/gm.conf', 'conf/battle/guild.conf', 'conf/battle/battleground.conf', 'conf/battle/items.conf', 'conf/battle/monster.conf', 'conf/battle/party.conf', 'conf/battle/pet.conf', 'conf/battle/homunc.conf', 'conf/battle/player.conf', 'conf/battle/skill.conf', 'conf/battle/status.conf', 'conf/battle/feature.conf', 'conf/battle/misc.conf', 'conf/import/battle_conf.txt']},
+ }
+ },
+);
+
+for (@ARGV) {
+ if (/^-q$/) { $silent = 1; }
+ elsif (/^-v$/) { $silent = 0; }
+ elsif (-d) { $confpath = $_; }
+ else { undef $confpath }
+}
+
+verbose(<<'EOF');
+=============== Hercules Configuration Migration Helper ===============
+= _ _ _ =
+= | | | | | | =
+= | |_| | ___ _ __ ___ _ _| | ___ ___ =
+= | _ |/ _ \ '__/ __| | | | |/ _ \/ __| =
+= | | | | __/ | | (__| |_| | | __/\__ \ =
+= \_| |_/\___|_| \___|\__,_|_|\___||___/ =
+=======================================================================
+This tool will assist you through the migration of the old (txt-based)
+configuration files to the new (libconfig-based) format.
+Please follow the displayed instructions.
+=======================================================================
+
+EOF
+
+die "Usage: ./$0 [-q | -v] [path to the conf directory]\nIf no options are passed, it acts as if called as ./$0 conf\n" unless defined $confpath and -d $confpath;
+
+my $count = 0;
+for (@defaults) {
+ my @files = map { $confpath . '/' . $_ } @{$_->{files}};
+ $count += process_conf(\@files, $_->{settings})
+}
+verbose("\nThere are no files to migrate.\n") unless $count;
diff --git a/tools/doxygen/Hercules128.png b/tools/doxygen/Hercules128.png
new file mode 100644
index 000000000..79919da9b
--- /dev/null
+++ b/tools/doxygen/Hercules128.png
Binary files differ
diff --git a/tools/doxygen/Hercules48.png b/tools/doxygen/Hercules48.png
new file mode 100644
index 000000000..022893953
--- /dev/null
+++ b/tools/doxygen/Hercules48.png
Binary files differ
diff --git a/tools/doxygen/Makefile.in b/tools/doxygen/Makefile.in
new file mode 100644
index 000000000..233779f05
--- /dev/null
+++ b/tools/doxygen/Makefile.in
@@ -0,0 +1,70 @@
+# 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/>.
+
+# @configure_input@
+
+@SET_MAKE@
+
+COMMON_D = ../../src/common
+MAP_D = ../../src/map
+CHAR_D = ../../src/char
+LOGIN_D = ../../src/login
+PLUGIN_D = ../../src/plugins
+COMMON_C = $(wildcard $(COMMON_D)/*.c)
+COMMON_H = $(wildcard $(COMMON_D)/*.h)
+MAP_C = $(wildcard $(MAP_D)/*.c)
+MAP_H = $(wildcard $(MAP_D)/*.h)
+CHAR_C = $(wildcard $(CHAR_D)/*.c)
+CHAR_H = $(wildcard $(CHAR_D)/*.h)
+LOGIN_C = $(wildcard $(LOGIN_D)/*.c)
+LOGIN_H = $(wildcard $(LOGIN_D)/*.h)
+ALL_C = $(COMMON_C) $(MAP_C) $(CHAR_C) $(LOGIN_C)
+ALL_H = $(COMMON_H) $(MAP_H) $(CHAR_H) $(LOGIN_H)
+
+HAVE_DOXYGEN=@HAVE_DOXYGEN@
+ifeq ($(HAVE_DOXYGEN),yes)
+ ALL_DEPENDS = docs
+else
+ ALL_DEPENDS = needs_doxygen
+endif
+
+#####################################################################
+.PHONY: clean buildclean
+
+all: $(ALL_DEPENDS)
+
+buildclean:
+
+clean: buildclean
+ @echo " CLEAN docs"
+ @rm -rf docs
+
+Makefile: Makefile.in
+ @$(MAKE) -C ../.. tools/doxygen/Makefile
+
+#####################################################################
+
+docs: $(ALL_C) $(ALL_H) doxygen.conf
+ @echo " Generating Doxygen documentation..."
+ @doxygen doxygen.conf
+
+#####################################################################
+
+needs_doxygen:
+ @echo "doxygen not found or disabled by the configure script"
+ @exit 1
diff --git a/tools/doxygen/doxygen.conf b/tools/doxygen/doxygen.conf
new file mode 100644
index 000000000..043b36dc8
--- /dev/null
+++ b/tools/doxygen/doxygen.conf
@@ -0,0 +1,505 @@
+# Doxyfile 1.8.8
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+DOXYFILE_ENCODING = UTF-8
+PROJECT_NAME = "Hercules"
+PROJECT_NUMBER =
+PROJECT_BRIEF =
+PROJECT_LOGO = Hercules48.png
+OUTPUT_DIRECTORY = docs
+CREATE_SUBDIRS = NO
+ALLOW_UNICODE_NAMES = NO
+OUTPUT_LANGUAGE = English
+BRIEF_MEMBER_DESC = YES
+REPEAT_BRIEF = YES
+ABBREVIATE_BRIEF =
+ALWAYS_DETAILED_SEC = NO
+INLINE_INHERITED_MEMB = NO
+FULL_PATH_NAMES = YES
+STRIP_FROM_PATH = ../../
+STRIP_FROM_INC_PATH = ../../
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
+# first line (until the first dot) of a Javadoc-style comment as the brief
+# description. If set to NO, the Javadoc-style will behave just like regular Qt-
+# style comments (thus requiring an explicit @brief command for a brief
+# description.)
+# The default value is: NO.
+JAVADOC_AUTOBRIEF = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
+# line (until the first dot) of a Qt-style comment as the brief description. If
+# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
+# requiring an explicit \brief command for a brief description.)
+# The default value is: NO.
+QT_AUTOBRIEF = NO
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
+# documentation from any documented member that it re-implements.
+# The default value is: YES.
+
+INHERIT_DOCS = YES
+SEPARATE_MEMBER_PAGES = NO
+TAB_SIZE = 8
+
+# This tag can be used to specify a number of aliases that act as commands in
+# the documentation. An alias has the form:
+# name=value
+# For example adding
+# "sideeffect=@par Side Effects:\n"
+# will allow you to put the command \sideeffect (or @sideeffect) in the
+# documentation, which will result in a user-defined paragraph with heading
+# "Side Effects:". You can put \n's in the value part of an alias to insert
+# newlines.
+ALIASES =
+TCL_SUBST =
+OPTIMIZE_OUTPUT_FOR_C = YES
+OPTIMIZE_OUTPUT_JAVA = NO
+OPTIMIZE_FOR_FORTRAN = NO
+OPTIMIZE_OUTPUT_VHDL = NO
+EXTENSION_MAPPING = h=C
+MARKDOWN_SUPPORT = YES
+
+# When enabled doxygen tries to link words that correspond to documented
+# classes, or namespaces to their corresponding documentation. Such a link can
+# be prevented in individual cases by by putting a % sign in front of the word
+# or globally by setting AUTOLINK_SUPPORT to NO.
+# The default value is: YES.
+AUTOLINK_SUPPORT = YES
+BUILTIN_STL_SUPPORT = NO
+CPP_CLI_SUPPORT = NO
+SIP_SUPPORT = NO
+IDL_PROPERTY_SUPPORT = NO
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+# The default value is: NNO
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES to allow class member groups of the same type
+# (for instance a group of public functions) to be put as a subgroup of that
+# type (e.g. under the Public Functions section). Set it to NO to prevent
+# subgrouping. Alternatively, this can be done per class using the
+# \nosubgrouping command.
+# The default value is: YENO
+SUBGROUPING = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
+# are shown inside the group in which they are included (e.g. using \ingroup)
+# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
+# and RTF).
+#
+# Note that this feature does not work in combination with
+# SEPARATE_MEMBER_PAGES.
+# The default value is: NNO
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
+# with only public data fields or simple typedef fields will be shown inline in
+# the documentation of the scope in which they are defined (i.e. file,
+# namespace, or group documentation), provided this scope is documented. If set
+# to NO, structs, classes, and unions are shown on a separate page (for HTML and
+# Man pages) or section (for LaTeX and RTF).
+# The default value is: NNO
+INLINE_SIMPLE_STRUCTS = NO
+TYPEDEF_HIDES_STRUCT = NO
+
+# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
+# cache is used to resolve symbols given their name and scope. Since this can be
+# an expensive process and often the same symbol appears multiple times in the
+# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
+# doxygen will become slower. If the cache is too large, memory is wasted. The
+# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
+# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
+# symbols. At the end of a run doxygen will report the cache usage and suggest
+# the optimal cache size from a speed point of view.
+# Minimum value: 0, maximum value: 9, default value: 0.
+LOOKUP_CACHE_SIZE = 0
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available. Private
+# class members and static file members will be hidden unless the
+# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
+# Note: This will also disable the warnings about undocumented members that are
+# normally produced when WARNINGS is set to YES.
+# The default value is: NO.
+EXTRACT_ALL = NO
+EXTRACT_PRIVATE = YES
+
+# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
+# scope will be included in the documentation.
+# The default value is: NO.
+EXTRACT_PACKAGE = NO
+EXTRACT_STATIC = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO
+# only classes defined in header files are included. Does not have any effect
+# for Java sources.
+# The default value is: YES.
+EXTRACT_LOCAL_CLASSES = YES
+EXTRACT_LOCAL_METHODS = YES
+EXTRACT_ANON_NSPACES = NO
+HIDE_UNDOC_MEMBERS = NO
+HIDE_UNDOC_CLASSES = NO
+HIDE_FRIEND_COMPOUNDS = NO
+HIDE_IN_BODY_DOCS = NO
+INTERNAL_DOCS = NO
+CASE_SENSE_NAMES = YES
+HIDE_SCOPE_NAMES = NO
+SHOW_INCLUDE_FILES = YES
+
+# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
+# grouped member an include statement to the documentation, telling the reader
+# which file to include in order to use the member.
+# The default value is: NO.
+SHOW_GROUPED_MEMB_INC = NO
+FORCE_LOCAL_INCLUDES = NO
+INLINE_INFO = YES
+SORT_MEMBER_DOCS = YES
+SORT_BRIEF_DOCS = NO
+SORT_MEMBERS_CTORS_1ST = NO
+SORT_GROUP_NAMES = NO
+SORT_BY_SCOPE_NAME = NO
+STRICT_PROTO_MATCHING = NO
+GENERATE_TODOLIST = YES
+GENERATE_TESTLIST = YES
+GENERATE_BUGLIST = YES
+GENERATE_DEPRECATEDLIST= YES
+ENABLED_SECTIONS =
+MAX_INITIALIZER_LINES = 30
+SHOW_USED_FILES = YES
+SHOW_FILES = YES
+SHOW_NAMESPACES = YES
+FILE_VERSION_FILTER = "git log -n 1 --pretty=format:%h -- "
+LAYOUT_FILE = layoutFile.xml
+CITE_BIB_FILES =
+#---------------------------------------------------------------------------
+# Configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+QUIET = NO
+WARNINGS = YES
+WARN_IF_UNDOCUMENTED = YES
+WARN_IF_DOC_ERROR = YES
+WARN_NO_PARAMDOC = YES
+WARN_FORMAT = "$file:$line: $text"
+WARN_LOGFILE =
+#---------------------------------------------------------------------------
+# Configuration options related to the input files
+#---------------------------------------------------------------------------
+INPUT = ../../src/map \
+ ../../src/common \
+ ../../src/char \
+ ../../src/login \
+ ../../src/config
+INPUT_ENCODING = UTF-8
+FILE_PATTERNS = *.c \
+ *.h
+RECURSIVE = YES
+EXCLUDE =
+EXCLUDE_SYMLINKS = NO
+EXCLUDE_PATTERNS =
+EXCLUDE_SYMBOLS =
+EXAMPLE_PATH =
+EXAMPLE_PATTERNS =
+EXAMPLE_RECURSIVE = NO
+IMAGE_PATH =
+INPUT_FILTER =
+FILTER_PATTERNS =
+FILTER_SOURCE_FILES = NO
+FILTER_SOURCE_PATTERNS =
+
+# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# is part of the input, its contents will be placed on the main page
+# (index.html). This can be useful if you have a project on for instance GitHub
+# and want to reuse the introduction page also for the doxygen output.
+USE_MDFILE_AS_MAINPAGE =
+#---------------------------------------------------------------------------
+# Configuration options related to source browsing
+#---------------------------------------------------------------------------
+SOURCE_BROWSER = YES
+INLINE_SOURCES = NO
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
+# function all documented functions referencing it will be listed.
+# The default value is: NO.
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES then for each documented function
+# all documented entities called/used by that function will be listed.
+# The default value is: NO.
+REFERENCES_RELATION = NO
+REFERENCES_LINK_SOURCE = YES
+SOURCE_TOOLTIPS = YES
+USE_HTAGS = NO
+VERBATIM_HEADERS = YES
+
+# If the CLANG_ASSISTED_PARSING tag is set to YES, then doxygen will use the
+# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the
+# cost of reduced performance. This can be particularly helpful with template
+# rich C++ code for which doxygen's built-in parser lacks the necessary type
+# information.
+# Note: The availability of this option depends on whether or not doxygen was
+# compiled with the --with-libclang option.
+# The default value is: NO.
+CLANG_ASSISTED_PARSING = NO
+
+# If clang assisted parsing is enabled you can provide the compiler with command
+# line options that you would normally use when invoking the compiler. Note that
+# the include paths will already be set by doxygen for the files and directories
+# specified with INPUT and INCLUDE_PATH.
+# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
+CLANG_OPTIONS =
+#---------------------------------------------------------------------------
+# Configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX = YES
+COLS_IN_ALPHA_INDEX = 5
+IGNORE_PREFIX =
+#---------------------------------------------------------------------------
+# Configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML = YES
+HTML_OUTPUT = html
+HTML_FILE_EXTENSION = .html
+HTML_HEADER =
+HTML_FOOTER =
+HTML_STYLESHEET =
+HTML_EXTRA_STYLESHEET =
+HTML_EXTRA_FILES =
+HTML_COLORSTYLE_HUE = 30
+HTML_COLORSTYLE_SAT = 100
+HTML_COLORSTYLE_GAMMA = 80
+HTML_TIMESTAMP = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+HTML_DYNAMIC_SECTIONS = NO
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
+# shown in the various tree structured indices initially; the user can expand
+# and collapse entries dynamically later on. Doxygen will expand the tree to
+# such a level that at most the specified number of entries are visible (unless
+# a fully collapsed tree already exceeds this amount). So setting the number of
+# entries 1 will produce a full collapsed tree by default. 0 is a special value
+# representing an infinite number of entries and will result in a full expanded
+# tree by default.
+# Minimum value: 0, maximum value: 9999, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+HTML_INDEX_NUM_ENTRIES = 100
+GENERATE_DOCSET = NO
+DOCSET_FEEDNAME = "Doxygen generated docs"
+DOCSET_BUNDLE_ID = org.doxygen.Project
+DOCSET_PUBLISHER_ID = org.doxygen.Publisher
+DOCSET_PUBLISHER_NAME = Publisher
+GENERATE_HTMLHELP = NO
+CHM_FILE =
+HHC_LOCATION =
+GENERATE_CHI = NO
+CHM_INDEX_ENCODING =
+BINARY_TOC = NO
+TOC_EXPAND = NO
+GENERATE_QHP = NO
+QCH_FILE =
+QHP_NAMESPACE = org.doxygen.Project
+QHP_VIRTUAL_FOLDER = doc
+QHP_CUST_FILTER_NAME =
+QHP_CUST_FILTER_ATTRS =
+QHP_SECT_FILTER_ATTRS =
+QHG_LOCATION =
+GENERATE_ECLIPSEHELP = NO
+ECLIPSE_DOC_ID = org.doxygen.Project
+DISABLE_INDEX = NO
+GENERATE_TREEVIEW = NO
+ENUM_VALUES_PER_LINE = 4
+TREEVIEW_WIDTH = 250
+EXT_LINKS_IN_WINDOW = NO
+FORMULA_FONTSIZE = 10
+FORMULA_TRANSPARENT = YES
+USE_MATHJAX = NO
+MATHJAX_FORMAT = HTML-CSS
+MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
+MATHJAX_EXTENSIONS =
+MATHJAX_CODEFILE =
+SEARCHENGINE = YES
+SERVER_BASED_SEARCH = NO
+EXTERNAL_SEARCH = NO
+SEARCHENGINE_URL =
+SEARCHDATA_FILE = searchdata.xml
+EXTERNAL_SEARCH_ID =
+EXTRA_SEARCH_MAPPINGS =
+#---------------------------------------------------------------------------
+# Configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX = NO
+LATEX_OUTPUT = latex
+LATEX_CMD_NAME = latex
+MAKEINDEX_CMD_NAME = makeindex
+COMPACT_LATEX = NO
+PAPER_TYPE = a4
+EXTRA_PACKAGES =
+LATEX_HEADER =
+LATEX_FOOTER =
+LATEX_EXTRA_FILES =
+PDF_HYPERLINKS = YES
+USE_PDFLATEX = YES
+LATEX_BATCHMODE = NO
+LATEX_HIDE_INDICES = NO
+LATEX_SOURCE_CODE = NO
+LATEX_BIB_STYLE = plain
+#---------------------------------------------------------------------------
+# Configuration options related to the RTF output
+#---------------------------------------------------------------------------
+GENERATE_RTF = NO
+RTF_OUTPUT = rtf
+COMPACT_RTF = NO
+RTF_HYPERLINKS = NO
+RTF_STYLESHEET_FILE =
+RTF_EXTENSIONS_FILE =
+#---------------------------------------------------------------------------
+# Configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN = NO
+MAN_OUTPUT = man
+MAN_EXTENSION = .3
+MAN_SUBDIR =
+MAN_LINKS = NO
+#---------------------------------------------------------------------------
+# Configuration options related to the XML output
+#---------------------------------------------------------------------------
+GENERATE_XML = NO
+XML_OUTPUT = xml
+XML_PROGRAMLISTING = YES
+#---------------------------------------------------------------------------
+# Configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+GENERATE_DOCBOOK = NO
+DOCBOOK_OUTPUT = docbook
+DOCBOOK_PROGRAMLISTING = NO
+#---------------------------------------------------------------------------
+# Configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+GENERATE_AUTOGEN_DEF = NO
+#---------------------------------------------------------------------------
+# Configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+GENERATE_PERLMOD = NO
+PERLMOD_LATEX = NO
+PERLMOD_PRETTY = YES
+PERLMOD_MAKEVAR_PREFIX =
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+ENABLE_PREPROCESSING = YES
+MACRO_EXPANSION = YES
+EXPAND_ONLY_PREDEF = NO
+SEARCH_INCLUDES = YES
+INCLUDE_PATH = ../../src \
+ ../../3rdparty
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that are
+# defined before the preprocessor is started (similar to the -D option of e.g.
+# gcc). The argument of the tag is a list of macros of the form: name or
+# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
+# is assumed. To prevent a macro definition from being undefined via #undef or
+# recursively expanded use the := operator instead of the = operator.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+PREDEFINED =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
+# tag can be used to specify a list of macro names that should be expanded. The
+# macro definition that is found in the sources will be used. Use the PREDEFINED
+# tag if you want to use a different macro definition that overrules the
+# definition found in the source code.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+EXPAND_AS_DEFINED =
+SKIP_FUNCTION_MACROS = NO
+#---------------------------------------------------------------------------
+# Configuration options related to external references
+#---------------------------------------------------------------------------
+TAGFILES =
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external class will be listed in the
+# class index. If set to NO only the inherited external classes will be listed.
+# The default value is: NO.
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed in
+# the modules index. If set to NO, only the current project's groups will be
+# listed.
+# The default value is: YES.
+EXTERNAL_GROUPS = YES
+EXTERNAL_PAGES = YES
+PERL_PATH = /usr/bin/perl
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+CLASS_DIAGRAMS = YES
+MSCGEN_PATH =
+DIA_PATH =
+HIDE_UNDOC_RELATIONS = NO
+HAVE_DOT = YES
+DOT_NUM_THREADS = 0
+
+# When you want a differently looking font in the dot files that doxygen
+# generates you can specify the font name using DOT_FONTNAME. You need to make
+# sure dot is able to find the font, which can be done by putting it in a
+# standard location or by setting the DOTFONTPATH environment variable or by
+# setting DOT_FONTPATH to the directory containing the font.
+# The default value is: Helvetica.
+# This tag requires that the tag HAVE_DOT is set to YES.
+DOT_FONTNAME = Helvetica
+DOT_FONTSIZE = 10
+DOT_FONTPATH =
+CLASS_GRAPH = YES
+COLLABORATION_GRAPH = YES
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+UML_LOOK = NO
+UML_LIMIT_NUM_FIELDS = 10
+
+# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
+# collaboration graphs will show the relations between templates and their
+# instances.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+TEMPLATE_RELATIONS = NO
+INCLUDE_GRAPH = YES
+INCLUDED_BY_GRAPH = YES
+CALL_GRAPH = YES
+CALLER_GRAPH = YES
+GRAPHICAL_HIERARCHY = YES
+DIRECTORY_GRAPH = YES
+DOT_IMAGE_FORMAT = png
+INTERACTIVE_SVG = NO
+DOT_PATH =
+DOTFILE_DIRS =
+MSCFILE_DIRS =
+DIAFILE_DIRS =
+PLANTUML_JAR_PATH =
+DOT_GRAPH_MAX_NODES = 100
+MAX_DOT_GRAPH_DEPTH = 0
+DOT_TRANSPARENT = YES
+DOT_MULTI_TARGETS = YES
+GENERATE_LEGEND = YES
+DOT_CLEANUP = YES
diff --git a/tools/doxygen/footer.html b/tools/doxygen/footer.html
new file mode 100644
index 000000000..aecaafcc4
--- /dev/null
+++ b/tools/doxygen/footer.html
@@ -0,0 +1,21 @@
+<!-- HTML footer for doxygen 1.8.8-->
+<!-- start footer part -->
+<!--BEGIN GENERATE_TREEVIEW-->
+<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
+ <ul>
+ $navpath
+ <li class="footer">$generatedby
+ <a href="http://www.doxygen.org/index.html">
+ <img class="footer" src="$relpath^doxygen.png" alt="doxygen"/></a> $doxygenversion </li>
+ </ul>
+</div>
+<!--END GENERATE_TREEVIEW-->
+<!--BEGIN !GENERATE_TREEVIEW-->
+<hr class="footer"/><address class="footer"><small>
+$generatedby &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="$relpath^doxygen.png" alt="doxygen"/>
+</a> $doxygenversion
+</small></address>
+<!--END !GENERATE_TREEVIEW-->
+</body>
+</html>
diff --git a/tools/doxygen/header.html b/tools/doxygen/header.html
new file mode 100644
index 000000000..31aae0ea2
--- /dev/null
+++ b/tools/doxygen/header.html
@@ -0,0 +1,55 @@
+<!-- HTML header for doxygen 1.8.8-->
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen $doxygenversion"/>
+<!--BEGIN PROJECT_NAME--><title>$projectname: $title</title><!--END PROJECT_NAME-->
+<!--BEGIN !PROJECT_NAME--><title>$title</title><!--END !PROJECT_NAME-->
+<link href="$relpath^tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="$relpath^jquery.js"></script>
+<script type="text/javascript" src="$relpath^dynsections.js"></script>
+$treeview
+$search
+$mathjax
+<link href="$relpath^$stylesheet" rel="stylesheet" type="text/css" />
+$extrastylesheet
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+
+<!--BEGIN TITLEAREA-->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <!--BEGIN PROJECT_LOGO-->
+ <td id="projectlogo"><img alt="Logo" src="$relpath^$projectlogo"/></td>
+ <!--END PROJECT_LOGO-->
+ <!--BEGIN PROJECT_NAME-->
+ <td style="padding-left: 0.5em;">
+ <div id="projectname">$projectname
+ <!--BEGIN PROJECT_NUMBER-->&#160;<span id="projectnumber">$projectnumber</span><!--END PROJECT_NUMBER-->
+ </div>
+ <!--BEGIN PROJECT_BRIEF--><div id="projectbrief">$projectbrief</div><!--END PROJECT_BRIEF-->
+ </td>
+ <!--END PROJECT_NAME-->
+ <!--BEGIN !PROJECT_NAME-->
+ <!--BEGIN PROJECT_BRIEF-->
+ <td style="padding-left: 0.5em;">
+ <div id="projectbrief">$projectbrief</div>
+ </td>
+ <!--END PROJECT_BRIEF-->
+ <!--END !PROJECT_NAME-->
+ <!--BEGIN DISABLE_INDEX-->
+ <!--BEGIN SEARCHENGINE-->
+ <td>$searchbox</td>
+ <!--END SEARCHENGINE-->
+ <!--END DISABLE_INDEX-->
+ </tr>
+ </tbody>
+</table>
+</div>
+<!--END TITLEAREA-->
+<!-- end header part -->
diff --git a/tools/doxygen/layoutFile.xml b/tools/doxygen/layoutFile.xml
new file mode 100644
index 000000000..740548619
--- /dev/null
+++ b/tools/doxygen/layoutFile.xml
@@ -0,0 +1,194 @@
+<doxygenlayout version="1.0">
+ <!-- Generated by doxygen 1.8.8 -->
+ <!-- Navigation index tabs for HTML output -->
+ <navindex>
+ <tab type="mainpage" visible="yes" title=""/>
+ <tab type="pages" visible="yes" title="" intro=""/>
+ <tab type="modules" visible="yes" title="" intro=""/>
+ <tab type="namespaces" visible="yes" title="">
+ <tab type="namespacelist" visible="yes" title="" intro=""/>
+ <tab type="namespacemembers" visible="yes" title="" intro=""/>
+ </tab>
+ <tab type="classes" visible="yes" title="">
+ <tab type="classlist" visible="yes" title="" intro=""/>
+ <tab type="classindex" visible="$ALPHABETICAL_INDEX" title=""/>
+ <tab type="hierarchy" visible="yes" title="" intro=""/>
+ <tab type="classmembers" visible="yes" title="" intro=""/>
+ </tab>
+ <tab type="files" visible="yes" title="">
+ <tab type="filelist" visible="yes" title="" intro=""/>
+ <tab type="globals" visible="yes" title="" intro=""/>
+ </tab>
+ <tab type="examples" visible="yes" title="" intro=""/>
+ </navindex>
+
+ <!-- Layout definition for a class page -->
+ <class>
+ <briefdescription visible="yes"/>
+ <includes visible="$SHOW_INCLUDE_FILES"/>
+ <inheritancegraph visible="$CLASS_GRAPH"/>
+ <collaborationgraph visible="$COLLABORATION_GRAPH"/>
+ <memberdecl>
+ <nestedclasses visible="yes" title=""/>
+ <publictypes title=""/>
+ <services title=""/>
+ <interfaces title=""/>
+ <publicslots title=""/>
+ <signals title=""/>
+ <publicmethods title=""/>
+ <publicstaticmethods title=""/>
+ <publicattributes title=""/>
+ <publicstaticattributes title=""/>
+ <protectedtypes title=""/>
+ <protectedslots title=""/>
+ <protectedmethods title=""/>
+ <protectedstaticmethods title=""/>
+ <protectedattributes title=""/>
+ <protectedstaticattributes title=""/>
+ <packagetypes title=""/>
+ <packagemethods title=""/>
+ <packagestaticmethods title=""/>
+ <packageattributes title=""/>
+ <packagestaticattributes title=""/>
+ <properties title=""/>
+ <events title=""/>
+ <privatetypes title=""/>
+ <privateslots title=""/>
+ <privatemethods title=""/>
+ <privatestaticmethods title=""/>
+ <privateattributes title=""/>
+ <privatestaticattributes title=""/>
+ <friends title=""/>
+ <related title="" subtitle=""/>
+ <membergroups visible="yes"/>
+ </memberdecl>
+ <detaileddescription title=""/>
+ <memberdef>
+ <inlineclasses title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <services title=""/>
+ <interfaces title=""/>
+ <constructors title=""/>
+ <functions title=""/>
+ <related title=""/>
+ <variables title=""/>
+ <properties title=""/>
+ <events title=""/>
+ </memberdef>
+ <allmemberslink visible="yes"/>
+ <usedfiles visible="$SHOW_USED_FILES"/>
+ <authorsection visible="yes"/>
+ </class>
+
+ <!-- Layout definition for a namespace page -->
+ <namespace>
+ <briefdescription visible="yes"/>
+ <memberdecl>
+ <nestednamespaces visible="yes" title=""/>
+ <constantgroups visible="yes" title=""/>
+ <classes visible="yes" title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <functions title=""/>
+ <variables title=""/>
+ <membergroups visible="yes"/>
+ </memberdecl>
+ <detaileddescription title=""/>
+ <memberdef>
+ <inlineclasses title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <functions title=""/>
+ <variables title=""/>
+ </memberdef>
+ <authorsection visible="yes"/>
+ </namespace>
+
+ <!-- Layout definition for a file page -->
+ <file>
+ <briefdescription visible="yes"/>
+ <includes visible="$SHOW_INCLUDE_FILES"/>
+ <includegraph visible="$INCLUDE_GRAPH"/>
+ <includedbygraph visible="$INCLUDED_BY_GRAPH"/>
+ <sourcelink visible="yes"/>
+ <memberdecl>
+ <classes visible="yes" title=""/>
+ <namespaces visible="yes" title=""/>
+ <constantgroups visible="yes" title=""/>
+ <defines title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <functions title=""/>
+ <variables title=""/>
+ <membergroups visible="yes"/>
+ </memberdecl>
+ <detaileddescription title=""/>
+ <memberdef>
+ <inlineclasses title=""/>
+ <defines title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <functions title=""/>
+ <variables title=""/>
+ </memberdef>
+ <authorsection/>
+ </file>
+
+ <!-- Layout definition for a group page -->
+ <group>
+ <briefdescription visible="yes"/>
+ <groupgraph visible="$GROUP_GRAPHS"/>
+ <memberdecl>
+ <nestedgroups visible="yes" title=""/>
+ <dirs visible="yes" title=""/>
+ <files visible="yes" title=""/>
+ <namespaces visible="yes" title=""/>
+ <classes visible="yes" title=""/>
+ <defines title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <enumvalues title=""/>
+ <functions title=""/>
+ <variables title=""/>
+ <signals title=""/>
+ <publicslots title=""/>
+ <protectedslots title=""/>
+ <privateslots title=""/>
+ <events title=""/>
+ <properties title=""/>
+ <friends title=""/>
+ <membergroups visible="yes"/>
+ </memberdecl>
+ <detaileddescription title=""/>
+ <memberdef>
+ <pagedocs/>
+ <inlineclasses title=""/>
+ <defines title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <enumvalues title=""/>
+ <functions title=""/>
+ <variables title=""/>
+ <signals title=""/>
+ <publicslots title=""/>
+ <protectedslots title=""/>
+ <privateslots title=""/>
+ <events title=""/>
+ <properties title=""/>
+ <friends title=""/>
+ </memberdef>
+ <authorsection visible="yes"/>
+ </group>
+
+ <!-- Layout definition for a directory page -->
+ <directory>
+ <briefdescription visible="yes"/>
+ <directorygraph visible="yes"/>
+ <memberdecl>
+ <dirs visible="yes"/>
+ <files visible="yes"/>
+ </memberdecl>
+ <detaileddescription title=""/>
+ </directory>
+</doxygenlayout>
diff --git a/tools/doxygen/pages_index.html b/tools/doxygen/pages_index.html
new file mode 100644
index 000000000..c9ca5b58c
--- /dev/null
+++ b/tools/doxygen/pages_index.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+ <meta http-equiv="X-UA-Compatible" content="IE=9"/>
+ <title>Hercules documentation</title>
+ <link href="docs/doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+ <div id="top">
+ <div id="titlearea">
+ <table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectlogo"><img alt="Logo" src="docs/Hercules48.png"/></td>
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">Hercules</div>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </div>
+ <div class="header">
+ <div class="headertitle">
+ <div class="title">Hercules Documentation</div>
+ </div>
+ </div><!--header-->
+ <div class="contents">
+ <ul>
+ <li><a href="docs/">Doxygen</a></li>
+ <li><a href="gcov_pre.html">Coverage Report: pre-renewal build</a> <a href="gcov_pre.txt">(raw data)</a></li>
+ <li><a href="gcov_re.html">Coverage Report: renewal build</a> <a href="gcov_re.txt">(raw data)</a></li>
+ <li><a href="https://github.com/HerculesWS/Hercules">GitHub</a></li>
+ <li><a href="https://gitlab.com/HerculesWS/Hercules">GitLab</a></li>
+ </ul>
+ </div><!-- contents -->
+ <hr class="footer">
+</body></html>
diff --git a/tools/doxygen/style.css b/tools/doxygen/style.css
new file mode 100644
index 000000000..02e8b0152
--- /dev/null
+++ b/tools/doxygen/style.css
@@ -0,0 +1,1440 @@
+/* The standard CSS for doxygen 1.8.8 */
+
+body, table, div, p, dl {
+ font: 400 14px/22px Roboto,sans-serif;
+}
+
+/* @group Heading Levels */
+
+h1.groupheader {
+ font-size: 150%;
+}
+
+.title {
+ font: 400 14px/28px Roboto,sans-serif;
+ font-size: 150%;
+ font-weight: bold;
+ margin: 10px 2px;
+}
+
+h2.groupheader {
+ border-bottom: 1px solid #879ECB;
+ color: #354C7B;
+ font-size: 150%;
+ font-weight: normal;
+ margin-top: 1.75em;
+ padding-top: 8px;
+ padding-bottom: 4px;
+ width: 100%;
+}
+
+h3.groupheader {
+ font-size: 100%;
+}
+
+h1, h2, h3, h4, h5, h6 {
+ -webkit-transition: text-shadow 0.5s linear;
+ -moz-transition: text-shadow 0.5s linear;
+ -ms-transition: text-shadow 0.5s linear;
+ -o-transition: text-shadow 0.5s linear;
+ transition: text-shadow 0.5s linear;
+ margin-right: 15px;
+}
+
+h1.glow, h2.glow, h3.glow, h4.glow, h5.glow, h6.glow {
+ text-shadow: 0 0 15px cyan;
+}
+
+dt {
+ font-weight: bold;
+}
+
+div.multicol {
+ -moz-column-gap: 1em;
+ -webkit-column-gap: 1em;
+ -moz-column-count: 3;
+ -webkit-column-count: 3;
+}
+
+p.startli, p.startdd {
+ margin-top: 2px;
+}
+
+p.starttd {
+ margin-top: 0px;
+}
+
+p.endli {
+ margin-bottom: 0px;
+}
+
+p.enddd {
+ margin-bottom: 4px;
+}
+
+p.endtd {
+ margin-bottom: 2px;
+}
+
+/* @end */
+
+caption {
+ font-weight: bold;
+}
+
+span.legend {
+ font-size: 70%;
+ text-align: center;
+}
+
+h3.version {
+ font-size: 90%;
+ text-align: center;
+}
+
+div.qindex, div.navtab{
+ background-color: #EBEFF6;
+ border: 1px solid #A3B4D7;
+ text-align: center;
+}
+
+div.qindex, div.navpath {
+ width: 100%;
+ line-height: 140%;
+}
+
+div.navtab {
+ margin-right: 15px;
+}
+
+/* @group Link Styling */
+
+a {
+ color: #3D578C;
+ font-weight: normal;
+ text-decoration: none;
+}
+
+.contents a:visited {
+ color: #4665A2;
+}
+
+a:hover {
+ text-decoration: underline;
+}
+
+a.qindex {
+ font-weight: bold;
+}
+
+a.qindexHL {
+ font-weight: bold;
+ background-color: #9CAFD4;
+ color: #ffffff;
+ border: 1px double #869DCA;
+}
+
+.contents a.qindexHL:visited {
+ color: #ffffff;
+}
+
+a.el {
+ font-weight: bold;
+}
+
+a.elRef {
+}
+
+a.code, a.code:visited, a.line, a.line:visited {
+ color: #4665A2;
+}
+
+a.codeRef, a.codeRef:visited, a.lineRef, a.lineRef:visited {
+ color: #4665A2;
+}
+
+/* @end */
+
+dl.el {
+ margin-left: -1cm;
+}
+
+pre.fragment {
+ border: 1px solid #C4CFE5;
+ background-color: #FBFCFD;
+ padding: 4px 6px;
+ margin: 4px 8px 4px 2px;
+ overflow: auto;
+ word-wrap: break-word;
+ font-size: 9pt;
+ line-height: 125%;
+ font-family: monospace, fixed;
+ font-size: 105%;
+}
+
+div.fragment {
+ padding: 4px 6px;
+ margin: 4px 8px 4px 2px;
+ background-color: #FBFCFD;
+ border: 1px solid #C4CFE5;
+}
+
+div.line {
+ font-family: monospace, fixed;
+ font-size: 13px;
+ min-height: 13px;
+ line-height: 1.0;
+ text-wrap: unrestricted;
+ white-space: -moz-pre-wrap; /* Moz */
+ white-space: -pre-wrap; /* Opera 4-6 */
+ white-space: -o-pre-wrap; /* Opera 7 */
+ white-space: pre-wrap; /* CSS3 */
+ word-wrap: break-word; /* IE 5.5+ */
+ text-indent: -53px;
+ padding-left: 53px;
+ padding-bottom: 0px;
+ margin: 0px;
+ -webkit-transition-property: background-color, box-shadow;
+ -webkit-transition-duration: 0.5s;
+ -moz-transition-property: background-color, box-shadow;
+ -moz-transition-duration: 0.5s;
+ -ms-transition-property: background-color, box-shadow;
+ -ms-transition-duration: 0.5s;
+ -o-transition-property: background-color, box-shadow;
+ -o-transition-duration: 0.5s;
+ transition-property: background-color, box-shadow;
+ transition-duration: 0.5s;
+}
+
+div.line.glow {
+ background-color: cyan;
+ box-shadow: 0 0 10px cyan;
+}
+
+
+span.lineno {
+ padding-right: 4px;
+ text-align: right;
+ border-right: 2px solid #0F0;
+ background-color: #E8E8E8;
+ white-space: pre;
+}
+span.lineno a {
+ background-color: #D8D8D8;
+}
+
+span.lineno a:hover {
+ background-color: #C8C8C8;
+}
+
+div.ah {
+ background-color: black;
+ font-weight: bold;
+ color: #ffffff;
+ margin-bottom: 3px;
+ margin-top: 3px;
+ padding: 0.2em;
+ border: solid thin #333;
+ border-radius: 0.5em;
+ -webkit-border-radius: .5em;
+ -moz-border-radius: .5em;
+ box-shadow: 2px 2px 3px #999;
+ -webkit-box-shadow: 2px 2px 3px #999;
+ -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px;
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#000),color-stop(0.3, #444));
+ background-image: -moz-linear-gradient(center top, #eee 0%, #444 40%, #000);
+}
+
+div.groupHeader {
+ margin-left: 16px;
+ margin-top: 12px;
+ font-weight: bold;
+}
+
+div.groupText {
+ margin-left: 16px;
+ font-style: italic;
+}
+
+body {
+ background-color: white;
+ color: black;
+ margin: 0;
+}
+
+div.contents {
+ margin-top: 10px;
+ margin-left: 12px;
+ margin-right: 8px;
+}
+
+td.indexkey {
+ background-color: #EBEFF6;
+ font-weight: bold;
+ border: 1px solid #C4CFE5;
+ margin: 2px 0px 2px 0;
+ padding: 2px 10px;
+ white-space: nowrap;
+ vertical-align: top;
+}
+
+td.indexvalue {
+ background-color: #EBEFF6;
+ border: 1px solid #C4CFE5;
+ padding: 2px 10px;
+ margin: 2px 0px;
+}
+
+tr.memlist {
+ background-color: #EEF1F7;
+}
+
+p.formulaDsp {
+ text-align: center;
+}
+
+img.formulaDsp {
+
+}
+
+img.formulaInl {
+ vertical-align: middle;
+}
+
+div.center {
+ text-align: center;
+ margin-top: 0px;
+ margin-bottom: 0px;
+ padding: 0px;
+}
+
+div.center img {
+ border: 0px;
+}
+
+address.footer {
+ text-align: right;
+ padding-right: 12px;
+}
+
+img.footer {
+ border: 0px;
+ vertical-align: middle;
+}
+
+/* @group Code Colorization */
+
+span.keyword {
+ color: #008000
+}
+
+span.keywordtype {
+ color: #604020
+}
+
+span.keywordflow {
+ color: #e08000
+}
+
+span.comment {
+ color: #800000
+}
+
+span.preprocessor {
+ color: #806020
+}
+
+span.stringliteral {
+ color: #002080
+}
+
+span.charliteral {
+ color: #008080
+}
+
+span.vhdldigit {
+ color: #ff00ff
+}
+
+span.vhdlchar {
+ color: #000000
+}
+
+span.vhdlkeyword {
+ color: #700070
+}
+
+span.vhdllogic {
+ color: #ff0000
+}
+
+blockquote {
+ background-color: #F7F8FB;
+ border-left: 2px solid #9CAFD4;
+ margin: 0 24px 0 4px;
+ padding: 0 12px 0 16px;
+}
+
+/* @end */
+
+/*
+.search {
+ color: #003399;
+ font-weight: bold;
+}
+
+form.search {
+ margin-bottom: 0px;
+ margin-top: 0px;
+}
+
+input.search {
+ font-size: 75%;
+ color: #000080;
+ font-weight: normal;
+ background-color: #e8eef2;
+}
+*/
+
+td.tiny {
+ font-size: 75%;
+}
+
+.dirtab {
+ padding: 4px;
+ border-collapse: collapse;
+ border: 1px solid #A3B4D7;
+}
+
+th.dirtab {
+ background: #EBEFF6;
+ font-weight: bold;
+}
+
+hr {
+ height: 0px;
+ border: none;
+ border-top: 1px solid #4A6AAA;
+}
+
+hr.footer {
+ height: 1px;
+}
+
+/* @group Member Descriptions */
+
+table.memberdecls {
+ border-spacing: 0px;
+ padding: 0px;
+}
+
+.memberdecls td, .fieldtable tr {
+ -webkit-transition-property: background-color, box-shadow;
+ -webkit-transition-duration: 0.5s;
+ -moz-transition-property: background-color, box-shadow;
+ -moz-transition-duration: 0.5s;
+ -ms-transition-property: background-color, box-shadow;
+ -ms-transition-duration: 0.5s;
+ -o-transition-property: background-color, box-shadow;
+ -o-transition-duration: 0.5s;
+ transition-property: background-color, box-shadow;
+ transition-duration: 0.5s;
+}
+
+.memberdecls td.glow, .fieldtable tr.glow {
+ background-color: cyan;
+ box-shadow: 0 0 15px cyan;
+}
+
+.mdescLeft, .mdescRight,
+.memItemLeft, .memItemRight,
+.memTemplItemLeft, .memTemplItemRight, .memTemplParams {
+ background-color: #F9FAFC;
+ border: none;
+ margin: 4px;
+ padding: 1px 0 0 8px;
+}
+
+.mdescLeft, .mdescRight {
+ padding: 0px 8px 4px 8px;
+ color: #555;
+}
+
+.memSeparator {
+ border-bottom: 1px solid #DEE4F0;
+ line-height: 1px;
+ margin: 0px;
+ padding: 0px;
+}
+
+.memItemLeft, .memTemplItemLeft {
+ white-space: nowrap;
+}
+
+.memItemRight {
+ width: 100%;
+}
+
+.memTemplParams {
+ color: #4665A2;
+ white-space: nowrap;
+ font-size: 80%;
+}
+
+/* @end */
+
+/* @group Member Details */
+
+/* Styles for detailed member documentation */
+
+.memtemplate {
+ font-size: 80%;
+ color: #4665A2;
+ font-weight: normal;
+ margin-left: 9px;
+}
+
+.memnav {
+ background-color: #EBEFF6;
+ border: 1px solid #A3B4D7;
+ text-align: center;
+ margin: 2px;
+ margin-right: 15px;
+ padding: 2px;
+}
+
+.mempage {
+ width: 100%;
+}
+
+.memitem {
+ padding: 0;
+ margin-bottom: 10px;
+ margin-right: 5px;
+ -webkit-transition: box-shadow 0.5s linear;
+ -moz-transition: box-shadow 0.5s linear;
+ -ms-transition: box-shadow 0.5s linear;
+ -o-transition: box-shadow 0.5s linear;
+ transition: box-shadow 0.5s linear;
+ display: table !important;
+ width: 100%;
+}
+
+.memitem.glow {
+ box-shadow: 0 0 15px cyan;
+}
+
+.memname {
+ font-weight: bold;
+ margin-left: 6px;
+}
+
+.memname td {
+ vertical-align: bottom;
+}
+
+.memproto, dl.reflist dt {
+ border-top: 1px solid #A8B8D9;
+ border-left: 1px solid #A8B8D9;
+ border-right: 1px solid #A8B8D9;
+ padding: 6px 0px 6px 0px;
+ color: #253555;
+ font-weight: bold;
+ text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9);
+ background-image:url('nav_f.png');
+ background-repeat:repeat-x;
+ background-color: #E2E8F2;
+ /* opera specific markup */
+ box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
+ border-top-right-radius: 4px;
+ border-top-left-radius: 4px;
+ /* firefox specific markup */
+ -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px;
+ -moz-border-radius-topright: 4px;
+ -moz-border-radius-topleft: 4px;
+ /* webkit specific markup */
+ -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
+ -webkit-border-top-right-radius: 4px;
+ -webkit-border-top-left-radius: 4px;
+
+}
+
+.memdoc, dl.reflist dd {
+ border-bottom: 1px solid #A8B8D9;
+ border-left: 1px solid #A8B8D9;
+ border-right: 1px solid #A8B8D9;
+ padding: 6px 10px 2px 10px;
+ background-color: #FBFCFD;
+ border-top-width: 0;
+ background-image:url('nav_g.png');
+ background-repeat:repeat-x;
+ background-color: #FFFFFF;
+ /* opera specific markup */
+ border-bottom-left-radius: 4px;
+ border-bottom-right-radius: 4px;
+ box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
+ /* firefox specific markup */
+ -moz-border-radius-bottomleft: 4px;
+ -moz-border-radius-bottomright: 4px;
+ -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px;
+ /* webkit specific markup */
+ -webkit-border-bottom-left-radius: 4px;
+ -webkit-border-bottom-right-radius: 4px;
+ -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
+}
+
+dl.reflist dt {
+ padding: 5px;
+}
+
+dl.reflist dd {
+ margin: 0px 0px 10px 0px;
+ padding: 5px;
+}
+
+.paramkey {
+ text-align: right;
+}
+
+.paramtype {
+ white-space: nowrap;
+}
+
+.paramname {
+ color: #602020;
+ white-space: nowrap;
+}
+.paramname em {
+ font-style: normal;
+}
+.paramname code {
+ line-height: 14px;
+}
+
+.params, .retval, .exception, .tparams {
+ margin-left: 0px;
+ padding-left: 0px;
+}
+
+.params .paramname, .retval .paramname {
+ font-weight: bold;
+ vertical-align: top;
+}
+
+.params .paramtype {
+ font-style: italic;
+ vertical-align: top;
+}
+
+.params .paramdir {
+ font-family: "courier new",courier,monospace;
+ vertical-align: top;
+}
+
+table.mlabels {
+ border-spacing: 0px;
+}
+
+td.mlabels-left {
+ width: 100%;
+ padding: 0px;
+}
+
+td.mlabels-right {
+ vertical-align: bottom;
+ padding: 0px;
+ white-space: nowrap;
+}
+
+span.mlabels {
+ margin-left: 8px;
+}
+
+span.mlabel {
+ background-color: #728DC1;
+ border-top:1px solid #5373B4;
+ border-left:1px solid #5373B4;
+ border-right:1px solid #C4CFE5;
+ border-bottom:1px solid #C4CFE5;
+ text-shadow: none;
+ color: white;
+ margin-right: 4px;
+ padding: 2px 3px;
+ border-radius: 3px;
+ font-size: 7pt;
+ white-space: nowrap;
+ vertical-align: middle;
+}
+
+
+
+/* @end */
+
+/* these are for tree view inside a (index) page */
+
+div.directory {
+ margin: 10px 0px;
+ border-top: 1px solid #9CAFD4;
+ border-bottom: 1px solid #9CAFD4;
+ width: 100%;
+}
+
+.directory table {
+ border-collapse:collapse;
+}
+
+.directory td {
+ margin: 0px;
+ padding: 0px;
+ vertical-align: top;
+}
+
+.directory td.entry {
+ white-space: nowrap;
+ padding-right: 6px;
+ padding-top: 3px;
+}
+
+.directory td.entry a {
+ outline:none;
+}
+
+.directory td.entry a img {
+ border: none;
+}
+
+.directory td.desc {
+ width: 100%;
+ padding-left: 6px;
+ padding-right: 6px;
+ padding-top: 3px;
+ border-left: 1px solid rgba(0,0,0,0.05);
+}
+
+.directory tr.even {
+ padding-left: 6px;
+ background-color: #F7F8FB;
+}
+
+.directory img {
+ vertical-align: -30%;
+}
+
+.directory .levels {
+ white-space: nowrap;
+ width: 100%;
+ text-align: right;
+ font-size: 9pt;
+}
+
+.directory .levels span {
+ cursor: pointer;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: #3D578C;
+}
+
+.arrow {
+ color: #9CAFD4;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ cursor: pointer;
+ font-size: 80%;
+ display: inline-block;
+ width: 16px;
+ height: 22px;
+}
+
+.icon {
+ font-family: Arial, Helvetica;
+ font-weight: bold;
+ font-size: 12px;
+ height: 14px;
+ width: 16px;
+ display: inline-block;
+ background-color: #728DC1;
+ color: white;
+ text-align: center;
+ border-radius: 4px;
+ margin-left: 2px;
+ margin-right: 2px;
+}
+
+.icona {
+ width: 24px;
+ height: 22px;
+ display: inline-block;
+}
+
+.iconfopen {
+ width: 24px;
+ height: 18px;
+ margin-bottom: 4px;
+ background-image:url('ftv2folderopen.png');
+ background-position: 0px -4px;
+ background-repeat: repeat-y;
+ vertical-align:top;
+ display: inline-block;
+}
+
+.iconfclosed {
+ width: 24px;
+ height: 18px;
+ margin-bottom: 4px;
+ background-image:url('ftv2folderclosed.png');
+ background-position: 0px -4px;
+ background-repeat: repeat-y;
+ vertical-align:top;
+ display: inline-block;
+}
+
+.icondoc {
+ width: 24px;
+ height: 18px;
+ margin-bottom: 4px;
+ background-image:url('ftv2doc.png');
+ background-position: 0px -4px;
+ background-repeat: repeat-y;
+ vertical-align:top;
+ display: inline-block;
+}
+
+table.directory {
+ font: 400 14px Roboto,sans-serif;
+}
+
+/* @end */
+
+div.dynheader {
+ margin-top: 8px;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+address {
+ font-style: normal;
+ color: #2A3D61;
+}
+
+table.doxtable {
+ border-collapse:collapse;
+ margin-top: 4px;
+ margin-bottom: 4px;
+}
+
+table.doxtable td, table.doxtable th {
+ border: 1px solid #2D4068;
+ padding: 3px 7px 2px;
+}
+
+table.doxtable th {
+ background-color: #374F7F;
+ color: #FFFFFF;
+ font-size: 110%;
+ padding-bottom: 4px;
+ padding-top: 5px;
+}
+
+table.fieldtable {
+ /*width: 100%;*/
+ margin-bottom: 10px;
+ border: 1px solid #A8B8D9;
+ border-spacing: 0px;
+ -moz-border-radius: 4px;
+ -webkit-border-radius: 4px;
+ border-radius: 4px;
+ -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px;
+ -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15);
+ box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15);
+}
+
+.fieldtable td, .fieldtable th {
+ padding: 3px 7px 2px;
+}
+
+.fieldtable td.fieldtype, .fieldtable td.fieldname {
+ white-space: nowrap;
+ border-right: 1px solid #A8B8D9;
+ border-bottom: 1px solid #A8B8D9;
+ vertical-align: top;
+}
+
+.fieldtable td.fieldname {
+ padding-top: 3px;
+}
+
+.fieldtable td.fielddoc {
+ border-bottom: 1px solid #A8B8D9;
+ /*width: 100%;*/
+}
+
+.fieldtable td.fielddoc p:first-child {
+ margin-top: 0px;
+}
+
+.fieldtable td.fielddoc p:last-child {
+ margin-bottom: 2px;
+}
+
+.fieldtable tr:last-child td {
+ border-bottom: none;
+}
+
+.fieldtable th {
+ background-image:url('nav_f.png');
+ background-repeat:repeat-x;
+ background-color: #E2E8F2;
+ font-size: 90%;
+ color: #253555;
+ padding-bottom: 4px;
+ padding-top: 5px;
+ text-align:left;
+ -moz-border-radius-topleft: 4px;
+ -moz-border-radius-topright: 4px;
+ -webkit-border-top-left-radius: 4px;
+ -webkit-border-top-right-radius: 4px;
+ border-top-left-radius: 4px;
+ border-top-right-radius: 4px;
+ border-bottom: 1px solid #A8B8D9;
+}
+
+
+.tabsearch {
+ top: 0px;
+ left: 10px;
+ height: 36px;
+ background-image: url('tab_b.png');
+ z-index: 101;
+ overflow: hidden;
+ font-size: 13px;
+}
+
+.navpath ul
+{
+ font-size: 11px;
+ background-image:url('tab_b.png');
+ background-repeat:repeat-x;
+ background-position: 0 -5px;
+ height:30px;
+ line-height:30px;
+ color:#8AA0CC;
+ border:solid 1px #C2CDE4;
+ overflow:hidden;
+ margin:0px;
+ padding:0px;
+}
+
+.navpath li
+{
+ list-style-type:none;
+ float:left;
+ padding-left:10px;
+ padding-right:15px;
+ background-image:url('bc_s.png');
+ background-repeat:no-repeat;
+ background-position:right;
+ color:#364D7C;
+}
+
+.navpath li.navelem a
+{
+ height:32px;
+ display:block;
+ text-decoration: none;
+ outline: none;
+ color: #283A5D;
+ font-family: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif;
+ text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9);
+ text-decoration: none;
+}
+
+.navpath li.navelem a:hover
+{
+ color:#6884BD;
+}
+
+.navpath li.footer
+{
+ list-style-type:none;
+ float:right;
+ padding-left:10px;
+ padding-right:15px;
+ background-image:none;
+ background-repeat:no-repeat;
+ background-position:right;
+ color:#364D7C;
+ font-size: 8pt;
+}
+
+
+div.summary
+{
+ float: right;
+ font-size: 8pt;
+ padding-right: 5px;
+ width: 50%;
+ text-align: right;
+}
+
+div.summary a
+{
+ white-space: nowrap;
+}
+
+div.ingroups
+{
+ font-size: 8pt;
+ width: 50%;
+ text-align: left;
+}
+
+div.ingroups a
+{
+ white-space: nowrap;
+}
+
+div.header
+{
+ background-image:url('nav_h.png');
+ background-repeat:repeat-x;
+ background-color: #F9FAFC;
+ margin: 0px;
+ border-bottom: 1px solid #C4CFE5;
+}
+
+div.headertitle
+{
+ padding: 5px 5px 5px 10px;
+}
+
+dl
+{
+ padding: 0 0 0 10px;
+}
+
+/* dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug */
+dl.section
+{
+ margin-left: 0px;
+ padding-left: 0px;
+}
+
+dl.note
+{
+ margin-left:-7px;
+ padding-left: 3px;
+ border-left:4px solid;
+ border-color: #D0C000;
+}
+
+dl.warning, dl.attention
+{
+ margin-left:-7px;
+ padding-left: 3px;
+ border-left:4px solid;
+ border-color: #FF0000;
+}
+
+dl.pre, dl.post, dl.invariant
+{
+ margin-left:-7px;
+ padding-left: 3px;
+ border-left:4px solid;
+ border-color: #00D000;
+}
+
+dl.deprecated
+{
+ margin-left:-7px;
+ padding-left: 3px;
+ border-left:4px solid;
+ border-color: #505050;
+}
+
+dl.todo
+{
+ margin-left:-7px;
+ padding-left: 3px;
+ border-left:4px solid;
+ border-color: #00C0E0;
+}
+
+dl.test
+{
+ margin-left:-7px;
+ padding-left: 3px;
+ border-left:4px solid;
+ border-color: #3030E0;
+}
+
+dl.bug
+{
+ margin-left:-7px;
+ padding-left: 3px;
+ border-left:4px solid;
+ border-color: #C08050;
+}
+
+dl.section dd {
+ margin-bottom: 6px;
+}
+
+
+#projectlogo
+{
+ text-align: center;
+ vertical-align: bottom;
+ border-collapse: separate;
+}
+
+#projectlogo img
+{
+ border: 0px none;
+}
+
+#projectname
+{
+ font: 300% Tahoma, Arial,sans-serif;
+ margin: 0px;
+ padding: 2px 0px;
+}
+
+#projectbrief
+{
+ font: 120% Tahoma, Arial,sans-serif;
+ margin: 0px;
+ padding: 0px;
+}
+
+#projectnumber
+{
+ font: 50% Tahoma, Arial,sans-serif;
+ margin: 0px;
+ padding: 0px;
+}
+
+#titlearea
+{
+ padding: 0px;
+ margin: 0px;
+ width: 100%;
+ border-bottom: 1px solid #5373B4;
+}
+
+.image
+{
+ text-align: center;
+}
+
+.dotgraph
+{
+ text-align: center;
+}
+
+.mscgraph
+{
+ text-align: center;
+}
+
+.diagraph
+{
+ text-align: center;
+}
+
+.caption
+{
+ font-weight: bold;
+}
+
+div.zoom
+{
+ border: 1px solid #90A5CE;
+}
+
+dl.citelist {
+ margin-bottom:50px;
+}
+
+dl.citelist dt {
+ color:#334975;
+ float:left;
+ font-weight:bold;
+ margin-right:10px;
+ padding:5px;
+}
+
+dl.citelist dd {
+ margin:2px 0;
+ padding:5px 0;
+}
+
+div.toc {
+ padding: 14px 25px;
+ background-color: #F4F6FA;
+ border: 1px solid #D8DFEE;
+ border-radius: 7px 7px 7px 7px;
+ float: right;
+ height: auto;
+ margin: 0 20px 10px 10px;
+ width: 200px;
+}
+
+div.toc li {
+ background: url("bdwn.png") no-repeat scroll 0 5px transparent;
+ font: 10px/1.2 Verdana,DejaVu Sans,Geneva,sans-serif;
+ margin-top: 5px;
+ padding-left: 10px;
+ padding-top: 2px;
+}
+
+div.toc h3 {
+ font: bold 12px/1.2 Arial,FreeSans,sans-serif;
+ color: #4665A2;
+ border-bottom: 0 none;
+ margin: 0;
+}
+
+div.toc ul {
+ list-style: none outside none;
+ border: medium none;
+ padding: 0px;
+}
+
+div.toc li.level1 {
+ margin-left: 0px;
+}
+
+div.toc li.level2 {
+ margin-left: 15px;
+}
+
+div.toc li.level3 {
+ margin-left: 30px;
+}
+
+div.toc li.level4 {
+ margin-left: 45px;
+}
+
+.inherit_header {
+ font-weight: bold;
+ color: gray;
+ cursor: pointer;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+.inherit_header td {
+ padding: 6px 0px 2px 5px;
+}
+
+.inherit {
+ display: none;
+}
+
+tr.heading h2 {
+ margin-top: 12px;
+ margin-bottom: 4px;
+}
+
+/* tooltip related style info */
+
+.ttc {
+ position: absolute;
+ display: none;
+}
+
+#powerTip {
+ cursor: default;
+ white-space: nowrap;
+ background-color: white;
+ border: 1px solid gray;
+ border-radius: 4px 4px 4px 4px;
+ box-shadow: 1px 1px 7px gray;
+ display: none;
+ font-size: smaller;
+ max-width: 80%;
+ opacity: 0.9;
+ padding: 1ex 1em 1em;
+ position: absolute;
+ z-index: 2147483647;
+}
+
+#powerTip div.ttdoc {
+ color: grey;
+ font-style: italic;
+}
+
+#powerTip div.ttname a {
+ font-weight: bold;
+}
+
+#powerTip div.ttname {
+ font-weight: bold;
+}
+
+#powerTip div.ttdeci {
+ color: #006318;
+}
+
+#powerTip div {
+ margin: 0px;
+ padding: 0px;
+ font: 12px/16px Roboto,sans-serif;
+}
+
+#powerTip:before, #powerTip:after {
+ content: "";
+ position: absolute;
+ margin: 0px;
+}
+
+#powerTip.n:after, #powerTip.n:before,
+#powerTip.s:after, #powerTip.s:before,
+#powerTip.w:after, #powerTip.w:before,
+#powerTip.e:after, #powerTip.e:before,
+#powerTip.ne:after, #powerTip.ne:before,
+#powerTip.se:after, #powerTip.se:before,
+#powerTip.nw:after, #powerTip.nw:before,
+#powerTip.sw:after, #powerTip.sw:before {
+ border: solid transparent;
+ content: " ";
+ height: 0;
+ width: 0;
+ position: absolute;
+}
+
+#powerTip.n:after, #powerTip.s:after,
+#powerTip.w:after, #powerTip.e:after,
+#powerTip.nw:after, #powerTip.ne:after,
+#powerTip.sw:after, #powerTip.se:after {
+ border-color: rgba(255, 255, 255, 0);
+}
+
+#powerTip.n:before, #powerTip.s:before,
+#powerTip.w:before, #powerTip.e:before,
+#powerTip.nw:before, #powerTip.ne:before,
+#powerTip.sw:before, #powerTip.se:before {
+ border-color: rgba(128, 128, 128, 0);
+}
+
+#powerTip.n:after, #powerTip.n:before,
+#powerTip.ne:after, #powerTip.ne:before,
+#powerTip.nw:after, #powerTip.nw:before {
+ top: 100%;
+}
+
+#powerTip.n:after, #powerTip.ne:after, #powerTip.nw:after {
+ border-top-color: #ffffff;
+ border-width: 10px;
+ margin: 0px -10px;
+}
+#powerTip.n:before {
+ border-top-color: #808080;
+ border-width: 11px;
+ margin: 0px -11px;
+}
+#powerTip.n:after, #powerTip.n:before {
+ left: 50%;
+}
+
+#powerTip.nw:after, #powerTip.nw:before {
+ right: 14px;
+}
+
+#powerTip.ne:after, #powerTip.ne:before {
+ left: 14px;
+}
+
+#powerTip.s:after, #powerTip.s:before,
+#powerTip.se:after, #powerTip.se:before,
+#powerTip.sw:after, #powerTip.sw:before {
+ bottom: 100%;
+}
+
+#powerTip.s:after, #powerTip.se:after, #powerTip.sw:after {
+ border-bottom-color: #ffffff;
+ border-width: 10px;
+ margin: 0px -10px;
+}
+
+#powerTip.s:before, #powerTip.se:before, #powerTip.sw:before {
+ border-bottom-color: #808080;
+ border-width: 11px;
+ margin: 0px -11px;
+}
+
+#powerTip.s:after, #powerTip.s:before {
+ left: 50%;
+}
+
+#powerTip.sw:after, #powerTip.sw:before {
+ right: 14px;
+}
+
+#powerTip.se:after, #powerTip.se:before {
+ left: 14px;
+}
+
+#powerTip.e:after, #powerTip.e:before {
+ left: 100%;
+}
+#powerTip.e:after {
+ border-left-color: #ffffff;
+ border-width: 10px;
+ top: 50%;
+ margin-top: -10px;
+}
+#powerTip.e:before {
+ border-left-color: #808080;
+ border-width: 11px;
+ top: 50%;
+ margin-top: -11px;
+}
+
+#powerTip.w:after, #powerTip.w:before {
+ right: 100%;
+}
+#powerTip.w:after {
+ border-right-color: #ffffff;
+ border-width: 10px;
+ top: 50%;
+ margin-top: -10px;
+}
+#powerTip.w:before {
+ border-right-color: #808080;
+ border-width: 11px;
+ top: 50%;
+ margin-top: -11px;
+}
+
+@media print
+{
+ #top { display: none; }
+ #side-nav { display: none; }
+ #nav-path { display: none; }
+ body { overflow:visible; }
+ h1, h2, h3, h4, h5, h6 { page-break-after: avoid; }
+ .summary { display: none; }
+ .memitem { page-break-inside: avoid; }
+ #doc-content
+ {
+ margin-left:0 !important;
+ height:auto !important;
+ width:auto !important;
+ overflow:inherit;
+ display:inline;
+ }
+}
+
diff --git a/tools/item_merge.lua b/tools/item_merge.lua
index 38708f452..2ef08eb7b 100644
--- a/tools/item_merge.lua
+++ b/tools/item_merge.lua
@@ -16,7 +16,7 @@
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--- Base Author: Dastgir @ http://hercules.ws
+-- Base Author: Dastgir @ http://herc.ws
--
-- This script requires lua 5.1 to run.
diff --git a/tools/itemdb_jobmask_converter.pl b/tools/itemdb_jobmask_converter.pl
new file mode 100644
index 000000000..11a5e7a5f
--- /dev/null
+++ b/tools/itemdb_jobmask_converter.pl
@@ -0,0 +1,100 @@
+#!/usr/bin/perl
+#
+# 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/>.
+
+# Base Author: Dastgir @ http://herc.ws
+
+# This script converts item_db.conf Jobmask field into groups format
+# usage example: perl tools/itemdb_jobmask_converter.pl < db/item_db2.conf > db/item_db_out.conf
+
+use strict;
+use warnings;
+
+sub parsedb (@) {
+ my @input = @_;
+ my @jobNames = (
+ "Novice",
+ "Swordsman",
+ "Magician",
+ "Archer",
+ "Acolyte",
+ "Merchant",
+ "Thief",
+ "Knight",
+ "Priest",
+ "Wizard",
+ "Blacksmith",
+ "Hunter",
+ "Assassin",
+ "Unused",
+ "Crusader",
+ "Monk",
+ "Sage",
+ "Rogue",
+ "Alchemist",
+ "Bard",
+ "Unused",
+ "Taekwon",
+ "Star_Gladiator",
+ "Soul_Linker",
+ "Gunslinger",
+ "Ninja",
+ "Gangsi",
+ "Death_Knight",
+ "Dark_Collector",
+ "Kagerou",
+ "Rebellion"
+ );
+ my $jobSize = $#jobNames + 1;
+
+ foreach (@input) {
+ chomp $_;
+ if ($_ =~ /^\s*Job\s*:\s*(?<Job>(?:0x)?[0-9A-Fa-f]+)/x) {
+ my %cols = map { $_ => $+{$_} } keys %+;
+ my $jobMask = hex($cols{Job});
+ my $allJobs = 0xFFFFFFFF;
+ my $allJobsExceptNovice = 0xFFFFFFFE;
+ if ($jobMask < 0 || $jobMask eq "") {
+ print "$_\n";
+ next;
+ }
+ print "\tJob: {\n";
+ if (($jobMask&$allJobs) == $allJobs) {
+ print "\t\tAll: true\n";
+ } elsif (($jobMask&$allJobsExceptNovice) == $allJobsExceptNovice) {
+ print "\t\tAll: true\n";
+ print "\t\tNovice: false\n";
+ } elsif ($jobMask == 0) {
+ print "\t\tAll: false\n";
+ } else {
+ for (my $i = 0; $i < $jobSize; $i++) {
+ my $currBit = 1<<$i;
+ if (($jobMask & $currBit) == $currBit) {
+ print "\t\t$jobNames[$i]: true\n" unless $jobNames[$i] eq "Unused";
+ }
+ }
+ }
+ print "\t}\n";
+ } else {
+ print "$_\n";
+ }
+ }
+}
+
+parsedb(<>);
diff --git a/tools/skilldbconverter.php b/tools/skilldbconverter.php
new file mode 100644
index 000000000..d926e4474
--- /dev/null
+++ b/tools/skilldbconverter.php
@@ -0,0 +1,1201 @@
+<?php
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+* _ _ _
+* | | | | | |
+* | |_| | ___ _ __ ___ _ _| | ___ ___
+* | _ |/ _ \ '__/ __| | | | |/ _ \/ __|
+* | | | | __/ | | (__| |_| | | __/\__ \
+* \_| |_/\___|_| \___|\__,_|_|\___||___/
+*
+* * * * * * * * * * * * * * License * * * * * * * * * * * * * * * * * * * * * *
+* This file is part of Hercules.
+* http://herc.ws - http://github.com/HerculesWS/Hercules
+*
+* Copyright (C) 2016- Smokexyz/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/>.
+* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+* Credits : Smokexyz */
+
+// Credits before anything else.
+printcredits();
+
+if(!isset($argv[1]))
+ gethelp();
+
+function issetarg($arg) {
+ global $argv;
+ for($i=1; $i<sizeof($argv); $i++) {
+ if(strncmp($argv[$i],$arg,strlen($arg)) == 0)
+ return $i;
+ }
+ return 0;
+}
+
+$renewal = (issetarg("-re") || issetarg("--renewal"));
+$prere = (issetarg("-pre-re") || issetarg("--pre-renewal"));
+$constants = (!issetarg("-itid") && !issetarg("--use-itemid"));
+$help = (issetarg("-h") || issetarg("--help"));
+$directory = function() use($argv) {
+ $arg = issetarg("--directory")?issetarg("--directory"):(issetarg("-dir")?issetarg("-dir"):0);
+ if ($arg) {
+ $part = explode("=", $argv[$arg]);
+ if(!isset($part[1])) {
+ die("A directory path was not provided!\n");
+ } else if(!is_dir($part[1])) {
+ die("The given directory ".$part[1]." doesn't exist.\n");
+ } else {
+ return $part[1];
+ }
+ }
+};
+
+$dir = $directory();
+
+if ($dir) {
+ print "Read/Write Directory has been set to '".$dir."'\n";
+ print "Please ensure all skill_db TXT files are placed in this path.\n";
+ print "Please also provide the correct version of the database (re/pre-re).\n";
+ define('DIRPATH', $dir);
+}
+
+$debug = (issetarg("-dbg") || issetarg("--with-debug"));
+
+if ($debug) {
+ print "\033[0mDebug Mode Enabled.\n";
+ $t_init = microtime_float();
+}
+
+if($help || (!$renewal && !$prere) || ($renewal && $prere)) {
+ gethelp();
+}
+
+if ($renewal) {
+ print "Renewal enabled.\n";
+ print "skill_db.txt and associated files (cast, nocastdex, require & unit) will be converted.\n";
+ if(!defined('DIRPATH'))
+ define('DIRPATH', '../db/re/');
+ define('RENEWAL', true);
+} else if ($prere) {
+ print "Pre-Renewal enabled.\n";
+ print "skill_db.txt and associated files (cast, nocastdex, require & unit) will be converted.\n";
+ if(!defined('DIRPATH'))
+ define('DIRPATH', '../db/pre-re/');
+}
+
+// check for existence of files.
+
+$file_check = [
+ DIRPATH."skill_require_db.txt",
+ DIRPATH."skill_cast_db.txt",
+ DIRPATH."skill_castnodex_db.txt",
+ DIRPATH."skill_unit_db.txt",
+ DIRPATH."skill_db.txt"
+];
+
+if($constants) array_push($file_check, DIRPATH."item_db.conf");
+
+foreach($file_check as $file) {
+ if(file_exists($file))
+ print $file." - Found\n";
+ else
+ die($file." - Not Found!\n");
+}
+
+if ($constants) {
+ print "Using of Item Constants : enabled\n";
+} else {
+ print "Using of Item Constants : disabled.\n";
+}
+
+/* Begin the Loading of Files */
+
+$i=0;
+$file="skill_require_db.txt";
+$requiredb = fopen(DIRPATH.$file, "r") or die("Unable to open '".DIRPATH.$file."'.\n");
+print "Reading '".DIRPATH.$file."' ...\n";
+while(!feof($requiredb))
+{
+ $line = fgets($requiredb);
+ if(substr($line, 0, 2) == "//" || strlen($line) < 10) continue;
+ $line = strstr(preg_replace('/\s+/','',$line), "//", true);
+ $arr = explode(",", $line);
+ if(!isset($arr[0])) continue;
+ $skreq['ID'][$i] = $arr[0];
+ $skreq['HPCost'][$i] = $arr[1];
+ $skreq['MaxHPTrigger'][$i] = $arr[2];
+ $skreq['SPCost'][$i] = $arr[3];
+ $skreq['HPRateCost'][$i] = $arr[4];
+ $skreq['SPRateCost'][$i] = $arr[5];
+ $skreq['ZenyCost'][$i] = $arr[6];
+ $skreq['Weapons'][$i] = $arr[7];
+ $skreq['AmmoTypes'][$i] = $arr[8];
+ $skreq['AmmoAmount'][$i] = $arr[9];
+ $skreq['State'][$i] = $arr[10];
+ $skreq['SpiritSphere'][$i] = $arr[11];
+ $k=0;
+ for($j=12; $j<=31; $j+=2) {
+ $skreqit['ItemId'][$i][$k] = isset($arr[$j])?$arr[$j]:0;
+ $skreqit['Amount'][$i][$k] = isset($arr[$j+1])?$arr[$j+1]:0;
+ $k++;
+ }
+ $i++;
+}
+if ($debug) {
+ print "[Debug] Read require_db Memory: ".print_mem()."\n";
+}
+fclose($requiredb);
+
+$file="skill_cast_db.txt";
+$skillcastdb = fopen(DIRPATH.$file, "r") or die("Unable to open '".DIRPATH.$file."'.\n");
+print "Reading '".DIRPATH.$file."' ...\n";
+$i=0;
+while(!feof($skillcastdb))
+{
+ $line = fgets($skillcastdb);
+ if (substr($line, 0, 2) == "//" || strlen($line) < 10) continue;
+ $arr = explode(",",$line);
+ if (!isset($arr[0])) continue;
+ $skcast["ID"][$i] = $arr[0]; // SkillCastDBId
+ $skcast["casttime"][$i] = $arr[1];
+ $skcast["actdelay"][$i] = $arr[2];
+ $skcast["walkdelay"][$i] = $arr[3];
+ $skcast["data1"][$i] = $arr[4];
+ $skcast["data2"][$i] = $arr[5];
+ $skcast["cooldown"][$i] = $arr[6];
+ if(defined('RENEWAL')) $skcast["fixedcast"][$i] = $arr[7];
+
+ $i++;
+}
+if($debug) {
+ print "[Debug] Read cast_db Memory: ".print_mem()."\n";
+}
+fclose($skillcastdb);
+
+$file="skill_castnodex_db.txt";
+$castnodex = fopen(DIRPATH.$file, "r") or die("Unable to open '".DIRPATH.$file."'.\n");
+print "Reading '".DIRPATH.$file."' ...\n";
+$i=0;
+while(!feof($castnodex))
+{
+ $line = fgets($castnodex);
+ if(substr($line, 0, 2) == "//" || strlen($line) <= 2) continue;
+ $line = strstr(preg_replace('/\s+/','',$line), "//", true);
+ $arr = explode(",",$line);
+ $sknodex["ID"][$i] = $arr[0];
+ $sknodex["cast"][$i] = isset($arr[1])?$arr[1]:0;
+ $sknodex["delay"][$i] = isset($arr[2])?$arr[2]:0;
+ $i++;
+}
+if($debug) {
+ print "[Debug] Read cast_nodex Memory: ".print_mem()."\n";
+}
+fclose($castnodex);
+
+/***
+* Read item_db.conf to gather aegis item name informations.
+*/
+if ($constants) {
+ $itemdb[] = array();
+
+ $file = "item_db.conf";
+ if(file_exists(DIRPATH.$file)) {
+ $itemconf = fopen(DIRPATH.$file, "r") or die ("Unable to open '".DIRPATH.$file."'.\n");
+ print "Reading '".DIRPATH.$file."' ...\n";
+
+ $started = false;
+ $i=0;
+ while(!feof($itemconf)) {
+ $line = fgets($itemconf);
+ $line = trim($line);
+ if(strcmp($line,"{\n"))
+ $started = true;
+ else if (strcmp($line,"},\n"))
+ $started = false;
+ //echo str_replace(" ","",$line)."\n";
+
+ if($started == true) {
+ $p = explode(":", $line);
+ if(isset($p[0])) {
+ if($p[0] == "Id") {
+ //echo $p[0]." ".(isset($p[1])?$p[1]:NULL)."\n";
+ $itemdb['ID'][$i] = intval($p[1]);
+ }
+ if($p[0] == "AegisName") {
+ //echo $p[0]." ".(isset($p[1])?str_replace("\"","",$p[1]):NULL)."\n";
+ $itemdb['name'][$i] = str_replace("\"","",$p[1]);
+ $i++;
+ }
+ }
+ }
+ }
+ if($debug) {
+ print "[Debug] Read item_db Memory: ".print_mem()."\n";
+ }
+ fclose($itemconf);
+ } else {
+ print "Unable to open '".DIRPATH.$file."'... defaulting to using Item ID's instead of Constants.\n";
+ $constants = false;
+ }
+}
+
+/* * *
+* Bring forth the contents of skill_unit_db.txt and store them.
+*/
+$i=0;
+$file="skill_unit_db.txt";
+$unitdb = fopen(DIRPATH.$file, "r") or die("Unable to open '".DIRPATH.$file."'.\n");
+print "Reading '".DIRPATH.$file."' ...\n";
+while(!feof($unitdb)) {
+ $line = fgets($unitdb);
+ if(substr($line, 0, 2) == "//" || strlen($line) < 10) continue;
+ $line = strstr(preg_replace('/\s+/','',$line), "//", true);
+ $arr = explode(",",$line);
+ $skunit['ID'][$i] = $arr[0];
+ $skunit['UnitID'][$i] = $arr[1];
+ $skunit['UnitID2'][$i] = $arr[2];
+ $skunit['Layout'][$i] = $arr[3];
+ $skunit['Range'][$i] = $arr[4];
+ $skunit['Interval'][$i] = $arr[5];
+ $skunit['Target'][$i] = $arr[6];
+ $skunit['Flag'][$i] = hexdec($arr[7]);
+ $i++;
+}
+if($debug) {
+ print "[Debug] Read unit_db Memory: ".print_mem()."\n";
+}
+fclose($unitdb);
+
+$putsk = ""; // initialize variable for file_put_contents.
+// Publish all comments
+$putsk .= getcomments((defined('RENEWAL')?true:false));
+
+$putsk .= "skill_db: (\n";
+// Get Main Skilldb File
+$file="skill_db.txt";
+$skmain = fopen(DIRPATH.$file, "r") or die("Unable to open '".DIRPATH.$file."'.\n");
+print "Reading '".DIRPATH.$file."' ...\n";
+$linecount = 0;
+
+// Get Number of entries
+while(!feof($skmain)) {
+ $line = fgets($skmain);
+ if(substr($line, 0, 2) == "//" || strlen($line) < 10) continue;
+ $linecount++;
+}
+if($debug) {
+ print "[Debug] Read skill_db Memory: ".print_mem()."\n";
+}
+fclose($skmain);
+print $linecount." entries found in skill_db.txt.\n";
+
+$i=0;
+$skmain = fopen(DIRPATH.$file, "r") or die("Unable to open '".DIRPATH.$file."'.\n");
+// Begin converting process.
+$max_level = 10;
+$max_items = 10;
+while(!feof($skmain)) {
+ $line = fgets($skmain);
+ if(substr($line, 0, 2) == "//" || strlen($line) < 10) continue;
+ $arr = explode(",", $line);
+ // id,range,hit,inf,element,nk,splash,max,list_num,castcancel,cast_defence_rate,inf2,maxcount,skill_type,blow_count,name,description
+ $id = $arr[0];
+ $range = $arr[1];
+ $hit = $arr[2];
+ $inf = $arr[3];
+ $element = $arr[4];
+ $nk = $arr[5];
+ $splash = $arr[6];
+ $max = $arr[7];
+ $max = ($max < 1) ? 1 : $max;
+ $list_num = $arr[8];
+ $castcancel = $arr[9];
+ $cast_defence_rate = $arr[10];
+ $inf2 = $arr[11];
+ $maxcount = $arr[12];
+ $skill_type = $arr[13];
+ $blow_count = $arr[14];
+ $name = $arr[15];
+ if(strlen(substr($arr[16], 0, strpos($arr[16], "//"))))
+ $description = substr($arr[16], 0, strpos($arr[16], "//"));
+ else
+ $description = $arr[16];
+
+ $putsk .= "{\n".
+ "\tId: ".$id."\n".
+ "\tName: \"".trim($name)."\"\n".
+ "\tDescription: \"".trim($description)."\"\n".
+ "\tMaxLevel: ".$max."\n";
+ if($range) $putsk .= "\tRange: ".leveled_guessfill($range, $max_level, $id)."\n";
+ if($hit==8) $putsk .= "\tHit: \"BDT_MULTIHIT\"\n";
+ else if($hit==6) $putsk .= "\tHit: \"BDT_SKILL\"\n";
+ if($inf) $putsk .= "\tSkillType: ".getinf($inf)."\n";
+ if($inf2) $putsk .= "\tSkillInfo: ".getinf2($inf2)."\n";
+ if($skill_type != "none") $putsk .= "\tAttackType: \"".ucfirst($skill_type)."\"\n";
+ if($element) $putsk .= "\tElement: ".leveled_ele($element, $max_level, $id)."\n";
+ if($nk && $nk != "0x0") $putsk .= "\tDamageType: ".getnk($nk)."\n";
+ if($splash) $putsk .= "\tSplashRange: ".leveled_guessfill($splash, $max_level, $id)."\n";
+ if($list_num != "1") $putsk .= "\tNumberOfHits: ".leveled_guessfill($list_num, $max_level, $id)."\n";
+ if($castcancel == "yes") $putsk .= "\tInterruptCast: true\n";
+ if($cast_defence_rate) $putsk .= "\tCastDefRate: ".$cast_defence_rate."\n";
+ if($maxcount) $putsk .= "\tSkillInstances: ".leveled_guessfill($maxcount, $max_level, $id)."\n";
+ if($blow_count) $putsk .= "\tKnockBackTiles: ".leveled_guessfill($blow_count, $max_level, $id)."\n";
+ // Cast Db
+ $key = array_search($id, $skcast['ID']);
+ if($key !== FALSE) {
+ if($skcast['casttime'][$key]) $putsk .= "\tCastTime: ".leveled_guessfill($skcast['casttime'][$key], $max_level, $id)."\n";
+ if($skcast['actdelay'][$key]) $putsk .= "\tAfterCastActDelay: ".leveled_guessfill($skcast['actdelay'][$key], $max_level, $id)."\n";
+ if($skcast['walkdelay'][$key] !== '0') $putsk .= "\tAfterCastWalkDelay: ".leveled_guessfill($skcast['walkdelay'][$key], $max_level, $id)."\n";
+ if($skcast['data1'][$key] !== '0') $putsk .= "\tSkillData1: ".leveled_guessfill($skcast['data1'][$key], $max_level, $id)."\n";
+ if($skcast['data2'][$key] !== '0') $putsk .= "\tSkillData2: ".leveled_guessfill($skcast['data2'][$key], $max_level, $id)."\n";
+ if($skcast['cooldown'][$key] !== '0') $putsk .= "\tCoolDown: ".leveled_guessfill($skcast['cooldown'][$key], $max_level, $id)."\n";
+ if(defined('RENEWAL') && strlen($skcast['fixedcast'][$key]) > 1 && $skcast['fixedcast'][$key] !== '0')
+ $putsk .= "\tFixedCastTime: ".leveled_guessfill($skcast['fixedcast'][$key], $max_level, $id)."\n";
+ }
+ // Cast NoDex
+ unset($key);
+ $key = array_search($id, $sknodex['ID']);
+ if($key !== FALSE) {
+ if (isset($sknodex["cast"][$key]) && $sknodex["cast"][$key] != 0) $putsk .= "\tCastTimeOptions: ".getnocast($sknodex["cast"][$key], $id)."\n";
+ if (isset($sknodex["delay"][$key]) && $sknodex["delay"][$key] != 0) $putsk .= "\tSkillDelayOptions: ".getnocast($sknodex["delay"][$key], $id)."\n";
+ unset($sknodex["ID"][$key]);
+ unset($sknodex["cast"][$key]);
+ unset($sknodex["delay"][$key]);
+ }
+
+ // require DB
+ unset($key);
+ $key = array_search($id, $skreq['ID']);
+ if($key !== FALSE) {
+ $putsk .= "\tRequirements: {\n";
+ if ($skreq['HPCost'][$key]) $putsk .= "\t\tHPCost: ".leveled_guessfill($skreq['HPCost'][$key], $max_level, $id, 1)."\n";
+ if ($skreq['SPCost'][$key]) $putsk .= "\t\tSPCost: ".leveled_guessfill($skreq['SPCost'][$key], $max_level, $id, 1)."\n";
+ if ($skreq['HPRateCost'][$key]) $putsk .= "\t\tHPRateCost: ".leveled_guessfill($skreq['HPRateCost'][$key], $max_level, $id, 1)."\n";
+ if ($skreq['SPRateCost'][$key]) $putsk .= "\t\tSPRateCost: ".leveled_guessfill($skreq['SPRateCost'][$key], $max_level, $id, 1)."\n";
+ if ($skreq['ZenyCost'][$key]) $putsk .= "\t\tZenyCost: ".leveled_guessfill($skreq['ZenyCost'][$key], $max_level, $id, 1)."\n";
+ if ($skreq['Weapons'][$key] != 99) $putsk .= "\t\tWeaponTypes: ".getweapontypes($skreq['Weapons'][$key], $id)."\n";
+ if ($skreq['AmmoTypes'][$key] == 99) $putsk .= "\t\tAmmoTypes: \"All\"\n";
+ else if ($skreq['AmmoTypes'][$key]) $putsk .= "\t\tAmmoTypes: ".getammotypes($skreq['AmmoTypes'][$key], $id)."\n";
+ if ($skreq['AmmoAmount'][$key]) $putsk .= "\t\tAmmoAmount: ".leveled_guessfill($skreq['AmmoAmount'][$key], $max_level, $id, 1)."\n";
+ if ($skreq['State'][$key] != "none" && $skreq['State'][$key]) $putsk .= "\t\tState: \"".getstate($skreq['State'][$key],$id)."\"\n";
+ if ($skreq['SpiritSphere'][$key]) $putsk .= "\t\tSpiritSphereCost: ".leveled_guessfill($skreq['SpiritSphere'][$key], $max_level, $id, 1)."\n";
+ if ($skreqit['ItemId'][$key][0] > 0) {
+ $putsk .= "\t\tItems: {\n";
+ for ($index=0; $index<sizeof($skreqit['ItemId'][$key]); $index++) {
+ $itemID = $skreqit['ItemId'][$key][$index]; // Required Item
+ $itemamt = $skreqit['Amount'][$key][$index]; // Required Amount
+
+ if (strpos($itemID, ':') == true) {
+ $items = explode(":", $itemID);
+ $it = 0;
+ while (isset($items) && isset($items[$it])) {
+ if ($constants && $itemID) {
+ $itkey = array_search($items[$it], $itemdb['ID']);
+ if($itkey === FALSE)
+ $itemname = "ID".$items[$it];
+ else
+ $itemname = $itemdb['name'][$itkey];
+ $putsk .= "\t\t\t".trim($itemname).": ".leveled($itemamt, $max_level, $id, 2)."\n";
+ } else if (intval($itemID)) {
+ $putsk .= "\t\t\tID".$items[$it].": ".leveled($itemamt, $max_level, $id, 2)."\n";
+ }
+ $it++;
+ }
+ } else {
+ if ($constants && $itemID) {
+ $itkey = array_search($skreqit['ItemId'][$key][$index], $itemdb['ID']);
+ if($itkey === FALSE)
+ $itemname = "ID".$itemID;
+ else
+ $itemname = $itemdb['name'][$itkey];
+ $putsk .= "\t\t\t".trim($itemname).": ".leveled($itemamt, $max_items, $id, 2)."\n";
+ } else if ($itemID) {
+ $putsk .= "\t\t\tID".$itemID.": ".leveled($itemamt, $max_items, $id, 2)."\n";
+ }
+ }
+ }
+ $putsk .= "\t\t}\n";
+ }
+ $putsk .= "\t}\n";
+ }
+
+ unset($key);
+ $key = array_search($id, $skunit['ID']);
+ if($key !== FALSE) {
+ $putsk .= "\tUnit: {\n";
+ if(isset($skunit['UnitID'][$key])) {
+ if(isset($skunit['UnitID2'][$key]) && strlen($skunit['UnitID2'][$key])) {
+ $putsk .= "\t\tId: [ ".$skunit['UnitID'][$key].", ".$skunit['UnitID2'][$key]." ]\n";
+ } else $putsk .= "\t\tId: ".$skunit['UnitID'][$key]."\n";
+ }
+ if(isset($skunit['Layout'][$key]) && $skunit['Layout'][$key] != 0) $putsk .= "\t\tLayout: ".leveled_guessfill($skunit['Layout'][$key], $max_level, $id, 1)."\n";
+ if(isset($skunit['Range'][$key]) && $skunit['Range'][$key] != 0) $putsk .= "\t\tRange: ".leveled_guessfill($skunit['Range'][$key], $max_level, $id, 1)."\n";
+# if(isset($skunit['Interval'][$key])) $putsk .= "\t\tInterval: ".leveled_guessfill($skunit['Interval'][$key], $max_level, $id, 1)."\n";
+# in memory present space only for one interval, but in old db intervals present for each level
+ if(isset($skunit['Interval'][$key])) $putsk .= "\t\tInterval: ".intval($skunit['Interval'][$key])."\n";
+ if(isset($skunit['Target'][$key]) && $skunit['Target'][$key] != "noone") $putsk .= "\t\tTarget: \"".trim(ucfirst($skunit['Target'][$key]))."\"\n";
+ if(isset($skunit['Flag'][$key]) && $skunit['Flag'][$key] != "") {
+ $putsk .= "\t\tFlag: ".getunitflag($skunit['Flag'][$key], $id)."\n";
+ }
+ $putsk .= "\t}\n";
+ }
+ // close skill
+ $putsk .= "},\n";
+ // Display progress bar
+ show_status($i++, $linecount);
+}
+show_status($linecount, $linecount);
+/**
+ * Print final messages and exit the script, conversion has completed.
+ */
+print "\n";
+print "The skill database has been successfully converted to Hercules' libconfig\n";
+print "format and has been saved as '".DIRPATH."skill_db.conf'.\n";
+print "The following files are now deprecated and can be deleted -\n";
+print DIRPATH."skill_db.txt\n";
+print DIRPATH."skill_cast_db.txt\n";
+print DIRPATH."skill_castnodex_db.txt\n";
+print DIRPATH."skill_require_db.txt\n";
+print DIRPATH."skill_unit_db.txt\n";
+$putsk .= ")";
+$skconf = "skill_db.conf";
+file_put_contents(DIRPATH.$skconf, $putsk);
+if($debug) {
+ print "[Debug] Memory after converting: ".print_mem()."\n";
+ print "[Debug] Execution Time : ".(microtime_float()-$t_init)."s\n";
+}
+fclose($skmain);
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+/* Functions
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+function microtime_float()
+{
+ list($usec, $sec) = explode(" ", microtime());
+ return ((float)$usec + (float)$sec);
+}
+
+function show_status($done, $total) {
+ $perc = floor(($done / $total) * 100);
+ $perc = floor($perc/2);
+ $left = 50-$perc;
+ $finalperc = $perc * 2;
+ $write = sprintf("[%'={$perc}s>%-{$left}s] - $finalperc%% - $done/$total\r", "", "");
+ fwrite(STDERR, $write);
+}
+function get_element($ele,$id)
+{
+ switch($ele)
+ {
+ case -1: return "Ele_Weapon";
+ case -2: return "Ele_Endowed";
+ case -3: return "Ele_Random";
+ case 0: return "Ele_Neutral";
+ case 1: return "Ele_Water";
+ case 2: return "Ele_Earth";
+ case 3: return "Ele_Fire";
+ case 4: return "Ele_Wind";
+ case 5: return "Ele_Poison";
+ case 6: return "Ele_Holy";
+ case 7: return "Ele_Dark";
+ case 8: return "Ele_Ghost";
+ case 9: return "Ele_Undead";
+ default: print "\rWarningUnknown Element ".$ele." provided for skill Id ".$id."\n";
+ }
+
+ return NULL;
+}
+function leveled_ele($str, $max, $skill_id)
+{
+ if(strpos($str, ':') == true)
+ {
+ $lvs = explode(":", $str);
+ $retval = "{\n";
+ for($i = 0; $i < $max && isset($lvs[$i]); $i++) {
+ $retval .= "\t\tLv".($i+1).": \"".get_element($lvs[$i],$skill_id)."\"\n";
+ }
+ $retval .= "\t}";
+ } else {
+ $retval = "\"".get_element($str,$skill_id)."\"";
+ }
+
+ return $retval;
+}
+
+function leveled($str, $max, $id, $tab=0)
+{
+ switch($tab) {
+ case 1:
+ $ittab = "\t\t\t";
+ $endtab = "\t\t";
+ break;
+ case 2:
+ $ittab = "\t\t\t\t";
+ $endtab = "\t\t\t";
+ break;
+ default:
+ $ittab = "\t\t";
+ $endtab = "\t";
+ break;
+ }
+
+ $retval = "";
+ if(strpos($str, ':') == true) {
+ $lvs = explode(":", trim($str));
+ $retval = "{\n";
+ for ($i = 0; $i < $max && isset($lvs[$i]); $i++) {
+ $retval .= $ittab."Lv".($i+1).": ".$lvs[$i]."\n";
+ }
+ $retval .= $endtab."}";
+ } else {
+ $retval = intval($str);
+ }
+
+ return $retval;
+}
+
+function leveled_guessfill($str, $max, $id, $tab=0)
+{
+ switch($tab) {
+ case 1:
+ $ittab = "\t\t\t";
+ $endtab = "\t\t";
+ break;
+ case 2:
+ $ittab = "\t\t\t\t";
+ $endtab = "\t\t\t";
+ break;
+ default:
+ $ittab = "\t\t";
+ $endtab = "\t";
+ break;
+ }
+
+ $retval = "";
+ if(strpos($str, ':') == true) {
+ $lvs = explode(":", trim($str));
+ $retval = "{\n";
+ for ($i = 0; $i < $max && isset($lvs[$i]); $i++) {
+ $retval .= $ittab."Lv".($i+1).": ".$lvs[$i]."\n";
+ }
+ if ($i < $max) {
+ /* Algorithm borrowed from skill_split_atoi(), as used by the old parser */
+ for ($step = 1; $step <= $i/2; $step++) {
+ $diff = $lvs[$i - 1] - $lvs[$i - $step - 1];
+ for ($j = $i - 1; $j >= $step; $j--)
+ if ($lvs[$j] - $lvs[$j - $step] != $diff)
+ break;
+
+ if ($j >= $step) //No match, try next step.
+ continue;
+
+ for(; $i < $max; $i++) { //Apply linear increase
+ $lvs[$i] = $lvs[$i - $step] + $diff;
+ if ($lvs[$i] < 1 && $lvs[$i - 1] >= 0) {
+ //Check if we have switched from + to -, cap the decrease to 0 in said cases.
+ $lvs[$i] = 1;
+ $diff = 0;
+ $step = 1;
+ }
+ $retval .= $ittab."Lv".($i+1).": ".$lvs[$i]."\n";
+ }
+ $retval .= $endtab."}";
+ return $retval;
+ }
+ //Okay.. we can't figure this one out, just fill out the stuff with the previous value.
+ for (; $i < $max; $i++) {
+ $lvs[$i] = $lvs[$i - 1];
+ $retval .= $ittab."Lv".($i+1).": ".$lvs[$i]."\n";
+ }
+ }
+ $retval .= $endtab."}";
+ } else {
+ $retval = intval($str);
+ }
+
+ return $retval;
+}
+
+function getstate($state,$id)
+{
+ if( strcmp($state,"hiding") == 0 ) return "Hiding";
+ else if( strcmp($state,"cloaking") == 0 ) return "Cloaking";
+ else if( strcmp($state,"hidden") == 0 ) return "Hidden";
+ else if( strcmp($state,"riding") == 0 ) return "Riding";
+ else if( strcmp($state,"falcon") == 0 ) return "Falcon";
+ else if( strcmp($state,"cart") == 0 ) return "Cart";
+ else if( strcmp($state,"shield") == 0 ) return "Shield";
+ else if( strcmp($state,"sight") == 0 ) return "Sight";
+ else if( strcmp($state,"explosionspirits") == 0 ) return "ExplosionSpirits";
+ else if( strcmp($state,"cartboost") == 0 ) return "CartBoost";
+ else if( strcmp($state,"recover_weight_rate") == 0 ) return "NotOverWeight";
+ else if( strcmp($state,"move_enable") == 0 ) return "Moveable";
+ else if( strcmp($state,"water") == 0 ) return "InWater";
+ else if( strcmp($state,"dragon") == 0 ) return "Dragon";
+ else if( strcmp($state,"warg") == 0 ) return "Warg";
+ else if( strcmp($state,"ridingwarg") == 0 ) return "RidingWarg";
+ else if( strcmp($state,"mado") == 0 ) return "MadoGear";
+ else if( strcmp($state,"elementalspirit") == 0 ) return "ElementalSpirit";
+ else if( strcmp($state,"poisonweapon") == 0 ) return "PoisonWeapon";
+ else if( strcmp($state,"rollingcutter") == 0 ) return "RollingCutter";
+ else if( strcmp($state,"mh_fighting") == 0 ) return "MH_Fighting";
+ else if( strcmp($state,"mh_grappling") == 0 ) return "MH_Grappling";
+ else if( strcmp($state,"peco") == 0 ) return "Peco";
+ else print "\rWarning - Invalid State ".$state." provided for Skill ID ".$id.", please correct this manually.\n";
+}
+
+function getinf($inf)
+{
+ $bitmask = array(
+ "Passive" => 0,
+ "Enemy" => 1,
+ "Place" => 2,
+ "Self" => 4,
+ "Friend" => 16,
+ "Trap" => 32,
+ );
+
+ $retval = "{\n";
+ foreach ($bitmask as $key => $val)
+ {
+ if($inf&$val)
+ $retval .= "\t\t".$key.": true\n";
+ }
+ $retval .= "\t}";
+
+ return $retval;
+}
+
+function getinf2($inf2=0x0000)
+{
+ $bitmask = array(
+ "Quest" => intval(0x0001), // = quest skill
+ "NPC" => intval(0x0002), // = npc skill
+ "Wedding" => intval(0x0004), // = wedding skill
+ "Spirit" => intval(0x0008), // = spirit skill
+ "Guild" => intval(0x0010), // = guild skill
+ "Song" => intval(0x0020), // = song/dance
+ "Ensemble" => intval(0x0040), // = ensemble skill
+ "Trap" => intval(0x0080), // = trap
+ "TargetSelf" => intval(0x0100), // = skill that damages/targets yourself
+ "NoCastSelf" => intval(0x0200), // = cannot be casted on self (if inf = 4, auto-select target skill)
+ "PartyOnly" => intval(0x0400), // = usable only on party-members (and enemies if skill is offensive)
+ "GuildOnly" => intval(0x0800), // = usable only on guild-mates (and enemies if skill is offensive)
+ "NoEnemy" => intval(0x1000), // = disable usage on enemies (for non-offensive skills).
+ "IgnoreLandProtector" => intval(0x2000), // = skill ignores land protector (e.g. arrow shower)
+ "Chorus" => intval(0x4000) // = chorus skill
+ );
+
+ $inf2 = intval(substr($inf2, 2),16);
+
+ $retval = "{\n";
+ foreach($bitmask as $key => $val) {
+ if($inf2&$val) {
+ $retval .= "\t\t".$key.": true\n";
+ }
+ }
+ $retval .= "\t}";
+
+ return $retval;
+}
+
+function getnk($nk)
+{
+ $bitmask = array(
+ "NoDamage" => intval(0x01), //- No damage skill
+ "SplashArea" => intval(0x02), //- Has splash area (requires source modification)
+ "SplitDamage" => intval(0x04), //- Damage should be split among targets (requires 0x02 in order to work)
+ "IgnoreCards" => intval(0x08), //- Skill ignores caster's % damage cards (misc type always ignores)
+ "IgnoreElement" => intval(0x10), //- Skill ignores elemental adjustments
+ "IgnoreDefense" => intval(0x20), //- Skill ignores target's defense (misc type always ignores)
+ "IgnoreFlee" => intval(0x40), //- Skill ignores target's flee (magic type always ignores)
+ "IgnoreDefCards" => intval(0x80) //- Skill ignores target's def cards
+ );
+ $nk = intval($nk,16);
+ $retval = "{\n";
+ foreach($bitmask as $key => $val) {
+ if($nk&$val) {
+ $retval .= "\t\t".$key.": true\n";
+ }
+ }
+ $retval .= "\t}";
+
+ return $retval;
+}
+
+function getnocast($opt, $id)
+{
+ $bitmask = array(
+ 'Default' => 0, //- everything affects the skill's cast time
+ 'IgnoreDex' => 1, //- skill's cast time is not affected by dex
+ 'IgnoreStatusEffect' => 2, //- skill's cast time is not affected by statuses (Suffragium, etc)
+ 'IgnoreItemBonus' => 4 //- skill's cast time is not affected by item bonuses (equip, cards)
+ );
+
+ if($opt > array_sum($bitmask) || $opt < 0)
+ print "\rWarning - a bitmask for CastNoDex entry for skill ID ".$id." is higher than total of masks or lower than 0.";
+
+ $retval = "{\n";
+ foreach($bitmask as $key => $val) {
+ if($opt&$val) {
+ $retval .= "\t\t".$key.": true\n";
+ }
+ }
+ $retval .= "\t}";
+
+ return $retval;
+}
+
+function getweapontypes($list, $id)
+{
+ $bitmask = array(
+ 0 => "NoWeapon",
+ 1 => "Daggers",
+ 2 => "1HSwords",
+ 3 => "2HSwords",
+ 4 => "1HSpears",
+ 5 => "2HSpears",
+ 6 => "1HAxes",
+ 7 => "2HAxes",
+ 8 => "Maces",
+ 9 => "2HMaces",
+ 10 => "Staves",
+ 11 => "Bows",
+ 12 => "Knuckles",
+ 13 => "Instruments",
+ 14 => "Whips",
+ 15 => "Books",
+ 16 => "Katars",
+ 17 => "Revolvers",
+ 18 => "Rifles",
+ 19 => "GatlingGuns",
+ 20 => "Shotguns",
+ 21 => "GrenadeLaunchers",
+ 22 => "FuumaShurikens",
+ 23 => "2HStaves",
+ 24 => "MaxSingleWeaponType",
+ 25 => "DWDaggers",
+ 26 => "DWSwords",
+ 27 => "DWAxes",
+ 28 => "DWDaggerSword",
+ 29 => "DWDaggerAxe",
+ 30 => "DWSwordAxe",
+ );
+ if(strpos($list, ':') == true) {
+ $type = explode(":", $list);
+ $wmask = 0;
+ for($i=0; $i<sizeof($type); $i++) {
+ $wmask |= 1<<$type[$i];
+ if($type[$i] > 30 || $type[$i] < 0)
+ print "\rWarning - Invalid weapon type ".$i." for skill ID ".$id."\n";
+ }
+ $retval = "{\n";
+ for($j=0; $j<sizeof($type); $j++) {
+ if($wmask&1<<$type[$j])
+ $retval .= "\t\t\t".$bitmask[$type[$j]].": true\n";
+ }
+ $retval .= "\t\t}";
+ } else {
+ $retval = "{\n";
+ $retval .= "\t\t\t".$bitmask[$list].": true\n";
+ $retval .= "\t\t}";
+ }
+
+ return $retval;
+}
+
+function getammotypes($list, $id) {
+ $bitmask = array(
+ 1 => "A_ARROW",
+ 2 => "A_DAGGER",
+ 3 => "A_BULLET",
+ 4 => "A_SHELL",
+ 5 => "A_GRENADE",
+ 6 => "A_SHURIKEN",
+ 7 => "A_KUNAI",
+ 8 => "A_CANNONBALL",
+ 9 => "A_THROWWEAPON"
+ );
+
+ if(strpos($list, ':') == true) {
+ $type = explode(":", $list);
+ $wmask = 0;
+ for($i=0; $i<sizeof($type); $i++) {
+ $wmask |= 1<<$type[$i];
+ if($type[$i] > 9 || $type[$i] < 1) {
+ print "\rWarning - Invalid weapon type ".$i." for skill ID ".$id."\n";
+ }
+ }
+ $retval = "{\n";
+ for($j=0; $j<sizeof($type); $j++) {
+ if($wmask&1<<$type[$j]) {
+ $retval .= "\t\t\t".$bitmask[$type[$j]].": true\n";
+ }
+ }
+ $retval .= "\t\t}";
+ } else {
+ $retval = "{\n";
+ $retval .= "\t\t\t".$bitmask[$list].": true\n";
+ $retval .= "\t\t}";
+ }
+
+ return $retval;
+}
+
+function getunitflag($flag, $id)
+{
+ $bitmask = array(
+ 'UF_DEFNOTENEMY' => intval(0x001), //0x001(UF_DEFNOTENEMY)If 'defunit_not_enemy' is set, the target is changed to 'friend'
+ 'UF_NOREITERATION' => intval(0x002), //0x002(UF_NOREITERATION)Spell cannot be stacked
+ 'UF_NOFOOTSET' => intval(0x004), //0x004(UF_NOFOOTSET)Spell cannot be cast near/on targets
+ 'UF_NOOVERLAP' => intval(0x008), //0x008(UF_NOOVERLAP)Spell effects do not overlap
+ 'UF_PATHCHECK' => intval(0x010), //0x010(UF_PATHCHECK)Only cells with a shootable path will be placed
+ 'UF_NOPC' => intval(0x020), //0x020(UF_NOPC)Spell cannot affect players.
+ 'UF_NOMOB' => intval(0x040), //0x040(UF_NOMOB)Spell cannot affect mobs.
+ 'UF_SKILL' => intval(0x080), //0x080(UF_SKILL)Spell CAN affect skills.
+ 'UF_DANCE' => intval(0x100), //0x100(UF_DANCE)Dance skill
+ 'UF_ENSEMBLE' => intval(0x200), //0x200(UF_ENSEMBLE)Ensemble skill
+ 'UF_SONG' => intval(0x400), //0x400(UF_SONG)Song skill
+ 'UF_DUALMODE' => intval(0x800), //0x800(UF_DUALMODE)Spell has effects both at an interval and when you step in/out
+ 'UF_RANGEDSINGLEUNIT' => intval(0x2000) //0x2000(UF_RANGEDSINGLEUNIT)Layout hack, use layout range propriety but only display center.
+ );
+
+ $count = 0;
+ if($flag <= 0) return 0;
+
+ $ret = "{\n";
+ foreach($bitmask as $key => $val) {
+ if($flag&$val) {
+ $ret .= "\t\t\t".$key.": true\n";
+ }
+ }
+
+ if($flag > array_sum($bitmask))
+ print "\rWarning - Invalid Unit Flag ".$flag." provided for skill Id ".$id."\n";
+
+ $ret .= "\t\t}";
+
+ return $ret;
+}
+
+function print_mem()
+{
+ return convert(memory_get_usage(true));
+}
+
+function convert($size)
+{
+ $unit=array('b','kb','mb','gb','tb','pb');
+ return @round($size/pow(1024,($i=floor(log($size,1024)))),2).' '.$unit[$i];
+}
+
+function gethelp()
+{
+ print "Usage: php skilldbconverter.php [option]\n";
+ print "Options:\n";
+ print "\t-re [--renewal] for renewal skill database conversion.\n";
+ print "\t-pre-re [--pre-renewal] for pre-renewal skill database conversion.\n";
+ print "\t-itid [--use-itemid] to use item IDs instead of constants.\n";
+ print "\t-dir [--directory] provide a custom directory.\n";
+ print "\t (Must include the correct -pre-re/-re option)\n";
+ print "\t-dbg [--with-debug] print debug information.\n";
+ print "\t-h [--help] to display this help text.\n\n";
+ print "----------------------- Additional Notes ----------------------\n";
+ print "Important!\n";
+ print "* Please be advised that either and only one of the arguments -re/-pre-re\n";
+ print " must be specified on execution.\n";
+ print "* When using the -dir option, -re/-pre-re options must be specified. \n";
+ print "* This tool isn't designed to convert renewal data to pre-renewal.\n";
+ print "* This tool should ideally be used from the 'tools/' folder, which can be found\n";
+ print " in the root of your Hercules installation. This tool will not delete any files\n";
+ print " from any of the directories that it reads from or prints to.\n\n";
+ print "* Prior to using this tool, please ensure at least 30MB of free RAM.\n";
+ print "----------------------- Usage Example -------------------------\n";
+ print "- Renewal Conversion: php skilldbconverter.php --renewal\n";
+ print "- Pre-renewal Conversion: php skilldbconverter.php --pre-renewal\n";
+ print "----------------------------------------------------------------\n";
+ exit;
+}
+
+function printcredits()
+{
+ print " _ _ _ \n";
+ print " | | | | | | \n";
+ print " | |_| | ___ _ __ ___ _ _| | ___ ___ \n";
+ print " | _ |/ _ \ '__/ __| | | | |/ _ \/ __|\n";
+ print " | | | | __/ | | (__| |_| | | __/\__ \ \n";
+ print " \_| |_/\___|_| \___|\__,_|_|\___||___/\n";
+ print "Hercules Skill Database TXT to Libconfig Converter by Smokexyz\n";
+ print "Copyright (C) 2016 Hercules\n";
+ print "-----------------------------------------------\n\n";
+}
+
+function getcomments($re)
+{
+ return "//================= Hercules Database ==========================================
+//= _ _ _
+//= | | | | | |
+//= | |_| | ___ _ __ ___ _ _| | ___ ___
+//= | _ |/ _ \ '__/ __| | | | |/ _ \/ __|
+//= | | | | __/ | | (__| |_| | | __/\__ \
+//= \_| |_/\___|_| \___|\__,_|_|\___||___/
+//================= 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/>.
+//==============================================================================
+//= ".($re?"Renewal":"Pre-Renewal")." Skill Database [Hercules]
+//==============================================================================
+//= @Format Notes:
+//= - All string entries are case-sensitive and must be quoted.
+//= - All setting names are case-sensitive and must be keyed accurately.
+
+
+/******************************************************************************
+********************************* Entry structure *****************************
+*******************************************************************************
+{
+ // ------------------------------ Mandatory Fields ----------------------------
+ Id: ID (int) (Required)
+ Name: \"Skill Name\" (string) (Required)
+ MaxLevel: Skill Level (int) (Required)
+ // ------------------------------ Optional Fields -----------------------------
+ Description: \"Skill Description\" (string) (optional but recommended)
+ Range: Skill Range (int) (optional, defaults to 0) (can be grouped by Levels)
+ Note: Range < 5 is considered Melee range.
+ Hit: Hit Type (int) (optional, default \"BDT_NORMAL\")
+ Types - \"BDT_SKILL\", \"BDT_MULTIHIT\" or \"BDT_NORMAL\"
+ SkillType: { (bool, defaults to \"Passive\")
+ Passive: true/false (boolean, defaults to false)
+ Enemy: true/false (boolean, defaults to false)
+ Place: true/false (boolean, defaults to false)
+ Self: true/false (boolean, defaults to false)
+ Friend: true/false (boolean, defaults to false)
+ Trap: true/false (boolean, defaults to false)
+ }
+ SkillInfo: { (bool, defaults to \"None\")
+ Quest: true/false (boolean, defaults to false)
+ NPC: true/false (boolean, defaults to false)
+ Wedding: true/false (boolean, defaults to false)
+ Spirit: true/false (boolean, defaults to false)
+ Guild: true/false (boolean, defaults to false)
+ Song: true/false (boolean, defaults to false)
+ Ensemble: true/false (boolean, defaults to false)
+ Trap: true/false (boolean, defaults to false)
+ TargetSelf: true/false (boolean, defaults to false)
+ NoCastSelf: true/false (boolean, defaults to false)
+ PartyOnly: true/false (boolean, defaults to false)
+ GuildOnly: true/false (boolean, defaults to false)
+ NoEnemy: true/false (boolean, defaults to false)
+ IgnoreLandProtector: true/false (boolean, defaults to false)
+ Chorus: true/false (boolean, defaults to false)
+ FreeCastReduced: true/false (boolean, defaults to false)
+ Works like skill SA_FREECAST, allow move and attack with reduced speed.
+ FreeCastNormal: true/false (boolean, defaults to false)
+ Works like FreeCastReduced, but not reduce speed.
+ }
+ AttackType: \"Attack Type\" (string, defaults to \"None\")
+ Types: \"None\", \"Weapon\", \"Magic\" or \"Misc\"
+ Element: \"Element Type\" (string) (Optional field - Default \"Ele_Neutral\")
+ (can be grouped by Levels)
+ Types: \"Ele_Neutral\", \"Ele_Water\", \"Ele_Earth\", \"Ele_Fire\", \"Ele_Wind\"
+ \"Ele_Poison\", \"Ele_Holy\", \"Ele_Dark\", \"Ele_Ghost\", \"Ele_Undead\"
+ \"Ele_Weapon\" - Uses weapon's element.
+ \"Ele_Endowed\" - Uses Endowed element.
+ \"Ele_Random\" - Uses random element.
+ DamageType: { (bool, default to \"NoDamage\")
+ NoDamage: true/false No damage skill
+ SplashArea: true/false Has splash area (requires source modification)
+ SplitDamage: true/false Damage should be split among targets (requires 'SplashArea' in order to work)
+ IgnoreCards: true/false Skill ignores caster's % damage cards (misc type always ignores)
+ IgnoreElement: true/false Skill ignores elemental adjustments
+ IgnoreDefense: true/false Skill ignores target's defense (misc type always ignores)
+ IgnoreFlee: true/false Skill ignores target's flee (magic type always ignores)
+ IgnoreDefCards: true/false Skill ignores target's def cards
+ }
+ SplashRange: Damage Splash Area (int, defaults to 0) (can be grouped by Levels)
+ Note: -1 for screen-wide.
+ NumberOfHits: Number of Hits (int, defaults to 1) (can be grouped by Levels)
+ Note: when positive, damage is increased by hits,
+ negative values just show number of hits without
+ increasing total damage.
+ InterruptCast: Cast Interruption (bool, defaults to false)
+ CastDefRate: Cast Defense Reduction (int, defaults to 0)
+ SkillInstances: Skill instances (int, defaults to 0) (can be grouped by Levels)
+ Notes: max amount of skill instances to place on the ground when
+ player_land_skill_limit/monster_land_skill_limit is enabled. For skills
+ that attack using a path, this is the path length to be used.
+ KnockBackTiles: Knock-back by 'n' Tiles (int, defaults to 0) (can be grouped by Levels)
+ CastTime: Skill cast Time (in ms) (int, defaults to 0) (can be grouped by Levels)
+ AfterCastActDelay: Skill Delay (in ms) (int, defaults to 0) (can be grouped by Levels)
+ AfterCastWalkDelay: Walk Delay (in ms) (int, defaults to 0) (can be grouped by Levels)
+ SkillData1: Skill Data/Duration (in ms) (int, defaults to 0) (can be grouped by Levels)
+ SkillData2: Skill Data/Duration (in ms) (int, defaults to 0) (can be grouped by Levels)
+ CoolDown: Skill Cooldown (in ms) (int, defaults to 0) (can be grouped by Levels)
+ ".($re?
+ "FixedCastTime: Fixed Cast Time (in ms) (int, defaults to 0) (can be grouped by Levels)
+ Note: when 0, uses 20% of cast time and less than
+ 0 means no fixed cast time.":"")."
+ CastTimeOptions: {
+ IgnoreDex: true/false (boolean, defaults to false)
+ IgnoreStatusEffect: true/false (boolean, defaults to false)
+ IgnoreItemBonus: true/false (boolean, defaults to false)
+ Note: Delay setting 'IgnoreDex' only makes sense when
+ delay_dependon_dex is enabled.
+ }
+ SkillDelayOptions: {
+ IgnoreDex: true/false (boolean, defaults to false)
+ IgnoreStatusEffect: true/false (boolean, defaults to false)
+ IgnoreItemBonus: true/false (boolean, defaults to false)
+ Note: Delay setting 'IgnoreDex' only makes sense when
+ delay_dependon_dex is enabled.
+ }
+ Requirements: {
+ HPCost: HP Cost (int, defaults to 0) (can be grouped by Levels)
+ SPCost: SP Cost (int, defaults to 0) (can be grouped by Levels)
+ HPRateCost: HP % Cost (int, defaults to 0) (can be grouped by Levels)
+ Note: If positive, it is a percent of your current hp,
+ otherwise it is a percent of your max hp.
+ SPRateCost: SP % Cost (int, defaults to 0) (can be grouped by Levels)
+ Note: If positive, it is a percent of your current sp,
+ otherwise it is a percent of your max sp.
+ ZenyCost: Zeny Cost (int, defaults to 0) (can be grouped by Levels)
+ WeaponTypes: { (bool or string, defaults to \"All\")
+ NoWeapon: true/false (boolean, defaults to false)
+ Daggers: true/false (boolean, defaults to false)
+ 1HSwords: true/false (boolean, defaults to false)
+ 2HSwords: true/false (boolean, defaults to false)
+ 1HSpears: true/false (boolean, defaults to false)
+ 2HSpears: true/false (boolean, defaults to false)
+ 1HAxes: true/false (boolean, defaults to false)
+ 2HAxes: true/false (boolean, defaults to false)
+ Maces: true/false (boolean, defaults to false)
+ 2HMaces: true/false (boolean, defaults to false)
+ Staves: true/false (boolean, defaults to false)
+ Bows: true/false (boolean, defaults to false)
+ Knuckles: true/false (boolean, defaults to false)
+ Instruments: true/false (boolean, defaults to false)
+ Whips: true/false (boolean, defaults to false)
+ Books: true/false (boolean, defaults to false)
+ Katars: true/false (boolean, defaults to false)
+ Revolvers: true/false (boolean, defaults to false)
+ Rifles: true/false (boolean, defaults to false)
+ GatlingGuns: true/false (boolean, defaults to false)
+ Shotguns: true/false (boolean, defaults to false)
+ GrenadeLaunchers: true/false (boolean, defaults to false)
+ FuumaShurikens: true/false (boolean, defaults to false)
+ 2HStaves: true/false (boolean, defaults to false)
+ MaxSingleWeaponType: true/false (boolean, defaults to false)
+ DWDaggers: true/false (boolean, defaults to false)
+ DWSwords: true/false (boolean, defaults to false)
+ DWAxes: true/false (boolean, defaults to false)
+ DWDaggerSword: true/false (boolean, defaults to false)
+ DWDaggerAxe: true/false (boolean, defaults to false)
+ DWSwordAxe: true/false (boolean, defaults to false)
+ }
+ AmmoTypes: { (for all types use string \"All\")
+ A_ARROW: true/false (boolean, defaults to false)
+ A_DAGGER: true/false (boolean, defaults to false)
+ A_BULLET: true/false (boolean, defaults to false)
+ A_SHELL: true/false (boolean, defaults to false)
+ A_GRENADE: true/false (boolean, defaults to false)
+ A_SHURIKEN: true/false (boolean, defaults to false)
+ A_KUNAI: true/false (boolean, defaults to false)
+ A_CANNONBALL: true/false (boolean, defaults to false)
+ A_THROWWEAPON: true/false (boolean, defaults to false)
+ }
+ AmmoAmount: Ammunition Amount (int, defaults to 0) (can be grouped by Levels)
+ State: \"Required State\" (string, defaults to \"None\") (can be grouped by Levels)
+ Types : 'None' = Nothing special
+ 'Moveable' = Requires to be able to move
+ 'NotOverWeight' = Requires to be less than 50% weight
+ 'InWater' = Requires to be standing on a water cell
+ 'Cart' = Requires a Pushcart
+ 'Riding' = Requires to ride either a peco or a dragon
+ 'Falcon' = Requires a Falcon
+ 'Sight' = Requires Sight skill activated
+ 'Hiding' = Requires Hiding skill activated
+ 'Cloaking' = Requires Cloaking skill activated
+ 'ExplosionSpirits' = Requires Fury skill activated
+ 'CartBoost' = Requires a Pushcart and Cart Boost skill activated
+ 'Shield' = Requires a 0,shield equipped
+ 'Warg' = Requires a Warg
+ 'Dragon' = Requires to ride a Dragon
+ 'RidingWarg' = Requires to ride a Warg
+ 'Mado' = Requires to have an active mado
+ 'PoisonWeapon' = Requires to be under Poisoning Weapon.
+ 'RollingCutter' = Requires at least one Rotation Counter from Rolling Cutter.
+ 'ElementalSpirit' = Requires to have an Elemental Spirit summoned.
+ 'MH_Fighting' = Requires Eleanor fighthing mode
+ 'MH_Grappling' = Requires Eleanor grappling mode
+ 'Peco' = Requires riding a peco
+ SpiritSphereCost: Spirit Sphere Cost (int, defaults to 0) (can be grouped by Levels)
+ Items: {
+ ItemID or Aegis_Name : Amount (int, defaults to 0) (can be grouped by Levels)
+ Item example: \"ID717\" or \"Blue_Gemstone\".
+ Notes: Items with amount 0 will not be consumed.
+ Amount can also be grouped by levels.
+ }
+ }
+ Unit: {
+ Id: [ UnitID, UnitID2 ] (int, defaults to 0) (can be grouped by Levels)
+ Layout: Unit Layout (int, defaults to 0) (can be grouped by Levels)
+ Range: Unit Range (int, defaults to 0) (can be grouped by Levels)
+ Interval: Unit Interval (int, defaults to 0) (can be grouped by Levels)
+ Target: \"Unit Target\" (string, defaults to \"None\")
+ Types:
+ All - affects everyone
+ NotEnemy - affects anyone who isn't an enemy
+ Friend - affects party, guildmates and neutral players
+ Party - affects party only
+ Guild - affects guild only
+ Ally - affects party and guildmates only
+ Sameguild - affects guild but not allies
+ Enemy - affects enemies only
+ None - affects nobody
+ Flag: {
+ UF_DEFNOTENEMY: true/false (boolean, defaults to false)
+ UF_NOREITERATION: true/false (boolean, defaults to false)
+ UF_NOFOOTSET: true/false (boolean, defaults to false)
+ UF_NOOVERLAP: true/false (boolean, defaults to false)
+ UF_PATHCHECK: true/false (boolean, defaults to false)
+ UF_NOPC: true/false (boolean, defaults to false)
+ UF_NOMOB: true/false (boolean, defaults to false)
+ UF_SKILL: true/false (boolean, defaults to false)
+ UF_DANCE: true/false (boolean, defaults to false)
+ UF_ENSEMBLE: true/false (boolean, defaults to false)
+ UF_SONG: true/false (boolean, defaults to false)
+ UF_DUALMODE: true/false (boolean, defaults to false)
+ UF_RANGEDSINGLEUNI: true/false (boolean, defaults to false)
+ }
+ }
+}
+* This file has been generated by Smokexyz's skilldbconverter.php tool.
+* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */\n\n";
+}