From c81491f97ebebf988b5ee96a9c505d690bc59870 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 20 Oct 2014 01:05:08 -0400 Subject: [PATCH 1/6] Inspect buffs rank 1 will now show NPC buffs in target window (SoD+) --- changelog.txt | 3 +++ zone/client_packet.cpp | 22 +++++++++++++++++++--- zone/entity.cpp | 32 +++++++++++++++++++++++++------- zone/entity.h | 2 +- zone/spell_effects.cpp | 6 ++++++ zone/spells.cpp | 6 ++++++ 6 files changed, 60 insertions(+), 11 deletions(-) diff --git a/changelog.txt b/changelog.txt index ed10c7173..915f7a812 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 10/20/2014 == +demonstar55: Inspect Buffs rank 1 will now show NPC buffs in target window (SoD+) + == 10/19/2014 == Uleat: Updated command #peekinv to display item links properly in RoF clients demonstar55: Group Mentoring in raids diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 6d9291685..efc8a5d8a 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -12951,9 +12951,25 @@ void Client::Handle_OP_TargetCommand(const EQApplicationPacket *app) if (nt) { SetTarget(nt); - if ((nt->IsClient() && !nt->CastToClient()->GetPVP()) || - (nt->IsPet() && nt->GetOwner() && nt->GetOwner()->IsClient() && !nt->GetOwner()->CastToClient()->GetPVP()) || - (nt->IsMerc() && nt->GetOwner() && nt->GetOwner()->IsClient() && !nt->GetOwner()->CastToClient()->GetPVP())) + bool inspect_buffs = false; + // rank 1 gives you ability to see NPC buffs in target window (SoD+) + if (nt->IsNPC()) { + if (IsRaidGrouped()) { + Raid *raid = GetRaid(); + if (raid) { + uint32 gid = raid->GetGroup(this); + if (gid < 12 && raid->GroupCount(gid) > 2) + inspect_buffs = raid->GetLeadershipAA(groupAAInspectBuffs, gid); + } + } else { + Group *group = GetGroup(); + if (group && group->GroupCount() > 2) + inspect_buffs = group->GetLeadershipAA(groupAAInspectBuffs); + } + } + if (nt == this || inspect_buffs || (nt->IsClient() && !nt->CastToClient()->GetPVP()) || + (nt->IsPet() && nt->GetOwner() && nt->GetOwner()->IsClient() && !nt->GetOwner()->CastToClient()->GetPVP()) || + (nt->IsMerc() && nt->GetOwner() && nt->GetOwner()->IsClient() && !nt->GetOwner()->CastToClient()->GetPVP())) nt->SendBuffsToClient(this); } else diff --git a/zone/entity.cpp b/zone/entity.cpp index 4a8329639..0ce530419 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -1351,7 +1351,7 @@ void EntityList::RefreshClientXTargets(Client *c) } void EntityList::QueueClientsByTarget(Mob *sender, const EQApplicationPacket *app, - bool iSendToSender, Mob *SkipThisMob, bool ackreq, bool HoTT, uint32 ClientVersionBits) + bool iSendToSender, Mob *SkipThisMob, bool ackreq, bool HoTT, uint32 ClientVersionBits, bool inspect_buffs) { auto it = client_list.begin(); while (it != client_list.end()) { @@ -1365,8 +1365,7 @@ void EntityList::QueueClientsByTarget(Mob *sender, const EQApplicationPacket *ap Mob *TargetsTarget = nullptr; - if (Target) - TargetsTarget = Target->GetTarget(); + TargetsTarget = Target->GetTarget(); bool Send = false; @@ -1378,11 +1377,30 @@ void EntityList::QueueClientsByTarget(Mob *sender, const EQApplicationPacket *ap Send = true; if (c != sender) { - if (Target == sender) - Send = true; - else if (HoTT) - if (TargetsTarget == sender) + if (Target == sender) { + if (inspect_buffs) { // if inspect_buffs is true we're sending a mob's buffs to those with the LAA + if (c->IsRaidGrouped()) { + Raid *raid = c->GetRaid(); + if (!raid) + continue; + uint32 gid = raid->GetGroup(c); + if (gid > 11 || raid->GroupCount(gid) < 3) + continue; + if (raid->GetLeadershipAA(groupAAInspectBuffs, gid)) + Send = true; + } else { + Group *group = c->GetGroup(); + if (!group || group->GroupCount() < 3) + continue; + if (group->GetLeadershipAA(groupAAInspectBuffs)) + Send = true; + } + } else { Send = true; + } + } else if (HoTT && TargetsTarget == sender) { + Send = true; + } } if (Send && (c->GetClientVersionBit() & ClientVersionBits)) diff --git a/zone/entity.h b/zone/entity.h index 9599aa7fc..5776ed936 100644 --- a/zone/entity.h +++ b/zone/entity.h @@ -297,7 +297,7 @@ public: void QueueClientsGuild(Mob* sender, const EQApplicationPacket* app, bool ignore_sender = false, uint32 guildeqid = 0); void QueueClientsGuildBankItemUpdate(const GuildBankItemUpdate_Struct *gbius, uint32 GuildID); void QueueClientsByTarget(Mob* sender, const EQApplicationPacket* app, bool iSendToSender = true, Mob* SkipThisMob = 0, bool ackreq = true, - bool HoTT = true, uint32 ClientVersionBits = 0xFFFFFFFF); + bool HoTT = true, uint32 ClientVersionBits = 0xFFFFFFFF, bool inspect_buffs = false); void QueueClientsByXTarget(Mob* sender, const EQApplicationPacket* app, bool iSendToSender = true); void QueueToGroupsForNPCHealthAA(Mob* sender, const EQApplicationPacket* app); diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 7496a07a5..41e8f1e50 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -4168,6 +4168,12 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses) safe_delete(outapp); } + if (IsNPC()) { + EQApplicationPacket *outapp = MakeBuffsPacket(); + entity_list.QueueClientsByTarget(this, outapp, false, nullptr, true, false, BIT_SoDAndLater, true); + safe_delete(outapp); + } + if(IsClient() && CastToClient()->GetClientVersionBit() & BIT_UnderfootAndLater) { EQApplicationPacket *outapp = MakeBuffsPacket(false); diff --git a/zone/spells.cpp b/zone/spells.cpp index c6fb43b24..50eb9479f 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -3128,6 +3128,12 @@ int Mob::AddBuff(Mob *caster, uint16 spell_id, int duration, int32 level_overrid safe_delete(outapp); } + if (IsNPC()) { + EQApplicationPacket *outapp = MakeBuffsPacket(); + entity_list.QueueClientsByTarget(this, outapp, false, nullptr, true, false, BIT_SoDAndLater, true); + safe_delete(outapp); + } + // recalculate bonuses since we stripped/added buffs CalcBonuses(); From 0a27273d6414e6d97b622ff59cc38d27d3db8188 Mon Sep 17 00:00:00 2001 From: RicardoCampos Date: Tue, 21 Oct 2014 22:48:42 +0100 Subject: [PATCH 2/6] Bugfix: Corpse stays locked when looting fails If looting fails either because of cooldown or there are items on your cursor, the client is sent an end loot packet- the client releases the corpse but no one else can loot. This simply resets BeingLootedBy in this instance. --- zone/corpse.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/zone/corpse.cpp b/zone/corpse.cpp index da9ffab17..7300db608 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -1069,6 +1069,10 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) if(!loot_cooldown_timer.Check()) { SendEndLootErrorPacket(client); + //unlock corpse for others + if (this->BeingLootedBy = client->GetID()) { + BeingLootedBy = 0xFFFFFFFF; + } return; } @@ -1077,6 +1081,10 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { client->Message(13, "You may not loot an item while you have an item on your cursor."); SendEndLootErrorPacket(client); + //unlock corpse for others + if (this->BeingLootedBy = client->GetID()) { + BeingLootedBy = 0xFFFFFFFF; + } return; } From a062c27e1a845fe8276d507096f711b018888e01 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 22 Oct 2014 22:27:51 -0400 Subject: [PATCH 3/6] Take into account endurance bonuses from AAs --- zone/client_mods.cpp | 2 +- zone/merc.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/zone/client_mods.cpp b/zone/client_mods.cpp index 2fb7ad9ca..1540b2a5f 100644 --- a/zone/client_mods.cpp +++ b/zone/client_mods.cpp @@ -1907,7 +1907,7 @@ uint16 Mob::GetInstrumentMod(uint16 spell_id) const void Client::CalcMaxEndurance() { - max_end = CalcBaseEndurance() + spellbonuses.Endurance + itembonuses.Endurance; + max_end = CalcBaseEndurance() + spellbonuses.Endurance + itembonuses.Endurance + aabonuses.Endurance; if (max_end < 0) { max_end = 0; diff --git a/zone/merc.cpp b/zone/merc.cpp index 6f500b12e..0fac55de2 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -1044,7 +1044,7 @@ int32 Merc::CalcManaRegenCap() void Merc::CalcMaxEndurance() { - max_end = CalcBaseEndurance() + spellbonuses.Endurance + itembonuses.Endurance; + max_end = CalcBaseEndurance() + spellbonuses.Endurance + itembonuses.Endurance + aabonuses.Endurance; if (max_end < 0) { max_end = 0; From c95b18da858570fe35f3e7c3964b21e7eeeae262 Mon Sep 17 00:00:00 2001 From: Uleat Date: Wed, 22 Oct 2014 22:57:20 -0400 Subject: [PATCH 4/6] Fixed stacking issue in world tradeskill containers. (Added #peekinv world) --- changelog.txt | 3 +++ zone/command.cpp | 37 ++++++++++++++++++++++++++++++++++++- zone/inventory.cpp | 1 + zone/object.cpp | 8 ++++++++ zone/object.h | 1 + 5 files changed, 49 insertions(+), 1 deletion(-) diff --git a/changelog.txt b/changelog.txt index 915f7a812..c13ee4b05 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 10/22/2014 == +Uleat: Fix for stacking items in a world object..added a new command option: #peekinv world - will show world container contents, if one is in use by target. + == 10/20/2014 == demonstar55: Inspect Buffs rank 1 will now show NPC buffs in target window (SoD+) diff --git a/zone/command.cpp b/zone/command.cpp index 33f7c2068..c1121932c 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -258,7 +258,7 @@ int command_init(void) { command_add("heal","- Completely heal your target",10,command_heal) || command_add("appearance","[type] [value] - Send an appearance packet for you or your target",150,command_appearance) || command_add("nukeitem","[itemid] - Remove itemid from your player target's inventory",150,command_nukeitem) || - command_add("peekinv","[worn/cursor/inv/bank/trade/trib/all] - Print out contents of your player target's inventory",100,command_peekinv) || + command_add("peekinv","[worn/inv/cursor/trib/bank/trade/world/all] - Print out contents of your player target's inventory",100,command_peekinv) || command_add("findnpctype","[search criteria] - Search database NPC types",100,command_findnpctype) || command_add("findzone","[search criteria] - Search database zones",100,command_findzone) || command_add("fz",nullptr,100, command_findzone) || @@ -2965,6 +2965,41 @@ void command_peekinv(Client *c, const Seperator *sep) } } + if (bAll || (strcasecmp(sep->arg[1], "world") == 0)) { + // Items in world container (if present) + bFound = true; + + Object* tsobject = c->GetTradeskillObject(); + + if (tsobject == nullptr) { + c->Message(1, "No world tradeskill object selected..."); + } + else { + c->Message(0, "[WorldObject DBID: %i (entityid: %i)]", tsobject->GetDBID(), tsobject->GetID()); + + for (int16 i = MAIN_BEGIN; i < EmuConstants::MAP_WORLD_SIZE; ++i) { + const ItemInst* inst = tsobject->GetItem(i); + item = (inst) ? inst->GetItem() : nullptr; + + linkbase = StringFormat(linkcore, 0x12, ((item == 0) ? 0 : item->ID), ((item == 0) ? "null" : item->Name), 0x12); + c->Message((item == 0), "WorldSlot: %i, Item: %i (%s), Charges: %i", + (EmuConstants::WORLD_BEGIN + i), ((item == 0) ? 0 : item->ID), linkbase.c_str(), ((item == 0) ? 0 : inst->GetCharges())); + + // this should never happen ('WorldBagSlot' as -1 indicates an error state in this implementation) + if (inst && inst->IsType(ItemClassContainer)) { + for (uint8 j = SUB_BEGIN; j < EmuConstants::ITEM_CONTAINER_SIZE; ++j) { + const ItemInst* instbag = inst->GetItem(j); + item = (instbag) ? instbag->GetItem() : nullptr; + + linkbase = StringFormat(linkcore, 0x12, ((item == 0) ? 0 : item->ID), ((item == 0) ? "null" : item->Name), 0x12); + c->Message((item == 0), " WorldBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%s), Charges: %i", + -1, i, j, ((item == 0) ? 0 : item->ID), linkbase.c_str(), ((item == 0) ? 0 : inst->GetCharges())); + } + } + } + } + } + if (!bFound) { c->Message(0, "Usage: #peekinv [worn|cursor|inv|bank|trade|trib|all]"); diff --git a/zone/inventory.cpp b/zone/inventory.cpp index 76841c86d..6a80aefe1 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -1480,6 +1480,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { } world_inst->SetCharges(world_charges); + m_tradeskill_object->PutItem(world_idx, world_inst); m_tradeskill_object->Save(); if (src_charges == 0) { diff --git a/zone/object.cpp b/zone/object.cpp index c560191f1..51d0e924a 100644 --- a/zone/object.cpp +++ b/zone/object.cpp @@ -318,6 +318,14 @@ void Object::Delete(bool reset_state) } } +const ItemInst* Object::GetItem(uint8 index) { + if (index < EmuConstants::MAP_WORLD_SIZE) { + return m_inst->GetItem(index); + } + + return nullptr; +} + // Add item to object (only logical for world tradeskill containers void Object::PutItem(uint8 index, const ItemInst* inst) { diff --git a/zone/object.h b/zone/object.h index 226b02ec5..da41d9815 100644 --- a/zone/object.h +++ b/zone/object.h @@ -121,6 +121,7 @@ public: void StartDecay() {decay_timer.Start();} // Container functions + const ItemInst* GetItem(uint8 index); void PutItem(uint8 index, const ItemInst* inst); void DeleteItem(uint8 index); // Item inside container ItemInst* PopItem(uint8 index); // Pop item out of container From 7f85d8c8a2bbc40b08fec8150b1466d2e72dac89 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 24 Oct 2014 01:05:22 -0400 Subject: [PATCH 5/6] Optional SQL to add AA Quick Draw --- utils/sql/git/optional/2014_10_24_Quick_Draw.sql | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 utils/sql/git/optional/2014_10_24_Quick_Draw.sql diff --git a/utils/sql/git/optional/2014_10_24_Quick_Draw.sql b/utils/sql/git/optional/2014_10_24_Quick_Draw.sql new file mode 100644 index 000000000..1dafd19a3 --- /dev/null +++ b/utils/sql/git/optional/2014_10_24_Quick_Draw.sql @@ -0,0 +1,4 @@ +INSERT INTO altadv_vars SET skill_id="4698", name="Quick Draw", cost="5", max_level="1", hotkey_sid="4294967295", hotkey_sid2="4294967295", title_sid="4698", desc_sid="4698", type="1", spellid="4294967295", prereq_skill="0", prereq_minpoints="0", spell_type="0", spell_refresh="0", class_type="51", cost_inc="0", aa_expansion="12", special_category="4294967295", sof_type="1", sof_cost_inc="0", sof_max_level="2", sof_next_skill="4698", clientver="4", account_time_required="0", sof_current_level="0", sof_next_id="6545", level_inc="0", classes="65534", berserker="1"; +INSERT INTO aa_effects SET aaid=4698, slot=1, effectid=362, base1=1, base2=0; +INSERT INTO altadv_vars SET skill_id="6545", name="Quick Draw II", cost="5", max_level="1", hotkey_sid="4294967295", hotkey_sid2="4294967295", title_sid="4698", desc_sid="4698", type="1", spellid="4294967295", prereq_skill="4698", prereq_minpoints="1", spell_type="0", spell_refresh="0", class_type="56", cost_inc="0", aa_expansion="14", special_category="4294967295", sof_type="1", sof_cost_inc="0", sof_max_level="2", sof_next_skill="4698", clientver="5", account_time_required="0", sof_current_level="1", sof_next_id="0", level_inc="0", classes="65534", berserker="1"; +INSERT INTO aa_effects SET aaid=6545, slot=1, effectid=362, base1=1, base2=0; From b54411e53316d7d91e55611b50340e75c0396bc4 Mon Sep 17 00:00:00 2001 From: KimLS Date: Fri, 24 Oct 2014 19:05:04 -0700 Subject: [PATCH 6/6] Fix for not loading some account data on character load --- zone/client_packet.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index efc8a5d8a..d929118b0 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -1374,10 +1374,9 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) query = StringFormat("SELECT `status`, `name`, `lsaccount_id`, `gmspeed`, `revoked`, `hideme` FROM `account` WHERE `id` = %u", this->AccountID()); auto results = database.QueryDatabase(query); for (auto row = results.begin(); row != results.end(); ++row) { - if (admin){ admin = atoi(row[0]); } - if (account_name){ strcpy(account_name, row[1]); } - if (lsaccountid && atoi(row[2]) > 0){ lsaccountid = atoi(row[2]); } - else{ lsaccountid = 0; } + admin = atoi(row[0]); + strncpy(account_name, row[1], 30); + lsaccountid = atoi(row[2]); gmspeed = atoi(row[3]); revoked = atoi(row[4]); gmhideme = atoi(row[5]);