Refactor loot response a bit

Invis is dropped after ALL error checking now
Identified all the response types
This commit is contained in:
Michael Cook (mackal) 2016-06-30 14:00:18 -04:00
parent 3e0af2928b
commit a64343689c
6 changed files with 48 additions and 44 deletions

View File

@ -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;
}

View File

@ -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;

View File

@ -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<uint8>(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<uint8>(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;
}

View File

@ -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);

View File

@ -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<HealRotation>* heal_rotation)
{

View File

@ -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();