From 3cbec0a83b20c88ceb7c68fea532b79260c583a8 Mon Sep 17 00:00:00 2001 From: Asheraf Date: Sat, 10 Aug 2019 12:05:02 +0100 Subject: Implementation of new guild ui client features --- src/common/mmo.h | 8 +++ src/map/clif.c | 126 +++++++++++++++++++++++++++++++++++++++++++++++ src/map/clif.h | 12 +++++ src/map/guild.c | 52 ++++++++++++++++++- src/map/guild.h | 1 + src/map/packets.h | 5 ++ src/map/packets_struct.h | 43 ++++++++++++++++ src/map/script.c | 5 ++ src/map/script.h | 10 ++++ 9 files changed, 261 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/common/mmo.h b/src/common/mmo.h index 1fa6fadc8..66736bff0 100644 --- a/src/common/mmo.h +++ b/src/common/mmo.h @@ -907,6 +907,14 @@ struct guild_castle { int mapindex; char castle_name[NAME_LENGTH]; char castle_event[NAME_LENGTH]; + int siege_type; + bool enable_client_warp; + struct { + int x; + int y; + int zeny; + int zeny_siege; + } client_warp; int guild_id; int economy; int defense; diff --git a/src/map/clif.c b/src/map/clif.c index c7f81a471..33c003321 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -8106,6 +8106,54 @@ static void clif_guild_allianceinfo(struct map_session_data *sd) WFIFOSET(fd,WFIFOW(fd,2)); } +static void clif_guild_castlelist(struct map_session_data *sd) +{ +#if PACKETVER_MAIN_NUM >= 20190731 || PACKETVER_RE_NUM >= 20190717 || PACKETVER_ZERO_NUM >= 20190814 + nullpo_retv(sd); + + struct guild *g = sd->guild; + if (g == NULL) + return; + + int castle_count = guild->checkcastles(g); + if (castle_count > 0) { + int len = sizeof(struct PACKET_ZC_GUILD_CASTLE_LIST) + castle_count; + struct PACKET_ZC_GUILD_CASTLE_LIST *p = aMalloc(len); + p->packetType = HEADER_ZC_GUILD_CASTLE_LIST; + p->packetLength = len; + + int i = 0; + struct DBIterator *iter = db_iterator(guild->castle_db); + for (struct guild_castle *gc = dbi_first(iter); dbi_exists(iter); gc = dbi_next(iter)) { + if (gc->guild_id == g->guild_id) { + p->castle_list[i] = gc->castle_id; + ++i; + } + } + dbi_destroy(iter); + + clif->send(p, len, &sd->bl, SELF); + aFree(p); + } +#endif +} + +static void clif_guild_castleinfo(struct map_session_data *sd, struct guild_castle *gc) +{ +#if PACKETVER_MAIN_NUM >= 20190731 || PACKETVER_RE_NUM >= 20190717 || PACKETVER_ZERO_NUM >= 20190814 + + nullpo_retv(sd); + nullpo_retv(gc); + + struct PACKET_ZC_CASTLE_INFO p = { 0 }; + p.packetType = HEADER_ZC_CASTLE_INFO; + p.castle_id = gc->castle_id; + p.economy = gc->economy; + p.defense = gc->defense; + clif->send(&p, sizeof(p), &sd->bl, SELF); +#endif +} + /// Guild member manager information (ZC_MEMBERMGR_INFO). /// 0154 .W { .L .L .W .W .W .W .W .L .L .L .50B .24B }* /// state: @@ -14407,6 +14455,7 @@ static void clif_parse_GuildRequestInfo(int fd, struct map_session_data *sd) case 0: // Basic Information Guild, hostile alliance information clif->guild_basicinfo(sd); clif->guild_allianceinfo(sd); + clif->guild_castlelist(sd); break; case 1: // Members list, list job title clif->guild_positionnamelist(sd); @@ -23211,6 +23260,78 @@ static void clif_announce_refine_status(struct map_session_data *sd, int item_id #endif } +static void clif_parse_GuildCastleTeleportRequest(int fd, struct map_session_data *sd) __attribute__((nonnull(2))); +static void clif_parse_GuildCastleTeleportRequest(int fd, struct map_session_data *sd) +{ +#if PACKETVER_MAIN_NUM >= 20190522 || PACKETVER_RE_NUM >= 20190522 || PACKETVER_ZERO_NUM >= 20190515 + const struct PACKET_CZ_CASTLE_TELEPORT_REQUEST *p = RFIFO2PTR(fd); + struct guild *g = sd->guild; + + if (g == NULL) + return; + + struct guild_castle *gc = guild->castle_search(p->castle_id); + if (gc == NULL) + return; + if (gc->enable_client_warp == false) + return; + if (gc->guild_id != g->guild_id) + return; + + if (map->list[sd->bl.m].flag.gvg_castle == 1) + return; + + int zeny = gc->client_warp.zeny; + if (gc->siege_type == SIEGE_TYPE_FE && map->agit_flag == 1) { + zeny = gc->client_warp.zeny_siege; + } else if (gc->siege_type == SIEGE_TYPE_SE && map->agit2_flag == 1) { + zeny = gc->client_warp.zeny_siege; + } else if (gc->siege_type == SIEGE_TYPE_TE) { + clif->guild_castleteleport_res(sd, SIEGE_TP_INVALID_MODE); + return; + } + + if (sd->status.zeny < zeny) { + clif->guild_castleteleport_res(sd, SIEGE_TP_NOT_ENOUGH_ZENY); + return; + } + sd->status.zeny -= zeny; + clif->updatestatus(sd, SP_ZENY); + pc->setpos(sd, gc->mapindex, gc->client_warp.x, gc->client_warp.y, CLR_OUTSIGHT); +#endif +} + +static void clif_guild_castleteleport_res(struct map_session_data *sd, enum siege_teleport_result result) +{ +#if PACKETVER_MAIN_NUM >= 20190731 || PACKETVER_RE_NUM >= 20190717 || PACKETVER_ZERO_NUM >= 20190814 + + nullpo_retv(sd); + + struct PACKET_ZC_CASTLE_TELEPORT_RESPONSE p = { 0 }; + p.packetType = HEADER_ZC_CASTLE_TELEPORT_RESPONSE; + p.result = (int16)result; + clif->send(&p, sizeof(p), &sd->bl, SELF); +#endif +} +static void clif_parse_GuildCastleInfoRequest(int fd, struct map_session_data *sd) __attribute__((nonnull(2))); +static void clif_parse_GuildCastleInfoRequest(int fd, struct map_session_data *sd) +{ +#if PACKETVER_MAIN_NUM >= 20190522 || PACKETVER_RE_NUM >= 20190522 || PACKETVER_ZERO_NUM >= 20190515 + const struct PACKET_CZ_CASTLE_INFO_REQUEST *p = RFIFO2PTR(fd); + struct guild *g = sd->guild; + + if (g == NULL) + return; + + struct guild_castle *gc = guild->castle_search(p->castle_id); + if (gc == NULL) + return; + if (gc->guild_id != g->guild_id) + return; + clif->guild_castleinfo(sd, gc); +#endif +} + /*========================================== * Main client packet processing function *------------------------------------------*/ @@ -23895,6 +24016,8 @@ void clif_defaults(void) clif->guild_masterormember = clif_guild_masterormember; clif->guild_basicinfo = clif_guild_basicinfo; clif->guild_allianceinfo = clif_guild_allianceinfo; + clif->guild_castlelist = clif_guild_castlelist; + clif->guild_castleinfo = clif_guild_castleinfo; clif->guild_memberlist = clif_guild_memberlist; clif->guild_skillinfo = clif_guild_skillinfo; clif->guild_send_onlineinfo = clif_guild_send_onlineinfo; @@ -24436,4 +24559,7 @@ void clif_defaults(void) clif->pRefineryUIClose = clif_parse_RefineryUIClose; clif->pRefineryUIRefine = clif_parse_RefineryUIRefine; clif->announce_refine_status = clif_announce_refine_status; + clif->pGuildCastleTeleportRequest = clif_parse_GuildCastleTeleportRequest; + clif->pGuildCastleInfoRequest = clif_parse_GuildCastleInfoRequest; + clif->guild_castleteleport_res = clif_guild_castleteleport_res; } diff --git a/src/map/clif.h b/src/map/clif.h index f3d7c78eb..245352b9c 100644 --- a/src/map/clif.h +++ b/src/map/clif.h @@ -633,6 +633,13 @@ enum inventory_type { INVTYPE_GUILD_STORAGE = 3, }; +/** Guild Teleport Results */ +enum siege_teleport_result { + SIEGE_TP_SUCCESS = 0x0, + SIEGE_TP_NOT_ENOUGH_ZENY = 0x1, + SIEGE_TP_INVALID_MODE = 0x2 +}; + /** * Structures **/ @@ -1114,6 +1121,8 @@ struct clif_interface { void (*guild_masterormember) (struct map_session_data *sd); void (*guild_basicinfo) (struct map_session_data *sd); void (*guild_allianceinfo) (struct map_session_data *sd); + void (*guild_castlelist) (struct map_session_data *sd); + void (*guild_castleinfo) (struct map_session_data *sd, struct guild_castle *gc); void (*guild_memberlist) (struct map_session_data *sd); void (*guild_skillinfo) (struct map_session_data* sd); void (*guild_send_onlineinfo) (struct map_session_data *sd); //[LuzZza] @@ -1647,6 +1656,9 @@ struct clif_interface { void (*pRefineryUIClose) (int fd, struct map_session_data *sd); void (*pRefineryUIRefine) (int fd, struct map_session_data *sd); void (*announce_refine_status) (struct map_session_data *sd, int item_id, int refine_level, bool success, enum send_target target); + void (*pGuildCastleTeleportRequest) (int fd, struct map_session_data *sd); + void (*pGuildCastleInfoRequest) (int fd, struct map_session_data *sd); + void (*guild_castleteleport_res) (struct map_session_data *sd, enum siege_teleport_result result); }; #ifdef HERCULES_CORE diff --git a/src/map/guild.c b/src/map/guild.c index 415a46db5..3191515f7 100644 --- a/src/map/guild.c +++ b/src/map/guild.c @@ -169,7 +169,7 @@ static bool guild_read_castledb_libconfig(void) } libconfig->destroy(&castle_conf); - ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", i, config_filename); + ShowStatus("Done reading '"CL_WHITE"%u"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", db_size(guild->castle_db), config_filename); return true; } @@ -217,10 +217,59 @@ static bool guild_read_castledb_libconfig_sub(struct config_setting_t *it, int i } safestrncpy(gc->castle_event, name, sizeof(gc->castle_event)); + if (itemdb->lookup_const(it, "SiegeType", &i32) && (i32 >= SIEGE_TYPE_MAX || i32 < 0)) { + ShowWarning("guild_read_castledb_libconfig_sub: Invalid SiegeType in \"%s\", entry #%d, defaulting to SIEGE_TYPE_FE.\n", source, idx); + gc->siege_type = SIEGE_TYPE_FE; + } else { + gc->siege_type = i32; + } + + libconfig->setting_lookup_bool_real(it, "EnableClientWarp", &gc->enable_client_warp); + if (gc->enable_client_warp == true) { + struct config_setting_t *wd = libconfig->setting_get_member(it, "ClientWarp"); + guild->read_castledb_libconfig_sub_warp(wd, source, gc); + } idb_put(guild->castle_db, gc->castle_id, gc); return true; } +static bool guild_read_castledb_libconfig_sub_warp(struct config_setting_t *wd, const char *source, struct guild_castle *gc) +{ + nullpo_retr(false, wd); + nullpo_retr(false, gc); + nullpo_retr(false, source); + + int64 i64 = 0; + struct config_setting_t *it = libconfig->setting_get_member(wd, "Position"); + if (config_setting_is_list(it)) { + int m = map->mapindex2mapid(gc->mapindex); + + gc->client_warp.x = libconfig->setting_get_int_elem(it, 0); + gc->client_warp.y = libconfig->setting_get_int_elem(it, 1); + if (gc->client_warp.x < 0 || gc->client_warp.x >= map->list[m].xs || gc->client_warp.y < 0 || gc->client_warp.y >= map->list[m].ys) { + ShowWarning("guild_read_castledb_libconfig_sub_warp: Invalid Position in \"%s\", for castle (%d).\n", source, gc->castle_id); + return false; + } + } else { + ShowWarning("guild_read_castledb_libconfig_sub_warp: Invalid format for Position in \"%s\", for castle (%d).\n", source, gc->castle_id); + return false; + } + + if (libconfig->setting_lookup_int64(wd, "ZenyCost", &i64)) { + if (i64 > MAX_ZENY) { + ShowWarning("guild_read_castledb_libconfig_sub_warp: ZenyCost is too big in \"%s\", for castle (%d), capping to MAX_ZENY.\n", source, gc->castle_id); + } + gc->client_warp.zeny = cap_value((int)i64, 0, MAX_ZENY); + } + if (libconfig->setting_lookup_int64(wd, "ZenyCostSiegeTime", &i64)) { + if (i64 > MAX_ZENY) { + ShowWarning("guild_read_castledb_libconfig_sub_warp: ZenyCostSiegeTime is too big in \"%s\", for castle (%d), capping to MAX_ZENY.\n", source, gc->castle_id); + } + gc->client_warp.zeny_siege = cap_value((int)i64, 0, MAX_ZENY); + } + return true; +} + /// lookup: guild id -> guild* static struct guild *guild_search(int guild_id) { @@ -2497,6 +2546,7 @@ void guild_defaults(void) guild->read_guildskill_tree_db = guild_read_guildskill_tree_db; guild->read_castledb_libconfig = guild_read_castledb_libconfig; guild->read_castledb_libconfig_sub = guild_read_castledb_libconfig_sub; + guild->read_castledb_libconfig_sub_warp = guild_read_castledb_libconfig_sub_warp; guild->payexp_timer_sub = guild_payexp_timer_sub; guild->send_xy_timer_sub = guild_send_xy_timer_sub; guild->send_xy_timer = guild_send_xy_timer; diff --git a/src/map/guild.h b/src/map/guild.h index d0374103f..41f52711d 100644 --- a/src/map/guild.h +++ b/src/map/guild.h @@ -166,6 +166,7 @@ struct guild_interface { bool (*read_guildskill_tree_db) (char* split[], int columns, int current); bool (*read_castledb_libconfig) (void); bool (*read_castledb_libconfig_sub) (struct config_setting_t *it, int idx, const char *source); + bool (*read_castledb_libconfig_sub_warp) (struct config_setting_t *wd, const char *source, struct guild_castle *gc); int (*payexp_timer_sub) (union DBKey key, struct DBData *data, va_list ap); int (*send_xy_timer_sub) (union DBKey key, struct DBData *data, va_list ap); int (*send_xy_timer) (int tid, int64 tick, int id, intptr_t data); diff --git a/src/map/packets.h b/src/map/packets.h index 83a9d0322..e91421cfc 100644 --- a/src/map/packets.h +++ b/src/map/packets.h @@ -1954,4 +1954,9 @@ packet(0x96e,clif->ackmergeitems); packet(0x0b22,clif->pHotkeyRowShift2); // CZ_SHORTCUTKEYBAR_ROTATE #endif +#if PACKETVER_MAIN_NUM >= 20190522 || PACKETVER_RE_NUM >= 20190522 || PACKETVER_ZERO_NUM >= 20190515 + packet(0x0b28,clif->pGuildCastleTeleportRequest); + packet(0x0b2c,clif->pGuildCastleInfoRequest); +#endif + #endif /* MAP_PACKETS_H */ diff --git a/src/map/packets_struct.h b/src/map/packets_struct.h index 93b4abcca..24bb718da 100644 --- a/src/map/packets_struct.h +++ b/src/map/packets_struct.h @@ -3626,6 +3626,49 @@ struct PACKET_ZC_TALKBOX_CHATCONTENTS { } __attribute__((packed)); DEFINE_PACKET_HEADER(ZC_TALKBOX_CHATCONTENTS, 0x0191); +#if PACKETVER_MAIN_NUM >= 20190731 || PACKETVER_RE_NUM >= 20190717 || PACKETVER_ZERO_NUM >= 20190814 +struct PACKET_ZC_GUILD_CASTLE_LIST { + int16 packetType; + int16 packetLength; + int8 castle_list[]; +} __attribute__((packed)); +DEFINE_PACKET_HEADER(ZC_GUILD_CASTLE_LIST, 0x0b27); +#endif + +#if PACKETVER_MAIN_NUM >= 20190522 || PACKETVER_RE_NUM >= 20190522 || PACKETVER_ZERO_NUM >= 20190515 +struct PACKET_CZ_CASTLE_TELEPORT_REQUEST { + int16 packetType; + int8 castle_id; +} __attribute__((packed)); +DEFINE_PACKET_HEADER(CZ_CASTLE_TELEPORT_REQUEST, 0x0b28); +#endif + +#if PACKETVER_MAIN_NUM >= 20190731 || PACKETVER_RE_NUM >= 20190717 || PACKETVER_ZERO_NUM >= 20190814 +struct PACKET_ZC_CASTLE_TELEPORT_RESPONSE { + int16 packetType; + int16 result; +} __attribute__((packed)); +DEFINE_PACKET_HEADER(ZC_CASTLE_TELEPORT_RESPONSE, 0x0b2e); +#endif + +#if PACKETVER_MAIN_NUM >= 20190731 || PACKETVER_RE_NUM >= 20190717 || PACKETVER_ZERO_NUM >= 20190814 +struct PACKET_ZC_CASTLE_INFO { + int16 packetType; + int8 castle_id; + int32 economy; + int32 defense; +} __attribute__((packed)); +DEFINE_PACKET_HEADER(ZC_CASTLE_INFO, 0x0b2d); +#endif + +#if PACKETVER_MAIN_NUM >= 20190522 || PACKETVER_RE_NUM >= 20190522 || PACKETVER_ZERO_NUM >= 20190515 +struct PACKET_CZ_CASTLE_INFO_REQUEST { + int16 packetType; + int8 castle_id; +} __attribute__((packed)); +DEFINE_PACKET_HEADER(CZ_CASTLE_INFO_REQUEST, 0x0b2c); +#endif + #if !defined(sun) && (!defined(__NETBSD__) || __NetBSD_Version__ >= 600000000) // NetBSD 5 and Solaris don't like pragma pack but accept the packed attribute #pragma pack(pop) #endif // not NetBSD < 6 / Solaris diff --git a/src/map/script.c b/src/map/script.c index 4fc47e039..e88e8da0f 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -27078,6 +27078,11 @@ static void script_hardcoded_constants(void) script->set_constant("GUILD_ONLINE_VENDOR", GUILD_ONLINE_VENDOR, false, false); script->set_constant("GUILD_ONLINE_NO_VENDOR", GUILD_ONLINE_NO_VENDOR, false, false); + script->constdb_comment("Siege Types"); + script->set_constant("SIEGE_TYPE_FE", SIEGE_TYPE_FE, false, false); + script->set_constant("SIEGE_TYPE_SE", SIEGE_TYPE_SE, false, false); + script->set_constant("SIEGE_TYPE_TE", SIEGE_TYPE_TE, false, false); + script->constdb_comment("Renewal"); #ifdef RENEWAL script->set_constant("RENEWAL", 1, false, false); diff --git a/src/map/script.h b/src/map/script.h index 5dc480a15..64e709a27 100644 --- a/src/map/script.h +++ b/src/map/script.h @@ -541,6 +541,16 @@ enum pcblock_action_flag { PCBLOCK_ALL = 0xFF, }; +/** + * Types of Siege (WoE) + */ +enum siege_type { + SIEGE_TYPE_FE, + SIEGE_TYPE_SE, + SIEGE_TYPE_TE, + SIEGE_TYPE_MAX +}; + /** * Structures **/ -- cgit v1.2.3-60-g2f50