Browse Source

Added new guild UI features (#6285)

Co-authored-by: Aleos <aleos89@users.noreply.github.com>
Co-authored-by: Lemongrass3110 <lemongrass@kstp.at>
Co-authored-by: Null Ragnarok Relation <59070443+iberryRO@users.noreply.github.com>
Balfear 2 năm trước cách đây
mục cha
commit
134bfbe986

+ 8 - 164
db/castle_db.yml

@@ -26,174 +26,18 @@
 #   Map               Map name to be considered as the castle map.
 #   Name              Name of the castle (used by scripts and guardian name tags).
 #   Npc               NPC unique name to invoke ::OnGuildBreak on, when a occupied castle is abandoned during guild break.
+#   Type              The WoE type this castle belongs to. (Default: First_Edition)
+#   ClientId          Client side ID of the castle. (Default: 0)
+#   WarpEnabled       If the warp to the castle is enabled. (Default: false)
+#   WarpX             X coordinate to warp to. (Default: 0)
+#   WarpY             Y coordinate to warp to. (Default: 0)
+#   WarpCost          Zeny cost to use the warp. (Default: 100)
+#   WarpCostSiege     Zeny cost to use the warp during WoE. (Default: 100000)
 ###########################################################################
 
 Header:
   Type: CASTLE_DB
-  Version: 1
-
-Body:
-# WOE FE castle
-  - Id: 0
-    Map: aldeg_cas01
-    Name: Neuschwanstein
-    #Name: Noisyubantian
-    Npc: Agit#aldeg_cas01
-  - Id: 1
-    Map: aldeg_cas02
-    Name: Hohenschwangau
-    #Name: Hohensyubangawoo
-    Npc: Agit#aldeg_cas02
-  - Id: 2
-    Map: aldeg_cas03
-    Name: Nuernberg
-    #Name: Nyirenverk
-    Npc: Agit#aldeg_cas03
-  - Id: 3
-    Map: aldeg_cas04
-    Name: Wuerzburg
-    #Name: Byirtsburi
-    Npc: Agit#aldeg_cas04
-  - Id: 4
-    Map: aldeg_cas05
-    Name: Rothenburg
-    #Name: Rotenburk
-    Npc: Agit#aldeg_cas05
-  - Id: 5
-    Map: gefg_cas01
-    Name: Repherion
-    #Name: Reprion
-    Npc: Agit#gefg_cas01
-  - Id: 6
-    Map: gefg_cas02
-    Name: Eeyolbriggar
-    #Name: Yolbriger
-    Npc: Agit#gefg_cas02
-  - Id: 7
-    Map: gefg_cas03
-    Name: Yesnelph
-    #Name: Isinlife
-    Npc: Agit#gefg_cas03
-  - Id: 8
-    Map: gefg_cas04
-    Name: Bergel
-    #Name: Berigel
-    Npc: Agit#gefg_cas04
-  - Id: 9
-    Map: gefg_cas05
-    Name: Mersetzdeitz
-    #Name: Melsedetsu
-    Npc: Agit#gefg_cas05
-  - Id: 10
-    Map: payg_cas01
-    Name: Bright Arbor
-    #Name: Mingting
-    Npc: Agit#payg_cas01
-  - Id: 11
-    Map: payg_cas02
-    Name: Scarlet Palace
-    #Name: Tiantan
-    Npc: Agit#payg_cas02
-  - Id: 12
-    Map: payg_cas03
-    Name: Holy Shadow
-    #Name: Fuying
-    Npc: Agit#payg_cas03
-  - Id: 13
-    Map: payg_cas04
-    Name: Sacred Altar
-    #Name: Honglou
-    Npc: Agit#payg_cas04
-  - Id: 14
-    Map: payg_cas05
-    Name: Bamboo Grove Hill
-    #Name: Zhulinxian
-    Npc: Agit#payg_cas05
-  - Id: 15
-    Map: prtg_cas01
-    Name: Kriemhild
-    #Name: Creamhilt
-    Npc: Agit#prtg_cas01
-  - Id: 16
-    Map: prtg_cas02
-    Name: Swanhild
-    #Name: Sbanhealt
-    Npc: Agit#prtg_cas02
-  - Id: 17
-    Map: prtg_cas03
-    Name: Fadhgridh
-    #Name: Lazrigees
-    Npc: Agit#prtg_cas03
-  - Id: 18
-    Map: prtg_cas04
-    Name: Skoegul
-    #Name: Squagul
-    Npc: Agit#prtg_cas04
-  - Id: 19
-    Map: prtg_cas05
-    Name: Gondul
-    #Name: Guindull
-    Npc: Agit#prtg_cas05
-
-# WOE NGuild castle
-  - Id: 20
-    Map: nguild_alde
-    Name: Earth
-    Npc: Agit_N01
-  - Id: 21
-    Map: nguild_gef
-    Name: Air
-    Npc: Agit_N02
-  - Id: 22
-    Map: nguild_pay
-    Name: Water
-    Npc: Agit_N03
-  - Id: 23
-    Map: nguild_prt
-    Name: Fire
-    Npc: Agit_N04
-
-# WOE SE castle
-  - Id: 24
-    Map: schg_cas01
-    Name: Himinn
-    Npc: Manager#schg_cas01
-  - Id: 25
-    Map: schg_cas02
-    Name: Andlangr
-    Npc: Manager#schg_cas02
-  - Id: 26
-    Map: schg_cas03
-    Name: Viblainn
-    Npc: Manager#schg_cas03
-  - Id: 27
-    Map: schg_cas04
-    Name: Hljod
-    Npc: Manager#schg_cas04
-  - Id: 28
-    Map: schg_cas05
-    Name: Skidbladnir
-    Npc: Manager#schg_cas05
-  - Id: 29
-    Map: arug_cas01
-    Name: Mardol
-    Npc: Manager#arug_cas01
-  - Id: 30
-    Map: arug_cas02
-    Name: Cyr
-    Npc: Manager#arug_cas02
-  - Id: 31
-    Map: arug_cas03
-    Name: Horn
-    Npc: Manager#arug_cas03
-  - Id: 32
-    Map: arug_cas04
-    Name: Gefn
-    Npc: Manager#arug_cas04
-  - Id: 33
-    Map: arug_cas05
-    Name: Bandis
-    Npc: Manager#arug_cas05
+  Version: 2
 
 Footer:
   Imports:

+ 8 - 1
db/import-tmpl/castle_db.yml

@@ -26,8 +26,15 @@
 #   Map               Map name to be considered as the castle map.
 #   Name              Name of the castle (used by scripts and guardian name tags).
 #   Npc               NPC unique name to invoke ::OnGuildBreak on, when a occupied castle is abandoned during guild break.
+#   Type              The WoE type this castle belongs to. (Default: First_Edition)
+#   ClientId          Client side ID of the castle. (Default: 0)
+#   WarpEnabled       If the warp to the castle is enabled. (Default: false)
+#   WarpX             X coordinate to warp to. (Default: 0)
+#   WarpY             Y coordinate to warp to. (Default: 0)
+#   WarpCost          Zeny cost to use the warp. (Default: 100)
+#   WarpCostSiege     Zeny cost to use the warp during WoE. (Default: 100000)
 ###########################################################################
 
 Header:
   Type: CASTLE_DB
-  Version: 1
+  Version: 2

+ 235 - 1
db/pre-re/castle_db.yml

@@ -26,8 +26,242 @@
 #   Map               Map name to be considered as the castle map.
 #   Name              Name of the castle (used by scripts and guardian name tags).
 #   Npc               NPC unique name to invoke ::OnGuildBreak on, when a occupied castle is abandoned during guild break.
+#   Type              The WoE type this castle belongs to. (Default: First_Edition)
+#   ClientId          Client side ID of the castle. (Default: 0)
+#   WarpEnabled       If the warp to the castle is enabled. (Default: false)
+#   WarpX             X coordinate to warp to. (Default: 0)
+#   WarpY             Y coordinate to warp to. (Default: 0)
+#   WarpCost          Zeny cost to use the warp. (Default: 100)
+#   WarpCostSiege     Zeny cost to use the warp during WoE. (Default: 100000)
 ###########################################################################
 
 Header:
   Type: CASTLE_DB
-  Version: 1
+  Version: 2
+
+Body:
+# WOE FE castle
+  - Id: 0
+    Map: aldeg_cas01
+    Name: Neuschwanstein
+    #Name: Noisyubantian
+    Npc: Agit#aldeg_cas01
+    Type: First_Edition
+    ClientId: 6
+  - Id: 1
+    Map: aldeg_cas02
+    Name: Hohenschwangau
+    #Name: Hohensyubangawoo
+    Npc: Agit#aldeg_cas02
+    Type: First_Edition
+    ClientId: 7
+  - Id: 2
+    Map: aldeg_cas03
+    Name: Nuernberg
+    #Name: Nyirenverk
+    Npc: Agit#aldeg_cas03
+    Type: First_Edition
+    ClientId: 8
+  - Id: 3
+    Map: aldeg_cas04
+    Name: Wuerzburg
+    #Name: Byirtsburi
+    Npc: Agit#aldeg_cas04
+    Type: First_Edition
+    ClientId: 9
+  - Id: 4
+    Map: aldeg_cas05
+    Name: Rothenburg
+    #Name: Rotenburk
+    Npc: Agit#aldeg_cas05
+    Type: First_Edition
+    ClientId: 10
+  - Id: 5
+    Map: gefg_cas01
+    Name: Repherion
+    #Name: Reprion
+    Npc: Agit#gefg_cas01
+    Type: First_Edition
+    ClientId: 11
+  - Id: 6
+    Map: gefg_cas02
+    Name: Eeyolbriggar
+    #Name: Yolbriger
+    Npc: Agit#gefg_cas02
+    Type: First_Edition
+    ClientId: 12
+  - Id: 7
+    Map: gefg_cas03
+    Name: Yesnelph
+    #Name: Isinlife
+    Npc: Agit#gefg_cas03
+    Type: First_Edition
+    ClientId: 13
+  - Id: 8
+    Map: gefg_cas04
+    Name: Bergel
+    #Name: Berigel
+    Npc: Agit#gefg_cas04
+    Type: First_Edition
+    ClientId: 14
+  - Id: 9
+    Map: gefg_cas05
+    Name: Mersetzdeitz
+    #Name: Melsedetsu
+    Npc: Agit#gefg_cas05
+    Type: First_Edition
+    ClientId: 15
+  - Id: 10
+    Map: payg_cas01
+    Name: Bright Arbor
+    #Name: Mingting
+    Npc: Agit#payg_cas01
+    Type: First_Edition
+    ClientId: 16
+  - Id: 11
+    Map: payg_cas02
+    Name: Scarlet Palace
+    #Name: Tiantan
+    Npc: Agit#payg_cas02
+    Type: First_Edition
+    ClientId: 17
+  - Id: 12
+    Map: payg_cas03
+    Name: Holy Shadow
+    #Name: Fuying
+    Npc: Agit#payg_cas03
+    Type: First_Edition
+    ClientId: 18
+  - Id: 13
+    Map: payg_cas04
+    Name: Sacred Altar
+    #Name: Honglou
+    Npc: Agit#payg_cas04
+    Type: First_Edition
+    ClientId: 19
+  - Id: 14
+    Map: payg_cas05
+    Name: Bamboo Grove Hill
+    #Name: Zhulinxian
+    Npc: Agit#payg_cas05
+    Type: First_Edition
+    ClientId: 20
+  - Id: 15
+    Map: prtg_cas01
+    Name: Kriemhild
+    #Name: Creamhilt
+    Npc: Agit#prtg_cas01
+    Type: First_Edition
+    ClientId: 1
+  - Id: 16
+    Map: prtg_cas02
+    Name: Swanhild
+    #Name: Sbanhealt
+    Npc: Agit#prtg_cas02
+    Type: First_Edition
+    ClientId: 2
+  - Id: 17
+    Map: prtg_cas03
+    Name: Fadhgridh
+    #Name: Lazrigees
+    Npc: Agit#prtg_cas03
+    Type: First_Edition
+    ClientId: 3
+  - Id: 18
+    Map: prtg_cas04
+    Name: Skoegul
+    #Name: Squagul
+    Npc: Agit#prtg_cas04
+    Type: First_Edition
+    ClientId: 4
+  - Id: 19
+    Map: prtg_cas05
+    Name: Gondul
+    #Name: Guindull
+    Npc: Agit#prtg_cas05
+    Type: First_Edition
+    ClientId: 5
+
+# WOE NGuild castle
+  - Id: 20
+    Map: nguild_alde
+    Name: Earth
+    Npc: Agit_N01
+    Type: First_Edition
+  - Id: 21
+    Map: nguild_gef
+    Name: Air
+    Npc: Agit_N02
+    Type: First_Edition
+  - Id: 22
+    Map: nguild_pay
+    Name: Water
+    Npc: Agit_N03
+    Type: First_Edition
+  - Id: 23
+    Map: nguild_prt
+    Name: Fire
+    Npc: Agit_N04
+    Type: First_Edition
+
+# WOE SE castle
+  - Id: 24
+    Map: schg_cas01
+    Name: Himinn
+    Npc: Manager#schg_cas01
+    Type: Second_Edition
+    ClientId: 26
+  - Id: 25
+    Map: schg_cas02
+    Name: Andlangr
+    Npc: Manager#schg_cas02
+    Type: Second_Edition
+    ClientId: 27
+  - Id: 26
+    Map: schg_cas03
+    Name: Viblainn
+    Npc: Manager#schg_cas03
+    Type: Second_Edition
+    ClientId: 28
+  - Id: 27
+    Map: schg_cas04
+    Name: Hljod
+    Npc: Manager#schg_cas04
+    Type: Second_Edition
+    ClientId: 29
+  - Id: 28
+    Map: schg_cas05
+    Name: Skidbladnir
+    Npc: Manager#schg_cas05
+    Type: Second_Edition
+    ClientId: 30
+  - Id: 29
+    Map: arug_cas01
+    Name: Mardol
+    Npc: Manager#arug_cas01
+    Type: Second_Edition
+    ClientId: 21
+  - Id: 30
+    Map: arug_cas02
+    Name: Cyr
+    Npc: Manager#arug_cas02
+    Type: Second_Edition
+    ClientId: 22
+  - Id: 31
+    Map: arug_cas03
+    Name: Horn
+    Npc: Manager#arug_cas03
+    Type: Second_Edition
+    ClientId: 23
+  - Id: 32
+    Map: arug_cas04
+    Name: Gefn
+    Npc: Manager#arug_cas04
+    Type: Second_Edition
+    ClientId: 24
+  - Id: 33
+    Map: arug_cas05
+    Name: Bandis
+    Npc: Manager#arug_cas05
+    Type: Second_Edition
+    ClientId: 25

+ 334 - 1
db/re/castle_db.yml

@@ -26,51 +26,384 @@
 #   Map               Map name to be considered as the castle map.
 #   Name              Name of the castle (used by scripts and guardian name tags).
 #   Npc               NPC unique name to invoke ::OnGuildBreak on, when a occupied castle is abandoned during guild break.
+#   Type              The WoE type this castle belongs to. (Default: First_Edition)
+#   ClientId          Client side ID of the castle. (Default: 0)
+#   WarpEnabled       If the warp to the castle is enabled. (Default: false)
+#   WarpX             X coordinate to warp to. (Default: 0)
+#   WarpY             Y coordinate to warp to. (Default: 0)
+#   WarpCost          Zeny cost to use the warp. (Default: 100)
+#   WarpCostSiege     Zeny cost to use the warp during WoE. (Default: 100000)
 ###########################################################################
 
 Header:
   Type: CASTLE_DB
-  Version: 1
+  Version: 2
 
 Body:
+# WOE FE castle
+  - Id: 0
+    Map: aldeg_cas01
+    Name: Neuschwanstein
+    #Name: Noisyubantian
+    Npc: Agit#aldeg_cas01
+    Type: First_Edition
+    ClientId: 6
+    WarpEnabled: true
+    WarpX: 212
+    WarpY: 175
+  - Id: 1
+    Map: aldeg_cas02
+    Name: Hohenschwangau
+    #Name: Hohensyubangawoo
+    Npc: Agit#aldeg_cas02
+    Type: First_Edition
+    ClientId: 7
+    WarpEnabled: true
+    WarpX: 82
+    WarpY: 71
+  - Id: 2
+    Map: aldeg_cas03
+    Name: Nuernberg
+    #Name: Nyirenverk
+    Npc: Agit#aldeg_cas03
+    Type: First_Edition
+    ClientId: 8
+    WarpEnabled: true
+    WarpX: 109
+    WarpY: 112
+  - Id: 3
+    Map: aldeg_cas04
+    Name: Wuerzburg
+    #Name: Byirtsburi
+    Npc: Agit#aldeg_cas04
+    Type: First_Edition
+    ClientId: 9
+    WarpEnabled: true
+    WarpX: 60
+    WarpY: 116
+  - Id: 4
+    Map: aldeg_cas05
+    Name: Rothenburg
+    #Name: Rotenburk
+    Npc: Agit#aldeg_cas05
+    Type: First_Edition
+    ClientId: 10
+    WarpEnabled: true
+    WarpX: 61
+    WarpY: 185
+  - Id: 5
+    Map: gefg_cas01
+    Name: Repherion
+    #Name: Reprion
+    Npc: Agit#gefg_cas01
+    Type: First_Edition
+    ClientId: 11
+    WarpEnabled: true
+    WarpX: 40
+    WarpY: 43
+  - Id: 6
+    Map: gefg_cas02
+    Name: Eeyolbriggar
+    #Name: Yolbriger
+    Npc: Agit#gefg_cas02
+    Type: First_Edition
+    ClientId: 12
+    WarpEnabled: true
+    WarpX: 22
+    WarpY: 66
+  - Id: 7
+    Map: gefg_cas03
+    Name: Yesnelph
+    #Name: Isinlife
+    Npc: Agit#gefg_cas03
+    Type: First_Edition
+    ClientId: 13
+    WarpEnabled: true
+    WarpX: 112
+    WarpY: 23
+  - Id: 8
+    Map: gefg_cas04
+    Name: Bergel
+    #Name: Berigel
+    Npc: Agit#gefg_cas04
+    Type: First_Edition
+    ClientId: 14
+    WarpEnabled: true
+    WarpX: 58
+    WarpY: 46
+  - Id: 9
+    Map: gefg_cas05
+    Name: Mersetzdeitz
+    #Name: Melsedetsu
+    Npc: Agit#gefg_cas05
+    Type: First_Edition
+    ClientId: 15
+    WarpEnabled: true
+    WarpX: 66
+    WarpY: 48
+  - Id: 10
+    Map: payg_cas01
+    Name: Bright Arbor
+    #Name: Mingting
+    Npc: Agit#payg_cas01
+    Type: First_Edition
+    ClientId: 16
+    WarpEnabled: true
+    WarpX: 115
+    WarpY: 57
+  - Id: 11
+    Map: payg_cas02
+    Name: Scarlet Palace
+    #Name: Tiantan
+    Npc: Agit#payg_cas02
+    Type: First_Edition
+    ClientId: 17
+    WarpEnabled: true
+    WarpX: 26
+    WarpY: 265
+  - Id: 12
+    Map: payg_cas03
+    Name: Holy Shadow
+    #Name: Fuying
+    Npc: Agit#payg_cas03
+    Type: First_Edition
+    ClientId: 18
+    WarpEnabled: true
+    WarpX: 43
+    WarpY: 264
+  - Id: 13
+    Map: payg_cas04
+    Name: Sacred Altar
+    #Name: Honglou
+    Npc: Agit#payg_cas04
+    Type: First_Edition
+    ClientId: 19
+    WarpEnabled: true
+    WarpX: 36
+    WarpY: 272
+  - Id: 14
+    Map: payg_cas05
+    Name: Bamboo Grove Hill
+    #Name: Zhulinxian
+    Npc: Agit#payg_cas05
+    Type: First_Edition
+    ClientId: 20
+    WarpEnabled: true
+    WarpX: 274
+    WarpY: 246
+  - Id: 15
+    Map: prtg_cas01
+    Name: Kriemhild
+    #Name: Creamhilt
+    Npc: Agit#prtg_cas01
+    Type: First_Edition
+    ClientId: 1
+    WarpEnabled: true
+    WarpX: 107
+    WarpY: 180
+  - Id: 16
+    Map: prtg_cas02
+    Name: Swanhild
+    #Name: Sbanhealt
+    Npc: Agit#prtg_cas02
+    Type: First_Edition
+    ClientId: 2
+    WarpEnabled: true
+    WarpX: 94
+    WarpY: 56
+  - Id: 17
+    Map: prtg_cas03
+    Name: Fadhgridh
+    #Name: Lazrigees
+    Npc: Agit#prtg_cas03
+    Type: First_Edition
+    ClientId: 3
+    WarpEnabled: true
+    WarpX: 46
+    WarpY: 97
+  - Id: 18
+    Map: prtg_cas04
+    Name: Skoegul
+    #Name: Squagul
+    Npc: Agit#prtg_cas04
+    Type: First_Edition
+    ClientId: 4
+    WarpEnabled: true
+    WarpX: 260
+    WarpY: 262
+  - Id: 19
+    Map: prtg_cas05
+    Name: Gondul
+    #Name: Guindull
+    Npc: Agit#prtg_cas05
+    Type: First_Edition
+    ClientId: 5
+    WarpEnabled: true
+    WarpX: 26
+    WarpY: 38
+
+# WOE NGuild castle
+  - Id: 20
+    Map: nguild_alde
+    Name: Earth
+    Npc: Agit_N01
+    Type: First_Edition
+  - Id: 21
+    Map: nguild_gef
+    Name: Air
+    Npc: Agit_N02
+    Type: First_Edition
+  - Id: 22
+    Map: nguild_pay
+    Name: Water
+    Npc: Agit_N03
+    Type: First_Edition
+  - Id: 23
+    Map: nguild_prt
+    Name: Fire
+    Npc: Agit_N04
+    Type: First_Edition
+
+# WOE SE castle
+  - Id: 24
+    Map: schg_cas01
+    Name: Himinn
+    Npc: Manager#schg_cas01
+    Type: Second_Edition
+    ClientId: 26
+    WarpEnabled: true
+    WarpX: 233
+    WarpY: 300
+  - Id: 25
+    Map: schg_cas02
+    Name: Andlangr
+    Npc: Manager#schg_cas02
+    Type: Second_Edition
+    ClientId: 27
+    WarpEnabled: true
+    WarpX: 101
+    WarpY: 372
+  - Id: 26
+    Map: schg_cas03
+    Name: Viblainn
+    Npc: Manager#schg_cas03
+    Type: Second_Edition
+    ClientId: 28
+    WarpEnabled: true
+    WarpX: 81
+    WarpY: 94
+  - Id: 27
+    Map: schg_cas04
+    Name: Hljod
+    Npc: Manager#schg_cas04
+    Type: Second_Edition
+    ClientId: 29
+    WarpEnabled: true
+    WarpX: 233
+    WarpY: 300
+  - Id: 28
+    Map: schg_cas05
+    Name: Skidbladnir
+    Npc: Manager#schg_cas05
+    Type: Second_Edition
+    ClientId: 30
+    WarpEnabled: true
+    WarpX: 233
+    WarpY: 300
+  - Id: 29
+    Map: arug_cas01
+    Name: Mardol
+    Npc: Manager#arug_cas01
+    Type: Second_Edition
+    ClientId: 21
+    WarpEnabled: true
+    WarpX: 77
+    WarpY: 371
+  - Id: 30
+    Map: arug_cas02
+    Name: Cyr
+    Npc: Manager#arug_cas02
+    Type: Second_Edition
+    ClientId: 22
+    WarpEnabled: true
+    WarpX: 301
+    WarpY: 332
+  - Id: 31
+    Map: arug_cas03
+    Name: Horn
+    Npc: Manager#arug_cas03
+    Type: Second_Edition
+    ClientId: 23
+    WarpEnabled: true
+    WarpX: 322
+    WarpY: 91
+  - Id: 32
+    Map: arug_cas04
+    Name: Gefn
+    Npc: Manager#arug_cas04
+    Type: Second_Edition
+    ClientId: 24
+    WarpEnabled: true
+    WarpX: 322
+    WarpY: 91
+  - Id: 33
+    Map: arug_cas05
+    Name: Bandis
+    Npc: Manager#arug_cas05
+    Type: Second_Edition
+    ClientId: 25
+    WarpEnabled: true
+    WarpX: 322
+    WarpY: 91
+
 # WOE TE castle
   - Id: 34
     Map: te_aldecas1
     Name: Kafragarten 1
     Npc: Manager_TE#Glaris
+    Type: Third_Edition
   - Id: 35
     Map: te_aldecas2
     Name: Kafragarten 2
     Npc: Manager_TE#Defolty
+    Type: Third_Edition
   - Id: 36
     Map: te_aldecas3
     Name: Kafragarten 3
     Npc: Manager_TE#Sorin
+    Type: Third_Edition
   - Id: 37
     Map: te_aldecas4
     Name: Kafragarten 4
     Npc: Manager_TE#Bennit
+    Type: Third_Edition
   - Id: 38
     Map: te_aldecas5
     Name: Kafragarten 5
     Npc: Manager_TE#W
+    Type: Third_Edition
   - Id: 39
     Map: te_prtcas01
     Name: Gloria 1
     Npc: Manager_TE#Gaebolg
+    Type: Third_Edition
   - Id: 40
     Map: te_prtcas02
     Name: Gloria 2
     Npc: Manager_TE#Richard
+    Type: Third_Edition
   - Id: 41
     Map: te_prtcas03
     Name: Gloria 3
     Npc: Manager_TE#Wigner
+    Type: Third_Edition
   - Id: 42
     Map: te_prtcas04
     Name: Gloria 4
     Npc: Manager_TE#Heine
+    Type: Third_Edition
   - Id: 43
     Map: te_prtcas05
     Name: Gloria 5
     Npc: Manager_TE#Nerious
+    Type: Third_Edition

+ 14 - 0
src/common/mmo.hpp

@@ -760,11 +760,25 @@ struct guild {
 	int32 chargeshout_flag_id;
 };
 
+enum e_woe_type{
+	WOE_FIRST_EDITION = 1,
+	WOE_SECOND_EDITION,
+	WOE_THIRD_EDITION,
+	WOE_MAX
+};
+
 struct guild_castle {
 	int castle_id;
 	int mapindex;
 	char castle_name[NAME_LENGTH];
 	char castle_event[NPC_NAME_LENGTH];
+	e_woe_type type;
+	uint16 client_id;
+	bool warp_enabled;
+	uint16 warp_x;
+	uint16 warp_y;
+	uint32 zeny;
+	uint32 zeny_siege;
 	int guild_id;
 	int economy;
 	int defense;

+ 143 - 0
src/map/clif.cpp

@@ -3290,6 +3290,148 @@ void clif_guild_xy_remove(map_session_data *sd)
 	clif_send(buf,packet_len(0x1eb),&sd->bl,GUILD_SAMEMAP_WOS);
 }
 
+/*==========================================
+ * Load castle list for guild UI. [Asheraf] / [Balfear]
+ *------------------------------------------*/
+void clif_guild_castle_list(map_session_data& sd){
+#if PACKETVER_MAIN_NUM >= 20190731 || PACKETVER_RE_NUM >= 20190717 || PACKETVER_ZERO_NUM >= 20190814
+	struct guild* g = sd.guild;
+
+	if (g == nullptr)
+		return;
+
+	int castle_count = guild_checkcastles(g);
+
+	if (castle_count > 0) {
+		struct PACKET_ZC_GUILD_AGIT_INFO* p = (struct PACKET_ZC_GUILD_AGIT_INFO*)packet_buffer;
+
+		p->packetType = HEADER_ZC_GUILD_AGIT_INFO;
+		p->packetLength = static_cast<int16>( sizeof( struct PACKET_ZC_GUILD_AGIT_INFO ) );
+
+		int i = 0;
+		for (const auto& gc : castle_db) {
+			if (gc.second->guild_id == g->guild_id && gc.second->client_id) {
+				p->castle_list[i] = static_cast<int8>( gc.second->client_id );
+				p->packetLength += static_cast<int16>( sizeof( p->castle_list[0] ) );
+				++i;
+			}
+		}
+
+		clif_send(p, p->packetLength, &sd.bl, SELF);
+	}
+#endif
+}
+
+/*==========================================
+ * Send castle info Economy/Defence. [Asheraf] / [Balfear]
+ *------------------------------------------*/
+void clif_guild_castleinfo(map_session_data& sd, std::shared_ptr<guild_castle> castle ){
+#if PACKETVER_MAIN_NUM >= 20190731 || PACKETVER_RE_NUM >= 20190717 || PACKETVER_ZERO_NUM >= 20190814
+	if( castle->client_id == 0 ){
+		return;
+	}
+
+	struct PACKET_ZC_REQ_ACK_AGIT_INVESTMENT p = {};
+
+	p.packetType = HEADER_ZC_REQ_ACK_AGIT_INVESTMENT;
+	p.castle_id = static_cast<int8>( castle->client_id );
+	p.economy = castle->economy;
+	p.defense = castle->defense;
+
+	clif_send(&p, sizeof(p), &sd.bl, SELF);
+#endif
+}
+
+/*==========================================
+ * Show teleport request result. [Asheraf] / [Balfear]
+ *------------------------------------------*/
+void clif_guild_castle_teleport_res(map_session_data& sd, enum e_siege_teleport_result result){
+#if PACKETVER_MAIN_NUM >= 20190731 || PACKETVER_RE_NUM >= 20190717 || PACKETVER_ZERO_NUM >= 20190814
+	struct PACKET_ZC_REQ_ACK_MOVE_GUILD_AGIT p = {};
+
+	p.packetType = HEADER_ZC_REQ_ACK_MOVE_GUILD_AGIT;
+	p.result = static_cast<int16>( result );
+
+	clif_send(&p, sizeof(p), &sd.bl, SELF);
+#endif
+}
+
+/*==========================================
+ * Request castle info. [Asheraf] / [Balfear]
+ *------------------------------------------*/
+void clif_parse_guild_castle_info_request(int fd, map_session_data* sd){
+#if PACKETVER_MAIN_NUM >= 20190522 || PACKETVER_RE_NUM >= 20190522 || PACKETVER_ZERO_NUM >= 20190515
+	const struct PACKET_CZ_REQ_AGIT_INVESTMENT* p = (struct PACKET_CZ_REQ_AGIT_INVESTMENT*)RFIFOP(fd, 0);
+	struct guild* g = sd->guild;
+
+	if (g == nullptr)
+		return;
+
+	std::shared_ptr<guild_castle> gc = castle_db.find_by_clientid( p->castle_id );
+
+	if (gc == nullptr)
+		return;
+	if (gc->guild_id != g->guild_id)
+		return;
+
+	clif_guild_castleinfo(*sd, gc);
+#endif
+}
+
+/*==========================================
+ * Teleport to castle. [Asheraf] / [Balfear]
+ *------------------------------------------*/
+void clif_parse_guild_castle_teleport_request(int fd, map_session_data* sd){
+#if PACKETVER_MAIN_NUM >= 20190522 || PACKETVER_RE_NUM >= 20190522 || PACKETVER_ZERO_NUM >= 20190515
+	const struct PACKET_CZ_REQ_MOVE_GUILD_AGIT* p = (struct PACKET_CZ_REQ_MOVE_GUILD_AGIT*)RFIFOP(fd, 0);
+	struct guild* g = sd->guild;
+
+	if (g == nullptr)
+		return;
+
+	std::shared_ptr<guild_castle> gc = castle_db.find_by_clientid( p->castle_id );
+
+	if (gc == nullptr)
+		return;
+	if (!gc->warp_enabled)
+		return;
+	if (gc->guild_id != g->guild_id)
+		return;
+
+	if (map_getmapflag(sd->bl.m, MF_GVG_CASTLE) 
+		|| map_getmapflag(sd->bl.m, MF_NOTELEPORT)
+		|| map_getmapflag(sd->bl.m, MF_NOWARP))
+		return;
+
+	uint32 zeny = gc->zeny;
+
+	switch( gc->type ){
+		case WOE_FIRST_EDITION:
+			if( agit_flag ){
+				zeny = gc->zeny_siege;
+			}
+			break;
+		case WOE_SECOND_EDITION:
+			if( agit2_flag ){
+				zeny = gc->zeny_siege;
+			}
+			break;
+		case WOE_THIRD_EDITION:
+			if( agit3_flag ){
+				zeny = gc->zeny_siege;
+			}
+			break;
+	}
+
+	if (zeny && pc_payzeny(sd, zeny, LOG_TYPE_OTHER, nullptr)) {
+		clif_guild_castle_teleport_res(*sd, SIEGE_TP_NOT_ENOUGH_ZENY);
+		return;
+	}
+
+	pc_setpos(sd, gc->mapindex, gc->warp_x, gc->warp_y, CLR_OUTSIGHT);
+#endif
+}
+
 /*==========================================
  *
  *------------------------------------------*/
@@ -14063,6 +14205,7 @@ void clif_parse_GuildRequestInfo(int fd, map_session_data *sd)
 	case 0:	// Basic Information Guild, hostile alliance information
 		clif_guild_basicinfo( *sd );
 		clif_guild_allianceinfo(sd);
+		clif_guild_castle_list(*sd);
 		break;
 	case 1:	// Members list, list job title
 		clif_guild_positionnamelist(sd);

+ 9 - 0
src/map/clif.hpp

@@ -611,6 +611,12 @@ enum e_dynamicnpc_result : int32{
 	DYNAMICNPC_RESULT_OUTOFTIME
 };
 
+enum e_siege_teleport_result : uint8 {
+	SIEGE_TP_SUCCESS = 0,
+	SIEGE_TP_NOT_ENOUGH_ZENY = 1,
+	SIEGE_TP_INVALID_MODE = 2
+};
+
 int clif_setip(const char* ip);
 void clif_setbindip(const char* ip);
 void clif_setport(uint16 port);
@@ -861,6 +867,9 @@ void clif_guild_broken(map_session_data *sd,int flag);
 void clif_guild_xy(map_session_data *sd);
 void clif_guild_xy_single(int fd, map_session_data *sd);
 void clif_guild_xy_remove(map_session_data *sd);
+void clif_guild_castle_list(map_session_data& sd);
+void clif_guild_castle_info(map_session_data& sd, std::shared_ptr<guild_castle> castle );
+void clif_guild_castle_teleport_res(map_session_data& sd, enum e_siege_teleport_result result);
 
 // Battleground
 void clif_bg_hp(map_session_data *sd);

+ 5 - 0
src/map/clif_packetdb.hpp

@@ -2384,6 +2384,11 @@
 	parseable_packet( HEADER_CZ_PING_LIVE, sizeof( struct PACKET_CZ_PING_LIVE ), clif_parse_dull, 0 );
 #endif
 
+#if PACKETVER_MAIN_NUM >= 20190522 || PACKETVER_RE_NUM >= 20190522 || PACKETVER_ZERO_NUM >= 20190515
+	parseable_packet( HEADER_CZ_REQ_MOVE_GUILD_AGIT, sizeof(PACKET_CZ_REQ_MOVE_GUILD_AGIT), clif_parse_guild_castle_teleport_request, 0);
+	parseable_packet( HEADER_CZ_REQ_AGIT_INVESTMENT, sizeof(PACKET_CZ_REQ_AGIT_INVESTMENT), clif_parse_guild_castle_info_request, 0);
+#endif
+
 #if PACKETVER >= 20190724
 	parseable_packet(HEADER_CZ_GUILD_EMBLEM_CHANGE2, sizeof( PACKET_CZ_GUILD_EMBLEM_CHANGE2 ), clif_parse_GuildChangeEmblem2, 0 );
 	packet(HEADER_ZC_CHANGE_GUILD, sizeof(PACKET_ZC_CHANGE_GUILD));

+ 192 - 1
src/map/guild.cpp

@@ -330,12 +330,193 @@ uint64 CastleDatabase::parseBodyNode(const ryml::NodeRef& node) {
 		safestrncpy(gc->castle_event, npc_name.c_str(), sizeof(gc->castle_event));
 	}
 
+	if( this->nodeExists( node, "Type" ) ){
+		std::string type;
+
+		if( !this->asString( node, "Type", type ) ){
+			return 0;
+		}
+
+		std::string type_constant = "WOE_" + type;
+		int64 constant;
+
+		if( !script_get_constant( type_constant.c_str(), &constant ) || constant < WOE_FIRST_EDITION || constant >= WOE_MAX ){
+			this->invalidWarning( node["Type"], "Invalid WoE type %s.\n", type.c_str() );
+			return 0;
+		}
+
+		gc->type = static_cast<e_woe_type>( constant );
+	}else{
+		if( !exists ){
+			gc->type = WOE_FIRST_EDITION;
+		}
+	}
+
+	if( this->nodeExists( node, "ClientId" ) ){
+		uint16 id;
+
+		if( !this->asUInt16( node, "ClientId", id ) ){
+			return 0;
+		}
+
+		gc->client_id = id;
+	}else{
+		if( !exists ){
+			gc->client_id = 0;
+		}
+	}
+
+	if( this->nodeExists( node, "WarpEnabled" ) ){
+		bool enabled;
+
+		if( !this->asBool( node, "WarpEnabled", enabled ) ){
+			return 0;
+		}
+
+		gc->warp_enabled = enabled;
+	}else{
+		if( !exists ){
+			gc->warp_enabled = false;
+		}
+	}
+
+	if (this->nodeExists(node, "WarpX")) {
+		uint16 warp_x;
+
+		if (!this->asUInt16(node, "WarpX", warp_x)) {
+			return 0;
+		}
+
+		if( warp_x == 0 ){
+			this->invalidWarning( node["WarpX"], "WarpX has to be greater than zero.\n" );
+			return 0;
+		}
+
+		map_data* md = map_getmapdata( map_mapindex2mapid( gc->mapindex ) );
+
+		if( warp_x >= md->xs ){
+			this->invalidWarning( node["WarpX"], "WarpX has to be smaller than %hu.\n", md->xs );
+			return 0;
+		}
+
+		gc->warp_x = warp_x;
+	}
+	else {
+		if (!exists)
+			gc->warp_x = 0;
+	}
+
+	if (this->nodeExists(node, "WarpY")) {
+		uint16 warp_y;
+
+		if (!this->asUInt16(node, "WarpY", warp_y)) {
+			return 0;
+		}
+
+		if( warp_y == 0 ){
+			this->invalidWarning( node["WarpY"], "WarpY has to be greater than zero.\n" );
+			return 0;
+		}
+
+		map_data* md = map_getmapdata( map_mapindex2mapid( gc->mapindex ) );
+
+		if( warp_y >= md->ys ){
+			this->invalidWarning( node["WarpY"], "WarpY has to be smaller than %hu.\n", md->ys );
+			return 0;
+		}
+
+		gc->warp_y = warp_y;
+	}
+	else {
+		if (!exists)
+			gc->warp_y = 0;
+	}
+
+	if (this->nodeExists(node, "WarpCost")) {
+		uint32 zeny;
+
+		if (!this->asUInt32(node, "WarpCost", zeny)) {
+			return 0;
+		}
+
+		if( zeny > MAX_ZENY ){
+			this->invalidWarning( node["WarpCost"], "WarpCost has to be smaller than %d.\n", MAX_ZENY );
+			return 0;
+		}
+
+		gc->zeny = zeny;
+	} else {
+		if (!exists)
+			gc->zeny = 100;
+	}
+
+	if (this->nodeExists(node, "WarpCostSiege")) {
+		uint32 zeny_siege;
+
+		if (!this->asUInt32(node, "WarpCostSiege", zeny_siege)) {
+			return 0;
+		}
+
+		if( zeny_siege > MAX_ZENY ){
+			this->invalidWarning( node["WarpCostSiege"], "WarpCostSiege has to be smaller than %d.\n", MAX_ZENY );
+			return 0;
+		}
+
+		gc->zeny_siege = zeny_siege;
+	}
+	else {
+		if (!exists)
+			gc->zeny_siege = 100000;
+	}
+
 	if (!exists)
 		this->put(castle_id, gc);
 
 	return 1;
 }
 
+void CastleDatabase::loadingFinished(){
+	for( const auto& pair : *this ){
+		std::shared_ptr<guild_castle> castle = pair.second;
+
+		if( castle->client_id != 0 ){
+			// Check if ClientId is unique
+			for( const auto& pair2 : *this ){
+				std::shared_ptr<guild_castle> castle2 = pair2.second;
+
+				if( castle->castle_id == castle2->castle_id ){
+					continue;
+				}
+
+				if( castle->client_id == castle2->client_id ){
+					ShowWarning( "Castle ClientId %hu is ambigous.\n", castle->client_id );
+					break;
+				}
+			}
+		}
+
+		if( castle->warp_enabled ){
+			if( castle->client_id == 0 ){
+				ShowWarning( "Warping to castle %d is enabled, but no ClientId is set. Disabling...\n", castle->castle_id );
+				castle->warp_enabled = false;
+				continue;
+			}
+
+			if( castle->warp_x == 0 ){
+				ShowWarning( "Warping to castle %d is enabled, but no WarpX is set. Disabling...\n", castle->castle_id );
+				castle->warp_enabled = false;
+				continue;
+			}
+
+			if( castle->warp_y == 0 ){
+				ShowWarning( "Warping to castle %d is enabled, but no WarpY is set. Disabling...\n", castle->castle_id );
+				castle->warp_enabled = false;
+				continue;
+			}
+		}
+	}
+}
+
 /// lookup: guild id -> guild*
 struct guild* guild_search(int guild_id) {
 	return (struct guild*)idb_get(guild_db,guild_id);
@@ -357,7 +538,7 @@ struct guild* guild_searchname(char* str) {
 
 /// lookup: map index -> castle*
 std::shared_ptr<guild_castle> CastleDatabase::mapindex2gc(int16 mapindex) {
-	for (const auto &it : castle_db) {
+	for (const auto &it : *this) {
 		if (it.second->mapindex == mapindex)
 			return it.second;
 	}
@@ -369,6 +550,16 @@ std::shared_ptr<guild_castle> CastleDatabase::mapname2gc(const char* mapname) {
 	return castle_db.mapindex2gc(mapindex_name2id(mapname));
 }
 
+std::shared_ptr<guild_castle> CastleDatabase::find_by_clientid( uint16 client_id ){
+	for( const auto &it : *this ){
+		if( it.second->client_id == client_id ){
+			return it.second;
+		}
+	}
+
+	return nullptr;
+}
+
 map_session_data* guild_getavailablesd(struct guild* g) {
 	int i;
 

+ 3 - 1
src/map/guild.hpp

@@ -118,16 +118,18 @@ void do_final_guild(void);
 
 class CastleDatabase : public TypesafeYamlDatabase <int32, guild_castle> {
 public:
-	CastleDatabase() : TypesafeYamlDatabase("CASTLE_DB", 1) {
+	CastleDatabase() : TypesafeYamlDatabase("CASTLE_DB", 2, 1) {
 
 	}
 
 	const std::string getDefaultLocation() override;
 	uint64 parseBodyNode(const ryml::NodeRef& node) override;
+	void loadingFinished() override;
 
 	// Additional
 	std::shared_ptr<guild_castle> mapname2gc(const char* mapname);
 	std::shared_ptr<guild_castle> mapindex2gc(int16 mapindex);
+	std::shared_ptr<guild_castle> find_by_clientid( uint16 client_id );
 };
 
 extern CastleDatabase castle_db;

+ 5 - 0
src/map/script_constants.hpp

@@ -9938,6 +9938,11 @@
 	export_constant(CASHSHOP_TAB_OTHER);
 	export_constant(CASHSHOP_TAB_SALE);
 
+	/* WoE Types */
+	export_constant(WOE_FIRST_EDITION);
+	export_constant(WOE_SECOND_EDITION);
+	export_constant(WOE_THIRD_EDITION);
+
 	#undef export_constant
 	#undef export_constant2
 	#undef export_parameter