From 134bfbe9862406a2c0fed2ba46b51ee9bb549c3d Mon Sep 17 00:00:00 2001 From: Balfear Date: Fri, 6 Jan 2023 01:39:30 +0300 Subject: [PATCH] Added new guild UI features (#6285) Co-authored-by: Aleos Co-authored-by: Lemongrass3110 Co-authored-by: Null Ragnarok Relation <59070443+iberryRO@users.noreply.github.com> --- db/castle_db.yml | 172 +----------------- db/import-tmpl/castle_db.yml | 9 +- db/pre-re/castle_db.yml | 236 +++++++++++++++++++++++- db/re/castle_db.yml | 335 ++++++++++++++++++++++++++++++++++- src/common/mmo.hpp | 14 ++ src/map/clif.cpp | 143 +++++++++++++++ src/map/clif.hpp | 9 + src/map/clif_packetdb.hpp | 5 + src/map/guild.cpp | 193 +++++++++++++++++++- src/map/guild.hpp | 4 +- src/map/script_constants.hpp | 5 + 11 files changed, 956 insertions(+), 169 deletions(-) diff --git a/db/castle_db.yml b/db/castle_db.yml index 9a513c6ef3..a43176fc75 100644 --- a/db/castle_db.yml +++ b/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: diff --git a/db/import-tmpl/castle_db.yml b/db/import-tmpl/castle_db.yml index 5e8cafbef2..cf74b5db71 100644 --- a/db/import-tmpl/castle_db.yml +++ b/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 diff --git a/db/pre-re/castle_db.yml b/db/pre-re/castle_db.yml index 5e8cafbef2..4fdbe14b70 100644 --- a/db/pre-re/castle_db.yml +++ b/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 diff --git a/db/re/castle_db.yml b/db/re/castle_db.yml index 8f8e06a110..5979ff9792 100644 --- a/db/re/castle_db.yml +++ b/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 diff --git a/src/common/mmo.hpp b/src/common/mmo.hpp index 588c4af61a..71de58e0d8 100644 --- a/src/common/mmo.hpp +++ b/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; diff --git a/src/map/clif.cpp b/src/map/clif.cpp index 9f91ee40c9..19f3f67dba 100644 --- a/src/map/clif.cpp +++ b/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( 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( gc.second->client_id ); + p->packetLength += static_cast( 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 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( 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( 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 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 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); diff --git a/src/map/clif.hpp b/src/map/clif.hpp index ac2149d742..3ce6dd9698 100644 --- a/src/map/clif.hpp +++ b/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 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); diff --git a/src/map/clif_packetdb.hpp b/src/map/clif_packetdb.hpp index 966077d2d3..4365aed002 100644 --- a/src/map/clif_packetdb.hpp +++ b/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)); diff --git a/src/map/guild.cpp b/src/map/guild.cpp index bcdc6a3ae6..dd8be1668e 100644 --- a/src/map/guild.cpp +++ b/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( 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 castle = pair.second; + + if( castle->client_id != 0 ){ + // Check if ClientId is unique + for( const auto& pair2 : *this ){ + std::shared_ptr 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 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 CastleDatabase::mapname2gc(const char* mapname) { return castle_db.mapindex2gc(mapindex_name2id(mapname)); } +std::shared_ptr 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; diff --git a/src/map/guild.hpp b/src/map/guild.hpp index 6100d464a0..34739a22ec 100644 --- a/src/map/guild.hpp +++ b/src/map/guild.hpp @@ -118,16 +118,18 @@ void do_final_guild(void); class CastleDatabase : public TypesafeYamlDatabase { 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 mapname2gc(const char* mapname); std::shared_ptr mapindex2gc(int16 mapindex); + std::shared_ptr find_by_clientid( uint16 client_id ); }; extern CastleDatabase castle_db; diff --git a/src/map/script_constants.hpp b/src/map/script_constants.hpp index c785c80945..9f1d377f47 100644 --- a/src/map/script_constants.hpp +++ b/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