summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/map/clif.c12
-rw-r--r--src/map/clif.h5
-rw-r--r--src/map/instance.c61
-rw-r--r--src/map/instance.h1
-rw-r--r--src/map/packets.h2
-rw-r--r--src/map/packets_struct.h5
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