Sfoglia il codice sorgente

Kamael Core initial import. Sorry for the delay guys, enjoy.

DrLecter 17 anni fa
parent
commit
9d9b0a10ae
100 ha cambiato i file con 26281 aggiunte e 0 eliminazioni
  1. 18 0
      L2_GameServer_T1/.classpath
  2. 19 0
      L2_GameServer_T1/.project
  3. 321 0
      L2_GameServer_T1/.settings/org.eclipse.jdt.core.prefs
  4. 10 0
      L2_GameServer_T1/.settings/org.eclipse.jdt.ui.prefs
  5. 3 0
      L2_GameServer_T1/.settings/org.eclipse.ltk.core.refactoring.prefs
  6. 348 0
      L2_GameServer_T1/LICENSE.txt
  7. 295 0
      L2_GameServer_T1/README.txt
  8. 265 0
      L2_GameServer_T1/build.xml
  9. 1 0
      L2_GameServer_T1/data/announcements.txt
  10. 17 0
      L2_GameServer_T1/data/geodata/Readme.txt
  11. 17 0
      L2_GameServer_T1/data/pathnode/Readme.txt
  12. 14 0
      L2_GameServer_T1/dist/GameServer_loop.sh
  13. 12 0
      L2_GameServer_T1/dist/LoginServer_loop.sh
  14. 2 0
      L2_GameServer_T1/dist/RegisterGameServer.bat
  15. 2 0
      L2_GameServer_T1/dist/RegisterGameServer.sh
  16. 29 0
      L2_GameServer_T1/dist/startGameServer.bat
  17. 4 0
      L2_GameServer_T1/dist/startGameServer.sh
  18. 23 0
      L2_GameServer_T1/dist/startLoginServer.bat
  19. 6 0
      L2_GameServer_T1/dist/startLoginServer.sh
  20. 2 0
      L2_GameServer_T1/dist/startSQLAccountManager.bat
  21. 2 0
      L2_GameServer_T1/dist/startSQLAccountManager.sh
  22. 2 0
      L2_GameServer_T1/java/banned_ip.cfg
  23. 46 0
      L2_GameServer_T1/java/config/GMAccess.properties
  24. 310 0
      L2_GameServer_T1/java/config/altsettings.properties
  25. 178 0
      L2_GameServer_T1/java/config/clanhall.properties
  26. 432 0
      L2_GameServer_T1/java/config/command-privileges.properties
  27. 1 0
      L2_GameServer_T1/java/config/extensions.properties
  28. 19 0
      L2_GameServer_T1/java/config/idfactory.properties
  29. 133 0
      L2_GameServer_T1/java/config/l2jmods.properties
  30. 80 0
      L2_GameServer_T1/java/config/loginserver.properties
  31. 5 0
      L2_GameServer_T1/java/config/olympiad.properties
  32. 267 0
      L2_GameServer_T1/java/config/options.properties
  33. 169 0
      L2_GameServer_T1/java/config/other.properties
  34. 31 0
      L2_GameServer_T1/java/config/pvp.properties
  35. 53 0
      L2_GameServer_T1/java/config/rates.properties
  36. 71 0
      L2_GameServer_T1/java/config/server.properties
  37. 59 0
      L2_GameServer_T1/java/config/sevensigns.properties
  38. 131 0
      L2_GameServer_T1/java/config/siege.properties
  39. 15 0
      L2_GameServer_T1/java/config/telnet.properties
  40. 7 0
      L2_GameServer_T1/java/console.cfg
  41. 104 0
      L2_GameServer_T1/java/log.cfg
  42. 32 0
      L2_GameServer_T1/java/net/sf/l2j/AuditFilter.java
  43. 56 0
      L2_GameServer_T1/java/net/sf/l2j/AuditFormatter.java
  44. 33 0
      L2_GameServer_T1/java/net/sf/l2j/AuditLogHandler.java
  45. 1328 0
      L2_GameServer_T1/java/net/sf/l2j/Base64.java
  46. 30 0
      L2_GameServer_T1/java/net/sf/l2j/ChatFilter.java
  47. 60 0
      L2_GameServer_T1/java/net/sf/l2j/ChatLogFormatter.java
  48. 29 0
      L2_GameServer_T1/java/net/sf/l2j/ChatLogHandler.java
  49. 2488 0
      L2_GameServer_T1/java/net/sf/l2j/Config.java
  50. 66 0
      L2_GameServer_T1/java/net/sf/l2j/ConsoleLogFormatter.java
  51. 30 0
      L2_GameServer_T1/java/net/sf/l2j/ErrorFilter.java
  52. 29 0
      L2_GameServer_T1/java/net/sf/l2j/ErrorLogHandler.java
  53. 62 0
      L2_GameServer_T1/java/net/sf/l2j/FileLogFormatter.java
  54. 29 0
      L2_GameServer_T1/java/net/sf/l2j/GMAuditFilter.java
  55. 32 0
      L2_GameServer_T1/java/net/sf/l2j/GMAuditFormatter.java
  56. 30 0
      L2_GameServer_T1/java/net/sf/l2j/GMAuditLogHandler.java
  57. 56 0
      L2_GameServer_T1/java/net/sf/l2j/ItemFilter.java
  58. 69 0
      L2_GameServer_T1/java/net/sf/l2j/ItemLogFormatter.java
  59. 34 0
      L2_GameServer_T1/java/net/sf/l2j/ItemLogHandler.java
  60. 206 0
      L2_GameServer_T1/java/net/sf/l2j/L2DatabaseFactory.java
  61. 34 0
      L2_GameServer_T1/java/net/sf/l2j/Server.java
  62. 350 0
      L2_GameServer_T1/java/net/sf/l2j/accountmanager/SQLAccountManager.java
  63. 246 0
      L2_GameServer_T1/java/net/sf/l2j/gameserver/Announcements.java
  64. 72 0
      L2_GameServer_T1/java/net/sf/l2j/gameserver/CastleUpdater.java
  65. 93 0
      L2_GameServer_T1/java/net/sf/l2j/gameserver/Crypt.java
  66. 51 0
      L2_GameServer_T1/java/net/sf/l2j/gameserver/CustomPacketHandlerInterface.java
  67. 722 0
      L2_GameServer_T1/java/net/sf/l2j/gameserver/GameServer.java
  68. 263 0
      L2_GameServer_T1/java/net/sf/l2j/gameserver/GameTimeController.java
  69. 153 0
      L2_GameServer_T1/java/net/sf/l2j/gameserver/GeoData.java
  70. 1221 0
      L2_GameServer_T1/java/net/sf/l2j/gameserver/GeoEngine.java
  71. 165 0
      L2_GameServer_T1/java/net/sf/l2j/gameserver/GmListTable.java
  72. 47 0
      L2_GameServer_T1/java/net/sf/l2j/gameserver/Item.java
  73. 111 0
      L2_GameServer_T1/java/net/sf/l2j/gameserver/ItemsAutoDestroy.java
  74. 613 0
      L2_GameServer_T1/java/net/sf/l2j/gameserver/LoginServerThread.java
  75. 150 0
      L2_GameServer_T1/java/net/sf/l2j/gameserver/MonsterRace.java
  76. 1997 0
      L2_GameServer_T1/java/net/sf/l2j/gameserver/Olympiad.java
  77. 90 0
      L2_GameServer_T1/java/net/sf/l2j/gameserver/PacketHistory.java
  78. 923 0
      L2_GameServer_T1/java/net/sf/l2j/gameserver/RecipeController.java
  79. 1419 0
      L2_GameServer_T1/java/net/sf/l2j/gameserver/SevenSigns.java
  80. 2414 0
      L2_GameServer_T1/java/net/sf/l2j/gameserver/SevenSignsFestival.java
  81. 484 0
      L2_GameServer_T1/java/net/sf/l2j/gameserver/Shutdown.java
  82. 30 0
      L2_GameServer_T1/java/net/sf/l2j/gameserver/TaskPriority.java
  83. 87 0
      L2_GameServer_T1/java/net/sf/l2j/gameserver/Territory.java
  84. 430 0
      L2_GameServer_T1/java/net/sf/l2j/gameserver/ThreadPoolManager.java
  85. 250 0
      L2_GameServer_T1/java/net/sf/l2j/gameserver/TradeController.java
  86. 493 0
      L2_GameServer_T1/java/net/sf/l2j/gameserver/Universe.java
  87. 808 0
      L2_GameServer_T1/java/net/sf/l2j/gameserver/ai/AbstractAI.java
  88. 86 0
      L2_GameServer_T1/java/net/sf/l2j/gameserver/ai/Ctrl.java
  89. 81 0
      L2_GameServer_T1/java/net/sf/l2j/gameserver/ai/CtrlEvent.java
  90. 47 0
      L2_GameServer_T1/java/net/sf/l2j/gameserver/ai/CtrlIntention.java
  91. 877 0
      L2_GameServer_T1/java/net/sf/l2j/gameserver/ai/L2AttackableAI.java
  92. 1056 0
      L2_GameServer_T1/java/net/sf/l2j/gameserver/ai/L2CharacterAI.java
  93. 583 0
      L2_GameServer_T1/java/net/sf/l2j/gameserver/ai/L2ControllableMobAI.java
  94. 137 0
      L2_GameServer_T1/java/net/sf/l2j/gameserver/ai/L2DoorAI.java
  95. 212 0
      L2_GameServer_T1/java/net/sf/l2j/gameserver/ai/L2NpcWalkerAI.java
  96. 294 0
      L2_GameServer_T1/java/net/sf/l2j/gameserver/ai/L2PlayerAI.java
  97. 761 0
      L2_GameServer_T1/java/net/sf/l2j/gameserver/ai/L2SiegeGuardAI.java
  98. 121 0
      L2_GameServer_T1/java/net/sf/l2j/gameserver/ai/L2SummonAI.java
  99. 50 0
      L2_GameServer_T1/java/net/sf/l2j/gameserver/ai2/AiEvent.java
  100. 38 0
      L2_GameServer_T1/java/net/sf/l2j/gameserver/ai2/AiEventType.java

+ 18 - 0
L2_GameServer_T1/.classpath

@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry excluding="**/.svn/*|.svn" kind="src" path="java"/>
+	<classpathentry excluding="**/.svn/*|.svn" kind="src" path="javaTest"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry kind="lib" path="lib/javolution.jar"/>
+	<classpathentry kind="lib" path="lib/jython.jar"/>
+	<classpathentry kind="lib" path="lib/bsh-2.0b4.jar"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
+	<classpathentry kind="lib" path="lib/mmocore.jar"/>
+	<classpathentry kind="lib" path="lib/c3p0-0.9.1.2.jar"/>
+	<classpathentry kind="lib" path="lib/mysql-connector-java-5.1.5-bin.jar"/>
+	<classpathentry kind="lib" path="lib/jython-engine.jar"/>
+	<classpathentry kind="lib" path="lib/bsh-engine.jar"/>
+	<classpathentry kind="lib" path="lib/ecj.jar"/>
+	<classpathentry kind="lib" path="lib/java-engine.jar"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>

+ 19 - 0
L2_GameServer_T1/.project

@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>L2_GameServer_t1</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jem.workbench.JavaEMFNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.jem.beaninfo.BeanInfoNature</nature>
+	</natures>
+</projectDescription>

+ 321 - 0
L2_GameServer_T1/.settings/org.eclipse.jdt.core.prefs

@@ -0,0 +1,321 @@
+#Sun Dec 16 06:06:20 GMT-02:00 2007
+eclipse.preferences.version=1
+org.eclipse.jdt.core.builder.cleanOutputFolder=clean
+org.eclipse.jdt.core.builder.duplicateResourceTask=warning
+org.eclipse.jdt.core.builder.invalidClasspath=abort
+org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch
+org.eclipse.jdt.core.circularClasspath=error
+org.eclipse.jdt.core.classpath.exclusionPatterns=enabled
+org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled
+org.eclipse.jdt.core.codeComplete.argumentPrefixes=
+org.eclipse.jdt.core.codeComplete.argumentSuffixes=
+org.eclipse.jdt.core.codeComplete.fieldPrefixes=_
+org.eclipse.jdt.core.codeComplete.fieldSuffixes=
+org.eclipse.jdt.core.codeComplete.localPrefixes=
+org.eclipse.jdt.core.codeComplete.localSuffixes=
+org.eclipse.jdt.core.codeComplete.staticFieldPrefixes=_
+org.eclipse.jdt.core.codeComplete.staticFieldSuffixes=
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.maxProblemPerUnit=100
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.fieldHiding=warning
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=enabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=warning
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedImport=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.source=1.5
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=0
+org.eclipse.jdt.core.formatter.alignment_for_assignment=0
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=0
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=49
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=0
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=1
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.blank_lines_before_package=0
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=next_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=next_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=next_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=next_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=next_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=next_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=next_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=next_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=next_line
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines=false
+org.eclipse.jdt.core.formatter.comment.format_comments=true
+org.eclipse.jdt.core.formatter.comment.format_header=true
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
+org.eclipse.jdt.core.formatter.comment.line_length=80
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=2
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true
+org.eclipse.jdt.core.formatter.indentation.size=4
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=80
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
+org.eclipse.jdt.core.formatter.tabulation.char=space
+org.eclipse.jdt.core.formatter.tabulation.size=4
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.incompatibleJDKLevel=ignore
+org.eclipse.jdt.core.incompleteClasspath=error

File diff suppressed because it is too large
+ 10 - 0
L2_GameServer_T1/.settings/org.eclipse.jdt.ui.prefs


+ 3 - 0
L2_GameServer_T1/.settings/org.eclipse.ltk.core.refactoring.prefs

@@ -0,0 +1,3 @@
+#Wed Nov 08 15:05:05 CET 2006
+eclipse.preferences.version=1
+org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false

+ 348 - 0
L2_GameServer_T1/LICENSE.txt

@@ -0,0 +1,348 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
+
+
+
+    L2J Server, Copyright (C) 2006 
+    L2J Server comes with ABSOLUTELY NO WARRANTY.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions.

+ 295 - 0
L2_GameServer_T1/README.txt

@@ -0,0 +1,295 @@
+ 
+ NOTE: This short guide is for a L2J Server. http://l2jserver.com
+
+ If you received this file as a part of a packaged or bundled build:
+ 
+L2J only supports L2J software obtained directly from L2J sources.
+
+What this means is, if you obtained L2J from a source other than our SVN or nightly distribution,
+you need to get support from where you got the files.
+We are unable to provide any technical assistance for unsupported software packages. 
+The software may have virii, cause security problems, 
+or even send your personal information to remote servers without your express consent. 
+We cannot recommend the use of any of these packages on a server.
+
+WARNING: L2J Server is not a plug and play type of server. 
+To setup the server and to run it successfully you need to do a lot of reading.
+If reading and learning are not something you like to do,
+Stop now.
+
+====================
+L2J Server 
+====================
+$Date: 2006/12/06 19:14:22 $
+
+TOC:
+I.    OVERVIEW
+II.   LEGAL 
+III.  REQUIREMENTS
+IV.   FIRST STARTUP
+V.    ADMIN/GM's GUIDE
+VI.   PLAYER's GUIDE
+VII.  UPDATING
+VIII. TROUBLESHOOTING
+IX.   CONTACT
+X.    CONTRIBUTING
+XI.   BUG REPORTING
+XII.  CREDITS
+
+  
+
+====================
+I. OVERVIEW
+====================
+
+L2J is an Alternative Lineage 2 Game Server written in pure Java for
+best compatibility. L2J gives you the possibility to legally host a game
+server for this popular Korean MMO created by NCSoft. It is still
+unfinished and many features are missing, but L2J Dev team is working
+hard on implementing them. L2J Server is distributed under the terms
+of GNU/GPL in a hope that open source model is the best for
+developing quality software giving everyone a possibility to
+participate on development by submitting the code.
+
+
+====================
+II. LEGAL
+====================
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, 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, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+USA.
+
+Full GNU/GPL License is included in LICENSE.TXT file.
+
+Whereas L2J is distributed under the terms of GNU/GPL, we require you to:
+a) Preserve logon notice. This gives us, L2J Developers, appropriate
+credit for our hard work done during our free time without any
+revenues.
+ 
+b) Do not distribute any extended data files with the server files in
+the same archive. NO world content should be incorporated in L2J
+distribution.
+Server and Datapack may not be not be bundled or packaged.
+
+====================
+III. REQUIREMENTS
+====================
+
+OS: 
+Any OS having Java JDK 1.5 installed and properly configured!
+    We recommend using SUN JDK available at java.sun.com
+
+Hardware: 
+Decent CPU & RAM
+
+Software:
+Java JDK 1.5
+MySql
+Datapack
+
+We recommend:
+That you do not play and host the server from the same computer. 
+Have a good Internet connection - dial up just won't cut it.
+Many low cost hosting options are available.
+
+====================
+IV. FIRST STARTUP
+====================
+
+Before you can start up the server it is extremely important to read 
+and get to know the wiki sites.
+They contain all the info you need to setup and run a L2J Server.
+
+L2J Server wiki: Server Guides, How-to's, bugtracker:
+https://l2jserver.com/trac/wiki
+
+L2J-Datapack wiki: Datapack Guides, How-to's, bugtracker:
+http://www.l2jdp.com/trac/wiki
+
+L2J Community wiki: Guides, How-to's:
+http://l2j.jot.com
+
+This Server distribution does not contain any spawn/drop data or any world
+content. (Datapack)
+
+L2J Server has also a possibility to change xp/sp/drop rates relative
+to data in spawnlist/droplist files. To do that, just change the rates 
+you need in server.properties file found in config folder.
+
+You should also configure your IP address in server.properties. 
+
+Server uses ports 2106 (LoginServer) and 7777 (GameServer) by
+default. If your server runs behind NAT or firewall you will need to
+open and/or forward these ports. 
+
+
+====================
+V. ADMIN/GM's GUIDE
+====================
+
+To make someone an admin you need to edit, in the l2jdb database, the desired character in the 
+characters table, while server is SHUT DOWN! Change the field, accesslevel from 0 to 100 or more. 
+You may start server after that and the person will have admin privileges. 
+Note that you must create the account and character before editing. 
+
+Possible access levels:
+-100 = banned
+0 = normal account/character
+51 or more = exempt from maximum connections limit (accounts table only)
+100 or more = admin
+
+More info can be found in the community wiki.
+ 
+Admin commands implemented:
+(Please see https://l2jserver.com/trac/wiki/GmCommands for more complete list.)
+//admin = main GM interface
+//gmchat = will send a message to all online GMs
+//invul = makes your character untouchable
+
+====================
+VI. PLAYER's GUIDE
+====================
+
+CLIENT COMPATIBILITY
+Our server is dependant on the official release of the North American lineage2 live client.
+http://www.lineage2.com
+All help and support will only be for the official client. 
+Any clients obtained elsewhere, must obtain support from where it was obtained.
+
+====================
+VI. UPDATING
+====================
+It may arrive that you want to update your server to new version while
+keeping old accounts. There are few steps you HAVE TO do in order to
+keep the data accurate.
+
+- You should ALWAYS look at timelines before updating, sometimes a file
+  format may change, so you will need to edit data manually to fit with
+  new format.
+- You should ALWAYS Backup all MySql data.
+- You should ALWAYS Backup all Server and Datapack files.
+- back up all .properties files (don't forget to check if new server use same 
+  format for those files)
+- download & unzip new server code to the Server directory
+- download & unzip new datapack code to the Server directory
+- edit and run update in the tools folder
+- run newly installed server & enjoy ;)
+
+
+====================
+VIII. TROUBLESHOOTING
+====================
+
+PROBLEM
+- Client outputs bunch of messages about missing templates.
+SOLUTION
+- Check that the datapack has been properly installed.
+
+PROBLEM
+- Message similar to "java is not recognized as internal command",
+"java not found" or "unknown command: java" appears.
+SOLUTION
+- Install java, or, if java is already installed just add your java
+binary directory to system PATH setting. If you don't know how to do
+that, than DO NOT bother running your own server please.
+
+PROBLEM
+- I can log in but ping is 9999s and I can't get past Server Select.
+SOLUTION
+- Set up your IP's properly, forward/open good ports if accessing from
+outside. (or find server with admin that knows how to do it)
+
+PROBLEM
+- Skills/quests/whatever don't work.
+SOLUTION
+- Patience brings it's fruits :p
+
+PROBLEM
+- I found a bug.
+SOLUTION
+- Please refer to BUG REPORTING section of this readme.
+
+Further help available at the wiki sites and the forums.
+
+
+====================
+IX. CONTACT
+====================
+
+Web: http://l2jserver.com
+IRC: #l2j @ Freenode (irc.freenode.net)
+
+Please note that L2J Devs can't help players with connecting issues or
+anything related to playing on private servers. If you can't connect,
+you should contact your server GM's. We can solve only L2J server
+~software~ related issues. We don't have any backdoors or anything
+that would enable us GM accounts on every server using L2J, so there's
+no point in coming to our channel if you need items/adena/whatever
+ingame.
+
+
+====================
+X. CONTRIBUTING
+====================
+
+Anyone who wants to contribute to the project is encouraged to do so. Java
+programming skills are not always required as L2J needs much more than
+java code.
+
+If you created any source code that may be helpful please use the User Contributions
+section on our forums. If you contributed good stuff that will be
+accepted, you might be invited to join L2J Dev Team.
+
+People willing to hang on chat and respond to user questions are also
+ALWAYS welcome ;)
+
+
+====================
+XI. BUG REPORTING
+====================
+
+Bugs can be reported on our wiki site.
+http://l2jserver.com/trac/newticket
+Basic rules for reporting are:
+    Please report only one bug/issue per ticket!!
+    You must include the revision (changeset) number when reporting a bug!
+    "The latest" does not mean anything when 5 more updates have been done since you set up the server.
+If you are not sure if it should be reported here, make a post about it in the L2J forum.
+
+Players should ALWAYS consult bugs with their Admin/GM's and have them report it
+on our wiki site. Some bugs may be caused by bad datapack, server
+installation or modifications server owner has made. We can't help you
+in that case.
+
+Please use the datapacks bugtracker for reporting datapack bugs.
+Please do NOT report bugs related to unofficial add-ons to L2J. L2J
+bugtracker is NOT a place to fix that. Contact the person who made
+modification instead.
+
+
+====================
+XII. CREDITS
+====================
+
+Dev team: 
+http://forum.l2jserver.com/team.php
+
+Have fun playing L2J ;)
+Dev Team
+
+    L2J Server, Copyright (C) 2006 
+    L2J Server comes with ABSOLUTELY NO WARRANTY.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions.

+ 265 - 0
L2_GameServer_T1/build.xml

@@ -0,0 +1,265 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="L2_GameServer_t1" default="dist" basedir=".">
+    <description>
+        This script will build the L2J server.
+        
+        This program is free software; you can redistribute it and/or modify
+        it under the terms of the GNU General Public License as published by
+        the Free Software Foundation; either version 2, 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, write to the Free Software
+        Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+        02111-1307, USA.
+        
+        http://www.gnu.org/copyleft/gpl.html      
+        
+    </description>
+    
+    <property name="src" location="java"/>
+    <property name="lib" location="lib"/>
+    <property name="build" location="build"/>
+    <property name="build.classes" location="${build}/classes"/>
+    <property name="build.dist" location="${build}/dist"/>
+	<property name="build.dist.login" location="${build.dist}/login"/>
+	<property name="build.dist.game" location="${build.dist}/gameserver"/>
+    <property name="build.dist.libs" location="${build.dist}/libs"/>
+    
+    <path id="classpath">
+        <fileset dir="${lib}">
+            <include name="c3p0-0.9.1.2.jar"/>
+        	<include name="jython.jar"/>
+        	<include name="javolution.jar"/>
+        	<include name="mysql-connector-java-5.1.5-bin.jar"/>
+        	<include name="mmocore.jar"/>
+        </fileset>
+    </path>
+    
+    <target name="init"
+    	depends="clean"
+        description="Create the output directories.">
+
+        <mkdir dir="${build}"/>
+        <mkdir dir="${build.classes}"/>
+        <mkdir dir="${build.dist}" />
+    	<mkdir dir="${build.dist.login}" />
+		<mkdir dir="${build.dist.game}" />
+    </target>
+    
+    
+    <target name="compile"
+            depends="version"
+            description="Compile the source.">
+
+        <javac destdir="${build.classes}"
+               optimize="on"
+               debug="on"
+               source="1.5"
+               target="1.5"
+               nowarn="off">
+            <src path="${src}"/>
+            <classpath refid="classpath"/>   
+        </javac>
+    </target>
+    
+    
+    <target name="jar"
+            depends="compile"
+            description="Create the jar file">
+
+        <jar destfile="${build}/l2jserver.jar">
+            <fileset dir="${build.classes}"/>
+        </jar>
+        
+    	<copy todir="${build.dist.login}">
+            <fileset dir="${build}">
+                <include name="l2jserver.jar"/>
+			</fileset>
+        </copy>
+    	<copy todir="${build.dist.game}">
+            <fileset dir="${build}">
+                <include name="l2jserver.jar"/>
+			</fileset>
+        </copy>
+        
+	</target>
+    
+
+    <target name="compile.gcj"
+            depends="jar"
+            description="Build machine executable binary">  
+            
+        <exec dir="." executable="gcj" failifexecutionfails="false" os="linux:Linux:freebsd:FreeBSD" >
+            <arg line="-O3 ${build.dist}/l2jserver.jar  -o ${build.dist}/l2jserver --main=net.sf.l2j.Server"/>
+        </exec>
+    </target>
+ 
+ 
+    <target name="dist" depends="jar">
+    	
+    	<copy todir="${build.dist.login}">
+            <fileset dir="${src}">
+                <include name="log.cfg"/>
+                <include name="banned_ip.cfg"/>
+                <include name="console.cfg"/>
+			</fileset>
+        </copy>
+    	
+    	<copy todir="${build.dist.game}">
+            <fileset dir="${src}">
+                <include name="log.cfg"/>
+                <include name="console.cfg"/>
+			</fileset>
+        </copy>
+    	
+	   	<copy todir="${build.dist.libs}">
+			<fileset dir="${src}/../lib">
+				<include name="*.jar"/>
+			</fileset>
+		</copy>
+    	
+        <copy todir="${build.dist}">
+            <fileset dir="${basedir}">
+                <include name="changes.txt"/>
+                <include name="LICENSE.txt"/>
+                <include name="README.txt"/>
+            </fileset>
+        </copy>
+    	
+	   	<copy todir="${build.dist}">
+			<fileset dir="${src}/../lib">
+				<include name="*LICENSE*"/>
+			</fileset>
+		</copy>
+        
+        <copy todir="${build.dist.login}">
+            <fileset dir="dist">
+                <include name="startAccountManager.*"/>
+                <include name="startSQLAccountManager.*"/>
+                <include name="LoginServer_loop.sh"/>
+                <include name="startLoginServer.*"/>
+            	<include name="RegisterGameServer.*"/>
+            </fileset>
+        </copy>
+    	<copy todir="${build.dist.game}">
+            <fileset dir="dist">
+                <include name="GameServer_loop.sh"/>
+                <include name="startGameServer.*"/>
+            	<include name="hibernate.cfg.xml"/>
+            </fileset>
+        </copy>
+    	
+		<fixcrlf 	srcdir="${build.dist.game}"
+					eol="lf"
+					eof="remove"
+					includes="**/*.sh">
+		</fixcrlf>
+    	<fixcrlf 	srcdir="${build.dist.login}"
+					eol="lf"
+					eof="remove"
+					includes="**/*.sh">
+		</fixcrlf>
+		
+		<fixcrlf 	srcdir="${build.dist.game}"
+					eol="crlf"
+					eof="remove"
+					includes="**/*.bat">
+		</fixcrlf>
+    	<fixcrlf 	srcdir="${build.dist.login}"
+					eol="crlf"
+					eof="remove"
+					includes="**/*.bat">
+		</fixcrlf>
+
+        
+        <mkdir dir="${build.dist.game}/log" />
+    	<mkdir dir="${build.dist.login}/log" />
+
+        <mkdir dir="${build.dist.game}/config" />
+    	<mkdir dir="${build.dist.login}/config" />
+    	<copy todir="${build.dist.game}/config">
+			<fileset dir="java/config">
+				<include name="*.properties"/>
+				<exclude name="loginserver.properties" />
+			</fileset>
+        </copy>
+    	<copy todir="${build.dist.login}/config">
+			<fileset dir="java/config">
+				<include name="loginserver.properties"/>
+				<include name="telnet.properties"/>
+			</fileset>
+		</copy>
+
+        <mkdir dir="${build.dist.game}/data" />
+        <copy todir="${build.dist.game}/data">
+            <fileset dir="data">
+                <include name="*.csv"/>
+            	<include name="*.txt"/>
+			</fileset>
+        </copy>
+    	
+        <mkdir dir="${build.dist.game}/data/geodata" />
+        <copy todir="${build.dist.game}/data/geodata">
+            <fileset dir="data/geodata">
+                <include name="*.txt"/>
+                <include name="*.l2j"/>
+            </fileset>
+        </copy>
+    	
+    	<mkdir dir="${build.dist.game}/data/pathnode" />
+    	<copy todir="${build.dist.game}/data/pathnode">
+    	    <fileset dir="data/pathnode">
+    	        <include name="*.txt"/>
+    	        <include name="*.pn"/>
+    	    </fileset>
+    	</copy>
+
+        <zip destfile="${build}/l2j-server.zip"
+             basedir="${build.dist}" />
+    </target>   
+    
+	<target name="version" 
+		depends="init"
+		description="Create l2j-version.properties file">
+		
+    	<tstamp>
+    	  <format property="build.tstamp"
+    	              pattern="yyyyMMdd_HHmm"/>
+    	</tstamp>
+
+
+    	<exec dir="." executable="svnversion" outputproperty="l2j.revision"
+			  failifexecutionfails="false">
+    	  <arg line="-n ."/>
+    	</exec>
+    	
+    	<concat destfile="${build.dist.game}/config/l2j-version.properties">
+    	version=${l2j.revision}
+    	builddate=${build.tstamp} 
+      detailed info:
+</concat>
+      <concat destfile="${build.dist.game}/config/l2j-version.properties" append="true">
+        <filelist dir="${src}/../.svn/" files="entries"/>
+        <filterchain>
+          <prefixlines prefix="          "/>
+          <headfilter lines="8" skip="4"/>
+          <tokenfilter>
+             <ignoreblank/>
+          </tokenfilter>
+        </filterchain>
+</concat>
+</target>
+	
+    
+    <target name="clean"
+            description="Remove the output directories">
+
+        <delete dir="${build}"/>
+    </target>
+</project>

+ 1 - 0
L2_GameServer_T1/data/announcements.txt

@@ -0,0 +1 @@
+Server admin is too lame to change announcements.txt file ;)

+ 17 - 0
L2_GameServer_T1/data/geodata/Readme.txt

@@ -0,0 +1,17 @@
+##############################################
+#               L2j geodata                  #
+#                                            #
+#       All files are integral part          # 
+#          part of l2j server.               #
+#                                            #
+#                                            #
+#         To make geodata  working           #
+#          unpack all files into             #
+#        /gameserver/data/geodata            #
+#                 folder                     #
+#                                            #
+#       Current link to geodata files:       #
+#         http://geodata.devcod.com/         #
+#                                            #
+##############################################
+

+ 17 - 0
L2_GameServer_T1/data/pathnode/Readme.txt

@@ -0,0 +1,17 @@
+##############################################
+#               L2j pathnode                 #
+#                                            #
+#       All files are integral part          # 
+#          part of l2j server.               #
+#                                            #
+#                                            #
+#         To make pathnode working           #
+#          unpack all files into             #
+#        /gameserver/data/pathnode           #
+#                 folder                     #
+#                                            #
+#       Current link to pathnode files:      #
+#         http://geodata.devcod.com/         #
+#                                            #
+##############################################
+

+ 14 - 0
L2_GameServer_T1/dist/GameServer_loop.sh

@@ -0,0 +1,14 @@
+#!/bin/bash
+
+# exit codes of GameServer:
+#  0 normal shutdown
+#  2 reboot attempt
+
+while :; do
+	[ -f log/java0.log.0 ] && mv log/java0.log.0 "log/`date +%Y-%m-%d_%H-%M-%S`_java.log"
+	[ -f log/stdout.log ] && mv log/stdout.log "log/`date +%Y-%m-%d_%H-%M-%S`_stdout.log"
+	java -Xms512m -Xmx512m -cp ./../libs/*:l2jserver.jar net.sf.l2j.gameserver.GameServer > log/stdout.log 2>&1
+	[ $? -ne 2 ] && break
+#	/etc/init.d/mysql restart
+	sleep 10
+done

+ 12 - 0
L2_GameServer_T1/dist/LoginServer_loop.sh

@@ -0,0 +1,12 @@
+#!/bin/bash
+
+err=1
+until [ $err == 0 ]; 
+do
+	[ -f log/java0.log.0 ] && mv log/java0.log.0 "log/`date +%Y-%m-%d_%H-%M-%S`_java.log"
+	[ -f log/stdout.log ] && mv log/stdout.log "log/`date +%Y-%m-%d_%H-%M-%S`_stdout.log"
+	nice -n -2 java -Xms512m -Xmx512m -cp ./../libs/*:l2jserver.jar net.sf.l2j.loginserver.L2LoginServer > log/stdout.log 2>&1
+	err=$?
+#	/etc/init.d/mysql restart
+	sleep 10;
+done

+ 2 - 0
L2_GameServer_T1/dist/RegisterGameServer.bat

@@ -0,0 +1,2 @@
+@java -Djava.util.logging.config.file=console.cfg -cp ./../libs/*;l2jserver.jar net.sf.l2j.gsregistering.GameServerRegister
+@pause

+ 2 - 0
L2_GameServer_T1/dist/RegisterGameServer.sh

@@ -0,0 +1,2 @@
+#!/bin/sh
+java -Djava.util.logging.config.file=console.cfg -cp ./../libs/*:l2jserver.jar net.sf.l2j.gsregistering.GameServerRegister

+ 29 - 0
L2_GameServer_T1/dist/startGameServer.bat

@@ -0,0 +1,29 @@
+@echo off
+title Game Server Console
+:start
+echo Starting L2J Game Server.
+echo.
+REM -------------------------------------
+REM Default parameters for a basic server.
+java -Xmx512m -cp ./../libs/*;l2jserver.jar net.sf.l2j.gameserver.GameServer
+REM
+REM If you have a big server and lots of memory, you could experiment for example with
+REM java -server -Xmx1536m -Xms1024m -Xmn512m -XX:PermSize=256m -XX:SurvivorRatio=8 -Xnoclassgc -XX:+AggressiveOpts
+REM -------------------------------------
+if ERRORLEVEL 2 goto restart
+if ERRORLEVEL 1 goto error
+goto end
+:restart
+echo.
+echo Admin Restart ...
+echo.
+goto start
+:error
+echo.
+echo Server terminated abnormaly
+echo.
+:end
+echo.
+echo server terminated
+echo.
+pause

+ 4 - 0
L2_GameServer_T1/dist/startGameServer.sh

@@ -0,0 +1,4 @@
+#! /bin/sh
+
+./GameServer_loop.sh &
+

+ 23 - 0
L2_GameServer_T1/dist/startLoginServer.bat

@@ -0,0 +1,23 @@
+@echo off
+title Login Server Console
+:start
+echo Starting L2J Login Server.
+echo.
+java -Xmx128m  -cp ./../libs/*;l2jserver.jar net.sf.l2j.loginserver.L2LoginServer
+if ERRORLEVEL 2 goto restart
+if ERRORLEVEL 1 goto error
+goto end
+:restart
+echo.
+echo Admin Restart ...
+echo.
+goto start
+:error
+echo.
+echo Server terminated abnormaly
+echo.
+:end
+echo.
+echo server terminated
+echo.
+pause

+ 6 - 0
L2_GameServer_T1/dist/startLoginServer.sh

@@ -0,0 +1,6 @@
+#!/bin/bash
+
+./LoginServer_loop.sh &
+
+
+

+ 2 - 0
L2_GameServer_T1/dist/startSQLAccountManager.bat

@@ -0,0 +1,2 @@
+@java -Djava.util.logging.config.file=console.cfg -cp ./../libs/*;l2jserver.jar net.sf.l2j.accountmanager.SQLAccountManager
+@pause

+ 2 - 0
L2_GameServer_T1/dist/startSQLAccountManager.sh

@@ -0,0 +1,2 @@
+#!/bin/sh
+java -Djava.util.logging.config.file=console.cfg -cp ./../libs/*:l2jserver.jar net.sf.l2j.accountmanager.SQLAccountManager

+ 2 - 0
L2_GameServer_T1/java/banned_ip.cfg

@@ -0,0 +1,2 @@
+10.255.255.255
+10.254.254.254

+ 46 - 0
L2_GameServer_T1/java/config/GMAccess.properties

@@ -0,0 +1,46 @@
+# Configure GM AccessLevels
+GMAccessLevel = 100
+GMMinLevel = 100
+GMCanAltG = 100
+GMCanAnnounce = 100
+GMCanBan = 100
+GMCanBanChat = 100
+GMCanShop = 100
+GMCanDelete = 100
+GMCanKick = 100
+GMMenu = 100
+GMGodMode = 100
+GMCanEditChar = 100
+GMCanEditCharOther = 100
+GMCanViewChar = 100
+GMCanEditNPC = 100
+GMCanViewNPC = 100
+GMCanTeleport = 100
+GMCanTeleportOther = 100
+GMCanRestart = 100
+GMMonsterRace = 100
+GMRider = 100
+GMFastUnstuck = 100
+GMResurectFixed = 100
+GMEnchant = 100
+GMDoor = 100
+GMRes = 100
+GMPeaceAttack = 100
+GMHeal = 100
+GMUnblock = 100
+GMCache = 100
+GMTalkBlock = 100
+GMTest = 100
+
+#Disable Transaction
+# False = Transaction enable for GM
+# Max,Min = Transaction disable for this range
+GMDisableTransaction = False
+
+# Minimum level to deal damage
+#  (GM with level below won't deal damage)
+GMCanGiveDamage = 90
+# GM with level below or equal don't take aggro)
+GMDontTakeAggro = 90
+# GM with level below or equal don't take Exp/Sp)
+GMDontGiveExpSp = 90

+ 310 - 0
L2_GameServer_T1/java/config/altsettings.properties

@@ -0,0 +1,310 @@
+#=============================================================
+#                WARNING                WARNING
+#=============================================================
+# Those settings can modify the behaviour of your server.
+# Your server will NOT be as retail servers.
+# 
+# Those settings are usefull if you own some special server
+# or really small server.
+#=============================================================
+
+#-------------------------------------------------------------
+# Server config
+#-------------------------------------------------------------
+# AutoLoot enable... True to enable, False to disable
+AutoLoot = False
+
+# If False herbs will drop on ground even if AutoLoot is enabled
+AutoLootHerbs = False
+
+# AutoLearnSkills... True to enable, False to disable
+AutoLearnSkills = False
+
+# Party range for l2attackable (default 1600)
+AltPartyRange = 1600
+# Party range for l2party (default 1400)
+AltPartyRange2 = 1400
+
+# Weight Limit multiplier - default 1
+AltWeightLimit = 1
+
+# If XP loss (and deleveling) is enabled, default is 'true'
+Delevel = True
+
+# If disabled, magic dmg has always 100% chance of success, default is 'true'
+MagicFailures = True
+
+# Alternative cancel of attack (bow, cast, all)
+AltGameCancelByHit = cast
+
+# Alternative rules for shields - if they block, the damage is powerAtk-shieldDef,
+# otherwice it's powerAttak / (shieldDef + powerDef)
+AltShieldBlocks = False
+
+# Alternative Rate Value for Perfect Shield Block Rate.
+AltPerfectShieldBlockRate = 5
+
+# Alternative AltGameMobAttackAI, like C1
+AltGameMobAttackAI = False
+
+# Alternative mob behavior in peace zones 
+# Default = True; Set to False to prevent mobs from auto-agro against players in peace zones  
+AltMobAgroInPeaceZone = True
+
+# Alternative Freight mode. If true, freights can be withdrawed from any place.
+# Also, possibility to change Freight price (in adena) for each item slot in freight.
+# NOTE: AltGameFreightPrice WILL NOT change the value shown to the player, but the
+# player will actually get charged for the value set in here.
+AltGameFreights = True
+AltGameFreightPrice = 1000
+
+# Alternative Xp/Sp rewards, if not 0, then calculated as 2^((mob.level-player.level) / coef),
+# A few examples for "AltGameExponentXp = 5." and "AltGameExponentSp = 3."
+# diff = 0 (player and mob has the same level), XP bonus rate = 1, SP bonus rate = 1
+# diff = 3 (mob is 3 levels above), XP bonus rate = 1.52, SP bonus rate = 2
+# diff = 5 (mob is 5 levels above), XP bonus rate = 2, SP bonus rate = 3.17
+# diff = -8 (mob is 8 levels below), XP bonus rate = 0.4, SP bonus rate = 0.16
+AltGameExponentXp = 0
+AltGameExponentSp = 0
+
+# Use tiredness (instead of combat points)
+AltGameTiredness = False
+
+#-------------------------------------------------------------
+# Alternative settings against player with karma
+#-------------------------------------------------------------
+AltKarmaPlayerCanBeKilledInPeaceZone = False
+AltKarmaPlayerCanShop = True
+# Can the player use Scroll of Escape or Return skill?
+AltKarmaPlayerCanTeleport = True
+# Can the player use gatekeepers (GK)?
+AltKarmaPlayerCanUseGK = False
+AltKarmaPlayerCanTrade = True
+AltKarmaPlayerCanUseWareHouse = True
+
+# Allow free teleportation around the world.
+AltFreeTeleporting = False
+
+#Set true for disallow recommend character twice or more a day
+AltRecommend = False
+
+#-------------------------------------------------------------
+# Crafting config
+#-------------------------------------------------------------
+# Crafting enabled/disabled. On by default
+CraftingEnabled = True
+
+#Limits for recipes (defal: 50 - for dwarf , 50 - for common)
+DwarfRecipeLimit = 50
+CommonRecipeLimit = 50
+
+# Alternative crafting rules:
+# - crafting takes time
+# - players get EXP/SP for crafting
+AltGameCreation = False
+
+# time multiplier - bigger number ===> slower crafting but more XP/SP 
+AltGameCreationSpeed = 1
+
+# Additional XP/SP rate multiplier (for increased XP/SP)  default = 1
+AltGameCreationRateXp = 1
+AltGameCreationRateSp = 1
+
+# If set to False, blacksmiths don't take recipes from players inventory when crafting.
+# Default = True (on retail it's confirmed that blacksmith use recipes for each crafted item) 
+AltBlacksmithUseRecipes = True
+
+#-------------------------------------------------------------
+# Skills config
+#-------------------------------------------------------------
+# Allow use Event Managers for change occupation
+# If you need change occupation only use quest then set this to False
+# Default = False
+AllowClassMasters = False
+
+# Life crystal needed to learn clan skills
+LifeCrystalNeeded = True
+# Spell Book needed to learn skills
+SpBookNeeded = True
+
+# Book needed to enchant skills
+EnchantSkillSpBookNeeded = True
+
+# Alternative skill learn rules:
+# - all classes can learn all skills
+# - skills of another class costs x2 SP
+# - skills of another race costs x2 SP
+# - skills of fighters/mages costs x3 SP
+AltGameSkillLearn = False
+
+# Allow player sub-class addition without checking for unique quest items.
+AltSubClassWithoutQuests = False
+
+#-------------------------------------------------------------
+# Buffs config
+#-------------------------------------------------------------
+# Maximum number of buffs (default = 24 in C5)
+maxbuffamount = 20
+
+#-------------------------------------------------------------
+# Equipment Restriction config
+#-------------------------------------------------------------
+# Alternate Gaming
+# Usage: True  - Restriction enabled
+#        False - Restriction disabled
+# Castle Shield can be equiped by all clan members if they own a castle. - default True
+CastleShieldRestriction = True
+# ClanHall Shield can be equiped by all clan members if they own a clan hall. - default True
+ClanHallShieldRestriction = True
+# Apella armors can be equiped only by clan members if their class is Baron or higher - default True
+ApellaArmorsRestriction = True
+# Clan Oath Armors can be equiped only by clan members - default True
+OathArmorsRestriction = True
+# Castle Crown can be equiped only by castle lord - default True
+CastleLordsCrownRestriction = True
+#Castle Circlets can be equiped only by clan members if they own a castle - default True
+CastleCircletsRestriction = True
+
+#-------------------------------------------------------------
+# Clans config
+#-------------------------------------------------------------
+# Number of days you have to wait before :
+#   - joining another clan
+DaysBeforeJoinAClan = 1
+#   - creating a new clan
+DaysBeforeCreateAClan = 10
+# Number of days it takes to dissolve a clan
+DaysToPassToDissolveAClan = 7
+# Number of days before joining a new alliance when clan voluntarily leave an alliance
+DaysBeforeJoinAllyWhenLeaved = 1
+# Number of days before joining a new alliance when clan was dismissed from an alliance
+DaysBeforeJoinAllyWhenDismissed = 1
+# Number of days before accepting a new clan for alliance when clan was dismissed from an alliance
+DaysBeforeAcceptNewClanWhenDismissed = 1
+# Number of days before creating a new alliance when dissolved an alliance
+DaysBeforeCreateNewAllyWhenDissolved = 10
+
+# Maximum number of clans in ally
+AltMaxNumOfClansInAlly = 3
+
+# Number of members needed to request a clan war
+AltClanMembersForWar = 15
+
+# All new characters of the same account are newbies, not only first one
+AltNewCharAlwaysIsNewbie = True
+
+# Privilege browse warehouse enables at the same time also withdraw from warehouse!
+AltMembersCanWithdrawFromClanWH = False
+
+#Remove Castle circlets after a clan lose its castle or a player leaves a clan? - default true
+RemoveCastleCirclets = True
+
+#-------------------------------------------------------------
+# Olympiad config
+#-------------------------------------------------------------
+# Olympiad Start Time in Military hours Default 6pm (18) 
+AltOlyStartTime = 18
+
+# Olympiad Start Time for Min's, Default 00 so at the start of the hour.
+AltOlyMin = 00
+
+# Olympiad Compeition Period, Default 6 hours.
+# (If set different, should be increment by 10mins)
+AltOlyCPeriod = 21600000
+
+# Olympiad Battle Period, Default 6 minutes. (If set different, should be < AltOlyBWait)
+AltOlyBattle = 360000
+
+# Olympiad Battle Wait, Default 10 Minutes
+AltOlyBWait = 600000
+
+# Olympiad Inital Wait Period, Default 5 minutes
+AltOlyIWait = 300000
+
+# Olympiad Weekly Period, Default 1 week
+AltOlyWPeriod = 604800000
+
+# Olympiad Validation Period, Default 24 Hours.
+AltOlyVPeriod = 86400000
+
+#-----------------------------------------------------------------
+# Manor Config
+#-----------------------------------------------------------------
+
+# Manor Refresh Time in Military hours Default 8pm (20) 
+AltManorRefreshTime = 20
+
+# Manor Refresh Time for Min's, Default 00 so at the start of the hour.
+AltManorRefreshMin = 00
+
+# Manor Next Period Approve Time in Military hours Default 6am 
+AltManorApproveTime = 6
+
+# Manor Next Period Approve Time for Min's, Default 00 so at the start of the hour.
+AltManorApproveMin = 00
+
+# Manor Maintenance time, Default 6 minutes. 
+AltManorMaintenancePeriod = 360000
+
+# Manor Save Type. 1-Save data into db after every action; Default false
+AltManorSaveAllActions = True
+
+# Manor Save Period (used only if AltManorSaveAllActions=false) Default very 2 hours
+AltManorSavePeriodRate = 2
+
+#-------------------------------------------------------------
+# Lottery config
+#-------------------------------------------------------------
+# Initial Lottery prize
+AltLotteryPrize = 50000
+
+# Lottery Ticket Price
+AltLotteryTicketPrice = 2000
+
+# What part of jackpot amount should receive characters who pick 5 wining numbers
+AltLottery5NumberRate = 0.6
+
+# What part of jackpot amount should receive characters who pick 4 wining numbers
+AltLottery4NumberRate = 0.2
+
+# What part of jackpot amount should receive characters who pick 3 wining numbers
+AltLottery3NumberRate = 0.2
+
+# How much adena receive characters who pick two or less of the winning number
+AltLottery2and1NumberPrize = 200
+
+#-------------------------------------------------------------
+# Debug & Dev config
+#-------------------------------------------------------------
+# Don't load quests
+AltDevNoQuests = False
+# Don't load spawntable
+AltDevNoSpawns = False
+
+#-----------------------------------
+# Dimension Rift Config
+#-----------------------------------
+# Minimal party size to enter rift. Min = 2, Max = 9.
+# If in rift party will become smaller all members will be teleported back
+RiftMinPartySize = 5
+
+# Number of maximum jumps between rooms allowed, after this time party will be teleported back
+MaxRiftJumps = 4
+
+# Time in ms the party has to wait until the mobs spawn when entering a room. C4 retail: 10s
+RiftSpawnDelay = 10000
+
+# Time between automatic jumps in seconds
+AutoJumpsDelayMin = 480
+AutoJumpsDelayMax = 600
+
+# Time Multiplier for stay in the boss room
+BossRoomTimeMultiply = 1.5
+
+# Cost in dimension fragments to enter the rift, each party member must own this amount
+RecruitCost = 18
+SoldierCost = 21
+OfficerCost = 24
+CaptainCost = 27
+CommanderCost = 30
+HeroCost = 33

+ 178 - 0
L2_GameServer_T1/java/config/clanhall.properties

@@ -0,0 +1,178 @@
+#=============================================================
+#                Clan Hall Function price
+#=============================================================
+
+# Price = 7 day(one day price = price/7)
+#-------------------------------------------------------------
+# Teleport Function price
+#-------------------------------------------------------------
+# 1st level
+ClanHallTeleportFunctionFeeLvl1 = 7000
+# 2nd level
+ClanHallTeleportFunctionFeeLvl2 = 14000
+# 3rd level
+#ClanHallTeleportFunctionFeeLvl3 = 2100
+# Need core support, need more information on functions in different
+# Clan Hall in different Towns.
+# 4th level
+#ClanHallTeleportFunctionFeeLvl4 = 28000
+
+#-------------------------------------------------------------
+# Support magic buf price 
+#-------------------------------------------------------------
+# 1st level
+ClanHallSupportFeeLvl1 = 17500
+# 2nd level
+ClanHallSupportFeeLvl2 = 35000
+# 3rd level
+ClanHallSupportFeeLvl3 = 49000
+# 4th level
+ClanHallSupportFeeLvl4 = 77000
+# 5th level                       
+ClanHallSupportFeeLvl5 = 147000
+# 6th level
+ClanHallSupportFeeLvl6 = 252000
+# 7th level
+ClanHallSupportFeeLvl7 = 259000
+# 8th level
+ClanHallSupportFeeLvl8 = 364000
+
+# Need core support, need more information on functions in different
+# Clan Hall in different Towns.
+# 9th level
+#ClanHallSupportFeeLvl9 = 469000
+
+#-------------------------------------------------------------
+#  MpRegeneration price   
+#-------------------------------------------------------------
+# 5% MpRegeneration
+ClanHallMpRegenerationFeeLvl1 = 14000
+# 10% MpRegeneration
+ClanHallMpRegenerationFeeLvl2 = 26250
+# 15% MpRegeneration
+ClanHallMpRegenerationFeeLvl3 = 45500
+# 30% MpRegeneration
+ClanHallMpRegenerationFeeLvl4 = 96250
+# 40% MpRegeneration
+ClanHallMpRegenerationFeeLvl5 = 140000
+
+# Need core support, need more information on functions in different
+# Clan Hall in different Towns.
+# 20% MpRegeneration
+#ClanHallMpRegenerationFeeLvl? = 59500
+# 25% MpRegeneration
+#ClanHallMpRegenerationFeeLvl? = 84000
+# 35% MpRegeneration
+#ClanHallMpRegenerationFeeLvl? = 129500
+# 40% MpRegeneration
+#ClanHallMpRegenerationFeeLvl? = 140000
+# 45% MpRegeneration
+#ClanHallMpRegenerationFeeLvl? = 182000
+# 50% MpRegeneration
+#ClanHallMpRegenerationFeeLvl? = 192500
+
+#-------------------------------------------------------------
+#  HpRegeneration price   
+#-------------------------------------------------------------
+
+# 20% HpRegeneration
+ClanHallHpRegenerationFeeLvl1 = 4900
+# 40% HpRegeneration
+ClanHallHpRegenerationFeeLvl2 = 5600
+# 80% HpRegeneration
+ClanHallHpRegenerationFeeLvl3 = 7000
+# 100% HpRegeneration
+ClanHallHpRegenerationFeeLvl4 = 8166
+# 120% HpRegeneration
+ClanHallHpRegenerationFeeLvl5 = 10500
+# 140% HpRegeneration
+ClanHallHpRegenerationFeeLvl6 = 12250
+# 160% HpRegeneration
+ClanHallHpRegenerationFeeLvl7 = 14000
+# 180% HpRegeneration
+ClanHallHpRegenerationFeeLvl8 = 15750
+# 200% HpRegeneration
+ClanHallHpRegenerationFeeLvl9 = 17500
+# 220% HpRegeneration
+ClanHallHpRegenerationFeeLvl10 = 22750
+# 240% HpRegeneration
+ClanHallHpRegenerationFeeLvl11 = 26250
+# 260% HpRegeneration
+ClanHallHpRegenerationFeeLvl12 = 29750
+# 300% HpRegeneration
+ClanHallHpRegenerationFeeLvl13 = 36166
+
+# Need core support, need more information on functions in different
+# Clan Hall in different Towns.
+# 60% HpRegeneration
+#ClanHallHpRegenerationFeeLvl? = 6300
+# 280% HpRegeneration
+#ClanHallHpRegenerationFeeLvl? = 33250
+# 320% HpRegeneration
+#ClanHallHpRegenerationFeeLvl? = 43750
+# 340% HpRegeneration
+#ClanHallHpRegenerationFeeLvl? = 49000
+# 360% HpRegeneration
+#ClanHallHpRegenerationFeeLvl? = 54250
+# 380% HpRegeneration
+#ClanHallHpRegenerationFeeLvl? = 59500
+# 400% HpRegeneration
+#ClanHallHpRegenerationFeeLvl? = 61833
+
+#-------------------------------------------------------------
+#  ExpRegeneration price  
+#-------------------------------------------------------------
+# 5% ExpRegeneration
+ClanHallExpRegenerationFeeLvl1 = 21000
+# 10% ExpRegeneration
+ClanHallExpRegenerationFeeLvl2 = 42000
+# 15% ExpRegeneration
+ClanHallExpRegenerationFeeLvl3 = 63000
+# 25% ExpRegeneration
+ClanHallExpRegenerationFeeLvl4 = 105000
+# 35% ExpRegeneration
+ClanHallExpRegenerationFeeLvl5 = 147000
+# 40% ExpRegeneration
+ClanHallExpRegenerationFeeLvl6 = 163331
+# 50% ExpRegeneration
+ClanHallExpRegenerationFeeLvl7 = 210000
+# Need core support, need more information on functions in different
+# Clan Hall in different Towns.
+
+# 20% ExpRegeneration
+#ClanHallExpRegenerationFeeLvl? = 81666
+# 30% ExpRegeneration
+#ClanHallExpRegenerationFeeLvl? = 126000
+# 35% ExpRegeneration
+#ClanHallExpRegenerationFeeLvl? = 147000
+# 45% ExpRegeneration
+#ClanHallExpRegenerationFeeLvl? = 189000
+# 50% ExpRegeneration
+#ClanHallExpRegenerationFeeLvl? = 210000
+# 55% ExpRegeneration
+#ClanHallExpRegenerationFeeLvl? = 231000
+# 60% ExpRegeneration
+#ClanHallExpRegenerationFeeLvl? = 245000
+
+#-------------------------------------------------------------
+# Creation item function  
+#-------------------------------------------------------------
+#Time after count of Item is restored (in Hours)
+#ClanHallItemCreationFunctionTaskRestore = 24
+# 1st level
+ClanHallItemCreationFunctionFeeLvl1 = 210000
+# 2nd level
+ClanHallItemCreationFunctionFeeLvl2 = 490000
+# 3rd level
+ClanHallItemCreationFunctionFeeLvl3 = 980000
+
+#-------------------------------------------------------------
+# Decor function  
+#-------------------------------------------------------------
+# Need core support, need more information on functions in different
+# Clan Hall in different Towns.
+#
+ClanHallCurtainFunctionFeeLvl1 = 2002
+ClanHallCurtainFunctionFeeLvl2 = 2625
+ClanHallFrontPlatformFunctionFeeLvl1 = 3031
+ClanHallFrontPlatformFunctionFeeLvl2 = 9331

+ 432 - 0
L2_GameServer_T1/java/config/command-privileges.properties

@@ -0,0 +1,432 @@
+# Alternative Configure GM commands access level
+#
+# This file only read if "AltPrivilegesAdmin = True"!!!
+#
+# Information:
+# 1) If AltPrivilegesSecureCheck = True
+#    Every commands need a entry in this file, else the command cannot be executed.
+#    else if a command haven't got a entry in this file the minimun access level is
+#    AltPrivilegesDefaultLevel (default = 100)
+# 2) Some commands need a correct access level on GM Access table too, like:  
+#    the commands contained into AdminEditChar.java,AdminEditNpc.java,AdminSpawn.java files
+
+admin_admin = 100
+admin_admin1 = 100
+admin_admin2 = 100
+admin_admin3 = 100
+admin_admin4 = 100
+admin_admin5 = 100
+#######################
+### COMMON COMMANDS ###
+#######################
+admin_delete = 100
+admin_gmshop = 100
+admin_heal = 75
+admin_help = 75
+admin_vis = 75
+admin_invis = 75
+admin_invis_menu = 75
+admin_invul = 75
+admin_kill = 75
+admin_res = 75
+admin_silence = 75
+admin_target = 75
+ 
+#######################
+### CHAR MANAGEMENT ###
+#######################
+admin_ban = 100
+admin_banchat = 75
+admin_jail = 100
+admin_character_disconnect = 75
+admin_kick = 75
+admin_unban = 100
+admin_unbanchat = 75
+admin_unjail = 100
+ 
+#################
+### CLAN HALL ###
+#################
+admin_clanhall = 100
+admin_clanhalldel = 100
+admin_clanhallset = 100
+admin_clanhallopendoors = 100
+admin_clanhallteleportself = 100
+ 
+####################
+### ANNOUNCEMENT ###
+####################
+admin_add_announcement = 100
+admin_announce = 75
+admin_announce_announcements = 75
+admin_announce_menu = 75
+admin_del_announcement = 100
+admin_list_announcements = 75
+admin_reload_announcements = 100
+ 
+#######################
+### RELOAD COMMANDS ###
+#######################
+admin_cache_htm_rebuild = 100
+admin_cache_htm_reload = 100
+admin_cache_crest_fix = 100
+admin_cache_crest_rebuild = 100
+admin_cache_crest_reload = 100
+ 
+admin_quest_reload = 100
+admin_teleport_reload = 100
+admin_spawn_reload = 100
+admin_zone_reload = 100
+ 
+####################
+### DOOR CONTROL ###
+####################
+admin_close = 75
+admin_closeall = 100
+admin_open = 75
+admin_openall = 100
+ 
+#########################
+### CHAR MODIFICATION ###
+#########################
+admin_setclass = 100
+admin_add_exp_sp = 100
+admin_add_exp_sp_to_character = 100
+admin_add_level = 100
+admin_set_level = 100
+admin_changename = 100
+admin_changename_menu = 100
+admin_character_list = 75
+admin_character_info = 75
+admin_current_player = 75
+admin_edit_character = 100
+admin_find_character = 75
+admin_find_ip = 75
+admin_find_account = 75
+admin_nokarma = 100
+admin_rec = 75
+admin_repair = 75
+admin_restore = 75
+admin_setew = 100
+admin_setkarma = 100
+admin_save_modifications = 100
+admin_setcolor = 75
+admin_setname = 100
+admin_setsex = 100
+admin_settitle = 75
+admin_show_characters = 75
+ 
+################
+### EDIT NPC ###
+################
+admin_edit_npc = 100
+admin_save_npc = 100
+admin_show_droplist = 100
+admin_edit_drop = 100
+admin_add_drop = 100
+admin_del_drop = 100
+admin_showShop = 100
+admin_showShopList = 100
+admin_addShopItem = 100
+admin_delShopItem = 100
+admin_box_access = 100
+admin_editShopItem = 100
+ 
+###############
+### EFFECTS ###
+###############
+admin_atmosphere = 75
+admin_invisible = 75
+admin_visible = 75
+admin_earthquake = 75
+admin_bighead = 100
+admin_shrinkhead = 100
+admin_gmspeed = 75
+admin_unpara_all = 100
+admin_para_all = 100
+admin_unpara = 100
+admin_para = 100
+admin_polymorph = 75
+admin_unpolymorph = 75
+admin_polyself = 75
+admin_unpolyself = 75
+admin_clearteams = 100
+admin_setteam_close = 100
+admin_setteam = 100
+admin_effect = 100
+admin_social = 100
+admin_play_sounds = 75
+admin_play_sound =  75
+admin_abnormal = 100
+admin_atmosphere_menu = 75
+admin_unpara_all_menu = 100
+admin_para_all_menu = 100
+admin_unpara_menu = 100
+admin_para_menu = 100
+admin_polymorph_menu = 75
+admin_unpolymorph_menu = 75
+admin_polyself_menu = 75
+admin_unpolyself_menu = 75
+admin_social_menu = 100
+admin_effect_menu = 100
+admin_abnormal_menu = 100
+
+####################
+### ENCHANT MENU ###
+####################
+admin_seteh = 100
+admin_setec = 100
+admin_seteg = 100
+admin_setel = 100
+admin_seteb = 100
+admin_setes = 100
+admin_setle = 100
+admin_setre = 100
+admin_setlf = 100
+admin_setrf = 100
+admin_seten = 100
+admin_setun = 100
+admin_setba = 100
+admin_enchant = 100
+ 
+#############
+### EVENT ###
+#############
+admin_event = 100
+admin_event_new = 100
+admin_event_choose = 100
+admin_event_store = 100
+admin_event_set = 100
+admin_event_change_teams_number = 100
+admin_event_announce = 100
+admin_event_panel = 100
+admin_event_control_begin = 100
+admin_event_control_teleport = 100
+admin_add = 100
+admin_event_see = 100
+admin_event_del = 100
+admin_delete_buffer = 100
+admin_event_control_sit = 100
+admin_event_name = 100
+admin_event_control_kill = 100
+admin_event_control_res = 100
+admin_event_control_poly = 100
+admin_event_control_unpoly = 100
+admin_event_control_prize = 100
+admin_event_control_chatban = 100
+admin_event_control_finish = 100
+ 
+#######################
+### SERVER SETTINGS ###
+#######################
+admin_server_shutdown = 100
+admin_server_restart = 75
+admin_server_abort = 75
+admin_server_gm_only = 100
+admin_server_all = 100
+admin_server_max_player = 100
+admin_server_list_clock = 100
+admin_server_login = 100
+ 
+############
+### MENU ###
+############
+admin_char_manage = 75
+admin_teleport_character_to_menu = 75
+admin_recall_char_menu = 75
+admin_recall_party_menu = 75
+admin_recall_clan_menu = 75
+admin_goto_char_menu = 75
+admin_kick_menu = 75
+admin_kill_menu = 100
+admin_ban_menu = 100
+admin_unban_menu = 100
+ 
+#################
+### MOB GROUP ###
+#################
+admin_mobmenu = 100
+admin_mobgroup_create = 100
+admin_mobgroup_spawn = 100
+admin_mobgroup_unspawn = 100
+admin_mobgroup_kill = 100
+admin_mobgroup_idle = 100
+admin_mobgroup_attack = 100
+admin_mobgroup_rnd = 100
+admin_mobgroup_return = 100
+admin_mobgroup_follow = 100
+admin_mobgroup_casting = 100
+admin_mobgroup_nomove = 100
+admin_mobgroup_attackgrp = 100
+admin_mobgroup_invul = 100
+admin_mobinst = 100 
+admin_mobgroup_remove = 100
+ 
+#################
+### PATH NODE ###
+#################
+admin_pn_info = 100
+admin_show_path = 100
+admin_path_debug = 100
+admin_show_pn = 100
+admin_find_path = 100
+ 
+#############
+### RIDE ####
+#############
+admin_ride_wyvern = 75
+admin_ride_strider = 75
+admin_unride_wyvern = 75
+admin_unride_strider = 75
+admin_unride = 75
+ 
+#############
+### SIEGE ###
+#############
+admin_siege = 100
+admin_add_attacker = 100
+admin_add_defender = 100
+admin_add_guard = 100
+admin_list_siege_clans = 100
+admin_clear_siege_list = 100
+admin_move_defenders = 100
+admin_spawn_doors = 100
+admin_endsiege = 100
+admin_startsiege = 100
+admin_setcastle = 100
+ 
+#############
+### SKILL ###
+#############
+admin_show_skills = 100
+admin_remove_skills = 100
+admin_skill_list = 100
+admin_skill_index = 100
+admin_add_skill = 100
+admin_add_clan_skill = 100
+admin_remove_skill = 100
+admin_get_skills = 100
+admin_reset_skills = 100
+admin_give_all_skills = 100
+admin_remove_all_skills = 100
+ 
+#############
+### SPAWN ###
+#############
+admin_mammon_find = 75
+admin_mammon_respawn = 75
+admin_list_spawns = 75
+admin_show_spawns = 75
+admin_spawn = 100
+admin_spawn_once = 100
+admin_spawn_index = 100
+admin_spawn_monster = 100
+admin_respawnall = 100
+admin_unspawnall = 100
+ 
+################
+### TELEPORT ###
+################
+admin_show_moves = 75
+admin_show_moves_other = 75
+admin_show_teleport = 75
+admin_teleport_to_character = 75
+admin_teleportto = 75
+admin_move_to = 75
+admin_teleport_character = 75
+admin_recall = 75
+admin_walk = 75
+admin_explore = 75
+admin_recall_npc = 100
+admin_gonorth = 75
+admin_gosouth = 75
+admin_goeast = 75
+admin_gowest = 75
+admin_goup = 75
+admin_godown = 75
+admin_tele = 75
+admin_teleto = 75
+ 
+#####################
+### TEST COMMANDS ###
+#####################
+admin_known = 100
+admin_mp = 100
+admin_msg = 100
+admin_forge = 100
+admin_forge2 = 100
+admin_forge3 = 100
+admin_skill_test = 75
+admin_st = 75
+admin_stats = 100
+admin_test = 100
+admin_zone_check = 100
+admin_fight_calculator=100
+admin_fight_calculator_show=100
+admin_fcs=100
+#################
+### PETITIONS ###
+#################
+admin_accept_petition = 75
+admin_reject_petition = 75
+admin_reset_petitions = 100
+admin_view_petition = 75
+admin_view_petitions = 75
+ 
+###################
+### GM SETTINGS ###
+###################
+admin_changelvl = 100
+admin_gm = 75
+admin_gmchat = 75
+admin_gmchat_menu = 75
+admin_gmlistoff = 75
+admin_gmliston = 75
+admin_snoop = 75
+ 
+#####################
+### MISCELLANEOUS ###
+#####################
+admin_buy = 100
+admin_create_item = 100
+admin_itemcreate = 100
+admin_pledge = 100
+admin_set = 100
+admin_set_menu = 100
+admin_set_mod = 100
+admin_tradeoff = 75
+admin_unblockip = 100 
+
+###############
+### GEODATA ###
+###############
+admin_geo_z = 100
+admin_geo_type = 100
+admin_geo_nswe = 100
+admin_geo_los = 100
+admin_geo_position = 100
+admin_geo_bug = 100
+admin_geo_load = 100
+admin_geo_unload = 100
+admin_geoeditor_connect = 100
+admin_geoeditor_join = 100
+admin_geoeditor_leave = 100
+
+###############
+### ZARICHE ###
+###############
+admin_cw_info = 75
+admin_cw_info_menu = 75
+admin_cw_add = 75
+admin_cw_remove = 75
+admin_cw_goto = 75
+admin_cw_reload = 100
+###############
+###  MANOR  ###
+###############
+admin_manor_info = 75
+admin_manor_setnext = 100
+admin_manor_approve = 100
+admin_manor_disable = 100
+admin_manor_setmaintenance = 100
+admin_manor_save = 75

+ 1 - 0
L2_GameServer_T1/java/config/extensions.properties

@@ -0,0 +1 @@
+# Configuration file for dynamic extensions

+ 19 - 0
L2_GameServer_T1/java/config/idfactory.properties

@@ -0,0 +1,19 @@
+# Allows selection of new Classes for storage of World Objects.
+# This may help servers with large amounts of players recieving error
+# messages related to the L2ObjectHashMap and L2ObejctHashSet classes.
+#
+# By default it uses the new method, to use the old classes add the
+# comment at the front of each line.
+L2Map = WorldObjectMap
+L2Set = WorldObjectSet
+
+# Tell server which IDFactory Class to use
+# Options are:
+# Compaction (Original method),
+# BitSet (One non compaction method - default),
+# Stack  (Another non compaction method)
+IDFactory = BitSet
+
+# Check for bad ids in the database on server boot up
+# Much faster load time without it, but may cause problems
+BadIdChecking = True

+ 133 - 0
L2_GameServer_T1/java/config/l2jmods.properties

@@ -0,0 +1,133 @@
+#---------------------------------------------------------------
+#--L2JMODS------------------------------------------------------
+#---------------------------------------------------------------
+# All modifications can be enabled and disabled without effect -
+# effecting the server, designed specifically to add non       -
+# retail types of gameplay into the L2J server.                -
+#---------------------------------------------------------------
+
+
+#---------------------------------------------------------------
+# Champion mobs                                                -
+# Turns random mobs into Champions                             -
+#---------------------------------------------------------------
+# Enable Champions L2JMod
+ChampionEnable = false
+# Chance for a mob to became champion (in percents) - 0 to disable
+ChampionFrequency = 5
+# Min and max lvl allowed for a mob to be champion.
+ChampionMinLevel = 20
+ChampionMaxLevel = 70
+# Hp multiplier
+ChampionHp = 8
+# Hp Regen Multiplier
+ChampionRegenHp = 1.
+# Rewards multiplier
+ChampionRewards = 8
+# Adenas & seal stones rewards multiplier
+ChampionAdenasRewards = 1
+# Atk bonus for champion (changes apply on patk & matk)
+ChampionAtk = 1.
+# Spd Atk bonus for champion (changes apply on patkspd & matkspd)
+ChampionSpdAtk = 1.
+# Chance to obtain a specified reward item from a higher lvl champion (in percents)   default is off using glittering medal as reward
+ChampionRewardItem = 0
+# Specified reward item ID
+ChampionRewardItemID = 6393
+# Specified reward item rnd qty
+ChampionRewardItemQty = 1
+
+#---------------------------------------------------------------
+# Wedding System (by evill33t)                     
+#---------------------------------------------------------------
+# description by unical3:
+# It's 2 parted.
+# First part "engage" 
+# 1) Target the player that you want to make a couple with 
+# 2) Write in chatwindow .engage nameofyourpartner then enter
+# 3) if player has you on friendlist popup will apppear with engage request
+# ============ 
+# ok cancel 
+# ============
+# and a systemsg that you wanna engage with him/her
+# if not in your friendlist nothing will happen. (/friendinvite nameplayer)
+# 4) if player accepts you are engaged. Congratulations!
+#
+# Second part "marriage" 
+# 1) if you are engaged go to a Wedding Priest named Andromeda 
+# in Hot Springs Guild House (Goddard) and ask for marriage 
+# [ you need Formal Wear (C4Items) and it costs 11k ]
+# 2) your partner goes to the npc and confirms after you make the request
+# 3) fireworks,wedding marchs and your are married 
+#
+# You can use .gotolove nameofyourpartner to teleport to your partner if 
+# you're married (costs 500 adena) 
+#
+# if you want to cancel your engagement / marriage enter .divorce nameofyourpartner
+# if you're married you have to pay 20 % of adena to your partner 
+#
+# When you try to engage with someone and you have already a partner you get 
+# a bighead + debuff 
+#
+# You find a priest NPC in Hot Springs Guild House (Goddard).
+# Wedding Manager Id: //spawn 50007
+#---------------------------------------------------------------
+#True Allows Wedding, False disables Wedding.
+AllowWedding=False
+#Cost of Wedding, set the price in Adena, remember not to exceed the max!
+WeddingPrice=250000000
+#Would you like to punish the player for for disloyalty to their spouses? If you want them punished set to True, if you would like NO punishment then set to False
+WeddingPunishInfidelity=True
+#Have the players teleported for marriage? If so True, if not False
+WeddingTeleport=True
+#The Price for Teleport is configurable below in Adena
+WeddingTeleportPrice=50000
+#Time before character is teleported can be set below (in seconds)
+WeddingTeleportDuration=60
+#Homosexuality- Allowed = True, Not Allowed = False
+WeddingAllowSameSex=False
+#Require Players to wear formal wear, True is yes require formal wear, False is not require formal wear.
+WeddingFormalWear=True
+#Cost of Divorce, % of Adena
+WeddingDivorceCosts=20
+
+#---------------------------------------------------------------
+# Team vs. Team Event Engine (by FBIagent)                     -
+#---------------------------------------------------------------
+# enable TvTEvent
+TvTEventEnabled = false
+# Time Between TvT events (in minutes, 300 = 5 hours)
+TvTEventInterval = 300
+#  Registration timer (in minutes) from start of event.
+TvTEventParticipationTime = 60
+#  Event running time, in minutes
+TvTEventRunningTime = 20
+# TvT Event NPC Details (create a custom npc of type L2TvTEventNpc)
+TvTEventParticipationNpcId = 70010
+TvTEventParticipationNpcCoordinates = 83425,148585,-3406
+# Minimum amount of players allowed in each team 
+TvTEventMinPlayersInTeams = 1
+TvTEventMaxPlayersInTeams = 20
+# Level rules 
+TvTEventMinPlayerLevel = 1
+TvTEventMaxPlayerLevel = 80
+# Teleport delay Timers (in seconds)
+TvTEventRespawnTeleportDelay = 10
+TvTEventStartLeaveTeleportDelay = 10
+# First Team Details (name, start and death x,y,z tp point)
+TvTEventTeam1Name = Team1
+TvTEventTeam1Coordinates = 148695,46725,-3414
+# Second Team Details (name, start and death x,y,z tp point)
+TvTEventTeam2Name = Team2
+TvTEventTeam2Coordinates = 149999,46728,-3414
+# Reward for winning team 
+# itemId,amount;itemId,amount;itemId,amount;...
+# no ";" at the start or end
+TvTEventReward = 57,100000;5575,1000
+# TvTEvent Rules
+TvTEventTargetTeamMembersAllowed = true
+TvTEventPotionsAllowed = false
+TvTEventSummonByItemAllowed = false# Door id's to close/open on start/end
+# ex.: 1;2;3;4;5;6
+# no ";" at the start or end
+TvTEventDoorsCloseOpenOnStartEnd =

+ 80 - 0
L2_GameServer_T1/java/config/loginserver.properties

@@ -0,0 +1,80 @@
+# This is the server configuration file. Here you can set up the connection for your server.
+# Usually you have to change the ExternalHostname option to
+# - 127.0.0.1 (if you want to play alone / testing purpose)
+# - LAN IP* (if you want to play from another computer in the network)
+# - WAN IP** (if you want to play with friends over internet)
+# - Questions? => http://l2jserver.com
+#
+# * = If you want to get your LAN IP, simply choose "Start" => "Run..." then type "cmd" => "ipconfig"
+# **= If you want to get you WAN IP, visit http://www.whatismyip.com
+# ===================================================================================================
+
+# ================================================================
+# General server setting !!! REQUIRED to configure to everyone !!!
+# ================================================================
+
+# This is transmitted to the clients connecting from an external network, so it has to be a public IP or resolvable hostname
+ExternalHostname=127.0.0.1
+
+# This is transmitted to the client from the same network, so it has to be a local IP or resolvable hostname
+InternalHostname=127.0.0.1
+
+# Bind ip of the LoginServer, use * to bind on all available IPs
+LoginserverHostname=*
+LoginserverPort=2106
+# How many times you can provide an invalid account/pass before the IP gets banned
+LoginTryBeforeBan=10
+# Time you won't be able to login back again after LoginTryBeforeBan tries to login. Provide a value in seconds. Default 10min. (600)
+LoginBlockAfterBan=600
+GMMinLevel=100
+
+# The address on which login will listen for GameServers, use * to bind on all available IPs
+LoginHostname=*
+
+# The port on which login will listen for GameServers
+LoginPort=9014
+
+# If set to true any GameServer can register on your login's free slots
+AcceptNewGameServer = False
+
+# If false, the licence (after the login) will not be shown
+# It is highly recomended for Account Seciurity to leave this option as defalut (True)
+ShowLicence = True
+
+# Database info
+Driver=com.mysql.jdbc.Driver
+#Driver=org.hsqldb.jdbcDriver
+#Driver=com.microsoft.sqlserver.jdbc.SQLServerDriver
+URL=jdbc:mysql://localhost/l2jdb
+#URL=jdbc:hsqldb:hsql://localhost/l2jdb
+#URL=jdbc:sqlserver://localhost/database=l2jdb/user=sa/password=
+Login=root
+Password=
+MaximumDbConnections=10
+
+# Useable values: "true" - "false", use this option to choose whether accounts will be created
+# automatically or not.
+AutoCreateAccounts=true
+
+# The delay in minutes after which the login updates the gameservers IP's (usefull when their ip is dynamic)
+IpUpdateTime=15
+
+
+# ==============================================================
+# Test server setting, shoudnt be touched in online game server
+# ==============================================================
+
+Debug = False
+Assert = False
+Developer = False
+
+# Enforce GG Authorization from client
+# Login server will kick client if client bypassed GameGuard authentication
+ForceGGAuth=True
+
+#FloodProtection. time in ms
+EnableFloodProtection=True
+FastConnectionLimit=15
+NormalConnectionTime=700
+FastConnectionTime=350
+MaxConnectionPerIP=50

+ 5 - 0
L2_GameServer_T1/java/config/olympiad.properties

@@ -0,0 +1,5 @@
+CurrentCycle = 1
+Period = 0
+OlympiadEnd = 0
+ValdationEnd = 0
+NextWeeklyChange = 0

+ 267 - 0
L2_GameServer_T1/java/config/options.properties

@@ -0,0 +1,267 @@
+# =================================================================
+# Test server setting, shouldn't be touched for production game servers
+# =================================================================
+
+Debug = False
+Assert = False
+Developer = False
+AcceptGeoeditorConn = False
+# if true the server will be a test server (listed by testserver clients only)
+TestServer = False
+
+# =================================================================
+# Additional server settings, not required, can be left with defaults
+# =================================================================
+
+# If next switch is set to true every newly created character will have access level 200.
+EverybodyHasAdminRights = False
+
+# Setting for serverList
+# Displays [] in front of server name
+ServerListBrackets = False
+# Displays a clock next to the server name
+ServerListClock = False
+# If true, the server will be set as GM only
+ServerGMOnly = False
+
+# This is setting of experimental Client <--> Server Player coordinates synchronization,
+#   0 - no synchronization at all
+#   1 - parcial synchronization Client --> Server only * using this option it is difficult for players to bypass obstacles
+#   2 - parcial synchronization Server --> Client only
+#   3 - full synchronization Client <--> Server
+#  -1 - Old system: will synchronize Z only
+CoordSynchronize = -1
+
+# Zone Setting
+#   0 = Peace All the Time
+#   1 = PVP During Siege for siege participants
+#   2 = PVP All the Time
+ZoneTown = 0
+
+# Chat configuration
+# Global Chat - ON (=region), OFF, GM, GLOBAL
+GlobalChat = ON
+# Trade Chat - ON (=global, might be good for small servers), OFF, GM, LIMITED (=region)
+TradeChat = LIMITED
+
+# Player punishment for illegal acions
+#   1 - broadcast warning to gms only
+#   2 - kick player(default)
+#   3 - kick & ban player
+#   4 - jail player (define minutes of jail with param: 0 = infinite)
+DefaultPunish = 2
+DefaultPunishParam = 0
+
+# Bypass exploit protection
+BypassValidation = True
+
+# Enforce gameguard for clients
+#   GameGuardEnforce - enforces gameguard query on character login
+#   GameGuardProhibitAction - don't allow player to perform trade, talk with npc
+#     or move until gameguard reply is received.
+GameGuardEnforce = True
+GameGuardProhibitAction = True
+
+# Allow delete chars after nnn days, 0 = feature disabled
+DeleteCharAfterDays = 7
+
+
+# =================================================================
+# Server optimizations
+# =================================================================
+# === Flood Protector ===
+# set the initial size of the flood protector (should equal ~player count)
+FloodProtectorInitialSize = 50
+# === Items on ground management ===
+# Allow players to drop items on the ground
+AllowDiscardItem = True
+# delete from world dropped reward items after n seconds. 0 - disabled
+AutoDestroyDroppedItemAfter = 0
+# Time in secs after wich droped herb will be autodestroyed (default: 15 seconds)
+AutoDestroyHerbTime = 15
+# List of items that will not be destroyed (seperated by ",")
+# NOTE: Make sure the lists do NOT CONTAIN trailing spaces or spaces between the numbers!
+# items on this list will be protected regardless below options
+ListOfProtectedItems = 57,5575,6673
+
+# also delete from world misc. items dropped by players (all except equipable items)
+# NOTE: work only if AutoDestroyDroppedItemAfter >0
+DestroyPlayerDroppedItem = false
+# Destroy also equipable items (armor, weapon, jewelry)
+# NOTE: Work only if DestroyPlayerDroppedItem = true
+DestroyEquipableItem = false
+
+# save into DB droppped items for restoring after reboot
+SaveDroppedItem = false
+# Empty table after items are loaded into memory - safety setting
+# if server crash before saving items, on next start old items will be restored 
+# and players may already picked up some of them - so this will prevent duplicates
+EmptyDroppedItemTableAfterLoad = false
+# Time interval in minutes to save in DB items on ground, 0 to disable
+# NOTE: If SaveDroppedItemInterval is disabled items will be saved into DB only at server shutdown
+SaveDroppedItemInterval = 60
+# delete all saved items form DB On next start
+# NOTE: Work only if SaveDroppedItem = false
+ClearDroppedItemTable = false
+--------------------------------------------
+# delete invalid quest from player
+AutoDeleteInvalidQuestData = False
+# setting false can improve server performance on high rate servers
+PreciseDropCalculation = True
+# allows creating multiple nonstackable items at one time 
+MultipleItemDrop = True
+
+# Forces full item inventory packet to be sent for any item change
+# Note: This can increase network traffic 
+ForceInventoryUpdate = False
+
+# Set the html cache's lazy loading True or False
+# (Load html's into cache only on first time requested)
+LazyCache = True
+
+# Maximum range mobs can randomly go from spawn point
+MaxDriftRange = 200
+
+# Minimum and maximum variable in seconds for npc animation delay.
+# You must keep MinNPCAnimation <= MaxNPCAnimation.
+# "0" is default value.
+MinNPCAnimation = 10
+MaxNPCAnimation = 20
+MinMonsterAnimation = 5
+MaxMonsterAnimation = 20
+
+
+# Show "data/html/servnews.htm" when a character enters world.
+ShowServerNews = False
+
+# Show L2Monster level and aggro 
+ShowNpcLevel = False
+
+# Activate the position recorder
+# valid 3D points will be recorded and written to data/universe.txt on shutdown
+ActivatePositionRecorder = False
+
+
+# =================================================================
+# Additionnal features that can be enabled or disabled
+# =================================================================
+# If you are experiencing problems with Warehouse or Freight transactions,
+# feel free to disable them here. (They are both enabled by default).
+AllowWarehouse   = True
+# Enable Warehouse Cache - if WH is not used will server clear memory used by this WH
+WarehouseCache   = False
+# How long Warehouse should be store in Memory
+WarehouseCacheTime = 15
+AllowFreight     = True
+# If True player can try on weapon and armor in shop
+# Each Item tried cost WearPrice adena
+AllowWear        = True
+WearDelay        = 10
+WearPrice        = 10
+# =============== Test features ===============
+AllowLottery     = False
+AllowRace        = False
+AllowWater       = False
+# Enable pet for rent(wyvern&strider) from pet managers
+AllowRentPet     = False
+# Allow fishing disabled until all code uploaded
+AllowFishing     = True
+#Allow boat
+AllowBoat        = False
+#Allow cursed weapons
+AllowCursedWeapons = True
+#Allow Manor
+AllowManor		 = False
+#Allow WalkerNPC
+AllowNpcWalkers = False
+
+
+# Allow L2Walker client (Default False)
+# Can be True, False, GM
+AllowL2Walker      = False
+L2WalkerRevision   = 552
+# Ban account if account using l2walker and is not GM, AllowL2Walker = False
+AutobanL2WalkerAcc = False
+# Apply default punish if player buy items for zero adena
+OnlyGMItemsFree = True
+
+# =================================================================
+# Logging features
+# =================================================================
+# Logging ChatWindow
+LogChat = True
+# Logging Item handling NOTE: This can be very space consuming if enabled for all items.
+LogItems = False
+# Log GM actions
+GMAudit = False
+
+
+# =================================================================
+# Community board configuration
+# =================================================================
+# Type of the Community board
+#  - Full = new Community Board ( /!\ Experimental)
+#  - Old = old Community Bord
+#  - off =  no community Board
+CommunityType = old
+BBSDefault = _bbshome
+# show level of character to others in Community Board
+ShowLevelOnCommunityBoard = False
+ShowStatusOnCommunityBoard = True
+NamePageSizeOnCommunityBoard = 50
+NamePerRowOnCommunityBoard = 5
+
+
+# =================================================================
+# Threads configuration - Take care changing this
+# =================================================================
+
+ThreadPoolSizeEffects = 10
+ThreadPoolSizeGeneral = 13
+
+#Default 2
+UrgentPacketThreadCoreSize = 2
+#Default 4
+GeneralPacketThreadCoreSize = 4
+#Default 4
+GeneralThreadCoreSize = 4
+
+AiMaxThread = 6
+
+
+# Thread pools execution priority
+# default values are -1,0,1 (low/med/high pools)
+ExecutorPriLow = -1
+ExecutorPriMed = 0
+ExecutorPriHigh = 1
+
+#Packet LifeTime in miliseconds, 0 - disabled feature
+PacketLifeTime = 0
+
+#Grid options: Grids can now turn themselves on and off.  This also affects
+#the loading and processing of all AI tasks and (in the future) geodata 
+#within this grid.
+#Turn on for a grid with a person in it is immediate, but it then turns on 
+#the 8 neighboring grids based on the specified number of seconds.
+#Turn off for self and neighbors occures after the specified number of 
+#seconds have passed during which a grid has had no players in or in 
+#any of its neighbors.
+#The always on option allows to ignore all this and let all grids be active
+#at all times
+GridsAlwaysOn = False
+GridNeighborTurnOnTime = 30
+GridNeighborTurnOffTime = 300
+
+# GeoData options: 
+# 0 = GeoData and PathFinding OFF (default)
+# 1 = GeoData used to check Line Of Sight (LOS) targetting and 
+#     L2Playable movement. You need to download files for data/geodata folder.
+#     Monsters can pass walls but not aggro through them.
+# 2 = Full GeoData enabled, CURRENTLY FOR TESTING ONLY. Includes PathFinding
+#     (requires also /data/pathnode files) and all character moves go
+#     through geodata checks (if a mob passes a wall, pathing is wrong).
+GeoData = 0
+
+#[True]Loads GeoData buffer's content into physical memory.
+#[False] Does not necessarily imply that the GeoData buffer's content is not resident in physical memory.
+ForceGeodata = True

+ 169 - 0
L2_GameServer_T1/java/config/other.properties

@@ -0,0 +1,169 @@
+#Amount of adena that a new character is given
+#Default is 0
+StartingAdena = 0
+
+# movement speed for strider and wyvern
+WyvernSpeed = 100
+StriderSpeed = 80
+
+#Allow the wyvern manager located in every castle to train wyverns and striders from hatchlings
+AllowWyvernUpgrader = False
+
+# If True, when effects of the same stack group are used, lesser
+# effects will be canceled if stronger effects are used. New effects
+# that are added will be canceled if they are of lesser priority to the old one.
+# If False, they will not be canceled, and it will switch to them after the
+# stronger one runs out, if the lesser one is still in effect.
+CancelLesserEffect = True
+
+# If you wish to disable the use of guards agains agressive monsters.
+# Default is False.
+AllowGuards = False
+
+# If True, the following deep blue mobs' drop penalties will be applied:
+# - When player's level is 9 times greater than mob's level, drops got divided by 3
+# - After 9 lvl's of difference between player and deep blue mobs, drop chance is
+# lowered by 9% each lvl that difference increases. (9lvls diff = -9%; 10lvls diff = -18%; ...)
+# NOTE1: These rules are applied to both normal and sweep drops
+# NOTE2: These rules ignores the server's rate when drop is of adena type (Complies with retail server)
+UseDeepBlueDropRules = True
+
+# Inventory space limits
+MaximumSlotsForNoDwarf = 80
+MaximumSlotsForDwarf = 100
+MaximumSlotsForGMPlayer = 250
+
+# Warehouse space limits (Must be < 300 for prevent client crash)
+# Dwarfs will get bonus from lvl 60
+MaximumWarehouseSlotsForDwarf = 120
+MaximumWarehouseSlotsForNoDwarf = 100
+MaximumWarehouseSlotsForClan = 200
+MaximumFreightSlots = 20
+
+# % Chance of succeding to enchant an item when it has a chance of breaking
+EnchantChanceWeapon = 68
+EnchantChanceArmor = 52
+EnchantChanceJewelry = 54
+# Enchant limit [default = 0 (unlimited)]
+EnchantMaxWeapon = 0
+EnchantMaxArmor = 0
+EnchantMaxJewelry = 0
+# if EnchantSafeMax is set to for ex '8' the item will be safly enchanted to '8'
+# regardless of enchant chance(default = 3 for EnchantSafeMax and default = 4 for EnchantSafeMaxFull)
+# EnchantSafeMaxFull is for full body armor (upper and lower)
+# SHOULD BE > 0
+EnchantSafeMax = 3
+EnchantSafeMaxFull = 4
+
+# % regeneration of normal regeneration speed
+HpRegenMultiplier = 100
+MpRegenMultiplier = 100
+CpRegenMultiplier = 100
+
+# % regeneration and defence for RaidBoss and their minions
+RaidHpRegenMultiplier = 100
+RaidMpRegenMultiplier = 100
+RaidDefenceMultiplier = 300
+
+#Configure Minimum and Maximum multiplier time between RaidBoss respawn.
+#By Default 12Hours*1.0 for Minimum Time and 24Hours*1.0 for Maximum Time.
+RaidMinRespawnMultiplier = 1.0
+RaidMaxRespawnMultiplier = 1.0
+
+# Minions respawn timer 300000 = 5 mins
+RaidMinionRespawnTime = 300000
+
+# Unstuck interval, seconds, default is 300 sec.
+UnstuckInterval = 300
+
+# Player Protection after teleporting or login in seconds, 0 for disabled
+PlayerSpawnProtection = 0
+
+# Player Protection from (agro) mobs after getting up from fake death; in seconds, 0 for disabled
+PlayerFakeDeathUpProtection = 0
+# PARTY XP DISTRIBUTION
+# Set the first option here to one of the (auto, percentage, level, none).
+# With "auto method" member is cut from Exp/SP distribution when his share is lower
+# then party bonus acquired for him (30% for 2 member party)
+# In that case he will not receive any Exp/SP from party and is not counted for party bonus
+# The second option takes effect when "percentage" method is choosen. Don't use high values for this!
+# The third option takes effect when "level" method is choosen. Don't use low values for this!
+# If you don't want to have a cutoff point for party members' XP distribution,
+# then just set the first option to "none". Defaults are: percentage , 3.0 , 30 ; respectively.
+PartyXpCutoffMethod = auto
+PartyXpCutoffPercent = 3.0
+PartyXpCutoffLevel = 30
+
+# Amount of HP, MP, and CP is restored
+# Values are in percent of max
+RespawnRestoreCP = 0
+RespawnRestoreHP = 70
+RespawnRestoreMP = 70
+
+# Allow random respawning in towns, based on a maximum random offset
+# from the base respawn co-ordinates.
+RespawnRandomInTown = True
+RespawnRandomMaxOffset = 20
+
+# Maximum number of allowed slots for Private Stores (sell/buy) for dwarves and for all other races
+# Normally, dwarves get 5 slots for pvt stores, while other races get only 4
+MaxPvtStoreSlotsDwarf = 5
+MaxPvtStoreSlotsOther = 4
+
+# Store buffs/debuffs other effects on user logout?
+StoreSkillCooltime=True
+
+# List of pet rent (wyvern,strider). etc: 111,222,333
+ListPetRentNpc = 30827
+
+# Announce to players the location of the Mammon NPCs during Seal Validation.
+# Default is False.
+AnnounceMammonSpawn = False
+
+# Alt privileges for GMs based on command privileges
+AltPrivilegesAdmin = False
+AltPrivilegesSecureCheck = True
+AltPrivilegesDefaultLevel = 100
+
+# Allow different name color for GM and Admin characters.
+GMNameColorEnabled = True
+# Color to use for Admin names, if enabled. (access level 100+).
+# (Must be in hex BGR format: eg. 00FF00 = Green)
+AdminNameColor = 00FF00
+# Color to use for GM names, if enabled. (access level 75+).
+# (Must be in hex BGR format: eg. FFFF00 = Yellow)
+GMNameColor = FFFF00
+
+# Enable GMs to have the glowing aura of a Hero character.
+GMHeroAura = False
+
+# Auto set invulnerable status to a GM on login.
+GMStartupInvulnerable = False
+# Auto set invisible status to a GM on login.
+GMStartupInvisible = False
+# Auto block private messages to a GM on login.
+GMStartupSilence = False
+# Auto list GMs in GM list (/gmlist) on login.
+GMStartupAutoList = True
+# The way //admin panel looks can be "modern" or "classic" 
+# (default is modern while classic provides more compatibility) 
+GMAdminMenuStyle = modern
+# Enable players to send in-game petitions. 
+PetitioningAllowed = True
+# Total number of petitions to allow per player, per session.
+MaxPetitionsPerPlayer = 5
+# Total number of petitions pending, if more are submitted they will be rejected.
+MaxPetitionsPending = 25
+
+#---------------------------------------------
+# Jail configuration
+#---------------------------------------------
+# Jail is a PvP zone
+JailIsPvp = True
+# Disable all chat in jail (except normal one)
+JailDisableChat = True
+
+#------------------------------------------
+# Death Penalty chance if killed by mob (%)
+#------------------------------------------
+DeathPenaltyChance = 20

+ 31 - 0
L2_GameServer_T1/java/config/pvp.properties

@@ -0,0 +1,31 @@
+# ==================================================================
+# 		-- KARMA VARS --
+# ==================================================================
+
+# Karma gain/loss
+MinKarma = 240
+MaxKarma = 10000
+# the number to divide the xp recieved by, to calculate karma lost on xp gain/lost
+XPDivider = 260
+# The Minimum Karma lost if 0 karma is to be removed
+BaseKarmaLost = 0
+
+# Equipment loss
+CanGMDropEquipment = False
+
+# NOTE: Make sure the lists do NOT CONTAIN trailing spaces or spaces between the numbers!
+# List of pet items we cannot drop
+ListOfPetItems = 2375,3500,3501,3502,4422,4423,4424,4425,6648,6649,6650
+# Lists of items which should NEVER be dropped (note, adena will never be dropped) whether on this list or not
+ListOfNonDroppableItems = 57,1147,425,1146,461,10,2368,7,6,2370,2369,6842,6611,6612,6613,6614,6615,6616,6617,6618,6619,6620,6621,7694,8181,5575,7694
+
+# item drop related min/max
+MinimumPKRequiredToDrop = 5
+
+# Should we award a pvp point for killing a player with karma?
+AwardPKKillPVPPoint = True
+
+# Length one stays in PvP mode after hitting an inocent (in ms)
+PvPVsNormalTime = 40000
+# Length one stays in PvP mode after hitting a purple player (in ms)
+PvPVsPvPTime = 20000

+ 53 - 0
L2_GameServer_T1/java/config/rates.properties

@@ -0,0 +1,53 @@
+# =================================================================
+# NORMAL RATES
+# =================================================================
+# Rate control, float values
+RateXp = 1.
+RateSp = 1.
+RatePartyXp = 1.
+RatePartySp = 1.
+RateDropAdena = 1.
+RateConsumableCost = 1.
+RateDropItems = 1.
+RateDropSpoil = 1.
+RateDropManor = 1
+# NOTE: this need quests to be rewritten in dp in order to work
+RateDropQuest = 1.
+RateQuestsReward = 1.
+RateKarmaExpLost = 1
+RateSiegeGuardsPrice = 1
+
+# Player Drop Rate control, values are the percent values
+PlayerDropLimit = 0
+PlayerRateDrop = 0
+PlayerRateDropItem = 0
+PlayerRateDropEquip = 0
+PlayerRateDropEquipWeapon = 0
+
+# Karma Drop Rate control, values are the percent values
+KarmaDropLimit = 10
+KarmaRateDrop = 40
+KarmaRateDropItem = 50
+KarmaRateDropEquip = 40
+KarmaRateDropEquipWeapon = 10
+
+# Multiplier for pet rate control (with lower values pet will grow slower)
+PetXpRate = 1.
+# Pet Food Rate control, 1 food = PetFoodRate
+PetFoodRate = 1
+# SinEater exp rate 
+SinEaterXpRate =1. 
+
+# =================================================================
+# HERBS RATES
+# =================================================================
+# Herb of Power, Herb of Magic, Herb of Atk. Spd., Herb of Casting Spd., Herb of Critical Attack, Herb of Speed
+RateCommonHerbs = 15.
+# Herb of Life, Herb of Mana
+RateHpMpHerbs = 10.
+# Greater herb of Life, Greater Herb of Mana
+RateGreaterHerbs = 4.
+# Superior Herb of Life, Superior Herb of Mana
+RateSuperiorHerbs = 0.8
+# Herb of Warrior, Herb of Mystic, Herb of Recovery
+RateSpecialHerbs = 0.2

+ 71 - 0
L2_GameServer_T1/java/config/server.properties

@@ -0,0 +1,71 @@
+# This is the server configuration file. Here you can set up the connection for your server.
+# Usually you have to change the ExternalHostname option to
+# - 127.0.0.1 (if you want to play alone / testing purpose)
+# - LAN IP* (if you want to play from another computer in the network)
+# - WAN IP** (if you want to play with friends over internet)
+# - Questions? => http://l2jserver.com
+#
+# * = If you want to get your LAN IP, simply choose "Start" => "Run..." then type "cmd" => "ipconfig"
+# **= If you want to get you WAN IP, visit http://www.whatismyip.com
+# ===================================================================================================
+ 
+# ================================================================
+# General server setting !!! REQUIRED to configure to everyone !!!
+# ================================================================
+
+# Bind ip of the gameserver, use * to bind on all available IPs
+GameserverHostname=*
+GameserverPort=7777
+
+# This is transmitted to the clients connecting from an external network, so it has to be a public IP or resolvable hostname
+# If this ip is resolvable by Login just leave *
+ExternalHostname=*
+
+# This is transmitted to the client from the same network, so it has to be a local IP or resolvable hostname
+# If this ip is resolvable by Login just leave *
+InternalHostname=*
+
+# The Loginserver host and port
+LoginPort=9014
+LoginHost=127.0.0.1
+
+# This is the server id that the gameserver will request (i.e. 1 is Bartz)
+RequestServerID = 1
+# If set to true, the login will give an other id to the server  if the requested id is allready reserved
+AcceptAlternateID = True
+
+# Database info
+Driver=com.mysql.jdbc.Driver
+#Driver=org.hsqldb.jdbcDriver
+#Driver=com.microsoft.sqlserver.jdbc.SQLServerDriver
+URL=jdbc:mysql://localhost/l2jdb
+#URL=jdbc:hsqldb:hsql://localhost/l2jdb
+#URL=jdbc:sqlserver://localhost/database=l2jdb/user=sa/password=
+Login=root
+Password=
+MaximumDbConnections=100
+
+# Datapack root directory, defaults to current directory from which the server is started
+# DatapackRoot = C:/Work/tmp/DataPack
+
+# Define character name template
+# Example to use only : CnameTemplate=[A-Z][a-z]{3,3}[A-Za-z0-9]*
+# will allow names with first capital letter, next three small letters,
+# and any (capital or not) letter or number, like ZbigN1eW
+# Most rational to have CnameTemplate=[A-Z][a-z]*
+# meaning names only of letters with first one capital, like Zbigniew
+# Default .* - any namy of any symbols
+CnameTemplate=.*
+PetNameTemplate=.*
+
+# Maximum number of chars per account - Default 7 (0 = unlimited [7 is the client limit])
+CharMaxNumber = 7
+
+# Define how many players are allowed to play simultaneously on your server.
+MaximumOnlineUsers=100
+
+
+# Minimum and maximum protocol revision that server allow to connect.
+# You must keep MinProtocolRevision <= MaxProtocolRevision.
+MinProtocolRevision = 828
+MaxProtocolRevision = 828

+ 59 - 0
L2_GameServer_T1/java/config/sevensigns.properties

@@ -0,0 +1,59 @@
+#-------------------------------------
+# Seven Signs Configuration File
+# Adjusting this file will effect the way your seven signs runs
+# Do so only if you want to run diffrent to retail
+#-------------------------------------
+
+# Sign up Rules
+# -----------------------------------------
+
+# Require a player to be in a castle/alliance-owning clan to be able to sign for Dawn.
+AltRequireCastleForDawn = False
+
+# Determines whether castle ownership is determined by clan or by alliance.
+# Default is by alliance, as on official servers.
+AltRequireClanCastle = False
+
+# -----------------------------------------
+# Festival Rules.
+# -----------------------------------------
+
+# Minimum Players for participate in SevenSigns Festival.
+#   Default : 5
+AltFestivalMinPlayer = 5
+
+# Maximum contribution per player during festival
+#   /!\ This value is NOT impacted by server drop rate. 
+AltMaxPlayerContrib = 1000000
+
+# Festival Manager Start time.
+#   Default : 2 minutes
+AltFestivalManagerStart = 120000
+
+# Festival Length.
+#   Default : 18 minutes
+AltFestivalLength = 1080000
+
+# Festival Cycle Length.
+#   Default : 38 Minutes (20 minutes wait time, + Festival time) 
+AltFestivalCycleLength = 2280000
+
+# At what point the first festival spawn occures.
+#   Default : 2 minutes
+AltFestivalFirstSpawn = 120000
+
+# At what Point the first festival swarm occures.
+#   Default : 5 minutes
+AltFestivalFirstSwarm = 300000
+
+# At what Point the Second Festival spawn occures.
+#   Default : 9 minutes
+AltFestivalSecondSpawn = 540000
+
+# At what Point the Second Festival Swarm occures.
+#   Default : 12 minutes
+AltFestivalSecondSwarm = 720000
+
+# At what point the Chests Spawn in.
+#   Default : 15 minutes
+AltFestivalChestspawn = 900000

+ 131 - 0
L2_GameServer_T1/java/config/siege.properties

@@ -0,0 +1,131 @@
+#Quick hack up Siege data file, plz dont use any spaces.
+#Rewards are given every 2 hours to all castle owner clans warehouses
+
+#Length of siege before the count down (in minutes)
+SiegeLength=120
+
+#Count down length, best to use a multiple of 5 (in minutes)
+CountDownLength=10
+
+#Max no. flags per clan
+MaxFlags=1
+
+#Minimum level to register
+SiegeClanMinLevel=4
+
+#Max no. of clans that can register on each side
+AttackerMaxClans=500
+DefenderMaxClans=500
+
+#Respawn times in ms
+DefenderRespawn=20000
+AttackerRespawn=0
+
+#Respawn time penalty for loosing each Control tower
+CTLossPenalty=20000
+
+#Caste Artefacts and Control Towers spawns
+#
+#Control Towers syntax:  NameControlTowerN=x,y,z,npc_id,hp
+# Name - castle name
+# N - number
+# x,y,z - coords
+# npc_id - id of template
+# hp - maximum health
+#
+#Artefacts syntax:  NameArtefactN=x,y,z,heading,npc_id
+# Name - castle name
+# N - number
+# x,y,z - coords
+# heading
+# npc_id - id of template
+
+#-------------------------------------------------------------
+# Gludio
+#-------------------------------------------------------------
+
+GludioControlTower1=-18134,109785,-2683,13002,8000
+GludioControlTower2=-18137,108583,-2379,13002,20000
+GludioControlTower3=-18061,107294,-2409,13002,8000
+GludioControlTower4=-18359,112879,-2409,13002,8000
+GludioArtefact1=-18120,107984,-2483,16384,35063
+
+#-------------------------------------------------------------
+# Giran
+#-------------------------------------------------------------
+GiranControlTower1=118623,145150,-2476,13002,10000
+GiranControlTower2=117339,145051,-2446,13002,30000
+GiranControlTower3=116116,145016,-2750,13002,10000
+GiranControlTower4=113049,144849,-2476,13002,10000
+GiranArtefact1=117939,145090,-2550,32768,35147
+
+#-------------------------------------------------------------
+# Dion
+#-------------------------------------------------------------
+DionControlTower1=22158,161167,-2573,13002,8000
+DionControlTower2=22138,159901,-2877,13002,20000
+DionControlTower3=22027,162449,-2603,13002,80000
+DionControlTower4=22319,156863,-2603,13002,8000
+DionArtefact1=22081,161771,-2677,49017,35105
+
+#-------------------------------------------------------------
+# Oren
+#-------------------------------------------------------------
+OrenControlTower1=83416,37164,-2173,13002,10000
+OrenControlTower2=82129,37131,-2477,13002,30000
+OrenControlTower3=84709,37234,-2203,13002,10000
+OrenControlTower4=79103,36942,-2203,13002,10000
+OrenArtefact1=84014,37184,-2277,16384,35189
+
+#-------------------------------------------------------------
+# Aden
+#-------------------------------------------------------------
+AdenControlTower1=147455,5624,-911,13002,6000
+AdenControlTower2=147460,1303,-176,13002,6000
+AdenControlTower3=146158,6929,-426,13002,6000
+AdenControlTower4=148755,6930,-426,13002,6000
+AdenControlTower5=148775,2351,-426,13002,6000
+AdenControlTower6=146137,2351,-426,13002,6000
+AdenControlTower7=144954,1603,-494,13002,6000
+AdenControlTower8=149976,1585,-494,13002,6000
+AdenArtefact1=147465,1537,-373,16384,35233
+
+#-------------------------------------------------------------
+# Innadril
+#-------------------------------------------------------------
+InnadrilControlTower1=116062,248649,-973,13002,6000
+InnadrilControlTower2=116037,249948,-669,13002,6000
+InnadrilControlTower3=115977,251223,-699,13002,6000
+InnadrilControlTower4=116261,245621,-699,13002,6000
+InnadrilArtefact1=116031,250555,-798,49200,35279
+
+#-------------------------------------------------------------
+# Goddard
+#-------------------------------------------------------------
+GoddardControlTower1=147456,-46029,-1360,13002,6000
+GoddardControlTower2=150183,-48201,-1744,13002,6000
+GoddardControlTower3=144741,-48188,-1744,13002,6000
+GoddardControlTower4=147477,-48516,-505,13002,6000
+GoddardArtefact1=146601,-50441,-1505,32768,35322
+GoddardArtefact2=148353,-50457,-1505,0,35323
+
+#-------------------------------------------------------------
+# Rune
+#-------------------------------------------------------------
+RuneControlTower1=18260,-49161,-571,13002,6000
+RuneControlTower2=16690,-50330,-641,13002,6000
+RuneControlTower3=16727,-47952,-641,13002,6000
+RuneControlTower4=14796,-47041,1027,13002,6000
+RuneControlTower5=14822,-51282,1027,13002,6000
+RuneControlTower6=12259,-47510,1295,13002,6000
+RuneArtefact1=9126,-49161,1094,64270,35469
+
+#-------------------------------------------------------------
+# Schuttgart
+#-------------------------------------------------------------
+SchuttgartControlTower1=77561,-150087,371,13002,6000
+SchuttgartControlTower2=80306,-152257,-12,13002,6000
+SchuttgartControlTower3=74862,-152162,-12,13002,6000
+SchuttgartControlTower4=77568,-152541,1226,13002,6000
+SchuttgartArtefact1=76668,-154520,226,0,35515
+SchuttgartArtefact2=78446,-154524,227,0,35514

+ 15 - 0
L2_GameServer_T1/java/config/telnet.properties

@@ -0,0 +1,15 @@
+#Telnet is disabled by default.
+EnableTelnet = false
+
+#This is the port telnet server will bind to
+StatusPort = 12345
+
+#If the following is not set, a random password is generated on server startup.
+#StatusPW = somePass
+
+#This list can contain IPs or Hosts of clients you wish to allow.
+#Hosts must be resolvable to an IP.
+#The format is as follows:
+#ListOfHosts = 0.0.0.0,host,0.0.0.1,host2,host3,host4,0.0.0.3
+#Make sure there are no spaces between hosts/ips
+ListOfHosts = 127.0.0.1,localhost

+ 7 - 0
L2_GameServer_T1/java/console.cfg

@@ -0,0 +1,7 @@
+# Default global logging level.
+# This specifies which kinds of events are logged across
+# all loggers.  For any given facility this global level
+# can be overriden by a facility specific level
+# Note that the ConsoleHandler also has a separate level
+# setting to limit messages printed to the console.
+.level=OFF

+ 104 - 0
L2_GameServer_T1/java/log.cfg

@@ -0,0 +1,104 @@
+############################################################
+#  	Global properties
+############################################################
+
+# "handlers" specifies a comma separated list of log Handler 
+# classes.  These handlers will be installed during VM startup.
+# Note that these classes must be on the system classpath.
+# By default we only configure a ConsoleHandler, which will only
+# show messages at the INFO and above levels.
+#handlers= java.util.logging.ConsoleHandler
+
+# To also add the FileHandler, use the following line instead.
+handlers = java.util.logging.FileHandler,java.util.logging.ConsoleHandler,\
+           net.sf.l2j.ErrorLogHandler
+chat.handlers = net.sf.l2j.ChatLogHandler
+chat.useParentHandlers = false
+gmaudit.handlers = net.sf.l2j.GMAuditLogHandler
+gmaudit.useParentHandlers = false
+item.handlers = net.sf.l2j.ItemLogHandler
+item.useParentHandlers = false
+audit.handlers = net.sf.l2j.AuditLogHandler
+audit.useParentHandlers = false
+
+
+# Default global logging level.
+# This specifies which kinds of events are logged across
+# all loggers.  For any given facility this global level
+# can be overriden by a facility specific level
+# Note that the ConsoleHandler also has a separate level
+# setting to limit messages printed to the console.
+.level= CONFIG
+
+############################################################
+# Handler specific properties.
+# Describes specific configuration info for Handlers.
+############################################################
+
+# default file output is in user's home directory.
+java.util.logging.FileHandler.pattern = log/java%u.log
+java.util.logging.FileHandler.limit = 500000
+java.util.logging.FileHandler.count = 5
+java.util.logging.FileHandler.formatter = net.sf.l2j.FileLogFormatter
+java.util.logging.FileHandler.level = CONFIG
+
+# Limit the message that are printed on the console to INFO and above.
+java.util.logging.ConsoleHandler.level = FINER
+java.util.logging.ConsoleHandler.formatter = net.sf.l2j.ConsoleLogFormatter
+
+# log errors (exceptions)
+net.sf.l2j.ErrorLogHandler.pattern = log/error%u.log
+net.sf.l2j.ErrorLogHandler.count = 5
+net.sf.l2j.ErrorLogHandler.formatter = java.util.logging.SimpleFormatter
+net.sf.l2j.ErrorLogHandler.filter = net.sf.l2j.ErrorFilter
+net.sf.l2j.ErrorLogHandler.level = CONFIG
+
+# log chats
+net.sf.l2j.ChatLogHandler.pattern = log/chat.log
+net.sf.l2j.ChatLogHandler.formatter = net.sf.l2j.ChatLogFormatter
+net.sf.l2j.ChatLogHandler.filter = net.sf.l2j.ChatFilter
+net.sf.l2j.ChatLogHandler.append = true
+net.sf.l2j.ChatLogHandler.level = INFO
+
+# log GM Audit
+net.sf.l2j.GMAuditLogHandler.pattern = log/gmaudit.log
+net.sf.l2j.GMAuditLogHandler.formatter = net.sf.l2j.GMAuditFormatter
+net.sf.l2j.GMAuditLogHandler.filter = net.sf.l2j.GMAuditFilter
+net.sf.l2j.GMAuditLogHandler.append = true
+net.sf.l2j.GMAuditLogHandler.level = INFO
+
+# log items
+net.sf.l2j.ItemLogHandler.pattern = log/item.log
+net.sf.l2j.ItemLogHandler.formatter = net.sf.l2j.ItemLogFormatter
+net.sf.l2j.ItemLogHandler.filter = net.sf.l2j.ItemFilter
+net.sf.l2j.ItemLogHandler.append = true
+net.sf.l2j.ItemLogHandler.level = INFO
+
+# audit
+net.sf.l2j.AuditLogHandler.pattern = log/audit.log
+net.sf.l2j.AuditLogHandler.formatter = net.sf.l2j.AuditFormatter
+net.sf.l2j.AuditLogHandler.filter = net.sf.l2j.AuditFilter
+net.sf.l2j.AuditLogHandler.append = true
+net.sf.l2j.AuditLogHandler.level = INFO
+
+
+############################################################
+# Facility specific properties.
+# Provides extra control for each logger.
+############################################################
+
+# For example, set the com.xyz.foo logger to only log SEVERE
+# messages:
+net.sf.l2j.gameserver.level = CONFIG
+net.sf.l2j.loginserver.level = CONFIG
+net.sf.l2j.gameserver.Connection.level = CONFIG
+net.sf.l2j.gameserver.serverpackets.level = FINER
+net.sf.l2j.gameserver.clientpackets.level = FINER
+net.sf.l2j.gameserver.model.L2Character.level = FINER
+net.sf.l2j.gameserver.skills.SkillsEngine.level = WARNING
+
+# Alt Privileges Administration
+AltPrivilegesAdmin.pattern = log/admin-commands.log
+AltPrivilegesAdmin.formatter = net.sf.l2j.FileLogFormatter
+AltPrivilegesAdmin.append = true
+AltPrivilegesAdmin.level = CONFIG

+ 32 - 0
L2_GameServer_T1/java/net/sf/l2j/AuditFilter.java

@@ -0,0 +1,32 @@
+/* This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+package net.sf.l2j;
+
+import java.util.logging.Filter;
+import java.util.logging.LogRecord;
+
+/**
+ * @author zabbix
+ * Lets drink to code!
+ */
+public class AuditFilter implements Filter
+{
+	public boolean isLoggable(LogRecord record) {
+		return record.getLoggerName().equalsIgnoreCase("audit");
+	}
+}

+ 56 - 0
L2_GameServer_T1/java/net/sf/l2j/AuditFormatter.java

@@ -0,0 +1,56 @@
+/* This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+package net.sf.l2j;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.logging.Formatter;
+import java.util.logging.LogRecord;
+
+import javolution.text.TextBuilder;
+
+/**
+ * @author zabbix
+ * Lets drink to code!
+ */
+public class AuditFormatter extends Formatter
+{
+	private static final String CRLF = "\r\n";
+	private SimpleDateFormat dateFmt = new SimpleDateFormat("dd MMM H:mm:ss");
+
+	@Override
+	public String format(LogRecord record)
+	{
+        TextBuilder output = new TextBuilder();
+		output.append('[');
+		output.append(dateFmt.format(new Date(record.getMillis())));
+		output.append(']');
+		output.append(' ');
+		output.append(record.getMessage());
+		for (Object p : record.getParameters())
+		{
+			if (p == null) continue;
+			output.append(',');
+			output.append(' ');
+			output.append(p.toString());
+		}
+		output.append(CRLF);
+
+		return output.toString();
+	}
+}

+ 33 - 0
L2_GameServer_T1/java/net/sf/l2j/AuditLogHandler.java

@@ -0,0 +1,33 @@
+/* This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+package net.sf.l2j;
+
+import java.io.IOException;
+import java.util.logging.FileHandler;
+
+/**
+ * @author zabbix
+ * Lets drink to code!
+ */
+public class AuditLogHandler extends FileHandler
+{
+	public AuditLogHandler() throws IOException, SecurityException
+	{
+		super();
+	}
+}

+ 1328 - 0
L2_GameServer_T1/java/net/sf/l2j/Base64.java

@@ -0,0 +1,1328 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+package net.sf.l2j;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+
+/**
+ * Encodes and decodes to and from Base64 notation.
+ *
+ * The source is based on the work of Robert Harder
+ *
+ * <p>
+ * I am placing this code in the Public Domain. Do with it as you will.
+ * This software comes with no guarantees or warranties but with
+ * plenty of well-wishing instead!
+ * Please visit <a href="http://iharder.net/xmlizable">http://iharder.net/base64</a>
+ * periodically to check for updates or to contribute improvements.
+ * </p>
+ *
+ * @author Robert Harder
+ * @author rob@iharder.net
+ * @version 2.0
+ */
+public class Base64
+{
+
+    /* ********  P U B L I C   F I E L D S  ******** */
+
+    /** No options specified. Value is zero. */
+    public final static int NO_OPTIONS = 0;
+
+    /** Specify encoding. */
+    public final static int ENCODE = 1;
+
+    /** Specify decoding. */
+    public final static int DECODE = 0;
+
+    /** Specify that data should be gzip-compressed. */
+    public final static int GZIP = 2;
+
+    /** Don't break lines when encoding (violates strict Base64 specification) */
+    public final static int DONT_BREAK_LINES = 8;
+
+    /* ********  P R I V A T E   F I E L D S  ******** */
+
+    /** Maximum line length (76) of Base64 output. */
+    private final static int MAX_LINE_LENGTH = 76;
+
+    /** The equals sign (=) as a byte. */
+    private final static byte EQUALS_SIGN = (byte) '=';
+
+    /** The new line character (\n) as a byte. */
+    private final static byte NEW_LINE = (byte) '\n';
+
+    /** Preferred encoding. */
+    private final static String PREFERRED_ENCODING = "UTF-8";
+
+    /** The 64 valid Base64 values. */
+    private final static byte[] ALPHABET;
+    private final static byte[] _NATIVE_ALPHABET = /* May be something funny like EBCDIC */
+    {(byte) 'A', (byte) 'B', (byte) 'C', (byte) 'D', (byte) 'E', (byte) 'F', (byte) 'G', (byte) 'H',
+     (byte) 'I', (byte) 'J', (byte) 'K', (byte) 'L', (byte) 'M', (byte) 'N', (byte) 'O', (byte) 'P',
+     (byte) 'Q', (byte) 'R', (byte) 'S', (byte) 'T', (byte) 'U', (byte) 'V', (byte) 'W', (byte) 'X',
+     (byte) 'Y', (byte) 'Z', (byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e', (byte) 'f',
+     (byte) 'g', (byte) 'h', (byte) 'i', (byte) 'j', (byte) 'k', (byte) 'l', (byte) 'm', (byte) 'n',
+     (byte) 'o', (byte) 'p', (byte) 'q', (byte) 'r', (byte) 's', (byte) 't', (byte) 'u', (byte) 'v',
+     (byte) 'w', (byte) 'x', (byte) 'y', (byte) 'z', (byte) '0', (byte) '1', (byte) '2', (byte) '3',
+     (byte) '4', (byte) '5', (byte) '6', (byte) '7', (byte) '8', (byte) '9', (byte) '+', (byte) '/'};
+
+    public static void main(String[] args) throws IOException
+    {
+        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
+        System.out.print("Enter String to encode: ");
+        System.out.println(Base64.encodeBytes(bf.readLine().getBytes()));
+    }
+
+    /** Determine which ALPHABET to use. */
+    static
+    {
+        byte[] __bytes;
+        try
+        {
+            __bytes = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".getBytes(PREFERRED_ENCODING);
+        } // end try
+        catch (java.io.UnsupportedEncodingException use)
+        {
+            __bytes = _NATIVE_ALPHABET; // Fall back to native encoding
+        } // end catch
+        ALPHABET = __bytes;
+    } // end static
+
+    /**
+     * Translates a Base64 value to either its 6-bit reconstruction value
+     * or a negative number indicating some other meaning.
+     **/
+    final static byte[] DECODABET = {-9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal  0 -  8
+                                     -5, -5, // Whitespace: Tab and Linefeed
+                                     -9, -9, // Decimal 11 - 12
+                                     -5, // Whitespace: Carriage Return
+                                     -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 14 - 26
+                                     -9, -9, -9, -9, -9, // Decimal 27 - 31
+                                     -5, // Whitespace: Space
+                                     -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 33 - 42
+                                     62, // Plus sign at decimal 43
+                                     -9, -9, -9, // Decimal 44 - 46
+                                     63, // Slash at decimal 47
+                                     52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // Numbers zero through nine
+                                     -9, -9, -9, // Decimal 58 - 60
+                                     -1, // Equals sign at decimal 61
+                                     -9, -9, -9, // Decimal 62 - 64
+                                     0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, // Letters 'A' through 'N'
+                                     14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // Letters 'O' through 'Z'
+                                     -9, -9, -9, -9, -9, -9, // Decimal 91 - 96
+                                     26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, // Letters 'a' through 'm'
+                                     39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // Letters 'n' through 'z'
+                                     -9, -9, -9, -9 // Decimal 123 - 126
+    /*,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,     // Decimal 127 - 139
+     -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,     // Decimal 140 - 152
+     -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,     // Decimal 153 - 165
+     -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,     // Decimal 166 - 178
+     -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,     // Decimal 179 - 191
+     -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,     // Decimal 192 - 204
+     -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,     // Decimal 205 - 217
+     -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,     // Decimal 218 - 230
+     -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,     // Decimal 231 - 243
+     -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9         // Decimal 244 - 255 */
+    };
+
+    //private final static byte BAD_ENCODING    = -9; // Indicates error in encoding
+    private final static byte WHITE_SPACE_ENC = -5; // Indicates white space in encoding
+    private final static byte EQUALS_SIGN_ENC = -1; // Indicates equals sign in encoding
+
+    /** Defeats instantiation. */
+    private Base64()
+    {
+    }
+
+    /* ********  E N C O D I N G   M E T H O D S  ******** */
+
+    //    /**
+    //     * Encodes the first three bytes of array <var>threeBytes</var>
+    //     * and returns a four-byte array in Base64 notation.
+    //     *
+    //     * @param threeBytes the array to convert
+    //     * @return four byte array in Base64 notation.
+    //     * @since 1.3
+    //     */
+    //    private static byte[] encode3to4( byte[] threeBytes )
+    //    {
+    //        return encode3to4( threeBytes, 3 );
+    //    }   // end encodeToBytes
+
+    //    /**
+    //     * Encodes up to the first three bytes of array <var>threeBytes</var>
+    //     * and returns a four-byte array in Base64 notation.
+    //     * The actual number of significant bytes in your array is
+    //     * given by <var>numSigBytes</var>.
+    //     * The array <var>threeBytes</var> needs only be as big as
+    //     * <var>numSigBytes</var>.
+    //     *
+    //     * @param threeBytes the array to convert
+    //     * @param numSigBytes the number of significant bytes in your array
+    //     * @return four byte array in Base64 notation.
+    //     * @since 1.3
+    //     */
+    //    private static byte[] encode3to4( byte[] threeBytes, int numSigBytes )
+    //    {
+    //        byte[] dest = new byte[4];
+    //        encode3to4( threeBytes, 0, numSigBytes, dest, 0 );
+    //        return dest;
+    //    }
+    /**
+     * Encodes up to the first three bytes of array <var>threeBytes</var>
+     * and returns a four-byte array in Base64 notation.
+     * The actual number of significant bytes in your array is
+     * given by <var>numSigBytes</var>.
+     * The array <var>threeBytes</var> needs only be as big as
+     * <var>numSigBytes</var>.
+     * Code can reuse a byte array by passing a four-byte array as <var>b4</var>.
+     *
+     * @param b4 A reusable byte array to reduce array instantiation
+     * @param threeBytes the array to convert
+     * @param numSigBytes the number of significant bytes in your array
+     * @return four byte array in Base64 notation.
+     * @since 1.5.1
+     */
+    static byte[] encode3to4(byte[] b4, byte[] threeBytes, int numSigBytes)
+    {
+        encode3to4(threeBytes, 0, numSigBytes, b4, 0);
+        return b4;
+    } // end encode3to4
+
+    /**
+     * Encodes up to three bytes of the array <var>source</var>
+     * and writes the resulting four Base64 bytes to <var>destination</var>.
+     * The source and destination arrays can be manipulated
+     * anywhere along their length by specifying
+     * <var>srcOffset</var> and <var>destOffset</var>.
+     * This method does not check to make sure your arrays
+     * are large enough to accomodate <var>srcOffset</var> + 3 for
+     * the <var>source</var> array or <var>destOffset</var> + 4 for
+     * the <var>destination</var> array.
+     * The actual number of significant bytes in your array is
+     * given by <var>numSigBytes</var>.
+     *
+     * @param source the array to convert
+     * @param srcOffset the index where conversion begins
+     * @param numSigBytes the number of significant bytes in your array
+     * @param destination the array to hold the conversion
+     * @param destOffset the index where output will be put
+     * @return the <var>destination</var> array
+     * @since 1.3
+     */
+    static byte[] encode3to4(byte[] source, int srcOffset, int numSigBytes, byte[] destination,
+                             int destOffset)
+    {
+        //           1         2         3
+        // 01234567890123456789012345678901 Bit position
+        // --------000000001111111122222222 Array position from threeBytes
+        // --------|    ||    ||    ||    | Six bit groups to index ALPHABET
+        //          >>18  >>12  >> 6  >> 0  Right shift necessary
+        //                0x3f  0x3f  0x3f  Additional AND
+
+        // Create buffer with zero-padding if there are only one or two
+        // significant bytes passed in the array.
+        // We have to shift left 24 in order to flush out the 1's that appear
+        // when Java treats a value as negative that is cast from a byte to an int.
+        int inBuff = (numSigBytes > 0 ? ((source[srcOffset] << 24) >>> 8) : 0)
+            | (numSigBytes > 1 ? ((source[srcOffset + 1] << 24) >>> 16) : 0)
+            | (numSigBytes > 2 ? ((source[srcOffset + 2] << 24) >>> 24) : 0);
+
+        switch (numSigBytes)
+        {
+            case 3:
+                destination[destOffset] = ALPHABET[(inBuff >>> 18)];
+                destination[destOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3f];
+                destination[destOffset + 2] = ALPHABET[(inBuff >>> 6) & 0x3f];
+                destination[destOffset + 3] = ALPHABET[(inBuff) & 0x3f];
+                return destination;
+
+            case 2:
+                destination[destOffset] = ALPHABET[(inBuff >>> 18)];
+                destination[destOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3f];
+                destination[destOffset + 2] = ALPHABET[(inBuff >>> 6) & 0x3f];
+                destination[destOffset + 3] = EQUALS_SIGN;
+                return destination;
+
+            case 1:
+                destination[destOffset] = ALPHABET[(inBuff >>> 18)];
+                destination[destOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3f];
+                destination[destOffset + 2] = EQUALS_SIGN;
+                destination[destOffset + 3] = EQUALS_SIGN;
+                return destination;
+
+            default:
+                return destination;
+        } // end switch
+    } // end encode3to4
+
+    /**
+     * Serializes an object and returns the Base64-encoded
+     * version of that serialized object. If the object
+     * cannot be serialized or there is another error,
+     * the method will return <tt>null</tt>.
+     * The object is not GZip-compressed before being encoded.
+     *
+     * @param serializableObject The object to encode
+     * @return The Base64-encoded object
+     * @since 1.4
+     */
+    public static String encodeObject(java.io.Serializable serializableObject)
+    {
+        return encodeObject(serializableObject, NO_OPTIONS);
+    } // end encodeObject
+
+    /**
+     * Serializes an object and returns the Base64-encoded
+     * version of that serialized object. If the object
+     * cannot be serialized or there is another error,
+     * the method will return <tt>null</tt>.
+     * <p>
+     * Valid options:<pre>
+     *   GZIP: gzip-compresses object before encoding it.
+     *   DONT_BREAK_LINES: don't break lines at 76 characters
+     *     <i>Note: Technically, this makes your encoding non-compliant.</i>
+     * </pre>
+     * <p>
+     * Example: <code>encodeObject( myObj, Base64.GZIP )</code> or
+     * <p>
+     * Example: <code>encodeObject( myObj, Base64.GZIP | Base64.DONT_BREAK_LINES )</code>
+     *
+     * @param serializableObject The object to encode
+     * @options Specified options
+     * @return The Base64-encoded object
+     * @see Base64#GZIP
+     * @see Base64#DONT_BREAK_LINES
+     * @since 2.0
+     */
+    public static String encodeObject(java.io.Serializable serializableObject, int options)
+    {
+        // Streams
+        java.io.ByteArrayOutputStream baos = null;
+        java.io.OutputStream b64os = null;
+        java.io.ObjectOutputStream oos = null;
+        java.util.zip.GZIPOutputStream gzos = null;
+
+        // Isolate options
+        int gzip = (options & GZIP);
+        int dontBreakLines = (options & DONT_BREAK_LINES);
+
+        try
+        {
+            // ObjectOutputStream -> (GZIP) -> Base64 -> ByteArrayOutputStream
+            baos = new java.io.ByteArrayOutputStream();
+            b64os = new Base64.OutputStream(baos, ENCODE | dontBreakLines);
+
+            // GZip?
+            if (gzip == GZIP)
+            {
+                gzos = new java.util.zip.GZIPOutputStream(b64os);
+                oos = new java.io.ObjectOutputStream(gzos);
+            } // end if: gzip
+            else oos = new java.io.ObjectOutputStream(b64os);
+
+            oos.writeObject(serializableObject);
+        } // end try
+        catch (java.io.IOException e)
+        {
+            e.printStackTrace();
+            return null;
+        } // end catch
+        finally
+        {
+            try
+            {
+                oos.close();
+            }
+            catch (Exception e)
+            {
+            }
+            try
+            {
+                gzos.close();
+            }
+            catch (Exception e)
+            {
+            }
+            try
+            {
+                b64os.close();
+            }
+            catch (Exception e)
+            {
+            }
+            try
+            {
+                baos.close();
+            }
+            catch (Exception e)
+            {
+            }
+        } // end finally
+
+        // Return value according to relevant encoding.
+        try
+        {
+            return new String(baos.toByteArray(), PREFERRED_ENCODING);
+        } // end try
+        catch (java.io.UnsupportedEncodingException uue)
+        {
+            return new String(baos.toByteArray());
+        } // end catch
+
+    } // end encode
+
+    /**
+     * Encodes a byte array into Base64 notation.
+     * Does not GZip-compress data.
+     *
+     * @param source The data to convert
+     * @since 1.4
+     */
+    public static String encodeBytes(byte[] source)
+    {
+        return encodeBytes(source, 0, source.length, NO_OPTIONS);
+    } // end encodeBytes
+
+    /**
+     * Encodes a byte array into Base64 notation.
+     * <p>
+     * Valid options:<pre>
+     *   GZIP: gzip-compresses object before encoding it.
+     *   DONT_BREAK_LINES: don't break lines at 76 characters
+     *     <i>Note: Technically, this makes your encoding non-compliant.</i>
+     * </pre>
+     * <p>
+     * Example: <code>encodeBytes( myData, Base64.GZIP )</code> or
+     * <p>
+     * Example: <code>encodeBytes( myData, Base64.GZIP | Base64.DONT_BREAK_LINES )</code>
+     *
+     *
+     * @param source The data to convert
+     * @param options Specified options
+     * @see Base64#GZIP
+     * @see Base64#DONT_BREAK_LINES
+     * @since 2.0
+     */
+    public static String encodeBytes(byte[] source, int options)
+    {
+        return encodeBytes(source, 0, source.length, options);
+    } // end encodeBytes
+
+    /**
+     * Encodes a byte array into Base64 notation.
+     * Does not GZip-compress data.
+     *
+     * @param source The data to convert
+     * @param off Offset in array where conversion should begin
+     * @param len Length of data to convert
+     * @since 1.4
+     */
+    public static String encodeBytes(byte[] source, int off, int len)
+    {
+        return encodeBytes(source, off, len, NO_OPTIONS);
+    } // end encodeBytes
+
+    /**
+     * Encodes a byte array into Base64 notation.
+     * <p>
+     * Valid options:<pre>
+     *   GZIP: gzip-compresses object before encoding it.
+     *   DONT_BREAK_LINES: don't break lines at 76 characters
+     *     <i>Note: Technically, this makes your encoding non-compliant.</i>
+     * </pre>
+     * <p>
+     * Example: <code>encodeBytes( myData, Base64.GZIP )</code> or
+     * <p>
+     * Example: <code>encodeBytes( myData, Base64.GZIP | Base64.DONT_BREAK_LINES )</code>
+     *
+     *
+     * @param source The data to convert
+     * @param off Offset in array where conversion should begin
+     * @param len Length of data to convert
+     * @param breakLines Break lines at 80 characters or less.
+     * @param options Specified options
+     * @see Base64#GZIP
+     * @see Base64#DONT_BREAK_LINES
+     * @since 2.0
+     */
+    public static String encodeBytes(byte[] source, int off, int len, int options)
+    {
+        // Isolate options
+        int dontBreakLines = (options & DONT_BREAK_LINES);
+        int gzip = (options & GZIP);
+
+        // Compress?
+        if (gzip == GZIP)
+        {
+            java.io.ByteArrayOutputStream baos = null;
+            java.util.zip.GZIPOutputStream gzos = null;
+            Base64.OutputStream b64os = null;
+
+            try
+            {
+                // GZip -> Base64 -> ByteArray
+                baos = new java.io.ByteArrayOutputStream();
+                b64os = new Base64.OutputStream(baos, ENCODE | dontBreakLines);
+                gzos = new java.util.zip.GZIPOutputStream(b64os);
+
+                gzos.write(source, off, len);
+                gzos.close();
+            } // end try
+            catch (java.io.IOException e)
+            {
+                e.printStackTrace();
+                return null;
+            } // end catch
+            finally
+            {
+                try
+                {
+                    gzos.close();
+                }
+                catch (Exception e)
+                {
+                }
+                try
+                {
+                    b64os.close();
+                }
+                catch (Exception e)
+                {
+                }
+                try
+                {
+                    baos.close();
+                }
+                catch (Exception e)
+                {
+                }
+            } // end finally
+
+            // Return value according to relevant encoding.
+            try
+            {
+                return new String(baos.toByteArray(), PREFERRED_ENCODING);
+            } // end try
+            catch (java.io.UnsupportedEncodingException uue)
+            {
+                return new String(baos.toByteArray());
+            } // end catch
+        } // end if: compress
+
+        // Convert option to boolean in way that code likes it.
+        boolean breakLines = dontBreakLines == 0;
+
+        int len43 = len * 4 / 3;
+        byte[] outBuff = new byte[(len43) // Main 4:3
+            + ((len % 3) > 0 ? 4 : 0) // Account for padding
+            + (breakLines ? (len43 / MAX_LINE_LENGTH) : 0)]; // New lines
+        int d = 0;
+        int e = 0;
+        int len2 = len - 2;
+        int lineLength = 0;
+        for (; d < len2; d += 3, e += 4)
+        {
+            encode3to4(source, d + off, 3, outBuff, e);
+
+            lineLength += 4;
+            if (breakLines && lineLength == MAX_LINE_LENGTH)
+            {
+                outBuff[e + 4] = NEW_LINE;
+                e++;
+                lineLength = 0;
+            } // end if: end of line
+        } // en dfor: each piece of array
+
+        if (d < len)
+        {
+            encode3to4(source, d + off, len - d, outBuff, e);
+            e += 4;
+        } // end if: some padding needed
+
+        // Return value according to relevant encoding.
+        try
+        {
+            return new String(outBuff, 0, e, PREFERRED_ENCODING);
+        } // end try
+        catch (java.io.UnsupportedEncodingException uue)
+        {
+            return new String(outBuff, 0, e);
+        } // end catch
+        // end else: don't compress
+
+    } // end encodeBytes
+
+    /* ********  D E C O D I N G   M E T H O D S  ******** */
+
+    //    /**
+    //     * Decodes the first four bytes of array <var>fourBytes</var>
+    //     * and returns an array up to three bytes long with the
+    //     * decoded values.
+    //     *
+    //     * @param fourBytes the array with Base64 content
+    //     * @return array with decoded values
+    //     * @since 1.3
+    //     */
+    //    private static byte[] decode4to3( byte[] fourBytes )
+    //    {
+    //        byte[] outBuff1 = new byte[3];
+    //        int    count    = decode4to3( fourBytes, 0, outBuff1, 0 );
+    //        byte[] outBuff2 = new byte[ count ];
+    //
+    //        for( int i = 0; i < count; i++ )
+    //            outBuff2[i] = outBuff1[i];
+    //
+    //        return outBuff2;
+    //    }
+
+    /**
+     * Decodes four bytes from array <var>source</var>
+     * and writes the resulting bytes (up to three of them)
+     * to <var>destination</var>.
+     * The source and destination arrays can be manipulated
+     * anywhere along their length by specifying
+     * <var>srcOffset</var> and <var>destOffset</var>.
+     * This method does not check to make sure your arrays
+     * are large enough to accomodate <var>srcOffset</var> + 4 for
+     * the <var>source</var> array or <var>destOffset</var> + 3 for
+     * the <var>destination</var> array.
+     * This method returns the actual number of bytes that
+     * were converted from the Base64 encoding.
+     *
+     *
+     * @param source the array to convert
+     * @param srcOffset the index where conversion begins
+     * @param destination the array to hold the conversion
+     * @param destOffset the index where output will be put
+     * @return the number of decoded bytes converted
+     * @since 1.3
+     */
+    static int decode4to3(byte[] source, int srcOffset, byte[] destination, int destOffset)
+    {
+        // Example: Dk==
+        if (source[srcOffset + 2] == EQUALS_SIGN)
+        {
+            // Two ways to do the same thing. Don't know which way I like best.
+            //int outBuff =   ( ( DECODABET[ source[ srcOffset    ] ] << 24 ) >>>  6 )
+            //              | ( ( DECODABET[ source[ srcOffset + 1] ] << 24 ) >>> 12 );
+            int outBuff = ((DECODABET[source[srcOffset]] & 0xFF) << 18)
+                | ((DECODABET[source[srcOffset + 1]] & 0xFF) << 12);
+
+            destination[destOffset] = (byte) (outBuff >>> 16);
+            return 1;
+        }
+
+        // Example: DkL=
+        else if (source[srcOffset + 3] == EQUALS_SIGN)
+        {
+            // Two ways to do the same thing. Don't know which way I like best.
+            //int outBuff =   ( ( DECODABET[ source[ srcOffset     ] ] << 24 ) >>>  6 )
+            //              | ( ( DECODABET[ source[ srcOffset + 1 ] ] << 24 ) >>> 12 )
+            //              | ( ( DECODABET[ source[ srcOffset + 2 ] ] << 24 ) >>> 18 );
+            int outBuff = ((DECODABET[source[srcOffset]] & 0xFF) << 18)
+                | ((DECODABET[source[srcOffset + 1]] & 0xFF) << 12)
+                | ((DECODABET[source[srcOffset + 2]] & 0xFF) << 6);
+
+            destination[destOffset] = (byte) (outBuff >>> 16);
+            destination[destOffset + 1] = (byte) (outBuff >>> 8);
+            return 2;
+        }
+
+        // Example: DkLE
+        else
+        {
+            try
+            {
+                // Two ways to do the same thing. Don't know which way I like best.
+                //int outBuff =   ( ( DECODABET[ source[ srcOffset     ] ] << 24 ) >>>  6 )
+                //              | ( ( DECODABET[ source[ srcOffset + 1 ] ] << 24 ) >>> 12 )
+                //              | ( ( DECODABET[ source[ srcOffset + 2 ] ] << 24 ) >>> 18 )
+                //              | ( ( DECODABET[ source[ srcOffset + 3 ] ] << 24 ) >>> 24 );
+                int outBuff = ((DECODABET[source[srcOffset]] & 0xFF) << 18)
+                    | ((DECODABET[source[srcOffset + 1]] & 0xFF) << 12)
+                    | ((DECODABET[source[srcOffset + 2]] & 0xFF) << 6)
+                    | ((DECODABET[source[srcOffset + 3]] & 0xFF));
+
+                destination[destOffset] = (byte) (outBuff >> 16);
+                destination[destOffset + 1] = (byte) (outBuff >> 8);
+                destination[destOffset + 2] = (byte) (outBuff);
+
+                return 3;
+            }
+            catch (Exception e)
+            {
+                System.out.println("" + source[srcOffset] + ": " + (DECODABET[source[srcOffset]]));
+                System.out.println("" + source[srcOffset + 1] + ": "
+                    + (DECODABET[source[srcOffset + 1]]));
+                System.out.println("" + source[srcOffset + 2] + ": "
+                    + (DECODABET[source[srcOffset + 2]]));
+                System.out.println("" + source[srcOffset + 3] + ": "
+                    + (DECODABET[source[srcOffset + 3]]));
+                return -1;
+            } //e nd catch
+        }
+    } // end decodeToBytes
+
+    /**
+     * Very low-level access to decoding ASCII characters in
+     * the form of a byte array. Does not support automatically
+     * gunzipping or any other "fancy" features.
+     *
+     * @param source The Base64 encoded data
+     * @param off    The offset of where to begin decoding
+     * @param len    The length of characters to decode
+     * @return decoded data
+     * @since 1.3
+     */
+    public static byte[] decode(byte[] source, int off, int len)
+    {
+        int len34 = len * 3 / 4;
+        byte[] outBuff = new byte[len34]; // Upper limit on size of output
+        int outBuffPosn = 0;
+
+        byte[] b4 = new byte[4];
+        int b4Posn = 0;
+        int i = 0;
+        byte sbiCrop = 0;
+        byte sbiDecode = 0;
+        for (i = off; i < off + len; i++)
+        {
+            sbiCrop = (byte) (source[i] & 0x7f); // Only the low seven bits
+            sbiDecode = DECODABET[sbiCrop];
+
+            if (sbiDecode >= WHITE_SPACE_ENC) // White space, Equals sign or better
+            {
+                if (sbiDecode >= EQUALS_SIGN_ENC)
+                {
+                    b4[b4Posn++] = sbiCrop;
+                    if (b4Posn > 3)
+                    {
+                        outBuffPosn += decode4to3(b4, 0, outBuff, outBuffPosn);
+                        b4Posn = 0;
+
+                        // If that was the equals sign, break out of 'for' loop
+                        if (sbiCrop == EQUALS_SIGN) break;
+                    } // end if: quartet built
+
+                } // end if: equals sign or better
+
+            } // end if: white space, equals sign or better
+            else
+            {
+                System.err.println("Bad Base64 input character at " + i + ": " + source[i] + "(decimal)");
+                return null;
+            } // end else:
+        } // each input character
+
+        byte[] out = new byte[outBuffPosn];
+        System.arraycopy(outBuff, 0, out, 0, outBuffPosn);
+        return out;
+    } // end decode
+
+    /**
+     * Decodes data from Base64 notation, automatically
+     * detecting gzip-compressed data and decompressing it.
+     *
+     * @param s the string to decode
+     * @return the decoded data
+     * @since 1.4
+     */
+    public static byte[] decode(String s)
+    {
+        byte[] bytes;
+        try
+        {
+            bytes = s.getBytes(PREFERRED_ENCODING);
+        } // end try
+        catch (java.io.UnsupportedEncodingException uee)
+        {
+            bytes = s.getBytes();
+        } // end catch
+        //</change>
+
+        // Decode
+        bytes = decode(bytes, 0, bytes.length);
+
+        // Check to see if it's gzip-compressed
+        // GZIP Magic Two-Byte Number: 0x8b1f (35615)
+        if (bytes.length >= 2)
+        {
+
+            int head = (bytes[0] & 0xff) | ((bytes[1] << 8) & 0xff00);
+            if (bytes != null && // In case decoding returned null
+                bytes.length >= 4 && // Don't want to get ArrayIndexOutOfBounds exception
+                java.util.zip.GZIPInputStream.GZIP_MAGIC == head)
+            {
+                java.io.ByteArrayInputStream bais = null;
+                java.util.zip.GZIPInputStream gzis = null;
+                java.io.ByteArrayOutputStream baos = null;
+                byte[] buffer = new byte[2048];
+                int length = 0;
+
+                try
+                {
+                    baos = new java.io.ByteArrayOutputStream();
+                    bais = new java.io.ByteArrayInputStream(bytes);
+                    gzis = new java.util.zip.GZIPInputStream(bais);
+
+                    while ((length = gzis.read(buffer)) >= 0)
+                    {
+                        baos.write(buffer, 0, length);
+                    } // end while: reading input
+
+                    // No error? Get new bytes.
+                    bytes = baos.toByteArray();
+
+                } // end try
+                catch (java.io.IOException e)
+                {
+                    // Just return originally-decoded bytes
+                } // end catch
+                finally
+                {
+                    try
+                    {
+                        baos.close();
+                    }
+                    catch (Exception e)
+                    {
+                    }
+                    try
+                    {
+                        gzis.close();
+                    }
+                    catch (Exception e)
+                    {
+                    }
+                    try
+                    {
+                        bais.close();
+                    }
+                    catch (Exception e)
+                    {
+                    }
+                } // end finally
+
+            } // end if: gzipped
+        } // end if: bytes.length >= 2
+
+        return bytes;
+    } // end decode
+
+    /**
+     * Attempts to decode Base64 data and deserialize a Java
+     * Object within. Returns <tt>null</tt> if there was an error.
+     *
+     * @param encodedObject The Base64 data to decode
+     * @return The decoded and deserialized object
+     * @since 1.5
+     */
+    public static Object decodeToObject(String encodedObject)
+    {
+        // Decode and gunzip if necessary
+        byte[] objBytes = decode(encodedObject);
+
+        java.io.ByteArrayInputStream bais = null;
+        java.io.ObjectInputStream ois = null;
+        Object obj = null;
+
+        try
+        {
+            bais = new java.io.ByteArrayInputStream(objBytes);
+            ois = new java.io.ObjectInputStream(bais);
+
+            obj = ois.readObject();
+        } // end try
+        catch (java.io.IOException e)
+        {
+            e.printStackTrace();
+            obj = null;
+        } // end catch
+        catch (java.lang.ClassNotFoundException e)
+        {
+            e.printStackTrace();
+            obj = null;
+        } // end catch
+        finally
+        {
+            try
+            {
+                bais.close();
+            }
+            catch (Exception e)
+            {
+            }
+            try
+            {
+                ois.close();
+            }
+            catch (Exception e)
+            {
+            }
+        } // end finally
+
+        return obj;
+    } // end decodeObject
+
+    /* ********  I N N E R   C L A S S   I N P U T S T R E A M  ******** */
+
+    /**
+     * A {@link Base64#InputStream} will read data from another
+     * {@link java.io.InputStream}, given in the constructor,
+     * and encode/decode to/from Base64 notation on the fly.
+     *
+     * @see Base64
+     * @see java.io.FilterInputStream
+     * @since 1.3
+     */
+    public static class InputStream extends java.io.FilterInputStream
+    {
+        //private int     options;        // Options specified
+        private boolean encode; // Encoding or decoding
+        private int position; // Current position in the buffer
+        private byte[] buffer; // Small buffer holding converted data
+        private int bufferLength; // Length of buffer (3 or 4)
+        private int numSigBytes; // Number of meaningful bytes in the buffer
+        private int lineLength;
+        private boolean breakLines; // Break lines at less than 80 characters
+
+        /**
+         * Constructs a {@link Base64#InputStream} in DECODE mode.
+         *
+         * @param in the {@link java.io.InputStream} from which to read data.
+         * @since 1.3
+         */
+        public InputStream(java.io.InputStream pIn)
+        {
+            this(pIn, DECODE);
+        } // end constructor
+
+        /**
+         * Constructs a {@link Base64#InputStream} in
+         * either ENCODE or DECODE mode.
+         * <p>
+         * Valid options:<pre>
+         *   ENCODE or DECODE: Encode or Decode as data is read.
+         *   DONT_BREAK_LINES: don't break lines at 76 characters
+         *     (only meaningful when encoding)
+         *     <i>Note: Technically, this makes your encoding non-compliant.</i>
+         * </pre>
+         * <p>
+         * Example: <code>new Base64.InputStream( in, Base64.DECODE )</code>
+         *
+         *
+         * @param in the {@link java.io.InputStream} from which to read data.
+         * @param options Specified options
+         * @see Base64#ENCODE
+         * @see Base64#DECODE
+         * @see Base64#DONT_BREAK_LINES
+         * @since 2.0
+         */
+        public InputStream(java.io.InputStream pIn, int options)
+        {
+            super(pIn);
+            //this.options      = options;
+            breakLines = (options & DONT_BREAK_LINES) != DONT_BREAK_LINES;
+            encode = (options & ENCODE) == ENCODE;
+            bufferLength = encode ? 4 : 3;
+            buffer = new byte[bufferLength];
+            position = -1;
+            lineLength = 0;
+        } // end constructor
+
+        /**
+         * Reads enough of the input stream to convert
+         * to/from Base64 and returns the next byte.
+         *
+         * @return next byte
+         * @since 1.3
+         */
+        @Override
+		public int read() throws java.io.IOException
+        {
+            // Do we need to get data?
+            if (position < 0)
+            {
+                if (encode)
+                {
+                    byte[] b3 = new byte[3];
+                    int numBinaryBytes = 0;
+                    for (int i = 0; i < 3; i++)
+                    {
+                        try
+                        {
+                            int b = in.read();
+
+                            // If end of stream, b is -1.
+                            if (b >= 0)
+                            {
+                                b3[i] = (byte) b;
+                                numBinaryBytes++;
+                            } // end if: not end of stream
+
+                        } // end try: read
+                        catch (java.io.IOException e)
+                        {
+                            // Only a problem if we got no data at all.
+                            if (i == 0) throw e;
+
+                        } // end catch
+                    } // end for: each needed input byte
+
+                    if (numBinaryBytes > 0)
+                    {
+                        encode3to4(b3, 0, numBinaryBytes, buffer, 0);
+                        position = 0;
+                        numSigBytes = 4;
+                    } // end if: got data
+                    else
+                    {
+                        return -1;
+                    } // end else
+                } // end if: encoding
+
+                // Else decoding
+                else
+                {
+                    byte[] b4 = new byte[4];
+                    int i = 0;
+                    for (i = 0; i < 4; i++)
+                    {
+                        // Read four "meaningful" bytes:
+                        int b = 0;
+                        do
+                        {
+                            b = in.read();
+                        }
+                        while (b >= 0 && DECODABET[b & 0x7f] <= WHITE_SPACE_ENC);
+
+                        if (b < 0) break; // Reads a -1 if end of stream
+
+                        b4[i] = (byte) b;
+                    } // end for: each needed input byte
+
+                    if (i == 4)
+                    {
+                        numSigBytes = decode4to3(b4, 0, buffer, 0);
+                        position = 0;
+                    } // end if: got four characters
+                    else if (i == 0)
+                    {
+                        return -1;
+                    } // end else if: also padded correctly
+                    else
+                    {
+                        // Must have broken out from above.
+                        throw new java.io.IOException("Improperly padded Base64 input.");
+                    } // end
+
+                } // end else: decode
+            } // end else: get data
+
+            // Got data?
+            if (position >= 0)
+            {
+                // End of relevant data?
+                if ( /*!encode &&*/position >= numSigBytes) return -1;
+
+                if (encode && breakLines && lineLength >= MAX_LINE_LENGTH)
+                {
+                    lineLength = 0;
+                    return '\n';
+                } // end if
+                lineLength++; // This isn't important when decoding
+                // but throwing an extra "if" seems
+                // just as wasteful.
+
+                int b = buffer[position++];
+
+                if (position >= bufferLength) position = -1;
+
+                return b & 0xFF; // This is how you "cast" a byte that's
+                // intended to be unsigned.
+                // end else
+            } // end if: position >= 0
+
+            // When JDK1.4 is more accepted, use an assertion here.
+            throw new java.io.IOException("Error in Base64 code reading stream.");
+            // end else
+        } // end read
+
+        /**
+         * Calls {@link #read} repeatedly until the end of stream
+         * is reached or <var>len</var> bytes are read.
+         * Returns number of bytes read into array or -1 if
+         * end of stream is encountered.
+         *
+         * @param dest array to hold values
+         * @param off offset for array
+         * @param len max number of bytes to read into array
+         * @return bytes read into array or -1 if end of stream is encountered.
+         * @since 1.3
+         */
+        @Override
+		public int read(byte[] dest, int off, int len) throws java.io.IOException
+        {
+            int i;
+            int b;
+            for (i = 0; i < len; i++)
+            {
+                b = read();
+
+                //if( b < 0 && i == 0 )
+                //    return -1;
+
+                if (b >= 0) dest[off + i] = (byte) b;
+                else if (i == 0) return -1;
+                else break; // Out of 'for' loop
+            } // end for: each byte read
+            return i;
+        } // end read
+
+    } // end inner class InputStream
+
+    /* ********  I N N E R   C L A S S   O U T P U T S T R E A M  ******** */
+
+    /**
+     * A {@link Base64#OutputStream} will write data to another
+     * {@link java.io.OutputStream}, given in the constructor,
+     * and encode/decode to/from Base64 notation on the fly.
+     *
+     * @see Base64
+     * @see java.io.FilterOutputStream
+     * @since 1.3
+     */
+    public static class OutputStream extends java.io.FilterOutputStream
+    {
+        //private int     options;
+        private boolean encode;
+        private int position;
+        private byte[] buffer;
+        private int bufferLength;
+        private int lineLength;
+        private boolean breakLines;
+        private byte[] b4; // Scratch used in a few places
+        private boolean suspendEncoding;
+
+        /**
+         * Constructs a {@link Base64#OutputStream} in ENCODE mode.
+         *
+         * @param out the {@link java.io.OutputStream} to which data will be written.
+         * @since 1.3
+         */
+        public OutputStream(java.io.OutputStream pOut)
+        {
+            this(pOut, ENCODE);
+        } // end constructor
+
+        /**
+         * Constructs a {@link Base64#OutputStream} in
+         * either ENCODE or DECODE mode.
+         * <p>
+         * Valid options:<pre>
+         *   ENCODE or DECODE: Encode or Decode as data is read.
+         *   DONT_BREAK_LINES: don't break lines at 76 characters
+         *     (only meaningful when encoding)
+         *     <i>Note: Technically, this makes your encoding non-compliant.</i>
+         * </pre>
+         * <p>
+         * Example: <code>new Base64.OutputStream( out, Base64.ENCODE )</code>
+         *
+         * @param out the {@link java.io.OutputStream} to which data will be written.
+         * @param options Specified options.
+         * @see Base64#ENCODE
+         * @see Base64#DECODE
+         * @see Base64#DONT_BREAK_LINES
+         * @since 1.3
+         */
+        public OutputStream(java.io.OutputStream pOut, int options)
+        {
+            super(pOut);
+            //this.options      = options;
+            breakLines = (options & DONT_BREAK_LINES) != DONT_BREAK_LINES;
+            encode = (options & ENCODE) == ENCODE;
+            bufferLength = encode ? 3 : 4;
+            buffer = new byte[bufferLength];
+            position = 0;
+            lineLength = 0;
+            suspendEncoding = false;
+            b4 = new byte[4];
+        } // end constructor
+
+        /**
+         * Writes the byte to the output stream after
+         * converting to/from Base64 notation.
+         * When encoding, bytes are buffered three
+         * at a time before the output stream actually
+         * gets a write() call.
+         * When decoding, bytes are buffered four
+         * at a time.
+         *
+         * @param theByte the byte to write
+         * @since 1.3
+         */
+        @Override
+		public void write(int theByte) throws java.io.IOException
+        {
+            // Encoding suspended?
+            if (suspendEncoding)
+            {
+                super.out.write(theByte);
+                return;
+            } // end if: supsended
+
+            // Encode?
+            if (encode)
+            {
+                buffer[position++] = (byte) theByte;
+                if (position >= bufferLength) // Enough to encode.
+                {
+                    out.write(encode3to4(b4, buffer, bufferLength));
+
+                    lineLength += 4;
+                    if (breakLines && lineLength >= MAX_LINE_LENGTH)
+                    {
+                        out.write(NEW_LINE);
+                        lineLength = 0;
+                    } // end if: end of line
+
+                    position = 0;
+                } // end if: enough to output
+            } // end if: encoding
+
+            // Else, Decoding
+            else
+            {
+                // Meaningful Base64 character?
+                if (DECODABET[theByte & 0x7f] > WHITE_SPACE_ENC)
+                {
+                    buffer[position++] = (byte) theByte;
+                    if (position >= bufferLength) // Enough to output.
+                    {
+                        int len = Base64.decode4to3(buffer, 0, b4, 0);
+                        out.write(b4, 0, len);
+                        //out.write( Base64.decode4to3( buffer ) );
+                        position = 0;
+                    } // end if: enough to output
+                } // end if: meaningful base64 character
+                else if (DECODABET[theByte & 0x7f] != WHITE_SPACE_ENC)
+                {
+                    throw new java.io.IOException("Invalid character in Base64 data.");
+                } // end else: not white space either
+            } // end else: decoding
+        } // end write
+
+        /**
+         * Calls {@link #write} repeatedly until <var>len</var>
+         * bytes are written.
+         *
+         * @param theBytes array from which to read bytes
+         * @param off offset for array
+         * @param len max number of bytes to read into array
+         * @since 1.3
+         */
+        @Override
+		public void write(byte[] theBytes, int off, int len) throws java.io.IOException
+        {
+            // Encoding suspended?
+            if (suspendEncoding)
+            {
+                super.out.write(theBytes, off, len);
+                return;
+            } // end if: supsended
+
+            for (int i = 0; i < len; i++)
+            {
+                write(theBytes[off + i]);
+            } // end for: each byte written
+
+        } // end write
+
+        /**
+         * Method added by PHIL. [Thanks, PHIL. -Rob]
+         * This pads the buffer without closing the stream.
+         */
+        public void flushBase64() throws java.io.IOException
+        {
+            if (position > 0)
+            {
+                if (encode)
+                {
+                    out.write(encode3to4(b4, buffer, position));
+                    position = 0;
+                } // end if: encoding
+                else
+                {
+                    throw new java.io.IOException("Base64 input not properly padded.");
+                } // end else: decoding
+            } // end if: buffer partially full
+
+        } // end flush
+
+        /**
+         * Flushes and closes (I think, in the superclass) the stream.
+         *
+         * @since 1.3
+         */
+        @Override
+		public void close() throws java.io.IOException
+        {
+            // 1. Ensure that pending characters are written
+            flushBase64();
+
+            // 2. Actually close the stream
+            // Base class both flushes and closes.
+            super.close();
+
+            buffer = null;
+            out = null;
+        } // end close
+
+        /**
+         * Suspends encoding of the stream.
+         * May be helpful if you need to embed a piece of
+         * base640-encoded data in a stream.
+         *
+         * @since 1.5.1
+         */
+        public void suspendEncoding() throws java.io.IOException
+        {
+            flushBase64();
+            suspendEncoding = true;
+        } // end suspendEncoding
+
+        /**
+         * Resumes encoding of the stream.
+         * May be helpful if you need to embed a piece of
+         * base640-encoded data in a stream.
+         *
+         * @since 1.5.1
+         */
+        public void resumeEncoding()
+        {
+            suspendEncoding = false;
+        } // end resumeEncoding
+
+    } // end inner class OutputStream
+
+} // end class Base64

+ 30 - 0
L2_GameServer_T1/java/net/sf/l2j/ChatFilter.java

@@ -0,0 +1,30 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+package net.sf.l2j;
+
+import java.util.logging.Filter;
+import java.util.logging.LogRecord;
+
+public class ChatFilter implements Filter {
+
+	public boolean isLoggable(LogRecord record) {
+		return record.getLoggerName() == "chat";
+	}
+
+}

+ 60 - 0
L2_GameServer_T1/java/net/sf/l2j/ChatLogFormatter.java

@@ -0,0 +1,60 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+package net.sf.l2j;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.logging.Formatter;
+import java.util.logging.LogRecord;
+
+import javolution.text.TextBuilder;
+
+/**
+ * This class ...
+ *
+ * @version $Revision: 1.1.4.1 $ $Date: 2005/02/06 16:14:46 $
+ */
+
+public class ChatLogFormatter extends Formatter
+{
+	private static final String CRLF = "\r\n";
+
+	private SimpleDateFormat dateFmt = new SimpleDateFormat("dd MMM H:mm:ss");
+
+	@Override
+	public String format(LogRecord record)
+	{
+		Object[] params = record.getParameters();
+        TextBuilder output = new TextBuilder();
+		output.append('[');
+		output.append(dateFmt.format(new Date(record.getMillis())));
+		output.append(']');
+		output.append(' ');
+		if (params != null) {
+			for (Object p : params) {
+				output.append(p);
+				output.append(' ');
+			}
+		}
+		output.append(record.getMessage());
+		output.append(CRLF);
+
+		return output.toString();
+	}
+}

+ 29 - 0
L2_GameServer_T1/java/net/sf/l2j/ChatLogHandler.java

@@ -0,0 +1,29 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+package net.sf.l2j;
+
+import java.io.IOException;
+import java.util.logging.FileHandler;
+
+public class ChatLogHandler extends FileHandler {
+
+	public ChatLogHandler() throws IOException, SecurityException {
+		super();
+	}
+}

+ 2488 - 0
L2_GameServer_T1/java/net/sf/l2j/Config.java

@@ -0,0 +1,2488 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+package net.sf.l2j;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.math.BigInteger;
+import java.util.List;
+import java.util.Properties;
+import java.util.logging.Logger;
+
+import javolution.util.FastList;
+import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
+
+/**
+ * This class contains global server configuration.<br>
+ * It has static final fields initialized from configuration files.<br>
+ * It's initialized at the very begin of startup, and later JIT will optimize
+ * away debug/unused code.
+ *
+ * @author mkizub
+ */
+public final class Config
+{
+    protected static final Logger _log = Logger.getLogger(Config.class.getName());
+    /** Debug/release mode */
+    public static boolean DEBUG;
+    /** Enable/disable assertions */
+    public static boolean ASSERT;
+    /** Enable/disable code 'in progress' */
+    public static boolean DEVELOPER;
+
+    /** Set if this server is a test server used for development */
+    public static boolean TEST_SERVER;
+
+    /** Game Server ports */
+    public static int PORT_GAME;
+    /** Login Server port */
+    public static int PORT_LOGIN;
+    /** Login Server bind ip */
+    public static String LOGIN_BIND_ADDRESS;
+    /** Number of login tries before IP ban gets activated, default 10*/
+    public static int LOGIN_TRY_BEFORE_BAN;
+    /** Number of seconds the IP ban will last, default 10 minutes */
+    public static int LOGIN_BLOCK_AFTER_BAN;
+    /** Hostname of the Game Server */
+    public static String GAMESERVER_HOSTNAME;
+
+    // Access to database
+    /** Driver to access to database */
+    public static String DATABASE_DRIVER;
+    /** Path to access to database */
+    public static String DATABASE_URL;
+    /** Database login */
+    public static String DATABASE_LOGIN;
+    /** Database password */
+    public static String DATABASE_PASSWORD;
+    /** Maximum number of connections to the database */
+    public static int DATABASE_MAX_CONNECTIONS;
+
+    /** Maximum number of players allowed to play simultaneously on server */
+    public static int   MAXIMUM_ONLINE_USERS;
+
+    // Setting for serverList
+    /** Displays [] in front of server name ? */
+    public static boolean SERVER_LIST_BRACKET;
+    /** Displays a clock next to the server name ? */
+    public static boolean SERVER_LIST_CLOCK;
+    /** Display test server in the list of servers ? */
+    public static boolean SERVER_LIST_TESTSERVER;
+    /** Set the server as gm only at startup ? */
+    public static boolean SERVER_GMONLY;
+
+    // Thread pools size
+    /** Thread pool size effect */
+    public static int THREAD_P_EFFECTS;
+    /** Thread pool size general */
+    public static int THREAD_P_GENERAL;
+    /** Packet max thread */
+    public static int GENERAL_PACKET_THREAD_CORE_SIZE;
+    public static int IO_PACKET_THREAD_CORE_SIZE;
+    /** General max thread */
+    public static int GENERAL_THREAD_CORE_SIZE;
+    /** AI max thread */
+    public static int AI_MAX_THREAD;
+
+    /** Accept auto-loot ? */
+    public static boolean AUTO_LOOT;
+    public static boolean AUTO_LOOT_HERBS;
+
+    /** Character name template */
+    public static String CNAME_TEMPLATE;
+    /** Pet name template */
+    public static String PET_NAME_TEMPLATE;
+    /** Maximum number of characters per account */
+    public static int MAX_CHARACTERS_NUMBER_PER_ACCOUNT;
+
+    /** Global chat state */
+    public static String  DEFAULT_GLOBAL_CHAT;
+    /** Trade chat state */
+    public static String  DEFAULT_TRADE_CHAT;
+    /** For test servers - everybody has admin rights */
+    public static boolean EVERYBODY_HAS_ADMIN_RIGHTS;
+    /** Alternative game crafting */
+    public static boolean ALT_GAME_CREATION;
+    /** Alternative game crafting speed mutiplier - default 0 (fastest but still not instant) */
+    public static double ALT_GAME_CREATION_SPEED;
+    /** Alternative game crafting XP rate multiplier - default 1*/
+    public static double ALT_GAME_CREATION_XP_RATE;
+    /** Alternative game crafting SP rate multiplier - default 1*/
+    public static double ALT_GAME_CREATION_SP_RATE;
+    /** Alternative setting to blacksmith use of recipes to craft - default true*/
+    public static boolean ALT_BLACKSMITH_USE_RECIPES;
+
+    /** Remove Castle circlets after clan lose his castle? - default true*/
+	public static boolean REMOVE_CASTLE_CIRCLETS;
+    /** Alternative game weight limit multiplier - default 1*/
+    public static double ALT_WEIGHT_LIMIT;
+
+    /** Alternative game skill learning */
+    public static boolean ALT_GAME_SKILL_LEARN;
+    /** Alternative auto skill learning */
+    public static boolean AUTO_LEARN_SKILLS;
+    /** Cancel attack bow by hit */
+    public static boolean ALT_GAME_CANCEL_BOW;
+    /** Cancel cast by hit */
+    public static boolean ALT_GAME_CANCEL_CAST;
+
+    /** Alternative game - use tiredness, instead of CP */
+    public static boolean ALT_GAME_TIREDNESS;
+    public static int ALT_PARTY_RANGE;
+    public static int ALT_PARTY_RANGE2;
+    /** Alternative shield defence */
+    public static boolean ALT_GAME_SHIELD_BLOCKS;
+    /** Alternative Perfect shield defence rate */
+    public static int ALT_PERFECT_SHLD_BLOCK;
+    /** Alternative game mob ATTACK AI */
+    public static boolean ALT_GAME_MOB_ATTACK_AI;
+    public static boolean ALT_MOB_AGRO_IN_PEACEZONE;
+
+    /** Alternative freight modes - Freights can be withdrawed from any village */
+    public static boolean ALT_GAME_FREIGHTS;
+    /** Alternative freight modes - Sets the price value for each freightened item */
+    public static int ALT_GAME_FREIGHT_PRICE;
+
+    /** Fast or slow multiply coefficient for skill hit time */
+    public static float ALT_GAME_SKILL_HIT_RATE;
+
+    /** Alternative gameing - loss of XP on death */
+    public static boolean ALT_GAME_DELEVEL;
+
+    /** Alternative gameing - magic dmg failures */
+    public static boolean ALT_GAME_MAGICFAILURES;
+
+    /** Alternative gaming - player must be in a castle-owning clan or ally to sign up for Dawn. */
+    public static boolean ALT_GAME_REQUIRE_CASTLE_DAWN;
+
+    /** Alternative gaming - allow clan-based castle ownage check rather than ally-based. */
+    public static boolean ALT_GAME_REQUIRE_CLAN_CASTLE;
+
+    /** Alternative gaming - allow free teleporting around the world. */
+    public static boolean ALT_GAME_FREE_TELEPORT;
+
+    /** Disallow recommend character twice or more a day ? */
+    public static boolean ALT_RECOMMEND;
+
+    /** Alternative gaming - allow sub-class addition without quest completion. */
+    public static boolean ALT_GAME_SUBCLASS_WITHOUT_QUESTS;
+
+    /** View npc stats/drop by shift-cliking it for nongm-players */
+    public static boolean ALT_GAME_VIEWNPC;
+
+    /** Minimum number of player to participate in SevenSigns Festival */
+    public static int ALT_FESTIVAL_MIN_PLAYER;
+
+    /** Maximum of player contrib during Festival */
+    public static int ALT_MAXIMUM_PLAYER_CONTRIB;
+
+    /** Festival Manager start time. */
+    public static long ALT_FESTIVAL_MANAGER_START;
+
+    /** Festival Length */
+    public static long ALT_FESTIVAL_LENGTH;
+
+    /** Festival Cycle Length */
+    public static long ALT_FESTIVAL_CYCLE_LENGTH;
+
+    /** Festival First Spawn */
+    public static long ALT_FESTIVAL_FIRST_SPAWN;
+
+    /** Festival First Swarm */
+    public static long ALT_FESTIVAL_FIRST_SWARM;
+
+    /** Festival Second Spawn */
+    public static long ALT_FESTIVAL_SECOND_SPAWN;
+
+    /** Festival Second Swarm */
+    public static long ALT_FESTIVAL_SECOND_SWARM;
+
+    /** Festival Chest Spawn */
+    public static long ALT_FESTIVAL_CHEST_SPAWN;
+
+    /** Number of members needed to request a clan war */
+    public static int ALT_CLAN_MEMBERS_FOR_WAR;
+
+    /** Number of days before joining a new clan */
+    public static int ALT_CLAN_JOIN_DAYS;
+    /** Number of days before creating a new clan */
+    public static int ALT_CLAN_CREATE_DAYS;
+    /** Number of days it takes to dissolve a clan */
+    public static int ALT_CLAN_DISSOLVE_DAYS;
+    /** Number of days before joining a new alliance when clan voluntarily leave an alliance */
+    public static int ALT_ALLY_JOIN_DAYS_WHEN_LEAVED;
+    /** Number of days before joining a new alliance when clan was dismissed from an alliance */
+    public static int ALT_ALLY_JOIN_DAYS_WHEN_DISMISSED;
+    /** Number of days before accepting a new clan for alliance when clan was dismissed from an alliance */
+    public static int ALT_ACCEPT_CLAN_DAYS_WHEN_DISMISSED;
+    /** Number of days before creating a new alliance when dissolved an alliance */
+    public static int ALT_CREATE_ALLY_DAYS_WHEN_DISSOLVED;
+
+    /** Alternative gaming - all new characters always are newbies. */
+    public static boolean ALT_GAME_NEW_CHAR_ALWAYS_IS_NEWBIE;
+
+    /** Alternative gaming - clan members with see privilege can also withdraw from clan warehouse. */
+    public static boolean ALT_MEMBERS_CAN_WITHDRAW_FROM_CLANWH;
+
+    /** Alternative gaming - Castle Shield can be equiped by all clan members if they own a castle. - default True */
+    public static boolean CASTLE_SHIELD;
+    /** Alternative gaming - Clan Hall Shield can be equiped by all clan members if they own a clan hall. - default True */
+    public static boolean CLANHALL_SHIELD;
+    /** Alternative gaming - Apella armors can be equiped only by clan members if their class is Baron or higher - default True */
+    public static boolean APELLA_ARMORS;
+    /** Alternative gaming - Clan Oath Armors can be equiped only by clan members - default True */
+    public static boolean OATH_ARMORS;
+    /** Alternative gaming - Castle Crown can be equiped only by castle lord - default True */
+    public static boolean CASTLE_CROWN;
+    /** Alternative gaming - Castle Circlets can be equiped only by clan members if they own a castle - default True */
+    public static boolean CASTLE_CIRCLETS;
+
+    /** Maximum number of clans in ally */
+    public static int ALT_MAX_NUM_OF_CLANS_IN_ALLY;
+    /** Life Crystal needed to learn clan skill */
+    public static boolean LIFE_CRYSTAL_NEEDED;
+    /** Spell Book needed to learn skill */
+    public static boolean SP_BOOK_NEEDED;
+    /** Spell Book needet to enchant skill */
+    public static boolean ES_SP_BOOK_NEEDED;
+    /** Logging Chat Window */
+    public static boolean LOG_CHAT;
+    /** Logging Item Window */
+    public static boolean LOG_ITEMS;
+
+    /** Alternative privileges for admin */
+    public static boolean ALT_PRIVILEGES_ADMIN;
+    /** Alternative secure check privileges */
+    public static boolean ALT_PRIVILEGES_SECURE_CHECK;
+    /** Alternative default level for privileges */
+    public static int ALT_PRIVILEGES_DEFAULT_LEVEL;
+
+    /** Olympiad Competition Starting time */
+    public static int ALT_OLY_START_TIME;
+    /** Olympiad Minutes */
+    public static int ALT_OLY_MIN;
+
+    /** Olympiad Competition Period */
+    public static long ALT_OLY_CPERIOD;
+
+    /** Olympiad Battle Period */
+    public static long ALT_OLY_BATTLE;
+
+    /** Olympiad Battle Wait */
+    public static long ALT_OLY_BWAIT;
+
+    /** Olympiad Inital Wait */
+    public static long ALT_OLY_IWAIT;
+
+    /** Olympaid Weekly Period */
+    public static long ALT_OLY_WPERIOD;
+
+    /** Olympaid Validation Period */
+    public static long ALT_OLY_VPERIOD;
+
+    /** Manor Refresh Starting time */
+    public static int ALT_MANOR_REFRESH_TIME;
+
+    /** Manor Refresh Min */
+    public static int ALT_MANOR_REFRESH_MIN;
+
+    /** Manor Next Period Approve Starting time */
+    public static int ALT_MANOR_APPROVE_TIME;
+
+    /** Manor Next Period Approve Min */
+    public static int ALT_MANOR_APPROVE_MIN;
+
+    /** Manor Maintenance Time */
+    public static int ALT_MANOR_MAINTENANCE_PERIOD;
+
+    /** Manor Save All Actions */
+    public static boolean ALT_MANOR_SAVE_ALL_ACTIONS;
+
+    /** Manor Save Period Rate */
+    public static int ALT_MANOR_SAVE_PERIOD_RATE;
+
+    /** Initial Lottery prize */
+    public static int ALT_LOTTERY_PRIZE;
+
+    /** Lottery Ticket Price */
+    public static int ALT_LOTTERY_TICKET_PRICE;
+
+    /** What part of jackpot amount should receive characters who pick 5 wining numbers */
+    public static float ALT_LOTTERY_5_NUMBER_RATE;
+
+    /** What part of jackpot amount should receive characters who pick 4 wining numbers */
+    public static float ALT_LOTTERY_4_NUMBER_RATE;
+
+    /** What part of jackpot amount should receive characters who pick 3 wining numbers */
+    public static float ALT_LOTTERY_3_NUMBER_RATE;
+
+    /** How much adena receive characters who pick two or less of the winning number */
+    public static int ALT_LOTTERY_2_AND_1_NUMBER_PRIZE;
+
+    /** Minimum siz e of a party that may enter dimensional rift */
+    public static int RIFT_MIN_PARTY_SIZE;
+
+    /** Time in ms the party has to wait until the mobs spawn when entering a room */
+    public static int RIFT_SPAWN_DELAY;
+
+    /** Amount of random rift jumps before party is ported back */
+    public static int RIFT_MAX_JUMPS;
+
+    /** Random time between two jumps in dimensional rift - in seconds */
+    public static int RIFT_AUTO_JUMPS_TIME_MIN;
+    public static int RIFT_AUTO_JUMPS_TIME_MAX;
+
+    /** Dimensional Fragment cost for entering rift */
+    public static int RIFT_ENTER_COST_RECRUIT;
+    public static int RIFT_ENTER_COST_SOLDIER;
+    public static int RIFT_ENTER_COST_OFFICER;
+    public static int RIFT_ENTER_COST_CAPTAIN;
+    public static int RIFT_ENTER_COST_COMMANDER;
+    public static int RIFT_ENTER_COST_HERO;
+
+    /** time multiplier for boss room */
+    public static float RIFT_BOSS_ROOM_TIME_MUTIPLY;
+
+
+    /* **************************************************************************
+     * GM CONFIG General GM AccessLevel *
+     ************************************************************************* */
+    /** General GM access level */
+    public static int     GM_ACCESSLEVEL;
+    /** General GM Minimal AccessLevel */
+    public static int     GM_MIN;
+    /** Minimum privileges level for a GM to do Alt+G*/
+    public static int     GM_ALTG_MIN_LEVEL;
+    /** General GM AccessLevel to change announcements */
+    public static int     GM_ANNOUNCE;
+    /** General GM AccessLevel can /ban /unban */
+    public static int     GM_BAN;
+    /** General GM AccessLevel can /ban /unban for chat */
+    public static int     GM_BAN_CHAT;
+    /** General GM AccessLevel can /create_item and /gmshop */
+    public static int     GM_CREATE_ITEM;
+    /** General GM AccessLevel can /delete */
+    public static int     GM_DELETE;
+    /** General GM AccessLevel can /kick /disconnect */
+    public static int     GM_KICK;
+    /** General GM AccessLevel for access to GMMenu */
+    public static int     GM_MENU;
+    /** General GM AccessLevel to use god mode command */
+    public static int     GM_GODMODE;
+    /** General GM AccessLevel with character edit rights */
+    public static int     GM_CHAR_EDIT;
+    /** General GM AccessLevel with edit rights for other characters */
+    public static int     GM_CHAR_EDIT_OTHER;
+    /** General GM AccessLevel with character view rights */
+    public static int     GM_CHAR_VIEW;
+    /** General GM AccessLevel with NPC edit rights */
+    public static int     GM_NPC_EDIT;
+    public static int     GM_NPC_VIEW;
+    /** General GM AccessLevel to teleport to any location */
+    public static int     GM_TELEPORT;
+    /** General GM AccessLevel to teleport character to any location */
+    public static int     GM_TELEPORT_OTHER;
+    /** General GM AccessLevel to restart server */
+    public static int     GM_RESTART;
+    /** General GM AccessLevel for MonsterRace */
+    public static int     GM_MONSTERRACE;
+    /** General GM AccessLevel to ride Wyvern */
+    public static int     GM_RIDER;
+    /** General GM AccessLevel to unstuck without 5min delay */
+    public static int     GM_ESCAPE;
+    /** General GM AccessLevel to resurect fixed after death */
+    public static int     GM_FIXED;
+    /** General GM AccessLevel to create Path Nodes */
+    public static int     GM_CREATE_NODES;
+    /** General GM AccessLevel with Enchant rights */
+    public static int     GM_ENCHANT;
+    /** General GM AccessLevel to close/open Doors */
+    public static int     GM_DOOR;
+    /** General GM AccessLevel with Resurrection rights */
+    public static int     GM_RES;
+    /** General GM AccessLevel to attack in the peace zone */
+    public static int     GM_PEACEATTACK;
+    /** General GM AccessLevel to heal */
+    public static int     GM_HEAL;
+    /** General GM AccessLevel to unblock IPs detected as hack IPs */
+    public static int     GM_UNBLOCK;
+    /** General GM AccessLevel to use Cache commands */
+    public static int     GM_CACHE;
+    /** General GM AccessLevel to use test&st commands */
+    public static int     GM_TALK_BLOCK;
+    public static int     GM_TEST;
+    /** Disable transaction on AccessLevel **/
+    public static boolean GM_DISABLE_TRANSACTION;
+    /** GM transactions disabled from this range */
+    public static int     GM_TRANSACTION_MIN;
+    /** GM transactions disabled to this range */
+    public static int     GM_TRANSACTION_MAX;
+    /** Minimum level to allow a GM giving damage */
+    public static int     GM_CAN_GIVE_DAMAGE;
+    /** Minimum level to don't give Exp/Sp in party */
+    public static int     GM_DONT_TAKE_EXPSP;
+    /** Minimum level to don't take aggro */
+    public static int     GM_DONT_TAKE_AGGRO;
+
+    public static int GM_REPAIR = 75;
+
+    /* Rate control */
+    /** Rate for eXperience Point rewards */
+    public static float   RATE_XP;
+    /** Rate for Skill Point rewards */
+    public static float   RATE_SP;
+    /** Rate for party eXperience Point rewards */
+    public static float   RATE_PARTY_XP;
+    /** Rate for party Skill Point rewards */
+    public static float   RATE_PARTY_SP;
+    /** Rate for Quest rewards (XP and SP) */
+    public static float   RATE_QUESTS_REWARD;
+    /** Rate for drop adena */
+    public static float   RATE_DROP_ADENA;
+    /** Rate for cost of consumable */
+    public static float   RATE_CONSUMABLE_COST;
+    /** Rate for dropped items */
+    public static float   RATE_DROP_ITEMS;
+    /** Rate for spoiled items */
+    public static float   RATE_DROP_SPOIL;
+    /** Rate for manored items */
+    public static int   RATE_DROP_MANOR;
+    /** Rate for quest items */
+    public static float   RATE_DROP_QUEST;
+    /** Rate for karma and experience lose */
+    public static float   RATE_KARMA_EXP_LOST;
+    /** Rate siege guards prices */
+    public static float   RATE_SIEGE_GUARDS_PRICE;
+    /*Alternative Xp/Sp rewards, if not 0, then calculated as 2^((mob.level-player.level) / coef),
+     * A few examples for "AltGameExponentXp = 5." and "AltGameExponentSp = 3."
+     * diff = 0 (player and mob has the same level), XP bonus rate = 1, SP bonus rate = 1
+     * diff = 3 (mob is 3 levels above), XP bonus rate = 1.52, SP bonus rate = 2
+     * diff = 5 (mob is 5 levels above), XP bonus rate = 2, SP bonus rate = 3.17
+     * diff = -8 (mob is 8 levels below), XP bonus rate = 0.4, SP bonus rate = 0.16 */
+    /** Alternative eXperience Point rewards */
+    public static float   ALT_GAME_EXPONENT_XP;
+    /** Alternative Spirit Point rewards */
+    public static float   ALT_GAME_EXPONENT_SP;
+
+    /** Rate Common herbs */
+    public static float   RATE_DROP_COMMON_HERBS;
+    /** Rate MP/HP herbs */
+    public static float   RATE_DROP_MP_HP_HERBS;
+    /** Rate Common herbs */
+    public static float   RATE_DROP_GREATER_HERBS;
+    /** Rate Common herbs */
+    public static float   RATE_DROP_SUPERIOR_HERBS;
+    /** Rate Common herbs */
+    public static float   RATE_DROP_SPECIAL_HERBS;
+
+    // Player Drop Rate control
+    /** Limit for player drop */
+    public static int   PLAYER_DROP_LIMIT;
+    /** Rate for drop */
+    public static int   PLAYER_RATE_DROP;
+    /** Rate for player's item drop */
+    public static int   PLAYER_RATE_DROP_ITEM;
+    /** Rate for player's equipment drop */
+    public static int   PLAYER_RATE_DROP_EQUIP;
+    /** Rate for player's equipment and weapon drop */
+    public static int   PLAYER_RATE_DROP_EQUIP_WEAPON;
+
+    // Pet Rates (Multipliers)
+    /** Rate for experience rewards of the pet */
+    public static float         PET_XP_RATE;
+    /** Rate for food consumption of the pet */
+    public static int           PET_FOOD_RATE;
+    /** Rate for experience rewards of the Sin Eater */
+    public static float         SINEATER_XP_RATE;
+
+    // Karma Drop Rate control
+    /** Karma drop limit */
+    public static int   KARMA_DROP_LIMIT;
+    /** Karma drop rate */
+    public static int   KARMA_RATE_DROP;
+    /** Karma drop rate for item */
+    public static int   KARMA_RATE_DROP_ITEM;
+    /** Karma drop rate for equipment */
+    public static int   KARMA_RATE_DROP_EQUIP;
+    /** Karma drop rate for equipment and weapon */
+    public static int   KARMA_RATE_DROP_EQUIP_WEAPON;
+
+    /** Time after which item will auto-destroy */
+    public static int     AUTODESTROY_ITEM_AFTER;
+    /** Auto destroy herb time */
+    public static int     HERB_AUTO_DESTROY_TIME;
+    /** List of items that will not be destroyed (seperated by ",") */
+    public static String  PROTECTED_ITEMS;
+    /** List of items that will not be destroyed */
+    public static List<Integer> LIST_PROTECTED_ITEMS = new FastList<Integer>();
+
+    /** Auto destroy nonequipable items dropped by players */
+    public static boolean     DESTROY_DROPPED_PLAYER_ITEM;
+    /** Auto destroy equipable items dropped by players */
+    public static boolean     DESTROY_EQUIPABLE_PLAYER_ITEM;
+    /** Save items on ground for restoration on server restart */
+    public static boolean     SAVE_DROPPED_ITEM;
+    /** Empty table ItemsOnGround after load all items */
+    public static boolean     EMPTY_DROPPED_ITEM_TABLE_AFTER_LOAD;
+    /** Time interval to save into db items on ground */
+    public static int         SAVE_DROPPED_ITEM_INTERVAL;
+    /** Clear all items stored in ItemsOnGround table */
+    public static boolean     CLEAR_DROPPED_ITEM_TABLE;
+
+    /** Accept precise drop calculation ? */
+    public static boolean PRECISE_DROP_CALCULATION;
+    /** Accept multi-items drop ? */
+    public static boolean MULTIPLE_ITEM_DROP;
+
+    /** This is setting of experimental Client <--> Server Player coordinates synchronization<br>
+     * <b><u>Valeurs :</u></b>
+     * <li>0 - no synchronization at all</li>
+     * <li>1 - parcial synchronization Client --> Server only * using this option it is difficult for players
+     *         to bypass obstacles</li>
+     * <li>2 - parcial synchronization Server --> Client only</li>
+     * <li>3 - full synchronization Client <--> Server</li>
+     * <li>-1 - Old system: will synchronize Z only</li>
+     */
+    public static int     COORD_SYNCHRONIZE;
+
+    /** Period in days after which character is deleted */
+    public static int     DELETE_DAYS;
+
+    /** Datapack root directory */
+    public static File    DATAPACK_ROOT;
+
+    /** Maximum range mobs can randomly go from spawn point */
+    public static int MAX_DRIFT_RANGE;
+
+    /** Allow fishing ? */
+    public static boolean ALLOWFISHING;
+
+    /** Allow Manor system */
+    public static boolean ALLOW_MANOR;
+
+    /** Jail config **/
+    public static boolean JAIL_IS_PVP;
+    public static boolean JAIL_DISABLE_CHAT;
+
+
+    /** Enumeration describing values for Allowing the use of L2Walker client */
+    public static enum L2WalkerAllowed
+    {
+        True,
+        False,
+        GM
+    }
+
+    /** Allow the use of L2Walker client ? */
+    public static L2WalkerAllowed ALLOW_L2WALKER_CLIENT;
+    /** Auto-ban client that use L2Walker ? */
+    public static boolean         AUTOBAN_L2WALKER_ACC;
+    /** Revision of L2Walker */
+    public static int             L2WALKER_REVISION;
+
+    /** FloodProtector initial capacity */
+    public static int              FLOODPROTECTOR_INITIALSIZE;
+
+    /** Allow Discard item ?*/
+    public static boolean         ALLOW_DISCARDITEM;
+    /** Allow freight ? */
+    public static boolean         ALLOW_FREIGHT;
+    /** Allow warehouse ? */
+    public static boolean         ALLOW_WAREHOUSE;
+    /** Allow warehouse cache? */
+    public static boolean         WAREHOUSE_CACHE;
+    /** How long store WH datas */
+    public static int             WAREHOUSE_CACHE_TIME;
+    /** Allow wear ? (try on in shop) */
+    public static boolean           ALLOW_WEAR;
+    /** Duration of the try on after which items are taken back */
+    public static int               WEAR_DELAY;
+    /** Price of the try on of one item */
+    public static int               WEAR_PRICE;
+    /** Allow lottery ? */
+    public static boolean           ALLOW_LOTTERY;
+    /** Allow race ? */
+    public static boolean           ALLOW_RACE;
+    /** Allow water ? */
+    public static boolean           ALLOW_WATER;
+    /** Allow rent pet ? */
+    public static boolean         ALLOW_RENTPET;
+    /** Allow boat ? */
+    public static boolean           ALLOW_BOAT;
+    /** Allow cursed weapons ? */
+    public static boolean           ALLOW_CURSED_WEAPONS;
+
+    //WALKER NPC
+    public static boolean          ALLOW_NPC_WALKERS;
+    
+    /** Time after which a packet is considered as lost */
+    public static int             PACKET_LIFETIME;
+
+    // Pets
+    /** Speed of Weverns */
+    public static int WYVERN_SPEED;
+    /** Speed of Striders */
+    public static int STRIDER_SPEED;
+    /** Allow Wyvern Upgrader ? */
+    public static boolean ALLOW_WYVERN_UPGRADER;
+
+    // protocol revision
+    /** Minimal protocol revision */
+    public static int MIN_PROTOCOL_REVISION;
+    /** Maximal protocol revision */
+    public static int MAX_PROTOCOL_REVISION;
+
+    // random animation interval
+    /** Minimal time between 2 animations of a NPC */
+    public static int MIN_NPC_ANIMATION;
+    /** Maximal time between 2 animations of a NPC */
+    public static int MAX_NPC_ANIMATION;
+    /** Minimal time between animations of a MONSTER */
+    public static int MIN_MONSTER_ANIMATION;
+    /** Maximal time between animations of a MONSTER */
+    public static int MAX_MONSTER_ANIMATION;
+
+
+
+    /** Activate position recorder ? */
+    public static boolean ACTIVATE_POSITION_RECORDER;
+    /** Use 3D Map ? */
+    public static boolean USE_3D_MAP;
+
+    // Community Board
+    /** Type of community */
+    public static String COMMUNITY_TYPE;
+    public static String BBS_DEFAULT;
+    /** Show level of the community board ? */
+    public static boolean SHOW_LEVEL_COMMUNITYBOARD;
+    /** Show status of the community board ? */
+    public static boolean SHOW_STATUS_COMMUNITYBOARD;
+    /** Size of the name page on the community board */
+    public static int     NAME_PAGE_SIZE_COMMUNITYBOARD;
+    /** Name per row on community board */
+    public static int     NAME_PER_ROW_COMMUNITYBOARD;
+
+    // Configuration files
+    /** Properties file that allows selection of new Classes for storage of World Objects.
+     * <br>This may help servers with large amounts of players recieving error messages related to
+     * the <i>L2ObjectHashMap</i> and <i>L2ObejctHashSet</i> classes.*/
+    /** Properties file for game server (connection and ingame) configurations */
+    public static final String  CONFIGURATION_FILE          = "./config/server.properties";
+    /** Properties file for game server options */
+    public static final String  OPTIONS_FILE                = "./config/options.properties";
+    /** Properties file for login server configurations */
+    public static final String  LOGIN_CONFIGURATION_FILE    = "./config/loginserver.properties";
+    /** Properties file for the ID factory */
+    public static final String  ID_CONFIG_FILE                = "./config/idfactory.properties";
+    /** Properties file for other configurations */
+    public static final String  OTHER_CONFIG_FILE            = "./config/other.properties";
+    /** Properties file for rates configurations */
+    public static final String  RATES_CONFIG_FILE            = "./config/rates.properties";
+    /** Properties file for alternative configuration */
+    public static final String  ALT_SETTINGS_FILE            = "./config/altsettings.properties";
+    /** Properties file for PVP configurations */
+    public static final String  PVP_CONFIG_FILE                = "./config/pvp.properties";
+    /** Properties file for GM access configurations */
+    public static final String  GM_ACCESS_FILE                = "./config/GMAccess.properties";
+    /** Properties file for telnet configuration */
+    public static final String  TELNET_FILE                    = "./config/telnet.properties";
+    /** Properties file for l2j server version configurations */
+    public static final String  SERVER_VERSION_FILE            = "./config/l2j-version.properties";
+    /** Properties file for l2j datapack version configurations */
+    public static final String  DATAPACK_VERSION_FILE       = "./config/l2jdp-version.properties";
+    /** Properties file for siege configuration */
+    public static final String  SIEGE_CONFIGURATION_FILE    = "./config/siege.properties";
+    /** XML file for banned IP */
+    public static final String  BANNED_IP_XML                = "./config/banned.xml";
+    /** Text file containing hexadecimal value of server ID */
+    public static final String  HEXID_FILE                    = "./config/hexid.txt";
+    /** Properties file for alternative configure GM commands access level.<br>
+     * Note that this file only read if "AltPrivilegesAdmin = True" */
+    public static final String  COMMAND_PRIVILEGES_FILE     = "./config/command-privileges.properties";
+    /** Properties file for AI configurations */
+    public static final String  AI_FILE                     = "./config/ai.properties";
+    /** Properties file for 7 Signs Festival */
+    public static final String  SEVENSIGNS_FILE             = "./config/sevensigns.properties";
+    public static final String  CLANHALL_CONFIG_FILE        = "./config/clanhall.properties";
+    public static final String  L2JMOD_CONFIG_FILE            = "./config/l2jmods.properties";
+    public static int MAX_ITEM_IN_PACKET;
+
+    public static boolean CHECK_KNOWN;
+
+    /** Game Server login port */
+    public static int        GAME_SERVER_LOGIN_PORT;
+    /** Game Server login Host */
+    public static String     GAME_SERVER_LOGIN_HOST;
+    /** Internal Hostname */
+    public static String     INTERNAL_HOSTNAME;
+    /** External Hostname */
+    public static String     EXTERNAL_HOSTNAME;
+    public static int        PATH_NODE_RADIUS;
+    public static int        NEW_NODE_ID;
+    public static int        SELECTED_NODE_ID;
+    public static int        LINKED_NODE_ID;
+    public static String     NEW_NODE_TYPE;
+
+    /** Show "data/html/servnews.htm" whenever a character enters world.*/
+    public static boolean SERVER_NEWS;
+    /** Show L2Monster level and aggro ? */
+    public static boolean    SHOW_NPC_LVL;
+
+    /** Force full item inventory packet to be sent for any item change ?<br>
+     * <u><i>Note:</i></u> This can increase network traffic*/
+    public static boolean    FORCE_INVENTORY_UPDATE;
+    /** Disable the use of guards against agressive monsters ? */
+    public static boolean    ALLOW_GUARDS;
+    /** Allow use Event Managers for change occupation ?*/
+    public static boolean    ALLOW_CLASS_MASTERS;
+    /** Time between 2 updates of IP */
+    public static int        IP_UPDATE_TIME;
+
+    // Server version
+    /** Server version */
+    public static String     SERVER_VERSION;
+    /** Date of server build */
+    public static String     SERVER_BUILD_DATE;
+
+    // Datapack version
+    /** Datapack version */
+    public static String     DATAPACK_VERSION;
+
+    /** Zone Setting */
+    public static int ZONE_TOWN;
+
+    /** Crafting Enabled? */
+    public static boolean IS_CRAFTING_ENABLED;
+
+    // Inventory slots limit
+    /** Maximum inventory slots limits for non dwarf characters */
+    public static int INVENTORY_MAXIMUM_NO_DWARF;
+    /** Maximum inventory slots limits for dwarf characters */
+    public static int INVENTORY_MAXIMUM_DWARF;
+    /** Maximum inventory slots limits for GM */
+    public static int INVENTORY_MAXIMUM_GM;
+
+    // Warehouse slots limits
+    /** Maximum inventory slots limits for non dwarf warehouse */
+    public static int WAREHOUSE_SLOTS_NO_DWARF;
+    /** Maximum inventory slots limits for dwarf warehouse */
+    public static int WAREHOUSE_SLOTS_DWARF;
+    /** Maximum inventory slots limits for clan warehouse */
+    public static int WAREHOUSE_SLOTS_CLAN;
+    /** Maximum inventory slots limits for freight */
+    public static int FREIGHT_SLOTS;
+
+    // Karma System Variables
+    /** Minimum karma gain/loss */
+    public static int     KARMA_MIN_KARMA;
+    /** Maximum karma gain/loss */
+    public static int     KARMA_MAX_KARMA;
+    /** Number to divide the xp recieved by, to calculate karma lost on xp gain/lost */
+    public static int     KARMA_XP_DIVIDER;
+    /** The Minimum Karma lost if 0 karma is to be removed */
+    public static int     KARMA_LOST_BASE;
+    /** Can a GM drop item ? */
+    public static boolean KARMA_DROP_GM;
+    /** Should award a pvp point for killing a player with karma ? */
+    public static boolean KARMA_AWARD_PK_KILL;
+    /** Minimum PK required to drop */
+    public static int     KARMA_PK_LIMIT;
+
+    /** List of pet items that cannot be dropped (seperated by ",") when PVP */
+    public static String        KARMA_NONDROPPABLE_PET_ITEMS;
+    /** List of items that cannot be dropped (seperated by ",") when PVP*/
+    public static String        KARMA_NONDROPPABLE_ITEMS;
+    /** List of pet items that cannot be dropped when PVP */
+    public static List<Integer> KARMA_LIST_NONDROPPABLE_PET_ITEMS   = new FastList<Integer>();
+    /** List of items that cannot be dropped when PVP */
+    public static List<Integer> KARMA_LIST_NONDROPPABLE_ITEMS       = new FastList<Integer>();
+
+    /** List of items that cannot be dropped (seperated by ",") */
+    public static String        NONDROPPABLE_ITEMS;
+    /** List of items that cannot be dropped */
+    public static List<Integer> LIST_NONDROPPABLE_ITEMS       = new FastList<Integer>();
+
+    /** List of NPCs that rent pets (seperated by ",") */
+    public static String        PET_RENT_NPC;
+    /** List of NPCs that rent pets */
+    public static List<Integer> LIST_PET_RENT_NPC   = new FastList<Integer>();
+
+    /** Duration (in ms) while a player stay in PVP mode after hitting an innocent */
+    public static int PVP_NORMAL_TIME;
+    /** Duration (in ms) while a player stay in PVP mode after hitting a purple player */
+    public static int PVP_PVP_TIME;
+
+    // Karma Punishment
+    /** Allow player with karma to be killed in peace zone ? */
+    public static boolean ALT_GAME_KARMA_PLAYER_CAN_BE_KILLED_IN_PEACEZONE;
+    /** Allow player with karma to shop ? */
+    public static boolean ALT_GAME_KARMA_PLAYER_CAN_SHOP;
+    /** Allow player with karma to use gatekeepers ? */
+    public static boolean ALT_GAME_KARMA_PLAYER_CAN_USE_GK;
+    /** Allow player with karma to use SOE or Return skill ? */
+    public static boolean ALT_GAME_KARMA_PLAYER_CAN_TELEPORT;
+    /** Allow player with karma to trade ? */
+    public static boolean ALT_GAME_KARMA_PLAYER_CAN_TRADE;
+    /** Allow player with karma to use warehouse ?*/
+    public static boolean ALT_GAME_KARMA_PLAYER_CAN_USE_WAREHOUSE;
+
+    /**define L2JMODS */
+    /** Champion Mod*/
+    public static boolean L2JMOD_CHAMPION_ENABLE;
+    public static int L2JMOD_CHAMPION_FREQUENCY;
+    public static int L2JMOD_CHAMP_MIN_LVL;
+    public static int L2JMOD_CHAMP_MAX_LVL;
+    public static int L2JMOD_CHAMPION_HP;
+    public static int L2JMOD_CHAMPION_REWARDS;
+    public static int L2JMOD_CHAMPION_ADENAS_REWARDS;
+    public static float L2JMOD_CHAMPION_HP_REGEN;
+    public static float L2JMOD_CHAMPION_ATK;
+    public static float L2JMOD_CHAMPION_SPD_ATK;
+    public static int L2JMOD_CHAMPION_REWARD;
+    public static int L2JMOD_CHAMPION_REWARD_ID;
+    public static int L2JMOD_CHAMPION_REWARD_QTY;
+
+    /** Team vs. Team Event Engine */
+    public static boolean TVT_EVENT_ENABLED;
+    public static int TVT_EVENT_INTERVAL;
+    public static int TVT_EVENT_PARTICIPATION_TIME;
+    public static int TVT_EVENT_RUNNING_TIME;
+    public static int TVT_EVENT_PARTICIPATION_NPC_ID;
+    public static int[] TVT_EVENT_PARTICIPATION_NPC_COORDINATES = new int[3];
+    public static int TVT_EVENT_MIN_PLAYERS_IN_TEAMS;
+    public static int TVT_EVENT_MAX_PLAYERS_IN_TEAMS;
+    public static int TVT_EVENT_RESPAWN_TELEPORT_DELAY;
+    public static int TVT_EVENT_START_LEAVE_TELEPORT_DELAY;
+    public static String TVT_EVENT_TEAM_1_NAME;
+    public static int[] TVT_EVENT_TEAM_1_COORDINATES = new int[3];
+    public static String TVT_EVENT_TEAM_2_NAME;
+    public static int[] TVT_EVENT_TEAM_2_COORDINATES = new int[3];
+    public static List<int[]> TVT_EVENT_REWARDS = new FastList<int[]>();
+    public static boolean TVT_EVENT_TARGET_TEAM_MEMBERS_ALLOWED;
+    public static boolean TVT_EVENT_POTIONS_ALLOWED;
+    public static boolean TVT_EVENT_SUMMON_BY_ITEM_ALLOWED;
+    public static List<Integer> TVT_EVENT_DOOR_IDS = new FastList<Integer>();
+    public static byte TVT_EVENT_MIN_LVL;
+    public static byte TVT_EVENT_MAX_LVL;
+
+    /** L2JMOD Wedding system  */
+    public static boolean L2JMOD_ALLOW_WEDDING;
+    public static int L2JMOD_WEDDING_PRICE;
+    public static boolean L2JMOD_WEDDING_PUNISH_INFIDELITY;
+    public static boolean L2JMOD_WEDDING_TELEPORT;
+    public static int L2JMOD_WEDDING_TELEPORT_PRICE;
+    public static int L2JMOD_WEDDING_TELEPORT_DURATION;
+    public static boolean L2JMOD_WEDDING_SAMESEX;
+    public static boolean L2JMOD_WEDDING_FORMALWEAR;
+    public static int L2JMOD_WEDDING_DIVORCE_COSTS;
+
+    // Packet information
+    /** Count the amount of packets per minute ? */
+    public static boolean  COUNT_PACKETS           = false;
+    /** Dump packet count ? */
+    public static boolean  DUMP_PACKET_COUNTS      = false;
+    /** Time interval between 2 dumps */
+    public static int      DUMP_INTERVAL_SECONDS   = 60;
+
+    /** Enumeration for type of ID Factory */
+    public static enum IdFactoryType
+    {
+        Compaction,
+        BitSet,
+        Stack
+    }
+
+    /** ID Factory type */
+    public static IdFactoryType IDFACTORY_TYPE;
+    /** Check for bad ID ? */
+    public static boolean BAD_ID_CHECKING;
+
+    /** Enumeration for type of maps object */
+    public static enum ObjectMapType
+    {
+        L2ObjectHashMap,
+        WorldObjectMap
+    }
+
+    /** Enumeration for type of set object */
+    public static enum ObjectSetType
+    {
+        L2ObjectHashSet,
+        WorldObjectSet
+    }
+
+    /** Type of map object */
+    public static ObjectMapType   MAP_TYPE;
+    /** Type of set object */
+    public static ObjectSetType   SET_TYPE;
+
+    /**
+     * Allow lesser effects to be canceled if stronger effects are used when effects of the same stack group are used.<br>
+     * New effects that are added will be canceled if they are of lesser priority to the old one.
+     */
+    public static boolean EFFECT_CANCELING;
+
+    /** Auto-delete invalid quest data ? */
+    public static boolean AUTODELETE_INVALID_QUEST_DATA;
+
+    /** Chance that an item will succesfully be enchanted */
+    public static int ENCHANT_CHANCE_WEAPON;
+    public static int ENCHANT_CHANCE_ARMOR;
+    public static int ENCHANT_CHANCE_JEWELRY;
+    /** Maximum level of enchantment */
+    public static int ENCHANT_MAX_WEAPON;
+    public static int ENCHANT_MAX_ARMOR;
+    public static int ENCHANT_MAX_JEWELRY;
+    /** maximum level of safe enchantment for normal items*/
+    public static int ENCHANT_SAFE_MAX;
+    /** maximum level of safe enchantment for full body armor*/
+    public static int ENCHANT_SAFE_MAX_FULL;
+
+    // Character multipliers
+    /** Multiplier for character HP regeneration */
+    public static double  HP_REGEN_MULTIPLIER;
+    /** Mutilplier for character MP regeneration */
+    public static double  MP_REGEN_MULTIPLIER;
+    /** Multiplier for character CP regeneration */
+    public static double  CP_REGEN_MULTIPLIER;
+
+    // Raid Boss multipliers
+    /** Multiplier for Raid boss HP regeneration */
+    public static double   RAID_HP_REGEN_MULTIPLIER;
+    /** Mulitplier for Raid boss MP regeneration */
+    public static double   RAID_MP_REGEN_MULTIPLIER;
+    /** Multiplier for Raid boss defense multiplier */
+    public static double   RAID_DEFENCE_MULTIPLIER;
+    /** Raid Boss Minin Spawn Timer */
+    public static double   RAID_MINION_RESPAWN_TIMER;
+    /** Mulitplier for Raid boss minimum time respawn */
+    public static float   RAID_MIN_RESPAWN_MULTIPLIER;
+    /** Mulitplier for Raid boss maximum time respawn */
+    public static float   RAID_MAX_RESPAWN_MULTIPLIER;
+    /** Amount of adenas when starting a new character */
+    public static int STARTING_ADENA;
+
+    /** Deep Blue Mobs' Drop Rules Enabled */
+    public static boolean DEEPBLUE_DROP_RULES;
+    public static int     UNSTUCK_INTERVAL;
+
+    /** Is telnet enabled ? */
+    public static boolean IS_TELNET_ENABLED;
+
+    /** Death Penalty chance */
+    public static int   DEATH_PENALTY_CHANCE;
+
+    /** Player Protection control */
+    public static int   PLAYER_SPAWN_PROTECTION;
+    public static int   PLAYER_FAKEDEATH_UP_PROTECTION;
+
+    /** Define Party XP cutoff point method - Possible values: level and percentage */
+    public static String  PARTY_XP_CUTOFF_METHOD;
+    /** Define the cutoff point value for the "level" method */
+    public static int PARTY_XP_CUTOFF_LEVEL;
+    /** Define the cutoff point value for the "percentage" method */
+    public static double  PARTY_XP_CUTOFF_PERCENT;
+
+    /** Percent CP is restore on respawn */
+    public static double  RESPAWN_RESTORE_CP;
+    /** Percent HP is restore on respawn */
+    public static double  RESPAWN_RESTORE_HP;
+    /** Percent MP is restore on respawn */
+    public static double  RESPAWN_RESTORE_MP;
+    /** Allow randomizing of the respawn point in towns. */
+    public static boolean RESPAWN_RANDOM_ENABLED;
+    /** The maximum offset from the base respawn point to allow. */
+    public static int RESPAWN_RANDOM_MAX_OFFSET;
+
+    /** Maximum number of available slots for pvt stores (sell/buy) - Dwarves */
+    public static int  MAX_PVTSTORE_SLOTS_DWARF;
+    /** Maximum number of available slots for pvt stores (sell/buy) - Others */
+    public static int  MAX_PVTSTORE_SLOTS_OTHER;
+
+    /** Store skills cooltime on char exit/relogin */
+    public static boolean STORE_SKILL_COOLTIME;
+    /** Show licence or not just after login (if false, will directly go to the Server List */
+    public static boolean SHOW_LICENCE;
+    /** Force GameGuard authorization in loginserver */
+    public static boolean FORCE_GGAUTH;
+
+    /** Default punishment for illegal actions */
+    public static int DEFAULT_PUNISH;
+    /** Parameter for default punishment */
+    public static int DEFAULT_PUNISH_PARAM;
+
+    /** Accept new game server ? */
+    public static boolean ACCEPT_NEW_GAMESERVER;
+
+    /** Server ID used with the HexID */
+    public static int SERVER_ID;
+    /** Hexadecimal ID of the game server */
+    public static byte[] HEX_ID;
+
+    /** Accept alternate ID for server ? */
+    public static boolean ACCEPT_ALTERNATE_ID;
+    /** ID for request to the server */
+    public static int REQUEST_ID;
+    public static boolean RESERVE_HOST_ON_LOGIN = false;
+
+    public static int MINIMUM_UPDATE_DISTANCE;
+    public static int KNOWNLIST_FORGET_DELAY;
+    public static int MINIMUN_UPDATE_TIME;
+
+    public static boolean ANNOUNCE_MAMMON_SPAWN;
+    public static boolean LAZY_CACHE;
+
+    /** Enable colored name for GM ? */
+    public static boolean GM_NAME_COLOR_ENABLED;
+    /** Color of GM name */
+    public static int     GM_NAME_COLOR;
+    /** Color of admin name */
+    public static int     ADMIN_NAME_COLOR;
+    /** Place an aura around the GM ? */
+    public static boolean GM_HERO_AURA;
+    /** Set the GM invulnerable at startup ? */
+    public static boolean GM_STARTUP_INVULNERABLE;
+    /** Set the GM invisible at startup ? */
+    public static boolean GM_STARTUP_INVISIBLE;
+    /** Set silence to GM at startup ? */
+    public static boolean GM_STARTUP_SILENCE;
+    /** Add GM in the GM list at startup ? */
+    public static boolean GM_STARTUP_AUTO_LIST;
+    /** Change the way admin panel is shown */
+    public static String GM_ADMIN_MENU_STYLE;
+
+    /** Allow petition ? */
+    public static boolean PETITIONING_ALLOWED;
+    /** Maximum number of petitions per player */
+    public static int     MAX_PETITIONS_PER_PLAYER;
+    /** Maximum number of petitions pending */
+    public static int     MAX_PETITIONS_PENDING;
+
+
+    /** Bypass exploit protection ? */
+    public static boolean BYPASS_VALIDATION;
+
+    /** Only GM buy items for free**/
+    public static boolean ONLY_GM_ITEMS_FREE;
+
+    /** GM Audit ?*/
+    public static boolean GMAUDIT;
+
+    /** Allow auto-create account ? */
+    public static boolean AUTO_CREATE_ACCOUNTS;
+
+
+    public static boolean FLOOD_PROTECTION;
+    public static int     FAST_CONNECTION_LIMIT;
+    public static int     NORMAL_CONNECTION_TIME;
+    public static int     FAST_CONNECTION_TIME;
+    public static int     MAX_CONNECTION_PER_IP;
+
+    /** Enforce gameguard query on character login ? */
+    public static boolean GAMEGUARD_ENFORCE;
+    /** Don't allow player to perform trade,talk with npc and move until gameguard reply received ? */
+    public static boolean GAMEGUARD_PROHIBITACTION;
+
+    /** Recipebook limits */
+    public static int DWARF_RECIPE_LIMIT;
+    public static int COMMON_RECIPE_LIMIT;
+
+    /** Grid Options */
+    public static boolean GRIDS_ALWAYS_ON;
+    public static int GRID_NEIGHBOR_TURNON_TIME;
+    public static int GRID_NEIGHBOR_TURNOFF_TIME;
+
+    /** Clan Hall function related configs*/
+    public static long CH_TELE_FEE_RATIO;
+    public static int CH_TELE1_FEE;
+    public static int CH_TELE2_FEE;
+    public static long CH_ITEM_FEE_RATIO;
+    public static int CH_ITEM1_FEE;
+    public static int CH_ITEM2_FEE;
+    public static int CH_ITEM3_FEE;
+    public static long CH_MPREG_FEE_RATIO;
+    public static int CH_MPREG1_FEE;
+    public static int CH_MPREG2_FEE;
+    public static int CH_MPREG3_FEE;
+    public static int CH_MPREG4_FEE;
+    public static int CH_MPREG5_FEE;
+    public static long CH_HPREG_FEE_RATIO;
+    public static int CH_HPREG1_FEE;
+    public static int CH_HPREG2_FEE;
+    public static int CH_HPREG3_FEE;
+    public static int CH_HPREG4_FEE;
+    public static int CH_HPREG5_FEE;
+    public static int CH_HPREG6_FEE;
+    public static int CH_HPREG7_FEE;
+    public static int CH_HPREG8_FEE;
+    public static int CH_HPREG9_FEE;
+    public static int CH_HPREG10_FEE;
+    public static int CH_HPREG11_FEE;
+    public static int CH_HPREG12_FEE;
+    public static int CH_HPREG13_FEE;
+    public static long CH_EXPREG_FEE_RATIO;
+    public static int CH_EXPREG1_FEE;
+    public static int CH_EXPREG2_FEE;
+    public static int CH_EXPREG3_FEE;
+    public static int CH_EXPREG4_FEE;
+    public static int CH_EXPREG5_FEE;
+    public static int CH_EXPREG6_FEE;
+    public static int CH_EXPREG7_FEE;
+    public static long CH_SUPPORT_FEE_RATIO;
+    public static int CH_SUPPORT1_FEE;
+    public static int CH_SUPPORT2_FEE;
+    public static int CH_SUPPORT3_FEE;
+    public static int CH_SUPPORT4_FEE;
+    public static int CH_SUPPORT5_FEE;
+    public static int CH_SUPPORT6_FEE;
+    public static int CH_SUPPORT7_FEE;
+    public static int CH_SUPPORT8_FEE;
+    public static long CH_CURTAIN_FEE_RATIO;
+    public static int CH_CURTAIN1_FEE;
+    public static int CH_CURTAIN2_FEE;
+    public static long CH_FRONT_FEE_RATIO;
+    public static int CH_FRONT1_FEE;
+    public static int CH_FRONT2_FEE;
+
+    /** GeoData 0/1/2 */
+    public static int GEODATA;
+    /** Force loading GeoData to psychical memory */
+    public static boolean FORCE_GEODATA;
+    public static boolean ACCEPT_GEOEDITOR_CONN;
+
+    /** Max amount of buffs */
+    public static byte BUFFS_MAX_AMOUNT;
+
+    /** Alt Settings for devs */
+    public static boolean ALT_DEV_NO_QUESTS;
+    public static boolean ALT_DEV_NO_SPAWNS;
+
+
+    /**
+     * This class initializes all global variables for configuration.<br>
+     * If key doesn't appear in properties file, a default value is setting on by this class.
+     * @see CONFIGURATION_FILE (propertie file) for configuring your server.
+     */
+    public static void load()
+    {
+        if(Server.serverMode == Server.MODE_GAMESERVER)
+        {
+            _log.info("loading gameserver config");
+            try {
+                Properties serverSettings    = new Properties();
+                InputStream is               = new FileInputStream(new File(CONFIGURATION_FILE));
+                serverSettings.load(is);
+                is.close();
+
+                GAMESERVER_HOSTNAME     = serverSettings.getProperty("GameserverHostname");
+                PORT_GAME               = Integer.parseInt(serverSettings.getProperty("GameserverPort", "7777"));
+
+                EXTERNAL_HOSTNAME       = serverSettings.getProperty("ExternalHostname", "*");
+                INTERNAL_HOSTNAME       = serverSettings.getProperty("InternalHostname", "*");
+
+                GAME_SERVER_LOGIN_PORT  = Integer.parseInt(serverSettings.getProperty("LoginPort","9014"));
+                GAME_SERVER_LOGIN_HOST  = serverSettings.getProperty("LoginHost","127.0.0.1");
+
+                REQUEST_ID              = Integer.parseInt(serverSettings.getProperty("RequestServerID","0"));
+                ACCEPT_ALTERNATE_ID     = Boolean.parseBoolean(serverSettings.getProperty("AcceptAlternateID","True"));
+
+                DATABASE_DRIVER             = serverSettings.getProperty("Driver", "com.mysql.jdbc.Driver");
+                DATABASE_URL                = serverSettings.getProperty("URL", "jdbc:mysql://localhost/l2jdb");
+                DATABASE_LOGIN              = serverSettings.getProperty("Login", "root");
+                DATABASE_PASSWORD           = serverSettings.getProperty("Password", "");
+                DATABASE_MAX_CONNECTIONS    = Integer.parseInt(serverSettings.getProperty("MaximumDbConnections", "10"));
+
+                DATAPACK_ROOT           = new File(serverSettings.getProperty("DatapackRoot", ".")).getCanonicalFile();
+
+                CNAME_TEMPLATE          = serverSettings.getProperty("CnameTemplate", ".*");
+                PET_NAME_TEMPLATE       = serverSettings.getProperty("PetNameTemplate", ".*");
+
+                MAX_CHARACTERS_NUMBER_PER_ACCOUNT = Integer.parseInt(serverSettings.getProperty("CharMaxNumber", "0"));
+                MAXIMUM_ONLINE_USERS        = Integer.parseInt(serverSettings.getProperty("MaximumOnlineUsers", "100"));
+
+                MIN_PROTOCOL_REVISION   = Integer.parseInt(serverSettings.getProperty("MinProtocolRevision", "660"));
+                MAX_PROTOCOL_REVISION   = Integer.parseInt(serverSettings.getProperty("MaxProtocolRevision", "665"));
+
+                if (MIN_PROTOCOL_REVISION > MAX_PROTOCOL_REVISION)
+                {
+                    throw new Error("MinProtocolRevision is bigger than MaxProtocolRevision in server configuration file.");
+                }
+            }
+            catch (Exception e)
+            {
+                e.printStackTrace();
+                throw new Error("Failed to Load "+CONFIGURATION_FILE+" File.");
+            }
+            try
+            {
+                Properties optionsSettings    = new Properties();
+                InputStream is               = new FileInputStream(new File(OPTIONS_FILE));
+                optionsSettings.load(is);
+                is.close();
+
+                EVERYBODY_HAS_ADMIN_RIGHTS      = Boolean.parseBoolean(optionsSettings.getProperty("EverybodyHasAdminRights", "false"));
+
+                DEBUG                           = Boolean.parseBoolean(optionsSettings.getProperty("Debug", "false"));
+                ASSERT                          = Boolean.parseBoolean(optionsSettings.getProperty("Assert", "false"));
+                DEVELOPER                       = Boolean.parseBoolean(optionsSettings.getProperty("Developer", "false"));
+                TEST_SERVER                     = Boolean.parseBoolean(optionsSettings.getProperty("TestServer", "false"));
+                SERVER_LIST_TESTSERVER          = Boolean.parseBoolean(optionsSettings.getProperty("TestServer", "false"));
+
+                SERVER_LIST_BRACKET             = Boolean.valueOf(optionsSettings.getProperty("ServerListBrackets", "false"));
+                SERVER_LIST_CLOCK               = Boolean.valueOf(optionsSettings.getProperty("ServerListClock", "false"));
+                SERVER_GMONLY                   = Boolean.valueOf(optionsSettings.getProperty("ServerGMOnly", "false"));
+
+                AUTODESTROY_ITEM_AFTER          = Integer.parseInt(optionsSettings.getProperty("AutoDestroyDroppedItemAfter", "0"));
+                HERB_AUTO_DESTROY_TIME          = Integer.parseInt(optionsSettings.getProperty("AutoDestroyHerbTime","15"))*1000;
+                PROTECTED_ITEMS                    = optionsSettings.getProperty("ListOfProtectedItems");
+                LIST_PROTECTED_ITEMS = new FastList<Integer>();
+                for (String id : PROTECTED_ITEMS.split(",")) {
+                    LIST_PROTECTED_ITEMS.add(Integer.parseInt(id));
+                }
+                DESTROY_DROPPED_PLAYER_ITEM        = Boolean.valueOf(optionsSettings.getProperty("DestroyPlayerDroppedItem", "false"));
+                DESTROY_EQUIPABLE_PLAYER_ITEM    = Boolean.valueOf(optionsSettings.getProperty("DestroyEquipableItem", "false"));
+                SAVE_DROPPED_ITEM                = Boolean.valueOf(optionsSettings.getProperty("SaveDroppedItem", "false"));
+                EMPTY_DROPPED_ITEM_TABLE_AFTER_LOAD    = Boolean.valueOf(optionsSettings.getProperty("EmptyDroppedItemTableAfterLoad", "false"));
+                SAVE_DROPPED_ITEM_INTERVAL        = Integer.parseInt(optionsSettings.getProperty("SaveDroppedItemInterval", "0"))*60000;
+                CLEAR_DROPPED_ITEM_TABLE        = Boolean.valueOf(optionsSettings.getProperty("ClearDroppedItemTable", "false"));
+
+                PRECISE_DROP_CALCULATION        = Boolean.valueOf(optionsSettings.getProperty("PreciseDropCalculation", "True"));
+                MULTIPLE_ITEM_DROP              = Boolean.valueOf(optionsSettings.getProperty("MultipleItemDrop", "True"));
+
+                COORD_SYNCHRONIZE               = Integer.parseInt(optionsSettings.getProperty("CoordSynchronize", "-1"));
+
+                ONLY_GM_ITEMS_FREE                = Boolean.valueOf(optionsSettings.getProperty("OnlyGMItemsFree", "True"));
+
+                ALLOW_WAREHOUSE                 = Boolean.valueOf(optionsSettings.getProperty("AllowWarehouse", "True"));
+                WAREHOUSE_CACHE                 = Boolean.valueOf(optionsSettings.getProperty("WarehouseCache", "False"));
+                WAREHOUSE_CACHE_TIME            = Integer.parseInt(optionsSettings.getProperty("WarehouseCacheTime", "15"));
+                ALLOW_FREIGHT                   = Boolean.valueOf(optionsSettings.getProperty("AllowFreight", "True"));
+                ALLOW_WEAR                      = Boolean.valueOf(optionsSettings.getProperty("AllowWear", "False"));
+                WEAR_DELAY                      = Integer.parseInt(optionsSettings.getProperty("WearDelay", "5"));
+                WEAR_PRICE                      = Integer.parseInt(optionsSettings.getProperty("WearPrice", "10"));
+                ALLOW_LOTTERY                   = Boolean.valueOf(optionsSettings.getProperty("AllowLottery", "False"));
+                ALLOW_RACE                      = Boolean.valueOf(optionsSettings.getProperty("AllowRace", "False"));
+                ALLOW_WATER                     = Boolean.valueOf(optionsSettings.getProperty("AllowWater", "False"));
+                ALLOW_RENTPET                   = Boolean.valueOf(optionsSettings.getProperty("AllowRentPet", "False"));
+                FLOODPROTECTOR_INITIALSIZE        = Integer.parseInt(optionsSettings.getProperty("FloodProtectorInitialSize", "50"));
+                ALLOW_DISCARDITEM               = Boolean.valueOf(optionsSettings.getProperty("AllowDiscardItem", "True"));
+                ALLOWFISHING                    = Boolean.valueOf(optionsSettings.getProperty("AllowFishing", "False"));
+                ALLOW_MANOR                     = Boolean.parseBoolean(optionsSettings.getProperty("AllowManor", "False"));
+                ALLOW_BOAT                      = Boolean.valueOf(optionsSettings.getProperty("AllowBoat", "False"));
+                ALLOW_NPC_WALKERS               = Boolean.valueOf(optionsSettings.getProperty("AllowNpcWalkers", "true"));
+                ALLOW_CURSED_WEAPONS            = Boolean.valueOf(optionsSettings.getProperty("AllowCursedWeapons", "False"));
+
+                ALLOW_L2WALKER_CLIENT           = L2WalkerAllowed.valueOf(optionsSettings.getProperty("AllowL2Walker", "False"));
+                L2WALKER_REVISION               = Integer.parseInt(optionsSettings.getProperty("L2WalkerRevision", "537"));
+                AUTOBAN_L2WALKER_ACC            = Boolean.valueOf(optionsSettings.getProperty("AutobanL2WalkerAcc", "False"));
+
+                ACTIVATE_POSITION_RECORDER      = Boolean.valueOf(optionsSettings.getProperty("ActivatePositionRecorder", "False"));
+
+                DEFAULT_GLOBAL_CHAT             = optionsSettings.getProperty("GlobalChat", "ON");
+                DEFAULT_TRADE_CHAT              = optionsSettings.getProperty("TradeChat", "ON");
+
+                LOG_CHAT                        = Boolean.valueOf(optionsSettings.getProperty("LogChat", "false"));
+                LOG_ITEMS                       = Boolean.valueOf(optionsSettings.getProperty("LogItems", "false"));
+
+                GMAUDIT                         = Boolean.valueOf(optionsSettings.getProperty("GMAudit", "False"));
+
+                COMMUNITY_TYPE                  = optionsSettings.getProperty("CommunityType", "old").toLowerCase();
+                BBS_DEFAULT                     = optionsSettings.getProperty("BBSDefault", "_bbshome");
+                SHOW_LEVEL_COMMUNITYBOARD       = Boolean.valueOf(optionsSettings.getProperty("ShowLevelOnCommunityBoard", "False"));
+                SHOW_STATUS_COMMUNITYBOARD      = Boolean.valueOf(optionsSettings.getProperty("ShowStatusOnCommunityBoard", "True"));
+                NAME_PAGE_SIZE_COMMUNITYBOARD   = Integer.parseInt(optionsSettings.getProperty("NamePageSizeOnCommunityBoard", "50"));
+                NAME_PER_ROW_COMMUNITYBOARD     = Integer.parseInt(optionsSettings.getProperty("NamePerRowOnCommunityBoard", "5"));
+
+                ZONE_TOWN                       = Integer.parseInt(optionsSettings.getProperty("ZoneTown", "0"));
+
+                MAX_DRIFT_RANGE                 = Integer.parseInt(optionsSettings.getProperty("MaxDriftRange", "300"));
+
+                MIN_NPC_ANIMATION               = Integer.parseInt(optionsSettings.getProperty("MinNPCAnimation", "10"));
+                MAX_NPC_ANIMATION               = Integer.parseInt(optionsSettings.getProperty("MaxNPCAnimation", "20"));
+                MIN_MONSTER_ANIMATION           = Integer.parseInt(optionsSettings.getProperty("MinMonsterAnimation", "5"));
+                MAX_MONSTER_ANIMATION           = Integer.parseInt(optionsSettings.getProperty("MaxMonsterAnimation", "20"));
+ 
+                
+                SERVER_NEWS                     = Boolean.valueOf(optionsSettings.getProperty("ShowServerNews", "False"));
+                SHOW_NPC_LVL                    = Boolean.valueOf(optionsSettings.getProperty("ShowNpcLevel", "False"));
+
+                FORCE_INVENTORY_UPDATE          = Boolean.valueOf(optionsSettings.getProperty("ForceInventoryUpdate", "False"));
+
+                AUTODELETE_INVALID_QUEST_DATA   = Boolean.valueOf(optionsSettings.getProperty("AutoDeleteInvalidQuestData", "False"));
+
+                THREAD_P_EFFECTS                = Integer.parseInt(optionsSettings.getProperty("ThreadPoolSizeEffects", "6"));
+                THREAD_P_GENERAL                = Integer.parseInt(optionsSettings.getProperty("ThreadPoolSizeGeneral", "15"));
+                GENERAL_PACKET_THREAD_CORE_SIZE         = Integer.parseInt(optionsSettings.getProperty("GeneralPacketThreadCoreSize", "4"));
+                IO_PACKET_THREAD_CORE_SIZE          =Integer.parseInt(optionsSettings.getProperty("UrgentPacketThreadCoreSize", "2"));
+                AI_MAX_THREAD                   = Integer.parseInt(optionsSettings.getProperty("AiMaxThread", "10"));
+                GENERAL_THREAD_CORE_SIZE        = Integer.parseInt(optionsSettings.getProperty("GeneralThreadCoreSize", "4"));
+
+                DELETE_DAYS                     = Integer.parseInt(optionsSettings.getProperty("DeleteCharAfterDays", "7"));
+
+                DEFAULT_PUNISH                  = Integer.parseInt(optionsSettings.getProperty("DefaultPunish", "2"));
+                DEFAULT_PUNISH_PARAM            = Integer.parseInt(optionsSettings.getProperty("DefaultPunishParam", "0"));
+
+                LAZY_CACHE                      = Boolean.valueOf(optionsSettings.getProperty("LazyCache", "False"));
+
+                PACKET_LIFETIME                 = Integer.parseInt(optionsSettings.getProperty("PacketLifeTime", "0"));
+
+                BYPASS_VALIDATION               = Boolean.valueOf(optionsSettings.getProperty("BypassValidation", "True"));
+
+                GAMEGUARD_ENFORCE               = Boolean.valueOf(optionsSettings.getProperty("GameGuardEnforce", "False"));
+                GAMEGUARD_PROHIBITACTION        = Boolean.valueOf(optionsSettings.getProperty("GameGuardProhibitAction", "False"));
+
+                GRIDS_ALWAYS_ON                 = Boolean.parseBoolean(optionsSettings.getProperty("GridsAlwaysOn", "False"));
+                GRID_NEIGHBOR_TURNON_TIME       = Integer.parseInt(optionsSettings.getProperty("GridNeighborTurnOnTime", "30"));
+                GRID_NEIGHBOR_TURNOFF_TIME      = Integer.parseInt(optionsSettings.getProperty("GridNeighborTurnOffTime", "300"));
+
+                GEODATA                         = Integer.parseInt(optionsSettings.getProperty("GeoData", "0"));
+                FORCE_GEODATA                   = Boolean.parseBoolean(optionsSettings.getProperty("ForceGeoData", "True"));
+                ACCEPT_GEOEDITOR_CONN           = Boolean.parseBoolean(optionsSettings.getProperty("AcceptGeoeditorConn", "False"));
+
+                // ---------------------------------------------------
+                // Configuration values not found in config files
+                // ---------------------------------------------------
+
+                USE_3D_MAP                      = Boolean.valueOf(optionsSettings.getProperty("Use3DMap", "False"));
+
+                PATH_NODE_RADIUS                = Integer.parseInt(optionsSettings.getProperty("PathNodeRadius", "50"));
+                NEW_NODE_ID                     = Integer.parseInt(optionsSettings.getProperty("NewNodeId", "7952"));
+                SELECTED_NODE_ID                = Integer.parseInt(optionsSettings.getProperty("NewNodeId", "7952"));
+                LINKED_NODE_ID                  = Integer.parseInt(optionsSettings.getProperty("NewNodeId", "7952"));
+                NEW_NODE_TYPE                   = optionsSettings.getProperty("NewNodeType", "npc");
+
+                COUNT_PACKETS                   = Boolean.valueOf(optionsSettings.getProperty("CountPacket", "false"));
+                DUMP_PACKET_COUNTS              = Boolean.valueOf(optionsSettings.getProperty("DumpPacketCounts", "false"));
+                DUMP_INTERVAL_SECONDS           = Integer.parseInt(optionsSettings.getProperty("PacketDumpInterval", "60"));
+
+                MINIMUM_UPDATE_DISTANCE         = Integer.parseInt(optionsSettings.getProperty("MaximumUpdateDistance", "50"));
+                MINIMUN_UPDATE_TIME             = Integer.parseInt(optionsSettings.getProperty("MinimumUpdateTime", "500"));
+                CHECK_KNOWN                     = Boolean.valueOf(optionsSettings.getProperty("CheckKnownList", "false"));
+                KNOWNLIST_FORGET_DELAY          = Integer.parseInt(optionsSettings.getProperty("KnownListForgetDelay", "10000"));
+            }
+            catch (Exception e)
+            {
+                e.printStackTrace();
+                throw new Error("Failed to Load "+OPTIONS_FILE+" File.");
+            }
+
+            /*
+             * Load L2J Server Version Properties file (if exists)
+             */
+            try
+            {
+                Properties serverVersion    = new Properties();
+                InputStream is              = new FileInputStream(new File(SERVER_VERSION_FILE));
+                serverVersion.load(is);
+                is.close();
+
+                SERVER_VERSION      = serverVersion.getProperty("version", "Unsupported Custom Version.");
+                SERVER_BUILD_DATE   = serverVersion.getProperty("builddate", "Undefined Date.");
+            }
+            catch (Exception e)
+            {
+                //Ignore Properties file if it doesnt exist
+                SERVER_VERSION      = "Unsupported Custom Version.";
+                SERVER_BUILD_DATE   = "Undefined Date.";
+            }
+
+            /*
+             * Load L2J Datapack Version Properties file (if exists)
+             */
+            try
+            {
+                Properties serverVersion    = new Properties();
+                InputStream is              = new FileInputStream(new File(DATAPACK_VERSION_FILE));
+                serverVersion.load(is);
+                is.close();
+
+                DATAPACK_VERSION      = serverVersion.getProperty("version", "Unsupported Custom Version.");
+            }
+            catch (Exception e)
+            {
+                //Ignore Properties file if it doesnt exist
+                DATAPACK_VERSION      = "Unsupported Custom Version.";
+            }
+
+            // telnet
+            try
+            {
+                Properties telnetSettings   = new Properties();
+                InputStream is              = new FileInputStream(new File(TELNET_FILE));
+                telnetSettings.load(is);
+                is.close();
+
+                IS_TELNET_ENABLED   = Boolean.valueOf(telnetSettings.getProperty("EnableTelnet", "false"));
+            }
+            catch (Exception e)
+            {
+                e.printStackTrace();
+                throw new Error("Failed to Load "+TELNET_FILE+" File.");
+            }
+
+            // id factory
+            try
+            {
+                Properties idSettings   = new Properties();
+                InputStream is          = new FileInputStream(new File(ID_CONFIG_FILE));
+                idSettings.load(is);
+                is.close();
+
+                MAP_TYPE        = ObjectMapType.valueOf(idSettings.getProperty("L2Map", "WorldObjectMap"));
+                SET_TYPE        = ObjectSetType.valueOf(idSettings.getProperty("L2Set", "WorldObjectSet"));
+                IDFACTORY_TYPE  = IdFactoryType.valueOf(idSettings.getProperty("IDFactory", "Compaction"));
+                BAD_ID_CHECKING = Boolean.valueOf(idSettings.getProperty("BadIdChecking", "True"));
+            }
+            catch (Exception e)
+            {
+                e.printStackTrace();
+                throw new Error("Failed to Load "+ID_CONFIG_FILE+" File.");
+            }
+
+            // other
+            try
+            {
+                Properties otherSettings    = new Properties();
+                InputStream is              = new FileInputStream(new File(OTHER_CONFIG_FILE));
+                otherSettings.load(is);
+                is.close();
+
+                DEEPBLUE_DROP_RULES = Boolean.parseBoolean(otherSettings.getProperty("UseDeepBlueDropRules", "True"));
+                ALLOW_GUARDS        = Boolean.valueOf(otherSettings.getProperty("AllowGuards", "False"));
+                EFFECT_CANCELING    = Boolean.valueOf(otherSettings.getProperty("CancelLesserEffect", "True"));
+                WYVERN_SPEED        = Integer.parseInt(otherSettings.getProperty("WyvernSpeed", "100"));
+                STRIDER_SPEED       = Integer.parseInt(otherSettings.getProperty("StriderSpeed", "80"));
+                ALLOW_WYVERN_UPGRADER     = Boolean.valueOf(otherSettings.getProperty("AllowWyvernUpgrader", "False"));
+
+                /* Inventory slots limits */
+                INVENTORY_MAXIMUM_NO_DWARF  = Integer.parseInt(otherSettings.getProperty("MaximumSlotsForNoDwarf", "80"));
+                INVENTORY_MAXIMUM_DWARF  = Integer.parseInt(otherSettings.getProperty("MaximumSlotsForDwarf", "100"));
+                INVENTORY_MAXIMUM_GM    = Integer.parseInt(otherSettings.getProperty("MaximumSlotsForGMPlayer", "250"));
+                MAX_ITEM_IN_PACKET = Math.max(INVENTORY_MAXIMUM_NO_DWARF, Math.max(INVENTORY_MAXIMUM_DWARF, INVENTORY_MAXIMUM_GM));
+
+                /* Inventory slots limits */
+                WAREHOUSE_SLOTS_NO_DWARF = Integer.parseInt(otherSettings.getProperty("MaximumWarehouseSlotsForNoDwarf", "100"));
+                WAREHOUSE_SLOTS_DWARF = Integer.parseInt(otherSettings.getProperty("MaximumWarehouseSlotsForDwarf", "120"));
+                WAREHOUSE_SLOTS_CLAN = Integer.parseInt(otherSettings.getProperty("MaximumWarehouseSlotsForClan", "150"));
+                FREIGHT_SLOTS       = Integer.parseInt(otherSettings.getProperty("MaximumFreightSlots", "20"));
+
+
+                /* chance to enchant an item over +3 */
+                ENCHANT_CHANCE_WEAPON  = Integer.parseInt(otherSettings.getProperty("EnchantChanceWeapon", "68"));
+                ENCHANT_CHANCE_ARMOR  = Integer.parseInt(otherSettings.getProperty("EnchantChanceArmor", "52"));
+                ENCHANT_CHANCE_JEWELRY  = Integer.parseInt(otherSettings.getProperty("EnchantChanceJewelry", "54"));
+                /* limit on enchant */
+                ENCHANT_MAX_WEAPON = Integer.parseInt(otherSettings.getProperty("EnchantMaxWeapon", "255"));
+                ENCHANT_MAX_ARMOR = Integer.parseInt(otherSettings.getProperty("EnchantMaxArmor", "255"));
+                ENCHANT_MAX_JEWELRY = Integer.parseInt(otherSettings.getProperty("EnchantMaxJewelry", "255"));
+                /*limit of safe enchant normal */
+                ENCHANT_SAFE_MAX = Integer.parseInt(otherSettings.getProperty("EnchantSafeMax", "3"));
+                /*limit of safe enchant full */
+                ENCHANT_SAFE_MAX_FULL = Integer.parseInt(otherSettings.getProperty("EnchantSafeMaxFull", "4"));
+
+                /* if different from 100 (ie 100%) heal rate is modified acordingly */
+                HP_REGEN_MULTIPLIER = Double.parseDouble(otherSettings.getProperty("HpRegenMultiplier", "100")) /100;
+                MP_REGEN_MULTIPLIER = Double.parseDouble(otherSettings.getProperty("MpRegenMultiplier", "100")) /100;
+                CP_REGEN_MULTIPLIER = Double.parseDouble(otherSettings.getProperty("CpRegenMultiplier", "100")) /100;
+
+                RAID_HP_REGEN_MULTIPLIER  = Double.parseDouble(otherSettings.getProperty("RaidHpRegenMultiplier", "100")) /100;
+                RAID_MP_REGEN_MULTIPLIER  = Double.parseDouble(otherSettings.getProperty("RaidMpRegenMultiplier", "100")) /100;
+                RAID_DEFENCE_MULTIPLIER  = Double.parseDouble(otherSettings.getProperty("RaidDefenceMultiplier", "100")) /100;
+                RAID_MINION_RESPAWN_TIMER  = Integer.parseInt(otherSettings.getProperty("RaidMinionRespawnTime", "300000"));
+                RAID_MIN_RESPAWN_MULTIPLIER = Float.parseFloat(otherSettings.getProperty("RaidMinRespawnMultiplier", "1.0"));
+                RAID_MAX_RESPAWN_MULTIPLIER = Float.parseFloat(otherSettings.getProperty("RaidMaxRespawnMultiplier", "1.0"));
+
+                STARTING_ADENA      = Integer.parseInt(otherSettings.getProperty("StartingAdena", "100"));
+                UNSTUCK_INTERVAL    = Integer.parseInt(otherSettings.getProperty("UnstuckInterval", "300"));
+
+                /* Player protection after teleport or login */
+                PLAYER_SPAWN_PROTECTION = Integer.parseInt(otherSettings.getProperty("PlayerSpawnProtection", "0"));
+
+                /* Player protection after recovering from fake death (works against mobs only) */
+                PLAYER_FAKEDEATH_UP_PROTECTION = Integer.parseInt(otherSettings.getProperty("PlayerFakeDeathUpProtection", "0"));
+
+                /* Defines some Party XP related values */
+                PARTY_XP_CUTOFF_METHOD  = otherSettings.getProperty("PartyXpCutoffMethod", "percentage");
+                PARTY_XP_CUTOFF_PERCENT = Double.parseDouble(otherSettings.getProperty("PartyXpCutoffPercent", "3."));
+                PARTY_XP_CUTOFF_LEVEL   = Integer.parseInt(otherSettings.getProperty("PartyXpCutoffLevel", "30"));
+
+                /* Amount of HP, MP, and CP is restored */
+                RESPAWN_RESTORE_CP = Double.parseDouble(otherSettings.getProperty("RespawnRestoreCP", "0")) / 100;
+                RESPAWN_RESTORE_HP = Double.parseDouble(otherSettings.getProperty("RespawnRestoreHP", "70")) / 100;
+                RESPAWN_RESTORE_MP = Double.parseDouble(otherSettings.getProperty("RespawnRestoreMP", "70")) / 100;
+
+                RESPAWN_RANDOM_ENABLED = Boolean.parseBoolean(otherSettings.getProperty("RespawnRandomInTown", "False"));
+                RESPAWN_RANDOM_MAX_OFFSET = Integer.parseInt(otherSettings.getProperty("RespawnRandomMaxOffset", "50"));
+
+                /* Maximum number of available slots for pvt stores */
+                MAX_PVTSTORE_SLOTS_DWARF = Integer.parseInt(otherSettings.getProperty("MaxPvtStoreSlotsDwarf", "5"));
+                MAX_PVTSTORE_SLOTS_OTHER = Integer.parseInt(otherSettings.getProperty("MaxPvtStoreSlotsOther", "4"));
+
+                STORE_SKILL_COOLTIME = Boolean.parseBoolean(otherSettings.getProperty("StoreSkillCooltime", "true"));
+
+                PET_RENT_NPC =  otherSettings.getProperty("ListPetRentNpc", "30827");
+                LIST_PET_RENT_NPC = new FastList<Integer>();
+                for (String id : PET_RENT_NPC.split(",")) {
+                    LIST_PET_RENT_NPC.add(Integer.parseInt(id));
+                }
+                NONDROPPABLE_ITEMS        = otherSettings.getProperty("ListOfNonDroppableItems", "1147,425,1146,461,10,2368,7,6,2370,2369,5598");
+
+                LIST_NONDROPPABLE_ITEMS = new FastList<Integer>();
+                for (String id : NONDROPPABLE_ITEMS.split(",")) {
+                    LIST_NONDROPPABLE_ITEMS.add(Integer.parseInt(id));
+                }
+
+                ANNOUNCE_MAMMON_SPAWN = Boolean.parseBoolean(otherSettings.getProperty("AnnounceMammonSpawn", "True"));
+
+                ALT_PRIVILEGES_ADMIN = Boolean.parseBoolean(otherSettings.getProperty("AltPrivilegesAdmin", "False"));
+                ALT_PRIVILEGES_SECURE_CHECK = Boolean.parseBoolean(otherSettings.getProperty("AltPrivilegesSecureCheck", "True"));
+                ALT_PRIVILEGES_DEFAULT_LEVEL = Integer.parseInt(otherSettings.getProperty("AltPrivilegesDefaultLevel", "100"));
+
+                GM_NAME_COLOR_ENABLED = Boolean.parseBoolean(otherSettings.getProperty("GMNameColorEnabled", "False"));
+                GM_NAME_COLOR = Integer.decode("0x" + otherSettings.getProperty("GMNameColor", "FFFF00"));
+                ADMIN_NAME_COLOR = Integer.decode("0x" + otherSettings.getProperty("AdminNameColor", "00FF00"));
+                GM_HERO_AURA = Boolean.parseBoolean(otherSettings.getProperty("GMHeroAura", "True"));
+                GM_STARTUP_INVULNERABLE = Boolean.parseBoolean(otherSettings.getProperty("GMStartupInvulnerable", "True"));
+                GM_STARTUP_INVISIBLE = Boolean.parseBoolean(otherSettings.getProperty("GMStartupInvisible", "True"));
+                GM_STARTUP_SILENCE = Boolean.parseBoolean(otherSettings.getProperty("GMStartupSilence", "True"));
+                GM_STARTUP_AUTO_LIST = Boolean.parseBoolean(otherSettings.getProperty("GMStartupAutoList", "True"));
+                GM_ADMIN_MENU_STYLE = otherSettings.getProperty("GMAdminMenuStyle", "modern");
+
+
+                PETITIONING_ALLOWED = Boolean.parseBoolean(otherSettings.getProperty("PetitioningAllowed", "True"));
+                MAX_PETITIONS_PER_PLAYER = Integer.parseInt(otherSettings.getProperty("MaxPetitionsPerPlayer", "5"));
+                MAX_PETITIONS_PENDING = Integer.parseInt(otherSettings.getProperty("MaxPetitionsPending", "25"));
+
+                JAIL_IS_PVP       = Boolean.valueOf(otherSettings.getProperty("JailIsPvp", "True"));
+                JAIL_DISABLE_CHAT = Boolean.valueOf(otherSettings.getProperty("JailDisableChat", "True"));
+
+                DEATH_PENALTY_CHANCE = Integer.parseInt(otherSettings.getProperty("DeathPenaltyChance", "20"));
+            }
+            catch (Exception e)
+            {
+                e.printStackTrace();
+                throw new Error("Failed to Load "+OTHER_CONFIG_FILE+" File.");
+            }
+
+            // rates
+            try
+            {
+                Properties ratesSettings    = new Properties();
+                InputStream is              = new FileInputStream(new File(RATES_CONFIG_FILE));
+                ratesSettings.load(is);
+                is.close();
+
+                RATE_XP                         = Float.parseFloat(ratesSettings.getProperty("RateXp", "1."));
+                RATE_SP                         = Float.parseFloat(ratesSettings.getProperty("RateSp", "1."));
+                RATE_PARTY_XP                   = Float.parseFloat(ratesSettings.getProperty("RatePartyXp", "1."));
+                RATE_PARTY_SP                   = Float.parseFloat(ratesSettings.getProperty("RatePartySp", "1."));
+                RATE_QUESTS_REWARD              = Float.parseFloat(ratesSettings.getProperty("RateQuestsReward", "1."));
+                RATE_DROP_ADENA                 = Float.parseFloat(ratesSettings.getProperty("RateDropAdena", "1."));
+                RATE_CONSUMABLE_COST            = Float.parseFloat(ratesSettings.getProperty("RateConsumableCost", "1."));
+                RATE_DROP_ITEMS                 = Float.parseFloat(ratesSettings.getProperty("RateDropItems", "1."));
+                RATE_DROP_SPOIL                 = Float.parseFloat(ratesSettings.getProperty("RateDropSpoil", "1."));
+                RATE_DROP_MANOR                 = Integer.parseInt(ratesSettings.getProperty("RateDropManor", "1"));
+                RATE_DROP_QUEST                 = Float.parseFloat(ratesSettings.getProperty("RateDropQuest", "1."));
+                RATE_KARMA_EXP_LOST             = Float.parseFloat(ratesSettings.getProperty("RateKarmaExpLost", "1."));
+                RATE_SIEGE_GUARDS_PRICE         = Float.parseFloat(ratesSettings.getProperty("RateSiegeGuardsPrice", "1."));
+                RATE_DROP_COMMON_HERBS             = Float.parseFloat(ratesSettings.getProperty("RateCommonHerbs", "15."));
+                RATE_DROP_MP_HP_HERBS           = Float.parseFloat(ratesSettings.getProperty("RateHpMpHerbs", "10."));
+                RATE_DROP_GREATER_HERBS         = Float.parseFloat(ratesSettings.getProperty("RateGreaterHerbs", "4."));
+                RATE_DROP_SUPERIOR_HERBS        = Float.parseFloat(ratesSettings.getProperty("RateSuperiorHerbs", "0.8"))*10;
+                RATE_DROP_SPECIAL_HERBS         = Float.parseFloat(ratesSettings.getProperty("RateSpecialHerbs", "0.2"))*10;
+
+                PLAYER_DROP_LIMIT               = Integer.parseInt(ratesSettings.getProperty("PlayerDropLimit", "3"));
+                PLAYER_RATE_DROP                = Integer.parseInt(ratesSettings.getProperty("PlayerRateDrop", "5"));
+                PLAYER_RATE_DROP_ITEM           = Integer.parseInt(ratesSettings.getProperty("PlayerRateDropItem", "70"));
+                PLAYER_RATE_DROP_EQUIP          = Integer.parseInt(ratesSettings.getProperty("PlayerRateDropEquip", "25"));
+                PLAYER_RATE_DROP_EQUIP_WEAPON   = Integer.parseInt(ratesSettings.getProperty("PlayerRateDropEquipWeapon", "5"));
+
+                PET_XP_RATE                     = Float.parseFloat(ratesSettings.getProperty("PetXpRate", "1."));
+                PET_FOOD_RATE                   = Integer.parseInt(ratesSettings.getProperty("PetFoodRate", "1"));
+                SINEATER_XP_RATE                = Float.parseFloat(ratesSettings.getProperty("SinEaterXpRate", "1."));
+
+                KARMA_DROP_LIMIT                = Integer.parseInt(ratesSettings.getProperty("KarmaDropLimit", "10"));
+                KARMA_RATE_DROP                 = Integer.parseInt(ratesSettings.getProperty("KarmaRateDrop", "70"));
+                KARMA_RATE_DROP_ITEM            = Integer.parseInt(ratesSettings.getProperty("KarmaRateDropItem", "50"));
+                KARMA_RATE_DROP_EQUIP           = Integer.parseInt(ratesSettings.getProperty("KarmaRateDropEquip", "40"));
+                KARMA_RATE_DROP_EQUIP_WEAPON    = Integer.parseInt(ratesSettings.getProperty("KarmaRateDropEquipWeapon", "10"));
+
+            }
+            catch (Exception e) {
+                e.printStackTrace();
+                throw new Error("Failed to Load "+RATES_CONFIG_FILE+" File.");
+            }
+
+            // alternative settings
+            try
+            {
+                Properties altSettings  = new Properties();
+                InputStream is          = new FileInputStream(new File(ALT_SETTINGS_FILE));
+                altSettings.load(is);
+                is.close();
+
+                ALT_GAME_TIREDNESS      = Boolean.parseBoolean(altSettings.getProperty("AltGameTiredness", "false"));
+                ALT_GAME_CREATION       = Boolean.parseBoolean(altSettings.getProperty("AltGameCreation", "false"));
+                ALT_GAME_CREATION_SPEED = Double.parseDouble(altSettings.getProperty("AltGameCreationSpeed", "1"));
+                ALT_GAME_CREATION_XP_RATE=Double.parseDouble(altSettings.getProperty("AltGameCreationRateXp", "1"));
+                ALT_GAME_CREATION_SP_RATE=Double.parseDouble(altSettings.getProperty("AltGameCreationRateSp", "1"));
+                ALT_WEIGHT_LIMIT        =Double.parseDouble(altSettings.getProperty("AltWeightLimit", "1"));
+                ALT_BLACKSMITH_USE_RECIPES=Boolean.parseBoolean(altSettings.getProperty("AltBlacksmithUseRecipes", "true"));
+                ALT_GAME_SKILL_LEARN    = Boolean.parseBoolean(altSettings.getProperty("AltGameSkillLearn", "false"));
+                AUTO_LEARN_SKILLS       = Boolean.parseBoolean(altSettings.getProperty("AutoLearnSkills", "false"));
+                ALT_GAME_CANCEL_BOW     = altSettings.getProperty("AltGameCancelByHit", "Cast").equalsIgnoreCase("bow") || altSettings.getProperty("AltGameCancelByHit", "Cast").equalsIgnoreCase("all");
+                ALT_GAME_CANCEL_CAST    = altSettings.getProperty("AltGameCancelByHit", "Cast").equalsIgnoreCase("cast") || altSettings.getProperty("AltGameCancelByHit", "Cast").equalsIgnoreCase("all");
+                ALT_GAME_SHIELD_BLOCKS  = Boolean.parseBoolean(altSettings.getProperty("AltShieldBlocks", "false"));
+                ALT_PERFECT_SHLD_BLOCK  = Integer.parseInt(altSettings.getProperty("AltPerfectShieldBlockRate", "10"));
+                ALT_GAME_DELEVEL        = Boolean.parseBoolean(altSettings.getProperty("Delevel", "true"));
+                ALT_GAME_MAGICFAILURES  = Boolean.parseBoolean(altSettings.getProperty("MagicFailures", "false"));
+                ALT_GAME_MOB_ATTACK_AI  = Boolean.parseBoolean(altSettings.getProperty("AltGameMobAttackAI", "false"));
+	            ALT_MOB_AGRO_IN_PEACEZONE  = Boolean.parseBoolean(altSettings.getProperty("AltMobAgroInPeaceZone", "true"));
+                ALT_GAME_EXPONENT_XP    = Float.parseFloat(altSettings.getProperty("AltGameExponentXp", "0."));
+                ALT_GAME_EXPONENT_SP    = Float.parseFloat(altSettings.getProperty("AltGameExponentSp", "0."));
+                ALLOW_CLASS_MASTERS     = Boolean.valueOf(altSettings.getProperty("AllowClassMasters", "False"));
+                ALT_GAME_FREIGHTS       = Boolean.parseBoolean(altSettings.getProperty("AltGameFreights", "false"));
+                ALT_GAME_FREIGHT_PRICE  = Integer.parseInt(altSettings.getProperty("AltGameFreightPrice", "1000"));
+                ALT_PARTY_RANGE 		= Integer.parseInt(altSettings.getProperty("AltPartyRange", "1600"));
+                ALT_PARTY_RANGE2  		= Integer.parseInt(altSettings.getProperty("AltPartyRange2", "1400"));
+                REMOVE_CASTLE_CIRCLETS  = Boolean.parseBoolean(altSettings.getProperty("RemoveCastleCirclets", "true"));
+                IS_CRAFTING_ENABLED     = Boolean.parseBoolean(altSettings.getProperty("CraftingEnabled", "true"));
+                LIFE_CRYSTAL_NEEDED     = Boolean.parseBoolean(altSettings.getProperty("LifeCrystalNeeded", "true"));
+                SP_BOOK_NEEDED          = Boolean.parseBoolean(altSettings.getProperty("SpBookNeeded", "true"));
+                ES_SP_BOOK_NEEDED       = Boolean.parseBoolean(altSettings.getProperty("EnchantSkillSpBookNeeded","true"));
+                AUTO_LOOT               = altSettings.getProperty("AutoLoot").equalsIgnoreCase("True");
+                AUTO_LOOT_HERBS         = altSettings.getProperty("AutoLootHerbs").equalsIgnoreCase("True");
+                ALT_GAME_KARMA_PLAYER_CAN_BE_KILLED_IN_PEACEZONE    = Boolean.valueOf(altSettings.getProperty("AltKarmaPlayerCanBeKilledInPeaceZone", "false"));
+                ALT_GAME_KARMA_PLAYER_CAN_SHOP                      = Boolean.valueOf(altSettings.getProperty("AltKarmaPlayerCanShop", "true"));
+                ALT_GAME_KARMA_PLAYER_CAN_USE_GK                    = Boolean.valueOf(altSettings.getProperty("AltKarmaPlayerCanUseGK", "false"));
+                ALT_GAME_KARMA_PLAYER_CAN_TELEPORT                  = Boolean.valueOf(altSettings.getProperty("AltKarmaPlayerCanTeleport", "true"));
+                ALT_GAME_KARMA_PLAYER_CAN_TRADE                     = Boolean.valueOf(altSettings.getProperty("AltKarmaPlayerCanTrade", "true"));
+                ALT_GAME_KARMA_PLAYER_CAN_USE_WAREHOUSE             = Boolean.valueOf(altSettings.getProperty("AltKarmaPlayerCanUseWareHouse", "true"));
+                ALT_GAME_FREE_TELEPORT                              = Boolean.parseBoolean(altSettings.getProperty("AltFreeTeleporting", "False"));
+                ALT_RECOMMEND                                       = Boolean.parseBoolean(altSettings.getProperty("AltRecommend", "False"));
+                ALT_GAME_SUBCLASS_WITHOUT_QUESTS                    = Boolean.parseBoolean(altSettings.getProperty("AltSubClassWithoutQuests", "False"));
+                ALT_GAME_VIEWNPC                                    = Boolean.parseBoolean(altSettings.getProperty("AltGameViewNpc", "False"));
+                ALT_GAME_NEW_CHAR_ALWAYS_IS_NEWBIE                  = Boolean.parseBoolean(altSettings.getProperty("AltNewCharAlwaysIsNewbie", "False"));
+                ALT_MEMBERS_CAN_WITHDRAW_FROM_CLANWH                = Boolean.parseBoolean(altSettings.getProperty("AltMembersCanWithdrawFromClanWH", "False"));
+                ALT_MAX_NUM_OF_CLANS_IN_ALLY                        = Integer.parseInt(altSettings.getProperty("AltMaxNumOfClansInAlly", "3"));
+                DWARF_RECIPE_LIMIT                                  = Integer.parseInt(altSettings.getProperty("DwarfRecipeLimit","50"));
+                COMMON_RECIPE_LIMIT                                 = Integer.parseInt(altSettings.getProperty("CommonRecipeLimit","50"));
+
+                ALT_CLAN_MEMBERS_FOR_WAR    = Integer.parseInt(altSettings.getProperty("AltClanMembersForWar", "15"));
+                ALT_CLAN_JOIN_DAYS          = Integer.parseInt(altSettings.getProperty("DaysBeforeJoinAClan", "5"));
+                ALT_CLAN_CREATE_DAYS        = Integer.parseInt(altSettings.getProperty("DaysBeforeCreateAClan", "10"));
+                ALT_CLAN_DISSOLVE_DAYS      = Integer.parseInt(altSettings.getProperty("DaysToPassToDissolveAClan", "7"));
+                ALT_ALLY_JOIN_DAYS_WHEN_LEAVED       = Integer.parseInt(altSettings.getProperty("DaysBeforeJoinAllyWhenLeaved", "1"));
+                ALT_ALLY_JOIN_DAYS_WHEN_DISMISSED    = Integer.parseInt(altSettings.getProperty("DaysBeforeJoinAllyWhenDismissed", "1"));
+                ALT_ACCEPT_CLAN_DAYS_WHEN_DISMISSED  = Integer.parseInt(altSettings.getProperty("DaysBeforeAcceptNewClanWhenDismissed", "1"));
+                ALT_CREATE_ALLY_DAYS_WHEN_DISSOLVED  = Integer.parseInt(altSettings.getProperty("DaysBeforeCreateNewAllyWhenDissolved", "10"));
+                CASTLE_SHIELD = Boolean.parseBoolean(altSettings.getProperty("CastleShieldRestriction", "True"));
+                CLANHALL_SHIELD = Boolean.parseBoolean(altSettings.getProperty("ClanHallShieldRestriction", "True"));
+                APELLA_ARMORS = Boolean.parseBoolean(altSettings.getProperty("ApellaArmorsRestriction", "True"));
+                OATH_ARMORS = Boolean.parseBoolean(altSettings.getProperty("OathArmorsRestriction", "True"));
+                CASTLE_CROWN = Boolean.parseBoolean(altSettings.getProperty("CastleLordsCrownRestriction", "True"));
+                CASTLE_CIRCLETS = Boolean.parseBoolean(altSettings.getProperty("CastleCircletsRestriction", "True"));
+
+                ALT_OLY_START_TIME                                  = Integer.parseInt(altSettings.getProperty("AltOlyStartTime", "18"));
+                ALT_OLY_MIN                                         = Integer.parseInt(altSettings.getProperty("AltOlyMin","00"));
+                ALT_OLY_CPERIOD                                     = Long.parseLong(altSettings.getProperty("AltOlyCPeriod","21600000"));
+                ALT_OLY_BATTLE                                      = Long.parseLong(altSettings.getProperty("AltOlyBattle","360000"));
+                ALT_OLY_BWAIT                                       = Long.parseLong(altSettings.getProperty("AltOlyBWait","600000"));
+                ALT_OLY_IWAIT                                       = Long.parseLong(altSettings.getProperty("AltOlyIWait","300000"));
+                ALT_OLY_WPERIOD                                     = Long.parseLong(altSettings.getProperty("AltOlyWPeriod","604800000"));
+                ALT_OLY_VPERIOD                                     = Long.parseLong(altSettings.getProperty("AltOlyVPeriod","86400000"));
+
+                ALT_MANOR_REFRESH_TIME                              = Integer.parseInt(altSettings.getProperty("AltManorRefreshTime","20"));
+    	        ALT_MANOR_REFRESH_MIN                               = Integer.parseInt(altSettings.getProperty("AltManorRefreshMin","00"));
+    	        ALT_MANOR_APPROVE_TIME                              = Integer.parseInt(altSettings.getProperty("AltManorApproveTime","6"));
+    	        ALT_MANOR_APPROVE_MIN                               = Integer.parseInt(altSettings.getProperty("AltManorApproveMin","00"));
+    	        ALT_MANOR_MAINTENANCE_PERIOD                        = Integer.parseInt(altSettings.getProperty("AltManorMaintenancePeriod","360000"));
+    	        ALT_MANOR_SAVE_ALL_ACTIONS                          = Boolean.parseBoolean(altSettings.getProperty("AltManorSaveAllActions","false"));
+    	        ALT_MANOR_SAVE_PERIOD_RATE                          = Integer.parseInt(altSettings.getProperty("AltManorSavePeriodRate","2"));
+
+                ALT_LOTTERY_PRIZE                = Integer.parseInt(altSettings.getProperty("AltLotteryPrize","50000"));
+                ALT_LOTTERY_TICKET_PRICE         = Integer.parseInt(altSettings.getProperty("AltLotteryTicketPrice","2000"));
+                ALT_LOTTERY_5_NUMBER_RATE        = Float.parseFloat(altSettings.getProperty("AltLottery5NumberRate","0.6"));
+                ALT_LOTTERY_4_NUMBER_RATE        = Float.parseFloat(altSettings.getProperty("AltLottery4NumberRate","0.2"));
+                ALT_LOTTERY_3_NUMBER_RATE        = Float.parseFloat(altSettings.getProperty("AltLottery3NumberRate","0.2"));
+                ALT_LOTTERY_2_AND_1_NUMBER_PRIZE = Integer.parseInt(altSettings.getProperty("AltLottery2and1NumberPrize","200"));
+                BUFFS_MAX_AMOUNT                 = Byte.parseByte(altSettings.getProperty("maxbuffamount","24"));
+
+                ALT_DEV_NO_QUESTS                = Boolean.parseBoolean(altSettings.getProperty("AltDevNoQuests", "False"));
+                ALT_DEV_NO_SPAWNS                = Boolean.parseBoolean(altSettings.getProperty("AltDevNoSpawns", "False"));
+
+                // Dimensional Rift Config
+                RIFT_MIN_PARTY_SIZE              = Integer.parseInt(altSettings.getProperty("RiftMinPartySize", "5"));
+                RIFT_MAX_JUMPS                   = Integer.parseInt(altSettings.getProperty("MaxRiftJumps", "4"));
+				RIFT_SPAWN_DELAY                 = Integer.parseInt(altSettings.getProperty("RiftSpawnDelay", "10000"));
+                RIFT_AUTO_JUMPS_TIME_MIN         = Integer.parseInt(altSettings.getProperty("AutoJumpsDelayMin", "480"));
+                RIFT_AUTO_JUMPS_TIME_MAX         = Integer.parseInt(altSettings.getProperty("AutoJumpsDelayMax", "600"));
+                RIFT_ENTER_COST_RECRUIT          = Integer.parseInt(altSettings.getProperty("RecruitCost", "18"));
+                RIFT_ENTER_COST_SOLDIER          = Integer.parseInt(altSettings.getProperty("SoldierCost", "21"));
+                RIFT_ENTER_COST_OFFICER          = Integer.parseInt(altSettings.getProperty("OfficerCost", "24"));
+                RIFT_ENTER_COST_CAPTAIN          = Integer.parseInt(altSettings.getProperty("CaptainCost", "27"));
+                RIFT_ENTER_COST_COMMANDER        = Integer.parseInt(altSettings.getProperty("CommanderCost", "30"));
+                RIFT_ENTER_COST_HERO             = Integer.parseInt(altSettings.getProperty("HeroCost", "33"));
+                RIFT_BOSS_ROOM_TIME_MUTIPLY      = Float.parseFloat(altSettings.getProperty("BossRoomTimeMultiply", "1.5"));
+            }
+            catch (Exception e)
+            {
+                e.printStackTrace();
+                throw new Error("Failed to Load "+ALT_SETTINGS_FILE+" File.");
+            }
+
+            // Seven Signs Config
+            try
+            {
+                Properties SevenSettings  = new Properties();
+                InputStream is            = new FileInputStream(new File(SEVENSIGNS_FILE));
+                SevenSettings.load(is);
+                is.close();
+
+                ALT_GAME_REQUIRE_CASTLE_DAWN    = Boolean.parseBoolean(SevenSettings.getProperty("AltRequireCastleForDawn", "False"));
+                ALT_GAME_REQUIRE_CLAN_CASTLE    = Boolean.parseBoolean(SevenSettings.getProperty("AltRequireClanCastle", "False"));
+                ALT_FESTIVAL_MIN_PLAYER         = Integer.parseInt(SevenSettings.getProperty("AltFestivalMinPlayer", "5"));
+                ALT_MAXIMUM_PLAYER_CONTRIB      = Integer.parseInt(SevenSettings.getProperty("AltMaxPlayerContrib", "1000000"));
+                ALT_FESTIVAL_MANAGER_START      = Long.parseLong(SevenSettings.getProperty("AltFestivalManagerStart", "120000"));
+                ALT_FESTIVAL_LENGTH             = Long.parseLong(SevenSettings.getProperty("AltFestivalLength", "1080000"));
+                ALT_FESTIVAL_CYCLE_LENGTH       = Long.parseLong(SevenSettings.getProperty("AltFestivalCycleLength", "2280000"));
+                ALT_FESTIVAL_FIRST_SPAWN        = Long.parseLong(SevenSettings.getProperty("AltFestivalFirstSpawn", "120000"));
+                ALT_FESTIVAL_FIRST_SWARM        = Long.parseLong(SevenSettings.getProperty("AltFestivalFirstSwarm", "300000"));
+                ALT_FESTIVAL_SECOND_SPAWN       = Long.parseLong(SevenSettings.getProperty("AltFestivalSecondSpawn", "540000"));
+                ALT_FESTIVAL_SECOND_SWARM       = Long.parseLong(SevenSettings.getProperty("AltFestivalSecondSwarm", "720000"));
+                ALT_FESTIVAL_CHEST_SPAWN        = Long.parseLong(SevenSettings.getProperty("AltFestivalChestSpawn", "900000"));
+            }
+            catch (Exception e)
+            {
+                e.printStackTrace();
+                throw new Error("Failed to Load "+SEVENSIGNS_FILE+" File.");
+            }
+
+            // clanhall settings
+            try
+            {
+                Properties clanhallSettings  = new Properties();
+                InputStream is          = new FileInputStream(new File(CLANHALL_CONFIG_FILE));
+                clanhallSettings.load(is);
+                is.close();
+                CH_TELE_FEE_RATIO                                   = Long.valueOf(clanhallSettings.getProperty("ClanHallTeleportFunctionFeeRation", "86400000"));
+                CH_TELE1_FEE                                        = Integer.valueOf(clanhallSettings.getProperty("ClanHallTeleportFunctionFeeLvl1", "86400000"));
+                CH_TELE2_FEE                                        = Integer.valueOf(clanhallSettings.getProperty("ClanHallTeleportFunctionFeeLvl2", "86400000"));
+                CH_SUPPORT_FEE_RATIO                                = Long.valueOf(clanhallSettings.getProperty("ClanHallSupportFunctionFeeRation", "86400000"));
+                CH_SUPPORT1_FEE                                     = Integer.valueOf(clanhallSettings.getProperty("ClanHallSupportFeeLvl1", "86400000"));
+                CH_SUPPORT2_FEE                                     = Integer.valueOf(clanhallSettings.getProperty("ClanHallSupportFeeLvl2", "86400000"));
+                CH_SUPPORT3_FEE                                     = Integer.valueOf(clanhallSettings.getProperty("ClanHallSupportFeeLvl3", "86400000"));
+                CH_SUPPORT4_FEE                                     = Integer.valueOf(clanhallSettings.getProperty("ClanHallSupportFeeLvl4", "86400000"));
+                CH_SUPPORT5_FEE                                     = Integer.valueOf(clanhallSettings.getProperty("ClanHallSupportFeeLvl5", "86400000"));
+                CH_SUPPORT6_FEE                                     = Integer.valueOf(clanhallSettings.getProperty("ClanHallSupportFeeLvl6", "86400000"));
+                CH_SUPPORT7_FEE                                     = Integer.valueOf(clanhallSettings.getProperty("ClanHallSupportFeeLvl7", "86400000"));
+                CH_SUPPORT8_FEE                                     = Integer.valueOf(clanhallSettings.getProperty("ClanHallSupportFeeLvl8", "86400000"));
+                CH_MPREG_FEE_RATIO                                  = Long.valueOf(clanhallSettings.getProperty("ClanHallMpRegenerationFunctionFeeRation", "86400000"));
+                CH_MPREG1_FEE                                       = Integer.valueOf(clanhallSettings.getProperty("ClanHallMpRegenerationFeeLvl1", "86400000"));
+                CH_MPREG2_FEE                                       = Integer.valueOf(clanhallSettings.getProperty("ClanHallMpRegenerationFeeLvl2", "86400000"));
+                CH_MPREG3_FEE                                       = Integer.valueOf(clanhallSettings.getProperty("ClanHallMpRegenerationFeeLvl3", "86400000"));
+                CH_MPREG4_FEE                                       = Integer.valueOf(clanhallSettings.getProperty("ClanHallMpRegenerationFeeLvl4", "86400000"));
+                CH_MPREG5_FEE                                       = Integer.valueOf(clanhallSettings.getProperty("ClanHallMpRegenerationFeeLvl5", "86400000"));
+                CH_HPREG_FEE_RATIO                                  = Long.valueOf(clanhallSettings.getProperty("ClanHallHpRegenerationFunctionFeeRation", "86400000"));
+                CH_HPREG1_FEE                                       = Integer.valueOf(clanhallSettings.getProperty("ClanHallHpRegenerationFeeLvl1", "86400000"));
+                CH_HPREG2_FEE                                       = Integer.valueOf(clanhallSettings.getProperty("ClanHallHpRegenerationFeeLvl2", "86400000"));
+                CH_HPREG3_FEE                                       = Integer.valueOf(clanhallSettings.getProperty("ClanHallHpRegenerationFeeLvl3", "86400000"));
+                CH_HPREG4_FEE                                       = Integer.valueOf(clanhallSettings.getProperty("ClanHallHpRegenerationFeeLvl4", "86400000"));
+                CH_HPREG5_FEE                                       = Integer.valueOf(clanhallSettings.getProperty("ClanHallHpRegenerationFeeLvl5", "86400000"));
+                CH_HPREG6_FEE                                       = Integer.valueOf(clanhallSettings.getProperty("ClanHallHpRegenerationFeeLvl6", "86400000"));
+                CH_HPREG7_FEE                                       = Integer.valueOf(clanhallSettings.getProperty("ClanHallHpRegenerationFeeLvl7", "86400000"));
+                CH_HPREG8_FEE                                       = Integer.valueOf(clanhallSettings.getProperty("ClanHallHpRegenerationFeeLvl8", "86400000"));
+                CH_HPREG9_FEE                                       = Integer.valueOf(clanhallSettings.getProperty("ClanHallHpRegenerationFeeLvl9", "86400000"));
+                CH_HPREG10_FEE                                       = Integer.valueOf(clanhallSettings.getProperty("ClanHallHpRegenerationFeeLvl10", "86400000"));
+                CH_HPREG11_FEE                                       = Integer.valueOf(clanhallSettings.getProperty("ClanHallHpRegenerationFeeLvl11", "86400000"));
+                CH_HPREG12_FEE                                       = Integer.valueOf(clanhallSettings.getProperty("ClanHallHpRegenerationFeeLvl12", "86400000"));
+                CH_HPREG13_FEE                                       = Integer.valueOf(clanhallSettings.getProperty("ClanHallHpRegenerationFeeLvl13", "86400000"));
+                CH_EXPREG_FEE_RATIO                                 = Long.valueOf(clanhallSettings.getProperty("ClanHallExpRegenerationFunctionFeeRation", "86400000"));
+                CH_EXPREG1_FEE                                      = Integer.valueOf(clanhallSettings.getProperty("ClanHallExpRegenerationFeeLvl1", "86400000"));
+                CH_EXPREG2_FEE                                      = Integer.valueOf(clanhallSettings.getProperty("ClanHallExpRegenerationFeeLvl2", "86400000"));
+                CH_EXPREG3_FEE                                      = Integer.valueOf(clanhallSettings.getProperty("ClanHallExpRegenerationFeeLvl3", "86400000"));
+                CH_EXPREG4_FEE                                      = Integer.valueOf(clanhallSettings.getProperty("ClanHallExpRegenerationFeeLvl4", "86400000"));
+                CH_EXPREG5_FEE                                      = Integer.valueOf(clanhallSettings.getProperty("ClanHallExpRegenerationFeeLvl5", "86400000"));
+                CH_EXPREG6_FEE                                      = Integer.valueOf(clanhallSettings.getProperty("ClanHallExpRegenerationFeeLvl6", "86400000"));
+                CH_EXPREG7_FEE                                      = Integer.valueOf(clanhallSettings.getProperty("ClanHallExpRegenerationFeeLvl7", "86400000"));
+                CH_ITEM_FEE_RATIO                                   = Long.valueOf(clanhallSettings.getProperty("ClanHallItemCreationFunctionFeeRation", "86400000"));
+                CH_ITEM1_FEE                                        = Integer.valueOf(clanhallSettings.getProperty("ClanHallItemCreationFunctionFeeLvl1", "86400000"));
+                CH_ITEM2_FEE                                        = Integer.valueOf(clanhallSettings.getProperty("ClanHallItemCreationFunctionFeeLvl2", "86400000"));
+                CH_ITEM3_FEE                                        = Integer.valueOf(clanhallSettings.getProperty("ClanHallItemCreationFunctionFeeLvl3", "86400000"));
+                CH_CURTAIN_FEE_RATIO                                = Long.valueOf(clanhallSettings.getProperty("ClanHallCurtainFunctionFeeRation", "86400000"));
+                CH_CURTAIN1_FEE                                        = Integer.valueOf(clanhallSettings.getProperty("ClanHallCurtainFunctionFeeLvl1", "86400000"));
+                CH_CURTAIN2_FEE                                        = Integer.valueOf(clanhallSettings.getProperty("ClanHallCurtainFunctionFeeLvl2", "86400000"));
+                CH_FRONT_FEE_RATIO                                = Long.valueOf(clanhallSettings.getProperty("ClanHallFrontPlatformFunctionFeeRation", "86400000"));
+                CH_FRONT1_FEE                                        = Integer.valueOf(clanhallSettings.getProperty("ClanHallFrontPlatformFunctionFeeLvl1", "86400000"));
+                CH_FRONT2_FEE                                        = Integer.valueOf(clanhallSettings.getProperty("ClanHallFrontPlatformFunctionFeeLvl2", "86400000"));
+            }
+            catch (Exception e)
+            {
+                e.printStackTrace();
+                throw new Error("Failed to Load "+CLANHALL_CONFIG_FILE+" File.");
+            }
+            try
+            {
+                Properties L2JModSettings  = new Properties();
+                InputStream is          = new FileInputStream(new File(L2JMOD_CONFIG_FILE));
+                L2JModSettings.load(is);
+                is.close();
+
+                L2JMOD_CHAMPION_ENABLE              = Boolean.parseBoolean(L2JModSettings.getProperty("ChampionEnable", "false"));
+                L2JMOD_CHAMPION_FREQUENCY              = Integer.parseInt(L2JModSettings.getProperty("ChampionFrequency", "0"));
+                L2JMOD_CHAMP_MIN_LVL                = Integer.parseInt(L2JModSettings.getProperty("ChampionMinLevel", "20"));
+                L2JMOD_CHAMP_MAX_LVL                = Integer.parseInt(L2JModSettings.getProperty("ChampionMaxLevel", "60"));
+                L2JMOD_CHAMPION_HP                     = Integer.parseInt(L2JModSettings.getProperty("ChampionHp", "7"));
+                L2JMOD_CHAMPION_HP_REGEN               = Float.parseFloat(L2JModSettings.getProperty("ChampionHpRegen", "1."));
+                L2JMOD_CHAMPION_REWARDS                = Integer.parseInt(L2JModSettings.getProperty("ChampionRewards", "8"));
+                L2JMOD_CHAMPION_ADENAS_REWARDS         = Integer.parseInt(L2JModSettings.getProperty("ChampionAdenasRewards", "1"));
+                L2JMOD_CHAMPION_ATK                 = Float.parseFloat(L2JModSettings.getProperty("ChampionAtk", "1."));
+                L2JMOD_CHAMPION_SPD_ATK             = Float.parseFloat(L2JModSettings.getProperty("ChampionSpdAtk", "1."));
+                L2JMOD_CHAMPION_REWARD                 = Integer.parseInt(L2JModSettings.getProperty("ChampionRewardItem", "0"));
+                L2JMOD_CHAMPION_REWARD_ID             = Integer.parseInt(L2JModSettings.getProperty("ChampionRewardItemID", "6393"));
+                L2JMOD_CHAMPION_REWARD_QTY            = Integer.parseInt(L2JModSettings.getProperty("ChampionRewardItemQty", "1"));
+
+                TVT_EVENT_ENABLED                        = Boolean.parseBoolean(L2JModSettings.getProperty("TvTEventEnabled", "false"));
+                TVT_EVENT_INTERVAL                        = Integer.parseInt(L2JModSettings.getProperty("TvTEventInterval", "18000"));
+                TVT_EVENT_PARTICIPATION_TIME            = Integer.parseInt(L2JModSettings.getProperty("TvTEventParticipationTime", "3600"));
+                TVT_EVENT_RUNNING_TIME                    = Integer.parseInt(L2JModSettings.getProperty("TvTEventRunningTime", "1800"));
+                TVT_EVENT_PARTICIPATION_NPC_ID            = Integer.parseInt(L2JModSettings.getProperty("TvTEventParticipationNpcId", "0"));
+
+                /** L2JMOD Wedding system  */
+                L2JMOD_ALLOW_WEDDING                    = Boolean.valueOf(L2JModSettings.getProperty("AllowWedding", "False"));
+                L2JMOD_WEDDING_PRICE                    = Integer.parseInt(L2JModSettings.getProperty("WeddingPrice", "250000000"));
+                L2JMOD_WEDDING_PUNISH_INFIDELITY        = Boolean.parseBoolean(L2JModSettings.getProperty("WeddingPunishInfidelity", "True"));
+                L2JMOD_WEDDING_TELEPORT                 = Boolean.parseBoolean(L2JModSettings.getProperty("WeddingTeleport", "True"));
+                L2JMOD_WEDDING_TELEPORT_PRICE           = Integer.parseInt(L2JModSettings.getProperty("WeddingTeleportPrice", "50000"));
+                L2JMOD_WEDDING_TELEPORT_DURATION        = Integer.parseInt(L2JModSettings.getProperty("WeddingTeleportDuration", "60"));
+                L2JMOD_WEDDING_SAMESEX                  = Boolean.parseBoolean(L2JModSettings.getProperty("WeddingAllowSameSex", "False"));
+                L2JMOD_WEDDING_FORMALWEAR               = Boolean.parseBoolean(L2JModSettings.getProperty("WeddingFormalWear", "True"));
+                L2JMOD_WEDDING_DIVORCE_COSTS            = Integer.parseInt(L2JModSettings.getProperty("WeddingDivorceCosts", "20"));
+
+                if (TVT_EVENT_PARTICIPATION_NPC_ID == 0)
+                {
+                    TVT_EVENT_ENABLED = false;
+                    System.out.println("TvTEventEngine[Config.load()]: invalid config property -> TvTEventParticipationNpcId");
+                }
+                else
+                {
+                    String[] propertySplit                = L2JModSettings.getProperty("TvTEventParticipationNpcCoordinates", "0,0,0").split(",");
+
+                    if (propertySplit.length < 3)
+                    {
+                        TVT_EVENT_ENABLED = false;
+                        System.out.println("TvTEventEngine[Config.load()]: invalid config property -> TvTEventParticipationNpcCoordinates");
+                    }
+                    else
+                    {
+                        TVT_EVENT_PARTICIPATION_NPC_COORDINATES[0]  = Integer.parseInt(propertySplit[0]);
+                        TVT_EVENT_PARTICIPATION_NPC_COORDINATES[1]  = Integer.parseInt(propertySplit[1]);
+                        TVT_EVENT_PARTICIPATION_NPC_COORDINATES[2]  = Integer.parseInt(propertySplit[2]);
+
+                        TVT_EVENT_MIN_PLAYERS_IN_TEAMS              = Integer.parseInt(L2JModSettings.getProperty("TvTEventMinPlayersInTeams", "1"));
+                        TVT_EVENT_MAX_PLAYERS_IN_TEAMS              = Integer.parseInt(L2JModSettings.getProperty("TvTEventMaxPlayersInTeams", "20"));
+                        TVT_EVENT_MIN_LVL							= (byte)Integer.parseInt(L2JModSettings.getProperty("TvTEventMinPlayerLevel", "1"));
+                        TVT_EVENT_MAX_LVL							= (byte)Integer.parseInt(L2JModSettings.getProperty("TvTEventMaxPlayerLevel", "80"));
+                        TVT_EVENT_RESPAWN_TELEPORT_DELAY            = Integer.parseInt(L2JModSettings.getProperty("TvTEventRespawnTeleportDelay", "20"));
+                        TVT_EVENT_START_LEAVE_TELEPORT_DELAY        = Integer.parseInt(L2JModSettings.getProperty("TvTEventStartLeaveTeleportDelay", "20"));
+
+                        TVT_EVENT_TEAM_1_NAME                       = L2JModSettings.getProperty("TvTEventTeam1Name", "Team1");
+                        propertySplit                               = L2JModSettings.getProperty("TvTEventTeam1Coordinates", "0,0,0").split(",");
+
+                        if (propertySplit.length < 3)
+                        {
+                            TVT_EVENT_ENABLED = false;
+                            System.out.println("TvTEventEngine[Config.load()]: invalid config property -> TvTEventTeam1Coordinates");
+                        }
+                        else
+                        {
+                            TVT_EVENT_TEAM_1_COORDINATES[0]    = Integer.parseInt(propertySplit[0]);
+                            TVT_EVENT_TEAM_1_COORDINATES[1]    = Integer.parseInt(propertySplit[1]);
+                            TVT_EVENT_TEAM_1_COORDINATES[2]    = Integer.parseInt(propertySplit[2]);
+
+                            TVT_EVENT_TEAM_2_NAME            = L2JModSettings.getProperty("TvTEventTeam2Name", "Team2");
+                            propertySplit                    = L2JModSettings.getProperty("TvTEventTeam2Coordinates", "0,0,0").split(",");
+
+                            if (propertySplit.length < 3)
+                            {
+                                TVT_EVENT_ENABLED= false;
+                                System.out.println("TvTEventEngine[Config.load()]: invalid config property -> TvTEventTeam2Coordinates");
+                            }
+                            else
+                            {
+                                TVT_EVENT_TEAM_2_COORDINATES[0]    = Integer.parseInt(propertySplit[0]);
+                                TVT_EVENT_TEAM_2_COORDINATES[1]    = Integer.parseInt(propertySplit[1]);
+                                TVT_EVENT_TEAM_2_COORDINATES[2]    = Integer.parseInt(propertySplit[2]);
+                                propertySplit                    = L2JModSettings.getProperty("TvTEventReward", "57,100000").split(";");
+
+                                for (String reward : propertySplit)
+                                {
+                                	String[] rewardSplit = reward.split(",");
+
+                                	if (rewardSplit.length != 2)
+                                		System.out.println("TvTEventEngine[Config.load()]: invalid config property -> TvTEventReward \"" + reward + "\"");
+                                	else
+                                	{
+                                		try
+                                		{
+                                			TVT_EVENT_REWARDS.add(new int[]{Integer.valueOf(rewardSplit[0]), Integer.valueOf(rewardSplit[1])});
+                                		}
+                                		catch (NumberFormatException nfe)
+                                		{
+                                			if (!reward.equals(""))
+                                				System.out.println("TvTEventEngine[Config.load()]: invalid config property -> TvTEventReward \"" + reward + "\"");
+                                		}
+                                	}
+                                }
+
+                                TVT_EVENT_TARGET_TEAM_MEMBERS_ALLOWED	= Boolean.parseBoolean(L2JModSettings.getProperty("TvTEventTargetTeamMembersAllowed", "true"));
+                        		TVT_EVENT_POTIONS_ALLOWED				= Boolean.parseBoolean(L2JModSettings.getProperty("TvTEventPotionsAllowed", "false"));
+                        		TVT_EVENT_SUMMON_BY_ITEM_ALLOWED		= Boolean.parseBoolean(L2JModSettings.getProperty("TvTEventSummonByItemAllowed", "false"));
+                        		propertySplit							= L2JModSettings.getProperty("TvTEventDoorsCloseOpenOnStartEnd", "").split(";");
+
+                        		for (String door : propertySplit)
+                        		{
+                        			try
+                        			{
+                        				TVT_EVENT_DOOR_IDS.add(Integer.valueOf(door));
+                        			}
+                        			catch (NumberFormatException nfe)
+                        			{
+                        				if (!door.equals(""))
+                        					System.out.println("TvTEventEngine[Config.load()]: invalid config property -> TvTEventDoorsCloseOpenOnStartEnd \"" + door + "\"");
+                        			}
+                        		}
+                            }
+                        }
+                    }
+                }
+
+            }
+            catch (Exception e)
+            {
+                e.printStackTrace();
+                throw new Error("Failed to Load "+L2JMOD_CONFIG_FILE+" File.");
+            }
+            // pvp config
+            try
+            {
+                Properties pvpSettings      = new Properties();
+                InputStream is              = new FileInputStream(new File(PVP_CONFIG_FILE));
+                pvpSettings.load(is);
+                is.close();
+
+                /* KARMA SYSTEM */
+                KARMA_MIN_KARMA     = Integer.parseInt(pvpSettings.getProperty("MinKarma", "240"));
+                KARMA_MAX_KARMA     = Integer.parseInt(pvpSettings.getProperty("MaxKarma", "10000"));
+                KARMA_XP_DIVIDER    = Integer.parseInt(pvpSettings.getProperty("XPDivider", "260"));
+                KARMA_LOST_BASE     = Integer.parseInt(pvpSettings.getProperty("BaseKarmaLost", "0"));
+
+                KARMA_DROP_GM               = Boolean.parseBoolean(pvpSettings.getProperty("CanGMDropEquipment", "false"));
+                KARMA_AWARD_PK_KILL         = Boolean.parseBoolean(pvpSettings.getProperty("AwardPKKillPVPPoint", "true"));
+
+                KARMA_PK_LIMIT                      = Integer.parseInt(pvpSettings.getProperty("MinimumPKRequiredToDrop", "5"));
+
+                KARMA_NONDROPPABLE_PET_ITEMS    = pvpSettings.getProperty("ListOfPetItems", "2375,3500,3501,3502,4422,4423,4424,4425,6648,6649,6650");
+                KARMA_NONDROPPABLE_ITEMS        = pvpSettings.getProperty("ListOfNonDroppableItems", "57,1147,425,1146,461,10,2368,7,6,2370,2369,6842,6611,6612,6613,6614,6615,6616,6617,6618,6619,6620,6621");
+
+                KARMA_LIST_NONDROPPABLE_PET_ITEMS = new FastList<Integer>();
+                for (String id : KARMA_NONDROPPABLE_PET_ITEMS.split(",")) {
+                    KARMA_LIST_NONDROPPABLE_PET_ITEMS.add(Integer.parseInt(id));
+                }
+
+                KARMA_LIST_NONDROPPABLE_ITEMS = new FastList<Integer>();
+                for (String id : KARMA_NONDROPPABLE_ITEMS.split(",")) {
+                    KARMA_LIST_NONDROPPABLE_ITEMS.add(Integer.parseInt(id));
+                }
+
+                PVP_NORMAL_TIME = Integer.parseInt(pvpSettings.getProperty("PvPVsNormalTime", "15000"));
+                PVP_PVP_TIME = Integer.parseInt(pvpSettings.getProperty("PvPVsPvPTime", "30000"));
+            }
+            catch (Exception e)
+            {
+                e.printStackTrace();
+                throw new Error("Failed to Load "+PVP_CONFIG_FILE+" File.");
+            }
+
+            // access levels
+            try
+            {
+                Properties gmSettings   = new Properties();
+                InputStream is          = new FileInputStream(new File(GM_ACCESS_FILE));
+                gmSettings.load(is);
+                is.close();
+
+                GM_ACCESSLEVEL  = Integer.parseInt(gmSettings.getProperty("GMAccessLevel", "100"));
+                GM_MIN          = Integer.parseInt(gmSettings.getProperty("GMMinLevel", "100"));
+                GM_ALTG_MIN_LEVEL = Integer.parseInt(gmSettings.getProperty("GMCanAltG", "100"));
+                GM_ANNOUNCE     = Integer.parseInt(gmSettings.getProperty("GMCanAnnounce", "100"));
+                GM_BAN          = Integer.parseInt(gmSettings.getProperty("GMCanBan", "100"));
+                GM_BAN_CHAT     = Integer.parseInt(gmSettings.getProperty("GMCanBanChat", "100"));
+                GM_CREATE_ITEM  = Integer.parseInt(gmSettings.getProperty("GMCanShop", "100"));
+                GM_DELETE       = Integer.parseInt(gmSettings.getProperty("GMCanDelete", "100"));
+                GM_KICK         = Integer.parseInt(gmSettings.getProperty("GMCanKick", "100"));
+                GM_MENU         = Integer.parseInt(gmSettings.getProperty("GMMenu", "100"));
+                GM_GODMODE      = Integer.parseInt(gmSettings.getProperty("GMGodMode", "100"));
+                GM_CHAR_EDIT    = Integer.parseInt(gmSettings.getProperty("GMCanEditChar", "100"));
+                GM_CHAR_EDIT_OTHER    = Integer.parseInt(gmSettings.getProperty("GMCanEditCharOther", "100"));
+                GM_CHAR_VIEW    = Integer.parseInt(gmSettings.getProperty("GMCanViewChar", "100"));
+                GM_NPC_EDIT     = Integer.parseInt(gmSettings.getProperty("GMCanEditNPC", "100"));
+                GM_NPC_VIEW     = Integer.parseInt(gmSettings.getProperty("GMCanViewNPC", "100"));
+                GM_TELEPORT     = Integer.parseInt(gmSettings.getProperty("GMCanTeleport", "100"));
+                GM_TELEPORT_OTHER     = Integer.parseInt(gmSettings.getProperty("GMCanTeleportOther", "100"));
+                GM_RESTART      = Integer.parseInt(gmSettings.getProperty("GMCanRestart", "100"));
+                GM_MONSTERRACE  = Integer.parseInt(gmSettings.getProperty("GMMonsterRace", "100"));
+                GM_RIDER        = Integer.parseInt(gmSettings.getProperty("GMRider", "100"));
+                GM_ESCAPE       = Integer.parseInt(gmSettings.getProperty("GMFastUnstuck", "100"));
+                GM_FIXED        = Integer.parseInt(gmSettings.getProperty("GMResurectFixed", "100"));
+                GM_CREATE_NODES = Integer.parseInt(gmSettings.getProperty("GMCreateNodes", "100"));
+                GM_ENCHANT      = Integer.parseInt(gmSettings.getProperty("GMEnchant", "100"));
+                GM_DOOR         = Integer.parseInt(gmSettings.getProperty("GMDoor", "100"));
+                GM_RES          = Integer.parseInt(gmSettings.getProperty("GMRes", "100"));
+                GM_PEACEATTACK  = Integer.parseInt(gmSettings.getProperty("GMPeaceAttack", "100"));
+                GM_HEAL         = Integer.parseInt(gmSettings.getProperty("GMHeal", "100"));
+                GM_UNBLOCK      = Integer.parseInt(gmSettings.getProperty("GMUnblock", "100"));
+                GM_CACHE        = Integer.parseInt(gmSettings.getProperty("GMCache", "100"));
+                GM_TALK_BLOCK   = Integer.parseInt(gmSettings.getProperty("GMTalkBlock", "100"));
+                GM_TEST         = Integer.parseInt(gmSettings.getProperty("GMTest", "100"));
+
+                String gmTrans = gmSettings.getProperty("GMDisableTransaction", "False");
+
+                if (!gmTrans.equalsIgnoreCase("false"))
+                {
+                    String[] params = gmTrans.split(",");
+                    GM_DISABLE_TRANSACTION = true;
+                    GM_TRANSACTION_MIN = Integer.parseInt(params[0]);
+                    GM_TRANSACTION_MAX = Integer.parseInt(params[1]);
+                }
+                else
+                {
+                    GM_DISABLE_TRANSACTION = false;
+                }
+                GM_CAN_GIVE_DAMAGE = Integer.parseInt(gmSettings.getProperty("GMCanGiveDamage", "90"));
+                GM_DONT_TAKE_AGGRO = Integer.parseInt(gmSettings.getProperty("GMDontTakeAggro", "90"));
+                GM_DONT_TAKE_EXPSP = Integer.parseInt(gmSettings.getProperty("GMDontGiveExpSp", "90"));
+
+            }
+            catch (Exception e)
+            {
+                e.printStackTrace();
+                throw new Error("Failed to Load "+GM_ACCESS_FILE+" File.");
+            }
+
+            try
+            {
+                Properties Settings   = new Properties();
+                InputStream is          = new FileInputStream(HEXID_FILE);
+                Settings.load(is);
+                is.close();
+                SERVER_ID = Integer.parseInt(Settings.getProperty("ServerID"));
+                HEX_ID = new BigInteger(Settings.getProperty("HexID"), 16).toByteArray();
+            }
+            catch (Exception e)
+            {
+                _log.warning("Could not load HexID file ("+HEXID_FILE+"). Hopefully login will give us one.");
+            }
+        }
+        else if(Server.serverMode == Server.MODE_LOGINSERVER)
+        {
+            _log.info("loading login config");
+            try
+            {
+                Properties serverSettings    = new Properties();
+                InputStream is               = new FileInputStream(new File(LOGIN_CONFIGURATION_FILE));
+                serverSettings.load(is);
+                is.close();
+
+                GAME_SERVER_LOGIN_HOST = serverSettings.getProperty("LoginHostname","*");
+                GAME_SERVER_LOGIN_PORT = Integer.parseInt(serverSettings.getProperty("LoginPort","9013"));
+
+                LOGIN_BIND_ADDRESS     = serverSettings.getProperty("LoginserverHostname", "*");
+                PORT_LOGIN            = Integer.parseInt(serverSettings.getProperty("LoginserverPort", "2106"));
+
+                DEBUG        = Boolean.parseBoolean(serverSettings.getProperty("Debug", "false"));
+                DEVELOPER    = Boolean.parseBoolean(serverSettings.getProperty("Developer", "false"));
+                ASSERT       = Boolean.parseBoolean(serverSettings.getProperty("Assert", "false"));
+
+                ACCEPT_NEW_GAMESERVER = Boolean.parseBoolean(serverSettings.getProperty("AcceptNewGameServer","True"));
+                REQUEST_ID = Integer.parseInt(serverSettings.getProperty("RequestServerID","0"));
+                ACCEPT_ALTERNATE_ID = Boolean.parseBoolean(serverSettings.getProperty("AcceptAlternateID","True"));
+
+                LOGIN_TRY_BEFORE_BAN    = Integer.parseInt(serverSettings.getProperty("LoginTryBeforeBan", "10"));
+                LOGIN_BLOCK_AFTER_BAN   = Integer.parseInt(serverSettings.getProperty("LoginBlockAfterBan", "600"));
+                GM_MIN          = Integer.parseInt(serverSettings.getProperty("GMMinLevel", "100"));
+
+                DATAPACK_ROOT    = new File(serverSettings.getProperty("DatapackRoot", ".")).getCanonicalFile(); //FIXME: in login?
+
+                INTERNAL_HOSTNAME   = serverSettings.getProperty("InternalHostname", "localhost");
+                EXTERNAL_HOSTNAME   = serverSettings.getProperty("ExternalHostname", "localhost");
+
+                DATABASE_DRIVER             = serverSettings.getProperty("Driver", "com.mysql.jdbc.Driver");
+                DATABASE_URL                = serverSettings.getProperty("URL", "jdbc:mysql://localhost/l2jdb");
+                DATABASE_LOGIN              = serverSettings.getProperty("Login", "root");
+                DATABASE_PASSWORD           = serverSettings.getProperty("Password", "");
+                DATABASE_MAX_CONNECTIONS    = Integer.parseInt(serverSettings.getProperty("MaximumDbConnections", "10"));
+
+                SHOW_LICENCE = Boolean.parseBoolean(serverSettings.getProperty("ShowLicence", "true"));
+                IP_UPDATE_TIME                = Integer.parseInt(serverSettings.getProperty("IpUpdateTime","15"));
+                FORCE_GGAUTH = Boolean.parseBoolean(serverSettings.getProperty("ForceGGAuth", "false"));
+
+                AUTO_CREATE_ACCOUNTS = Boolean.parseBoolean(serverSettings.getProperty("AutoCreateAccounts","True"));
+
+                FLOOD_PROTECTION = Boolean.parseBoolean(serverSettings.getProperty("EnableFloodProtection","True"));
+                FAST_CONNECTION_LIMIT = Integer.parseInt(serverSettings.getProperty("FastConnectionLimit","15"));
+                NORMAL_CONNECTION_TIME = Integer.parseInt(serverSettings.getProperty("NormalConnectionTime","700"));
+                FAST_CONNECTION_TIME = Integer.parseInt(serverSettings.getProperty("FastConnectionTime","350"));
+                MAX_CONNECTION_PER_IP = Integer.parseInt(serverSettings.getProperty("MaxConnectionPerIP","50"));
+            }
+            catch (Exception e)
+            {
+                e.printStackTrace();
+                throw new Error("Failed to Load "+CONFIGURATION_FILE+" File.");
+            }
+
+            // telnet
+            try
+            {
+                Properties telnetSettings   = new Properties();
+                InputStream is              = new FileInputStream(new File(TELNET_FILE));
+                telnetSettings.load(is);
+                is.close();
+
+                IS_TELNET_ENABLED   = Boolean.valueOf(telnetSettings.getProperty("EnableTelnet", "false"));
+            }
+            catch (Exception e)
+            {
+                e.printStackTrace();
+                throw new Error("Failed to Load "+TELNET_FILE+" File.");
+            }
+
+        }
+        else
+        {
+            _log.severe("Could not Load Config: server mode was not set");
+        }
+
+    }
+
+    /**
+     * Set a new value to a game parameter from the admin console.
+     * @param pName (String) : name of the parameter to change
+     * @param pValue (String) : new value of the parameter
+     * @return boolean : true if modification has been made
+     * @link useAdminCommand
+     */
+    public static boolean setParameterValue(String pName, String pValue)
+    {
+        // Server settings
+        if (pName.equalsIgnoreCase("RateXp")) RATE_XP = Float.parseFloat(pValue);
+        else if (pName.equalsIgnoreCase("RateSp")) RATE_SP = Float.parseFloat(pValue);
+        else if (pName.equalsIgnoreCase("RatePartyXp")) RATE_PARTY_XP = Float.parseFloat(pValue);
+        else if (pName.equalsIgnoreCase("RatePartySp")) RATE_PARTY_SP = Float.parseFloat(pValue);
+        else if (pName.equalsIgnoreCase("RateQuestsReward")) RATE_QUESTS_REWARD = Float.parseFloat(pValue);
+        else if (pName.equalsIgnoreCase("RateDropAdena")) RATE_DROP_ADENA = Float.parseFloat(pValue);
+        else if (pName.equalsIgnoreCase("RateConsumableCost")) RATE_CONSUMABLE_COST = Float.parseFloat(pValue);
+        else if (pName.equalsIgnoreCase("RateDropItems")) RATE_DROP_ITEMS = Float.parseFloat(pValue);
+        else if (pName.equalsIgnoreCase("RateDropSpoil")) RATE_DROP_SPOIL = Float.parseFloat(pValue);
+        else if (pName.equalsIgnoreCase("RateDropManor")) RATE_DROP_MANOR = Integer.parseInt(pValue);
+        else if (pName.equalsIgnoreCase("RateDropQuest")) RATE_DROP_QUEST = Float.parseFloat(pValue);
+        else if (pName.equalsIgnoreCase("RateKarmaExpLost")) RATE_KARMA_EXP_LOST = Float.parseFloat(pValue);
+        else if (pName.equalsIgnoreCase("RateSiegeGuardsPrice")) RATE_SIEGE_GUARDS_PRICE = Float.parseFloat(pValue);
+
+        else if (pName.equalsIgnoreCase("PlayerDropLimit")) PLAYER_DROP_LIMIT = Integer.parseInt(pValue);
+        else if (pName.equalsIgnoreCase("PlayerRateDrop")) PLAYER_RATE_DROP = Integer.parseInt(pValue);
+        else if (pName.equalsIgnoreCase("PlayerRateDropItem")) PLAYER_RATE_DROP_ITEM = Integer.parseInt(pValue);
+        else if (pName.equalsIgnoreCase("PlayerRateDropEquip")) PLAYER_RATE_DROP_EQUIP = Integer.parseInt(pValue);
+        else if (pName.equalsIgnoreCase("PlayerRateDropEquipWeapon")) PLAYER_RATE_DROP_EQUIP_WEAPON = Integer.parseInt(pValue);
+
+        else if (pName.equalsIgnoreCase("KarmaDropLimit")) KARMA_DROP_LIMIT = Integer.parseInt(pValue);
+        else if (pName.equalsIgnoreCase("KarmaRateDrop")) KARMA_RATE_DROP = Integer.parseInt(pValue);
+        else if (pName.equalsIgnoreCase("KarmaRateDropItem")) KARMA_RATE_DROP_ITEM = Integer.parseInt(pValue);
+        else if (pName.equalsIgnoreCase("KarmaRateDropEquip")) KARMA_RATE_DROP_EQUIP = Integer.parseInt(pValue);
+        else if (pName.equalsIgnoreCase("KarmaRateDropEquipWeapon")) KARMA_RATE_DROP_EQUIP_WEAPON = Integer.parseInt(pValue);
+
+        else if (pName.equalsIgnoreCase("AutoDestroyDroppedItemAfter")) AUTODESTROY_ITEM_AFTER = Integer.parseInt(pValue);
+        else if (pName.equalsIgnoreCase("DestroyPlayerDroppedItem")) DESTROY_DROPPED_PLAYER_ITEM = Boolean.valueOf(pValue);
+        else if (pName.equalsIgnoreCase("DestroyEquipableItem")) DESTROY_EQUIPABLE_PLAYER_ITEM = Boolean.valueOf(pValue);
+        else if (pName.equalsIgnoreCase("SaveDroppedItem")) SAVE_DROPPED_ITEM = Boolean.valueOf(pValue);
+        else if (pName.equalsIgnoreCase("EmptyDroppedItemTableAfterLoad")) EMPTY_DROPPED_ITEM_TABLE_AFTER_LOAD = Boolean.valueOf(pValue);
+        else if (pName.equalsIgnoreCase("SaveDroppedItemInterval")) SAVE_DROPPED_ITEM_INTERVAL = Integer.parseInt(pValue);
+        else if (pName.equalsIgnoreCase("ClearDroppedItemTable")) CLEAR_DROPPED_ITEM_TABLE = Boolean.valueOf(pValue);
+
+        else if (pName.equalsIgnoreCase("PreciseDropCalculation")) PRECISE_DROP_CALCULATION = Boolean.valueOf(pValue);
+        else if (pName.equalsIgnoreCase("MultipleItemDrop")) MULTIPLE_ITEM_DROP = Boolean.valueOf(pValue);
+        else if (pName.equalsIgnoreCase("CoordSynchronize")) COORD_SYNCHRONIZE = Integer.parseInt(pValue);
+        else if (pName.equalsIgnoreCase("DeleteCharAfterDays")) DELETE_DAYS = Integer.parseInt(pValue);
+
+        else if (pName.equalsIgnoreCase("AllowDiscardItem")) ALLOW_DISCARDITEM = Boolean.valueOf(pValue);
+        else if (pName.equalsIgnoreCase("AllowFreight")) ALLOW_FREIGHT = Boolean.valueOf(pValue);
+        else if (pName.equalsIgnoreCase("AllowWarehouse")) ALLOW_WAREHOUSE = Boolean.valueOf(pValue);
+        else if (pName.equalsIgnoreCase("AllowWear")) ALLOW_WEAR = Boolean.valueOf(pValue);
+        else if (pName.equalsIgnoreCase("WearDelay")) WEAR_DELAY = Integer.parseInt(pValue);
+        else if (pName.equalsIgnoreCase("WearPrice")) WEAR_PRICE = Integer.parseInt(pValue);
+        else if (pName.equalsIgnoreCase("AllowWater")) ALLOW_WATER = Boolean.valueOf(pValue);
+        else if (pName.equalsIgnoreCase("AllowRentPet")) ALLOW_RENTPET = Boolean.valueOf(pValue);
+        else if (pName.equalsIgnoreCase("AllowBoat")) ALLOW_BOAT = Boolean.valueOf(pValue);
+        else if (pName.equalsIgnoreCase("AllowCursedWeapons")) ALLOW_CURSED_WEAPONS = Boolean.valueOf(pValue);
+        else if (pName.equalsIgnoreCase("AllowManor")) ALLOW_MANOR = Boolean.valueOf(pValue);        
+        else if (pName.equalsIgnoreCase("BypassValidation")) BYPASS_VALIDATION = Boolean.valueOf(pValue);
+
+        else if (pName.equalsIgnoreCase("CommunityType")) COMMUNITY_TYPE = pValue.toLowerCase();
+        else if (pName.equalsIgnoreCase("BBSDefault")) BBS_DEFAULT = pValue;
+        else if (pName.equalsIgnoreCase("ShowLevelOnCommunityBoard")) SHOW_LEVEL_COMMUNITYBOARD = Boolean.valueOf(pValue);
+        else if (pName.equalsIgnoreCase("ShowStatusOnCommunityBoard")) SHOW_STATUS_COMMUNITYBOARD = Boolean.valueOf(pValue);
+        else if (pName.equalsIgnoreCase("NamePageSizeOnCommunityBoard")) NAME_PAGE_SIZE_COMMUNITYBOARD = Integer.parseInt(pValue);
+        else if (pName.equalsIgnoreCase("NamePerRowOnCommunityBoard")) NAME_PER_ROW_COMMUNITYBOARD = Integer.parseInt(pValue);
+
+        else if (pName.equalsIgnoreCase("ShowServerNews")) SERVER_NEWS = Boolean.valueOf(pValue);
+        else if (pName.equalsIgnoreCase("ShowNpcLevel")) SHOW_NPC_LVL = Boolean.valueOf(pValue);
+
+        else if (pName.equalsIgnoreCase("ForceInventoryUpdate")) FORCE_INVENTORY_UPDATE = Boolean.valueOf(pValue);
+
+        else if (pName.equalsIgnoreCase("AutoDeleteInvalidQuestData")) AUTODELETE_INVALID_QUEST_DATA = Boolean.valueOf(pValue);
+
+        else if (pName.equalsIgnoreCase("MaximumOnlineUsers")) MAXIMUM_ONLINE_USERS = Integer.parseInt(pValue);
+
+        else if (pName.equalsIgnoreCase("ZoneTown")) ZONE_TOWN = Integer.parseInt(pValue);
+
+        else if (pName.equalsIgnoreCase("MaximumUpdateDistance")) MINIMUM_UPDATE_DISTANCE = Integer.parseInt(pValue);
+        else if (pName.equalsIgnoreCase("MinimumUpdateTime")) MINIMUN_UPDATE_TIME = Integer.parseInt(pValue);
+        else if (pName.equalsIgnoreCase("CheckKnownList")) CHECK_KNOWN = Boolean.valueOf(pValue);
+        else if (pName.equalsIgnoreCase("KnownListForgetDelay")) KNOWNLIST_FORGET_DELAY = Integer.parseInt(pValue);
+
+        // Other settings
+        else if (pName.equalsIgnoreCase("UseDeepBlueDropRules")) DEEPBLUE_DROP_RULES = Boolean.valueOf(pValue);
+        else if (pName.equalsIgnoreCase("AllowGuards")) ALLOW_GUARDS = Boolean.valueOf(pValue);
+        else if (pName.equalsIgnoreCase("CancelLesserEffect")) EFFECT_CANCELING = Boolean.valueOf(pValue);
+        else if (pName.equalsIgnoreCase("WyvernSpeed")) WYVERN_SPEED = Integer.parseInt(pValue);
+        else if (pName.equalsIgnoreCase("StriderSpeed")) STRIDER_SPEED = Integer.parseInt(pValue);
+
+        else if (pName.equalsIgnoreCase("MaximumSlotsForNoDwarf")) INVENTORY_MAXIMUM_NO_DWARF = Integer.parseInt(pValue);
+        else if (pName.equalsIgnoreCase("MaximumSlotsForDwarf")) INVENTORY_MAXIMUM_DWARF = Integer.parseInt(pValue);
+        else if (pName.equalsIgnoreCase("MaximumSlotsForGMPlayer")) INVENTORY_MAXIMUM_GM = Integer.parseInt(pValue);
+
+        else if (pName.equalsIgnoreCase("MaximumWarehouseSlotsForNoDwarf")) WAREHOUSE_SLOTS_NO_DWARF = Integer.parseInt(pValue);
+        else if (pName.equalsIgnoreCase("MaximumWarehouseSlotsForDwarf")) WAREHOUSE_SLOTS_DWARF = Integer.parseInt(pValue);
+        else if (pName.equalsIgnoreCase("MaximumWarehouseSlotsForClan")) WAREHOUSE_SLOTS_CLAN = Integer.parseInt(pValue);
+        else if (pName.equalsIgnoreCase("MaximumFreightSlots")) FREIGHT_SLOTS = Integer.parseInt(pValue);
+
+        else if (pName.equalsIgnoreCase("EnchantChanceWeapon")) ENCHANT_CHANCE_WEAPON = Integer.parseInt(pValue);
+        else if (pName.equalsIgnoreCase("EnchantChanceArmor")) ENCHANT_CHANCE_ARMOR = Integer.parseInt(pValue);
+        else if (pName.equalsIgnoreCase("EnchantChanceJewelry")) ENCHANT_CHANCE_JEWELRY = Integer.parseInt(pValue);
+        else if (pName.equalsIgnoreCase("EnchantMaxWeapon")) ENCHANT_MAX_WEAPON = Integer.parseInt(pValue);
+        else if (pName.equalsIgnoreCase("EnchantMaxArmor")) ENCHANT_MAX_ARMOR = Integer.parseInt(pValue);
+        else if (pName.equalsIgnoreCase("EnchantMaxJewelry")) ENCHANT_MAX_JEWELRY = Integer.parseInt(pValue);
+        else if (pName.equalsIgnoreCase("EnchantSafeMax")) ENCHANT_SAFE_MAX = Integer.parseInt(pValue);
+        else if (pName.equalsIgnoreCase("EnchantSafeMaxFull")) ENCHANT_SAFE_MAX_FULL = Integer.parseInt(pValue);
+
+        else if (pName.equalsIgnoreCase("HpRegenMultiplier")) HP_REGEN_MULTIPLIER = Double.parseDouble(pValue);
+        else if (pName.equalsIgnoreCase("MpRegenMultiplier")) MP_REGEN_MULTIPLIER = Double.parseDouble(pValue);
+        else if (pName.equalsIgnoreCase("CpRegenMultiplier")) CP_REGEN_MULTIPLIER = Double.parseDouble(pValue);
+
+        else if (pName.equalsIgnoreCase("RaidHpRegenMultiplier")) RAID_HP_REGEN_MULTIPLIER = Double.parseDouble(pValue);
+        else if (pName.equalsIgnoreCase("RaidMpRegenMultiplier")) RAID_MP_REGEN_MULTIPLIER = Double.parseDouble(pValue);
+        else if (pName.equalsIgnoreCase("RaidDefenceMultiplier")) RAID_DEFENCE_MULTIPLIER = Double.parseDouble(pValue) /100;
+        else if (pName.equalsIgnoreCase("RaidMinionRespawnTime")) RAID_MINION_RESPAWN_TIMER =Integer.parseInt(pValue);
+
+        else if (pName.equalsIgnoreCase("StartingAdena")) STARTING_ADENA = Integer.parseInt(pValue);
+        else if (pName.equalsIgnoreCase("UnstuckInterval")) UNSTUCK_INTERVAL = Integer.parseInt(pValue);
+
+        else if (pName.equalsIgnoreCase("PlayerSpawnProtection")) PLAYER_SPAWN_PROTECTION = Integer.parseInt(pValue);
+        else if (pName.equalsIgnoreCase("PlayerFakeDeathUpProtection")) PLAYER_FAKEDEATH_UP_PROTECTION = Integer.parseInt(pValue);
+
+        else if (pName.equalsIgnoreCase("PartyXpCutoffMethod")) PARTY_XP_CUTOFF_METHOD = pValue;
+        else if (pName.equalsIgnoreCase("PartyXpCutoffPercent")) PARTY_XP_CUTOFF_PERCENT = Double.parseDouble(pValue);
+        else if (pName.equalsIgnoreCase("PartyXpCutoffLevel")) PARTY_XP_CUTOFF_LEVEL = Integer.parseInt(pValue);
+
+        else if (pName.equalsIgnoreCase("RespawnRestoreCP")) RESPAWN_RESTORE_CP = Double.parseDouble(pValue) / 100;
+        else if (pName.equalsIgnoreCase("RespawnRestoreHP")) RESPAWN_RESTORE_HP = Double.parseDouble(pValue) / 100;
+        else if (pName.equalsIgnoreCase("RespawnRestoreMP")) RESPAWN_RESTORE_MP = Double.parseDouble(pValue) / 100;
+
+        else if (pName.equalsIgnoreCase("MaxPvtStoreSlotsDwarf")) MAX_PVTSTORE_SLOTS_DWARF = Integer.parseInt(pValue);
+        else if (pName.equalsIgnoreCase("MaxPvtStoreSlotsOther")) MAX_PVTSTORE_SLOTS_OTHER = Integer.parseInt(pValue);
+
+        else if (pName.equalsIgnoreCase("StoreSkillCooltime")) STORE_SKILL_COOLTIME = Boolean.valueOf(pValue);
+        else if (pName.equalsIgnoreCase("AnnounceMammonSpawn")) ANNOUNCE_MAMMON_SPAWN = Boolean.valueOf(pValue);
+
+        // Alternative settings
+        else if (pName.equalsIgnoreCase("AltGameTiredness")) ALT_GAME_TIREDNESS = Boolean.valueOf(pValue);
+        else if (pName.equalsIgnoreCase("AltGameCreation")) ALT_GAME_CREATION = Boolean.valueOf(pValue);
+        else if (pName.equalsIgnoreCase("AltGameCreationSpeed")) ALT_GAME_CREATION_SPEED = Double.parseDouble(pValue);
+        else if (pName.equalsIgnoreCase("AltGameCreationXpRate")) ALT_GAME_CREATION_XP_RATE = Double.parseDouble(pValue);
+        else if (pName.equalsIgnoreCase("AltGameCreationSpRate")) ALT_GAME_CREATION_SP_RATE = Double.parseDouble(pValue);
+        else if (pName.equalsIgnoreCase("AltWeightLimit")) ALT_WEIGHT_LIMIT = Double.parseDouble(pValue);
+        else if (pName.equalsIgnoreCase("AltBlacksmithUseRecipes")) ALT_BLACKSMITH_USE_RECIPES = Boolean.valueOf(pValue);
+        else if (pName.equalsIgnoreCase("AltGameSkillLearn")) ALT_GAME_SKILL_LEARN = Boolean.valueOf(pValue);
+        else if (pName.equalsIgnoreCase("RemoveCastleCirclets")) REMOVE_CASTLE_CIRCLETS = Boolean.valueOf(pValue);
+        else if (pName.equalsIgnoreCase("AltGameCancelByHit"))
+        {
+            ALT_GAME_CANCEL_BOW     = pValue.equalsIgnoreCase("bow") || pValue.equalsIgnoreCase("all");
+            ALT_GAME_CANCEL_CAST    = pValue.equalsIgnoreCase("cast") || pValue.equalsIgnoreCase("all");
+        }
+
+        else if (pName.equalsIgnoreCase("AltShieldBlocks")) ALT_GAME_SHIELD_BLOCKS = Boolean.valueOf(pValue);
+        else if (pName.equalsIgnoreCase("AltPerfectShieldBlockRate")) ALT_PERFECT_SHLD_BLOCK = Integer.parseInt(pValue);
+        else if (pName.equalsIgnoreCase("Delevel")) ALT_GAME_DELEVEL = Boolean.valueOf(pValue);
+        else if (pName.equalsIgnoreCase("MagicFailures")) ALT_GAME_MAGICFAILURES = Boolean.valueOf(pValue);
+        else if (pName.equalsIgnoreCase("AltGameMobAttackAI")) ALT_GAME_MOB_ATTACK_AI = Boolean.valueOf(pValue);
+        else if (pName.equalsIgnoreCase("AltMobAgroInPeaceZone")) ALT_MOB_AGRO_IN_PEACEZONE = Boolean.valueOf(pValue);
+
+        else if (pName.equalsIgnoreCase("AltGameExponentXp")) ALT_GAME_EXPONENT_XP = Float.parseFloat(pValue);
+        else if (pName.equalsIgnoreCase("AltGameExponentSp")) ALT_GAME_EXPONENT_SP = Float.parseFloat(pValue);
+
+        else if (pName.equalsIgnoreCase("AllowClassMasters")) ALLOW_CLASS_MASTERS = Boolean.valueOf(pValue);
+        else if (pName.equalsIgnoreCase("AltGameFreights")) ALT_GAME_FREIGHTS = Boolean.valueOf(pValue);
+        else if (pName.equalsIgnoreCase("AltGameFreightPrice")) ALT_GAME_FREIGHT_PRICE = Integer.parseInt(pValue);
+        else if (pName.equalsIgnoreCase("AltPartyRange")) ALT_PARTY_RANGE = Integer.parseInt(pValue);
+        else if (pName.equalsIgnoreCase("AltPartyRange2")) ALT_PARTY_RANGE2 = Integer.parseInt(pValue);
+
+        else if (pName.equalsIgnoreCase("CraftingEnabled")) IS_CRAFTING_ENABLED = Boolean.valueOf(pValue);
+        else if (pName.equalsIgnoreCase("LifeCrystalNeeded")) LIFE_CRYSTAL_NEEDED = Boolean.valueOf(pValue);
+        else if (pName.equalsIgnoreCase("SpBookNeeded")) SP_BOOK_NEEDED = Boolean.valueOf(pValue);
+        else if (pName.equalsIgnoreCase("AutoLoot")) AUTO_LOOT = Boolean.valueOf(pValue);
+        else if (pName.equalsIgnoreCase("AutoLootHerbs")) AUTO_LOOT_HERBS = Boolean.valueOf(pValue);
+
+        else if (pName.equalsIgnoreCase("AltKarmaPlayerCanBeKilledInPeaceZone")) ALT_GAME_KARMA_PLAYER_CAN_BE_KILLED_IN_PEACEZONE = Boolean.valueOf(pValue);
+        else if (pName.equalsIgnoreCase("AltKarmaPlayerCanShop")) ALT_GAME_KARMA_PLAYER_CAN_SHOP = Boolean.valueOf(pValue);
+        else if (pName.equalsIgnoreCase("AltKarmaPlayerCanUseGK")) ALT_GAME_KARMA_PLAYER_CAN_USE_GK = Boolean.valueOf(pValue);
+        else if (pName.equalsIgnoreCase("AltKarmaPlayerCanTeleport")) ALT_GAME_KARMA_PLAYER_CAN_TELEPORT = Boolean.valueOf(pValue);
+        else if (pName.equalsIgnoreCase("AltKarmaPlayerCanTrade")) ALT_GAME_KARMA_PLAYER_CAN_TRADE = Boolean.valueOf(pValue);
+        else if (pName.equalsIgnoreCase("AltKarmaPlayerCanUseWareHouse")) ALT_GAME_KARMA_PLAYER_CAN_USE_WAREHOUSE = Boolean.valueOf(pValue);
+        else if (pName.equalsIgnoreCase("AltRequireCastleForDawn")) ALT_GAME_REQUIRE_CASTLE_DAWN = Boolean.valueOf(pValue);
+        else if (pName.equalsIgnoreCase("AltRequireClanCastle")) ALT_GAME_REQUIRE_CLAN_CASTLE = Boolean.valueOf(pValue);
+        else if (pName.equalsIgnoreCase("AltFreeTeleporting")) ALT_GAME_FREE_TELEPORT = Boolean.valueOf(pValue);
+        else if (pName.equalsIgnoreCase("AltSubClassWithoutQuests")) ALT_GAME_SUBCLASS_WITHOUT_QUESTS = Boolean.valueOf(pValue);
+        else if (pName.equalsIgnoreCase("AltNewCharAlwaysIsNewbie")) ALT_GAME_NEW_CHAR_ALWAYS_IS_NEWBIE = Boolean.valueOf(pValue);
+        else if (pName.equalsIgnoreCase("AltMembersCanWithdrawFromClanWH")) ALT_MEMBERS_CAN_WITHDRAW_FROM_CLANWH = Boolean.valueOf(pValue);
+        else if (pName.equalsIgnoreCase("DwarfRecipeLimit")) DWARF_RECIPE_LIMIT = Integer.parseInt(pValue);
+        else if (pName.equalsIgnoreCase("CommonRecipeLimit")) COMMON_RECIPE_LIMIT = Integer.parseInt(pValue);
+        else if (pName.equalsIgnoreCase("CastleShieldRestriction")) CASTLE_SHIELD = Boolean.valueOf(pValue);
+        else if (pName.equalsIgnoreCase("ClanHallShieldRestriction")) CLANHALL_SHIELD = Boolean.valueOf(pValue);
+        else if (pName.equalsIgnoreCase("ApellaArmorsRestriction")) APELLA_ARMORS = Boolean.valueOf(pValue);
+        else if (pName.equalsIgnoreCase("OathArmorsRestriction")) OATH_ARMORS = Boolean.valueOf(pValue);
+        else if (pName.equalsIgnoreCase("CastleLordsCrownRestriction")) CASTLE_CROWN = Boolean.valueOf(pValue);
+        else if (pName.equalsIgnoreCase("CastleCircletsRestriction")) CASTLE_CIRCLETS = Boolean.valueOf(pValue);
+
+        //ChampionMobs L2JMOD
+        else if (pName.equalsIgnoreCase("ChampionEnable")) L2JMOD_CHAMPION_ENABLE =  Boolean.valueOf(pValue);
+        else if (pName.equalsIgnoreCase("ChampionFrequency")) L2JMOD_CHAMPION_FREQUENCY = Integer.parseInt(pValue);
+        else if (pName.equalsIgnoreCase("ChampionMinLevel")) L2JMOD_CHAMP_MIN_LVL = Integer.parseInt(pValue);
+        else if (pName.equalsIgnoreCase("ChampionMaxLevel")) L2JMOD_CHAMP_MAX_LVL = Integer.parseInt(pValue);
+        else if (pName.equalsIgnoreCase("ChampionHp")) L2JMOD_CHAMPION_HP = Integer.parseInt(pValue);
+        else if (pName.equalsIgnoreCase("ChampionHpRegen")) L2JMOD_CHAMPION_HP_REGEN = Float.parseFloat(pValue);
+        else if (pName.equalsIgnoreCase("ChampionRewards")) L2JMOD_CHAMPION_REWARDS = Integer.parseInt(pValue);
+        else if (pName.equalsIgnoreCase("ChampionAdenasRewards")) L2JMOD_CHAMPION_ADENAS_REWARDS = Integer.parseInt(pValue);
+        else if (pName.equalsIgnoreCase("ChampionAtk")) L2JMOD_CHAMPION_ATK = Float.parseFloat(pValue);
+        else if (pName.equalsIgnoreCase("ChampionSpdAtk")) L2JMOD_CHAMPION_SPD_ATK = Float.parseFloat(pValue);
+        else if (pName.equalsIgnoreCase("ChampionRewardItem")) L2JMOD_CHAMPION_REWARD = Integer.parseInt(pValue);
+        else if (pName.equalsIgnoreCase("ChampionRewardItemID")) L2JMOD_CHAMPION_REWARD_ID = Integer.parseInt(pValue);
+        else if (pName.equalsIgnoreCase("ChampionRewardItemQty")) L2JMOD_CHAMPION_REWARD_QTY = Integer.parseInt(pValue);
+
+        // L2JMOD Wedding System
+        else if (pName.equalsIgnoreCase("AllowWedding")) L2JMOD_ALLOW_WEDDING = Boolean.valueOf(pValue);
+        else if (pName.equalsIgnoreCase("WeddingPrice")) L2JMOD_WEDDING_PRICE = Integer.parseInt(pValue);
+        else if (pName.equalsIgnoreCase("WeddingPunishInfidelity")) L2JMOD_WEDDING_PUNISH_INFIDELITY = Boolean.parseBoolean(pValue);
+        else if (pName.equalsIgnoreCase("WeddingTeleport")) L2JMOD_WEDDING_TELEPORT = Boolean.parseBoolean(pValue);
+        else if (pName.equalsIgnoreCase("WeddingTeleportPrice")) L2JMOD_WEDDING_TELEPORT_PRICE = Integer.parseInt(pValue);
+        else if (pName.equalsIgnoreCase("WeddingTeleportDuration")) L2JMOD_WEDDING_TELEPORT_DURATION = Integer.parseInt(pValue);
+        else if (pName.equalsIgnoreCase("WeddingAllowSameSex")) L2JMOD_WEDDING_SAMESEX = Boolean.parseBoolean(pValue);
+        else if (pName.equalsIgnoreCase("WeddingFormalWear")) L2JMOD_WEDDING_FORMALWEAR = Boolean.parseBoolean(pValue);
+        else if (pName.equalsIgnoreCase("WeddingDivorceCosts")) L2JMOD_WEDDING_DIVORCE_COSTS = Integer.parseInt(pValue);
+        else if (pName.equalsIgnoreCase("TvTEventEnabled")) TVT_EVENT_ENABLED = Boolean.parseBoolean(pValue);
+        else if (pName.equalsIgnoreCase("TvTEventInterval")) TVT_EVENT_INTERVAL = Integer.parseInt(pValue);
+        else if (pName.equalsIgnoreCase("TvTEventParticipationTime")) TVT_EVENT_PARTICIPATION_TIME = Integer.parseInt(pValue);
+        else if (pName.equalsIgnoreCase("TvTEventRunningTime")) TVT_EVENT_RUNNING_TIME = Integer.parseInt(pValue);
+        else if (pName.equalsIgnoreCase("TvTEventParticipationNpcId")) TVT_EVENT_PARTICIPATION_NPC_ID = Integer.parseInt(pValue);
+
+        // PvP settings
+        else if (pName.equalsIgnoreCase("MinKarma")) KARMA_MIN_KARMA = Integer.parseInt(pValue);
+        else if (pName.equalsIgnoreCase("MaxKarma")) KARMA_MAX_KARMA = Integer.parseInt(pValue);
+        else if (pName.equalsIgnoreCase("XPDivider")) KARMA_XP_DIVIDER = Integer.parseInt(pValue);
+        else if (pName.equalsIgnoreCase("BaseKarmaLost")) KARMA_LOST_BASE = Integer.parseInt(pValue);
+
+        else if (pName.equalsIgnoreCase("CanGMDropEquipment")) KARMA_DROP_GM = Boolean.valueOf(pValue);
+        else if (pName.equalsIgnoreCase("AwardPKKillPVPPoint")) KARMA_AWARD_PK_KILL = Boolean.valueOf(pValue);
+        else if (pName.equalsIgnoreCase("MinimumPKRequiredToDrop")) KARMA_PK_LIMIT = Integer.parseInt(pValue);
+
+        else if (pName.equalsIgnoreCase("PvPVsNormalTime")) PVP_NORMAL_TIME = Integer.parseInt(pValue);
+        else if (pName.equalsIgnoreCase("PvPVsPvPTime")) PVP_PVP_TIME = Integer.parseInt(pValue);
+        else if (pName.equalsIgnoreCase("GlobalChat")) DEFAULT_GLOBAL_CHAT = pValue;
+        else if (pName.equalsIgnoreCase("TradeChat"))  DEFAULT_TRADE_CHAT = pValue;
+        else if (pName.equalsIgnoreCase("MenuStyle"))  GM_ADMIN_MENU_STYLE = pValue;
+        else return false;
+        return true;
+    }
+
+    /**
+     * Allow the player to use L2Walker ?
+     * @param player (L2PcInstance) : Player trying to use L2Walker
+     * @return boolean : true if (L2Walker allowed as a general rule) or (L2Walker client allowed for GM and
+     *                   player is a GM)
+     */
+    public static boolean allowL2Walker(L2PcInstance player)
+    {
+        return (ALLOW_L2WALKER_CLIENT == L2WalkerAllowed.True ||
+                (ALLOW_L2WALKER_CLIENT == L2WalkerAllowed.GM && player != null && player.isGM()));
+    }
+
+    // it has no instances
+    private Config() {}
+
+    /**
+     * Save hexadecimal ID of the server in the properties file.
+     * @param string (String) : hexadecimal ID of the server to store
+     * @see HEXID_FILE
+     * @see saveHexid(String string, String fileName)
+     * @link LoginServerThread
+     */
+    public static void saveHexid(int serverId, String string)
+    {
+        Config.saveHexid(serverId, string, HEXID_FILE);
+    }
+
+    /**
+     * Save hexadecimal ID of the server in the properties file.
+     * @param hexId (String) : hexadecimal ID of the server to store
+     * @param fileName (String) : name of the properties file
+     */
+    public static void saveHexid(int serverId, String hexId, String fileName)
+    {
+        try
+        {
+            Properties hexSetting = new Properties();
+            File file = new File(fileName);
+            //Create a new empty file only if it doesn't exist
+            file.createNewFile();
+            OutputStream out = new FileOutputStream(file);
+            hexSetting.setProperty("ServerID",String.valueOf(serverId));
+            hexSetting.setProperty("HexID",hexId);
+            hexSetting.store(out,"the hexID to auth into login");
+            out.close();
+        }
+        catch (Exception e)
+        {
+            _log.warning("Failed to save hex id to "+fileName+" File.");
+            e.printStackTrace();
+        }
+    }
+
+}

+ 66 - 0
L2_GameServer_T1/java/net/sf/l2j/ConsoleLogFormatter.java

@@ -0,0 +1,66 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+package net.sf.l2j;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.logging.Formatter;
+import java.util.logging.LogRecord;
+
+import javolution.text.TextBuilder;
+
+/**
+ * This class ...
+ *
+ * @version $Revision: 1.1.4.2 $ $Date: 2005/03/27 15:30:08 $
+ */
+
+public class ConsoleLogFormatter extends Formatter
+{
+
+	/* (non-Javadoc)
+	 * @see java.util.logging.Formatter#format(java.util.logging.LogRecord)
+	 */
+//	private static final String _ = " ";
+	private static final String CRLF = "\r\n";
+	@Override
+	public String format(LogRecord record)
+	{
+        TextBuilder output = new TextBuilder();
+//		output.append(record.getLevel().getName());
+//		output.append(_);
+//		output.append(record.getLoggerName());
+//		output.append(_);
+		output.append(record.getMessage());
+		output.append(CRLF);
+		if (record.getThrown() != null) {
+		    try {
+		        StringWriter sw = new StringWriter();
+		        PrintWriter pw = new PrintWriter(sw);
+		        record.getThrown().printStackTrace(pw);
+		        pw.close();
+				output.append(sw.toString());
+				output.append(CRLF);
+		    } catch (Exception ex) {
+		    }
+		}
+
+		return output.toString();
+	}
+}

+ 30 - 0
L2_GameServer_T1/java/net/sf/l2j/ErrorFilter.java

@@ -0,0 +1,30 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+package net.sf.l2j;
+
+import java.util.logging.Filter;
+import java.util.logging.LogRecord;
+
+public class ErrorFilter implements Filter {
+
+	public boolean isLoggable(LogRecord record) {
+		return record.getThrown() != null;
+	}
+
+}

+ 29 - 0
L2_GameServer_T1/java/net/sf/l2j/ErrorLogHandler.java

@@ -0,0 +1,29 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+package net.sf.l2j;
+
+import java.io.IOException;
+import java.util.logging.FileHandler;
+
+public class ErrorLogHandler extends FileHandler {
+
+	public ErrorLogHandler() throws IOException, SecurityException {
+		super();
+	}
+}

+ 62 - 0
L2_GameServer_T1/java/net/sf/l2j/FileLogFormatter.java

@@ -0,0 +1,62 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+package net.sf.l2j;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.logging.Formatter;
+import java.util.logging.LogRecord;
+
+import javolution.text.TextBuilder;
+
+/**
+ * This class ...
+ *
+ * @version $Revision: 1.1.4.1 $ $Date: 2005/03/27 15:30:08 $
+ */
+
+public class FileLogFormatter extends Formatter
+{
+
+	/* (non-Javadoc)
+	 * @see java.util.logging.Formatter#format(java.util.logging.LogRecord)
+	 */
+	private static final String CRLF = "\r\n";
+	private static final String _ = "\t";
+	private SimpleDateFormat dateFmt = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss,SSS");
+
+	@Override
+	public String format(LogRecord record)
+	{
+        TextBuilder output = new TextBuilder();
+
+		return output
+		.append(dateFmt.format(new Date(record.getMillis())))
+		.append(_)
+		.append(record.getLevel().getName())
+		.append(_)
+		.append(record.getThreadID())
+		.append(_)
+		.append(record.getLoggerName())
+		.append(_)
+		.append(record.getMessage())
+		.append(CRLF)
+		.toString();
+	}
+}

+ 29 - 0
L2_GameServer_T1/java/net/sf/l2j/GMAuditFilter.java

@@ -0,0 +1,29 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+package net.sf.l2j;
+
+import java.util.logging.Filter;
+import java.util.logging.LogRecord;
+
+public class GMAuditFilter implements Filter {
+
+	public boolean isLoggable(LogRecord record) {
+		return record.getLoggerName().equalsIgnoreCase("gmaudit");
+	}
+}

+ 32 - 0
L2_GameServer_T1/java/net/sf/l2j/GMAuditFormatter.java

@@ -0,0 +1,32 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+package net.sf.l2j;
+
+import java.util.logging.Formatter;
+import java.util.logging.LogRecord;
+
+public class GMAuditFormatter extends Formatter {
+
+	@Override
+	public String format(LogRecord record) {
+		return record.getMessage()+"\r\n";
+	}
+
+}

+ 30 - 0
L2_GameServer_T1/java/net/sf/l2j/GMAuditLogHandler.java

@@ -0,0 +1,30 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+package net.sf.l2j;
+
+import java.io.IOException;
+import java.util.logging.FileHandler;
+
+public class GMAuditLogHandler extends FileHandler {
+
+	public GMAuditLogHandler() throws IOException, SecurityException {
+		super();
+	}
+}
+

+ 56 - 0
L2_GameServer_T1/java/net/sf/l2j/ItemFilter.java

@@ -0,0 +1,56 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+package net.sf.l2j;
+
+import java.util.logging.Filter;
+import java.util.logging.LogRecord;
+
+import net.sf.l2j.gameserver.model.L2ItemInstance;
+
+/**
+ * @author Advi
+ *
+ */
+public class ItemFilter implements Filter
+{
+	private String _excludeProcess;
+	private String _excludeItemType;
+
+//	This is example how to exclude consuming of shots and arrows from logging
+//	private String _excludeProcess = "Consume";
+//	private String _excludeItemType = "Arrow, Shot";
+
+	public boolean isLoggable(LogRecord record)
+	{
+		if (record.getLoggerName() != "item") return false;
+		if (_excludeProcess != null)
+		{
+//			if (record.getMessage() == null) return true;
+			String[] messageList = record.getMessage().split(":");
+			if (messageList.length < 2 || !_excludeProcess.contains(messageList[1])) return true;
+		}
+		if (_excludeItemType != null)
+		{
+//			if (record.getParameters() == null || record.getParameters().length == 0 || !(record.getParameters()[0] instanceof L2ItemInstance)) return true;
+			L2ItemInstance item = ((L2ItemInstance)record.getParameters()[0]);
+			if (!_excludeItemType.contains(item.getItemType().toString())) return true;
+		}
+		return (_excludeProcess == null && _excludeItemType == null);
+	}
+}

+ 69 - 0
L2_GameServer_T1/java/net/sf/l2j/ItemLogFormatter.java

@@ -0,0 +1,69 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+package net.sf.l2j;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.logging.Formatter;
+import java.util.logging.LogRecord;
+
+import javolution.text.TextBuilder;
+import net.sf.l2j.gameserver.model.L2ItemInstance;
+
+/**
+ * @author Advi
+ *
+ */
+public class ItemLogFormatter extends Formatter
+{
+	private static final String CRLF = "\r\n";
+	private SimpleDateFormat dateFmt = new SimpleDateFormat("dd MMM H:mm:ss");
+
+	@Override
+	public String format(LogRecord record)
+	{
+        TextBuilder output = new TextBuilder();
+		output.append('[');
+		output.append(dateFmt.format(new Date(record.getMillis())));
+		output.append(']');
+		output.append(' ');
+		output.append(record.getMessage());
+		for (Object p : record.getParameters())
+		{
+			if (p == null) continue;
+			output.append(',');
+			output.append(' ');
+			if (p instanceof L2ItemInstance)
+			{
+				L2ItemInstance item = (L2ItemInstance)p;
+				output.append("item " + item.getObjectId() + ":");
+				if (item.getEnchantLevel() > 0) output.append("+" + item.getEnchantLevel() + " ");
+				output.append(item.getItem().getName());
+				output.append("(" + item.getCount() + ")");
+			}
+//			else if (p instanceof L2PcInstance)
+//				output.append(((L2PcInstance)p).getName());
+			else output.append(p.toString()/* + ":" + ((L2Object)p).getObjectId()*/);
+		}
+		output.append(CRLF);
+
+		return output.toString();
+	}
+
+}

+ 34 - 0
L2_GameServer_T1/java/net/sf/l2j/ItemLogHandler.java

@@ -0,0 +1,34 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+package net.sf.l2j;
+
+import java.io.IOException;
+import java.util.logging.FileHandler;
+
+/**
+ * @author Advi
+ *
+ */
+public class ItemLogHandler extends FileHandler
+{
+	public ItemLogHandler() throws IOException, SecurityException
+	{
+		super();
+	}
+}

+ 206 - 0
L2_GameServer_T1/java/net/sf/l2j/L2DatabaseFactory.java

@@ -0,0 +1,206 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+package net.sf.l2j;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.mchange.v2.c3p0.ComboPooledDataSource;
+
+public class L2DatabaseFactory
+{
+    static Logger _log = Logger.getLogger(L2DatabaseFactory.class.getName());
+
+    public static enum ProviderType
+    {
+        MySql,
+        MsSql
+    }
+
+    // =========================================================
+    // Data Field
+    private static L2DatabaseFactory _instance;
+    private ProviderType _providerType;
+	private ComboPooledDataSource _source;
+
+    // =========================================================
+    // Constructor
+	public L2DatabaseFactory() throws SQLException
+	{
+		try
+		{
+			if (Config.DATABASE_MAX_CONNECTIONS < 2)
+            {
+                Config.DATABASE_MAX_CONNECTIONS = 2;
+                _log.warning("at least " + Config.DATABASE_MAX_CONNECTIONS + " db connections are required.");
+            }
+
+			_source = new ComboPooledDataSource();
+			_source.setAutoCommitOnClose(true);
+
+			_source.setInitialPoolSize(10);
+			_source.setMinPoolSize(10);
+			_source.setMaxPoolSize(Config.DATABASE_MAX_CONNECTIONS);
+
+
+			_source.setAcquireRetryAttempts(0); // try to obtain connections indefinitely (0 = never quit)
+			_source.setAcquireRetryDelay(500);  // 500 miliseconds wait before try to acquire connection again
+			_source.setCheckoutTimeout(0);      // 0 = wait indefinitely for new connection
+			// if pool is exhausted
+			_source.setAcquireIncrement(5);     // if pool is exhausted, get 5 more connections at a time
+			// cause there is a "long" delay on acquire connection
+			// so taking more than one connection at once will make connection pooling
+			// more effective.
+
+			// this "connection_test_table" is automatically created if not already there
+			_source.setAutomaticTestTable("connection_test_table");
+			_source.setTestConnectionOnCheckin(false);
+
+			// testing OnCheckin used with IdleConnectionTestPeriod is faster than  testing on checkout
+
+			_source.setIdleConnectionTestPeriod(3600); // test idle connection every 60 sec
+			_source.setMaxIdleTime(0); // 0 = idle connections never expire
+			// *THANKS* to connection testing configured above
+			// but I prefer to disconnect all connections not used
+			// for more than 1 hour
+
+			// enables statement caching,  there is a "semi-bug" in c3p0 0.9.0 but in 0.9.0.2 and later it's fixed
+			_source.setMaxStatementsPerConnection(100);
+
+			_source.setBreakAfterAcquireFailure(false);  // never fail if any way possible
+			// setting this to true will make
+			// c3p0 "crash" and refuse to work
+			// till restart thus making acquire
+			// errors "FATAL" ... we don't want that
+			// it should be possible to recover
+			_source.setDriverClass(Config.DATABASE_DRIVER);
+			_source.setJdbcUrl(Config.DATABASE_URL);
+			_source.setUser(Config.DATABASE_LOGIN);
+			_source.setPassword(Config.DATABASE_PASSWORD);
+
+			/* Test the connection */
+			_source.getConnection().close();
+
+			if (Config.DEBUG) _log.fine("Database Connection Working");
+
+			if (Config.DATABASE_DRIVER.toLowerCase().contains("microsoft"))
+                _providerType = ProviderType.MsSql;
+            else
+                _providerType = ProviderType.MySql;
+		}
+		catch (SQLException x)
+		{
+			if (Config.DEBUG) _log.fine("Database Connection FAILED");
+			// rethrow the exception
+			throw x;
+		}
+		catch (Exception e)
+		{
+			if (Config.DEBUG) _log.fine("Database Connection FAILED");
+			throw new SQLException("could not init DB connection:"+e);
+		}
+	}
+
+    // =========================================================
+    // Method - Public
+    public final String prepQuerySelect(String[] fields, String tableName, String whereClause, boolean returnOnlyTopRecord)
+    {
+        String msSqlTop1 = "";
+        String mySqlTop1 = "";
+        if (returnOnlyTopRecord)
+        {
+            if (getProviderType() == ProviderType.MsSql) msSqlTop1 = " Top 1 ";
+            if (getProviderType() == ProviderType.MySql) mySqlTop1 = " Limit 1 ";
+        }
+        String query = "SELECT " + msSqlTop1 + safetyString(fields) + " FROM " + tableName + " WHERE " + whereClause + mySqlTop1;
+        return query;
+    }
+
+    public void shutdown()
+    {
+        try {
+            _source.close();
+        } catch (Exception e) {_log.log(Level.INFO, "", e);}
+        try {
+            _source = null;
+        } catch (Exception e) {_log.log(Level.INFO, "", e);}
+    }
+
+    public final String safetyString(String... whatToCheck)
+    {
+        // NOTE: Use brace as a safty percaution just incase name is a reserved word
+        String braceLeft = "`";
+        String braceRight = "`";
+        if (getProviderType() == ProviderType.MsSql)
+        {
+            braceLeft = "[";
+            braceRight = "]";
+        }
+
+        String result = "";
+        for(String word : whatToCheck)
+        {
+            if(result != "") result += ", ";
+            result += braceLeft + word + braceRight;
+        }
+        return result;
+    }
+
+    // =========================================================
+    // Property - Public
+	public static L2DatabaseFactory getInstance() throws SQLException
+	{
+		if (_instance == null)
+		{
+			_instance = new L2DatabaseFactory();
+		}
+		return _instance;
+	}
+
+	public Connection getConnection() //throws SQLException
+	{
+		Connection con=null;
+
+		while(con==null)
+		{
+			try
+			{
+				con=_source.getConnection();
+			} catch (SQLException e)
+			{
+				_log.warning("L2DatabaseFactory: getConnection() failed, trying again "+e);
+			}
+		}
+		return con;
+	}
+
+	public int getBusyConnectionCount() throws SQLException
+	{
+	    return _source.getNumBusyConnectionsDefaultUser();
+	}
+
+	public int getIdleConnectionCount() throws SQLException
+	{
+	    return _source.getNumIdleConnectionsDefaultUser();
+	}
+
+    public final ProviderType getProviderType() { return _providerType; }
+}

+ 34 - 0
L2_GameServer_T1/java/net/sf/l2j/Server.java

@@ -0,0 +1,34 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+package net.sf.l2j;
+
+/**
+ * This class used to be the starter class, since LS/GS split, it only retains server mode
+ *
+ */
+public class Server
+{
+	//constants for the server mode
+	public static final int MODE_NONE = 0;
+	public static final int MODE_GAMESERVER = 1;
+	public static final int MODE_LOGINSERVER = 2;
+
+	public static int serverMode = MODE_NONE;
+
+}

+ 350 - 0
L2_GameServer_T1/java/net/sf/l2j/accountmanager/SQLAccountManager.java

@@ -0,0 +1,350 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+package net.sf.l2j.accountmanager;
+
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.LineNumberReader;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+import net.sf.l2j.Base64;
+import net.sf.l2j.Config;
+import net.sf.l2j.L2DatabaseFactory;
+import net.sf.l2j.Server;
+
+/**
+ * This class SQL Account Manager
+ *
+ * @author netimperia
+ * @version $Revision: 2.3.2.1.2.3 $ $Date: 2005/08/08 22:47:12 $
+ */
+public class SQLAccountManager
+{
+	private static String _uname = "";
+	private static String _pass = "";
+	private static String _level = "";
+	private static String _mode = "";
+
+	public static void main(String[] args) throws SQLException, IOException, NoSuchAlgorithmException
+	{
+		Server.serverMode = Server.MODE_LOGINSERVER;
+		Config.load();
+		System.out.println("Please choose an option:");
+        System.out.println("");
+		System.out.println("1 - Create new account or update existing one (change pass and access level).");
+		System.out.println("2 - Change access level.");
+		System.out.println("3 - Delete existing account.");
+		System.out.println("4 - List accounts & access levels.");
+		System.out.println("5 - Exit.");
+		LineNumberReader _in = new LineNumberReader(new InputStreamReader(System.in));
+		while (!(_mode.equals("1") || _mode.equals("2") || _mode.equals("3")
+				|| _mode.equals("4") || _mode.equals("5")) )
+		{
+			System.out.print("Your choice: ");
+			_mode = _in.readLine();
+		}
+
+		if (_mode.equals("1") || _mode.equals("2") || _mode.equals("3"))
+		{
+			if (_mode.equals("1") || _mode.equals("2") || _mode.equals("3"))
+			while (_uname.length() == 0)
+			{
+				System.out.print("Username: ");
+				_uname = _in.readLine().toLowerCase();
+			}
+
+			if (_mode.equals("1"))
+			while (_pass.length() == 0)
+			{
+				System.out.print("Password: ");
+				_pass = _in.readLine();
+			}
+
+			if (_mode.equals("1") || _mode.equals("2"))
+			while (_level.length() == 0)
+			{
+				System.out.print("Access level: ");
+				_level = _in.readLine();
+			}
+
+		}
+
+		if (_mode.equals("1")) {
+			// Add or Update
+			addOrUpdateAccount(_uname,_pass,_level);
+		} else if(_mode.equals("2")) {
+			// Change Level
+			changeAccountLevel(_uname,_level);
+		} else if(_mode.equals("3")) {
+			// Delete
+			System.out.print("Do you really want to delete this account ? Y/N : ");
+			String yesno = _in.readLine();
+			if (yesno.equals("Y"))
+			{
+				// Yes
+				deleteAccount(_uname);
+			}
+
+		} else if(_mode.equals("4")) {
+			// List
+ 			printAccInfo();
+		}
+
+		return;
+	}
+
+	private static void printAccInfo() throws SQLException
+	{
+		int count = 0;
+		java.sql.Connection con = null;
+		con = L2DatabaseFactory.getInstance().getConnection();
+		PreparedStatement statement = con.prepareStatement("SELECT login, access_level FROM accounts ORDER BY login ASC");
+		ResultSet rset = statement.executeQuery();
+        while (rset.next())
+        {
+			System.out.println(rset.getString("login")	+ " -> " + rset.getInt("access_level"));
+			count++;
+        }
+		rset.close();
+		statement.close();
+		System.out.println("Number of accounts: " + count + ".");
+	}
+
+	private static void addOrUpdateAccount(String account,String password, String level) throws IOException, SQLException, NoSuchAlgorithmException
+	{
+		// Encode Password
+		MessageDigest md = MessageDigest.getInstance("SHA");
+		byte[] newpass;
+		newpass = password.getBytes("UTF-8");
+		newpass = md.digest(newpass);
+
+		// Add to Base
+		java.sql.Connection con = null;
+		con = L2DatabaseFactory.getInstance().getConnection();
+		PreparedStatement statement = con.prepareStatement("REPLACE	accounts (login, password, access_level) VALUES (?,?,?)");
+		statement.setString(1, account);
+		statement.setString(2, Base64.encodeBytes(newpass));
+		statement.setString(3, level);
+		statement.executeUpdate();
+		statement.close();
+	}
+
+	private static void changeAccountLevel(String account, String level) throws SQLException
+	{
+		java.sql.Connection con = null;
+		con = L2DatabaseFactory.getInstance().getConnection();
+
+		// Check Account Exist
+		PreparedStatement statement = con.prepareStatement("SELECT COUNT(*) FROM accounts WHERE login=?;");
+		statement.setString(1, account);
+		ResultSet rset = statement.executeQuery();
+		if(rset.next()==false) {
+			System.out.println("False");
+
+		} else if(rset.getInt(1)>0) {
+
+			// Exist
+
+			// Update
+			statement = con.prepareStatement("UPDATE accounts SET access_level=? WHERE login=?;");
+			statement.setEscapeProcessing(true);
+			statement.setString(1, level);
+			statement.setString(2, account);
+			statement.executeUpdate();
+
+			System.out.println("Account " + account + " has been updated.");
+		} else {
+			// Not Exist
+			System.out.println("Account " + account + " does not exist.");
+		}
+		rset.close();
+
+		// Close Connection
+		statement.close();
+	}
+
+	private static void deleteAccount(String account) throws SQLException
+	{
+		java.sql.Connection con = null;
+		con = L2DatabaseFactory.getInstance().getConnection();
+
+		// Check Account Exist
+		PreparedStatement statement = con.prepareStatement("SELECT COUNT(*) FROM accounts WHERE login=?;");
+		statement.setString(1, account);
+		ResultSet rset = statement.executeQuery();
+		if(rset.next()==false) {
+			System.out.println("False");
+			rset.close();
+		} else if(rset.getInt(1)>0) {
+			rset.close();
+			// Account exist
+
+			// Get Accounts ID
+			ResultSet rcln;
+			statement = con.prepareStatement("SELECT obj_Id, char_name, clanid FROM characters WHERE account_name=?;");
+			statement.setEscapeProcessing(true);
+			statement.setString(1, account);
+			rset = statement.executeQuery();
+
+			while (rset.next())
+			{
+				System.out.println("Deleting character " + rset.getString("char_name") + ".");
+
+				// Check If clan leader Remove Clan and remove all from it
+				statement.close();
+				statement = con.prepareStatement("SELECT COUNT(*) FROM clan_data WHERE leader_id=?;");
+				statement.setString(1, rset.getString("clanid"));
+				rcln = statement.executeQuery();
+				rcln.next();
+				if(rcln.getInt(1)>0) {
+					rcln.close();
+					// Clan Leader
+
+					// Get Clan Name
+					statement.close();
+					statement = con.prepareStatement("SELECT clan_name FROM clan_data WHERE leader_id=?;");
+					statement.setString(1, rset.getString("clanid"));
+					rcln = statement.executeQuery();
+					rcln.next();
+
+					System.out.println("Deleting clan " + rcln.getString("clan_name") + ".");
+
+					// Delete Clan Wars
+					statement.close();
+					statement = con.prepareStatement("DELETE FROM clan_wars WHERE clan1=? OR clan2=?;");
+					statement.setEscapeProcessing(true);
+					statement.setString(1, rcln.getString("clan_name"));
+					statement.setString(2, rcln.getString("clan_name"));
+					statement.executeUpdate();
+
+					rcln.close();
+
+					// Remove All From clan
+					statement.close();
+					statement = con.prepareStatement("UPDATE characters SET clanid=0 WHERE clanid=?;");
+					statement.setString(1, rset.getString("clanid"));
+					statement.executeUpdate();
+
+
+					// Delete Clan
+					statement.close();
+					statement = con.prepareStatement("DELETE FROM clan_data WHERE clan_id=?;");
+					statement.setString(1, rset.getString("clanid"));
+					statement.executeUpdate();
+
+					statement.close();
+					statement = con.prepareStatement("DELETE FROM clan_privs WHERE clan_id=?;");
+					statement.setString(1, rset.getString("clanid"));
+					statement.executeUpdate();
+
+					statement.close();
+					statement = con.prepareStatement("DELETE FROM clan_subpledges WHERE clan_id=?;");
+					statement.setString(1, rset.getString("clanid"));
+					statement.executeUpdate();
+
+				} else {
+					rcln.close();
+				}
+
+				// skills
+				statement.close();
+				statement = con.prepareStatement("DELETE FROM character_skills WHERE char_obj_id=?;");
+				statement.setString(1, rset.getString("obj_Id"));
+				statement.executeUpdate();
+
+				// shortcuts
+				statement.close();
+				statement = con.prepareStatement("DELETE FROM character_shortcuts WHERE char_obj_id=?;");
+				statement.setString(1, rset.getString("obj_Id"));
+				statement.executeUpdate();
+
+				// items
+				statement.close();
+				statement = con.prepareStatement("DELETE FROM items WHERE owner_id=?;");
+				statement.setString(1, rset.getString("obj_Id"));
+				statement.executeUpdate();
+
+				// recipebook
+				statement.close();
+				statement = con.prepareStatement("DELETE FROM character_recipebook WHERE char_id=?;");
+				statement.setString(1, rset.getString("obj_Id"));
+				statement.executeUpdate();
+
+				// quests
+				statement.close();
+				statement = con.prepareStatement("DELETE FROM character_quests WHERE char_id=?;");
+				statement.setString(1, rset.getString("obj_Id"));
+				statement.executeUpdate();
+
+				// macroses
+				statement.close();
+				statement = con.prepareStatement("DELETE FROM character_macroses WHERE char_obj_id=?;");
+				statement.setString(1, rset.getString("obj_Id"));
+				statement.executeUpdate();
+
+				// friends
+				statement.close();
+				statement = con.prepareStatement("DELETE FROM character_friends WHERE char_id=?;");
+				statement.setString(1, rset.getString("obj_Id"));
+				statement.executeUpdate();
+
+				// merchant_lease
+				statement.close();
+				statement = con.prepareStatement("DELETE FROM merchant_lease WHERE player_id=?;");
+				statement.setString(1, rset.getString("obj_Id"));
+				statement.executeUpdate();
+
+				// boxaccess
+				statement.close();
+				statement = con.prepareStatement("DELETE FROM boxaccess WHERE charname=?;");
+				statement.setString(1, rset.getString("char_name"));
+				statement.executeUpdate();
+
+				// characters
+				statement.close();
+				statement = con.prepareStatement("DELETE FROM characters WHERE obj_Id=?;");
+				statement.setString(1, rset.getString("obj_Id"));
+				statement.executeUpdate();
+
+			}
+
+			// Delete Account
+			statement.close();
+			statement = con.prepareStatement("DELETE FROM accounts WHERE login=?;");
+			statement.setEscapeProcessing(true);
+			statement.setString(1, account);
+			statement.executeUpdate();
+
+			System.out.println("Account " + account + " has been deleted.");
+		} else {
+			// Not Exist
+			System.out.println("Account " + account + " does not exist.");
+		}
+
+		// Close Connection
+		rset.close();
+		statement.close();
+		con.close();
+	}
+
+}

+ 246 - 0
L2_GameServer_T1/java/net/sf/l2j/gameserver/Announcements.java

@@ -0,0 +1,246 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+package net.sf.l2j.gameserver;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.LineNumberReader;
+import java.util.Date;
+import java.util.List;
+import java.util.StringTokenizer;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javolution.text.TextBuilder;
+import javolution.util.FastList;
+import net.sf.l2j.Config;
+import net.sf.l2j.gameserver.cache.HtmCache;
+import net.sf.l2j.gameserver.clientpackets.Say2;
+import net.sf.l2j.gameserver.model.L2World;
+import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
+import net.sf.l2j.gameserver.network.SystemMessageId;
+import net.sf.l2j.gameserver.script.DateRange;
+import net.sf.l2j.gameserver.serverpackets.CreatureSay;
+import net.sf.l2j.gameserver.serverpackets.NpcHtmlMessage;
+import net.sf.l2j.gameserver.serverpackets.SystemMessage;
+
+/**
+ * This class ...
+ *
+ * @version $Revision: 1.5.2.1.2.7 $ $Date: 2005/03/29 23:15:14 $
+ */
+public class Announcements
+{
+	private static Logger _log = Logger.getLogger(Announcements.class.getName());
+
+	private static Announcements _instance;
+	private List<String> _announcements = new FastList<String>();
+	private List<List<Object>> _eventAnnouncements = new FastList<List<Object>>();
+
+	public Announcements()
+	{
+		loadAnnouncements();
+	}
+
+	public static Announcements getInstance()
+	{
+		if (_instance == null)
+		{
+			_instance = new Announcements();
+		}
+
+		return _instance;
+	}
+
+
+	public void loadAnnouncements()
+	{
+		_announcements.clear();
+		File file = new File(Config.DATAPACK_ROOT, "data/announcements.txt");
+		if (file.exists())
+		{
+			readFromDisk(file);
+		}
+		else
+		{
+			_log.config("data/announcements.txt doesn't exist");
+		}
+	}
+
+	public void showAnnouncements(L2PcInstance activeChar)
+	{
+		for (int i = 0; i < _announcements.size(); i++)
+		{
+			CreatureSay cs = new CreatureSay(0, Say2.ANNOUNCEMENT, activeChar.getName(), _announcements.get(i));
+			activeChar.sendPacket(cs);
+		}
+
+		for (int i = 0; i < _eventAnnouncements.size(); i++)
+		{
+		    List<Object> entry   = _eventAnnouncements.get(i);
+
+            DateRange validDateRange  = (DateRange)entry.get(0);
+            String[] msg              = (String[])entry.get(1);
+		    Date currentDate          = new Date();
+
+		    if (!validDateRange.isValid() || validDateRange.isWithinRange(currentDate))
+		    {
+                SystemMessage sm = new SystemMessage(SystemMessageId.S1_S2);
+                for (int j=0; j<msg.length; j++)
+                {
+                    sm.addString(msg[j]);
+                }
+                activeChar.sendPacket(sm);
+		    }
+
+		}
+	}
+
+	public void addEventAnnouncement(DateRange validDateRange, String[] msg)
+	{
+	    List<Object> entry = new FastList<Object>();
+	    entry.add(validDateRange);
+	    entry.add(msg);
+	    _eventAnnouncements.add(entry);
+	}
+
+	public void listAnnouncements(L2PcInstance activeChar)
+	{
+        String content = HtmCache.getInstance().getHtmForce("data/html/admin/announce.htm");
+        NpcHtmlMessage adminReply = new NpcHtmlMessage(5);
+        adminReply.setHtml(content);
+        TextBuilder replyMSG = new TextBuilder("<br>");
+		for (int i = 0; i < _announcements.size(); i++)
+		{
+			replyMSG.append("<table width=260><tr><td width=220>" + _announcements.get(i) + "</td><td width=40>");
+			replyMSG.append("<button value=\"Delete\" action=\"bypass -h admin_del_announcement " + i + "\" width=60 height=15 back=\"sek.cbui94\" fore=\"sek.cbui92\"></td></tr></table>");
+		}
+        adminReply.replace("%announces%", replyMSG.toString());
+		activeChar.sendPacket(adminReply);
+	}
+
+	public void addAnnouncement(String text)
+	{
+		_announcements.add(text);
+		saveToDisk();
+	}
+
+	public void delAnnouncement(int line)
+	{
+		_announcements.remove(line);
+		saveToDisk();
+	}
+
+	private void readFromDisk(File file)
+	{
+		LineNumberReader lnr = null;
+		try
+		{
+			int i=0;
+			String line = null;
+			lnr = new LineNumberReader(new FileReader(file));
+			while ( (line = lnr.readLine()) != null)
+			{
+				StringTokenizer st = new StringTokenizer(line,"\n\r");
+				if (st.hasMoreTokens())
+				{
+					String announcement = st.nextToken();
+					_announcements.add(announcement);
+
+					i++;
+				}
+			}
+
+			_log.config("Announcements: Loaded " + i + " Announcements.");
+		}
+		catch (IOException e1)
+		{
+			_log.log(Level.SEVERE, "Error reading announcements", e1);
+		}
+		finally
+		{
+			try
+			{
+				lnr.close();
+			}
+			catch (Exception e2)
+			{
+				// nothing
+			}
+		}
+	}
+
+	private void saveToDisk()
+	{
+		File file = new File("data/announcements.txt");
+		FileWriter save = null;
+
+		try
+		{
+			save = new FileWriter(file);
+			for (int i = 0; i < _announcements.size(); i++)
+			{
+				save.write(_announcements.get(i));
+				save.write("\r\n");
+			}
+			save.flush();
+			save.close();
+			save = null;
+		}
+		catch (IOException e)
+		{
+			_log.warning("saving the announcements file has failed: " + e);
+		}
+	}
+
+	public void announceToAll(String text) {
+		CreatureSay cs = new CreatureSay(0, Say2.ANNOUNCEMENT, "", text);
+
+		for (L2PcInstance player : L2World.getInstance().getAllPlayers())
+		{
+			player.sendPacket(cs);
+		}
+	}
+	public void announceToAll(SystemMessage sm) {
+
+		for (L2PcInstance player : L2World.getInstance().getAllPlayers())
+		{
+			player.sendPacket(sm);
+		}
+	}
+
+	// Method fo handling announcements from admin
+	public void handleAnnounce(String command, int lengthToTrim)
+	{
+		try
+		{
+			// Announce string to everyone on server
+			String text = command.substring(lengthToTrim);
+			Announcements.getInstance().announceToAll(text);
+		}
+
+		// No body cares!
+		catch (StringIndexOutOfBoundsException e)
+		{
+			// empty message.. ignore
+		}
+	}
+}

+ 72 - 0
L2_GameServer_T1/java/net/sf/l2j/gameserver/CastleUpdater.java

@@ -0,0 +1,72 @@
+/* This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+package net.sf.l2j.gameserver;
+
+import java.util.logging.Logger;
+
+import net.sf.l2j.Config;
+import net.sf.l2j.gameserver.instancemanager.CastleManager;
+import net.sf.l2j.gameserver.model.ItemContainer;
+import net.sf.l2j.gameserver.model.L2Clan;
+import net.sf.l2j.gameserver.model.entity.Castle;
+
+/**
+ *
+ * Thorgrim - 2005
+ * Class managing periodical events with castle
+ *
+ */
+public class CastleUpdater implements Runnable
+{
+		protected static Logger _log = Logger.getLogger(CastleUpdater.class.getName());
+		private L2Clan _clan;
+        private int _runCount = 0;
+
+		public CastleUpdater(L2Clan clan, int runCount)
+		{
+			_clan = clan;
+            _runCount = runCount;
+		}
+
+		public void run()
+		{
+			try
+			{
+				// Move current castle treasury to clan warehouse every 2 hour
+				ItemContainer warehouse = _clan.getWarehouse();
+				if ((warehouse != null) && (_clan.getHasCastle() > 0))
+				{
+					Castle castle = CastleManager.getInstance().getCastleById(_clan.getHasCastle());
+					if (!Config.ALT_MANOR_SAVE_ALL_ACTIONS)
+					{
+						if (_runCount % Config.ALT_MANOR_SAVE_PERIOD_RATE == 0)
+						{
+							castle.saveSeedData();
+							castle.saveCropData();
+							_log.info("Manor System: all data for " + castle.getName() + " saved");
+						}
+					}
+                    _runCount++;
+					CastleUpdater cu = new CastleUpdater(_clan, _runCount);
+					ThreadPoolManager.getInstance().scheduleGeneral(cu, 3600000);
+				}
+			} catch (Throwable e) {
+				e.printStackTrace();
+			}
+		}
+}

+ 93 - 0
L2_GameServer_T1/java/net/sf/l2j/gameserver/Crypt.java

@@ -0,0 +1,93 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+package net.sf.l2j.gameserver;
+
+import java.nio.ByteBuffer;
+
+
+/**
+ * This class ...
+ *
+ * @version $Revision: 1.3.4.3 $ $Date: 2005/03/27 15:29:18 $
+ */
+public class Crypt
+{
+	private final byte[] _key = new byte[16];
+	private boolean _isEnabled;
+
+	public void setKey(byte[] key)
+	{
+		System.arraycopy(key,0, _key, 0, key.length);
+		_isEnabled = true;
+	}
+
+	public void decrypt(ByteBuffer buf)
+	{
+		if (!_isEnabled)
+			return;
+
+		final int sz = buf.remaining();
+		int temp = 0;
+		for (int i = 0; i < sz; i++)
+		{
+			int temp2 = buf.get(i);
+			buf.put(i, (byte)(temp2 ^ _key[i&15] ^ temp));
+			temp = temp2;
+		}
+
+		int old = _key[8] &0xff;
+		old |= _key[9] << 8 &0xff00;
+		old |= _key[10] << 0x10 &0xff0000;
+		old |= _key[11] << 0x18 &0xff000000;
+
+		old += sz;
+
+		_key[8] = (byte)(old &0xff);
+		_key[9] = (byte)(old >> 0x08 &0xff);
+		_key[10] = (byte)(old >> 0x10 &0xff);
+		_key[11] = (byte)(old >> 0x18 &0xff);
+	}
+
+	public void encrypt(ByteBuffer buf)
+	{
+		if (!_isEnabled)
+			return;
+
+		int temp = 0;
+		final int sz = buf.remaining();
+		for (int i = 0; i < sz; i++)
+		{
+			int temp2 = buf.get(i);
+			temp = temp2 ^ _key[i&15] ^ temp;
+			buf.put(i, (byte) temp);
+		}
+
+		int old = _key[8] &0xff;
+		old |= _key[9] << 8 &0xff00;
+		old |= _key[10] << 0x10 &0xff0000;
+		old |= _key[11] << 0x18 &0xff000000;
+
+		old += sz;
+
+		_key[8] = (byte)(old &0xff);
+		_key[9] = (byte)(old >> 0x08 &0xff);
+		_key[10] = (byte)(old >> 0x10 &0xff);
+		_key[11] = (byte)(old >> 0x18 &0xff);
+	}
+}

+ 51 - 0
L2_GameServer_T1/java/net/sf/l2j/gameserver/CustomPacketHandlerInterface.java

@@ -0,0 +1,51 @@
+/*
+ * $HeadURL: $
+ *
+ * $Author: $
+ * $Date: $
+ * $Revision: $
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+package net.sf.l2j.gameserver;
+
+import java.nio.ByteBuffer;
+
+import net.sf.l2j.gameserver.clientpackets.L2GameClientPacket;
+import net.sf.l2j.gameserver.network.L2GameClient;
+
+/**
+ * This interface can be implemented by custom extensions to l2j to get packets
+ * before the normal processing of PacketHandler
+ *
+ * @version $Revision: $ $Date: $
+ * @author  galun
+ */
+public interface CustomPacketHandlerInterface
+{
+
+    /**
+     * interface for a custom packethandler to ckeck received packets
+     * PacketHandler will take care of the packet if this function returns null.
+     * @param data the packet
+     * @param client the ClientThread
+     * @return a ClientBasePacket if the packet has been processed, null otherwise
+     */
+    public L2GameClientPacket handlePacket(ByteBuffer data, L2GameClient client);
+}

+ 722 - 0
L2_GameServer_T1/java/net/sf/l2j/gameserver/GameServer.java

@@ -0,0 +1,722 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+package net.sf.l2j.gameserver;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Calendar;
+import java.util.logging.Level;
+import java.util.logging.LogManager;
+import java.util.logging.Logger;
+
+import net.sf.l2j.Config;
+import net.sf.l2j.L2DatabaseFactory;
+import net.sf.l2j.Server;
+import net.sf.l2j.gameserver.cache.CrestCache;
+import net.sf.l2j.gameserver.cache.HtmCache;
+import net.sf.l2j.gameserver.communitybbs.Manager.ForumsBBSManager;
+import net.sf.l2j.gameserver.datatables.ArmorSetsTable;
+import net.sf.l2j.gameserver.datatables.AugmentationData;
+import net.sf.l2j.gameserver.datatables.CharNameTable;
+import net.sf.l2j.gameserver.datatables.CharTemplateTable;
+import net.sf.l2j.gameserver.datatables.ClanTable;
+import net.sf.l2j.gameserver.datatables.DoorTable;
+import net.sf.l2j.gameserver.datatables.EventDroplist;
+import net.sf.l2j.gameserver.datatables.ExtractableItemsData;
+import net.sf.l2j.gameserver.datatables.FishTable;
+import net.sf.l2j.gameserver.datatables.HelperBuffTable;
+import net.sf.l2j.gameserver.datatables.HennaTable;
+import net.sf.l2j.gameserver.datatables.HennaTreeTable;
+import net.sf.l2j.gameserver.datatables.HeroSkillTable;
+import net.sf.l2j.gameserver.datatables.ItemTable;
+import net.sf.l2j.gameserver.datatables.LevelUpData;
+import net.sf.l2j.gameserver.datatables.MapRegionTable;
+import net.sf.l2j.gameserver.datatables.MerchantPriceConfigTable;
+import net.sf.l2j.gameserver.datatables.NobleSkillTable;
+import net.sf.l2j.gameserver.datatables.NpcTable;
+import net.sf.l2j.gameserver.datatables.NpcWalkerRoutesTable;
+import net.sf.l2j.gameserver.datatables.SkillSpellbookTable;
+import net.sf.l2j.gameserver.datatables.SkillTable;
+import net.sf.l2j.gameserver.datatables.SkillTreeTable;
+import net.sf.l2j.gameserver.datatables.SpawnTable;
+import net.sf.l2j.gameserver.datatables.StaticObjects;
+import net.sf.l2j.gameserver.datatables.SummonItemsData;
+import net.sf.l2j.gameserver.datatables.TeleportLocationTable;
+import net.sf.l2j.gameserver.datatables.ZoneData;
+import net.sf.l2j.gameserver.geoeditorcon.GeoEditorListener;
+import net.sf.l2j.gameserver.handler.AdminCommandHandler;
+import net.sf.l2j.gameserver.handler.ItemHandler;
+import net.sf.l2j.gameserver.handler.SkillHandler;
+import net.sf.l2j.gameserver.handler.UserCommandHandler;
+import net.sf.l2j.gameserver.handler.VoicedCommandHandler;
+import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminAdmin;
+import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminAnnouncements;
+import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminBBS;
+import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminBan;
+import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminBanChat;
+import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminCache;
+import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminChangeAccessLevel;
+import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminCreateItem;
+import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminCursedWeapons;
+import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminDelete;
+import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminDoorControl;
+import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminEditChar;
+import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminEditNpc;
+import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminEffects;
+import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminEnchant;
+import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminEventEngine;
+import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminExpSp;
+import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminFightCalculator;
+import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminGeoEditor;
+import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminGeodata;
+import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminGm;
+import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminGmChat;
+import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminHeal;
+import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminHelpPage;
+import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminInvul;
+import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminKick;
+import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminKill;
+import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminLevel;
+import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminLogin;
+import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminMammon;
+import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminManor;
+import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminMenu;
+import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminMobGroup;
+import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminMonsterRace;
+import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminPForge;
+import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminPathNode;
+import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminPetition;
+import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminPledge;
+import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminPolymorph;
+import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminQuest;
+import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminRepairChar;
+import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminRes;
+import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminRideWyvern;
+import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminShop;
+import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminShutdown;
+import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminSiege;
+import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminSkill;
+import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminSpawn;
+import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminTarget;
+import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminTeleport;
+import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminTest;
+import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminTvTEvent;
+import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminUnblockIp;
+import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminZone;
+import net.sf.l2j.gameserver.handler.itemhandlers.BeastSoulShot;
+import net.sf.l2j.gameserver.handler.itemhandlers.BeastSpice;
+import net.sf.l2j.gameserver.handler.itemhandlers.BeastSpiritShot;
+import net.sf.l2j.gameserver.handler.itemhandlers.BlessedSpiritShot;
+import net.sf.l2j.gameserver.handler.itemhandlers.Book;
+import net.sf.l2j.gameserver.handler.itemhandlers.CharChangePotions;
+import net.sf.l2j.gameserver.handler.itemhandlers.ChestKey;
+import net.sf.l2j.gameserver.handler.itemhandlers.CrystalCarol;
+import net.sf.l2j.gameserver.handler.itemhandlers.EnchantScrolls;
+import net.sf.l2j.gameserver.handler.itemhandlers.EnergyStone;
+import net.sf.l2j.gameserver.handler.itemhandlers.ExtractableItems;
+import net.sf.l2j.gameserver.handler.itemhandlers.Firework;
+import net.sf.l2j.gameserver.handler.itemhandlers.FishShots;
+import net.sf.l2j.gameserver.handler.itemhandlers.Harvester;
+import net.sf.l2j.gameserver.handler.itemhandlers.Maps;
+import net.sf.l2j.gameserver.handler.itemhandlers.MercTicket;
+import net.sf.l2j.gameserver.handler.itemhandlers.MysteryPotion;
+import net.sf.l2j.gameserver.handler.itemhandlers.PaganKeys;
+import net.sf.l2j.gameserver.handler.itemhandlers.Potions;
+import net.sf.l2j.gameserver.handler.itemhandlers.Recipes;
+import net.sf.l2j.gameserver.handler.itemhandlers.Remedy;
+import net.sf.l2j.gameserver.handler.itemhandlers.RollingDice;
+import net.sf.l2j.gameserver.handler.itemhandlers.ScrollOfEscape;
+import net.sf.l2j.gameserver.handler.itemhandlers.ScrollOfResurrection;
+import net.sf.l2j.gameserver.handler.itemhandlers.Scrolls;
+import net.sf.l2j.gameserver.handler.itemhandlers.Seed;
+import net.sf.l2j.gameserver.handler.itemhandlers.SevenSignsRecord;
+import net.sf.l2j.gameserver.handler.itemhandlers.SoulCrystals;
+import net.sf.l2j.gameserver.handler.itemhandlers.SoulShots;
+import net.sf.l2j.gameserver.handler.itemhandlers.SpecialXMas;
+import net.sf.l2j.gameserver.handler.itemhandlers.SpiritShot;
+import net.sf.l2j.gameserver.handler.itemhandlers.SummonItems;
+import net.sf.l2j.gameserver.handler.skillhandlers.BalanceLife;
+import net.sf.l2j.gameserver.handler.skillhandlers.BeastFeed;
+import net.sf.l2j.gameserver.handler.skillhandlers.Blow;
+import net.sf.l2j.gameserver.handler.skillhandlers.Charge;
+import net.sf.l2j.gameserver.handler.skillhandlers.CombatPointHeal;
+import net.sf.l2j.gameserver.handler.skillhandlers.Continuous;
+import net.sf.l2j.gameserver.handler.skillhandlers.CpDam;
+import net.sf.l2j.gameserver.handler.skillhandlers.Craft;
+import net.sf.l2j.gameserver.handler.skillhandlers.DeluxeKey;
+import net.sf.l2j.gameserver.handler.skillhandlers.Disablers;
+import net.sf.l2j.gameserver.handler.skillhandlers.DrainSoul;
+import net.sf.l2j.gameserver.handler.skillhandlers.Fishing;
+import net.sf.l2j.gameserver.handler.skillhandlers.FishingSkill;
+import net.sf.l2j.gameserver.handler.skillhandlers.GetPlayer;
+import net.sf.l2j.gameserver.handler.skillhandlers.Harvest;
+import net.sf.l2j.gameserver.handler.skillhandlers.Heal;
+import net.sf.l2j.gameserver.handler.skillhandlers.ManaHeal;
+import net.sf.l2j.gameserver.handler.skillhandlers.Manadam;
+import net.sf.l2j.gameserver.handler.skillhandlers.Mdam;
+import net.sf.l2j.gameserver.handler.skillhandlers.Pdam;
+import net.sf.l2j.gameserver.handler.skillhandlers.Recall;
+import net.sf.l2j.gameserver.handler.skillhandlers.Resurrect;
+import net.sf.l2j.gameserver.handler.skillhandlers.SiegeFlag;
+import net.sf.l2j.gameserver.handler.skillhandlers.Signets;
+import net.sf.l2j.gameserver.handler.skillhandlers.Sow;
+import net.sf.l2j.gameserver.handler.skillhandlers.Spoil;
+import net.sf.l2j.gameserver.handler.skillhandlers.StrSiegeAssault;
+import net.sf.l2j.gameserver.handler.skillhandlers.SummonFriend;
+import net.sf.l2j.gameserver.handler.skillhandlers.SummonTreasureKey;
+import net.sf.l2j.gameserver.handler.skillhandlers.Sweep;
+import net.sf.l2j.gameserver.handler.skillhandlers.TakeCastle;
+import net.sf.l2j.gameserver.handler.skillhandlers.Unlock;
+import net.sf.l2j.gameserver.handler.usercommandhandlers.ChannelDelete;
+import net.sf.l2j.gameserver.handler.usercommandhandlers.ChannelLeave;
+import net.sf.l2j.gameserver.handler.usercommandhandlers.ChannelListUpdate;
+import net.sf.l2j.gameserver.handler.usercommandhandlers.ClanPenalty;
+import net.sf.l2j.gameserver.handler.usercommandhandlers.ClanWarsList;
+import net.sf.l2j.gameserver.handler.usercommandhandlers.DisMount;
+import net.sf.l2j.gameserver.handler.usercommandhandlers.Escape;
+import net.sf.l2j.gameserver.handler.usercommandhandlers.Loc;
+import net.sf.l2j.gameserver.handler.usercommandhandlers.Mount;
+import net.sf.l2j.gameserver.handler.usercommandhandlers.OlympiadStat;
+import net.sf.l2j.gameserver.handler.usercommandhandlers.PartyInfo;
+import net.sf.l2j.gameserver.handler.usercommandhandlers.Time;
+import net.sf.l2j.gameserver.handler.voicedcommandhandlers.Wedding;
+import net.sf.l2j.gameserver.handler.voicedcommandhandlers.stats;
+import net.sf.l2j.gameserver.idfactory.IdFactory;
+import net.sf.l2j.gameserver.instancemanager.AuctionManager;
+import net.sf.l2j.gameserver.instancemanager.BoatManager;
+import net.sf.l2j.gameserver.instancemanager.CastleManager;
+import net.sf.l2j.gameserver.instancemanager.CastleManorManager;
+import net.sf.l2j.gameserver.instancemanager.ClanHallManager;
+import net.sf.l2j.gameserver.instancemanager.CoupleManager;
+import net.sf.l2j.gameserver.instancemanager.CursedWeaponsManager;
+import net.sf.l2j.gameserver.instancemanager.DayNightSpawnManager;
+import net.sf.l2j.gameserver.instancemanager.DimensionalRiftManager;
+import net.sf.l2j.gameserver.instancemanager.ItemsOnGroundManager;
+import net.sf.l2j.gameserver.instancemanager.MercTicketManager;
+import net.sf.l2j.gameserver.instancemanager.PetitionManager;
+import net.sf.l2j.gameserver.instancemanager.QuestManager;
+import net.sf.l2j.gameserver.instancemanager.RaidBossSpawnManager;
+import net.sf.l2j.gameserver.instancemanager.SiegeManager;
+import net.sf.l2j.gameserver.instancemanager.TransformationManager;
+import net.sf.l2j.gameserver.model.AutoChatHandler;
+import net.sf.l2j.gameserver.model.AutoSpawnHandler;
+import net.sf.l2j.gameserver.model.L2Manor;
+import net.sf.l2j.gameserver.model.L2PetDataTable;
+import net.sf.l2j.gameserver.model.L2World;
+import net.sf.l2j.gameserver.model.entity.Hero;
+import net.sf.l2j.gameserver.model.entity.TvTManager;
+import net.sf.l2j.gameserver.network.L2GameClient;
+import net.sf.l2j.gameserver.network.L2GamePacketHandler;
+import net.sf.l2j.gameserver.pathfinding.geonodes.GeoPathFinding;
+import net.sf.l2j.gameserver.script.faenor.FaenorScriptEngine;
+import net.sf.l2j.gameserver.scripting.L2ScriptEngineManager;
+import net.sf.l2j.gameserver.taskmanager.TaskManager;
+import net.sf.l2j.gameserver.util.DynamicExtension;
+import net.sf.l2j.gameserver.util.FloodProtector;
+import net.sf.l2j.status.Status;
+
+import org.mmocore.network.SelectorConfig;
+import org.mmocore.network.SelectorThread;
+
+/**
+ * This class ...
+ *
+ * @version $Revision: 1.29.2.15.2.19 $ $Date: 2005/04/05 19:41:23 $
+ */
+public class GameServer
+{
+	private static final Logger _log = Logger.getLogger(GameServer.class.getName());
+	private final SelectorThread<L2GameClient> _selectorThread;
+	private final SkillTable _skillTable;
+	private final ItemTable _itemTable;
+	private final NpcTable _npcTable;
+	private final HennaTable _hennaTable;
+	private final IdFactory _idFactory;
+	public static GameServer gameServer;
+	private static ClanHallManager _cHManager;
+	private final ItemHandler _itemHandler;
+	private final SkillHandler _skillHandler;
+	private final AdminCommandHandler _adminCommandHandler;
+	private final Shutdown _shutdownHandler;
+	private final UserCommandHandler _userCommandHandler;
+    private final VoicedCommandHandler _voicedCommandHandler;
+    private final DoorTable _doorTable;
+    private final SevenSigns _sevenSignsEngine;
+    private final AutoChatHandler _autoChatHandler;
+	private final AutoSpawnHandler _autoSpawnHandler;
+	private LoginServerThread _loginThread;
+    private final HelperBuffTable _helperBuffTable;
+
+	private static Status _statusServer;
+	@SuppressWarnings("unused")
+	private final ThreadPoolManager _threadpools;
+
+    public static final Calendar dateTimeServerStarted = Calendar.getInstance();
+
+    public long getUsedMemoryMB()
+	{
+		return (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory())/1048576; // 1024 * 1024 = 1048576;
+	}
+
+    public SelectorThread<L2GameClient> getSelectorThread()
+    {
+    	return _selectorThread;
+    }
+
+	public ClanHallManager getCHManager(){
+		return _cHManager;
+	}
+	public GameServer() throws Exception
+	{
+        gameServer = this;
+		_log.finest("used mem:" + getUsedMemoryMB()+"MB" );
+
+        if (Config.SERVER_VERSION != null)
+        {
+            _log.info("L2J Server Version:    "+Config.SERVER_VERSION);
+        }
+        if (Config.DATAPACK_VERSION != null)
+        {
+            _log.info("L2J Datapack Version:  "+Config.DATAPACK_VERSION);
+        }
+		_idFactory = IdFactory.getInstance();
+        if (!_idFactory.isInitialized())
+        {
+            _log.severe("Could not read object IDs from DB. Please Check Your Data.");
+            throw new Exception("Could not initialize the ID factory");
+        }
+
+        _threadpools = ThreadPoolManager.getInstance();
+
+		new File(Config.DATAPACK_ROOT, "data/clans").mkdirs();
+		new File(Config.DATAPACK_ROOT, "data/crests").mkdirs();
+        new File("pathnode").mkdirs();
+
+        // load script engines
+        L2ScriptEngineManager.getInstance();
+        
+		// start game time control early
+		GameTimeController.getInstance();
+
+		// keep the references of Singletons to prevent garbage collection
+		CharNameTable.getInstance();
+
+		_itemTable = ItemTable.getInstance();
+		if (!_itemTable.isInitialized())
+		{
+		    _log.severe("Could not find the extraced files. Please Check Your Data.");
+		    throw new Exception("Could not initialize the item table");
+		}
+
+		ExtractableItemsData.getInstance();
+		SummonItemsData.getInstance();
+
+		MerchantPriceConfigTable.getInstance();
+		TradeController.getInstance();
+		_skillTable = SkillTable.getInstance();
+		if (!_skillTable.isInitialized())
+		{
+		    _log.severe("Could not find the extraced files. Please Check Your Data.");
+		    throw new Exception("Could not initialize the skill table");
+		}
+		
+//		L2EMU_ADD by Rayan. L2J - BigBro
+		//if(Config.ALLOW_NPC_WALKERS)
+		NpcWalkerRoutesTable.getInstance().load();
+		//L2EMU_ADD by Rayan. L2J - BigBro
+		
+		RecipeController.getInstance();
+
+		SkillTreeTable.getInstance();
+		ArmorSetsTable.getInstance();
+		FishTable.getInstance();
+		SkillSpellbookTable.getInstance();
+		CharTemplateTable.getInstance();
+		NobleSkillTable.getInstance();
+		HeroSkillTable.getInstance();
+
+        //Call to load caches
+        HtmCache.getInstance();
+        CrestCache.getInstance();
+        ClanTable.getInstance();
+		_npcTable = NpcTable.getInstance();
+
+		if (!_npcTable.isInitialized())
+		{
+		    _log.severe("Could not find the extraced files. Please Check Your Data.");
+		    throw new Exception("Could not initialize the npc table");
+		}
+
+		_hennaTable = HennaTable.getInstance();
+
+		if (!_hennaTable.isInitialized())
+		{
+		   throw new Exception("Could not initialize the Henna Table");
+		}
+
+		HennaTreeTable.getInstance();
+
+		if (!_hennaTable.isInitialized())
+		{
+		   throw new Exception("Could not initialize the Henna Tree Table");
+		}
+
+        _helperBuffTable = HelperBuffTable.getInstance();
+
+        if (!_helperBuffTable.isInitialized())
+        {
+           throw new Exception("Could not initialize the Helper Buff Table");
+        }
+
+        GeoData.getInstance();
+        if (Config.GEODATA == 2)
+        	GeoPathFinding.getInstance();
+
+        // Load clan hall data before zone data
+        _cHManager = ClanHallManager.getInstance();
+		CastleManager.getInstance();
+		SiegeManager.getInstance();
+
+		TeleportLocationTable.getInstance();
+		LevelUpData.getInstance();
+		L2World.getInstance();
+		ZoneData.getInstance();
+        SpawnTable.getInstance();
+        RaidBossSpawnManager.getInstance();
+        DayNightSpawnManager.getInstance().notifyChangeMode();
+        DimensionalRiftManager.getInstance();
+		Announcements.getInstance();
+		MapRegionTable.getInstance();
+		EventDroplist.getInstance();
+
+		/** Load Manor data */
+		L2Manor.getInstance();
+
+		/** Load Manager */
+		AuctionManager.getInstance();
+		BoatManager.getInstance();
+		CastleManorManager.getInstance();
+		MercTicketManager.getInstance();
+		//PartyCommandManager.getInstance();
+		PetitionManager.getInstance();
+		QuestManager.getInstance();
+        TransformationManager.getInstance();
+        
+        try
+        {
+            _log.info("Loading Server Scripts");
+            File scripts = new File("data/scripts.cfg");
+            L2ScriptEngineManager.getInstance().executeScriptList(scripts);
+        }
+        catch (IOException ioe)
+        {
+            _log.severe("Failed loading scripts.cfg, no script going to be loaded");
+        }
+        
+        QuestManager.getInstance().report();
+        TransformationManager.getInstance().report();
+        
+		AugmentationData.getInstance();
+		if (Config.SAVE_DROPPED_ITEM)
+			ItemsOnGroundManager.getInstance();
+
+		if (Config.AUTODESTROY_ITEM_AFTER > 0 || Config.HERB_AUTO_DESTROY_TIME > 0)
+    	    ItemsAutoDestroy.getInstance();
+
+        MonsterRace.getInstance();
+
+		_doorTable = DoorTable.getInstance();
+		_doorTable.parseData();
+        StaticObjects.getInstance();
+
+		_sevenSignsEngine = SevenSigns.getInstance();
+        SevenSignsFestival.getInstance();
+		_autoSpawnHandler = AutoSpawnHandler.getInstance();
+		_autoChatHandler = AutoChatHandler.getInstance();
+
+        // Spawn the Orators/Preachers if in the Seal Validation period.
+        _sevenSignsEngine.spawnSevenSignsNPC();
+
+        Olympiad.getInstance();
+        Hero.getInstance();
+        FaenorScriptEngine.getInstance();
+        // Init of a cursed weapon manager
+        CursedWeaponsManager.getInstance();
+
+		_log.config("AutoChatHandler: Loaded " + _autoChatHandler.size() + " handlers in total.");
+		_log.config("AutoSpawnHandler: Loaded " + _autoSpawnHandler.size() + " handlers in total.");
+
+		_itemHandler = ItemHandler.getInstance();
+		_itemHandler.registerItemHandler(new ScrollOfEscape());
+		_itemHandler.registerItemHandler(new ScrollOfResurrection());
+		_itemHandler.registerItemHandler(new SoulShots());
+		_itemHandler.registerItemHandler(new SpiritShot());
+		_itemHandler.registerItemHandler(new BlessedSpiritShot());
+        _itemHandler.registerItemHandler(new BeastSoulShot());
+        _itemHandler.registerItemHandler(new BeastSpiritShot());
+        _itemHandler.registerItemHandler(new ChestKey());
+        _itemHandler.registerItemHandler(new PaganKeys());
+		_itemHandler.registerItemHandler(new Maps());
+		_itemHandler.registerItemHandler(new Potions());
+		_itemHandler.registerItemHandler(new Recipes());
+        _itemHandler.registerItemHandler(new RollingDice());
+        _itemHandler.registerItemHandler(new MysteryPotion());
+		_itemHandler.registerItemHandler(new EnchantScrolls());
+        _itemHandler.registerItemHandler(new EnergyStone());
+		_itemHandler.registerItemHandler(new Book());
+		_itemHandler.registerItemHandler(new Remedy());
+		_itemHandler.registerItemHandler(new Scrolls());
+		_itemHandler.registerItemHandler(new CrystalCarol());
+		_itemHandler.registerItemHandler(new SoulCrystals());
+		_itemHandler.registerItemHandler(new SevenSignsRecord());
+        _itemHandler.registerItemHandler(new CharChangePotions());
+        _itemHandler.registerItemHandler(new Firework());
+        _itemHandler.registerItemHandler(new Seed());
+        _itemHandler.registerItemHandler(new Harvester());
+        _itemHandler.registerItemHandler(new MercTicket());
+		_itemHandler.registerItemHandler(new FishShots());
+		_itemHandler.registerItemHandler(new ExtractableItems());
+		_itemHandler.registerItemHandler(new SpecialXMas());
+		_itemHandler.registerItemHandler(new SummonItems());
+		_itemHandler.registerItemHandler(new BeastSpice());
+        _log.config("ItemHandler: Loaded " + _itemHandler.size() + " handlers.");
+
+		_skillHandler = SkillHandler.getInstance();
+		_skillHandler.registerSkillHandler(new Blow());
+		_skillHandler.registerSkillHandler(new Pdam());
+		_skillHandler.registerSkillHandler(new Mdam());
+		_skillHandler.registerSkillHandler(new CpDam());
+		_skillHandler.registerSkillHandler(new Manadam());
+		_skillHandler.registerSkillHandler(new Heal());
+        _skillHandler.registerSkillHandler(new CombatPointHeal());
+		_skillHandler.registerSkillHandler(new ManaHeal());
+		_skillHandler.registerSkillHandler(new BalanceLife());
+		_skillHandler.registerSkillHandler(new Charge());
+		_skillHandler.registerSkillHandler(new Continuous());
+		_skillHandler.registerSkillHandler(new Resurrect());
+        _skillHandler.registerSkillHandler(new Spoil());
+        _skillHandler.registerSkillHandler(new Sweep());
+        _skillHandler.registerSkillHandler(new StrSiegeAssault());
+        _skillHandler.registerSkillHandler(new SummonFriend());
+        _skillHandler.registerSkillHandler(new SummonTreasureKey());
+        _skillHandler.registerSkillHandler(new Disablers());
+		_skillHandler.registerSkillHandler(new Recall());
+        _skillHandler.registerSkillHandler(new SiegeFlag());
+        _skillHandler.registerSkillHandler(new TakeCastle());
+        _skillHandler.registerSkillHandler(new Unlock());
+        _skillHandler.registerSkillHandler(new DrainSoul());
+        _skillHandler.registerSkillHandler(new Craft());
+		_skillHandler.registerSkillHandler(new Fishing());
+		_skillHandler.registerSkillHandler(new FishingSkill());
+        _skillHandler.registerSkillHandler(new BeastFeed());
+        _skillHandler.registerSkillHandler(new DeluxeKey());
+        _skillHandler.registerSkillHandler(new Sow());
+        _skillHandler.registerSkillHandler(new Harvest());
+        _skillHandler.registerSkillHandler(new Signets());
+        _skillHandler.registerSkillHandler(new GetPlayer());
+        _log.config("SkillHandler: Loaded " + _skillHandler.size() + " handlers.");
+
+		_adminCommandHandler = AdminCommandHandler.getInstance();
+		_adminCommandHandler.registerAdminCommandHandler(new AdminAdmin());
+		_adminCommandHandler.registerAdminCommandHandler(new AdminInvul());
+		_adminCommandHandler.registerAdminCommandHandler(new AdminDelete());
+		_adminCommandHandler.registerAdminCommandHandler(new AdminKill());
+		_adminCommandHandler.registerAdminCommandHandler(new AdminTarget());
+		_adminCommandHandler.registerAdminCommandHandler(new AdminShop());
+		_adminCommandHandler.registerAdminCommandHandler(new AdminAnnouncements());
+		_adminCommandHandler.registerAdminCommandHandler(new AdminCreateItem());
+        _adminCommandHandler.registerAdminCommandHandler(new AdminHeal());
+		_adminCommandHandler.registerAdminCommandHandler(new AdminHelpPage());
+		_adminCommandHandler.registerAdminCommandHandler(new AdminShutdown());
+		_adminCommandHandler.registerAdminCommandHandler(new AdminSpawn());
+		_adminCommandHandler.registerAdminCommandHandler(new AdminSkill());
+		_adminCommandHandler.registerAdminCommandHandler(new AdminExpSp());
+        _adminCommandHandler.registerAdminCommandHandler(new AdminEventEngine());
+		_adminCommandHandler.registerAdminCommandHandler(new AdminGmChat());
+		_adminCommandHandler.registerAdminCommandHandler(new AdminEditChar());
+		_adminCommandHandler.registerAdminCommandHandler(new AdminGm());
+		_adminCommandHandler.registerAdminCommandHandler(new AdminTeleport());
+		_adminCommandHandler.registerAdminCommandHandler(new AdminRepairChar());
+        _adminCommandHandler.registerAdminCommandHandler(new AdminChangeAccessLevel());
+        _adminCommandHandler.registerAdminCommandHandler(new AdminBan());
+        _adminCommandHandler.registerAdminCommandHandler(new AdminPolymorph());
+		_adminCommandHandler.registerAdminCommandHandler(new AdminBanChat());
+        _adminCommandHandler.registerAdminCommandHandler(new AdminKick());
+        _adminCommandHandler.registerAdminCommandHandler(new AdminMonsterRace());
+        _adminCommandHandler.registerAdminCommandHandler(new AdminEditNpc());
+        _adminCommandHandler.registerAdminCommandHandler(new AdminFightCalculator());
+        _adminCommandHandler.registerAdminCommandHandler(new AdminMenu());
+        _adminCommandHandler.registerAdminCommandHandler(new AdminSiege());
+        _adminCommandHandler.registerAdminCommandHandler(new AdminPathNode());
+        _adminCommandHandler.registerAdminCommandHandler(new AdminPetition());
+        _adminCommandHandler.registerAdminCommandHandler(new AdminPForge());
+        _adminCommandHandler.registerAdminCommandHandler(new AdminBBS());
+        _adminCommandHandler.registerAdminCommandHandler(new AdminEffects());
+        _adminCommandHandler.registerAdminCommandHandler(new AdminDoorControl());
+        _adminCommandHandler.registerAdminCommandHandler(new AdminTest());
+        _adminCommandHandler.registerAdminCommandHandler(new AdminEnchant());
+        _adminCommandHandler.registerAdminCommandHandler(new AdminMobGroup());
+        _adminCommandHandler.registerAdminCommandHandler(new AdminRes());
+        _adminCommandHandler.registerAdminCommandHandler(new AdminMammon());
+        _adminCommandHandler.registerAdminCommandHandler(new AdminUnblockIp());
+        _adminCommandHandler.registerAdminCommandHandler(new AdminPledge());
+        _adminCommandHandler.registerAdminCommandHandler(new AdminRideWyvern());
+        _adminCommandHandler.registerAdminCommandHandler(new AdminLogin());
+        _adminCommandHandler.registerAdminCommandHandler(new AdminCache());
+        _adminCommandHandler.registerAdminCommandHandler(new AdminLevel());
+        _adminCommandHandler.registerAdminCommandHandler(new AdminQuest());
+        _adminCommandHandler.registerAdminCommandHandler(new AdminZone());
+        _adminCommandHandler.registerAdminCommandHandler(new AdminCursedWeapons());
+        _adminCommandHandler.registerAdminCommandHandler(new AdminGeodata());
+        _adminCommandHandler.registerAdminCommandHandler(new AdminGeoEditor());
+        _adminCommandHandler.registerAdminCommandHandler(new AdminManor());
+        _adminCommandHandler.registerAdminCommandHandler(new AdminTvTEvent());
+        //_adminCommandHandler.registerAdminCommandHandler(new AdminRadar());
+        _log.config("AdminCommandHandler: Loaded " + _adminCommandHandler.size() + " handlers.");
+
+        _userCommandHandler = UserCommandHandler.getInstance();
+        _userCommandHandler.registerUserCommandHandler(new ClanPenalty());
+        _userCommandHandler.registerUserCommandHandler(new ClanWarsList());
+        _userCommandHandler.registerUserCommandHandler(new DisMount());
+        _userCommandHandler.registerUserCommandHandler(new Escape());
+        _userCommandHandler.registerUserCommandHandler(new Loc());
+        _userCommandHandler.registerUserCommandHandler(new Mount());
+        _userCommandHandler.registerUserCommandHandler(new PartyInfo());
+		_userCommandHandler.registerUserCommandHandler(new Time());
+		_userCommandHandler.registerUserCommandHandler(new OlympiadStat());
+		_userCommandHandler.registerUserCommandHandler(new ChannelLeave());
+		_userCommandHandler.registerUserCommandHandler(new ChannelDelete());
+		_userCommandHandler.registerUserCommandHandler(new ChannelListUpdate());
+
+        _log.config("UserCommandHandler: Loaded " + _userCommandHandler.size() + " handlers.");
+
+		_voicedCommandHandler = VoicedCommandHandler.getInstance();
+		_voicedCommandHandler.registerVoicedCommandHandler(new stats());
+
+		if(Config.L2JMOD_ALLOW_WEDDING)
+			_voicedCommandHandler.registerVoicedCommandHandler(new Wedding());
+
+		_log.config("VoicedCommandHandler: Loaded " + _voicedCommandHandler.size() + " handlers.");
+
+		
+						
+		if(Config.L2JMOD_ALLOW_WEDDING)
+			CoupleManager.getInstance();
+
+        TaskManager.getInstance();
+
+		GmListTable.getInstance();
+
+        // read pet stats from db
+        L2PetDataTable.getInstance().loadPetsData();
+
+        Universe.getInstance();
+
+		if (Config.ACCEPT_GEOEDITOR_CONN)
+			GeoEditorListener.getInstance();
+
+		_shutdownHandler = Shutdown.getInstance();
+		Runtime.getRuntime().addShutdownHook(_shutdownHandler);
+
+		try
+        {
+            _doorTable.getDoor(24190001).openMe();
+            _doorTable.getDoor(24190002).openMe();
+            _doorTable.getDoor(24190003).openMe();
+            _doorTable.getDoor(24190004).openMe();
+            _doorTable.getDoor(23180001).openMe();
+            _doorTable.getDoor(23180002).openMe();
+            _doorTable.getDoor(23180003).openMe();
+            _doorTable.getDoor(23180004).openMe();
+            _doorTable.getDoor(23180005).openMe();
+            _doorTable.getDoor(23180006).openMe();
+
+            _doorTable.checkAutoOpen();
+        }
+        catch (NullPointerException e)
+        {
+            _log.warning("There is errors in your Door.csv file. Update door.csv");
+            if (Config.DEBUG)
+            	e.printStackTrace();
+        }
+        ForumsBBSManager.getInstance();
+        _log.config("IdFactory: Free ObjectID's remaining: " + IdFactory.getInstance().size());
+
+        // initialize the dynamic extension loader
+        try {
+            DynamicExtension.getInstance();
+        } catch (Exception ex) {
+            _log.log(Level.WARNING, "DynamicExtension could not be loaded and initialized", ex);
+        }
+
+        FloodProtector.getInstance();
+        TvTManager.getInstance();
+		System.gc();
+		// maxMemory is the upper limit the jvm can use, totalMemory the size of the current allocation pool, freeMemory the unused memory in the allocation pool
+		long freeMem = (Runtime.getRuntime().maxMemory()-Runtime.getRuntime().totalMemory()+Runtime.getRuntime().freeMemory()) / 1048576; // 1024 * 1024 = 1048576;
+		long totalMem = Runtime.getRuntime().maxMemory() / 1048576;
+		_log.info("GameServer Started, free memory "+freeMem+" Mb of "+totalMem+" Mb");
+
+		_loginThread = LoginServerThread.getInstance();
+		_loginThread.start();
+        
+        L2GamePacketHandler gph = new L2GamePacketHandler();
+		SelectorConfig<L2GameClient> sc = new SelectorConfig<L2GameClient>(null, gph);
+        sc.setMaxSendPerPass(12);
+        sc.setSelectorSleepTime(20);
+        
+		_selectorThread = new SelectorThread<L2GameClient>(sc, null, gph, gph, gph, null);
+		_selectorThread.openServerSocket(null, Config.PORT_GAME);
+		_selectorThread.start();
+		_log.config("Maximum Numbers of Connected Players: " + Config.MAXIMUM_ONLINE_USERS);
+	}
+
+	public static void main(String[] args) throws Exception
+    {
+		Server.serverMode = Server.MODE_GAMESERVER;
+//      Local Constants
+		final String LOG_FOLDER = "log"; // Name of folder for log file
+		final String LOG_NAME   = "./log.cfg"; // Name of log file
+
+		/*** Main ***/
+		// Create log folder
+		File logFolder = new File(Config.DATAPACK_ROOT, LOG_FOLDER);
+		logFolder.mkdir();
+
+		// Create input stream for log file -- or store file data into memory
+		InputStream is =  new FileInputStream(new File(LOG_NAME));
+		LogManager.getLogManager().readConfiguration(is);
+		is.close();
+
+		// Initialize config
+		Config.load();
+		L2DatabaseFactory.getInstance();
+		gameServer = new GameServer();
+
+		if ( Config.IS_TELNET_ENABLED ) {
+		    _statusServer = new Status(Server.serverMode);
+		    _statusServer.start();
+		}
+		else {
+		    System.out.println("Telnet server is currently disabled.");
+		}
+    }
+}

+ 263 - 0
L2_GameServer_T1/java/net/sf/l2j/gameserver/GameTimeController.java

@@ -0,0 +1,263 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+package net.sf.l2j.gameserver;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.List;
+import java.util.concurrent.ScheduledFuture;
+import java.util.logging.Logger;
+
+import javolution.util.FastList;
+import net.sf.l2j.gameserver.ai.CtrlEvent;
+import net.sf.l2j.gameserver.instancemanager.DayNightSpawnManager;
+import net.sf.l2j.gameserver.model.L2Character;
+
+/**
+ * This class ...
+ *
+ * @version $Revision: 1.1.4.8 $ $Date: 2005/04/06 16:13:24 $
+ */
+public class GameTimeController
+{
+	static final Logger _log = Logger.getLogger(GameTimeController.class.getName());
+
+	public static final int TICKS_PER_SECOND = 10;
+	public static final int MILLIS_IN_TICK = 1000 / TICKS_PER_SECOND;
+
+	private static GameTimeController _instance = new GameTimeController();
+
+	protected static int _gameTicks;
+	protected static long _gameStartTime;
+	protected static boolean _isNight = false;
+
+	private static List<L2Character> _movingObjects = new FastList<L2Character>();
+
+	protected static TimerThread _timer;
+	private ScheduledFuture<?> _timerWatcher;
+
+	/**
+	 * one ingame day is 240 real minutes
+	 */
+	public static GameTimeController getInstance()
+	{
+		return _instance;
+	}
+
+	private GameTimeController()
+	{
+		_gameStartTime = System.currentTimeMillis() - 3600000; // offset so that the server starts a day begin
+		_gameTicks = 3600000 / MILLIS_IN_TICK; // offset so that the server starts a day begin
+
+		_timer = new TimerThread();
+		_timer.start();
+
+		_timerWatcher = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(new TimerWatcher(), 0, 1000);
+        ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(new BroadcastSunState(), 0, 600000);
+
+	}
+
+	public boolean isNowNight()
+	{
+		return _isNight;
+	}
+
+	public int getGameTime()
+	{
+		return (_gameTicks / (TICKS_PER_SECOND * 10));
+	}
+
+	public static int getGameTicks()
+	{
+		return _gameTicks;
+	}
+
+	/**
+	 * Add a L2Character to movingObjects of GameTimeController.<BR><BR>
+	 *
+	 * <B><U> Concept</U> :</B><BR><BR>
+	 * All L2Character in movement are identified in <B>movingObjects</B> of GameTimeController.<BR><BR>
+	 *
+	 * @param cha The L2Character to add to movingObjects of GameTimeController
+	 *
+	 */
+	public synchronized void registerMovingObject(L2Character cha)
+	{
+		if(cha == null) return;
+		if (!_movingObjects.contains(cha)) _movingObjects.add(cha);
+	}
+
+	/**
+	 * Move all L2Characters contained in movingObjects of GameTimeController.<BR><BR>
+	 *
+	 * <B><U> Concept</U> :</B><BR><BR>
+	 * All L2Character in movement are identified in <B>movingObjects</B> of GameTimeController.<BR><BR>
+	 *
+	 * <B><U> Actions</U> :</B><BR><BR>
+	 * <li>Update the position of each L2Character </li>
+	 * <li>If movement is finished, the L2Character is removed from movingObjects </li>
+	 * <li>Create a task to update the _knownObject and _knowPlayers of each L2Character that finished its movement and of their already known L2Object then notify AI with EVT_ARRIVED </li><BR><BR>
+	 *
+	 */
+	protected synchronized void moveObjects()
+	{
+		// Get all L2Character from the ArrayList movingObjects and put them into a table
+		L2Character[] chars = _movingObjects.toArray(new L2Character[_movingObjects.size()]);
+
+		// Create an ArrayList to contain all L2Character that are arrived to destination
+		List<L2Character> ended = null;
+
+		// Go throw the table containing L2Character in movement
+		for (int i = 0; i < chars.length; i++)
+		{
+
+			L2Character cha = chars[i];
+
+			// Update the position of the L2Character and return True if the movement is finished
+			boolean end = cha.updatePosition(_gameTicks);
+
+			// If movement is finished, the L2Character is removed from movingObjects and added to the ArrayList ended
+			if (end)
+			{
+				_movingObjects.remove(cha);
+				if (ended == null) ended = new FastList<L2Character>();
+
+				ended.add(cha);
+			}
+		}
+
+		// Create a task to update the _knownObject and _knowPlayers of each L2Character that finished its movement and of their already known L2Object
+		// then notify AI with EVT_ARRIVED
+		// TODO: maybe a general TP is needed for that kinda stuff (all knownlist updates should be done in a TP anyway).
+		if (ended != null)
+			ThreadPoolManager.getInstance().executeTask(new MovingObjectArrived(ended));
+
+	}
+
+	public void stopTimer()
+	{
+		_timerWatcher.cancel(true);
+		_timer.interrupt();
+	}
+
+	class TimerThread extends Thread
+	{
+		protected Exception _error;
+
+		public TimerThread()
+		{
+			super("GameTimeController");
+			setDaemon(true);
+			setPriority(MAX_PRIORITY);
+			_error = null;
+		}
+
+		@Override
+		public void run()
+		{
+			try
+			{
+				for (;;)
+				{
+					int _oldTicks=_gameTicks; // save old ticks value to avoid moving objects 2x in same tick
+					long runtime = System.currentTimeMillis() - _gameStartTime; // from server boot to now
+
+					_gameTicks = (int) (runtime / MILLIS_IN_TICK); // new ticks value (ticks now)
+
+					if (_oldTicks != _gameTicks) moveObjects(); // XXX: if this makes objects go slower, remove it
+					// but I think it can't make that effect. is it better to call moveObjects() twice in same
+					// tick to make-up for missed tick ?   or is it better to ignore missed tick ?
+					// (will happen very rarely but it will happen ... on garbage collection definitely)
+
+					runtime = (System.currentTimeMillis() - _gameStartTime) - runtime;
+
+					// calculate sleep time... time needed to next tick minus time it takes to call moveObjects()
+					int sleepTime = 1 + MILLIS_IN_TICK - ((int) runtime) % MILLIS_IN_TICK;
+
+					//_log.finest("TICK: "+_gameTicks);
+
+					sleep(sleepTime); // hope other threads will have much more cpu time available now
+					// SelectorThread most of all
+				}
+			}
+			catch (Exception e)
+			{
+				_error = e;
+			}
+		}
+	}
+
+	class TimerWatcher implements Runnable
+	{
+		public void run()
+		{
+			if (!_timer.isAlive())
+			{
+				String time = (new SimpleDateFormat("HH:mm:ss")).format(new Date());
+				_log.warning(time + " TimerThread stop with following error. restart it.");
+				if (_timer._error != null) _timer._error.printStackTrace();
+
+				_timer = new TimerThread();
+				_timer.start();
+			}
+		}
+	}
+
+	/**
+	 * Update the _knownObject and _knowPlayers of each L2Character that finished its movement and of their already known L2Object then notify AI with EVT_ARRIVED.<BR><BR>
+	 */
+	class MovingObjectArrived implements Runnable
+	{
+		private final List<L2Character> _ended;
+
+		MovingObjectArrived(List<L2Character> ended)
+		{
+			_ended = ended;
+		}
+
+		public void run()
+		{
+			for (L2Character cha : _ended)
+			{
+				try {
+					cha.getKnownList().updateKnownObjects();
+					cha.getAI().notifyEvent(CtrlEvent.EVT_ARRIVED);
+				} catch (NullPointerException e) {}
+			}
+		}
+	}
+
+	/**
+	 * @param rise
+	 */
+	class BroadcastSunState implements Runnable
+	{
+		public void run()
+		{
+			int h = (getGameTime() / 60) % 24; // Time in hour
+			boolean tempIsNight = (h < 6);
+
+			if (tempIsNight != _isNight) { // If diff day/night state
+                _isNight = tempIsNight; // Set current day/night varible to value of temp varible
+
+                DayNightSpawnManager.getInstance().notifyChangeMode();
+            }
+		}
+	}
+}

+ 153 - 0
L2_GameServer_T1/java/net/sf/l2j/gameserver/GeoData.java

@@ -0,0 +1,153 @@
+/* This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+package net.sf.l2j.gameserver;
+
+import java.util.logging.Logger;
+
+import net.sf.l2j.Config;
+import net.sf.l2j.gameserver.model.L2Object;
+import net.sf.l2j.gameserver.model.Location;
+import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
+
+/**
+ *
+ * @author  -Nemesiss-
+ */
+public class GeoData
+{
+	private static Logger _log = Logger.getLogger(GeoData.class.getName());
+	private static GeoData _instance;
+
+	public static GeoData getInstance()
+    {
+        if(_instance == null)
+        {
+        	if (Config.GEODATA > 0)
+        		_instance = GeoEngine.getInstance();
+        	else
+        	{
+        		_instance = new GeoData();
+        		_log.info("Geodata Engine: Disabled.");
+        	}
+        }
+        return _instance;
+    }
+
+    // Public Methods
+    /**
+     * @param x
+     * @param y
+     * @return Geo Block Type
+     */
+    public short getType  (int x, int y)
+    {
+        return 0;
+    }
+    /**
+     * @param x
+     * @param y
+     * @param z
+     * @return Nearles Z
+     */
+    public short getHeight(int x, int y, int z)
+    {
+        return (short)z;
+    }
+    /**
+     * @param x
+     * @param y
+     * @param zmin
+     * @param zmax
+     * @param spawnid
+     * @return
+     */
+    public short getSpawnHeight(int x, int y, int zmin, int zmax, int spawnid)
+    {
+        return (short)zmin;
+    }
+    /**
+     * @param x
+     * @param y
+     * @return
+     */
+    public String geoPosition(int x, int y)
+    {
+    	return "";
+    }
+
+    /**
+     * @param cha
+     * @param target
+     * @return True if cha can see target (LOS)
+     */
+    public boolean canSeeTarget(L2Object cha, L2Object target)
+    {
+    	//If geo is off do simple check :]
+    	//Don't allow casting on players on different dungeon lvls etc
+        return (Math.abs(target.getZ() - cha.getZ()) < 1000);
+    }
+    /**
+     * @param cha
+     * @param target
+     * @return True if cha can see target (LOS) and send usful info to PC
+     */
+    public boolean canSeeTargetDebug(L2PcInstance gm, L2Object target)
+    {
+        return true;
+    }
+    /**
+     * @param x
+     * @param y
+     * @param z
+     * @return Geo NSWE (0-15)
+     */
+    public short getNSWE(int x, int y, int z)
+    {
+        return 15;
+    }
+    /**
+     * @param x
+     * @param y
+     * @param z
+     * @param tx
+     * @param ty
+     * @param tz
+     * @return Last Location (x,y,z) where player can walk - just befor wall
+     */
+    public Location moveCheck(int x, int y, int z, int tx, int ty, int tz)
+    {
+        return new Location(tx,ty,tz);
+    }
+    /**
+     * @param gm
+     * @param comment
+     */
+    public void addGeoDataBug(L2PcInstance gm, String comment)
+    {
+    	//Do Nothing
+    }
+    public static void unloadGeodata(byte rx, byte ry)
+	{
+
+	}
+    @Deprecated //TODO: cleanup?
+    public static boolean loadGeodataFile(byte rx, byte ry)
+    {
+    	return false;
+    }
+}

+ 1221 - 0
L2_GameServer_T1/java/net/sf/l2j/gameserver/GeoEngine.java

@@ -0,0 +1,1221 @@
+/* This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+package net.sf.l2j.gameserver;
+
+import java.io.BufferedOutputStream;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.LineNumberReader;
+import java.io.RandomAccessFile;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.IntBuffer;
+import java.nio.MappedByteBuffer;
+import java.nio.channels.FileChannel;
+import java.util.Map;
+import java.util.StringTokenizer;
+import java.util.logging.Logger;
+
+import javolution.util.FastMap;
+import net.sf.l2j.Config;
+import net.sf.l2j.gameserver.datatables.DoorTable;
+import net.sf.l2j.gameserver.model.L2Object;
+import net.sf.l2j.gameserver.model.L2World;
+import net.sf.l2j.gameserver.model.Location;
+import net.sf.l2j.gameserver.model.actor.instance.L2DoorInstance;
+import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
+import net.sf.l2j.gameserver.model.actor.instance.L2SiegeGuardInstance;
+
+/**
+ *
+ * @author -Nemesiss-
+ */
+public class GeoEngine extends GeoData
+{
+	private static Logger _log = Logger.getLogger(GeoData.class.getName());
+	private static GeoEngine _instance;
+    private final static byte _e = 1;
+    private final static byte _w = 2;
+    private final static byte _s = 4;
+    private final static byte _n = 8;
+	private static Map<Short, MappedByteBuffer> _geodata = new FastMap<Short, MappedByteBuffer>();
+	private static Map<Short, IntBuffer> _geodataIndex = new FastMap<Short, IntBuffer>();
+	private static BufferedOutputStream _geoBugsOut;
+
+	public static GeoEngine getInstance()
+    {
+        if(_instance == null)
+            _instance = new GeoEngine();
+        return _instance;
+    }
+    public GeoEngine()
+    {
+        nInitGeodata();
+    }
+
+    //Public Methods
+    /**
+     * @see net.sf.l2j.gameserver.GeoData#getType(int, int)
+     */
+    @Override
+    public short getType(int x, int y)
+    {
+        return nGetType((x - L2World.MAP_MIN_X) >> 4, (y - L2World.MAP_MIN_Y) >> 4);
+    }
+    /**
+     * @see net.sf.l2j.gameserver.GeoData#getHeight(int, int, int)
+     */
+    @Override
+    public short getHeight(int x, int y, int z)
+    {
+        return nGetHeight((x - L2World.MAP_MIN_X) >> 4,(y - L2World.MAP_MIN_Y) >> 4,z);
+    }
+    /**
+     * @see net.sf.l2j.gameserver.GeoData#getSpawnHeight(int, int, int, int, int)
+     */
+    @Override
+    public short getSpawnHeight(int x, int y, int zmin, int zmax, int spawnid)
+    {
+    	return nGetSpawnHeight((x - L2World.MAP_MIN_X) >> 4,(y - L2World.MAP_MIN_Y) >> 4,zmin,zmax,spawnid);
+    }
+    /**
+     * @see net.sf.l2j.gameserver.GeoData#geoPosition(int, int)
+     */
+    @Override
+    public String geoPosition(int x, int y)
+    {
+    	int gx = (x - L2World.MAP_MIN_X) >> 4;
+    	int gy = (y - L2World.MAP_MIN_Y) >> 4;
+    	return "bx: "+getBlock(gx)+" by: "+getBlock(gy)+" cx: "+getCell(gx)+" cy: "+getCell(gy)+"  region offset: "+getRegionOffset(gx,gy);
+    }
+    /**
+     * @see net.sf.l2j.gameserver.GeoData#canSeeTarget(net.sf.l2j.gameserver.model.L2Object, net.sf.l2j.gameserver.model.L2Object)
+     */
+    @Override
+    public boolean canSeeTarget(L2Object cha, L2Object target)
+    {
+    	// To be able to see over fences and give the player the viewpoint
+    	// game client has, all coordinates are lifted 45 from ground.
+    	// Because of layer selection in LOS algorithm (it selects -45 there
+    	// and some layers can be very close...) do not change this without
+    	// changing the LOS code.
+    	// Basically the +45 is character height. Raid bosses are naturally higher,
+    	// dwarves shorter, but this should work relatively well.
+    	// If this is going to be improved, use e.g.
+    	// ((L2Character)cha).getTemplate().collisionHeight
+    	int z = cha.getZ()+45;
+    	if(cha instanceof L2SiegeGuardInstance) z += 30; // well they don't move closer to balcony fence at the moment :(
+    	int z2 = target.getZ()+45;
+    	if (!(target instanceof L2DoorInstance)
+    			&& DoorTable.getInstance().checkIfDoorsBetween(cha.getX(),cha.getY(),z,target.getX(),target.getY(),z2))
+    		return false;
+    	if(target instanceof L2DoorInstance) return true; // door coordinates are hinge coords..
+    	if(target instanceof L2SiegeGuardInstance) z2 += 30; // well they don't move closer to balcony fence at the moment :(
+    	if(cha.getZ() >= target.getZ())
+    		return canSeeTarget(cha.getX(),cha.getY(),z,target.getX(),target.getY(),z2);
+    	else
+    		return canSeeTarget(target.getX(),target.getY(),z2, cha.getX(),cha.getY(),z);
+    }
+    /**
+     * @see net.sf.l2j.gameserver.GeoData#canSeeTargetDebug(net.sf.l2j.gameserver.model.actor.instance.L2PcInstance, net.sf.l2j.gameserver.model.L2Object)
+     */
+    @Override
+    public boolean canSeeTargetDebug(L2PcInstance gm, L2Object target)
+    {
+    	// comments: see above
+    	int z = gm.getZ()+45;
+    	int z2 = target.getZ()+45;
+    	if(target instanceof L2DoorInstance)
+    	{
+    		gm.sendMessage("door always true");
+    		return true; // door coordinates are hinge coords..
+    	}
+
+    	if(gm.getZ() >= target.getZ())
+    		return canSeeDebug(gm,(gm.getX() - L2World.MAP_MIN_X) >> 4,(gm.getY() - L2World.MAP_MIN_Y) >> 4,z,(target.getX() - L2World.MAP_MIN_X) >> 4,(target.getY() - L2World.MAP_MIN_Y) >> 4,z2);
+    	else
+    		return canSeeDebug(gm,(target.getX() - L2World.MAP_MIN_X) >> 4,(target.getY() - L2World.MAP_MIN_Y) >> 4,z2,(gm.getX() - L2World.MAP_MIN_X) >> 4,(gm.getY() - L2World.MAP_MIN_Y) >> 4,z);
+    }
+    /**
+     * @see net.sf.l2j.gameserver.GeoData#getNSWE(int, int, int)
+     */
+    @Override
+    public short getNSWE(int x, int y, int z)
+    {
+        return nGetNSWE((x - L2World.MAP_MIN_X) >> 4,(y - L2World.MAP_MIN_Y) >> 4,z);
+    }
+    /**
+     * @see net.sf.l2j.gameserver.GeoData#moveCheck(int, int, int, int, int, int)
+     */
+    @Override
+    public Location moveCheck(int x, int y, int z, int tx, int ty, int tz)
+    {
+    	Location startpoint = new Location(x,y,z);
+    	if (DoorTable.getInstance().checkIfDoorsBetween(x,y,z,tx,ty,tz))
+    		return startpoint;
+
+    	Location destiny = new Location(tx,ty,tz);
+        return moveCheck(startpoint, destiny,(x - L2World.MAP_MIN_X) >> 4,(y - L2World.MAP_MIN_Y) >> 4,z,(tx - L2World.MAP_MIN_X) >> 4,(ty - L2World.MAP_MIN_Y) >> 4,tz);
+    }
+    /**
+     * @see net.sf.l2j.gameserver.GeoData#addGeoDataBug(net.sf.l2j.gameserver.model.actor.instance.L2PcInstance, java.lang.String)
+     */
+    @Override
+    public void addGeoDataBug(L2PcInstance gm, String comment)
+    {
+    	int gx = (gm.getX() - L2World.MAP_MIN_X) >> 4;
+    	int gy = (gm.getY() - L2World.MAP_MIN_Y) >> 4;
+    	int bx = getBlock(gx);
+    	int by = getBlock(gy);
+    	int cx = getCell(gx);
+    	int cy = getCell(gy);
+    	int rx = (gx >> 11) + 16;
+	    int ry = (gy >> 11) + 10;
+    	String out = rx+";"+ry+";"+bx+";"+by+";"+cx+";"+cy+";"+gm.getZ()+";"+comment+"\n";
+    	try
+		{
+    		_geoBugsOut.write(out.getBytes());
+    		_geoBugsOut.flush();
+    		gm.sendMessage("GeoData bug saved!");
+		} catch (Exception e) {
+			e.printStackTrace();
+			gm.sendMessage("GeoData bug save Failed!");
+		}
+    }
+
+    // Private Methods
+    private boolean canSeeTarget(int x, int y, int z, int tx, int ty, int tz)
+    {
+        return canSee((x - L2World.MAP_MIN_X) >> 4,(y - L2World.MAP_MIN_Y) >> 4,z,(tx - L2World.MAP_MIN_X) >> 4,(ty - L2World.MAP_MIN_Y) >> 4,tz);
+    }
+
+    private static boolean canSee(int x, int y, double z, int tx, int ty, int tz)
+    {
+    	int dx = (tx - x);
+        int dy = (ty - y);
+        final double dz = (tz - z);
+        final int distance2 = dx*dx+dy*dy;
+
+        if (distance2 > 90000) // (300*300) 300*16 = 4800 in world coord
+        {
+            //Avoid too long check
+            return false;
+        }
+        // very short checks: 9 => 144 world distance
+        // this ensures NLOS function has enough points to calculate,
+        // it might not work when distance is small and path vertical
+        else if (distance2 < 82)
+        {
+        	// 200 too deep/high. This value should be in sync with NLOS
+        	if(dz*dz > 40000)
+        	{
+        		short region = getRegionOffset(x,y);
+        		// geodata is loaded for region and mobs should have correct Z coordinate...
+        		// so there would likely be a floor in between the two
+        		if (_geodata.get(region) != null)
+        			return false;
+        	}
+        	return true;
+        }
+
+        // Increment in Z coordinate when moving along X or Y axis
+        // and not straight to the target. This is done because
+        // calculation moves either in X or Y direction.
+        final int inc_x = sign(dx);
+        final int inc_y = sign(dy);
+        dx = Math.abs(dx);
+        dy = Math.abs(dy);
+        final double inc_z_directionx = dz*dx / (distance2);
+        final double inc_z_directiony = dz*dy / (distance2);
+
+        // next_* are used in NLOS check from x,y
+        int next_x = x;
+        int next_y = y;
+
+        // creates path to the target
+        // calculation stops when next_* == target
+        if (dx >= dy)// dy/dx <= 1
+        {
+        	int delta_A = 2*dy;
+        	int d = delta_A - dx;
+            int delta_B = delta_A - 2*dx;
+
+            for (int i = 0; i < dx; i++)
+            {
+            	x = next_x;
+            	y = next_y;
+            	if (d > 0)
+            	{
+            		d += delta_B;
+            		next_x += inc_x;
+            		z += inc_z_directionx;
+            		next_y += inc_y;
+            		z += inc_z_directiony;
+            		//_log.warning("1: next_x:"+next_x+" next_y"+next_y);
+            		if (!nLOS(x,y,(int)z,inc_x,inc_y,tz,false))
+            			return false;
+            	}
+            	else
+            	{
+            		d += delta_A;
+            		next_x += inc_x;
+            		//_log.warning("2: next_x:"+next_x+" next_y"+next_y);
+            		z += inc_z_directionx;
+            		if (!nLOS(x,y,(int)z,inc_x,0,tz,false))
+            			return false;
+            	}
+            }
+        }
+        else
+        {
+        	int delta_A = 2*dx;
+        	int d = delta_A - dy;
+            int delta_B = delta_A - 2*dy;
+            for (int i = 0; i < dy; i++)
+            {
+            	x = next_x;
+            	y = next_y;
+            	if (d > 0)
+            	{
+            		d += delta_B;
+            		next_y += inc_y;
+            		z += inc_z_directiony;
+            		next_x += inc_x;
+            		z += inc_z_directionx;
+            		//_log.warning("3: next_x:"+next_x+" next_y"+next_y);
+            		if (!nLOS(x,y,(int)z,inc_x,inc_y,tz,false))
+            			return false;
+            	}
+            	else
+            	{
+            		d += delta_A;
+            		next_y += inc_y;
+            		//_log.warning("4: next_x:"+next_x+" next_y"+next_y);
+            		z += inc_z_directiony;
+            		if (!nLOS(x,y,(int)z,0,inc_y,tz,false))
+            			return false;
+            	}
+            }
+        }
+        return true;
+    }
+    /*
+     * Debug function for checking if there's a line of sight between
+     * two coordinates.
+     *
+     * Creates points for line of sight check (x,y,z towards target) and
+     * in each point, layer and movement checks are made with NLOS function.
+     *
+     * Coordinates here are geodata x,y but z coordinate is world coordinate
+     */
+    private static boolean canSeeDebug(L2PcInstance gm, int x, int y, double z, int tx, int ty, int tz)
+    {
+    	int dx = (tx - x);
+        int dy = (ty - y);
+        final double dz = (tz - z);
+        final int distance2 = dx*dx+dy*dy;
+
+        if (distance2 > 90000) // (300*300) 300*16 = 4800 in world coord
+        {
+            //Avoid too long check
+        	gm.sendMessage("dist > 300");
+            return false;
+        }
+        // very short checks: 9 => 144 world distance
+        // this ensures NLOS function has enough points to calculate,
+        // it might not work when distance is small and path vertical
+        else if (distance2 < 82)
+        {
+        	// 200 too deep/high. This value should be in sync with NLOS
+        	if(dz*dz > 40000)
+        	{
+        		short region = getRegionOffset(x,y);
+        		// geodata is loaded for region and mobs should have correct Z coordinate...
+        		// so there would likely be a floor in between the two
+        		if (_geodata.get(region) != null)
+        			return false;
+        	}
+        	return true;
+        }
+
+        // Increment in Z coordinate when moving along X or Y axis
+        // and not straight to the target. This is done because
+        // calculation moves either in X or Y direction.
+        final int inc_x = sign(dx);
+        final int inc_y = sign(dy);
+        dx = Math.abs(dx);
+        dy = Math.abs(dy);
+        final double inc_z_directionx = dz*dx / (distance2);
+        final double inc_z_directiony = dz*dy / (distance2);
+
+        gm.sendMessage("Los: from X: "+x+ "Y: "+y+ "--->> X: "+tx+" Y: "+ty);
+
+        // next_* are used in NLOS check from x,y
+        int next_x = x;
+        int next_y = y;
+
+        // creates path to the target
+        // calculation stops when next_* == target
+        if (dx >= dy)// dy/dx <= 1
+        {
+        	int delta_A = 2*dy;
+        	int d = delta_A - dx;
+            int delta_B = delta_A - 2*dx;
+
+            for (int i = 0; i < dx; i++)
+            {
+            	x = next_x;
+            	y = next_y;
+            	if (d > 0)
+            	{
+            		d += delta_B;
+            		next_x += inc_x;
+            		z += inc_z_directionx;
+            		next_y += inc_y;
+            		z += inc_z_directiony;
+            		//_log.warning("1: next_x:"+next_x+" next_y"+next_y);
+            		if (!nLOS(x,y,(int)z,inc_x,inc_y,tz,true))
+            			return false;
+            	}
+            	else
+            	{
+            		d += delta_A;
+            		next_x += inc_x;
+            		//_log.warning("2: next_x:"+next_x+" next_y"+next_y);
+            		z += inc_z_directionx;
+            		if (!nLOS(x,y,(int)z,inc_x,0,tz,true))
+            			return false;
+            	}
+            }
+        }
+        else
+        {
+        	int delta_A = 2*dx;
+        	int d = delta_A - dy;
+            int delta_B = delta_A - 2*dy;
+            for (int i = 0; i < dy; i++)
+            {
+            	x = next_x;
+            	y = next_y;
+            	if (d > 0)
+            	{
+            		d += delta_B;
+            		next_y += inc_y;
+            		z += inc_z_directiony;
+            		next_x += inc_x;
+            		z += inc_z_directionx;
+            		//_log.warning("3: next_x:"+next_x+" next_y"+next_y);
+            		if (!nLOS(x,y,(int)z,inc_x,inc_y,tz,true))
+            			return false;
+            	}
+            	else
+            	{
+            		d += delta_A;
+            		next_y += inc_y;
+            		//_log.warning("4: next_x:"+next_x+" next_y"+next_y);
+            		z += inc_z_directiony;
+            		if (!nLOS(x,y,(int)z,0,inc_y,tz,true))
+            			return false;
+            	}
+            }
+        }
+        return true;
+    }
+    /*
+     *  MoveCheck
+     */
+    private static Location moveCheck(Location startpoint, Location destiny, int x, int y, double z, int tx, int ty, int tz)
+    {
+    	int dx = (tx - x);
+        int dy = (ty - y);
+        final int distance2 = dx*dx+dy*dy;
+
+        if (distance2 == 0)
+        	return destiny;
+        if (distance2 > 36100) // 190*190*16 = 3040 world coord
+        {
+            // Avoid too long check
+        	// Currently we calculate a middle point
+        	// for wyvern users and otherwise for comfort
+        	double divider = Math.sqrt((double)30000/distance2);
+        	tx = x + (int)(divider * dx);
+        	ty = y + (int)(divider * dy);
+        	int dz = (tz - startpoint.getZ());
+        	tz = startpoint.getZ() + (int)(divider * dz);
+        	dx = (tx - x);
+        	dy = (ty - y);
+            //return startpoint;
+        }
+
+        // Increment in Z coordinate when moving along X or Y axis
+        // and not straight to the target. This is done because
+        // calculation moves either in X or Y direction.
+        final int inc_x = sign(dx);
+        final int inc_y = sign(dy);
+        dx = Math.abs(dx);
+        dy = Math.abs(dy);
+
+        //gm.sendMessage("MoveCheck: from X: "+x+ "Y: "+y+ "--->> X: "+tx+" Y: "+ty);
+
+        // next_* are used in NcanMoveNext check from x,y
+        int next_x = x;
+        int next_y = y;
+        double tempz = z;
+
+        // creates path to the target, using only x or y direction
+        // calculation stops when next_* == target
+        if (dx >= dy)// dy/dx <= 1
+        {
+        	int delta_A = 2*dy;
+        	int d = delta_A - dx;
+            int delta_B = delta_A - 2*dx;
+
+            for (int i = 0; i < dx; i++)
+            {
+            	x = next_x;
+            	y = next_y;
+            	if (d > 0)
+            	{
+            		d += delta_B;
+            		next_x += inc_x;
+            		next_y += inc_y;
+            		//_log.warning("2: next_x:"+next_x+" next_y"+next_y);
+            		tempz = nCanMoveNext(x,y,(int)z,next_x,next_y,tz);
+            		if (tempz == Double.MIN_VALUE)
+            			return new Location((x << 4) + L2World.MAP_MIN_X,(y << 4) + L2World.MAP_MIN_Y,(int)z);
+            		else z = tempz;
+            	}
+            	else
+            	{
+            		d += delta_A;
+            		next_x += inc_x;
+            		//_log.warning("3: next_x:"+next_x+" next_y"+next_y);
+            		tempz = nCanMoveNext(x,y,(int)z,next_x,next_y,tz);
+            		if (tempz == Double.MIN_VALUE)
+            			return new Location((x << 4) + L2World.MAP_MIN_X,(y << 4) + L2World.MAP_MIN_Y,(int)z);
+            		else z = tempz;
+            	}
+            }
+        }
+        else
+        {
+        	int delta_A = 2*dx;
+        	int d = delta_A - dy;
+            int delta_B = delta_A - 2*dy;
+            for (int i = 0; i < dy; i++)
+            {
+            	x = next_x;
+            	y = next_y;
+            	if (d > 0)
+            	{
+            		d += delta_B;
+            		next_y += inc_y;
+            		next_x += inc_x;
+            		//_log.warning("5: next_x:"+next_x+" next_y"+next_y);
+            		tempz = nCanMoveNext(x,y,(int)z,next_x,next_y,tz);
+            		if (tempz == Double.MIN_VALUE)
+            			return new Location((x << 4) + L2World.MAP_MIN_X,(y << 4) + L2World.MAP_MIN_Y,(int)z);
+            		else z = tempz;
+            	}
+            	else
+            	{
+            		d += delta_A;
+            		next_y += inc_y;
+            		//_log.warning("6: next_x:"+next_x+" next_y"+next_y);
+            		tempz = nCanMoveNext(x,y,(int)z,next_x,next_y,tz);
+            		if (tempz == Double.MIN_VALUE)
+            			return new Location((x << 4) + L2World.MAP_MIN_X,(y << 4) + L2World.MAP_MIN_Y,(int)z);
+            		else z = tempz;
+            	}
+            }
+        }
+        return destiny; // should actually return correct z here instead of tz
+    }
+
+    private static byte sign(int x)
+    {
+    	if (x >= 0)
+    		return +1;
+        else
+        	return -1;
+    }
+
+	//GeoEngine
+	private static void nInitGeodata()
+	{
+		LineNumberReader lnr = null;
+		try
+		{
+			_log.info("Geo Engine: - Loading Geodata...");
+			File Data = new File("./data/geodata/geo_index.txt");
+			if (!Data.exists())
+				return;
+
+			lnr = new LineNumberReader(new BufferedReader(new FileReader(Data)));
+		} catch (Exception e) {
+			e.printStackTrace();
+			throw new Error("Failed to Load geo_index File.");
+		}
+		String line;
+		try
+		{
+			while ((line = lnr.readLine()) != null) {
+				if (line.trim().length() == 0)
+					continue;
+				StringTokenizer st = new StringTokenizer(line, "_");
+				byte rx = Byte.parseByte(st.nextToken());
+				byte ry = Byte.parseByte(st.nextToken());
+				loadGeodataFile(rx,ry);
+			}
+		} catch (Exception e) {
+			e.printStackTrace();
+			throw new Error("Failed to Read geo_index File.");
+		}
+		try
+		{
+			File geo_bugs = new File("./data/geodata/geo_bugs.txt");
+
+			_geoBugsOut = new BufferedOutputStream(new FileOutputStream(geo_bugs,true));
+		} catch (Exception e) {
+			e.printStackTrace();
+			throw new Error("Failed to Load geo_bugs.txt File.");
+		}
+	}
+	public static void unloadGeodata(byte rx, byte ry)
+	{
+		short regionoffset = (short)((rx << 5) + ry);
+		_geodataIndex.remove(regionoffset);
+		_geodata.remove(regionoffset);
+	}
+	public static boolean loadGeodataFile(byte rx, byte ry)
+	{
+		String fname = "./data/geodata/"+rx+"_"+ry+".l2j";
+		short regionoffset = (short)((rx << 5) + ry);
+		_log.info("Geo Engine: - Loading: "+fname+" -> region offset: "+regionoffset+"X: "+rx+" Y: "+ry);
+		File Geo = new File(fname);
+		int size, index = 0, block = 0, flor = 0;
+		try {
+	        // Create a read-only memory-mapped file
+	        FileChannel roChannel = new RandomAccessFile(Geo, "r").getChannel();
+			size = (int)roChannel.size();
+			MappedByteBuffer geo;
+			if (Config.FORCE_GEODATA) //Force O/S to Loads this buffer's content into physical memory.
+				//it is not guarantee, because the underlying operating system may have paged out some of the buffer's data
+				geo = roChannel.map(FileChannel.MapMode.READ_ONLY, 0, size).load();
+			else
+				geo = roChannel.map(FileChannel.MapMode.READ_ONLY, 0, size);
+			geo.order(ByteOrder.LITTLE_ENDIAN);
+
+			if (size > 196608)
+			{
+				// Indexing geo files, so we will know where each block starts
+				IntBuffer indexs = IntBuffer.allocate(65536);
+				while(block < 65536)
+			    {
+					byte type = geo.get(index);
+			        indexs.put(block,index);
+					block++;
+					index++;
+			        if(type == 0)
+			        	index += 2; // 1x short
+			        else if(type == 1)
+			        	index += 128; // 64 x short
+			        else
+			        {
+			            int b;
+			            for(b=0;b<64;b++)
+			            {
+			                byte layers = geo.get(index);
+			                index += (layers << 1) + 1;
+			                if (layers > flor)
+			                     flor = layers;
+			            }
+			        }
+			    }
+				_geodataIndex.put(regionoffset, indexs);
+			}
+			_geodata.put(regionoffset,geo);
+
+			_log.info("Geo Engine: - Max Layers: "+flor+" Size: "+size+" Loaded: "+index);
+	    } catch (Exception e)
+		{
+			e.printStackTrace();
+			_log.warning("Failed to Load GeoFile at block: "+block+"\n");
+			return false;
+	    }
+	    return true;
+	}
+
+	//Geodata Methods
+	/**
+	 * @param x
+	 * @param y
+	 * @return Region Offset
+	 */
+	private static short getRegionOffset(int x, int y)
+	{
+	    int rx = x >> 11; // =/(256 * 8)
+	    int ry = y >> 11;
+	    return (short)(((rx+16) << 5) + (ry+10));
+	}
+
+	/**
+	 * @param pos
+	 * @return Block Index: 0-255
+	 */
+	private  static int getBlock(int geo_pos)
+	{
+	    return (geo_pos >> 3) % 256;
+	}
+
+	/**
+	 * @param pos
+	 * @return Cell Index: 0-7
+	 */
+	private static int getCell(int geo_pos)
+	{
+	    return geo_pos % 8;
+	}
+
+	//Geodata Functions
+
+	/**
+	 * @param x
+	 * @param y
+	 * @return Type of geo_block: 0-2
+	 */
+	private static short nGetType(int x, int y)
+	{
+	    short region = getRegionOffset(x,y);
+		int blockX = getBlock(x);
+		int blockY = getBlock(y);
+		int index = 0;
+		//Geodata without index - it is just empty so index can be calculated on the fly
+		if(_geodataIndex.get(region) == null) index = ((blockX << 8) + blockY)*3;
+		//Get Index for current block of current geodata region
+		else index = _geodataIndex.get(region).get((blockX << 8) + blockY);
+		//Buffer that Contains current Region GeoData
+		ByteBuffer geo = _geodata.get(region);
+		if(geo == null)
+		{
+			if(Config.DEBUG)
+				_log.warning("Geo Region - Region Offset: "+region+" dosnt exist!!");
+			return 0;
+		}
+		return geo.get(index);
+	}
+	/**
+	 * @param x
+	 * @param y
+	 * @param z
+	 * @return Nearlest Z
+	 */
+	private static short nGetHeight(int geox, int geoy, int z)
+	{
+	    short region = getRegionOffset(geox,geoy);
+	    int blockX = getBlock(geox);
+		int blockY = getBlock(geoy);
+		int cellX, cellY, index;
+		//Geodata without index - it is just empty so index can be calculated on the fly
+		if(_geodataIndex.get(region) == null) index = ((blockX << 8) + blockY)*3;
+		//Get Index for current block of current region geodata
+		else index = _geodataIndex.get(region).get(((blockX << 8))+(blockY));
+		//Buffer that Contains current Region GeoData
+		ByteBuffer geo = _geodata.get(region);
+		if(geo == null)
+		{
+			if(Config.DEBUG)
+				_log.warning("Geo Region - Region Offset: "+region+" dosnt exist!!");
+			return (short)z;
+		}
+		//Read current block type: 0-flat,1-complex,2-multilevel
+		byte type = geo.get(index);
+		index++;
+	    if(type == 0)//flat
+	        return geo.getShort(index);
+	    else if(type == 1)//complex
+	    {
+	    	cellX = getCell(geox);
+			cellY = getCell(geoy);
+	        index += ((cellX << 3) + cellY) << 1;
+	        short height = geo.getShort(index);
+			height = (short)(height&0x0fff0);
+			height = (short)(height >> 1); //height / 2
+			return height;
+	    }
+	    else //multilevel
+	    {
+	    	cellX = getCell(geox);
+			cellY = getCell(geoy);
+	        int offset = (cellX << 3) + cellY;
+	        while(offset > 0)
+	        {
+	            byte lc = geo.get(index);
+	            index += (lc << 1) + 1;
+	            offset--;
+	        }
+	        byte layers = geo.get(index);
+	        index++;
+	        short height=-1;
+			if(layers <= 0 || layers > 125)
+			{
+				_log.warning("Broken geofile (case1), region: "+region+" - invalid layer count: "+layers+" at: "+geox+" "+geoy);
+	            return (short)z;
+			}
+	        short temph = Short.MIN_VALUE;
+	        while(layers > 0)
+	        {
+	            height = geo.getShort(index);
+	            height = (short)(height&0x0fff0);
+				height = (short)(height >> 1); //height / 2
+	            if ((z-temph)*(z-temph) > (z-height)*(z-height))
+	                temph = height;
+	            layers--;
+	            index += 2;
+	        }
+		 return temph;
+	    }
+	}
+	/**
+	 * @param x
+	 * @param y
+	 * @param zmin
+	 * @param zmax
+	 * @return Z betwen zmin and zmax
+	 */
+	private static short nGetSpawnHeight(int geox, int geoy, int zmin, int zmax, int spawnid)
+	{
+	    short region = getRegionOffset(geox,geoy);
+	    int blockX = getBlock(geox);
+		int blockY = getBlock(geoy);
+		int cellX, cellY, index;
+		short temph = Short.MIN_VALUE;
+		//Geodata without index - it is just empty so index can be calculated on the fly
+		if(_geodataIndex.get(region) == null) index = ((blockX << 8) + blockY)*3;
+		//Get Index for current block of current region geodata
+		else index = _geodataIndex.get(region).get(((blockX << 8))+(blockY));
+		//Buffer that Contains current Region GeoData
+		ByteBuffer geo = _geodata.get(region);
+		if(geo == null)
+		{
+			if(Config.DEBUG)
+				_log.warning("Geo Region - Region Offset: "+region+" dosnt exist!!");
+			return (short)zmin;
+		}
+		//Read current block type: 0-flat,1-complex,2-multilevel
+		byte type = geo.get(index);
+		index++;
+	    if(type == 0)//flat
+	    	temph = geo.getShort(index);
+	    else if(type == 1)//complex
+	    {
+	    	cellX = getCell(geox);
+			cellY = getCell(geoy);
+	        index += ((cellX << 3) + cellY) << 1;
+	        short height = geo.getShort(index);
+			height = (short)(height&0x0fff0);
+			height = (short)(height >> 1); //height / 2
+            temph = height;
+	    }
+	    else//multilevel
+	    {
+	    	cellX = getCell(geox);
+			cellY = getCell(geoy);
+			short height;
+	        int offset = (cellX << 3) + cellY;
+	        while(offset > 0)
+	        {
+	            byte lc = geo.get(index);
+	            index += (lc << 1) + 1;
+	            offset--;
+	        }
+	        //Read current block type: 0-flat,1-complex,2-multilevel
+	        byte layers = geo.get(index);
+	        index++;
+			if(layers <= 0 || layers > 125)
+			{
+				_log.warning("Broken geofile (case2), region: "+region+" - invalid layer count: "+layers+" at: "+geox+" "+geoy);
+	            return (short)zmin;
+			}
+	        while(layers > 0)
+	        {
+	            height = geo.getShort(index);
+	            height = (short)(height&0x0fff0);
+				height = (short)(height >> 1); //height / 2
+	            if ((zmin-temph)*(zmin-temph) > (zmin-height)*(zmin-height))
+	                temph = height;
+	            layers--;
+	            index += 2;
+	        }
+	        if (temph > zmax + 200 || temph < zmin - 200)
+	        {
+	        	if(Config.DEBUG)
+	        		_log.warning("SpawnHeight Error - Couldnt find correct layer to spawn NPC - GeoData or Spawnlist Bug!: zmin: "+zmin+" zmax: "+zmax+" value: "+temph+" SpawnId: "+spawnid+" at: "+geox+" : "+geoy);
+	        	return (short)zmin;
+	        }
+	    }
+	    if (temph > zmax + 1000 || temph < zmin - 1000)
+	    {
+	    	if(Config.DEBUG)
+	    		_log.warning("SpawnHeight Error - Spawnlist z value is wrong or GeoData error: zmin: "+zmin+" zmax: "+zmax+" value: "+temph+" SpawnId: "+spawnid+" at: "+geox+" : "+geoy);
+	    	return (short)zmin;
+        }
+	    return temph;
+	}
+	/**
+	 * @param x
+	 * @param y
+	 * @param z
+	 * @param tx
+	 * @param ty
+	 * @param tz
+	 * @return True if char can move to (tx,ty,tz)
+	 */
+	private static double nCanMoveNext(int x, int y, int z, int tx, int ty, int tz)
+	{
+	    short region = getRegionOffset(x,y);
+	    int blockX = getBlock(x);
+		int blockY = getBlock(y);
+		int cellX, cellY;
+	    short NSWE = 0;
+
+		int index = 0;
+		//Geodata without index - it is just empty so index can be calculated on the fly
+		if(_geodataIndex.get(region) == null) index = ((blockX << 8) + blockY)*3;
+		//Get Index for current block of current region geodata
+		else index = _geodataIndex.get(region).get(((blockX << 8))+(blockY));
+		//Buffer that Contains current Region GeoData
+		ByteBuffer geo = _geodata.get(region);
+		if(geo == null)
+		{
+			if(Config.DEBUG)
+				_log.warning("Geo Region - Region Offset: "+region+" dosnt exist!!");
+			return z;
+		}
+		//Read current block type: 0-flat,1-complex,2-multilevel
+		byte type = geo.get(index);
+		index++;
+	    if(type == 0) //flat
+	        return z;
+	    else if(type == 1) //complex
+	    {
+	    	cellX = getCell(x);
+			cellY = getCell(y);
+	        index += ((cellX << 3) + cellY) << 1;
+	        short height = geo.getShort(index);
+			NSWE = (short)(height&0x0F);
+			height = (short)(height&0x0fff0);
+			height = (short)(height >> 1); //height / 2
+			if(checkNSWE(NSWE,x,y,tx,ty)) return height;
+			else return Double.MIN_VALUE;
+	    }
+	    else //multilevel, type == 2
+	    {
+	    	cellX = getCell(x);
+			cellY = getCell(y);
+	        int offset = (cellX << 3) + cellY;
+	        while(offset > 0) // iterates (too many times?) to get to layer count
+	        {
+	            byte lc = geo.get(index);
+	            index += (lc << 1) + 1;
+	            offset--;
+	        }
+	        byte layers = geo.get(index);
+	        //_log.warning("layers"+layers);
+	        index++;
+	        short height=-1;
+	        if(layers <= 0 || layers > 125)
+	        {
+	        	_log.warning("Broken geofile (case3), region: "+region+" - invalid layer count: "+layers+" at: "+x+" "+y);
+	            return z;
+	        }
+	        short tempz = Short.MIN_VALUE;
+	        while(layers > 0)
+	        {
+	            height = geo.getShort(index);
+	            height = (short)(height&0x0fff0);
+				height = (short)(height >> 1); //height / 2
+
+				// searches the closest layer to current z coordinate
+	            if ((z-tempz)*(z-tempz) > (z-height)*(z-height))
+	            {
+	                //layercurr = layers;
+	            	tempz = height;
+	                NSWE = geo.getShort(index);
+	                NSWE = (short)(NSWE&0x0F);
+	            }
+	            layers--;
+	            index += 2;
+	        }
+	        if(checkNSWE(NSWE,x,y,tx,ty)) return tempz;
+	        else return Double.MIN_VALUE;
+	    }
+	}
+	/**
+	 * @param x
+	 * @param y
+	 * @param z
+	 * @param inc_x
+	 * @param inc_y
+	 * @param tz
+	 * @return True if Char can see target
+	 */
+	private static boolean nLOS(int x, int y, int z, int inc_x, int inc_y, int tz, boolean debug)
+	{
+	    short region = getRegionOffset(x,y);
+	    int blockX = getBlock(x);
+		int blockY = getBlock(y);
+		int cellX, cellY;
+	    short NSWE = 0;
+
+		int index;
+		//Geodata without index - it is just empty so index can be calculated on the fly
+		if(_geodataIndex.get(region) == null) index = ((blockX << 8) + blockY)*3;
+		//Get Index for current block of current region geodata
+		else index = _geodataIndex.get(region).get(((blockX << 8))+(blockY));
+		//Buffer that Contains current Region GeoData
+		ByteBuffer geo = _geodata.get(region);
+		if(geo == null)
+		{
+			if(Config.DEBUG)
+				_log.warning("Geo Region - Region Offset: "+region+" dosnt exist!!");
+			return true;
+		}
+		//Read current block type: 0-flat,1-complex,2-multilevel
+		byte type = geo.get(index);
+		index++;
+	    if(type == 0) //flat, movement and sight always possible
+	    {
+	    	if(debug) _log.warning("flatheight:"+geo.getShort(index));
+	    	return true;
+	    }
+	    else if(type == 1) //complex
+	    {
+	    	cellX = getCell(x);
+			cellY = getCell(y);
+	        index += ((cellX << 3) + cellY) << 1;
+	        short height = geo.getShort(index);
+	        NSWE = (short)(height&0x0F);
+	        height = (short)(height&0x0fff0);
+			height = (short)(height >> 1); //height / 2
+			if(debug) {
+				_log.warning("height:"+height+" z"+z);
+				if(!checkNSWE(NSWE,x,y,x+inc_x,y+inc_y)) _log.warning("would block");
+			}
+			if(z - height > 50) return true; // this value is just an approximate
+	    }
+	    else//multilevel, type == 2
+	    {
+	    	cellX = getCell(x);
+			cellY = getCell(y);
+	        int offset = (cellX << 3) + cellY;
+	        while(offset > 0) // iterates (too many times?) to get to layer count
+	        {
+	            byte lc = geo.get(index);
+	            index += (lc << 1) + 1;
+	            offset--;
+	        }
+	        byte layers = geo.get(index);
+	        if (debug) _log.warning("layers"+layers);
+	        index++;
+	        short height=-1;
+	        if(layers <= 0 || layers > 125)
+	        {
+	        	_log.warning("Broken geofile (case4), region: "+region+" - invalid layer count: "+layers+" at: "+x+" "+y);
+	            return false;
+	        }
+	        short tempz = Short.MIN_VALUE; // big negative value
+	        byte temp_layers = layers;
+	        boolean highestlayer = true;
+
+	        z -= 25; // lowering level temporarily to avoid selecting ceiling
+	        while(temp_layers > 0)
+	        {
+	            // reads height for current layer, result in world z coordinate
+	        	height = geo.getShort(index);
+	            height = (short)(height&0x0fff0);
+				height = (short)(height >> 1); //height / 2
+				//height -= 8; // old geo files had -8 around giran, new data seems better
+
+				// searches the closest layer to current z coordinate
+				if ((z-tempz)*(z-tempz) > (z-height)*(z-height))
+	            {
+					if(tempz > Short.MIN_VALUE) highestlayer = false;
+					tempz = height;
+					if (debug) _log.warning("z"+(z+45)+" tempz"+tempz+" dz"+(z-tempz));
+	                NSWE = geo.getShort(index);
+	                NSWE = (short)(NSWE&0x0F);
+	            }
+				temp_layers--;
+	            index += 2;
+	        }
+	        z += 25; // level rises back
+
+	        // Check if LOS goes under a layer/floor
+	        if((z-tempz) < -20) return false; // -20 => clearly under, approximates also fence width
+
+	        // this helps in some cases (occasional under-highest-layer block which isn't wall)
+	        // but might also create problems in others (passes walls when you're standing high)
+	        if((z-tempz) > 250) return true;
+
+	        // or there's a fence/wall ahead when we're not on highest layer
+	        // this part of the check is problematic
+	        if(!highestlayer)
+	        {
+	        	//a probable wall, there's movement block and layers above you
+	        	if(!checkNSWE(NSWE,x,y,x+inc_x,y+inc_y)) // cannot move
+	        	{
+	        		// the height after 2 inc_x,inc_y
+	        		short nextheight = nGetHeight(x+2*inc_x,y+2*inc_y,z-50);
+	        		if(debug)
+	        		{
+	        			_log.warning("0: z:"+z+" tz"+nGetHeight(x,y,z-60));
+	        			_log.warning("1: z:"+z+" tz"+nGetHeight(x+inc_x,y+inc_y,z-60));
+	        			_log.warning("2: z:"+z+" tz"+nGetHeight(x+2*inc_x,y+2*inc_y,z-60));
+	        			_log.warning("3: z:"+z+" tz"+nGetHeight(x+3*inc_x,y+3*inc_y,z-60));
+	        		}
+	        		// Probably a very thin fence (e.g. castle fences above artefact),
+	        		// where height instantly drops after 1-2 cells and layer ends.
+	        		if(z-nextheight>100) return true;
+	        		// layer continues so close we can see over it
+	        		if(nextheight-tempz>5 && nextheight-tempz<20) return true;
+	        		return false;
+	        	}
+	        	else return true;
+	        }
+	        else return true;
+	    }
+	    return checkNSWE(NSWE,x,y,x+inc_x,y+inc_y);
+	}
+	/**
+	 * @param x
+	 * @param y
+	 * @param z
+	 * @return NSWE: 0-15
+	 */
+	private short nGetNSWE(int x, int y, int z)
+	{
+		short region = getRegionOffset(x,y);
+	    int blockX = getBlock(x);
+		int blockY = getBlock(y);
+		int cellX, cellY;
+	    short NSWE = 0;
+
+		int index = 0;
+		//Geodata without index - it is just empty so index can be calculated on the fly
+		if(_geodataIndex.get(region) == null) index = ((blockX << 8) + blockY)*3;
+		//Get Index for current block of current region geodata
+		else index = _geodataIndex.get(region).get(((blockX << 8))+(blockY));
+		//Buffer that Contains current Region GeoData
+		ByteBuffer geo = _geodata.get(region);
+		if(geo == null)
+		{
+			if(Config.DEBUG)
+				_log.warning("Geo Region - Region Offset: "+region+" dosnt exist!!");
+			return 15;
+		}
+		//Read current block type: 0-flat,1-complex,2-multilevel
+		byte type = geo.get(index);
+		index++;
+	    if(type == 0)//flat
+	        return 15;
+	    else if(type == 1)//complex
+	    {
+	    	cellX = getCell(x);
+			cellY = getCell(y);
+	        index += ((cellX << 3) + cellY) << 1;
+	        short height = geo.getShort(index);
+			NSWE = (short)(height&0x0F);
+	    }
+	    else//multilevel
+	    {
+	    	cellX = getCell(x);
+			cellY = getCell(y);
+	        int offset = (cellX << 3) + cellY;
+	        while(offset > 0)
+	        {
+	        	byte lc = geo.get(index);
+	            index += (lc << 1) + 1;
+	            offset--;
+	        }
+	        byte layers = geo.get(index);
+	        index++;
+	        short height=-1;
+	        if(layers <= 0 || layers > 125)
+	        {
+	        	_log.warning("Broken geofile (case5), region: "+region+" - invalid layer count: "+layers+" at: "+x+" "+y);
+	            return 15;
+	        }
+	        short tempz = Short.MIN_VALUE;
+	        while(layers > 0)
+	        {
+	            height = geo.getShort(index);
+	            height = (short)(height&0x0fff0);
+				height = (short)(height >> 1); //height / 2
+
+	            if ((z-tempz)*(z-tempz) > (z-height)*(z-height))
+	            {
+	                tempz = height;
+	                NSWE = geo.get(index);
+	                NSWE = (short)(NSWE&0x0F);
+	            }
+	            layers--;
+	            index += 2;
+	        }
+	    }
+	    return NSWE;
+	}
+
+	/**
+	 * @param NSWE
+	 * @param x
+	 * @param y
+	 * @param tx
+	 * @param ty
+	 * @return True if NSWE dont block given direction
+	 */
+	private static boolean checkNSWE(short NSWE, int x, int y, int tx, int ty)
+    {
+        //Check NSWE
+	    if(NSWE == 15)
+	       return true;
+	    if(tx > x)//E
+	    {
+	    	if ((NSWE & _e) == 0)
+	            return false;
+	    }
+	    else if (tx < x)//W
+	    {
+	    	if ((NSWE & _w) == 0)
+	            return false;
+	    }
+	    if (ty > y)//S
+	    {
+	    	if ((NSWE & _s) == 0)
+	            return false;
+	    }
+	    else if (ty < y)//N
+	    {
+	    	if ((NSWE & _n) == 0)
+	            return false;
+	    }
+	    return true;
+    }
+}

+ 165 - 0
L2_GameServer_T1/java/net/sf/l2j/gameserver/GmListTable.java

@@ -0,0 +1,165 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+package net.sf.l2j.gameserver;
+
+import javolution.util.FastList;
+import javolution.util.FastMap;
+import java.util.logging.Logger;
+
+import net.sf.l2j.Config;
+import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
+import net.sf.l2j.gameserver.network.SystemMessageId;
+import net.sf.l2j.gameserver.serverpackets.L2GameServerPacket;
+import net.sf.l2j.gameserver.serverpackets.SystemMessage;
+
+/**
+ * This class stores references to all online game masters. (access level > 100)
+ * 
+ * @version $Revision: 1.2.2.1.2.7 $ $Date: 2005/04/05 19:41:24 $
+ */
+public class GmListTable
+{
+	private static Logger _log = Logger.getLogger(GmListTable.class.getName());
+	private static GmListTable _instance;
+	
+	
+	/** Set(L2PcInstance>) containing all the GM in game */
+	private FastMap<L2PcInstance, Boolean> _gmList;
+	
+	public static GmListTable getInstance()
+	{
+		if (_instance == null)
+		{
+			_instance = new GmListTable();
+		}
+		return _instance;
+	}
+	
+	public FastList<L2PcInstance> getAllGms(boolean includeHidden)
+	{
+		FastList<L2PcInstance> tmpGmList = new FastList<L2PcInstance>();
+		
+		for (FastMap.Entry<L2PcInstance, Boolean> n = _gmList.head(), end = _gmList.tail(); (n = n.getNext())!=end;)
+			if (includeHidden || !n.getValue())
+				tmpGmList.add(n.getKey());
+		
+		return tmpGmList;
+	}
+	
+	public FastList<String> getAllGmNames(boolean includeHidden)
+	{
+		FastList<String> tmpGmList = new FastList<String>();
+		
+		for (FastMap.Entry<L2PcInstance, Boolean> n = _gmList.head(), end = _gmList.tail(); (n = n.getNext())!=end;)
+			if (!n.getValue())
+				tmpGmList.add(n.getKey().getName());
+			else if (includeHidden)
+				tmpGmList.add(n.getKey().getName()+" (invis)");
+		
+		return tmpGmList;
+	}
+	
+	private GmListTable()
+	{
+		_gmList = new FastMap<L2PcInstance,Boolean>().setShared(true);
+	}
+	
+	/**
+	 * Add a L2PcInstance player to the Set _gmList
+	 */
+	public void addGm(L2PcInstance player, boolean hidden)
+	{
+		if (Config.DEBUG) _log.fine("added gm: "+player.getName());
+		_gmList.put(player,hidden);
+	}
+	
+	public void deleteGm(L2PcInstance player)
+	{
+		if (Config.DEBUG) _log.fine("deleted gm: "+player.getName());
+		
+		_gmList.remove(player);
+	}
+	
+	/**
+	 * GM will be displayed on clients gmlist
+	 * @param player
+	 */
+	public void showGm(L2PcInstance player)
+	{
+		FastMap.Entry<L2PcInstance, Boolean> gm = _gmList.getEntry(player);
+		if (gm != null) gm.setValue(false);
+	}
+	
+	/**
+	 * GM will no longer be displayed on clients gmlist
+	 * @param player
+	 */
+	public void hideGm(L2PcInstance player)
+	{
+		FastMap.Entry<L2PcInstance, Boolean> gm = _gmList.getEntry(player);
+		if (gm != null) gm.setValue(true);
+	}
+	
+	public boolean isGmOnline(boolean includeHidden)
+	{
+		for (FastMap.Entry<L2PcInstance, Boolean> n = _gmList.head(), end = _gmList.tail(); (n = n.getNext())!=end;)
+		{
+			if (includeHidden || !n.getValue())
+				return true;
+		}
+		
+		return false;
+	}
+	
+	public void sendListToPlayer (L2PcInstance player)
+	{
+		if (!isGmOnline(player.isGM()))
+		{
+			SystemMessage sm = new SystemMessage(SystemMessageId.NO_GM_PROVIDING_SERVICE_NOW); //There are not any GMs that are providing customer service currently.
+			player.sendPacket(sm);
+		} else
+		{
+			SystemMessage sm = new SystemMessage(SystemMessageId.GM_LIST);
+			player.sendPacket(sm);
+			
+            for (String name : getAllGmNames(player.isGM()))
+            {
+				sm = new SystemMessage(SystemMessageId.GM_S1);
+				sm.addString(name);
+				player.sendPacket(sm);
+			}
+		}
+	}
+	
+	public static void broadcastToGMs(L2GameServerPacket packet)
+	{
+		for (L2PcInstance gm : getInstance().getAllGms(true))
+		{
+			gm.sendPacket(packet);
+		}
+	}
+	
+	public static void broadcastMessageToGMs(String message)
+	{
+		for (L2PcInstance gm : getInstance().getAllGms(true))
+		{
+			gm.sendPacket(SystemMessage.sendString(message));
+		}
+	}
+}

+ 47 - 0
L2_GameServer_T1/java/net/sf/l2j/gameserver/Item.java

@@ -0,0 +1,47 @@
+/*
+ * $Header: Item.java, 2/08/2005 00:49:12 luisantonioa Exp $
+ *
+ * $Author: luisantonioa $
+ * $Date: 2/08/2005 00:49:12 $
+ * $Revision: 1 $
+ * $Log: Item.java,v $
+ * Revision 1  2/08/2005 00:49:12  luisantonioa
+ * Added copyright notice
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+package net.sf.l2j.gameserver;
+
+import net.sf.l2j.gameserver.templates.L2Item;
+import net.sf.l2j.gameserver.templates.StatsSet;
+
+/**
+ * This class ...
+ *
+ * @version $Revision: 1.2 $ $Date: 2004/06/27 08:12:59 $
+ */
+public class Item
+{
+    public int      id;
+    public Enum     type;
+    public String   name;
+    public StatsSet set;
+    public int      currentLevel;
+    public L2Item   item;
+}

+ 111 - 0
L2_GameServer_T1/java/net/sf/l2j/gameserver/ItemsAutoDestroy.java

@@ -0,0 +1,111 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+package net.sf.l2j.gameserver;
+
+import java.util.List;
+import java.util.logging.Logger;
+
+import javolution.util.FastList;
+import net.sf.l2j.Config;
+import net.sf.l2j.gameserver.instancemanager.ItemsOnGroundManager;
+import net.sf.l2j.gameserver.model.L2ItemInstance;
+import net.sf.l2j.gameserver.model.L2World;
+import net.sf.l2j.gameserver.templates.L2EtcItemType;
+
+public class ItemsAutoDestroy
+{
+	protected static final Logger _log = Logger.getLogger("ItemsAutoDestroy");
+	private static ItemsAutoDestroy _instance;
+	protected List<L2ItemInstance> _items = null;
+	protected static long _sleep;
+
+    private ItemsAutoDestroy()
+    {
+        _items = new FastList<L2ItemInstance>();
+        _sleep	= Config.AUTODESTROY_ITEM_AFTER * 1000;
+        if(_sleep == 0) // it should not happend as it is not called when AUTODESTROY_ITEM_AFTER = 0 but we never know..
+        	_sleep = 3600000;
+        ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(new CheckItemsForDestroy(),5000,5000);
+    }
+
+    public static ItemsAutoDestroy getInstance()
+    {
+        if (_instance == null)
+        {
+			System.out.println("Initializing ItemsAutoDestroy.");
+            _instance = new ItemsAutoDestroy();
+        }
+        return _instance;
+    }
+
+    public synchronized void addItem (L2ItemInstance item)
+    {
+        item.setDropTime(System.currentTimeMillis());
+        _items.add(item);
+    }
+
+    public synchronized void removeItems()
+    {
+    	if (Config.DEBUG)
+    		_log.info("[ItemsAutoDestroy] : "+_items.size()+" items to check.");
+
+    	if (_items.isEmpty()) return;
+
+        long curtime = System.currentTimeMillis();
+        for (L2ItemInstance item : _items)
+        {
+            if (item == null || item.getDropTime()==0 || item.getLocation() != L2ItemInstance.ItemLocation.VOID)
+                _items.remove(item);
+            else
+            {
+            	if(item.getItemType() == L2EtcItemType.HERB )
+            	{
+            		if((curtime - item.getDropTime()) > Config.HERB_AUTO_DESTROY_TIME)
+            		{
+            			L2World.getInstance().removeVisibleObject(item,item.getWorldRegion());
+            			L2World.getInstance().removeObject(item);
+            			_items.remove(item);
+            			if (Config.SAVE_DROPPED_ITEM)
+                			ItemsOnGroundManager.getInstance().removeObject(item);
+            		}
+            	}
+            	else if ( (curtime - item.getDropTime()) > _sleep)
+                {
+                    L2World.getInstance().removeVisibleObject(item,item.getWorldRegion());
+                    L2World.getInstance().removeObject(item);
+                    _items.remove(item);
+                    if (Config.SAVE_DROPPED_ITEM)
+                    	ItemsOnGroundManager.getInstance().removeObject(item);
+                }
+            }
+        }
+
+    	if (Config.DEBUG)
+    		_log.info("[ItemsAutoDestroy] : "+_items.size()+" items remaining.");
+    }
+
+    protected class CheckItemsForDestroy extends Thread
+    {
+        @Override
+		public void run()
+        {
+        	removeItems();
+        }
+    }
+}

+ 613 - 0
L2_GameServer_T1/java/net/sf/l2j/gameserver/LoginServerThread.java

@@ -0,0 +1,613 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+package net.sf.l2j.gameserver;
+
+import java.io.BufferedOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.math.BigInteger;
+import java.net.Socket;
+import java.net.UnknownHostException;
+import java.security.GeneralSecurityException;
+import java.security.KeyFactory;
+import java.security.interfaces.RSAPublicKey;
+import java.security.spec.RSAKeyGenParameterSpec;
+import java.security.spec.RSAPublicKeySpec;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Logger;
+
+import javolution.util.FastList;
+import javolution.util.FastMap;
+import net.sf.l2j.Config;
+import net.sf.l2j.gameserver.gameserverpackets.AuthRequest;
+import net.sf.l2j.gameserver.gameserverpackets.BlowFishKey;
+import net.sf.l2j.gameserver.gameserverpackets.ChangeAccessLevel;
+import net.sf.l2j.gameserver.gameserverpackets.GameServerBasePacket;
+import net.sf.l2j.gameserver.gameserverpackets.PlayerAuthRequest;
+import net.sf.l2j.gameserver.gameserverpackets.PlayerInGame;
+import net.sf.l2j.gameserver.gameserverpackets.PlayerLogout;
+import net.sf.l2j.gameserver.gameserverpackets.ServerStatus;
+import net.sf.l2j.gameserver.loginserverpackets.AuthResponse;
+import net.sf.l2j.gameserver.loginserverpackets.InitLS;
+import net.sf.l2j.gameserver.loginserverpackets.KickPlayer;
+import net.sf.l2j.gameserver.loginserverpackets.LoginServerFail;
+import net.sf.l2j.gameserver.loginserverpackets.PlayerAuthResponse;
+import net.sf.l2j.gameserver.model.L2World;
+import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
+import net.sf.l2j.gameserver.network.L2GameClient;
+import net.sf.l2j.gameserver.network.L2GameClient.GameClientState;
+import net.sf.l2j.gameserver.serverpackets.LoginFail;
+import net.sf.l2j.gameserver.serverpackets.CharSelectionInfo;
+import net.sf.l2j.loginserver.crypt.NewCrypt;
+import net.sf.l2j.util.Rnd;
+import net.sf.l2j.util.Util;
+
+public class LoginServerThread extends Thread
+{
+	protected static final Logger _log = Logger.getLogger(LoginServerThread.class.getName());
+
+	/** The LoginServerThread singleton */
+	private static LoginServerThread	_instance;
+
+	/** {@see net.sf.l2j.loginserver.LoginServer#PROTOCOL_REV } */
+	private static final int			REVISION = 0x0102;
+	private RSAPublicKey				_publicKey;
+	private String						_hostname;
+	private int							_port;
+	private int							_gamePort;
+	private Socket						_loginSocket;
+	private InputStream 				_in;
+	private OutputStream 				_out;
+
+	/**
+	 * The BlowFish engine used to encrypt packets<br>
+	 * It is first initialized with a unified key:<br>
+	 * "_;v.]05-31!|+-%xT!^[$\00"<br>
+	 * <br>
+	 * and then after handshake, with a new key sent by<br>
+	 * loginserver during the handshake. This new key is stored<br>
+	 * in {@link #_blowfishKey}
+	 */
+	private NewCrypt 					_blowfish;
+	private byte[]			 			_blowfishKey;
+	private byte[] 						_hexID;
+	private boolean			 			_acceptAlternate;
+	private int							_requestID;
+	private int							_serverID;
+	private boolean 					_reserveHost;
+	private int							_maxPlayer;
+	private List<WaitingClient>			_waitingClients;
+	private Map<String, L2GameClient>	_accountsInGameServer;
+	private int							_status;
+	private String						_serverName;
+	private String						_gameExternalHost;
+	private String						_gameInternalHost;
+
+	public LoginServerThread()
+	{
+		super("LoginServerThread");
+		_port = Config.GAME_SERVER_LOGIN_PORT;
+		_gamePort = Config.PORT_GAME;
+		_hostname = Config.GAME_SERVER_LOGIN_HOST;
+		_hexID = Config.HEX_ID;
+		if(_hexID == null)
+		{
+			_requestID = Config.REQUEST_ID;
+			_hexID = generateHex(16);
+		}
+		else
+		{
+			_requestID = Config.SERVER_ID;
+		}
+		_acceptAlternate = Config.ACCEPT_ALTERNATE_ID;
+		_reserveHost = Config.RESERVE_HOST_ON_LOGIN;
+		_gameExternalHost = Config.EXTERNAL_HOSTNAME;
+		_gameInternalHost = Config.INTERNAL_HOSTNAME;
+		_waitingClients = new FastList<WaitingClient>();
+		_accountsInGameServer = new FastMap<String, L2GameClient>().setShared(true);
+		_maxPlayer = Config.MAXIMUM_ONLINE_USERS;
+	}
+
+	public static LoginServerThread getInstance()
+	{
+		if(_instance == null)
+		{
+			_instance = new LoginServerThread();
+		}
+		return _instance;
+	}
+
+	@Override
+	public void run()
+	{
+		while(true)
+		{
+			int lengthHi =0;
+			int lengthLo =0;
+			int length = 0;
+			boolean checksumOk = false;
+			try
+			{
+				// Connection
+				_log.info("Connecting to login on "+_hostname+":"+_port);
+				_loginSocket = new Socket(_hostname,_port);
+				_in = _loginSocket.getInputStream();
+				_out = new BufferedOutputStream(_loginSocket.getOutputStream());
+
+				//init Blowfish
+				_blowfishKey = generateHex(40);
+				_blowfish = new NewCrypt("_;v.]05-31!|+-%xT!^[$\00");
+				while (true)
+				{
+					lengthLo = _in.read();
+					lengthHi = _in.read();
+					length= lengthHi*256 + lengthLo;
+
+					if (lengthHi < 0 )
+					{
+						_log.finer("LoginServerThread: Login terminated the connection.");
+						break;
+					}
+
+					byte[] incoming = new byte[length];
+					incoming[0] = (byte) lengthLo;
+					incoming[1] = (byte) lengthHi;
+
+					int receivedBytes = 0;
+					int newBytes = 0;
+					while (newBytes != -1 && receivedBytes<length-2)
+					{
+						newBytes =  _in.read(incoming, 2, length-2);
+						receivedBytes = receivedBytes + newBytes;
+					}
+
+					if (receivedBytes != length-2)
+					{
+						_log.warning("Incomplete Packet is sent to the server, closing connection.(LS)");
+						break;
+					}
+
+					byte[] decrypt = new byte[length - 2];
+					System.arraycopy(incoming, 2, decrypt, 0, decrypt.length);
+					// decrypt if we have a key
+					decrypt = _blowfish.decrypt(decrypt);
+					checksumOk = NewCrypt.verifyChecksum(decrypt);
+
+					if (!checksumOk)
+					{
+						_log.warning("Incorrect packet checksum, ignoring packet (LS)");
+						break;
+					}
+
+					if (Config.DEBUG)
+						_log.warning("[C]\n"+Util.printData(decrypt));
+
+					int packetType = decrypt[0]&0xff;
+					switch (packetType)
+					{
+					case 00:
+						InitLS init = new InitLS(decrypt);
+						if (Config.DEBUG) _log.info("Init received");
+						if(init.getRevision() != REVISION)
+						{
+							//TODO: revision mismatch
+							_log.warning("/!\\ Revision mismatch between LS and GS /!\\");
+							break;
+						}
+						try
+						{
+							KeyFactory kfac = KeyFactory.getInstance("RSA");
+							BigInteger modulus = new BigInteger(init.getRSAKey());
+							RSAPublicKeySpec kspec1 = new RSAPublicKeySpec(modulus, RSAKeyGenParameterSpec.F4);
+							_publicKey = (RSAPublicKey)kfac.generatePublic(kspec1);
+							if (Config.DEBUG) _log.info("RSA key set up");
+						}
+
+						catch (GeneralSecurityException e)
+						{
+							_log.warning("Troubles while init the public key send by login");
+							break;
+						}
+						//send the blowfish key through the rsa encryption
+						BlowFishKey bfk = new BlowFishKey(_blowfishKey,_publicKey);
+						sendPacket(bfk);
+						if (Config.DEBUG)_log.info("Sent new blowfish key");
+						//now, only accept paket with the new encryption
+						_blowfish = new NewCrypt(_blowfishKey);
+						if (Config.DEBUG)_log.info("Changed blowfish key");
+						AuthRequest ar = new AuthRequest(_requestID, _acceptAlternate, _hexID, _gameExternalHost, _gameInternalHost, _gamePort, _reserveHost, _maxPlayer);
+						sendPacket(ar);
+						if (Config.DEBUG)_log.info("Sent AuthRequest to login");
+						break;
+					case 01:
+						LoginServerFail lsf = new LoginServerFail(decrypt);
+						_log.info("Damn! Registeration Failed: "+lsf.getReasonString());
+						// login will close the connection here
+						break;
+					case 02:
+						AuthResponse aresp = new AuthResponse(decrypt);
+						_serverID = aresp.getServerId();
+						_serverName = aresp.getServerName();
+						Config.saveHexid(_serverID, hexToString(_hexID));
+						_log.info("Registered on login as Server "+_serverID+" : "+_serverName);
+						ServerStatus st = new ServerStatus();
+						if(Config.SERVER_LIST_BRACKET)
+						{
+							st.addAttribute(ServerStatus.SERVER_LIST_SQUARE_BRACKET,ServerStatus.ON);
+						}
+						else
+						{
+							st.addAttribute(ServerStatus.SERVER_LIST_SQUARE_BRACKET,ServerStatus.OFF);
+						}
+						if(Config.SERVER_LIST_CLOCK)
+						{
+							st.addAttribute(ServerStatus.SERVER_LIST_CLOCK,ServerStatus.ON);
+						}
+						else
+						{
+							st.addAttribute(ServerStatus.SERVER_LIST_CLOCK,ServerStatus.OFF);
+						}
+						if(Config.SERVER_LIST_TESTSERVER)
+						{
+							st.addAttribute(ServerStatus.TEST_SERVER,ServerStatus.ON);
+						}
+						else
+						{
+							st.addAttribute(ServerStatus.TEST_SERVER,ServerStatus.OFF);
+						}
+						if(Config.SERVER_GMONLY)
+						{
+							st.addAttribute(ServerStatus.SERVER_LIST_STATUS,ServerStatus.STATUS_GM_ONLY);
+						}
+						else
+						{
+							st.addAttribute(ServerStatus.SERVER_LIST_STATUS,ServerStatus.STATUS_AUTO);
+						}
+						sendPacket(st);
+						if(L2World.getInstance().getAllPlayersCount() > 0)
+						{
+							FastList<String> playerList = new FastList<String>();
+							for(L2PcInstance player : L2World.getInstance().getAllPlayers())
+							{
+								playerList.add(player.getAccountName());
+							}
+							PlayerInGame pig = new PlayerInGame(playerList);
+							sendPacket(pig);
+						}
+						break;
+					case 03:
+						PlayerAuthResponse par = new PlayerAuthResponse(decrypt);
+						String account = par.getAccount();
+						WaitingClient wcToRemove = null;
+						synchronized(_waitingClients)
+						{
+							for(WaitingClient wc : _waitingClients)
+							{
+								if(wc.account.equals(account))
+								{
+									wcToRemove = wc;
+								}
+							}
+						}
+						if(wcToRemove != null)
+						{
+							if (par.isAuthed())
+							{
+								if (Config.DEBUG)_log.info("Login accepted player "+wcToRemove.account+" waited("+(GameTimeController.getGameTicks()-wcToRemove.timestamp)+"ms)");
+								PlayerInGame pig = new PlayerInGame(par.getAccount());
+								sendPacket(pig);
+								wcToRemove.gameClient.setState(GameClientState.AUTHED);
+								wcToRemove.gameClient.setSessionId(wcToRemove.session);
+								CharSelectionInfo cl = new CharSelectionInfo(wcToRemove.account, wcToRemove.gameClient.getSessionId().playOkID1);
+								wcToRemove.gameClient.getConnection().sendPacket(cl);
+								wcToRemove.gameClient.setCharSelection(cl.getCharInfo());
+							}
+							else
+							{
+								_log.warning("session key is not correct. closing connection");
+								wcToRemove.gameClient.getConnection().sendPacket(new LoginFail(1));
+								wcToRemove.gameClient.closeNow();
+							}
+							_waitingClients.remove(wcToRemove);
+						}
+						break;
+					case 04:
+						KickPlayer kp = new KickPlayer(decrypt);
+						doKickPlayer(kp.getAccount());
+						break;
+					}
+				}
+			}
+			catch (UnknownHostException e)
+			{
+				if (Config.DEBUG) e.printStackTrace();
+			}
+			catch (IOException e)
+			{
+				_log.info("Deconnected from Login, Trying to reconnect:");
+				_log.info(e.toString());
+			}
+			finally
+			{
+				try { _loginSocket.close(); } catch (Exception e) {}
+			}
+
+			try
+			{
+				Thread.sleep(5000); // 5 seconds tempo.
+			}
+			catch(InterruptedException e)
+			{
+				//
+			}
+		}
+	}
+
+	public void addWaitingClientAndSendRequest(String acc, L2GameClient client, SessionKey key)
+	{
+		if(Config.DEBUG) System.out.println(key);
+		WaitingClient wc = new WaitingClient(acc, client, key);
+		synchronized(_waitingClients)
+		{
+			_waitingClients.add(wc);
+		}
+		PlayerAuthRequest par = new PlayerAuthRequest(acc,key);
+		try
+		{
+			sendPacket(par);
+		}
+		catch (IOException e)
+		{
+			_log.warning("Error while sending player auth request");
+			if (Config.DEBUG) e.printStackTrace();
+		}
+	}
+
+	public void removeWaitingClient(L2GameClient client)
+	{
+		WaitingClient toRemove = null;
+		synchronized(_waitingClients)
+		{
+			for(WaitingClient c :_waitingClients)
+			{
+				if(c.gameClient == client)
+				{
+					toRemove = c;
+				}
+			}
+			if(toRemove != null)
+				_waitingClients.remove(toRemove);
+		}
+	}
+
+	public void sendLogout(String account)
+	{
+		PlayerLogout pl = new PlayerLogout(account);
+		try
+		{
+			sendPacket(pl);
+		}
+		catch (IOException e)
+		{
+			_log.warning("Error while sending logout packet to login");
+			if (Config.DEBUG) e.printStackTrace();
+		}
+	}
+
+	public void addGameServerLogin(String account, L2GameClient client)
+	{
+		_accountsInGameServer.put(account, client);
+	}
+
+	public void sendAccessLevel(String account, int level)
+	{
+		ChangeAccessLevel cal = new ChangeAccessLevel(account, level);
+		try
+		{
+			sendPacket(cal);
+		}
+		catch (IOException e)
+		{
+			if (Config.DEBUG)
+				e.printStackTrace();
+		}
+	}
+
+	private String hexToString(byte[] hex)
+	{
+		return new BigInteger(hex).toString(16);
+	}
+
+	public void doKickPlayer(String account)
+	{
+		if(_accountsInGameServer.get(account) != null)
+		{
+			_accountsInGameServer.get(account).closeNow();
+			LoginServerThread.getInstance().sendLogout(account);
+		}
+	}
+
+	public static byte[] generateHex(int size)
+	{
+		byte [] array = new byte[size];
+		Rnd.nextBytes(array);
+		if (Config.DEBUG)_log.fine("Generated random String:  \""+array+"\"");
+		return array;
+	}
+
+	/**
+	 * @param sl
+	 * @throws IOException
+	 */
+	private void sendPacket(GameServerBasePacket sl) throws IOException
+	{
+		byte[] data = sl.getContent();
+		NewCrypt.appendChecksum(data);
+		if (Config.DEBUG) _log.finest("[S]\n"+Util.printData(data));
+		data = _blowfish.crypt(data);
+
+		int len = data.length+2;
+		synchronized (_out) //avoids tow threads writing in the mean time
+		{
+			_out.write(len & 0xff);
+			_out.write(len >> 8 &0xff);
+			_out.write(data);
+			_out.flush();
+		}
+	}
+
+	/**
+	 * @param maxPlayer The maxPlayer to set.
+	 */
+	public void setMaxPlayer(int maxPlayer)
+	{
+		sendServerStatus(ServerStatus.MAX_PLAYERS,maxPlayer);
+		_maxPlayer = maxPlayer;
+	}
+
+	/**
+	 * @return Returns the maxPlayer.
+	 */
+	public int getMaxPlayer()
+	{
+		return _maxPlayer;
+	}
+
+	/**
+	 * @param server_gm_only
+	 */
+	public void sendServerStatus(int id, int value)
+	{
+		ServerStatus ss = new ServerStatus();
+		ss.addAttribute(id,value);
+		try
+		{
+			sendPacket(ss);
+		}
+		catch (IOException e)
+		{
+			if (Config.DEBUG) e.printStackTrace();
+		}
+	}
+
+	/**
+	 * @return
+	 */
+	public String getStatusString()
+	{
+		return ServerStatus.STATUS_STRING[_status];
+	}
+
+	/**
+	 * @return
+	 */
+	public boolean isClockShown()
+	{
+		return Config.SERVER_LIST_CLOCK;
+	}
+
+	/**
+	 * @return
+	 */
+	public boolean isBracketShown()
+	{
+		return Config.SERVER_LIST_BRACKET;
+	}
+
+	/**
+	 * @return Returns the serverName.
+	 */
+	public String getServerName()
+	{
+		return _serverName;
+	}
+
+	public void setServerStatus(int status)
+	{
+		switch(status)
+		{
+		case ServerStatus.STATUS_AUTO:
+			sendServerStatus(ServerStatus.SERVER_LIST_STATUS,ServerStatus.STATUS_AUTO);
+			_status = status;
+			break;
+		case ServerStatus.STATUS_DOWN:
+			sendServerStatus(ServerStatus.SERVER_LIST_STATUS,ServerStatus.STATUS_DOWN);
+			_status = status;
+			break;
+		case ServerStatus.STATUS_FULL:
+			sendServerStatus(ServerStatus.SERVER_LIST_STATUS,ServerStatus.STATUS_FULL);
+			_status = status;
+			break;
+		case ServerStatus.STATUS_GM_ONLY:
+			sendServerStatus(ServerStatus.SERVER_LIST_STATUS,ServerStatus.STATUS_GM_ONLY);
+			_status = status;
+			break;
+		case ServerStatus.STATUS_GOOD:
+			sendServerStatus(ServerStatus.SERVER_LIST_STATUS,ServerStatus.STATUS_GOOD);
+			_status = status;
+			break;
+		case ServerStatus.STATUS_NORMAL:
+			sendServerStatus(ServerStatus.SERVER_LIST_STATUS,ServerStatus.STATUS_NORMAL);
+			_status = status;
+			break;
+		default:
+			throw new IllegalArgumentException("Status does not exists:"+status);
+		}
+	}
+
+	public static class SessionKey
+	{
+		public int playOkID1;
+		public int playOkID2;
+		public int loginOkID1;
+		public int loginOkID2;
+
+		public SessionKey(int loginOK1, int loginOK2, int playOK1, int playOK2)
+		{
+			playOkID1 = playOK1;
+			playOkID2 = playOK2;
+			loginOkID1 = loginOK1;
+			loginOkID2 = loginOK2;
+		}
+
+		@Override
+		public String toString()
+		{
+			return "PlayOk: "+playOkID1+" "+playOkID2+" LoginOk:"+loginOkID1+" "+loginOkID2;
+		}
+	}
+
+	private class WaitingClient
+	{
+		public int timestamp;
+		public String account;
+		public L2GameClient gameClient;
+		public SessionKey session;
+
+		public WaitingClient(String acc, L2GameClient client, SessionKey key)
+		{
+			account = acc;
+			timestamp = GameTimeController.getGameTicks();
+			gameClient = client;
+			session = key;
+		}
+	}
+}

+ 150 - 0
L2_GameServer_T1/java/net/sf/l2j/gameserver/MonsterRace.java

@@ -0,0 +1,150 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+package net.sf.l2j.gameserver;
+
+import java.lang.reflect.Constructor;
+
+import net.sf.l2j.gameserver.datatables.NpcTable;
+import net.sf.l2j.gameserver.idfactory.IdFactory;
+import net.sf.l2j.gameserver.model.actor.instance.L2NpcInstance;
+import net.sf.l2j.gameserver.templates.L2NpcTemplate;
+import net.sf.l2j.util.Rnd;
+
+
+public class MonsterRace
+{
+    private L2NpcInstance[] _monsters;
+    private static MonsterRace _instance;
+    private Constructor<?> _constructor;
+    private int[][] _speeds;
+    private int[] _first, _second;
+
+    private MonsterRace()
+    {
+        _monsters    = new L2NpcInstance[8];
+        _speeds      = new int[8][20];
+        _first       = new int[2];
+        _second      = new int[2];
+    }
+
+    public static MonsterRace getInstance()
+    {
+        if (_instance == null)
+        {
+            _instance = new MonsterRace();
+        }
+
+        return _instance;
+    }
+
+    public void newRace()
+    {
+        int random = 0;
+
+        for (int i=0; i<8; i++)
+        {
+            int id = 31003;
+            random = Rnd.get(24);
+            while(true)
+            {
+                for (int j=i-1; j>=0; j--)
+                {
+                    if (_monsters[j].getTemplate().npcId == (id + random))
+                    {
+                        random = Rnd.get(24);
+                        continue;
+                    }
+                }
+                break;
+            }
+            try
+            {
+                L2NpcTemplate template = NpcTable.getInstance().getTemplate(id+random);
+                _constructor = Class.forName("net.sf.l2j.gameserver.model.actor.instance." + template.type + "Instance").getConstructors()[0];
+                int objectId = IdFactory.getInstance().getNextId();
+                _monsters[i] = (L2NpcInstance)_constructor.newInstance(objectId, template);
+            }
+            catch (Exception e)
+            {
+                e.printStackTrace();
+            }
+            //System.out.println("Monster "+i+" is id: "+(id+random));
+        }
+        newSpeeds();
+    }
+
+    public void newSpeeds()
+    {
+        _speeds = new int[8][20];
+        int total = 0;
+        _first[1]=0;_second[1]=0;
+        for (int i=0; i<8; i++)
+        {
+            total = 0;
+            for (int j=0; j<20 ;j++)
+            {
+                if (j == 19)
+                    _speeds[i][j] = 100;
+                else
+                    _speeds[i][j] = Rnd.get(60) + 65;
+                total += _speeds[i][j];
+            }
+            if (total >= _first[1])
+            {
+                _second[0] = _first[0];
+                _second[1] = _first[1];
+                _first[0] = 8 - i;
+                _first[1] = total;
+            }
+            else if (total >= _second[1])
+            {
+                _second[0] = 8 - i;
+                _second[1] = total;
+            }
+        }
+    }
+
+    /**
+     * @return Returns the monsters.
+     */
+    public L2NpcInstance[] getMonsters()
+    {
+        return _monsters;
+    }
+
+    /**
+     * @return Returns the speeds.
+     */
+    public int[][] getSpeeds()
+    {
+        return _speeds;
+    }
+
+    public int getFirstPlace()
+    {
+        return _first[0];
+    }
+
+    public int getSecondPlace()
+    {
+        return _second[0];
+    }
+
+
+}

+ 1997 - 0
L2_GameServer_T1/java/net/sf/l2j/gameserver/Olympiad.java

@@ -0,0 +1,1997 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/**
+ * @author godson
+ */
+
+package net.sf.l2j.gameserver;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Calendar;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.concurrent.ScheduledFuture;
+import java.util.logging.Logger;
+
+import javolution.util.FastList;
+import javolution.util.FastMap;
+import net.sf.l2j.Config;
+import net.sf.l2j.L2DatabaseFactory;
+import net.sf.l2j.gameserver.datatables.HeroSkillTable;
+import net.sf.l2j.gameserver.datatables.SkillTable;
+import net.sf.l2j.gameserver.instancemanager.OlympiadStadiaManager;
+import net.sf.l2j.gameserver.model.Inventory;
+import net.sf.l2j.gameserver.model.L2ItemInstance;
+import net.sf.l2j.gameserver.model.L2Party;
+import net.sf.l2j.gameserver.model.L2Skill;
+import net.sf.l2j.gameserver.model.L2Summon;
+import net.sf.l2j.gameserver.model.L2World;
+import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
+import net.sf.l2j.gameserver.model.actor.instance.L2PetInstance;
+import net.sf.l2j.gameserver.model.entity.Hero;
+import net.sf.l2j.gameserver.network.SystemMessageId;
+import net.sf.l2j.gameserver.serverpackets.ExOlympiadUserInfoSpectator;
+import net.sf.l2j.gameserver.serverpackets.InventoryUpdate;
+import net.sf.l2j.gameserver.serverpackets.MagicSkillUse;
+import net.sf.l2j.gameserver.serverpackets.SystemMessage;
+import net.sf.l2j.gameserver.templates.StatsSet;
+import net.sf.l2j.util.Rnd;
+
+public class Olympiad
+{
+	protected static final Logger _log = Logger.getLogger(Olympiad.class.getName());
+
+    private static Olympiad _instance;
+
+    protected static Map<Integer, StatsSet> _nobles;
+    protected static List<StatsSet> _heroesToBe;
+    protected static List<L2PcInstance> _nonClassBasedRegisters;
+    protected static Map<Integer, List<L2PcInstance>> _classBasedRegisters;
+
+    private static final String OLYMPIAD_DATA_FILE = "config/olympiad.properties";
+    public static final String OLYMPIAD_HTML_FILE = "data/html/olympiad/";
+    private static final String OLYMPIAD_LOAD_NOBLES = "SELECT * from olympiad_nobles";
+    private static final String OLYMPIAD_SAVE_NOBLES = "INSERT INTO olympiad_nobles " +
+            "values (?,?,?,?,?)";
+    private static final String OLYMPIAD_UPDATE_NOBLES = "UPDATE olympiad_nobles set " +
+            "olympiad_points = ?, competitions_done = ? where char_id = ?";
+    private static final String OLYMPIAD_GET_HEROS = "SELECT char_id, char_name from " +
+    		"olympiad_nobles where class_id = ? and competitions_done >= 9 order by " +
+    		"olympiad_points desc, competitions_done desc";
+    private static final String GET_EACH_CLASS_LEADER = "SELECT char_name from " +
+    		"olympiad_nobles where class_id = ? order by olympiad_points desc, " +
+    		"competitions_done desc";
+    private static final String OLYMPIAD_DELETE_ALL = "DELETE from olympiad_nobles";
+
+    private static final int COMP_START = Config.ALT_OLY_START_TIME; // 6PM
+    private static final int COMP_MIN = Config.ALT_OLY_MIN; // 00 mins
+    private static final long COMP_PERIOD = Config.ALT_OLY_CPERIOD; // 6 hours
+    protected static final long BATTLE_PERIOD = Config.ALT_OLY_BATTLE; // 6 mins
+    protected static final long BATTLE_WAIT = Config.ALT_OLY_BWAIT; // 10mins
+    protected static final long INITIAL_WAIT = Config.ALT_OLY_IWAIT;  // 5mins
+    protected static final long WEEKLY_PERIOD = Config.ALT_OLY_WPERIOD; // 1 week
+    protected static final long VALIDATION_PERIOD = Config.ALT_OLY_VPERIOD; // 24 hours
+
+    /* FOR TESTING
+    private static final int COMP_START = 8; // 1PM - 2PM
+    private static final int COMP_MIN = 15; // 20mins
+    private static final long COMP_PERIOD = 7200000; // 2hours
+    private static final long BATTLE_PERIOD = 180000; // 3mins
+    private static final long BATTLE_WAIT = 600000; // 10mins
+    private static final long INITIAL_WAIT = 300000;  // 5mins
+    private static final long WEEKLY_PERIOD = 7200000; // 2 hours
+    private static final long VALIDATION_PERIOD = 3600000; // 1 hour */
+
+    private static final int COLLISIEUMS = 11;  // 22 in all, 11 each for (Classed and NonClassed)
+
+    private static final int DEFAULT_POINTS = 18;
+    protected static final int WEEKLY_POINTS = 3;
+
+    public static final String CHAR_ID = "char_id";
+    public static final String CLASS_ID = "class_id";
+    public static final String CHAR_NAME = "char_name";
+    public static final String POINTS = "olympiad_points";
+    public static final String COMP_DONE = "competitions_done";
+
+    protected long _olympiadEnd;
+    protected long _validationEnd;
+    protected int _period;
+    protected long _nextWeeklyChange;
+    protected int _currentCycle;
+    private long _compEnd;
+    private Calendar _compStart;
+    protected static boolean _inCompPeriod;
+    protected static boolean _isOlympiadEnd;
+    protected static boolean _compStarted;
+    protected static boolean _battleStarted;
+    protected ScheduledFuture<?> _scheduledCompStart;
+    protected ScheduledFuture<?> _scheduledCompEnd;
+    protected ScheduledFuture<?> _scheduledOlympiadEnd;
+    protected ScheduledFuture<?> _scheduledManagerTask;
+    protected ScheduledFuture<?> _scheduledWeeklyTask;
+    protected ScheduledFuture<?> _scheduledValdationTask;
+
+    protected static final int[][] STADIUMS =
+    {
+     {-20814, -21189, -3030},
+     {-120324, -225077, -3331},
+     {-102495, -209023, -3331},
+     {-120156, -207378, -3331},
+     {-87628, -225021, -3331},
+     {-81705, -213209, -3331},
+     {-87593, -207339, -3331},
+     {-93709, -218304, -3331},
+     {-77157, -218608, -3331},
+     {-69682, -209027, -3331},
+     {-76887, -201256, -3331},
+     {-109985, -218701, -3331},
+     {-126367, -218228, -3331},
+     {-109629, -201292, -3331},
+     {-87523, -240169, -3331},
+     {-81748, -245950, -3331},
+     {-77123, -251473, -3331},
+     {-69778, -241801, -3331},
+     {-76754, -234014, -3331},
+     {-93742, -251032, -3331},
+     {-87466, -257752, -3331},
+     {-114413, -213241, -3331}
+    };
+
+    private static enum COMP_TYPE
+    {
+    	CLASSED,
+    	NON_CLASSED
+    }
+
+    protected static OlympiadManager _manager;
+
+    public static Olympiad getInstance()
+    {
+        if (_instance == null)
+            _instance = new Olympiad();
+        return _instance;
+    }
+
+    public Olympiad()
+    {
+    	try
+        {
+            load();
+        }
+        catch(IOException e)
+        {
+            e.printStackTrace();
+        }
+        catch(SQLException s)
+        {
+            s.printStackTrace();
+        }
+
+        if (_period == 0) init();
+    }
+
+    private void load() throws IOException, SQLException
+    {
+        _nobles = new FastMap<Integer, StatsSet>();
+
+        Properties OlympiadProperties = new Properties();
+        InputStream is =  new FileInputStream(new File("./" + OLYMPIAD_DATA_FILE));
+        OlympiadProperties.load(is);
+        is.close();
+
+        _currentCycle = Integer.parseInt(OlympiadProperties.getProperty("CurrentCycle", "1"));
+        _period = Integer.parseInt(OlympiadProperties.getProperty("Period", "0"));
+        _olympiadEnd = Long.parseLong(OlympiadProperties.getProperty("OlympiadEnd", "0"));
+        _validationEnd = Long.parseLong(OlympiadProperties.getProperty("ValdationEnd", "0"));
+        _nextWeeklyChange = Long.parseLong(OlympiadProperties.getProperty("NextWeeklyChange", "0"));
+
+        switch(_period)
+        {
+            case 0:
+                if (_olympiadEnd == 0 || _olympiadEnd < Calendar.getInstance().getTimeInMillis())
+                    setNewOlympiadEnd();
+                else
+                    _isOlympiadEnd = false;
+                break;
+            case 1:
+                if (_validationEnd > Calendar.getInstance().getTimeInMillis())
+                {
+                    _isOlympiadEnd = true;
+
+                    _scheduledValdationTask  = ThreadPoolManager.getInstance().scheduleGeneral(new Runnable() {
+                        public void run()
+                        {
+                            _period = 0;
+                            _currentCycle++;
+                            deleteNobles();
+                            setNewOlympiadEnd();
+                            init();
+                        }
+                    }, getMillisToValidationEnd());
+                }
+                else
+                {
+                    _currentCycle++;
+                    _period = 0;
+                    deleteNobles();
+                    setNewOlympiadEnd();
+                }
+                break;
+                default:
+                    _log.warning("Olympiad System: Omg something went wrong in loading!! Period = " + _period);
+                return;
+        }
+
+        try
+        {
+            Connection con = L2DatabaseFactory.getInstance().getConnection();
+            PreparedStatement statement = con.prepareStatement(OLYMPIAD_LOAD_NOBLES);
+            ResultSet rset = statement.executeQuery();
+
+            while(rset.next())
+            {
+                StatsSet statDat = new StatsSet();
+                int charId = rset.getInt(CHAR_ID);
+                statDat.set(CLASS_ID, rset.getInt(CLASS_ID));
+                statDat.set(CHAR_NAME, rset.getString(CHAR_NAME));
+                statDat.set(POINTS, rset.getInt(POINTS));
+                statDat.set(COMP_DONE, rset.getInt(COMP_DONE));
+                statDat.set("to_save", false);
+
+                _nobles.put(charId, statDat);
+            }
+
+            rset.close();
+            statement.close();
+            con.close();
+        }
+        catch(Exception e)
+        {
+            e.printStackTrace();
+        }
+
+        synchronized(this)
+        {
+            _log.info("Olympiad System: Loading Olympiad System....");
+            if (_period == 0)
+                _log.info("Olympiad System: Currently in Olympiad Period");
+            else
+                _log.info("Olympiad System: Currently in Validation Period");
+
+            _log.info("Olympiad System: Period Ends....");
+
+            long milliToEnd;
+            if (_period == 0)
+                milliToEnd = getMillisToOlympiadEnd();
+            else
+                milliToEnd = getMillisToValidationEnd();
+
+            double numSecs = (milliToEnd / 1000) % 60;
+            double countDown = ((milliToEnd / 1000) - numSecs) / 60;
+            int numMins = (int) Math.floor(countDown % 60);
+            countDown = (countDown - numMins) / 60;
+            int numHours = (int) Math.floor(countDown % 24);
+            int numDays = (int) Math.floor((countDown - numHours) / 24);
+
+            _log.info("Olympiad System: In " + numDays + " days, " + numHours
+                + " hours and " + numMins + " mins.");
+
+            if (_period == 0)
+            {
+                _log.info("Olympiad System: Next Weekly Change is in....");
+
+                milliToEnd = getMillisToWeekChange();
+
+                double numSecs2 = (milliToEnd / 1000) % 60;
+                double countDown2 = ((milliToEnd / 1000) - numSecs2) / 60;
+                int numMins2 = (int) Math.floor(countDown2 % 60);
+                countDown2 = (countDown2 - numMins2) / 60;
+                int numHours2 = (int) Math.floor(countDown2 % 24);
+                int numDays2 = (int) Math.floor((countDown2 - numHours2) / 24);
+
+                _log.info("Olympiad System: " + numDays2 + " days, " + numHours2
+                    + " hours and " + numMins2 + " mins.");
+            }
+        }
+
+        _log.info("Olympiad System: Loaded " + _nobles.size() + " Nobles");
+
+    }
+
+    protected void init()
+    {
+        if (_period == 1)
+            return;
+    	_nonClassBasedRegisters = new FastList<L2PcInstance>();
+        _classBasedRegisters = new FastMap<Integer, List<L2PcInstance>>();
+
+        _compStart = Calendar.getInstance();
+        _compStart.set(Calendar.HOUR_OF_DAY, COMP_START);
+        _compStart.set(Calendar.MINUTE, COMP_MIN);
+        _compEnd = _compStart.getTimeInMillis() + COMP_PERIOD;
+
+    	_scheduledOlympiadEnd = ThreadPoolManager.getInstance().scheduleGeneral(new Runnable(){
+    		public void run()
+    		{
+                SystemMessage sm = new SystemMessage(SystemMessageId.OLYMPIAD_PERIOD_S1_HAS_ENDED);
+                sm.addNumber(_currentCycle);
+
+                Announcements.getInstance().announceToAll(sm);
+                Announcements.getInstance().announceToAll("Olympiad Validation Period has began");
+
+    			_isOlympiadEnd = true;
+                if (_scheduledManagerTask != null)
+                    _scheduledManagerTask.cancel(true);
+                if (_scheduledWeeklyTask != null)
+                    _scheduledWeeklyTask.cancel(true);
+
+                Calendar validationEnd = Calendar.getInstance();
+                _validationEnd = validationEnd.getTimeInMillis() + VALIDATION_PERIOD;
+
+                saveNobleData();
+
+                _period = 1;
+
+                sortHerosToBe();
+
+                giveHeroBonus();
+
+                Hero.getInstance().computeNewHeroes(_heroesToBe);
+
+                try {
+                    save();
+                }
+                catch (Exception e) {
+                    _log.warning("Olympiad System: Failed to save Olympiad configuration: " + e);
+                }
+
+                _scheduledValdationTask  = ThreadPoolManager.getInstance().scheduleGeneral(new Runnable() {
+                    public void run()
+                    {
+                        Announcements.getInstance().announceToAll("Olympiad Validation Period has ended");
+                        _period = 0;
+                        _currentCycle++;
+                        deleteNobles();
+                        setNewOlympiadEnd();
+                        init();
+                    }
+                }, getMillisToValidationEnd());
+    		}
+    	}, getMillisToOlympiadEnd());
+
+        updateCompStatus();
+    	scheduleWeeklyChange();
+    }
+
+    public boolean registerNoble(L2PcInstance noble, boolean classBased)
+    {
+        SystemMessage sm;
+
+        if (_compStarted)
+        {
+            noble.sendMessage("Cant Register whilst competition is under way");
+            return false;
+        }
+
+        if (!_inCompPeriod)
+        {
+            sm = new SystemMessage(SystemMessageId.THE_OLYMPIAD_GAME_IS_NOT_CURRENTLY_IN_PROGRESS);
+            noble.sendPacket(sm);
+            return false;
+        }
+
+        if (noble.isCursedWeaponEquiped())
+        {
+        	noble.sendMessage("You can't participate to Olympiad while holding a cursed weapon.");
+        	return false;
+        }
+
+        if (!noble.isNoble())
+        {
+            sm = new SystemMessage(SystemMessageId.ONLY_NOBLESS_CAN_PARTICIPATE_IN_THE_OLYMPIAD);
+            noble.sendPacket(sm);
+        	return false;
+        }
+
+        if (noble.getBaseClass() != noble.getClassId().getId())
+        {
+            sm = new SystemMessage(SystemMessageId.YOU_CANT_JOIN_THE_OLYMPIAD_WITH_A_SUB_JOB_CHARACTER);
+            noble.sendPacket(sm);
+        	return false;
+        }
+
+        if (!_nobles.containsKey(noble.getObjectId()))
+        {
+        	StatsSet statDat = new StatsSet();
+        	statDat.set(CLASS_ID, noble.getClassId().getId());
+        	statDat.set(CHAR_NAME, noble.getName());
+            statDat.set(POINTS, DEFAULT_POINTS);
+            statDat.set(COMP_DONE, 0);
+            statDat.set("to_save", true);
+
+            _nobles.put(noble.getObjectId(), statDat);
+        }
+
+        if (_classBasedRegisters.containsKey(noble.getClassId().getId()))
+        {
+            List<L2PcInstance> classed = _classBasedRegisters.get(noble.getClassId().getId());
+            for (L2PcInstance partecipant: classed)
+            {
+            	if (partecipant.getObjectId()==noble.getObjectId())
+            		{
+            		sm = new SystemMessage(SystemMessageId.YOU_ARE_ALREADY_ON_THE_WAITING_LIST_TO_PARTICIPATE_IN_THE_GAME_FOR_YOUR_CLASS);
+            		noble.sendPacket(sm);
+            		return false;
+            		}
+            }
+        }
+
+        for (L2PcInstance partecipant: _nonClassBasedRegisters)
+        {
+        	if (partecipant.getObjectId()==noble.getObjectId())
+        		{
+        		sm = new SystemMessage(SystemMessageId.YOU_ARE_ALREADY_ON_THE_WAITING_LIST_FOR_ALL_CLASSES_WAITING_TO_PARTICIPATE_IN_THE_GAME);
+        		noble.sendPacket(sm);
+        		return false;
+        		}
+        }
+
+        if (getNoblePoints(noble.getObjectId()) < 3)
+        {
+            noble.sendMessage("Cant register when you have less than 3 points");
+            return false;
+        }
+
+        if (classBased)
+        {
+            if (_classBasedRegisters.containsKey(noble.getClassId().getId()))
+            {
+                List<L2PcInstance> classed = _classBasedRegisters.get(noble.getClassId().getId());
+                classed.add(noble);
+
+                _classBasedRegisters.remove(noble.getClassId().getId());
+                _classBasedRegisters.put(noble.getClassId().getId(), classed);
+
+                sm = new SystemMessage(SystemMessageId.YOU_HAVE_BEEN_REGISTERED_IN_A_WAITING_LIST_OF_CLASSIFIED_GAMES);
+                noble.sendPacket(sm);
+            }
+            else
+            {
+                List<L2PcInstance> classed = new FastList<L2PcInstance>();
+                classed.add(noble);
+
+                _classBasedRegisters.put(noble.getClassId().getId(), classed);
+
+                sm = new SystemMessage(SystemMessageId.YOU_HAVE_BEEN_REGISTERED_IN_A_WAITING_LIST_OF_CLASSIFIED_GAMES);
+                noble.sendPacket(sm);
+
+            }
+        }
+        else
+        {
+        	_nonClassBasedRegisters.add(noble);
+            sm = new SystemMessage(SystemMessageId.YOU_HAVE_BEEN_REGISTERED_IN_A_WAITING_LIST_OF_NO_CLASS_GAMES);
+            noble.sendPacket(sm);
+        }
+
+        return true;
+    }
+
+    public boolean isRegistered(L2PcInstance noble)
+    {
+    	if(_nonClassBasedRegisters == null) return false;
+    	if(_classBasedRegisters == null) return false;
+    	if (!_nonClassBasedRegisters.contains(noble))
+        {
+        	if (!_classBasedRegisters.containsKey(noble.getClassId().getId()))
+            {
+        		return false;
+            }
+            else
+            {
+                List<L2PcInstance> classed = _classBasedRegisters.get(noble.getClassId().getId());
+                if (!classed.contains(noble))
+                {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    public boolean unRegisterNoble(L2PcInstance noble)
+    {
+        SystemMessage sm;
+
+    	if (_compStarted)
+    	{
+    		noble.sendMessage("Cant Unregister whilst competition is under way");
+    		return false;
+    	}
+
+        if (!_inCompPeriod)
+        {
+            sm = new SystemMessage(SystemMessageId.THE_OLYMPIAD_GAME_IS_NOT_CURRENTLY_IN_PROGRESS);
+            noble.sendPacket(sm);
+            return false;
+        }
+
+    	if (!noble.isNoble())
+        {
+            sm = new SystemMessage(SystemMessageId.ONLY_NOBLESS_CAN_PARTICIPATE_IN_THE_OLYMPIAD);
+            noble.sendPacket(sm);
+            return false;
+        }
+
+    	if (!isRegistered(noble))
+    	{
+    		sm = new SystemMessage(SystemMessageId.YOU_HAVE_NOT_BEEN_REGISTERED_IN_A_WAITING_LIST_OF_A_GAME);
+            noble.sendPacket(sm);
+            return false;
+        }
+
+        if (_nonClassBasedRegisters.contains(noble))
+            _nonClassBasedRegisters.remove(noble);
+        else
+        {
+            List<L2PcInstance> classed = _classBasedRegisters.get(noble.getClassId().getId());
+            classed.remove(noble);
+
+            _classBasedRegisters.remove(noble.getClassId().getId());
+            _classBasedRegisters.put(noble.getClassId().getId(), classed);
+        }
+
+        sm = new SystemMessage(SystemMessageId.YOU_HAVE_BEEN_DELETED_FROM_THE_WAITING_LIST_OF_A_GAME);
+        noble.sendPacket(sm);
+
+    	return true;
+    }
+
+    private void updateCompStatus()
+    {
+    	_compStarted = false;
+
+        synchronized(this)
+        {
+            long milliToStart = getMillisToCompBegin();
+
+            double numSecs = (milliToStart / 1000) % 60;
+            double countDown = ((milliToStart / 1000) - numSecs) / 60;
+            int numMins = (int) Math.floor(countDown % 60);
+            countDown = (countDown - numMins) / 60;
+            int numHours = (int) Math.floor(countDown % 24);
+            int numDays = (int) Math.floor((countDown - numHours) / 24);
+
+            _log.info("Olympiad System: Competition Period Starts in "
+                      + numDays + " days, " + numHours
+                + " hours and " + numMins + " mins.");
+
+            _log.info("Olympiad System: Event starts/started : " + _compStart.getTime());
+        }
+
+    	_scheduledCompStart = ThreadPoolManager.getInstance().scheduleGeneral(new Runnable(){
+    		public void run()
+    		{
+                if (isOlympiadEnd())
+                    return;
+
+    			_inCompPeriod = true;
+    			OlympiadManager om = new OlympiadManager();
+
+                Announcements.getInstance().announceToAll(new SystemMessage(SystemMessageId.THE_OLYMPIAD_GAME_HAS_STARTED));
+                _log.info("Olympiad System: Olympiad Game Started");
+
+    			_scheduledManagerTask = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(om, INITIAL_WAIT, BATTLE_WAIT);
+    			_scheduledCompEnd = ThreadPoolManager.getInstance().scheduleGeneral(new Runnable(){
+    				public void run()
+    				{
+                        if (isOlympiadEnd())
+                            return;
+                        _scheduledManagerTask.cancel(true);
+    					_inCompPeriod = false;
+                        Announcements.getInstance().announceToAll(new SystemMessage(SystemMessageId.THE_OLYMPIAD_GAME_HAS_ENDED));
+                        _log.info("Olympiad System: Olympiad Game Ended");
+
+                        try {
+                            save();
+                        }
+                        catch (Exception e) {
+                            _log.warning("Olympiad System: Failed to save Olympiad configuration: " + e);
+                        }
+
+                        init();
+    				}
+    				}, getMillisToCompEnd());
+    		}
+    		}, getMillisToCompBegin());
+    }
+
+    private long getMillisToOlympiadEnd()
+    {
+        //if (_olympiadEnd > Calendar.getInstance().getTimeInMillis())
+            return (_olympiadEnd - Calendar.getInstance().getTimeInMillis());
+        //return 10L;
+    }
+
+    public void manualSelectHeroes()
+    {
+        SystemMessage sm = new SystemMessage(SystemMessageId.OLYMPIAD_PERIOD_S1_HAS_ENDED);
+        sm.addNumber(_currentCycle);
+
+        Announcements.getInstance().announceToAll(sm);
+        Announcements.getInstance().announceToAll("Olympiad Validation Period has began");
+
+        _isOlympiadEnd = true;
+        if (_scheduledManagerTask != null)
+            _scheduledManagerTask.cancel(true);
+        if (_scheduledWeeklyTask != null)
+            _scheduledWeeklyTask.cancel(true);
+        if(_scheduledOlympiadEnd != null)
+            _scheduledOlympiadEnd.cancel(true);
+
+        Calendar validationEnd = Calendar.getInstance();
+        _validationEnd = validationEnd.getTimeInMillis() + VALIDATION_PERIOD;
+
+        saveNobleData();
+
+        _period = 1;
+
+        sortHerosToBe();
+
+        giveHeroBonus();
+
+        Hero.getInstance().computeNewHeroes(_heroesToBe);
+
+        try {
+            save();
+        }
+        catch (Exception e) {
+            _log.warning("Olympiad System: Failed to save Olympiad configuration: " + e);
+        }
+
+        _scheduledValdationTask  = ThreadPoolManager.getInstance().scheduleGeneral(new Runnable() {
+            public void run()
+            {
+                Announcements.getInstance().announceToAll("Olympiad Validation Period has ended");
+                _period = 0;
+                _currentCycle++;
+                deleteNobles();
+                setNewOlympiadEnd();
+                init();
+            }
+        }, getMillisToValidationEnd());
+    }
+
+    protected long getMillisToValidationEnd()
+    {
+        if (_validationEnd > Calendar.getInstance().getTimeInMillis())
+            return (_validationEnd - Calendar.getInstance().getTimeInMillis());
+        return 10L;
+    }
+
+    public boolean isOlympiadEnd()
+    {
+    	return _isOlympiadEnd;
+    }
+
+    protected void setNewOlympiadEnd()
+    {
+        SystemMessage sm = new SystemMessage(SystemMessageId.OLYMPIAD_PERIOD_S1_HAS_STARTED);
+        sm.addNumber(_currentCycle);
+
+        Announcements.getInstance().announceToAll(sm);
+
+        Calendar currentTime = Calendar.getInstance();
+        currentTime.add(Calendar.MONTH, 1);
+        currentTime.set(Calendar.DAY_OF_MONTH, 1);
+        currentTime.set(Calendar.AM_PM, Calendar.AM);
+        currentTime.set(Calendar.HOUR, 12);
+        currentTime.set(Calendar.MINUTE, 0);
+        currentTime.set(Calendar.SECOND, 0);
+        _olympiadEnd = currentTime.getTimeInMillis();
+
+        Calendar nextChange = Calendar.getInstance();
+        _nextWeeklyChange = nextChange.getTimeInMillis() + WEEKLY_PERIOD;
+
+        _isOlympiadEnd = false;
+    }
+
+    public boolean inCompPeriod()
+    {
+    	return _inCompPeriod;
+    }
+
+    private long getMillisToCompBegin()
+    {
+        if (_compStart.getTimeInMillis() < Calendar.getInstance().getTimeInMillis() &&
+                _compEnd > Calendar.getInstance().getTimeInMillis())
+            return 10L;
+
+        if (_compStart.getTimeInMillis() > Calendar.getInstance().getTimeInMillis())
+            return (_compStart.getTimeInMillis() - Calendar.getInstance().getTimeInMillis());
+
+        return setNewCompBegin();
+    }
+
+    private long setNewCompBegin()
+    {
+        _compStart = Calendar.getInstance();
+        _compStart.set(Calendar.HOUR_OF_DAY, COMP_START);
+        _compStart.set(Calendar.MINUTE, COMP_MIN);
+        _compStart.add(Calendar.HOUR_OF_DAY, 24);
+        _compEnd = _compStart.getTimeInMillis() + COMP_PERIOD;
+
+        _log.info("Olympiad System: New Schedule @ " + _compStart.getTime());
+
+        return (_compStart.getTimeInMillis() - Calendar.getInstance().getTimeInMillis());
+    }
+
+    protected long getMillisToCompEnd()
+    {
+        //if (_compEnd > Calendar.getInstance().getTimeInMillis())
+            return (_compEnd - Calendar.getInstance().getTimeInMillis());
+        //return 10L;
+    }
+
+    private long getMillisToWeekChange()
+    {
+        if (_nextWeeklyChange > Calendar.getInstance().getTimeInMillis())
+            return (_nextWeeklyChange - Calendar.getInstance().getTimeInMillis());
+        return 10L;
+    }
+
+    private void scheduleWeeklyChange()
+    {
+    	_scheduledWeeklyTask = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(new Runnable() {
+    		public void run()
+    		{
+    			addWeeklyPoints();
+                _log.info("Olympiad System: Added weekly points to nobles");
+
+                Calendar nextChange = Calendar.getInstance();
+                _nextWeeklyChange = nextChange.getTimeInMillis() + WEEKLY_PERIOD;
+    		}
+    	}, getMillisToWeekChange(), WEEKLY_PERIOD);
+    }
+
+    protected synchronized void addWeeklyPoints()
+    {
+        if (_period == 1)
+            return;
+
+        for (Integer nobleId : _nobles.keySet())
+        {
+            StatsSet nobleInfo = _nobles.get(nobleId);
+            int currentPoints = nobleInfo.getInteger(POINTS);
+            currentPoints += WEEKLY_POINTS;
+            nobleInfo.set(POINTS, currentPoints);
+
+            _nobles.remove(nobleId);
+            _nobles.put(nobleId, nobleInfo);
+        }
+    }
+
+    public String[] getMatchList()
+    {
+    	return (_manager == null)? null : _manager.getAllTitles();
+    }
+
+    public int getCurrentCycle()
+    {
+        return _currentCycle;
+    }
+
+    public void addSpectator(int id, L2PcInstance spectator)
+    {
+        if (_manager == null || (_manager.getOlympiadInstance(id) == null) || !_battleStarted)
+        {
+            spectator.sendPacket(new SystemMessage(SystemMessageId.THE_OLYMPIAD_GAME_IS_NOT_CURRENTLY_IN_PROGRESS));
+            return;
+        }
+
+    	L2PcInstance[] players = _manager.getOlympiadInstance(id).getPlayers();
+
+        if (players == null) return;
+
+    	spectator.enterOlympiadObserverMode(STADIUMS[id][0], STADIUMS[id][1], STADIUMS[id][2], id);
+
+        _manager.getOlympiadInstance(id).addSpectator(spectator);
+
+        spectator.sendPacket(new ExOlympiadUserInfoSpectator(players[0], 2));
+        spectator.sendPacket(new ExOlympiadUserInfoSpectator(players[1], 1));
+    }
+
+    public void removeSpectator(int id, L2PcInstance spectator)
+    {
+        if (_manager == null || (_manager.getOlympiadInstance(id) == null)) return;
+
+        _manager.getOlympiadInstance(id).removeSpectator(spectator);
+    }
+
+    public List<L2PcInstance> getSpectators(int id)
+    {
+        return _manager.getOlympiadInstance(id).getSpectators();
+    }
+
+    public Map<Integer, L2OlympiadGame> getOlympiadGames()
+    {
+    	return _manager.getOlympiadGames();
+    }
+
+    public boolean playerInStadia(L2PcInstance player)
+    {
+        return (OlympiadStadiaManager.getInstance().getStadium(player) != null);
+    }
+
+    public int[] getWaitingList()
+    {
+        int[] array = new int[2];
+
+        if (!inCompPeriod())
+            return null;
+
+        int classCount = 0;
+
+        if (_classBasedRegisters.size() != 0)
+            for (List<L2PcInstance> classed : _classBasedRegisters.values())
+            {
+                classCount += classed.size();
+            }
+
+        array[0] = classCount;
+        array[1] = _nonClassBasedRegisters.size();
+
+        return array;
+    }
+
+    protected synchronized void saveNobleData()
+    {
+        Connection con = null;
+
+        if (_nobles == null)
+            return;
+
+        try
+        {
+            con = L2DatabaseFactory.getInstance().getConnection();
+            PreparedStatement statement;
+
+            for (Integer nobleId : _nobles.keySet())
+            {
+                StatsSet nobleInfo = _nobles.get(nobleId);
+
+                int charId = nobleId;
+                int classId = nobleInfo.getInteger(CLASS_ID);
+                String charName = nobleInfo.getString(CHAR_NAME);
+                int points = nobleInfo.getInteger(POINTS);
+                int compDone = nobleInfo.getInteger(COMP_DONE);
+                boolean toSave = nobleInfo.getBool("to_save");
+
+                if (toSave)
+                {
+                    statement = con.prepareStatement(OLYMPIAD_SAVE_NOBLES);
+                    statement.setInt(1, charId);
+                    statement.setInt(2, classId);
+                    statement.setString(3, charName);
+                    statement.setInt(4, points);
+                    statement.setInt(5, compDone);
+                    statement.execute();
+
+                    statement.close();
+
+                    nobleInfo.set("to_save", false);
+
+                    _nobles.remove(nobleId);
+                    _nobles.put(nobleId, nobleInfo);
+                }
+                else
+                {
+                    statement = con.prepareStatement(OLYMPIAD_UPDATE_NOBLES);
+                    statement.setInt(1, points);
+                    statement.setInt(2, compDone);
+                    statement.setInt(3, charId);
+                    statement.execute();
+                    statement.close();
+                }
+            }
+        }
+        catch(SQLException e) {_log.warning("Olympiad System: Couldnt save nobles info in db");}
+        finally
+        {
+            try{con.close();}catch(Exception e){e.printStackTrace();}
+        }
+    }
+
+    protected void sortHerosToBe()
+    {
+        if (_period != 1) return;
+
+         _heroesToBe = new FastList<StatsSet>();
+
+         Connection con = null;
+
+         try
+         {
+             con = L2DatabaseFactory.getInstance().getConnection();
+             PreparedStatement statement;
+             ResultSet rset;
+             StatsSet hero;
+
+             for (int i = 88; i < 119; i++)
+             {
+                 statement = con.prepareStatement(OLYMPIAD_GET_HEROS);
+                 statement.setInt(1, i);
+                 rset = statement.executeQuery();
+
+                 if (rset.next())
+                 {
+                     hero = new StatsSet();
+                     hero.set(CLASS_ID, i);
+                     hero.set(CHAR_ID, rset.getInt(CHAR_ID));
+                     hero.set(CHAR_NAME, rset.getString(CHAR_NAME));
+
+                     _heroesToBe.add(hero);
+                 }
+
+                 statement.close();
+                 rset.close();
+             }
+         }
+         catch(SQLException e){_log.warning("Olympiad System: Couldnt heros from db");}
+         finally
+         {
+             try{con.close();}catch(Exception e){e.printStackTrace();}
+         }
+
+    }
+
+    public List<String> getClassLeaderBoard(int classId)
+    {
+        //if (_period != 1) return;
+
+         List<String> names = new FastList<String>();
+
+         Connection con = null;
+
+         try
+         {
+             con = L2DatabaseFactory.getInstance().getConnection();
+             PreparedStatement statement;
+             ResultSet rset;
+             statement = con.prepareStatement(GET_EACH_CLASS_LEADER);
+             statement.setInt(1, classId);
+             rset = statement.executeQuery();
+
+             while (rset.next())
+             {
+                 names.add(rset.getString(CHAR_NAME));
+             }
+
+             statement.close();
+             rset.close();
+
+             return names;
+         }
+         catch(SQLException e){_log.warning("Olympiad System: Couldnt heros from db");}
+         finally
+         {
+             try{con.close();}catch(Exception e){e.printStackTrace();}
+         }
+
+         return names;
+
+    }
+
+    protected void giveHeroBonus()
+    {
+        if (_heroesToBe.size() == 0)
+            return;
+
+        for (StatsSet hero : _heroesToBe)
+        {
+            int charId = hero.getInteger(CHAR_ID);
+
+            StatsSet noble = _nobles.get(charId);
+            int currentPoints = noble.getInteger(POINTS);
+            currentPoints += 300;
+            noble.set(POINTS, currentPoints);
+
+            _nobles.remove(charId);
+            _nobles.put(charId, noble);
+        }
+    }
+
+    public int getNoblessePasses(int objId)
+    {
+        if (_period != 1 || _nobles.size() == 0)
+            return 0;
+
+        StatsSet noble = _nobles.get(objId);
+        if (noble == null)
+            return 0;
+        int points = noble.getInteger(POINTS);
+        if (points <= 50)
+            return 0;
+
+        noble.set(POINTS, 0);
+        _nobles.remove(objId);
+        _nobles.put(objId, noble);
+
+        points *= 1000;
+
+        return points;
+    }
+
+    public boolean isRegisteredInComp(L2PcInstance player)
+    {
+        boolean result = false;
+
+        if (_nonClassBasedRegisters != null && _nonClassBasedRegisters.contains(player))
+            result = true;
+
+        else if (_classBasedRegisters != null && _classBasedRegisters.containsKey(player.getClassId().getId()))
+        {
+            List<L2PcInstance> classed = _classBasedRegisters.get(player.getClassId().getId());
+            if (classed.contains(player))
+                result = true;
+        }
+
+        return result;
+    }
+
+    public int getNoblePoints(int objId)
+    {
+        if (_nobles.size() ==  0)
+            return 0;
+
+        StatsSet noble = _nobles.get(objId);
+        if (noble == null)
+            return 0;
+        int points = noble.getInteger(POINTS);
+
+        return points;
+    }
+
+    public int getCompetitionDone(int objId)
+    {
+        if (_nobles.size() ==  0)
+            return 0;
+
+        StatsSet noble = _nobles.get(objId);
+        if (noble == null)
+            return 0;
+        int points = noble.getInteger(COMP_DONE);
+
+        return points;
+    }
+
+    protected void deleteNobles()
+    {
+        Connection con = null;
+
+        try
+        {
+            con = L2DatabaseFactory.getInstance().getConnection();
+            PreparedStatement statement = con.prepareStatement(OLYMPIAD_DELETE_ALL);
+            statement.execute();
+            statement.close();
+        }
+        catch(SQLException e){_log.warning("Olympiad System: Couldnt delete nobles from db");}
+        finally
+        {
+            try{con.close();}catch(Exception e){e.printStackTrace();}
+        }
+
+        _nobles.clear();
+    }
+
+    public void save() throws IOException
+    {
+        saveNobleData();
+
+        Properties OlympiadProperties = new Properties();
+        FileOutputStream fos = new FileOutputStream(new File(Config.DATAPACK_ROOT, OLYMPIAD_DATA_FILE));
+
+        OlympiadProperties.setProperty("CurrentCycle", String.valueOf(_currentCycle));
+        OlympiadProperties.setProperty("Period", String.valueOf(_period));
+        OlympiadProperties.setProperty("OlympiadEnd", String.valueOf(_olympiadEnd));
+        OlympiadProperties.setProperty("ValdationEnd", String.valueOf(_validationEnd));
+        OlympiadProperties.setProperty("NextWeeklyChange", String.valueOf(_nextWeeklyChange));
+
+        OlympiadProperties.store(fos, "Olympiad Properties");
+        fos.close();
+    }
+
+    private class OlympiadManager implements Runnable
+    {
+    	private Map<Integer, L2OlympiadGame> _olympiadInstances;
+        private Map<Integer, List<L2PcInstance>> _classBasedParticipants;
+        private Map<Integer, List<L2PcInstance>> _nonClassBasedParticipants;
+
+    	public OlympiadManager()
+    	{
+    		_olympiadInstances = new FastMap<Integer, L2OlympiadGame>();
+    		_manager = this;
+    	}
+
+    	public synchronized void run()
+    	{
+    		if (isOlympiadEnd())
+    		{
+    			_scheduledManagerTask.cancel(true);
+    			return;
+    		}
+
+    		if (!inCompPeriod())
+    			return;
+
+            //Announcements.getInstance().announceToAll("Comp Match Init");
+
+    		if (_nobles.size() == 0)
+    			return;
+
+    		_compStarted = true;
+
+    		try{
+                sortClassBasedOpponents();
+    			_nonClassBasedParticipants = pickOpponents(_nonClassBasedRegisters);
+    		}catch(Exception e){e.printStackTrace();}
+
+            int classIndex = 0;
+            int nonClassIndex = 0;
+            int index = 0;
+
+            for (int i = 0; i < COLLISIEUMS; i++)
+            {
+                if (_classBasedParticipants.get(classIndex) != null)
+                {
+                    _olympiadInstances.put(index, new L2OlympiadGame(index, COMP_TYPE.CLASSED, _classBasedParticipants.get(classIndex), STADIUMS[index]));
+                    index++;
+                    classIndex++;
+                }
+                if (_nonClassBasedParticipants.get(nonClassIndex) != null)
+                {
+                    _olympiadInstances.put(index, new L2OlympiadGame(index, COMP_TYPE.NON_CLASSED, _nonClassBasedParticipants.get(nonClassIndex), STADIUMS[index]));
+                    nonClassIndex++;
+                    index++;
+                }
+            }
+
+    		if (_olympiadInstances.size() == 0)
+            {
+                _compStarted = false;
+                return;
+            }
+
+    		for (L2OlympiadGame instance : _olympiadInstances.values())
+    			instance.sendMessageToPlayers(false,30);
+
+    		//Wait 30 seconds
+    		try{
+    			wait(30000);
+    		}catch (InterruptedException e){}
+
+    		for (L2OlympiadGame instance : _olympiadInstances.values())
+    			instance.portPlayersToArena();
+
+            //Wait 20 seconds
+            try{
+                wait(20000);
+            }catch (InterruptedException e){}
+
+            for (L2OlympiadGame instance : _olympiadInstances.values())
+                instance.removals();
+
+            _battleStarted = true;
+
+    		//Wait 1 min
+    		for (int i=60;i>10;i-=10)
+    		{
+    			for (L2OlympiadGame instance : _olympiadInstances.values())
+                {
+    				instance.sendMessageToPlayers(true,i);
+    				if (i==20)
+        				instance.additions();
+                }
+
+    			try{
+    				wait(10000);
+        		}catch (InterruptedException e){}
+    		}
+
+    		for (L2OlympiadGame instance : _olympiadInstances.values())
+            {
+    			instance.sendMessageToPlayers(true,10);
+            }
+    		try{
+				wait(5000);
+    		}catch (InterruptedException e){}
+
+    		for (int i=5;i>0;i--)
+    		{
+    			for (L2OlympiadGame instance : _olympiadInstances.values())
+                {
+    				instance.sendMessageToPlayers(true,i);
+                }
+    			try{
+    				wait(1000);
+        		}catch (InterruptedException e){}
+    		}
+
+    		for (L2OlympiadGame instance : _olympiadInstances.values())
+    		{
+    			instance.makeCompetitionStart();
+    		}
+
+    		//Wait 6 mins (Battle)
+    		try{
+    			wait(BATTLE_PERIOD);
+    		}catch (InterruptedException e){}
+
+    		for (L2OlympiadGame instance : _olympiadInstances.values())
+    		{
+    			try{
+    				instance.validateWinner();
+    			}catch(Exception e){e.printStackTrace();}
+    		}
+
+    		//Wait 20 seconds
+    		try{
+    			wait(20000);
+    		}catch (InterruptedException e){}
+
+    		for (L2OlympiadGame instance : _olympiadInstances.values())
+            {
+    			instance.portPlayersBack();
+                instance.clearSpectators();
+            }
+
+            //Wait 20 seconds
+            try{
+                wait(20000);
+            }catch (InterruptedException e){}
+
+    		_classBasedParticipants.clear();
+    		_nonClassBasedParticipants.clear();
+
+    		_olympiadInstances.clear();
+            _classBasedRegisters.clear();
+            _nonClassBasedRegisters.clear();
+
+            _battleStarted = false;
+    		_compStarted = false;
+
+    	}
+
+    	protected L2OlympiadGame getOlympiadInstance(int index)
+    	{
+    		if (_olympiadInstances != null || _compStarted)
+    		{
+    			return _olympiadInstances.get(index);
+    		}
+    		return null;
+    	}
+
+        private void sortClassBasedOpponents()
+        {
+            Map<Integer, List<L2PcInstance>> result = new FastMap<Integer, List<L2PcInstance>>();
+            _classBasedParticipants = new FastMap<Integer, List<L2PcInstance>>();
+
+            int count = 0;
+
+            if (_classBasedRegisters.size() == 0) return;
+
+            for (List<L2PcInstance> classed : _classBasedRegisters.values())
+            {
+                if (classed.size() == 0) continue;
+
+                try{
+                   result = pickOpponents(classed);
+                }catch(Exception e){e.printStackTrace();}
+
+                if (result.size() == 0)
+                    continue;
+
+                for (List<L2PcInstance> list : result.values())
+                {
+                    if (count == 10) break;
+                    _classBasedParticipants.put(count, list);
+                    count++;
+                }
+
+                if (count == 10) break;
+            }
+        }
+
+    	protected Map<Integer, L2OlympiadGame> getOlympiadGames()
+    	{
+    		return (_olympiadInstances == null)? null : _olympiadInstances;
+    	}
+
+    	private Map<Integer, List<L2PcInstance>> pickOpponents(List<L2PcInstance> list) throws Exception
+    	{
+    		Map<Integer, List<L2PcInstance>> result =
+    			new FastMap<Integer, List<L2PcInstance>>();
+
+            if (list.size() == 0)
+                return result;
+
+    		int loopCount = (list.size() / 2);
+
+    		int first;
+    		int second;
+
+    		if (loopCount < 1)
+    			return result;
+
+    		int count = 0;
+
+    		for (int i = 0; i < loopCount; i++)
+    		{
+    			count++;
+
+    			List<L2PcInstance> opponents = new FastList<L2PcInstance>();
+    			first = Rnd.nextInt(list.size());
+    			opponents.add(list.get(first));
+    			list.remove(first);
+
+    			second = Rnd.nextInt(list.size());
+    			opponents.add(list.get(second));
+    			list.remove(second);
+
+    			result.put(i, opponents);
+
+    			if (count == 11)
+    				break;
+    		}
+
+            return result;
+        }
+
+    	protected String[] getAllTitles()
+    	{
+    		if(!_compStarted)
+    			return null;
+
+            if(_olympiadInstances.size() == 0)
+                return null;
+
+    		String[] msg = new String[_olympiadInstances.size()];
+    		int count = 0;
+    		int match = 1;
+
+    		for (L2OlympiadGame instance : _olympiadInstances.values())
+    		{
+    			msg[count] = match + "_In Progress_" + instance.getTitle();
+    			count++;
+    			match++;
+    		}
+
+    		return msg;
+    	}
+    }
+
+    private class L2OlympiadGame
+    {
+    	protected COMP_TYPE _type;
+    	private boolean _aborted;
+    	private String _playerOneName;
+    	private String _playerTwoName;
+    	private int _playerOneID = 0;
+    	private int _playerTwoID = 0;
+    	private L2PcInstance _playerOne;
+    	private L2PcInstance _playerTwo;
+    	private List<L2PcInstance> _players;
+    	private int[] _playerOneLocation;
+    	private int[] _playerTwoLocation;
+        private int[] _stadiumPort;
+        private List<L2PcInstance> _spectators;
+        private SystemMessage _sm;
+        private SystemMessage _sm2;
+        private SystemMessage _sm3;
+
+    	protected L2OlympiadGame(int id, COMP_TYPE type, List<L2PcInstance> list, int[] stadiumPort)
+    	{
+    		_aborted = false;
+    		_type = type;
+            _stadiumPort = stadiumPort;
+            _spectators = new FastList<L2PcInstance>();
+
+    		if (list != null)
+    		{
+    			_players = list;
+    			_playerOne = list.get(0);
+    			_playerTwo = list.get(1);
+
+                try {
+                	_playerOneName = _playerOne.getName();
+                	_playerTwoName = _playerTwo.getName();
+                	_playerOne.setOlympiadGameId(id);
+                	_playerTwo.setOlympiadGameId(id);
+                	_playerOneID = _playerOne.getObjectId();
+                	_playerTwoID = _playerTwo.getObjectId();
+                }
+                catch (Exception e)  {
+                	_aborted = true;
+                	clearPlayers();
+                }
+                _log.info("Olympiad System: Game - " + id + ": "
+                          + _playerOne.getName() + " Vs " + _playerTwo.getName());
+    		}
+            else {
+            	_aborted = true;
+            	clearPlayers();
+            	return;
+            }
+    	}
+
+    	protected void removals()
+    	{
+    		if (_aborted) return;
+
+            if (_playerOne == null || _playerTwo == null) return;
+
+    		for (L2PcInstance player : _players)
+    		{
+    		  try{
+    			//Remove Clan Skills
+				if (player.getClan() != null)
+				{
+					for(L2Skill skill: player.getClan().getAllSkills())
+						player.removeSkill(skill,false);
+				}
+				//Abort casting if player casting  
+				if (player.isCastingNow())
+				{
+					player.abortCast();  
+				}  
+
+				//Remove Hero Skills
+				if (player.isHero())
+				{
+					for(L2Skill skill: HeroSkillTable.GetHeroSkills())
+						player.removeSkill(skill,false);
+				}
+				
+				//Remove Buffs
+				player.stopAllEffects();
+				
+				//Remove Summon's Buffs
+				if (player.getPet() != null)
+				{
+					L2Summon summon = player.getPet();
+					summon.stopAllEffects();
+					
+					if (summon instanceof L2PetInstance)
+						summon.unSummon(player);
+		    	}
+                
+                /*if (player.getCubics() != null)
+                {
+                    for(L2CubicInstance cubic : player.getCubics().values())
+                    {
+                        cubic.stopAction();
+                        player.delCubic(cubic.getId());
+                    }
+                    player.getCubics().clear();
+                }*/
+				
+				//Remove player from his party
+				if (player.getParty() != null)
+				{
+					L2Party party = player.getParty();
+					party.removePartyMember(player);
+				}
+
+				//Remove Hero Weapons
+				// check to prevent the using of weapon/shield on strider/wyvern
+				L2ItemInstance wpn = player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_RHAND);
+				if (wpn == null) wpn = player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LRHAND);
+				if (wpn != null &&
+						(
+								(wpn.getItemId() >= 6611 && wpn.getItemId() <= 6621) ||
+								wpn.getItemId() == 6842
+						)
+					)
+				{
+					L2ItemInstance[] unequiped = player.getInventory().unEquipItemInBodySlotAndRecord(wpn.getItem().getBodyPart());
+					InventoryUpdate iu = new InventoryUpdate();
+					for (int i = 0; i < unequiped.length; i++)
+						iu.addModifiedItem(unequiped[i]);
+					player.sendPacket(iu);
+					player.abortAttack();
+					player.broadcastUserInfo();
+
+					// this can be 0 if the user pressed the right mousebutton twice very fast
+					if (unequiped.length > 0)
+					{
+						if (unequiped[0].isWear())
+							return;
+						SystemMessage sm = null;
+						if (unequiped[0].getEnchantLevel() > 0){
+							sm = new SystemMessage(SystemMessageId.EQUIPMENT_S1_S2_REMOVED);
+							sm.addNumber(unequiped[0].getEnchantLevel());
+							sm.addItemName(unequiped[0].getItemId());
+						}else{
+							sm = new SystemMessage(SystemMessageId.S1_DISARMED);
+							sm.addItemName(unequiped[0].getItemId());
+						}
+						player.sendPacket(sm);
+					}
+				}
+
+				//Remove ss/sps/bsps automation
+				Map<Integer, Integer> activeSoulShots = player.getAutoSoulShot();
+				for (int itemId : activeSoulShots.values())
+					player.removeAutoSoulShot(itemId);
+				player.sendSkillList(); 
+    		  } catch (Exception e) {}
+    		}
+            
+            _sm = new SystemMessage(SystemMessageId.THE_GAME_WILL_START_IN_S1_SECOND_S);
+            _sm.addNumber(120);
+            broadcastMessage(_sm, false);
+    	}
+    	
+    	protected void clearPlayers()
+    	{
+    		_playerOne = null;
+    		_playerTwo = null;
+    		_players = null;
+    		_playerOneName = "";
+    		_playerTwoName = "";
+    		_playerOneID = 0;
+    		_playerTwoID = 0;
+    	}
+    	
+    	protected boolean portPlayersToArena()
+    	{
+    		_playerOneLocation = new int[3];
+    		_playerTwoLocation = new int[3];
+    		
+    		boolean _playerOneCrash = true;
+    		boolean _playerTwoCrash = true;
+    		
+    		try {
+    			if (_playerOne != null && _playerOne.getOlympiadGameId() != -1)
+    				_playerOneCrash=false;
+    		} catch (Exception e) {}
+
+    		try {
+    			if (_playerTwo != null && _playerTwo.getOlympiadGameId() != -1)
+    				_playerTwoCrash=false;
+    		} catch (Exception e){ }
+    		
+    		if (_playerOneCrash){
+    			StatsSet playerOneStat;
+    			playerOneStat = _nobles.get(_playerOneID);
+				int playerOnePoints = playerOneStat.getInteger(POINTS);
+				playerOneStat.set(POINTS, playerOnePoints - (playerOnePoints / 5));
+				_log.info("Olympia Result: "+_playerOneName+" vs "+_playerTwoName+" ... "+_playerOneName+" lost "+(playerOnePoints - (playerOnePoints / 5))+" points for crash before teleport to arena");
+    		}
+
+    		if (_playerTwoCrash){
+    			StatsSet playerTwoStat;
+    			playerTwoStat = _nobles.get(_playerTwoID);
+    			int playerTwoPoints = playerTwoStat.getInteger(POINTS);
+				playerTwoStat.set(POINTS, playerTwoPoints - (playerTwoPoints / 5));
+				_log.info("Olympia Result: "+_playerOneName+" vs "+_playerTwoName+" ... "+_playerTwoName+" lost "+(playerTwoPoints - (playerTwoPoints / 5))+" points for crash before teleport to arena");
+        	}
+
+    		if (_playerOneCrash || _playerTwoCrash){
+    			_playerOne=null;  
+    			_playerTwo=null; 
+    			_aborted = true;
+    			return false;
+    		}
+
+    		try { 
+    			_playerOneLocation[0] = _playerOne.getX();
+    			_playerOneLocation[1] = _playerOne.getY();
+    			_playerOneLocation[2] = _playerOne.getZ();
+    		
+    			_playerTwoLocation[0] = _playerTwo.getX();
+    			_playerTwoLocation[1] = _playerTwo.getY();
+    			_playerTwoLocation[2] = _playerTwo.getZ();
+    		
+    			//_playerOne.getAppearance().setInvisible();
+    			//_playerOne.broadcastUserInfo();
+    			//_playerOne.decayMe();
+    			//_playerOne.spawnMe();
+    			//_playerTwo.getAppearance().setInvisible();
+    			//_playerTwo.broadcastUserInfo();
+    			//_playerTwo.decayMe();
+    			//_playerTwo.spawnMe();
+            
+    			if (_playerOne.isSitting())
+    				_playerOne.standUp();
+            
+    			if (_playerTwo.isSitting())
+    				_playerTwo.standUp();
+            
+    			_playerOne.setTarget(null);
+    			_playerTwo.setTarget(null);
+    		
+    			_playerOne.teleToLocation(_stadiumPort[0], _stadiumPort[1], _stadiumPort[2], true);
+    			_playerTwo.teleToLocation(_stadiumPort[0], _stadiumPort[1], _stadiumPort[2], true);
+            
+    			_playerOne.setIsInOlympiadMode(true);
+    			_playerOne.setIsOlympiadStart(false);
+
+    			_playerTwo.setIsInOlympiadMode(true);
+    			_playerTwo.setIsOlympiadStart(false);
+    		} catch (Exception e) { 
+    			return false; 
+    		}
+    		return true;
+    	}
+    	
+    	protected void sendMessageToPlayers(boolean toBattleBegin, int nsecond)
+    	{
+            if(!toBattleBegin)
+                _sm = new SystemMessage(SystemMessageId.YOU_WILL_ENTER_THE_OLYMPIAD_STADIUM_IN_S1_SECOND_S);
+            else
+                _sm = new SystemMessage(SystemMessageId.THE_GAME_WILL_START_IN_S1_SECOND_S);
+            
+            _sm.addNumber(nsecond);
+            try {    		
+            	for (L2PcInstance player : _players)
+            		player.sendPacket(_sm);
+            } catch (Exception e) {};
+    	}
+    	
+    	protected void portPlayersBack()
+    	{
+            try { 
+            	_playerOne.teleToLocation(_playerOneLocation[0], 
+            			_playerOneLocation[1], _playerOneLocation[2], true);
+            }
+            catch (Exception e) {}
+    		
+            try {
+    			_playerTwo.teleToLocation(_playerTwoLocation[0],
+    					_playerTwoLocation[1], _playerTwoLocation[2], true);
+            }
+            catch (Exception e) {}
+    		
+    		for (L2PcInstance player : _players)
+    		{
+    		  try {
+    			player.setIsInOlympiadMode(false);
+    			player.setIsOlympiadStart(false);
+                player.setOlympiadSide(-1);
+                player.setOlympiadGameId(-1);
+                player.setCurrentCp(player.getMaxCp());
+                player.setCurrentHp(player.getMaxHp());
+                player.setCurrentMp(player.getMaxMp());
+                player.getStatus().startHpMpRegeneration();
+
+                //Add Clan Skills
+				if (player.getClan() != null)
+				{
+					for(L2Skill skill: player.getClan().getAllSkills())
+					{
+						if ( skill.getMinPledgeClass() <= player.getPledgeClass() )
+							player.addSkill(skill,false);
+				 	}
+				}
+
+                //Add Hero Skills
+				if (player.isHero())
+				{
+					for(L2Skill skill: HeroSkillTable.GetHeroSkills())
+						player.addSkill(skill,false);
+				}
+				player.sendSkillList();
+    		  } catch (Exception e) {}
+    		}
+    	}
+    	
+    	protected void validateWinner()
+    	{
+			if (_aborted || (_playerOne == null && _playerTwo == null))
+			{					
+				_log.info("Olympia Result: "+_playerOneName+" vs "+_playerTwoName+" ... aborted/tie due to crashes!");
+				return;
+			}
+
+    		StatsSet playerOneStat;
+    		StatsSet playerTwoStat;
+    		
+    		playerOneStat = _nobles.get(_playerOneID);
+			playerTwoStat = _nobles.get(_playerTwoID);
+			
+			int playerOnePlayed = playerOneStat.getInteger(COMP_DONE);
+			int playerTwoPlayed = playerTwoStat.getInteger(COMP_DONE);
+			
+			int playerOnePoints = playerOneStat.getInteger(POINTS);
+			int playerTwoPoints = playerTwoStat.getInteger(POINTS);
+
+			double playerOneHp = 0;
+			double hpDiffOne = 9999999;
+			try{
+				if (_playerOne != null && _playerOne.getOlympiadGameId() != -1)
+				{
+					playerOneHp = _playerOne.getCurrentHp()+_playerOne.getCurrentCp();
+					hpDiffOne = (_playerOne.getMaxHp()+_playerOne.getMaxCp()) - playerOneHp;
+				}
+			}catch (Exception e){
+				playerOneHp = 0;
+				hpDiffOne = 9999999;
+			}
+
+			double playerTwoHp = 0;
+			double hpDiffTwo = 9999999;
+			try{
+				if (_playerTwo != null && _playerTwo.getOlympiadGameId()!=-1)
+				{
+					playerTwoHp = _playerTwo.getCurrentHp()+_playerTwo.getCurrentCp();
+					hpDiffTwo = (_playerTwo.getMaxHp()+_playerTwo.getMaxCp()) - playerTwoHp;
+				}
+			}catch (Exception e){
+				playerTwoHp = 0;
+				hpDiffTwo = 9999999;
+			}
+
+            _sm = new SystemMessage(SystemMessageId.S1_HAS_WON_THE_GAME);
+    		_sm2 = new SystemMessage(SystemMessageId.S1_HAS_GAINED_S2_OLYMPIAD_POINTS);
+            _sm3 = new SystemMessage(SystemMessageId.S1_HAS_LOST_S2_OLYMPIAD_POINTS);
+            
+            String result = "";
+
+            if (playerTwoHp==0 || hpDiffOne < hpDiffTwo)
+    		{
+            	int pointDiff;
+            	pointDiff = (playerTwoPoints / 3);
+    			playerOneStat.set(POINTS, playerOnePoints + pointDiff);
+    			playerTwoStat.set(POINTS, playerTwoPoints - pointDiff);
+
+                _sm.addString(_playerOneName);
+                broadcastMessage(_sm, true);
+                _sm2.addString(_playerOneName);
+                _sm2.addNumber(pointDiff);
+                broadcastMessage(_sm2, true);
+                _sm3.addString(_playerTwoName);
+                _sm3.addNumber(pointDiff);
+                broadcastMessage(_sm3, true);
+
+                _playerOne =  L2World.getInstance().getPlayer(_playerOneName); // why this...
+                try {
+        			result=" ("+playerOneHp+"hp vs "+playerTwoHp+"hp - "+hpDiffOne+" vs "+hpDiffTwo+") "+_playerOneName+" win "+pointDiff+" points";
+        			L2ItemInstance item = _playerOne.getInventory().addItem("Olympiad", 6651, 30, _playerOne, null);
+        			InventoryUpdate iu = new InventoryUpdate();
+        			iu.addModifiedItem(item);
+        			_playerOne.sendPacket(iu);
+
+        			SystemMessage sm = new SystemMessage(SystemMessageId.EARNED_S2_S1_S);
+        			sm.addItemName(item.getItemId());
+        			sm.addNumber(30);
+        			_playerOne.sendPacket(sm);
+                } catch (Exception e) { }
+    		}
+            else if (playerOneHp==0 || hpDiffOne > hpDiffTwo)
+    		{
+            	int pointDiff;
+            	pointDiff = (playerOnePoints / 3);
+    			playerTwoStat.set(POINTS, playerTwoPoints + pointDiff);
+    			playerOneStat.set(POINTS, playerOnePoints - pointDiff);
+                
+                _sm.addString(_playerTwo.getName());
+                broadcastMessage(_sm, true);
+                _sm2.addString(_playerTwo.getName());
+                _sm2.addNumber(pointDiff);
+                broadcastMessage(_sm2, true);
+                _sm3.addString(_playerOne.getName());
+                _sm3.addNumber(pointDiff);
+                broadcastMessage(_sm3, true);
+
+                _playerTwo =  L2World.getInstance().getPlayer(_playerTwoName); // why this...
+                try {
+                	result=" ("+playerOneHp+"hp vs "+playerTwoHp+"hp - "+hpDiffOne+" vs "+hpDiffTwo+") "+_playerTwoName+" win "+pointDiff+" points";
+                	L2ItemInstance item = _playerTwo.getInventory().addItem("Olympiad", 6651, 30, _playerTwo, null);
+                	InventoryUpdate iu = new InventoryUpdate();
+                	iu.addModifiedItem(item);
+                	_playerTwo.sendPacket(iu);
+
+                	SystemMessage sm = new SystemMessage(SystemMessageId.EARNED_S2_S1_S);
+                	sm.addItemName(item.getItemId());
+                	sm.addNumber(30);
+                	_playerTwo.sendPacket(sm);
+                } catch (Exception e) { }
+    		}
+    		else
+    		{
+    			result=" tie";
+    			_sm = new SystemMessage(SystemMessageId.THE_GAME_ENDED_IN_A_TIE);
+                broadcastMessage(_sm, true);
+    		}
+            _log.info("Olympia Result: "+_playerOneName+" vs "+_playerTwoName+" ... "+result);
+            
+    		playerOneStat.set(COMP_DONE, playerOnePlayed + 1);
+    		playerTwoStat.set(COMP_DONE, playerTwoPlayed + 1);
+    		
+    		_nobles.remove(_playerOneID);
+    		_nobles.remove(_playerTwoID);
+    		
+    		_nobles.put(_playerOneID, playerOneStat);
+    		_nobles.put(_playerTwoID, playerTwoStat);
+            
+            _sm = new SystemMessage(SystemMessageId.YOU_WILL_GO_BACK_TO_THE_VILLAGE_IN_S1_SECOND_S);
+            _sm.addNumber(20);
+            broadcastMessage(_sm, true);
+    	}
+    	
+    	protected void additions()
+    	{
+    		for (L2PcInstance player : _players)
+    		{
+    		  try {
+    			//Set HP/CP/MP to Max
+    			player.setCurrentCp(player.getMaxCp());
+    			player.setCurrentHp(player.getMaxHp());
+    			player.setCurrentMp(player.getMaxMp());
+                
+                //Wind Walk Buff for Both
+    			L2Skill skill;
+    			SystemMessage sm;
+
+    			skill = SkillTable.getInstance().getInfo(1204, 2);
+    			skill.getEffects(player, player);
+    			player.broadcastPacket(new MagicSkillUse(player, player, skill.getId(), 2, skill.getHitTime(), 0));
+    			sm = new SystemMessage(SystemMessageId.YOU_FEEL_S1_EFFECT);
+    			sm.addSkillName(1204);
+    			player.sendPacket(sm);
+                
+                if (!player.isMageClass())
+                {
+                	//Haste Buff to Fighters
+                	skill = SkillTable.getInstance().getInfo(1086, 1);
+                    skill.getEffects(player, player);
+                    player.broadcastPacket(new MagicSkillUse(player, player, skill.getId(), 1, skill.getHitTime(), 0));
+                    sm = new SystemMessage(SystemMessageId.YOU_FEEL_S1_EFFECT);
+                    sm.addSkillName(1086);
+                    player.sendPacket(sm);
+                
+                }else{
+                	//Acumen Buff to Mages
+                	skill = SkillTable.getInstance().getInfo(1085, 1);
+                    skill.getEffects(player, player);
+                    player.broadcastPacket(new MagicSkillUse(player, player, skill.getId(), 1, skill.getHitTime(), 0));
+                    sm = new SystemMessage(SystemMessageId.YOU_FEEL_S1_EFFECT);
+                    sm.addSkillName(1085);
+                    player.sendPacket(sm);
+                }
+    		  } catch (Exception e) { }
+     		}
+     	}
+    	
+    	protected boolean makePlayersVisible()
+    	{
+            _sm = new SystemMessage(SystemMessageId.STARTS_THE_GAME);
+            try {
+            	for (L2PcInstance player : _players)
+            	{
+            		player.getAppearance().setVisible();
+            		player.broadcastUserInfo();
+            		player.sendPacket(_sm);
+            		if (player.getPet() != null)
+            			player.getPet().updateAbnormalEffect();
+            	}
+            } catch (NullPointerException e) { _aborted = true; return false; }
+            return true;
+    	}
+
+    	protected boolean makeCompetitionStart()
+    	{
+           if (_playerOne == null || _playerTwo == null)
+           {
+        	   _aborted = true; 
+        	   return false;
+           }
+
+    		_sm = new SystemMessage(SystemMessageId.STARTS_THE_GAME);
+            
+    		try {
+    			for (L2PcInstance player : _players)
+    			{
+    				player.setIsOlympiadStart(true);
+    				player.sendPacket(_sm);
+    			}
+    		} catch (Exception e) { 
+    			_aborted = true;
+    			return false; 
+    		}
+    		return true;
+    	}
+
+    	protected String getTitle()
+    	{
+    		String msg = "";
+    		msg+= _playerOneName + " : " + _playerTwoName;
+    		return msg;
+    	}
+    	
+    	protected L2PcInstance[] getPlayers()
+    	{
+            L2PcInstance[] players = new L2PcInstance[2];
+            
+            if (_playerOne == null || _playerTwo == null) return null;
+            
+    		players[0] = _playerOne;
+    		players[1] = _playerTwo;
+    		
+    		return players;
+    	}
+        
+        protected List<L2PcInstance> getSpectators()
+        {
+            return _spectators;
+        }
+        
+        protected void addSpectator(L2PcInstance spec)
+        {
+            _spectators.add(spec);
+        }
+        
+        protected void removeSpectator(L2PcInstance spec)
+        {
+            if (_spectators != null && _spectators.contains(spec))
+                _spectators.remove(spec);
+        }
+        
+        protected void clearSpectators()
+        { 
+            if (_spectators != null)
+            {
+                for (L2PcInstance pc : _spectators)
+                {
+                    try {
+                    	if(!pc.inObserverMode()) continue;
+                    	pc.leaveOlympiadObserverMode();
+                    } catch (NullPointerException e) {}
+                }
+                _spectators.clear();
+            }
+        }
+        
+        private void broadcastMessage(SystemMessage sm, boolean toAll)
+        {
+        	try { _playerOne.sendPacket(sm); } catch (Exception e) {}
+        	try { _playerTwo.sendPacket(sm); } catch (Exception e) {}
+        	
+            if (toAll && _spectators != null)
+            {
+                    for (L2PcInstance spec : _spectators)
+                    {
+                    	try { spec.sendPacket(sm); } catch (NullPointerException e) {}
+                    }
+            }
+        }
+    }
+}

+ 90 - 0
L2_GameServer_T1/java/net/sf/l2j/gameserver/PacketHistory.java

@@ -0,0 +1,90 @@
+/*
+ * $Header: PacketHistory.java, 27/11/2005 01:57:03 luisantonioa Exp $
+ *
+ * $Author: luisantonioa $
+ * $Date: 27/11/2005 01:57:03 $
+ * $Revision: 1 $
+ * $Log: PacketHistory.java,v $
+ * Revision 1  27/11/2005 01:57:03  luisantonioa
+ * Added copyright notice
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+package net.sf.l2j.gameserver;
+
+import java.util.Date;
+import java.util.Map;
+
+import javolution.xml.XMLFormat;
+import javolution.xml.stream.XMLStreamException;
+
+class PacketHistory
+{
+    protected Map<Class<?>, Long> _info;
+    protected long _timeStamp;
+
+    protected static final XMLFormat<PacketHistory> PACKET_HISTORY_XML = new XMLFormat<PacketHistory>(PacketHistory.class)
+    {
+        /**
+		 * @see javolution.xml.XMLFormat#read(javolution.xml.XMLFormat.InputElement, java.lang.Object)
+		 */
+		@Override
+		public void read(InputElement xml, PacketHistory packetHistory) throws XMLStreamException
+		{
+			packetHistory._timeStamp = xml.getAttribute("time-stamp", 0);
+			packetHistory._info = xml.<Map<Class<?>, Long>> get("info");
+		}
+
+		/**
+		 * @see javolution.xml.XMLFormat#write(java.lang.Object, javolution.xml.XMLFormat.OutputElement)
+		 */
+		@Override
+		public void write(PacketHistory packetHistory, OutputElement xml) throws XMLStreamException
+		{
+			// TODO Auto-generated method stub
+			xml.setAttribute("time-stamp", new Date(packetHistory._timeStamp).toString());
+
+			for (Class<?> cls : packetHistory._info.keySet())
+				xml.setAttribute(cls.getSimpleName(), packetHistory._info.get(cls));
+		}
+
+//		public void format(PacketHistory packetHistory, XmlElement xml)
+//        {
+//            xml.setAttribute("time-stamp", new Date(packetHistory.timeStamp).toString());
+//
+//            for (Class cls : packetHistory.info.keySet())
+//            {
+//                xml.setAttribute(cls.getSimpleName(), packetHistory.info.get(cls));
+//            }
+//        }
+//
+//        public PacketHistory parse(XmlElement xml)
+//        {
+//            PacketHistory packetHistory = new PacketHistory();
+//            packetHistory.timeStamp     = xml.getAttribute("time-stamp", (long) 0);
+//            packetHistory.info          = xml.<Map<Class, Long>> get("info");
+//            return packetHistory;
+//        }
+//
+//        public String defaultName()
+//        {
+//            return "packet-history";
+//        }
+    };
+}

+ 923 - 0
L2_GameServer_T1/java/net/sf/l2j/gameserver/RecipeController.java

@@ -0,0 +1,923 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+package net.sf.l2j.gameserver;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.WeakHashMap;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.xml.sax.SAXException;
+
+import javolution.util.FastList;
+import javolution.util.FastMap;
+import net.sf.l2j.Config;
+import net.sf.l2j.gameserver.model.Inventory;
+import net.sf.l2j.gameserver.model.L2ItemInstance;
+import net.sf.l2j.gameserver.model.L2ManufactureItem;
+import net.sf.l2j.gameserver.model.L2RecipeInstance;
+import net.sf.l2j.gameserver.model.L2RecipeList;
+import net.sf.l2j.gameserver.model.L2Skill;
+import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
+import net.sf.l2j.gameserver.network.SystemMessageId;
+import net.sf.l2j.gameserver.serverpackets.ActionFailed;
+import net.sf.l2j.gameserver.serverpackets.ItemList;
+import net.sf.l2j.gameserver.serverpackets.MagicSkillUse;
+import net.sf.l2j.gameserver.serverpackets.RecipeBookItemList;
+import net.sf.l2j.gameserver.serverpackets.RecipeItemMakeInfo;
+import net.sf.l2j.gameserver.serverpackets.RecipeShopItemInfo;
+import net.sf.l2j.gameserver.serverpackets.SetupGauge;
+import net.sf.l2j.gameserver.serverpackets.StatusUpdate;
+import net.sf.l2j.gameserver.serverpackets.SystemMessage;
+import net.sf.l2j.gameserver.skills.Stats;
+import net.sf.l2j.gameserver.util.Util;
+import net.sf.l2j.util.Rnd;
+
+public class RecipeController
+{
+	protected static final Logger _log = Logger.getLogger(RecipeController.class.getName());
+
+	private static RecipeController _instance;
+	private Map<Integer, L2RecipeList> _lists;
+	protected static final Map<L2PcInstance, RecipeItemMaker> _activeMakers = Collections.synchronizedMap(new WeakHashMap<L2PcInstance, RecipeItemMaker>());
+    private static final String RECIPES_FILE = "recipes.xml";
+    
+	public static RecipeController getInstance()
+	{
+		return _instance == null ? _instance = new RecipeController() : _instance;
+	}
+
+	public RecipeController()
+	{
+		_lists = new FastMap<Integer, L2RecipeList>();
+
+		try
+        {
+            this.loadFromXML();
+            _log.info("RecipeController: Loaded "+_lists.size()+" recipes.");
+        }
+        catch (Exception e)
+        {
+            _log.log(Level.SEVERE, "Failed loading recipe list", e);
+        }
+	}
+
+	public int getRecipesCount()
+	{
+		return _lists.size();
+	}
+
+	public L2RecipeList getRecipeList(int listId)
+	{
+		return _lists.get(listId);
+	}
+
+	public L2RecipeList getRecipeByItemId(int itemId)
+	{
+		for (int i = 0; i < _lists.size(); i++)
+		{
+			L2RecipeList find = _lists.get(new Integer(i));
+			if (find.getRecipeId() == itemId)
+			{
+				return find;
+			}
+		}
+		return null;
+	}
+
+    public L2RecipeList getRecipeById(int recId)
+    {
+        for (int i = 0; i < _lists.size(); i++)
+        {
+            L2RecipeList find = _lists.get(new Integer(i));
+            if (find.getId() == recId)
+            {
+                return find;
+            }
+        }
+        return null;
+    }
+
+	public synchronized void requestBookOpen(L2PcInstance player, boolean isDwarvenCraft)
+	{
+		RecipeItemMaker maker = null;
+		if (Config.ALT_GAME_CREATION) maker = _activeMakers.get(player);
+
+		if (maker == null)
+		{
+			RecipeBookItemList response = new RecipeBookItemList(isDwarvenCraft, player.getMaxMp());
+			response.addRecipes(isDwarvenCraft	? player.getDwarvenRecipeBook()
+			                                  	: player.getCommonRecipeBook());
+			player.sendPacket(response);
+			return;
+		}
+
+		SystemMessage sm = new SystemMessage(SystemMessageId.CANT_ALTER_RECIPEBOOK_WHILE_CRAFTING);
+		player.sendPacket(sm);
+		return;
+	}
+
+	public synchronized void requestMakeItemAbort(L2PcInstance player)
+	{
+		_activeMakers.remove(player);  // TODO:  anything else here?
+	}
+
+	public synchronized void requestManufactureItem(L2PcInstance manufacturer, int recipeListId,
+	                                                L2PcInstance player)
+	{
+		L2RecipeList recipeList = getValidRecipeList(player, recipeListId);
+
+		if (recipeList == null) return;
+
+		List<L2RecipeList> dwarfRecipes = Arrays.asList(manufacturer.getDwarvenRecipeBook());
+		List<L2RecipeList> commonRecipes = Arrays.asList(manufacturer.getCommonRecipeBook());
+
+		if (!dwarfRecipes.contains(recipeList) && !commonRecipes.contains(recipeList))
+		{
+			Util.handleIllegalPlayerAction(player,"Warning!! Character "+player.getName()+" of account "+player.getAccountName()+" sent a false recipe id.",Config.DEFAULT_PUNISH);
+    		return;
+		}
+
+
+		RecipeItemMaker maker;
+
+		if (Config.ALT_GAME_CREATION && (maker = _activeMakers.get(manufacturer)) != null) // check if busy
+		{
+			player.sendMessage("Manufacturer is busy, please try later.");
+			return;
+		}
+
+		maker = new RecipeItemMaker(manufacturer, recipeList, player);
+		if (maker._isValid)
+		{
+			if (Config.ALT_GAME_CREATION)
+			{
+				_activeMakers.put(manufacturer, maker);
+				ThreadPoolManager.getInstance().scheduleGeneral(maker, 100);
+			}
+			else maker.run();
+		}
+	}
+
+	public synchronized void requestMakeItem(L2PcInstance player, int recipeListId)
+	{
+		if (player.isInDuel())
+		{
+			player.sendPacket(new SystemMessage(SystemMessageId.CANT_CRAFT_DURING_COMBAT));
+			return;
+		}
+
+		L2RecipeList recipeList = getValidRecipeList(player, recipeListId);
+
+		if (recipeList == null)	return;
+
+		List<L2RecipeList> dwarfRecipes = Arrays.asList(player.getDwarvenRecipeBook());
+		List<L2RecipeList> commonRecipes = Arrays.asList(player.getCommonRecipeBook());
+
+		if (!dwarfRecipes.contains(recipeList) && !commonRecipes.contains(recipeList))
+		{
+			Util.handleIllegalPlayerAction(player,"Warning!! Character "+player.getName()+" of account "+player.getAccountName()+" sent a false recipe id.",Config.DEFAULT_PUNISH);
+    		return;
+		}
+
+		RecipeItemMaker maker;
+
+		// check if already busy (possible in alt mode only)
+		if (Config.ALT_GAME_CREATION && ((maker = _activeMakers.get(player)) != null))
+		{
+			SystemMessage sm = new SystemMessage(SystemMessageId.S1_S2);
+			sm.addString("You are busy creating ");
+			sm.addItemName(recipeList.getItemId());
+			player.sendPacket(sm);
+			return;
+		}
+
+		maker = new RecipeItemMaker(player, recipeList, player);
+		if (maker._isValid)
+		{
+			if (Config.ALT_GAME_CREATION)
+			{
+				_activeMakers.put(player, maker);
+				ThreadPoolManager.getInstance().scheduleGeneral(maker, 100);
+			}
+			else maker.run();
+		}
+	}
+
+	//TODO XMLize the recipe list
+	/*private void parseList(String line)
+	{
+		try
+		{
+			StringTokenizer st = new StringTokenizer(line, ";");
+			List<L2RecipeInstance> recipePartList = new FastList<L2RecipeInstance>();
+
+			//we use common/dwarf for easy reading of the recipes.csv file
+			String recipeTypeString = st.nextToken();
+
+			// now parse the string into a boolean
+			boolean isDwarvenRecipe;
+
+			if (recipeTypeString.equalsIgnoreCase("dwarven")) isDwarvenRecipe = true;
+			else if (recipeTypeString.equalsIgnoreCase("common")) isDwarvenRecipe = false;
+			else
+			{ //prints a helpfull message
+				_log.warning("Error parsing recipes.csv, unknown recipe type " + recipeTypeString);
+				return;
+			}
+
+			String recipeName = st.nextToken();
+			int id = Integer.parseInt(st.nextToken());
+			int recipeId = Integer.parseInt(st.nextToken());
+			int level = Integer.parseInt(st.nextToken());
+
+			//material
+			StringTokenizer st2 = new StringTokenizer(st.nextToken(), "[],");
+			while (st2.hasMoreTokens())
+			{
+				StringTokenizer st3 = new StringTokenizer(st2.nextToken(), "()");
+				int rpItemId = Integer.parseInt(st3.nextToken());
+				int quantity = Integer.parseInt(st3.nextToken());
+				L2RecipeInstance rp = new L2RecipeInstance(rpItemId, quantity);
+				recipePartList.add(rp);
+			}
+
+			int itemId = Integer.parseInt(st.nextToken());
+			int count = Integer.parseInt(st.nextToken());
+
+			//npc fee
+			//String notdoneyet = 
+            st.nextToken();
+
+			int mpCost = Integer.parseInt(st.nextToken());
+			int successRate = Integer.parseInt(st.nextToken());
+
+			L2RecipeList recipeList = new L2RecipeList(id, level, recipeId, recipeName, successRate,
+			                                           mpCost, itemId, count, isDwarvenRecipe);
+			for (L2RecipeInstance recipePart : recipePartList)
+			{
+				recipeList.addRecipe(recipePart);
+			}
+			_lists.put(new Integer(_lists.size()), recipeList);
+		}
+		catch (Exception e)
+		{
+			_log.severe("Exception in RecipeController.parseList() - " + e);
+		}
+	}*/
+    
+    private void loadFromXML() throws SAXException, IOException, ParserConfigurationException
+    {
+        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+        factory.setValidating(false);
+        factory.setIgnoringComments(true);
+        File file = new File(Config.DATAPACK_ROOT+"/data/"+RECIPES_FILE);
+        if (file.exists())
+        {
+            Document doc = factory.newDocumentBuilder().parse(file);
+            List<L2RecipeInstance> recipePartList = new FastList<L2RecipeInstance>();
+            
+            for (Node n = doc.getFirstChild(); n != null; n = n.getNextSibling())
+            {
+                if ("list".equalsIgnoreCase(n.getNodeName()))
+                {
+                    String recipeName;
+                    int id;
+                    for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
+                    {
+                        if ("item".equalsIgnoreCase(d.getNodeName()))
+                        {
+                            recipePartList.clear();
+                            NamedNodeMap attrs = d.getAttributes();
+                            Node att;
+                            att = attrs.getNamedItem("id");
+                            if (att == null)
+                            {
+                                _log.severe("Missing id for recipe item, skipping");
+                                continue;
+                            }
+                            id = Integer.parseInt(att.getNodeValue());
+                            
+                            att = attrs.getNamedItem("name");
+                            if (att == null)
+                            {
+                                _log.severe("Missing name for recipe item id: "+id+", skipping");
+                                continue;
+                            }
+                            recipeName = att.getNodeValue();
+                            
+                            int recipeId = -1;
+                            int level = -1;
+                            boolean isDwarvenRecipe = true;
+                            int mpCost = -1;
+                            int successRate = -1;
+                            int prodId = -1;
+                            int count = -1;
+                            for (Node c = d.getFirstChild(); c != null; c = c.getNextSibling())
+                            {
+                                if ("recipe".equalsIgnoreCase(c.getNodeName()))
+                                {
+                                    NamedNodeMap atts = c.getAttributes();
+                                    
+                                    recipeId = Integer.parseInt(atts.getNamedItem("id").getNodeValue());
+                                    level = Integer.parseInt(atts.getNamedItem("level").getNodeValue());
+                                    isDwarvenRecipe = atts.getNamedItem("type").getNodeValue().equalsIgnoreCase("dwarven");
+                                }
+                                else if ("mpCost".equalsIgnoreCase(c.getNodeName()))
+                                {
+                                    mpCost = Integer.parseInt(c.getTextContent());
+                                }
+                                else if ("successRate".equalsIgnoreCase(c.getNodeName()))
+                                {
+                                    successRate = Integer.parseInt(c.getTextContent());
+                                }
+                                else if ("ingredient".equalsIgnoreCase(c.getNodeName()))
+                                {
+                                    int ingId = Integer.parseInt(c.getAttributes().getNamedItem("id").getNodeValue());
+                                    int ingCount = Integer.parseInt(c.getAttributes().getNamedItem("count").getNodeValue());
+                                    recipePartList.add(new L2RecipeInstance(ingId, ingCount));
+                                }
+                                else if ("production".equalsIgnoreCase(c.getNodeName()))
+                                {
+                                    prodId = Integer.parseInt(c.getAttributes().getNamedItem("id").getNodeValue());
+                                    count = Integer.parseInt(c.getAttributes().getNamedItem("count").getNodeValue());
+                                }
+                            }
+                            L2RecipeList recipeList = new L2RecipeList(id, level, recipeId, recipeName, successRate, mpCost, prodId, count, isDwarvenRecipe);
+                            for (L2RecipeInstance recipePart : recipePartList)
+                            {
+                                recipeList.addRecipe(recipePart);
+                            }
+                            _lists.put(_lists.size(), recipeList);
+                        }
+                    }
+                }
+            }
+        }
+        else
+        {
+            _log.severe("Recipes file ("+file.getAbsolutePath()+") doesnt exists.");
+        }
+    }
+
+	private class RecipeItemMaker implements Runnable
+	{
+		protected boolean _isValid;
+		protected List<TempItem> _items = null;
+		protected final L2RecipeList _recipeList;
+		protected final L2PcInstance _player; // "crafter"
+		protected final L2PcInstance _target; // "customer"
+		protected final L2Skill _skill;
+		protected final int _skillId;
+		protected final int _skillLevel;
+		protected double _creationPasses;
+		protected double _manaRequired;
+		protected int _price;
+		protected int _totalItems;
+		protected int _materialsRefPrice;
+		protected int _delay;
+
+		public RecipeItemMaker(L2PcInstance pPlayer, L2RecipeList pRecipeList, L2PcInstance pTarget)
+		{
+			_player = pPlayer;
+			_target = pTarget;
+			_recipeList = pRecipeList;
+
+			_isValid = false;
+			_skillId = _recipeList.isDwarvenRecipe()	? L2Skill.SKILL_CREATE_DWARVEN
+			                                      	: L2Skill.SKILL_CREATE_COMMON;
+			_skillLevel = _player.getSkillLevel(_skillId);
+			_skill = _player.getKnownSkill(_skillId);
+
+			_player.isInCraftMode(true);
+
+			if (_player.isAlikeDead())
+			{
+				_player.sendMessage("Dead people don't craft.");
+				_player.sendPacket(new ActionFailed());
+				abort();
+				return;
+			}
+
+			if (_target.isAlikeDead())
+			{
+				_target.sendMessage("Dead customers can't use manufacture.");
+				_target.sendPacket(new ActionFailed());
+				abort();
+				return;
+			}
+
+			if(_target.isProcessingTransaction())
+			{
+				_target.sendMessage("You are busy.");
+				_target.sendPacket(new ActionFailed());
+				abort();
+				return;
+			}
+
+			if(_player.isProcessingTransaction())
+			{
+				if(_player!=_target)
+				{
+					_target.sendMessage("Manufacturer "+_player.getName() + " is busy.");
+				}
+				_player.sendPacket(new ActionFailed());
+				abort();
+				return;
+			}
+
+			// validate recipe list
+			if ((_recipeList == null) || (_recipeList.getRecipes().length == 0))
+			{
+				_player.sendMessage("No such recipe");
+				_player.sendPacket(new ActionFailed());
+				abort();
+				return;
+			}
+
+			_manaRequired = _recipeList.getMpCost();
+
+			// validate skill level
+			if (_recipeList.getLevel() > _skillLevel)
+			{
+				_player.sendMessage("Need skill level " + _recipeList.getLevel());
+				_player.sendPacket(new ActionFailed());
+				abort();
+				return;
+			}
+
+			// check that customer can afford to pay for creation services
+			if (_player != _target)
+			{
+				for (L2ManufactureItem temp : _player.getCreateList().getList())
+					if (temp.getRecipeId() == _recipeList.getId()) // find recipe for item we want manufactured
+					{
+						_price = temp.getCost();
+						if (_target.getAdena() < _price) // check price
+						{
+							_target.sendPacket(new SystemMessage(SystemMessageId.YOU_NOT_ENOUGH_ADENA));
+							abort();
+							return;
+						}
+						break;
+					}
+			}
+
+			// make temporary items
+			if ((_items = listItems(false)) == null)
+				{
+					abort();
+					return;
+				}
+
+			// calculate reference price
+			for (TempItem i : _items)
+			{
+				_materialsRefPrice += i.getReferencePrice() * i.getQuantity();
+				_totalItems += i.getQuantity();
+			}
+			// initial mana check requires MP as written on recipe
+			if (_player.getCurrentMp() < _manaRequired)
+			{
+				_target.sendPacket(new SystemMessage(SystemMessageId.NOT_ENOUGH_MP));
+				abort();
+				return;
+			}
+
+			// determine number of creation passes needed
+			// can "equip"  skillLevel items each pass
+			_creationPasses = (_totalItems / _skillLevel) + ((_totalItems % _skillLevel)!=0 ? 1 : 0);
+
+			if (Config.ALT_GAME_CREATION && _creationPasses != 0) // update mana required to "per pass"
+				_manaRequired /= _creationPasses; // checks to validateMp() will only need portion of mp for one pass
+
+			updateMakeInfo(true);
+			updateCurMp();
+			updateCurLoad();
+
+			_player.isInCraftMode(false);
+			_isValid = true;
+		}
+
+		public void run()
+		{
+			if (!Config.IS_CRAFTING_ENABLED)
+			{
+				_target.sendMessage("Item creation is currently disabled.");
+				abort();
+				return;
+			}
+
+			if (_player == null || _target == null)
+			{
+				_log.warning("player or target == null (disconnected?), aborting"+_target+_player);
+				abort();
+				return;
+			}
+
+			if (_player.isOnline()==0 || _target.isOnline()==0)
+			{
+				_log.warning("player or target is not online, aborting "+_target+_player);
+				abort();
+				return;
+			}
+
+			if (Config.ALT_GAME_CREATION && _activeMakers.get(_player) == null)
+			{
+				if (_target!=_player)
+				{
+					_target.sendMessage("Manufacture aborted");
+					_player.sendMessage("Manufacture aborted");
+				}
+				else
+				{
+					_player.sendMessage("Item creation aborted");
+				}
+
+				abort();
+				return;
+			}
+
+			if (Config.ALT_GAME_CREATION && !_items.isEmpty())
+			{
+
+				if (!validateMp()) return;				// check mana
+				_player.reduceCurrentMp(_manaRequired); 	// use some mp
+				updateCurMp();							// update craft window mp bar
+
+				grabSomeItems(); // grab (equip) some more items with a nice msg to player
+
+				// if still not empty, schedule another pass
+				if(!_items.isEmpty())
+				{
+					// divided by RATE_CONSUMABLES_COST to remove craft time increase on higher consumables rates
+					_delay = (int) (Config.ALT_GAME_CREATION_SPEED * _player.getMReuseRate(_skill)
+							* GameTimeController.TICKS_PER_SECOND / Config.RATE_CONSUMABLE_COST)
+							* GameTimeController.MILLIS_IN_TICK;
+
+					// FIXME: please fix this packet to show crafting animation (somebody)
+					MagicSkillUse msk = new MagicSkillUse(_player, _skillId, _skillLevel, _delay, 0);
+					_player.broadcastPacket(msk);
+
+					_player.sendPacket(new SetupGauge(0, _delay));
+					ThreadPoolManager.getInstance().scheduleGeneral(this, 100 + _delay);
+				}
+				else
+				{
+					// for alt mode, sleep delay msec before finishing
+					_player.sendPacket(new SetupGauge(0, _delay));
+
+					try {
+						Thread.sleep(_delay);
+					} catch (InterruptedException e) {
+					} finally {
+						finishCrafting();
+					}
+				}
+			}    // for old craft mode just finish
+			else finishCrafting();
+		}
+
+		private void finishCrafting()
+		{
+			if(!Config.ALT_GAME_CREATION) _player.reduceCurrentMp(_manaRequired);
+
+			// first take adena for manufacture
+			if ((_target != _player) && _price > 0) // customer must pay for services
+			{
+				// attempt to pay for item
+				L2ItemInstance adenatransfer = _target.transferItem("PayManufacture",
+										_target.getInventory().getAdenaInstance().getObjectId(),
+										_price, _player.getInventory(), _player);
+
+				if(adenatransfer==null)
+				{
+					_target.sendPacket(new SystemMessage(SystemMessageId.YOU_NOT_ENOUGH_ADENA));
+					abort();
+					return;
+				}
+			}
+
+			if ((_items = listItems(true)) == null) // this line actually takes materials from inventory
+			{ // handle possible cheaters here
+			  // (they click craft then try to get rid of items in order to get free craft)
+			}
+			else if (Rnd.get(100) < _recipeList.getSuccessRate())
+			{
+				rewardPlayer(); // and immediately puts created item in its place
+				updateMakeInfo(true);
+			}
+			else
+			{
+				_player.sendMessage("Item(s) failed to create");
+				if (_target != _player)
+					_target.sendMessage("Item(s) failed to create");
+
+				updateMakeInfo(false);
+			}
+			// update load and mana bar of craft window
+			updateCurMp();
+			updateCurLoad();
+			_activeMakers.remove(_player);
+			_player.isInCraftMode(false);
+			_target.sendPacket(new ItemList(_target, false));
+		}
+		private void updateMakeInfo(boolean success)
+		{
+			if (_target == _player) _target.sendPacket(new RecipeItemMakeInfo(_recipeList.getId(), _target,
+			                                                               success));
+			else _target.sendPacket(new RecipeShopItemInfo(_player.getObjectId(), _recipeList.getId()));
+		}
+
+		private void updateCurLoad()
+		{
+			StatusUpdate su = new StatusUpdate(_target.getObjectId());
+			su.addAttribute(StatusUpdate.CUR_LOAD, _target.getCurrentLoad());
+			_target.sendPacket(su);
+		}
+
+		private void updateCurMp()
+		{
+			StatusUpdate su = new StatusUpdate(_target.getObjectId());
+			su.addAttribute(StatusUpdate.CUR_MP, (int) _target.getCurrentMp());
+			_target.sendPacket(su);
+		}
+
+		private void grabSomeItems()
+		{
+			int numItems = _skillLevel;
+
+			while (numItems > 0 && !_items.isEmpty())
+			{
+				TempItem item = _items.get(0);
+
+				int count = item.getQuantity();
+				if (count >= numItems) count = numItems;
+
+				item.setQuantity(item.getQuantity() - count);
+				if (item.getQuantity() <= 0) _items.remove(0);
+				else _items.set(0, item);
+
+				numItems -= count;
+
+				if (_target == _player)
+				{
+					SystemMessage sm = new SystemMessage(SystemMessageId.S1_S2_EQUIPPED); // you equipped ...
+					sm.addNumber(count);
+					sm.addItemName(item.getItemId());
+					_player.sendPacket(sm);
+				}
+				else _target.sendMessage("Manufacturer " + _player.getName() + " used " + count + " "
+				                        + item.getItemName());
+			}
+		}
+
+		private boolean validateMp()
+		{
+			if (_player.getCurrentMp() < _manaRequired)
+			{
+				// rest (wait for MP)
+				if (Config.ALT_GAME_CREATION)
+				{
+					_player.sendPacket(new SetupGauge(0, _delay));
+					ThreadPoolManager.getInstance().scheduleGeneral(this, 100 + _delay);
+				}
+				else
+					// no rest - report no mana
+				{
+					_target.sendPacket(new SystemMessage(SystemMessageId.NOT_ENOUGH_MP));
+					abort();
+				}
+				return false;
+			}
+			return true;
+		}
+
+		private List<TempItem> listItems(boolean remove)
+		{
+			L2RecipeInstance[] recipes = _recipeList.getRecipes();
+			Inventory inv = _target.getInventory();
+			List<TempItem> materials = new FastList<TempItem>();
+
+			for (L2RecipeInstance recipe : recipes)
+			{
+				int quantity = _recipeList.isConsumable() ? (int) (recipe.getQuantity() * Config.RATE_CONSUMABLE_COST)
+				                                         : (int) recipe.getQuantity();
+
+				if (quantity > 0)
+				{
+					L2ItemInstance item = inv.getItemByItemId(recipe.getItemId());
+
+					// check materials
+					if (item==null || item.getCount() < quantity)
+					{
+						_target.sendMessage("You dont have the right elements for making this item"
+						                   + ((_recipeList.isConsumable() && Config.RATE_CONSUMABLE_COST != 1)	? ".\nDue to server rates you need "
+						                                                                                     	  + Config.RATE_CONSUMABLE_COST
+						                                                                                     	  + "x more material than listed in recipe"
+						                                                                                     	  : ""));
+						abort();
+						return null;
+					}
+
+					// make new temporary object, just for counting puroses
+
+					TempItem temp = new TempItem(item, quantity);
+					materials.add(temp);
+				}
+			}
+
+			if (remove)
+			{
+				for(TempItem tmp : materials)
+					{
+					inv.destroyItemByItemId("Manufacture", tmp.getItemId(), tmp.getQuantity(), _target, _player);
+					}
+			}
+			return materials;
+		}
+
+		private void abort()
+		{
+			updateMakeInfo(false);
+			_player.isInCraftMode(false);
+			_activeMakers.remove(_player);
+		}
+
+		/**
+		 * FIXME: This class should be in some other file, but I don't know where
+		 *
+		 * Class explanation:
+		 * For item counting or checking purposes. When you don't want to modify inventory
+		 * class contains itemId, quantity, ownerId, referencePrice, but not objectId
+		 */
+		private class TempItem
+		{ // no object id stored, this will be only "list" of items with it's owner
+			private int _itemId;
+			private int _quantity;
+			private int _ownerId;
+			private int _referencePrice;
+			private String _itemName;
+
+			/**
+			 * @param item
+			 * @param quantity of that item
+			 */
+			public TempItem(L2ItemInstance item, int quantity)
+			{
+				super();
+				_itemId = item.getItemId();
+				_quantity = quantity;
+				_ownerId = item.getOwnerId();
+				_itemName = item.getItem().getName();
+				_referencePrice = item.getReferencePrice();
+			}
+
+			/**
+			 * @return Returns the quantity.
+			 */
+			public int getQuantity()
+			{
+				return _quantity;
+			}
+
+			/**
+			 * @param quantity The quantity to set.
+			 */
+			public void setQuantity(int quantity)
+			{
+				_quantity = quantity;
+			}
+
+			public int getReferencePrice()
+			{
+				return _referencePrice;
+			}
+
+			/**
+			 * @return Returns the itemId.
+			 */
+			public int getItemId()
+			{
+				return _itemId;
+			}
+
+			/**
+			 * @return Returns the ownerId.
+			 */
+			public int getOwnerId()
+			{
+				return _ownerId;
+			}
+
+			/**
+			 * @return Returns the itemName.
+			 */
+			public String getItemName()
+			{
+				return _itemName;
+			}
+		}
+
+		private void rewardPlayer()
+		{
+			int itemId = _recipeList.getItemId();
+			int itemCount = _recipeList.getCount();
+
+			L2ItemInstance createdItem = _target.getInventory().addItem("Manufacture", itemId, itemCount,
+			                                                           _target, _player);
+
+			// inform customer of earned item
+            SystemMessage sm = null;
+            if (itemCount > 1)
+            {
+    			sm = new SystemMessage(SystemMessageId.EARNED_S2_S1_S);
+    			sm.addItemName(itemId);
+                sm.addNumber(itemCount);
+    			_target.sendPacket(sm);
+            } else
+            {
+                sm = new SystemMessage(SystemMessageId.EARNED_ITEM);
+                sm.addItemName(itemId);
+                _target.sendPacket(sm);
+            }
+
+			if (_target != _player)
+			{
+				// inform manufacturer of earned profit
+				sm = new SystemMessage(SystemMessageId.EARNED_ADENA);
+				sm.addNumber(_price);
+				_player.sendPacket(sm);
+			}
+
+			if (Config.ALT_GAME_CREATION)
+			{
+				int recipeLevel = _recipeList.getLevel();
+				int exp = createdItem.getReferencePrice() * itemCount;
+				// one variation
+
+				// exp -= materialsRefPrice;   // mat. ref. price is not accurate so other method is better
+
+				if (exp < 0) exp = 0;
+
+				// another variation
+				exp /= recipeLevel;
+				for (int i = _skillLevel; i > recipeLevel; i--)
+					exp /= 4;
+
+				int sp = exp / 10;
+
+				// Added multiplication of Creation speed with XP/SP gain
+				// slower crafting -> more XP,  faster crafting -> less XP
+				// you can use ALT_GAME_CREATION_XP_RATE/SP to
+				// modify XP/SP gained (default = 1)
+
+				_player.addExpAndSp((int) _player.calcStat(Stats.EXPSP_RATE, exp * Config.ALT_GAME_CREATION_XP_RATE
+				                                         * Config.ALT_GAME_CREATION_SPEED, null, null)
+				                  ,(int) _player.calcStat(Stats.EXPSP_RATE, sp * Config.ALT_GAME_CREATION_SP_RATE
+				                                         * Config.ALT_GAME_CREATION_SPEED, null, null));
+			}
+			updateMakeInfo(true); // success
+		}
+	}
+
+	private L2RecipeList getValidRecipeList(L2PcInstance player, int id)
+	{
+		L2RecipeList recipeList = getRecipeList(id - 1);
+
+		if ((recipeList == null) || (recipeList.getRecipes().length == 0))
+		{
+			player.sendMessage("No recipe for: " + id);
+			player.isInCraftMode(false);
+			return null;
+		}
+		return recipeList;
+	}
+}

+ 1419 - 0
L2_GameServer_T1/java/net/sf/l2j/gameserver/SevenSigns.java

@@ -0,0 +1,1419 @@
+/* This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+package net.sf.l2j.gameserver;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Calendar;
+import java.util.Map;
+import java.util.logging.Logger;
+
+import javolution.util.FastMap;
+import net.sf.l2j.Config;
+import net.sf.l2j.L2DatabaseFactory;
+import net.sf.l2j.gameserver.datatables.MapRegionTable;
+import net.sf.l2j.gameserver.instancemanager.CastleManager;
+import net.sf.l2j.gameserver.model.AutoChatHandler;
+import net.sf.l2j.gameserver.model.AutoSpawnHandler;
+import net.sf.l2j.gameserver.model.L2World;
+import net.sf.l2j.gameserver.model.AutoSpawnHandler.AutoSpawnInstance;
+import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
+import net.sf.l2j.gameserver.network.SystemMessageId;
+import net.sf.l2j.gameserver.serverpackets.SSQInfo;
+import net.sf.l2j.gameserver.serverpackets.SystemMessage;
+import net.sf.l2j.gameserver.templates.StatsSet;
+
+/**
+ *  Seven Signs Engine
+ *
+ *  TODO:
+ *  - Implementation of the Seal of Strife for sieges.
+ *
+ *  @author Tempy
+ */
+public class SevenSigns
+{
+    protected static final Logger _log = Logger.getLogger(SevenSigns.class.getName());
+	private static SevenSigns _instance;
+
+	// Basic Seven Signs Constants \\
+	public static final String SEVEN_SIGNS_DATA_FILE = "config/signs.properties";
+	public static final String SEVEN_SIGNS_HTML_PATH = "data/html/seven_signs/";
+
+	public static final int CABAL_NULL = 0;
+	public static final int CABAL_DUSK = 1;
+	public static final int CABAL_DAWN = 2;
+
+	public static final int SEAL_NULL = 0;
+	public static final int SEAL_AVARICE = 1;
+	public static final int SEAL_GNOSIS = 2;
+	public static final int SEAL_STRIFE = 3;
+
+	public static final int PERIOD_COMP_RECRUITING = 0;
+	public static final int PERIOD_COMPETITION = 1;
+	public static final int PERIOD_COMP_RESULTS = 2;
+	public static final int PERIOD_SEAL_VALIDATION = 3;
+
+	public static final int PERIOD_START_HOUR = 18;
+	public static final int PERIOD_START_MINS = 00;
+    public static final int PERIOD_START_DAY = Calendar.MONDAY;
+
+    // The quest event and seal validation periods last for approximately one week
+    // with a 15 minutes "interval" period sandwiched between them.
+    public static final int PERIOD_MINOR_LENGTH = 900000;
+    public static final int PERIOD_MAJOR_LENGTH = 604800000 - PERIOD_MINOR_LENGTH;
+
+	public static final int ANCIENT_ADENA_ID = 5575;
+	public static final int RECORD_SEVEN_SIGNS_ID = 5707;
+    public static final int CERTIFICATE_OF_APPROVAL_ID = 6388;
+	public static final int RECORD_SEVEN_SIGNS_COST = 500;
+    public static final int ADENA_JOIN_DAWN_COST = 50000;
+
+    // NPC Related Constants \\
+	public static final int ORATOR_NPC_ID = 31094;
+	public static final int PREACHER_NPC_ID = 31093;
+    public static final int MAMMON_MERCHANT_ID = 31113;
+    public static final int MAMMON_BLACKSMITH_ID = 31126;
+    public static final int MAMMON_MARKETEER_ID = 31092;
+    public static final int SPIRIT_IN_ID = 31111;
+    public static final int SPIRIT_OUT_ID = 31112;
+    public static final int LILITH_NPC_ID = 25283;
+    public static final int ANAKIM_NPC_ID = 25286;
+    public static final int CREST_OF_DAWN_ID = 31170;
+    public static final int CREST_OF_DUSK_ID = 31171;
+	// Seal Stone Related Constants \\
+	public static final int SEAL_STONE_BLUE_ID = 6360;
+	public static final int SEAL_STONE_GREEN_ID = 6361;
+	public static final int SEAL_STONE_RED_ID = 6362;
+
+	public static final int SEAL_STONE_BLUE_VALUE = 3;
+	public static final int SEAL_STONE_GREEN_VALUE = 5;
+	public static final int SEAL_STONE_RED_VALUE = 10;
+
+	public static final int BLUE_CONTRIB_POINTS = 3;
+	public static final int GREEN_CONTRIB_POINTS = 5;
+	public static final int RED_CONTRIB_POINTS = 10;
+
+	private final Calendar _calendar = Calendar.getInstance();
+
+    protected int _activePeriod;
+    protected int _currentCycle;
+    protected double _dawnStoneScore;
+    protected double _duskStoneScore;
+    protected int _dawnFestivalScore;
+    protected int _duskFestivalScore;
+    protected int _compWinner;
+    protected int _previousWinner;
+
+	private Map<Integer, StatsSet> _signsPlayerData;
+
+	private Map<Integer, Integer> _signsSealOwners;
+	private Map<Integer, Integer> _signsDuskSealTotals;
+	private Map<Integer, Integer> _signsDawnSealTotals;
+
+    private static AutoSpawnInstance _merchantSpawn;
+    private static AutoSpawnInstance _blacksmithSpawn;
+    private static AutoSpawnInstance _spiritInSpawn;
+    private static AutoSpawnInstance _spiritOutSpawn;
+    private static AutoSpawnInstance _lilithSpawn;
+    private static AutoSpawnInstance _anakimSpawn;
+    private static AutoSpawnInstance _crestofdawnspawn;
+    private static AutoSpawnInstance _crestofduskspawn;
+    private static Map<Integer, AutoSpawnInstance> _oratorSpawns;
+    private static Map<Integer, AutoSpawnInstance> _preacherSpawns;
+    private static Map<Integer, AutoSpawnInstance> _marketeerSpawns;
+
+	public SevenSigns()
+	{
+		_signsPlayerData = new FastMap<Integer, StatsSet>();
+		_signsSealOwners = new FastMap<Integer, Integer>();
+		_signsDuskSealTotals = new FastMap<Integer, Integer>();
+		_signsDawnSealTotals = new FastMap<Integer, Integer>();
+
+		try
+		{
+			restoreSevenSignsData();
+		}
+		catch (Exception e) {
+			_log.severe("SevenSigns: Failed to load configuration: " + e);
+		}
+
+		_log.info("SevenSigns: Currently in the " + getCurrentPeriodName() + " period!");
+		initializeSeals();
+
+		if (isSealValidationPeriod())
+			if (getCabalHighestScore() == CABAL_NULL)
+	            _log.info("SevenSigns: The competition ended with a tie last week.");
+			else
+	            _log.info("SevenSigns: The " + getCabalName(getCabalHighestScore()) + " were victorious last week.");
+		else
+			if (getCabalHighestScore() == CABAL_NULL)
+				_log.info("SevenSigns: The competition, if the current trend continues, will end in a tie this week.");
+			else
+				_log.info("SevenSigns: The " + getCabalName(getCabalHighestScore()) + " are in the lead this week.");
+
+		synchronized (this)
+		{
+            setCalendarForNextPeriodChange();
+            long milliToChange = getMilliToPeriodChange();
+
+			// Schedule a time for the next period change.
+			SevenSignsPeriodChange sspc = new SevenSignsPeriodChange();
+			ThreadPoolManager.getInstance().scheduleGeneral(sspc, milliToChange);
+
+			// Thanks to http://rainbow.arch.scriptmania.com/scripts/timezone_countdown.html for help with this.
+			double numSecs = (milliToChange / 1000) % 60;
+			double countDown = ((milliToChange / 1000) - numSecs) / 60;
+			int numMins = (int)Math.floor(countDown % 60);
+			countDown = (countDown - numMins) / 60;
+			int numHours = (int)Math.floor(countDown % 24);
+			int numDays = (int)Math.floor((countDown - numHours) / 24);
+
+			_log.info("SevenSigns: Next period begins in " + numDays + " days, " + numHours + " hours and " + numMins + " mins.");
+		}
+	}
+
+    /**
+     * Registers all random spawns and auto-chats for Seven Signs NPCs,
+     * along with spawns for the Preachers of Doom and Orators of Revelations
+     * at the beginning of the Seal Validation period.
+     *
+     */
+	public void spawnSevenSignsNPC()
+	{
+		_merchantSpawn = AutoSpawnHandler.getInstance().getAutoSpawnInstance(MAMMON_MERCHANT_ID, false);
+		_blacksmithSpawn = AutoSpawnHandler.getInstance().getAutoSpawnInstance(MAMMON_BLACKSMITH_ID, false);
+		_marketeerSpawns = AutoSpawnHandler.getInstance().getAutoSpawnInstances(MAMMON_MARKETEER_ID);
+		_spiritInSpawn = AutoSpawnHandler.getInstance().getAutoSpawnInstance(SPIRIT_IN_ID, false);
+		_spiritOutSpawn = AutoSpawnHandler.getInstance().getAutoSpawnInstance(SPIRIT_OUT_ID, false);
+		_lilithSpawn = AutoSpawnHandler.getInstance().getAutoSpawnInstance(LILITH_NPC_ID, false);
+		_anakimSpawn = AutoSpawnHandler.getInstance().getAutoSpawnInstance(ANAKIM_NPC_ID, false);
+		_crestofdawnspawn = AutoSpawnHandler.getInstance().getAutoSpawnInstance(CREST_OF_DAWN_ID, false);
+		_crestofduskspawn = AutoSpawnHandler.getInstance().getAutoSpawnInstance(CREST_OF_DUSK_ID, false);
+		_oratorSpawns = AutoSpawnHandler.getInstance().getAutoSpawnInstances(ORATOR_NPC_ID);
+		_preacherSpawns = AutoSpawnHandler.getInstance().getAutoSpawnInstances(PREACHER_NPC_ID);
+
+		if (isSealValidationPeriod() || isCompResultsPeriod())
+		{
+			for (AutoSpawnInstance spawnInst: _marketeerSpawns.values())
+				AutoSpawnHandler.getInstance().setSpawnActive(spawnInst, true);
+
+			if (getSealOwner(SEAL_GNOSIS) == getCabalHighestScore() && getSealOwner(SEAL_GNOSIS) != CABAL_NULL)
+			{
+		        if (!Config.ANNOUNCE_MAMMON_SPAWN)
+		            _blacksmithSpawn.setBroadcast(false);
+
+		        if (!AutoSpawnHandler.getInstance().getAutoSpawnInstance(_blacksmithSpawn.getObjectId(), true).isSpawnActive())
+		        	AutoSpawnHandler.getInstance().setSpawnActive(_blacksmithSpawn, true);
+
+				for (AutoSpawnInstance spawnInst: _oratorSpawns.values())
+					if (!AutoSpawnHandler.getInstance().getAutoSpawnInstance(spawnInst.getObjectId(), true).isSpawnActive())
+						AutoSpawnHandler.getInstance().setSpawnActive(spawnInst, true);
+
+				for (AutoSpawnInstance spawnInst: _preacherSpawns.values())
+					if (!AutoSpawnHandler.getInstance().getAutoSpawnInstance(spawnInst.getObjectId(), true).isSpawnActive())
+						AutoSpawnHandler.getInstance().setSpawnActive(spawnInst, true);
+
+				if (!AutoChatHandler.getInstance().getAutoChatInstance(PREACHER_NPC_ID, false).isActive() && !AutoChatHandler.getInstance().getAutoChatInstance(ORATOR_NPC_ID, false).isActive())
+					AutoChatHandler.getInstance().setAutoChatActive(true);
+			}
+	        else
+	        {
+				AutoSpawnHandler.getInstance().setSpawnActive(_blacksmithSpawn, false);
+
+				for (AutoSpawnInstance spawnInst: _oratorSpawns.values())
+					AutoSpawnHandler.getInstance().setSpawnActive(spawnInst, false);
+
+				for (AutoSpawnInstance spawnInst: _preacherSpawns.values())
+					AutoSpawnHandler.getInstance().setSpawnActive(spawnInst, false);
+
+				AutoChatHandler.getInstance().setAutoChatActive(false);
+	        }
+
+	        if (getSealOwner(SEAL_AVARICE) == getCabalHighestScore() && getSealOwner(SEAL_AVARICE) != CABAL_NULL)
+	        {
+		        if (!Config.ANNOUNCE_MAMMON_SPAWN)
+		            _merchantSpawn.setBroadcast(false);
+
+		        if (!AutoSpawnHandler.getInstance().getAutoSpawnInstance(_merchantSpawn.getObjectId(), true).isSpawnActive())
+		        	AutoSpawnHandler.getInstance().setSpawnActive(_merchantSpawn, true);
+
+		        if (!AutoSpawnHandler.getInstance().getAutoSpawnInstance(_spiritInSpawn.getObjectId(), true).isSpawnActive())
+		        	AutoSpawnHandler.getInstance().setSpawnActive(_spiritInSpawn, true);
+
+		        if (!AutoSpawnHandler.getInstance().getAutoSpawnInstance(_spiritOutSpawn.getObjectId(), true).isSpawnActive())
+		        	AutoSpawnHandler.getInstance().setSpawnActive(_spiritOutSpawn, true);
+
+				switch (getCabalHighestScore())
+		        {
+		        	case CABAL_DAWN:
+				        if (!AutoSpawnHandler.getInstance().getAutoSpawnInstance(_lilithSpawn.getObjectId(), true).isSpawnActive())
+				        	AutoSpawnHandler.getInstance().setSpawnActive(_lilithSpawn, true);
+
+		        		AutoSpawnHandler.getInstance().setSpawnActive(_anakimSpawn, false);
+				        if (!AutoSpawnHandler.getInstance().getAutoSpawnInstance(_crestofdawnspawn.getObjectId(), true).isSpawnActive())
+				        	AutoSpawnHandler.getInstance().setSpawnActive(_crestofdawnspawn, true);
+
+		        		AutoSpawnHandler.getInstance().setSpawnActive(_crestofduskspawn, false);
+		        		break;
+
+		        	case CABAL_DUSK:
+				        if (!AutoSpawnHandler.getInstance().getAutoSpawnInstance(_anakimSpawn.getObjectId(), true).isSpawnActive())
+				        	AutoSpawnHandler.getInstance().setSpawnActive(_anakimSpawn, true);
+
+		        		AutoSpawnHandler.getInstance().setSpawnActive(_lilithSpawn, false);
+				        if (!AutoSpawnHandler.getInstance().getAutoSpawnInstance(_crestofduskspawn.getObjectId(), true).isSpawnActive())
+				        	AutoSpawnHandler.getInstance().setSpawnActive(_crestofduskspawn, true);
+
+		        		AutoSpawnHandler.getInstance().setSpawnActive(_crestofdawnspawn, false);
+		        		break;
+		        }
+	        }
+	        else
+	        {
+				AutoSpawnHandler.getInstance().setSpawnActive(_merchantSpawn, false);
+				AutoSpawnHandler.getInstance().setSpawnActive(_lilithSpawn, false);
+				AutoSpawnHandler.getInstance().setSpawnActive(_anakimSpawn, false);
+				AutoSpawnHandler.getInstance().setSpawnActive(_crestofdawnspawn, false);
+				AutoSpawnHandler.getInstance().setSpawnActive(_crestofduskspawn, false);
+				AutoSpawnHandler.getInstance().setSpawnActive(_spiritInSpawn, false);
+				AutoSpawnHandler.getInstance().setSpawnActive(_spiritOutSpawn, false);
+	        }
+		}
+		else
+		{
+			AutoSpawnHandler.getInstance().setSpawnActive(_merchantSpawn, false);
+			AutoSpawnHandler.getInstance().setSpawnActive(_blacksmithSpawn, false);
+			AutoSpawnHandler.getInstance().setSpawnActive(_lilithSpawn, false);
+			AutoSpawnHandler.getInstance().setSpawnActive(_anakimSpawn, false);
+			AutoSpawnHandler.getInstance().setSpawnActive(_crestofdawnspawn, false);
+			AutoSpawnHandler.getInstance().setSpawnActive(_crestofduskspawn, false);
+			AutoSpawnHandler.getInstance().setSpawnActive(_spiritInSpawn, false);
+			AutoSpawnHandler.getInstance().setSpawnActive(_spiritOutSpawn, false);
+
+			for (AutoSpawnInstance spawnInst: _oratorSpawns.values())
+				AutoSpawnHandler.getInstance().setSpawnActive(spawnInst, false);
+
+			for (AutoSpawnInstance spawnInst: _preacherSpawns.values())
+				AutoSpawnHandler.getInstance().setSpawnActive(spawnInst, false);
+
+			for (AutoSpawnInstance spawnInst: _marketeerSpawns.values())
+				AutoSpawnHandler.getInstance().setSpawnActive(spawnInst, false);
+
+			AutoChatHandler.getInstance().setAutoChatActive(false);
+		}
+	}
+
+	public static SevenSigns getInstance()
+    {
+		if (_instance == null)
+			_instance = new SevenSigns();
+
+		return _instance;
+	}
+
+	public static int calcContributionScore(int blueCount, int greenCount, int redCount)
+	{
+		int contrib = blueCount * BLUE_CONTRIB_POINTS;
+		contrib += greenCount * GREEN_CONTRIB_POINTS;
+		contrib += redCount * RED_CONTRIB_POINTS;
+
+		return contrib;
+	}
+
+	public static int calcAncientAdenaReward(int blueCount, int greenCount, int redCount)
+	{
+		int reward = blueCount * SEAL_STONE_BLUE_VALUE;
+		reward += greenCount * SEAL_STONE_GREEN_VALUE;
+		reward += redCount * SEAL_STONE_RED_VALUE;
+
+		return reward;
+	}
+
+	public static final String getCabalShortName(int cabal)
+	{
+		switch (cabal)
+		{
+			case CABAL_DAWN:
+				return "dawn";
+			case CABAL_DUSK:
+				return "dusk";
+		}
+
+		return "No Cabal";
+	}
+
+	public static final String getCabalName(int cabal)
+	{
+		switch (cabal)
+		{
+			case CABAL_DAWN:
+				return "Lords of Dawn";
+			case CABAL_DUSK:
+				return "Revolutionaries of Dusk";
+		}
+
+		return "No Cabal";
+	}
+
+	public static final String getSealName(int seal, boolean shortName)
+	{
+		String sealName = (!shortName) ? "Seal of " : "";
+
+		switch (seal)
+		{
+			case SEAL_AVARICE:
+				sealName += "Avarice";
+				break;
+			case SEAL_GNOSIS:
+				sealName += "Gnosis";
+				break;
+			case SEAL_STRIFE:
+				sealName += "Strife";
+				break;
+		}
+
+		return sealName;
+	}
+
+	public final int getCurrentCycle()
+    {
+		return _currentCycle;
+	}
+
+	public final int getCurrentPeriod()
+    {
+		return _activePeriod;
+	}
+
+	private final int getDaysToPeriodChange()
+    {
+		int numDays = _calendar.get(Calendar.DAY_OF_WEEK) - PERIOD_START_DAY;
+
+		if (numDays < 0)
+			return 0 - numDays;
+
+        return 7 - numDays;
+	}
+
+    public final long getMilliToPeriodChange()
+    {
+        long currTimeMillis = System.currentTimeMillis();
+        long changeTimeMillis = _calendar.getTimeInMillis();
+
+        return (changeTimeMillis - currTimeMillis);
+    }
+
+    protected void setCalendarForNextPeriodChange()
+    {
+        // Calculate the number of days until the next period
+        // A period starts at 18:00 pm (local time), like on official servers.
+        switch (getCurrentPeriod())
+        {
+            case PERIOD_SEAL_VALIDATION:
+            case PERIOD_COMPETITION:
+                int daysToChange = getDaysToPeriodChange();
+
+                if (daysToChange == 7)
+                	if (_calendar.get(Calendar.HOUR_OF_DAY) < PERIOD_START_HOUR)
+                		daysToChange = 0;
+                	else if (_calendar.get(Calendar.HOUR_OF_DAY) == PERIOD_START_HOUR && _calendar.get(Calendar.MINUTE) < PERIOD_START_MINS)
+                		daysToChange = 0;
+
+                // Otherwise...
+                if (daysToChange > 0)
+                    _calendar.add(Calendar.DATE, daysToChange);
+
+                _calendar.set(Calendar.HOUR_OF_DAY, PERIOD_START_HOUR);
+                _calendar.set(Calendar.MINUTE, PERIOD_START_MINS);
+                break;
+            case PERIOD_COMP_RECRUITING:
+            case PERIOD_COMP_RESULTS:
+                _calendar.add(Calendar.MILLISECOND, PERIOD_MINOR_LENGTH);
+                break;
+        }
+    }
+
+	public final String getCurrentPeriodName()
+    {
+		String periodName = null;
+
+		switch (_activePeriod)
+		{
+			case PERIOD_COMP_RECRUITING:
+				periodName = "Quest Event Initialization";
+				break;
+			case PERIOD_COMPETITION:
+				periodName = "Competition (Quest Event)";
+				break;
+			case PERIOD_COMP_RESULTS:
+				periodName = "Quest Event Results";
+				break;
+			case PERIOD_SEAL_VALIDATION:
+				periodName = "Seal Validation";
+				break;
+		}
+
+		return periodName;
+	}
+
+	public final boolean isSealValidationPeriod()
+	{
+		return (_activePeriod == PERIOD_SEAL_VALIDATION);
+	}
+
+	public final boolean isCompResultsPeriod()
+	{
+		return (_activePeriod == PERIOD_COMP_RESULTS);
+	}
+
+	public final int getCurrentScore(int cabal)
+	{
+        double totalStoneScore = _dawnStoneScore + _duskStoneScore;
+
+		switch (cabal)
+		{
+			case CABAL_NULL:
+				return 0;
+			case CABAL_DAWN:
+				return Math.round((float)(_dawnStoneScore / ((float)totalStoneScore == 0 ? 1 : totalStoneScore)) * 500) + _dawnFestivalScore;
+			case CABAL_DUSK:
+				return Math.round((float)(_duskStoneScore / ((float)totalStoneScore == 0 ? 1 : totalStoneScore)) * 500) + _duskFestivalScore;
+		}
+
+		return 0;
+	}
+
+	public final double getCurrentStoneScore(int cabal)
+	{
+		switch (cabal)
+		{
+			case CABAL_NULL:
+				return 0;
+			case CABAL_DAWN:
+				return _dawnStoneScore;
+			case CABAL_DUSK:
+				return _duskStoneScore;
+		}
+
+		return 0;
+	}
+
+	public final int getCurrentFestivalScore(int cabal)
+	{
+		switch (cabal)
+		{
+			case CABAL_NULL:
+				return 0;
+			case CABAL_DAWN:
+				return _dawnFestivalScore;
+			case CABAL_DUSK:
+				return _duskFestivalScore;
+		}
+
+		return 0;
+	}
+
+	public final int getCabalHighestScore()
+	{
+		if (getCurrentScore(CABAL_DUSK) == getCurrentScore(CABAL_DAWN))
+			return CABAL_NULL;
+		else if (getCurrentScore(CABAL_DUSK) > getCurrentScore(CABAL_DAWN))
+			return CABAL_DUSK;
+		else
+			return CABAL_DAWN;
+	}
+
+	public final int getSealOwner(int seal)
+	{
+		return _signsSealOwners.get(seal);
+	}
+
+	public final int getSealProportion(int seal, int cabal)
+	{
+		if (cabal == CABAL_NULL)
+			return 0;
+		else if (cabal == CABAL_DUSK)
+			return _signsDuskSealTotals.get(seal);
+		else
+			return _signsDawnSealTotals.get(seal);
+	}
+
+	public final int getTotalMembers(int cabal)
+	{
+		int cabalMembers = 0;
+		String cabalName = getCabalShortName(cabal);
+
+		for (StatsSet sevenDat : _signsPlayerData.values())
+			if (sevenDat.getString("cabal").equals(cabalName))
+				cabalMembers++;
+
+		return cabalMembers;
+	}
+
+    public final StatsSet getPlayerData(L2PcInstance player)
+    {
+        if (!hasRegisteredBefore(player))
+            return null;
+
+        return _signsPlayerData.get(player.getObjectId());
+    }
+
+	public int getPlayerStoneContrib(L2PcInstance player)
+	{
+		if (!hasRegisteredBefore(player))
+			return 0;
+
+		int stoneCount = 0;
+
+		StatsSet currPlayer = getPlayerData(player);
+
+		stoneCount += currPlayer.getInteger("red_stones");
+		stoneCount += currPlayer.getInteger("green_stones");
+		stoneCount += currPlayer.getInteger("blue_stones");
+
+		return stoneCount;
+	}
+
+	public int getPlayerContribScore(L2PcInstance player)
+	{
+		if (!hasRegisteredBefore(player))
+			return 0;
+
+		StatsSet currPlayer = getPlayerData(player);
+
+		return currPlayer.getInteger("contribution_score");
+	}
+
+	public int getPlayerAdenaCollect(L2PcInstance player)
+	{
+		if (!hasRegisteredBefore(player))
+			return 0;
+
+		return _signsPlayerData.get(player.getObjectId()).getInteger("ancient_adena_amount");
+	}
+
+	public int getPlayerSeal(L2PcInstance player)
+	{
+		if (!hasRegisteredBefore(player))
+			return SEAL_NULL;
+
+		return getPlayerData(player).getInteger("seal");
+	}
+
+	public int getPlayerCabal(L2PcInstance player)
+	{
+		if (!hasRegisteredBefore(player))
+			return CABAL_NULL;
+
+		String playerCabal = getPlayerData(player).getString("cabal");
+
+		if (playerCabal.equalsIgnoreCase("dawn"))
+			return CABAL_DAWN;
+		else if (playerCabal.equalsIgnoreCase("dusk"))
+			return CABAL_DUSK;
+		else
+			return CABAL_NULL;
+	}
+
+    /**
+     * Restores all Seven Signs data and settings, usually called at server startup.
+     *
+     * @throws Exception
+     */
+    protected void restoreSevenSignsData()
+	{
+    	Connection con = null;
+    	PreparedStatement statement = null;
+    	ResultSet rset = null;
+
+    	try
+    	{
+	    	con = L2DatabaseFactory.getInstance().getConnection();
+		    statement = con.prepareStatement("SELECT char_obj_id, cabal, seal, red_stones, green_stones, blue_stones, " +
+		    	"ancient_adena_amount, contribution_score FROM seven_signs");
+		    rset = statement.executeQuery();
+
+		    while (rset.next())
+		    {
+		    	int charObjId = rset.getInt("char_obj_id");
+
+		    	StatsSet sevenDat = new StatsSet();
+				sevenDat.set("char_obj_id", charObjId);
+				sevenDat.set("cabal", rset.getString("cabal"));
+				sevenDat.set("seal", rset.getInt("seal"));
+				sevenDat.set("red_stones", rset.getInt("red_stones"));
+				sevenDat.set("green_stones", rset.getInt("green_stones"));
+				sevenDat.set("blue_stones", rset.getInt("blue_stones"));
+				sevenDat.set("ancient_adena_amount", rset.getDouble("ancient_adena_amount"));
+				sevenDat.set("contribution_score", rset.getDouble("contribution_score"));
+
+                if (Config.DEBUG)
+					_log.info("SevenSigns: Loaded data from DB for char ID " + charObjId + " (" + sevenDat.getString("cabal") + ")");
+
+				_signsPlayerData.put(charObjId, sevenDat);
+		    }
+
+		    rset.close();
+		    statement.close();
+
+		    statement = con.prepareStatement("SELECT * FROM seven_signs_status WHERE id=0");
+	        rset = statement.executeQuery();
+
+	        while (rset.next())
+	        {
+	            _currentCycle = rset.getInt("current_cycle");
+	            _activePeriod = rset.getInt("active_period");
+	            _previousWinner = rset.getInt("previous_winner");
+
+	            _dawnStoneScore = rset.getDouble("dawn_stone_score");
+	            _dawnFestivalScore = rset.getInt("dawn_festival_score");
+	            _duskStoneScore = rset.getDouble("dusk_stone_score");
+	            _duskFestivalScore = rset.getInt("dusk_festival_score");
+
+	            _signsSealOwners.put(SEAL_AVARICE, rset.getInt("avarice_owner"));
+	            _signsSealOwners.put(SEAL_GNOSIS, rset.getInt("gnosis_owner"));
+	            _signsSealOwners.put(SEAL_STRIFE, rset.getInt("strife_owner"));
+
+	            _signsDawnSealTotals.put(SEAL_AVARICE, rset.getInt("avarice_dawn_score"));
+	            _signsDawnSealTotals.put(SEAL_GNOSIS, rset.getInt("gnosis_dawn_score"));
+	            _signsDawnSealTotals.put(SEAL_STRIFE, rset.getInt("strife_dawn_score"));
+	            _signsDuskSealTotals.put(SEAL_AVARICE, rset.getInt("avarice_dusk_score"));
+	            _signsDuskSealTotals.put(SEAL_GNOSIS, rset.getInt("gnosis_dusk_score"));
+	            _signsDuskSealTotals.put(SEAL_STRIFE, rset.getInt("strife_dusk_score"));
+	        }
+
+	        rset.close();
+	        statement.close();
+
+	        statement = con.prepareStatement("UPDATE seven_signs_status SET date=? WHERE id=0");
+	        statement.setInt(1, Calendar.getInstance().get(Calendar.DAY_OF_WEEK));
+	        statement.execute();
+
+	        statement.close();
+	        con.close();
+    	}
+    	catch (SQLException e)
+    	{
+    		_log.severe("SevenSigns: Unable to load Seven Signs data from database: " + e);
+    	}
+    	finally
+    	{
+    		try
+    		{
+    		    rset.close();
+    		    statement.close();
+    		    con.close();
+    		}
+    		catch (Exception e) {}
+    	}
+
+		// Festival data is loaded now after the Seven Signs engine data.
+	}
+
+	/**
+     * Saves all Seven Signs data, both to the database and properties file (if updateSettings = True).
+     * Often called to preserve data integrity and synchronization with DB, in case of errors.
+     * <BR>
+     * If player != null, just that player's data is updated in the database, otherwise all player's data is
+     * sequentially updated.
+     *
+	 * @param player
+	 * @param updateSettings
+	 * @throws Exception
+	 */
+	public void saveSevenSignsData(L2PcInstance player, boolean updateSettings)
+	{
+		Connection con = null;
+		PreparedStatement statement = null;
+
+        if (Config.DEBUG)
+            System.out.println("SevenSigns: Saving data to disk.");
+
+		try
+		{
+			con = L2DatabaseFactory.getInstance().getConnection();
+
+			for (StatsSet sevenDat : _signsPlayerData.values())
+		    {
+		    	if (player != null)
+		    		if (sevenDat.getInteger("char_obj_id") != player.getObjectId())
+		    			continue;
+
+		    	statement = con.prepareStatement(
+		    		"UPDATE seven_signs SET cabal=?, seal=?, red_stones=?, " +
+		    		"green_stones=?, blue_stones=?, " +
+		    		"ancient_adena_amount=?, contribution_score=? " +
+		    		"WHERE char_obj_id=?");
+		    	statement.setString(1, sevenDat.getString("cabal"));
+		    	statement.setInt(2, sevenDat.getInteger("seal"));
+		    	statement.setInt(3, sevenDat.getInteger("red_stones"));
+		    	statement.setInt(4, sevenDat.getInteger("green_stones"));
+		    	statement.setInt(5, sevenDat.getInteger("blue_stones"));
+		    	statement.setDouble(6, sevenDat.getDouble("ancient_adena_amount"));
+		    	statement.setDouble(7, sevenDat.getDouble("contribution_score"));
+		    	statement.setInt(8, sevenDat.getInteger("char_obj_id"));
+		    	statement.execute();
+
+		    	statement.close();
+
+				if (Config.DEBUG)
+					_log.info("SevenSigns: Updated data in database for char ID " + sevenDat.getInteger("char_obj_id") + " (" + sevenDat.getString("cabal") + ")");
+		    }
+
+	        if (updateSettings)
+	        {
+	        	String sqlQuery = "UPDATE seven_signs_status SET current_cycle=?, active_period=?, previous_winner=?, " +
+	               "dawn_stone_score=?, dawn_festival_score=?, dusk_stone_score=?, dusk_festival_score=?, " +
+	               "avarice_owner=?, gnosis_owner=?, strife_owner=?, avarice_dawn_score=?, gnosis_dawn_score=?, " +
+	               "strife_dawn_score=?, avarice_dusk_score=?, gnosis_dusk_score=?, strife_dusk_score=?, " +
+	               "festival_cycle=?, ";
+
+	            for (int i = 0; i < (SevenSignsFestival.FESTIVAL_COUNT); i++)
+	                sqlQuery += "accumulated_bonus" + String.valueOf(i) + "=?, ";
+
+                sqlQuery += "date=? WHERE id=0";
+
+	            statement = con.prepareStatement(sqlQuery);
+	            statement.setInt(1, _currentCycle);
+	            statement.setInt(2, _activePeriod);
+	            statement.setInt(3, _previousWinner);
+	            statement.setDouble(4, _dawnStoneScore);
+	            statement.setInt(5, _dawnFestivalScore);
+	            statement.setDouble(6, _duskStoneScore);
+	            statement.setInt(7, _duskFestivalScore);
+	            statement.setInt(8, _signsSealOwners.get(SEAL_AVARICE));
+	            statement.setInt(9, _signsSealOwners.get(SEAL_GNOSIS));
+	            statement.setInt(10, _signsSealOwners.get(SEAL_STRIFE));
+	            statement.setInt(11, _signsDawnSealTotals.get(SEAL_AVARICE));
+	            statement.setInt(12, _signsDawnSealTotals.get(SEAL_GNOSIS));
+	            statement.setInt(13, _signsDawnSealTotals.get(SEAL_STRIFE));
+	            statement.setInt(14, _signsDuskSealTotals.get(SEAL_AVARICE));
+	            statement.setInt(15, _signsDuskSealTotals.get(SEAL_GNOSIS));
+	            statement.setInt(16, _signsDuskSealTotals.get(SEAL_STRIFE));
+	            statement.setInt(17, SevenSignsFestival.getInstance().getCurrentFestivalCycle());
+
+	            for (int i = 0; i < SevenSignsFestival.FESTIVAL_COUNT; i++)
+	                statement.setInt(18 + i, SevenSignsFestival.getInstance().getAccumulatedBonus(i));
+
+	            statement.setInt(18 + SevenSignsFestival.FESTIVAL_COUNT, Calendar.getInstance().get(Calendar.DAY_OF_WEEK));
+	            statement.execute();
+
+	            statement.close();
+		        con.close();
+
+	            if (Config.DEBUG)
+	                _log.info("SevenSigns: Updated data in database.");
+
+	        }
+		}
+		catch (SQLException e)
+		{
+			_log.severe("SevenSigns: Unable to save data to database: " + e);
+		}
+		finally
+        {
+    		try	{
+    		    statement.close();
+    		    con.close();
+    		}
+    		catch (Exception e) {}
+		}
+	}
+
+    /**
+     * Used to reset the cabal details of all players, and update the database.<BR>
+     * Primarily used when beginning a new cycle, and should otherwise never be called.
+     */
+    protected void resetPlayerData()
+	{
+		if (Config.DEBUG)
+			_log.info("SevenSigns: Resetting player data for new event period.");
+
+		// Reset each player's contribution data as well as seal and cabal.
+		for (StatsSet sevenDat : _signsPlayerData.values())
+		{
+		    int charObjId = sevenDat.getInteger("char_obj_id");
+
+			// Reset the player's cabal and seal information
+			sevenDat.set("cabal", "");
+			sevenDat.set("seal", SEAL_NULL);
+            sevenDat.set("contribution_score", 0);
+
+            _signsPlayerData.put(charObjId, sevenDat);
+		}
+	}
+
+	/**
+     * Tests whether the specified player has joined a cabal in the past.
+     *
+	 * @param player
+	 * @return boolean hasRegistered
+	 */
+	private boolean hasRegisteredBefore(L2PcInstance player)
+    {
+		return _signsPlayerData.containsKey(player.getObjectId());
+	}
+
+
+	/**
+     * Used to specify cabal-related details for the specified player. This method
+     * checks to see if the player has registered before and will update the database
+     * if necessary.
+     * <BR>
+     * Returns the cabal ID the player has joined.
+     *
+	 * @param player
+	 * @param chosenCabal
+	 * @param chosenSeal
+	 * @return int cabal
+	 */
+	public int setPlayerInfo(L2PcInstance player, int chosenCabal, int chosenSeal)
+	{
+		int charObjId = player.getObjectId();
+		Connection con = null;
+		PreparedStatement statement = null;
+		StatsSet currPlayerData = getPlayerData(player);
+
+		if (currPlayerData != null)
+		{
+			// If the seal validation period has passed,
+			// cabal information was removed and so "re-register" player
+			currPlayerData.set("cabal", getCabalShortName(chosenCabal));
+			currPlayerData.set("seal", chosenSeal);
+
+			_signsPlayerData.put(charObjId, currPlayerData);
+		}
+		else
+		{
+			currPlayerData = new StatsSet();
+			currPlayerData.set("char_obj_id", charObjId);
+			currPlayerData.set("cabal", getCabalShortName(chosenCabal));
+			currPlayerData.set("seal", chosenSeal);
+			currPlayerData.set("red_stones", 0);
+			currPlayerData.set("green_stones", 0);
+			currPlayerData.set("blue_stones", 0);
+			currPlayerData.set("ancient_adena_amount", 0);
+			currPlayerData.set("contribution_score", 0);
+
+			_signsPlayerData.put(charObjId, currPlayerData);
+
+			// Update data in database, as we have a new player signing up.
+			try
+			{
+				con = L2DatabaseFactory.getInstance().getConnection();
+				statement = con.prepareStatement(
+		    		"INSERT INTO seven_signs (char_obj_id, cabal, seal) VALUES (?,?,?)");
+				statement.setInt(1, charObjId);
+				statement.setString(2, getCabalShortName(chosenCabal));
+				statement.setInt(3, chosenSeal);
+				statement.execute();
+
+				statement.close();
+				con.close();
+
+				if (Config.DEBUG)
+					_log.info("SevenSigns: Inserted data in DB for char ID " + currPlayerData.getInteger("char_obj_id") + " (" + currPlayerData.getString("cabal") + ")");
+			}
+			catch (SQLException e)
+			{
+				_log.severe("SevenSigns: Failed to save data: " + e);
+			}
+			finally
+			{
+	    		try
+                {
+	    		    statement.close();
+	    		    con.close();
+	    		}
+	    		catch (Exception e) {}
+			}
+		}
+
+		// Increasing Seal total score for the player chosen Seal.
+		if (currPlayerData.getString("cabal") == "dawn")
+			_signsDawnSealTotals.put(chosenSeal, _signsDawnSealTotals.get(chosenSeal) + 1);
+		else
+			_signsDuskSealTotals.put(chosenSeal, _signsDuskSealTotals.get(chosenSeal) + 1);
+
+        saveSevenSignsData(player, true);
+
+		if (Config.DEBUG)
+			_log.info("SevenSigns: " + player.getName() + " has joined the " + getCabalName(chosenCabal) + " for the " + getSealName(chosenSeal, false) + "!");
+
+		return chosenCabal;
+	}
+
+	/**
+     * Returns the amount of ancient adena the specified player can claim, if any.<BR>
+     * If removeReward = True, all the ancient adena owed to them is removed, then
+     * DB is updated.
+     *
+	 * @param player
+	 * @param removeReward
+	 * @return int rewardAmount
+	 */
+	public int getAncientAdenaReward(L2PcInstance player, boolean removeReward)
+    {
+		StatsSet currPlayer = getPlayerData(player);
+		int rewardAmount = currPlayer.getInteger("ancient_adena_amount");
+
+		currPlayer.set("red_stones", 0);
+        currPlayer.set("green_stones", 0);
+        currPlayer.set("blue_stones", 0);
+        currPlayer.set("ancient_adena_amount", 0);
+
+		if (removeReward)
+		{
+			_signsPlayerData.put(player.getObjectId(), currPlayer);
+			saveSevenSignsData(player, true);
+		}
+
+		return rewardAmount;
+	}
+
+    /**
+     * Used to add the specified player's seal stone contribution points
+     * to the current total for their cabal. Returns the point score the
+     * contribution was worth.
+     *
+     * Each stone count <B>must be</B> broken down and specified by the stone's color.
+     *
+	 * @param player
+	 * @param blueCount
+	 * @param greenCount
+	 * @param redCount
+	 * @return int contribScore
+	 */
+	public int addPlayerStoneContrib(L2PcInstance player, int blueCount, int greenCount, int redCount)
+	{
+		StatsSet currPlayer = getPlayerData(player);
+
+		int contribScore = calcContributionScore(blueCount, greenCount, redCount);
+		int totalAncientAdena = currPlayer.getInteger("ancient_adena_amount") + calcAncientAdenaReward(blueCount, greenCount, redCount);
+		int totalContribScore = currPlayer.getInteger("contribution_score") + contribScore;
+
+		if (totalContribScore > Config.ALT_MAXIMUM_PLAYER_CONTRIB)
+			return -1;
+
+		currPlayer.set("red_stones", currPlayer.getInteger("red_stones") + redCount);
+		currPlayer.set("green_stones", currPlayer.getInteger("green_stones") + greenCount);
+		currPlayer.set("blue_stones", currPlayer.getInteger("blue_stones") + blueCount);
+		currPlayer.set("ancient_adena_amount", totalAncientAdena);
+		currPlayer.set("contribution_score", totalContribScore);
+		_signsPlayerData.put(player.getObjectId(), currPlayer);
+
+        switch (getPlayerCabal(player))
+        {
+            case CABAL_DAWN:
+                _dawnStoneScore += contribScore;
+                break;
+            case CABAL_DUSK:
+                _duskStoneScore += contribScore;
+                break;
+        }
+
+		saveSevenSignsData(player, true);
+
+		if (Config.DEBUG)
+			_log.info("SevenSigns: " + player.getName() + " contributed " + contribScore + " seal stone points to their cabal.");
+
+		return contribScore;
+	}
+
+	/**
+     * Adds the specified number of festival points to the specified cabal.
+     * Remember, the same number of points are <B>deducted from the rival cabal</B>
+     * to maintain proportionality.
+     *
+	 * @param cabal
+	 * @param amount
+	 */
+	public void addFestivalScore(int cabal, int amount)
+    {
+		if (cabal == CABAL_DUSK) {
+			_duskFestivalScore += amount;
+
+            // To prevent negative scores!
+            if (_dawnFestivalScore >= amount)
+                _dawnFestivalScore -= amount;
+        }
+		else {
+			_dawnFestivalScore += amount;
+
+            if (_duskFestivalScore >= amount)
+                _duskFestivalScore -= amount;
+        }
+	}
+
+	/**
+     * Send info on the current Seven Signs period to the specified player.
+     *
+	 * @param player
+	 */
+	public void sendCurrentPeriodMsg(L2PcInstance player)
+	{
+        SystemMessage sm = null;
+
+    	switch (getCurrentPeriod())
+        {
+            case PERIOD_COMP_RECRUITING:
+                sm = new SystemMessage(SystemMessageId.PREPARATIONS_PERIOD_BEGUN);
+                break;
+            case PERIOD_COMPETITION:
+                sm = new SystemMessage(SystemMessageId.COMPETITION_PERIOD_BEGUN);
+                break;
+            case PERIOD_COMP_RESULTS:
+                sm = new SystemMessage(SystemMessageId.RESULTS_PERIOD_BEGUN);
+                break;
+            case PERIOD_SEAL_VALIDATION:
+                sm = new SystemMessage(SystemMessageId.VALIDATION_PERIOD_BEGUN);
+                break;
+        }
+
+   		player.sendPacket(sm);
+	}
+
+	/**
+     * Sends the built-in system message specified by sysMsgId to all online players.
+     *
+	 * @param sysMsgId
+	 */
+	public void sendMessageToAll(SystemMessageId sysMsgId)
+	{
+        SystemMessage sm = new SystemMessage(sysMsgId);
+
+		for (L2PcInstance player : L2World.getInstance().getAllPlayers())
+			player.sendPacket(sm);
+	}
+
+    /**
+     * Used to initialize the seals for each cabal. (Used at startup or at beginning of a new cycle).
+     * This method should  be called after <B>resetSeals()</B> and <B>calcNewSealOwners()</B> on a new cycle.
+     */
+    protected void initializeSeals()
+	{
+		for (Integer currSeal : _signsSealOwners.keySet())
+		{
+			int sealOwner = _signsSealOwners.get(currSeal);
+
+			if (sealOwner != CABAL_NULL)
+				if (isSealValidationPeriod())
+					_log.info("SevenSigns: The " + getCabalName(sealOwner) + " have won the " + getSealName(currSeal, false) + ".");
+				else
+					_log.info("SevenSigns: The " + getSealName(currSeal, false) + " is currently owned by " + getCabalName(sealOwner) + ".");
+			else
+				_log.info("SevenSigns: The " + getSealName(currSeal, false) + " remains unclaimed.");
+		}
+	}
+
+    /**
+     * Only really used at the beginning of a new cycle, this method resets all seal-related data.
+     */
+    protected void resetSeals()
+	{
+		_signsDawnSealTotals.put(SEAL_AVARICE, 0);
+		_signsDawnSealTotals.put(SEAL_GNOSIS, 0);
+		_signsDawnSealTotals.put(SEAL_STRIFE, 0);
+		_signsDuskSealTotals.put(SEAL_AVARICE, 0);
+		_signsDuskSealTotals.put(SEAL_GNOSIS, 0);
+		_signsDuskSealTotals.put(SEAL_STRIFE, 0);
+	}
+
+    /**
+     * Calculates the ownership of the three Seals of the Seven Signs,
+     * based on various criterion.
+     * <BR><BR>
+     * Should only ever called at the beginning of a new cycle.
+     */
+    protected void calcNewSealOwners()
+	{
+		if (Config.DEBUG)
+		{
+			_log.info("SevenSigns: (Avarice) Dawn = " + _signsDawnSealTotals.get(SEAL_AVARICE) + ", Dusk = " + _signsDuskSealTotals.get(SEAL_AVARICE));
+			_log.info("SevenSigns: (Gnosis) Dawn = " + _signsDawnSealTotals.get(SEAL_GNOSIS) + ", Dusk = " + _signsDuskSealTotals.get(SEAL_GNOSIS));
+			_log.info("SevenSigns: (Strife) Dawn = " + _signsDawnSealTotals.get(SEAL_STRIFE) + ", Dusk = " + _signsDuskSealTotals.get(SEAL_STRIFE));
+		}
+
+		for (Integer currSeal : _signsDawnSealTotals.keySet())
+		{
+			int prevSealOwner = _signsSealOwners.get(currSeal);
+			int newSealOwner = CABAL_NULL;
+			int dawnProportion = getSealProportion(currSeal, CABAL_DAWN);
+			int totalDawnMembers = getTotalMembers(CABAL_DAWN) == 0 ? 1 : getTotalMembers(CABAL_DAWN);
+            int dawnPercent = Math.round(((float)dawnProportion / (float)totalDawnMembers) * 100);
+			int duskProportion = getSealProportion(currSeal, CABAL_DUSK);
+			int totalDuskMembers = getTotalMembers(CABAL_DUSK) == 0 ? 1 : getTotalMembers(CABAL_DUSK);
+            int duskPercent = Math.round(((float)duskProportion / (float)totalDuskMembers) * 100);
+
+			/*
+			 * - If a Seal was already closed or owned by the opponent and the new winner wants
+			 *   to assume ownership of the Seal, 35% or more of the members of the Cabal must
+			 *   have chosen the Seal. If they chose less than 35%, they cannot own the Seal.
+			 *
+			 * - If the Seal was owned by the winner in the previous Seven Signs, they can retain
+			 *   that seal if 10% or more members have chosen it. If they want to possess a new Seal,
+			 *   at least 35% of the members of the Cabal must have chosen the new Seal.
+			 */
+			switch (prevSealOwner)
+			{
+				case CABAL_NULL:
+					switch (getCabalHighestScore())
+					{
+						case CABAL_NULL:
+							newSealOwner = CABAL_NULL;
+							break;
+						case CABAL_DAWN:
+							if (dawnPercent >= 35)
+								newSealOwner = CABAL_DAWN;
+							else
+								newSealOwner = CABAL_NULL;
+							break;
+						case CABAL_DUSK:
+							if (duskPercent >= 35)
+								newSealOwner = CABAL_DUSK;
+							else
+								newSealOwner = CABAL_NULL;
+							break;
+					}
+					break;
+				case CABAL_DAWN:
+					switch (getCabalHighestScore())
+					{
+						case CABAL_NULL:
+							if (dawnPercent >= 10)
+								newSealOwner = CABAL_DAWN;
+							else
+								newSealOwner = CABAL_NULL;
+							break;
+						case CABAL_DAWN:
+							if (dawnPercent >= 10)
+								newSealOwner = CABAL_DAWN;
+							else
+								newSealOwner = CABAL_NULL;
+							break;
+						case CABAL_DUSK:
+							if (duskPercent >= 35)
+								newSealOwner = CABAL_DUSK;
+							else if (dawnPercent >= 10)
+								newSealOwner = CABAL_DAWN;
+							else
+								newSealOwner = CABAL_NULL;
+							break;
+					}
+					break;
+				case CABAL_DUSK:
+					switch (getCabalHighestScore())
+					{
+						case CABAL_NULL:
+							if (duskPercent >= 10)
+								newSealOwner = CABAL_DUSK;
+							else
+								newSealOwner = CABAL_NULL;
+							break;
+						case CABAL_DAWN:
+							if (dawnPercent >= 35)
+								newSealOwner = CABAL_DAWN;
+							else if (duskPercent >= 10)
+								newSealOwner = CABAL_DUSK;
+							else
+								newSealOwner = CABAL_NULL;
+							break;
+						case CABAL_DUSK:
+							if (duskPercent >= 10)
+								newSealOwner = CABAL_DUSK;
+							else
+								newSealOwner = CABAL_NULL;
+							break;
+					}
+					break;
+			}
+
+			_signsSealOwners.put(currSeal, newSealOwner);
+
+			// Alert all online players to new seal status.
+			switch (currSeal)
+			{
+				case SEAL_AVARICE:
+					if (newSealOwner == CABAL_DAWN)
+						sendMessageToAll(SystemMessageId.DAWN_OBTAINED_AVARICE);
+					else if (newSealOwner == CABAL_DUSK)
+						sendMessageToAll(SystemMessageId.DUSK_OBTAINED_AVARICE);
+					break;
+				case SEAL_GNOSIS:
+					if (newSealOwner == CABAL_DAWN)
+						sendMessageToAll(SystemMessageId.DAWN_OBTAINED_GNOSIS);
+					else if (newSealOwner == CABAL_DUSK)
+						sendMessageToAll(SystemMessageId.DUSK_OBTAINED_GNOSIS);
+					break;
+				case SEAL_STRIFE:
+					if (newSealOwner == CABAL_DAWN)
+						sendMessageToAll(SystemMessageId.DAWN_OBTAINED_STRIFE);
+					else if (newSealOwner == CABAL_DUSK)
+						sendMessageToAll(SystemMessageId.DUSK_OBTAINED_STRIFE);
+
+					CastleManager.getInstance().validateTaxes(newSealOwner);
+					break;
+			}
+		}
+	}
+
+    /**
+     * This method is called to remove all players from catacombs and
+     * necropolises, who belong to the losing cabal.
+     * <BR><BR>
+     * Should only ever called at the beginning of Seal Validation.
+     */
+    protected void teleLosingCabalFromDungeons(String compWinner)
+    {
+        for (L2PcInstance onlinePlayer : L2World.getInstance().getAllPlayers())
+        {
+			StatsSet currPlayer = getPlayerData(onlinePlayer);
+
+            if (isSealValidationPeriod() || isCompResultsPeriod())
+            {
+                if (!onlinePlayer.isGM() && onlinePlayer.isIn7sDungeon() && !currPlayer.getString("cabal").equals(compWinner))
+                {
+                    onlinePlayer.teleToLocation(MapRegionTable.TeleportWhereType.Town);
+                    onlinePlayer.setIsIn7sDungeon(false);
+                    onlinePlayer.sendMessage("You have been teleported to the nearest town due to the beginning of the Seal Validation period.");
+                }
+            }
+            else
+            {
+                if (!onlinePlayer.isGM() && onlinePlayer.isIn7sDungeon() && !currPlayer.getString("cabal").equals(""))
+                {
+                    onlinePlayer.teleToLocation(MapRegionTable.TeleportWhereType.Town);
+                    onlinePlayer.setIsIn7sDungeon(false);
+                    onlinePlayer.sendMessage("You have been teleported to the nearest town because you have not signed for any cabal.");
+                }
+            }
+        }
+    }
+
+	/**
+     * The primary controller of period change of the Seven Signs system.
+     * This runs all related tasks depending on the period that is about to begin.
+     *
+	 * @author Tempy
+	 */
+	protected class SevenSignsPeriodChange implements Runnable
+	{
+        public void run()
+        {
+            /*
+             * Remember the period check here refers to the period just ENDED!
+             */
+            final int periodEnded = getCurrentPeriod();
+            _activePeriod++;
+
+	        switch (periodEnded)
+	        {
+	            case PERIOD_COMP_RECRUITING: // Initialization
+
+                    // Start the Festival of Darkness cycle.
+                    SevenSignsFestival.getInstance().startFestivalManager();
+
+                    // Send message that Competition has begun.
+                    sendMessageToAll(SystemMessageId.QUEST_EVENT_PERIOD_BEGUN);
+	                break;
+	            case PERIOD_COMPETITION: // Results Calculation
+
+	                // Send message that Competition has ended.
+	                sendMessageToAll(SystemMessageId.QUEST_EVENT_PERIOD_ENDED);
+
+	                int compWinner = getCabalHighestScore();
+
+	                // Schedule a stop of the festival engine.
+	                SevenSignsFestival.getInstance().getFestivalManagerSchedule().cancel(false);
+
+                    calcNewSealOwners();
+
+                    switch (compWinner)
+                    {
+                    	case CABAL_DAWN:
+                    		sendMessageToAll(SystemMessageId.DAWN_WON);
+                    		break;
+                    	case CABAL_DUSK:
+                    		sendMessageToAll(SystemMessageId.DUSK_WON);
+                    		break;
+                    }
+
+                    _previousWinner = compWinner;
+	                break;
+	            case PERIOD_COMP_RESULTS: // Seal Validation
+
+                    // Perform initial Seal Validation set up.
+                    initializeSeals();
+
+                    // Send message that Seal Validation has begun.
+                    sendMessageToAll(SystemMessageId.SEAL_VALIDATION_PERIOD_BEGUN);
+
+                    _log.info("SevenSigns: The " + getCabalName(_previousWinner) + " have won the competition with " + getCurrentScore(_previousWinner) + " points!");
+	                break;
+	            case PERIOD_SEAL_VALIDATION: // Reset for New Cycle
+
+	            	SevenSignsFestival.getInstance().rewardHighestRanked(); // reward highest ranking members from cycle
+
+	                // Ensure a cycle restart when this period ends.
+                    _activePeriod = PERIOD_COMP_RECRUITING;
+
+	                // Send message that Seal Validation has ended.
+	                sendMessageToAll(SystemMessageId.SEAL_VALIDATION_PERIOD_ENDED);
+
+	                // Reset all data
+	                resetPlayerData();
+	                resetSeals();
+
+                    // Reset all Festival-related data and remove any unused blood offerings.
+                    // NOTE: A full update of Festival data in the database is also performed.
+                    SevenSignsFestival.getInstance().resetFestivalData(false);
+
+	                _dawnStoneScore = 0;
+	                _duskStoneScore = 0;
+
+	                _dawnFestivalScore = 0;
+	                _duskFestivalScore = 0;
+
+	                _currentCycle++;
+	                break;
+	        }
+
+	        // Make sure all Seven Signs data is saved for future use.
+	        saveSevenSignsData(null, true);
+
+            teleLosingCabalFromDungeons(getCabalShortName(getCabalHighestScore()));
+
+            SSQInfo ss = new SSQInfo();
+
+	        for (L2PcInstance player : L2World.getInstance().getAllPlayers())
+	            player.sendPacket(ss);
+
+            spawnSevenSignsNPC();
+
+            _log.info("SevenSigns: The " + getCurrentPeriodName() + " period has begun!");
+
+            setCalendarForNextPeriodChange();
+
+	        SevenSignsPeriodChange sspc = new SevenSignsPeriodChange();
+	        ThreadPoolManager.getInstance().scheduleGeneral(sspc, getMilliToPeriodChange());
+	    }
+	}
+}

+ 2414 - 0
L2_GameServer_T1/java/net/sf/l2j/gameserver/SevenSignsFestival.java

@@ -0,0 +1,2414 @@
+/* This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+package net.sf.l2j.gameserver;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ScheduledFuture;
+import java.util.logging.Logger;
+
+import javolution.util.FastList;
+import javolution.util.FastMap;
+import net.sf.l2j.Config;
+import net.sf.l2j.L2DatabaseFactory;
+import net.sf.l2j.gameserver.ai.CtrlIntention;
+import net.sf.l2j.gameserver.datatables.ClanTable;
+import net.sf.l2j.gameserver.datatables.MapRegionTable;
+import net.sf.l2j.gameserver.datatables.NpcTable;
+import net.sf.l2j.gameserver.datatables.SpawnTable;
+import net.sf.l2j.gameserver.model.L2CharPosition;
+import net.sf.l2j.gameserver.model.L2Clan;
+import net.sf.l2j.gameserver.model.L2ItemInstance;
+import net.sf.l2j.gameserver.model.L2Party;
+import net.sf.l2j.gameserver.model.L2Spawn;
+import net.sf.l2j.gameserver.model.L2World;
+import net.sf.l2j.gameserver.model.SpawnListener;
+import net.sf.l2j.gameserver.model.actor.instance.L2FestivalMonsterInstance;
+import net.sf.l2j.gameserver.model.actor.instance.L2NpcInstance;
+import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
+import net.sf.l2j.gameserver.model.base.Experience;
+import net.sf.l2j.gameserver.network.SystemMessageId;
+import net.sf.l2j.gameserver.serverpackets.CreatureSay;
+import net.sf.l2j.gameserver.serverpackets.MagicSkillUse;
+import net.sf.l2j.gameserver.serverpackets.PledgeShowInfoUpdate;
+import net.sf.l2j.gameserver.serverpackets.SystemMessage;
+import net.sf.l2j.gameserver.templates.L2NpcTemplate;
+import net.sf.l2j.gameserver.templates.StatsSet;
+import net.sf.l2j.gameserver.util.Util;
+import net.sf.l2j.util.Rnd;
+
+/**
+ *  Seven Signs Festival of Darkness Engine
+ *
+ *  TODO:
+ *  - Archer mobs should target healer characters over other party members.
+ *  - ADDED 29 Sep: Players that leave a party during the Seven Signs Festival will now take damage and cannot be healed.
+ *
+ *  @author Tempy
+ */
+public class SevenSignsFestival implements SpawnListener
+{
+    protected static final Logger _log = Logger.getLogger(SevenSignsFestival.class.getName());
+    private static SevenSignsFestival _instance;
+
+    private static final String GET_CLAN_NAME = "SELECT clan_name FROM clan_data WHERE clan_id = (SELECT clanid FROM characters WHERE char_name = ?)";
+
+    /**
+     * These length settings are important! :)
+     * All times are relative to the ELAPSED time (in ms) since a festival begins.
+     *
+     * Festival manager start is the time after the server starts to begin the first
+     * festival cycle.
+     *
+     * The cycle length should ideally be at least 2x longer than the festival length.
+     * This allows ample time for players to sign-up to participate in the festival.
+     *
+     * The intermission is the time between the festival participants being moved
+     * to the "arenas" and the spawning of the first set of mobs.
+     *
+     * The monster swarm time is the time before the monsters swarm to the center of the arena,
+     * after they are spawned.
+     *
+     * The chest spawn time is for when the bonus festival chests spawn, usually
+     * towards the end of the festival.
+     */
+    public static final long FESTIVAL_SIGNUP_TIME = Config.ALT_FESTIVAL_CYCLE_LENGTH - Config.ALT_FESTIVAL_LENGTH - 60000;
+
+    // Key Constants \\
+    private static final int FESTIVAL_MAX_OFFSET_X = 230;
+    private static final int FESTIVAL_MAX_OFFSET_Y = 230;
+    private static final int FESTIVAL_DEFAULT_RESPAWN = 60; // Specify in seconds!
+
+    public static final int FESTIVAL_COUNT = 5;
+    public static final int FESTIVAL_LEVEL_MAX_31 = 0;
+    public static final int FESTIVAL_LEVEL_MAX_42 = 1;
+    public static final int FESTIVAL_LEVEL_MAX_53 = 2;
+    public static final int FESTIVAL_LEVEL_MAX_64 = 3;
+    public static final int FESTIVAL_LEVEL_MAX_NONE = 4;
+    public static final int[] FESTIVAL_LEVEL_SCORES = {60, 70, 100, 120, 150}; // 500 maximum possible score
+
+    public static final int FESTIVAL_OFFERING_ID = 5901;
+    public static final int FESTIVAL_OFFERING_VALUE = 5;
+
+    //////////////////////// \\\\\\\\\\\\\\\\\\\\\\\\\\
+    /*
+    * The following contains all the necessary spawn data for:
+    * - Player Start Locations
+    * - Witches
+    * - Monsters
+    * - Chests
+    *
+    * All data is given by: X, Y, Z (coords), Heading, NPC ID (if necessary)
+    * This may be moved externally in time, but the data should not change.
+    */
+    public static final int[][] FESTIVAL_DAWN_PLAYER_SPAWNS =
+    {
+         {-79187, 113186, -4895, 0}, // 31 and below
+         {-75918, 110137, -4895, 0}, // 42 and below
+         {-73835, 111969, -4895, 0}, // 53 and below
+         {-76170, 113804, -4895, 0}, // 64 and below
+         {-78927, 109528, -4895, 0}  // No level limit
+    };
+
+    public static final int[][] FESTIVAL_DUSK_PLAYER_SPAWNS =
+    {
+         {-77200, 88966, -5151, 0}, // 31 and below
+         {-76941, 85307, -5151, 0}, // 42 and below
+         {-74855, 87135, -5151, 0}, // 53 and below
+         {-80208, 88222, -5151, 0}, // 64 and below
+         {-79954, 84697, -5151, 0}  // No level limit
+    };
+
+    protected static final int[][] FESTIVAL_DAWN_WITCH_SPAWNS =
+    {
+         {-79183, 113052, -4891, 0, 31132}, // 31 and below
+         {-75916, 110270, -4891, 0, 31133}, // 42 and below
+         {-73979, 111970, -4891, 0, 31134}, // 53 and below
+         {-76174, 113663, -4891, 0, 31135}, // 64 and below
+         {-78930, 109664, -4891, 0, 31136}  // No level limit
+    };
+
+    protected static final int[][] FESTIVAL_DUSK_WITCH_SPAWNS =
+    {
+         {-77199, 88830, -5147, 0, 31142}, // 31 and below
+         {-76942, 85438, -5147, 0, 31143}, // 42 and below
+         {-74990, 87135, -5147, 0, 31144}, // 53 and below
+         {-80207, 88222, -5147, 0, 31145}, // 64 and below
+         {-79952, 84833, -5147, 0, 31146}  // No level limit
+    };
+
+    protected static final int[][][] FESTIVAL_DAWN_PRIMARY_SPAWNS =
+    {
+     {
+         /* Level 31 and Below - Offering of the Branded */
+         {-78537, 113839, -4895, -1, 18009},
+         {-78466, 113852, -4895, -1, 18010},
+         {-78509, 113899, -4895, -1, 18010},
+
+         {-78481, 112557, -4895, -1, 18009},
+         {-78559, 112504, -4895, -1, 18010},
+         {-78489, 112494, -4895, -1, 18010},
+
+         {-79803, 112543, -4895, -1, 18012},
+         {-79854, 112492, -4895, -1, 18013},
+         {-79886, 112557, -4895, -1, 18014},
+
+         {-79821, 113811, -4895, -1, 18015},
+         {-79857, 113896, -4895, -1, 18017},
+         {-79878, 113816, -4895, -1, 18018},
+
+         // Archers and Marksmen \\
+         {-79190, 113660, -4895, -1, 18011},
+         {-78710, 113188, -4895, -1, 18011},
+         {-79190, 112730, -4895, -1, 18016},
+         {-79656, 113188, -4895, -1, 18016}
+     },
+     {
+         /* Level 42 and Below - Apostate Offering */
+         {-76558, 110784, -4895, -1, 18019},
+         {-76607, 110815, -4895, -1, 18020}, // South West
+         {-76559, 110820, -4895, -1, 18020},
+
+         {-75277, 110792, -4895, -1, 18019},
+         {-75225, 110801, -4895, -1, 18020}, // South East
+         {-75262, 110832, -4895, -1, 18020},
+
+         {-75249, 109441, -4895, -1, 18022},
+         {-75278, 109495, -4895, -1, 18023}, // North East
+         {-75223, 109489, -4895, -1, 18024},
+
+         {-76556, 109490, -4895, -1, 18025},
+         {-76607, 109469, -4895, -1, 18027}, // North West
+         {-76561, 109450, -4895, -1, 18028},
+
+         // Archers and Marksmen \\
+         {-76399, 110144, -4895, -1, 18021},
+         {-75912, 110606, -4895, -1, 18021},
+         {-75444, 110144, -4895, -1, 18026},
+         {-75930, 109665, -4895, -1, 18026}
+     },
+     {
+         /* Level 53 and Below - Witch's Offering */
+         {-73184, 111319, -4895, -1, 18029},
+         {-73135, 111294, -4895, -1, 18030}, // South West
+         {-73185, 111281, -4895, -1, 18030},
+
+         {-74477, 111321, -4895, -1, 18029},
+         {-74523, 111293, -4895, -1, 18030}, // South East
+         {-74481, 111280, -4895, -1, 18030},
+
+         {-74489, 112604, -4895, -1, 18032},
+         {-74491, 112660, -4895, -1, 18033}, // North East
+         {-74527, 112629, -4895, -1, 18034},
+
+         {-73197, 112621, -4895, -1, 18035},
+         {-73142, 112631, -4895, -1, 18037}, // North West
+         {-73182, 112656, -4895, -1, 18038},
+
+         // Archers and Marksmen \\
+         {-73834, 112430, -4895, -1, 18031},
+         {-74299, 111959, -4895, -1, 18031},
+         {-73841, 111491, -4895, -1, 18036},
+         {-73363, 111959, -4895, -1, 18036}
+     },
+     {
+         /* Level 64 and Below - Dark Omen Offering */
+         {-75543, 114461, -4895, -1, 18039},
+         {-75514, 114493, -4895, -1, 18040}, // South West
+         {-75488, 114456, -4895, -1, 18040},
+
+         {-75521, 113158, -4895, -1, 18039},
+         {-75504, 113110, -4895, -1, 18040}, // South East
+         {-75489, 113142, -4895, -1, 18040},
+
+         {-76809, 113143, -4895, -1, 18042},
+         {-76860, 113138, -4895, -1, 18043}, // North East
+         {-76831, 113112, -4895, -1, 18044},
+
+         {-76831, 114441, -4895, -1, 18045},
+         {-76840, 114490, -4895, -1, 18047}, // North West
+         {-76864, 114455, -4895, -1, 18048},
+
+         // Archers and Marksmen \\
+         {-75703, 113797, -4895, -1, 18041},
+         {-76180, 114263, -4895, -1, 18041},
+         {-76639, 113797, -4895, -1, 18046},
+         {-76180, 113337, -4895, -1, 18046}
+     },
+     {
+         /* No Level Limit - Offering of Forbidden Path */
+         {-79576, 108881, -4895, -1, 18049},
+         {-79592, 108835, -4895, -1, 18050}, // South West
+         {-79614, 108871, -4895, -1, 18050},
+
+         {-79586, 110171, -4895, -1, 18049},
+         {-79589, 110216, -4895, -1, 18050}, // South East
+         {-79620, 110177, -4895, -1, 18050},
+
+         {-78825, 110182, -4895, -1, 18052},
+         {-78238, 110182, -4895, -1, 18053}, // North East
+         {-78266, 110218, -4895, -1, 18054},
+
+         {-78275, 108883, -4895, -1, 18055},
+         {-78267, 108839, -4895, -1, 18057}, // North West
+         {-78241, 108871, -4895, -1, 18058},
+
+         // Archers and Marksmen \\
+         {-79394, 109538, -4895, -1, 18051},
+         {-78929, 109992, -4895, -1, 18051},
+         {-78454, 109538, -4895, -1, 18056},
+         {-78929, 109053, -4895, -1, 18056}
+     }
+    };
+
+    protected static final int[][][] FESTIVAL_DUSK_PRIMARY_SPAWNS =
+    {
+     {
+         /* Level 31 and Below - Offering of the Branded */
+         {-76542, 89653, -5151, -1, 18009},
+         {-76509, 89637, -5151, -1, 18010},
+         {-76548, 89614, -5151, -1, 18010},
+
+         {-76539, 88326, -5151, -1, 18009},
+         {-76512, 88289, -5151, -1, 18010},
+         {-76546, 88287, -5151, -1, 18010},
+
+         {-77879, 88308, -5151, -1, 18012},
+         {-77886, 88310, -5151, -1, 18013},
+         {-77879, 88278, -5151, -1, 18014},
+
+         {-77857, 89605, -5151, -1, 18015},
+         {-77858, 89658, -5151, -1, 18017},
+         {-77891, 89633, -5151, -1, 18018},
+
+         // Archers and Marksmen \\
+         {-76728, 88962, -5151, -1, 18011},
+         {-77194, 88494, -5151, -1, 18011},
+         {-77660, 88896, -5151, -1, 18016},
+         {-77195, 89438, -5151, -1, 18016}
+     },
+     {
+         /* Level 42 and Below - Apostate's Offering */
+         {-77585, 84650, -5151, -1, 18019},
+         {-77628, 84643, -5151, -1, 18020},
+         {-77607, 84613, -5151, -1, 18020},
+
+         {-76603, 85946, -5151, -1, 18019},
+         {-77606, 85994, -5151, -1, 18020},
+         {-77638, 85959, -5151, -1, 18020},
+
+         {-76301, 85960, -5151, -1, 18022},
+         {-76257, 85972, -5151, -1, 18023},
+         {-76286, 85992, -5151, -1, 18024},
+
+         {-76281, 84667, -5151, -1, 18025},
+         {-76291, 84611, -5151, -1, 18027},
+         {-76257, 84616, -5151, -1, 18028},
+
+         // Archers and Marksmen \\
+         {-77419, 85307, -5151, -1, 18021},
+         {-76952, 85768, -5151, -1, 18021},
+         {-76477, 85312, -5151, -1, 18026},
+         {-76942, 84832, -5151, -1, 18026}
+     },
+     {
+         /* Level 53 and Below - Witch's Offering */
+         {-74211, 86494, -5151, -1, 18029},
+         {-74200, 86449, -5151, -1, 18030},
+         {-74167, 86464, -5151, -1, 18030},
+
+         {-75495, 86482, -5151, -1, 18029},
+         {-75540, 86473, -5151, -1, 18030},
+         {-75509, 86445, -5151, -1, 18030},
+
+         {-75509, 87775, -5151, -1, 18032},
+         {-75518, 87826, -5151, -1, 18033},
+         {-75542, 87780, -5151, -1, 18034},
+
+         {-74214, 87789, -5151, -1, 18035},
+         {-74169, 87801, -5151, -1, 18037},
+         {-74198, 87827, -5151, -1, 18038},
+
+         // Archers and Marksmen \\
+         {-75324, 87135, -5151, -1, 18031},
+         {-74852, 87606, -5151, -1, 18031},
+         {-74388, 87146, -5151, -1, 18036},
+         {-74856, 86663, -5151, -1, 18036}
+     },
+     {
+         /* Level 64 and Below - Dark Omen Offering */
+         {-79560, 89007, -5151, -1, 18039},
+         {-79521, 89016, -5151, -1, 18040},
+         {-79544, 89047, -5151, -1, 18040},
+
+         {-79552, 87717, -5151, -1, 18039},
+         {-79552, 87673, -5151, -1, 18040},
+         {-79510, 87702, -5151, -1, 18040},
+
+         {-80866, 87719, -5151, -1, 18042},
+         {-80897, 87689, -5151, -1, 18043},
+         {-80850, 87685, -5151, -1, 18044},
+
+         {-80848, 89013, -5151, -1, 18045},
+         {-80887, 89051, -5151, -1, 18047},
+         {-80891, 89004, -5151, -1, 18048},
+
+         // Archers and Marksmen \\
+         {-80205, 87895, -5151, -1, 18041},
+         {-80674, 88350, -5151, -1, 18041},
+         {-80209, 88833, -5151, -1, 18046},
+         {-79743, 88364, -5151, -1, 18046}
+     },
+     {
+         /* No Level Limit - Offering of Forbidden Path */
+         {-80624, 84060, -5151, -1, 18049},
+         {-80621, 84007, -5151, -1, 18050},
+         {-80590, 84039, -5151, -1, 18050},
+
+         {-80605, 85349, -5151, -1, 18049},
+         {-80639, 85363, -5151, -1, 18050},
+         {-80611, 85385, -5151, -1, 18050},
+
+         {-79311, 85353, -5151, -1, 18052},
+         {-79277, 85384, -5151, -1, 18053},
+         {-79273, 85539, -5151, -1, 18054},
+
+         {-79297, 84054, -5151, -1, 18055},
+         {-79285, 84006, -5151, -1, 18057},
+         {-79260, 84040, -5151, -1, 18058},
+
+         // Archers and Marksmen \\
+         {-79945, 85171, -5151, -1, 18051},
+         {-79489, 84707, -5151, -1, 18051},
+         {-79952, 84222, -5151, -1, 18056},
+         {-80423, 84703, -5151, -1, 18056}
+     }
+    };
+
+    protected static final int[][][] FESTIVAL_DAWN_SECONDARY_SPAWNS =
+    {
+     {
+         /* 31 and Below */
+         {-78757, 112834, -4895, -1, 18016},
+         {-78581, 112834, -4895, -1, 18016},
+
+         {-78822, 112526, -4895, -1, 18011},
+         {-78822, 113702, -4895, -1, 18011},
+         {-78822, 113874, -4895, -1, 18011},
+
+         {-79524, 113546, -4895, -1, 18011},
+         {-79693, 113546, -4895, -1, 18011},
+         {-79858, 113546, -4895, -1, 18011},
+
+         {-79545, 112757, -4895, -1, 18016},
+         {-79545, 112586, -4895, -1, 18016},
+     },
+     {
+         /* 42 and Below */
+         {-75565, 110580, -4895, -1, 18026},
+         {-75565, 110740, -4895, -1, 18026},
+
+         {-75577, 109776, -4895, -1, 18021},
+         {-75413, 109776, -4895, -1, 18021},
+         {-75237, 109776, -4895, -1, 18021},
+
+         {-76274, 109468, -4895, -1, 18021},
+         {-76274, 109635, -4895, -1, 18021},
+         {-76274, 109795, -4895, -1, 18021},
+
+         {-76351, 110500, -4895, -1, 18056},
+         {-76528, 110500, -4895, -1, 18056},
+     },
+     {
+         /* 53 and Below */
+         {-74191, 111527, -4895, -1, 18036},
+         {-74191, 111362, -4895, -1, 18036},
+
+         {-73495, 111611, -4895, -1, 18031},
+         {-73327, 111611, -4895, -1, 18031},
+         {-73154, 111611, -4895, -1, 18031},
+
+         {-73473, 112301, -4895, -1, 18031},
+         {-73473, 112475, -4895, -1, 18031},
+         {-73473, 112649, -4895, -1, 18031},
+
+         {-74270, 112326, -4895, -1, 18036},
+         {-74443, 112326, -4895, -1, 18036},
+     },
+     {
+         /* 64 and Below */
+         {-75738, 113439, -4895, -1, 18046},
+         {-75571, 113439, -4895, -1, 18046},
+
+         {-75824, 114141, -4895, -1, 18041},
+         {-75824, 114309, -4895, -1, 18041},
+         {-75824, 114477, -4895, -1, 18041},
+
+         {-76513, 114158, -4895, -1, 18041},
+         {-76683, 114158, -4895, -1, 18041},
+         {-76857, 114158, -4895, -1, 18041},
+
+         {-76535, 113357, -4895, -1, 18056},
+         {-76535, 113190, -4895, -1, 18056},
+     },
+     {
+         /* No Level Limit */
+         {-79350, 109894, -4895, -1, 18056},
+         {-79534, 109894, -4895, -1, 18056},
+
+         {-79285, 109187, -4895, -1, 18051},
+         {-79285, 109019, -4895, -1, 18051},
+         {-79285, 108860, -4895, -1, 18051},
+
+         {-78587, 109172, -4895, -1, 18051},
+         {-78415, 109172, -4895, -1, 18051},
+         {-78249, 109172, -4895, -1, 18051},
+
+         {-78575, 109961, -4895, -1, 18056},
+         {-78575, 110130, -4895, -1, 18056},
+     }
+    };
+
+    protected static final int[][][] FESTIVAL_DUSK_SECONDARY_SPAWNS =
+    {
+     {
+         /* 31 and Below */
+         {-76844, 89304, -5151, -1, 18011},
+         {-76844, 89479, -5151, -1, 18011},
+         {-76844, 89649, -5151, -1, 18011},
+
+         {-77544, 89326, -5151, -1, 18011},
+         {-77716, 89326, -5151, -1, 18011},
+         {-77881, 89326, -5151, -1, 18011},
+
+         {-77561, 88530, -5151, -1, 18016},
+         {-77561, 88364, -5151, -1, 18016},
+
+         {-76762, 88615, -5151, -1, 18016},
+         {-76594, 88615, -5151, -1, 18016},
+     },
+     {
+         /* 42 and Below */
+         {-77307, 84969, -5151, -1, 18021},
+         {-77307, 84795, -5151, -1, 18021},
+         {-77307, 84623, -5151, -1, 18021},
+
+         {-76614, 84944, -5151, -1, 18021},
+         {-76433, 84944, -5151, -1, 18021},
+         {-7626-1, 84944, -5151, -1, 18021},
+
+         {-76594, 85745, -5151, -1, 18026},
+         {-76594, 85910, -5151, -1, 18026},
+
+         {-77384, 85660, -5151, -1, 18026},
+         {-77555, 85660, -5151, -1, 18026},
+     },
+     {
+         /* 53 and Below */
+         {-74517, 86782, -5151, -1, 18031},
+         {-74344, 86782, -5151, -1, 18031},
+         {-74185, 86782, -5151, -1, 18031},
+
+         {-74496, 87464, -5151, -1, 18031},
+         {-74496, 87636, -5151, -1, 18031},
+         {-74496, 87815, -5151, -1, 18031},
+
+         {-75298, 87497, -5151, -1, 18036},
+         {-75460, 87497, -5151, -1, 18036},
+
+         {-75219, 86712, -5151, -1, 18036},
+         {-75219, 86531, -5151, -1, 18036},
+     },
+     {
+         /* 64 and Below */
+         {-79851, 88703, -5151, -1, 18041},
+         {-79851, 88868, -5151, -1, 18041},
+         {-79851, 89040, -5151, -1, 18041},
+
+         {-80548, 88722, -5151, -1, 18041},
+         {-80711, 88722, -5151, -1, 18041},
+         {-80883, 88722, -5151, -1, 18041},
+
+         {-80565, 87916, -5151, -1, 18046},
+         {-80565, 87752, -5151, -1, 18046},
+
+         {-79779, 87996, -5151, -1, 18046},
+         {-79613, 87996, -5151, -1, 18046},
+     },
+     {
+         /* No Level Limit */
+         {-79271, 84330, -5151, -1, 18051},
+         {-79448, 84330, -5151, -1, 18051},
+         {-79601, 84330, -5151, -1, 18051},
+
+         {-80311, 84367, -5151, -1, 18051},
+         {-80311, 84196, -5151, -1, 18051},
+         {-80311, 84015, -5151, -1, 18051},
+
+         {-80556, 85049, -5151, -1, 18056},
+         {-80384, 85049, -5151, -1, 18056},
+
+         {-79598, 85127, -5151, -1, 18056},
+         {-79598, 85303, -5151, -1, 18056},
+     }
+    };
+
+    protected static final int[][][] FESTIVAL_DAWN_CHEST_SPAWNS =
+    {
+     {
+         /* Level 31 and Below */
+         {-78999, 112957, -4927, -1, 18109},
+         {-79153, 112873, -4927, -1, 18109},
+         {-79256, 112873, -4927, -1, 18109},
+         {-79368, 112957, -4927, -1, 18109},
+
+         {-79481, 113124, -4927, -1, 18109},
+         {-79481, 113275, -4927, -1, 18109},
+
+         {-79364, 113398, -4927, -1, 18109},
+         {-79213, 113500, -4927, -1, 18109},
+         {-79099, 113500, -4927, -1, 18109},
+         {-78960, 113398, -4927, -1, 18109},
+
+         {-78882, 113235, -4927, -1, 18109},
+         {-78882, 113099, -4927, -1, 18109},
+     },
+     {
+         /* Level 42 and Below */
+         {-76119, 110383, -4927, -1, 18110},
+         {-75980, 110442, -4927, -1, 18110},
+         {-75848, 110442, -4927, -1, 18110},
+         {-75720, 110383, -4927, -1, 18110},
+
+         {-75625, 110195, -4927, -1, 18110},
+         {-75625, 110063, -4927, -1, 18110},
+
+         {-75722, 109908, -4927, -1, 18110},
+         {-75863, 109832, -4927, -1, 18110},
+         {-75989, 109832, -4927, -1, 18110},
+         {-76130, 109908, -4927, -1, 18110},
+
+         {-76230, 110079, -4927, -1, 18110},
+         {-76230, 110215, -4927, -1, 18110},
+     },
+     {
+         /* Level 53 and Below */
+         {-74055, 111781, -4927, -1, 18111},
+         {-74144, 111938, -4927, -1, 18111},
+         {-74144, 112075, -4927, -1, 18111},
+         {-74055, 112173, -4927, -1, 18111},
+
+         {-73885, 112289, -4927, -1, 18111},
+         {-73756, 112289, -4927, -1, 18111},
+
+         {-73574, 112141, -4927, -1, 18111},
+         {-73511, 112040, -4927, -1, 18111},
+         {-73511, 111912, -4927, -1, 18111},
+         {-73574, 111772, -4927, -1, 18111},
+
+         {-73767, 111669, -4927, -1, 18111},
+         {-73899, 111669, -4927, -1, 18111},
+     },
+     {
+         /* Level 64 and Below */
+         {-76008, 113566, -4927, -1, 18112},
+         {-76159, 113485, -4927, -1, 18112},
+         {-76267, 113485, -4927, -1, 18112},
+         {-76386, 113566, -4927, -1, 18112},
+
+         {-76482, 113748, -4927, -1, 18112},
+         {-76482, 113885, -4927, -1, 18112},
+
+         {-76371, 114029, -4927, -1, 18112},
+         {-76220, 114118, -4927, -1, 18112},
+         {-76092, 114118, -4927, -1, 18112},
+         {-75975, 114029, -4927, -1, 18112},
+
+         {-75861, 11385-1, -4927, -1, 18112},
+         {-75861, 113713, -4927, -1, 18112},
+     },
+     {
+         /* No Level Limit */
+         {-79100, 109782, -4927, -1, 18113},
+         {-78962, 109853, -4927, -1, 18113},
+         {-78851, 109853, -4927, -1, 18113},
+         {-78721, 109782, -4927, -1, 18113},
+
+         {-78615, 109596, -4927, -1, 18113},
+         {-78615, 109453, -4927, -1, 18113},
+
+         {-78746, 109300, -4927, -1, 18113},
+         {-78881, 109203, -4927, -1, 18113},
+         {-79027, 109203, -4927, -1, 18113},
+         {-79159, 109300, -4927, -1, 18113},
+
+         {-79240, 109480, -4927, -1, 18113},
+         {-79240, 109615, -4927, -1, 18113},
+     }
+    };
+
+    protected static final int[][][] FESTIVAL_DUSK_CHEST_SPAWNS =
+    {
+     {
+         /* Level 31 and Below */
+         {-77016, 88726, -5183, -1, 18114},
+         {-77136, 88646, -5183, -1, 18114},
+         {-77247, 88646, -5183, -1, 18114},
+         {-77380, 88726, -5183, -1, 18114},
+
+         {-77512, 88883, -5183, -1, 18114},
+         {-77512, 89053, -5183, -1, 18114},
+
+         {-77378, 89287, -5183, -1, 18114},
+         {-77254, 89238, -5183, -1, 18114},
+         {-77095, 89238, -5183, -1, 18114},
+         {-76996, 89287, -5183, -1, 18114},
+
+         {-76901, 89025, -5183, -1, 18114},
+         {-76901, 88891, -5183, -1, 18114},
+     },
+     {
+         /* Level 42 and Below */
+         {-77128, 85553, -5183, -1, 18115},
+         {-77036, 85594, -5183, -1, 18115},
+         {-76919, 85594, -5183, -1, 18115},
+         {-76755, 85553, -5183, -1, 18115},
+
+         {-76635, 85392, -5183, -1, 18115},
+         {-76635, 85216, -5183, -1, 18115},
+
+         {-76761, 85025, -5183, -1, 18115},
+         {-76908, 85004, -5183, -1, 18115},
+         {-77041, 85004, -5183, -1, 18115},
+         {-77138, 85025, -5183, -1, 18115},
+
+         {-77268, 85219, -5183, -1, 18115},
+         {-77268, 85410, -5183, -1, 18115},
+     },
+     {
+         /* Level 53 and Below */
+         {-75150, 87303, -5183, -1, 18116},
+         {-75150, 87175, -5183, -1, 18116},
+         {-75150, 87175, -5183, -1, 18116},
+         {-75150, 87303, -5183, -1, 18116},
+
+         {-74943, 87433, -5183, -1, 18116},
+         {-74767, 87433, -5183, -1, 18116},
+
+         {-74556, 87306, -5183, -1, 18116},
+         {-74556, 87184, -5183, -1, 18116},
+         {-74556, 87184, -5183, -1, 18116},
+         {-74556, 87306, -5183, -1, 18116},
+
+         {-74757, 86830, -5183, -1, 18116},
+         {-74927, 86830, -5183, -1, 18116},
+     },
+     {
+         /* Level 64 and Below */
+         {-80010, 88128, -5183, -1, 18117},
+         {-80113, 88066, -5183, -1, 18117},
+         {-80220, 88066, -5183, -1, 18117},
+         {-80359, 88128, -5183, -1, 18117},
+
+         {-80467, 88267, -5183, -1, 18117},
+         {-80467, 88436, -5183, -1, 18117},
+
+         {-80381, 88639, -5183, -1, 18117},
+         {-80278, 88577, -5183, -1, 18117},
+         {-80142, 88577, -5183, -1, 18117},
+         {-80028, 88639, -5183, -1, 18117},
+
+         {-79915, 88466, -5183, -1, 18117},
+         {-79915, 88322, -5183, -1, 18117},
+     },
+     {
+         /* No Level Limit */
+         {-80153, 84947, -5183, -1, 18118},
+         {-80003, 84962, -5183, -1, 18118},
+         {-79848, 84962, -5183, -1, 18118},
+         {-79742, 84947, -5183, -1, 18118},
+
+         {-79668, 84772, -5183, -1, 18118},
+         {-79668, 84619, -5183, -1, 18118},
+
+         {-79772, 84471, -5183, -1, 18118},
+         {-79888, 84414, -5183, -1, 18118},
+         {-80023, 84414, -5183, -1, 18118},
+         {-80166, 84471, -5183, -1, 18118},
+
+         {-80253, 84600, -5183, -1, 18118},
+         {-80253, 84780, -5183, -1, 18118},
+     }
+    };
+
+    //////////////////////// \\\\\\\\\\\\\\\\\\\\\\\\\\
+
+    protected FestivalManager _managerInstance;
+    protected ScheduledFuture<?> _managerScheduledTask;
+
+    protected int _signsCycle = SevenSigns.getInstance().getCurrentCycle();
+    protected int _festivalCycle;
+    protected long _nextFestivalCycleStart;
+    protected long _nextFestivalStart;
+    protected boolean _festivalInitialized;
+    protected boolean _festivalInProgress;
+    protected List<Integer> _accumulatedBonuses;   // The total bonus available (in Ancient Adena)
+
+    private L2NpcInstance _dawnChatGuide;
+    private L2NpcInstance _duskChatGuide;
+
+    protected Map<Integer, List<L2PcInstance>> _dawnFestivalParticipants;
+    protected Map<Integer, List<L2PcInstance>> _duskFestivalParticipants;
+
+    protected Map<Integer, List<L2PcInstance>> _dawnPreviousParticipants;
+    protected Map<Integer, List<L2PcInstance>> _duskPreviousParticipants;
+
+    private Map<Integer, Integer> _dawnFestivalScores;
+    private Map<Integer, Integer> _duskFestivalScores;
+
+    /**
+     * _festivalData is essentially an instance of the seven_signs_festival table and
+     * should be treated as such.
+     *
+     * Data is initially accessed by the related Seven Signs cycle, with _signsCycle representing
+     * data for the current round of Festivals.
+     *
+     * The actual table data is stored as a series of StatsSet constructs. These are accessed by
+     * the use of an offset based on the number of festivals, thus:
+     *
+     *  offset = FESTIVAL_COUNT + festivalId
+     *  (Data for Dawn is always accessed by offset > FESTIVAL_COUNT)
+     */
+    private Map<Integer, Map<Integer, StatsSet>> _festivalData;
+
+    public SevenSignsFestival()
+    {
+        _accumulatedBonuses = new FastList<Integer>();
+
+        _dawnFestivalParticipants = new FastMap<Integer, List<L2PcInstance>>();
+        _dawnPreviousParticipants = new FastMap<Integer, List<L2PcInstance>>();
+        _dawnFestivalScores = new FastMap<Integer, Integer>();
+
+        _duskFestivalParticipants = new FastMap<Integer, List<L2PcInstance>>();
+        _duskPreviousParticipants = new FastMap<Integer, List<L2PcInstance>>();
+        _duskFestivalScores = new FastMap<Integer, Integer>();
+
+        _festivalData = new FastMap<Integer, Map<Integer, StatsSet>>();
+
+        restoreFestivalData();
+
+        if (SevenSigns.getInstance().isSealValidationPeriod())
+        {
+            _log.info("SevenSignsFestival: Initialization bypassed due to Seal Validation in effect.");
+            return;
+        }
+
+        L2Spawn.addSpawnListener(this);
+        startFestivalManager();
+    }
+
+    public static SevenSignsFestival getInstance()
+    {
+        if (_instance == null)
+            _instance = new SevenSignsFestival();
+
+        return _instance;
+    }
+
+    /**
+     * Returns the associated name (level range) to a given festival ID.
+     *
+     * @param int festivalID
+     * @return String festivalName
+     */
+    public static final String getFestivalName(int festivalID)
+    {
+        String festivalName;
+
+        switch (festivalID)
+        {
+            case FESTIVAL_LEVEL_MAX_31:
+                festivalName = "Level 31 or lower";
+                break;
+            case FESTIVAL_LEVEL_MAX_42:
+                festivalName = "Level 42 or lower";
+                break;
+            case FESTIVAL_LEVEL_MAX_53:
+                festivalName = "Level 53 or lower";
+                break;
+            case FESTIVAL_LEVEL_MAX_64:
+                festivalName = "Level 64 or lower";
+                break;
+            default:
+                festivalName = "No Level Limit";
+            break;
+        }
+
+        return festivalName;
+    }
+
+    /**
+     * Returns the maximum allowed player level for the given festival type.
+     *
+     * @param festivalId
+     * @return int maxLevel
+     */
+    public static final int getMaxLevelForFestival(int festivalId)
+    {
+        int maxLevel = (Experience.MAX_LEVEL - 1);
+
+        switch (festivalId)
+        {
+            case SevenSignsFestival.FESTIVAL_LEVEL_MAX_31:
+                maxLevel = 31;
+                break;
+            case SevenSignsFestival.FESTIVAL_LEVEL_MAX_42:
+                maxLevel = 42;
+                break;
+            case SevenSignsFestival.FESTIVAL_LEVEL_MAX_53:
+                maxLevel = 53;
+                break;
+            case SevenSignsFestival.FESTIVAL_LEVEL_MAX_64:
+                maxLevel = 64;
+                break;
+        }
+
+        return maxLevel;
+    }
+
+    /**
+     * Returns true if the monster ID given is of an archer/marksman type.
+     *
+     * @param npcId
+     * @return boolean isArcher
+     */
+    protected static final boolean isFestivalArcher(int npcId)
+    {
+        if (npcId < 18009 || npcId > 18108)
+            return false;
+
+        int identifier = npcId%10;
+        return (identifier == 4 || identifier == 9);
+    }
+
+    /**
+     * Returns true if the monster ID given is a festival chest.
+     *
+     * @param npcId
+     * @return boolean isChest
+     */
+    protected static final boolean isFestivalChest(int npcId)
+    {
+        return (npcId < 18109 || npcId > 18118);
+    }
+
+    /**
+     * Primarily used to terminate the Festival Manager, when the Seven Signs period changes.
+     *
+     * @return ScheduledFuture festManagerScheduler
+     */
+    protected final ScheduledFuture<?> getFestivalManagerSchedule()
+    {
+        if (_managerScheduledTask == null)
+            startFestivalManager();
+
+        return _managerScheduledTask;
+    }
+
+    /**
+     * Used to start the Festival Manager, if the current period is not Seal Validation.
+     */
+    protected void startFestivalManager()
+    {
+        // Start the Festival Manager for the first time after the server has started
+        // at the specified time, then invoke it automatically after every cycle.
+        FestivalManager fm = new FestivalManager();
+        setNextFestivalStart(Config.ALT_FESTIVAL_MANAGER_START + FESTIVAL_SIGNUP_TIME);
+        _managerScheduledTask = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(fm, Config.ALT_FESTIVAL_MANAGER_START, Config.ALT_FESTIVAL_CYCLE_LENGTH);
+
+        _log.info("SevenSignsFestival: The first Festival of Darkness cycle begins in " + (Config.ALT_FESTIVAL_MANAGER_START / 60000) + " minute(s).");
+    }
+
+    /**
+     * Restores saved festival data, basic settings from the properties file
+     * and past high score data from the database.
+     *
+     * @throws Exception
+     */
+    protected void restoreFestivalData()
+    {
+        Connection con = null;
+        PreparedStatement statement = null;
+        ResultSet rset = null;
+
+        if (Config.DEBUG)
+            _log.info("SevenSignsFestival: Restoring festival data. Current SS Cycle: " + _signsCycle);
+
+        try
+        {
+	        con = L2DatabaseFactory.getInstance().getConnection();
+	        statement = con.prepareStatement("SELECT festivalId, cabal, cycle, date, score, members " +
+	            "FROM seven_signs_festival");
+	        rset = statement.executeQuery();
+
+	        while (rset.next())
+	        {
+	            int festivalCycle = rset.getInt("cycle");
+	            int festivalId = rset.getInt("festivalId");
+	            String cabal = rset.getString("cabal");
+
+	            StatsSet festivalDat = new StatsSet();
+	            festivalDat.set("festivalId", festivalId);
+	            festivalDat.set("cabal", cabal);
+	            festivalDat.set("cycle", festivalCycle);
+	            festivalDat.set("date", rset.getString("date"));
+	            festivalDat.set("score", rset.getInt("score"));
+	            festivalDat.set("members", rset.getString("members"));
+
+	            if (Config.DEBUG)
+	                _log.info("SevenSignsFestival: Loaded data from DB for (Cycle = " + festivalCycle + ", Oracle = " + cabal + ", Festival = "+ getFestivalName(festivalId));
+
+	            if (cabal.equals("dawn"))
+	                festivalId += FESTIVAL_COUNT;
+
+	            Map<Integer, StatsSet> tempData = _festivalData.get(festivalCycle);
+
+	            if (tempData == null)
+	                tempData = new FastMap<Integer, StatsSet>();
+
+	            tempData.put(festivalId, festivalDat);
+	            _festivalData.put(festivalCycle, tempData);
+	        }
+
+	        rset.close();
+	        statement.close();
+
+	        String query = "SELECT festival_cycle, ";
+
+	        for (int i = 0; i < FESTIVAL_COUNT-1; i++)
+
+	            query += "accumulated_bonus" + String.valueOf(i) + ", ";
+	        query += "accumulated_bonus" + String.valueOf(FESTIVAL_COUNT -1) + " ";
+	        query += "FROM seven_signs_status WHERE id=0";
+
+	        statement = con.prepareStatement(query);
+	        rset = statement.executeQuery();
+
+	        while (rset.next())
+	        {
+	            _festivalCycle = rset.getInt("festival_cycle");
+
+	            for(int i = 0; i < FESTIVAL_COUNT; i++)
+	                _accumulatedBonuses.add(i, rset.getInt("accumulated_bonus" + String.valueOf(i)));
+	        }
+
+	        rset.close();
+	        statement.close();
+	        con.close();
+
+	        if (Config.DEBUG)
+	            _log.info("SevenSignsFestival: Loaded data from database.");
+        }
+        catch (SQLException e)
+        {
+            _log.severe("SevenSignsFestival: Failed to load configuration: " + e);
+        }
+        finally
+        {
+        	try
+        	{
+        	    rset.close();
+        	    statement.close();
+        	    con.close();
+        	}
+        	catch (SQLException e) {}
+        }
+     }
+
+    /**
+     * Stores current festival data, basic settings to the properties file
+     * and past high score data to the database.
+     *
+     * If updateSettings = true, then all Seven Signs data is updated in the database.
+     *
+     * @param updateSettings
+     * @throws Exception
+     */
+    public void saveFestivalData(boolean updateSettings)
+    {
+    	Connection con = null;
+    	PreparedStatement statement = null;
+
+    	if (Config.DEBUG)
+            System.out.println("SevenSignsFestival: Saving festival data to disk.");
+
+        try
+        {
+        	con = L2DatabaseFactory.getInstance().getConnection();
+
+        	for (Map<Integer, StatsSet> currCycleData : _festivalData.values())
+	        {
+	            for (StatsSet festivalDat : currCycleData.values())
+	            {
+	                int festivalCycle = festivalDat.getInteger("cycle");
+	                int festivalId = festivalDat.getInteger("festivalId");
+	                String cabal = festivalDat.getString("cabal");
+
+	                // Try to update an existing record.
+	                statement = con.prepareStatement(
+	                    "UPDATE seven_signs_festival SET date=?, score=?, members=? WHERE cycle=? AND cabal=? AND festivalId=?");
+	                statement.setLong(1, Long.valueOf(festivalDat.getString("date")));
+	                statement.setInt(2, festivalDat.getInteger("score"));
+	                statement.setString(3, festivalDat.getString("members"));
+	                statement.setInt(4, festivalCycle);
+	                statement.setString(5, cabal);
+	                statement.setInt(6, festivalId);
+
+	                // If there was no record to update, assume it doesn't exist and add a new one,
+	                // otherwise continue with the next record to store.
+	                if (statement.executeUpdate() > 0)
+	                {
+	                    if (Config.DEBUG)
+	                        _log.info("SevenSignsFestival: Updated data in DB (Cycle = " + festivalCycle + ", Cabal = " + cabal + ", FestID = " + festivalId + ")");
+
+		                statement.close();
+	                    continue;
+	                }
+
+	                statement.close();
+
+	            	statement = con.prepareStatement(
+	                    "INSERT INTO seven_signs_festival (festivalId, cabal, cycle, date, score, members) VALUES (?,?,?,?,?,?)");
+	                statement.setInt(1, festivalId);
+	                statement.setString(2, cabal);
+	                statement.setInt(3, festivalCycle);
+	                statement.setLong(4, Long.valueOf(festivalDat.getString("date")));
+	                statement.setInt(5, festivalDat.getInteger("score"));
+	                statement.setString(6, festivalDat.getString("members"));
+	                statement.execute();
+	                statement.close();
+
+	                if (Config.DEBUG)
+	                    _log.info("SevenSignsFestival: Inserted data in DB (Cycle = " + festivalCycle + ", Cabal = " + cabal + ", FestID = " + festivalId + ")");
+	            }
+	        }
+
+        	con.close();
+
+	        // Updates Seven Signs DB data also, so call only if really necessary.
+	        if (updateSettings)
+	            SevenSigns.getInstance().saveSevenSignsData(null, true);
+        }
+        catch (SQLException e)
+        {
+        	_log.severe("SevenSignsFestival: Failed to save configuration: " + e);
+        }
+        finally
+        {
+        	try
+        	{
+        	    statement.close();
+        	    con.close();
+        	}
+        	catch (Exception e) {}
+        }
+    }
+
+    /**
+     * If a clan member is a member of the highest-ranked party in the Festival of Darkness, 100 points are added per member
+     */
+    protected void rewardHighestRanked()
+    {
+    	String[] partyMembers;
+    	StatsSet overallData = getOverallHighestScoreData(FESTIVAL_LEVEL_MAX_31);
+        if (overallData != null)
+    	{
+    		partyMembers = overallData.getString("members").split(",");
+    		for (String partyMemberName : partyMembers)
+    			addReputationPointsForPartyMemberClan(partyMemberName);
+    	}
+
+    	overallData = getOverallHighestScoreData(FESTIVAL_LEVEL_MAX_42);
+    	if (overallData != null)
+    	{
+    		partyMembers = overallData.getString("members").split(",");
+    		for (String partyMemberName : partyMembers)
+    			addReputationPointsForPartyMemberClan(partyMemberName);
+    	}
+
+    	overallData = getOverallHighestScoreData(FESTIVAL_LEVEL_MAX_53);
+    	if (overallData != null)
+    	{
+    		partyMembers = overallData.getString("members").split(",");
+    		for (String partyMemberName : partyMembers)
+    			addReputationPointsForPartyMemberClan(partyMemberName);
+    	}
+
+    	overallData = getOverallHighestScoreData(FESTIVAL_LEVEL_MAX_64);
+    	if (overallData != null)
+    	{
+    		partyMembers = overallData.getString("members").split(",");
+    		for (String partyMemberName : partyMembers)
+    			addReputationPointsForPartyMemberClan(partyMemberName);
+    	}
+
+    	overallData = getOverallHighestScoreData(FESTIVAL_LEVEL_MAX_NONE);
+    	if (overallData != null)
+    	{
+    		partyMembers = overallData.getString("members").split(",");
+    		for (String partyMemberName : partyMembers)
+    			addReputationPointsForPartyMemberClan(partyMemberName);
+    	}
+    }
+
+    private void addReputationPointsForPartyMemberClan(String partyMemberName)
+    {
+    	L2PcInstance player = L2World.getInstance().getPlayer(partyMemberName);
+		if (player != null)
+		{
+			if (player.getClan() != null)
+			{
+				player.getClan().setReputationScore(player.getClan().getReputationScore()+100, true);
+				player.getClan().broadcastToOnlineMembers(new PledgeShowInfoUpdate(player.getClan()));
+				SystemMessage sm = new SystemMessage(SystemMessageId.CLAN_MEMBER_S1_WAS_IN_HIGHEST_RANKED_PARTY_IN_FESTIVAL_OF_DARKNESS_AND_GAINED_S2_REPUTATION);
+                sm.addString(partyMemberName);
+                sm.addNumber(100);
+				player.getClan().broadcastToOnlineMembers(sm);
+			}
+		}
+		else
+		{
+			java.sql.Connection con = null;
+
+        	try
+        	{
+        		con = L2DatabaseFactory.getInstance().getConnection();
+        		PreparedStatement statement = con.prepareStatement(GET_CLAN_NAME);
+        		statement.setString(1, partyMemberName);
+        		ResultSet rset = statement.executeQuery();
+        		if (rset.next())
+        		{
+        			String clanName = rset.getString("clan_name");
+        			if (clanName != null)
+        			{
+        				L2Clan clan = ClanTable.getInstance().getClanByName(clanName);
+        				if (clan != null)
+        				{
+        					clan.setReputationScore(clan.getReputationScore()+100, true);
+        					clan.broadcastToOnlineMembers(new PledgeShowInfoUpdate(clan));
+        					SystemMessage sm = new SystemMessage(SystemMessageId.CLAN_MEMBER_S1_WAS_IN_HIGHEST_RANKED_PARTY_IN_FESTIVAL_OF_DARKNESS_AND_GAINED_S2_REPUTATION);
+        	                sm.addString(partyMemberName);
+        	                sm.addNumber(100);
+        					clan.broadcastToOnlineMembers(sm);
+        				}
+        			}
+        		}
+
+        		rset.close();
+        		statement.close();
+        	}
+        	catch (Exception e)
+        	{
+        		_log.warning("could not get clan name of " + partyMemberName + ": "+e);
+        	}
+        	finally
+        	{
+        		try { con.close(); } catch (Exception e) {}
+        	}
+		}
+    }
+
+
+    /**
+     * Used to reset all festival data at the beginning of a new quest event period.
+     */
+    protected void resetFestivalData(boolean updateSettings)
+    {
+        _festivalCycle = 0;
+        _signsCycle = SevenSigns.getInstance().getCurrentCycle();
+
+        // Set all accumulated bonuses back to 0.
+        for (int i = 0; i < FESTIVAL_COUNT; i++)
+            _accumulatedBonuses.set(i, 0);
+
+        _dawnFestivalParticipants.clear();
+        _dawnPreviousParticipants.clear();
+        _dawnFestivalScores.clear();
+
+        _duskFestivalParticipants.clear();
+        _duskPreviousParticipants.clear();
+        _duskFestivalScores.clear();
+
+        // Set up a new data set for the current cycle of festivals
+        Map<Integer, StatsSet> newData = new FastMap<Integer, StatsSet>();
+
+        for (int i = 0; i < FESTIVAL_COUNT * 2; i++)
+        {
+            int festivalId = i;
+
+            if (i >= FESTIVAL_COUNT)
+                festivalId -= FESTIVAL_COUNT;
+
+            // Create a new StatsSet with "default" data for Dusk
+            StatsSet tempStats = new StatsSet();
+            tempStats.set("festivalId", festivalId);
+            tempStats.set("cycle", _signsCycle);
+            tempStats.set("date", "0");
+            tempStats.set("score", 0);
+            tempStats.set("members", "");
+
+            if (i >= FESTIVAL_COUNT)
+                tempStats.set("cabal", SevenSigns.getCabalShortName(SevenSigns.CABAL_DAWN));
+            else
+                tempStats.set("cabal", SevenSigns.getCabalShortName(SevenSigns.CABAL_DUSK));
+
+            newData.put(i, tempStats);
+        }
+
+        // Add the newly created cycle data to the existing festival data, and
+        // subsequently save it to the database.
+        _festivalData.put(_signsCycle, newData);
+
+        saveFestivalData(updateSettings);
+
+        // Remove any unused blood offerings from online players.
+        for (L2PcInstance onlinePlayer : L2World.getInstance().getAllPlayers())
+        {
+            try {
+            	L2ItemInstance bloodOfferings = onlinePlayer.getInventory().getItemByItemId(FESTIVAL_OFFERING_ID);
+
+            	if (bloodOfferings != null)
+            		onlinePlayer.destroyItem("SevenSigns", bloodOfferings, null, false);
+            } catch (NullPointerException e) {}
+        }
+
+        _log.info("SevenSignsFestival: Reinitialized engine for next competition period.");
+    }
+
+
+    public final int getCurrentFestivalCycle()
+    {
+        return _festivalCycle;
+    }
+
+    public final boolean isFestivalInitialized()
+    {
+        return _festivalInitialized;
+    }
+
+    public final boolean isFestivalInProgress()
+    {
+        return _festivalInProgress;
+    }
+
+    public void setNextCycleStart()
+    {
+        _nextFestivalCycleStart = System.currentTimeMillis() + Config.ALT_FESTIVAL_CYCLE_LENGTH;
+    }
+
+    public void setNextFestivalStart(long milliFromNow)
+    {
+        _nextFestivalStart = System.currentTimeMillis() + milliFromNow;
+    }
+
+    public final int getMinsToNextCycle()
+    {
+        if (SevenSigns.getInstance().isSealValidationPeriod())
+            return -1;
+
+        return Math.round((_nextFestivalCycleStart - System.currentTimeMillis()) / 60000);
+    }
+
+    public final int getMinsToNextFestival()
+    {
+        if (SevenSigns.getInstance().isSealValidationPeriod())
+            return -1;
+
+        return Math.round((_nextFestivalStart - System.currentTimeMillis()) / 60000) + 1;
+    }
+
+    public final String getTimeToNextFestivalStr()
+    {
+        if (SevenSigns.getInstance().isSealValidationPeriod())
+            return "<font color=\"FF0000\">This is the Seal Validation period. Festivals will resume next week.</font>";
+
+        return "<font color=\"FF0000\">The next festival will begin in " + getMinsToNextFestival() + " minute(s).</font>";
+    }
+
+    /**
+     * Returns the current festival ID and oracle ID that the specified player is in,
+     * but will return the default of {-1, -1} if the player is not found as a participant.
+     *
+     * @param player
+     * @return int[] playerFestivalInfo
+     */
+    public final int[] getFestivalForPlayer(L2PcInstance player)
+    {
+        int[] playerFestivalInfo = {-1, -1};
+        int festivalId = 0;
+
+        while (festivalId < FESTIVAL_COUNT)
+        {
+            List<L2PcInstance> participants = _dawnFestivalParticipants.get(festivalId);
+
+            // If there are no participants in this festival, move on to the next.
+            if (participants != null && participants.contains(player))
+            {
+                playerFestivalInfo[0] = SevenSigns.CABAL_DAWN;
+                playerFestivalInfo[1] = festivalId;
+
+                return playerFestivalInfo;
+            }
+
+            festivalId++;
+
+            participants = _duskFestivalParticipants.get(festivalId);
+
+            if (participants != null && participants.contains(player))
+            {
+                playerFestivalInfo[0] = SevenSigns.CABAL_DUSK;
+                playerFestivalInfo[1] = festivalId;
+
+                return playerFestivalInfo;
+            }
+
+            festivalId++;
+        }
+
+        // Return default data if the player is not found as a participant.
+        return playerFestivalInfo;
+    }
+
+    public final boolean isParticipant(L2PcInstance player)
+    {
+        if (SevenSigns.getInstance().isSealValidationPeriod())
+            return false;
+
+        if (_managerInstance == null)
+            return false;
+
+        for (List<L2PcInstance> participants : _dawnFestivalParticipants.values())
+            if (participants.contains(player))
+                return true;
+
+        for (List<L2PcInstance> participants : _duskFestivalParticipants.values())
+            if (participants.contains(player))
+                return true;
+
+        return false;
+    }
+
+    public final List<L2PcInstance> getParticipants(int oracle, int festivalId)
+    {
+        if (oracle == SevenSigns.CABAL_DAWN)
+            return _dawnFestivalParticipants.get(festivalId);
+
+        return _duskFestivalParticipants.get(festivalId);
+    }
+
+    public final List<L2PcInstance> getPreviousParticipants(int oracle, int festivalId)
+    {
+        if (oracle == SevenSigns.CABAL_DAWN)
+            return _dawnPreviousParticipants.get(festivalId);
+
+        return _duskPreviousParticipants.get(festivalId);
+    }
+
+    public void setParticipants(int oracle, int festivalId, L2Party festivalParty)
+    {
+        List<L2PcInstance> participants = new FastList<L2PcInstance>();
+
+        if (festivalParty != null)
+        {
+            participants = festivalParty.getPartyMembers();
+
+            if (Config.DEBUG)
+                _log.info("SevenSignsFestival: " + festivalParty.getPartyMembers().toString() +
+                    " have signed up to the " + SevenSigns.getCabalShortName(oracle) + " " + getFestivalName(festivalId) + " festival.");
+        }
+
+        if (oracle == SevenSigns.CABAL_DAWN)
+            _dawnFestivalParticipants.put(festivalId, participants);
+        else
+            _duskFestivalParticipants.put(festivalId, participants);
+    }
+
+    public void updateParticipants(L2PcInstance player, L2Party festivalParty)
+    {
+        if (!isParticipant(player))
+            return;
+
+        final int[] playerFestInfo = getFestivalForPlayer(player);
+        final int oracle = playerFestInfo[0];
+        final int festivalId = playerFestInfo[1];
+
+        if (festivalId > -1)
+        {
+            if (_festivalInitialized)
+            {
+                L2DarknessFestival festivalInst = _managerInstance.getFestivalInstance(oracle, festivalId);
+
+                if (festivalParty == null)
+                    for (L2PcInstance partyMember : getParticipants(oracle, festivalId))
+                        festivalInst.relocatePlayer(partyMember, true);
+                else
+                    festivalInst.relocatePlayer(player, true);
+            }
+
+            setParticipants(oracle, festivalId, festivalParty);
+        }
+    }
+
+    public final int getFinalScore(int oracle, int festivalId)
+    {
+        if (oracle == SevenSigns.CABAL_DAWN)
+            return _dawnFestivalScores.get(festivalId);
+
+        return _duskFestivalScores.get(festivalId);
+    }
+
+    public final int getHighestScore(int oracle, int festivalId)
+    {
+        return getHighestScoreData(oracle, festivalId).getInteger("score");
+    }
+
+    /**
+     * Returns a stats set containing the highest score <b>this cycle</b> for the
+     * the specified cabal and associated festival ID.
+     *
+     * @param oracle
+     * @param festivalId
+     * @return StatsSet festivalDat
+     */
+    public final StatsSet getHighestScoreData(int oracle, int festivalId)
+    {
+        int offsetId = festivalId;
+
+        if (oracle == SevenSigns.CABAL_DAWN)
+            offsetId += 5;
+
+        // Attempt to retrieve existing score data (if found), otherwise create a
+        // new blank data set and display a console warning.
+        StatsSet currData = null;
+
+        try
+        {
+            currData = _festivalData.get(_signsCycle).get(offsetId);
+        }
+        catch (Exception e)
+        {
+            currData = new StatsSet();
+            currData.set("score", 0);
+            currData.set("members", "");
+
+            if (Config.DEBUG)
+            	_log.info("SevenSignsFestival: Data missing for " + SevenSigns.getCabalName(oracle) + ", FestivalID = " + festivalId + " (Current Cycle " + _signsCycle + ")");
+        }
+
+        return currData;
+    }
+
+    /**
+     * Returns a stats set containing the highest ever recorded
+     * score data for the specified festival.
+     *
+     * @param festivalId
+     * @return StatsSet result
+     */
+    public final StatsSet getOverallHighestScoreData(int festivalId)
+    {
+        StatsSet result = null;
+        int highestScore = 0;
+
+        for (Map<Integer, StatsSet> currCycleData : _festivalData.values())
+        {
+            for (StatsSet currFestData : currCycleData.values())
+            {
+                int currFestID = currFestData.getInteger("festivalId");
+                int festivalScore = currFestData.getInteger("score");
+
+                if (currFestID != festivalId)
+                    continue;
+
+                if (festivalScore > highestScore)
+                {
+                    highestScore = festivalScore;
+                    result = currFestData;
+                }
+            }
+        }
+
+        return result;
+    }
+
+    /**
+     * Set the final score details for the last participants of the specified festival data.
+     * Returns <b>true</b> if the score is higher than that previously recorded <b>this cycle</b>.
+     *
+     * @param player
+     * @param oracle
+     * @param festivalId
+     * @param offeringScore
+     * @return boolean isHighestScore
+     */
+    public boolean setFinalScore(L2PcInstance player, int oracle, int festivalId, int offeringScore)
+    {
+        List<String> partyMembers;
+
+        int currDawnHighScore = getHighestScore(SevenSigns.CABAL_DAWN, festivalId);
+        int currDuskHighScore = getHighestScore(SevenSigns.CABAL_DUSK, festivalId);
+
+        int thisCabalHighScore = 0;
+        int otherCabalHighScore = 0;
+
+        if (oracle == SevenSigns.CABAL_DAWN)
+        {
+            thisCabalHighScore = currDawnHighScore;
+            otherCabalHighScore = currDuskHighScore;
+
+            _dawnFestivalScores.put(festivalId, offeringScore);
+        }
+        else
+        {
+            thisCabalHighScore = currDuskHighScore;
+            otherCabalHighScore = currDawnHighScore;
+
+            _duskFestivalScores.put(festivalId, offeringScore);
+        }
+
+        StatsSet currFestData = getHighestScoreData(oracle, festivalId);
+
+        // Check if this is the highest score for this level range so far for the player's cabal.
+        if (offeringScore > thisCabalHighScore)
+        {
+            // If the current score is greater than that for the other cabal,
+            // then they already have the points from this festival.
+            if (thisCabalHighScore > otherCabalHighScore)
+                return false;
+
+            partyMembers = new FastList<String>();
+            List<L2PcInstance> prevParticipants = getPreviousParticipants(oracle, festivalId);
+
+            // Record a string list of the party members involved.
+            for (L2PcInstance partyMember : prevParticipants)
+            {
+                try {
+                	partyMembers.add(partyMember.getName());
+                } catch (NullPointerException e) {}
+            }
+
+            // Update the highest scores and party list.
+            currFestData.set("date", String.valueOf(System.currentTimeMillis()));
+            currFestData.set("score", offeringScore);
+            currFestData.set("members", Util.implodeString(partyMembers, ","));
+
+            if (Config.DEBUG)
+                _log.info("SevenSignsFestival: " + player.getName() + "'s party has the highest score (" +
+                    offeringScore + ") so far for " + SevenSigns.getCabalName(oracle) + " in " + getFestivalName(festivalId));
+
+            // Only add the score to the cabal's overall if it's higher than the other cabal's score.
+            if (offeringScore > otherCabalHighScore)
+            {
+                int contribPoints = FESTIVAL_LEVEL_SCORES[festivalId];
+
+                // Give this cabal the festival points, while deducting them from the other.
+                SevenSigns.getInstance().addFestivalScore(oracle, contribPoints);
+
+                //if (Config.DEBUG)
+                    _log.info("SevenSignsFestival: This is the highest score overall so far for the " + getFestivalName(festivalId) + " festival!");
+            }
+
+            saveFestivalData(true);
+
+            return true;
+        }
+
+        return false;
+    }
+
+    public final int getAccumulatedBonus(int festivalId)
+    {
+        return _accumulatedBonuses.get(festivalId);
+    }
+
+    public final int getTotalAccumulatedBonus()
+    {
+        int totalAccumBonus = 0;
+
+        for (int accumBonus : _accumulatedBonuses)
+            totalAccumBonus += accumBonus;
+
+        return totalAccumBonus;
+    }
+
+    public void addAccumulatedBonus(int festivalId, int stoneType, int stoneAmount)
+    {
+        int eachStoneBonus = 0;
+
+        switch (stoneType)
+        {
+            case SevenSigns.SEAL_STONE_BLUE_ID:
+                eachStoneBonus = SevenSigns.SEAL_STONE_BLUE_VALUE;
+                break;
+            case SevenSigns.SEAL_STONE_GREEN_ID:
+                eachStoneBonus = SevenSigns.SEAL_STONE_GREEN_VALUE;
+                break;
+            case SevenSigns.SEAL_STONE_RED_ID:
+                eachStoneBonus = SevenSigns.SEAL_STONE_RED_VALUE;
+                break;
+        }
+
+        int newTotalBonus = _accumulatedBonuses.get(festivalId) + (stoneAmount * eachStoneBonus);
+        _accumulatedBonuses.set(festivalId, newTotalBonus);
+    }
+
+    /**
+     * Calculate and return the proportion of the accumulated bonus for the festival
+     * where the player was in the winning party, if the winning party's cabal won the event.
+     *
+     * The accumulated bonus is then updated, with the player's share deducted.
+     *
+     * @param player
+     * @return playerBonus (the share of the bonus for the party)
+     */
+    public final int distribAccumulatedBonus(L2PcInstance player)
+    {
+        int playerBonus = 0;
+        String playerName = player.getName();
+        int playerCabal = SevenSigns.getInstance().getPlayerCabal(player);
+
+        if (playerCabal != SevenSigns.getInstance().getCabalHighestScore())
+            return 0;
+
+        if (_festivalData.get(_signsCycle) != null)
+            for (StatsSet festivalData : _festivalData.get(_signsCycle).values())
+            {
+                if (festivalData.getString("members").indexOf(playerName) > -1)
+                {
+                    int festivalId = festivalData.getInteger("festivalId");
+                    int numPartyMembers = festivalData.getString("members").split(",").length;
+                    int totalAccumBonus = _accumulatedBonuses.get(festivalId);
+
+                    playerBonus = totalAccumBonus / numPartyMembers;
+                    _accumulatedBonuses.set(festivalId, totalAccumBonus - playerBonus);
+                    break;
+                }
+            }
+
+        return playerBonus;
+    }
+
+    /**
+     * Used to send a "shout" message to all players currently present in an Oracle.
+     * Primarily used for Festival Guide and Witch related speech.
+     *
+     * @param senderName
+     * @param message
+     */
+    public void sendMessageToAll(String senderName, String message)
+    {
+        if (_dawnChatGuide == null || _duskChatGuide == null)
+            return;
+
+        CreatureSay cs = new CreatureSay(_dawnChatGuide.getObjectId(), 1, senderName, message);
+        _dawnChatGuide.broadcastPacket(cs);
+
+        cs = new CreatureSay(_duskChatGuide.getObjectId(), 1, senderName, message);
+        _duskChatGuide.broadcastPacket(cs);
+    }
+
+    /**
+     * Basically a wrapper-call to signal to increase the challenge of the specified festival.
+     *
+     * @param oracle
+     * @param festivalId
+     * @return boolean isChalIncreased
+     */
+    public final boolean increaseChallenge(int oracle, int festivalId)
+    {
+        L2DarknessFestival festivalInst = _managerInstance.getFestivalInstance(oracle, festivalId);
+
+        return festivalInst.increaseChallenge();
+    }
+
+    /**
+     * Used with the SpawnListener, to update the required "chat guide" instances,
+     * for use with announcements in the oracles.
+     *
+     * @param npc
+     */
+    public void npcSpawned(L2NpcInstance npc)
+    {
+        if (npc == null)
+            return;
+
+        int npcId = npc.getNpcId();
+
+        // If the spawned NPC ID matches the ones we need, assign their instances.
+        if (npcId == 31127)
+        {
+            if (Config.DEBUG)
+                _log.config("SevenSignsFestival: Instance found for NPC ID 31127 (" + npc.getObjectId() + ").");
+
+            _dawnChatGuide = npc;
+        }
+
+        if (npcId == 31137)
+        {
+            if (Config.DEBUG)
+                _log.config("SevenSignsFestival: Instance found for NPC ID 31137 (" + npc.getObjectId() + ").");
+
+            _duskChatGuide = npc;
+        }
+    }
+
+
+    /**
+     * The FestivalManager class is the main runner of all the festivals.
+     * It is used for easier integration and management of all running festivals.
+     *
+     * @author Tempy
+     */
+    private class FestivalManager implements Runnable
+    {
+        protected Map<Integer, L2DarknessFestival> _festivalInstances;
+
+        public FestivalManager()
+        {
+            _festivalInstances = new FastMap<Integer, L2DarknessFestival>();
+            _managerInstance = this;
+
+            // Increment the cycle counter.
+            _festivalCycle++;
+
+            // Set the next start timers.
+            setNextCycleStart();
+            setNextFestivalStart(Config.ALT_FESTIVAL_CYCLE_LENGTH - FESTIVAL_SIGNUP_TIME);
+        }
+
+        public synchronized void run()
+        {
+            // The manager shouldn't be running if Seal Validation is in effect.
+            if (SevenSigns.getInstance().isSealValidationPeriod())
+                return;
+
+            // If the next period is due to start before the end of this
+            // festival cycle, then don't run it.
+            if (SevenSigns.getInstance().getMilliToPeriodChange() < Config.ALT_FESTIVAL_CYCLE_LENGTH)
+                return;
+
+            if (Config.DEBUG)
+                _log.info("SevenSignsFestival: Festival manager initialized. Those wishing to participate have " + getMinsToNextFestival() + " minute(s) to sign up.");
+
+            sendMessageToAll("Festival Guide", "The main event will start in " + getMinsToNextFestival() + " minutes. Please register now.");
+
+            // Stand by until the allowed signup period has elapsed.
+            try {
+                wait(FESTIVAL_SIGNUP_TIME);
+            }
+            catch (InterruptedException e) { }
+
+            // Clear past participants, they can no longer register their score if not done so already.
+            _dawnPreviousParticipants.clear();
+            _duskPreviousParticipants.clear();
+
+            // Get rid of random monsters that avoided deletion after last festival
+            for (L2DarknessFestival festivalInst : _festivalInstances.values())
+            	festivalInst.unspawnMobs();
+
+            /* INITIATION */
+            // Set the festival timer to 0, as it is just beginning.
+            long elapsedTime = 0;
+
+            // Create the instances for the festivals in both Oracles,
+            // but only if they have participants signed up for them.
+            for (int i = 0; i < FESTIVAL_COUNT; i++)
+            {
+                if (_duskFestivalParticipants.get(i) != null)
+                    _festivalInstances.put(10 + i, new L2DarknessFestival(SevenSigns.CABAL_DUSK, i));
+
+                if (_dawnFestivalParticipants.get(i) != null)
+                    _festivalInstances.put(20 + i, new L2DarknessFestival(SevenSigns.CABAL_DAWN, i));
+            }
+
+            // Prevent future signups while festival is in progress.
+            _festivalInitialized = true;
+
+            setNextFestivalStart(Config.ALT_FESTIVAL_CYCLE_LENGTH);
+            sendMessageToAll("Festival Guide", "The main event is now starting.");
+
+            if (Config.DEBUG)
+                _log.info("SevenSignsFestival: The current set of festivals will begin in " + (Config.ALT_FESTIVAL_FIRST_SPAWN / 60000) + " minute(s).");
+
+            // Stand by for a short length of time before starting the festival.
+            try {
+                wait(Config.ALT_FESTIVAL_FIRST_SPAWN);
+            }
+            catch (InterruptedException e) { }
+
+            elapsedTime = Config.ALT_FESTIVAL_FIRST_SPAWN;
+
+            // Participants can now opt to increase the challenge, if desired.
+            _festivalInProgress = true;
+
+
+            /* PROPOGATION */
+            // Sequentially set all festivals to begin, spawn the Festival Witch and notify participants.
+            for (L2DarknessFestival festivalInst : _festivalInstances.values())
+            {
+                festivalInst.festivalStart();
+                festivalInst.sendMessageToParticipants("The festival is about to begin!");
+            }
+
+            if (Config.DEBUG)
+                _log.info("SevenSignsFestival: Each of the festivals will end in " + (Config.ALT_FESTIVAL_LENGTH / 60000) + " minutes. New participants can signup then.");
+
+
+            // After a short time period, move all idle spawns to the center of the arena.
+            try {
+                wait(Config.ALT_FESTIVAL_FIRST_SWARM - Config.ALT_FESTIVAL_FIRST_SPAWN);
+            }
+            catch (InterruptedException e) { }
+
+            elapsedTime += Config.ALT_FESTIVAL_FIRST_SWARM - Config.ALT_FESTIVAL_FIRST_SPAWN;
+
+            for (L2DarknessFestival festivalInst : _festivalInstances.values())
+                festivalInst.moveMonstersToCenter();
+
+
+            // Stand by until the time comes for the second spawn.
+            try {
+                wait(Config.ALT_FESTIVAL_SECOND_SPAWN - Config.ALT_FESTIVAL_FIRST_SWARM);
+            }
+            catch (InterruptedException e) { }
+
+            // Spawn an extra set of monsters (archers) on the free platforms with
+            // a faster respawn when killed.
+            for (L2DarknessFestival festivalInst : _festivalInstances.values())
+            {
+                festivalInst.spawnFestivalMonsters(FESTIVAL_DEFAULT_RESPAWN / 2, 2);
+                festivalInst.sendMessageToParticipants("The festival will end in " + ((Config.ALT_FESTIVAL_LENGTH - Config.ALT_FESTIVAL_SECOND_SPAWN) / 60000) + " minute(s).");
+            }
+
+            elapsedTime += Config.ALT_FESTIVAL_SECOND_SPAWN - Config.ALT_FESTIVAL_FIRST_SWARM;
+
+
+            // After another short time period, again move all idle spawns to the center of the arena.
+            try {
+                wait(Config.ALT_FESTIVAL_SECOND_SWARM - Config.ALT_FESTIVAL_SECOND_SPAWN);
+            }
+            catch (InterruptedException e) { }
+
+            for (L2DarknessFestival festivalInst : _festivalInstances.values())
+                festivalInst.moveMonstersToCenter();
+
+            elapsedTime += Config.ALT_FESTIVAL_SECOND_SWARM - Config.ALT_FESTIVAL_SECOND_SPAWN;
+
+
+            // Stand by until the time comes for the chests to be spawned.
+            try {
+                wait(Config.ALT_FESTIVAL_CHEST_SPAWN - Config.ALT_FESTIVAL_SECOND_SWARM);
+            }
+            catch (InterruptedException e) { }
+
+            // Spawn the festival chests, which enable the team to gain greater rewards
+            // for each chest they kill.
+            for (L2DarknessFestival festivalInst : _festivalInstances.values())
+            {
+                festivalInst.spawnFestivalMonsters(FESTIVAL_DEFAULT_RESPAWN, 3);
+                festivalInst.sendMessageToParticipants("The chests have spawned! Be quick, the festival will end soon.");
+            }
+
+            elapsedTime += Config.ALT_FESTIVAL_CHEST_SPAWN - Config.ALT_FESTIVAL_SECOND_SWARM;
+
+            // Stand by and wait until it's time to end the festival.
+            try {
+                wait(Config.ALT_FESTIVAL_LENGTH - elapsedTime);
+            }
+            catch (InterruptedException e) { }
+
+            // Participants can no longer opt to increase the challenge, as the festival will soon close.
+            _festivalInProgress = false;
+
+
+            /* TERMINATION */
+            // Sequentially begin the ending sequence for all running festivals.
+            for (L2DarknessFestival festivalInst : _festivalInstances.values())
+                festivalInst.festivalEnd();
+
+            // Clear the participants list for the next round of signups.
+            _dawnFestivalParticipants.clear();
+            _duskFestivalParticipants.clear();
+
+            // Allow signups for the next festival cycle.
+            _festivalInitialized = false;
+
+            sendMessageToAll("Festival Witch", "That will do! I'll move you to the outside soon.");
+
+            if (Config.DEBUG)
+                _log.info("SevenSignsFestival: The next set of festivals begin in " + getMinsToNextFestival() + " minute(s).");
+        }
+
+        /**
+         * Returns the running instance of a festival for the given Oracle and festivalID.
+         * <BR>
+         * A <B>null</B> value is returned if there are no participants in that festival.
+         *
+         * @param oracle
+         * @param festivalId
+         * @return L2DarknessFestival festivalInst
+         */
+        public final L2DarknessFestival getFestivalInstance(int oracle, int festivalId)
+        {
+            if (!isFestivalInitialized())
+                return null;
+
+            /* Compute the offset if a Dusk instance is required.
+             *
+             * ID:      0   1   2   3   4
+             * Dusk 1:  10  11  12  13  14
+             * Dawn 2:  20  21  22  23  24
+             */
+
+            festivalId += (oracle == SevenSigns.CABAL_DUSK) ? 10 : 20;
+            return _festivalInstances.get(festivalId);
+        }
+
+        /**
+         * Returns the number of currently running festivals <b>WITH</b> participants.
+         *
+         * @return int Count
+         */
+        public final int getInstanceCount()
+        {
+            return _festivalInstances.size();
+        }
+    }
+
+
+    /**
+     * Each running festival is represented by an L2DarknessFestival class.
+     * It contains all the spawn information and data for the running festival.
+     *
+     * All festivals are managed by the FestivalManager class, which must be initialized first.
+     *
+     * @author Tempy
+     */
+    private class L2DarknessFestival
+    {
+        protected final int _cabal;
+        protected final int _levelRange;
+        protected boolean _challengeIncreased;
+
+        private FestivalSpawn _startLocation;
+        private FestivalSpawn _witchSpawn;
+
+        private L2NpcInstance _witchInst;
+        private List<L2FestivalMonsterInstance> _npcInsts;
+
+        private List<L2PcInstance> _participants;
+        private Map<L2PcInstance, FestivalSpawn> _originalLocations;
+
+        protected L2DarknessFestival(int cabal, int levelRange)
+        {
+            _cabal = cabal;
+            _levelRange = levelRange;
+            _originalLocations = new FastMap<L2PcInstance, FestivalSpawn>();
+            _npcInsts = new FastList<L2FestivalMonsterInstance>();
+
+            if (cabal == SevenSigns.CABAL_DAWN)
+            {
+                _participants = _dawnFestivalParticipants.get(levelRange);
+                _witchSpawn = new FestivalSpawn(FESTIVAL_DAWN_WITCH_SPAWNS[levelRange]);
+                _startLocation = new FestivalSpawn(FESTIVAL_DAWN_PLAYER_SPAWNS[levelRange]);
+            }
+            else
+            {
+                _participants = _duskFestivalParticipants.get(levelRange);
+                _witchSpawn = new FestivalSpawn(FESTIVAL_DUSK_WITCH_SPAWNS[levelRange]);
+                _startLocation = new FestivalSpawn(FESTIVAL_DUSK_PLAYER_SPAWNS[levelRange]);
+            }
+
+            // FOR TESTING!
+            if (_participants == null)
+                _participants = new FastList<L2PcInstance>();
+
+            festivalInit();
+        }
+
+        protected void festivalInit()
+        {
+            boolean isPositive;
+
+            if (Config.DEBUG)
+                _log.info("SevenSignsFestival: Initializing festival for " + SevenSigns.getCabalShortName(_cabal) + " (" + getFestivalName(_levelRange) + ")");
+
+            // Teleport all players to arena and notify them.
+            if (_participants.size() > 0)
+            {
+              try {
+            	 for (L2PcInstance participant : _participants)
+                 {
+                    _originalLocations.put(participant, new FestivalSpawn(participant.getX(), participant.getY(), participant.getZ(), participant.getHeading()));
+
+                    // Randomize the spawn point around the specific centerpoint for each player.
+                    int x = _startLocation._x;
+                    int y = _startLocation._y;
+
+                    isPositive = (Rnd.nextInt(2) == 1);
+
+                    if (isPositive)
+                    {
+                        x += Rnd.nextInt(FESTIVAL_MAX_OFFSET_X);
+                        y += Rnd.nextInt(FESTIVAL_MAX_OFFSET_Y);
+                    }
+                    else
+                    {
+                        x -= Rnd.nextInt(FESTIVAL_MAX_OFFSET_X);
+                        y -= Rnd.nextInt(FESTIVAL_MAX_OFFSET_Y);
+                    }
+
+                    participant.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
+                    participant.teleToLocation(x, y, _startLocation._z, true);
+
+                    // Remove all buffs from all participants on entry. Works like the skill Cancel.
+                    participant.stopAllEffects();
+
+                    // Remove any stray blood offerings in inventory
+                    L2ItemInstance bloodOfferings = participant.getInventory().getItemByItemId(FESTIVAL_OFFERING_ID);
+                    if (bloodOfferings != null)
+                    	participant.destroyItem("SevenSigns", bloodOfferings, null, true);
+                 }
+              } catch (NullPointerException e)
+              {
+            	  // deleteMe handling should teleport party out in case of disconnect
+              }
+            }
+
+            L2NpcTemplate witchTemplate = NpcTable.getInstance().getTemplate(_witchSpawn._npcId);
+
+            // Spawn the festival witch for this arena
+            try
+            {
+                L2Spawn npcSpawn = new L2Spawn(witchTemplate);
+
+                npcSpawn.setLocx(_witchSpawn._x);
+                npcSpawn.setLocy(_witchSpawn._y);
+                npcSpawn.setLocz(_witchSpawn._z);
+                npcSpawn.setHeading(_witchSpawn._heading);
+                npcSpawn.setAmount(1);
+                npcSpawn.setRespawnDelay(1);
+
+                // Needed as doSpawn() is required to be called also for the NpcInstance it returns.
+                npcSpawn.startRespawn();
+
+                SpawnTable.getInstance().addNewSpawn(npcSpawn, false);
+                _witchInst = npcSpawn.doSpawn();
+
+                if (Config.DEBUG)
+                    _log.fine("SevenSignsFestival: Spawned the Festival Witch " + npcSpawn.getNpcid() + " at " + _witchSpawn._x + " " + _witchSpawn._y + " " + _witchSpawn._z);
+            }
+            catch (Exception e)
+            {
+                _log.warning("SevenSignsFestival: Error while spawning Festival Witch ID " + _witchSpawn._npcId + ": " + e);
+            }
+
+            // Make it appear as though the Witch has apparated there.
+            MagicSkillUse msu = new MagicSkillUse(_witchInst, _witchInst, 2003, 1, 1, 0);
+            _witchInst.broadcastPacket(msu);
+
+            // And another one...:D
+            msu = new MagicSkillUse(_witchInst, _witchInst, 2133, 1, 1, 0);
+            _witchInst.broadcastPacket(msu);
+
+            // Send a message to all participants from the witch.
+            sendMessageToParticipants("The festival will begin in 2 minutes.");
+        }
+
+        protected void festivalStart()
+        {
+            if (Config.DEBUG)
+                _log.info("SevenSignsFestival: Starting festival for " + SevenSigns.getCabalShortName(_cabal) + " (" + getFestivalName(_levelRange) + ")");
+
+            spawnFestivalMonsters(FESTIVAL_DEFAULT_RESPAWN, 0);
+        }
+
+        protected void moveMonstersToCenter()
+        {
+            boolean isPositive;
+
+            if (Config.DEBUG)
+                _log.info("SevenSignsFestival: Moving spawns to arena center for festival " + SevenSigns.getCabalShortName(_cabal) + " (" + getFestivalName(_levelRange) + ")");
+
+            for (L2FestivalMonsterInstance festivalMob : _npcInsts)
+            {
+                if (festivalMob.isDead())
+                    continue;
+
+                // Only move monsters that are idle or doing their usual functions.
+                CtrlIntention currIntention = festivalMob.getAI().getIntention();
+
+                if (currIntention != CtrlIntention.AI_INTENTION_IDLE && currIntention != CtrlIntention.AI_INTENTION_ACTIVE)
+                    continue;
+
+                int x = _startLocation._x;
+                int y = _startLocation._y;
+
+                /*
+                 * Random X and Y coords around the player start location, up to half of the
+                 * maximum allowed offset are generated to prevent the mobs from all moving
+                 * to the exact same place.
+                 */
+                isPositive = (Rnd.nextInt(2) == 1);
+
+                if (isPositive)
+                {
+                    x += Rnd.nextInt(FESTIVAL_MAX_OFFSET_X);
+                    y += Rnd.nextInt(FESTIVAL_MAX_OFFSET_Y);
+                }
+                else
+                {
+                    x -= Rnd.nextInt(FESTIVAL_MAX_OFFSET_X);
+                    y -= Rnd.nextInt(FESTIVAL_MAX_OFFSET_Y);
+                }
+
+                L2CharPosition moveTo = new L2CharPosition(x, y, _startLocation._z, Rnd.nextInt(65536));
+
+                festivalMob.setRunning();
+                festivalMob.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, moveTo);
+            }
+        }
+
+        public void setSpawnRate(int respawnDelay)
+        {
+            if (Config.DEBUG)
+                _log.info("SevenSignsFestival: Modifying spawn rate of festival mobs to " + respawnDelay + " ms for festival " + SevenSigns.getCabalShortName(_cabal) + " (" + getFestivalName(_levelRange) + ")");
+
+            for (L2FestivalMonsterInstance monsterInst : _npcInsts)
+                monsterInst.getSpawn().setRespawnDelay(respawnDelay);
+        }
+
+        /**
+         * Used to spawn monsters unique to the festival.
+         * <BR>
+         * Valid SpawnTypes:<BR>
+         * 0 - All Primary Monsters (starting monsters)
+         * <BR>
+         * 1 - Same as 0, but without archers/marksmen. (used for challenge increase)
+         * <BR>
+         * 2 - Secondary Monsters (archers)
+         * <BR>
+         * 3 - Festival Chests
+         *
+         * @param respawnDelay
+         * @param spawnType
+         */
+        protected void spawnFestivalMonsters(int respawnDelay, int spawnType)
+        {
+            int[][] _npcSpawns = null;
+
+            switch (spawnType)
+            {
+                case 0:
+                case 1:
+                    _npcSpawns = (_cabal == SevenSigns.CABAL_DAWN) ? FESTIVAL_DAWN_PRIMARY_SPAWNS[_levelRange] : FESTIVAL_DUSK_PRIMARY_SPAWNS[_levelRange];
+                    break;
+                case 2:
+                    _npcSpawns = (_cabal == SevenSigns.CABAL_DAWN) ? FESTIVAL_DAWN_SECONDARY_SPAWNS[_levelRange] : FESTIVAL_DUSK_SECONDARY_SPAWNS[_levelRange];
+                    break;
+                case 3:
+                    _npcSpawns = (_cabal == SevenSigns.CABAL_DAWN) ? FESTIVAL_DAWN_CHEST_SPAWNS[_levelRange] : FESTIVAL_DUSK_CHEST_SPAWNS[_levelRange];
+                    break;
+            }
+
+            for (int i = 0; i < _npcSpawns.length; i++)
+            {
+                FestivalSpawn currSpawn = new FestivalSpawn(_npcSpawns[i]);
+
+                // Only spawn archers/marksmen if specified to do so.
+                if (spawnType == 1 && isFestivalArcher(currSpawn._npcId))
+                    continue;
+
+                L2NpcTemplate npcTemplate = NpcTable.getInstance().getTemplate(currSpawn._npcId);
+
+                try
+                {
+                    L2Spawn npcSpawn = new L2Spawn(npcTemplate);
+
+                    npcSpawn.setLocx(currSpawn._x);
+                    npcSpawn.setLocy(currSpawn._y);
+                    npcSpawn.setLocz(currSpawn._z);
+                    npcSpawn.setHeading(Rnd.nextInt(65536));
+                    npcSpawn.setAmount(1);
+                    npcSpawn.setRespawnDelay(respawnDelay);
+
+                    // Needed as doSpawn() is required to be called also for the NpcInstance it returns.
+                    npcSpawn.startRespawn();
+
+                    SpawnTable.getInstance().addNewSpawn(npcSpawn, false);
+                    L2FestivalMonsterInstance festivalMob = (L2FestivalMonsterInstance)npcSpawn.doSpawn();
+
+                    // Set the offering bonus to 2x or 5x the amount per kill,
+                    // if this spawn is part of an increased challenge or is a festival chest.
+                    if (spawnType == 1)
+                        festivalMob.setOfferingBonus(2);
+                    else if (spawnType == 3)
+                        festivalMob.setOfferingBonus(5);
+
+                    _npcInsts.add(festivalMob);
+
+                    if (Config.DEBUG)
+                        _log.fine("SevenSignsFestival: Spawned NPC ID " + currSpawn._npcId + " at " + currSpawn._x + " " + currSpawn._y + " " + currSpawn._z);
+                }
+                catch (Exception e)
+                {
+                    _log.warning("SevenSignsFestival: Error while spawning NPC ID " + currSpawn._npcId + ": " + e);
+                }
+            }
+        }
+
+        protected boolean increaseChallenge()
+        {
+            if (_challengeIncreased)
+                return false;
+
+            // Set this flag to true to make sure that this can only be done once.
+            _challengeIncreased = true;
+
+            if (Config.DEBUG)
+                _log.info("SevenSignsFestival: " + _participants.get(0).getName() + "'s team have opted to increase the festival challenge!");
+
+            // Spawn more festival monsters, but this time with a twist.
+            spawnFestivalMonsters(FESTIVAL_DEFAULT_RESPAWN, 1);
+            return true;
+        }
+
+        public void sendMessageToParticipants(String message)
+        {
+            if (_participants.size() > 0)
+            {
+                CreatureSay cs = new CreatureSay(_witchInst.getObjectId(), 0, "Festival Witch", message);
+
+                for (L2PcInstance participant : _participants)
+                {
+                	try {
+                		participant.sendPacket(cs);
+                	} catch (NullPointerException e) { }
+                }
+            }
+        }
+
+        protected void festivalEnd()
+        {
+            if (Config.DEBUG)
+                _log.info("SevenSignsFestival: Ending festival for " + SevenSigns.getCabalShortName(_cabal) + " (" + getFestivalName(_levelRange) + ")");
+
+            if (_participants.size() > 0)
+            {
+                for (L2PcInstance participant : _participants)
+                {
+                    try {
+                    	relocatePlayer(participant, false);
+                    	participant.sendMessage("The festival has ended. Your party leader must now register your score before the next festival takes place.");
+                    } catch (NullPointerException e) { }
+                }
+
+                if (_cabal == SevenSigns.CABAL_DAWN)
+                    _dawnPreviousParticipants.put(_levelRange, _participants);
+                else
+                    _duskPreviousParticipants.put(_levelRange, _participants);
+            }
+            _participants = null;
+
+            unspawnMobs();
+        }
+
+        protected void unspawnMobs()
+        {
+        	// Delete all the NPCs in the current festival arena.
+        	if (_witchInst != null)
+        		_witchInst.deleteMe();
+
+        	if (_npcInsts != null)
+	            for (L2FestivalMonsterInstance monsterInst : _npcInsts)
+	            	if (monsterInst != null)
+	            		monsterInst.deleteMe();
+        }
+
+        public void relocatePlayer(L2PcInstance participant, boolean isRemoving)
+        {
+            try
+            {
+                FestivalSpawn origPosition = _originalLocations.get(participant);
+
+                if (isRemoving) _originalLocations.remove(participant);
+
+                participant.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
+                participant.teleToLocation(origPosition._x, origPosition._y, origPosition._z, true);
+                participant.sendMessage("You have been removed from the festival arena.");
+            }
+            catch (Exception e)
+            {
+                // If an exception occurs, just move the player to the nearest town.
+                try {
+                	participant.teleToLocation(MapRegionTable.TeleportWhereType.Town);
+                	participant.sendMessage("You have been removed from the festival arena.");
+                } catch (NullPointerException e2) {}
+            }
+        }
+    }
+
+    private class FestivalSpawn
+    {
+        protected final int _x;
+        protected final int _y;
+        protected final int _z;
+        protected final int _heading;
+        protected final int _npcId;
+
+        protected FestivalSpawn(int x, int y, int z, int heading)
+        {
+            _x = x;
+            _y = y;
+            _z = z;
+
+            // Generate a random heading if no positive one given.
+            _heading = (heading < 0) ? Rnd.nextInt(65536) : heading;
+
+            _npcId = -1;
+        }
+
+        protected FestivalSpawn(int[] spawnData)
+        {
+            _x = spawnData[0];
+            _y = spawnData[1];
+            _z = spawnData[2];
+
+            _heading = (spawnData[3] < 0) ? Rnd.nextInt(65536) : spawnData[3];
+
+            if (spawnData.length > 4)
+                _npcId = spawnData[4];
+            else
+                _npcId = -1;
+        }
+    }
+}

+ 484 - 0
L2_GameServer_T1/java/net/sf/l2j/gameserver/Shutdown.java

@@ -0,0 +1,484 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+package net.sf.l2j.gameserver;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import net.sf.l2j.Config;
+import net.sf.l2j.L2DatabaseFactory;
+import net.sf.l2j.gameserver.gameserverpackets.ServerStatus;
+import net.sf.l2j.gameserver.instancemanager.CastleManorManager;
+import net.sf.l2j.gameserver.instancemanager.CursedWeaponsManager;
+import net.sf.l2j.gameserver.instancemanager.ItemsOnGroundManager;
+import net.sf.l2j.gameserver.instancemanager.RaidBossSpawnManager;
+import net.sf.l2j.gameserver.instancemanager.QuestManager;
+import net.sf.l2j.gameserver.model.L2World;
+import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
+import net.sf.l2j.gameserver.network.L2GameClient;
+import net.sf.l2j.gameserver.serverpackets.ServerClose;
+
+/**
+ *
+ * This class provides the functions for shutting down and restarting the server
+ * It closes all open clientconnections and saves all data.
+ *
+ * @version $Revision: 1.2.4.5 $ $Date: 2005/03/27 15:29:09 $
+ */
+public class Shutdown extends Thread
+{
+	private static Logger _log = Logger.getLogger(Shutdown.class.getName());
+	private static Shutdown _instance;
+	private static Shutdown _counterInstance = null;
+
+	private int _secondsShut;
+
+	private int _shutdownMode;
+	public static final int SIGTERM = 0;
+	public static final int GM_SHUTDOWN = 1;
+	public static final int GM_RESTART = 2;
+	public static final int ABORT = 3;
+	private static final String[] MODE_TEXT = {"SIGTERM", "shutting down", "restarting", "aborting"};
+
+    /**
+     * This function starts a shutdown countdown from Telnet (Copied from Function startShutdown())
+     *
+     * @param ip            IP Which Issued shutdown command
+     * @param seconds       seconds untill shutdown
+     * @param restart       true if the server will restart after shutdown
+     */
+
+    public void startTelnetShutdown(String IP, int seconds, boolean restart)
+    {
+        Announcements _an = Announcements.getInstance();
+        _log.warning("IP: " + IP + " issued shutdown command. " + MODE_TEXT[_shutdownMode] + " in "+seconds+ " seconds!");
+        //_an.announceToAll("Server is " + _modeText[shutdownMode] + " in "+seconds+ " seconds!");
+
+        if (restart) {
+            _shutdownMode = GM_RESTART;
+        } else {
+            _shutdownMode = GM_SHUTDOWN;
+        }
+
+        if(_shutdownMode > 0)
+        {
+            _an.announceToAll("Attention players!");
+            _an.announceToAll("Server is " + MODE_TEXT[_shutdownMode] + " in "+seconds+ " seconds!");
+            if(_shutdownMode == 1 || _shutdownMode == 2)
+            {
+                _an.announceToAll("Please, avoid to use Gatekeepers/SoE");
+                _an.announceToAll("during server " + MODE_TEXT[_shutdownMode] + " procedure.");
+            }
+        }
+
+        if (_counterInstance != null) {
+            _counterInstance._abort();
+        }
+        _counterInstance = new Shutdown(seconds, restart);
+        _counterInstance.start();
+    }
+
+    /**
+     * This function aborts a running countdown
+     *
+     * @param IP            IP Which Issued shutdown command
+     */
+    public void telnetAbort(String IP) {
+        Announcements _an = Announcements.getInstance();
+        _log.warning("IP: " + IP + " issued shutdown ABORT. " + MODE_TEXT[_shutdownMode] + " has been stopped!");
+        _an.announceToAll("Server aborts " + MODE_TEXT[_shutdownMode] + " and continues normal operation!");
+
+        if (_counterInstance != null) {
+            _counterInstance._abort();
+        }
+    }
+
+	/**
+	 * Default constucter is only used internal to create the shutdown-hook instance
+	 *
+	 */
+	public Shutdown() {
+		_secondsShut = -1;
+		_shutdownMode = SIGTERM;
+	}
+
+	/**
+	 * This creates a countdown instance of Shutdown.
+	 *
+	 * @param seconds	how many seconds until shutdown
+	 * @param restart	true is the server shall restart after shutdown
+	 *
+	 */
+	public Shutdown(int seconds, boolean restart) {
+		if (seconds < 0) {
+			seconds = 0;
+		}
+		_secondsShut = seconds;
+		if (restart) {
+			_shutdownMode = GM_RESTART;
+		} else {
+			_shutdownMode = GM_SHUTDOWN;
+		}
+	}
+
+	/**
+	 * get the shutdown-hook instance
+	 * the shutdown-hook instance is created by the first call of this function,
+	 * but it has to be registrered externaly.
+	 *
+	 * @return	instance of Shutdown, to be used as shutdown hook
+	 */
+	public static Shutdown getInstance()
+	{
+		if (_instance == null)
+		{
+			_instance = new Shutdown();
+		}
+		return _instance;
+	}
+
+	/**
+	 * this function is called, when a new thread starts
+	 *
+	 * if this thread is the thread of getInstance, then this is the shutdown hook
+	 * and we save all data and disconnect all clients.
+	 *
+	 * after this thread ends, the server will completely exit
+	 *
+	 * if this is not the thread of getInstance, then this is a countdown thread.
+	 * we start the countdown, and when we finished it, and it was not aborted,
+	 * we tell the shutdown-hook why we call exit, and then call exit
+	 *
+	 * when the exit status of the server is 1, startServer.sh / startServer.bat
+	 * will restart the server.
+	 *
+	 */
+	@Override
+	public void run()
+	{
+		// disallow new logins
+		try
+		{
+            //Doesnt actually do anything
+			//Server.gameServer.getLoginController().setMaxAllowedOnlinePlayers(0);
+		}
+		catch (Throwable t)
+		{
+			// ignore
+		}
+
+		if (this == _instance)
+		{
+			// ensure all services are stopped
+			try
+			{
+				GameTimeController.getInstance().stopTimer();
+			}
+			catch (Throwable t)
+			{
+				// ignore
+			}
+
+			// stop all threadpolls
+			try
+			{
+				ThreadPoolManager.getInstance().shutdown();
+			}
+			catch (Throwable t)
+			{
+				// ignore
+			}
+
+			// last byebye, save all data and quit this server
+			// logging doesnt work here :(
+			saveData();
+
+			try
+			{
+				LoginServerThread.getInstance().interrupt();
+			}
+			catch (Throwable t)
+			{
+				// ignore
+			}
+
+			// saveData sends messages to exit players, so sgutdown selector after it
+			try
+			{
+				GameServer.gameServer.getSelectorThread().shutdown();
+				GameServer.gameServer.getSelectorThread().setDaemon(true);
+			}
+			catch (Throwable t)
+			{
+				// ignore
+			}
+
+			// commit data, last chance
+			try
+			{
+				L2DatabaseFactory.getInstance().shutdown();
+			}
+			catch (Throwable t)
+			{
+
+			}
+
+			// server will quit, when this function ends.
+			if (_instance._shutdownMode == GM_RESTART)
+			{
+				Runtime.getRuntime().halt(2);
+			}
+			else
+			{
+				Runtime.getRuntime().halt(0);
+			}
+		}
+		else
+		{
+			// gm shutdown: send warnings and then call exit to start shutdown sequence
+			countdown();
+			// last point where logging is operational :(
+			_log.warning("GM shutdown countdown is over. " + MODE_TEXT[_shutdownMode] + " NOW!");
+			switch (_shutdownMode) {
+				case GM_SHUTDOWN:
+					_instance.setMode(GM_SHUTDOWN);
+					System.exit(0);
+					break;
+				case GM_RESTART:
+					_instance.setMode(GM_RESTART);
+					System.exit(2);
+					break;
+			}
+		}
+	}
+
+	/**
+	 * This functions starts a shutdown countdown
+	 *
+	 * @param activeChar	GM who issued the shutdown command
+	 * @param seconds		seconds until shutdown
+	 * @param restart		true if the server will restart after shutdown
+	 */
+	public void startShutdown(L2PcInstance activeChar, int seconds, boolean restart) {
+		Announcements _an = Announcements.getInstance();
+		_log.warning("GM: "+activeChar.getName()+"("+activeChar.getObjectId()+") issued shutdown command. " + MODE_TEXT[_shutdownMode] + " in "+seconds+ " seconds!");
+
+		if (restart) {
+            _shutdownMode = GM_RESTART;
+        } else {
+            _shutdownMode = GM_SHUTDOWN;
+        }
+
+        if(_shutdownMode > 0)
+        {
+            _an.announceToAll("Attention players!");
+            _an.announceToAll("Server is " + MODE_TEXT[_shutdownMode] + " in "+seconds+ " seconds!");
+            if(_shutdownMode == 1 || _shutdownMode == 2)
+            {
+                _an.announceToAll("Please, avoid to use Gatekeepers/SoE");
+                _an.announceToAll("during server " + MODE_TEXT[_shutdownMode] + " procedure.");
+            }
+        }
+
+		if (_counterInstance != null) {
+			_counterInstance._abort();
+		}
+
+//		 the main instance should only run for shutdown hook, so we start a new instance
+		_counterInstance = new Shutdown(seconds, restart);
+		_counterInstance.start();
+	}
+
+	/**
+	 * This function aborts a running countdown
+	 *
+	 * @param activeChar	GM who issued the abort command
+	 */
+	public void abort(L2PcInstance activeChar) {
+		Announcements _an = Announcements.getInstance();
+		_log.warning("GM: "+activeChar.getName()+"("+activeChar.getObjectId()+") issued shutdown ABORT. " + MODE_TEXT[_shutdownMode] + " has been stopped!");
+		_an.announceToAll("Server aborts " + MODE_TEXT[_shutdownMode] + " and continues normal operation!");
+
+		if (_counterInstance != null) {
+			_counterInstance._abort();
+		}
+	}
+
+	/**
+	 * set the shutdown mode
+	 * @param mode	what mode shall be set
+	 */
+	private void setMode(int mode) {
+		_shutdownMode = mode;
+	}
+
+	/**
+	 * set shutdown mode to ABORT
+	 *
+	 */
+	private void _abort() {
+		_shutdownMode = ABORT;
+	}
+
+	/**
+	 * this counts the countdown and reports it to all players
+	 * countdown is aborted if mode changes to ABORT
+	 */
+	private void countdown() {
+		Announcements _an = Announcements.getInstance();
+
+		try {
+			while (_secondsShut > 0) {
+
+				switch (_secondsShut)
+				{
+				    case 540:_an.announceToAll("The server is " + MODE_TEXT[_shutdownMode] + " in 9 minutes.");break;
+				    case 480:_an.announceToAll("The server is " + MODE_TEXT[_shutdownMode] + " in 8 minutes.");break;
+				    case 420:_an.announceToAll("The server is " + MODE_TEXT[_shutdownMode] + " in 7 minutes.");break;
+				    case 360:_an.announceToAll("The server is " + MODE_TEXT[_shutdownMode] + " in 6 minutes.");break;
+					case 300:_an.announceToAll("The server is " + MODE_TEXT[_shutdownMode] + " in 5 minutes.");break;
+					case 240:_an.announceToAll("The server is " + MODE_TEXT[_shutdownMode] + " in 4 minutes.");break;
+					case 180:_an.announceToAll("The server is " + MODE_TEXT[_shutdownMode] + " in 3 minutes.");break;
+					case 120:_an.announceToAll("The server is " + MODE_TEXT[_shutdownMode] + " in 2 minutes.");break;
+					case 60:
+						LoginServerThread.getInstance().setServerStatus(ServerStatus.STATUS_DOWN); //avoids new players from logging in
+						_an.announceToAll("The server is " + MODE_TEXT[_shutdownMode] + " in 1 minute.");break;
+					case 30:_an.announceToAll("The server is " + MODE_TEXT[_shutdownMode] + " in 30 seconds.");break;
+					case 5:_an.announceToAll("The server is " + MODE_TEXT[_shutdownMode] + " in 5 seconds, please delog NOW !");break;
+				}
+
+				_secondsShut--;
+
+				int delay = 1000; //milliseconds
+				Thread.sleep(delay);
+
+				if(_shutdownMode == ABORT) break;
+			}
+		} catch (InterruptedException e) {
+			//this will never happen
+		}
+	}
+
+	/**
+	 * this sends a last byebye, disconnects all players and saves data
+	 *
+	 */
+	private void saveData() {
+		Announcements _an = Announcements.getInstance();
+		switch (_shutdownMode)
+		{
+			case SIGTERM:
+				System.err.println("SIGTERM received. Shutting down NOW!");
+				break;
+			case GM_SHUTDOWN:
+				System.err.println("GM shutdown received. Shutting down NOW!");
+				break;
+			case GM_RESTART:
+				System.err.println("GM restart received. Restarting NOW!");
+				break;
+
+		}
+		if (Config.ACTIVATE_POSITION_RECORDER)
+			Universe.getInstance().implode(true);
+		try
+		{
+		    _an.announceToAll("Server is " + MODE_TEXT[_shutdownMode] + " NOW!");
+		} catch (Throwable t) {
+			_log.log(Level.INFO, "", t);
+		}
+
+		// we cannt abort shutdown anymore, so i removed the "if"
+		disconnectAllCharacters();
+
+        // Seven Signs data is now saved along with Festival data.
+        if (!SevenSigns.getInstance().isSealValidationPeriod())
+            SevenSignsFestival.getInstance().saveFestivalData(false);
+
+        // Save Seven Signs data before closing. :)
+        SevenSigns.getInstance().saveSevenSignsData(null, true);
+
+        // Save all raidboss status ^_^
+        RaidBossSpawnManager.getInstance().cleanUp();
+        System.err.println("RaidBossSpawnManager: All raidboss info saved!!");
+        TradeController.getInstance().dataCountStore();
+        System.err.println("TradeController: All count Item Saved");
+        try
+        {
+            Olympiad.getInstance().save();
+        }
+        catch(Exception e){e.printStackTrace();}
+        System.err.println("Olympiad System: Data saved!!");
+        
+        // Save Cursed Weapons data before closing.
+        CursedWeaponsManager.getInstance().saveData();
+        
+        // Save all manor data
+        CastleManorManager.getInstance().save();
+        
+        // Save all global (non-player specific) Quest data that needs to persist after reboot
+        QuestManager.getInstance().save();
+        
+        //Save items on ground before closing
+        if(Config.SAVE_DROPPED_ITEM){
+        ItemsOnGroundManager.getInstance().saveInDb();        
+        ItemsOnGroundManager.getInstance().cleanUp();
+        System.err.println("ItemsOnGroundManager: All items on ground saved!!");
+        }
+		System.err.println("Data saved. All players disconnected, shutting down.");
+		
+		try {
+			int delay = 5000;
+			Thread.sleep(delay);
+		} 
+		catch (InterruptedException e) {
+			//never happens :p
+		}
+	}
+
+	/**
+	 * this disconnects all clients from the server
+	 *
+	 */
+	private void disconnectAllCharacters()
+	{
+		for (L2PcInstance player : L2World.getInstance().getAllPlayers())
+		{
+			//Logout Character
+			try {
+				L2GameClient.saveCharToDisk(player);
+				//SystemMessage sm = new SystemMessage(SystemMessage.YOU_HAVE_WON_THE_WAR_OVER_THE_S1_CLAN);
+				//player.sendPacket(sm);
+				ServerClose ql = new ServerClose();
+				player.sendPacket(ql);
+			} catch (Throwable t)	{}
+		}
+		try { Thread.sleep(1000); } catch (Throwable t) {_log.log(Level.INFO, "", t);}
+		
+		
+		for (L2PcInstance player : L2World.getInstance().getAllPlayers())
+		{
+			try {
+				player.closeNetConnection();
+			} catch (Throwable t)	{
+				// just to make sure we try to kill the connection 
+			}				
+		}
+	}
+
+}

+ 30 - 0
L2_GameServer_T1/java/net/sf/l2j/gameserver/TaskPriority.java

@@ -0,0 +1,30 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+package net.sf.l2j.gameserver;
+
+/**
+ * @author mkizub
+ *
+ * TODO To change the template for this generated type comment go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+public enum TaskPriority {
+	PR_NORMAL, PR_HIGH, PR_URGENT;
+
+}

+ 87 - 0
L2_GameServer_T1/java/net/sf/l2j/gameserver/Territory.java

@@ -0,0 +1,87 @@
+/* This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+/*
+	coded by Balancer
+	ported to L2JRU by Mr
+	balancer@balancer.ru
+	http://balancer.ru
+
+	version 0.1.1, 2005-06-07
+	version 0.1, 2005-03-16
+*/
+
+package net.sf.l2j.gameserver;
+
+import java.util.Map;
+import java.util.logging.Logger;
+
+import javolution.util.FastMap;
+import net.sf.l2j.gameserver.lib.SqlUtils;
+import net.sf.l2j.gameserver.model.L2Territory;
+
+public class Territory
+{
+	private static Logger _log = Logger.getLogger(TradeController.class.getName());
+	private static final Territory _instance = new Territory();
+	private static Map<Integer,L2Territory> _territory;
+
+	public static Territory getInstance()
+	{
+		return _instance;
+	}
+
+	private Territory()
+	{
+		// load all data at server start
+		reload_data();
+	}
+
+	public int[] getRandomPoint(int terr)
+	{
+		return _territory.get(terr).getRandomPoint();
+	}
+
+	public int getProcMax(int terr)
+	{
+		return _territory.get(terr).getProcMax();
+	}
+
+	public void reload_data()
+	{
+		_territory = new FastMap<Integer,L2Territory>();
+
+		Integer[][] point = SqlUtils.get2DIntArray(new String[]{"loc_id","loc_x","loc_y","loc_zmin","loc_zmax","proc"}, "locations", "loc_id > 0");
+		for(Integer[] row : point)
+		{
+//			_log.info("row = "+row[0]);
+			Integer terr = row[0];
+			if(terr == null)
+			{
+				_log.warning("Null territory!");
+				continue;
+			}
+
+			if(_territory.get(terr) == null)
+			{
+				L2Territory t = new L2Territory(terr);
+				_territory.put(terr, t);
+		   	}
+			_territory.get(terr).add(row[1],row[2],row[3],row[4],row[5]);
+		}
+	}
+}

+ 430 - 0
L2_GameServer_T1/java/net/sf/l2j/gameserver/ThreadPoolManager.java

@@ -0,0 +1,430 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+package net.sf.l2j.gameserver;
+
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import javolution.text.TextBuilder;
+import net.sf.l2j.Config;
+import net.sf.l2j.gameserver.network.L2GameClient;
+
+import org.mmocore.network.ReceivablePacket;
+
+/**
+ * <p>This class is made to handle all the ThreadPools used in L2j.</p>
+ * <p>Scheduled Tasks can either be sent to a {@link #_generalScheduledThreadPool "general"} or {@link #_effectsScheduledThreadPool "effects"} {@link ScheduledThreadPoolExecutor ScheduledThreadPool}:
+ * The "effects" one is used for every effects (skills, hp/mp regen ...) while the "general" one is used for
+ * everything else that needs to be scheduled.<br>
+ * There also is an {@link #_aiScheduledThreadPool "ai"} {@link ScheduledThreadPoolExecutor ScheduledThreadPool} used for AI Tasks.</p>
+ * <p>Tasks can be sent to {@link ScheduledThreadPoolExecutor ScheduledThreadPool} either with:
+ * <ul>
+ * <li>{@link #scheduleEffect(Runnable, long)} : for effects Tasks that needs to be executed only once.</li>
+ * <li>{@link #scheduleGeneral(Runnable, long)} : for scheduled Tasks that needs to be executed once.</li>
+ * <li>{@link #scheduleAi(Runnable, long)} : for AI Tasks that needs to be executed once</li>
+ * </ul>
+ * or
+ * <ul>
+ * <li>{@link #scheduleEffectAtFixedRate(Runnable, long, long)(Runnable, long)} : for effects Tasks that needs to be executed periodicaly.</li>
+ * <li>{@link #scheduleGeneralAtFixedRate(Runnable, long, long)(Runnable, long)} : for scheduled Tasks that needs to be executed periodicaly.</li>
+ * <li>{@link #scheduleAiAtFixedRate(Runnable, long, long)(Runnable, long)} : for AI Tasks that needs to be executed periodicaly</li>
+ * </ul></p>
+ *
+ * <p>For all Tasks that should be executed with no delay asynchronously in a ThreadPool there also are usual {@link ThreadPoolExecutor ThreadPools}
+ * that can grow/shrink according to their load.:
+ * <ul>
+ * <li>{@link #_generalPacketsThreadPool GeneralPackets} where most packets handler are executed.</li>
+ * <li>{@link #_ioPacketsThreadPool I/O Packets} where all the i/o packets are executed.</li>
+ * <li>There will be an AI ThreadPool where AI events should be executed</li>
+ * <li>A general ThreadPool where everything else that needs to run asynchronously with no delay should be executed ({@link net.sf.l2j.gameserver.model.actor.knownlist KnownList} updates, SQL updates/inserts...)?</li>
+ * </ul>
+ * </p>
+ * @author -Wooden-
+ *
+ */
+public class ThreadPoolManager
+{
+	private static ThreadPoolManager _instance;
+	
+	public ScheduledThreadPoolExecutor _effectsScheduledThreadPool;
+	private ScheduledThreadPoolExecutor _generalScheduledThreadPool;
+	
+	private ThreadPoolExecutor _generalPacketsThreadPool;
+	private ThreadPoolExecutor _ioPacketsThreadPool;
+	// will be really used in the next AI implementation.
+	private ThreadPoolExecutor _aiThreadPool;
+	private ThreadPoolExecutor _generalThreadPool;
+
+	// temp
+	private ScheduledThreadPoolExecutor _aiScheduledThreadPool;
+
+	private boolean _shutdown;
+
+	public static ThreadPoolManager getInstance()
+	{
+		if(_instance == null)
+		{
+			_instance = new ThreadPoolManager();
+		}
+		return _instance;
+	}
+
+	private ThreadPoolManager()
+	{
+		_effectsScheduledThreadPool = new ScheduledThreadPoolExecutor(Config.THREAD_P_EFFECTS, new PriorityThreadFactory("EffectsSTPool", Thread.NORM_PRIORITY));
+		_generalScheduledThreadPool = new ScheduledThreadPoolExecutor(Config.THREAD_P_GENERAL, new PriorityThreadFactory("GerenalSTPool", Thread.NORM_PRIORITY));
+
+		_ioPacketsThreadPool = new ThreadPoolExecutor(Config.IO_PACKET_THREAD_CORE_SIZE, Integer.MAX_VALUE,
+		                                                  5L, TimeUnit.SECONDS,
+		                                                  new LinkedBlockingQueue<Runnable>(),
+		                                                  new PriorityThreadFactory("I/O Packet Pool",Thread.NORM_PRIORITY+1));
+
+		_generalPacketsThreadPool = new ThreadPoolExecutor(Config.GENERAL_PACKET_THREAD_CORE_SIZE, Config.GENERAL_PACKET_THREAD_CORE_SIZE+2,
+		                                                   15L, TimeUnit.SECONDS,
+		                                                   new LinkedBlockingQueue<Runnable>(),
+		                                                   new PriorityThreadFactory("Normal Packet Pool",Thread.NORM_PRIORITY+1));
+
+		_generalThreadPool = new ThreadPoolExecutor(Config.GENERAL_THREAD_CORE_SIZE, Config.GENERAL_THREAD_CORE_SIZE+2,
+		                                                   5L, TimeUnit.SECONDS,
+		                                                   new LinkedBlockingQueue<Runnable>(),
+		                                                   new PriorityThreadFactory("General Pool",Thread.NORM_PRIORITY));
+
+		// will be really used in the next AI implementation.
+		_aiThreadPool = new ThreadPoolExecutor(1, Config.AI_MAX_THREAD,
+			                                      10L, TimeUnit.SECONDS,
+			                                      new LinkedBlockingQueue<Runnable>());
+
+		_aiScheduledThreadPool = new ScheduledThreadPoolExecutor(Config.AI_MAX_THREAD, new PriorityThreadFactory("AISTPool", Thread.NORM_PRIORITY));
+	}
+
+	public ScheduledFuture<?> scheduleEffect(Runnable r, long delay)
+	{
+		try
+		{
+			if (delay < 0) delay = 0;
+			return _effectsScheduledThreadPool.schedule(r, delay, TimeUnit.MILLISECONDS);
+		} catch (RejectedExecutionException e) { return null; /* shutdown, ignore */ }
+	}
+
+	public ScheduledFuture<?> scheduleEffectAtFixedRate(Runnable r, long initial, long delay)
+	{
+		try
+		{
+			if (delay < 0) delay = 0;
+			if (initial < 0) initial = 0;
+			return _effectsScheduledThreadPool.scheduleAtFixedRate(r, initial, delay, TimeUnit.MILLISECONDS);
+		} catch (RejectedExecutionException e) { return null; /* shutdown, ignore */ }
+	}
+
+	public ScheduledFuture<?> scheduleGeneral(Runnable r, long delay)
+	{
+		try
+		{
+			if (delay < 0) delay = 0;
+			return _generalScheduledThreadPool.schedule(r, delay, TimeUnit.MILLISECONDS);
+		} catch (RejectedExecutionException e) { return null; /* shutdown, ignore */ }
+	}
+
+	public ScheduledFuture<?> scheduleGeneralAtFixedRate(Runnable r, long initial, long delay)
+	{
+		try
+		{
+			if (delay < 0) delay = 0;
+			if (initial < 0) initial = 0;
+			return _generalScheduledThreadPool.scheduleAtFixedRate(r, initial, delay, TimeUnit.MILLISECONDS);
+		} catch (RejectedExecutionException e) { return null; /* shutdown, ignore */ }
+	}
+
+	public ScheduledFuture<?> scheduleAi(Runnable r, long delay)
+	{
+		try
+		{
+			if (delay < 0) delay = 0;
+			return _aiScheduledThreadPool.schedule(r, delay, TimeUnit.MILLISECONDS);
+		} catch (RejectedExecutionException e) { return null; /* shutdown, ignore */ }
+	}
+
+	public ScheduledFuture<?> scheduleAiAtFixedRate(Runnable r, long initial, long delay)
+	{
+		try
+		{
+			if (delay < 0) delay = 0;
+			if (initial < 0) initial = 0;
+			return _aiScheduledThreadPool.scheduleAtFixedRate(r, initial, delay, TimeUnit.MILLISECONDS);
+		} catch (RejectedExecutionException e) { return null; /* shutdown, ignore */ }
+	}
+
+	public void executePacket(ReceivablePacket<L2GameClient> pkt)
+	{
+		_generalPacketsThreadPool.execute(pkt);
+	}
+
+	public void executeIOPacket(ReceivablePacket<L2GameClient> pkt)
+	{
+		_ioPacketsThreadPool.execute(pkt);
+	}
+
+	public void executeTask(Runnable r)
+	{
+		_generalThreadPool.execute(r);
+	}
+
+	public void executeAi(Runnable r)
+	{
+		_aiThreadPool.execute(r);
+	}
+
+	public String[] getStats()
+	{
+		return new String[] {
+		                     "STP:",
+		                     " + Effects:",
+		                     " |- ActiveThreads:   "+_effectsScheduledThreadPool.getActiveCount(),
+		                     " |- getCorePoolSize: "+_effectsScheduledThreadPool.getCorePoolSize(),
+		                     " |- PoolSize:        "+_effectsScheduledThreadPool.getPoolSize(),
+		                     " |- MaximumPoolSize: "+_effectsScheduledThreadPool.getMaximumPoolSize(),
+		                     " |- CompletedTasks:  "+_effectsScheduledThreadPool.getCompletedTaskCount(),
+		                     " |- ScheduledTasks:  "+(_effectsScheduledThreadPool.getTaskCount() - _effectsScheduledThreadPool.getCompletedTaskCount()),
+		                     " | -------",
+		                     " + General:",
+		                     " |- ActiveThreads:   "+_generalScheduledThreadPool.getActiveCount(),
+		                     " |- getCorePoolSize: "+_generalScheduledThreadPool.getCorePoolSize(),
+		                     " |- PoolSize:        "+_generalScheduledThreadPool.getPoolSize(),
+		                     " |- MaximumPoolSize: "+_generalScheduledThreadPool.getMaximumPoolSize(),
+		                     " |- CompletedTasks:  "+_generalScheduledThreadPool.getCompletedTaskCount(),
+		                     " |- ScheduledTasks:  "+(_generalScheduledThreadPool.getTaskCount() - _generalScheduledThreadPool.getCompletedTaskCount()),
+		                     " | -------",
+		                     " + AI:",
+		                     " |- ActiveThreads:   "+_aiScheduledThreadPool.getActiveCount(),
+		                     " |- getCorePoolSize: "+_aiScheduledThreadPool.getCorePoolSize(),
+		                     " |- PoolSize:        "+_aiScheduledThreadPool.getPoolSize(),
+		                     " |- MaximumPoolSize: "+_aiScheduledThreadPool.getMaximumPoolSize(),
+		                     " |- CompletedTasks:  "+_aiScheduledThreadPool.getCompletedTaskCount(),
+		                     " |- ScheduledTasks:  "+(_aiScheduledThreadPool.getTaskCount() - _aiScheduledThreadPool.getCompletedTaskCount()),
+		                     "TP:",
+		                     " + Packets:",
+		                     " |- ActiveThreads:   "+_generalPacketsThreadPool.getActiveCount(),
+		                     " |- getCorePoolSize: "+_generalPacketsThreadPool.getCorePoolSize(),
+		                     " |- MaximumPoolSize: "+_generalPacketsThreadPool.getMaximumPoolSize(),
+		                     " |- LargestPoolSize: "+_generalPacketsThreadPool.getLargestPoolSize(),
+		                     " |- PoolSize:        "+_generalPacketsThreadPool.getPoolSize(),
+		                     " |- CompletedTasks:  "+_generalPacketsThreadPool.getCompletedTaskCount(),
+		                     " |- QueuedTasks:     "+_generalPacketsThreadPool.getQueue().size(),
+		                     " | -------",
+		                     " + I/O Packets:",
+		                     " |- ActiveThreads:   "+_ioPacketsThreadPool.getActiveCount(),
+		                     " |- getCorePoolSize: "+_ioPacketsThreadPool.getCorePoolSize(),
+		                     " |- MaximumPoolSize: "+_ioPacketsThreadPool.getMaximumPoolSize(),
+		                     " |- LargestPoolSize: "+_ioPacketsThreadPool.getLargestPoolSize(),
+		                     " |- PoolSize:        "+_ioPacketsThreadPool.getPoolSize(),
+		                     " |- CompletedTasks:  "+_ioPacketsThreadPool.getCompletedTaskCount(),
+		                     " |- QueuedTasks:     "+_ioPacketsThreadPool.getQueue().size(),
+		                     " | -------",
+		                     " + General Tasks:",
+		                     " |- ActiveThreads:   "+_generalThreadPool.getActiveCount(),
+		                     " |- getCorePoolSize: "+_generalThreadPool.getCorePoolSize(),
+		                     " |- MaximumPoolSize: "+_generalThreadPool.getMaximumPoolSize(),
+		                     " |- LargestPoolSize: "+_generalThreadPool.getLargestPoolSize(),
+		                     " |- PoolSize:        "+_generalThreadPool.getPoolSize(),
+		                     " |- CompletedTasks:  "+_generalThreadPool.getCompletedTaskCount(),
+		                     " |- QueuedTasks:     "+_generalThreadPool.getQueue().size(),
+		                     " | -------",
+		                     " + AI:",
+		                     " |- Not Done"
+		};
+	}
+
+    private class PriorityThreadFactory implements ThreadFactory
+    {
+    	private int _prio;
+		private String _name;
+		private AtomicInteger _threadNumber = new AtomicInteger(1);
+		private ThreadGroup _group;
+
+		public PriorityThreadFactory(String name, int prio)
+    	{
+    		_prio = prio;
+    		_name = name;
+    		_group = new ThreadGroup(_name);
+    	}
+		/* (non-Javadoc)
+		 * @see java.util.concurrent.ThreadFactory#newThread(java.lang.Runnable)
+		 */
+		public Thread newThread(Runnable r)
+		{
+			Thread t = new Thread(_group,r);
+			t.setName(_name+"-"+_threadNumber.getAndIncrement());
+			t.setPriority(_prio);
+			return t;
+		}
+
+		public ThreadGroup getGroup()
+		{
+			return _group;
+		}
+    }
+
+	/**
+	 *
+	 */
+	public void shutdown()
+	{
+		_shutdown = true;
+		try
+		{
+			_effectsScheduledThreadPool.awaitTermination(1,TimeUnit.SECONDS);
+			_generalScheduledThreadPool.awaitTermination(1,TimeUnit.SECONDS);
+			_generalPacketsThreadPool.awaitTermination(1,TimeUnit.SECONDS);
+			_ioPacketsThreadPool.awaitTermination(1,TimeUnit.SECONDS);
+			_generalThreadPool.awaitTermination(1,TimeUnit.SECONDS);
+			_aiThreadPool.awaitTermination(1,TimeUnit.SECONDS);
+			_effectsScheduledThreadPool.shutdown();
+			_generalScheduledThreadPool.shutdown();
+			_generalPacketsThreadPool.shutdown();
+			_ioPacketsThreadPool.shutdown();
+			_generalThreadPool.shutdown();
+			_aiThreadPool.shutdown();
+			System.out.println("All ThreadPools are now stoped");
+
+		}
+		catch (InterruptedException e)
+		{
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+	}
+
+	public boolean isShutdown()
+	{
+		return _shutdown;
+	}
+
+	/**
+	 *
+	 */
+	public void purge()
+	{
+		_effectsScheduledThreadPool.purge();
+		_generalScheduledThreadPool.purge();
+		_aiScheduledThreadPool.purge();
+		_ioPacketsThreadPool.purge();
+		_generalPacketsThreadPool.purge();
+		_generalThreadPool.purge();
+		_aiThreadPool.purge();
+	}
+
+	/**
+	 *
+	 */
+	public String getPacketStats()
+	{
+		TextBuilder tb = new TextBuilder();
+		ThreadFactory tf = _generalPacketsThreadPool.getThreadFactory();
+		if (tf instanceof PriorityThreadFactory)
+		{
+			tb.append("General Packet Thread Pool:\r\n");
+			tb.append("Tasks in the queue: "+_generalPacketsThreadPool.getQueue().size()+"\r\n");
+			tb.append("Showing threads stack trace:\r\n");
+			PriorityThreadFactory ptf = (PriorityThreadFactory) tf;
+			int count = ptf.getGroup().activeCount();
+			Thread[] threads = new Thread[count+2];
+			ptf.getGroup().enumerate(threads);
+			tb.append("There should be "+count+" Threads\r\n");
+			for(Thread t : threads)
+			{
+				if(t == null)
+					continue;
+				tb.append(t.getName()+"\r\n");
+				for(StackTraceElement ste :t.getStackTrace())
+				{
+					tb.append(ste.toString());
+					tb.append("\r\n");
+				}
+			}
+		}
+		tb.append("Packet Tp stack traces printed.\r\n");
+		return tb.toString();
+	}
+
+	public String getIOPacketStats()
+	{
+		TextBuilder tb = new TextBuilder();
+		ThreadFactory tf = _ioPacketsThreadPool.getThreadFactory();
+		if (tf instanceof PriorityThreadFactory)
+		{
+			tb.append("I/O Packet Thread Pool:\r\n");
+			tb.append("Tasks in the queue: "+_ioPacketsThreadPool.getQueue().size()+"\r\n");
+			tb.append("Showing threads stack trace:\r\n");
+			PriorityThreadFactory ptf = (PriorityThreadFactory) tf;
+			int count = ptf.getGroup().activeCount();
+			Thread[] threads = new Thread[count+2];
+			ptf.getGroup().enumerate(threads);
+			tb.append("There should be "+count+" Threads\r\n");
+			for(Thread t : threads)
+			{
+				if(t == null)
+					continue;
+				tb.append(t.getName()+"\r\n");
+				for(StackTraceElement ste :t.getStackTrace())
+				{
+					tb.append(ste.toString());
+					tb.append("\r\n");
+				}
+			}
+		}
+		tb.append("Packet Tp stack traces printed.\r\n");
+		return tb.toString();
+	}
+
+	public String getGeneralStats()
+	{
+		TextBuilder tb = new TextBuilder();
+		ThreadFactory tf = _generalThreadPool.getThreadFactory();
+		if (tf instanceof PriorityThreadFactory)
+		{
+			tb.append("General Thread Pool:\r\n");
+			tb.append("Tasks in the queue: "+_generalThreadPool.getQueue().size()+"\r\n");
+			tb.append("Showing threads stack trace:\r\n");
+			PriorityThreadFactory ptf = (PriorityThreadFactory) tf;
+			int count = ptf.getGroup().activeCount();
+			Thread[] threads = new Thread[count+2];
+			ptf.getGroup().enumerate(threads);
+			tb.append("There should be "+count+" Threads\r\n");
+			for(Thread t : threads)
+			{
+				if(t == null)
+					continue;
+				tb.append(t.getName()+"\r\n");
+				for(StackTraceElement ste :t.getStackTrace())
+				{
+					tb.append(ste.toString());
+					tb.append("\r\n");
+				}
+			}
+		}
+		tb.append("Packet Tp stack traces printed.\r\n");
+		return tb.toString();
+	}
+}

+ 250 - 0
L2_GameServer_T1/java/net/sf/l2j/gameserver/TradeController.java

@@ -0,0 +1,250 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+package net.sf.l2j.gameserver;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javolution.util.FastList;
+import javolution.util.FastMap;
+import net.sf.l2j.Config;
+import net.sf.l2j.L2DatabaseFactory;
+import net.sf.l2j.gameserver.datatables.ItemTable;
+import net.sf.l2j.gameserver.model.L2TradeList;
+import net.sf.l2j.gameserver.model.L2TradeList.L2TradeItem;
+
+/**
+ * This class ...
+ *
+ * @version $Revision: 1.5.4.13 $ $Date: 2005/04/06 16:13:38 $
+ */
+public class TradeController
+{
+    private static Logger _log = Logger.getLogger(TradeController.class.getName());
+    private static TradeController _instance;
+    
+    private int _nextListId;
+    private Map<Integer, L2TradeList> _lists;
+    
+    /** Task launching the function for restore count of Item (Clan Hall) */
+    /*public class RestoreCount implements Runnable
+    {
+        private int _timer;
+        
+        public RestoreCount(int time)
+        {
+            _timer = time;
+        }
+        
+        public void run()
+        {
+            restoreCount(_timer);
+            dataTimerSave(_timer);
+            ThreadPoolManager.getInstance().scheduleGeneral(new RestoreCount(_timer), (long)_timer*60*60*1000);
+        }
+    }*/
+    
+    public static TradeController getInstance()
+    {
+        if (_instance == null)
+        {
+            _instance = new TradeController();
+        }
+        return _instance;
+    }
+    
+    private TradeController()
+    {
+        _lists = new FastMap<Integer, L2TradeList>();
+        java.sql.Connection con = null;
+        
+        /*
+         * Initialize Shop buylist
+         */
+        try
+        {
+            con = L2DatabaseFactory.getInstance().getConnection();
+            PreparedStatement statement1 = con.prepareStatement("SELECT  shop_id, npc_id FROM merchant_shopids");
+            ResultSet rset1 = statement1.executeQuery();
+            
+            int itemId, price, maxCount, currentCount, time;
+            long saveTimer;
+            while (rset1.next())
+            {
+                PreparedStatement statement = con.prepareStatement("SELECT item_id, price, shop_id, "+L2DatabaseFactory.getInstance().safetyString("order")+", count, currentCount, time, savetimer FROM merchant_buylists WHERE shop_id=? ORDER BY "+L2DatabaseFactory.getInstance().safetyString("order")+" ASC");
+                statement.setString(1, String.valueOf(rset1.getInt("shop_id")));
+                ResultSet rset = statement.executeQuery();
+                L2TradeList buy1 = new L2TradeList(rset1.getInt("shop_id"));
+                
+                while (rset.next())
+                {
+                    itemId = rset.getInt("item_id");
+                    price = rset.getInt("price");
+                    maxCount = rset.getInt("count");
+                    currentCount = rset.getInt("currentCount");
+                    time = rset.getInt("time");
+                    saveTimer = rset.getLong("saveTimer");
+                    
+                    L2TradeItem item = new L2TradeItem(itemId);
+                    if (ItemTable.getInstance().getTemplate(itemId) == null)
+                    {
+                        _log.warning("Skipping itemId: "+itemId+" on buylistId: "+buy1.getListId()+", missing data for that item.");
+                        continue;
+                    }
+                    
+                    if (price <= -1)
+                    {
+                        price = ItemTable.getInstance().getTemplate(itemId).getReferencePrice();
+                    }
+                    
+                    if (Config.DEBUG)
+                    {
+                        // debug
+                        double diff = ((double) (price)) / ItemTable.getInstance().getTemplate(itemId).getReferencePrice();
+                        if (diff < 0.8 || diff > 1.2)
+                        {
+                            _log.severe("PRICING DEBUG: TradeListId: "+buy1.getListId()+" -  ItemId: "+itemId+" ("+ItemTable.getInstance().getTemplate(itemId).getName()+") diff: "+diff+" - Price: "+price+" - Reference: "+ItemTable.getInstance().getTemplate(itemId).getReferencePrice());
+                        }
+                    }
+                    
+                    item.setPrice(price);
+                    
+                    item.setRestoreDelay(time);
+                    item.setNextRestoreTime(saveTimer);
+                    item.setMaxCount(maxCount);
+                    
+                    if (currentCount > -1)
+                    {
+                        item.setCurrentCount(currentCount);
+                    }
+                    else
+                    {
+                        item.setCurrentCount(maxCount);
+                    }
+                    
+                    buy1.addItem(item);
+                }
+                
+                buy1.setNpcId(rset1.getString("npc_id"));
+                _lists.put(buy1.getListId(), buy1);
+                _nextListId = Math.max(_nextListId, buy1.getListId() + 1);
+                
+                rset.close();
+                statement.close();
+            }
+            rset1.close();
+            statement1.close();
+            
+            _log.config("TradeController: Loaded " + _lists.size() + " Buylists.");
+        }
+        catch (Exception e)
+        {
+            // problem with initializing spawn, go to next one
+            _log.warning("TradeController: Buylists could not be initialized.");
+            e.printStackTrace();
+        }
+        finally
+        {
+            try
+            {
+                con.close();
+            }
+            catch (Exception e)
+            {
+                
+            }
+        }
+    }
+    
+    public L2TradeList getBuyList(int listId)
+    {
+        return _lists.get(listId);
+    }
+    
+    public List<L2TradeList> getBuyListByNpcId(int npcId)
+    {
+        List<L2TradeList> lists = new FastList<L2TradeList>();
+        Collection<L2TradeList> values = _lists.values();
+        
+        for (L2TradeList list : values)
+        {
+            String tradeNpcId = list.getNpcId();
+            if (tradeNpcId.startsWith("gm"))
+                continue;
+            if (npcId == Integer.parseInt(tradeNpcId))
+                lists.add(list);
+        }
+        return lists;
+    }
+    
+    
+    
+    public void dataCountStore()
+    {
+        java.sql.Connection con = null;
+        PreparedStatement statement;
+        
+        try
+        {
+            con = L2DatabaseFactory.getInstance().getConnection();
+            
+            for (L2TradeList list : _lists.values())
+            {
+                if (list.hasLimitedStockItem())
+                {
+                    
+                    int listId = list.getListId();
+                    
+                    for (L2TradeItem item :list.getItems())
+                    {
+                        if (item.hasLimitedStock() && item.getCurrentCount() < item.getMaxCount()) //needed?
+                        {
+                            statement = con.prepareStatement("UPDATE merchant_buylists SET currentCount=? WHERE item_id=? AND shop_id=?");
+                            statement.setInt(1, item.getCurrentCount());
+                            statement.setInt(2, item.getItemId());
+                            statement.setInt(3, listId);
+                            statement.executeUpdate();
+                            statement.close();
+                        }
+                    }
+                }
+            }
+        }
+        catch (Exception e)
+        {
+            _log.log(Level.SEVERE, "TradeController: Could not store Count Item" );
+        }
+        finally
+        {
+            try { con.close(); } catch (Exception e) { e.printStackTrace(); }
+        }
+    }
+    /**
+     * @return
+     */
+    public synchronized int getNextId()
+    {
+        return _nextListId++;
+    }
+}

+ 493 - 0
L2_GameServer_T1/java/net/sf/l2j/gameserver/Universe.java

@@ -0,0 +1,493 @@
+/* This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+package net.sf.l2j.gameserver;
+
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
+import java.io.BufferedReader;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.StringTokenizer;
+import java.util.TreeSet;
+import java.util.logging.Logger;
+import java.util.zip.GZIPInputStream;
+
+import javax.imageio.ImageIO;
+
+import net.sf.l2j.Config;
+import net.sf.l2j.gameserver.model.L2CharPosition;
+
+public class Universe implements java.io.Serializable
+{
+
+    /**
+     * Comment for <code>serialVersionUID</code>
+     */
+    private static final long serialVersionUID = -2040223695811104704L;
+    public static final int MIN_X = -127900;
+    public static final int MAX_X = 194327;
+    public static final int MIN_Y = -30000;
+    public static final int MAX_Y = 259536;
+    public static final int MIN_Z = -17000;
+    public static final int MAX_Z = 17000;
+    public static final int MIN_X_GRID = 60;
+    public static final int MIN_Y_GRID = 60;
+    public static final int MIN_Z_GRID = 60;
+    public static final int MIN_GRID = 360;
+    private static Universe _instance;
+    protected static final Logger _log = Logger.getLogger(Universe.class.getName());
+
+    protected List<Coord> _coordList;
+
+    private HashSet<Integer> _logPlayers;
+    private boolean _logAll = true;
+
+
+    public static void main(String[] args)
+    {
+        Universe u = new Universe();
+        u.load();
+        //u.removeDoubles();
+        u.implode(false);
+    }
+
+    private class Position implements Comparable<Position>, java.io.Serializable
+    {
+        /**
+         * Comment for <code>serialVersionUID</code>
+         */
+        private static final long serialVersionUID = -8798746764450022287L;
+        protected int _x;
+        protected int _flag;
+        protected int _y;
+        protected int _z;
+
+        public Position(int x, int y, int z, int flag)
+        {
+            _x = x;
+            _y = y;
+            _z = z;
+            _flag = flag;
+        }
+
+        public Position(L2CharPosition pos)
+        {
+            _x = pos.x;
+            _y = pos.y;
+            _z = pos.z;
+            _flag = 0;
+        }
+
+        @Deprecated
+        public L2CharPosition l2CP()
+        {
+            return new L2CharPosition(_x, _y, _z, 0);
+        }
+
+        public int compareTo(Position obj)
+        {
+            int res = Integer.valueOf(_x).compareTo(obj._x);
+            if (res != 0) return res;
+            res = Integer.valueOf(_y).compareTo(obj._y);
+            if (res != 0) return res;
+            res = Integer.valueOf(_z).compareTo(obj._z);
+            return res;
+        }
+
+        @Override
+		public String toString()
+        {
+            return String.valueOf(_x) + " " + _y + " " + _z + " " + _flag;
+        }
+    }
+
+    private class Coord implements Comparable<Position>, java.io.Serializable
+    {
+        /**
+         * Comment for <code>serialVersionUID</code>
+         */
+        private static final long serialVersionUID = -558060332886829552L;
+        protected int _x;
+        protected int _y;
+        protected int _z;
+
+        public Coord(int x, int y, int z)
+        {
+            _x = x;
+            _y = y;
+            _z = z;
+        }
+
+        public Coord(L2CharPosition pos)
+        {
+            _x = pos.x;
+            _y = pos.y;
+            _z = pos.z;
+        }
+
+        public int compareTo(Position obj)
+        {
+            int res = Integer.valueOf(_x).compareTo(obj._x);
+            if (res != 0) return res;
+            res = Integer.valueOf(_y).compareTo(obj._y);
+            if (res != 0) return res;
+            res = Integer.valueOf(_z).compareTo(obj._z);
+            return res;
+        }
+
+        @Override
+		public String toString()
+        {
+            return String.valueOf(_x) + " " + _y + " " + _z;
+        }
+    }
+
+    public static Universe getInstance()
+    {
+        if (_instance == null && Config.ACTIVATE_POSITION_RECORDER)
+        {
+            _instance = new Universe();
+        }
+        return _instance;
+    }
+
+    private Universe()
+    {
+        _coordList = new LinkedList<Coord>();
+        _logPlayers = new HashSet<Integer>();
+
+        ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(new UniverseDump(), 30000, 30000);
+    }
+
+    public void registerHeight(int x, int y, int z)
+    {
+        // don't overwrite obstacle entries
+        //Position p  = new Position(x, y, z, 0);
+        //_map.add(p);
+        _coordList.add(new Coord(x, y, z));
+        //if (Config.USE_3D_MAP) insertInto3DMap(p);
+    }
+
+    public void registerObstacle(int x, int y, int z)
+    {
+        //Position p = new Position(x, y, z, -1);
+        //_map.add(p);
+        _coordList.add(new Coord(x, y, z));
+        //if (Config.USE_3D_MAP) insertInto3DMap(p);
+    }
+
+    public boolean shouldLog(Integer id)
+    {
+        return (_logPlayers.contains(id) || _logAll);
+    }
+
+    public void setLogAll(boolean flag)
+    {
+        _logAll = flag;
+    }
+
+    public void addLogPlayer(Integer id)
+    {
+        _logPlayers.add(id);
+        _logAll = false;
+    }
+
+    public void removeLogPlayer(Integer id)
+    {
+        _logPlayers.remove(id);
+    }
+
+    public void loadAscii()
+    {
+        int initialSize = _coordList.size();
+        try
+        {
+            BufferedReader r = new BufferedReader(new FileReader("data/universe.txt"));
+            String line;
+            while ((line = r.readLine()) != null)
+            {
+                StringTokenizer st = new StringTokenizer(line);
+                String x1 = st.nextToken();
+                String y1 = st.nextToken();
+                String z1 = st.nextToken();
+                //                String f1 = st.nextToken();
+                int x = Integer.parseInt(x1);
+                int y = Integer.parseInt(y1);
+                int z = Integer.parseInt(z1);
+                //                int f = Integer.parseInt(f1);
+                _coordList.add(new Coord(x, y, z));
+            }
+            r.close();
+            _log.info((_coordList.size() - initialSize) + " additional nodes loaded from text file.");
+        }
+        catch (Exception e)
+        {
+            _log.info("could not read text file universe.txt");
+        }
+    }
+
+    public void createMap()
+    {
+        int zoom = 100;
+        int w = (MAX_X - MIN_X) / zoom;
+        int h = (MAX_Y - MIN_Y) / zoom;
+        BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_USHORT_GRAY);
+        Graphics2D gr = bi.createGraphics();
+        int min_z = 0, max_z = 0;
+        for (Coord pos : _coordList)
+        {
+            if (pos == null) continue;
+
+            if (pos._z < min_z) min_z = pos._z;
+            if (pos._z > max_z) max_z = pos._z;
+        }
+        for (Coord pos : _coordList)
+        {
+            if (pos == null) continue;
+
+            int x = (pos._x - MIN_X) / zoom;
+            int y = (pos._y - MIN_Y) / zoom;
+            int color = (int) (((long) pos._z - MIN_Z) * 0xFFFFFF / (MAX_Z - MIN_Z));
+            gr.setColor(new Color(color));
+            gr.drawLine(x, y, x, y);
+        }
+        try
+        {
+            ImageIO.write(bi, "png", new File("universe.png"));
+        }
+        catch (Exception e)
+        {
+            _log.warning("cannot create universe.png: " + e);
+        }
+    }
+
+    public class UniverseFilter implements FilenameFilter
+    {
+        String _ext = "";
+
+        public UniverseFilter(String pExt)
+        {
+            _ext = pExt;
+        }
+
+        /* (non-Javadoc)
+         * @see java.io.FilenameFilter#accept(java.io.File, java.lang.String)
+         */
+        public boolean accept(@SuppressWarnings("unused")
+        File arg0, String name)
+        {
+            return name.startsWith("universe") && name.endsWith("." + _ext);
+        }
+
+    }
+
+    public void load()
+    {
+        int total = 0;
+        if (_coordList == null)
+        {
+            _coordList = new LinkedList<Coord>();
+        }
+        try
+        {
+            loadBinFiles();
+
+            loadHexFiles();
+
+            loadFinFiles();
+
+            _log.info(_coordList.size() + " map vertices loaded in total.");
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+        System.out.println("Total: " + total);
+    }
+
+    /**
+     * @throws FileNotFoundException
+     * @throws IOException
+     */
+    private void loadFinFiles() throws FileNotFoundException, IOException
+    {
+        FilenameFilter filter = new UniverseFilter("fin");
+        File directory = new File("data");
+        File[] files = directory.listFiles(filter);
+        for (File file : files)
+        {
+            FileInputStream fos = new FileInputStream(file); // Save to file
+            DataInputStream data = new DataInputStream(fos);
+            int count = data.readInt();
+            List<Coord> newMap = new LinkedList<Coord>();
+            for (int i = 0; i < count; i++)
+            {
+                newMap.add(new Coord(data.readInt(), data.readInt(), data.readInt()));
+            }
+            data.close(); // Close the stream.
+
+            _log.info(newMap.size() + " map vertices loaded from file " + file.getName());
+
+            _coordList.addAll(newMap);
+        }
+    }
+
+    /**
+     * @throws FileNotFoundException
+     * @throws IOException
+     */
+    private void loadHexFiles() throws FileNotFoundException, IOException
+    {
+        FilenameFilter filter = new UniverseFilter("hex");
+        File directory = new File("data");
+        File[] files = directory.listFiles(filter);
+        for (File file : files)
+        {
+            FileInputStream fos = new FileInputStream(file); // Save to file
+            GZIPInputStream gzos = new GZIPInputStream(fos);
+            DataInputStream data = new DataInputStream(gzos);
+            int count = data.readInt();
+            List<Coord> newMap = new LinkedList<Coord>();
+            for (int i = 0; i < count; i++)
+            {
+                newMap.add(new Coord(data.readInt(), data.readInt(), data.readInt()));
+                data.readInt();
+            }
+            data.close(); // Close the stream.
+
+            _log.info(newMap.size() + " map vertices loaded from file " + file.getName());
+
+            _coordList.addAll(newMap);
+        }
+    }
+
+    /**
+     * @throws FileNotFoundException
+     * @throws IOException
+     * @throws ClassNotFoundException
+     */
+    @SuppressWarnings(value = {"unchecked"})
+    private void loadBinFiles() throws FileNotFoundException, IOException, ClassNotFoundException
+    {
+        FilenameFilter filter = new UniverseFilter("bin");
+        File directory = new File("data");
+        File[] files = directory.listFiles(filter);
+        for (File file : files)
+        {
+            //Create necessary input streams
+            FileInputStream fis = new FileInputStream(file); // Read from file
+            GZIPInputStream gzis = new GZIPInputStream(fis); // Uncompress
+            ObjectInputStream in = new ObjectInputStream(gzis); // Read objects
+            // Read in an object. It should be a vector of scribbles
+
+            TreeSet<Position> temp = (TreeSet<Position>) in.readObject();
+            _log.info(temp.size() + " map vertices loaded from file " + file.getName());
+            in.close(); // Close the stream.
+            for (Position p : temp)
+            {
+                _coordList.add(new Coord(p._x, p._y, p._z));
+            }
+        }
+    }
+
+    public class UniverseDump implements Runnable
+    {
+        /* (non-Javadoc)
+         * @see java.lang.Runnable#run()
+         */
+        public void run()
+        {
+            int size = _coordList.size();
+            //System.out.println("Univere Map has " + _map.size() + " nodes.");
+            if (size > 100000)
+            {
+                flush();
+            }
+        }
+    }
+
+    public void flush()
+    {
+        //System.out.println("Size of dump: "+coordList.size());
+        List<Coord> oldMap = _coordList;
+        _coordList = new LinkedList<Coord>();
+        int size = oldMap.size();
+        dump(oldMap, true);
+        _log.info("Universe Map : Dumped " + size + " vertices.");
+    }
+
+    public int size()
+    {
+        int size = 0;
+        if (_coordList != null) size = _coordList.size();
+        return size;
+    }
+
+    public void dump(List<Coord> _map, boolean b)
+    {
+        try
+        {
+            String pad = "";
+            if (b) pad = "" + System.currentTimeMillis();
+            FileOutputStream fos = new FileOutputStream("data/universe" + pad + ".fin"); // Save to file
+            DataOutputStream data = new DataOutputStream(fos);
+            int count = _map.size();
+            //System.out.println("Size of dump: "+count);
+            data.writeInt(count);
+
+            if (_map != null)
+            {
+                for (Coord p : _map)
+                {
+                    if (p != null)
+                    {
+                        data.writeInt(p._x);
+                        data.writeInt(p._y);
+                        data.writeInt(p._z);
+                    }
+                }
+            }
+            data.flush();
+            data.close();
+            _log.info("Universe Map saved to: " + "data/universe" + pad + ".fin");
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+    }
+
+    // prepare for shutdown
+    public void implode(boolean b)
+    {
+        createMap();
+        dump(_coordList, b);
+    }
+}

+ 808 - 0
L2_GameServer_T1/java/net/sf/l2j/gameserver/ai/AbstractAI.java

@@ -0,0 +1,808 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+package net.sf.l2j.gameserver.ai;
+
+import static net.sf.l2j.gameserver.ai.CtrlIntention.AI_INTENTION_ATTACK;
+import static net.sf.l2j.gameserver.ai.CtrlIntention.AI_INTENTION_FOLLOW;
+import static net.sf.l2j.gameserver.ai.CtrlIntention.AI_INTENTION_IDLE;
+
+import java.util.concurrent.Future;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import net.sf.l2j.gameserver.GameTimeController;
+import net.sf.l2j.gameserver.ThreadPoolManager;
+import net.sf.l2j.gameserver.model.L2CharPosition;
+import net.sf.l2j.gameserver.model.L2Character;
+import net.sf.l2j.gameserver.model.L2Object;
+import net.sf.l2j.gameserver.model.L2Skill;
+import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
+import net.sf.l2j.gameserver.serverpackets.ActionFailed;
+import net.sf.l2j.gameserver.serverpackets.AutoAttackStart;
+import net.sf.l2j.gameserver.serverpackets.AutoAttackStop;
+import net.sf.l2j.gameserver.serverpackets.MoveToLocation;
+import net.sf.l2j.gameserver.serverpackets.Die;
+import net.sf.l2j.gameserver.serverpackets.MoveToLocationInVehicle;
+import net.sf.l2j.gameserver.serverpackets.MoveToPawn;
+import net.sf.l2j.gameserver.serverpackets.StopMove;
+import net.sf.l2j.gameserver.serverpackets.StopRotation;
+import net.sf.l2j.gameserver.taskmanager.AttackStanceTaskManager;
+
+/**
+ * Mother class of all objects AI in the world.<BR><BR>
+ *
+ * AbastractAI :<BR><BR>
+ * <li>L2CharacterAI</li><BR><BR>
+ *
+ */
+abstract class AbstractAI implements Ctrl
+{
+
+    protected static final Logger _log = Logger.getLogger(AbstractAI.class.getName());
+
+    class FollowTask implements Runnable
+    {
+        protected int _range = 60;
+
+        public FollowTask()
+        {
+        }
+
+        public FollowTask(int range)
+        {
+        	_range = range;
+        }
+
+        public void run()
+        {
+            try
+            {
+                if (_followTask == null) return;
+
+                if (_followTarget == null)
+                {
+                    stopFollow();
+                    return;
+                }
+                if (!_actor.isInsideRadius(_followTarget, _range, true, false))
+                {
+                	moveToPawn(_followTarget, _range);
+                }
+            }
+            catch (Throwable t)
+            {
+                _log.log(Level.WARNING, "", t);
+            }
+        }
+    }
+
+    /** The character that this AI manages */
+    protected final L2Character _actor;
+
+    /** An accessor for private methods of the actor */
+    protected final L2Character.AIAccessor _accessor;
+
+    /** Current long-term intention */
+    protected CtrlIntention _intention = AI_INTENTION_IDLE;
+    /** Current long-term intention parameter */
+    protected Object _intentionArg0 = null;
+    /** Current long-term intention parameter */
+    protected Object _intentionArg1 = null;
+
+    /** Flags about client's state, in order to know which messages to send */
+    protected boolean _clientMoving;
+    /** Flags about client's state, in order to know which messages to send */
+    protected boolean _clientAutoAttacking;
+    /** Flags about client's state, in order to know which messages to send */
+    protected int _clientMovingToPawnOffset;
+
+    /** Different targets this AI maintains */
+    private L2Object _target;
+    private L2Character _castTarget;
+    protected L2Character _attackTarget;
+    protected L2Character _followTarget;
+
+    /** The skill we are curently casting by INTENTION_CAST */
+    L2Skill _skill;
+
+    /** Diferent internal state flags */
+    private int _moveToPawnTimeout;
+
+    protected Future<?> _followTask = null;
+    private static final int FOLLOW_INTERVAL = 1000;
+    private static final int ATTACK_FOLLOW_INTERVAL = 500;
+
+    /**
+     * Constructor of AbstractAI.<BR><BR>
+     *
+     * @param accessor The AI accessor of the L2Character
+     *
+     */
+    protected AbstractAI(L2Character.AIAccessor accessor)
+    {
+        _accessor = accessor;
+
+        // Get the L2Character managed by this Accessor AI
+        _actor = accessor.getActor();
+    }
+
+    /**
+     * Return the L2Character managed by this Accessor AI.<BR><BR>
+     */
+    public L2Character getActor()
+    {
+        return _actor;
+    }
+
+    /**
+     * Return the current Intention.<BR><BR>
+     */
+    public CtrlIntention getIntention()
+    {
+        return _intention;
+    }
+
+    protected synchronized void setCastTarget(L2Character target)
+    {
+        _castTarget = target;
+    }
+
+    /**
+     * Return the current cast target.<BR><BR>
+     */
+    public L2Character getCastTarget()
+    {
+        return _castTarget;
+    }
+
+    protected synchronized void setAttackTarget(L2Character target)
+    {
+        _attackTarget = target;
+    }
+
+    /**
+     * Return current attack target.<BR><BR>
+     */
+    public L2Character getAttackTarget()
+    {
+        return _attackTarget;
+    }
+
+    /**
+     * Set the Intention of this AbstractAI.<BR><BR>
+     *
+     * <FONT COLOR=#FF0000><B> <U>Caution</U> : This method is USED by AI classes</B></FONT><BR><BR>
+     *
+     * <B><U> Overriden in </U> : </B><BR>
+     * <B>L2AttackableAI</B> : Create an AI Task executed every 1s (if necessary)<BR>
+     * <B>L2PlayerAI</B> : Stores the current AI intention parameters to later restore it if necessary<BR><BR>
+     *
+     * @param intention The new Intention to set to the AI
+     * @param arg0 The first parameter of the Intention
+     * @param arg1 The second parameter of the Intention
+     *
+     */
+    synchronized void changeIntention(CtrlIntention intention, Object arg0, Object arg1)
+    {
+        /*
+         if (Config.DEBUG)
+         _log.warning("AbstractAI: changeIntention -> " + intention + " " + arg0 + " " + arg1);
+         */
+
+        _intention = intention;
+        _intentionArg0 = arg0;
+        _intentionArg1 = arg1;
+    }
+
+    /**
+     * Launch the L2CharacterAI onIntention method corresponding to the new Intention.<BR><BR>
+     *
+     * <FONT COLOR=#FF0000><B> <U>Caution</U> : Stop the FOLLOW mode if necessary</B></FONT><BR><BR>
+     *
+     * @param intention The new Intention to set to the AI
+     *
+     */
+    public final void setIntention(CtrlIntention intention)
+    {
+        setIntention(intention, null, null);
+    }
+
+    /**
+     * Launch the L2CharacterAI onIntention method corresponding to the new Intention.<BR><BR>
+     *
+     * <FONT COLOR=#FF0000><B> <U>Caution</U> : Stop the FOLLOW mode if necessary</B></FONT><BR><BR>
+     *
+     * @param intention The new Intention to set to the AI
+     * @param arg0 The first parameter of the Intention (optional target)
+     *
+     */
+    public final void setIntention(CtrlIntention intention, Object arg0)
+    {
+        setIntention(intention, arg0, null);
+    }
+
+    /**
+     * Launch the L2CharacterAI onIntention method corresponding to the new Intention.<BR><BR>
+     *
+     * <FONT COLOR=#FF0000><B> <U>Caution</U> : Stop the FOLLOW mode if necessary</B></FONT><BR><BR>
+     *
+     * @param intention The new Intention to set to the AI
+     * @param arg0 The first parameter of the Intention (optional target)
+     * @param arg1 The second parameter of the Intention (optional target)
+     *
+     */
+    public final void setIntention(CtrlIntention intention, Object arg0, Object arg1)
+    {
+        if (!_actor.isVisible() || !_actor.hasAI()) return;
+
+        /*
+         if (Config.DEBUG)
+         _log.warning("AbstractAI: setIntention -> " + intention + " " + arg0 + " " + arg1);
+         */
+
+        // Stop the follow mode if necessary
+        if (intention != AI_INTENTION_FOLLOW && intention != AI_INTENTION_ATTACK) stopFollow();
+
+        // Launch the onIntention method of the L2CharacterAI corresponding to the new Intention
+        switch (intention)
+        {
+            case AI_INTENTION_IDLE:
+                onIntentionIdle();
+                break;
+            case AI_INTENTION_ACTIVE:
+                onIntentionActive();
+                break;
+            case AI_INTENTION_REST:
+                onIntentionRest();
+                break;
+            case AI_INTENTION_ATTACK:
+                onIntentionAttack((L2Character) arg0);
+                break;
+            case AI_INTENTION_CAST:
+                onIntentionCast((L2Skill) arg0, (L2Object) arg1);
+                break;
+            case AI_INTENTION_MOVE_TO:
+                onIntentionMoveTo((L2CharPosition) arg0);
+                break;
+            case AI_INTENTION_MOVE_TO_IN_A_BOAT:
+                onIntentionMoveToInABoat((L2CharPosition) arg0, (L2CharPosition) arg1);
+                break;
+            case AI_INTENTION_FOLLOW:
+                onIntentionFollow((L2Character) arg0);
+                break;
+            case AI_INTENTION_PICK_UP:
+                onIntentionPickUp((L2Object) arg0);
+                break;
+            case AI_INTENTION_INTERACT:
+                onIntentionInteract((L2Object) arg0);
+                break;
+        }
+    }
+
+    /**
+     * Launch the L2CharacterAI onEvt method corresponding to the Event.<BR><BR>
+     *
+     * <FONT COLOR=#FF0000><B> <U>Caution</U> : The current general intention won't be change
+     * (ex : If the character attack and is stunned, he will attack again after the stunned periode)</B></FONT><BR><BR>
+     *
+     * @param evt The event whose the AI must be notified
+     *
+     */
+    public final void notifyEvent(CtrlEvent evt)
+    {
+        notifyEvent(evt, null, null);
+    }
+
+    /**
+     * Launch the L2CharacterAI onEvt method corresponding to the Event.<BR><BR>
+     *
+     * <FONT COLOR=#FF0000><B> <U>Caution</U> : The current general intention won't be change
+     * (ex : If the character attack and is stunned, he will attack again after the stunned periode)</B></FONT><BR><BR>
+     *
+     * @param evt The event whose the AI must be notified
+     * @param arg0 The first parameter of the Event (optional target)
+     *
+     */
+    public final void notifyEvent(CtrlEvent evt, Object arg0)
+    {
+        notifyEvent(evt, arg0, null);
+    }
+
+    /**
+     * Launch the L2CharacterAI onEvt method corresponding to the Event.<BR><BR>
+     *
+     * <FONT COLOR=#FF0000><B> <U>Caution</U> : The current general intention won't be change
+     * (ex : If the character attack and is stunned, he will attack again after the stunned periode)</B></FONT><BR><BR>
+     *
+     * @param evt The event whose the AI must be notified
+     * @param arg0 The first parameter of the Event (optional target)
+     * @param arg1 The second parameter of the Event (optional target)
+     *
+     */
+    public final void notifyEvent(CtrlEvent evt, Object arg0, Object arg1)
+    {
+        if (!_actor.isVisible() || !_actor.hasAI()) return;
+
+        /*
+         if (Config.DEBUG)
+         _log.warning("AbstractAI: notifyEvent -> " + evt + " " + arg0 + " " + arg1);
+         */
+
+        switch (evt)
+        {
+            case EVT_THINK:
+                onEvtThink();
+                break;
+            case EVT_ATTACKED:
+                onEvtAttacked((L2Character) arg0);
+                break;
+            case EVT_AGGRESSION:
+                onEvtAggression((L2Character) arg0, ((Number) arg1).intValue());
+                break;
+            case EVT_STUNNED:
+                onEvtStunned((L2Character) arg0);
+                break;
+            case EVT_SLEEPING:
+                onEvtSleeping((L2Character) arg0);
+                break;
+            case EVT_ROOTED:
+                onEvtRooted((L2Character) arg0);
+                break;
+            case EVT_CONFUSED:
+                onEvtConfused((L2Character) arg0);
+                break;
+            case EVT_MUTED:
+                onEvtMuted((L2Character) arg0);
+                break;
+            case EVT_READY_TO_ACT:
+                onEvtReadyToAct();
+                break;
+            case EVT_USER_CMD:
+                onEvtUserCmd(arg0, arg1);
+                break;
+            case EVT_ARRIVED:
+                onEvtArrived();
+                break;
+            case EVT_ARRIVED_REVALIDATE:
+                onEvtArrivedRevalidate();
+                break;
+            case EVT_ARRIVED_BLOCKED:
+                onEvtArrivedBlocked((L2CharPosition) arg0);
+                break;
+            case EVT_FORGET_OBJECT:
+                onEvtForgetObject((L2Object) arg0);
+                break;
+            case EVT_CANCEL:
+                onEvtCancel();
+                break;
+            case EVT_DEAD:
+                onEvtDead();
+                break;
+            case EVT_FAKE_DEATH:
+                onEvtFakeDeath();
+                break;
+            case EVT_FINISH_CASTING:
+                onEvtFinishCasting();
+                break;
+        }
+    }
+
+    protected abstract void onIntentionIdle();
+
+    protected abstract void onIntentionActive();
+
+    protected abstract void onIntentionRest();
+
+    protected abstract void onIntentionAttack(L2Character target);
+
+    protected abstract void onIntentionCast(L2Skill skill, L2Object target);
+
+    protected abstract void onIntentionMoveTo(L2CharPosition destination);
+
+    protected abstract void onIntentionMoveToInABoat(L2CharPosition destination, L2CharPosition origin);
+
+    protected abstract void onIntentionFollow(L2Character target);
+
+    protected abstract void onIntentionPickUp(L2Object item);
+
+    protected abstract void onIntentionInteract(L2Object object);
+
+    protected abstract void onEvtThink();
+
+    protected abstract void onEvtAttacked(L2Character attacker);
+
+    protected abstract void onEvtAggression(L2Character target, int aggro);
+
+    protected abstract void onEvtStunned(L2Character attacker);
+
+    protected abstract void onEvtSleeping(L2Character attacker);
+
+    protected abstract void onEvtRooted(L2Character attacker);
+
+    protected abstract void onEvtConfused(L2Character attacker);
+
+    protected abstract void onEvtMuted(L2Character attacker);
+
+    protected abstract void onEvtReadyToAct();
+
+    protected abstract void onEvtUserCmd(Object arg0, Object arg1);
+
+    protected abstract void onEvtArrived();
+
+    protected abstract void onEvtArrivedRevalidate();
+
+    protected abstract void onEvtArrivedBlocked(L2CharPosition blocked_at_pos);
+
+    protected abstract void onEvtForgetObject(L2Object object);
+
+    protected abstract void onEvtCancel();
+
+    protected abstract void onEvtDead();
+
+    protected abstract void onEvtFakeDeath();
+
+    protected abstract void onEvtFinishCasting();
+
+    /**
+     * Cancel action client side by sending Server->Client packet ActionFailed to the L2PcInstance actor.<BR><BR>
+     *
+     * <FONT COLOR=#FF0000><B> <U>Caution</U> : Low level function, used by AI subclasses</B></FONT><BR><BR>
+     *
+     */
+    protected void clientActionFailed()
+    {
+        if (_actor instanceof L2PcInstance) _actor.sendPacket(new ActionFailed());
+    }
+
+    /**
+     * Move the actor to Pawn server side AND client side by sending Server->Client packet MoveToPawn <I>(broadcast)</I>.<BR><BR>
+     *
+     * <FONT COLOR=#FF0000><B> <U>Caution</U> : Low level function, used by AI subclasses</B></FONT><BR><BR>
+     *
+     */
+    protected void moveToPawn(L2Object pawn, int offset)
+    {
+        // Chek if actor can move
+        if (!_actor.isMovementDisabled())
+        {
+            if (offset < 10) offset = 10;
+
+            // prevent possible extra calls to this function (there is none?), 
+            // also don't send movetopawn packets too often
+            boolean sendPacket = true;
+            if (_clientMoving && _target == pawn) 
+            {
+            	if (_clientMovingToPawnOffset == offset)
+            	{
+            		if (GameTimeController.getGameTicks() < _moveToPawnTimeout) return;
+                    sendPacket = false;	
+            	}
+            	else if (_actor.isOnGeodataPath()) 
+            	{
+            		// minimum time to calculate new route is 2 seconds
+            		if (GameTimeController.getGameTicks() < (_moveToPawnTimeout+10)) return;            		
+            	}
+            }
+
+            // Set AI movement data
+            _clientMoving = true;
+            _clientMovingToPawnOffset = offset;
+            _target = pawn;
+            _moveToPawnTimeout = GameTimeController.getGameTicks();
+            _moveToPawnTimeout += 1000 / GameTimeController.MILLIS_IN_TICK;
+
+            if (pawn == null || _accessor == null) return;
+
+            // Calculate movement data for a move to location action and add the actor to movingObjects of GameTimeController
+            _accessor.moveTo(pawn.getX(), pawn.getY(), pawn.getZ(), offset);
+
+            if (!_actor.isMoving()) 
+            {
+            	_actor.sendPacket(new ActionFailed());
+            	return;
+            }
+
+            // Send a Server->Client packet MoveToPawn/CharMoveToLocation to the actor and all L2PcInstance in its _knownPlayers
+            if (pawn instanceof L2Character) {
+            	if(_actor.isOnGeodataPath())
+            	{
+            		_actor.broadcastPacket(new MoveToLocation(_actor));
+            		_clientMovingToPawnOffset = 0;
+            	}
+            	else if (sendPacket) // don't repeat unnecessarily
+            		_actor.broadcastPacket(new MoveToPawn(_actor, (L2Character) pawn, offset));
+            }
+            else 
+            	_actor.broadcastPacket(new MoveToLocation(_actor));
+        }
+        else
+        {
+            _actor.sendPacket(new ActionFailed());
+        }
+    }
+
+    /**
+     * Move the actor to Location (x,y,z) server side AND client side by sending Server->Client packet CharMoveToLocation <I>(broadcast)</I>.<BR><BR>
+     *
+     * <FONT COLOR=#FF0000><B> <U>Caution</U> : Low level function, used by AI subclasses</B></FONT><BR><BR>
+     *
+     */
+    protected void moveTo(int x, int y, int z)
+    {
+        // Chek if actor can move
+        if (!_actor.isMovementDisabled())
+        {
+            // Set AI movement data
+            _clientMoving = true;
+            _clientMovingToPawnOffset = 0;
+
+            // Calculate movement data for a move to location action and add the actor to movingObjects of GameTimeController
+            _accessor.moveTo(x, y, z);
+
+            // Send a Server->Client packet CharMoveToLocation to the actor and all L2PcInstance in its _knownPlayers
+            MoveToLocation msg = new MoveToLocation(_actor);
+            _actor.broadcastPacket(msg);
+
+        }
+        else
+        {
+            _actor.sendPacket(new ActionFailed());
+        }
+    }
+
+    protected void moveToInABoat(L2CharPosition destination, L2CharPosition origin)
+    {
+        // Chek if actor can move
+        if (!_actor.isMovementDisabled())
+        {
+            /*	// Set AI movement data
+             _client_moving = true;
+             _client_moving_to_pawn_offset = 0;
+
+             // Calculate movement data for a move to location action and add the actor to movingObjects of GameTimeController
+             _accessor.moveTo(((L2PcInstance)_actor).getBoat().getX() - destination.x,((L2PcInstance)_actor).getBoat().getY()- destination.y,((L2PcInstance)_actor).getBoat().getZ() - destination.z);
+             */
+            // Send a Server->Client packet CharMoveToLocation to the actor and all L2PcInstance in its _knownPlayers
+            //CharMoveToLocation msg = new CharMoveToLocation(_actor);
+            if (((L2PcInstance) _actor).getBoat() != null)
+            {
+                MoveToLocationInVehicle msg = new MoveToLocationInVehicle(_actor, destination, origin);
+                _actor.broadcastPacket(msg);
+            }
+
+        }
+        else
+        {
+            _actor.sendPacket(new ActionFailed());
+        }
+    }
+
+    /**
+     * Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation <I>(broadcast)</I>.<BR><BR>
+     *
+     * <FONT COLOR=#FF0000><B> <U>Caution</U> : Low level function, used by AI subclasses</B></FONT><BR><BR>
+     *
+     */
+    protected void clientStopMoving(L2CharPosition pos)
+    {
+        /*
+         if (Config.DEBUG)
+         _log.warning("clientStopMoving();");
+         */
+
+        // Stop movement of the L2Character
+        if (_actor.isMoving()) _accessor.stopMove(pos);
+
+        _clientMovingToPawnOffset = 0;
+
+        if (_clientMoving || pos != null)
+        {
+            _clientMoving = false;
+
+            // Send a Server->Client packet StopMove to the actor and all L2PcInstance in its _knownPlayers
+            StopMove msg = new StopMove(_actor);
+            _actor.broadcastPacket(msg);
+
+            if (pos != null)
+            {
+                // Send a Server->Client packet StopRotation to the actor and all L2PcInstance in its _knownPlayers
+                StopRotation sr = new StopRotation(_actor, pos.heading);
+                _actor.sendPacket(sr);
+                _actor.broadcastPacket(sr);
+            }
+        }
+    }
+
+    // Client has already arrived to target, no need to force StopMove packet
+    protected void clientStoppedMoving()
+    {
+    	if (_clientMovingToPawnOffset > 0) // movetoPawn needs to be stopped
+    	{
+    		_clientMovingToPawnOffset = 0;
+    		StopMove msg = new StopMove(_actor);
+            _actor.broadcastPacket(msg);
+    	}
+    	_clientMoving = false;
+    }
+
+    public boolean isAutoAttacking()
+    {
+        return _clientAutoAttacking;
+    }
+
+    public void setAutoAttacking(boolean isAutoAttacking)
+    {
+        _clientAutoAttacking = isAutoAttacking;
+    }
+
+    /**
+     * Start the actor Auto Attack client side by sending Server->Client packet AutoAttackStart <I>(broadcast)</I>.<BR><BR>
+     *
+     * <FONT COLOR=#FF0000><B> <U>Caution</U> : Low level function, used by AI subclasses</B></FONT><BR><BR>
+     *
+     */
+    public void clientStartAutoAttack()
+    {
+        if (!isAutoAttacking())
+        {
+            // Send a Server->Client packet AutoAttackStart to the actor and all L2PcInstance in its _knownPlayers
+            _actor.broadcastPacket(new AutoAttackStart(_actor.getObjectId()));
+            setAutoAttacking(true);
+        }
+        AttackStanceTaskManager.getInstance().addAttackStanceTask(_actor);
+    }
+
+    /**
+     * Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop <I>(broadcast)</I>.<BR><BR>
+     *
+     * <FONT COLOR=#FF0000><B> <U>Caution</U> : Low level function, used by AI subclasses</B></FONT><BR><BR>
+     *
+     */
+    public void clientStopAutoAttack()
+    {
+        if (_actor instanceof L2PcInstance)
+        {
+            if (!AttackStanceTaskManager.getInstance().getAttackStanceTask(_actor) && isAutoAttacking())
+                AttackStanceTaskManager.getInstance().addAttackStanceTask(_actor);
+        }
+        else if (isAutoAttacking())
+        {
+            _actor.broadcastPacket(new AutoAttackStop(_actor.getObjectId()));
+        }
+        setAutoAttacking(false);
+    }
+
+    /**
+     * Kill the actor client side by sending Server->Client packet AutoAttackStop, StopMove/StopRotation, Die <I>(broadcast)</I>.<BR><BR>
+     *
+     * <FONT COLOR=#FF0000><B> <U>Caution</U> : Low level function, used by AI subclasses</B></FONT><BR><BR>
+     *
+     */
+    protected void clientNotifyDead()
+    {
+        // Send a Server->Client packet Die to the actor and all L2PcInstance in its _knownPlayers
+        Die msg = new Die(_actor);
+        _actor.broadcastPacket(msg);
+
+        // Init AI
+        _intention = AI_INTENTION_IDLE;
+        _target = null;
+        _castTarget = null;
+        _attackTarget = null;
+
+        // Cancel the follow task if necessary
+        stopFollow();
+    }
+
+    /**
+     * Update the state of this actor client side by sending Server->Client packet MoveToPawn/CharMoveToLocation and AutoAttackStart to the L2PcInstance player.<BR><BR>
+     *
+     * <FONT COLOR=#FF0000><B> <U>Caution</U> : Low level function, used by AI subclasses</B></FONT><BR><BR>
+     *
+     * @param player The L2PcIstance to notify with state of this L2Character
+     *
+     */
+    public void describeStateToPlayer(L2PcInstance player)
+    {
+        if (_clientMoving)
+        {
+            if (_clientMovingToPawnOffset != 0 && _followTarget != null)
+            {
+                // Send a Server->Client packet MoveToPawn to the actor and all L2PcInstance in its _knownPlayers
+                MoveToPawn msg = new MoveToPawn(_actor, _followTarget, _clientMovingToPawnOffset);
+                player.sendPacket(msg);
+            }
+            else
+            {
+                // Send a Server->Client packet CharMoveToLocation to the actor and all L2PcInstance in its _knownPlayers
+                MoveToLocation msg = new MoveToLocation(_actor);
+                player.sendPacket(msg);
+            }
+        }
+    }
+
+    /**
+     * Create and Launch an AI Follow Task to execute every 1s.<BR><BR>
+     *
+     * @param target The L2Character to follow
+     *
+     */
+    public synchronized void startFollow(L2Character target)
+    {
+        if (_followTask != null)
+        {
+            _followTask.cancel(false);
+            _followTask = null;
+        }
+
+        // Create and Launch an AI Follow Task to execute every 1s
+        _followTarget = target;
+        _followTask = ThreadPoolManager.getInstance().scheduleAiAtFixedRate(new FollowTask(), 5,
+                                                                             FOLLOW_INTERVAL);
+    }
+
+    /**
+     * Create and Launch an AI Follow Task to execute every 0.5s, following at specified range.<BR><BR>
+     *
+     * @param target The L2Character to follow
+     *
+     */
+    public synchronized void startFollow(L2Character target, int range)
+    {
+        if (_followTask != null)
+        {
+            _followTask.cancel(false);
+            _followTask = null;
+        }
+
+        _followTarget = target;
+        _followTask = ThreadPoolManager.getInstance().scheduleAiAtFixedRate(new FollowTask(range), 5,
+                                                                             ATTACK_FOLLOW_INTERVAL);
+    }
+
+    /**
+     * Stop an AI Follow Task.<BR><BR>
+     */
+    public synchronized void stopFollow()
+    {
+        if (_followTask != null)
+        {
+            // Stop the Follow Task
+            _followTask.cancel(false);
+            _followTask = null;
+        }
+        _followTarget = null;
+    }
+
+    protected L2Character getFollowTarget()
+    {
+        return _followTarget;
+    }
+
+    protected L2Object getTarget()
+    {
+        return _target;
+    }
+
+    protected synchronized void setTarget(L2Object target)
+    {
+        _target = target;
+    }
+
+}

+ 86 - 0
L2_GameServer_T1/java/net/sf/l2j/gameserver/ai/Ctrl.java

@@ -0,0 +1,86 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+package net.sf.l2j.gameserver.ai;
+
+import net.sf.l2j.gameserver.model.L2Character;
+
+/**
+ * Interface of AI and client state.
+ *
+ * To correctly send messages to client we need it's state.
+ * For example, if we've sent 'StartAutoAttack' message, we need to
+ * send 'StopAutoAttack' message before any other action. Or
+ * if we've sent 'MoveToPawn', we need to send 'StopMove' when
+ * the movement of a character is canceled (by Root spell or
+ * any other reason). Thus, we need to know the state of
+ * client, i.e. which messages we've sent and how the client
+ * will show the scene.
+ *
+ * Close to this task is the task of AI.
+ * If a player's character is attacking a mob, his ATTACK may be
+ * iterrupted by an event, that temporary disable attacking.
+ * But when the possibility to ATTACK will be enabled, the
+ * character must continue the ATTACK. For mobs it may be
+ * more complex, since we want them to decide when to use magic,
+ * or when to follow the player for physical combat, or when to escape,
+ * to help another mob, etc.
+ *
+ * This interface is hiding complexity of server<->client
+ * interaction and multiple states of a character. It allows to
+ * set a desired, simple "wish" of a character, and the implementation
+ * of this interface will take care about the rest.
+ * The goal of a character may be like "ATTACK", "random walk" and so on.
+ * To reach the goal inplementation will split it into several small
+ * actions, several steps (possibly repeatable). Like "run to target"
+ * then "hit it", then if target is not dead - repeat.
+ * This flow of simplier steps may be interrupted by incoming events.
+ * Like a character's movement was disabled (by Root spell, for instance).
+ * Depending on character's ability AI may choose to wait, or to use
+ * magic ATTACK and so on.
+ * Additionally incoming events are compared with client's state
+ * of the character, and required network messages are sent to
+ * client's, i.e. if we have incoming event that character's movement
+ * was disabled, it causes changing if its behavour, and if client's
+ * state for the character is "moving" we send messages to clients
+ * to stop the avatar/mob.
+ *
+ */
+public interface Ctrl {
+
+	/** the character this AI serves */
+	L2Character getActor();
+
+	/** get current intention */
+	CtrlIntention getIntention();
+
+	/** get current ATTACK target */
+	L2Character getAttackTarget();
+
+	/** Set general state/intention for AI, with optional data */
+	void setIntention(CtrlIntention intention);
+	void setIntention(CtrlIntention intention, Object arg0);
+	void setIntention(CtrlIntention intention, Object arg0, Object arg1);
+
+	/** Event, that notifies about previous step result, or user command,
+	 * that does not change current general intention */
+	void notifyEvent(CtrlEvent evt);
+	void notifyEvent(CtrlEvent evt, Object arg0);
+	void notifyEvent(CtrlEvent evt, Object arg0, Object arg1);
+}
+

+ 81 - 0
L2_GameServer_T1/java/net/sf/l2j/gameserver/ai/CtrlEvent.java

@@ -0,0 +1,81 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+package net.sf.l2j.gameserver.ai;
+
+/**
+ * This class contains an enum of each possibles evenements that can happen on an AI character.
+ */
+
+public enum CtrlEvent {
+	/** Something has changed, usually a previous step has being completed
+	 * or maybe was completed, the AI must thing on next action
+	 */
+	EVT_THINK,
+	/** The actor was attacked. This event comes each time a physical or magical
+	 * attack was done on the actor. NPC may start attack in responce, or ignore
+	 * this event if they already attack someone, or change target and so on.
+	 */
+	EVT_ATTACKED,
+	/** Increase/decrease aggression towards a target, or reduce global aggression if target is null */
+	EVT_AGGRESSION,
+	/** Actor is in stun state */
+	EVT_STUNNED,
+	/** Actor starts/stops sleeping */
+	EVT_SLEEPING,
+	/** Actor is in rooted state (cannot move) */
+	EVT_ROOTED,
+	/** An event that previous action was completed. The action may be an attempt
+	 * to physically/magically hit an enemy, or an action that discarded
+	 * attack attempt has finished. */
+	EVT_READY_TO_ACT,
+	/** User's command, like using a combat magic or changing weapon, etc.
+	 * The command is not intended to change final goal */
+	EVT_USER_CMD,
+	/** The actor arrived to assigned location, or it's a time to modify
+	 * movement destination (follow, interact, random move and others intentions). */
+	EVT_ARRIVED,
+	/** The actor arrived to an intermidiate point, and needs revalidate destination.
+	 * This is sent when follow/move to pawn if destination is far away. */
+	EVT_ARRIVED_REVALIDATE,
+	/** The actor cannot move anymore. */
+	EVT_ARRIVED_BLOCKED,
+	/** Forgets an object (if it's used as attack target, follow target and so on */
+	EVT_FORGET_OBJECT,
+	/** Attempt to cancel current step execution, but not change the intention.
+	 * For example, the actor was putted into a stun, so it's current attack
+	 * or movement has to be canceled. But after the stun state expired, the
+	 * actor may try to attack again. Another usage for CANCEL is a user's
+	 * attempt to cancel a cast/bow attack and so on.
+	 */
+	EVT_CANCEL,
+	/** The character is dead */
+	EVT_DEAD,
+    /** The character looks like dead */
+    EVT_FAKE_DEATH,
+	/** The character attack anyone randomly **/
+	EVT_CONFUSED,
+	/** The character cannot cast spells anymore **/
+	EVT_MUTED,
+	/** The character flee in randoms directions **/
+	EVT_AFFRAID,
+	/** The character finish casting **/
+	EVT_FINISH_CASTING,
+	/** The character betrayed its master */
+	EVT_BETRAYED
+}

+ 47 - 0
L2_GameServer_T1/java/net/sf/l2j/gameserver/ai/CtrlIntention.java

@@ -0,0 +1,47 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+package net.sf.l2j.gameserver.ai;
+
+/** Enumaration of generic intentions of an NPC/PC, an intention may require
+ * several steps to be completed */
+
+public enum CtrlIntention
+{
+	/** Do nothing, disconnect AI of NPC if no players around */
+	AI_INTENTION_IDLE,
+	/** Alerted state without goal : scan attackable targets, random walk, etc */
+	AI_INTENTION_ACTIVE,
+	/** Rest (sit until attacked) */
+	AI_INTENTION_REST,
+	/** Attack target (cast combat magic, go to target, combat), may be ignored,
+	 * if target is locked on another character or a peacefull zone and so on */
+	AI_INTENTION_ATTACK,
+	/** Cast a spell, depending on the spell - may start or stop attacking */
+	AI_INTENTION_CAST,
+	/** Just move to another location */
+	AI_INTENTION_MOVE_TO,
+	/** Like move, but check target's movement and follow it */
+	AI_INTENTION_FOLLOW,
+	/** PickUp and item, (got to item, pickup it, become idle */
+	AI_INTENTION_PICK_UP,
+	/** Move to target, then interact */
+	AI_INTENTION_INTERACT,
+	/** Move to another location in a boat */
+	AI_INTENTION_MOVE_TO_IN_A_BOAT;
+}

+ 877 - 0
L2_GameServer_T1/java/net/sf/l2j/gameserver/ai/L2AttackableAI.java

@@ -0,0 +1,877 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+package net.sf.l2j.gameserver.ai;
+
+import static net.sf.l2j.gameserver.ai.CtrlIntention.AI_INTENTION_ACTIVE;
+import static net.sf.l2j.gameserver.ai.CtrlIntention.AI_INTENTION_ATTACK;
+import static net.sf.l2j.gameserver.ai.CtrlIntention.AI_INTENTION_IDLE;
+
+import java.util.concurrent.Future;
+
+import net.sf.l2j.Config;
+import net.sf.l2j.gameserver.GameTimeController;
+import net.sf.l2j.gameserver.GeoData;
+import net.sf.l2j.gameserver.Territory;
+import net.sf.l2j.gameserver.ThreadPoolManager;
+import net.sf.l2j.gameserver.instancemanager.DimensionalRiftManager;
+import net.sf.l2j.gameserver.model.L2Attackable;
+import net.sf.l2j.gameserver.model.L2CharPosition;
+import net.sf.l2j.gameserver.model.L2Character;
+import net.sf.l2j.gameserver.model.L2Effect;
+import net.sf.l2j.gameserver.model.L2Object;
+import net.sf.l2j.gameserver.model.L2Skill;
+import net.sf.l2j.gameserver.model.L2Summon;
+import net.sf.l2j.gameserver.model.actor.instance.L2DoorInstance;
+import net.sf.l2j.gameserver.model.actor.instance.L2FestivalMonsterInstance;
+import net.sf.l2j.gameserver.model.actor.instance.L2FolkInstance;
+import net.sf.l2j.gameserver.model.actor.instance.L2FriendlyMobInstance;
+import net.sf.l2j.gameserver.model.actor.instance.L2GuardInstance;
+import net.sf.l2j.gameserver.model.actor.instance.L2MinionInstance;
+import net.sf.l2j.gameserver.model.actor.instance.L2MonsterInstance;
+import net.sf.l2j.gameserver.model.actor.instance.L2NpcInstance;
+import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
+import net.sf.l2j.gameserver.model.actor.instance.L2PenaltyMonsterInstance;
+import net.sf.l2j.gameserver.model.actor.instance.L2RaidBossInstance;
+import net.sf.l2j.gameserver.model.actor.instance.L2RiftInvaderInstance;
+import net.sf.l2j.gameserver.templates.L2Weapon;
+import net.sf.l2j.gameserver.templates.L2WeaponType;
+import net.sf.l2j.util.Rnd;
+
+/**
+ * This class manages AI of L2Attackable.<BR><BR>
+ *
+ */
+public class L2AttackableAI extends L2CharacterAI implements Runnable
+{
+
+    //protected static final Logger _log = Logger.getLogger(L2AttackableAI.class.getName());
+
+    private static final int RANDOM_WALK_RATE = 30; // confirmed
+    // private static final int MAX_DRIFT_RANGE = 300;
+    private static final int MAX_ATTACK_TIMEOUT = 300; // int ticks, i.e. 30 seconds
+
+    /** The L2Attackable AI task executed every 1s (call onEvtThink method)*/
+    private Future<?> _aiTask;
+
+    /** The delay after wich the attacked is stopped */
+    private int _attackTimeout;
+
+    /** The L2Attackable aggro counter */
+    private int _globalAggro;
+
+    /** The flag used to indicate that a thinking action is in progress */
+    private boolean _thinking; // to prevent recursive thinking
+
+    /**
+     * Constructor of L2AttackableAI.<BR><BR>
+     *
+     * @param accessor The AI accessor of the L2Character
+     *
+     */
+    public L2AttackableAI(L2Character.AIAccessor accessor)
+    {
+        super(accessor);
+
+        _attackTimeout = Integer.MAX_VALUE;
+        _globalAggro = -10; // 10 seconds timeout of ATTACK after respawn
+    }
+
+    public void run()
+    {
+        // Launch actions corresponding to the Event Think
+        onEvtThink();
+
+    }
+
+    /**
+     * Return True if the target is autoattackable (depends on the actor type).<BR><BR>
+     *
+     * <B><U> Actor is a L2GuardInstance</U> :</B><BR><BR>
+     * <li>The target isn't a Folk or a Door</li>
+     * <li>The target isn't dead, isn't invulnerable, isn't in silent moving mode AND too far (>100)</li>
+     * <li>The target is in the actor Aggro range and is at the same height</li>
+     * <li>The L2PcInstance target has karma (=PK)</li>
+     * <li>The L2MonsterInstance target is aggressive</li><BR><BR>
+     *
+     * <B><U> Actor is a L2SiegeGuardInstance</U> :</B><BR><BR>
+     * <li>The target isn't a Folk or a Door</li>
+     * <li>The target isn't dead, isn't invulnerable, isn't in silent moving mode AND too far (>100)</li>
+     * <li>The target is in the actor Aggro range and is at the same height</li>
+     * <li>A siege is in progress</li>
+     * <li>The L2PcInstance target isn't a Defender</li><BR><BR>
+     *
+     * <B><U> Actor is a L2FriendlyMobInstance</U> :</B><BR><BR>
+     * <li>The target isn't a Folk, a Door or another L2NpcInstance</li>
+     * <li>The target isn't dead, isn't invulnerable, isn't in silent moving mode AND too far (>100)</li>
+     * <li>The target is in the actor Aggro range and is at the same height</li>
+     * <li>The L2PcInstance target has karma (=PK)</li><BR><BR>
+     *
+     * <B><U> Actor is a L2MonsterInstance</U> :</B><BR><BR>
+     * <li>The target isn't a Folk, a Door or another L2NpcInstance</li>
+     * <li>The target isn't dead, isn't invulnerable, isn't in silent moving mode AND too far (>100)</li>
+     * <li>The target is in the actor Aggro range and is at the same height</li>
+     * <li>The actor is Aggressive</li><BR><BR>
+     *
+     * @param target The targeted L2Object
+     *
+     */
+    private boolean autoAttackCondition(L2Character target)
+    {
+        if (target == null || !(_actor instanceof L2Attackable)) return false;
+        L2Attackable me = (L2Attackable) _actor;
+
+        // Check if the target isn't invulnerable
+        if (target.isInvul())
+        {
+            // However EffectInvincible requires to check GMs specially
+        	if (target instanceof L2PcInstance && ((L2PcInstance)target).isGM())
+                return false;
+            if (target instanceof L2Summon && ((L2Summon)target).getOwner().isGM())
+                return false;
+        }
+
+        // Check if the target isn't a Folk or a Door
+        if (target instanceof L2FolkInstance || target instanceof L2DoorInstance) return false;
+
+        // Check if the target isn't dead, is in the Aggro range and is at the same height
+        if (target.isAlikeDead()
+            || !me.isInsideRadius(target, me.getAggroRange(), false, false)
+            || Math.abs(_actor.getZ() - target.getZ()) > 300) return false;
+
+        // Check if the target is a L2PcInstance
+        if (target instanceof L2PcInstance)
+        {
+            // Don't take the aggro if the GM has the access level below or equal to GM_DONT_TAKE_AGGRO
+            if (((L2PcInstance)target).isGM() && ((L2PcInstance)target).getAccessLevel() <= Config.GM_DONT_TAKE_AGGRO)
+                return false;
+
+            // Check if the AI isn't a Raid Boss and the target isn't in silent move mode
+            if (!(me instanceof L2RaidBossInstance) && ((L2PcInstance)target).isSilentMoving())
+                return false;
+
+            // Check if player is an ally //TODO! [Nemesiss] it should be rather boolean or smth like that
+            // Comparing String isnt good idea!
+            if (me.getFactionId() == "varka" && ((L2PcInstance)target).isAlliedWithVarka())
+                return false;
+            if (me.getFactionId() == "ketra" && ((L2PcInstance)target).isAlliedWithKetra())
+                return false;
+            // check if the target is within the grace period for JUST getting up from fake death
+            if (((L2PcInstance)target).isRecentFakeDeath())
+                return false;
+
+            if (target.isInParty() && target.getParty().isInDimensionalRift())
+            {
+                byte riftType = target.getParty().getDimensionalRift().getType();
+                byte riftRoom = target.getParty().getDimensionalRift().getCurrentRoom();
+
+                if (me instanceof L2RiftInvaderInstance
+                        && !DimensionalRiftManager.getInstance().getRoom(riftType, riftRoom).checkIfInZone(me.getX(), me.getY(), me.getZ()))
+                    return false;
+            }
+        }
+
+        // Check if the actor is a L2GuardInstance
+        if (_actor instanceof L2GuardInstance)
+        {
+
+            // Check if the L2PcInstance target has karma (=PK)
+            if (target instanceof L2PcInstance && ((L2PcInstance) target).getKarma() > 0)
+                // Los Check
+                return GeoData.getInstance().canSeeTarget(me, target);
+
+            //if (target instanceof L2Summon)
+            //    return ((L2Summon)target).getKarma() > 0;
+
+            // Check if the L2MonsterInstance target is aggressive
+            if (target instanceof L2MonsterInstance)
+                return (((L2MonsterInstance) target).isAggressive() && GeoData.getInstance().canSeeTarget(me, target));
+
+            return false;
+        }
+        else if (_actor instanceof L2FriendlyMobInstance)
+        { // the actor is a L2FriendlyMobInstance
+
+            // Check if the target isn't another L2NpcInstance
+            if (target instanceof L2NpcInstance) return false;
+
+            // Check if the L2PcInstance target has karma (=PK)
+            if (target instanceof L2PcInstance && ((L2PcInstance) target).getKarma() > 0)
+                // Los Check
+               return GeoData.getInstance().canSeeTarget(me, target);
+            else
+                return false;
+        }
+        else
+        { //The actor is a L2MonsterInstance
+
+            // Check if the target isn't another L2NpcInstance
+            if (target instanceof L2NpcInstance) return false;
+
+            // depending on config, do not allow mobs to attack _new_ players in peacezones,
+            // unless they are already following those players from outside the peacezone.
+            if (!Config.ALT_MOB_AGRO_IN_PEACEZONE && target.isInsideZone(L2Character.ZONE_PEACE))
+                return false;
+
+            // Check if the actor is Aggressive
+            return (me.isAggressive() && GeoData.getInstance().canSeeTarget(me, target));
+        }
+    }
+    public void startAITask()
+    {
+        // If not idle - create an AI task (schedule onEvtThink repeatedly)
+        if (_aiTask == null)
+        {
+            _aiTask = ThreadPoolManager.getInstance().scheduleAiAtFixedRate(this, 1000, 1000);
+        }
+    }
+
+    public void stopAITask()
+    {
+        if (_aiTask != null)
+        {
+            _aiTask.cancel(false);
+            _aiTask = null;
+        }
+    }
+
+    @Override
+	protected void onEvtDead()
+    {
+        stopAITask();
+        super.onEvtDead();
+    }
+
+    /**
+     * Set the Intention of this L2CharacterAI and create an  AI Task executed every 1s (call onEvtThink method) for this L2Attackable.<BR><BR>
+     *
+     * <FONT COLOR=#FF0000><B> <U>Caution</U> : If actor _knowPlayer isn't EMPTY, AI_INTENTION_IDLE will be change in AI_INTENTION_ACTIVE</B></FONT><BR><BR>
+     *
+     * @param intention The new Intention to set to the AI
+     * @param arg0 The first parameter of the Intention
+     * @param arg1 The second parameter of the Intention
+     *
+     */
+    @Override
+	synchronized void changeIntention(CtrlIntention intention, Object arg0, Object arg1)
+    {
+        if (intention == AI_INTENTION_IDLE || intention == AI_INTENTION_ACTIVE)
+        {
+            // Check if actor is not dead
+            if (!_actor.isAlikeDead())
+            {
+                L2Attackable npc = (L2Attackable) _actor;
+
+                // If its _knownPlayer isn't empty set the Intention to AI_INTENTION_ACTIVE
+                if (npc.getKnownList().getKnownPlayers().size() > 0) intention = AI_INTENTION_ACTIVE;
+            }
+
+            if (intention == AI_INTENTION_IDLE)
+            {
+                // Set the Intention of this L2AttackableAI to AI_INTENTION_IDLE
+                super.changeIntention(AI_INTENTION_IDLE, null, null);
+
+                // Stop AI task and detach AI from NPC
+                if (_aiTask != null)
+                {
+                    _aiTask.cancel(true);
+                    _aiTask = null;
+                }
+
+                // Cancel the AI
+                _accessor.detachAI();
+
+                return;
+            }
+        }
+
+        // Set the Intention of this L2AttackableAI to intention
+        super.changeIntention(intention, arg0, arg1);
+
+        // If not idle - create an AI task (schedule onEvtThink repeatedly)
+        startAITask();
+    }
+
+    /**
+     * Manage the Attack Intention : Stop current Attack (if necessary), Calculate attack timeout, Start a new Attack and Launch Think Event.<BR><BR>
+     *
+     * @param target The L2Character to attack
+     *
+     */
+    @Override
+	protected void onIntentionAttack(L2Character target)
+    {
+        // Calculate the attack timeout
+        _attackTimeout = MAX_ATTACK_TIMEOUT + GameTimeController.getGameTicks();
+
+        // Manage the Attack Intention : Stop current Attack (if necessary), Start a new Attack and Launch Think Event
+        super.onIntentionAttack(target);
+    }
+
+    /**
+     * Manage AI standard thinks of a L2Attackable (called by onEvtThink).<BR><BR>
+     *
+     * <B><U> Actions</U> :</B><BR><BR>
+     * <li>Update every 1s the _globalAggro counter to come close to 0</li>
+     * <li>If the actor is Aggressive and can attack, add all autoAttackable L2Character in its Aggro Range to its _aggroList, chose a target and order to attack it</li>
+     * <li>If the actor is a L2GuardInstance that can't attack, order to it to return to its home location</li>
+     * <li>If the actor is a L2MonsterInstance that can't attack, order to it to random walk (1/100)</li><BR><BR>
+     *
+     */
+    private void thinkActive()
+    {
+        L2Attackable npc = (L2Attackable) _actor;
+
+        // Update every 1s the _globalAggro counter to come close to 0
+        if (_globalAggro != 0)
+        {
+            if (_globalAggro < 0) _globalAggro++;
+            else _globalAggro--;
+        }
+
+        // Add all autoAttackable L2Character in L2Attackable Aggro Range to its _aggroList with 0 damage and 1 hate
+        // A L2Attackable isn't aggressive during 10s after its spawn because _globalAggro is set to -10
+        if (_globalAggro >= 0)
+        {
+            // Get all visible objects inside its Aggro Range
+            //L2Object[] objects = L2World.getInstance().getVisibleObjects(_actor, ((L2NpcInstance)_actor).getAggroRange());
+            // Go through visible objects
+            for (L2Object obj : npc.getKnownList().getKnownObjects().values())
+            {
+                if (obj == null || !(obj instanceof L2Character)) continue;
+                L2Character target = (L2Character) obj;
+
+                /*
+                 * Check to see if this is a festival mob spawn.
+                 * If it is, then check to see if the aggro trigger
+                 * is a festival participant...if so, move to attack it.
+                 */
+                if ((_actor instanceof L2FestivalMonsterInstance) && obj instanceof L2PcInstance)
+                {
+                    L2PcInstance targetPlayer = (L2PcInstance) obj;
+
+                    if (!(targetPlayer.isFestivalParticipant())) continue;
+                }
+
+                // For each L2Character check if the target is autoattackable
+                if (autoAttackCondition(target)) // check aggression
+                {
+                    // Get the hate level of the L2Attackable against this L2Character target contained in _aggroList
+                    int hating = npc.getHating(target);
+
+                    // Add the attacker to the L2Attackable _aggroList with 0 damage and 1 hate
+                    if (hating == 0) npc.addDamageHate(target, 0, 1);
+                }
+            }
+
+            // Chose a target from its aggroList
+            L2Character hated;
+            if (_actor.isConfused()) hated = getAttackTarget(); // Force mobs to attak anybody if confused
+            else hated = npc.getMostHated();
+
+            // Order to the L2Attackable to attack the target
+            if (hated != null)
+            {
+                // Get the hate level of the L2Attackable against this L2Character target contained in _aggroList
+                int aggro = npc.getHating(hated);
+
+                if (aggro + _globalAggro > 0)
+                {
+                    // Set the L2Character movement type to run and send Server->Client packet ChangeMoveType to all others L2PcInstance
+                    if (!_actor.isRunning()) _actor.setRunning();
+
+                    // Set the AI Intention to AI_INTENTION_ATTACK
+                    setIntention(CtrlIntention.AI_INTENTION_ATTACK, hated);
+                }
+
+                return;
+            }
+
+        }
+
+        // Check if the actor is a L2GuardInstance
+        if (_actor instanceof L2GuardInstance)
+        {
+            // Order to the L2GuardInstance to return to its home location because there's no target to attack
+            ((L2GuardInstance) _actor).returnHome();
+        }
+
+        // If this is a festival monster, then it remains in the same location.
+        if (_actor instanceof L2FestivalMonsterInstance) return;
+
+        // Minions following leader
+        if (_actor instanceof L2MinionInstance && ((L2MinionInstance)_actor).getLeader() != null)
+        {
+            int offset;
+
+            if (_actor.isRaid()) offset = 500; // for Raids - need correction
+            else offset = 200; // for normal minions - need correction :)
+
+            if(((L2MinionInstance)_actor).getLeader().isRunning())	_actor.setRunning();
+            else _actor.setWalking();
+
+            if (_actor.getPlanDistanceSq(((L2MinionInstance)_actor).getLeader()) > offset*offset)
+            {
+                int x1, y1, z1;
+                x1 = ((L2MinionInstance)_actor).getLeader().getX() + Rnd.nextInt( (offset - 30) * 2 ) - ( offset - 30 );
+                y1 = ((L2MinionInstance)_actor).getLeader().getY() + Rnd.nextInt( (offset - 30) * 2 ) - ( offset - 30 );
+                z1 = ((L2MinionInstance)_actor).getLeader().getZ();
+                // Move the actor to Location (x,y,z) server side AND client side by sending Server->Client packet CharMoveToLocation (broadcast)
+                moveTo(x1, y1, z1);
+                return;
+            }
+        }
+        // Order to the L2MonsterInstance to random walk (1/100)
+        else if (npc.getSpawn() != null && Rnd.nextInt(RANDOM_WALK_RATE) == 0)
+        {
+            int x1, y1, z1;
+
+            // If NPC with random coord in territory
+            if (npc.getSpawn().getLocx() == 0 && npc.getSpawn().getLocy() == 0)
+            {
+                // If NPC with random fixed coord, don't move
+                if (Territory.getInstance().getProcMax(npc.getSpawn().getLocation()) > 0) return;
+
+                // Calculate a destination point in the spawn area
+                int p[] = Territory.getInstance().getRandomPoint(npc.getSpawn().getLocation());
+                x1 = p[0];
+                y1 = p[1];
+                z1 = p[2];
+
+                // Calculate the distance between the current position of the L2Character and the target (x,y)
+                double distance2 = _actor.getPlanDistanceSq(x1, y1);
+
+                if (distance2 > Config.MAX_DRIFT_RANGE * Config.MAX_DRIFT_RANGE)
+                {
+                    npc.setisReturningToSpawnPoint(true);
+                	float delay = (float) Math.sqrt(distance2) / Config.MAX_DRIFT_RANGE;
+                    x1 = _actor.getX() + (int) ((x1 - _actor.getX()) / delay);
+                    y1 = _actor.getY() + (int) ((y1 - _actor.getY()) / delay);
+                }
+                else
+                	npc.setisReturningToSpawnPoint(false);
+
+            }
+            else
+            {
+                // If NPC with fixed coord
+                x1 = npc.getSpawn().getLocx() + Rnd.nextInt(Config.MAX_DRIFT_RANGE * 2)
+                    - Config.MAX_DRIFT_RANGE;
+                y1 = npc.getSpawn().getLocy() + Rnd.nextInt(Config.MAX_DRIFT_RANGE * 2)
+                    - Config.MAX_DRIFT_RANGE;
+                z1 = npc.getZ();
+            }
+
+            //_log.config("Curent pos ("+getX()+", "+getY()+"), moving to ("+x1+", "+y1+").");
+            // Move the actor to Location (x,y,z) server side AND client side by sending Server->Client packet CharMoveToLocation (broadcast)
+            moveTo(x1, y1, z1);
+        }
+
+        return;
+
+    }
+
+    /**
+     * Manage AI attack thinks of a L2Attackable (called by onEvtThink).<BR><BR>
+     *
+     * <B><U> Actions</U> :</B><BR><BR>
+     * <li>Update the attack timeout if actor is running</li>
+     * <li>If target is dead or timeout is expired, stop this attack and set the Intention to AI_INTENTION_ACTIVE</li>
+     * <li>Call all L2Object of its Faction inside the Faction Range</li>
+     * <li>Chose a target and order to attack it with magic skill or physical attack</li><BR><BR>
+     *
+     * TODO: Manage casting rules to healer mobs (like Ant Nurses)
+     *
+     */
+    private void thinkAttack()
+    {
+        if (_attackTimeout < GameTimeController.getGameTicks())
+        {
+            // Check if the actor is running
+            if (_actor.isRunning())
+            {
+                // Set the actor movement type to walk and send Server->Client packet ChangeMoveType to all others L2PcInstance
+                _actor.setWalking();
+
+                // Calculate a new attack timeout
+                _attackTimeout = MAX_ATTACK_TIMEOUT + GameTimeController.getGameTicks();
+            }
+        }
+
+        // Check if target is dead or if timeout is expired to stop this attack
+        if (getAttackTarget() == null || getAttackTarget().isAlikeDead()
+            || _attackTimeout < GameTimeController.getGameTicks())
+        {
+            // Stop hating this target after the attack timeout or if target is dead
+            if (getAttackTarget() != null)
+            {
+                L2Attackable npc = (L2Attackable) _actor;
+                npc.stopHating(getAttackTarget());
+            }
+
+            // Set the AI Intention to AI_INTENTION_ACTIVE
+            setIntention(AI_INTENTION_ACTIVE);
+
+            _actor.setWalking();
+        }
+        else
+        {
+            // Call all L2Object of its Faction inside the Faction Range
+            if (((L2NpcInstance) _actor).getFactionId() != null)
+            {
+                String faction_id = ((L2NpcInstance) _actor).getFactionId();
+
+                // Go through all L2Object that belong to its faction
+                for (L2Object obj : _actor.getKnownList().getKnownObjects().values())
+                {
+                    if (obj instanceof L2NpcInstance)
+                    {
+                        L2NpcInstance npc = (L2NpcInstance) obj;
+
+                        if (npc == null || getAttackTarget() == null || faction_id != npc.getFactionId())
+                            continue;
+
+                        // Check if the L2Object is inside the Faction Range of the actor
+                        if (_actor.isInsideRadius(npc, npc.getFactionRange(), true, false)
+                            && GeoData.getInstance().canSeeTarget(_actor, npc)
+                            && Math.abs(getAttackTarget().getZ() - npc.getZ()) < 600
+                            && npc.getAI() != null
+                            && _actor.getAttackByList().contains(getAttackTarget())
+                            && (npc.getAI()._intention == CtrlIntention.AI_INTENTION_IDLE
+                            || npc.getAI()._intention == CtrlIntention.AI_INTENTION_ACTIVE))
+                        {
+                            if (getAttackTarget() instanceof L2PcInstance
+                                && getAttackTarget().isInParty()
+                                && getAttackTarget().getParty().isInDimensionalRift())
+                            {
+                                byte riftType = getAttackTarget().getParty().getDimensionalRift().getType();
+                                byte riftRoom = getAttackTarget().getParty().getDimensionalRift().getCurrentRoom();
+
+                                if (_actor instanceof L2RiftInvaderInstance
+                                    && !DimensionalRiftManager.getInstance().getRoom(riftType, riftRoom).checkIfInZone(npc.getX(), npc.getY(), npc.getZ()))
+                                    continue;
+                            }
+
+                            // Notify the L2Object AI with EVT_AGGRESSION
+                            npc.getAI().notifyEvent(CtrlEvent.EVT_AGGRESSION, getAttackTarget(), 1);
+                        }
+                    }
+                }
+            }
+
+            if(_actor.isAttackingDisabled()) return;
+
+            // Get all information needed to chose between physical or magical attack
+            L2Skill[] skills = null;
+            double dist2 = 0;
+            int range = 0;
+
+            try
+            {
+                _actor.setTarget(getAttackTarget());
+                skills = _actor.getAllSkills();
+                dist2 = _actor.getPlanDistanceSq(getAttackTarget().getX(), getAttackTarget().getY());
+                range = _actor.getPhysicalAttackRange() + _actor.getTemplate().collisionRadius + getAttackTarget().getTemplate().collisionRadius;
+            }
+            catch (NullPointerException e)
+            {
+                //_log.warning("AttackableAI: Attack target is NULL.");
+                setIntention(AI_INTENTION_ACTIVE);
+                return;
+            }
+
+            L2Weapon weapon = _actor.getActiveWeaponItem();
+            if (weapon != null && weapon.getItemType() == L2WeaponType.BOW)
+            {
+                // Micht: kepping this one otherwise we should do 2 sqrt
+                double distance2 = _actor.getPlanDistanceSq(getAttackTarget().getX(), getAttackTarget().getY());
+                if (distance2 <= 10000)
+                {
+                    int chance = 5;
+                    if (chance >= Rnd.get(100))
+                    {
+                        int posX = _actor.getX();
+                        int posY = _actor.getY();
+                        int posZ = _actor.getZ();
+                        double distance = Math.sqrt(distance2); // This way, we only do the sqrt if we need it
+
+                        int signx=-1;
+                        int signy=-1;
+                        if (_actor.getX()>getAttackTarget().getX())
+                            signx=1;
+                        if (_actor.getY()>getAttackTarget().getY())
+                            signy=1;
+                        posX += Math.round((float)((signx * ((range / 2) + (Rnd.get(range)))) - distance));
+                        posY += Math.round((float)((signy * ((range / 2) + (Rnd.get(range)))) - distance));
+                        setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, new L2CharPosition(posX, posY, posZ, 0));
+                        return;
+                    }
+                }
+            }
+
+            // Force mobs to attack anybody if confused
+            L2Character hated;
+            if (_actor.isConfused()) hated = getAttackTarget();
+            else hated = ((L2Attackable) _actor).getMostHated();
+
+            if (hated == null)
+            {
+                setIntention(AI_INTENTION_ACTIVE);
+                return;
+            }
+            if (hated != getAttackTarget())
+            {
+                setAttackTarget(hated);
+            }
+            // We should calculate new distance cuz mob can have changed the target
+            dist2 = _actor.getPlanDistanceSq(hated.getX(), hated.getY());
+
+            if (hated.isMoving()) range += 50;
+            // Check if the actor isn't far from target
+            if (dist2 > range*range)
+            {
+                // check for long ranged skills and heal/buff skills
+                if (!_actor.isMuted() &&
+                	(!Config.ALT_GAME_MOB_ATTACK_AI || (_actor instanceof L2MonsterInstance && Rnd.nextInt(100) <= 5))
+                   )
+                    for (L2Skill sk : skills)
+                    {
+                        int castRange = sk.getCastRange();
+
+                        if (((sk.getSkillType() == L2Skill.SkillType.BUFF || sk.getSkillType() == L2Skill.SkillType.HEAL) || (dist2 >= castRange * castRange / 9.0)
+                            && (dist2 <= castRange * castRange) && (castRange > 70))
+                            && !_actor.isSkillDisabled(sk.getId())
+                            && _actor.getCurrentMp() >= _actor.getStat().getMpConsume(sk)
+                            && !sk.isPassive()
+                            && Rnd.nextInt(100) <= 5)
+                        {
+                            L2Object OldTarget = _actor.getTarget();
+                            if (sk.getSkillType() == L2Skill.SkillType.BUFF
+                                || sk.getSkillType() == L2Skill.SkillType.HEAL)
+                            {
+                                boolean useSkillSelf = true;
+                                if (sk.getSkillType() == L2Skill.SkillType.HEAL
+                                    && _actor.getCurrentHp() > (int) (_actor.getMaxHp() / 1.5))
+                                {
+                                    useSkillSelf = false;
+                                    break;
+                                }
+                                if (sk.getSkillType() == L2Skill.SkillType.BUFF)
+                                {
+                                    L2Effect[] effects = _actor.getAllEffects();
+                                    for (int i = 0; effects != null && i < effects.length; i++)
+                                    {
+                                        L2Effect effect = effects[i];
+                                        if (effect.getSkill() == sk)
+                                        {
+                                            useSkillSelf = false;
+                                            break;
+                                        }
+                                    }
+                                }
+                                if (useSkillSelf) _actor.setTarget(_actor);
+                            }
+
+                            clientStopMoving(null);
+                            _accessor.doCast(sk);
+                            _actor.setTarget(OldTarget);
+                            return;
+                        }
+                    }
+
+                // Move the actor to Pawn server side AND client side by sending Server->Client packet MoveToPawn (broadcast)
+                if (hated.isMoving()) range -= 100; if (range < 5) range = 5;
+                moveToPawn(getAttackTarget(), range);
+                return;
+            }
+            // Else, if this is close enough to attack
+            else
+            {
+                _attackTimeout = MAX_ATTACK_TIMEOUT + GameTimeController.getGameTicks();
+
+                // check for close combat skills && heal/buff skills
+                if (!_actor.isMuted() /*&& _rnd.nextInt(100) <= 5*/)
+                {
+                	boolean useSkillSelf = true;;
+                    for (L2Skill sk : skills)
+                    {
+                        if (/*sk.getCastRange() >= dist && sk.getCastRange() <= 70 && */!sk.isPassive()
+                            && _actor.getCurrentMp() >= _actor.getStat().getMpConsume(sk)
+                            && !_actor.isSkillDisabled(sk.getId()) && (Rnd.nextInt(100) <= 8
+                            || (_actor instanceof L2PenaltyMonsterInstance && Rnd.nextInt(100) <= 20)))
+                        {
+                            L2Object OldTarget = _actor.getTarget();
+                            if (sk.getSkillType() == L2Skill.SkillType.BUFF
+                                || sk.getSkillType() == L2Skill.SkillType.HEAL)
+                            {
+                                useSkillSelf = true;
+                                if (sk.getSkillType() == L2Skill.SkillType.HEAL
+                                    && _actor.getCurrentHp() > (int) (_actor.getMaxHp() / 1.5))
+                                {
+                                    useSkillSelf = false;
+                                    break;
+                                }
+                                if (sk.getSkillType() == L2Skill.SkillType.BUFF)
+                                {
+                                    L2Effect[] effects = _actor.getAllEffects();
+                                    for (int i = 0; effects != null && i < effects.length; i++)
+                                    {
+                                        L2Effect effect = effects[i];
+                                        if (effect.getSkill() == sk)
+                                        {
+                                            useSkillSelf = false;
+                                            break;
+                                        }
+                                    }
+                                }
+                                if (useSkillSelf) _actor.setTarget(_actor);
+                            }
+                            // GeoData Los Check here
+                            if (!useSkillSelf && !GeoData.getInstance().canSeeTarget(_actor, _actor.getTarget()))
+                                return;
+                            clientStopMoving(null);
+                            _accessor.doCast(sk);
+                            _actor.setTarget(OldTarget);
+                            return;
+                        }
+                    }
+                }
+
+                // Finally, physical attacks
+           		clientStopMoving(null);
+           		_accessor.doAttack(hated);
+            }
+        }
+    }
+
+    /**
+     * Manage AI thinking actions of a L2Attackable.<BR><BR>
+     */
+    @Override
+	protected void onEvtThink()
+    {
+        // Check if the actor can't use skills and if a thinking action isn't already in progress
+        if (_thinking || _actor.isAllSkillsDisabled()) return;
+
+        // Start thinking action
+        _thinking = true;
+
+        try
+        {
+            // Manage AI thinks of a L2Attackable
+            if (getIntention() == AI_INTENTION_ACTIVE) thinkActive();
+            else if (getIntention() == AI_INTENTION_ATTACK) thinkAttack();
+        }
+        finally
+        {
+            // Stop thinking action
+            _thinking = false;
+        }
+    }
+
+    /**
+     * Launch actions corresponding to the Event Attacked.<BR><BR>
+     *
+     * <B><U> Actions</U> :</B><BR><BR>
+     * <li>Init the attack : Calculate the attack timeout, Set the _globalAggro to 0, Add the attacker to the actor _aggroList</li>
+     * <li>Set the L2Character movement type to run and send Server->Client packet ChangeMoveType to all others L2PcInstance</li>
+     * <li>Set the Intention to AI_INTENTION_ATTACK</li><BR><BR>
+     *
+     * @param attacker The L2Character that attacks the actor
+     *
+     */
+    @Override
+	protected void onEvtAttacked(L2Character attacker)
+    {
+    	//if (_actor instanceof L2ChestInstance && !((L2ChestInstance)_actor).isInteracted())
+    	//{
+    		//((L2ChestInstance)_actor).deleteMe();
+    		//((L2ChestInstance)_actor).getSpawn().startRespawn();
+    		//return;
+    	//}
+
+        // Calculate the attack timeout
+        _attackTimeout = MAX_ATTACK_TIMEOUT + GameTimeController.getGameTicks();
+
+        // Set the _globalAggro to 0 to permit attack even just after spawn
+        if (_globalAggro < 0) _globalAggro = 0;
+
+        // Add the attacker to the _aggroList of the actor
+        ((L2Attackable) _actor).addDamageHate(attacker, 0, 1);
+
+        // Set the L2Character movement type to run and send Server->Client packet ChangeMoveType to all others L2PcInstance
+        if (!_actor.isRunning()) _actor.setRunning();
+
+        // Set the Intention to AI_INTENTION_ATTACK
+        if (getIntention() != AI_INTENTION_ATTACK)
+        {
+            setIntention(CtrlIntention.AI_INTENTION_ATTACK, attacker);
+        }
+        else if (((L2Attackable) _actor).getMostHated() != getAttackTarget())
+        {
+            setIntention(CtrlIntention.AI_INTENTION_ATTACK, attacker);
+        }
+
+        super.onEvtAttacked(attacker);
+    }
+
+    /**
+     * Launch actions corresponding to the Event Aggression.<BR><BR>
+     *
+     * <B><U> Actions</U> :</B><BR><BR>
+     * <li>Add the target to the actor _aggroList or update hate if already present </li>
+     * <li>Set the actor Intention to AI_INTENTION_ATTACK (if actor is L2GuardInstance check if it isn't too far from its home location)</li><BR><BR>
+     *
+     * @param attacker The L2Character that attacks
+     * @param aggro The value of hate to add to the actor against the target
+     *
+     */
+    @Override
+	protected void onEvtAggression(L2Character target, int aggro)
+    {
+        L2Attackable me = (L2Attackable) _actor;
+
+    	if (target != null)
+        {
+            // Add the target to the actor _aggroList or update hate if already present
+            me.addDamageHate(target, 0, aggro);
+
+            // Set the actor AI Intention to AI_INTENTION_ATTACK
+            if (getIntention() != CtrlIntention.AI_INTENTION_ATTACK)
+            {
+                // Set the L2Character movement type to run and send Server->Client packet ChangeMoveType to all others L2PcInstance
+                if (!_actor.isRunning()) _actor.setRunning();
+
+                setIntention(CtrlIntention.AI_INTENTION_ATTACK, target);
+            }
+        }
+    }
+
+    @Override
+	protected void onIntentionActive()
+    {
+        // Cancel attack timeout
+        _attackTimeout = Integer.MAX_VALUE;
+    	super.onIntentionActive();
+    }
+
+    public void setGlobalAggro(int value)
+    {
+    	_globalAggro = value;
+    }
+}

+ 1056 - 0
L2_GameServer_T1/java/net/sf/l2j/gameserver/ai/L2CharacterAI.java

@@ -0,0 +1,1056 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+package net.sf.l2j.gameserver.ai;
+
+import static net.sf.l2j.gameserver.ai.CtrlIntention.AI_INTENTION_ACTIVE;
+import static net.sf.l2j.gameserver.ai.CtrlIntention.AI_INTENTION_ATTACK;
+import static net.sf.l2j.gameserver.ai.CtrlIntention.AI_INTENTION_CAST;
+import static net.sf.l2j.gameserver.ai.CtrlIntention.AI_INTENTION_FOLLOW;
+import static net.sf.l2j.gameserver.ai.CtrlIntention.AI_INTENTION_IDLE;
+import static net.sf.l2j.gameserver.ai.CtrlIntention.AI_INTENTION_INTERACT;
+import static net.sf.l2j.gameserver.ai.CtrlIntention.AI_INTENTION_MOVE_TO;
+import static net.sf.l2j.gameserver.ai.CtrlIntention.AI_INTENTION_PICK_UP;
+import static net.sf.l2j.gameserver.ai.CtrlIntention.AI_INTENTION_REST;
+import net.sf.l2j.Config;
+import net.sf.l2j.gameserver.Universe;
+import net.sf.l2j.gameserver.model.L2Attackable;
+import net.sf.l2j.gameserver.model.L2CharPosition;
+import net.sf.l2j.gameserver.model.L2Character;
+import net.sf.l2j.gameserver.model.L2Object;
+import net.sf.l2j.gameserver.model.L2Skill;
+import net.sf.l2j.gameserver.model.actor.instance.L2BoatInstance;
+import net.sf.l2j.gameserver.model.actor.instance.L2DoorInstance;
+import net.sf.l2j.gameserver.model.actor.instance.L2NpcInstance;
+import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
+import net.sf.l2j.gameserver.model.actor.instance.L2PlayableInstance;
+import net.sf.l2j.gameserver.serverpackets.AutoAttackStop;
+import net.sf.l2j.gameserver.taskmanager.AttackStanceTaskManager;
+
+/**
+ * This class manages AI of L2Character.<BR><BR>
+ *
+ * L2CharacterAI :<BR><BR>
+ * <li>L2AttackableAI</li>
+ * <li>L2DoorAI</li>
+ * <li>L2PlayerAI</li>
+ * <li>L2SummonAI</li><BR><BR>
+ *
+ */
+public class L2CharacterAI extends AbstractAI
+{
+    @Override
+	protected void onEvtAttacked(L2Character attacker)
+    {
+        clientStartAutoAttack();
+    }
+
+    /**
+     * Constructor of L2CharacterAI.<BR><BR>
+     *
+     * @param accessor The AI accessor of the L2Character
+     *
+     */
+    public L2CharacterAI(L2Character.AIAccessor accessor)
+    {
+        super(accessor);
+    }
+
+    /**
+     * Manage the Idle Intention : Stop Attack, Movement and Stand Up the actor.<BR><BR>
+     *
+     * <B><U> Actions</U> :</B><BR><BR>
+     * <li>Set the AI Intention to AI_INTENTION_IDLE </li>
+     * <li>Init cast and attack target </li>
+     * <li>Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast) </li>
+     * <li>Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast) </li>
+     * <li>Stand up the actor server side AND client side by sending Server->Client packet ChangeWaitType (broadcast) </li><BR><BR>
+     *
+     */
+    @Override
+	protected void onIntentionIdle()
+    {
+        // Set the AI Intention to AI_INTENTION_IDLE
+        changeIntention(AI_INTENTION_IDLE, null, null);
+
+        // Init cast and attack target
+        setCastTarget(null);
+        setAttackTarget(null);
+
+        // Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)
+        clientStopMoving(null);
+
+        // Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast)
+        clientStopAutoAttack();
+
+    }
+
+    /**
+     * Manage the Active Intention : Stop Attack, Movement and Launch Think Event.<BR><BR>
+     *
+     * <B><U> Actions</U> : <I>if the Intention is not already Active</I></B><BR><BR>
+     * <li>Set the AI Intention to AI_INTENTION_ACTIVE </li>
+     * <li>Init cast and attack target </li>
+     * <li>Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast) </li>
+     * <li>Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast) </li>
+     * <li>Launch the Think Event </li><BR><BR>
+     *
+     */
+    @Override
+	protected void onIntentionActive()
+    {
+        // Check if the Intention is not already Active
+        if (getIntention() != AI_INTENTION_ACTIVE)
+        {
+            // Set the AI Intention to AI_INTENTION_ACTIVE
+            changeIntention(AI_INTENTION_ACTIVE, null, null);
+
+            // Init cast and attack target
+            setCastTarget(null);
+            setAttackTarget(null);
+
+            // Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)
+            clientStopMoving(null);
+
+            // Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast)
+            clientStopAutoAttack();
+
+            // Also enable random animations for this L2Character if allowed
+			// This is only for mobs - town npcs are handled in their constructor
+            if (_actor instanceof L2Attackable)
+                ((L2NpcInstance)_actor).startRandomAnimationTimer();
+
+            // Launch the Think Event
+            onEvtThink();
+        }
+    }
+
+    /**
+     * Manage the Rest Intention.<BR><BR>
+     *
+     * <B><U> Actions</U> : </B><BR><BR>
+     * <li>Set the AI Intention to AI_INTENTION_IDLE </li><BR><BR>
+     *
+     */
+    @Override
+	protected void onIntentionRest()
+    {
+        // Set the AI Intention to AI_INTENTION_IDLE
+        setIntention(AI_INTENTION_IDLE);
+    }
+
+    /**
+     * Manage the Attack Intention : Stop current Attack (if necessary), Start a new Attack and Launch Think Event.<BR><BR>
+     *
+     * <B><U> Actions</U> : </B><BR><BR>
+     * <li>Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast) </li>
+     * <li>Set the Intention of this AI to AI_INTENTION_ATTACK </li>
+     * <li>Set or change the AI attack target </li>
+     * <li>Start the actor Auto Attack client side by sending Server->Client packet AutoAttackStart (broadcast) </li>
+     * <li>Launch the Think Event </li><BR><BR>
+     *
+     *
+     * <B><U> Overridden in</U> :</B><BR><BR>
+     * <li>L2AttackableAI : Calculate attack timeout</li><BR><BR>
+     *
+     */
+    @Override
+	protected void onIntentionAttack(L2Character target)
+    {
+        if (target == null)
+        {
+            clientActionFailed();
+            return;
+        }
+
+        if (getIntention() == AI_INTENTION_REST)
+        {
+            // Cancel action client side by sending Server->Client packet ActionFailed to the L2PcInstance actor
+            clientActionFailed();
+            return;
+        }
+
+        if (_actor.isAllSkillsDisabled() || _actor.isAfraid())
+        {
+            // Cancel action client side by sending Server->Client packet ActionFailed to the L2PcInstance actor
+            clientActionFailed();
+            return;
+        }
+
+        // Check if the Intention is already AI_INTENTION_ATTACK
+        if (getIntention() == AI_INTENTION_ATTACK)
+        {
+            // Check if the AI already targets the L2Character
+            if (getAttackTarget() != target)
+            {
+                // Set the AI attack target (change target)
+                setAttackTarget(target);
+
+                stopFollow();
+
+                // Launch the Think Event
+                notifyEvent(CtrlEvent.EVT_THINK, null);
+
+            }
+            else
+                clientActionFailed(); // else client freezes until cancel target
+        }
+        else
+        {
+            // Set the Intention of this AbstractAI to AI_INTENTION_ATTACK
+            changeIntention(AI_INTENTION_ATTACK, target, null);
+
+            // Set the AI attack target
+            setAttackTarget(target);
+
+            stopFollow();
+
+            // Launch the Think Event
+            notifyEvent(CtrlEvent.EVT_THINK, null);
+        }
+    }
+
+    /**
+     * Manage the Cast Intention : Stop current Attack, Init the AI in order to cast and Launch Think Event.<BR><BR>
+     *
+     * <B><U> Actions</U> : </B><BR><BR>
+     * <li>Set the AI cast target </li>
+     * <li>Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast) </li>
+     * <li>Cancel action client side by sending Server->Client packet ActionFailed to the L2PcInstance actor </li>
+     * <li>Set the AI skill used by INTENTION_CAST </li>
+     * <li>Set the Intention of this AI to AI_INTENTION_CAST </li>
+     * <li>Launch the Think Event </li><BR><BR>
+     *
+     */
+    @Override
+	protected void onIntentionCast(L2Skill skill, L2Object target)
+    {
+        if (getIntention() == AI_INTENTION_REST && skill.isMagic())
+        {
+            clientActionFailed();
+            return;
+        }
+
+        if (_actor.isAllSkillsDisabled())
+        {
+            // Cancel action client side by sending Server->Client packet ActionFailed to the L2PcInstance actor
+            clientActionFailed();
+            return;
+        }
+
+        // can't cast if muted
+        if (_actor.isMuted() && skill.isMagic())
+        {
+            // Cancel action client side by sending Server->Client packet ActionFailed to the L2PcInstance actor
+            clientActionFailed();
+            return;
+        }
+
+        // Set the AI cast target
+        setCastTarget((L2Character) target);
+
+        // Stop actions client-side to cast the skill
+        if (skill.getHitTime() > 50)
+        {
+            // Abort the attack of the L2Character and send Server->Client ActionFailed packet
+            _actor.abortAttack();
+
+            // Cancel action client side by sending Server->Client packet ActionFailed to the L2PcInstance actor
+            // no need for second ActionFailed packet, abortAttack() already sent it
+            //clientActionFailed();
+        }
+
+        // Set the AI skill used by INTENTION_CAST
+        _skill = skill;
+
+        // Change the Intention of this AbstractAI to AI_INTENTION_CAST
+        changeIntention(AI_INTENTION_CAST, skill, target);
+
+        // Launch the Think Event
+        notifyEvent(CtrlEvent.EVT_THINK, null);
+    }
+
+    /**
+     * Manage the Move To Intention : Stop current Attack and Launch a Move to Location Task.<BR><BR>
+     *
+     * <B><U> Actions</U> : </B><BR><BR>
+     * <li>Stop the actor auto-attack server side AND client side by sending Server->Client packet AutoAttackStop (broadcast) </li>
+     * <li>Set the Intention of this AI to AI_INTENTION_MOVE_TO </li>
+     * <li>Move the actor to Location (x,y,z) server side AND client side by sending Server->Client packet CharMoveToLocation (broadcast) </li><BR><BR>
+     *
+     */
+    @Override
+	protected void onIntentionMoveTo(L2CharPosition pos)
+    {
+        if (getIntention() == AI_INTENTION_REST)
+        {
+            // Cancel action client side by sending Server->Client packet ActionFailed to the L2PcInstance actor
+            clientActionFailed();
+            return;
+        }
+
+        if (_actor.isAllSkillsDisabled())
+        {
+            // Cancel action client side by sending Server->Client packet ActionFailed to the L2PcInstance actor
+            clientActionFailed();
+            return;
+        }
+
+        // Set the Intention of this AbstractAI to AI_INTENTION_MOVE_TO
+        changeIntention(AI_INTENTION_MOVE_TO, pos, null);
+
+        // Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast)
+        clientStopAutoAttack();
+
+        // Abort the attack of the L2Character and send Server->Client ActionFailed packet
+        _actor.abortAttack();
+
+        // Move the actor to Location (x,y,z) server side AND client side by sending Server->Client packet CharMoveToLocation (broadcast)
+        moveTo(pos.x, pos.y, pos.z);
+    }
+
+    /* (non-Javadoc)
+     * @see net.sf.l2j.gameserver.ai.AbstractAI#onIntentionMoveToInABoat(net.sf.l2j.gameserver.model.L2CharPosition, net.sf.l2j.gameserver.model.L2CharPosition)
+     */
+    @Override
+    protected void onIntentionMoveToInABoat(L2CharPosition destination, L2CharPosition origin)
+    {
+        if (getIntention() == AI_INTENTION_REST)
+        {
+            // Cancel action client side by sending Server->Client packet ActionFailed to the L2PcInstance actor
+            clientActionFailed();
+            return;
+        }
+
+        if (_actor.isAllSkillsDisabled())
+        {
+            // Cancel action client side by sending Server->Client packet ActionFailed to the L2PcInstance actor
+            clientActionFailed();
+            return;
+        }
+
+        // Set the Intention of this AbstractAI to AI_INTENTION_MOVE_TO
+        //
+        //changeIntention(AI_INTENTION_MOVE_TO, new L2CharPosition(((L2PcInstance)_actor).getBoat().getX() - destination.x, ((L2PcInstance)_actor).getBoat().getY() - destination.y, ((L2PcInstance)_actor).getBoat().getZ() - destination.z, 0)  , null);
+
+        // Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast)
+        clientStopAutoAttack();
+
+        // Abort the attack of the L2Character and send Server->Client ActionFailed packet
+        _actor.abortAttack();
+
+        // Move the actor to Location (x,y,z) server side AND client side by sending Server->Client packet CharMoveToLocation (broadcast)
+        moveToInABoat(destination, origin);
+    }
+
+    /**
+     * Manage the Follow Intention : Stop current Attack and Launch a Follow Task.<BR><BR>
+     *
+     * <B><U> Actions</U> : </B><BR><BR>
+     * <li>Stop the actor auto-attack server side AND client side by sending Server->Client packet AutoAttackStop (broadcast) </li>
+     * <li>Set the Intention of this AI to AI_INTENTION_FOLLOW </li>
+     * <li>Create and Launch an AI Follow Task to execute every 1s </li><BR><BR>
+     *
+     */
+    @Override
+	protected void onIntentionFollow(L2Character target)
+    {
+        if (getIntention() == AI_INTENTION_REST)
+        {
+            // Cancel action client side by sending Server->Client packet ActionFailed to the L2PcInstance actor
+            clientActionFailed();
+            return;
+        }
+
+        if (_actor.isAllSkillsDisabled())
+        {
+            // Cancel action client side by sending Server->Client packet ActionFailed to the L2PcInstance actor
+            clientActionFailed();
+            return;
+        }
+
+        if (_actor.isImobilised() || _actor.isRooted())
+        {
+            // Cancel action client side by sending Server->Client packet ActionFailed to the L2PcInstance actor
+            clientActionFailed();
+            return;
+        }
+
+        // Dead actors can`t follow
+        if (_actor.isDead())
+        {
+        	clientActionFailed();
+        	return;
+        }
+
+        // do not follow yourself
+        if (_actor == target)
+        {
+        	clientActionFailed();
+        	return;
+        }
+
+        // Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast)
+        clientStopAutoAttack();
+
+        // Set the Intention of this AbstractAI to AI_INTENTION_FOLLOW
+        changeIntention(AI_INTENTION_FOLLOW, target, null);
+
+        // Create and Launch an AI Follow Task to execute every 1s
+        startFollow(target);
+    }
+
+    /**
+     * Manage the PickUp Intention : Set the pick up target and Launch a Move To Pawn Task (offset=20).<BR><BR>
+     *
+     * <B><U> Actions</U> : </B><BR><BR>
+     * <li>Set the AI pick up target </li>
+     * <li>Set the Intention of this AI to AI_INTENTION_PICK_UP </li>
+     * <li>Move the actor to Pawn server side AND client side by sending Server->Client packet MoveToPawn (broadcast) </li><BR><BR>
+     *
+     */
+    @Override
+	protected void onIntentionPickUp(L2Object object)
+    {
+        if (getIntention() == AI_INTENTION_REST)
+        {
+            // Cancel action client side by sending Server->Client packet ActionFailed to the L2PcInstance actor
+            clientActionFailed();
+            return;
+        }
+
+        if (_actor.isAllSkillsDisabled())
+        {
+            // Cancel action client side by sending Server->Client packet ActionFailed to the L2PcInstance actor
+            clientActionFailed();
+            return;
+        }
+
+        // Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast)
+        clientStopAutoAttack();
+
+        // Set the Intention of this AbstractAI to AI_INTENTION_PICK_UP
+        changeIntention(AI_INTENTION_PICK_UP, object, null);
+
+        // Set the AI pick up target
+        setTarget(object);
+        if(object.getX() == 0 && object.getY() == 0) // TODO: Find the drop&spawn bug
+        {
+        	_log.warning("Object in coords 0,0 - using a temporary fix");
+        	object.setXYZ(getActor().getX(), getActor().getY(), getActor().getZ()+5);
+        }
+
+        // Move the actor to Pawn server side AND client side by sending Server->Client packet MoveToPawn (broadcast)
+        moveToPawn(object, 20);
+    }
+
+    /**
+     * Manage the Interact Intention : Set the interact target and Launch a Move To Pawn Task (offset=60).<BR><BR>
+     *
+     * <B><U> Actions</U> : </B><BR><BR>
+     * <li>Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast) </li>
+     * <li>Set the AI interact target </li>
+     * <li>Set the Intention of this AI to AI_INTENTION_INTERACT </li>
+     * <li>Move the actor to Pawn server side AND client side by sending Server->Client packet MoveToPawn (broadcast) </li><BR><BR>
+     *
+     */
+    @Override
+	protected void onIntentionInteract(L2Object object)
+    {
+        if (getIntention() == AI_INTENTION_REST)
+        {
+            // Cancel action client side by sending Server->Client packet ActionFailed to the L2PcInstance actor
+            clientActionFailed();
+            return;
+        }
+
+        if (_actor.isAllSkillsDisabled())
+        {
+            // Cancel action client side by sending Server->Client packet ActionFailed to the L2PcInstance actor
+            clientActionFailed();
+            return;
+        }
+
+        // Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast)
+        clientStopAutoAttack();
+
+        if (getIntention() != AI_INTENTION_INTERACT)
+        {
+            // Set the Intention of this AbstractAI to AI_INTENTION_INTERACT
+            changeIntention(AI_INTENTION_INTERACT, object, null);
+
+            // Set the AI interact target
+            setTarget(object);
+
+            // Move the actor to Pawn server side AND client side by sending Server->Client packet MoveToPawn (broadcast)
+            moveToPawn(object, 60);
+        }
+    }
+
+    /**
+     * Do nothing.<BR><BR>
+     */
+    @Override
+	protected void onEvtThink()
+    {
+        // do nothing
+    }
+
+    /**
+     * Do nothing.<BR><BR>
+     */
+    @Override
+	protected void onEvtAggression(@SuppressWarnings("unused")
+    L2Character target, @SuppressWarnings("unused")
+    int aggro)
+    {
+        // do nothing
+    }
+
+    /**
+     * Launch actions corresponding to the Event Stunned then onAttacked Event.<BR><BR>
+     *
+     * <B><U> Actions</U> :</B><BR><BR>
+     * <li>Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast)</li>
+     * <li>Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)</li>
+     * <li>Break an attack and send Server->Client ActionFailed packet and a System Message to the L2Character </li>
+     * <li>Break a cast and send Server->Client ActionFailed packet and a System Message to the L2Character </li>
+     * <li>Launch actions corresponding to the Event onAttacked (only for L2AttackableAI after the stunning periode) </li><BR><BR>
+     *
+     */
+    @Override
+	protected void onEvtStunned(L2Character attacker)
+    {
+        // Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast)
+        _actor.broadcastPacket(new AutoAttackStop(_actor.getObjectId()));
+        if (AttackStanceTaskManager.getInstance().getAttackStanceTask(_actor))
+            AttackStanceTaskManager.getInstance().removeAttackStanceTask(_actor);
+
+        // Stop Server AutoAttack also
+        setAutoAttacking(false);
+
+        // Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)
+        clientStopMoving(null);
+
+        // Launch actions corresponding to the Event onAttacked (only for L2AttackableAI after the stunning periode)
+        onEvtAttacked(attacker);
+    }
+
+    /**
+     * Launch actions corresponding to the Event Sleeping.<BR><BR>
+     *
+     * <B><U> Actions</U> :</B><BR><BR>
+     * <li>Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast)</li>
+     * <li>Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)</li>
+     * <li>Break an attack and send Server->Client ActionFailed packet and a System Message to the L2Character </li>
+     * <li>Break a cast and send Server->Client ActionFailed packet and a System Message to the L2Character </li><BR><BR>
+     *
+     */
+    @Override
+	protected void onEvtSleeping(@SuppressWarnings("unused")
+    L2Character attacker)
+    {
+        // Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast)
+        _actor.broadcastPacket(new AutoAttackStop(_actor.getObjectId()));
+        if (AttackStanceTaskManager.getInstance().getAttackStanceTask(_actor))
+            AttackStanceTaskManager.getInstance().removeAttackStanceTask(_actor);
+
+        // stop Server AutoAttack also
+        setAutoAttacking(false);
+
+        // Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)
+        clientStopMoving(null);
+    }
+
+    /**
+     * Launch actions corresponding to the Event Rooted.<BR><BR>
+     *
+     * <B><U> Actions</U> :</B><BR><BR>
+     * <li>Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)</li>
+     * <li>Launch actions corresponding to the Event onAttacked</li><BR><BR>
+     *
+     */
+    @Override
+	protected void onEvtRooted(L2Character attacker)
+    {
+        // Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast)
+        //_actor.broadcastPacket(new AutoAttackStop(_actor.getObjectId()));
+        //if (AttackStanceTaskManager.getInstance().getAttackStanceTask(_actor))
+        //    AttackStanceTaskManager.getInstance().removeAttackStanceTask(_actor);
+
+        // Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)
+        clientStopMoving(null);
+
+        // Launch actions corresponding to the Event onAttacked
+        onEvtAttacked(attacker);
+
+    }
+
+    /**
+     * Launch actions corresponding to the Event Confused.<BR><BR>
+     *
+     * <B><U> Actions</U> :</B><BR><BR>
+     * <li>Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)</li>
+     * <li>Launch actions corresponding to the Event onAttacked</li><BR><BR>
+     *
+     */
+    @Override
+	protected void onEvtConfused(L2Character attacker)
+    {
+        // Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)
+        clientStopMoving(null);
+
+        // Launch actions corresponding to the Event onAttacked
+        onEvtAttacked(attacker);
+    }
+
+    /**
+     * Launch actions corresponding to the Event Muted.<BR><BR>
+     *
+     * <B><U> Actions</U> :</B><BR><BR>
+     * <li>Break a cast and send Server->Client ActionFailed packet and a System Message to the L2Character </li><BR><BR>
+     *
+     */
+    @Override
+	protected void onEvtMuted(L2Character attacker)
+    {
+        // Break a cast and send Server->Client ActionFailed packet and a System Message to the L2Character
+        onEvtAttacked(attacker);
+    }
+
+    /**
+     * Launch actions corresponding to the Event ReadyToAct.<BR><BR>
+     *
+     * <B><U> Actions</U> :</B><BR><BR>
+     * <li>Launch actions corresponding to the Event Think</li><BR><BR>
+     *
+     */
+    @Override
+	protected void onEvtReadyToAct()
+    {
+        // Launch actions corresponding to the Event Think
+        onEvtThink();
+    }
+
+    /**
+     * Do nothing.<BR><BR>
+     */
+    @Override
+	protected void onEvtUserCmd(@SuppressWarnings("unused")
+    Object arg0, @SuppressWarnings("unused")
+    Object arg1)
+    {
+        // do nothing
+    }
+
+    /**
+     * Launch actions corresponding to the Event Arrived.<BR><BR>
+     *
+     * <B><U> Actions</U> :</B><BR><BR>
+     * <li>If the Intention was AI_INTENTION_MOVE_TO, set the Intention to AI_INTENTION_ACTIVE</li>
+     * <li>Launch actions corresponding to the Event Think</li><BR><BR>
+     *
+     */
+    @Override
+	protected void onEvtArrived()
+    {
+    	// Launch an explore task if necessary
+        if (_accessor.getActor() instanceof L2PcInstance)
+        {
+        	if (Config.ACTIVATE_POSITION_RECORDER)
+        		((L2PcInstance) _accessor.getActor()).explore();
+        	((L2PcInstance) _accessor.getActor()).revalidateZone(true);
+        }
+        else _accessor.getActor().revalidateZone();
+
+    	if (_accessor.getActor().moveToNextRoutePoint())
+    		return;
+
+    	clientStoppedMoving();
+
+    	// If the Intention was AI_INTENTION_MOVE_TO, set the Intention to AI_INTENTION_ACTIVE
+        if (getIntention() == AI_INTENTION_MOVE_TO) setIntention(AI_INTENTION_ACTIVE);
+
+        // Launch actions corresponding to the Event Think
+        onEvtThink();
+
+        if (_actor instanceof L2BoatInstance)
+        {
+            ((L2BoatInstance) _actor).evtArrived();
+        }
+    }
+
+    /**
+     * Launch actions corresponding to the Event ArrivedRevalidate.<BR><BR>
+     *
+     * <B><U> Actions</U> :</B><BR><BR>
+     * <li>Launch actions corresponding to the Event Think</li><BR><BR>
+     *
+     */
+    @Override
+	protected void onEvtArrivedRevalidate()
+    {
+        // Launch actions corresponding to the Event Think
+        onEvtThink();
+    }
+
+    /**
+     * Launch actions corresponding to the Event ArrivedBlocked.<BR><BR>
+     *
+     * <B><U> Actions</U> :</B><BR><BR>
+     * <li>Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)</li>
+     * <li>If the Intention was AI_INTENTION_MOVE_TO, set the Intention to AI_INTENTION_ACTIVE</li>
+     * <li>Launch actions corresponding to the Event Think</li><BR><BR>
+     *
+     */
+    @Override
+	protected void onEvtArrivedBlocked(L2CharPosition blocked_at_pos)
+    {
+        // Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)
+        clientStopMoving(blocked_at_pos);
+
+        if (Config.ACTIVATE_POSITION_RECORDER
+            && Universe.getInstance().shouldLog(_accessor.getActor().getObjectId()))
+        {
+            if (!_accessor.getActor().isFlying())
+                Universe.getInstance().registerObstacle(blocked_at_pos.x, blocked_at_pos.y,
+                                                        blocked_at_pos.z);
+            if (_accessor.getActor() instanceof L2PcInstance)
+                ((L2PcInstance) _accessor.getActor()).explore();
+        }
+
+        // If the Intention was AI_INTENTION_MOVE_TO, tet the Intention to AI_INTENTION_ACTIVE
+        if (getIntention() == AI_INTENTION_MOVE_TO) setIntention(AI_INTENTION_ACTIVE);
+
+        // Launch actions corresponding to the Event Think
+        onEvtThink();
+    }
+
+    /**
+     * Launch actions corresponding to the Event ForgetObject.<BR><BR>
+     *
+     * <B><U> Actions</U> :</B><BR><BR>
+     * <li>If the object was targeted  and the Intention was AI_INTENTION_INTERACT or AI_INTENTION_PICK_UP, set the Intention to AI_INTENTION_ACTIVE</li>
+     * <li>If the object was targeted to attack, stop the auto-attack, cancel target and set the Intention to AI_INTENTION_ACTIVE</li>
+     * <li>If the object was targeted to cast, cancel target and set the Intention to AI_INTENTION_ACTIVE</li>
+     * <li>If the object was targeted to follow, stop the movement, cancel AI Follow Task and set the Intention to AI_INTENTION_ACTIVE</li>
+     * <li>If the targeted object was the actor , cancel AI target, stop AI Follow Task, stop the movement and set the Intention to AI_INTENTION_IDLE </li><BR><BR>
+     *
+     */
+    @Override
+	protected void onEvtForgetObject(L2Object object)
+    {
+        // If the object was targeted  and the Intention was AI_INTENTION_INTERACT or AI_INTENTION_PICK_UP, set the Intention to AI_INTENTION_ACTIVE
+        if (getTarget() == object)
+        {
+            setTarget(null);
+
+            if (getIntention() == AI_INTENTION_INTERACT) setIntention(AI_INTENTION_ACTIVE);
+            else if (getIntention() == AI_INTENTION_PICK_UP) setIntention(AI_INTENTION_ACTIVE);
+        }
+
+        // Check if the object was targeted to attack
+        if (getAttackTarget() == object)
+        {
+            // Cancel attack target
+            setAttackTarget(null);
+
+            // Set the Intention of this AbstractAI to AI_INTENTION_ACTIVE
+            setIntention(AI_INTENTION_ACTIVE);
+        }
+
+        // Check if the object was targeted to cast
+        if (getCastTarget() == object)
+        {
+            // Cancel cast target
+            setCastTarget(null);
+
+            // Set the Intention of this AbstractAI to AI_INTENTION_ACTIVE
+            setIntention(AI_INTENTION_ACTIVE);
+        }
+
+        // Check if the object was targeted to follow
+        if (getFollowTarget() == object)
+        {
+            // Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)
+            clientStopMoving(null);
+
+            // Stop an AI Follow Task
+            stopFollow();
+
+            // Set the Intention of this AbstractAI to AI_INTENTION_ACTIVE
+            setIntention(AI_INTENTION_ACTIVE);
+        }
+
+        // Check if the targeted object was the actor
+        if (_actor == object)
+        {
+            // Cancel AI target
+            setTarget(null);
+            setAttackTarget(null);
+            setCastTarget(null);
+
+            // Stop an AI Follow Task
+            stopFollow();
+
+            // Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)
+            clientStopMoving(null);
+
+            // Set the Intention of this AbstractAI to AI_INTENTION_IDLE
+            changeIntention(AI_INTENTION_IDLE, null, null);
+        }
+    }
+
+    /**
+     * Launch actions corresponding to the Event Cancel.<BR><BR>
+     *
+     * <B><U> Actions</U> :</B><BR><BR>
+     * <li>Stop an AI Follow Task</li>
+     * <li>Launch actions corresponding to the Event Think</li><BR><BR>
+     *
+     */
+    @Override
+	protected void onEvtCancel()
+    {
+        // Stop an AI Follow Task
+        stopFollow();
+
+        if (!AttackStanceTaskManager.getInstance().getAttackStanceTask(_actor))
+            _actor.broadcastPacket(new AutoAttackStop(_actor.getObjectId()));
+
+        // Launch actions corresponding to the Event Think
+        onEvtThink();
+    }
+
+    /**
+     * Launch actions corresponding to the Event Dead.<BR><BR>
+     *
+     * <B><U> Actions</U> :</B><BR><BR>
+     * <li>Stop an AI Follow Task</li>
+     * <li>Kill the actor client side by sending Server->Client packet AutoAttackStop, StopMove/StopRotation, Die (broadcast)</li><BR><BR>
+     *
+     */
+    @Override
+	protected void onEvtDead()
+    {
+        // Stop an AI Follow Task
+        stopFollow();
+
+        // Kill the actor client side by sending Server->Client packet AutoAttackStop, StopMove/StopRotation, Die (broadcast)
+        clientNotifyDead();
+
+        if (!(_actor instanceof L2PcInstance))
+            _actor.setWalking();
+    }
+
+    /**
+     * Launch actions corresponding to the Event Fake Death.<BR><BR>
+     *
+     * <B><U> Actions</U> :</B><BR><BR>
+     * <li>Stop an AI Follow Task</li>
+     *
+     */
+    @Override
+	protected void onEvtFakeDeath()
+    {
+        // Stop an AI Follow Task
+        stopFollow();
+
+        // Stop the actor movement and send Server->Client packet StopMove/StopRotation (broadcast)
+        clientStopMoving(null);
+
+        // Init AI
+        _intention = AI_INTENTION_IDLE;
+        setTarget(null);
+        setCastTarget(null);
+        setAttackTarget(null);
+    }
+
+    /**
+     * Do nothing.<BR><BR>
+     */
+    @Override
+	protected void onEvtFinishCasting()
+    {
+        // do nothing
+    }
+
+    /**
+     * Manage the Move to Pawn action in function of the distance and of the Interact area.<BR><BR>
+     *
+     * <B><U> Actions</U> :</B><BR><BR>
+     * <li>Get the distance between the current position of the L2Character and the target (x,y)</li>
+     * <li>If the distance > offset+20, move the actor (by running) to Pawn server side AND client side by sending Server->Client packet MoveToPawn (broadcast)</li>
+     * <li>If the distance <= offset+20, Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)</li><BR><BR>
+     *
+     * <B><U> Example of use </U> :</B><BR><BR>
+     * <li> L2PLayerAI, L2SummonAI</li><BR><BR>
+     *
+     * @param target The targeted L2Object
+     * @param offset The Interact area radius
+     *
+     * @return True if a movement must be done
+     *
+     */
+    protected boolean maybeMoveToPawn(L2Object target, int offset)
+    {
+        // Get the distance between the current position of the L2Character and the target (x,y)
+        if (target == null)
+        {
+            _log.warning("maybeMoveToPawn: target == NULL!");
+            return false;
+        }
+        if(offset < 0) return false; // skill radius -1
+
+        offset += _actor.getTemplate().collisionRadius;
+        if (target instanceof L2Character)
+        	offset += ((L2Character)target).getTemplate().collisionRadius;
+
+        if (!_actor.isInsideRadius(target, offset, false, false))
+        {
+        	// Caller should be L2Playable and thinkAttack/thinkCast/thinkInteract/thinkPickUp
+            if (getFollowTarget() != null) {
+
+            	// prevent attack-follow into peace zones
+            	if(getAttackTarget() != null && _actor instanceof L2PlayableInstance && target instanceof L2PlayableInstance)
+                {
+                    if(getAttackTarget() == getFollowTarget())
+                    {
+                    	// allow GMs to keep following
+                    	boolean isGM = (_actor instanceof L2PcInstance ? ((L2PcInstance)_actor).isGM() : false);
+                        if (((L2PlayableInstance)_actor).isInsidePeaceZone(_actor, target) && !isGM)
+                        {
+                            stopFollow();
+                            setIntention(AI_INTENTION_IDLE);
+                            return true;
+                        }
+                    }
+                }
+            	// if the target is too far (maybe also teleported)
+            	if (!_actor.isInsideRadius(target, 2000, false, false))
+            	{
+            		stopFollow();
+            		setIntention(AI_INTENTION_IDLE);
+            		return true;
+            	}
+            	// allow larger hit range when the target is moving (check is run only once per second)
+                if (!_actor.isInsideRadius(target, offset + 100, false, false)) return true;
+                stopFollow();
+                return false;
+            }
+
+            if (_actor.isMovementDisabled()) return true;
+
+            // If not running, set the L2Character movement type to run and send Server->Client packet ChangeMoveType to all others L2PcInstance
+            if (!_actor.isRunning() && !(this instanceof L2PlayerAI)) _actor.setRunning();
+
+            stopFollow();
+            if ((target instanceof L2Character) && !(target instanceof L2DoorInstance))
+            {
+                if (((L2Character)target).isMoving()) offset -= 100;
+                if (offset < 5) offset = 5;
+
+            	startFollow((L2Character) target, offset);
+            }
+            else
+            {
+                // Move the actor to Pawn server side AND client side by sending Server->Client packet MoveToPawn (broadcast)
+            	moveToPawn(target, offset);
+            }
+            return true;
+        }
+
+        if (getFollowTarget() != null) stopFollow();
+
+        // Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)
+        // clientStopMoving(null);
+        return false;
+    }
+
+    /**
+     * Modify current Intention and actions if the target is lost or dead.<BR><BR>
+     *
+     * <B><U> Actions</U> : <I>If the target is lost or dead</I></B><BR><BR>
+     * <li>Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast)</li>
+     * <li>Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)</li>
+     * <li>Set the Intention of this AbstractAI to AI_INTENTION_ACTIVE</li><BR><BR>
+     *
+     * <B><U> Example of use </U> :</B><BR><BR>
+     * <li> L2PLayerAI, L2SummonAI</li><BR><BR>
+     *
+     * @param target The targeted L2Object
+     *
+     * @return True if the target is lost or dead (false if fakedeath)
+     *
+     */
+    protected boolean checkTargetLostOrDead(L2Character target)
+    {
+        if (target == null || target.isAlikeDead())
+        {
+            //check if player is fakedeath
+            if (target != null && target.isFakeDeath())
+            {
+                target.stopFakeDeath(null);
+                return false;
+            }
+
+            // Set the Intention of this AbstractAI to AI_INTENTION_ACTIVE
+            setIntention(AI_INTENTION_ACTIVE);
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Modify current Intention and actions if the target is lost.<BR><BR>
+     *
+     * <B><U> Actions</U> : <I>If the target is lost</I></B><BR><BR>
+     * <li>Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast)</li>
+     * <li>Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation (broadcast)</li>
+     * <li>Set the Intention of this AbstractAI to AI_INTENTION_ACTIVE</li><BR><BR>
+     *
+     * <B><U> Example of use </U> :</B><BR><BR>
+     * <li> L2PLayerAI, L2SummonAI</li><BR><BR>
+     *
+     * @param target The targeted L2Object
+     *
+     * @return True if the target is lost
+     *
+     */
+    protected boolean checkTargetLost(L2Object target)
+    {
+        // check if player is fakedeath
+        if (target instanceof L2PcInstance)
+        {
+            L2PcInstance target2 = (L2PcInstance) target; //convert object to chara
+
+            if (target2.isFakeDeath())
+            {
+                target2.stopFakeDeath(null);
+                return false;
+            }
+        }
+        if (target == null)
+        {
+            // Set the Intention of this AbstractAI to AI_INTENTION_ACTIVE
+            setIntention(AI_INTENTION_ACTIVE);
+            return true;
+        }
+        return false;
+    }
+}

+ 583 - 0
L2_GameServer_T1/java/net/sf/l2j/gameserver/ai/L2ControllableMobAI.java

@@ -0,0 +1,583 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+package net.sf.l2j.gameserver.ai;
+
+import static net.sf.l2j.gameserver.ai.CtrlIntention.AI_INTENTION_ACTIVE;
+import static net.sf.l2j.gameserver.ai.CtrlIntention.AI_INTENTION_ATTACK;
+
+import java.util.List;
+
+import javolution.util.FastList;
+import net.sf.l2j.gameserver.model.L2Attackable;
+import net.sf.l2j.gameserver.model.L2Character;
+import net.sf.l2j.gameserver.model.L2Object;
+import net.sf.l2j.gameserver.model.L2Skill;
+import net.sf.l2j.gameserver.model.MobGroup;
+import net.sf.l2j.gameserver.model.MobGroupTable;
+import net.sf.l2j.gameserver.model.L2Character.AIAccessor;
+import net.sf.l2j.gameserver.model.actor.instance.L2ControllableMobInstance;
+import net.sf.l2j.gameserver.model.actor.instance.L2DoorInstance;
+import net.sf.l2j.gameserver.model.actor.instance.L2FolkInstance;
+import net.sf.l2j.gameserver.model.actor.instance.L2NpcInstance;
+import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
+import net.sf.l2j.gameserver.util.Util;
+import net.sf.l2j.util.Rnd;
+
+/**
+ * @author littlecrow
+ * AI for controllable mobs
+ *
+ */
+public class L2ControllableMobAI extends L2AttackableAI
+{
+	public static final int AI_IDLE = 1;
+	public static final int AI_NORMAL = 2;
+	public static final int AI_FORCEATTACK = 3;
+	public static final int AI_FOLLOW = 4;
+	public static final int AI_CAST = 5;
+	public static final int AI_ATTACK_GROUP = 6;
+
+	private int _alternateAI;
+
+	private boolean _isThinking; // to prevent thinking recursively
+    private boolean _isNotMoving;
+
+	private L2Character _forcedTarget;
+    private MobGroup _targetGroup;
+
+	protected void thinkFollow()
+    {
+		L2Attackable me = (L2Attackable)_actor;
+
+		if (!Util.checkIfInRange(MobGroupTable.FOLLOW_RANGE, me, getForcedTarget(), true))
+        {
+			int signX = (Rnd.nextInt(2) == 0) ? -1 : 1;
+			int signY = (Rnd.nextInt(2) == 0) ? -1 : 1;
+			int randX = Rnd.nextInt(MobGroupTable.FOLLOW_RANGE);
+			int randY = Rnd.nextInt(MobGroupTable.FOLLOW_RANGE);
+
+			moveTo(getForcedTarget().getX() + signX * randX, getForcedTarget().getY() + signY * randY, getForcedTarget().getZ());
+		}
+	}
+
+	@Override
+	protected void onEvtThink()
+    {
+		if (isThinking() || _actor.isAllSkillsDisabled())
+			return;
+
+		setThinking(true);
+
+		try {
+		    switch (getAlternateAI())
+		    {
+		        case AI_IDLE:
+		            if (getIntention() != CtrlIntention.AI_INTENTION_ACTIVE)
+		                setIntention(CtrlIntention.AI_INTENTION_ACTIVE);
+		            break;
+		        case AI_FOLLOW:
+		            thinkFollow();
+		            break;
+		        case AI_CAST:
+		            thinkCast();
+		            break;
+		        case AI_FORCEATTACK:
+		            thinkForceAttack();
+		            break;
+		        case AI_ATTACK_GROUP:
+		            thinkAttackGroup();
+		            break;
+		        default:
+		            if (getIntention() == AI_INTENTION_ACTIVE)
+		                thinkActive();
+		            else if (getIntention() == AI_INTENTION_ATTACK)
+		                thinkAttack();
+		        break;
+		    }
+		}
+        finally {
+			setThinking(false);
+		}
+	}
+
+	protected void thinkCast()
+    {
+		L2Attackable npc = (L2Attackable)_actor;
+
+		if (getAttackTarget() == null || getAttackTarget().isAlikeDead())
+        {
+            setAttackTarget(findNextRndTarget());
+			clientStopMoving(null);
+		}
+
+		if (getAttackTarget() == null)
+			return;
+
+		npc.setTarget(getAttackTarget());
+
+		L2Skill[] skills = null;
+		//double dist2 = 0;
+
+		try {
+			skills = _actor.getAllSkills();
+		//	dist2 = _actor.getPlanDistanceSq(getAttackTarget().getX(), getAttackTarget().getY());
+		}
+        catch (NullPointerException e) {
+			_log.warning("Encountered Null Value.");
+			e.printStackTrace();
+		}
+
+		if (!_actor.isMuted())
+        {
+			int max_range = 0;
+			// check distant skills
+
+			for (L2Skill sk : skills)
+            {
+				if (Util.checkIfInRange(sk.getCastRange(), _actor, getAttackTarget(), true)
+						&& !_actor.isSkillDisabled(sk.getId())
+						&& _actor.getCurrentMp() > _actor.getStat().getMpConsume(sk))
+                {
+					_accessor.doCast(sk);
+					return;
+				}
+
+				max_range = Math.max(max_range, sk.getCastRange());
+			}
+
+			if (!isNotMoving())
+				moveToPawn(getAttackTarget(), max_range);
+
+			return;
+		}
+	}
+
+	protected void thinkAttackGroup()
+    {
+		L2Character target = getForcedTarget();
+		if (target == null || target.isAlikeDead())
+        {
+			// try to get next group target
+			setForcedTarget(findNextGroupTarget());
+			clientStopMoving(null);
+		}
+
+		if (target == null)
+			return;
+
+		L2Skill[] skills = null;
+		double dist2 = 0;
+		int range = 0;
+		int max_range = 0;
+
+		_actor.setTarget(target);
+		// as a response, we put the target in a forcedattack mode
+		L2ControllableMobInstance theTarget = (L2ControllableMobInstance)target;
+		L2ControllableMobAI ctrlAi = (L2ControllableMobAI)theTarget.getAI();
+		ctrlAi.forceAttack(_actor);
+
+		try {
+			skills = _actor.getAllSkills();
+			dist2 = _actor.getPlanDistanceSq(target.getX(), target.getY());
+			range = _actor.getPhysicalAttackRange() + _actor.getTemplate().collisionRadius + target.getTemplate().collisionRadius;;
+			max_range = range;
+		}
+        catch (NullPointerException e) {
+			_log.warning("Encountered Null Value.");
+			e.printStackTrace();
+		}
+
+		if (!_actor.isMuted() && dist2 > (range + 20) * (range + 20))
+        {
+			// check distant skills
+			for (L2Skill sk : skills)
+            {
+                int castRange = sk.getCastRange();
+
+				if (castRange * castRange >= dist2
+						&& !_actor.isSkillDisabled(sk.getId())
+						&& _actor.getCurrentMp() > _actor.getStat().getMpConsume(sk))
+                {
+					_accessor.doCast(sk);
+					return;
+				}
+
+				max_range = Math.max(max_range, castRange);
+			}
+
+			if (!isNotMoving())
+				moveToPawn(target, range);
+
+			return;
+		}
+		_accessor.doAttack(target);
+    }
+
+	protected void thinkForceAttack()
+    {
+		if (getForcedTarget() == null || getForcedTarget().isAlikeDead())
+        {
+			clientStopMoving(null);
+			setIntention(AI_INTENTION_ACTIVE);
+			setAlternateAI(AI_IDLE);
+		}
+
+		L2Skill[] skills = null;
+		double dist2 = 0;
+		int range = 0;
+		int max_range = 0;
+
+		try {
+			_actor.setTarget(getForcedTarget());
+			skills = _actor.getAllSkills();
+			dist2 = _actor.getPlanDistanceSq(getForcedTarget().getX(), getForcedTarget().getY());
+			range = _actor.getPhysicalAttackRange() + _actor.getTemplate().collisionRadius + getForcedTarget().getTemplate().collisionRadius;
+			max_range = range;
+		}
+        catch (NullPointerException e) {
+			_log.warning("Encountered Null Value.");
+			e.printStackTrace();
+		}
+
+		if (!_actor.isMuted() && dist2 > (range + 20) * (range + 20))
+        {
+			// check distant skills
+			for (L2Skill sk : skills)
+            {
+                int castRange = sk.getCastRange();
+
+				if (castRange * castRange >= dist2
+						&& !_actor.isSkillDisabled(sk.getId())
+						&& _actor.getCurrentMp() > _actor.getStat().getMpConsume(sk))
+                {
+					_accessor.doCast(sk);
+					return;
+				}
+
+				max_range = Math.max(max_range, castRange);
+			}
+
+			if (!isNotMoving())
+				moveToPawn(getForcedTarget(), _actor.getPhysicalAttackRange()/*range*/);
+
+			return;
+		}
+
+		_accessor.doAttack(getForcedTarget());
+	}
+
+	protected void thinkAttack()
+    {
+		if (getAttackTarget() == null || getAttackTarget().isAlikeDead())
+        {
+			if (getAttackTarget() != null)
+            {
+				// stop hating
+				L2Attackable npc = (L2Attackable) _actor;
+				npc.stopHating(getAttackTarget());
+			}
+
+			setIntention(AI_INTENTION_ACTIVE);
+		}
+        else
+        {
+			// notify aggression
+			if (((L2NpcInstance) _actor).getFactionId() != null)
+            {
+				String faction_id = ((L2NpcInstance) _actor).getFactionId();
+
+				for (L2Object obj : _actor.getKnownList().getKnownObjects().values())
+                {
+                    if (!(obj instanceof L2NpcInstance))
+                        continue;
+
+                    L2NpcInstance npc = (L2NpcInstance) obj;
+
+                    if (faction_id != npc.getFactionId())
+                        continue;
+
+                    if (_actor.isInsideRadius(npc, npc.getFactionRange(), false, true)
+                            && Math.abs(getAttackTarget().getZ() - npc.getZ()) < 200)
+                    {
+                        npc.getAI().notifyEvent(CtrlEvent.EVT_AGGRESSION, getAttackTarget(), 1);
+                    }
+				}
+			}
+
+			L2Skill[] skills = null;
+			double dist2 = 0;
+			int range = 0;
+			int max_range = 0;
+
+			try {
+				_actor.setTarget(getAttackTarget());
+				skills = _actor.getAllSkills();
+				dist2 = _actor.getPlanDistanceSq(getAttackTarget().getX(), getAttackTarget().getY());
+				range = _actor.getPhysicalAttackRange() + _actor.getTemplate().collisionRadius + getAttackTarget().getTemplate().collisionRadius;
+				max_range = range;
+			}
+            catch (NullPointerException e) {
+				_log.warning("Encountered Null Value.");
+				e.printStackTrace();
+			}
+
+			if (!_actor.isMuted() && dist2 > (range + 20) * (range + 20))
+            {
+				// check distant skills
+				for (L2Skill sk : skills)
+                {
+                    int castRange = sk.getCastRange();
+
+					if (castRange * castRange >= dist2
+							&& !_actor.isSkillDisabled(sk.getId())
+							&& _actor.getCurrentMp() > _actor.getStat().getMpConsume(sk))
+                    {
+						_accessor.doCast(sk);
+						return;
+					}
+
+					max_range = Math.max(max_range, castRange);
+				}
+
+				moveToPawn(getAttackTarget(), range);
+				return;
+			}
+
+            // Force mobs to attack anybody if confused.
+			L2Character hated;
+
+			if (_actor.isConfused())
+				hated = findNextRndTarget();
+			else
+				hated = getAttackTarget();
+
+			if (hated == null)
+            {
+				setIntention(AI_INTENTION_ACTIVE);
+				return;
+			}
+
+			if (hated != getAttackTarget())
+                setAttackTarget(hated);
+
+			if (!_actor.isMuted() && skills.length > 0 && Rnd.nextInt(5) == 3)
+            {
+				for (L2Skill sk : skills)
+                {
+                    int castRange = sk.getCastRange();
+
+					if (castRange * castRange >= dist2
+							&& !_actor.isSkillDisabled(sk.getId())
+							&& _actor.getCurrentMp() < _actor.getStat().getMpConsume(sk))
+                    {
+						_accessor.doCast(sk);
+						return;
+					}
+				}
+			}
+
+			_accessor.doAttack(getAttackTarget());
+		}
+	}
+
+	private void thinkActive()
+    {
+        setAttackTarget(findNextRndTarget());
+		L2Character hated;
+
+		if (_actor.isConfused())
+			hated = findNextRndTarget();
+		else
+			hated = getAttackTarget();
+
+		if (hated != null)
+        {
+			_actor.setRunning();
+			setIntention(CtrlIntention.AI_INTENTION_ATTACK, hated);
+		}
+
+		return;
+	}
+
+	private boolean autoAttackCondition(L2Character target)
+    {
+		if (target == null || !(_actor instanceof L2Attackable)) return false;
+		L2Attackable me = (L2Attackable)_actor;
+
+		if (target instanceof L2FolkInstance
+				|| target instanceof L2DoorInstance)
+			return false;
+
+		if (target.isAlikeDead()
+				|| !me.isInsideRadius(target, me.getAggroRange(), false, false)
+				|| Math.abs(_actor.getZ() - target.getZ()) > 100)
+			return false;
+
+        // Check if the target isn't invulnerable
+        if (target.isInvul())
+            return false;
+
+        // Check if the target is a L2PcInstance
+        if (target instanceof L2PcInstance)
+        {
+
+            // Check if the target isn't in silent move mode
+            if (((L2PcInstance)target).isSilentMoving())
+                return false;
+        }
+
+        if (target instanceof L2NpcInstance)
+        	return false;
+
+        return me.isAggressive();
+	}
+
+	private L2Character findNextRndTarget()
+    {
+        int aggroRange  = ((L2Attackable)_actor).getAggroRange();
+        L2Attackable npc = (L2Attackable)_actor;
+        int npcX, npcY, targetX, targetY;
+        double dy, dx;
+        double dblAggroRange = aggroRange*aggroRange;
+
+		List<L2Character> potentialTarget = new FastList<L2Character>();
+
+		for (L2Object obj : npc.getKnownList().getKnownObjects().values())
+        {
+			if (!(obj instanceof L2Character))
+				continue;
+
+            npcX    = npc.getX();
+            npcY    = npc.getY();
+            targetX = obj.getX();
+            targetY = obj.getY();
+
+            dx      = npcX - targetX;
+            dy      = npcY - targetY;
+
+            if (dx*dx + dy*dy > dblAggroRange)
+                continue;
+
+			L2Character target = (L2Character) obj;
+
+            if (autoAttackCondition(target)) // check aggression
+				potentialTarget.add(target);
+		}
+
+		if (potentialTarget.size() == 0) // nothing to do
+			return null;
+
+		// we choose a random target
+		int choice = Rnd.nextInt(potentialTarget.size());
+		L2Character target = potentialTarget.get(choice);
+
+		return target;
+	}
+
+	private L2ControllableMobInstance findNextGroupTarget()
+    {
+		return getGroupTarget().getRandomMob();
+	}
+
+	public L2ControllableMobAI(AIAccessor accessor)
+    {
+		super(accessor);
+		setAlternateAI(AI_IDLE);
+	}
+
+	public int getAlternateAI()
+    {
+		return _alternateAI;
+	}
+
+	public void setAlternateAI(int _alternateai)
+    {
+		_alternateAI = _alternateai;
+	}
+
+	public void forceAttack(L2Character target)
+    {
+		setAlternateAI(AI_FORCEATTACK);
+		setForcedTarget(target);
+	}
+
+	public void forceAttackGroup(MobGroup group)
+    {
+		setForcedTarget(null);
+		setGroupTarget(group);
+		setAlternateAI(AI_ATTACK_GROUP);
+	}
+
+	public void stop()
+    {
+		setAlternateAI(AI_IDLE);
+		clientStopMoving(null);
+	}
+
+	public void move(int x, int y, int z)
+    {
+		moveTo(x, y, z);
+	}
+
+	public void follow(L2Character target)
+    {
+		setAlternateAI(AI_FOLLOW);
+		setForcedTarget(target);
+	}
+
+    public boolean isThinking()
+    {
+        return _isThinking;
+    }
+
+	public boolean isNotMoving()
+    {
+		return _isNotMoving;
+	}
+
+	public void setNotMoving(boolean isNotMoving)
+    {
+		_isNotMoving = isNotMoving;
+	}
+
+    public void setThinking(boolean isThinking)
+    {
+        _isThinking = isThinking;
+    }
+
+    private L2Character getForcedTarget()
+    {
+        return _forcedTarget;
+    }
+
+    private MobGroup getGroupTarget()
+    {
+        return _targetGroup;
+    }
+
+    private void setForcedTarget(L2Character forcedTarget)
+    {
+        _forcedTarget = forcedTarget;
+    }
+
+    private void setGroupTarget(MobGroup targetGroup)
+    {
+        _targetGroup = targetGroup;
+    }
+}

+ 137 - 0
L2_GameServer_T1/java/net/sf/l2j/gameserver/ai/L2DoorAI.java

@@ -0,0 +1,137 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+package net.sf.l2j.gameserver.ai;
+
+import net.sf.l2j.gameserver.ThreadPoolManager;
+import net.sf.l2j.gameserver.model.L2CharPosition;
+import net.sf.l2j.gameserver.model.L2Character;
+import net.sf.l2j.gameserver.model.L2Object;
+import net.sf.l2j.gameserver.model.L2Skill;
+import net.sf.l2j.gameserver.model.actor.instance.L2DoorInstance;
+import net.sf.l2j.gameserver.model.actor.instance.L2SiegeGuardInstance;
+
+/**
+ * @author mkizub
+ *
+ * TODO To change the template for this generated type comment go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+public class L2DoorAI extends L2CharacterAI {
+
+	public L2DoorAI(L2DoorInstance.AIAccessor accessor)
+	{
+		super(accessor);
+	}
+
+	// rather stupid AI... well,  it's for doors :D
+	@Override
+	protected void onIntentionIdle() {}
+	@Override
+	protected void onIntentionActive() {}
+	@Override
+	protected void onIntentionRest() {}
+    @Override
+	@SuppressWarnings("unused")
+	protected void onIntentionAttack(L2Character target) {}
+    @Override
+	@SuppressWarnings("unused")
+	protected void onIntentionCast(L2Skill skill, L2Object target) {}
+    @Override
+	@SuppressWarnings("unused")
+	protected void onIntentionMoveTo(L2CharPosition destination) {}
+    @Override
+	@SuppressWarnings("unused")
+	protected void onIntentionFollow(L2Character target) {}
+    @Override
+	@SuppressWarnings("unused")
+	protected void onIntentionPickUp(L2Object item) {}
+    @Override
+	@SuppressWarnings("unused")
+	protected void onIntentionInteract(L2Object object) {}
+
+	@Override
+	protected void onEvtThink() {}
+    @Override
+	@SuppressWarnings("unused")
+	protected void onEvtAttacked(L2Character attacker)
+    {
+    	L2DoorInstance me = (L2DoorInstance)_actor;
+        ThreadPoolManager.getInstance().executeTask(new onEventAttackedDoorTask(me, attacker));
+	}
+    @Override
+	@SuppressWarnings("unused")
+	protected void onEvtAggression(L2Character target, int aggro) {}
+    @Override
+	@SuppressWarnings("unused")
+	protected void onEvtStunned(L2Character attacker) {}
+    @Override
+	@SuppressWarnings("unused")
+	protected void onEvtSleeping(L2Character attacker) {}
+    @Override
+	@SuppressWarnings("unused")
+	protected void onEvtRooted(L2Character attacker) {}
+	@Override
+	protected void onEvtReadyToAct() {}
+    @Override
+	@SuppressWarnings("unused")
+	protected void onEvtUserCmd(Object arg0, Object arg1) {}
+	@Override
+	protected void onEvtArrived() {}
+	@Override
+	protected void onEvtArrivedRevalidate() {}
+    @Override
+	@SuppressWarnings("unused")
+	protected void onEvtArrivedBlocked(L2CharPosition blocked_at_pos) {}
+    @Override
+	@SuppressWarnings("unused")
+	protected void onEvtForgetObject(L2Object object) {}
+	@Override
+	protected void onEvtCancel() {}
+	@Override
+	protected void onEvtDead() {}
+
+	private class onEventAttackedDoorTask implements Runnable
+	{
+		private L2DoorInstance _door;
+		private L2Character _attacker;
+
+		public onEventAttackedDoorTask(L2DoorInstance door, L2Character attacker)
+		{
+			_door = door;
+			_attacker = attacker;
+		}
+
+		/* (non-Javadoc)
+		 * @see java.lang.Runnable#run()
+		 */
+		public void run()
+		{
+			_door.getKnownList().updateKnownObjects();
+
+			for (L2SiegeGuardInstance guard : _door.getKnownSiegeGuards()) {
+	            if (_actor.isInsideRadius(guard, guard.getFactionRange(), false, true)
+	                    && Math.abs(_attacker.getZ()-guard.getZ()) < 200)
+	            {
+	                guard.getAI().notifyEvent(CtrlEvent.EVT_AGGRESSION, _attacker, 15);
+	            }
+			}
+		}
+	}
+
+}

+ 212 - 0
L2_GameServer_T1/java/net/sf/l2j/gameserver/ai/L2NpcWalkerAI.java

@@ -0,0 +1,212 @@
+/* This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+package net.sf.l2j.gameserver.ai;
+
+import javolution.util.FastList;
+import net.sf.l2j.Config;
+import net.sf.l2j.gameserver.ThreadPoolManager;
+import net.sf.l2j.gameserver.datatables.NpcWalkerRoutesTable;
+import net.sf.l2j.gameserver.model.L2CharPosition;
+import net.sf.l2j.gameserver.model.L2Character;
+import net.sf.l2j.gameserver.model.L2NpcWalkerNode;
+import net.sf.l2j.gameserver.model.actor.instance.L2NpcWalkerInstance;
+
+public class L2NpcWalkerAI extends L2CharacterAI implements Runnable
+{
+	private static final int DEFAULT_MOVE_DELAY = 0;
+
+	private long _nextMoveTime;
+
+	private boolean _walkingToNextPoint = false;
+
+	/**
+	 * home points for xyz
+	 */
+	int _homeX, _homeY, _homeZ;
+
+	/**
+	 * route of the current npc
+	 */
+	private final FastList<L2NpcWalkerNode> _route = NpcWalkerRoutesTable.getInstance().getRouteForNpc(getActor().getNpcId());
+
+	/**
+	 * current node
+	 */
+	private int _currentPos;
+
+
+	/**
+	 * Constructor of L2CharacterAI.<BR><BR>
+	 *
+	 * @param accessor The AI accessor of the L2Character
+	 */
+	public L2NpcWalkerAI(L2Character.AIAccessor accessor)
+	{
+		super(accessor);
+		// Do we really need 2 minutes delay before start?
+		// no we dont... :)
+		ThreadPoolManager.getInstance().scheduleAiAtFixedRate(this, 0, 1000);
+	}
+
+	public void run()
+	{
+		onEvtThink();
+	}
+
+	protected void onEvtThink()
+	{
+		if(!Config.ALLOW_NPC_WALKERS)
+			return;
+
+		if(isWalkingToNextPoint())
+		{
+			checkArrived();
+			return;
+		}
+
+		if(_nextMoveTime < System.currentTimeMillis())
+			walkToLocation();
+	}
+
+	/**
+	 * If npc can't walk to it's target then just teleport to next point
+	 * @param blocked_at_pos ignoring it
+	 */
+	protected void onEvtArrivedBlocked(L2CharPosition blocked_at_pos)
+	{
+		_log.warning("NpcWalker ID: " + getActor().getNpcId() + ": Blocked at rote position [" + _currentPos + "], coords: " + blocked_at_pos.x + ", " + blocked_at_pos.y + ", " + blocked_at_pos.z + ". Teleporting to next point");
+
+		int destinationX = _route.get(_currentPos).getMoveX();
+		int destinationY = _route.get(_currentPos).getMoveY();
+		int destinationZ = _route.get(_currentPos).getMoveZ();
+
+		getActor().teleToLocation(destinationX, destinationY, destinationZ, false);
+		super.onEvtArrivedBlocked(blocked_at_pos);
+	}
+
+	private void checkArrived()
+	{
+		int destinationX = _route.get(_currentPos).getMoveX();
+		int destinationY = _route.get(_currentPos).getMoveY();
+		int destinationZ = _route.get(_currentPos).getMoveZ();
+
+		if(getActor().getX() == destinationX && getActor().getY() == destinationY && getActor().getZ() == destinationZ)
+		{
+			String chat = _route.get(_currentPos).getChatText();
+			if(chat != null && !chat.equals(""))
+			{
+				try
+				{
+					getActor().broadcastChat(chat);
+				}
+				catch(ArrayIndexOutOfBoundsException e)
+				{
+					_log.info("L2NpcWalkerInstance: Error, " + e);
+				}
+			}
+
+			//time in millis
+			long delay = _route.get(_currentPos).getDelay()*1000;
+
+			//sleeps between each move
+			if(delay <= 0)
+			{
+				delay = DEFAULT_MOVE_DELAY;
+				if(Config.DEVELOPER)
+					_log.warning("Wrong Delay Set in Npc Walker Functions = " + delay + " secs, using default delay: " + DEFAULT_MOVE_DELAY + " secs instead.");
+			}
+
+			_nextMoveTime = System.currentTimeMillis() + delay;
+			setWalkingToNextPoint(false);
+		}
+	}
+
+	private void walkToLocation()
+	{
+		if(_currentPos < (_route.size() - 1))
+			_currentPos++;
+		else
+			_currentPos = 0;
+
+		boolean moveType = _route.get(_currentPos).getRunning();
+
+		/**
+		 * false - walking
+		 * true - Running
+		 */
+		if(moveType)
+			getActor().setRunning();
+		else
+			getActor().setWalking();
+
+		//now we define destination
+		int destinationX = _route.get(_currentPos).getMoveX();
+		int destinationY = _route.get(_currentPos).getMoveY();
+		int destinationZ = _route.get(_currentPos).getMoveZ();
+
+		//notify AI of MOVE_TO
+		setWalkingToNextPoint(true);
+	
+		setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, new L2CharPosition(destinationX, destinationY, destinationZ, 0));
+	}
+
+	public L2NpcWalkerInstance getActor()
+	{
+		return (L2NpcWalkerInstance) super.getActor();
+	}
+
+	public int getHomeX()
+	{
+		return _homeX;
+	}
+
+	public int getHomeY()
+	{
+		return _homeY;
+	}
+
+	public int getHomeZ()
+	{
+		return _homeZ;
+	}
+
+	public void setHomeX(int homeX)
+	{
+		_homeX = homeX;
+	}
+
+	public void setHomeY(int homeY)
+	{
+		_homeY = homeY;
+	}
+
+	public void setHomeZ(int homeZ)
+	{
+		_homeZ = homeZ;
+	}
+
+	public boolean isWalkingToNextPoint()
+	{
+		return _walkingToNextPoint;
+	}
+
+	public void setWalkingToNextPoint(boolean value)
+	{
+		_walkingToNextPoint = value;
+	}
+}

+ 294 - 0
L2_GameServer_T1/java/net/sf/l2j/gameserver/ai/L2PlayerAI.java

@@ -0,0 +1,294 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+package net.sf.l2j.gameserver.ai;
+
+import static net.sf.l2j.gameserver.ai.CtrlIntention.AI_INTENTION_ATTACK;
+import static net.sf.l2j.gameserver.ai.CtrlIntention.AI_INTENTION_CAST;
+import static net.sf.l2j.gameserver.ai.CtrlIntention.AI_INTENTION_IDLE;
+import static net.sf.l2j.gameserver.ai.CtrlIntention.AI_INTENTION_INTERACT;
+import static net.sf.l2j.gameserver.ai.CtrlIntention.AI_INTENTION_PICK_UP;
+import static net.sf.l2j.gameserver.ai.CtrlIntention.AI_INTENTION_REST;
+
+import java.util.EmptyStackException;
+import java.util.Stack;
+
+import net.sf.l2j.gameserver.ThreadPoolManager;
+import net.sf.l2j.gameserver.model.L2Character;
+import net.sf.l2j.gameserver.model.L2Object;
+import net.sf.l2j.gameserver.model.L2Character.AIAccessor;
+import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
+import net.sf.l2j.gameserver.model.actor.instance.L2StaticObjectInstance;
+import net.sf.l2j.gameserver.model.actor.knownlist.ObjectKnownList.KnownListAsynchronousUpdateTask;
+
+public class L2PlayerAI extends L2CharacterAI
+{
+
+    private boolean _thinking; // to prevent recursive thinking
+
+    class IntentionCommand
+    {
+        protected CtrlIntention _crtlIntention;
+        protected Object _arg0, _arg1;
+
+        protected IntentionCommand(CtrlIntention pIntention, Object pArg0, Object pArg1)
+        {
+        	_crtlIntention = pIntention;
+            _arg0 = pArg0;
+            _arg1 = pArg1;
+        }
+    }
+
+    private Stack<IntentionCommand> _interuptedIntentions = new Stack<IntentionCommand>();
+
+    public L2PlayerAI(AIAccessor accessor)
+    {
+        super(accessor);
+    }
+
+    /**
+     * Saves the current Intention for this L2PlayerAI if necessary and calls changeIntention in AbstractAI.<BR><BR>
+     *
+     * @param intention The new Intention to set to the AI
+     * @param arg0 The first parameter of the Intention
+     * @param arg1 The second parameter of the Intention
+     *
+     */
+    @Override
+	synchronized void changeIntention(CtrlIntention intention, Object arg0, Object arg1)
+    {
+        /*
+         if (Config.DEBUG)
+         _log.warning("L2PlayerAI: changeIntention -> " + intention + " " + arg0 + " " + arg1);
+         */
+
+        // nothing to do if it does not CAST intention
+        if (intention != AI_INTENTION_CAST)
+        {
+            super.changeIntention(intention, arg0, arg1);
+            return;
+        }
+
+        // do nothing if next intention is same as current one.
+        if (intention == _intention && arg0 == _intentionArg0 && arg1 == _intentionArg1)
+        {
+            super.changeIntention(intention, arg0, arg1);
+            return;
+        }
+
+        /*
+         if (Config.DEBUG)
+         _log.warning("L2PlayerAI: changeIntention -> Saving current intention: " + _intention + " " + _intention_arg0 + " " + _intention_arg1);
+         */
+
+        // push current intention to stack
+        _interuptedIntentions.push(new IntentionCommand(_intention, _intentionArg0, _intentionArg1));
+        super.changeIntention(intention, arg0, arg1);
+    }
+
+    /**
+     * Finalize the casting of a skill. This method overrides L2CharacterAI method.<BR><BR>
+     *
+     * <B>What it does:</B>
+     * Check if actual intention is set to CAST and, if so, retrieves latest intention
+     * before the actual CAST and set it as the current intention for the player
+     */
+    @Override
+	protected void onEvtFinishCasting()
+    {
+        // forget interupted actions after offensive skill
+        if (_skill != null && _skill.isOffensive()) _interuptedIntentions.clear();
+
+        if (getIntention() == AI_INTENTION_CAST)
+        {
+            // run interupted intention if it remain.
+            if (!_interuptedIntentions.isEmpty())
+            {
+                IntentionCommand cmd = null;
+                try
+                {
+                    cmd = _interuptedIntentions.pop();
+                }
+                catch (EmptyStackException ese)
+                {
+                }
+
+                /*
+                 if (Config.DEBUG)
+                 _log.warning("L2PlayerAI: onEvtFinishCasting -> " + cmd._intention + " " + cmd._arg0 + " " + cmd._arg1);
+                 */
+
+                if (cmd != null && cmd._crtlIntention != AI_INTENTION_CAST) // previous state shouldn't be casting
+                {
+                	setIntention(cmd._crtlIntention, cmd._arg0, cmd._arg1);
+                }
+                else setIntention(AI_INTENTION_IDLE);
+            }
+            else
+            {
+                /*
+                 if (Config.DEBUG)
+                 _log.warning("L2PlayerAI: no previous intention set... Setting it to IDLE");
+                 */
+                // set intention to idle if skill doesn't change intention.
+                setIntention(AI_INTENTION_IDLE);
+            }
+        }
+    }
+
+    @Override
+	protected void onIntentionRest()
+    {
+        if (getIntention() != AI_INTENTION_REST)
+        {
+            changeIntention(AI_INTENTION_REST, null, null);
+            setTarget(null);
+            if (getAttackTarget() != null)
+            {
+                setAttackTarget(null);
+            }
+            clientStopMoving(null);
+        }
+    }
+
+    @Override
+	protected void onIntentionActive()
+    {
+        setIntention(AI_INTENTION_IDLE);
+    }
+
+    @Override
+	protected void clientNotifyDead()
+    {
+        _clientMovingToPawnOffset = 0;
+        _clientMoving = false;
+
+        super.clientNotifyDead();
+    }
+
+    private void thinkAttack()
+    {
+    	L2Character target = getAttackTarget();
+    	if (target == null) return;
+        if (checkTargetLostOrDead(target))
+        {
+            if (target != null)
+            {
+                // Notify the target
+                setAttackTarget(null);
+            }
+            return;
+        }
+        if (maybeMoveToPawn(target, _actor.getPhysicalAttackRange())) return;
+
+        _accessor.doAttack(target);
+        return;
+    }
+
+    private void thinkCast()
+    {
+
+    	L2Character target = getCastTarget();
+        //if (Config.DEBUG) _log.warning("L2PlayerAI: thinkCast -> Start");
+
+        if (checkTargetLost(target))
+        {
+            if (_skill.isOffensive() && getAttackTarget() != null)
+            {
+                //Notify the target
+                setCastTarget(null);
+            }
+            return;
+        }
+
+        if (target != null)
+        	if (maybeMoveToPawn(target, _actor.getMagicalAttackRange(_skill))) return;
+
+        if (_skill.getHitTime() > 50) clientStopMoving(null);
+
+        L2Object oldTarget = _actor.getTarget();
+        if (oldTarget != null)
+        {
+            // Replace the current target by the cast target
+            if (target != null && oldTarget != target) _actor.setTarget(getCastTarget());
+
+            // Launch the Cast of the skill
+            _accessor.doCast(_skill);
+
+            // Restore the initial target
+            if (target != null && oldTarget != target) _actor.setTarget(oldTarget);
+        }
+        else _accessor.doCast(_skill);
+
+        return;
+    }
+
+    private void thinkPickUp()
+    {
+        if (_actor.isAllSkillsDisabled()) return;
+    	L2Object target = getTarget();
+        if (checkTargetLost(target)) return;
+        if (maybeMoveToPawn(target, 36)) return;
+        setIntention(AI_INTENTION_IDLE);
+        ((L2PcInstance.AIAccessor) _accessor).doPickupItem(target);
+        return;
+    }
+
+    private void thinkInteract()
+    {
+        if (_actor.isAllSkillsDisabled()) return;
+        L2Object target = getTarget();
+        if (checkTargetLost(target)) return;
+        if (maybeMoveToPawn(target, 36)) return;
+        if (!(target instanceof L2StaticObjectInstance)) ((L2PcInstance.AIAccessor) _accessor).doInteract((L2Character) target);
+        setIntention(AI_INTENTION_IDLE);
+        return;
+    }
+
+    @Override
+	protected void onEvtThink()
+    {
+        if (_thinking || _actor.isAllSkillsDisabled()) return;
+
+        /*
+         if (Config.DEBUG)
+         _log.warning("L2PlayerAI: onEvtThink -> Check intention");
+         */
+
+        _thinking = true;
+        try
+        {
+            if (getIntention() == AI_INTENTION_ATTACK) thinkAttack();
+            else if (getIntention() == AI_INTENTION_CAST) thinkCast();
+            else if (getIntention() == AI_INTENTION_PICK_UP) thinkPickUp();
+            else if (getIntention() == AI_INTENTION_INTERACT) thinkInteract();
+        }
+        finally
+        {
+            _thinking = false;
+        }
+    }
+
+    @Override
+	protected void onEvtArrivedRevalidate()
+    {
+        ThreadPoolManager.getInstance().executeTask(new KnownListAsynchronousUpdateTask(_actor));
+        super.onEvtArrivedRevalidate();
+    }
+
+}

+ 761 - 0
L2_GameServer_T1/java/net/sf/l2j/gameserver/ai/L2SiegeGuardAI.java

@@ -0,0 +1,761 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+package net.sf.l2j.gameserver.ai;
+
+import static net.sf.l2j.gameserver.ai.CtrlIntention.AI_INTENTION_ACTIVE;
+import static net.sf.l2j.gameserver.ai.CtrlIntention.AI_INTENTION_ATTACK;
+import static net.sf.l2j.gameserver.ai.CtrlIntention.AI_INTENTION_IDLE;
+
+import java.util.concurrent.Future;
+
+import net.sf.l2j.Config;
+import net.sf.l2j.gameserver.GameTimeController;
+import net.sf.l2j.gameserver.GeoData;
+import net.sf.l2j.gameserver.ThreadPoolManager;
+import net.sf.l2j.gameserver.model.L2Attackable;
+import net.sf.l2j.gameserver.model.L2Character;
+import net.sf.l2j.gameserver.model.L2Effect;
+import net.sf.l2j.gameserver.model.L2Object;
+import net.sf.l2j.gameserver.model.L2Skill;
+import net.sf.l2j.gameserver.model.L2Summon;
+import net.sf.l2j.gameserver.model.actor.instance.L2DoorInstance;
+import net.sf.l2j.gameserver.model.actor.instance.L2FolkInstance;
+import net.sf.l2j.gameserver.model.actor.instance.L2MonsterInstance;
+import net.sf.l2j.gameserver.model.actor.instance.L2NpcInstance;
+import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
+import net.sf.l2j.gameserver.model.actor.instance.L2SiegeGuardInstance;
+import net.sf.l2j.util.Rnd;
+
+/**
+ * This class manages AI of L2Attackable.<BR><BR>
+ *
+ */
+public class L2SiegeGuardAI extends L2CharacterAI implements Runnable
+{
+
+    //protected static final Logger _log = Logger.getLogger(L2SiegeGuardAI.class.getName());
+
+    private static final int MAX_ATTACK_TIMEOUT = 300; // int ticks, i.e. 30 seconds
+
+    /** The L2Attackable AI task executed every 1s (call onEvtThink method)*/
+    private Future<?> _aiTask;
+
+    /** The delay after wich the attacked is stopped */
+    private int _attackTimeout;
+
+    /** The L2Attackable aggro counter */
+    private int _globalAggro;
+
+    /** The flag used to indicate that a thinking action is in progress */
+    private boolean _thinking; // to prevent recursive thinking
+
+    private int _attackRange;
+
+    /**
+     * Constructor of L2AttackableAI.<BR><BR>
+     *
+     * @param accessor The AI accessor of the L2Character
+     *
+     */
+    public L2SiegeGuardAI(L2Character.AIAccessor accessor)
+    {
+        super(accessor);
+
+        _attackTimeout = Integer.MAX_VALUE;
+        _globalAggro = -10; // 10 seconds timeout of ATTACK after respawn
+
+        _attackRange = ((L2Attackable) _actor).getPhysicalAttackRange();
+    }
+
+    public void run()
+    {
+        // Launch actions corresponding to the Event Think
+        onEvtThink();
+
+    }
+
+    /**
+     * Return True if the target is autoattackable (depends on the actor type).<BR><BR>
+     *
+     * <B><U> Actor is a L2GuardInstance</U> :</B><BR><BR>
+     * <li>The target isn't a Folk or a Door</li>
+     * <li>The target isn't dead, isn't invulnerable, isn't in silent moving mode AND too far (>100)</li>
+     * <li>The target is in the actor Aggro range and is at the same height</li>
+     * <li>The L2PcInstance target has karma (=PK)</li>
+     * <li>The L2MonsterInstance target is aggressive</li><BR><BR>
+     *
+     * <B><U> Actor is a L2SiegeGuardInstance</U> :</B><BR><BR>
+     * <li>The target isn't a Folk or a Door</li>
+     * <li>The target isn't dead, isn't invulnerable, isn't in silent moving mode AND too far (>100)</li>
+     * <li>The target is in the actor Aggro range and is at the same height</li>
+     * <li>A siege is in progress</li>
+     * <li>The L2PcInstance target isn't a Defender</li><BR><BR>
+     *
+     * <B><U> Actor is a L2FriendlyMobInstance</U> :</B><BR><BR>
+     * <li>The target isn't a Folk, a Door or another L2NpcInstance</li>
+     * <li>The target isn't dead, isn't invulnerable, isn't in silent moving mode AND too far (>100)</li>
+     * <li>The target is in the actor Aggro range and is at the same height</li>
+     * <li>The L2PcInstance target has karma (=PK)</li><BR><BR>
+     *
+     * <B><U> Actor is a L2MonsterInstance</U> :</B><BR><BR>
+     * <li>The target isn't a Folk, a Door or another L2NpcInstance</li>
+     * <li>The target isn't dead, isn't invulnerable, isn't in silent moving mode AND too far (>100)</li>
+     * <li>The target is in the actor Aggro range and is at the same height</li>
+     * <li>The actor is Aggressive</li><BR><BR>
+     *
+     * @param target The targeted L2Object
+     *
+     */
+    private boolean autoAttackCondition(L2Character target)
+    {
+        // Check if the target isn't another guard, folk or a door
+        if (target == null ||
+        	target instanceof L2SiegeGuardInstance ||
+            target instanceof L2FolkInstance ||
+        	target instanceof L2DoorInstance ||
+        	target.isAlikeDead() ||
+        	target.isInvul()) return false;
+
+        // Get the owner if the target is a summon
+        if (target instanceof L2Summon)
+        {
+        	L2PcInstance owner = ((L2Summon)target).getOwner();
+        	if (_actor.isInsideRadius(owner, 1000, true, false))
+        		target = owner;
+        }
+
+        // Check if the target is a L2PcInstance
+        if (target instanceof L2PcInstance)
+        {
+            // Check if the target isn't in silent move mode AND too far (>100)
+            if (((L2PcInstance) target).isSilentMoving()
+                && !_actor.isInsideRadius(target, 250, false, false)) return false;
+        }
+               // Los Check Here
+        return (_actor.isAutoAttackable(target) && GeoData.getInstance().canSeeTarget(_actor, target));
+
+    }
+
+    /**
+     * Set the Intention of this L2CharacterAI and create an  AI Task executed every 1s (call onEvtThink method) for this L2Attackable.<BR><BR>
+     *
+     * <FONT COLOR=#FF0000><B> <U>Caution</U> : If actor _knowPlayer isn't EMPTY, AI_INTENTION_IDLE will be change in AI_INTENTION_ACTIVE</B></FONT><BR><BR>
+     *
+     * @param intention The new Intention to set to the AI
+     * @param arg0 The first parameter of the Intention
+     * @param arg1 The second parameter of the Intention
+     *
+     */
+    @Override
+	synchronized void changeIntention(CtrlIntention intention, Object arg0, Object arg1)
+    {
+        if (Config.DEBUG)
+            _log.info("L2SiegeAI.changeIntention(" + intention + ", " + arg0 + ", " + arg1 + ")");
+        ((L2Attackable)_actor).setisReturningToSpawnPoint(false);
+        
+        if (intention == AI_INTENTION_IDLE /*|| intention == AI_INTENTION_ACTIVE*/) // active becomes idle if only a summon is present
+        {
+            // Check if actor is not dead
+            if (!_actor.isAlikeDead())
+            {
+                L2Attackable npc = (L2Attackable) _actor;
+
+                // If its _knownPlayer isn't empty set the Intention to AI_INTENTION_ACTIVE
+                if (npc.getKnownList().getKnownPlayers().size() > 0) intention = AI_INTENTION_ACTIVE;
+                else intention = AI_INTENTION_IDLE;
+            }
+
+            if (intention == AI_INTENTION_IDLE)
+            {
+                // Set the Intention of this L2AttackableAI to AI_INTENTION_IDLE
+                super.changeIntention(AI_INTENTION_IDLE, null, null);
+
+                // Stop AI task and detach AI from NPC
+                if (_aiTask != null)
+                {
+                    _aiTask.cancel(true);
+                    _aiTask = null;
+                }
+
+                // Cancel the AI
+                _accessor.detachAI();
+
+                return;
+            }
+        }
+
+        // Set the Intention of this L2AttackableAI to intention
+        super.changeIntention(intention, arg0, arg1);
+
+        // If not idle - create an AI task (schedule onEvtThink repeatedly)
+        if (_aiTask == null)
+        {
+            _aiTask = ThreadPoolManager.getInstance().scheduleAiAtFixedRate(this, 1000, 1000);
+        }
+    }
+
+    /**
+     * Manage the Attack Intention : Stop current Attack (if necessary), Calculate attack timeout, Start a new Attack and Launch Think Event.<BR><BR>
+     *
+     * @param target The L2Character to attack
+     *
+     */
+    @Override
+	protected void onIntentionAttack(L2Character target)
+    {
+        // Calculate the attack timeout
+        _attackTimeout = MAX_ATTACK_TIMEOUT + GameTimeController.getGameTicks();
+
+        // Manage the Attack Intention : Stop current Attack (if necessary), Start a new Attack and Launch Think Event
+        //if (_actor.getTarget() != null)
+        super.onIntentionAttack(target);
+    }
+
+    /**
+     * Manage AI standard thinks of a L2Attackable (called by onEvtThink).<BR><BR>
+     *
+     * <B><U> Actions</U> :</B><BR><BR>
+     * <li>Update every 1s the _globalAggro counter to come close to 0</li>
+     * <li>If the actor is Aggressive and can attack, add all autoAttackable L2Character in its Aggro Range to its _aggroList, chose a target and order to attack it</li>
+     * <li>If the actor  can't attack, order to it to return to its home location</li>
+     *
+     */
+    private void thinkActive()
+    {
+        L2Attackable npc = (L2Attackable) _actor;
+
+        // Update every 1s the _globalAggro counter to come close to 0
+        if (_globalAggro != 0)
+        {
+            if (_globalAggro < 0) _globalAggro++;
+            else _globalAggro--;
+        }
+
+        // Add all autoAttackable L2Character in L2Attackable Aggro Range to its _aggroList with 0 damage and 1 hate
+        // A L2Attackable isn't aggressive during 10s after its spawn because _globalAggro is set to -10
+        if (_globalAggro >= 0)
+        {
+            for (L2Character target : npc.getKnownList().getKnownCharactersInRadius(_attackRange))
+            {
+                if (target == null) continue;
+                if (autoAttackCondition(target)) // check aggression
+                {
+                    // Get the hate level of the L2Attackable against this L2Character target contained in _aggroList
+                    int hating = npc.getHating(target);
+
+                    // Add the attacker to the L2Attackable _aggroList with 0 damage and 1 hate
+                    if (hating == 0) npc.addDamageHate(target, 0, 1);
+                }
+            }
+
+            // Chose a target from its aggroList
+            L2Character hated;
+            if (_actor.isConfused()) hated = _attackTarget; // Force mobs to attak anybody if confused
+            else hated = npc.getMostHated();
+
+            // Order to the L2Attackable to attack the target
+            if (hated != null)
+            {
+                // Get the hate level of the L2Attackable against this L2Character target contained in _aggroList
+                int aggro = npc.getHating(hated);
+
+                if (aggro + _globalAggro > 0)
+                {
+                    // Set the L2Character movement type to run and send Server->Client packet ChangeMoveType to all others L2PcInstance
+                    if (!_actor.isRunning()) _actor.setRunning();
+
+                    // Set the AI Intention to AI_INTENTION_ATTACK
+                    setIntention(CtrlIntention.AI_INTENTION_ATTACK, hated, null);
+                }
+
+                return;
+            }
+
+        }
+        // Order to the L2SiegeGuardInstance to return to its home location because there's no target to attack
+        ((L2SiegeGuardInstance) _actor).returnHome();
+        return;
+
+    }
+
+    private void attackPrepare()
+    {
+        // Get all information needed to chose between physical or magical attack
+        L2Skill[] skills = null;
+        double dist_2 = 0;
+        int range = 0;
+        L2SiegeGuardInstance sGuard = (L2SiegeGuardInstance) _actor;
+
+        try
+        {
+            _actor.setTarget(_attackTarget);
+            skills = _actor.getAllSkills();
+            dist_2 = _actor.getPlanDistanceSq(_attackTarget.getX(), _attackTarget.getY());
+            range = _actor.getPhysicalAttackRange() + _actor.getTemplate().collisionRadius + _attackTarget.getTemplate().collisionRadius;
+        }
+        catch (NullPointerException e)
+        {
+        	//_log.warning("AttackableAI: Attack target is NULL.");
+        	_actor.setTarget(null);
+        	setIntention(AI_INTENTION_IDLE, null, null);
+        	return;
+        }
+
+        // never attack defenders
+        if(_attackTarget instanceof L2PcInstance && sGuard.getCastle().getSiege().checkIsDefender(((L2PcInstance)_attackTarget).getClan()))
+        {
+        	// Cancel the target
+        	sGuard.stopHating(_attackTarget);
+        	_actor.setTarget(null);
+        	setIntention(AI_INTENTION_IDLE, null, null);
+        	return;
+        }
+
+        if (!GeoData.getInstance().canSeeTarget(_actor, _attackTarget))
+    	{
+        	// Siege guards differ from normal mobs currently:
+        	// If target cannot seen, don't attack any more
+        	sGuard.stopHating(_attackTarget);
+        	_actor.setTarget(null);
+        	setIntention(AI_INTENTION_IDLE, null, null);
+        	return;
+    	}
+
+        // Check if the actor isn't muted and if it is far from target
+        if (!_actor.isMuted() && dist_2 > (range + 20) * (range + 20))
+        {
+            // check for long ranged skills and heal/buff skills
+            if (!Config.ALT_GAME_MOB_ATTACK_AI
+                || (_actor instanceof L2MonsterInstance && Rnd.nextInt(100) <= 5))
+                for (L2Skill sk : skills)
+                {
+                    int castRange = sk.getCastRange();
+
+                    if (((sk.getSkillType() == L2Skill.SkillType.BUFF || sk.getSkillType() == L2Skill.SkillType.HEAL) || (dist_2 >= castRange * castRange / 9)
+                        && (dist_2 <= castRange * castRange) && (castRange > 70))
+                        && !_actor.isSkillDisabled(sk.getId())
+                        && _actor.getCurrentMp() >= _actor.getStat().getMpConsume(sk) && !sk.isPassive())
+                    {
+                        L2Object OldTarget = _actor.getTarget();
+                        if (sk.getSkillType() == L2Skill.SkillType.BUFF
+                            || sk.getSkillType() == L2Skill.SkillType.HEAL)
+                        {
+                            boolean useSkillSelf = true;
+                            if (sk.getSkillType() == L2Skill.SkillType.HEAL
+                                && _actor.getCurrentHp() > (int) (_actor.getMaxHp() / 1.5))
+                            {
+                                useSkillSelf = false;
+                                break;
+                            }
+                            if (sk.getSkillType() == L2Skill.SkillType.BUFF)
+                            {
+                                L2Effect[] effects = _actor.getAllEffects();
+                                for (int i = 0; effects != null && i < effects.length; i++)
+                                {
+                                    L2Effect effect = effects[i];
+                                    if (effect.getSkill() == sk)
+                                    {
+                                        useSkillSelf = false;
+                                        break;
+                                    }
+                                }
+                            }
+                            if (useSkillSelf) _actor.setTarget(_actor);
+                        }
+
+                        clientStopMoving(null);
+                        _accessor.doCast(sk);
+                        _actor.setTarget(OldTarget);
+                        return;
+                    }
+                }
+
+            // Check if the L2SiegeGuardInstance is attacking, knows the target and can't run
+            if (!(_actor.isAttackingNow()) && (_actor.getRunSpeed() == 0)
+                && (_actor.getKnownList().knowsObject(_attackTarget)))
+            {
+            	// Cancel the target
+                _actor.getKnownList().removeKnownObject(_attackTarget);
+                _actor.setTarget(null);
+                setIntention(AI_INTENTION_IDLE, null, null);
+            }
+            else
+            {
+                double dx = _actor.getX() - _attackTarget.getX();
+                double dy = _actor.getY() - _attackTarget.getY();
+                double dz = _actor.getZ() - _attackTarget.getZ();
+                double homeX = _attackTarget.getX() - sGuard.getHomeX();
+                double homeY = _attackTarget.getY() - sGuard.getHomeY();
+
+                // Check if the L2SiegeGuardInstance isn't too far from it's home location
+                if ((dx * dx + dy * dy > 10000) && (homeX * homeX + homeY * homeY > 3240000) // 1800 * 1800
+                    && (_actor.getKnownList().knowsObject(_attackTarget)))
+                {
+                    // Cancel the target
+                    _actor.getKnownList().removeKnownObject(_attackTarget);
+                    _actor.setTarget(null);
+                    setIntention(AI_INTENTION_IDLE, null, null);
+                }
+                else // Move the actor to Pawn server side AND client side by sending Server->Client packet MoveToPawn (broadcast)
+                {
+                	// Temporary hack for preventing guards jumping off towers,
+                	// before replacing this with effective geodata checks and AI modification
+                	if(dz*dz < 170*170) // normally 130 if guard z coordinates correct
+                		moveToPawn(_attackTarget, range);
+                }
+            }
+
+            return;
+
+        }
+        // Else, if the actor is muted and far from target, just "move to pawn"
+        else if (_actor.isMuted() && dist_2 > (range + 20) * (range + 20))
+        {
+        	// Temporary hack for preventing guards jumping off towers,
+        	// before replacing this with effective geodata checks and AI modification
+        	double dz = _actor.getZ() - _attackTarget.getZ();
+        	if(dz*dz < 170*170) // normally 130 if guard z coordinates correct
+        		moveToPawn(_attackTarget, range);
+            return;
+        }
+        // Else, if this is close enough to attack
+        else if (dist_2 <= (range + 20) * (range + 20))
+        {
+            // Force mobs to attak anybody if confused
+            L2Character hated = null;
+            if (_actor.isConfused()) hated = _attackTarget;
+            else hated = ((L2Attackable) _actor).getMostHated();
+
+            if (hated == null)
+            {
+                setIntention(AI_INTENTION_ACTIVE, null, null);
+                return;
+            }
+            if (hated != _attackTarget) _attackTarget = hated;
+
+            _attackTimeout = MAX_ATTACK_TIMEOUT + GameTimeController.getGameTicks();
+
+            // check for close combat skills && heal/buff skills
+            if (!_actor.isMuted() && Rnd.nextInt(100) <= 5)
+            {
+                for (L2Skill sk : skills)
+                {
+                    int castRange = sk.getCastRange();
+
+                    if (castRange * castRange >= dist_2 && castRange <= 70 && !sk.isPassive()
+                        && _actor.getCurrentMp() >= _actor.getStat().getMpConsume(sk)
+                        && !_actor.isSkillDisabled(sk.getId()))
+                    {
+                        L2Object OldTarget = _actor.getTarget();
+                        if (sk.getSkillType() == L2Skill.SkillType.BUFF
+                            || sk.getSkillType() == L2Skill.SkillType.HEAL)
+                        {
+                            boolean useSkillSelf = true;
+                            if (sk.getSkillType() == L2Skill.SkillType.HEAL
+                                && _actor.getCurrentHp() > (int) (_actor.getMaxHp() / 1.5))
+                            {
+                                useSkillSelf = false;
+                                break;
+                            }
+                            if (sk.getSkillType() == L2Skill.SkillType.BUFF)
+                            {
+                                L2Effect[] effects = _actor.getAllEffects();
+                                for (int i = 0; effects != null && i < effects.length; i++)
+                                {
+                                    L2Effect effect = effects[i];
+                                    if (effect.getSkill() == sk)
+                                    {
+                                        useSkillSelf = false;
+                                        break;
+                                    }
+                                }
+                            }
+                            if (useSkillSelf) _actor.setTarget(_actor);
+                        }
+
+                        clientStopMoving(null);
+                        _accessor.doCast(sk);
+                        _actor.setTarget(OldTarget);
+                        return;
+                    }
+                }
+            }
+            // Finally, do the physical attack itself
+            _accessor.doAttack(_attackTarget);
+        }
+    }
+
+    /**
+     * Manage AI attack thinks of a L2Attackable (called by onEvtThink).<BR><BR>
+     *
+     * <B><U> Actions</U> :</B><BR><BR>
+     * <li>Update the attack timeout if actor is running</li>
+     * <li>If target is dead or timeout is expired, stop this attack and set the Intention to AI_INTENTION_ACTIVE</li>
+     * <li>Call all L2Object of its Faction inside the Faction Range</li>
+     * <li>Chose a target and order to attack it with magic skill or physical attack</li><BR><BR>
+     *
+     * TODO: Manage casting rules to healer mobs (like Ant Nurses)
+     *
+     */
+    private void thinkAttack()
+    {
+        if (Config.DEBUG)
+            _log.info("L2SiegeGuardAI.thinkAttack(); timeout="
+                + (_attackTimeout - GameTimeController.getGameTicks()));
+
+        if (_attackTimeout < GameTimeController.getGameTicks())
+        {
+            // Check if the actor is running
+            if (_actor.isRunning())
+            {
+                // Set the actor movement type to walk and send Server->Client packet ChangeMoveType to all others L2PcInstance
+                _actor.setWalking();
+
+                // Calculate a new attack timeout
+                _attackTimeout = MAX_ATTACK_TIMEOUT + GameTimeController.getGameTicks();
+            }
+        }
+
+        // Check if target is dead or if timeout is expired to stop this attack
+        if (_attackTarget == null || _attackTarget.isAlikeDead()
+            || _attackTimeout < GameTimeController.getGameTicks())
+        {
+            // Stop hating this target after the attack timeout or if target is dead
+            if (_attackTarget != null)
+            {
+                L2Attackable npc = (L2Attackable) _actor;
+                npc.stopHating(_attackTarget);
+            }
+
+            // Cancel target and timeout
+            _attackTimeout = Integer.MAX_VALUE;
+            _attackTarget = null;
+
+            // Set the AI Intention to AI_INTENTION_ACTIVE
+            setIntention(AI_INTENTION_ACTIVE, null, null);
+
+            _actor.setWalking();
+            return;
+        }
+
+        attackPrepare();
+        factionNotify();
+    }
+
+    private final void factionNotify()
+    {
+        // Call all L2Object of its Faction inside the Faction Range
+        if (((L2NpcInstance) _actor).getFactionId() == null || _attackTarget == null || _actor == null)
+            return;
+
+        if (_attackTarget.isInvul()) return;
+
+        String faction_id = ((L2NpcInstance) _actor).getFactionId();
+
+        // Go through all L2Object that belong to its faction
+        for (L2Character cha : _actor.getKnownList().getKnownCharactersInRadius(1000))
+        {
+            if (cha == null) continue;
+
+            if (!(cha instanceof L2NpcInstance)) continue;
+
+            L2NpcInstance npc = (L2NpcInstance) cha;
+
+            if (faction_id != npc.getFactionId()) continue;
+
+            // Check if the L2Object is inside the Faction Range of the actor
+            if ((npc.getAI().getIntention() == CtrlIntention.AI_INTENTION_IDLE || npc.getAI().getIntention() == CtrlIntention.AI_INTENTION_ACTIVE)
+                && _actor.isInsideRadius(npc, npc.getFactionRange(), false, true)
+                && npc.getTarget() == null
+                && _attackTarget.isInsideRadius(npc, npc.getFactionRange(), false, true)
+                )
+            {
+                if (Config.GEODATA > 0)
+                {
+                	if (GeoData.getInstance().canSeeTarget(npc, _attackTarget))
+                		// Notify the L2Object AI with EVT_AGGRESSION
+                        npc.getAI().notifyEvent(CtrlEvent.EVT_AGGRESSION, _attackTarget, 1);
+                }
+                else
+                {
+                	if (Math.abs(_attackTarget.getZ() - npc.getZ()) < 600)
+                		// Notify the L2Object AI with EVT_AGGRESSION
+                        npc.getAI().notifyEvent(CtrlEvent.EVT_AGGRESSION, _attackTarget, 1);
+                }
+            }
+        }
+    }
+
+    /**
+     * Manage AI thinking actions of a L2Attackable.<BR><BR>
+     */
+    @Override
+	protected void onEvtThink()
+    {
+        //      if(getIntention() != AI_INTENTION_IDLE && (!_actor.isVisible() || !_actor.hasAI() || !_actor.isKnownPlayers()))
+        //          setIntention(AI_INTENTION_IDLE);
+
+        // Check if the actor can't use skills and if a thinking action isn't already in progress
+        if (_thinking || _actor.isAllSkillsDisabled()) return;
+
+        // Start thinking action
+        _thinking = true;
+
+        try
+        {
+            // Manage AI thinks of a L2Attackable
+            if (getIntention() == AI_INTENTION_ACTIVE) thinkActive();
+            else if (getIntention() == AI_INTENTION_ATTACK) thinkAttack();
+        }
+        finally
+        {
+            // Stop thinking action
+            _thinking = false;
+        }
+    }
+
+    /**
+     * Launch actions corresponding to the Event Attacked.<BR><BR>
+     *
+     * <B><U> Actions</U> :</B><BR><BR>
+     * <li>Init the attack : Calculate the attack timeout, Set the _globalAggro to 0, Add the attacker to the actor _aggroList</li>
+     * <li>Set the L2Character movement type to run and send Server->Client packet ChangeMoveType to all others L2PcInstance</li>
+     * <li>Set the Intention to AI_INTENTION_ATTACK</li><BR><BR>
+     *
+     * @param attacker The L2Character that attacks the actor
+     *
+     */
+    @Override
+	protected void onEvtAttacked(L2Character attacker)
+    {
+        // Calculate the attack timeout
+        _attackTimeout = MAX_ATTACK_TIMEOUT + GameTimeController.getGameTicks();
+
+        // Set the _globalAggro to 0 to permit attack even just after spawn
+        if (_globalAggro < 0) _globalAggro = 0;
+
+        // Add the attacker to the _aggroList of the actor
+        ((L2Attackable) _actor).addDamageHate(attacker, 0, 1);
+
+        // Set the L2Character movement type to run and send Server->Client packet ChangeMoveType to all others L2PcInstance
+        if (!_actor.isRunning()) _actor.setRunning();
+
+        // Set the Intention to AI_INTENTION_ATTACK
+        if (getIntention() != AI_INTENTION_ATTACK)
+        {
+            setIntention(CtrlIntention.AI_INTENTION_ATTACK, attacker, null);
+        }
+
+        super.onEvtAttacked(attacker);
+    }
+
+    /**
+     * Launch actions corresponding to the Event Aggression.<BR><BR>
+     *
+     * <B><U> Actions</U> :</B><BR><BR>
+     * <li>Add the target to the actor _aggroList or update hate if already present </li>
+     * <li>Set the actor Intention to AI_INTENTION_ATTACK (if actor is L2GuardInstance check if it isn't too far from its home location)</li><BR><BR>
+     *
+     * @param attacker The L2Character that attacks
+     * @param aggro The value of hate to add to the actor against the target
+     *
+     */
+    @Override
+	protected void onEvtAggression(L2Character target, int aggro)
+    {
+        if (_actor == null) return;
+        L2Attackable me = (L2Attackable) _actor;
+
+        if (target != null)
+        {
+            // Add the target to the actor _aggroList or update hate if already present
+            me.addDamageHate(target, 0, aggro);
+
+            // Get the hate of the actor against the target
+            aggro = me.getHating(target);
+
+            if (aggro <= 0)
+            {
+            	if (me.getMostHated() == null)
+            	{
+            		_globalAggro = -25;
+            		me.clearAggroList();
+            		setIntention(AI_INTENTION_IDLE, null, null);
+            	}
+        		return;
+            }
+
+            // Set the actor AI Intention to AI_INTENTION_ATTACK
+            if (getIntention() != CtrlIntention.AI_INTENTION_ATTACK)
+            {
+                // Set the L2Character movement type to run and send Server->Client packet ChangeMoveType to all others L2PcInstance
+                if (!_actor.isRunning()) _actor.setRunning();
+
+                L2SiegeGuardInstance sGuard = (L2SiegeGuardInstance) _actor;
+                double homeX = target.getX() - sGuard.getHomeX();
+                double homeY = target.getY() - sGuard.getHomeY();
+
+                // Check if the L2SiegeGuardInstance is not too far from its home location
+                if (homeX * homeX + homeY * homeY < 3240000) // 1800 * 1800
+                    setIntention(CtrlIntention.AI_INTENTION_ATTACK, target, null);
+            }
+        }
+        else
+        {
+        	// currently only for setting lower general aggro
+        	if(aggro >= 0) return;
+
+        	L2Character mostHated = me.getMostHated();
+        	if (mostHated == null)
+        	{
+        		_globalAggro = -25;
+        		return;
+        	}
+        	else
+        		for(L2Character aggroed : me.getAggroListRP().keySet())
+        			me.addDamageHate(aggroed, 0, aggro);
+
+        	aggro = me.getHating(mostHated);
+        	if (aggro <= 0)
+            {
+        		_globalAggro = -25;
+        		me.clearAggroList();
+        		setIntention(AI_INTENTION_IDLE, null, null);
+            }
+        }
+    }
+
+    @Override
+	protected void onEvtDead()
+    {
+    	stopAITask();
+    	super.onEvtDead();
+    }
+
+    public void stopAITask()
+    {
+        if (_aiTask != null)
+        {
+            _aiTask.cancel(false);
+            _aiTask = null;
+        }
+        _accessor.detachAI();
+    }
+
+}

+ 121 - 0
L2_GameServer_T1/java/net/sf/l2j/gameserver/ai/L2SummonAI.java

@@ -0,0 +1,121 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+package net.sf.l2j.gameserver.ai;
+
+import static net.sf.l2j.gameserver.ai.CtrlIntention.AI_INTENTION_ATTACK;
+import static net.sf.l2j.gameserver.ai.CtrlIntention.AI_INTENTION_CAST;
+import static net.sf.l2j.gameserver.ai.CtrlIntention.AI_INTENTION_FOLLOW;
+import static net.sf.l2j.gameserver.ai.CtrlIntention.AI_INTENTION_IDLE;
+import static net.sf.l2j.gameserver.ai.CtrlIntention.AI_INTENTION_INTERACT;
+import static net.sf.l2j.gameserver.ai.CtrlIntention.AI_INTENTION_PICK_UP;
+import net.sf.l2j.gameserver.model.L2Summon;
+import net.sf.l2j.gameserver.model.L2Character.AIAccessor;
+
+public class L2SummonAI extends L2CharacterAI
+{
+
+    private boolean _thinking; // to prevent recursive thinking
+
+    public L2SummonAI(AIAccessor accessor)
+    {
+        super(accessor);
+    }
+
+    @Override
+	protected void onIntentionIdle()
+    {
+        stopFollow();
+    	onIntentionActive();
+    }
+
+    @Override
+	protected void onIntentionActive()
+    {
+        L2Summon summon = (L2Summon) _actor;
+        if (summon.getFollowStatus()) setIntention(AI_INTENTION_FOLLOW, summon.getOwner());
+        else super.onIntentionActive();
+    }
+
+    private void thinkAttack()
+    {
+        if (checkTargetLostOrDead(getAttackTarget()))
+        {
+            setAttackTarget(null);
+            return;
+        }
+        if (maybeMoveToPawn(getAttackTarget(), _actor.getPhysicalAttackRange())) return;
+        clientStopMoving(null);
+        _accessor.doAttack(getAttackTarget());
+        return;
+    }
+
+    private void thinkCast()
+    {
+        L2Summon summon = (L2Summon) _actor;
+        if (checkTargetLost(getCastTarget()))
+        {
+            setCastTarget(null);
+            return;
+        }
+        if (maybeMoveToPawn(getCastTarget(), _actor.getMagicalAttackRange(_skill))) return;
+        clientStopMoving(null);
+        summon.setFollowStatus(false);
+        setIntention(AI_INTENTION_IDLE);
+        _accessor.doCast(_skill);
+        return;
+    }
+
+    private void thinkPickUp()
+    {
+        if (_actor.isAllSkillsDisabled()) return;
+        if (checkTargetLost(getTarget())) return;
+        if (maybeMoveToPawn(getTarget(), 36)) return;
+        setIntention(AI_INTENTION_IDLE);
+        ((L2Summon.AIAccessor) _accessor).doPickupItem(getTarget());
+        return;
+    }
+
+    private void thinkInteract()
+    {
+        if (_actor.isAllSkillsDisabled()) return;
+        if (checkTargetLost(getTarget())) return;
+        if (maybeMoveToPawn(getTarget(), 36)) return;
+        setIntention(AI_INTENTION_IDLE);
+        return;
+    }
+
+    @Override
+	protected void onEvtThink()
+    {
+        if (_thinking || _actor.isAllSkillsDisabled()) return;
+        _thinking = true;
+        try
+        {
+            if (getIntention() == AI_INTENTION_ATTACK) thinkAttack();
+            else if (getIntention() == AI_INTENTION_CAST) thinkCast();
+            else if (getIntention() == AI_INTENTION_PICK_UP) thinkPickUp();
+            else if (getIntention() == AI_INTENTION_INTERACT) thinkInteract();
+        }
+        finally
+        {
+            _thinking = false;
+        }
+    }
+
+}

+ 50 - 0
L2_GameServer_T1/java/net/sf/l2j/gameserver/ai2/AiEvent.java

@@ -0,0 +1,50 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+package net.sf.l2j.gameserver.ai2;
+
+import net.sf.l2j.gameserver.model.L2Character;
+
+public class AiEvent
+{
+	private AiEventType _type;
+	private L2Character _source;
+	private L2Character _target;
+
+	public AiEvent(AiEventType type, L2Character source, L2Character target)
+	{
+		_type = type;
+		_source = source;
+		_target = target;
+	}
+
+	public AiEventType getType()
+	{
+		return _type;
+	}
+
+	public L2Character getSource()
+	{
+		return _source;
+	}
+
+	public L2Character getTarget()
+	{
+		return _target;
+	}
+}

+ 38 - 0
L2_GameServer_T1/java/net/sf/l2j/gameserver/ai2/AiEventType.java

@@ -0,0 +1,38 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+package net.sf.l2j.gameserver.ai2;
+
+/**
+ *
+ * @author -Wooden-
+ *
+ */
+public enum AiEventType
+{
+	SEE_CREATURE,
+	SEE_SPELL,
+	SEE_ATTACK,
+	ATTACKED,
+	AGGRESSION,
+	SPAWNED,
+	MINION_DIED,
+	MINION_SPAWNED,
+	ARRIVED, //??
+	ARRIVED_WAYPOINT
+}

Some files were not shown because too many files changed in this diff