Browse Source

Fort siege bug fixing by Kerberos

DrHouse 16 years ago
parent
commit
65b028478b
75 changed files with 4056 additions and 1616 deletions
  1. 223 12
      L2_GameServer/java/config/fortsiege.properties
  2. 3 2
      L2_GameServer/java/net/sf/l2j/gameserver/GeoEngine.java
  3. 4 3
      L2_GameServer/java/net/sf/l2j/gameserver/TradeController.java
  4. 1 4
      L2_GameServer/java/net/sf/l2j/gameserver/ai/L2AttackableAI.java
  5. 1 9
      L2_GameServer/java/net/sf/l2j/gameserver/ai/L2CharacterAI.java
  6. 8 0
      L2_GameServer/java/net/sf/l2j/gameserver/ai/L2DoorAI.java
  7. 882 0
      L2_GameServer/java/net/sf/l2j/gameserver/ai/L2FortSiegeGuardAI.java
  8. 1 3
      L2_GameServer/java/net/sf/l2j/gameserver/ai/L2SiegeGuardAI.java
  9. 22 2
      L2_GameServer/java/net/sf/l2j/gameserver/datatables/ClanTable.java
  10. 3 3
      L2_GameServer/java/net/sf/l2j/gameserver/datatables/DoorTable.java
  11. 1 1
      L2_GameServer/java/net/sf/l2j/gameserver/datatables/MapRegionTable.java
  12. 53 2
      L2_GameServer/java/net/sf/l2j/gameserver/datatables/StaticObjects.java
  13. 1 0
      L2_GameServer/java/net/sf/l2j/gameserver/handler/ItemHandler.java
  14. 1 0
      L2_GameServer/java/net/sf/l2j/gameserver/handler/SkillHandler.java
  15. 19 31
      L2_GameServer/java/net/sf/l2j/gameserver/handler/admincommandhandlers/AdminFortSiege.java
  16. 92 0
      L2_GameServer/java/net/sf/l2j/gameserver/handler/itemhandlers/BallistaBomb.java
  17. 61 0
      L2_GameServer/java/net/sf/l2j/gameserver/handler/skillhandlers/BallistaBomb.java
  18. 1 1
      L2_GameServer/java/net/sf/l2j/gameserver/handler/skillhandlers/Disablers.java
  19. 25 12
      L2_GameServer/java/net/sf/l2j/gameserver/handler/skillhandlers/TakeFort.java
  20. 4 0
      L2_GameServer/java/net/sf/l2j/gameserver/instancemanager/CursedWeaponsManager.java
  21. 399 8
      L2_GameServer/java/net/sf/l2j/gameserver/instancemanager/FortManager.java
  22. 43 183
      L2_GameServer/java/net/sf/l2j/gameserver/instancemanager/FortSiegeGuardManager.java
  23. 50 60
      L2_GameServer/java/net/sf/l2j/gameserver/instancemanager/FortSiegeManager.java
  24. 1 1
      L2_GameServer/java/net/sf/l2j/gameserver/model/CharEffectList.java
  25. 7 32
      L2_GameServer/java/net/sf/l2j/gameserver/model/CombatFlag.java
  26. 6 0
      L2_GameServer/java/net/sf/l2j/gameserver/model/L2Attackable.java
  27. 11 2
      L2_GameServer/java/net/sf/l2j/gameserver/model/L2Character.java
  28. 11 0
      L2_GameServer/java/net/sf/l2j/gameserver/model/L2Skill.java
  29. 4 0
      L2_GameServer/java/net/sf/l2j/gameserver/model/L2Transformation.java
  30. 99 20
      L2_GameServer/java/net/sf/l2j/gameserver/model/actor/instance/L2DoorInstance.java
  31. 1 1
      L2_GameServer/java/net/sf/l2j/gameserver/model/actor/instance/L2DoormenInstance.java
  32. 109 0
      L2_GameServer/java/net/sf/l2j/gameserver/model/actor/instance/L2FortBallistaInstance.java
  33. 81 16
      L2_GameServer/java/net/sf/l2j/gameserver/model/actor/instance/L2FortCommanderInstance.java
  34. 132 0
      L2_GameServer/java/net/sf/l2j/gameserver/model/actor/instance/L2FortEnvoyInstance.java
  35. 4 37
      L2_GameServer/java/net/sf/l2j/gameserver/model/actor/instance/L2FortManagerInstance.java
  36. 186 0
      L2_GameServer/java/net/sf/l2j/gameserver/model/actor/instance/L2FortSiegeGuardInstance.java
  37. 27 40
      L2_GameServer/java/net/sf/l2j/gameserver/model/actor/instance/L2FortSiegeNpcInstance.java
  38. 16 0
      L2_GameServer/java/net/sf/l2j/gameserver/model/actor/instance/L2NpcInstance.java
  39. 34 8
      L2_GameServer/java/net/sf/l2j/gameserver/model/actor/instance/L2PcInstance.java
  40. 78 31
      L2_GameServer/java/net/sf/l2j/gameserver/model/actor/instance/L2SiegeFlagInstance.java
  41. 4 3
      L2_GameServer/java/net/sf/l2j/gameserver/model/actor/instance/L2SiegeGuardInstance.java
  42. 171 12
      L2_GameServer/java/net/sf/l2j/gameserver/model/actor/instance/L2StaticObjectInstance.java
  43. 13 2
      L2_GameServer/java/net/sf/l2j/gameserver/model/actor/instance/L2VillageMasterInstance.java
  44. 1 0
      L2_GameServer/java/net/sf/l2j/gameserver/model/actor/knownlist/CharKnownList.java
  45. 3 2
      L2_GameServer/java/net/sf/l2j/gameserver/model/actor/knownlist/DoorKnownList.java
  46. 13 13
      L2_GameServer/java/net/sf/l2j/gameserver/model/actor/knownlist/FortSiegeGuardKnownList.java
  47. 2 1
      L2_GameServer/java/net/sf/l2j/gameserver/model/actor/knownlist/PcKnownList.java
  48. 64 0
      L2_GameServer/java/net/sf/l2j/gameserver/model/actor/knownlist/StaticObjectKnownList.java
  49. 46 0
      L2_GameServer/java/net/sf/l2j/gameserver/model/actor/stat/StaticObjStat.java
  50. 3 1
      L2_GameServer/java/net/sf/l2j/gameserver/model/actor/status/CharStatus.java
  51. 41 0
      L2_GameServer/java/net/sf/l2j/gameserver/model/actor/status/StaticObjStatus.java
  52. 1 1
      L2_GameServer/java/net/sf/l2j/gameserver/model/entity/Castle.java
  53. 317 131
      L2_GameServer/java/net/sf/l2j/gameserver/model/entity/Fort.java
  54. 326 407
      L2_GameServer/java/net/sf/l2j/gameserver/model/entity/FortSiege.java
  55. 78 20
      L2_GameServer/java/net/sf/l2j/gameserver/model/zone/type/L2FortZone.java
  56. 10 10
      L2_GameServer/java/net/sf/l2j/gameserver/network/SystemMessageId.java
  57. 28 3
      L2_GameServer/java/net/sf/l2j/gameserver/network/clientpackets/EnterWorld.java
  58. 5 0
      L2_GameServer/java/net/sf/l2j/gameserver/network/clientpackets/RequestActionUse.java
  59. 16 2
      L2_GameServer/java/net/sf/l2j/gameserver/network/clientpackets/RequestFortressSiegeInfo.java
  60. 39 70
      L2_GameServer/java/net/sf/l2j/gameserver/network/clientpackets/RequestJoinSiege.java
  61. 0 6
      L2_GameServer/java/net/sf/l2j/gameserver/network/clientpackets/RequestRestartPoint.java
  62. 1 15
      L2_GameServer/java/net/sf/l2j/gameserver/network/clientpackets/RequestSiegeAttackerList.java
  63. 4 18
      L2_GameServer/java/net/sf/l2j/gameserver/network/clientpackets/RequestSiegeDefenderList.java
  64. 12 0
      L2_GameServer/java/net/sf/l2j/gameserver/network/clientpackets/UseItem.java
  65. 5 15
      L2_GameServer/java/net/sf/l2j/gameserver/network/serverpackets/ExShowFortressInfo.java
  66. 61 5
      L2_GameServer/java/net/sf/l2j/gameserver/network/serverpackets/ExShowFortressMapInfo.java
  67. 71 4
      L2_GameServer/java/net/sf/l2j/gameserver/network/serverpackets/ExShowFortressSiegeInfo.java
  68. 0 108
      L2_GameServer/java/net/sf/l2j/gameserver/network/serverpackets/FortSiegeAttackerList.java
  69. 0 139
      L2_GameServer/java/net/sf/l2j/gameserver/network/serverpackets/FortSiegeDefenderList.java
  70. 0 101
      L2_GameServer/java/net/sf/l2j/gameserver/network/serverpackets/FortressSiegeInfo.java
  71. 1 1
      L2_GameServer/java/net/sf/l2j/gameserver/network/serverpackets/StaticObject.java
  72. 9 0
      L2_GameServer/java/net/sf/l2j/gameserver/network/serverpackets/SystemMessage.java
  73. 4 0
      L2_GameServer/java/net/sf/l2j/gameserver/skills/effects/EffectFear.java
  74. 1 1
      L2_GameServer/java/net/sf/l2j/gameserver/templates/chars/L2CharTemplate.java
  75. 1 1
      L2_GameServer/java/net/sf/l2j/gameserver/templates/skills/L2SkillType.java

+ 223 - 12
L2_GameServer/java/config/fortsiege.properties

@@ -1,7 +1,13 @@
 #Length of siege before the count down (in minutes)
 SiegeLength=60
 
-#Count down length, best to use a multiple of 5 (in minutes)
+#This time define how long u need to wait till suspicious merchant will spawn after siege ends
+#keep in mind when merchant spawn, fort can be immeadately sieged
+#default: 180 minutes
+SuspiciousMerchantRespawnDelay=180
+
+#This timers define how long time u have to kill all commanders once u kill first one
+#after that time (if all commanders not killed) commanders and doors get respawned
 CountDownLength=10
 
 #Max no. flags per clan
@@ -12,34 +18,177 @@ 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
 
 # Fortress Commander spawns
 #
 # Commander syntax:  NameCommanderN=x,y,z,heading,npc_id
 # Name - fortress name
-# N - number
+# N - number - 1: Archer Comander
+#            - 2: Guard Commander
+#            - 3: Support Unit Commander
+#            - 4: Main Machine - not supported yet, used General
+#            - 5: General - not used yet, will be used once control room supported
+# please keep correct order of commanders, otherwise client will show wrong occupied barracks
+# control room (main machine) currently emulated in client
 # x,y,z - coords
 # heading
 # npc_id - id of template
 
-# Flag syntax:  NameCommanderN=x,y,z,flag_id
+# Flag syntax:  NameFlagN=x,y,z,flag_id
 # Name - fortress name
 # N - number
 # x,y,z - coords
 # flag_id - id of combat flag
+#-------------------------------------------------------------
+# Shanty Fortress
+#-------------------------------------------------------------
+ShantyCommander1=-52435,155188,-1768,20000,35683
+ShantyCommander2=-52128,157752,-2024,29864,35677
+ShantyCommander3=-53944,155433,-2024,7304,35680
+ShantyFlag1=-53086,156493,-1896,9819
+ShantyFlag2=-53054,156605,-1896,9819
+ShantyFlag3=-53032,156689,-1896,9819
+
+#-------------------------------------------------------------
+# Southern Fortress
+#-------------------------------------------------------------
+SouthernCommander1=-21328,218864,-2952,0,35719
+SouthernCommander2=-22992,218160,-3208,0,35713
+SouthernCommander3=-21520,221504,-3208,45328,35716
+SouthernCommander4=-22728,221746,-3200,33168,35721
+SouthernFlag1=-22386,219917,-3079,9819
+SouthernFlag2=-22386,219798,-3079,9819
+SouthernFlag3=-22386,219679,-3079,9819
+
+#-------------------------------------------------------------
+# Hive Fortress
+#-------------------------------------------------------------
+HiveCommander1=15152,188128,-2640,0,35752
+HiveCommander2=17984,187536,-2896,45056,35746
+HiveCommander3=16016,189520,-2888,0,35749
+HiveFlag1=16685,188358,-2770,9819
+HiveFlag2=16761,188306,-2770,9819
+HiveFlag3=16847,188257,-2770,9819
 
 #-------------------------------------------------------------
-# DragonSpine
+# Valley Fortress
 #-------------------------------------------------------------
+ValleyCommander1=124768,121856,-2296,0,35788
+ValleyCommander2=124299,123614,-2552,49192,35782
+ValleyCommander3=124768,124640,-2552,54480,35785
+ValleyCommander4=128048,123344,-2536,35028,35790
+ValleyFlag1=125970,123653,-2429,9819
+ValleyFlag2=126092,123650,-2429,9819
+ValleyFlag3=126205,123648,-2429,9819
 
+#-------------------------------------------------------------
+# Ivory Fortress
+#-------------------------------------------------------------
+IvoryCommander1=72400,2896,-2760,0,35821
+IvoryCommander2=73788,5479,-3016,55136,35815
+IvoryCommander3=71264,4144,-3008,0,35818
+IvoryFlag1=72565,4436,-2888,9819
+IvoryFlag2=72660,4512,-2888,9819
+IvoryFlag3=72759,4594,-2888,9819
+
+#-------------------------------------------------------------
+# Narsell Fortress
+#-------------------------------------------------------------
+NarsellCommander1=154704,53856,-2968,0,35852
+NarsellCommander2=155576,56592,-3224,59224,35846
+NarsellCommander3=153328,54848,-3216,5512,35849
+NarsellFlag1=154567,55397,-3097,9819
+NarsellFlag2=154650,55493,-3097,9819
+NarsellFlag3=154715,55587,-3097,9819
+
+#-------------------------------------------------------------
+# Bayou Fortress
+#-------------------------------------------------------------
+BayouCommander1=188624,38240,-3128,0,35888
+BayouCommander2=188160,39920,-3376,49284,35882
+BayouCommander3=188626,41066,-3376,57140,35885
+BayouCommander4=191846,39764,-3368,33020,35890
+BayouFlag1=189838,40063,-3253,9819
+BayouFlag2=189931,40060,-3253,9819
+BayouFlag3=190052,40062,-3253,9819
+
+#-------------------------------------------------------------
+# White Sands Fortress
+#-------------------------------------------------------------
+White SandsCommander1=117216,205648,-3048,0,35921
+White SandsCommander2=118880,203568,-3304,5396,35915
+White SandsCommander3=118560,206560,-3304,48872,35918
+White SandsFlag1=118640,205151,-3176,9819
+White SandsFlag2=118690,205062,-3176,9819
+White SandsFlag3=118742,204968,-3176,9819
+
+#-------------------------------------------------------------
+# Borderland Fortress
+#-------------------------------------------------------------
+BorderlandCommander1=159664,-72224,-2584,0,35957
+BorderlandCommander2=157968,-71659,-2832,59020,35951
+BorderlandCommander3=157312,-70640,-2832,0,35954
+BorderlandCommander4=160194,-68688,-2824,43272,35959
+BorderlandFlag1=158817,-70229,-2708,9819
+BorderlandFlag2=158883,-70145,-2708,9819
+BorderlandFlag3=158946,-70045,-2708,9819
+
+#-------------------------------------------------------------
+# Swamp Fortress
+#-------------------------------------------------------------
+SwampCommander1=71264,-60512,-2504,0,35995
+SwampCommander2=71248,-62352,-2752,12388,35989
+SwampCommander3=68688,-59648,-2752,56012,35992
+SwampCommander4=68005,-60866,-2744,5424,35997
+SwampFlag1=69829,-61087,-2629,9819
+SwampFlag2=69979,-61144,-2632,9819
+SwampFlag3=70069,-61182,-2629,9819
+
+#-------------------------------------------------------------
+# Archaic Fortress
+#-------------------------------------------------------------
+ArchaicCommander1=109856,-142640,-2672,0,36028
+ArchaicCommander2=109600,-139735,-2928,62612,36022
+ArchaicCommander3=108223,-142209,-2920,8524,36025
+ArchaicFlag1=109142,-141243,-2801,9819
+ArchaicFlag2=109184,-141129,-2801,9819
+ArchaicFlag3=109214,-141016,-2801,9819
+
+#-------------------------------------------------------------
+# Floran Fortress
+#-------------------------------------------------------------
+FloranCommander1=6528,151872,-2608,0,36064
+FloranCommander2=7006,148242,-2856,32768,36058
+FloranCommander3=4384,150992,-2856,0,36061
+FloranCommander4=5246,152319,-2848,49151,36066
+FloranFlag1=5293,149624,-2732,9819
+FloranFlag2=5306,149743,-2732,9819
+FloranFlag3=5299,149870,-2732,9819
+
+#-------------------------------------------------------------
+# Cloud Mountain Fortress
+#-------------------------------------------------------------
+Cloud MountainCommander1=-55248,90496,-2536,0,36102
+Cloud MountainCommander2=-55791,91856,-2792,0,36096
+Cloud MountainCommander3=-54168,92604,-2784,49196,36099
+Cloud MountainCommander4=-50913,92259,-2776,41188,36104
+Cloud MountainFlag1=-53354,91537,-2664,9819
+Cloud MountainFlag2=-53237,91537,-2664,9819
+Cloud MountainFlag3=-53112,91537,-2664,9819
+
+#-------------------------------------------------------------
+# Tanor Fortress
+#-------------------------------------------------------------
+TanorCommander1=58480,139648,-1464,0,36135
+TanorCommander2=61864,139257,-1728,46896,36129
+TanorCommander3=59436,140834,-1720,47296,36132
+TanorFlag1=60225,139771,-1597,9819
+TanorFlag2=60362,139742,-1597,9819
+TanorFlag3=60467,139727,-1597,9819
+
+#-------------------------------------------------------------
+# DragonSpine Fortress
+#-------------------------------------------------------------
 DragonspineCommander1=13184,94928,-3144,0,36166
 DragonspineCommander2=9472,94992,-3392,0,36160
 DragonspineCommander3=12829,96214,-3392,49152,36163
@@ -47,3 +196,65 @@ DragonspineFlag1=11459,95308,-3264,9819
 DragonspineFlag2=11527,95301,-3264,9819
 DragonspineFlag3=11623,95311,-3264,9819
 
+#-------------------------------------------------------------
+# Antharas Fortress
+#-------------------------------------------------------------
+AntharasCommander1=79440,88752,-2600,0,36202
+AntharasCommander2=77262,91704,-2856,5112,36196
+AntharasCommander3=80929,90510,-2856,40192,36199
+AntharasCommander4=80755,89002,-2848,21984,36204
+AntharasFlag1=79470,91299,-2728,9819
+AntharasFlag2=79528,91187,-2728,9819
+AntharasFlag3=79580,91095,-2728,9819
+
+#-------------------------------------------------------------
+# Western Fortress
+#-------------------------------------------------------------
+WesternCommander1=113481,-16058,-712,0,36240
+WesternCommander2=109872,-16624,-968,16384,36234
+WesternCommander3=112601,-13933,-960,49152,36237
+WesternCommander4=113929,-14801,-960,32768,36242
+WesternFlag1=11280,-14820,-839,9819
+WesternFlag2=11380,-14820,-839,9819
+WesternFlag3=11480,-14820,-839,9819
+
+#-------------------------------------------------------------
+# Hunters Fortress
+#-------------------------------------------------------------
+HuntersCommander1=123232,94400,-1856,0,36278
+HuntersCommander2=122688,95760,-2112,0,36272
+HuntersCommander3=124305,96528,-2104,49151,36275
+HuntersCommander4=127632,96240,-2096,40892,36280
+HuntersFlag1=125155,95455,-1984,9819
+HuntersFlag2=125255,95455,-1984,9819
+HuntersFlag3=125355,95455,-1984,9819
+
+#-------------------------------------------------------------
+# Aaru Fortress
+#-------------------------------------------------------------
+AaruCommander1=74288,186912,-2296,0,36311
+AaruCommander2=71392,184720,-2552,5528,36305
+AaruCommander3=71542,186410,-2552,55088,36308
+AaruFlag1=73029,186303,-2424,9819
+AaruFlag2=73923,186247,-2424,9819
+AaruFlag3=72833,186178,-2424,9819
+
+#-------------------------------------------------------------
+# Demon Fortress
+#-------------------------------------------------------------
+DemonCommander1=100752,-53664,-360,0,36347
+DemonCommander2=100688,-57440,-616,16384,36341
+DemonCommander3=99484,-54027,-616,0,36344
+DemonFlag1=100400,-55401,-488,9819
+DemonFlag2=100400,-55301,-488,9819
+DemonFlag3=100400,-55201,-488,9819
+
+#-------------------------------------------------------------
+# Monastic Fortress
+#-------------------------------------------------------------
+MonasticCommander1=73680,-95456,-1144,0,36385
+MonasticCommander2=70189,-93935,-1400,61576,36379
+MonasticCommander3=73831,-94119,-1400,45536,36382
+MonasticFlag1=72174,-94437,-1271,9819
+MonasticFlag2=72294,-94481,-1271,9819
+MonasticFlag3=72401,-94526,-1271,9819

+ 3 - 2
L2_GameServer/java/net/sf/l2j/gameserver/GeoEngine.java

@@ -39,6 +39,7 @@ 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.L2FortSiegeGuardInstance;
 import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
 import net.sf.l2j.gameserver.model.actor.instance.L2SiegeGuardInstance;
 import net.sf.l2j.gameserver.pathfinding.Node;
@@ -137,13 +138,13 @@ public class GeoEngine extends GeoData
     	// 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 :(
+    	if(cha instanceof L2SiegeGuardInstance || cha instanceof L2FortSiegeGuardInstance) 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,cha.getInstanceId()))
     		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(target instanceof L2SiegeGuardInstance || target instanceof L2FortSiegeGuardInstance) 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

+ 4 - 3
L2_GameServer/java/net/sf/l2j/gameserver/TradeController.java

@@ -14,6 +14,7 @@
  */
 package net.sf.l2j.gameserver;
 
+import java.sql.Connection;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.util.Collection;
@@ -41,7 +42,7 @@ public class TradeController
     private static TradeController _instance;
     
     private int _nextListId;
-    private Map<Integer, L2TradeList> _lists;
+    private Map<Integer, L2TradeList> _lists= new FastMap<Integer, L2TradeList>();
     
     /** Task launching the function for restore count of Item (Clan Hall) */
     /*public class RestoreCount implements Runnable
@@ -72,8 +73,8 @@ public class TradeController
     
     private TradeController()
     {
-        _lists = new FastMap<Integer, L2TradeList>();
-        java.sql.Connection con = null;
+        _lists.clear();
+        Connection con = null;
         
         /*
          * Initialize Shop buylist

+ 1 - 4
L2_GameServer/java/net/sf/l2j/gameserver/ai/L2AttackableAI.java

@@ -14,10 +14,7 @@
  */
 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 static net.sf.l2j.gameserver.ai.CtrlIntention.AI_INTENTION_INTERACT;
+import static net.sf.l2j.gameserver.ai.CtrlIntention.*;
 
 import java.util.Collection;
 import java.util.List;

+ 1 - 9
L2_GameServer/java/net/sf/l2j/gameserver/ai/L2CharacterAI.java

@@ -14,15 +14,7 @@
  */
 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 static net.sf.l2j.gameserver.ai.CtrlIntention.*;
 
 import java.util.List;
 

+ 8 - 0
L2_GameServer/java/net/sf/l2j/gameserver/ai/L2DoorAI.java

@@ -20,6 +20,7 @@ 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.L2FortSiegeGuardInstance;
 import net.sf.l2j.gameserver.model.actor.instance.L2SiegeGuardInstance;
 
 /**
@@ -177,6 +178,13 @@ public class L2DoorAI extends L2CharacterAI
 					guard.getAI().notifyEvent(CtrlEvent.EVT_AGGRESSION, _attacker, 15);
 				}
 			}
+			for (L2FortSiegeGuardInstance guard : _door.getKnownFortSiegeGuards())
+			{
+				if (_actor.isInsideRadius(guard, guard.getFactionRange(), false, true) && Math.abs(_attacker.getZ() - guard.getZ()) < 200)
+				{
+					guard.getAI().notifyEvent(CtrlEvent.EVT_AGGRESSION, _attacker, 15);
+				}
+			}
 		}
 	}
 	

+ 882 - 0
L2_GameServer/java/net/sf/l2j/gameserver/ai/L2FortSiegeGuardAI.java

@@ -0,0 +1,882 @@
+/*
+ * 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 3 of the License, or (at your option) any later
+ * version.
+ * 
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+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 java.util.logging.Logger;
+
+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.L2FortBallistaInstance;
+import net.sf.l2j.gameserver.model.actor.instance.L2FortCommanderInstance;
+import net.sf.l2j.gameserver.model.actor.instance.L2FortSiegeGuardInstance;
+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.templates.skills.L2SkillType;
+import net.sf.l2j.gameserver.util.Util;
+import net.sf.l2j.util.Rnd;
+
+/**
+ * This class manages AI of L2Attackable.<BR><BR>
+ *
+ */
+public class L2FortSiegeGuardAI extends L2CharacterAI implements Runnable
+{
+	
+	protected static final Logger _log1 = Logger.getLogger(L2FortSiegeGuardAI.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;
+	
+	/** For attack AI, analysis of mob and its targets */
+	private SelfAnalysis _selfAnalysis = new SelfAnalysis();
+	
+	/** The delay after which 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 L2FortSiegeGuardAI(L2Character.AIAccessor accessor)
+	{
+		super(accessor);
+		_selfAnalysis.init();
+		_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 L2FortSiegeGuardInstance || target instanceof L2FolkInstance || target instanceof L2DoorInstance
+				|| target.isAlikeDead() || target instanceof L2FortBallistaInstance || target instanceof L2FortCommanderInstance
+				|| target instanceof L2PlayableInstance)
+		{
+			L2PcInstance player = null;
+			if (target instanceof L2PcInstance)
+				player = ((L2PcInstance)target);
+			else if (target instanceof L2Summon)
+				player = ((L2Summon) target).getOwner();
+			if (player == null || (player != null && player.getClan() != null && player.getClan().getHasFort() == ((L2NpcInstance) _actor).getFort().getFortId()))
+				return false;
+		}
+		
+		// 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;
+		}
+		
+		// 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 L2PlayableInstance)
+		{
+			// Check if the target isn't in silent move mode AND too far (>100)
+			if (((L2PlayableInstance) 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)
+			_log1.info("L2SiegeAI.changeIntention(" + intention + ", " + arg0 + ", " + arg1 + ")");
+		
+		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 = getAttackTarget(); // Force mobs to attack anybody if confused
+			else
+				hated = npc.getMostHated();
+			//_mostHatedAnalysis.Update(hated);
+			
+			// 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
+		if (_actor.getWalkSpeed() >= 0)
+		{
+			if (_actor instanceof L2FortSiegeGuardInstance)
+				((L2FortSiegeGuardInstance) _actor).returnHome();
+			else
+				((L2FortCommanderInstance) _actor).returnHome();
+		}
+		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 (Config.DEBUG)
+			_log1.info("L2FortSiegeGuardAI.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();
+			}
+		}
+		
+		L2Character attackTarget = getAttackTarget();
+		// 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;
+			setAttackTarget(null);
+			
+			// Set the AI Intention to AI_INTENTION_ACTIVE
+			setIntention(AI_INTENTION_ACTIVE, null, null);
+			
+			_actor.setWalking();
+			return;
+		}
+		
+		factionNotifyAndSupport();
+		attackPrepare();
+	}
+	
+	private final void factionNotifyAndSupport()
+	{
+		L2Character target = getAttackTarget();
+		// Call all L2Object of its Faction inside the Faction Range
+		if (((L2NpcInstance) _actor).getFactionId() == null || target == null)
+			return;
+		
+		if (target.isInvul())
+			return; // speeding it up for siege guards
+		
+		if (Rnd.get(10) > 4) return; // test for reducing CPU load
+			
+		String faction_id = ((L2NpcInstance) _actor).getFactionId();
+		
+		// Go through all L2Character that belong to its faction
+		//for (L2Character cha : _actor.getKnownList().getKnownCharactersInRadius(((L2NpcInstance) _actor).getFactionRange()+_actor.getTemplate().collisionRadius))
+		for (L2Character cha : _actor.getKnownList().getKnownCharactersInRadius(1000))
+		{
+			if (cha == null)
+				continue;
+			
+			if (!(cha instanceof L2NpcInstance))
+			{
+				if (_selfAnalysis.hasHealOrResurrect && cha instanceof L2PcInstance && ((L2NpcInstance) _actor).getFort().getSiege().checkIsDefender(((L2PcInstance) cha).getClan()))
+				{
+					// heal friends
+					if (!_actor.isAttackingDisabled() && cha.getCurrentHp() < cha.getMaxHp() * 0.6 && _actor.getCurrentHp() > _actor.getMaxHp() / 2 && _actor.getCurrentMp() > _actor.getMaxMp() / 2 && cha.isInCombat())
+					{
+						for (L2Skill sk : _selfAnalysis.healSkills)
+						{
+							if (_actor.getCurrentMp() < sk.getMpConsume())
+								continue;
+							if (_actor.isSkillDisabled(sk.getId()))
+								continue;
+							if (!Util.checkIfInRange(sk.getCastRange(), _actor, cha, true))
+								continue;
+							
+							int chance = 5;
+							if (chance >= Rnd.get(100)) // chance
+								continue;
+							if (!GeoData.getInstance().canSeeTarget(_actor, cha))
+								break;
+							
+							L2Object OldTarget = _actor.getTarget();
+							_actor.setTarget(cha);
+							clientStopMoving(null);
+							_accessor.doCast(sk);
+							_actor.setTarget(OldTarget);
+							return;
+						}
+					}
+				}
+				continue;
+			}
+			
+			L2NpcInstance npc = (L2NpcInstance) cha;
+			
+			if (faction_id != npc.getFactionId())
+				continue;
+			
+			if (npc.getAI() != null) // TODO: possibly check not needed
+			{
+				if (!npc.isDead() && Math.abs(target.getZ() - npc.getZ()) < 600
+				//&& _actor.getAttackByList().contains(getAttackTarget())
+						&& (npc.getAI()._intention == CtrlIntention.AI_INTENTION_IDLE || npc.getAI()._intention == CtrlIntention.AI_INTENTION_ACTIVE)
+						//limiting aggro for siege guards
+						&& target.isInsideRadius(npc, 1500, true, false) && GeoData.getInstance().canSeeTarget(npc, target))
+				{
+					// Notify the L2Object AI with EVT_AGGRESSION
+					npc.getAI().notifyEvent(CtrlEvent.EVT_AGGRESSION, getAttackTarget(), 1);
+				}
+				// heal friends
+				if (_selfAnalysis.hasHealOrResurrect && !_actor.isAttackingDisabled() && npc.getCurrentHp() < npc.getMaxHp() * 0.6 && _actor.getCurrentHp() > _actor.getMaxHp() / 2 && _actor.getCurrentMp() > _actor.getMaxMp() / 2
+						&& npc.isInCombat())
+				{
+					for (L2Skill sk : _selfAnalysis.healSkills)
+					{
+						if (_actor.getCurrentMp() < sk.getMpConsume())
+							continue;
+						if (_actor.isSkillDisabled(sk.getId()))
+							continue;
+						if (!Util.checkIfInRange(sk.getCastRange(), _actor, npc, true))
+							continue;
+						
+						int chance = 4;
+						if (chance >= Rnd.get(100)) // chance
+							continue;
+						if (!GeoData.getInstance().canSeeTarget(_actor, npc))
+							break;
+						
+						L2Object OldTarget = _actor.getTarget();
+						_actor.setTarget(npc);
+						clientStopMoving(null);
+						_accessor.doCast(sk);
+						_actor.setTarget(OldTarget);
+						return;
+					}
+				}
+			}
+		}
+	}
+	
+	private void attackPrepare()
+	{
+		// Get all information needed to choose between physical or magical attack
+		L2Skill[] skills = null;
+		double dist_2 = 0;
+		int range = 0;
+		L2FortSiegeGuardInstance sGuard;
+		if (_actor instanceof L2FortSiegeGuardInstance)
+			sGuard = (L2FortSiegeGuardInstance) _actor;
+		else
+			sGuard = (L2FortCommanderInstance) _actor;
+		L2Character attackTarget = getAttackTarget();
+		
+		try
+		{
+			_actor.setTarget(attackTarget);
+			skills = _actor.getAllSkills();
+			dist_2 = _actor.getPlanDistanceSq(attackTarget.getX(), attackTarget.getY());
+			range = _actor.getPhysicalAttackRange() + _actor.getTemplate().collisionRadius + attackTarget.getTemplate().collisionRadius;
+			if (attackTarget.isMoving())
+				range += 50;
+		}
+		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.getFort().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 * range)
+		{
+			// check for long ranged skills and heal/buff skills
+			for (L2Skill sk : skills)
+			{
+				int castRange = sk.getCastRange();
+				
+				if ((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() == L2SkillType.BUFF || sk.getSkillType() == L2SkillType.HEAL)
+					{
+						boolean useSkillSelf = true;
+						if (sk.getSkillType() == L2SkillType.HEAL && _actor.getCurrentHp() > (int) (_actor.getMaxHp() / 1.5))
+						{
+							useSkillSelf = false;
+							break;
+						}
+						if (sk.getSkillType() == L2SkillType.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.getSpawn().getLocx();
+				double homeY = attackTarget.getY() - sGuard.getSpawn().getLocy();
+				
+				// 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
+					{
+						if (_selfAnalysis.isMage)
+							range = _selfAnalysis.maxCastRange - 50;
+						if (_actor.getWalkSpeed() <= 0)
+							return;
+						if (attackTarget.isMoving())
+							moveToPawn(attackTarget, range - 70);
+						else
+							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 * range)
+		{
+			// 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
+			{
+				if (_selfAnalysis.isMage)
+					range = _selfAnalysis.maxCastRange - 50;
+				if (_actor.getWalkSpeed() <= 0)
+					return;
+				if (attackTarget.isMoving())
+					moveToPawn(attackTarget, range - 70);
+				else
+					moveToPawn(attackTarget, range);
+			}
+			return;
+		}
+		// Else, if this is close enough to attack
+		else if (dist_2 <= range * range)
+		{
+			// Force mobs to attack 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 && !sk.isPassive() && _actor.getCurrentMp() >= _actor.getStat().getMpConsume(sk) && !_actor.isSkillDisabled(sk.getId()))
+					{
+						L2Object OldTarget = _actor.getTarget();
+						if (sk.getSkillType() == L2SkillType.BUFF || sk.getSkillType() == L2SkillType.HEAL)
+						{
+							boolean useSkillSelf = true;
+							if (sk.getSkillType() == L2SkillType.HEAL && _actor.getCurrentHp() > (int) (_actor.getMaxHp() / 1.5))
+							{
+								useSkillSelf = false;
+								break;
+							}
+							if (sk.getSkillType() == L2SkillType.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 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.isCastingNow() || _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();
+				
+				L2FortSiegeGuardInstance sGuard;
+				if (_actor instanceof L2FortSiegeGuardInstance)
+					sGuard = (L2FortSiegeGuardInstance) _actor;
+				else
+					sGuard = (L2FortCommanderInstance) _actor;
+				double homeX = target.getX() - sGuard.getSpawn().getLocx();
+				double homeY = target.getY() - sGuard.getSpawn().getLocy();
+				
+				// 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();
+	}
+	
+}

+ 1 - 3
L2_GameServer/java/net/sf/l2j/gameserver/ai/L2SiegeGuardAI.java

@@ -30,10 +30,8 @@ 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.L2CommanderInstance;
 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.L2FortMerchantInstance;
 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;
@@ -128,7 +126,7 @@ public class L2SiegeGuardAI extends L2CharacterAI implements Runnable
 	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 L2CommanderInstance || target instanceof L2FortMerchantInstance || target instanceof L2FolkInstance || target instanceof L2DoorInstance
+		if (target == null || target instanceof L2SiegeGuardInstance || target instanceof L2FolkInstance || target instanceof L2DoorInstance
 				|| target.isAlikeDead())
 			return false;
 		

+ 22 - 2
L2_GameServer/java/net/sf/l2j/gameserver/datatables/ClanTable.java

@@ -25,10 +25,14 @@ import net.sf.l2j.Config;
 import net.sf.l2j.L2DatabaseFactory;
 import net.sf.l2j.gameserver.ThreadPoolManager;
 import net.sf.l2j.gameserver.idfactory.IdFactory;
+import net.sf.l2j.gameserver.instancemanager.FortManager;
+import net.sf.l2j.gameserver.instancemanager.FortSiegeManager;
 import net.sf.l2j.gameserver.instancemanager.SiegeManager;
 import net.sf.l2j.gameserver.model.L2Clan;
 import net.sf.l2j.gameserver.model.L2ClanMember;
 import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
+import net.sf.l2j.gameserver.model.entity.Fort;
+import net.sf.l2j.gameserver.model.entity.FortSiege;
 import net.sf.l2j.gameserver.model.entity.Siege;
 import net.sf.l2j.gameserver.network.SystemMessageId;
 import net.sf.l2j.gameserver.network.serverpackets.PledgeShowInfoUpdate;
@@ -234,7 +238,14 @@ public class ClanTable
 				siege.removeSiegeClan(clanId);
 			}
 		}
-		
+		int fortId = clan.getHasFort();
+		if (fortId == 0)
+		{
+			for (FortSiege siege : FortSiegeManager.getInstance().getSieges())
+			{
+				siege.removeSiegeClan(clanId);
+			}
+		}
 		L2ClanMember leaderMember = clan.getLeader();
 		if (leaderMember == null)
 			clan.getWarehouse().destroyAllItems("ClanRemove", null, null);
@@ -286,7 +297,16 @@ public class ClanTable
 				statement.execute();
 				statement.close();
 			}
-			
+			if (fortId != 0)
+			{
+				Fort fort = FortManager.getInstance().getFortById(fortId);
+				if (fort != null)
+				{
+					L2Clan owner = fort.getOwnerClan();
+					if (clan == owner)
+						fort.removeOwner(true);
+				}
+			}
 			if (Config.DEBUG)
 				_log.fine("clan removed in db: " + clanId);
 		}

+ 3 - 3
L2_GameServer/java/net/sf/l2j/gameserver/datatables/DoorTable.java

@@ -144,9 +144,9 @@ public class DoorTable
 		boolean unlockable = false;
 		if (st.hasMoreTokens())
 			unlockable = Boolean.parseBoolean(st.nextToken());
-		boolean startOpen = false;
+		boolean isCommanderDoor = false;
 		if (st.hasMoreTokens())
-			startOpen = Boolean.parseBoolean(st.nextToken());
+			isCommanderDoor = Boolean.parseBoolean(st.nextToken());
 		
 		if (rangeXMin > rangeXMax)
 			_log.severe("Error in door data, ID:" + id);
@@ -217,7 +217,7 @@ public class DoorTable
 			_log.severe("Error in door data, ID:" + id);
 		}
 		door.setCurrentHpMp(door.getMaxHp(), door.getMaxMp());
-		door.setOpen(startOpen);
+		door.setIsCommanderDoor(isCommanderDoor);
 		door.setXYZInvisible(x, y, z);
 		
 		return door;

+ 1 - 1
L2_GameServer/java/net/sf/l2j/gameserver/datatables/MapRegionTable.java

@@ -433,7 +433,7 @@ public class MapRegionTable
 						fort = FortManager.getInstance().getFort(player);
 						if (!(fort != null 
 								&& fort.getSiege().getIsInProgress() 
-								&& fort.getSiege().getDefenderClan(player.getClan()) != null))
+								&& fort.getOwnerClan() == player.getClan()))
 							fort = null;
 					}
 					

+ 53 - 2
L2_GameServer/java/net/sf/l2j/gameserver/datatables/StaticObjects.java

@@ -27,6 +27,8 @@ import javolution.util.FastMap;
 import net.sf.l2j.Config;
 import net.sf.l2j.gameserver.idfactory.IdFactory;
 import net.sf.l2j.gameserver.model.actor.instance.L2StaticObjectInstance;
+import net.sf.l2j.gameserver.templates.StatsSet;
+import net.sf.l2j.gameserver.templates.chars.L2CharTemplate;
 
 public class StaticObjects
 {
@@ -102,13 +104,62 @@ public class StaticObjects
 		int map_x = Integer.parseInt(st.nextToken());
 		int map_y = Integer.parseInt(st.nextToken());
 		
-		L2StaticObjectInstance obj = new L2StaticObjectInstance(IdFactory.getInstance().getNextId());
+		StatsSet npcDat = new StatsSet();
+		npcDat.set("npcId", id);
+		npcDat.set("level", 0);
+		npcDat.set("jClass", "staticobject");
+		
+		npcDat.set("baseSTR", 0);
+		npcDat.set("baseCON", 0);
+		npcDat.set("baseDEX", 0);
+		npcDat.set("baseINT", 0);
+		npcDat.set("baseWIT", 0);
+		npcDat.set("baseMEN", 0);
+		
+		npcDat.set("baseShldDef", 0);
+		npcDat.set("baseShldRate", 0);
+		npcDat.set("baseAccCombat", 38);
+		npcDat.set("baseEvasRate", 38);
+		npcDat.set("baseCritRate", 38);
+		
+		//npcDat.set("name", "");
+		npcDat.set("collision_radius", 10);
+		npcDat.set("collision_height", 10);
+		npcDat.set("sex", "male");
+		npcDat.set("type", "");
+		npcDat.set("baseAtkRange", 0);
+		npcDat.set("baseMpMax", 0);
+		npcDat.set("baseCpMax", 0);
+		npcDat.set("rewardExp", 0);
+		npcDat.set("rewardSp", 0);
+		npcDat.set("basePAtk", 0);
+		npcDat.set("baseMAtk", 0);
+		npcDat.set("basePAtkSpd", 0);
+		npcDat.set("aggroRange", 0);
+		npcDat.set("baseMAtkSpd", 0);
+		npcDat.set("rhand", 0);
+		npcDat.set("lhand", 0);
+		npcDat.set("armor", 0);
+		npcDat.set("baseWalkSpd", 0);
+		npcDat.set("baseRunSpd", 0);
+		npcDat.set("name", "");
+		npcDat.set("baseHpMax", 1);
+		npcDat.set("baseHpReg", 3.e-3f);
+		npcDat.set("baseMpReg", 3.e-3f);
+		npcDat.set("basePDef", 1);
+		npcDat.set("baseMDef", 1);
+		
+		L2CharTemplate template = new L2CharTemplate(npcDat);
+		L2StaticObjectInstance obj = new L2StaticObjectInstance(IdFactory.getInstance().getNextId(), template, id);
 		obj.setType(type);
-		obj.setStaticObjectId(id);
 		obj.setXYZ(x, y, z);
 		obj.setMap(texture, map_x, map_y);
 		obj.spawnMe();
 		
 		return obj;
 	}
+	public void putObject(L2StaticObjectInstance obj)
+	{
+		_staticObjects.put(obj.getStaticObjectId(), obj);
+	}
 }

+ 1 - 0
L2_GameServer/java/net/sf/l2j/gameserver/handler/ItemHandler.java

@@ -66,6 +66,7 @@ public class ItemHandler
 		registerItemHandler(new SoulShots());
 		registerItemHandler(new SpiritShot());
 		registerItemHandler(new BlessedSpiritShot());
+		registerItemHandler(new BallistaBomb());
 		registerItemHandler(new BeastSoulShot());
 		registerItemHandler(new BeastSpiritShot());
 		registerItemHandler(new Key());

+ 1 - 0
L2_GameServer/java/net/sf/l2j/gameserver/handler/SkillHandler.java

@@ -66,6 +66,7 @@ public class SkillHandler
 		registerSkillHandler(new SummonTreasureKey());
 		registerSkillHandler(new Disablers());
 		registerSkillHandler(new Recall());
+		registerSkillHandler(new BallistaBomb());
 		registerSkillHandler(new TakeCastle());
 		registerSkillHandler(new TakeFort());
 		registerSkillHandler(new Unlock());

+ 19 - 31
L2_GameServer/java/net/sf/l2j/gameserver/handler/admincommandhandlers/AdminFortSiege.java

@@ -17,7 +17,6 @@ package net.sf.l2j.gameserver.handler.admincommandhandlers;
 import java.util.StringTokenizer;
 
 import javolution.text.TextBuilder;
-import net.sf.l2j.gameserver.datatables.ClanTable;
 import net.sf.l2j.gameserver.handler.IAdminCommandHandler;
 import net.sf.l2j.gameserver.instancemanager.FortManager;
 import net.sf.l2j.gameserver.model.L2Clan;
@@ -42,11 +41,8 @@ public class AdminFortSiege implements IAdminCommandHandler
 	{
 		"admin_fortsiege",
 		"admin_add_fortattacker",
-		"admin_add_fortdefender",
-		"admin_add_fortguard",
 		"admin_list_fortsiege_clans",
 		"admin_clear_fortsiege_list",
-		"admin_move_fortdefenders",
 		"admin_spawn_fortdoors",
 		"admin_endfortsiege",
 		"admin_startfortsiege",
@@ -61,14 +57,14 @@ public class AdminFortSiege implements IAdminCommandHandler
 		
 		// Get fort
 		Fort fort = null;
+		int fortId = 0;
 		if (st.hasMoreTokens())
-			fort = FortManager.getInstance().getFort(st.nextToken());
+		{
+			fortId = Integer.valueOf(st.nextToken());
+			fort = FortManager.getInstance().getFortById(fortId);
+		}
 		// Get fort
-		@SuppressWarnings("unused")
-		String val = "";
-		if (st.hasMoreTokens())
-			val = st.nextToken();
-		if ((fort == null || fort.getFortId() < 0))
+		if ((fort == null || fortId == 0))
 			// No fort specified
 			showFortSelectPage(activeChar);
 		else
@@ -83,14 +79,10 @@ public class AdminFortSiege implements IAdminCommandHandler
 				if (player == null)
 					activeChar.sendPacket(new SystemMessage(SystemMessageId.TARGET_IS_INCORRECT));
 				else
-					fort.getSiege().registerAttacker(player, true);
-			}
-			else if (command.equalsIgnoreCase("admin_add_fortdefender"))
-			{
-				if (player == null)
-					activeChar.sendPacket(new SystemMessage(SystemMessageId.TARGET_IS_INCORRECT));
-				else
-					fort.getSiege().registerDefender(player, true);
+				{
+					if (fort.getSiege().checkIfCanRegister(player))
+						fort.getSiege().registerAttacker(player, true);
+				}
 			}
 			else if (command.equalsIgnoreCase("admin_clear_fortsiege_list"))
 			{
@@ -101,11 +93,6 @@ public class AdminFortSiege implements IAdminCommandHandler
 				fort.getSiege().endSiege();
 			}
 			else if (command.equalsIgnoreCase("admin_list_fortsiege_clans"))
-			{
-				fort.getSiege().listRegisterClan(activeChar);
-				return true;
-			}
-			else if (command.equalsIgnoreCase("admin_move_fortdefenders"))
 			{
 				activeChar.sendMessage("Not implemented yet.");
 			}
@@ -114,26 +101,26 @@ public class AdminFortSiege implements IAdminCommandHandler
 				if (player == null || player.getClan() == null)
 					activeChar.sendPacket(new SystemMessage(SystemMessageId.TARGET_IS_INCORRECT));
 				else
-					fort.setOwner(player.getClan());
+					fort.setOwner(player.getClan(), false);
 			}
 			else if (command.equalsIgnoreCase("admin_removefort"))
 			{
-				L2Clan clan = ClanTable.getInstance().getClan(fort.getOwnerId());
+				L2Clan clan = fort.getOwnerClan();
 				if (clan != null)
-					fort.removeOwner(clan);
+					fort.removeOwner(true);
 				else
 					activeChar.sendMessage("Unable to remove fort");
 			}
 			else if (command.equalsIgnoreCase("admin_spawn_fortdoors"))
 			{
-				fort.spawnDoor();
+				fort.resetDoors();
 			}
 			else if (command.equalsIgnoreCase("admin_startfortsiege"))
 			{
 				fort.getSiege().startSiege();
 			}
 			
-			showFortSiegePage(activeChar, fort.getName());
+			showFortSiegePage(activeChar, fort);
 		}
 		return true;
 	}
@@ -149,7 +136,7 @@ public class AdminFortSiege implements IAdminCommandHandler
 			if (fort != null)
 			{
 				String name = fort.getName();
-				cList.append("<td fixwidth=90><a action=\"bypass -h admin_fortsiege " + name + "\">" + name + "</a></td>");
+				cList.append("<td fixwidth=90><a action=\"bypass -h admin_fortsiege " + String.valueOf(fort.getFortId()) + "\">" + name + " id: "+fort.getFortId()+"</a></td>");
 				i++;
 			}
 			if (i > 2)
@@ -162,11 +149,12 @@ public class AdminFortSiege implements IAdminCommandHandler
 		activeChar.sendPacket(adminReply);
 	}
 	
-	private void showFortSiegePage(L2PcInstance activeChar, String fortName)
+	private void showFortSiegePage(L2PcInstance activeChar, Fort fort)
 	{
 		NpcHtmlMessage adminReply = new NpcHtmlMessage(5);
 		adminReply.setFile("data/html/admin/fort.htm");
-		adminReply.replace("%fortName%", fortName);
+		adminReply.replace("%fortName%", fort.getName());
+		adminReply.replace("%fortId%", String.valueOf(fort.getFortId()));
 		activeChar.sendPacket(adminReply);
 	}
 	

+ 92 - 0
L2_GameServer/java/net/sf/l2j/gameserver/handler/itemhandlers/BallistaBomb.java

@@ -0,0 +1,92 @@
+/*
+ * 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 3 of the License, or (at your option) any later
+ * version.
+ * 
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package net.sf.l2j.gameserver.handler.itemhandlers;
+
+import net.sf.l2j.gameserver.datatables.SkillTable;
+import net.sf.l2j.gameserver.handler.IItemHandler;
+import net.sf.l2j.gameserver.model.L2ItemInstance;
+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.L2FortBallistaInstance;
+import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
+import net.sf.l2j.gameserver.model.actor.instance.L2PlayableInstance;
+import net.sf.l2j.gameserver.network.SystemMessageId;
+import net.sf.l2j.gameserver.network.serverpackets.SystemMessage;
+
+/**
+ * Ballista Bombs Handler
+ *
+ * @author Kerberos
+ */
+public class BallistaBomb implements IItemHandler
+{
+	// All the item IDs that this handler knows.
+	private static final int[] ITEM_IDS =
+	{
+		9688
+	};
+	
+	/**
+	 * 
+	 * @see net.sf.l2j.gameserver.handler.IItemHandler#useItem(net.sf.l2j.gameserver.model.actor.instance.L2PlayableInstance, net.sf.l2j.gameserver.model.L2ItemInstance)
+	 */
+	public void useItem(L2PlayableInstance playable, L2ItemInstance item)
+	{
+		if (playable == null)
+			return;
+		
+		L2PcInstance player = null;
+		if (playable instanceof L2Summon)
+		{
+			player = ((L2Summon) playable).getOwner();
+			player.sendPacket(new SystemMessage(SystemMessageId.PET_CANNOT_USE_ITEM));
+			return;
+		}
+		else if (playable instanceof L2PcInstance)
+		{
+			player = (L2PcInstance) playable;
+		}
+		
+		L2Object[] target ={player.getTarget()};
+		if (target[0] == null)
+		{
+			SystemMessage sm;
+			sm = new SystemMessage(SystemMessageId.S1_CANNOT_BE_USED);
+			sm.addSkillName(2342);
+			player.sendPacket(sm);
+		}
+		else if (target[0] instanceof L2FortBallistaInstance)
+		{
+			L2Skill skill = SkillTable.getInstance().getInfo(2342, 1);
+			player.useMagic(skill, false, false);
+		}
+		else
+		{
+			SystemMessage sm;
+			sm = new SystemMessage(SystemMessageId.INCORRECT_TARGET);
+			player.sendPacket(sm);
+		}
+	}
+	
+	/**
+	 * 
+	 * @see net.sf.l2j.gameserver.handler.IItemHandler#getItemIds()
+	 */
+	public int[] getItemIds()
+	{
+		return ITEM_IDS;
+	}
+}

+ 61 - 0
L2_GameServer/java/net/sf/l2j/gameserver/handler/skillhandlers/BallistaBomb.java

@@ -0,0 +1,61 @@
+/*
+ * 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 3 of the License, or (at your option) any later
+ * version.
+ * 
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package net.sf.l2j.gameserver.handler.skillhandlers;
+
+import net.sf.l2j.gameserver.handler.ISkillHandler;
+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.L2FortBallistaInstance;
+import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
+import net.sf.l2j.gameserver.templates.skills.L2SkillType;
+import net.sf.l2j.util.Rnd;
+
+public class BallistaBomb implements ISkillHandler
+{
+	private static final L2SkillType[] SKILL_IDS =
+	{
+		L2SkillType.BALLISTA
+	};
+
+	public void useSkill(L2Character activeChar, L2Skill skill, L2Object[] targets)
+	{
+		if (!(activeChar instanceof L2PcInstance))
+			return;
+
+		L2Object[] targetList = skill.getTargetList(activeChar);
+
+		if (targetList == null)
+		{
+			return;
+		}
+		L2Character target = (L2Character) targetList[0];
+		if (target instanceof L2FortBallistaInstance)
+		{
+			if (Rnd.get(3) == 0)
+			{
+				target.reduceCurrentHp(target.getMaxHp(), activeChar);
+			}
+		}
+	}
+
+	/**
+	 * @see net.sf.l2j.gameserver.handler.ISkillHandler#getSkillIds()
+	 */
+	public L2SkillType[] getSkillIds()
+	{
+		return SKILL_IDS;
+	}
+}

+ 1 - 1
L2_GameServer/java/net/sf/l2j/gameserver/handler/skillhandlers/Disablers.java

@@ -492,7 +492,7 @@ public class Disablers implements ISkillHandler
 					int count = (skill.getMaxNegatedEffects() > 0) ? 0 : -2;
 					for (L2Effect e : effects)
 					{
-						if (e.getSkill().isDebuff() && count < skill.getMaxNegatedEffects())
+						if (e.getSkill().isDebuff() && count < skill.getMaxNegatedEffects() && e.getSkill().getId() != 5660)
 						{
 							//Do not remove raid curse skills
 							if (e.getSkill().getId() != 4215 && e.getSkill().getId() != 4515 && e.getSkill().getId() != 4082)

+ 25 - 12
L2_GameServer/java/net/sf/l2j/gameserver/handler/skillhandlers/TakeFort.java

@@ -21,6 +21,8 @@ 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.model.entity.Fort;
+import net.sf.l2j.gameserver.network.SystemMessageId;
+import net.sf.l2j.gameserver.network.serverpackets.SystemMessage;
 import net.sf.l2j.gameserver.templates.skills.L2SkillType;
 import net.sf.l2j.gameserver.util.Util;
 
@@ -45,12 +47,12 @@ public class TakeFort implements ISkillHandler
 			return;
 		
 		L2PcInstance player = (L2PcInstance) activeChar;
-		
+		L2Object target = player.getTarget();
 		if (player.getClan() == null)
 			return;
 		
 		Fort fort = FortManager.getInstance().getFort(player);
-		if (fort == null || !checkIfOkToCastFlagDisplay(player, fort, true))
+		if (fort == null || !checkIfOkToCastFlagDisplay(player, fort, true, skill, target))
 			return;
 		
 		try
@@ -77,9 +79,9 @@ public class TakeFort implements ISkillHandler
 	 * @param activeChar The L2Character of the character placing the flag
 	 *
 	 */
-	public static boolean checkIfOkToCastFlagDisplay(L2Character activeChar, boolean isCheckOnly)
+	public static boolean checkIfOkToCastFlagDisplay(L2Character activeChar, boolean isCheckOnly, L2Skill skill, L2Object target)
 	{
-		return checkIfOkToCastFlagDisplay(activeChar, FortManager.getInstance().getFort(activeChar), isCheckOnly);
+		return checkIfOkToCastFlagDisplay(activeChar, FortManager.getInstance().getFort(activeChar), isCheckOnly, skill, target);
 	}
 	
 	/**
@@ -89,31 +91,42 @@ public class TakeFort implements ISkillHandler
 	 * @param isCheckOnly
 	 * @return
 	 */
-	public static boolean checkIfOkToCastFlagDisplay(L2Character activeChar, Fort fort, boolean isCheckOnly)
+	public static boolean checkIfOkToCastFlagDisplay(L2Character activeChar, Fort fort, boolean isCheckOnly,L2Skill skill, L2Object target)
 	{
 		if (!(activeChar instanceof L2PcInstance))
 			return false;
 		
-		String text = "";
+		SystemMessage sm;
 		L2PcInstance player = (L2PcInstance) activeChar;
 		
 		if (fort == null || fort.getFortId() <= 0)
-			text = "You must be on fort ground to use this skill";
+		{
+			sm = new SystemMessage(SystemMessageId.S1_CANNOT_BE_USED);
+			sm.addSkillName(skill);
+		}
 		else if (!fort.getSiege().getIsInProgress())
-			text = "You can only use this skill during a siege.";
+		{
+			sm = new SystemMessage(SystemMessageId.S1_CANNOT_BE_USED);
+			sm.addSkillName(skill);
+		}
 		else if (!Util.checkIfInRange(200, player, player.getTarget(), true))
-			text = "You are not in range of the flagpole.";
+		{
+			sm = new SystemMessage(SystemMessageId.DIST_TOO_FAR_CASTING_STOPPED);
+		}
 		else if (fort.getSiege().getAttackerClan(player.getClan()) == null)
-			text = "You must be an attacker to use this skill";
+		{
+			sm = new SystemMessage(SystemMessageId.S1_CANNOT_BE_USED);
+			sm.addSkillName(skill);
+		}
 		else
 		{
 			if (!isCheckOnly)
-				fort.getSiege().announceToPlayer("Clan " + player.getClan().getName() + " has begun to raise flag.", true);
+				fort.getSiege().announceToPlayer(new SystemMessage(SystemMessageId.S1_TRYING_RAISE_FLAG),player.getClan().getName());
 			return true;
 		}
 		
 		if (!isCheckOnly)
-			player.sendMessage(text);
+			player.sendPacket(sm);
 		return false;
 	}
 }

+ 4 - 0
L2_GameServer/java/net/sf/l2j/gameserver/instancemanager/CursedWeaponsManager.java

@@ -36,6 +36,8 @@ import net.sf.l2j.gameserver.model.L2Character;
 import net.sf.l2j.gameserver.model.L2ItemInstance;
 import net.sf.l2j.gameserver.model.actor.instance.L2FeedableBeastInstance;
 import net.sf.l2j.gameserver.model.actor.instance.L2FestivalMonsterInstance;
+import net.sf.l2j.gameserver.model.actor.instance.L2FortCommanderInstance;
+import net.sf.l2j.gameserver.model.actor.instance.L2FortSiegeGuardInstance;
 import net.sf.l2j.gameserver.model.actor.instance.L2GrandBossInstance;
 import net.sf.l2j.gameserver.model.actor.instance.L2GuardInstance;
 import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
@@ -332,6 +334,8 @@ public class CursedWeaponsManager
 			|| attackable instanceof L2GuardInstance
 			|| attackable instanceof L2GrandBossInstance
 			|| attackable instanceof L2FeedableBeastInstance
+			|| attackable instanceof L2FortSiegeGuardInstance
+			|| attackable instanceof L2FortCommanderInstance
 			)return;
 
 		for (CursedWeapon cw : _cursedWeapons.values())

+ 399 - 8
L2_GameServer/java/net/sf/l2j/gameserver/instancemanager/FortManager.java

@@ -14,24 +14,39 @@
  */
 package net.sf.l2j.gameserver.instancemanager;
 
+import java.sql.Connection;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.util.List;
 import java.util.logging.Logger;
 
 import javolution.util.FastList;
+import javolution.util.FastMap;
 import net.sf.l2j.L2DatabaseFactory;
+import net.sf.l2j.gameserver.ThreadPoolManager;
+import net.sf.l2j.gameserver.datatables.NpcTable;
+import net.sf.l2j.gameserver.datatables.SpawnTable;
 import net.sf.l2j.gameserver.model.L2Clan;
 import net.sf.l2j.gameserver.model.L2Object;
+import net.sf.l2j.gameserver.model.L2Spawn;
 import net.sf.l2j.gameserver.model.entity.Fort;
-
+import net.sf.l2j.gameserver.templates.chars.L2NpcTemplate;
 
 public class FortManager
 {
-    protected static final Logger _log = Logger.getLogger(FortManager.class.getName());
-    // =========================================================
-    private static FortManager _instance;
-    public static final FortManager getInstance()
+	protected static final Logger _log = Logger.getLogger(FortManager.class.getName());
+	// =========================================================
+	private static FortManager _instance;
+	protected FastMap<Integer, Integer> _envoyCastles = new FastMap<Integer, Integer>();
+	protected FastMap<Integer, FastList<L2Spawn>> _npcCommanders = new FastMap<Integer, FastList<L2Spawn>>();
+	protected FastMap<Integer, FastList<L2Spawn>> _siegeNpcs = new FastMap<Integer, FastList<L2Spawn>>();
+	protected FastMap<Integer, FastList<L2Spawn>> _specialEnvoys = new FastMap<Integer, FastList<L2Spawn>>();
+	protected FastList<L2Spawn> _npcCommandersSpawns;
+	protected FastList<L2Spawn> _siegeNpcsSpawns;
+	protected FastList<L2Spawn> _specialEnvoysSpawns;
+	protected int _respawnTime;
+
+	public static final FortManager getInstance()
     {
         if (_instance == null)
         {
@@ -44,12 +59,27 @@ public class FortManager
     
     // =========================================================
     // Data Field
+    private Fort _fort;
     private List<Fort> _forts;
     
     // =========================================================
     // Constructor
     public FortManager() {}
-    
+	public FortManager(Fort fort)
+	{
+		_fort = fort;
+		initNpcs(); // load and spawn npcs
+		initSiegeNpcs(); // load suspicious merchants
+		spawnSuspiciousMerchant();// spawn suspicious merchants
+		initNpcCommanders(); // npc Commanders (not monsters)
+		spawnNpcCommanders(); // spawn npc Commanders
+		initSpecialEnvoys(); // envoys from castles
+		if (_fort.getOwnerClan() != null && _fort.getFortState() == 0)
+		{
+			spawnSpecialEnvoys();
+			ThreadPoolManager.getInstance().scheduleGeneral(_fort.new ScheduleSpecialEnvoysDeSpawn(_fort), 1*60*60*1000); // Prepare 1hr task for special envoys despawn
+		}
+	}
     // =========================================================
     // Method - Public
 
@@ -100,6 +130,10 @@ public class FortManager
             statement.close();
 
             _log.info("Loaded: " + getForts().size() + " fortress");
+    		for (Fort fort : getForts())
+    		{
+    			fort.getSiege().getSiegeGuardManager().loadSiegeGuard();
+    		}
         }
         catch (Exception e)
         {
@@ -114,7 +148,10 @@ public class FortManager
                 con.close(); 
             } 
             catch (Exception e) 
-            {}
+            {
+            	_log.warning(""+e.getMessage());
+            	e.printStackTrace();
+            }
         }
     }
     
@@ -134,7 +171,7 @@ public class FortManager
     {
         for (Fort f : getForts())
         {
-            if (f.getOwnerId() == clan.getClanId())
+            if (f.getOwnerClan() == clan)
                 return f;
         }
         return null;
@@ -194,5 +231,359 @@ public class FortManager
         if (_forts == null) _forts = new FastList<Fort>();
         return _forts;
     }
+	public final Fort getFort()
+	{
+		return _fort;
+	}
     
+    private void initNpcs()
+    {
+    	Connection con = null;
+
+    	try
+		{
+			con = L2DatabaseFactory.getInstance().getConnection();
+			PreparedStatement statement = con.prepareStatement("SELECT * FROM fort_spawnlist Where fortId = ? and spawnType = ? ");
+			statement.setInt(1, getFort().getFortId());
+			statement.setInt(2, 0);
+			ResultSet rset = statement.executeQuery();
+			
+			L2Spawn spawnDat;
+			L2NpcTemplate template1;
+			
+			while (rset.next())
+			{
+				template1 = NpcTable.getInstance().getTemplate(rset.getInt("npcId"));
+				if (template1 != null)
+				{
+					spawnDat = new L2Spawn(template1);
+					spawnDat.setAmount(1);
+					spawnDat.setLocx(rset.getInt("x"));
+					spawnDat.setLocy(rset.getInt("y"));
+					spawnDat.setLocz(rset.getInt("z"));
+					spawnDat.setHeading(rset.getInt("heading"));
+					spawnDat.setRespawnDelay(60);
+					SpawnTable.getInstance().addNewSpawn(spawnDat, false);
+					spawnDat.doSpawn();
+					spawnDat.startRespawn();
+				}
+				else
+				{
+					_log.warning("FortManager.initNpcs: Data missing in NPC table for ID: "
+					        + rset.getInt("npcId") + ".");
+				}
+			}
+			
+			rset.close();
+			statement.close();
+		}
+		catch (Exception e)
+		{
+			// problem with initializing spawn, go to next one
+			_log.warning("FortManager.initNpcs: Spawn could not be initialized: "+ e.getMessage());
+			e.printStackTrace();
+		}
+		finally
+		{
+			try
+			{
+				con.close();
+			}
+			catch (Exception e)
+			{
+            	_log.warning(""+e.getMessage());
+            	e.printStackTrace();
+			}
+		}
+    }
+    private void initNpcCommanders()
+    {
+    	Connection con = null;
+    	_npcCommanders.clear();
+    	try
+		{
+			con = L2DatabaseFactory.getInstance().getConnection();
+			PreparedStatement statement1 = con.prepareStatement("SELECT Distinct fortId FROM fort_spawnlist Where spawnType = ? ORDER BY fortId");
+
+			statement1.setInt(1, 1);
+			ResultSet rset1 = statement1.executeQuery();
+
+			while (rset1.next())
+			{
+				int fortId = rset1.getInt("fortId");
+				PreparedStatement statement2 = con.prepareStatement("SELECT id, npcId, x, y, z, heading FROM fort_spawnlist Where fortId = ? and spawnType = ? ORDER BY id");
+				statement2.setInt(1, getFort().getFortId());
+				statement2.setInt(2, 1);
+				ResultSet rset2 = statement2.executeQuery();
+				
+				L2Spawn spawnDat;
+				L2NpcTemplate template1;
+				_npcCommandersSpawns = new FastList<L2Spawn>();
+				while (rset2.next())
+				{
+					template1 = NpcTable.getInstance().getTemplate(rset2.getInt("npcId"));
+					if (template1 != null)
+					{
+						spawnDat = new L2Spawn(template1);
+						spawnDat.setAmount(1);
+						spawnDat.setLocx(rset2.getInt("x"));
+						spawnDat.setLocy(rset2.getInt("y"));
+						spawnDat.setLocz(rset2.getInt("z"));
+						spawnDat.setHeading(rset2.getInt("heading"));
+						spawnDat.setRespawnDelay(60);
+						_npcCommandersSpawns.add(spawnDat);
+					}
+					else
+					{
+						_log.warning("FortManager.initNpcCommanders: Data missing in NPC table for ID: "
+					        + rset2.getInt("npcId") + ".");
+					}
+				}
+				rset2.close();
+				statement2.close();
+				_npcCommanders.put(fortId, _npcCommandersSpawns);
+			}
+			rset1.close();
+			statement1.close();
+		}
+		catch (Exception e)
+		{
+			// problem with initializing spawn, go to next one
+			_log.warning("FortManager.initNpcCommanders: Spawn could not be initialized: "
+			        + e.getMessage());
+			e.printStackTrace();
+		}
+		finally
+		{
+			try
+			{
+				con.close();
+			}
+			catch (Exception e)
+			{
+            	_log.warning(""+e.getMessage());
+            	e.printStackTrace();
+			}
+		}
+    }
+    private void initSiegeNpcs()
+    {
+    	Connection con = null;
+    	_siegeNpcs.clear();
+    	try
+		{
+			con = L2DatabaseFactory.getInstance().getConnection();
+			PreparedStatement statement1 = con.prepareStatement("SELECT Distinct fortId FROM fort_spawnlist Where spawnType = ? ORDER BY fortId");
+
+			statement1.setInt(1, 2);
+			ResultSet rset1 = statement1.executeQuery();
+
+			while (rset1.next())
+			{
+				int fortId = rset1.getInt("fortId");
+				PreparedStatement statement2 = con.prepareStatement("SELECT id, npcId, x, y, z, heading FROM fort_spawnlist Where fortId = ? and spawnType = ? ORDER BY id");
+				statement2.setInt(1, getFort().getFortId());
+				statement2.setInt(2, 2);
+				ResultSet rset2 = statement2.executeQuery();
+				
+				L2Spawn spawnDat;
+				L2NpcTemplate template1;
+				_siegeNpcsSpawns = new FastList<L2Spawn>();
+				while (rset2.next())
+				{
+					template1 = NpcTable.getInstance().getTemplate(rset2.getInt("npcId"));
+					if (template1 != null)
+					{
+						spawnDat = new L2Spawn(template1);
+						spawnDat.setAmount(1);
+						spawnDat.setLocx(rset2.getInt("x"));
+						spawnDat.setLocy(rset2.getInt("y"));
+						spawnDat.setLocz(rset2.getInt("z"));
+						spawnDat.setHeading(rset2.getInt("heading"));
+						spawnDat.setRespawnDelay(60);
+						_siegeNpcsSpawns.add(spawnDat);
+					}
+					else
+					{
+						_log.warning("FortManager.initSiegeNpcs: Data missing in NPC table for ID: "
+					        + rset2.getInt("npcId") + ".");
+					}
+				}
+				rset2.close();
+				statement2.close();
+				_siegeNpcs.put(fortId, _siegeNpcsSpawns);
+			}
+			rset1.close();
+			statement1.close();
+		}
+		catch (Exception e)
+		{
+			// problem with initializing spawn, go to next one
+			_log.warning("FortManager.initSiegeNpcs: Spawn could not be initialized: "
+			        + e.getMessage());
+			e.printStackTrace();
+		}
+		finally
+		{
+			try
+			{
+				con.close();
+			}
+			catch (Exception e)
+			{
+            	_log.warning(""+e.getMessage());
+            	e.printStackTrace();
+			}
+		}
+    }
+    private void initSpecialEnvoys()
+    {
+    	Connection con = null;
+    	_specialEnvoys.clear();
+    	_envoyCastles.clear();
+    	try
+		{
+			con = L2DatabaseFactory.getInstance().getConnection();
+			PreparedStatement statement1 = con.prepareStatement("SELECT Distinct fortId FROM fort_spawnlist Where spawnType = ? ORDER BY fortId");
+
+			statement1.setInt(1, 3);
+			ResultSet rset1 = statement1.executeQuery();
+
+			while (rset1.next())
+			{
+				int fortId = rset1.getInt("fortId");
+				PreparedStatement statement2 = con.prepareStatement("SELECT id, npcId, x, y, z, heading, castleId FROM fort_spawnlist Where fortId = ? and spawnType = ? ORDER BY id");
+				statement2.setInt(1, getFort().getFortId());
+				statement2.setInt(2, 3);
+				ResultSet rset2 = statement2.executeQuery();
+				
+				L2Spawn spawnDat;
+				L2NpcTemplate template1;
+				_specialEnvoysSpawns = new FastList<L2Spawn>();
+				while (rset2.next())
+				{
+					int castleId = rset2.getInt("castleId");
+					int npcId = rset2.getInt("npcId");
+					template1 = NpcTable.getInstance().getTemplate(npcId);
+					if (template1 != null)
+					{
+						spawnDat = new L2Spawn(template1);
+						spawnDat.setAmount(1);
+						spawnDat.setLocx(rset2.getInt("x"));
+						spawnDat.setLocy(rset2.getInt("y"));
+						spawnDat.setLocz(rset2.getInt("z"));
+						spawnDat.setHeading(rset2.getInt("heading"));
+						spawnDat.setRespawnDelay(60);
+						_specialEnvoysSpawns.add(spawnDat);
+						_envoyCastles.put(npcId, castleId);
+					}
+					else
+					{
+						_log.warning("FortManager.initSpecialEnvoys: Data missing in NPC table for ID: "
+					        + rset2.getInt("npcId") + ".");
+					}
+				}
+				rset2.close();
+				statement2.close();
+				_specialEnvoys.put(fortId, _specialEnvoysSpawns);
+			}
+			rset1.close();
+			statement1.close();
+		}
+		catch (Exception e)
+		{
+			// problem with initializing spawn, go to next one
+			_log.warning("FortManager.initSpecialEnvoys: Spawn could not be initialized: "
+			        + e.getMessage());
+			e.printStackTrace();
+		}
+		finally
+		{
+			try
+			{
+				con.close();
+			}
+			catch (Exception e)
+			{
+            	_log.warning(""+e.getMessage());
+            	e.printStackTrace();
+			}
+		}
+    }
+    public void spawnNpcCommanders()
+    {
+    	FastList<L2Spawn> monsterList = _npcCommanders.get(getFort().getFortId());
+    	if (monsterList != null)
+		{
+			for (L2Spawn spawnDat : monsterList)
+			{
+				spawnDat.doSpawn();
+				spawnDat.startRespawn();
+			}
+		}
+    }
+    public void despawnNpcCommanders()
+    {
+    	FastList<L2Spawn> monsterList = _npcCommanders.get(getFort().getFortId());
+    	if (monsterList != null)
+		{
+			for (L2Spawn spawnDat : monsterList)
+			{
+				spawnDat.stopRespawn();
+				spawnDat.getLastSpawn().deleteMe();
+			}
+		}
+    }
+    public void spawnSuspiciousMerchant()
+    {
+    	FastList<L2Spawn> monsterList = _siegeNpcs.get(getFort().getFortId());
+    	if (monsterList != null)
+		{
+			for (L2Spawn spawnDat : monsterList)
+			{
+				spawnDat.doSpawn();
+				spawnDat.startRespawn();
+			}
+		}
+    }
+    public void despawnSuspiciousMerchant()
+    {
+    	FastList<L2Spawn> monsterList = _siegeNpcs.get(getFort().getFortId());
+    	if (monsterList != null)
+		{
+			for (L2Spawn spawnDat : monsterList)
+			{
+				spawnDat.stopRespawn();
+				spawnDat.getLastSpawn().deleteMe();
+			}
+		}
+    }
+    public void spawnSpecialEnvoys()
+    {
+    	FastList<L2Spawn> monsterList = _specialEnvoys.get(getFort().getFortId());
+    	if (monsterList != null)
+		{
+			for (L2Spawn spawnDat : monsterList)
+			{
+				spawnDat.doSpawn();
+				spawnDat.startRespawn();
+			}
+		}
+    }
+	public void despawnSpecialEnvoys()
+	{
+		FastList<L2Spawn> monsterList = _specialEnvoys.get(getFort().getFortId());
+		if (monsterList != null)
+		{
+			for (L2Spawn spawnDat : monsterList)
+			{
+				spawnDat.stopRespawn();
+				spawnDat.getLastSpawn().deleteMe();
+			}
+		}
+	}
+	public int getEnvoyCastle(int npcId)
+	{
+		return _envoyCastles.get(npcId);
+	}
 }

+ 43 - 183
L2_GameServer/java/net/sf/l2j/gameserver/instancemanager/FortSiegeGuardManager.java

@@ -14,139 +14,34 @@
  */
 package net.sf.l2j.gameserver.instancemanager;
 
+import java.sql.Connection;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
-import java.util.List;
-import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import javolution.util.FastList;
+import javolution.util.FastMap;
 import net.sf.l2j.L2DatabaseFactory;
 import net.sf.l2j.gameserver.datatables.NpcTable;
 import net.sf.l2j.gameserver.model.L2Spawn;
-import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
+import net.sf.l2j.gameserver.model.actor.instance.L2FortBallistaInstance;
 import net.sf.l2j.gameserver.model.entity.Fort;
 import net.sf.l2j.gameserver.templates.chars.L2NpcTemplate;
 
 public class FortSiegeGuardManager
 {
 	
-	private static final Logger _log = Logger.getLogger(SiegeGuardManager.class.getName());
+	private static final Logger _log = Logger.getLogger(FortSiegeGuardManager.class.getName());
 	
-	// =========================================================
-	// Data Field
 	private Fort _fort;
-	private List<L2Spawn> _siegeGuardSpawn = new FastList<L2Spawn>();
+	protected FastMap<Integer, FastList<L2Spawn>> _siegeGuards = new FastMap<Integer, FastList<L2Spawn>>();
+	protected FastList<L2Spawn> _siegeGuardsSpawns;
 	
-	// =========================================================
-	// Constructor
 	public FortSiegeGuardManager(Fort fort)
 	{
 		_fort = fort;
 	}
 	
-	// =========================================================
-	// Method - Public
-	/**
-	 * Add guard.<BR><BR>
-	 */
-	public void addSiegeGuard(L2PcInstance activeChar, int npcId)
-	{
-		if (activeChar == null)
-			return;
-		addSiegeGuard(activeChar.getX(), activeChar.getY(), activeChar.getZ(), activeChar.getHeading(), npcId);
-	}
-	
-	/**
-	 * Add guard.<BR><BR>
-	 */
-	public void addSiegeGuard(int x, int y, int z, int heading, int npcId)
-	{
-		saveSiegeGuard(x, y, z, heading, npcId, 0);
-	}
-	
-	/**
-	 * Hire merc.<BR><BR>
-	 */
-	public void hireMerc(L2PcInstance activeChar, int npcId)
-	{
-		if (activeChar == null)
-			return;
-		hireMerc(activeChar.getX(), activeChar.getY(), activeChar.getZ(), activeChar.getHeading(), npcId);
-	}
-	
-	/**
-	 * Hire merc.<BR><BR>
-	 */
-	public void hireMerc(int x, int y, int z, int heading, int npcId)
-	{
-		saveSiegeGuard(x, y, z, heading, npcId, 1);
-	}
-	
-	/**
-	 * Remove a single mercenary, identified by the npcId and location.
-	 * Presumably, this is used when a fort lord picks up a previously dropped ticket
-	 */
-	public void removeMerc(int npcId, int x, int y, int z)
-	{
-		java.sql.Connection con = null;
-		try
-		{
-			con = L2DatabaseFactory.getInstance().getConnection();
-			PreparedStatement statement = con.prepareStatement("Delete From fort_siege_guards Where npcId = ? And x = ? AND y = ? AND z = ? AND isHired = 1");
-			statement.setInt(1, npcId);
-			statement.setInt(2, x);
-			statement.setInt(3, y);
-			statement.setInt(4, z);
-			statement.execute();
-			statement.close();
-		}
-		catch (Exception e1)
-		{
-			_log.warning("Error deleting hired siege guard at " + x + ',' + y + ',' + z + ":" + e1);
-		}
-		finally
-		{
-			try
-			{
-				con.close();
-			}
-			catch (Exception e)
-			{
-			}
-		}
-	}
-	
-	/**
-	 * Remove mercs.<BR><BR>
-	 */
-	public void removeMercs()
-	{
-		java.sql.Connection con = null;
-		try
-		{
-			con = L2DatabaseFactory.getInstance().getConnection();
-			PreparedStatement statement = con.prepareStatement("Delete From fort_siege_guards Where fortId = ? And isHired = 1");
-			statement.setInt(1, getFort().getFortId());
-			statement.execute();
-			statement.close();
-		}
-		catch (Exception e1)
-		{
-			_log.warning("Error deleting hired siege guard for fort " + getFort().getName() + ":" + e1);
-		}
-		finally
-		{
-			try
-			{
-				con.close();
-			}
-			catch (Exception e)
-			{
-			}
-		}
-	}
-	
 	/**
 	 * Spawn guards.<BR><BR>
 	 */
@@ -154,27 +49,23 @@ public class FortSiegeGuardManager
 	{
 		try
 		{
-			int hiredCount = 0;
-			//hiredMax    = MercTicketManager.getInstance().getMaxAllowedMerc(_fort.getFortId());  
-			boolean isHired = (getFort().getOwnerId() > 0) ? true : false;
-			loadSiegeGuard();
-			for (L2Spawn spawn : getSiegeGuardSpawn())
+			FastList<L2Spawn> monsterList = getSiegeGuardSpawn().get(getFort().getFortId());
+			if (monsterList != null)
 			{
-				if (spawn != null)
+				for (L2Spawn spawnDat : monsterList)
 				{
-					spawn.init();
-					if (isHired)
-					{
-						hiredCount++;
-						//if (hiredCount > hiredMax)
-						//    return;
-					}
+					spawnDat.doSpawn();
+					if (spawnDat.getLastSpawn() instanceof L2FortBallistaInstance)
+						spawnDat.stopRespawn();
+					else
+						spawnDat.startRespawn();
 				}
 			}
 		}
 		catch (Exception e)
 		{
-			_log.log(Level.SEVERE, "Error spawning siege guards for fort " + getFort().getName(), e);
+			_log.warning("Error spawning siege guards for fort " + getFort().getName() + ":" + e.getMessage());
+			e.printStackTrace();
 		}
 	}
 	
@@ -183,26 +74,33 @@ public class FortSiegeGuardManager
 	 */
 	public void unspawnSiegeGuard()
 	{
-		for (L2Spawn spawn : getSiegeGuardSpawn())
+		try
 		{
-			if (spawn == null)
-				continue;
+			FastList<L2Spawn> monsterList = getSiegeGuardSpawn().get(getFort().getFortId());
 			
-			spawn.stopRespawn();
-			spawn.getLastSpawn().doDie(spawn.getLastSpawn());
+			if (monsterList != null)
+			{
+				for (L2Spawn spawnDat : monsterList)
+				{
+					spawnDat.stopRespawn();
+					spawnDat.getLastSpawn().doDie(spawnDat.getLastSpawn());
+				}
+			}
+		}
+		catch (Exception e)
+		{
+			_log.warning("Error unspawning siege guards for fort " + getFort().getName() + ":" + e.getMessage());
+			e.printStackTrace();
 		}
-		
-		getSiegeGuardSpawn().clear();
 	}
 	
-	// =========================================================
-	// Method - Private
 	/**
 	 * Load guards.<BR><BR>
 	 */
-	private void loadSiegeGuard()
+	void loadSiegeGuard()
 	{
-		java.sql.Connection con = null;
+		_siegeGuards.clear();
+		Connection con = null;
 		try
 		{
 			con = L2DatabaseFactory.getInstance().getConnection();
@@ -212,9 +110,10 @@ public class FortSiegeGuardManager
 			
 			L2Spawn spawn1;
 			L2NpcTemplate template1;
-			
+			_siegeGuardsSpawns = new FastList<L2Spawn>();
 			while (rs.next())
 			{
+				int fortId = rs.getInt("fortId");
 				template1 = NpcTable.getInstance().getTemplate(rs.getInt("npcId"));
 				if (template1 != null)
 				{
@@ -228,12 +127,13 @@ public class FortSiegeGuardManager
 					spawn1.setRespawnDelay(rs.getInt("respawnDelay"));
 					spawn1.setLocation(0);
 					
-					_siegeGuardSpawn.add(spawn1);
+					_siegeGuardsSpawns.add(spawn1);
 				}
 				else
 				{
 					_log.warning("Missing npc data in npc table for id: " + rs.getInt("npcId"));
 				}
+				_siegeGuards.put(fortId, _siegeGuardsSpawns);
 			}
 			rs.close();
 			statement.close();
@@ -241,6 +141,7 @@ public class FortSiegeGuardManager
 		catch (Exception e1)
 		{
 			_log.warning("Error loading siege guard for fort " + getFort().getName() + ":" + e1);
+			e1.printStackTrace();
 		}
 		finally
 		{
@@ -250,60 +151,19 @@ public class FortSiegeGuardManager
 			}
 			catch (Exception e)
 			{
+				_log.warning("" + e.getMessage());
+				e.printStackTrace();
 			}
 		}
 	}
 	
-	/**
-	 * Save guards.<BR><BR>
-	 */
-	private void saveSiegeGuard(int x, int y, int z, int heading, int npcId, int isHire)
-	{
-		java.sql.Connection con = null;
-		try
-		{
-			con = L2DatabaseFactory.getInstance().getConnection();
-			PreparedStatement statement = con.prepareStatement("Insert Into fort_siege_guards (fortId, npcId, x, y, z, heading, respawnDelay, isHired) Values (?, ?, ?, ?, ?, ?, ?, ?)");
-			statement.setInt(1, getFort().getFortId());
-			statement.setInt(2, npcId);
-			statement.setInt(3, x);
-			statement.setInt(4, y);
-			statement.setInt(5, z);
-			statement.setInt(6, heading);
-			if (isHire == 1)
-				statement.setInt(7, 0);
-			else
-				statement.setInt(7, 600);
-			statement.setInt(8, isHire);
-			statement.execute();
-			statement.close();
-		}
-		catch (Exception e1)
-		{
-			_log.warning("Error adding siege guard for fort " + getFort().getName() + ":" + e1);
-		}
-		finally
-		{
-			try
-			{
-				con.close();
-			}
-			catch (Exception e)
-			{
-			}
-		}
-	}
-	
-	// =========================================================
-	// Proeprty
-	
 	public final Fort getFort()
 	{
 		return _fort;
 	}
 	
-	public final List<L2Spawn> getSiegeGuardSpawn()
+	public final FastMap<Integer, FastList<L2Spawn>> getSiegeGuardSpawn()
 	{
-		return _siegeGuardSpawn;
+		return _siegeGuards;
 	}
 }

+ 50 - 60
L2_GameServer/java/net/sf/l2j/gameserver/instancemanager/FortSiegeManager.java

@@ -38,6 +38,8 @@ import net.sf.l2j.gameserver.model.Location;
 import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
 import net.sf.l2j.gameserver.model.entity.Fort;
 import net.sf.l2j.gameserver.model.entity.FortSiege;
+import net.sf.l2j.gameserver.network.SystemMessageId;
+import net.sf.l2j.gameserver.network.serverpackets.SystemMessage;
 
 public class FortSiegeManager
 {
@@ -59,18 +61,15 @@ public class FortSiegeManager
     // =========================================================
     // Data Field
     private int _attackerMaxClans                              = 500; // Max number of clans
-    private int _attackerRespawnDelay                          = 20000; // Time in ms. Changeable in siege.config
-    private int _defenderMaxClans                              = 500; // Max number of clans
-    private int _defenderRespawnDelay                          = 10000; // Time in ms. Changeable in siege.config
 
     // Fort Siege settings
     private FastMap<Integer,FastList<SiegeSpawn>>  _commanderSpawnList;
     private FastMap<Integer,FastList<CombatFlag>>  _flagList;
-
-    private int _controlTowerLosePenalty                         = 20000; // Time in ms. Changeable in siege.config
-    private int _flagMaxCount                                   = 1; // Changeable in siege.config
-    private int _siegeClanMinLevel                             = 4; // Changeable in siege.config
-    private int _siegeLength                                    = 120; // Time in minute. Changeable in siege.config
+    private int _flagMaxCount                                   = 1; // Changeable in fortsiege.properties
+    private int _siegeClanMinLevel                              = 4; // Changeable in fortsiege.properties
+    private int _siegeLength                                    = 60; // Time in minute. Changeable in fortsiege.properties
+    private int _countDownLength                                = 10; // Time in minute. Changeable in fortsiege.properties
+	private int _suspiciousMerchantRespawnDelay                 = 180; // Time in minute. Changeable in fortsiege.properties
     private List<FortSiege> _sieges;
 
     // =========================================================
@@ -147,7 +146,14 @@ public class FortSiegeManager
         }
         finally
         {
-            try { con.close(); } catch (Exception e) {}
+            try {
+            	con.close(); 
+            }
+            catch (Exception e) 
+            {
+            	_log.warning(""+e.getMessage());
+            	e.printStackTrace();
+            }
         }
         return register;
     }
@@ -170,13 +176,11 @@ public class FortSiegeManager
             
             // Siege setting
             _attackerMaxClans = Integer.decode(siegeSettings.getProperty("AttackerMaxClans", "500"));
-            _attackerRespawnDelay = Integer.decode(siegeSettings.getProperty("AttackerRespawn", "30000"));
-            _controlTowerLosePenalty = Integer.decode(siegeSettings.getProperty("CTLossPenalty", "20000"));
-            _defenderMaxClans = Integer.decode(siegeSettings.getProperty("DefenderMaxClans", "500"));
-            _defenderRespawnDelay = Integer.decode(siegeSettings.getProperty("DefenderRespawn", "20000"));
             _flagMaxCount = Integer.decode(siegeSettings.getProperty("MaxFlags", "1"));
             _siegeClanMinLevel = Integer.decode(siegeSettings.getProperty("SiegeClanMinLevel", "4"));
-            _siegeLength = Integer.decode(siegeSettings.getProperty("SiegeLength", "120"));
+            _siegeLength = Integer.decode(siegeSettings.getProperty("SiegeLength", "60"));
+            _countDownLength = Integer.decode(siegeSettings.getProperty("CountDownLength", "10"));
+            _suspiciousMerchantRespawnDelay = Integer.decode(siegeSettings.getProperty("SuspiciousMerchantRespawnDelay", "180"));
 
             // Siege spawns settings
             _commanderSpawnList = new FastMap<Integer,FastList<SiegeSpawn>>();
@@ -184,15 +188,12 @@ public class FortSiegeManager
 
             for (Fort fort: FortManager.getInstance().getForts())
             {
-                FastList<SiegeSpawn> _commanderSpawns = new FastList<SiegeSpawn>();
+            	FastList<SiegeSpawn> _commanderSpawns = new FastList<SiegeSpawn>();
                 FastList<CombatFlag> _flagSpawns = new FastList<CombatFlag>();
-
                 for (int i=1; i<5; i++)
                 {
                     String _spawnParams = siegeSettings.getProperty(fort.getName() + "Commander" + Integer.toString(i), "");
-
                     if (_spawnParams.length() == 0) break;
-
                     StringTokenizer st = new StringTokenizer(_spawnParams.trim(), ",");
 
                     try
@@ -203,7 +204,7 @@ public class FortSiegeManager
                         int heading = Integer.parseInt(st.nextToken());
                         int npc_id = Integer.parseInt(st.nextToken());
 
-                        _commanderSpawns.add(new SiegeSpawn(fort.getFortId(),x,y,z,heading,npc_id));
+                        _commanderSpawns.add(new SiegeSpawn(fort.getFortId(),x,y,z,heading,npc_id,i));
                     }
                     catch (Exception e)
                     {
@@ -216,9 +217,7 @@ public class FortSiegeManager
                 for (int i=1; i<4; i++)
                 {
                     String _spawnParams = siegeSettings.getProperty(fort.getName() + "Flag" + Integer.toString(i), "");
-
                     if (_spawnParams.length() == 0) break;
-
                     StringTokenizer st = new StringTokenizer(_spawnParams.trim(), ",");
 
                     try
@@ -235,15 +234,14 @@ public class FortSiegeManager
                         _log.warning("Error while loading flag(s) for "+fort.getName()+" fort.");
                     }
                 }
-                _flagList.put(fort.getFortId(), _flagSpawns);
-                
+                _flagList.put(fort.getFortId(), _flagSpawns); 
             }
 
         }
         catch (Exception e)
         {
             //_initialized = false;
-            System.err.println("Error while loading fortsiege data.");
+            _log.warning("Error while loading fortsiege data."+e.getMessage());
             e.printStackTrace();
         }
         finally
@@ -254,6 +252,8 @@ public class FortSiegeManager
         	}
         	catch (Exception e)
         	{
+        		_log.warning(""+e.getMessage());
+        		e.printStackTrace();
         	}
         }
     }
@@ -263,9 +263,13 @@ public class FortSiegeManager
     public final FastList<SiegeSpawn> getCommanderSpawnList(int _fortId)
     {
         if (_commanderSpawnList.containsKey(_fortId))
+        {
             return _commanderSpawnList.get(_fortId);
+        }
         else
+        {
             return null;
+        }
     }
 
     public final FastList<CombatFlag> getFlagList(int _fortId)
@@ -278,16 +282,10 @@ public class FortSiegeManager
     
     public final int getAttackerMaxClans() { return _attackerMaxClans; }
 
-    public final int getAttackerRespawnDelay() { return _attackerRespawnDelay; }
-
-    public final int getControlTowerLosePenalty() { return _controlTowerLosePenalty; }
-
-    public final int getDefenderMaxClans() { return _defenderMaxClans; }
-
-    public final int getDefenderRespawnDelay() { return (_defenderRespawnDelay); }
-
     public final int getFlagMaxCount() { return _flagMaxCount; }
 
+    public final int getSuspiciousMerchantRespawnDelay() { return _suspiciousMerchantRespawnDelay; }
+    
     public final FortSiege getSiege(L2Object activeObject) { return getSiege(activeObject.getX(), activeObject.getY(), activeObject.getZ()); }
 
     public final FortSiege getSiege(int x, int y, int z)
@@ -301,6 +299,8 @@ public class FortSiegeManager
 
     public final int getSiegeLength() { return _siegeLength; }
 
+    public final int getCountDownLength() { return _countDownLength; }
+
     public final List<FortSiege> getSieges()
     {
         if (_sieges == null) 
@@ -320,10 +320,10 @@ public class FortSiegeManager
         return ( itemId == 9819);
     }
     
-    public void activateCombatFlag(L2PcInstance player, L2ItemInstance item)
+    public boolean activateCombatFlag(L2PcInstance player, L2ItemInstance item)
     {
         if (!checkIfCanPickup(player))
-            return;
+            return false;
         
         Fort fort = FortManager.getInstance().getFort(player);
         
@@ -335,14 +335,18 @@ public class FortSiegeManager
                 cf.activate(player, item);
             }
         }
+        return true;
     }
     
     public boolean checkIfCanPickup(L2PcInstance player)
     {
+    	SystemMessage sm;
+    	sm = new SystemMessage(SystemMessageId.THE_FORTRESS_BATTLE_OF_S1_HAS_FINISHED);
+    	sm.addItemName(9819);
         // Cannot own 2 combat flag
         if (player.isCombatFlagEquipped()) 
         {
-            player.sendMessage("You already have the combat flag");
+        	player.sendPacket(sm);
             return false;
         }
        
@@ -352,43 +356,37 @@ public class FortSiegeManager
         
         if (fort == null || fort.getFortId() <= 0)
         {
-            player.sendMessage("You must be on fort ground to pickup Combat Flag");
+        	player.sendPacket(sm);
             return false;
         }
         else if (!fort.getSiege().getIsInProgress())
         {
-            player.sendMessage("You can only pickup Combat Flag during a siege.");
+        	player.sendPacket(sm);
             return false;
         }
         else if (fort.getSiege().getAttackerClan(player.getClan()) == null)
         {
-            player.sendMessage("You must be an attacker to pickup Combat Flag");
+        	player.sendPacket(sm);
             return false;
         }
-      
         return true;
     }
     
     public void dropCombatFlag(L2PcInstance player)
     {
-        System.out.println("Player obj " + player.getObjectId());
         Fort fort = FortManager.getInstance().getFort(player);
-        System.out.println("Fort " + fort.getName());
-        
-        
+
         FastList<CombatFlag> fcf =  _flagList.get(fort.getFortId());
-        System.out.println("fast list size " + fcf.size());
 
         for ( CombatFlag cf : fcf)
         {
             if ( cf.playerId == player.getObjectId())
             {
-                System.out.println("found cf ");
                 cf.dropIt();
-                cf.spawnMe();
+                if (fort.getSiege().getIsInProgress())
+                	cf.spawnMe();
             }
         }
-        
     }
     
     public class  SiegeSpawn
@@ -397,23 +395,15 @@ public class FortSiegeManager
         private int _npcId;
         private int _heading;
         private int _fortId;
-        private int _hp;
-
-        public SiegeSpawn(int fort_id, int x, int y, int z, int heading, int npc_id)
-        {
-            _fortId = fort_id;
-            _location = new Location(x,y,z,heading);
-            _heading = heading;
-            _npcId = npc_id;
-        }
+        private int _id;
 
-        public SiegeSpawn(int fort_id, int x, int y, int z, int heading, int npc_id, int hp)
+        public SiegeSpawn(int fort_id, int x, int y, int z, int heading, int npc_id, int id)
         {
             _fortId = fort_id;
             _location = new Location(x,y,z,heading);
             _heading = heading;
             _npcId = npc_id;
-            _hp = hp;
+            _id = id;
         }
 
         public int getFortId()
@@ -431,9 +421,9 @@ public class FortSiegeManager
             return _heading;
         }
 
-        public int getHp()
+        public int getId()
         {
-            return _hp;
+            return _id;
         }
 
         public Location getLocation()

+ 1 - 1
L2_GameServer/java/net/sf/l2j/gameserver/model/CharEffectList.java

@@ -260,7 +260,7 @@ public class CharEffectList
 		// Exit them
 		for (L2Effect e : effects)
 		{
-			if (e != null)
+			if (e != null && e.getSkill().getId() != 5660)
 			{
 				e.exit(true);
 			}

+ 7 - 32
L2_GameServer/java/net/sf/l2j/gameserver/model/CombatFlag.java

@@ -16,7 +16,6 @@ package net.sf.l2j.gameserver.model;
 
 import net.sf.l2j.Config;
 import net.sf.l2j.gameserver.datatables.ItemTable;
-import net.sf.l2j.gameserver.datatables.SkillTable;
 import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
 import net.sf.l2j.gameserver.network.SystemMessageId;
 import net.sf.l2j.gameserver.network.serverpackets.InventoryUpdate;
@@ -73,18 +72,12 @@ public class CombatFlag
         }
     }
     
-    public void activate(L2PcInstance player, L2ItemInstance item)
+    public boolean activate(L2PcInstance player, L2ItemInstance item)
     {
-        // if the player is mounted, attempt to unmount first.  Only allow picking up 
-        // the comabt flag if unmounting is successful.
         if (player.isMounted())
         {
-            if (!player.dismount())
-            {
-                // TODO: correct this custom message.
-                player.sendMessage("You may not pick up this item while riding in this territory");
-                return;
-            }
+        	player.sendPacket(new SystemMessage(SystemMessageId.CANNOT_EQUIP_ITEM_DUE_TO_BAD_CONDITION));
+        	return false;
         }
 
         // Player holding it data
@@ -92,9 +85,6 @@ public class CombatFlag
         playerId = _player.getObjectId();
         itemInstance = null;
 
-        // Add skill
-        giveSkill();
-
         // Equip with the weapon
         _item = item;
         _player.getInventory().equipItemAndRecord(_item);
@@ -114,34 +104,19 @@ public class CombatFlag
         // Refresh player stats
         _player.broadcastUserInfo();
         _player.setCombatFlagEquipped(true);
-
+        return true;
     }
 
     public void dropIt()
     {
         // Reset player stats
         _player.setCombatFlagEquipped(false);
-        removeSkill();
-        _player.destroyItem("DieDrop", _item, null, false);
+        int slot = _player.getInventory().getSlotFromItem(_item);
+        _player.getInventory().unEquipItemInBodySlotAndRecord(slot);
+        _player.destroyItem("CombatFlag", _item, null, true);
         _item = null;
         _player.broadcastUserInfo();
         _player = null;
         playerId = 0;
     }
-    
-    public void giveSkill()
-    {
-        _player.addSkill(SkillTable.getInstance().getInfo(3318, 1), false);
-        _player.addSkill(SkillTable.getInstance().getInfo(3358, 1), false);
-        _player.sendSkillList();
-    }
-
-    public void removeSkill()
-    {
-        _player.removeSkill(SkillTable.getInstance().getInfo(3318, 1), false);
-        _player.removeSkill(SkillTable.getInstance().getInfo(3358, 1), false);
-        _player.sendSkillList();
-    }
-    
-    
 }

+ 6 - 0
L2_GameServer/java/net/sf/l2j/gameserver/model/L2Attackable.java

@@ -26,6 +26,7 @@ import net.sf.l2j.gameserver.ThreadPoolManager;
 import net.sf.l2j.gameserver.ai.CtrlIntention;
 import net.sf.l2j.gameserver.ai.L2AttackableAI;
 import net.sf.l2j.gameserver.ai.L2CharacterAI;
+import net.sf.l2j.gameserver.ai.L2FortSiegeGuardAI;
 import net.sf.l2j.gameserver.ai.L2SiegeGuardAI;
 import net.sf.l2j.gameserver.datatables.EventDroplist;
 import net.sf.l2j.gameserver.datatables.ItemTable;
@@ -34,6 +35,7 @@ import net.sf.l2j.gameserver.datatables.EventDroplist.DateDrop;
 import net.sf.l2j.gameserver.instancemanager.CursedWeaponsManager;
 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.L2FortSiegeGuardInstance;
 import net.sf.l2j.gameserver.model.actor.instance.L2GrandBossInstance;
 import net.sf.l2j.gameserver.model.actor.instance.L2MinionInstance;
 import net.sf.l2j.gameserver.model.actor.instance.L2MonsterInstance;
@@ -2163,10 +2165,14 @@ public class L2Attackable extends L2NpcInstance
 
         // check the region where this mob is, do not activate the AI if region is inactive.
         if (!isInActiveRegion())
+        {
             if (this instanceof L2SiegeGuardInstance)
                 ((L2SiegeGuardAI) getAI()).stopAITask();
+            else if (this instanceof L2FortSiegeGuardInstance)
+            	((L2FortSiegeGuardAI) getAI()).stopAITask();
             else
                 ((L2AttackableAI) getAI()).stopAITask();
+        }
     }
 
     /**

+ 11 - 2
L2_GameServer/java/net/sf/l2j/gameserver/model/L2Character.java

@@ -46,12 +46,13 @@ import net.sf.l2j.gameserver.instancemanager.TownManager;
 import net.sf.l2j.gameserver.model.L2Skill.SkillTargetType;
 import net.sf.l2j.gameserver.model.actor.instance.L2ArtefactInstance;
 import net.sf.l2j.gameserver.model.actor.instance.L2BoatInstance;
-import net.sf.l2j.gameserver.model.actor.instance.L2CommanderInstance;
 import net.sf.l2j.gameserver.model.actor.instance.L2ControlTowerInstance;
 import net.sf.l2j.gameserver.model.actor.instance.L2DecoyInstance;
 import net.sf.l2j.gameserver.model.actor.instance.L2DoorInstance;
 import net.sf.l2j.gameserver.model.actor.instance.L2EffectPointInstance;
 import net.sf.l2j.gameserver.model.actor.instance.L2FolkInstance;
+import net.sf.l2j.gameserver.model.actor.instance.L2FortCommanderInstance;
+import net.sf.l2j.gameserver.model.actor.instance.L2FortSiegeGuardInstance;
 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;
@@ -351,7 +352,8 @@ public abstract class L2Character extends L2Object
 			!(this instanceof L2DecoyInstance) && !(this instanceof L2SiegeSummonInstance) &&
 			!(this instanceof L2PetInstance) && !(this instanceof L2SummonInstance) &&
 			!(this instanceof L2SiegeFlagInstance) && !(this instanceof L2EffectPointInstance) &&
-			!(this instanceof L2CommanderInstance) && !(this instanceof L2FolkInstance))
+			!(this instanceof L2FortCommanderInstance) && !(this instanceof L2FolkInstance) &&
+			!(this instanceof L2FortSiegeGuardInstance))
 			setIsInvul(true);
 	}
 
@@ -693,6 +695,13 @@ public abstract class L2Character extends L2Object
 				sendPacket(ActionFailed.STATIC_PACKET);
 				return;
 			}
+			// TODO: unhardcode this to support boolean if with that weapon u can attack or not (for ex transform weapons)
+			if (((L2PcInstance)this).getActiveWeaponItem() != null && ((L2PcInstance)this).getActiveWeaponItem().getItemId() == 9819)
+			{
+	            sendPacket(new SystemMessage(SystemMessageId.THAT_WEAPON_CANT_ATTACK));
+	            sendPacket(ActionFailed.STATIC_PACKET);
+	            return;
+			}
 
 		}
 		else if (isInsidePeaceZone(this, target))

+ 11 - 0
L2_GameServer/java/net/sf/l2j/gameserver/model/L2Skill.java

@@ -376,6 +376,8 @@ public abstract class L2Skill
 
     private final boolean _isDebuff;
 
+	private boolean _isAdvancedFlag;
+
     protected L2Skill(StatsSet set)
     {
         _id = set.getInteger("skill_id");
@@ -406,6 +408,7 @@ public abstract class L2Skill
         
         _isCubic    = set.getBool("isCubic", false);
 
+         _isAdvancedFlag = set.getBool("isAdvancedFlag", false);
         _activationtime= set.getInteger("activationtime", 8);
         _activationchance= set.getInteger("activationchance", 30);
         
@@ -3103,4 +3106,12 @@ public abstract class L2Skill
     {
         return "" + _name + "[id=" + _id + ",lvl=" + _level + "]";
     }
+
+	/**
+	 * @return
+	 */
+	public boolean isAdvancedFlag()
+	{
+		return _isAdvancedFlag;
+	}
 }

+ 4 - 0
L2_GameServer/java/net/sf/l2j/gameserver/model/L2Transformation.java

@@ -88,6 +88,8 @@ public abstract class L2Transformation implements Cloneable, Runnable
      */
     public double getCollisionRadius()
     {
+    	if (getId()>=312 && getId()<=318)
+    		return _player.getTemplate().collisionRadius;
         return _collisionRadius;
     }
 
@@ -96,6 +98,8 @@ public abstract class L2Transformation implements Cloneable, Runnable
      */
     public double getCollisionHeight()
     {
+    	if (getId()>=312 && getId()<=318)
+    		return _player.getTemplate().collisionHeight;
         return _collisionHeight;
     }
 

+ 99 - 20
L2_GameServer/java/net/sf/l2j/gameserver/model/actor/instance/L2DoorInstance.java

@@ -17,6 +17,7 @@ package net.sf.l2j.gameserver.model.actor.instance;
 import java.util.Collection;
 import java.util.concurrent.ScheduledFuture;
 import java.util.logging.Level;
+import java.util.logging.Logger;
 
 import javolution.text.TextBuilder;
 import javolution.util.FastList;
@@ -29,6 +30,7 @@ import net.sf.l2j.gameserver.instancemanager.CastleManager;
 import net.sf.l2j.gameserver.instancemanager.FortManager;
 import net.sf.l2j.gameserver.model.L2CharPosition;
 import net.sf.l2j.gameserver.model.L2Character;
+import net.sf.l2j.gameserver.model.L2Clan;
 import net.sf.l2j.gameserver.model.L2ItemInstance;
 import net.sf.l2j.gameserver.model.L2Object;
 import net.sf.l2j.gameserver.model.L2Skill;
@@ -39,12 +41,14 @@ import net.sf.l2j.gameserver.model.entity.Castle;
 import net.sf.l2j.gameserver.model.entity.ClanHall;
 import net.sf.l2j.gameserver.model.entity.Fort;
 import net.sf.l2j.gameserver.network.L2GameClient;
+import net.sf.l2j.gameserver.network.SystemMessageId;
 import net.sf.l2j.gameserver.network.serverpackets.ActionFailed;
 import net.sf.l2j.gameserver.network.serverpackets.ConfirmDlg;
 import net.sf.l2j.gameserver.network.serverpackets.DoorStatusUpdate;
 import net.sf.l2j.gameserver.network.serverpackets.MyTargetSelected;
 import net.sf.l2j.gameserver.network.serverpackets.NpcHtmlMessage;
 import net.sf.l2j.gameserver.network.serverpackets.StaticObject;
+import net.sf.l2j.gameserver.network.serverpackets.SystemMessage;
 import net.sf.l2j.gameserver.network.serverpackets.ValidateLocation;
 import net.sf.l2j.gameserver.templates.chars.L2CharTemplate;
 import net.sf.l2j.gameserver.templates.item.L2Weapon;
@@ -56,7 +60,7 @@ import net.sf.l2j.gameserver.templates.item.L2Weapon;
  */
 public class L2DoorInstance extends L2Character
 {
-	//protected static final Logger _log = Logger.getLogger(L2DoorInstance.class.getName());
+	protected static final Logger log = Logger.getLogger(L2DoorInstance.class.getName());
 	
 	/** The castle index in the array of L2Castle this L2NpcInstance belongs to */
 	private int _castleIndex = -2;
@@ -81,6 +85,7 @@ public class L2DoorInstance extends L2Character
 	protected final int _doorId;
 	protected final String _name;
 	private boolean _open;
+	private boolean _isCommanderDoor;
 	private boolean _unlockable;
 	
 	private ClanHall _clanHall;
@@ -262,6 +267,23 @@ public class L2DoorInstance extends L2Character
 		_open = open;
 	}
 	
+	/**
+	 * @param val Used for Fortresses to determine if doors can be attacked during siege or not
+	 */
+	public void setIsCommanderDoor(boolean val)
+	{
+		_isCommanderDoor = val;
+	}
+	
+	/**
+	 * @return Doors that cannot be attacked during siege
+	 * these doors will be auto opened if u take control of all commanders buildings
+	 */
+	public boolean getIsCommanderDoor()
+	{
+		return _isCommanderDoor;
+	}
+	
 	/**
 	 * Sets the delay in milliseconds for automatic opening/closing
 	 * of this door instance.
@@ -331,7 +353,7 @@ public class L2DoorInstance extends L2Character
 	{
 		if (getCastle() != null && getCastle().getCastleId() > 0 && getCastle().getSiege().getIsInProgress())
 			return true;
-		if (getFort() != null && getFort().getFortId() > 0 && getFort().getSiege().getIsInProgress())
+		if (getFort() != null && getFort().getFortId() > 0 && getFort().getSiege().getIsInProgress() && !getIsCommanderDoor())
 			return true;
 		return false;
 	}
@@ -343,14 +365,43 @@ public class L2DoorInstance extends L2Character
 			return true;
 		
 		// Doors can`t be attacked by NPCs
-		if (!(attacker instanceof L2PcInstance))
+		if (!(attacker instanceof L2PlayableInstance))
 			return false;
 		
-		// Attackable  only during siege by everyone
+		// Attackable  only during siege by everyone (not owner)
 		boolean isCastle = (getCastle() != null && getCastle().getCastleId() > 0 && getCastle().getSiege().getIsInProgress());
+        boolean isFort = (getFort() != null && getFort().getFortId() > 0 && getFort().getSiege().getIsInProgress() && !getIsCommanderDoor());
 		
-		boolean isFort = (getFort() != null && getFort().getFortId() > 0 && getFort().getSiege().getIsInProgress());
-		
+		if (isFort)
+		{
+			if (attacker instanceof L2SummonInstance)
+			{
+				L2Clan clan = ((L2SummonInstance)attacker).getOwner().getClan();
+				if (clan != null && clan == getFort().getOwnerClan())
+					return false;
+			}
+			else if (attacker instanceof L2PcInstance)
+			{
+				L2Clan clan = ((L2PcInstance)attacker).getClan();
+				if (clan != null && clan == getFort().getOwnerClan())
+					return false;
+			}
+		}
+		else if (isCastle)
+		{
+			if (attacker instanceof L2SummonInstance)
+			{
+				L2Clan clan = ((L2SummonInstance)attacker).getOwner().getClan();
+				if (clan != null && clan.getClanId() == getCastle().getOwnerId())
+					return false;
+			}
+			else if (attacker instanceof L2PcInstance)
+			{
+				L2Clan clan = ((L2PcInstance)attacker).getClan();
+				if (clan != null && clan.getClanId() == getCastle().getOwnerId())
+					return false;
+			}
+		}
 		return (isCastle || isFort);
 	}
 	
@@ -434,7 +485,7 @@ public class L2DoorInstance extends L2Character
 			
 			// send HP amount if doors are inside castle/fortress zone
 			// TODO: needed to be added here doors from conquerable clanhalls
-			if (getCastle() != null && getCastle().getCastleId() > 0 || getFort() != null && getFort().getFortId() > 0)
+			if ((getCastle() != null && getCastle().getCastleId() > 0) || (getFort() != null && getFort().getFortId() > 0 && !getIsCommanderDoor()))
 				su = new StaticObject(this, true);
 			player.sendPacket(su);
 			
@@ -468,11 +519,10 @@ public class L2DoorInstance extends L2Character
 					else
 					{
 						player.sendPacket(new ConfirmDlg(1141));
-						;
 					}
 				}
 			}
-			else if (player.getClan() != null && getFort() != null && player.getClanId() == getFort().getOwnerId() && isUnlockable())
+			else if (player.getClan() != null && getFort() != null && player.getClan() == getFort().getOwnerClan() && isUnlockable() && !getFort().getSiege().getIsInProgress())
 			{
 				if (!isInsideRadius(player, L2NpcInstance.INTERACTION_DISTANCE, false, false))
 				{
@@ -488,7 +538,6 @@ public class L2DoorInstance extends L2Character
 					else
 					{
 						player.sendPacket(new ConfirmDlg(1141));
-						;
 					}
 				}
 			}
@@ -514,7 +563,7 @@ public class L2DoorInstance extends L2Character
 			
 			// send HP amount if doors are inside castle/fortress zone
 			// TODO: needed to be added here doors from conquerable clanhalls
-			if (getCastle() != null && getCastle().getCastleId() > 0 || getFort() != null && getFort().getFortId() > 0)
+			if ((getCastle() != null && getCastle().getCastleId() > 0) || (getFort() != null && getFort().getFortId() > 0 && !getIsCommanderDoor()))
 				su = new StaticObject(this, true);
 			
 			player.sendPacket(su);
@@ -524,14 +573,14 @@ public class L2DoorInstance extends L2Character
 			html1.append("<tr><td>S.Y.L. Says:</td></tr>");
 			html1.append("<tr><td>Current HP  " + getCurrentHp() + "</td></tr>");
 			html1.append("<tr><td>Max HP      " + getMaxHp() + "</td></tr>");
-			html1.append("<tr><td>Max X      " + getXMax() + "</td></tr>");
-			html1.append("<tr><td>Max Y      " + getYMax() + "</td></tr>");
-			html1.append("<tr><td>Max Z      " + getZMax() + "</td></tr>");
-			html1.append("<tr><td>Min X      " + getXMin() + "</td></tr>");
-			html1.append("<tr><td>Min Y      " + getYMin() + "</td></tr>");
-			html1.append("<tr><td>Min Z      " + getZMin() + "</td></tr>");
-			html1.append("<tr><td>Object ID: " + getObjectId() + "</td></tr>");
-			html1.append("<tr><td>Door ID:<br>" + getDoorId() + "</td></tr>");
+			html1.append("<tr><td>Max X       " + getXMax() + "</td></tr>");
+			html1.append("<tr><td>Max Y       " + getYMax() + "</td></tr>");
+			html1.append("<tr><td>Max Z       " + getZMax() + "</td></tr>");
+			html1.append("<tr><td>Min X       " + getXMin() + "</td></tr>");
+			html1.append("<tr><td>Min Y       " + getYMin() + "</td></tr>");
+			html1.append("<tr><td>Min Z       " + getZMin() + "</td></tr>");
+			html1.append("<tr><td>Object ID:  " + getObjectId() + "</td></tr>");
+			html1.append("<tr><td>Door ID: <br>" + getDoorId() + "</td></tr>");
 			html1.append("<tr><td><br></td></tr>");
 			
 			html1.append("<tr><td>Class: " + getClass().getName() + "</td></tr>");
@@ -570,7 +619,7 @@ public class L2DoorInstance extends L2Character
 		{
 			for (L2PcInstance player : knownPlayers)
 			{
-				if (getCastle() != null && getCastle().getCastleId() > 0 || getFort() != null && getFort().getFortId() > 0)
+				if ((getCastle() != null && getCastle().getCastleId() > 0) || (getFort() != null && getFort().getFortId() > 0 && !getIsCommanderDoor()))
 					su = new StaticObject(this, true);
 				
 				player.sendPacket(su);
@@ -684,6 +733,22 @@ public class L2DoorInstance extends L2Character
 		return result;
 	}
 	
+	public Collection<L2FortSiegeGuardInstance> getKnownFortSiegeGuards()
+	{
+		FastList<L2FortSiegeGuardInstance> result = new FastList<L2FortSiegeGuardInstance>();
+		
+		Collection<L2Object> objs = getKnownList().getKnownObjects().values();
+		//synchronized (getKnownList().getKnownObjects())
+		{
+			for (L2Object obj : objs)
+			{
+				if (obj instanceof L2FortSiegeGuardInstance)
+					result.add((L2FortSiegeGuardInstance) obj);
+			}
+		}
+		return result;
+	}
+	
 	public int getA()
 	{
 		return _A;
@@ -703,4 +768,18 @@ public class L2DoorInstance extends L2Character
 	{
 		return _D;
 	}
+	
+	@Override
+	public boolean doDie(L2Character killer) 
+	{
+		if (!super.doDie(killer))
+			return false;
+		
+		boolean isFort = (getFort() != null && getFort().getFortId() > 0 && getFort().getSiege().getIsInProgress()) && !getIsCommanderDoor();
+		boolean isCastle = (getCastle() != null	&& getCastle().getCastleId() > 0 && getCastle().getSiege().getIsInProgress());
+		
+		if (isFort || isCastle)
+			broadcastPacket(new SystemMessage(SystemMessageId.CASTLE_GATE_BROKEN_DOWN));
+		return true;
+	}
 }

+ 1 - 1
L2_GameServer/java/net/sf/l2j/gameserver/model/actor/instance/L2DoormenInstance.java

@@ -267,7 +267,7 @@ public class L2DoormenInstance extends L2FolkInstance
             
             if (getFort() != null && getFort().getFortId() > 0)
             {
-            	if (getFort().getOwnerId() == player.getClanId()) // Clan owns fortress
+            	if (getFort().getOwnerClan()!= null && getFort().getOwnerClan().getClanId()== player.getClanId()) // Clan owns fortress
             		return COND_FORT_OWNER; // Owner
             }
         }

+ 109 - 0
L2_GameServer/java/net/sf/l2j/gameserver/model/actor/instance/L2FortBallistaInstance.java

@@ -0,0 +1,109 @@
+/*
+ * 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 3 of the License, or (at your option) any later
+ * version.
+ * 
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package net.sf.l2j.gameserver.model.actor.instance;
+
+import net.sf.l2j.gameserver.ai.CtrlIntention;
+import net.sf.l2j.gameserver.model.L2Character;
+import net.sf.l2j.gameserver.network.SystemMessageId;
+import net.sf.l2j.gameserver.network.serverpackets.ActionFailed;
+import net.sf.l2j.gameserver.network.serverpackets.MyTargetSelected;
+import net.sf.l2j.gameserver.network.serverpackets.PledgeShowInfoUpdate;
+import net.sf.l2j.gameserver.network.serverpackets.SystemMessage;
+import net.sf.l2j.gameserver.network.serverpackets.ValidateLocation;
+import net.sf.l2j.gameserver.templates.chars.L2NpcTemplate;
+
+
+
+public class L2FortBallistaInstance extends L2NpcInstance
+{
+	public L2FortBallistaInstance(int objectId, L2NpcTemplate template)
+    {
+        super(objectId, template);
+        getKnownList(); // init knownlist
+    }
+	
+    @Override
+    public boolean isAutoAttackable(L2Character attacker)
+    {
+        return true;
+    }
+
+    @Override
+    public boolean doDie(L2Character killer)
+    {
+        if (!super.doDie(killer))
+            return false;
+        
+        if (getFort().getSiege().getIsInProgress())
+        {
+            if (killer instanceof L2PcInstance);
+            {
+            	L2PcInstance player = ((L2PcInstance)killer);
+            	if (player.getClan() != null && player.getClan().getLevel() >= 5)
+            	{
+            		player.getClan().setReputationScore(player.getClan().getReputationScore() + 30, true);
+            		player.getClan().broadcastToOnlineMembers(new PledgeShowInfoUpdate(player.getClan()));
+            	}
+            	player.sendPacket(new SystemMessage(SystemMessageId.BALLISTA_DESTROYED_CLAN_REPU_INCREASED));
+            }
+        }
+		
+        return true;
+    }
+    
+    @Override
+    public void onAction(L2PcInstance player)
+    {
+        if (!canTarget(player)) return;
+        
+        // Check if the L2PcInstance already target the L2NpcInstance
+        if (this != player.getTarget())
+        {
+            // Set the target of the L2PcInstance player
+            player.setTarget(this);
+
+            // Send a Server->Client packet MyTargetSelected to the L2PcInstance player
+            MyTargetSelected my = new MyTargetSelected(getObjectId(), 0);
+            player.sendPacket(my);
+
+            // Send a Server->Client packet ValidateLocation to correct the L2NpcInstance position and heading on the client
+            player.sendPacket(new ValidateLocation(this));
+        }
+        else
+        {
+			if (isAutoAttackable(player) && !isAlikeDead())
+			{
+				if (Math.abs(player.getZ() - getZ()) < 600) // this max heigth difference might need some tweaking
+				{
+					player.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, this);
+				}
+			}
+            // Calculate the distance between the L2PcInstance and the L2NpcInstance
+            if (!canInteract(player))
+            {
+                // Notify the L2PcInstance AI with AI_INTENTION_INTERACT
+                player.getAI().setIntention(CtrlIntention.AI_INTENTION_INTERACT, this);
+            }
+        }
+        // Send a Server->Client ActionFailed to the L2PcInstance in order to avoid that the client wait another packet
+        player.sendPacket(ActionFailed.STATIC_PACKET);
+    }
+
+    @Override
+	public boolean hasRandomAnimation()
+	{
+		return false;
+	}
+}

+ 81 - 16
L2_GameServer/java/net/sf/l2j/gameserver/model/actor/instance/L2CommanderInstance.java → L2_GameServer/java/net/sf/l2j/gameserver/model/actor/instance/L2FortCommanderInstance.java

@@ -14,21 +14,29 @@
  */
 package net.sf.l2j.gameserver.model.actor.instance;
 
+import javolution.util.FastList;
 import net.sf.l2j.Config;
+import net.sf.l2j.gameserver.ThreadPoolManager;
 import net.sf.l2j.gameserver.ai.CtrlIntention;
-import net.sf.l2j.gameserver.model.L2Attackable;
+import net.sf.l2j.gameserver.instancemanager.FortSiegeManager;
+import net.sf.l2j.gameserver.instancemanager.FortSiegeManager.SiegeSpawn;
 import net.sf.l2j.gameserver.model.L2CharPosition;
 import net.sf.l2j.gameserver.model.L2Character;
-import net.sf.l2j.gameserver.model.actor.knownlist.CommanderKnownList;
+import net.sf.l2j.gameserver.model.L2Spawn;
+import net.sf.l2j.gameserver.model.L2Summon;
+import net.sf.l2j.gameserver.network.serverpackets.NpcSay;
 import net.sf.l2j.gameserver.templates.chars.L2NpcTemplate;
 
-public class L2CommanderInstance extends L2Attackable
+public class L2FortCommanderInstance extends L2FortSiegeGuardInstance
 {
 
-	public L2CommanderInstance(int objectId, L2NpcTemplate template)
+	private boolean _canTalk;
+
+	public L2FortCommanderInstance(int objectId, L2NpcTemplate template)
     {
         super(objectId, template);
         getKnownList(); // init knownlist
+        _canTalk = true;
     }
 
     /**
@@ -48,22 +56,14 @@ public class L2CommanderInstance extends L2Attackable
         // Attackable during siege by all except defenders
         return (isFort);
     }
-    
-    @Override
-    public final CommanderKnownList getKnownList()
-    {
-        if(!(super.getKnownList() instanceof CommanderKnownList))
-            setKnownList(new CommanderKnownList(this));
-        return (CommanderKnownList)super.getKnownList();
-    }
-    
+   
     @Override
     public void addDamageHate(L2Character attacker, int damage, int aggro)
     {
         if (attacker == null)
             return;
 
-        if (!(attacker instanceof L2CommanderInstance))
+        if (!(attacker instanceof L2FortCommanderInstance))
         {
             super.addDamageHate(attacker, damage, aggro);
         }
@@ -90,9 +90,9 @@ public class L2CommanderInstance extends L2Attackable
      */
     public void returnHome()
     {
-        if (!isInsideRadius(getSpawn().getLocx(), getSpawn().getLocy(), 40, false))
+        if (!isInsideRadius(getSpawn().getLocx(), getSpawn().getLocy(), 200, false))
         {
-            if (Config.DEBUG) _log.fine(getObjectId()+": moving home");
+            if (Config.DEBUG) _log.info(getObjectId()+": moving home");
             setisReturningToSpawnPoint(true);    
             clearAggroList();
             
@@ -100,5 +100,70 @@ public class L2CommanderInstance extends L2Attackable
                 getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, new L2CharPosition(getSpawn().getLocx(), getSpawn().getLocy(), getSpawn().getLocz(), 0));
         }
     }
+    @Override
+    public final void addDamage(L2Character attacker, int damage)
+    {
+    	L2Spawn spawn = getSpawn();
+    	if (spawn != null && canTalk())
+		{
+			FastList<SiegeSpawn> commanders = FortSiegeManager.getInstance().getCommanderSpawnList(getFort().getFortId());
+			for (SiegeSpawn spawn2 : commanders)
+			{
+				if (spawn2.getNpcId() == spawn.getNpcid())
+				{
+					String text = "";
+					switch (spawn2.getId())
+					{
+						case 1:
+							text = "Attacking the enemy's reinforcements is necesary. Time to Die!";
+							break;
+						case 2:
+							if (attacker instanceof L2Summon)
+								attacker = ((L2Summon) attacker).getOwner();
+							text = "Everyone, concentrate your attacks on "+attacker.getName()+"! Show the enemy your resolve!";
+							break;
+						case 3:
+							text = "Spirit of Fire, unleash your power! Burn the enemy!!";
+							break;
+					}
+					if (text != "")
+					{
+						broadcastPacket(new NpcSay(getObjectId(), 1, getNpcId(), text));
+						setCanTalk(false);
+						ThreadPoolManager.getInstance().scheduleGeneral(new ScheduleTalkTask(), 10000);
+					}
+				}
+			}
+		}
+    	super.addDamage(attacker, damage);
+    }
     
+	private class ScheduleTalkTask implements Runnable
+	{
+		
+		public ScheduleTalkTask()
+		{
+		}
+		
+		public void run()
+		{
+			setCanTalk(true);
+		}
+	}
+	
+	void setCanTalk(boolean val)
+	{
+		_canTalk = val;
+	}
+	
+	private boolean canTalk()
+	{
+		return _canTalk;
+	}
+
+    @Override
+	public boolean hasRandomAnimation()
+	{
+		return false;
+	}
 }

+ 132 - 0
L2_GameServer/java/net/sf/l2j/gameserver/model/actor/instance/L2FortEnvoyInstance.java

@@ -0,0 +1,132 @@
+/*
+ * 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.model.actor.instance;
+
+import java.util.StringTokenizer;
+
+import net.sf.l2j.gameserver.ai.CtrlIntention;
+import net.sf.l2j.gameserver.instancemanager.CastleManager;
+import net.sf.l2j.gameserver.network.serverpackets.ActionFailed;
+import net.sf.l2j.gameserver.network.serverpackets.MyTargetSelected;
+import net.sf.l2j.gameserver.network.serverpackets.NpcHtmlMessage;
+import net.sf.l2j.gameserver.network.serverpackets.ValidateLocation;
+import net.sf.l2j.gameserver.templates.chars.L2NpcTemplate;
+
+public class L2FortEnvoyInstance extends L2NpcInstance
+{
+    public L2FortEnvoyInstance(int objectID, L2NpcTemplate template)
+    {
+        super(objectID, template);
+    }
+    @Override
+    public void onAction(L2PcInstance player)
+    {
+        if (!canTarget(player)) return;
+        
+        // Check if the L2PcInstance already target the L2NpcInstance
+        if (this != player.getTarget())
+        {
+            // Set the target of the L2PcInstance player
+            player.setTarget(this);
+
+            // Send a Server->Client packet MyTargetSelected to the L2PcInstance player
+            MyTargetSelected my = new MyTargetSelected(getObjectId(), 0);
+            player.sendPacket(my);
+
+            // Send a Server->Client packet ValidateLocation to correct the L2NpcInstance position and heading on the client
+            player.sendPacket(new ValidateLocation(this));
+        }
+        else
+        {
+            // Calculate the distance between the L2PcInstance and the L2NpcInstance
+            if (!canInteract(player))
+            {
+                // Notify the L2PcInstance AI with AI_INTENTION_INTERACT
+                player.getAI().setIntention(CtrlIntention.AI_INTENTION_INTERACT, this);
+            }
+            else
+            {
+                showMessageWindow(player);
+            }
+        }
+        // Send a Server->Client ActionFailed to the L2PcInstance in order to avoid that the client wait another packet
+        player.sendPacket(ActionFailed.STATIC_PACKET);
+    }
+
+    private void showMessageWindow(L2PcInstance player)
+    {
+        player.sendPacket(ActionFailed.STATIC_PACKET);
+
+        String filename;
+
+        if (!player.isClanLeader() || player.getClan() == null || getFort().getFortId() != player.getClan().getHasFort())
+            filename = "data/html/fortress/envoy-noclan.htm";
+        else if (getFort().getFortState() == 0)
+            filename = "data/html/fortress/envoy.htm";
+        else 
+        	filename = "data/html/fortress/envoy-no.htm";
+        NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
+        html.setFile(filename);
+        html.replace("%objectId%", String.valueOf(getObjectId()));
+        html.replace("%castleName%", String.valueOf(CastleManager.getInstance().getCastleById(getFort().getCastleIdFromEnvoy(getNpcId())).getName()));
+
+        player.sendPacket(html);
+    }
+
+    public void onBypassFeedback(L2PcInstance player, String command)
+    {
+        StringTokenizer st = new StringTokenizer(command, " ");
+        String actualCommand = st.nextToken(); // Get actual command
+
+        String par = "";
+        if (st.countTokens() >= 1) {par = st.nextToken();}
+
+        if (actualCommand.equalsIgnoreCase("select"))
+        {
+            int val = 0;
+            try
+            {
+                val = Integer.parseInt(par);
+            }
+            catch (IndexOutOfBoundsException ioobe){}
+            catch (NumberFormatException nfe){}
+            int castleId = 0;
+            NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
+            if (val == 2)
+            {
+            	castleId = getFort().getCastleIdFromEnvoy(getNpcId());
+            	if (CastleManager.getInstance().getCastleById(castleId).getOwnerId() < 1)
+            	{
+            		html.setHtml("<html><body>Contact is currently not possible, "+CastleManager.getInstance().getCastleById(castleId).getName()+" Castle isn't currently owned by clan.</body></html>");
+            		player.sendPacket(html);
+            		return;
+            	}
+            }
+            getFort().setFortState(val, castleId);
+            html.setFile("data/html/fortress/envoy-ok.htm");
+            html.replace("%castleName%", String.valueOf(CastleManager.getInstance().getCastleById(getFort().getCastleIdFromEnvoy(getNpcId())).getName()));
+
+            player.sendPacket(html);
+        }
+        else
+        {
+            super.onBypassFeedback(player, command);
+        }
+    }
+}

+ 4 - 37
L2_GameServer/java/net/sf/l2j/gameserver/model/actor/instance/L2FortManagerInstance.java

@@ -19,7 +19,6 @@ import java.util.StringTokenizer;
 
 import net.sf.l2j.Config;
 import net.sf.l2j.gameserver.ai.CtrlIntention;
-import net.sf.l2j.gameserver.datatables.ClanTable;
 import net.sf.l2j.gameserver.datatables.SkillTable;
 import net.sf.l2j.gameserver.datatables.TeleportLocationTable;
 import net.sf.l2j.gameserver.model.L2Clan;
@@ -135,22 +134,6 @@ public class L2FortManagerInstance extends L2MerchantInstance
 					return;
 				}
 			}
-			else if (actualCommand.equalsIgnoreCase("list_siege_clans"))
-			{
-				if ((player.getClanPrivileges() & L2Clan.CP_CS_MANAGE_SIEGE) == L2Clan.CP_CS_MANAGE_SIEGE)
-				{
-					getFort().getSiege().listRegisterClan(player); // List current register clan
-					return;
-				}
-				else
-				{
-					NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
-					html.setFile("data/html/fortress/foreman-noprivs.htm");
-					html.replace("%objectId%", String.valueOf(getObjectId()));
-					player.sendPacket(html);
-					return;
-				}
-			}
 			else if (actualCommand.equalsIgnoreCase("receive_report"))
 			{
 				if (player.isClanLeader())
@@ -158,7 +141,7 @@ public class L2FortManagerInstance extends L2MerchantInstance
 					NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
 					html.setFile("data/html/fortress/foreman-report.htm");
 					html.replace("%objectId%", String.valueOf(getObjectId()));
-					L2Clan clan = ClanTable.getInstance().getClan(getFort().getOwnerId());
+					L2Clan clan = getFort().getOwnerClan();
 					html.replace("%clanname%", clan.getName());
 					html.replace("%clanleadername%", clan.getLeaderName());
 					html.replace("%fortname%", getFort().getName());
@@ -174,22 +157,6 @@ public class L2FortManagerInstance extends L2MerchantInstance
 					return;
 				}
 			}
-			else if (actualCommand.equalsIgnoreCase("manage_siege_defender"))
-			{
-				if ((player.getClanPrivileges() & L2Clan.CP_CS_MANAGE_SIEGE) == L2Clan.CP_CS_MANAGE_SIEGE)
-				{
-					getFort().getSiege().listRegisterClan(player);
-					return;
-				}
-				else
-				{
-					NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
-					html.setFile("data/html/fortress/foreman-noprivs.htm");
-					html.replace("%objectId%", String.valueOf(getObjectId()));
-					player.sendPacket(html);
-					return;
-				}
-			}
 			else if (actualCommand.equalsIgnoreCase("operate_door")) // door
 			// control
 			{
@@ -280,7 +247,7 @@ public class L2FortManagerInstance extends L2MerchantInstance
 					{
 						if (st.countTokens() >= 1)
 						{
-							if (getFort().getOwnerId() == 0)
+							if (getFort().getOwnerClan() == null)
 							{
 								player.sendMessage("This fortress have no owner, you cannot change configuration");
 								return;
@@ -599,7 +566,7 @@ public class L2FortManagerInstance extends L2MerchantInstance
 					{
 						if (st.countTokens() >= 1)
 						{
-							if (getFort().getOwnerId() == 0)
+							if (getFort().getOwnerClan() == null)
 							{
 								player.sendMessage("This fortress have no owner, you cannot change configuration");
 								return;
@@ -950,7 +917,7 @@ public class L2FortManagerInstance extends L2MerchantInstance
 			{
 				if (getFort().getSiege().getIsInProgress())
 					return COND_BUSY_BECAUSE_OF_SIEGE; // Busy because of siege
-				else if (getFort().getOwnerId() == player.getClanId()) // Clan owns fortress
+				else if (getFort().getOwnerClan()!=null&&getFort().getOwnerClan().getClanId() == player.getClanId()) // Clan owns fortress
 					return COND_OWNER; // Owner
 			}
 		}

+ 186 - 0
L2_GameServer/java/net/sf/l2j/gameserver/model/actor/instance/L2FortSiegeGuardInstance.java

@@ -0,0 +1,186 @@
+/*
+ * 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 3 of the License, or (at your option) any later
+ * version.
+ * 
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package net.sf.l2j.gameserver.model.actor.instance;
+
+import net.sf.l2j.Config;
+import net.sf.l2j.gameserver.ai.CtrlIntention;
+import net.sf.l2j.gameserver.ai.L2CharacterAI;
+import net.sf.l2j.gameserver.ai.L2FortSiegeGuardAI;
+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.L2Summon;
+import net.sf.l2j.gameserver.model.actor.knownlist.FortSiegeGuardKnownList;
+import net.sf.l2j.gameserver.network.serverpackets.ActionFailed;
+import net.sf.l2j.gameserver.network.serverpackets.MyTargetSelected;
+import net.sf.l2j.gameserver.network.serverpackets.StatusUpdate;
+import net.sf.l2j.gameserver.network.serverpackets.ValidateLocation;
+import net.sf.l2j.gameserver.templates.chars.L2NpcTemplate;
+
+public class L2FortSiegeGuardInstance extends L2Attackable
+{
+	public L2FortSiegeGuardInstance(int objectId, L2NpcTemplate template)
+	{
+		super(objectId, template);
+		getKnownList(); //inits the knownlist
+	}
+
+	@Override
+	public FortSiegeGuardKnownList getKnownList()
+	{
+		if(!(super.getKnownList() instanceof FortSiegeGuardKnownList))
+			setKnownList(new FortSiegeGuardKnownList(this));
+		return (FortSiegeGuardKnownList)super.getKnownList();
+	}
+
+	@Override
+	public L2CharacterAI getAI()
+	{
+		L2CharacterAI ai = _ai; // copy handle
+		if (ai == null)
+		{
+			synchronized(this)
+			{
+				if (_ai == null) _ai = new L2FortSiegeGuardAI(new AIAccessor());
+				return _ai;
+			}
+		}
+		return ai;
+	}
+
+	/**
+	 * Return True if a siege is in progress and the L2Character attacker isn't a Defender.<BR><BR>
+	 *
+	 * @param attacker The L2Character that the L2SiegeGuardInstance try to attack
+	 *
+	 */
+    @Override
+	public boolean isAutoAttackable(L2Character attacker)
+	{
+    	if (!(attacker instanceof L2PlayableInstance) )
+    		return false;
+
+        boolean isFort = ( getFort() != null && getFort().getFortId() > 0 
+                && getFort().getSiege().getIsInProgress()
+                && !getFort().getSiege().checkIsDefender(((L2PcInstance)attacker).getClan()));
+        
+        // Attackable during siege by all except defenders
+		return isFort;
+    }
+
+    @Override
+	public boolean hasRandomAnimation()
+	{
+		return false;
+	}
+
+    /**
+     * This method forces guard to return to home location previously set
+     *
+     */
+    public void returnHome()
+    {
+    	if (getWalkSpeed() <= 0)
+    		return;
+        if (!isInsideRadius(getSpawn().getLocx(), getSpawn().getLocy(), 40, false))
+        {
+            if (Config.DEBUG) _log.info(getObjectId()+": moving home");
+            setisReturningToSpawnPoint(true);    
+            clearAggroList();
+            
+            if (hasAI())
+                getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, new L2CharPosition(getSpawn().getLocx(), getSpawn().getLocy(), getSpawn().getLocz(), 0));
+        }
+    }
+
+	/**
+	* Custom onAction behaviour. Note that super() is not called because guards need
+	* extra check to see if a player should interact or ATTACK them when clicked.
+	* 
+	*/
+	@Override
+	public void onAction(L2PcInstance player)
+	{
+		if (!canTarget(player))
+		{
+			player.sendPacket(ActionFailed.STATIC_PACKET);
+			return;
+		}
+
+		// Check if the L2PcInstance already target the L2NpcInstance
+		if (this != player.getTarget())
+		{
+			if (Config.DEBUG) _log.info("new target selected:"+getObjectId());
+
+			// Set the target of the L2PcInstance player
+			player.setTarget(this);
+
+			// Send a Server->Client packet MyTargetSelected to the L2PcInstance player
+			MyTargetSelected my = new MyTargetSelected(getObjectId(), player.getLevel() - getLevel());
+			player.sendPacket(my);
+
+			// Send a Server->Client packet StatusUpdate of the L2NpcInstance to the L2PcInstance to update its HP bar
+			StatusUpdate su = new StatusUpdate(getObjectId());
+			su.addAttribute(StatusUpdate.CUR_HP, (int)getStatus().getCurrentHp() );
+			su.addAttribute(StatusUpdate.MAX_HP, getMaxHp() );
+			player.sendPacket(su);
+
+			// Send a Server->Client packet ValidateLocation to correct the L2NpcInstance position and heading on the client
+			player.sendPacket(new ValidateLocation(this));
+		}
+		else
+		{
+			if (isAutoAttackable(player) && !isAlikeDead())
+			{
+				if (Math.abs(player.getZ() - getZ()) < 600) // this max heigth difference might need some tweaking
+				{
+					player.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, this);
+				}
+			}
+			if(!isAutoAttackable(player))
+			{
+				if (!canInteract(player))
+				{
+					// Notify the L2PcInstance AI with AI_INTENTION_INTERACT
+					player.getAI().setIntention(CtrlIntention.AI_INTENTION_INTERACT, this);
+				}
+			}
+		}
+		//Send a Server->Client ActionFailed to the L2PcInstance in order to avoid that the client wait another packet
+		player.sendPacket(ActionFailed.STATIC_PACKET);
+	}
+
+    @Override
+    public void addDamageHate(L2Character attacker, int damage, int aggro)
+    {
+        if (attacker == null)
+            return;
+
+        if (!(attacker instanceof L2FortSiegeGuardInstance))
+        {
+        	if (attacker instanceof L2PlayableInstance)
+        	{
+        		L2PcInstance player = null;
+        		if (attacker instanceof L2PcInstance)
+        			player = ((L2PcInstance)attacker);
+        		else if (attacker instanceof L2Summon)
+        			player = ((L2Summon)attacker).getOwner();
+        		if (player != null && player.getClan() != null && player.getClan().getHasFort() == getFort().getFortId())
+        			return;
+        	}
+            super.addDamageHate(attacker, damage, aggro);
+        }
+    }
+}

+ 27 - 40
L2_GameServer/java/net/sf/l2j/gameserver/model/actor/instance/L2FortMerchantInstance.java → L2_GameServer/java/net/sf/l2j/gameserver/model/actor/instance/L2FortSiegeNpcInstance.java

@@ -21,7 +21,6 @@ package net.sf.l2j.gameserver.model.actor.instance;
 import java.util.StringTokenizer;
 
 import net.sf.l2j.gameserver.ai.CtrlIntention;
-import net.sf.l2j.gameserver.datatables.ClanTable;
 import net.sf.l2j.gameserver.network.serverpackets.ActionFailed;
 import net.sf.l2j.gameserver.network.serverpackets.MyTargetSelected;
 import net.sf.l2j.gameserver.network.serverpackets.NpcHtmlMessage;
@@ -31,13 +30,14 @@ import net.sf.l2j.gameserver.templates.chars.L2NpcTemplate;
 /**
  * @author Vice 
  */
-public class L2FortMerchantInstance extends L2NpcWalkerInstance
+public class L2FortSiegeNpcInstance extends L2NpcInstance
 {
-    public L2FortMerchantInstance(int objectID, L2NpcTemplate template)
+    public L2FortSiegeNpcInstance(int objectID, L2NpcTemplate template)
     {
         super(objectID, template);
     }
 
+    @Override
     public void onAction(L2PcInstance player)
     {
         if (!canTarget(player)) return;
@@ -91,19 +91,30 @@ public class L2FortMerchantInstance extends L2NpcWalkerInstance
             catch (NumberFormatException nfe){}
             showMessageWindow(player, val);
         }
-        else if (actualCommand.equalsIgnoreCase("showSiegeInfo"))
+        else if (actualCommand.equalsIgnoreCase("register"))
         {
-            showSiegeInfoWindow(player);
+            if (player.getClan() == null || !player.isClanLeader()
+            		|| (getFort().getOwnerClan() != null && player.getClan().getHasCastle() != getFort().getCastleId())
+            		|| player.getClan().getLevel() < 4)
+            {
+            	player.sendMessage("ure not able to participate"); // replace me with html
+            }
+            else if (getFort().getSiege().getAttackerClans().size() == 0 && player.getInventory().getAdena() < 250000)
+            {
+            	player.sendMessage("u need 250.000 adena to register"); // replace me with html
+            }
+            else
+            {
+            	if (getFort().getSiege().registerAttacker(player, false))
+            		player.sendMessage("registered on siege :)");
+            }
         }
         else
         {
             super.onBypassFeedback(player, command);
         }
-        
-
     }
     
-    
     private void showMessageWindow(L2PcInstance player)
     {
         showMessageWindow(player, 0);
@@ -124,41 +135,17 @@ public class L2FortMerchantInstance extends L2NpcWalkerInstance
         html.setFile(filename);
         html.replace("%objectId%", String.valueOf(getObjectId()));
         html.replace("%npcId%", String.valueOf(getNpcId()));
-        if ( getFort().getOwnerId() > 0 ) 
-            html.replace("%clanname%", ClanTable.getInstance().getClan(getFort().getOwnerId()).getName());
+        if ( getFort().getOwnerClan() != null ) 
+            html.replace("%clanname%", getFort().getOwnerClan().getName());
         else
             html.replace("%clanname%", "NPC");
         
-        html.replace("%castleid%", Integer.toString(getFort().getFortId()));
         player.sendPacket(html);
-    }
-    
-    /**
-     * If siege is in progress shows the Busy HTML<BR>
-     * else Shows the SiegeInfo window
-     * 
-     * @param player
-     */
-    public void showSiegeInfoWindow(L2PcInstance player)
-    {
-        if (validateCondition(player))
-            getFort().getSiege().listRegisterClan(player);
-        else
-        {
-            NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
-            html.setFile("data/html/fortress/merchant-busy.htm");
-            html.replace("%fortname%", getFort().getName());
-            html.replace("%objectId%", String.valueOf(getObjectId()));
-            player.sendPacket(html);
-            player.sendPacket(ActionFailed.STATIC_PACKET);
-        }
-    }
-
-    private boolean validateCondition(L2PcInstance player)
-    {
-        if (getFort().getSiege().getIsInProgress())
-            return false; // Busy because of siege
-        return true;
-    }    
+    } 
 
+    @Override
+	public boolean hasRandomAnimation()
+	{
+		return false;
+	}
 }

+ 16 - 0
L2_GameServer/java/net/sf/l2j/gameserver/model/actor/instance/L2NpcInstance.java

@@ -142,6 +142,8 @@ public class L2NpcInstance extends L2Character
 	private int _currentRHandId; // normally this shouldn't change from the template, but there exist exceptions
 	private int _currentCollisionHeight; // used for npc grow effect skills
 	private int _currentCollisionRadius; // used for npc grow effect skills
+
+	private boolean _isRaid = false;
 	
 	/** Task launching the function onRandomAnimation() */
 	protected class RandomAnimationTask implements Runnable
@@ -2537,4 +2539,18 @@ public class L2NpcInstance extends L2Character
 		return _inventory;
 	}
 	
+    @Override
+	public boolean isRaid()
+    {
+        return _isRaid ;
+    }
+    
+	/**
+	 * Set this Npc as a Raid instance.<BR><BR>
+	 * @param isRaid
+	 */
+    public void setIsRaid(boolean isRaid)
+    {
+    	_isRaid = isRaid;
+    }
 }

+ 34 - 8
L2_GameServer/java/net/sf/l2j/gameserver/model/actor/instance/L2PcInstance.java

@@ -76,6 +76,7 @@ import net.sf.l2j.gameserver.instancemanager.CoupleManager;
 import net.sf.l2j.gameserver.instancemanager.CursedWeaponsManager;
 import net.sf.l2j.gameserver.instancemanager.DimensionalRiftManager;
 import net.sf.l2j.gameserver.instancemanager.DuelManager;
+import net.sf.l2j.gameserver.instancemanager.FortManager;
 import net.sf.l2j.gameserver.instancemanager.FortSiegeManager;
 import net.sf.l2j.gameserver.instancemanager.ItemsOnGroundManager;
 import net.sf.l2j.gameserver.instancemanager.QuestManager;
@@ -124,6 +125,7 @@ import net.sf.l2j.gameserver.model.base.Race;
 import net.sf.l2j.gameserver.model.base.SubClass;
 import net.sf.l2j.gameserver.model.entity.Castle;
 import net.sf.l2j.gameserver.model.entity.Duel;
+import net.sf.l2j.gameserver.model.entity.Fort;
 import net.sf.l2j.gameserver.model.entity.L2Event;
 import net.sf.l2j.gameserver.model.entity.Siege;
 import net.sf.l2j.gameserver.model.entity.TvTEvent;
@@ -1160,6 +1162,18 @@ public final class L2PcInstance extends L2PlayableInstance
 	 */
 	public void logout()
 	{
+		if (getInventory().getItemByItemId(9819) != null)
+		{
+			Fort fort = FortManager.getInstance().getFort(this);
+			if (fort != null)
+				FortSiegeManager.getInstance().dropCombatFlag(this);
+			else
+			{
+				int slot = getInventory().getSlotFromItem(getInventory().getItemByItemId(9819));
+				getInventory().unEquipItemInBodySlotAndRecord(slot);
+				destroyItem("CombatFlag", getInventory().getItemByItemId(9819), null, true);
+			}
+		}
 		closeNetConnection();
 	}
 
@@ -2991,8 +3005,13 @@ public final class L2PcInstance extends L2PlayableInstance
 			
 			// Combat Flag
             else if(FortSiegeManager.getInstance().isCombat(item.getItemId()))
-                FortSiegeManager.getInstance().activateCombatFlag(this, item);
-
+            {
+            	if(FortSiegeManager.getInstance().activateCombatFlag(this, item))
+            	{
+            		Fort fort = FortManager.getInstance().getFort(this);
+            		fort.getSiege().announceToPlayer(new SystemMessage(SystemMessageId.S1_ACQUIRED_THE_FLAG), this.getName());
+            	}
+            }
 		}
 	}
 
@@ -3083,7 +3102,13 @@ public final class L2PcInstance extends L2PlayableInstance
 
 				// Combat Flag
 				else if(FortSiegeManager.getInstance().isCombat(createdItem.getItemId()))
-					FortSiegeManager.getInstance().activateCombatFlag(this, createdItem);
+				{
+					if( FortSiegeManager.getInstance().activateCombatFlag(this, item))
+					{
+						Fort fort = FortManager.getInstance().getFort(this);
+						fort.getSiege().announceToPlayer(new SystemMessage(SystemMessageId.S1_ACQUIRED_THE_FLAG), this.getName());
+					}
+				}
 			}
 		}
 	}
@@ -4936,7 +4961,6 @@ public final class L2PcInstance extends L2PlayableInstance
 			else if (isCombatFlagEquipped())
 			{
 				FortSiegeManager.getInstance().dropCombatFlag(this);
-				System.out.println("Player with combat flag die");
 			}
 			else
 			{
@@ -7892,7 +7916,7 @@ public final class L2PcInstance extends L2PlayableInstance
 				return true;
 			}
 		}
-		else if (attacker instanceof L2SiegeGuardInstance)
+		else if (attacker instanceof L2SiegeGuardInstance || attacker instanceof L2FortSiegeGuardInstance)
 		{
 			if (getClan() != null)
 			{
@@ -8120,7 +8144,8 @@ public final class L2PcInstance extends L2PlayableInstance
                     && ((L2DoorInstance) target).getCastle().getSiege().getIsInProgress());
         	boolean isFort = (((L2DoorInstance) target).getFort() != null
                     && ((L2DoorInstance) target).getFort().getFortId() > 0
-                    && ((L2DoorInstance) target).getFort().getSiege().getIsInProgress());
+                    && ((L2DoorInstance) target).getFort().getSiege().getIsInProgress()
+                    && !((L2DoorInstance) target).getIsCommanderDoor());
         	if ((!isCastle && !isFort)&&(((L2DoorInstance) target).isUnlockable() && skill.getSkillType() != L2SkillType.UNLOCK))
         		return false;
         }
@@ -8429,7 +8454,7 @@ public final class L2PcInstance extends L2PlayableInstance
 		}
 
         if ((sklTargetType == SkillTargetType.TARGET_HOLY && !TakeCastle.checkIfOkToCastSealOfRule(this, false))
-        		|| (sklTargetType == SkillTargetType.TARGET_FLAGPOLE && !TakeFort.checkIfOkToCastFlagDisplay(this, false))
+        		|| (sklTargetType == SkillTargetType.TARGET_FLAGPOLE && !TakeFort.checkIfOkToCastFlagDisplay(this, false, skill, getTarget()))
         		|| (sklType == L2SkillType.SIEGEFLAG && !L2SkillSiegeFlag.checkIfOkToPlaceFlag(this, false))
         		|| (sklType == L2SkillType.STRSIEGEASSAULT && !StrSiegeAssault.checkIfOkToUseStriderSiegeAssault(this, false)))
         {
@@ -11548,7 +11573,8 @@ public final class L2PcInstance extends L2PlayableInstance
     			&& !(killer instanceof L2PcInstance) && !(this.isGM())
     			&& !(this.getCharmOfLuck() && killer.isRaid())
     			&& !isPhoenixBlessed()
-    			&& !(TvTEvent.isStarted() && TvTEvent.isPlayerParticipant(getObjectId()))) 
+    			&& !(TvTEvent.isStarted() && TvTEvent.isPlayerParticipant(getObjectId()))
+    			&& !(this.isInsideZone(L2Character.ZONE_PVP)||this.isInsideZone(L2Character.ZONE_SIEGE))) 
     		
     		increaseDeathPenaltyBuffLevel();
 	}

+ 78 - 31
L2_GameServer/java/net/sf/l2j/gameserver/model/actor/instance/L2SiegeFlagInstance.java

@@ -14,46 +14,52 @@
  */
 package net.sf.l2j.gameserver.model.actor.instance;
 
+import net.sf.l2j.gameserver.ThreadPoolManager;
 import net.sf.l2j.gameserver.ai.CtrlIntention;
 import net.sf.l2j.gameserver.instancemanager.SiegeManager;
 import net.sf.l2j.gameserver.model.L2Character;
+import net.sf.l2j.gameserver.model.L2Clan;
 import net.sf.l2j.gameserver.model.L2SiegeClan;
 import net.sf.l2j.gameserver.model.actor.status.SiegeFlagStatus;
 import net.sf.l2j.gameserver.model.entity.Siege;
+import net.sf.l2j.gameserver.network.SystemMessageId;
 import net.sf.l2j.gameserver.network.serverpackets.ActionFailed;
 import net.sf.l2j.gameserver.network.serverpackets.MyTargetSelected;
 import net.sf.l2j.gameserver.network.serverpackets.StatusUpdate;
+import net.sf.l2j.gameserver.network.serverpackets.SystemMessage;
 import net.sf.l2j.gameserver.network.serverpackets.ValidateLocation;
 import net.sf.l2j.gameserver.templates.chars.L2NpcTemplate;
 
 public class L2SiegeFlagInstance extends L2NpcInstance
 {
+    private L2Clan _clan;
     private L2PcInstance _player;
     private Siege _siege;
     private final boolean _isAdvanced;
+    private boolean _canTalk;
 
     public L2SiegeFlagInstance(L2PcInstance player, int objectId, L2NpcTemplate template, boolean advanced)
-    {
-    	super(objectId, template);
-    	
-    	_player = player;
-        _siege = SiegeManager.getInstance().getSiege(_player.getX(), _player.getY(), _player.getZ());
-        if (_player.getClan() == null || _siege == null)
-        {
-            deleteMe();
-        }
-        else
-        {
-            L2SiegeClan sc = _siege.getAttackerClan(_player.getClan());
-            if (sc == null)
-                deleteMe();
-            else
-                sc.addFlag(this);
-        }
-        
-        _isAdvanced = advanced;
-        
-        getStatus();
+	{
+		super(objectId, template);
+		
+		_clan = player.getClan();
+		_player = player;
+		_canTalk = true;
+		_siege = SiegeManager.getInstance().getSiege(_player.getX(), _player.getY(), _player.getZ());
+		if (_clan == null || _siege == null)
+		{
+			deleteMe();
+		}
+		else
+		{
+			L2SiegeClan sc = _siege.getAttackerClan(_player.getClan());
+			if (sc == null)
+				deleteMe();
+			else
+				sc.addFlag(this);
+		}
+		_isAdvanced = advanced;
+		getStatus();
     }
     
     /**
@@ -69,21 +75,13 @@ public class L2SiegeFlagInstance extends L2NpcInstance
     @Override
 	public boolean isAttackable()
     {
-        // Attackable during siege by attacker only
-        return (getCastle() != null
-                && getCastle().getCastleId() > 0
-                && getCastle().getSiege().getIsInProgress());
+        return true;
     }
 
 	@Override
 	public boolean isAutoAttackable(L2Character attacker)
 	{
-		// Attackable during siege by attacker only
-		return (attacker != null
-		        && attacker instanceof L2PcInstance
-		        && getCastle() != null
-		        && getCastle().getCastleId() > 0
-		        && getCastle().getSiege().getIsInProgress());
+		return true;
 	}
 
     @Override
@@ -152,4 +150,53 @@ public class L2SiegeFlagInstance extends L2NpcInstance
 			setStatus(new SiegeFlagStatus(this));
 		return (SiegeFlagStatus) super.getStatus();
 	}
+	
+    @Override
+	public void reduceCurrentHp(double damage, L2Character attacker)
+    {
+    	super.reduceCurrentHp(damage, attacker);
+    	if(canTalk())
+    	{
+    		if (getCastle() != null && getCastle().getSiege().getIsInProgress())
+    		{
+    			if (_clan != null)
+    			{
+    				// send warning to owners of headquarters that theirs base is under attack
+    				_clan.broadcastToOnlineMembers(new SystemMessage(SystemMessageId.BASE_UNDER_ATTACK));
+    	    		setCanTalk(false);
+    				ThreadPoolManager.getInstance().scheduleGeneral(new ScheduleTalkTask(), 20000);
+    			}
+    		}
+    		else if (getFort() != null && getFort().getSiege().getIsInProgress())
+    		{
+    			if (_clan != null)
+    			{
+    				// send warning to owners of headquarters that theirs base is under attack
+    				_clan.broadcastToOnlineMembers(new SystemMessage(SystemMessageId.BASE_UNDER_ATTACK));
+    	    		setCanTalk(false);
+    				ThreadPoolManager.getInstance().scheduleGeneral(new ScheduleTalkTask(), 20000);
+    			}
+    		}
+    	}
+    }
+	private class ScheduleTalkTask implements Runnable
+	{
+		
+		public ScheduleTalkTask() {}
+		
+		public void run()
+		{
+			setCanTalk(true);
+		}
+	}
+	
+	void setCanTalk(boolean val)
+	{
+		_canTalk = val;
+	}
+	
+	private boolean canTalk()
+	{
+		return _canTalk;
+	}
 }

+ 4 - 3
L2_GameServer/java/net/sf/l2j/gameserver/model/actor/instance/L2SiegeGuardInstance.java

@@ -38,10 +38,11 @@ import net.sf.l2j.util.Rnd;
  *
  * @version $Revision: 1.11.2.1.2.7 $ $Date: 2005/04/06 16:13:40 $
  */
-public final class L2SiegeGuardInstance extends L2Attackable
+public class L2SiegeGuardInstance extends L2Attackable
 {
     @SuppressWarnings("hiding")
-	private static Logger _log = Logger.getLogger(L2GuardInstance.class.getName());
+	protected
+	static Logger _log = Logger.getLogger(L2GuardInstance.class.getName());
 
     public L2SiegeGuardInstance(int objectId, L2NpcTemplate template)
     {
@@ -50,7 +51,7 @@ public final class L2SiegeGuardInstance extends L2Attackable
     }
 
     @Override
-	public final SiegeGuardKnownList getKnownList()
+	public SiegeGuardKnownList getKnownList()
     {
     	if(!(super.getKnownList() instanceof SiegeGuardKnownList))
     		setKnownList(new SiegeGuardKnownList(this));

+ 171 - 12
L2_GameServer/java/net/sf/l2j/gameserver/model/actor/instance/L2StaticObjectInstance.java

@@ -20,32 +20,66 @@ package net.sf.l2j.gameserver.model.actor.instance;
 
 import java.util.logging.Logger;
 
+import javolution.text.TextBuilder;
 import net.sf.l2j.gameserver.ai.CtrlIntention;
+import net.sf.l2j.gameserver.ai.L2CharacterAI;
 import net.sf.l2j.gameserver.cache.HtmCache;
+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.actor.knownlist.NullKnownList;
+import net.sf.l2j.gameserver.model.L2ItemInstance;
+import net.sf.l2j.gameserver.model.L2Skill;
+import net.sf.l2j.gameserver.model.actor.knownlist.StaticObjectKnownList;
+import net.sf.l2j.gameserver.model.actor.stat.StaticObjStat;
+import net.sf.l2j.gameserver.model.actor.status.StaticObjStatus;
+import net.sf.l2j.gameserver.network.L2GameClient;
 import net.sf.l2j.gameserver.network.serverpackets.ActionFailed;
 import net.sf.l2j.gameserver.network.serverpackets.MyTargetSelected;
 import net.sf.l2j.gameserver.network.serverpackets.NpcHtmlMessage;
 import net.sf.l2j.gameserver.network.serverpackets.ShowTownMap;
+import net.sf.l2j.gameserver.network.serverpackets.StaticObject;
+import net.sf.l2j.gameserver.templates.chars.L2CharTemplate;
+import net.sf.l2j.gameserver.templates.item.L2Weapon;
 
 /**
  * GODSON ROX!
  */
-public class L2StaticObjectInstance extends L2Object
+public class L2StaticObjectInstance extends L2Character
 {
-    private static Logger _log = Logger.getLogger(L2StaticObjectInstance.class.getName());
+	protected static final Logger log = Logger.getLogger(L2StaticObjectInstance.class.getName());
 
     /** The interaction distance of the L2StaticObjectInstance */
     public static final int INTERACTION_DISTANCE = 150;
 
     private int _staticObjectId;
+    private int _meshIndex = 0;     // 0 - static objects, alternate static objects
     private int _type = -1;         // 0 - map signs, 1 - throne , 2 - arena signs
     private int _x;
     private int _y;
     private String _texture;
 
+    /** This class may be created only by L2Character and only for AI */
+    public class AIAccessor extends L2Character.AIAccessor
+    {
+        protected AIAccessor() {}
+        @Override
+		public L2StaticObjectInstance getActor() { return L2StaticObjectInstance.this; }
+        @Override
+        public void moveTo(int x, int y, int z, int offset) {}
+        @Override
+        public void moveTo(int x, int y, int z) {}
+        @Override
+        public void stopMove(L2CharPosition pos) {}
+        @Override
+        public void doAttack(L2Character target) {}
+        @Override
+        public void doCast(L2Skill skill) {}
+    }
+
+    @Override
+	public L2CharacterAI getAI() 
+    {
+    	return null;
+    }
     /**
      * @return Returns the StaticObjectId.
      */
@@ -53,19 +87,40 @@ public class L2StaticObjectInstance extends L2Object
     {
         return _staticObjectId;
     }
+
     /**
-     * @param doorId The doorId to set.
      */
-    public void setStaticObjectId(int StaticObjectId)
+    public L2StaticObjectInstance(int objectId,L2CharTemplate template, int staticId)
     {
-        _staticObjectId = StaticObjectId;
+    	super(objectId, template);
+    	getKnownList();
+    	getStat();
+    	getStatus();
+    	_staticObjectId = staticId;
     }
-    /**
-     */
-    public L2StaticObjectInstance(int objectId)
+
+    @Override
+	public final StaticObjectKnownList getKnownList()
+    {
+    	if(!(super.getKnownList() instanceof StaticObjectKnownList))
+    		setKnownList(new StaticObjectKnownList(this));
+    	return (StaticObjectKnownList)super.getKnownList();
+    }
+
+    @Override
+	public final StaticObjStat getStat()
+    {
+    	if(!(super.getStat() instanceof StaticObjStat))
+    		setStat(new StaticObjStat(this));
+    	return (StaticObjStat)super.getStat();
+    }
+
+    @Override
+	public final StaticObjStatus getStatus()
     {
-        super(objectId);
-        setKnownList(new NullKnownList(this));
+    	if(!(super.getStatus() instanceof StaticObjStatus))
+    		setStatus(new StaticObjStatus(this));
+    	return (StaticObjStatus)super.getStatus();
     }
 
     public int getType()
@@ -95,6 +150,39 @@ public class L2StaticObjectInstance extends L2Object
 	return _y;
     }
 
+    @Override
+	public final int getLevel()
+    {
+        return 1;
+    }
+
+    /**
+     * Return null.<BR><BR>
+     */
+    @Override
+	public L2ItemInstance getActiveWeaponInstance()
+    {
+        return null;
+    }
+
+    @Override
+	public L2Weapon getActiveWeaponItem()
+    {
+        return null;
+    }
+
+    @Override
+	public L2ItemInstance getSecondaryWeaponInstance()
+    {
+        return null;
+    }
+
+    @Override
+    public L2Weapon getSecondaryWeaponItem()
+    {
+        return null;
+    }
+
     /**
      * this is called when a player interacts with this NPC
      * @param player
@@ -142,6 +230,47 @@ public class L2StaticObjectInstance extends L2Object
 
     }
 
+    @Override
+    public void onActionShift(L2GameClient client)
+    {
+        L2PcInstance player = client.getActiveChar();
+        if (player == null) return;
+
+        if (player.getAccessLevel().isGm())
+        {
+            player.setTarget(this);
+            MyTargetSelected my = new MyTargetSelected(getObjectId(), player
+                    .getLevel());
+            player.sendPacket(my);
+
+            StaticObject su = new StaticObject(this);
+
+            player.sendPacket(su);
+
+            NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
+            TextBuilder html1 = new TextBuilder("<html><body><table border=0>");
+            html1.append("<tr><td>S.Y.L. Says:</td></tr>");
+            html1.append("<tr><td>X: "+getX()+ "</td></tr>");
+            html1.append("<tr><td>Y: "+getY()+"</td></tr>");
+            html1.append("<tr><td>Z: "+getZ()+"</td></tr>");
+            html1.append("<tr><td>Object ID: " + getObjectId() + "</td></tr>");
+            html1.append("<tr><td>Static Object ID: "+getStaticObjectId()+"</td></tr>");
+            html1.append("<tr><td>Mesh Index: "+getMeshIndex()+"</td></tr>");
+            html1.append("<tr><td><br></td></tr>");
+
+            html1.append("<tr><td>Class: " + getClass().getName() + "</td></tr>");
+            html1.append("<tr><td><br></td></tr>");
+            html1.append("</table></body></html>");
+
+            html.setHtml(html1.toString());
+            player.sendPacket(html);
+        } else {
+            // ATTACK the mob without moving?
+        }
+
+        player.sendPacket(ActionFailed.STATIC_PACKET);
+    }
+
     /* (non-Javadoc)
      * @see net.sf.l2j.gameserver.model.L2Object#isAttackable()
      */
@@ -150,4 +279,34 @@ public class L2StaticObjectInstance extends L2Object
     {
         return false;
     }
+
+    /**
+     * Set the meshIndex of the object<BR><BR>
+     * 
+     * <B><U> Values </U> :</B><BR><BR>
+     * <li> default textures : 0</li>
+     * <li> alternate textures : 1 </li><BR><BR>
+     * @param meshIndex
+     */
+    public void setMeshIndex (int meshIndex)
+    {
+    	_meshIndex = meshIndex;
+    	this.broadcastPacket(new StaticObject(this));
+    }
+
+    /**
+     * Return the meshIndex of the object.<BR><BR>
+     *
+     * <B><U> Values </U> :</B><BR><BR>
+     * <li> default textures : 0</li>
+     * <li> alternate textures : 1 </li><BR><BR>
+     *
+     */
+    public int getMeshIndex()
+    {
+    	return _meshIndex;
+    }
+
+	@Override
+	public void updateAbnormalEffect() {}
 }

+ 13 - 2
L2_GameServer/java/net/sf/l2j/gameserver/model/actor/instance/L2VillageMasterInstance.java

@@ -24,6 +24,8 @@ import net.sf.l2j.gameserver.datatables.CharTemplateTable;
 import net.sf.l2j.gameserver.datatables.ClanTable;
 import net.sf.l2j.gameserver.datatables.SkillTreeTable;
 import net.sf.l2j.gameserver.instancemanager.CastleManager;
+import net.sf.l2j.gameserver.instancemanager.FortManager;
+import net.sf.l2j.gameserver.instancemanager.FortSiegeManager;
 import net.sf.l2j.gameserver.instancemanager.SiegeManager;
 import net.sf.l2j.gameserver.model.L2Clan;
 import net.sf.l2j.gameserver.model.L2ClanMember;
@@ -35,6 +37,7 @@ import net.sf.l2j.gameserver.model.base.PlayerClass;
 import net.sf.l2j.gameserver.model.base.Race;
 import net.sf.l2j.gameserver.model.base.SubClass;
 import net.sf.l2j.gameserver.model.entity.Castle;
+import net.sf.l2j.gameserver.model.entity.Fort;
 import net.sf.l2j.gameserver.model.quest.QuestState;
 import net.sf.l2j.gameserver.network.SystemMessageId;
 import net.sf.l2j.gameserver.network.serverpackets.AcquireSkillDone;
@@ -510,7 +513,7 @@ public final class L2VillageMasterInstance extends L2FolkInstance
             player.sendPacket(new SystemMessage(SystemMessageId.CANNOT_DISSOLVE_WHILE_IN_WAR));
             return;
         }
-        if (clan.getHasCastle() !=0 || clan.getHasHideout() != 0)
+        if (clan.getHasCastle() !=0 || clan.getHasHideout() != 0 || clan.getHasFort() != 0)
         {
             player.sendPacket(new SystemMessage(SystemMessageId.CANNOT_DISSOLVE_WHILE_OWNING_CLAN_HALL_OR_CASTLE));
             return;
@@ -519,10 +522,18 @@ public final class L2VillageMasterInstance extends L2FolkInstance
         {
             if (SiegeManager.getInstance().checkIsRegistered(clan, castle.getCastleId()))
             {
-                player.sendPacket(new SystemMessage(SystemMessageId.CANNOT_DISSOLVE_CAUSE_CLAN_WILL_PARTICIPATE_IN_CASTLE_SIEGE));
+                player.sendPacket(new SystemMessage(SystemMessageId.CANNOT_DISSOLVE_WHILE_IN_SIEGE));
                 return;
             }
         }
+        for (Fort fort : FortManager.getInstance().getForts())
+        {
+        	if (FortSiegeManager.getInstance().checkIsRegistered(clan, fort.getFortId()))
+        	{
+        		player.sendPacket(new SystemMessage(SystemMessageId.CANNOT_DISSOLVE_WHILE_IN_SIEGE));
+                return;
+        	}
+        }
         if (player.isInsideZone(L2PcInstance.ZONE_SIEGE))
         {
             player.sendPacket(new SystemMessage(SystemMessageId.CANNOT_DISSOLVE_WHILE_IN_SIEGE));

+ 1 - 0
L2_GameServer/java/net/sf/l2j/gameserver/model/actor/knownlist/CharKnownList.java

@@ -202,6 +202,7 @@ public class CharKnownList extends ObjectKnownList
 
        Collection<L2Object> objs = getKnownObjects().values();
        //synchronized (getKnownObjects())
+       if (objs != null && objs.size() > 0)
        {
 			for (L2Object obj : objs)
 			{

+ 3 - 2
L2_GameServer/java/net/sf/l2j/gameserver/model/actor/knownlist/DoorKnownList.java

@@ -16,6 +16,7 @@ package net.sf.l2j.gameserver.model.actor.knownlist;
 
 import net.sf.l2j.gameserver.model.L2Object;
 import net.sf.l2j.gameserver.model.actor.instance.L2DoorInstance;
+import net.sf.l2j.gameserver.model.actor.instance.L2FortSiegeGuardInstance;
 import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
 import net.sf.l2j.gameserver.model.actor.instance.L2SiegeGuardInstance;
 
@@ -45,7 +46,7 @@ public class DoorKnownList extends CharKnownList
     @Override
 	public int getDistanceToForgetObject(L2Object object)
     {
-        if (object instanceof L2SiegeGuardInstance) return 800;
+        if (object instanceof L2SiegeGuardInstance || object instanceof L2FortSiegeGuardInstance) return 800;
     	if (!(object instanceof L2PcInstance))
             return 0;
 
@@ -55,7 +56,7 @@ public class DoorKnownList extends CharKnownList
     @Override
 	public int getDistanceToWatchObject(L2Object object)
     {
-    	if (object instanceof L2SiegeGuardInstance) return 600;
+    	if (object instanceof L2SiegeGuardInstance || object instanceof L2FortSiegeGuardInstance) return 600;
     	if (!(object instanceof L2PcInstance))
             return 0;
         return 2000;

+ 13 - 13
L2_GameServer/java/net/sf/l2j/gameserver/model/actor/knownlist/CommanderKnownList.java → L2_GameServer/java/net/sf/l2j/gameserver/model/actor/knownlist/FortSiegeGuardKnownList.java

@@ -18,17 +18,18 @@ import net.sf.l2j.gameserver.ai.CtrlIntention;
 import net.sf.l2j.gameserver.model.L2Character;
 import net.sf.l2j.gameserver.model.L2Object;
 import net.sf.l2j.gameserver.model.L2Summon;
-import net.sf.l2j.gameserver.model.actor.instance.L2CommanderInstance;
+import net.sf.l2j.gameserver.model.actor.instance.L2FortCommanderInstance;
+import net.sf.l2j.gameserver.model.actor.instance.L2FortSiegeGuardInstance;
 import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
 
-public class CommanderKnownList extends AttackableKnownList
+public class FortSiegeGuardKnownList extends AttackableKnownList
 {
     // =========================================================
     // Data Field
 
     // =========================================================
     // Constructor
-    public CommanderKnownList(L2CommanderInstance activeChar)
+    public FortSiegeGuardKnownList(L2FortSiegeGuardInstance activeChar)
     {
         super(activeChar);
     }
@@ -36,9 +37,9 @@ public class CommanderKnownList extends AttackableKnownList
     // =========================================================
     // Method - Public
     @Override
-    public boolean addKnownObject(L2Object object) { return addKnownObject(object, null); }
+	public boolean addKnownObject(L2Object object) { return addKnownObject(object, null); }
     @Override
-    public boolean addKnownObject(L2Object object, L2Character dropper)
+	public boolean addKnownObject(L2Object object, L2Character dropper)
     {
         if (!super.addKnownObject(object, dropper)) return false;
 
@@ -54,21 +55,20 @@ public class CommanderKnownList extends AttackableKnownList
             // Check if player is not the defender
             if (player != null && (player.getClan() == null || getActiveChar().getFort().getSiege().getAttackerClan(player.getClan()) != null))
             {
-                //System.out.println(getActiveChar().getName()+": PK "+player.getObjectId()+" entered scan range");
                 if (getActiveChar().getAI().getIntention() == CtrlIntention.AI_INTENTION_IDLE)
-                    getActiveChar().getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE, null);//(L2Character)object);
+                    getActiveChar().getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE, null);
             }
-
         }
-
         return true;
     }
 
-    // =========================================================
-    // Method - Private
-
     // =========================================================
     // Property - Public
     @Override
-    public final L2CommanderInstance getActiveChar() { return (L2CommanderInstance)super.getActiveChar(); }
+	public final L2FortSiegeGuardInstance getActiveChar()
+    {
+    	if (super.getActiveChar() instanceof L2FortCommanderInstance)
+    		return (L2FortCommanderInstance)super.getActiveChar();
+    	return (L2FortSiegeGuardInstance)super.getActiveChar();
+    }
 }

+ 2 - 1
L2_GameServer/java/net/sf/l2j/gameserver/model/actor/knownlist/PcKnownList.java

@@ -258,7 +258,8 @@ public class PcKnownList extends PlayableKnownList
             {
                 // Update the state of the L2Character object client side by sending Server->Client packet MoveToPawn/CharMoveToLocation and AutoAttackStart to the L2PcInstance
                 L2Character obj = (L2Character) object;
-                obj.getAI().describeStateToPlayer(getActiveChar());
+                if (obj.getAI() != null)
+                	obj.getAI().describeStateToPlayer(getActiveChar());
             }
         }
 

+ 64 - 0
L2_GameServer/java/net/sf/l2j/gameserver/model/actor/knownlist/StaticObjectKnownList.java

@@ -0,0 +1,64 @@
+/*
+ * 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 3 of the License, or (at your option) any later
+ * version.
+ * 
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package net.sf.l2j.gameserver.model.actor.knownlist;
+
+import net.sf.l2j.gameserver.model.L2Object;
+import net.sf.l2j.gameserver.model.actor.instance.L2FortSiegeGuardInstance;
+import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
+import net.sf.l2j.gameserver.model.actor.instance.L2SiegeGuardInstance;
+import net.sf.l2j.gameserver.model.actor.instance.L2StaticObjectInstance;
+
+public class StaticObjectKnownList extends CharKnownList
+{
+    // =========================================================
+    // Data Field
+
+    // =========================================================
+    // Constructor
+    public StaticObjectKnownList(L2StaticObjectInstance activeChar)
+    {
+        super(activeChar);
+    }
+
+    // =========================================================
+    // Method - Public
+
+    // =========================================================
+    // Method - Private
+
+    // =========================================================
+    // Property - Public
+    @Override
+	public final L2StaticObjectInstance getActiveChar() { return (L2StaticObjectInstance)super.getActiveChar(); }
+
+    @Override
+	public int getDistanceToForgetObject(L2Object object)
+    {
+        if (object instanceof L2SiegeGuardInstance || object instanceof L2FortSiegeGuardInstance) return 800;
+    	if (!(object instanceof L2PcInstance))
+            return 0;
+
+        return 4000;
+    }
+
+    @Override
+	public int getDistanceToWatchObject(L2Object object)
+    {
+    	if (object instanceof L2SiegeGuardInstance || object instanceof L2FortSiegeGuardInstance) return 600;
+    	if (!(object instanceof L2PcInstance))
+            return 0;
+        return 2000;
+    }
+}

+ 46 - 0
L2_GameServer/java/net/sf/l2j/gameserver/model/actor/stat/StaticObjStat.java

@@ -0,0 +1,46 @@
+/*
+ * 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 3 of the License, or (at your option) any later
+ * version.
+ * 
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package net.sf.l2j.gameserver.model.actor.stat;
+
+import net.sf.l2j.gameserver.model.actor.instance.L2StaticObjectInstance;
+
+public class StaticObjStat extends CharStat
+{
+    // =========================================================
+    // Data Field
+
+    // =========================================================
+    // Constructor
+    public StaticObjStat(L2StaticObjectInstance activeChar)
+    {
+        super(activeChar);
+
+        setLevel((byte)1);
+    }
+
+    // =========================================================
+    // Method - Public
+
+    // =========================================================
+    // Method - Private
+
+    // =========================================================
+    // Property - Public
+    @Override
+	public L2StaticObjectInstance getActiveChar() { return (L2StaticObjectInstance)super.getActiveChar(); }
+
+    @Override
+	public final byte getLevel() { return 1; }
+}

+ 3 - 1
L2_GameServer/java/net/sf/l2j/gameserver/model/actor/status/CharStatus.java

@@ -26,6 +26,7 @@ import net.sf.l2j.gameserver.ai.CtrlIntention;
 import net.sf.l2j.gameserver.instancemanager.DuelManager;
 import net.sf.l2j.gameserver.model.L2Attackable;
 import net.sf.l2j.gameserver.model.L2Character;
+import net.sf.l2j.gameserver.model.actor.instance.L2FortBallistaInstance;
 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.L2SummonInstance;
@@ -121,7 +122,8 @@ public class CharStatus
     
     public void reduceHp(double value, L2Character attacker, boolean awake, boolean isDOT)
     {
-        if (getActiveChar().isInvul())
+    	if (getActiveChar() instanceof L2FortBallistaInstance && getActiveChar().getMaxHp() == value){}
+    	else if (getActiveChar().isInvul())
             return;
         if (getActiveChar().isDead())
             return;

+ 41 - 0
L2_GameServer/java/net/sf/l2j/gameserver/model/actor/status/StaticObjStatus.java

@@ -0,0 +1,41 @@
+/*
+ * 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 3 of the License, or (at your option) any later
+ * version.
+ * 
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package net.sf.l2j.gameserver.model.actor.status;
+
+import net.sf.l2j.gameserver.model.actor.instance.L2StaticObjectInstance;
+
+public class StaticObjStatus extends CharStatus
+{
+    // =========================================================
+    // Data Field
+
+    // =========================================================
+    // Constructor
+    public StaticObjStatus(L2StaticObjectInstance activeChar)
+    {
+        super(activeChar);
+    }
+
+    // =========================================================
+    // Method - Public
+
+    // =========================================================
+    // Method - Private
+
+    // =========================================================
+    // Property - Public
+    @Override
+	public L2StaticObjectInstance getActiveChar() { return (L2StaticObjectInstance)super.getActiveChar(); }
+}

+ 1 - 1
L2_GameServer/java/net/sf/l2j/gameserver/model/entity/Castle.java

@@ -509,7 +509,7 @@ public class Castle
 		
 		// if clan have fortress, remove it
 		if (clan.getHasFort() > 0)
-			FortManager.getInstance().getFortByOwner(clan).removeOwner(clan);
+			FortManager.getInstance().getFortByOwner(clan).removeOwner(true);
 		
 		if (getSiege().getIsInProgress()) // If siege in progress
 			getSiege().midVictory(); // Mid victory phase of siege

+ 317 - 131
L2_GameServer/java/net/sf/l2j/gameserver/model/entity/Fort.java

@@ -17,8 +17,8 @@ package net.sf.l2j.gameserver.model.entity;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.util.Calendar;
+import java.util.Collection;
 import java.util.List;
-import java.util.Map;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -26,19 +26,23 @@ import javolution.util.FastList;
 import javolution.util.FastMap;
 import net.sf.l2j.Config;
 import net.sf.l2j.L2DatabaseFactory;
-import net.sf.l2j.gameserver.Announcements;
 import net.sf.l2j.gameserver.FortUpdater;
 import net.sf.l2j.gameserver.ThreadPoolManager;
 import net.sf.l2j.gameserver.datatables.ClanTable;
 import net.sf.l2j.gameserver.datatables.DoorTable;
+import net.sf.l2j.gameserver.datatables.StaticObjects;
 import net.sf.l2j.gameserver.instancemanager.FortManager;
 import net.sf.l2j.gameserver.model.L2Clan;
 import net.sf.l2j.gameserver.model.L2Object;
+import net.sf.l2j.gameserver.model.L2World;
 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.L2StaticObjectInstance;
 import net.sf.l2j.gameserver.model.zone.type.L2FortZone;
+import net.sf.l2j.gameserver.network.SystemMessageId;
 import net.sf.l2j.gameserver.network.serverpackets.PlaySound;
 import net.sf.l2j.gameserver.network.serverpackets.PledgeShowInfoUpdate;
+import net.sf.l2j.gameserver.network.serverpackets.SystemMessage;
 
 public class Fort
 {
@@ -48,15 +52,20 @@ public class Fort
 	// Data Field
 	private int _fortId = 0;
 	private List<L2DoorInstance> _doors = new FastList<L2DoorInstance>();
+	private L2StaticObjectInstance _flagPole = null;
 	private List<String> _doorDefault = new FastList<String>();
+	private List<String> _flagPoleStats = new FastList<String>();
 	private String _name = "";
-	private int _ownerId = 0;
+	private FortManager	_spawnManager;
 	private FortSiege _siege = null;
 	private Calendar _siegeDate;
 	private Calendar _lastOwnedTime;
 	private L2FortZone _zone;
-	private L2Clan _formerOwner = null;
-	private Map<Integer, FortFunction> _function;
+	private L2Clan _fortOwner = null;
+	private int _fortType = 0;
+	private int _state = 0;
+	private int _castleId = 0;
+	private FastMap<Integer, FortFunction> _function;
 	
 	/** Fortress Functions */
 	public static final int FUNC_TELEPORT = 1;
@@ -129,7 +138,7 @@ public class Fort
 		
 		private void initializeTask(boolean cwh)
 		{
-			if (getOwnerId() <= 0)
+			if (getOwnerClan() == null)
 				return;
 			long currentTime = System.currentTimeMillis();
 			if (_endDate > currentTime)
@@ -149,9 +158,9 @@ public class Fort
 			{
 				try
 				{
-					if (getOwnerId() <= 0)
+					if (getOwnerClan() == null)
 						return;
-					if (ClanTable.getInstance().getClan(getOwnerId()).getWarehouse().getAdena() >= _fee || !_cwh)
+					if (getOwnerClan().getWarehouse().getAdena() >= _fee || !_cwh)
 					{
 						int fee = _fee;
 						boolean newfc = true;
@@ -169,7 +178,7 @@ public class Fort
 						dbSave(newfc);
 						if (_cwh)
 						{
-							ClanTable.getInstance().getClan(getOwnerId()).getWarehouse().destroyItemByItemId("CS_function_fee", 57, fee, null, null);
+							getOwnerClan().getWarehouse().destroyItemByItemId("CS_function_fee", 57, fee, null, null);
 							if (Config.DEBUG)
 								_log.warning("deducted " + fee + " adena from " + getName() + " owner's cwh for function id : " + getType());
 						}
@@ -226,6 +235,7 @@ public class Fort
 				}
 				catch (Exception e)
 				{
+					e.printStackTrace();
 				}
 			}
 		}
@@ -238,13 +248,16 @@ public class Fort
 		_fortId = fortId;
 		load();
 		loadDoor();
+		loadFlagPoles();
 		_function = new FastMap<Integer, FortFunction>();
-		if (getOwnerId() != 0)
+		if (getOwnerClan() != null)
 		{
+			setVisibleFlag(true);
 			loadFunctions();
 		}
+		_spawnManager = new FortManager(this);
 	}
-	
+		
 	/** Return function with id */
 	public FortFunction getFunction(int type)
 	{
@@ -253,19 +266,42 @@ public class Fort
 		return null;
 	}
 	
+	public class ScheduleSpecialEnvoysDeSpawn implements Runnable
+	{
+		private Fort _fortInst;
+		
+		public ScheduleSpecialEnvoysDeSpawn(Fort pFort)
+		{
+			_fortInst = pFort;
+		}
+		
+		public void run()
+		{
+			try
+			{
+				// if state not decided, change state to indenpendent
+				if (_fortInst.getFortState() == 0)
+					_fortInst.setFortState(1,0);
+				_fortInst.getSpawnManager().despawnSpecialEnvoys();
+			}
+			catch (Exception e)
+			{
+				_log.warning("Exception: ScheduleSpecialEnvoysSpawn() for Fort: "+_fortInst.getName()+" " + e.getMessage());
+				e.printStackTrace();
+			}
+		}
+	}	
 	// =========================================================
 	// Method - Public
 	
 	public void EndOfSiege(L2Clan clan)
 	{
 		ThreadPoolManager.getInstance().scheduleGeneral(new endFortressSiege(this, clan), 1000);
-		
 	}
 	
-	public void Engrave(L2Clan clan, int objId)
+	public void Engrave(L2Clan clan)
 	{
-		getSiege().announceToPlayer("Clan " + clan.getName() + " has finished to raise the flag.", true);
-		setOwner(clan);
+		setOwner(clan, true);
 	}
 	
 	/**
@@ -273,7 +309,7 @@ public class Fort
 	 */
 	public void banishForeigners()
 	{
-		_zone.banishForeigners(getOwnerId());
+		_zone.banishForeigners(getOwnerClan());
 	}
 	
 	/**
@@ -300,7 +336,7 @@ public class Fort
 	
 	/**
 	 * Get the objects distance to this fort
-	 * @param obj
+	 * @param object
 	 * @return
 	 */
 	public double getDistance(L2Object obj)
@@ -320,7 +356,7 @@ public class Fort
 	
 	public void openCloseDoor(L2PcInstance activeChar, int doorId, boolean open)
 	{
-		if (activeChar.getClanId() != getOwnerId())
+		if (activeChar.getClan() != getOwnerClan())
 			return;
 		
 		L2DoorInstance door = getDoor(doorId);
@@ -339,88 +375,83 @@ public class Fort
 		removeDoorUpgrade();
 	}
 	
-	// This method updates the fort tax rate
-	public void setOwner(L2Clan clan)
+	/**
+	 * This method will set owner for Fort
+	 * @param clan
+	 * @param updateClanPoints
+	 */
+	public boolean setOwner(L2Clan clan, boolean updateClansReputation)
 	{
+		if (updateClansReputation)
+		{
+			// update reputation first
+			updateClansReputation(clan);
+		}
 		// Remove old owner
-		if (getOwnerId() > 0 && (clan == null || clan.getClanId() != getOwnerId()))
+		if (getOwnerClan() != null && (clan != null && clan != getOwnerClan()))
 		{
-			L2Clan oldOwner = ClanTable.getInstance().getClan(getOwnerId()); // Try to find clan instance
-			if (oldOwner != null)
-			{
-				if (_formerOwner == null)
-				{
-					_formerOwner = oldOwner;
-				}
-				oldOwner.setHasFort(0); // Unset has fort flag for old owner
-				Announcements.getInstance().announceToAll(oldOwner.getName() + " has lost " + getName() + " fortress!");
-				
-			}
+			removeOwner(true);
+		}
+		setFortState(0,0); // initialize fort state
+		//	if clan already have castle, don't store him in fortress
+		if (clan.getHasCastle() > 0)
+		{
+			getSiege().announceToPlayer(new SystemMessage(SystemMessageId.NPCS_RECAPTURED_FORTRESS),0,false);
+			return false;
 		}
-		
-		// if clan have already fortress, remove it
-		if (clan.getHasFort() > 0)
-			FortManager.getInstance().getFortByOwner(clan).removeOwner(clan);
-		
-		//if clan already have castle, dont store him in fortress
-		if (clan.getHasCastle() <= 0)
-			updateOwnerInDB(clan); // Update in database
 		else
 		{
-			getSiege().setHasCastle();
-			updateOwnerInDB(null);
+			getSpawnManager().spawnSpecialEnvoys();
+			ThreadPoolManager.getInstance().scheduleGeneral(new ScheduleSpecialEnvoysDeSpawn(this), 1*60*60*1000); // Prepare 1hr task for special envoys despawn
+			// if clan have already fortress, remove it
+			if (clan.getHasFort() > 0)
+				FortManager.getInstance().getFortByOwner(clan).removeOwner(true);
+
+			setOwnerClan(clan);
+			updateOwnerInDB(); // Update in database
+
+			if (getSiege().getIsInProgress()) // If siege in progress
+				getSiege().endSiege();
+			return true;
 		}
-		
-		if (getSiege().getIsInProgress()) // If siege in progress
-			getSiege().midVictory(); // Mid victory phase of siege
-			
-		updateClansReputation();
 	}
 	
-	public void removeOwner(L2Clan clan)
+	public void removeOwner(boolean updateDB)
 	{
+		L2Clan clan = getOwnerClan();
 		if (clan != null)
 		{
-			_formerOwner = clan;
 			clan.setHasFort(0);
-			Announcements.getInstance().announceToAll(clan.getName() + " has lost " + getName() + " fort");
 			clan.broadcastToOnlineMembers(new PledgeShowInfoUpdate(clan));
+			setOwnerClan(null);
+			if (updateDB)
+				updateOwnerInDB();
+
 		}
-		
-		updateOwnerInDB(null);
-		if (getSiege().getIsInProgress())
-			getSiege().midVictory();
-		
-		updateClansReputation();
 	}
-	
 	/**
-	 * Respawn all doors on fort grounds<BR><BR>
+	 * Show or hide flag inside flagpole<BR><BR>
 	 */
-	public void spawnDoor()
+	public void setVisibleFlag(boolean val)
 	{
-		spawnDoor(false);
+			L2StaticObjectInstance flagPole = getFlagPole();
+			if (flagPole != null)
+				flagPole.setMeshIndex(val ? 1:0);
 	}
-	
 	/**
 	 * Respawn all doors on fort grounds<BR><BR>
 	 */
-	public void spawnDoor(boolean isDoorWeak)
+	public void resetDoors()
 	{
 		for (int i = 0; i < getDoors().size(); i++)
 		{
 			L2DoorInstance door = getDoors().get(i);
-			if (door.getCurrentHp() <= 0)
-			{
-				door.decayMe(); // Kill current if not killed already
-				door = DoorTable.parseList(_doorDefault.get(i));
-				if (isDoorWeak)
-					door.setCurrentHp(door.getMaxHp() / 2);
-				door.spawnMe(door.getX(), door.getY(), door.getZ());
-				getDoors().set(i, door);
-			}
-			else if (door.getOpen())
+			if (door.getOpen())
 				door.closeMe();
+			if (door.getCurrentHp() <= 0)
+				door.doRevive();
+			if (door.getCurrentHp() < door.getMaxHp())
+				door.setCurrentHp(door.getMaxHp());
 		}
 		loadDoorUpgrade(); // Check for any upgrade the doors may have
 	}
@@ -457,28 +488,34 @@ public class Fort
 			statement = con.prepareStatement("Select * from fort where id = ?");
 			statement.setInt(1, getFortId());
 			rs = statement.executeQuery();
+			int ownerId = 0;
 			
 			while (rs.next())
 			{
 				_name = rs.getString("name");
-				//_OwnerId = rs.getInt("ownerId");
 				
 				_siegeDate = Calendar.getInstance();
 				_lastOwnedTime = Calendar.getInstance();
 				_siegeDate.setTimeInMillis(rs.getLong("siegeDate"));
 				_lastOwnedTime.setTimeInMillis(rs.getLong("lastOwnedTime"));
-				_ownerId = rs.getInt("owner");
+				ownerId = rs.getInt("owner");
+				_fortType = rs.getInt("fortType");
+				_state = rs.getInt("state");
+				_castleId = rs.getInt("castleId");
 			}
 			
 			rs.close();
 			statement.close();
 			
-			if (getOwnerId() > 0)
+			if (ownerId > 0)
 			{
-				L2Clan clan = ClanTable.getInstance().getClan(getOwnerId()); // Try to find clan instance
+				L2Clan clan = ClanTable.getInstance().getClan(ownerId); // Try to find clan instance
 				clan.setHasFort(getFortId());
+				setOwnerClan(clan);
 				ThreadPoolManager.getInstance().scheduleGeneral(new FortUpdater(clan, 1), 3600000); // Schedule owner tasks to start running
 			}
+			else
+				setOwnerClan(null);
 			
 		}
 		catch (Exception e)
@@ -494,6 +531,8 @@ public class Fort
 			}
 			catch (Exception e)
 			{
+            	_log.warning(""+e.getMessage());
+            	e.printStackTrace();
 			}
 		}
 	}
@@ -568,7 +607,7 @@ public class Fort
 		if (player == null)
 			return false;
 		if (Config.DEBUG)
-			_log.warning("Called Fort.updateFunctions(int type, int lvl, int lease, long rate, boolean addNew) Owner : " + getOwnerId());
+			_log.warning("Called Fort.updateFunctions(int type, int lvl, int lease, long rate, boolean addNew) Owner : " + getOwnerClan());
 		if (lease > 0)
 			if (!player.destroyItemByItemId("Consume", 57, lease, null, true))
 				return false;
@@ -608,19 +647,19 @@ public class Fort
 		try
 		{
 			con = L2DatabaseFactory.getInstance().getConnection();
-			PreparedStatement statement = con.prepareStatement("Select * from fort_door where fortId = ?");
+			PreparedStatement statement = con.prepareStatement("Select * from fort_staticobjects where fortId = ? and objectType = ?");
 			statement.setInt(1, getFortId());
+			statement.setInt(2, 0);
 			ResultSet rs = statement.executeQuery();
 			
 			while (rs.next())
 			{
 				// Create list of the door default for use when respawning dead doors
 				_doorDefault.add(rs.getString("name") + ";" + rs.getInt("id") + ";" + rs.getInt("x") + ";" + rs.getInt("y") + ";" + rs.getInt("z") + ";" + rs.getInt("range_xmin") + ";" + rs.getInt("range_ymin") + ";"
-						+ rs.getInt("range_zmin") + ";" + rs.getInt("range_xmax") + ";" + rs.getInt("range_ymax") + ";" + rs.getInt("range_zmax") + ";" + rs.getInt("hp") + ";" + rs.getInt("pDef") + ";" + rs.getInt("mDef")+ ";" + rs.getBoolean("openType"));
-				
-				L2DoorInstance door = DoorTable.parseList(_doorDefault.get(_doorDefault.size() - 1));
+						+ rs.getInt("range_zmin") + ";" + rs.getInt("range_xmax") + ";" + rs.getInt("range_ymax") + ";" + rs.getInt("range_zmax") + ";" + rs.getInt("hp") + ";" + rs.getInt("pDef") + ";" + rs.getInt("mDef")+ ";" + rs.getBoolean("openType")+ ";" + rs.getBoolean("commanderDoor"));
+				L2DoorInstance door;
+				_doors.add(door = DoorTable.parseList(_doorDefault.get(_doorDefault.size() - 1)));
 				door.spawnMe(door.getX(), door.getY(), door.getZ());
-				_doors.add(door);
 				DoorTable.getInstance().putDoor(door);
 			}
 			
@@ -640,10 +679,52 @@ public class Fort
 			}
 			catch (Exception e)
 			{
+            	_log.warning(""+e.getMessage());
+            	e.printStackTrace();
 			}
 		}
 	}
 	
+	// This method loads fort flagpoles data from database
+	private void loadFlagPoles()
+	{
+		java.sql.Connection con = null;
+		try
+		{
+			con = L2DatabaseFactory.getInstance().getConnection();
+			PreparedStatement statement = con.prepareStatement("Select * from fort_staticobjects where fortId = ? and objectType = ?");
+			statement.setInt(1, getFortId());
+			statement.setInt(2, 1);
+			ResultSet rs = statement.executeQuery();
+			while (rs.next())
+			{
+				//Create list of the door default for use when respawning dead doors
+				_flagPoleStats.add(rs.getString("name") + ";" + rs.getInt("id") + ";" + rs.getInt("x") + ";" + rs.getInt("y") + ";" + rs.getInt("z") + ";3;none;0;0");
+				_flagPole = StaticObjects.parse(_flagPoleStats.get(_flagPoleStats.size() - 1));
+				StaticObjects.getInstance().putObject(_flagPole);
+			}
+			rs.close();
+			statement.close();
+		}
+		catch (Exception e)
+		{
+			_log.warning("Exception: loadFlagPoles(): " + e.getMessage());
+			e.printStackTrace();
+		}
+		finally
+		{
+			try
+			{
+				con.close();
+			}
+			catch (Exception e)
+			{
+            	_log.warning(""+e.getMessage());
+            	e.printStackTrace();
+			}
+		}
+	}
+
 	// This method loads fort door upgrade data from database
 	private void loadDoorUpgrade()
 	{
@@ -651,8 +732,9 @@ public class Fort
 		try
 		{
 			con = L2DatabaseFactory.getInstance().getConnection();
-			PreparedStatement statement = con.prepareStatement("Select * from fort_doorupgrade where doorId in (Select Id from fort_door where fortId = ?)");
+			PreparedStatement statement = con.prepareStatement("Select * from fort_doorupgrade where doorId in (Select Id from fort_staticobjects where fortId = ? and objectType = ?)");
 			statement.setInt(1, getFortId());
+			statement.setInt(2, 0);
 			ResultSet rs = statement.executeQuery();
 			
 			while (rs.next())
@@ -675,6 +757,8 @@ public class Fort
 			}
 			catch (Exception e)
 			{
+            	_log.warning(""+e.getMessage());
+            	e.printStackTrace();
 			}
 		}
 	}
@@ -685,8 +769,9 @@ public class Fort
 		try
 		{
 			con = L2DatabaseFactory.getInstance().getConnection();
-			PreparedStatement statement = con.prepareStatement("delete from fort_doorupgrade where doorId in (select id from fort_door where fortId=?)");
+			PreparedStatement statement = con.prepareStatement("delete from fort_doorupgrade where doorId in (select id from fort_staticobjects where fortId=? and objectType = ?)");
 			statement.setInt(1, getFortId());
+			statement.setInt(2, 0);
 			statement.execute();
 			statement.close();
 		}
@@ -703,6 +788,8 @@ public class Fort
 			}
 			catch (Exception e)
 			{
+            	_log.warning(""+e.getMessage());
+            	e.printStackTrace();
 			}
 		}
 	}
@@ -734,42 +821,53 @@ public class Fort
 			}
 			catch (Exception e)
 			{
+            	_log.warning(""+e.getMessage());
+            	e.printStackTrace();
 			}
 		}
 	}
 	
-	private void updateOwnerInDB(L2Clan clan)
+	private void updateOwnerInDB()
 	{
+		L2Clan clan = getOwnerClan();
+		int clanId = 0;
 		if (clan != null)
-			_ownerId = clan.getClanId(); // Update owner id property
-		else
-			_ownerId = 0; // Remove owner
-			
-		if (_ownerId != 0)
+		{
+			clanId = clan.getClanId();
 			_lastOwnedTime.setTimeInMillis(System.currentTimeMillis());
+		}
 		else
 			_lastOwnedTime.setTimeInMillis(0);
-		
+
 		java.sql.Connection con = null;
 		try
 		{
 			con = L2DatabaseFactory.getInstance().getConnection();
 			PreparedStatement statement;
-			
-			statement = con.prepareStatement("UPDATE fort SET owner=?,lastOwnedTime=? where id = ?");
-			statement.setInt(1, getOwnerId());
+
+			statement = con.prepareStatement("UPDATE fort SET owner=?,lastOwnedTime=?,state=?,castleId=? where id = ?");
+			statement.setInt(1, clanId);
 			statement.setLong(2, _lastOwnedTime.getTimeInMillis());
-			statement.setInt(3, getFortId());
+			statement.setInt(3, 0);
+			statement.setInt(4, 0);
+			statement.setInt(5, getFortId());
 			statement.execute();
 			statement.close();
-			
+
 			// ============================================================================
-			
 			// Announce to clan memebers
 			if (clan != null)
 			{
 				clan.setHasFort(getFortId()); // Set has fort flag for new owner
-				Announcements.getInstance().announceToAll(clan.getName() + " has taken " + getName() + " fort!");
+				SystemMessage sm;
+				sm = new SystemMessage(SystemMessageId.S1_CLAN_IS_VICTORIOUS_IN_THE_FORTRESS_BATTLE_OF_S2);
+				sm.addString(clan.getName());
+				sm.addFortId(getFortId());
+				Collection<L2PcInstance> pls = L2World.getInstance().getAllPlayers().values();
+				for (L2PcInstance player : pls)
+				{
+						player.sendPacket(sm);
+				}
 				clan.broadcastToOnlineMembers(new PledgeShowInfoUpdate(clan));
 				clan.broadcastToOnlineMembers(new PlaySound(1, "Siege_Victory", 0, 0, 0, 0, 0));
 				ThreadPoolManager.getInstance().scheduleGeneral(new FortUpdater(clan, 1), 3600000); // Schedule owner tasks to start running
@@ -788,22 +886,28 @@ public class Fort
 			}
 			catch (Exception e)
 			{
+            	_log.warning(""+e.getMessage());
+            	e.printStackTrace();
 			}
 		}
 	}
-	
-	// =========================================================
-	// Property
+
 	public final int getFortId()
 	{
 		return _fortId;
 	}
 	
-	public final int getOwnerId()
+	public final L2Clan getOwnerClan()
 	{
-		return _ownerId;
+		return _fortOwner;
 	}
-	
+
+	public final void setOwnerClan(L2Clan clan)
+	{
+		setVisibleFlag(clan != null ? true : false);
+		_fortOwner = clan;
+	}
+
 	public final L2DoorInstance getDoor(int doorId)
 	{
 		if (doorId <= 0)
@@ -821,7 +925,12 @@ public class Fort
 	{
 		return _doors;
 	}
-	
+
+	public final L2StaticObjectInstance getFlagPole()
+	{
+		return _flagPole;
+	}
+
 	public final FortSiege getSiege()
 	{
 		if (_siege == null)
@@ -855,33 +964,12 @@ public class Fort
 		return _name;
 	}
 	
-	public void updateClansReputation()
+	public void updateClansReputation(L2Clan owner)
 	{
-		if (_formerOwner != null)
-		{
-			if (_formerOwner != ClanTable.getInstance().getClan(getOwnerId()))
-			{
-				int maxreward = Math.max(0, _formerOwner.getReputationScore());
-				L2Clan owner = ClanTable.getInstance().getClan(getOwnerId());
-				if (owner != null)
-				{
-					owner.setReputationScore(owner.getReputationScore() + Math.min(500, maxreward), true);
-					owner.broadcastToOnlineMembers(new PledgeShowInfoUpdate(owner));
-				}
-			}
-			else
-				_formerOwner.setReputationScore(_formerOwner.getReputationScore() + 250, true);
-			
-			_formerOwner.broadcastToOnlineMembers(new PledgeShowInfoUpdate(_formerOwner));
-		}
-		else
+		if (owner != null)
 		{
-			L2Clan owner = ClanTable.getInstance().getClan(getOwnerId());
-			if (owner != null)
-			{
-				owner.setReputationScore(owner.getReputationScore() + 500, true);
-				owner.broadcastToOnlineMembers(new PledgeShowInfoUpdate(owner));
-			}
+			owner.setReputationScore(owner.getReputationScore() + 200, true);
+			owner.broadcastToOnlineMembers(new PledgeShowInfoUpdate(owner));
 		}
 	}
 	private class endFortressSiege implements Runnable
@@ -897,8 +985,106 @@ public class Fort
 		
 		public void run()
 		{
-			_f.Engrave(_clan, 0);
+			try
+			{
+				_f.Engrave(_clan);
+			}
+			catch (Exception e)
+			{
+            	_log.warning("Exception in endFortressSiege "+e.getMessage());
+            	e.printStackTrace();
+			}
 		}
 		
 	}
+
+	/**
+	 * @return Returns state of fortress.<BR><BR>
+	 * 0 - not decided yet<BR>
+	 * 1 - independent<BR>
+	 * 2 - contracted with castle<BR>
+	 */
+	public final int getFortState()
+	{
+		return _state;
+	}
+
+	/**
+	 * @param State.<BR>
+	 * 0 - not decided yet<BR>
+	 * 1 - independent<BR>
+	 * 2 - contracted with castle<BR><BR>
+	 * @param CastleId.<BR>
+	 * set Castle Id for contracted fort
+	 */
+	public final void setFortState(int state, int castleId)
+	{
+		_state = state;
+		_castleId = castleId;
+		java.sql.Connection con = null;
+		try
+		{
+			con = L2DatabaseFactory.getInstance().getConnection();
+			PreparedStatement statement;
+
+			statement = con.prepareStatement("UPDATE fort SET state=?,castleId=? where id = ?");
+			statement.setInt(1, getFortState());
+			statement.setInt(2, getCastleId());
+			statement.setInt(3, getFortId());
+			statement.execute();
+			statement.close();
+
+		}
+		catch (Exception e)
+		{
+			_log.warning("Exception: setFortState(int state, int castleId): " + e.getMessage());
+			e.printStackTrace();
+		}
+		finally
+		{
+			try
+			{
+				con.close();
+			}
+			catch (Exception e)
+			{
+            	_log.warning(""+e.getMessage());
+            	e.printStackTrace();
+			}
+		}
+	}
+	/**
+	 * @return Returns Castle Id of fortress contracted with castle.
+	 */
+	public final int getCastleId()
+	{
+		return _castleId;
+	}
+
+	/**
+	 * @return Returns fortress type.<BR><BR>
+	 * 0 - small (3 commanders) <BR>
+	 * 1 - big (4 commanders + control room)
+	 */
+	public final int getFortType()
+	{
+		return _fortType;
+	}
+
+	public final int getCastleIdFromEnvoy(int npcId)
+	{
+		return getSpawnManager().getEnvoyCastle(npcId);
+	}
+	/**
+	 * @return Returns amount of barracks.
+	 */
+	public final int getFortSize()
+	{
+		return getFortType() == 0 ? 3 : 5;
+	}
+	
+	public FortManager getSpawnManager()
+	{
+		return _spawnManager;
+	}
 }

File diff suppressed because it is too large
+ 326 - 407
L2_GameServer/java/net/sf/l2j/gameserver/model/entity/FortSiege.java


+ 78 - 20
L2_GameServer/java/net/sf/l2j/gameserver/model/zone/type/L2FortZone.java

@@ -15,9 +15,16 @@
 package net.sf.l2j.gameserver.model.zone.type;
 
 import javolution.util.FastList;
+import net.sf.l2j.gameserver.datatables.ClanTable;
 import net.sf.l2j.gameserver.datatables.MapRegionTable;
+import net.sf.l2j.gameserver.datatables.SkillTable;
 import net.sf.l2j.gameserver.instancemanager.FortManager;
+import net.sf.l2j.gameserver.instancemanager.FortSiegeManager;
 import net.sf.l2j.gameserver.model.L2Character;
+import net.sf.l2j.gameserver.model.L2Clan;
+import net.sf.l2j.gameserver.model.L2Effect;
+import net.sf.l2j.gameserver.model.L2SiegeClan;
+import net.sf.l2j.gameserver.model.L2Skill;
 import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
 import net.sf.l2j.gameserver.model.actor.instance.L2SiegeSummonInstance;
 import net.sf.l2j.gameserver.model.entity.Fort;
@@ -73,29 +80,25 @@ public class L2FortZone extends L2ZoneType
 	@Override
 	protected void onEnter(L2Character character)
 	{
+		character.setInsideZone(L2Character.ZONE_FORT, true);
 		if (_fort.getSiege().getIsInProgress())
 		{
 			character.setInsideZone(L2Character.ZONE_PVP, true);
 			character.setInsideZone(L2Character.ZONE_SIEGE, true);
-			character.setInsideZone(L2Character.ZONE_FORT, true);
-			character.setInsideZone(L2Character.ZONE_NOSUMMONFRIEND, true);
 			
 			if (character instanceof L2PcInstance)
 				((L2PcInstance) character).sendPacket(new SystemMessage(SystemMessageId.ENTERED_COMBAT_ZONE));
 		}
-		else
-			character.setInsideZone(L2Character.ZONE_FORT, true);
 	}
 	
 	@Override
 	protected void onExit(L2Character character)
 	{
+		character.setInsideZone(L2Character.ZONE_FORT, false);
 		if (_fort.getSiege().getIsInProgress())
 		{
 			character.setInsideZone(L2Character.ZONE_PVP, false);
 			character.setInsideZone(L2Character.ZONE_SIEGE, false);
-			character.setInsideZone(L2Character.ZONE_FORT, false);
-			character.setInsideZone(L2Character.ZONE_NOSUMMONFRIEND, false);
 			
 			if (character instanceof L2PcInstance)
 			{
@@ -106,25 +109,80 @@ public class L2FortZone extends L2ZoneType
 					((L2PcInstance) character).startPvPFlag();
 			}
 		}
-		else
-			character.setInsideZone(L2Character.ZONE_FORT, true);
-		
 		if (character instanceof L2SiegeSummonInstance)
 		{
 			((L2SiegeSummonInstance) character).unSummon(((L2SiegeSummonInstance) character).getOwner());
 		}
+		if (character instanceof L2PcInstance)
+		{
+			L2PcInstance activeChar = ((L2PcInstance)character);
+	        if (activeChar.getInventory().getItemByItemId(9819) != null)
+	        {
+	        	Fort fort = FortManager.getInstance().getFort(activeChar);
+	        	if (fort != null)
+	        	{
+	        		FortSiegeManager.getInstance().dropCombatFlag(activeChar);
+	        	}
+	        	else
+	        	{
+	        		int slot = activeChar.getInventory().getSlotFromItem(activeChar.getInventory().getItemByItemId(9819));
+	            	activeChar.getInventory().unEquipItemInBodySlotAndRecord(slot);
+	        		activeChar.destroyItem("CombatFlag", activeChar.getInventory().getItemByItemId(9819), null, true);
+	        	}
+	        }
+		}
 	}
 	
 	@Override
 	public void onDieInside(L2Character character)
 	{
+		if (_fort.getSiege().getIsInProgress())
+		{
+			// debuff participants only if they die inside siege zone
+			if (character instanceof L2PcInstance && ((L2PcInstance) character).getClan() != null)
+			{
+				int lvl = 1;
+				for (L2Effect effect: character.getAllEffects())
+				{
+					if (effect != null && effect.getSkill().getId() == 5660)
+					{
+						lvl = lvl+effect.getLevel();
+						if (lvl > 5)
+							lvl = 5;
+						break;
+					}
+				}
+				L2Clan clan;
+				L2Skill skill;
+				if (_fort.getOwnerClan() == ((L2PcInstance)character).getClan())
+				{
+					skill = SkillTable.getInstance().getInfo(5660, lvl);
+					if (skill != null)
+						skill.getEffects(character, character);
+				}
+				else
+				{
+					for (L2SiegeClan siegeclan : _fort.getSiege().getAttackerClans())
+					{
+						if (siegeclan == null)
+							continue;
+						clan = ClanTable.getInstance().getClan(siegeclan.getClanId());
+						if (((L2PcInstance) character).getClan() == clan)
+						{
+							skill = SkillTable.getInstance().getInfo(5660, lvl);
+							if (skill != null)
+								skill.getEffects(character, character);
+							break;
+						}
+					}
+				}
+			}
+		}
 	}
-	
+
 	@Override
-	public void onReviveInside(L2Character character)
-	{
-	}
-	
+	public void onReviveInside(L2Character character) {}
+
 	public void updateZoneStatusForCharactersInside()
 	{
 		if (_fort.getSiege().getIsInProgress())
@@ -137,6 +195,7 @@ public class L2FortZone extends L2ZoneType
 				}
 				catch (NullPointerException e)
 				{
+					e.printStackTrace();
 				}
 			}
 		}
@@ -148,8 +207,6 @@ public class L2FortZone extends L2ZoneType
 				{
 					character.setInsideZone(L2Character.ZONE_PVP, false);
 					character.setInsideZone(L2Character.ZONE_SIEGE, false);
-					character.setInsideZone(L2Character.ZONE_FORT, false);
-					character.setInsideZone(L2Character.ZONE_NOSUMMONFRIEND, false);
 					
 					if (character instanceof L2PcInstance)
 						((L2PcInstance) character).sendPacket(new SystemMessage(SystemMessageId.LEFT_COMBAT_ZONE));
@@ -160,6 +217,7 @@ public class L2FortZone extends L2ZoneType
 				}
 				catch (NullPointerException e)
 				{
+					e.printStackTrace();
 				}
 			}
 		}
@@ -167,18 +225,18 @@ public class L2FortZone extends L2ZoneType
 	
 	/**
 	 * Removes all foreigners from the fort
-	 * @param owningClanId
+	 * @param owningClan
 	 */
-	public void banishForeigners(int owningClanId)
+	public void banishForeigners(L2Clan owningClan)
 	{
 		for (L2Character temp : _characterList.values())
 		{
 			if (!(temp instanceof L2PcInstance))
 				continue;
-			if (((L2PcInstance) temp).getClanId() == owningClanId)
+			if (((L2PcInstance) temp).getClan() == owningClan)
 				continue;
 			
-			((L2PcInstance) temp).teleToLocation(MapRegionTable.TeleportWhereType.Town);
+			((L2PcInstance) temp).teleToLocation(MapRegionTable.TeleportWhereType.Town); // TODO: shouldnt be town, its outside of fort
 		}
 	}
 	

+ 10 - 10
L2_GameServer/java/net/sf/l2j/gameserver/network/SystemMessageId.java

@@ -12508,13 +12508,13 @@ public enum SystemMessageId
 	* ID: 2089<br>
 	* Message: $s1 minute(s) until the fortress battle starts.
 	*/
-	S1_MINUTES_UNTIL_THE_FORTRESS_BATTLE_STARTS2(2089),
+	S1_SECONDS_UNTIL_THE_FORTRESS_BATTLE_STARTS(2089),
 
 	/**
 	* ID: 2090<br>
 	* Message: The fortress battle $s1 has begun.
 	*/
-	THE_FORTRESS_BATTLE_S1_AS_BEGUN(2090),
+	THE_FORTRESS_BATTLE_S1_HAS_BEGUN(2090),
 
 	/**
 	* ID: 2091<br>
@@ -12972,17 +12972,11 @@ public enum SystemMessageId
 	*/
 	BARRACKS_FUNCTION_RESTORED(2165),
 
-	/**
-	* ID: 2165<br>
-	* Message: The door of the commanding barracks has been opened.
-	*/
-	BARRACKS_DOOR_OPENED1(2165),
-
 	/**
 	* ID: 2166<br>
-	* Message: The door of the commanding barracks has been opened.
+	* Message: All barracks are occupied.
 	*/
-	BARRACKS_DOOR_OPENED2(2166),
+	ALL_BARRACKS_OCCUPIED(2166),
 
 	/**
 	* ID: 2167<br>
@@ -13633,6 +13627,12 @@ public enum SystemMessageId
 	*/
 	SKILL_NOT_FOR_SUBCLASS(2273),
 	
+	/**
+	* ID: 2276<br>
+	* Message: The rebel army recaptured the fortress.
+	*/
+	NPCS_RECAPTURED_FORTRESS(2276),
+
 	/**
 	* ID: 2303<br>
 	* Message: There are $s2 second(s) remaining in $s1's re-use time.

+ 28 - 3
L2_GameServer/java/net/sf/l2j/gameserver/network/clientpackets/EnterWorld.java

@@ -37,6 +37,8 @@ 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.DimensionalRiftManager;
+import net.sf.l2j.gameserver.instancemanager.FortManager;
+import net.sf.l2j.gameserver.instancemanager.FortSiegeManager;
 import net.sf.l2j.gameserver.instancemanager.InstanceManager;
 import net.sf.l2j.gameserver.instancemanager.PetitionManager;
 import net.sf.l2j.gameserver.instancemanager.RaidBossPointsManager;
@@ -48,6 +50,8 @@ import net.sf.l2j.gameserver.model.L2World;
 import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
 import net.sf.l2j.gameserver.model.entity.ClanHall;
 import net.sf.l2j.gameserver.model.entity.Couple;
+import net.sf.l2j.gameserver.model.entity.Fort;
+import net.sf.l2j.gameserver.model.entity.FortSiege;
 import net.sf.l2j.gameserver.model.entity.Hero;
 import net.sf.l2j.gameserver.model.entity.L2Event;
 import net.sf.l2j.gameserver.model.entity.Siege;
@@ -165,6 +169,14 @@ public class EnterWorld extends L2GameClientPacket
                 else if (siege.checkIsDefender(activeChar.getClan()))
                     activeChar.setSiegeState((byte)2);
             }
+            for (FortSiege siege : FortSiegeManager.getInstance().getSieges())
+            {
+                if (!siege.getIsInProgress()) continue;
+                if (siege.checkIsAttacker(activeChar.getClan()))
+                    activeChar.setSiegeState((byte)1);
+                else if (siege.checkIsDefender(activeChar.getClan()))
+                    activeChar.setSiegeState((byte)2);
+            }
         }
         
         if (Hero.getInstance().getHeroes() != null &&
@@ -357,14 +369,27 @@ public class EnterWorld extends L2GameClientPacket
                 }
             }
         }
-
+        // remove combat flag before teleporting
+        if (activeChar.getInventory().getItemByItemId(9819) != null)
+        {
+        	Fort fort = FortManager.getInstance().getFort(activeChar);
+        	if (fort != null)
+        	{
+        		FortSiegeManager.getInstance().dropCombatFlag(activeChar);
+        	}
+        	else
+        	{
+        		int slot = activeChar.getInventory().getSlotFromItem(activeChar.getInventory().getItemByItemId(9819));
+            	activeChar.getInventory().unEquipItemInBodySlotAndRecord(slot);
+        		activeChar.destroyItem("CombatFlag", activeChar.getInventory().getItemByItemId(9819), null, true);
+        	}
+        }
         if (!activeChar.isGM() && activeChar.getSiegeState() < 2 && activeChar.isInsideZone(L2Character.ZONE_SIEGE))
         {
             // Attacker or spectator logging in to a siege zone. Actually should be checked for inside castle only?
             activeChar.teleToLocation(MapRegionTable.TeleportWhereType.Town);
-            activeChar.sendMessage("You have been teleported to the nearest town due to you being in siege zone");
+            //activeChar.sendMessage("You have been teleported to the nearest town due to you being in siege zone"); - custom
         }
-        
         RegionBBSManager.getInstance().changeCommunityBoard();
         
         TvTEvent.onLogin(activeChar);

+ 5 - 0
L2_GameServer/java/net/sf/l2j/gameserver/network/clientpackets/RequestActionUse.java

@@ -280,6 +280,11 @@ public final class RequestActionUse extends L2GameClientPacket
 						SystemMessage msg = new SystemMessage(SystemMessageId.STRIDER_CANT_BE_RIDDEN_WHILE_IN_BATTLE);
 						activeChar.sendPacket(msg);
 					}
+					else if (activeChar.getInventory().getItemByItemId(9819) != null)
+			        {
+						SystemMessage msg = new SystemMessage(SystemMessageId.YOU_CANNOT_MOUNT_A_STEED_WHILE_HOLDING_A_FLAG);
+						activeChar.sendPacket(msg);
+			        }
 					else if (!pet.isDead() && !activeChar.isMounted())
 					{
 						activeChar.mount(pet);

+ 16 - 2
L2_GameServer/java/net/sf/l2j/gameserver/network/clientpackets/RequestFortressSiegeInfo.java

@@ -14,6 +14,11 @@
  */
 package net.sf.l2j.gameserver.network.clientpackets;
 
+import net.sf.l2j.gameserver.instancemanager.FortManager;
+import net.sf.l2j.gameserver.model.entity.Fort;
+import net.sf.l2j.gameserver.network.L2GameClient;
+import net.sf.l2j.gameserver.network.serverpackets.ExShowFortressSiegeInfo;
+
 /**
  *
  * @author  KenM
@@ -45,7 +50,16 @@ public class RequestFortressSiegeInfo extends L2GameClientPacket
     @Override
     protected void runImpl()
     {
-        // send ExShowFortressSiegeInfo for fortress that are under siege now
+        L2GameClient client = this.getClient();
+        if (client != null)
+        {
+        	for (Fort fort : FortManager.getInstance().getForts())
+        	{
+        		if (fort != null && fort.getSiege().getIsInProgress())
+        		{
+        			client.sendPacket(new ExShowFortressSiegeInfo(fort));
+        		}
+        	}
+        }
     }
-    
 }

+ 39 - 70
L2_GameServer/java/net/sf/l2j/gameserver/network/clientpackets/RequestJoinSiege.java

@@ -16,10 +16,8 @@
 package net.sf.l2j.gameserver.network.clientpackets;
 
 import net.sf.l2j.gameserver.instancemanager.CastleManager;
-import net.sf.l2j.gameserver.instancemanager.FortManager;
 import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
 import net.sf.l2j.gameserver.model.entity.Castle;
-import net.sf.l2j.gameserver.model.entity.Fort;
 import net.sf.l2j.gameserver.network.SystemMessageId;
 import net.sf.l2j.gameserver.network.serverpackets.SystemMessage;
 
@@ -29,80 +27,51 @@ import net.sf.l2j.gameserver.network.serverpackets.SystemMessage;
  */
 public final class RequestJoinSiege extends L2GameClientPacket
 {
-    private static final String _C__A4_RequestJoinSiege = "[C] a4 RequestJoinSiege";
-    //private static Logger _log = Logger.getLogger(RequestJoinSiege.class.getName());
+	private static final String _C__A4_RequestJoinSiege = "[C] a4 RequestJoinSiege";
+	//private static Logger _log = Logger.getLogger(RequestJoinSiege.class.getName());
 
-    private int _castleId;
-    private int _isAttacker;
-    private int _isJoining;
+	private int _castleId;
+	private int _isAttacker;
+	private int _isJoining;
 
-    @Override
+	@Override
 	protected void readImpl()
-    {
-        _castleId = readD();
-        _isAttacker = readD();
-        _isJoining = readD();
-    }
+	{
+		_castleId = readD();
+		_isAttacker = readD();
+		_isJoining = readD();
+	}
 
-    @Override
+	@Override
 	protected void runImpl()
-    {
-        L2PcInstance activeChar = getClient().getActiveChar();
-        if(activeChar == null) return;
-        if (!activeChar.isClanLeader()) return;
+	{
+		L2PcInstance activeChar = getClient().getActiveChar();
+		if(activeChar == null) return;
+		if (!activeChar.isClanLeader()) return;
 
-        if (_castleId < 100)
-        {
-            Castle castle = CastleManager.getInstance().getCastleById(_castleId);
-            if (castle == null) return;
-    
-            if (_isJoining == 1)
-            {
-            	if (System.currentTimeMillis() < activeChar.getClan().getDissolvingExpiryTime())
-            	{
-            		activeChar.sendPacket(new SystemMessage(SystemMessageId.CANT_PARTICIPATE_IN_SIEGE_WHILE_DISSOLUTION_IN_PROGRESS));
-            		return;
-            	}
-                if (_isAttacker == 1)
-                    castle.getSiege().registerAttacker(activeChar);
-                else
-                    castle.getSiege().registerDefender(activeChar);
-            }
-            else
-                castle.getSiege().removeSiegeClan(activeChar);
-    
-            castle.getSiege().listRegisterClan(activeChar);
-        }
-        else
-        {
-            Fort fort = FortManager.getInstance().getFortById(_castleId);
-            if (fort == null) return;
-    
-            if (_isJoining == 1)
-            {
-                if (System.currentTimeMillis() < activeChar.getClan().getDissolvingExpiryTime())
-                {
-                    activeChar.sendPacket(new SystemMessage(SystemMessageId.CANT_PARTICIPATE_IN_SIEGE_WHILE_DISSOLUTION_IN_PROGRESS));
-                    return;
-                }
-                if (_isAttacker == 1)
-                    fort.getSiege().registerAttacker(activeChar);
-                else
-                    fort.getSiege().registerDefender(activeChar);
-            }
-            else
-                fort.getSiege().removeSiegeClan(activeChar);
-    
-            fort.getSiege().listRegisterClan(activeChar);
-        }
-            
+		Castle castle = CastleManager.getInstance().getCastleById(_castleId);
+		if (castle == null) return;
 
-    }
+		if (_isJoining == 1)
+		{
+			if (System.currentTimeMillis() < activeChar.getClan().getDissolvingExpiryTime())
+			{
+				activeChar.sendPacket(new SystemMessage(SystemMessageId.CANT_PARTICIPATE_IN_SIEGE_WHILE_DISSOLUTION_IN_PROGRESS));
+				return;
+			}
+			if (_isAttacker == 1)
+				castle.getSiege().registerAttacker(activeChar);
+			else
+				castle.getSiege().registerDefender(activeChar);
+		}
+		else
+			castle.getSiege().removeSiegeClan(activeChar);
+		castle.getSiege().listRegisterClan(activeChar);
+	}
 
-
-    @Override
+	@Override
 	public String getType()
-    {
-        return _C__A4_RequestJoinSiege;
-    }
-}
+	{
+		return _C__A4_RequestJoinSiege;
+	}
+}

+ 0 - 6
L2_GameServer/java/net/sf/l2j/gameserver/network/clientpackets/RequestRestartPoint.java

@@ -125,12 +125,6 @@ public final class RequestRestartPoint extends L2GameClientPacket
 				case 3: // to fortress
 					fort = FortManager.getInstance().getFort(activeChar);
 
-					if (fort != null && fort.getSiege().getIsInProgress())
-					{
-						//siege in progress
-						if (fort.getSiege().checkIsDefender(activeChar.getClan()))
-							isInDefense = true;
-					}
 					if ((activeChar.getClan() == null || activeChar.getClan().getHasFort() == 0) && !isInDefense)
 					{
 						_log.warning("Player ["+activeChar.getName()+"] called RestartPointPacket - To Fortress and he doesn't have Fortress!");

+ 1 - 15
L2_GameServer/java/net/sf/l2j/gameserver/network/clientpackets/RequestSiegeAttackerList.java

@@ -16,10 +16,7 @@
 package net.sf.l2j.gameserver.network.clientpackets;
 
 import net.sf.l2j.gameserver.instancemanager.CastleManager;
-import net.sf.l2j.gameserver.instancemanager.FortManager;
 import net.sf.l2j.gameserver.model.entity.Castle;
-import net.sf.l2j.gameserver.model.entity.Fort;
-import net.sf.l2j.gameserver.network.serverpackets.FortSiegeAttackerList;
 import net.sf.l2j.gameserver.network.serverpackets.SiegeAttackerList;
 
 /**
@@ -44,21 +41,10 @@ public final class RequestSiegeAttackerList extends L2GameClientPacket
     @Override
 	protected void runImpl()
     {
-        if (_castleId < 100)
-        {
             Castle castle = CastleManager.getInstance().getCastleById(_castleId);
             if (castle == null) return;
             SiegeAttackerList sal = new SiegeAttackerList(castle);
-            sendPacket(sal);
-        }
-        else
-        {
-            Fort fort = FortManager.getInstance().getFortById(_castleId);
-            if (fort == null) return;
-            FortSiegeAttackerList sal = new FortSiegeAttackerList(fort);
-            sendPacket(sal);
-        }
-            
+            sendPacket(sal);      
     }
 
 

+ 4 - 18
L2_GameServer/java/net/sf/l2j/gameserver/network/clientpackets/RequestSiegeDefenderList.java

@@ -16,10 +16,7 @@
 package net.sf.l2j.gameserver.network.clientpackets;
 
 import net.sf.l2j.gameserver.instancemanager.CastleManager;
-import net.sf.l2j.gameserver.instancemanager.FortManager;
 import net.sf.l2j.gameserver.model.entity.Castle;
-import net.sf.l2j.gameserver.model.entity.Fort;
-import net.sf.l2j.gameserver.network.serverpackets.FortSiegeDefenderList;
 import net.sf.l2j.gameserver.network.serverpackets.SiegeDefenderList;
 
 /**
@@ -43,21 +40,10 @@ public final class RequestSiegeDefenderList extends L2GameClientPacket
     @Override
 	protected void runImpl()
     {
-        if (_castleId < 100 )
-        {
-            Castle castle = CastleManager.getInstance().getCastleById(_castleId);
-            if (castle == null) return;
-            SiegeDefenderList sdl = new SiegeDefenderList(castle);
-            sendPacket(sdl);
-        }
-        else
-        {
-            Fort fort = FortManager.getInstance().getFortById(_castleId);
-            if (fort == null) return;
-            FortSiegeDefenderList sdl = new FortSiegeDefenderList(fort);
-            sendPacket(sdl);
-        }
-
+    	Castle castle = CastleManager.getInstance().getCastleById(_castleId);
+    	if (castle == null) return;
+    	SiegeDefenderList sdl = new SiegeDefenderList(castle);
+    	sendPacket(sdl);
     }
 
 

+ 12 - 0
L2_GameServer/java/net/sf/l2j/gameserver/network/clientpackets/UseItem.java

@@ -22,6 +22,7 @@ import net.sf.l2j.gameserver.ThreadPoolManager;
 import net.sf.l2j.gameserver.handler.IItemHandler;
 import net.sf.l2j.gameserver.handler.ItemHandler;
 import net.sf.l2j.gameserver.instancemanager.CastleManager;
+import net.sf.l2j.gameserver.instancemanager.FortSiegeManager;
 import net.sf.l2j.gameserver.model.L2Clan;
 import net.sf.l2j.gameserver.model.L2ItemInstance;
 import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
@@ -292,6 +293,12 @@ public final class UseItem extends L2GameClientPacket
                     case L2Item.SLOT_L_HAND:
                     case L2Item.SLOT_R_HAND:
                     {
+                    	// prevent players to equip weapon while wearing combat flag
+                    	if (activeChar.getActiveWeaponItem() != null && activeChar.getActiveWeaponItem().getItemId() == 9819)
+                    	{
+                    		activeChar.sendPacket(new SystemMessage(SystemMessageId.CANNOT_EQUIP_ITEM_DUE_TO_BAD_CONDITION));
+                        	return;
+                    	}
                         // Prevent player to remove the weapon on special conditions
                     	if (activeChar.isCastingNow() || activeChar.isCastingSimultaneouslyNow())
                     	{
@@ -300,7 +307,10 @@ public final class UseItem extends L2GameClientPacket
                     	}
                     	
                         if (activeChar.isMounted())
+                        {
+                        	activeChar.sendPacket(new SystemMessage(SystemMessageId.CANNOT_EQUIP_ITEM_DUE_TO_BAD_CONDITION));
                         	return;
+                        }
                         
                        
                         if (activeChar.isDisarmed())
@@ -563,6 +573,8 @@ public final class UseItem extends L2GameClientPacket
                 	return;
                 }
                 // Equip or unEquip
+                if(FortSiegeManager.getInstance().isCombat(item.getItemId()))
+                		return;	//no message
                 activeChar.useEquippableItem(item, true);
 			}
 			else

+ 5 - 15
L2_GameServer/java/net/sf/l2j/gameserver/network/serverpackets/ExShowFortressInfo.java

@@ -15,9 +15,7 @@
 package net.sf.l2j.gameserver.network.serverpackets;
 
 import java.util.List;
-import java.util.logging.Logger;
 
-import net.sf.l2j.gameserver.datatables.ClanTable;
 import net.sf.l2j.gameserver.instancemanager.FortManager;
 import net.sf.l2j.gameserver.model.L2Clan;
 import net.sf.l2j.gameserver.model.entity.Fort;
@@ -28,7 +26,7 @@ import net.sf.l2j.gameserver.model.entity.Fort;
  */
 public class ExShowFortressInfo extends L2GameServerPacket
 {
-    private static final Logger _log = Logger.getLogger(ExShowFortressInfo.class.getName());
+    //private static final Logger _log = Logger.getLogger(ExShowFortressInfo.class.getName());
 	
 	/**
      * @see net.sf.l2j.gameserver.network.serverpackets.L2GameServerPacket#getType()
@@ -51,26 +49,18 @@ public class ExShowFortressInfo extends L2GameServerPacket
         writeD(forts.size());
         for (Fort fort : forts)
         {
+        	L2Clan clan = fort.getOwnerClan();
             writeD(fort.getFortId());
-            if (fort.getOwnerId() > 0)
+            if (clan != null)
             {
-                L2Clan clan = ClanTable.getInstance().getClan(fort.getOwnerId());
-                if (clan != null)
-                {
-                    writeS(clan.getName());
-                }
-                else
-                {
-                    _log.warning("No owner clan for fortress: "+fort.getName()+" - Owner Id: "+fort.getOwnerId());
-                    writeS("");
-                }
+            	writeS(clan.getName());
             }
             else
             {
                 writeS("");
             }
             
-            if ((fort.getSiege().getIsScheduled()) || (fort.getSiege().getIsInProgress()))
+            if (fort.getSiege().getIsInProgress())
             {
                 writeD(1);
             }

+ 61 - 5
L2_GameServer/java/net/sf/l2j/gameserver/network/serverpackets/ExShowFortressMapInfo.java

@@ -14,6 +14,10 @@
  */
 package net.sf.l2j.gameserver.network.serverpackets;
 
+import javolution.util.FastList;
+import net.sf.l2j.gameserver.instancemanager.FortSiegeManager;
+import net.sf.l2j.gameserver.instancemanager.FortSiegeManager.SiegeSpawn;
+import net.sf.l2j.gameserver.model.L2Spawn;
 import net.sf.l2j.gameserver.model.entity.Fort;
 
 /**
@@ -48,11 +52,63 @@ public class ExShowFortressMapInfo extends L2GameServerPacket
         writeH(0x7d);
         
         writeD(_fortress.getFortId());
-        writeD(0); // fortress siege status
-        writeD(0); // barracks count
+        writeD(_fortress.getSiege().getIsInProgress() ? 1 : 0); // fortress siege status
+        writeD(_fortress.getFortSize()); // barracks count
         
-        // foreach barrack do:
-        // writeD() barrack status
+        FastList<SiegeSpawn> commanders = FortSiegeManager.getInstance().getCommanderSpawnList(_fortress.getFortId());
+        if (commanders != null && commanders.size() != 0 && _fortress.getSiege().getIsInProgress())
+        {
+        	switch (commanders.size())
+        	{
+        		case 3:
+        		{
+        			for (SiegeSpawn spawn : commanders)
+        			{
+        				if (isSpawned(spawn.getNpcId()))
+        					writeD(0);
+        				else
+        					writeD(1);
+        			}
+        			break;
+        		}
+        		case 4: // TODO: change 4 to 5 once control room supported
+        		{
+        			int count = 0;
+        			for (SiegeSpawn spawn : commanders)
+        			{
+        				count++;
+        				if (count == 4)
+        					writeD(1); // TODO: control room emulated
+        				if (isSpawned(spawn.getNpcId()))
+     						writeD(0);
+        				else
+        					writeD(1);
+        			}
+        			break;
+        		}
+        	}
+        }
+        else
+        {
+        	for (int i = 0; i <_fortress.getFortSize(); i++)
+        	{
+        		writeD(0);
+        	}
+        }
+    }
+
+    /**
+     * @param npcId
+     * @return
+     */
+    private boolean isSpawned(int npcId)
+    {
+    	boolean ret = false;
+    	for (L2Spawn spawn : _fortress.getSiege().getCommanders().get(_fortress.getFortId()))
+    	{
+    		if (spawn.getNpcid() == npcId)
+    			ret = true;
+    	}
+    	return ret;
     }
-    
 }

+ 71 - 4
L2_GameServer/java/net/sf/l2j/gameserver/network/serverpackets/ExShowFortressSiegeInfo.java

@@ -14,6 +14,11 @@
  */
 package net.sf.l2j.gameserver.network.serverpackets;
 
+import javolution.util.FastList;
+import net.sf.l2j.gameserver.instancemanager.FortSiegeManager;
+import net.sf.l2j.gameserver.instancemanager.FortSiegeManager.SiegeSpawn;
+import net.sf.l2j.gameserver.model.entity.Fort;
+
 /**
  *
  * @author  KenM
@@ -21,7 +26,21 @@ package net.sf.l2j.gameserver.network.serverpackets;
 public class ExShowFortressSiegeInfo extends L2GameServerPacket
 {
 
-    /**
+    private int _fortId;
+	private int _size;
+	private Fort _fort;
+
+	/**
+	 * @param fortId
+	 */
+	public ExShowFortressSiegeInfo(Fort fort)
+	{
+		_fort = fort;
+		_fortId = fort.getFortId();
+		_size = fort.getFortSize();
+	}
+
+	/**
      * @see net.sf.l2j.gameserver.network.serverpackets.L2GameServerPacket#getType()
      */
     @Override
@@ -39,9 +58,57 @@ public class ExShowFortressSiegeInfo extends L2GameServerPacket
         writeC(0xfe);
         writeH(0x17);
         
-        writeD(0x00); // Fortress Id
-        writeD(0x00); // Total Barracks Count
-        writeD(0x00); // Captured Barracks Count
+        writeD(_fortId); // Fortress Id
+        writeD(_size); // Total Barracks Count
+        FastList<SiegeSpawn> commanders = FortSiegeManager.getInstance().getCommanderSpawnList(_fortId);
+        if (commanders != null && commanders.size() != 0)
+        {
+        	switch (commanders.size())
+        	{
+        		case 3:
+        			switch (_fort.getSiege().getCommanders().get(_fortId).size())
+        			{
+        				case 0:
+        					writeD(0x03);
+        					break;
+        				case 1:
+        					writeD(0x02);
+        					break;
+        				case 2:
+        					writeD(0x01);
+        					break;
+        				case 3:
+        					writeD(0x00);
+        					break;
+        			}
+        			break;
+        		case 4: // TODO: change 4 to 5 once control room supported
+        			switch (_fort.getSiege().getCommanders().get(_fortId).size()) // TODO: once control room supported, update writeD(0x0x) to support 5th room
+        			{
+        				case 0:
+        					writeD(0x05);
+        					break;
+        				case 1:
+        					writeD(0x04);
+        					break;
+        				case 2:
+        					writeD(0x03);
+        					break;
+        				case 3:
+        					writeD(0x02);
+        					break;
+        				case 4:
+        					writeD(0x01);
+        					break;
+        			}
+        			break;
+        	}
+        }
+        else
+        {
+        	for(int i=0;i<_size;i++)
+        		writeD(0x00);
+        }
     }
     
 }

+ 0 - 108
L2_GameServer/java/net/sf/l2j/gameserver/network/serverpackets/FortSiegeAttackerList.java

@@ -1,108 +0,0 @@
-/*
- * 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 3 of the License, or (at your option) any later
- * version.
- * 
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
- * details.
- * 
- * You should have received a copy of the GNU General Public License along with
- * this program. If not, see <http://www.gnu.org/licenses/>.
- */
-package net.sf.l2j.gameserver.network.serverpackets;
-
-//import java.util.Calendar; //signed time related
-//import java.util.logging.Logger;
-
-import net.sf.l2j.gameserver.datatables.ClanTable;
-import net.sf.l2j.gameserver.model.L2Clan;
-import net.sf.l2j.gameserver.model.L2SiegeClan;
-import net.sf.l2j.gameserver.model.entity.Fort;
-/**
- * Populates the Siege Attacker List in the SiegeInfo Window<BR>
- * <BR>
- * packet type id 0xca<BR>
- * format: cddddddd + dSSdddSSd<BR>
- * <BR>
- * c = ca<BR>
- * d = FortID<BR>
- * d = unknow (0x00)<BR>
- * d = unknow (0x01)<BR>
- * d = unknow (0x00)<BR>
- * d = Number of Attackers Clans?<BR>
- * d = Number of Attackers Clans<BR>
- * { //repeats<BR>
- * d = ClanID<BR>
- * S = ClanName<BR>
- * S = ClanLeaderName<BR>
- * d = ClanCrestID<BR>
- * d = signed time (seconds)<BR>
- * d = AllyID<BR>
- * S = AllyName<BR>
- * S = AllyLeaderName<BR>
- * d = AllyCrestID<BR>
- *
- * @author KenM
- */
-public final class FortSiegeAttackerList extends L2GameServerPacket
-{
-    private static final String _S__CA_SiegeAttackerList = "[S] ca SiegeAttackerList";
-    //private static Logger _log = Logger.getLogger(SiegeAttackerList.class.getName());
-    private Fort _fort;
-
-    public FortSiegeAttackerList(Fort fort)
-    {
-        _fort = fort;
-    }
-
-    @Override
-    protected final void writeImpl()
-    {
-        writeC(0xca);
-        writeD(_fort.getFortId());
-        writeD(0x00); //0
-        writeD(0x01); //1
-        writeD(0x00); //0
-        int size = _fort.getSiege().getAttackerClans().size();
-        if (size > 0)
-        {
-            L2Clan clan;
-
-            writeD(size);
-            writeD(size);
-            for(L2SiegeClan siegeclan : _fort.getSiege().getAttackerClans())
-            {
-                clan = ClanTable.getInstance().getClan(siegeclan.getClanId());
-                if (clan == null) continue;
-
-                writeD(clan.getClanId());
-                writeS(clan.getName());
-                writeS(clan.getLeaderName());
-                writeD(clan.getCrestId());
-                writeD(0x00); //signed time (seconds) (not storated by L2J)
-                writeD(clan.getAllyId());
-                writeS(clan.getAllyName());
-                writeS(""); //AllyLeaderName
-                writeD(clan.getAllyCrestId());
-            }
-        }
-        else
-        {
-            writeD(0x00);
-            writeD(0x00);
-        }
-    }
-
-    /* (non-Javadoc)
-     * @see net.sf.l2j.gameserver.serverpackets.ServerBasePacket#getType()
-     */
-    @Override
-    public String getType()
-    {
-        return _S__CA_SiegeAttackerList;
-    }
-
-}

+ 0 - 139
L2_GameServer/java/net/sf/l2j/gameserver/network/serverpackets/FortSiegeDefenderList.java

@@ -1,139 +0,0 @@
-/*
- * 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 3 of the License, or (at your option) any later
- * version.
- * 
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
- * details.
- * 
- * You should have received a copy of the GNU General Public License along with
- * this program. If not, see <http://www.gnu.org/licenses/>.
- */
-package net.sf.l2j.gameserver.network.serverpackets;
-
-//import java.util.Calendar; //signed time related
-//import java.util.logging.Logger;
-
-import net.sf.l2j.gameserver.datatables.ClanTable;
-import net.sf.l2j.gameserver.model.L2Clan;
-import net.sf.l2j.gameserver.model.L2SiegeClan;
-import net.sf.l2j.gameserver.model.entity.Fort;
-/**
- * Populates the Siege Defender List in the SiegeInfo Window<BR>
- * <BR>
- * packet type id 0xcb<BR>
- * format: cddddddd + dSSdddSSd<BR>
- * <BR>
- * c = 0xcb<BR>
- * d = FortID<BR>
- * d = unknow (0x00)<BR>
- * d = unknow (0x01)<BR>
- * d = unknow (0x00)<BR>
- * d = Number of Defending Clans?<BR>
- * d = Number of Defending Clans<BR>
- * { //repeats<BR>
- * d = ClanID<BR>
- * S = ClanName<BR>
- * S = ClanLeaderName<BR>
- * d = ClanCrestID<BR>
- * d = signed time (seconds)<BR>
- * d = Type -> Owner = 0x01 || Waiting = 0x02 || Accepted = 0x03<BR>
- * d = AllyID<BR>
- * S = AllyName<BR>
- * S = AllyLeaderName<BR>
- * d = AllyCrestID<BR>
- *
- * @author KenM
- */
-public final class FortSiegeDefenderList extends L2GameServerPacket
-{
-    private static final String _S__CA_SiegeDefenderList = "[S] cb SiegeDefenderList";
-    //private static Logger _log = Logger.getLogger(SiegeDefenderList.class.getName());
-    private Fort _fort;
-
-    public FortSiegeDefenderList(Fort fort)
-    {
-        _fort = fort;
-    }
-
-    @Override
-    protected final void writeImpl()
-    {
-        writeC(0xcb);
-        writeD(_fort.getFortId());
-        writeD(0x00);  //0
-        writeD(0x01);  //1
-        writeD(0x00);  //0
-        int size = _fort.getSiege().getDefenderClans().size() + _fort.getSiege().getDefenderWaitingClans().size();
-        if (size > 0)
-        {
-            L2Clan clan;
-
-            writeD(size);
-            writeD(size);
-            // Listing the Lord and the approved clans
-            for(L2SiegeClan siegeclan : _fort.getSiege().getDefenderClans())
-            {
-                clan = ClanTable.getInstance().getClan(siegeclan.getClanId());
-                if (clan == null) continue;
-
-                writeD(clan.getClanId());
-                writeS(clan.getName());
-                writeS(clan.getLeaderName());
-                writeD(clan.getCrestId());
-                writeD(0x00); //signed time (seconds) (not storated by L2J)
-                switch(siegeclan.getType())
-                {
-                    case OWNER:
-                        writeD(0x01); //owner
-                        break;
-                    case DEFENDER_PENDING:
-                        writeD(0x02); //approved
-                        break;
-                    case DEFENDER:
-                        writeD(0x03); // waiting approved
-                        break;
-                    default:
-                        writeD(0x00);
-                    break;
-                }
-                writeD(clan.getAllyId());
-                writeS(clan.getAllyName());
-                writeS(""); //AllyLeaderName
-                writeD(clan.getAllyCrestId());
-            }
-            for(L2SiegeClan siegeclan : _fort.getSiege().getDefenderWaitingClans())
-            {
-                clan = ClanTable.getInstance().getClan(siegeclan.getClanId());
-                writeD(clan.getClanId());
-                writeS(clan.getName());
-                writeS(clan.getLeaderName());
-                writeD(clan.getCrestId());
-                writeD(0x00); //signed time (seconds) (not storated by L2J)
-                writeD(0x02); //waiting approval
-                writeD(clan.getAllyId());
-                writeS(clan.getAllyName());
-                writeS(""); //AllyLeaderName
-                writeD(clan.getAllyCrestId());
-            }
-        }
-        else
-        {
-            writeD(0x00);
-            writeD(0x00);
-        }
-    }
-
-    /* (non-Javadoc)
-     * @see net.sf.l2j.gameserver.serverpackets.ServerBasePacket#getType()
-     */
-    @Override
-    public String getType()
-    {
-        return _S__CA_SiegeDefenderList;
-    }
-
-}

+ 0 - 101
L2_GameServer/java/net/sf/l2j/gameserver/network/serverpackets/FortressSiegeInfo.java

@@ -1,101 +0,0 @@
-/*
- * 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 3 of the License, or (at your option) any later
- * version.
- * 
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
- * details.
- * 
- * You should have received a copy of the GNU General Public License along with
- * this program. If not, see <http://www.gnu.org/licenses/>.
- */
-package net.sf.l2j.gameserver.network.serverpackets;
-
-import java.util.Calendar;
-import java.util.logging.Logger;
-
-import net.sf.l2j.gameserver.datatables.ClanTable;
-import net.sf.l2j.gameserver.model.L2Clan;
-import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
-import net.sf.l2j.gameserver.model.entity.Fort;
-
-/**
- * Shows the Siege Info<BR>
- * <BR>
- * packet type id 0xc9<BR>
- * format: cdddSSdSdd<BR>
- * <BR>
- * c = c9<BR>
- * d = FortID<BR>
- * d = Show Owner Controls (0x00 default || >=0x02(mask?) owner)<BR>
- * d = Owner ClanID<BR>
- * S = Owner ClanName<BR>
- * S = Owner Clan LeaderName<BR>
- * d = Owner AllyID<BR>
- * S = Owner AllyName<BR>
- * d = current time (seconds)<BR>
- * d = Siege time (seconds) (0 for selectable)<BR>
- * d = (UNKNOW) Siege Time Select Related?
- * 
- * @author KenM
- */
-public class FortressSiegeInfo extends L2GameServerPacket
-{
-    private static final String _S__C9_SIEGEINFO = "[S] c9 SiegeInfo";
-    private static Logger _log = Logger.getLogger(FortressSiegeInfo.class.getName());
-    private Fort _fort;
-
-    public FortressSiegeInfo(Fort fort)
-    {
-        _fort = fort;
-    }
-
-    @Override
-    protected final void writeImpl()
-    {
-        L2PcInstance activeChar = getClient().getActiveChar();
-        if (activeChar == null) return;
-
-        writeC(0xc9);
-        writeD(_fort.getFortId());
-        writeD(((_fort.getOwnerId() == activeChar.getClanId()) && (activeChar.isClanLeader())) ? 0x01 : 0x00);
-        writeD(_fort.getOwnerId());
-        if (_fort.getOwnerId() > 0)
-        {
-            L2Clan owner = ClanTable.getInstance().getClan(_fort.getOwnerId());
-            if (owner != null)
-            {
-                writeS(owner.getName());        // Clan Name
-                writeS(owner.getLeaderName());  // Clan Leader Name
-                writeD(owner.getAllyId());      // Ally ID
-                writeS(owner.getAllyName());    // Ally Name
-            }
-            else
-                _log.warning("Null owner for fort: " + _fort.getName());
-        }
-        else
-        {
-            writeS("NPC");  // Clan Name
-            writeS("");     // Clan Leader Name
-            writeD(0);      // Ally ID
-            writeS("");     // Ally Name
-        }
-
-        writeD((int) (Calendar.getInstance().getTimeInMillis()/1000));
-        writeD((int) (_fort.getSiege().getSiegeDate().getTimeInMillis()/1000));
-        writeD(0x00); //number of choices?
-    }
-
-    /* (non-Javadoc)
-     * @see net.sf.l2j.gameserver.serverpackets.ServerBasePacket#getType()
-     */
-    @Override
-    public String getType()
-    {
-        return _S__C9_SIEGEINFO;
-    }
-
-}

+ 1 - 1
L2_GameServer/java/net/sf/l2j/gameserver/network/serverpackets/StaticObject.java

@@ -42,7 +42,7 @@ public class StaticObject extends L2GameServerPacket
         _objectId = staticObject.getObjectId();
         _type = 0;
         _isTargetable = true;
-        _meshIndex = 0;
+        _meshIndex = staticObject.getMeshIndex();
         _isClosed = false;
         _isEnemy = false;
         _maxHp = 0;

+ 9 - 0
L2_GameServer/java/net/sf/l2j/gameserver/network/serverpackets/SystemMessage.java

@@ -37,6 +37,7 @@ public final class SystemMessage extends L2GameServerPacket
 	// d d (d S/d d/d dd)
 	//      |--------------> 0 - String  1-number 2-textref npcname (1000000-1002655)  3-textref itemname 4-textref skills 5-??
 	private static final int TYPE_ZONE_NAME = 7;
+	private static final int TYPE_FORTRESS = 5; // maybe not only for fortress, rename if needed
 	private static final int TYPE_SKILL_NAME = 4;
 	private static final int TYPE_ITEM_NAME = 3;
 	private static final int TYPE_NPC_NAME = 2;
@@ -75,6 +76,13 @@ public final class SystemMessage extends L2GameServerPacket
 		return this;
 	}
 
+	public SystemMessage addFortId(int number)
+	{
+		_types.add(new Integer(TYPE_FORTRESS));
+		_values.add(new Integer(number));
+		return this;
+	}
+
 	public SystemMessage addNumber(int number)
 	{
 		_types.add(Integer.valueOf(TYPE_NUMBER));
@@ -198,6 +206,7 @@ public final class SystemMessage extends L2GameServerPacket
 					writeS( (String)_values.get(i));
 					break;
 				}
+				case TYPE_FORTRESS:
 				case TYPE_NUMBER:
 				case TYPE_NPC_NAME:
 				case TYPE_ITEM_NAME:

+ 4 - 0
L2_GameServer/java/net/sf/l2j/gameserver/skills/effects/EffectFear.java

@@ -18,6 +18,8 @@ import net.sf.l2j.gameserver.ai.CtrlIntention;
 import net.sf.l2j.gameserver.model.L2CharPosition;
 import net.sf.l2j.gameserver.model.L2Effect;
 import net.sf.l2j.gameserver.model.actor.instance.L2FolkInstance;
+import net.sf.l2j.gameserver.model.actor.instance.L2FortCommanderInstance;
+import net.sf.l2j.gameserver.model.actor.instance.L2FortSiegeGuardInstance;
 import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
 import net.sf.l2j.gameserver.model.actor.instance.L2SiegeFlagInstance;
 import net.sf.l2j.gameserver.model.actor.instance.L2SiegeGuardInstance;
@@ -72,6 +74,8 @@ final class EffectFear extends L2Effect
 		
 		if (getEffected() instanceof L2FolkInstance
 		        || getEffected() instanceof L2SiegeGuardInstance
+		        || getEffected() instanceof L2FortSiegeGuardInstance
+		        || getEffected() instanceof L2FortCommanderInstance
 		        || getEffected() instanceof L2SiegeFlagInstance
 		        || getEffected() instanceof L2SiegeSummonInstance)
 			return false;

+ 1 - 1
L2_GameServer/java/net/sf/l2j/gameserver/templates/chars/L2CharTemplate.java

@@ -30,7 +30,7 @@ public class L2CharTemplate
 	public final int baseINT;
 	public final int baseWIT;
 	public final int baseMEN;
-	public final float baseHpMax;
+	public float baseHpMax;
 	public final float baseCpMax;
 	public final float baseMpMax;
 	

+ 1 - 1
L2_GameServer/java/net/sf/l2j/gameserver/templates/skills/L2SkillType.java

@@ -172,7 +172,7 @@ public enum L2SkillType
 	COREDONE,
 	
 	// unimplemented
-	NOTDONE;
+	NOTDONE, BALLISTA;
 	
 	private final Class<? extends L2Skill> _class;
 	

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