From 83367ee80605acd57147333c0d3e3f0c0bc4bd09 Mon Sep 17 00:00:00 2001 From: Uleat Date: Tue, 30 Sep 2014 16:18:25 -0400 Subject: [PATCH] Added clicky items from bags for clients that support it (RoF, currently) --- changelog.txt | 3 ++ common/clientversions.h | 44 ++++++++++++++++++++++++---- common/eq_dictionary.cpp | 20 +++++++++++++ common/eq_dictionary.h | 1 + common/item.cpp | 24 +++++++++++++++ common/item.h | 27 +++++++++++++++-- common/patches/client62_constants.h | 1 + common/patches/rof_constants.h | 1 + common/patches/sod_constants.h | 1 + common/patches/sof_constants.h | 1 + common/patches/titanium_constants.h | 1 + common/patches/underfoot_constants.h | 1 + zone/client_packet.cpp | 15 +++++++--- 13 files changed, 129 insertions(+), 11 deletions(-) diff --git a/changelog.txt b/changelog.txt index 4657226a2..41b5a810d 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 09/30/2014 == +Uleat: Implemented click-casting from bag slots for clients that natively support it (RoF) + == 09/28/2014 == demonstar55: Add support for post June 18, 2014 Hundred Hands Effect spells (they changed the formula and stuff) set Spells:Jun182014HundredHandsRevamp to true if you're using a spell file from June 18, 2014+ diff --git a/common/clientversions.h b/common/clientversions.h index 47a7d0204..ee70d481c 100644 --- a/common/clientversions.h +++ b/common/clientversions.h @@ -17,7 +17,8 @@ static const uint32 BIT_RoFAndLater = 0xFFFFFFE0; static const uint32 BIT_RoF2AndLater = 0xFFFFFFC0; static const uint32 BIT_AllClients = 0xFFFFFFFF; -typedef enum { +typedef enum +{ EQClientUnknown = 0, EQClient62, // Build: 'Aug 4 2005 15:40:59' EQClientTitanium, // Build: 'Oct 31 2005 10:33:37' @@ -26,17 +27,50 @@ typedef enum { EQClientUnderfoot, // Build: 'Jun 8 2010 16:44:32' EQClientRoF, // Build: 'Dec 10 2012 17:35:44' EQClientRoF2, // Build: 'May 10 2013 23:30:08' - + _EQClientCount, // place new clients before this point (preferably, in release/attribute order) - + // Values below are not implemented, as yet... - + EmuNPC = _EQClientCount, EmuMerc, EmuBot, EmuPet, - + _EmuClientCount // array size for EQLimits } EQClientVersion; +static const char* EQClientVersionName(EQClientVersion version) +{ + switch (version) + { + case EQClientUnknown: + return "EQClientUnknown"; + case EQClient62: + return "EQClient62"; + case EQClientTitanium: + return "EQClientTitanium"; + case EQClientSoF: + return "EQClientSoF"; + case EQClientSoD: + return "EQClientSoD"; + case EQClientUnderfoot: + return "EQClientUnderfoot"; + case EQClientRoF: + return "EQClientRoF"; + case EQClientRoF2: + return "EQClientRoF2"; + case EmuNPC: + return "EmuNPC"; + case EmuMerc: + return "EmuMerc"; + case EmuBot: + return "EmuBot"; + case EmuPet: + return "EmuPet"; + default: + return "ERROR: Invalid EQClientVersion"; + }; +} + #endif /* CLIENTVERSIONS_H */ diff --git a/common/eq_dictionary.cpp b/common/eq_dictionary.cpp index 595d0cc5f..f85d3110f 100644 --- a/common/eq_dictionary.cpp +++ b/common/eq_dictionary.cpp @@ -1024,6 +1024,26 @@ bool EQLimits::AllowsEmptyBagInBag(uint32 version) { //return local[ValidateMobVersion(version)]; } +bool EQLimits::AllowsClickCastFromBag(uint32 version) { + static const bool local[_EmuClientCount] = { +/*Unknown*/ false, +/*62*/ Client62::limits::ALLOWS_CLICK_CAST_FROM_BAG, +/*Titanium*/ Titanium::limits::ALLOWS_CLICK_CAST_FROM_BAG, +/*SoF*/ SoF::limits::ALLOWS_CLICK_CAST_FROM_BAG, +/*SoD*/ SoD::limits::ALLOWS_CLICK_CAST_FROM_BAG, +/*Underfoot*/ Underfoot::limits::ALLOWS_CLICK_CAST_FROM_BAG, +/*RoF*/ RoF::limits::ALLOWS_CLICK_CAST_FROM_BAG, +/*RoF2*/ false, + +/*NPC*/ false, +/*Merc*/ false, +/*Bot*/ false, +/*Pet*/ false + }; + + return local[ValidateMobVersion(version)]; +} + // items uint16 EQLimits::ItemCommonSize(uint32 version) { static const uint16 local[_EmuClientCount] = { diff --git a/common/eq_dictionary.h b/common/eq_dictionary.h index 14f9d53d3..c08809a12 100644 --- a/common/eq_dictionary.h +++ b/common/eq_dictionary.h @@ -184,6 +184,7 @@ public: static uint64 CursorBitmask(uint32 version); static bool AllowsEmptyBagInBag(uint32 version); + static bool AllowsClickCastFromBag(uint32 version); // items static uint16 ItemCommonSize(uint32 version); diff --git a/common/item.cpp b/common/item.cpp index 513ddb23f..cfa52e0c4 100644 --- a/common/item.cpp +++ b/common/item.cpp @@ -911,6 +911,30 @@ bool Inventory::CanItemFitInContainer(const Item_Struct *ItemToTry, const Item_S return true; } +bool Inventory::SupportsClickCasting(int16 slot_id) +{ + // there are a few non-potion items that identify as ItemTypePotion..so, we still need to ubiquitously include the equipment range + if ((uint16)slot_id <= EmuConstants::GENERAL_END || slot_id == MainPowerSource) + { + return true; + } + else if (slot_id >= EmuConstants::GENERAL_BAGS_BEGIN && slot_id <= EmuConstants::GENERAL_BAGS_END) + { + if (EQLimits::AllowsClickCastFromBag(m_version)) + return true; + } + + return false; +} + +bool Inventory::SupportsPotionBeltCasting(int16 slot_id) +{ + if ((uint16)slot_id <= EmuConstants::GENERAL_END || slot_id == MainPowerSource || (slot_id >= EmuConstants::GENERAL_BAGS_BEGIN && slot_id <= EmuConstants::GENERAL_BAGS_END)) + return true; + + return false; +} + // Test whether a given slot can support a container item bool Inventory::SupportsContainers(int16 slot_id) { diff --git a/common/item.h b/common/item.h index c24c708b1..9be660117 100644 --- a/common/item.h +++ b/common/item.h @@ -121,8 +121,22 @@ public: // Public Methods /////////////////////////////// + Inventory() { m_version = EQClientUnknown; m_versionset = false; } ~Inventory(); + // Inventory v2 creep + bool SetInventoryVersion(EQClientVersion version) { + if (!m_versionset) { + m_version = version; + return (m_versionset = true); + } + else { + return false; + } + } + + EQClientVersion GetInventoryVersion() { return m_version; } + static void CleanDirty(); static void MarkDirty(ItemInst *inst); @@ -132,7 +146,7 @@ public: inline iter_queue cursor_begin() { return m_cursor.begin(); } inline iter_queue cursor_end() { return m_cursor.end(); } - inline bool CursorEmpty() { return (m_cursor.size() == 0); } + inline bool CursorEmpty() { return (m_cursor.size() == 0); } // Retrieve a read-only item from inventory inline const ItemInst* operator[](int16 slot_id) const { return GetItem(slot_id); } @@ -183,6 +197,10 @@ public: static bool CanItemFitInContainer(const Item_Struct *ItemToTry, const Item_Struct *Container); + // Test for valid inventory casting slot + bool SupportsClickCasting(int16 slot_id); + bool SupportsPotionBeltCasting(int16 slot_id); + // Test whether a given slot can support a container item static bool SupportsContainers(int16 slot_id); @@ -229,7 +247,12 @@ protected: std::map m_bank; // Items in character bank std::map m_shbank; // Items in character shared bank std::map m_trade; // Items in a trade session - ItemInstQueue m_cursor; // Items on cursor: FIFO + ItemInstQueue m_cursor; // Items on cursor: FIFO + +private: + // Active inventory version + EQClientVersion m_version; + bool m_versionset; }; class SharedDatabase; diff --git a/common/patches/client62_constants.h b/common/patches/client62_constants.h index 7d2125028..0e672a5de 100644 --- a/common/patches/client62_constants.h +++ b/common/patches/client62_constants.h @@ -180,6 +180,7 @@ namespace Client62 { namespace limits { static const bool ALLOWS_EMPTY_BAG_IN_BAG = false; + static const bool ALLOWS_CLICK_CAST_FROM_BAG = false; static const bool COIN_HAS_WEIGHT = true; } diff --git a/common/patches/rof_constants.h b/common/patches/rof_constants.h index 62a161dc5..97cb25aa5 100644 --- a/common/patches/rof_constants.h +++ b/common/patches/rof_constants.h @@ -184,6 +184,7 @@ namespace RoF { namespace limits { static const bool ALLOWS_EMPTY_BAG_IN_BAG = true; + static const bool ALLOWS_CLICK_CAST_FROM_BAG = true; static const bool COIN_HAS_WEIGHT = false; } diff --git a/common/patches/sod_constants.h b/common/patches/sod_constants.h index 9a8907f13..8bdf45532 100644 --- a/common/patches/sod_constants.h +++ b/common/patches/sod_constants.h @@ -181,6 +181,7 @@ namespace SoD { namespace limits { static const bool ALLOWS_EMPTY_BAG_IN_BAG = false; + static const bool ALLOWS_CLICK_CAST_FROM_BAG = false; static const bool COIN_HAS_WEIGHT = false; } diff --git a/common/patches/sof_constants.h b/common/patches/sof_constants.h index d80fa2dcb..0b959ef3a 100644 --- a/common/patches/sof_constants.h +++ b/common/patches/sof_constants.h @@ -181,6 +181,7 @@ namespace SoF { namespace limits { static const bool ALLOWS_EMPTY_BAG_IN_BAG = false; + static const bool ALLOWS_CLICK_CAST_FROM_BAG = false; static const bool COIN_HAS_WEIGHT = true; } diff --git a/common/patches/titanium_constants.h b/common/patches/titanium_constants.h index 71625362a..85e525fe8 100644 --- a/common/patches/titanium_constants.h +++ b/common/patches/titanium_constants.h @@ -180,6 +180,7 @@ namespace Titanium { namespace limits { static const bool ALLOWS_EMPTY_BAG_IN_BAG = false; + static const bool ALLOWS_CLICK_CAST_FROM_BAG = false; static const bool COIN_HAS_WEIGHT = true; } diff --git a/common/patches/underfoot_constants.h b/common/patches/underfoot_constants.h index fdbe54086..b89a4f255 100644 --- a/common/patches/underfoot_constants.h +++ b/common/patches/underfoot_constants.h @@ -181,6 +181,7 @@ namespace Underfoot { namespace limits { static const bool ALLOWS_EMPTY_BAG_IN_BAG = false; + static const bool ALLOWS_CLICK_CAST_FROM_BAG = false; static const bool COIN_HAS_WEIGHT = false; } diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 0061efff4..340723385 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -1307,7 +1307,13 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) conn_state = ReceivedZoneEntry; ClientVersion = Connection()->ClientVersion(); - ClientVersionBit = 1 << (ClientVersion - 1); + if (ClientVersion != EQClientUnknown) + ClientVersionBit = 1 << (ClientVersion - 1); + else + ClientVersionBit = 0; + + bool siv = m_inv.SetInventoryVersion(ClientVersion); + LogFile->write(EQEMuLog::Debug, "%s inventory version to %s(%i)", (siv ? "Succeeded in setting" : "Failed to set"), EQClientVersionName(ClientVersion), ClientVersion); /* Antighost code tmp var is so the search doesnt find this object @@ -3999,15 +4005,16 @@ void Client::Handle_OP_CastSpell(const EQApplicationPacket *app) else if ((castspell->slot == USE_ITEM_SPELL_SLOT) || (castspell->slot == POTION_BELT_SPELL_SLOT)) // ITEM or POTION cast { //discipline, using the item spell slot - if (castspell->inventoryslot == 0xFFFFFFFF) { + if (castspell->inventoryslot == INVALID_INDEX) { if (!UseDiscipline(castspell->spell_id, castspell->target_id)) { LogFile->write(EQEMuLog::Debug, "Unknown ability being used by %s, spell being cast is: %i\n", GetName(), castspell->spell_id); InterruptSpell(castspell->spell_id); } return; } - else if ((castspell->inventoryslot <= EmuConstants::GENERAL_END) || (castspell->slot == POTION_BELT_SPELL_SLOT)) // sanity check + else if (m_inv.SupportsClickCasting(castspell->inventoryslot) || (castspell->slot == POTION_BELT_SPELL_SLOT)) // sanity check { + // packet field types will be reviewed as packet transistions occur -U const ItemInst* inst = m_inv[castspell->inventoryslot]; //slot values are int16, need to check packet on this field //bool cancast = true; if (inst && inst->IsType(ItemClassCommon)) @@ -8555,7 +8562,7 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app) LogFile->write(EQEMuLog::Debug, "OP ItemVerifyRequest: spell=%i, target=%i, inv=%i", spell_id, target_id, slot_id); - if ((slot_id < MainCursor) || (slot_id == MainPowerSource) || (slot_id > 250 && slot_id < 331 && ((item->ItemType == ItemTypePotion) || item->PotionBelt))) // sanity check + if (m_inv.SupportsClickCasting(slot_id) || ((item->ItemType == ItemTypePotion || item->PotionBelt) && m_inv.SupportsPotionBeltCasting(slot_id))) // sanity check { ItemInst* p_inst = (ItemInst*)inst;