diff --git a/common/database/database_update_manifest.cpp b/common/database/database_update_manifest.cpp index d4d4f1f18..b93e79a31 100644 --- a/common/database/database_update_manifest.cpp +++ b/common/database/database_update_manifest.cpp @@ -4827,6 +4827,24 @@ UPDATE data_buckets SET bot_id = SUBSTRING_INDEX(SUBSTRING_INDEX( `key`, '-', 2 )" }, + ManifestEntry{ + .version = 9234, + .description = "2023_07_27_update_raid_details.sql", + .check = "SHOW COLUMNS FROM `raid_details` LIKE 'marked_npc_1_entity_id';", + .condition = "empty", + .match = "", + .sql = R"(ALTER TABLE `raid_details` + CHANGE COLUMN `marked_npc_1` `marked_npc_1_entity_id` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `motd`, + ADD COLUMN `marked_npc_1_zone_id` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `marked_npc_1_entity_id`, + ADD COLUMN `marked_npc_1_instance_id` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `marked_npc_1_zone_id`, + CHANGE COLUMN `marked_npc_2` `marked_npc_2_entity_id` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `marked_npc_1_instance_id`, + ADD COLUMN `marked_npc_2_zone_id` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `marked_npc_2_entity_id`, + ADD COLUMN `marked_npc_2_instance_id` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `marked_npc_2_zone_id`, + CHANGE COLUMN `marked_npc_3` `marked_npc_3_entity_id` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `marked_npc_2_instance_id`, + ADD COLUMN `marked_npc_3_zone_id` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `marked_npc_3_entity_id`, + ADD COLUMN `marked_npc_3_instance_id` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `marked_npc_3_zone_id`; + )" + }, // -- template; copy/paste this when you need to create a new entry // ManifestEntry{ diff --git a/common/repositories/base/base_raid_details_repository.h b/common/repositories/base/base_raid_details_repository.h index 5479595bd..616490dd5 100644 --- a/common/repositories/base/base_raid_details_repository.h +++ b/common/repositories/base/base_raid_details_repository.h @@ -24,9 +24,15 @@ public: int32_t loottype; int8_t locked; std::string motd; - uint16_t marked_npc_1; - uint16_t marked_npc_2; - uint16_t marked_npc_3; + uint32_t marked_npc_1_entity_id; + uint32_t marked_npc_1_zone_id; + uint32_t marked_npc_1_instance_id; + uint32_t marked_npc_2_entity_id; + uint32_t marked_npc_2_zone_id; + uint32_t marked_npc_2_instance_id; + uint32_t marked_npc_3_entity_id; + uint32_t marked_npc_3_zone_id; + uint32_t marked_npc_3_instance_id; }; static std::string PrimaryKey() @@ -41,9 +47,15 @@ public: "loottype", "locked", "motd", - "marked_npc_1", - "marked_npc_2", - "marked_npc_3", + "marked_npc_1_entity_id", + "marked_npc_1_zone_id", + "marked_npc_1_instance_id", + "marked_npc_2_entity_id", + "marked_npc_2_zone_id", + "marked_npc_2_instance_id", + "marked_npc_3_entity_id", + "marked_npc_3_zone_id", + "marked_npc_3_instance_id", }; } @@ -54,9 +66,15 @@ public: "loottype", "locked", "motd", - "marked_npc_1", - "marked_npc_2", - "marked_npc_3", + "marked_npc_1_entity_id", + "marked_npc_1_zone_id", + "marked_npc_1_instance_id", + "marked_npc_2_entity_id", + "marked_npc_2_zone_id", + "marked_npc_2_instance_id", + "marked_npc_3_entity_id", + "marked_npc_3_zone_id", + "marked_npc_3_instance_id", }; } @@ -97,13 +115,19 @@ public: { RaidDetails e{}; - e.raidid = 0; - e.loottype = 0; - e.locked = 0; - e.motd = ""; - e.marked_npc_1 = 0; - e.marked_npc_2 = 0; - e.marked_npc_3 = 0; + e.raidid = 0; + e.loottype = 0; + e.locked = 0; + e.motd = ""; + e.marked_npc_1_entity_id = 0; + e.marked_npc_1_zone_id = 0; + e.marked_npc_1_instance_id = 0; + e.marked_npc_2_entity_id = 0; + e.marked_npc_2_zone_id = 0; + e.marked_npc_2_instance_id = 0; + e.marked_npc_3_entity_id = 0; + e.marked_npc_3_zone_id = 0; + e.marked_npc_3_instance_id = 0; return e; } @@ -140,13 +164,19 @@ public: if (results.RowCount() == 1) { RaidDetails e{}; - e.raidid = static_cast(atoi(row[0])); - e.loottype = static_cast(atoi(row[1])); - e.locked = static_cast(atoi(row[2])); - e.motd = row[3] ? row[3] : ""; - e.marked_npc_1 = static_cast(strtoul(row[4], nullptr, 10)); - e.marked_npc_2 = static_cast(strtoul(row[5], nullptr, 10)); - e.marked_npc_3 = static_cast(strtoul(row[6], nullptr, 10)); + e.raidid = static_cast(atoi(row[0])); + e.loottype = static_cast(atoi(row[1])); + e.locked = static_cast(atoi(row[2])); + e.motd = row[3] ? row[3] : ""; + e.marked_npc_1_entity_id = static_cast(strtoul(row[4], nullptr, 10)); + e.marked_npc_1_zone_id = static_cast(strtoul(row[5], nullptr, 10)); + e.marked_npc_1_instance_id = static_cast(strtoul(row[6], nullptr, 10)); + e.marked_npc_2_entity_id = static_cast(strtoul(row[7], nullptr, 10)); + e.marked_npc_2_zone_id = static_cast(strtoul(row[8], nullptr, 10)); + e.marked_npc_2_instance_id = static_cast(strtoul(row[9], nullptr, 10)); + e.marked_npc_3_entity_id = static_cast(strtoul(row[10], nullptr, 10)); + e.marked_npc_3_zone_id = static_cast(strtoul(row[11], nullptr, 10)); + e.marked_npc_3_instance_id = static_cast(strtoul(row[12], nullptr, 10)); return e; } @@ -184,9 +214,15 @@ public: v.push_back(columns[1] + " = " + std::to_string(e.loottype)); v.push_back(columns[2] + " = " + std::to_string(e.locked)); v.push_back(columns[3] + " = '" + Strings::Escape(e.motd) + "'"); - v.push_back(columns[4] + " = " + std::to_string(e.marked_npc_1)); - v.push_back(columns[5] + " = " + std::to_string(e.marked_npc_2)); - v.push_back(columns[6] + " = " + std::to_string(e.marked_npc_3)); + v.push_back(columns[4] + " = " + std::to_string(e.marked_npc_1_entity_id)); + v.push_back(columns[5] + " = " + std::to_string(e.marked_npc_1_zone_id)); + v.push_back(columns[6] + " = " + std::to_string(e.marked_npc_1_instance_id)); + v.push_back(columns[7] + " = " + std::to_string(e.marked_npc_2_entity_id)); + v.push_back(columns[8] + " = " + std::to_string(e.marked_npc_2_zone_id)); + v.push_back(columns[9] + " = " + std::to_string(e.marked_npc_2_instance_id)); + v.push_back(columns[10] + " = " + std::to_string(e.marked_npc_3_entity_id)); + v.push_back(columns[11] + " = " + std::to_string(e.marked_npc_3_zone_id)); + v.push_back(columns[12] + " = " + std::to_string(e.marked_npc_3_instance_id)); auto results = db.QueryDatabase( fmt::format( @@ -212,9 +248,15 @@ public: v.push_back(std::to_string(e.loottype)); v.push_back(std::to_string(e.locked)); v.push_back("'" + Strings::Escape(e.motd) + "'"); - v.push_back(std::to_string(e.marked_npc_1)); - v.push_back(std::to_string(e.marked_npc_2)); - v.push_back(std::to_string(e.marked_npc_3)); + v.push_back(std::to_string(e.marked_npc_1_entity_id)); + v.push_back(std::to_string(e.marked_npc_1_zone_id)); + v.push_back(std::to_string(e.marked_npc_1_instance_id)); + v.push_back(std::to_string(e.marked_npc_2_entity_id)); + v.push_back(std::to_string(e.marked_npc_2_zone_id)); + v.push_back(std::to_string(e.marked_npc_2_instance_id)); + v.push_back(std::to_string(e.marked_npc_3_entity_id)); + v.push_back(std::to_string(e.marked_npc_3_zone_id)); + v.push_back(std::to_string(e.marked_npc_3_instance_id)); auto results = db.QueryDatabase( fmt::format( @@ -248,9 +290,15 @@ public: v.push_back(std::to_string(e.loottype)); v.push_back(std::to_string(e.locked)); v.push_back("'" + Strings::Escape(e.motd) + "'"); - v.push_back(std::to_string(e.marked_npc_1)); - v.push_back(std::to_string(e.marked_npc_2)); - v.push_back(std::to_string(e.marked_npc_3)); + v.push_back(std::to_string(e.marked_npc_1_entity_id)); + v.push_back(std::to_string(e.marked_npc_1_zone_id)); + v.push_back(std::to_string(e.marked_npc_1_instance_id)); + v.push_back(std::to_string(e.marked_npc_2_entity_id)); + v.push_back(std::to_string(e.marked_npc_2_zone_id)); + v.push_back(std::to_string(e.marked_npc_2_instance_id)); + v.push_back(std::to_string(e.marked_npc_3_entity_id)); + v.push_back(std::to_string(e.marked_npc_3_zone_id)); + v.push_back(std::to_string(e.marked_npc_3_instance_id)); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } @@ -284,13 +332,19 @@ public: for (auto row = results.begin(); row != results.end(); ++row) { RaidDetails e{}; - e.raidid = static_cast(atoi(row[0])); - e.loottype = static_cast(atoi(row[1])); - e.locked = static_cast(atoi(row[2])); - e.motd = row[3] ? row[3] : ""; - e.marked_npc_1 = static_cast(strtoul(row[4], nullptr, 10)); - e.marked_npc_2 = static_cast(strtoul(row[5], nullptr, 10)); - e.marked_npc_3 = static_cast(strtoul(row[6], nullptr, 10)); + e.raidid = static_cast(atoi(row[0])); + e.loottype = static_cast(atoi(row[1])); + e.locked = static_cast(atoi(row[2])); + e.motd = row[3] ? row[3] : ""; + e.marked_npc_1_entity_id = static_cast(strtoul(row[4], nullptr, 10)); + e.marked_npc_1_zone_id = static_cast(strtoul(row[5], nullptr, 10)); + e.marked_npc_1_instance_id = static_cast(strtoul(row[6], nullptr, 10)); + e.marked_npc_2_entity_id = static_cast(strtoul(row[7], nullptr, 10)); + e.marked_npc_2_zone_id = static_cast(strtoul(row[8], nullptr, 10)); + e.marked_npc_2_instance_id = static_cast(strtoul(row[9], nullptr, 10)); + e.marked_npc_3_entity_id = static_cast(strtoul(row[10], nullptr, 10)); + e.marked_npc_3_zone_id = static_cast(strtoul(row[11], nullptr, 10)); + e.marked_npc_3_instance_id = static_cast(strtoul(row[12], nullptr, 10)); all_entries.push_back(e); } @@ -315,13 +369,19 @@ public: for (auto row = results.begin(); row != results.end(); ++row) { RaidDetails e{}; - e.raidid = static_cast(atoi(row[0])); - e.loottype = static_cast(atoi(row[1])); - e.locked = static_cast(atoi(row[2])); - e.motd = row[3] ? row[3] : ""; - e.marked_npc_1 = static_cast(strtoul(row[4], nullptr, 10)); - e.marked_npc_2 = static_cast(strtoul(row[5], nullptr, 10)); - e.marked_npc_3 = static_cast(strtoul(row[6], nullptr, 10)); + e.raidid = static_cast(atoi(row[0])); + e.loottype = static_cast(atoi(row[1])); + e.locked = static_cast(atoi(row[2])); + e.motd = row[3] ? row[3] : ""; + e.marked_npc_1_entity_id = static_cast(strtoul(row[4], nullptr, 10)); + e.marked_npc_1_zone_id = static_cast(strtoul(row[5], nullptr, 10)); + e.marked_npc_1_instance_id = static_cast(strtoul(row[6], nullptr, 10)); + e.marked_npc_2_entity_id = static_cast(strtoul(row[7], nullptr, 10)); + e.marked_npc_2_zone_id = static_cast(strtoul(row[8], nullptr, 10)); + e.marked_npc_2_instance_id = static_cast(strtoul(row[9], nullptr, 10)); + e.marked_npc_3_entity_id = static_cast(strtoul(row[10], nullptr, 10)); + e.marked_npc_3_zone_id = static_cast(strtoul(row[11], nullptr, 10)); + e.marked_npc_3_instance_id = static_cast(strtoul(row[12], nullptr, 10)); all_entries.push_back(e); } diff --git a/common/repositories/raid_details_repository.h b/common/repositories/raid_details_repository.h index 61030c2fd..d37a42434 100644 --- a/common/repositories/raid_details_repository.h +++ b/common/repositories/raid_details_repository.h @@ -47,17 +47,21 @@ public: static int UpdateRaidMarkedNPC( Database& db, int32_t raid_id, - uint8_t marked_npc_number, - uint8_t value + uint32_t marked_npc_entity_id, + uint32_t marked_npc_zone_id, + uint32_t marked_npc_instance_id, + uint32_t slot_number ) { auto results = db.QueryDatabase( fmt::format( - "UPDATE `{}` SET `marked_npc_{}` = '{}' WHERE raidid = '{}';", + "UPDATE `{0}` SET `marked_npc_{4}_entity_id` = '{1}',`marked_npc_{4}_zone_id` = '{2}',`marked_npc_{4}_instance_id` = '{3}' WHERE raidid = '{5}';", TableName(), - marked_npc_number, - value, + marked_npc_entity_id, + marked_npc_zone_id, + marked_npc_instance_id, + slot_number, raid_id - ) + ) ); return results.Success() ? results.RowsAffected() : 0; diff --git a/common/version.h b/common/version.h index faaaebaa7..d4f961c48 100644 --- a/common/version.h +++ b/common/version.h @@ -42,7 +42,7 @@ * Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt */ -#define CURRENT_BINARY_DATABASE_VERSION 9233 +#define CURRENT_BINARY_DATABASE_VERSION 9234 #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9039 diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index cd9a5202d..c983a30e1 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -15953,7 +15953,7 @@ void Client::Handle_OP_XTargetRequest(const EQApplicationPacket *app) if (t.type == Type) { Raid* r = GetRaid(); if (r) { - auto mm = entity_list.GetNPCByID(r->marked_npcs[t.assist_slot]); + auto mm = entity_list.GetNPCByID(r->marked_npcs[t.assist_slot].entity_id); if (mm) { UpdateXTargetType(t.type, mm->CastToMob(), mm->CastToMob()->GetName()); } diff --git a/zone/command.h b/zone/command.h index 4b20761ea..553c93c09 100644 --- a/zone/command.h +++ b/zone/command.h @@ -135,7 +135,7 @@ void command_petitems(Client *c, const Seperator *sep); void command_picklock(Client *c, const Seperator *sep); void command_profanity(Client *c, const Seperator *sep); void command_push(Client *c, const Seperator *sep); -void command_pvp(Client *c, const Seperator *sep);; +void command_pvp(Client *c, const Seperator *sep); void command_raidloot(Client* c, const Seperator* sep); void command_randomfeatures(Client *c, const Seperator *sep); void command_refreshgroup(Client *c, const Seperator *sep); diff --git a/zone/raids.cpp b/zone/raids.cpp index c0385167d..16a4a3f6c 100644 --- a/zone/raids.cpp +++ b/zone/raids.cpp @@ -55,7 +55,9 @@ Raid::Raid(uint32 raidID) for (int i = 0; i < MAX_NO_RAID_MAIN_ASSISTERS; i++) { memset(main_assister_pcs[i], 0, 64); memset(main_marker_pcs[i], 0, 64); - marked_npcs[i] = 0; + marked_npcs[i].entity_id = 0; + marked_npcs[i].zone_id = 0; + marked_npcs[i].instance_id = 0; } } @@ -80,7 +82,9 @@ Raid::Raid(Client* nLeader) for (int i = 0; i < MAX_NO_RAID_MAIN_ASSISTERS; i++) { memset(main_assister_pcs[i], 0, 64); memset(main_marker_pcs[i], 0, 64); - marked_npcs[i] = 0; + marked_npcs[i].entity_id = 0; + marked_npcs[i].zone_id = 0; + marked_npcs[i].instance_id = 0; } } @@ -1678,9 +1682,15 @@ void Raid::GetRaidDetails() locked = raid_details.locked; LootType = raid_details.loottype; motd = raid_details.motd; - marked_npcs[0] = raid_details.marked_npc_1; - marked_npcs[1] = raid_details.marked_npc_2; - marked_npcs[2] = raid_details.marked_npc_3; + marked_npcs[0].entity_id = raid_details.marked_npc_1_entity_id; + marked_npcs[0].zone_id = raid_details.marked_npc_1_zone_id; + marked_npcs[0].instance_id = raid_details.marked_npc_1_instance_id; + marked_npcs[1].entity_id = raid_details.marked_npc_2_entity_id; + marked_npcs[1].zone_id = raid_details.marked_npc_2_zone_id; + marked_npcs[1].instance_id = raid_details.marked_npc_2_instance_id; + marked_npcs[2].entity_id = raid_details.marked_npc_3_entity_id; + marked_npcs[2].zone_id = raid_details.marked_npc_3_zone_id; + marked_npcs[2].instance_id = raid_details.marked_npc_3_instance_id; } void Raid::SaveRaidMOTD() @@ -2419,8 +2429,8 @@ void Raid::UpdateRaidXTargets() }; for (auto& u : marked_updates) { - if (marked_npcs[u.slot]) { - auto m = entity_list.GetMob(marked_npcs[u.slot]); + if (marked_npcs[u.slot].entity_id) { + auto m = entity_list.GetMob(marked_npcs[u.slot].entity_id); if (m && m->GetHP() > 0) { UpdateXTargetType(u.mark_target, m, m->GetName()); } @@ -2562,13 +2572,17 @@ void Raid::RaidMarkNPC(Mob* mob, uint32 parameter) for (int i = 0; i < MAX_NO_RAID_MAIN_MARKERS; i++) { auto cname = c->GetCleanName(); if (strcasecmp(main_marker_pcs[i], cname) == 0 || strcasecmp(leadername, cname) == 0) { - marked_npcs[parameter - 1] = c->GetTarget()->GetID(); + marked_npcs[parameter - 1].entity_id = c->GetTarget()->GetID(); + marked_npcs[parameter - 1].zone_id = c->GetTarget()->GetZoneID(); + marked_npcs[parameter - 1].instance_id = c->GetTarget()->GetInstanceVersion(); auto result = RaidDetailsRepository::UpdateRaidMarkedNPC( database, GetID(), - parameter, - marked_npcs[parameter - 1] - ); + marked_npcs[parameter - 1].entity_id, + marked_npcs[parameter - 1].zone_id, + marked_npcs[parameter - 1].instance_id, + parameter + ); if (!result) { LogError("Unable to set MarkedNPC{} from slot: [{}] for guild [{}].", parameter, @@ -2579,7 +2593,7 @@ void Raid::RaidMarkNPC(Mob* mob, uint32 parameter) auto outapp = new EQApplicationPacket(OP_MarkRaidNPC, sizeof(MarkNPC_Struct)); MarkNPC_Struct* mnpcs = (MarkNPC_Struct*)outapp->pBuffer; - mnpcs->TargetID = marked_npcs[parameter - 1]; + mnpcs->TargetID = marked_npcs[parameter - 1].entity_id; mnpcs->Number = parameter; strcpy(mnpcs->Name, c->GetTarget()->GetCleanName()); QueuePacket(outapp); @@ -2596,7 +2610,7 @@ void Raid::RaidMarkNPC(Mob* mob, uint32 parameter) void Raid::UpdateXtargetMarkedNPC() { for (int i = 0; i < MAX_MARKED_NPCS; i++) { - auto mm = entity_list.GetNPCByID(marked_npcs[i]); + auto mm = entity_list.GetNPCByID(marked_npcs[i].entity_id); if (mm) { UpdateXTargetType(static_cast(RaidMarkTarget1 + i), mm->CastToMob(), mm->CastToMob()->GetName()); } @@ -2614,19 +2628,25 @@ void Raid::RaidClearNPCMarks(Client* c) Strings::EqualFold(main_marker_pcs[MAIN_MARKER_2_SLOT], c->GetCleanName()) || Strings::EqualFold(main_marker_pcs[MAIN_MARKER_3_SLOT], c->GetCleanName())) { for (int i = 0; i < MAX_MARKED_NPCS; i++) { - if (marked_npcs[i]) { - auto npc_name = entity_list.GetNPCByID(marked_npcs[i])->GetCleanName(); + if (marked_npcs[i].entity_id > 0 && marked_npcs[i].zone_id == c->GetZoneID() + && marked_npcs[i].instance_id == c->GetInstanceID()) + { + auto npc_name = entity_list.GetNPCByID(marked_npcs[i].entity_id)->GetCleanName(); RaidMessageString(nullptr, Chat::Cyan, RAID_NO_LONGER_MARKED, npc_name); - } - marked_npcs[i] = 0; - auto result = RaidDetailsRepository::UpdateRaidMarkedNPC( - database, - GetID(), - i + 1, - 0 - ); - if (!result) { - LogError("Unable to clear MarkedNPC{} from slot: [{}] for guild [{}].", i + 1, i, GetID()); + marked_npcs[i].entity_id = 0; + marked_npcs[i].zone_id = 0; + marked_npcs[i].instance_id = 0; + auto result = RaidDetailsRepository::UpdateRaidMarkedNPC( + database, + GetID(), + 0, + 0, + 0, + i + 1 + ); + if (!result) { + LogError("Unable to clear MarkedNPC{} from slot: [{}] for guild [{}].", i + 1, i, GetID()); + } } } @@ -2934,12 +2954,13 @@ void Raid::SendMarkTargets(Client* c) } for (int i = 0; i < MAX_MARKED_NPCS; i++) { - if (marked_npcs[i] > 0) { - auto marked_mob = entity_list.GetMob(marked_npcs[i]); + if (marked_npcs[i].entity_id > 0 && marked_npcs[i].zone_id == c->GetZoneID() + && marked_npcs[i].instance_id == c->GetInstanceID()) { + auto marked_mob = entity_list.GetMob(marked_npcs[i].entity_id); if (marked_mob) { auto outapp = new EQApplicationPacket(OP_MarkRaidNPC, sizeof(MarkNPC_Struct)); MarkNPC_Struct* mnpcs = (MarkNPC_Struct*)outapp->pBuffer; - mnpcs->TargetID = marked_npcs[i]; + mnpcs->TargetID = marked_mob->GetID(); mnpcs->Number = i + 1; strcpy(mnpcs->Name, marked_mob->GetCleanName()); QueuePacket(outapp); diff --git a/zone/raids.h b/zone/raids.h index 551b1fcaa..1c1dabc02 100644 --- a/zone/raids.h +++ b/zone/raids.h @@ -110,6 +110,12 @@ enum { DELEGATE_ON = 1 }; +struct Raid_Marked_NPC { + uint32 entity_id; + uint32 zone_id; + uint32 instance_id; +}; + constexpr uint8_t MAX_RAID_GROUPS = 12; constexpr uint8_t MAX_RAID_MEMBERS = 72; @@ -326,7 +332,7 @@ public: char leadername[64]; char main_assister_pcs[MAX_NO_RAID_MAIN_ASSISTERS][64]; char main_marker_pcs[MAX_NO_RAID_MAIN_MARKERS][64]; - uint32 marked_npcs[MAX_MARKED_NPCS]; + Raid_Marked_NPC marked_npcs[MAX_MARKED_NPCS]; protected: Client *leader; bool locked;