diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 7f77a2eb9..fc376c64e 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -9177,39 +9177,7 @@ void Client::Handle_OP_LootRequest(const EQApplicationPacket *app) if (ent->IsCorpse()) { SetLooting(ent->GetID()); //store the entity we are looting - Corpse *ent_corpse = ent->CastToCorpse(); - if (DistanceSquaredNoZ(m_Position, ent_corpse->GetPosition()) > 625) - { - Message(13, "Corpse too far away."); - Corpse::SendLootReqErrorPacket(this); - return; - } - if (invisible) { - BuffFadeByEffect(SE_Invisibility); - BuffFadeByEffect(SE_Invisibility2); - invisible = false; - } - if (invisible_undead) { - BuffFadeByEffect(SE_InvisVsUndead); - BuffFadeByEffect(SE_InvisVsUndead2); - invisible_undead = false; - } - if (invisible_animals){ - BuffFadeByEffect(SE_InvisVsAnimals); - invisible_animals = false; - } - if (hidden || improved_hidden){ - hidden = false; - improved_hidden = false; - auto outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct)); - SpawnAppearance_Struct* sa_out = (SpawnAppearance_Struct*)outapp->pBuffer; - sa_out->spawn_id = GetID(); - sa_out->type = 0x03; - sa_out->parameter = 0; - entity_list.QueueClients(this, outapp, true); - safe_delete(outapp); - } ent->CastToCorpse()->MakeLootRequestPackets(this, app); return; } diff --git a/zone/common.h b/zone/common.h index d517bb721..97bb1a50b 100644 --- a/zone/common.h +++ b/zone/common.h @@ -189,6 +189,16 @@ enum class PlayerState : uint32 { SecondaryWeaponEquipped = 128 }; +enum class LootResponse : uint8 { + SomeoneElse = 0, + Normal = 1, + NotAtThisTime = 2, + Normal2 = 3, // acts exactly the same as Normal, maybe group vs ungroup? No idea + Hostiles = 4, + TooFar = 5, + LootAll = 6 // SoD+ +}; + //this is our internal representation of the BUFF struct, can put whatever we want in it struct Buffs_Struct { uint16 spellid; diff --git a/zone/corpse.cpp b/zone/corpse.cpp index 0fc02a2ac..ff5e4806b 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -64,10 +64,10 @@ void Corpse::SendEndLootErrorPacket(Client* client) { safe_delete(outapp); } -void Corpse::SendLootReqErrorPacket(Client* client, uint8 response) { +void Corpse::SendLootReqErrorPacket(Client* client, LootResponse response) { auto outapp = new EQApplicationPacket(OP_MoneyOnCorpse, sizeof(moneyOnCorpseStruct)); moneyOnCorpseStruct* d = (moneyOnCorpseStruct*) outapp->pBuffer; - d->response = response; + d->response = static_cast(response); d->unknown1 = 0x5a; d->unknown2 = 0x40; client->QueuePacket(outapp); @@ -876,7 +876,7 @@ void Corpse::AllowPlayerLoot(Mob *them, uint8 slot) { void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* app) { // Added 12/08. Started compressing loot struct on live. if(player_corpse_depop) { - SendLootReqErrorPacket(client, 0); + SendLootReqErrorPacket(client, LootResponse::SomeoneElse); return; } @@ -888,7 +888,7 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a } if(is_locked && client->Admin() < 100) { - SendLootReqErrorPacket(client, 0); + SendLootReqErrorPacket(client, LootResponse::SomeoneElse); client->Message(13, "Error: Corpse locked by GM."); return; } @@ -899,7 +899,7 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a if(this->being_looted_by != 0xFFFFFFFF) { // lets double check.... Entity* looter = entity_list.GetID(this->being_looted_by); - if(looter == 0) + if(looter == nullptr) this->being_looted_by = 0xFFFFFFFF; } @@ -909,8 +909,14 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a if(database.GetVariable("LootCoin", tmp)) loot_coin = tmp[0] == 1 && tmp[1] == '\0'; - if (this->being_looted_by != 0xFFFFFFFF && this->being_looted_by != client->GetID()) { - SendLootReqErrorPacket(client, 0); + if (DistanceSquaredNoZ(client->GetPosition(), m_Position) > 625) { + SendLootReqErrorPacket(client, LootResponse::TooFar); + // not sure if we need to send the packet back in this case? Didn't before! + // Will just return for now + return; + } + else if (this->being_looted_by != 0xFFFFFFFF && this->being_looted_by != client->GetID()) { + SendLootReqErrorPacket(client, LootResponse::SomeoneElse); Loot_Request_Type = 0; } else if (IsPlayerCorpse() && char_id == client->CharacterID()) { @@ -931,16 +937,17 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a if (Loot_Request_Type == 1) { if (client->Admin() < 100 || !client->GetGM()) { - SendLootReqErrorPacket(client, 2); + SendLootReqErrorPacket(client, LootResponse::NotAtThisTime); } } if(Loot_Request_Type >= 2 || (Loot_Request_Type == 1 && client->Admin() >= 100 && client->GetGM())) { + client->CommonBreakInvisible(); // we should be "all good" so lets break invis now instead of earlier before all error checking is done this->being_looted_by = client->GetID(); auto outapp = new EQApplicationPacket(OP_MoneyOnCorpse, sizeof(moneyOnCorpseStruct)); moneyOnCorpseStruct* d = (moneyOnCorpseStruct*) outapp->pBuffer; - d->response = 1; + d->response = static_cast(LootResponse::Normal); d->unknown1 = 0x42; d->unknown2 = 0xef; @@ -1052,7 +1059,8 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a // This is required for the 'Loot All' feature to work for SoD clients. I expect it is to tell the client that the // server has now sent all the items on the corpse. - if (client->ClientVersion() >= EQEmu::versions::ClientVersion::SoD) { SendLootReqErrorPacket(client, 6); } + if (client->ClientVersion() >= EQEmu::versions::ClientVersion::SoD) + SendLootReqErrorPacket(client, LootResponse::LootAll); } void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { @@ -1092,7 +1100,7 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { return; } if (is_locked && client->Admin() < 100) { - SendLootReqErrorPacket(client, 0); + SendLootReqErrorPacket(client, LootResponse::SomeoneElse); client->Message(13, "Error: Corpse locked by GM."); return; } diff --git a/zone/corpse.h b/zone/corpse.h index c08bece02..509899827 100644 --- a/zone/corpse.h +++ b/zone/corpse.h @@ -37,7 +37,7 @@ class Corpse : public Mob { public: static void SendEndLootErrorPacket(Client* client); - static void SendLootReqErrorPacket(Client* client, uint8 response = 2); + static void SendLootReqErrorPacket(Client* client, LootResponse response = LootResponse::NotAtThisTime); Corpse(NPC* in_npc, ItemList* in_itemlist, uint32 in_npctypeid, const NPCType** in_npctypedata, uint32 in_decaytime = 600000); Corpse(Client* client, int32 in_rezexp); diff --git a/zone/mob.cpp b/zone/mob.cpp index f76902da9..a4aa4e15a 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -5854,6 +5854,23 @@ int Mob::CheckBaneDamage(const ItemInst *item) return damage; } +void Mob::CommonBreakInvisible() +{ + BreakInvisibleSpells(); + + if (hidden || improved_hidden) { + hidden = false; + improved_hidden = false; + auto outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct)); + SpawnAppearance_Struct* sa_out = (SpawnAppearance_Struct*)outapp->pBuffer; + sa_out->spawn_id = GetID(); + sa_out->type = 0x03; + sa_out->parameter = 0; + entity_list.QueueClients(this, outapp, true); + safe_delete(outapp); + } +} + #ifdef BOTS bool Mob::JoinHealRotationTargetPool(std::shared_ptr* heal_rotation) { diff --git a/zone/mob.h b/zone/mob.h index a282fb89c..3608efa9c 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -173,6 +173,7 @@ public: void RogueEvade(Mob *other); void CommonOutgoingHitSuccess(Mob* defender, int32 &damage, EQEmu::skills::SkillType skillInUse, ExtraAttackOptions *opts = nullptr); void BreakInvisibleSpells(); + void CommonBreakInvisible(); void CommonBreakInvisibleFromCombat(); bool HasDied(); virtual bool CheckDualWield();