Mob* HateList::GetClosest(Mob *hater) { Mob* close_entity = nullptr; float close_distance = 99999.9f; float this_distance; if (!hater && owner) hater = owner; if (!hater) return nullptr; auto iterator = list.begin(); while(iterator != list.end()) { this_distance = DistanceSquaredNoZ((*iterator)->ent->GetPosition(), hater->GetPosition()); if((*iterator)->ent != nullptr && this_distance <= close_distance) { close_distance = this_distance; close_entity = (*iterator)->ent; } ++iterator; } if ((!close_entity && hater->IsNPC()) || (close_entity && close_entity->DivineAura())) close_entity = hater->CastToNPC()->GetHateTop(); return close_entity; }
bool Corpse::Summon(Client* client, bool spell, bool CheckDistance) { uint32 dist2 = 10000; // pow(100, 2); if (!spell) { if (this->GetCharID() == client->CharacterID()) { if (IsLocked() && client->Admin() < 100) { client->Message(13, "That corpse is locked by a GM."); return false; } if (!CheckDistance || (DistanceSquaredNoZ(m_Position, client->GetPosition()) <= dist2)) { GMMove(client->GetX(), client->GetY(), client->GetZ()); is_corpse_changed = true; } else { client->Message(0, "Corpse is too far away."); return false; } } else { bool consented = false; std::list<std::string>::iterator itr; for(itr = client->consent_list.begin(); itr != client->consent_list.end(); ++itr) { if(strcmp(this->GetOwnerName(), itr->c_str()) == 0) { if (!CheckDistance || (DistanceSquaredNoZ(m_Position, client->GetPosition()) <= dist2)) { GMMove(client->GetX(), client->GetY(), client->GetZ()); is_corpse_changed = true; } else { client->Message(0, "Corpse is too far away."); return false; } consented = true; } } if(!consented) { client->Message(0, "You do not have permission to move this corpse."); return false; } } } else { GMMove(client->GetX(), client->GetY(), client->GetZ()); is_corpse_changed = true; } Save(); return true; }
void EntityList::AETaunt(Client* taunter, float range) { if (range == 0) range = 100; //arbitrary default... range = range * range; auto it = npc_list.begin(); while (it != npc_list.end()) { NPC *them = it->second; float zdiff = taunter->GetZ() - them->GetZ(); if (zdiff < 0) zdiff *= -1; if (zdiff < 10 && taunter->IsAttackAllowed(them) && DistanceSquaredNoZ(taunter->GetPosition(), them->GetPosition()) <= range) { if (taunter->CheckLosFN(them)) { taunter->Taunt(them, true); } } ++it; } }
void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* app) { // Added 12/08. Started compressing loot struct on live. if(player_corpse_depop) { SendLootReqErrorPacket(client, LootResponse::SomeoneElse); return; } if(IsPlayerCorpse() && corpse_db_id == 0) { // SendLootReqErrorPacket(client, 0); client->Message(13, "Warning: Corpse's dbid = 0! Corpse will not survive zone shutdown!"); std::cout << "Error: PlayerCorpse::MakeLootRequestPackets: dbid = 0!" << std::endl; // return; } if(is_locked && client->Admin() < 100) { SendLootReqErrorPacket(client, LootResponse::SomeoneElse); client->Message(13, "Error: Corpse locked by GM."); return; } if(being_looted_by == 0) being_looted_by = 0xFFFFFFFF; if(this->being_looted_by != 0xFFFFFFFF) { // lets double check.... Entity* looter = entity_list.GetID(this->being_looted_by); if(looter == nullptr) this->being_looted_by = 0xFFFFFFFF; } uint8 Loot_Request_Type = 1; bool loot_coin = false; std::string tmp; if(database.GetVariable("LootCoin", tmp)) loot_coin = tmp[0] == 1 && tmp[1] == '\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()) { Loot_Request_Type = 2; } else if ((IsNPCCorpse() || become_npc) && CanPlayerLoot(client->CharacterID())) { Loot_Request_Type = 2; } else if (GetPlayerKillItem() == -1 && CanPlayerLoot(client->CharacterID())) { /* PVP loot all items, variable cash */ Loot_Request_Type = 3; } else if (GetPlayerKillItem() == 1 && CanPlayerLoot(client->CharacterID())) { /* PVP loot 1 item, variable cash */ Loot_Request_Type = 4; } else if (GetPlayerKillItem() > 1 && CanPlayerLoot(client->CharacterID())) { /* PVP loot 1 set item, variable cash */ Loot_Request_Type = 5; } if (Loot_Request_Type == 1) { if (client->Admin() < 100 || !client->GetGM()) { 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 = static_cast<uint8>(LootResponse::Normal); d->unknown1 = 0x42; d->unknown2 = 0xef; /* Dont take the coin off if it's a gm peeking at the corpse */ if(Loot_Request_Type == 2 || (Loot_Request_Type >= 3 && loot_coin)) { if(!IsPlayerCorpse() && client->IsGrouped() && client->AutoSplitEnabled() && client->GetGroup()) { d->copper = 0; d->silver = 0; d->gold = 0; d->platinum = 0; Group *cgroup = client->GetGroup(); cgroup->SplitMoney(GetCopper(), GetSilver(), GetGold(), GetPlatinum(), client); } else { d->copper = this->GetCopper(); d->silver = this->GetSilver(); d->gold = this->GetGold(); d->platinum = this->GetPlatinum(); client->AddMoneyToPP(GetCopper(), GetSilver(), GetGold(), GetPlatinum(), false); } RemoveCash(); Save(); } auto timestamps = database.GetItemRecastTimestamps(client->CharacterID()); outapp->priority = 6; client->QueuePacket(outapp); safe_delete(outapp); if(Loot_Request_Type == 5) { int pkitem = GetPlayerKillItem(); const EQEmu::ItemData* item = database.GetItem(pkitem); EQEmu::ItemInstance* inst = database.CreateItem(item, item->MaxCharges); if(inst) { if (item->RecastDelay) inst->SetRecastTimestamp(timestamps.count(item->RecastType) ? timestamps.at(item->RecastType) : 0); client->SendItemPacket(EQEmu::legacy::CORPSE_BEGIN, inst, ItemPacketLoot); safe_delete(inst); } else { client->Message(13, "Could not find item number %i to send!!", GetPlayerKillItem()); } client->QueuePacket(app); return; } int i = 0; const EQEmu::ItemData* item = 0; ItemList::iterator cur,end; cur = itemlist.begin(); end = itemlist.end(); int corpselootlimit = EQEmu::inventory::Lookup(EQEmu::versions::ConvertClientVersionToMobVersion(client->ClientVersion()))->InventoryTypeSize[EQEmu::inventory::typeCorpse]; for(; cur != end; ++cur) { ServerLootItem_Struct* item_data = *cur; item_data->lootslot = 0xFFFF; // Dont display the item if it's in a bag // Added cursor queue slots to corpse item visibility list. Nothing else should be making it to corpse. if (!IsPlayerCorpse() || item_data->equip_slot <= EQEmu::inventory::slotCursor || item_data->equip_slot == EQEmu::inventory::slotPowerSource || Loot_Request_Type >= 3 || (item_data->equip_slot >= 8000 && item_data->equip_slot <= 8999)) { if(i < corpselootlimit) { item = database.GetItem(item_data->item_id); if(client && item) { EQEmu::ItemInstance* inst = database.CreateItem(item, item_data->charges, item_data->aug_1, item_data->aug_2, item_data->aug_3, item_data->aug_4, item_data->aug_5, item_data->aug_6, item_data->attuned); if(inst) { if (item->RecastDelay) inst->SetRecastTimestamp(timestamps.count(item->RecastType) ? timestamps.at(item->RecastType) : 0); // SlotGeneral1 is the corpse inventory start offset for Ti(EMu) - CORPSE_END = SlotGeneral1 + SlotCursor client->SendItemPacket(i + EQEmu::legacy::CORPSE_BEGIN, inst, ItemPacketLoot); safe_delete(inst); } item_data->lootslot = i; } } i++; } } if(IsPlayerCorpse() && (char_id == client->CharacterID() || client->GetGM())) { if(i > corpselootlimit) { client->Message(15, "*** This corpse contains more items than can be displayed! ***"); client->Message(0, "Remove items and re-loot corpse to access remaining inventory."); client->Message(0, "(%s contains %i additional %s.)", GetName(), (i - corpselootlimit), (i - corpselootlimit) == 1 ? "item" : "items"); } if(IsPlayerCorpse() && i == 0 && itemlist.size() > 0) { // somehow, player corpse contains items, but client doesn't see them... client->Message(13, "This corpse contains items that are inaccessable!"); client->Message(15, "Contact a GM for item replacement, if necessary."); client->Message(15, "BUGGED CORPSE [DBID: %i, Name: %s, Item Count: %i]", GetCorpseDBID(), GetName(), itemlist.size()); cur = itemlist.begin(); end = itemlist.end(); for(; cur != end; ++cur) { ServerLootItem_Struct* item_data = *cur; item = database.GetItem(item_data->item_id); Log.Out(Logs::General, Logs::None, "Corpse Looting: %s was not sent to client loot window (corpse_dbid: %i, charname: %s(%s))", item->Name, GetCorpseDBID(), client->GetName(), client->GetGM() ? "GM" : "Owner"); client->Message(0, "Inaccessable Corpse Item: %s", item->Name); } } } } // Disgrace: Client seems to require that we send the packet back... client->QueuePacket(app); // 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, LootResponse::LootAll); }