diff options
-rw-r--r-- | src/map/clif.c | 12 | ||||
-rw-r--r-- | src/map/clif.h | 5 | ||||
-rw-r--r-- | src/map/instance.c | 61 | ||||
-rw-r--r-- | src/map/instance.h | 1 | ||||
-rw-r--r-- | src/map/packets.h | 2 | ||||
-rw-r--r-- | src/map/packets_struct.h | 5 |
6 files changed, 85 insertions, 1 deletions
diff --git a/src/map/clif.c b/src/map/clif.c index 4e48d7886..bc3e4f4af 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -21747,6 +21747,17 @@ static void clif_party_dead_notification(struct map_session_data *sd) #endif } +static void clif_parse_memorial_dungeon_command(int fd, struct map_session_data *sd) __attribute__((nonnull(2))); +static void clif_parse_memorial_dungeon_command(int fd, struct map_session_data *sd) +{ + const struct PACKET_CZ_MEMORIALDUNGEON_COMMAND *p = RP2PTR(fd); + + switch (p->command) { + case COMMAND_MEMORIALDUNGEON_DESTROY_FORCE: + instance->force_destroy(sd); + } +} + /*========================================== * Main client packet processing function *------------------------------------------*/ @@ -22902,4 +22913,5 @@ void clif_defaults(void) clif->pPetEvolution = clif_parse_pet_evolution; clif->petEvolutionResult = clif_pet_evolution_result; + clif->pMemorialDungeonCommand = clif_parse_memorial_dungeon_command; } diff --git a/src/map/clif.h b/src/map/clif.h index e3b2a90d3..13693bd11 100644 --- a/src/map/clif.h +++ b/src/map/clif.h @@ -660,6 +660,10 @@ enum stylist_shop { STYLIST_SHOP_FAILURE }; +enum memorial_dungeon_command { + COMMAND_MEMORIALDUNGEON_DESTROY_FORCE = 0x3, +}; + /** * Clif.c Interface **/ @@ -1527,6 +1531,7 @@ struct clif_interface { void (*pPetEvolution) (int fd, struct map_session_data *sd); void (*petEvolutionResult) (int fd, enum pet_evolution_result result); void (*party_dead_notification) (struct map_session_data *sd); + void (*pMemorialDungeonCommand) (int fd, struct map_session_data *sd); }; #ifdef HERCULES_CORE diff --git a/src/map/instance.c b/src/map/instance.c index 8bd45ba50..1e83b0b76 100644 --- a/src/map/instance.c +++ b/src/map/instance.c @@ -727,6 +727,66 @@ static void instance_check_kick(struct map_session_data *sd) } } +/** + * Look up existing memorial dungeon of the player and destroy it + * + * @param sd session data. + * + */ +static void instance_force_destroy(struct map_session_data *sd) +{ + nullpo_retv(sd); + + for (int i = 0; i < instance->instances; ++i) { + switch (instance->list[i].owner_type) { + case IOT_CHAR: + { + if (instance->list[i].owner_id != sd->status.char_id) + continue; + break; + } + case IOT_PARTY: + { + int party_id = sd->status.party_id; + if (instance->list[i].owner_id != party_id) + continue; + int j = 0; + struct party_data *pt = party->search(party_id); + nullpo_retv(pt); + + ARR_FIND(0, MAX_PARTY, j, pt->party.member[j].leader); + if (j == MAX_PARTY) { + ShowWarning("clif_parse_memorial_dungeon_command: trying to destroy a party instance, while the party has no leader."); + return; + } + if (pt->party.member[j].char_id != sd->status.char_id) { + ShowWarning("clif_parse_memorial_dungeon_command: trying to destroy a party instance, from a non party-leader player."); + return; + } + break; + } + case IOT_GUILD: + { + int guild_id = sd->status.guild_id; + if (instance->list[i].owner_id != guild_id) + continue; + struct guild *g = guild->search(guild_id); + nullpo_retv(g); + + if (g->member[0].char_id != sd->status.char_id) { + ShowWarning("clif_parse_memorial_dungeon_command: trying to destroy a guild instance, from a non guild-master player."); + return; + } + break; + } + default: + continue; + } + instance->destroy(instance->list[i].id); + return; + } +} + static void do_reload_instance(void) { struct s_mapiterator *iter; @@ -810,4 +870,5 @@ void instance_defaults(void) instance->set_timeout = instance_set_timeout; instance->valid = instance_is_valid; instance->destroy_timer = instance_destroy_timer; + instance->force_destroy = instance_force_destroy; } diff --git a/src/map/instance.h b/src/map/instance.h index ff7e49a7f..91928bf40 100644 --- a/src/map/instance.h +++ b/src/map/instance.h @@ -96,6 +96,7 @@ struct instance_interface { void (*set_timeout) (int instance_id, unsigned int progress_timeout, unsigned int idle_timeout); bool (*valid) (int instance_id); int (*destroy_timer) (int tid, int64 tick, int id, intptr_t data); + void (*force_destroy) (struct map_session_data *sd); }; #ifdef HERCULES_CORE diff --git a/src/map/packets.h b/src/map/packets.h index 1d1046e8a..c879fcee3 100644 --- a/src/map/packets.h +++ b/src/map/packets.h @@ -1142,7 +1142,7 @@ packet(0x96e,-1,clif->ackmergeitems); packet(0x02cc,4); packet(0x02cd,26); packet(0x02ce,10); - packet(0x02cf,6); + packet(0x02cf,6,clif->pMemorialDungeonCommand); packet(0x02d0,-1); packet(0x02d1,-1); packet(0x02d2,-1); diff --git a/src/map/packets_struct.h b/src/map/packets_struct.h index 852a44cb8..90255938b 100644 --- a/src/map/packets_struct.h +++ b/src/map/packets_struct.h @@ -2784,6 +2784,11 @@ struct PACKET_ZC_ACK_LEAVE_GUILD2 { char reason[40]; } __attribute__((packed)); +struct PACKET_CZ_MEMORIALDUNGEON_COMMAND { + int16 packetType; + int32 command; +} __attribute__((packed)); + #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 |