Added clicky items from bags for clients that support it (RoF, currently)

This commit is contained in:
Uleat 2014-09-30 16:18:25 -04:00
parent 3e0c1bc02e
commit 83367ee806
13 changed files with 129 additions and 11 deletions

View File

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

View File

@ -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 */

View File

@ -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] = {

View File

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

View File

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

View File

@ -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<int16, ItemInst*> m_bank; // Items in character bank
std::map<int16, ItemInst*> m_shbank; // Items in character shared bank
std::map<int16, ItemInst*> 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;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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