Merge git://github.com/EQEmu/Server into Development

This commit is contained in:
KayenEQ 2015-02-07 20:19:58 -05:00
commit 9aac1b0081
14 changed files with 222 additions and 130 deletions

View File

@ -1,5 +1,14 @@
EQEMu Changelog (Started on Sept 24, 2003 15:50) EQEMu Changelog (Started on Sept 24, 2003 15:50)
------------------------------------------------------- -------------------------------------------------------
== 02/06/2015 ==
Uleat: Updated returns for Inventory and ItemInst const iterators. (const == const)
Uleat: Replaced 'iter_inst' and 'iter_contents' typedefs with their stl definitions
Uleat: Removed 'limbo' from the 'HasItem' series of checks - including lore checks. The client excludes this range and it causes issues when performing item searches - dupe lore checks were added to account for this.
Uleat: Updated command #iteminfo to show light source information and a few other things
== 02/05/2015 ==
Trevius: Fixed Environmental Damage for RoF2.
== 02/03/2015 == == 02/03/2015 ==
Trevius: Crashfix for TempName() when numbers are passed at the end of the name. Trevius: Crashfix for TempName() when numbers are passed at the end of the name.
Uleat: Tweaking of item type exclusions to alleviate strobing conditions with light sources Uleat: Tweaking of item type exclusions to alleviate strobing conditions with light sources

View File

@ -506,6 +506,7 @@ int16 Inventory::HasItem(uint32 item_id, uint8 quantity, uint8 where)
return slot_id; return slot_id;
} }
// Behavioral change - Limbo is no longer checked due to improper handling of return value
if (where & invWhereCursor) { if (where & invWhereCursor) {
// Check cursor queue // Check cursor queue
slot_id = _HasItem(m_cursor, item_id, quantity); slot_id = _HasItem(m_cursor, item_id, quantity);
@ -552,6 +553,7 @@ int16 Inventory::HasItemByUse(uint8 use, uint8 quantity, uint8 where)
return slot_id; return slot_id;
} }
// Behavioral change - Limbo is no longer checked due to improper handling of return value
if (where & invWhereCursor) { if (where & invWhereCursor) {
// Check cursor queue // Check cursor queue
slot_id = _HasItemByUse(m_cursor, use, quantity); slot_id = _HasItemByUse(m_cursor, use, quantity);
@ -597,6 +599,7 @@ int16 Inventory::HasItemByLoreGroup(uint32 loregroup, uint8 where)
return slot_id; return slot_id;
} }
// Behavioral change - Limbo is no longer checked due to improper handling of return value
if (where & invWhereCursor) { if (where & invWhereCursor) {
// Check cursor queue // Check cursor queue
slot_id = _HasItemByLoreGroup(m_cursor, loregroup); slot_id = _HasItemByLoreGroup(m_cursor, loregroup);
@ -1060,7 +1063,7 @@ int Inventory::GetSlotByItemInstCollection(const std::map<int16, ItemInst*> &col
} }
if (t_inst && !t_inst->IsType(ItemClassContainer)) { if (t_inst && !t_inst->IsType(ItemClassContainer)) {
for (auto b_iter = t_inst->_begin(); b_iter != t_inst->_end(); ++b_iter) { for (auto b_iter = t_inst->_cbegin(); b_iter != t_inst->_cend(); ++b_iter) {
if (b_iter->second == inst) { if (b_iter->second == inst) {
return Inventory::CalcSlotId(iter->first, b_iter->first); return Inventory::CalcSlotId(iter->first, b_iter->first);
} }
@ -1071,13 +1074,10 @@ int Inventory::GetSlotByItemInstCollection(const std::map<int16, ItemInst*> &col
return -1; return -1;
} }
void Inventory::dumpItemCollection(const std::map<int16, ItemInst*> &collection) { void Inventory::dumpItemCollection(const std::map<int16, ItemInst*> &collection)
iter_inst it; {
iter_contents itb; for (auto it = collection.cbegin(); it != collection.cend(); ++it) {
ItemInst* inst = nullptr; auto inst = it->second;
for (it = collection.begin(); it != collection.end(); ++it) {
inst = it->second;
if (!inst || !inst->GetItem()) if (!inst || !inst->GetItem())
continue; continue;
@ -1088,14 +1088,13 @@ void Inventory::dumpItemCollection(const std::map<int16, ItemInst*> &collection)
} }
} }
void Inventory::dumpBagContents(ItemInst *inst, iter_inst *it) { void Inventory::dumpBagContents(ItemInst *inst, std::map<int16, ItemInst*>::const_iterator *it)
iter_contents itb; {
if (!inst || !inst->IsType(ItemClassContainer)) if (!inst || !inst->IsType(ItemClassContainer))
return; return;
// Go through bag, if bag // Go through bag, if bag
for (itb = inst->_begin(); itb != inst->_end(); ++itb) { for (auto itb = inst->_cbegin(); itb != inst->_cend(); ++itb) {
ItemInst* baginst = itb->second; ItemInst* baginst = itb->second;
if (!baginst || !baginst->GetItem()) if (!baginst || !baginst->GetItem())
continue; continue;
@ -1110,7 +1109,7 @@ void Inventory::dumpBagContents(ItemInst *inst, iter_inst *it) {
// Internal Method: Retrieves item within an inventory bucket // Internal Method: Retrieves item within an inventory bucket
ItemInst* Inventory::_GetItem(const std::map<int16, ItemInst*>& bucket, int16 slot_id) const ItemInst* Inventory::_GetItem(const std::map<int16, ItemInst*>& bucket, int16 slot_id) const
{ {
iter_inst it = bucket.find(slot_id); auto it = bucket.find(slot_id);
if (it != bucket.end()) { if (it != bucket.end()) {
return it->second; return it->second;
} }
@ -1123,6 +1122,8 @@ ItemInst* Inventory::_GetItem(const std::map<int16, ItemInst*>& bucket, int16 sl
// Assumes item has already been allocated // Assumes item has already been allocated
int16 Inventory::_PutItem(int16 slot_id, ItemInst* inst) int16 Inventory::_PutItem(int16 slot_id, ItemInst* inst)
{ {
// What happens here when we _PutItem(MainCursor)? Bad things..really bad things...
//
// If putting a nullptr into slot, we need to remove slot without memory delete // If putting a nullptr into slot, we need to remove slot without memory delete
if (inst == nullptr) { if (inst == nullptr) {
//Why do we not delete the poped item here???? //Why do we not delete the poped item here????
@ -1204,7 +1205,7 @@ int16 Inventory::_HasItem(std::map<int16, ItemInst*>& bucket, uint32 item_id, ui
if (!inst->IsType(ItemClassContainer)) { continue; } if (!inst->IsType(ItemClassContainer)) { continue; }
for (auto bag_iter = inst->_begin(); bag_iter != inst->_end(); ++bag_iter) { for (auto bag_iter = inst->_cbegin(); bag_iter != inst->_cend(); ++bag_iter) {
auto bag_inst = bag_iter->second; auto bag_inst = bag_iter->second;
if (bag_inst == nullptr) { continue; } if (bag_inst == nullptr) { continue; }
@ -1235,7 +1236,7 @@ int16 Inventory::_HasItem(ItemInstQueue& iqueue, uint32 item_id, uint8 quantity)
uint8 quantity_found = 0; uint8 quantity_found = 0;
for (auto iter = iqueue.begin(); iter != iqueue.end(); ++iter) { for (auto iter = iqueue.cbegin(); iter != iqueue.cend(); ++iter) {
auto inst = *iter; auto inst = *iter;
if (inst == nullptr) { continue; } if (inst == nullptr) { continue; }
@ -1252,7 +1253,7 @@ int16 Inventory::_HasItem(ItemInstQueue& iqueue, uint32 item_id, uint8 quantity)
if (!inst->IsType(ItemClassContainer)) { continue; } if (!inst->IsType(ItemClassContainer)) { continue; }
for (auto bag_iter = inst->_begin(); bag_iter != inst->_end(); ++bag_iter) { for (auto bag_iter = inst->_cbegin(); bag_iter != inst->_cend(); ++bag_iter) {
auto bag_inst = bag_iter->second; auto bag_inst = bag_iter->second;
if (bag_inst == nullptr) { continue; } if (bag_inst == nullptr) { continue; }
@ -1267,6 +1268,9 @@ int16 Inventory::_HasItem(ItemInstQueue& iqueue, uint32 item_id, uint8 quantity)
return legacy::SLOT_AUGMENT; return legacy::SLOT_AUGMENT;
} }
} }
// We only check the visible cursor due to lack of queue processing ability (client allows duplicate in limbo)
break;
} }
return INVALID_INDEX; return INVALID_INDEX;
@ -1289,7 +1293,7 @@ int16 Inventory::_HasItemByUse(std::map<int16, ItemInst*>& bucket, uint8 use, ui
if (!inst->IsType(ItemClassContainer)) { continue; } if (!inst->IsType(ItemClassContainer)) { continue; }
for (auto bag_iter = inst->_begin(); bag_iter != inst->_end(); ++bag_iter) { for (auto bag_iter = inst->_cbegin(); bag_iter != inst->_cend(); ++bag_iter) {
auto bag_inst = bag_iter->second; auto bag_inst = bag_iter->second;
if (bag_inst == nullptr) { continue; } if (bag_inst == nullptr) { continue; }
@ -1309,7 +1313,7 @@ int16 Inventory::_HasItemByUse(ItemInstQueue& iqueue, uint8 use, uint8 quantity)
{ {
uint8 quantity_found = 0; uint8 quantity_found = 0;
for (auto iter = iqueue.begin(); iter != iqueue.end(); ++iter) { for (auto iter = iqueue.cbegin(); iter != iqueue.cend(); ++iter) {
auto inst = *iter; auto inst = *iter;
if (inst == nullptr) { continue; } if (inst == nullptr) { continue; }
@ -1321,7 +1325,7 @@ int16 Inventory::_HasItemByUse(ItemInstQueue& iqueue, uint8 use, uint8 quantity)
if (!inst->IsType(ItemClassContainer)) { continue; } if (!inst->IsType(ItemClassContainer)) { continue; }
for (auto bag_iter = inst->_begin(); bag_iter != inst->_end(); ++bag_iter) { for (auto bag_iter = inst->_cbegin(); bag_iter != inst->_cend(); ++bag_iter) {
auto bag_inst = bag_iter->second; auto bag_inst = bag_iter->second;
if (bag_inst == nullptr) { continue; } if (bag_inst == nullptr) { continue; }
@ -1331,6 +1335,9 @@ int16 Inventory::_HasItemByUse(ItemInstQueue& iqueue, uint8 use, uint8 quantity)
return Inventory::CalcSlotId(MainCursor, bag_iter->first); return Inventory::CalcSlotId(MainCursor, bag_iter->first);
} }
} }
// We only check the visible cursor due to lack of queue processing ability (client allows duplicate in limbo)
break;
} }
return INVALID_INDEX; return INVALID_INDEX;
@ -1355,7 +1362,7 @@ int16 Inventory::_HasItemByLoreGroup(std::map<int16, ItemInst*>& bucket, uint32
if (!inst->IsType(ItemClassContainer)) { continue; } if (!inst->IsType(ItemClassContainer)) { continue; }
for (auto bag_iter = inst->_begin(); bag_iter != inst->_end(); ++bag_iter) { for (auto bag_iter = inst->_cbegin(); bag_iter != inst->_cend(); ++bag_iter) {
auto bag_inst = bag_iter->second; auto bag_inst = bag_iter->second;
if (bag_inst == nullptr) { continue; } if (bag_inst == nullptr) { continue; }
@ -1378,7 +1385,7 @@ int16 Inventory::_HasItemByLoreGroup(std::map<int16, ItemInst*>& bucket, uint32
// Internal Method: Checks an inventory queue type bucket for a particular item // Internal Method: Checks an inventory queue type bucket for a particular item
int16 Inventory::_HasItemByLoreGroup(ItemInstQueue& iqueue, uint32 loregroup) int16 Inventory::_HasItemByLoreGroup(ItemInstQueue& iqueue, uint32 loregroup)
{ {
for (auto iter = iqueue.begin(); iter != iqueue.end(); ++iter) { for (auto iter = iqueue.cbegin(); iter != iqueue.cend(); ++iter) {
auto inst = *iter; auto inst = *iter;
if (inst == nullptr) { continue; } if (inst == nullptr) { continue; }
@ -1395,7 +1402,7 @@ int16 Inventory::_HasItemByLoreGroup(ItemInstQueue& iqueue, uint32 loregroup)
if (!inst->IsType(ItemClassContainer)) { continue; } if (!inst->IsType(ItemClassContainer)) { continue; }
for (auto bag_iter = inst->_begin(); bag_iter != inst->_end(); ++bag_iter) { for (auto bag_iter = inst->_cbegin(); bag_iter != inst->_cend(); ++bag_iter) {
auto bag_inst = bag_iter->second; auto bag_inst = bag_iter->second;
if (bag_inst == nullptr) { continue; } if (bag_inst == nullptr) { continue; }
@ -1410,6 +1417,9 @@ int16 Inventory::_HasItemByLoreGroup(ItemInstQueue& iqueue, uint32 loregroup)
return legacy::SLOT_AUGMENT; return legacy::SLOT_AUGMENT;
} }
} }
// We only check the visible cursor due to lack of queue processing ability (client allows duplicate in limbo)
break;
} }
return INVALID_INDEX; return INVALID_INDEX;
@ -1505,8 +1515,7 @@ ItemInst::ItemInst(const ItemInst& copy)
m_attuned=copy.m_attuned; m_attuned=copy.m_attuned;
m_merchantcount=copy.m_merchantcount; m_merchantcount=copy.m_merchantcount;
// Copy container contents // Copy container contents
iter_contents it; for (auto it = copy.m_contents.begin(); it != copy.m_contents.end(); ++it) {
for (it=copy.m_contents.begin(); it!=copy.m_contents.end(); ++it) {
ItemInst* inst_old = it->second; ItemInst* inst_old = it->second;
ItemInst* inst_new = nullptr; ItemInst* inst_new = nullptr;
@ -1676,7 +1685,7 @@ bool ItemInst::IsAugmentSlotAvailable(int32 augtype, uint8 slot) const
// Retrieve item inside container // Retrieve item inside container
ItemInst* ItemInst::GetItem(uint8 index) const ItemInst* ItemInst::GetItem(uint8 index) const
{ {
iter_contents it = m_contents.find(index); auto it = m_contents.find(index);
if (it != m_contents.end()) { if (it != m_contents.end()) {
return it->second; return it->second;
} }
@ -1739,7 +1748,7 @@ void ItemInst::ClearByFlags(byFlagSetting is_nodrop, byFlagSetting is_norent)
// TODO: This needs work... // TODO: This needs work...
// Destroy container contents // Destroy container contents
iter_contents cur, end, del; std::map<uint8, ItemInst*>::const_iterator cur, end, del;
cur = m_contents.begin(); cur = m_contents.begin();
end = m_contents.end(); end = m_contents.end();
for (; cur != end;) { for (; cur != end;) {

View File

@ -33,9 +33,6 @@ class EvolveInfo; // Stores information about an evolving item family
#include <list> #include <list>
#include <map> #include <map>
// Helper typedefs
typedef std::map<int16, ItemInst*>::const_iterator iter_inst;
typedef std::map<uint8, ItemInst*>::const_iterator iter_contents;
namespace ItemField namespace ItemField
{ {
@ -86,8 +83,8 @@ public:
// Public Methods // Public Methods
///////////////////////// /////////////////////////
inline std::list<ItemInst*>::const_iterator begin() { return m_list.begin(); } inline std::list<ItemInst*>::const_iterator cbegin() { return m_list.cbegin(); }
inline std::list<ItemInst*>::const_iterator end() { return m_list.end(); } inline std::list<ItemInst*>::const_iterator cend() { return m_list.cend(); }
inline int size() { return static_cast<int>(m_list.size()); } // TODO: change to size_t inline int size() { return static_cast<int>(m_list.size()); } // TODO: change to size_t
inline bool empty() { return m_list.empty(); } inline bool empty() { return m_list.empty(); }
@ -140,8 +137,8 @@ public:
ItemInst* GetItem(int16 slot_id) const; ItemInst* GetItem(int16 slot_id) const;
ItemInst* GetItem(int16 slot_id, uint8 bagidx) const; ItemInst* GetItem(int16 slot_id, uint8 bagidx) const;
inline std::list<ItemInst*>::const_iterator cursor_begin() { return m_cursor.begin(); } inline std::list<ItemInst*>::const_iterator cursor_cbegin() { return m_cursor.cbegin(); }
inline std::list<ItemInst*>::const_iterator cursor_end() { return m_cursor.end(); } inline std::list<ItemInst*>::const_iterator cursor_cend() { return m_cursor.cend(); }
inline int CursorSize() { return m_cursor.size(); } inline int CursorSize() { return m_cursor.size(); }
inline bool CursorEmpty() { return m_cursor.empty(); } inline bool CursorEmpty() { return m_cursor.empty(); }
@ -227,7 +224,7 @@ protected:
int GetSlotByItemInstCollection(const std::map<int16, ItemInst*> &collection, ItemInst *inst); int GetSlotByItemInstCollection(const std::map<int16, ItemInst*> &collection, ItemInst *inst);
void dumpItemCollection(const std::map<int16, ItemInst*> &collection); void dumpItemCollection(const std::map<int16, ItemInst*> &collection);
void dumpBagContents(ItemInst *inst, iter_inst *it); void dumpBagContents(ItemInst *inst, std::map<int16, ItemInst*>::const_iterator *it);
// Retrieves item within an inventory bucket // Retrieves item within an inventory bucket
ItemInst* _GetItem(const std::map<int16, ItemInst*>& bucket, int16 slot_id) const; ItemInst* _GetItem(const std::map<int16, ItemInst*>& bucket, int16 slot_id) const;
@ -425,8 +422,8 @@ protected:
////////////////////////// //////////////////////////
// Protected Members // Protected Members
////////////////////////// //////////////////////////
iter_contents _begin() { return m_contents.begin(); } std::map<uint8, ItemInst*>::const_iterator _cbegin() { return m_contents.cbegin(); }
iter_contents _end() { return m_contents.end(); } std::map<uint8, ItemInst*>::const_iterator _cend() { return m_contents.cend(); }
friend class Inventory; friend class Inventory;

View File

@ -2865,7 +2865,7 @@ struct SetRunMode_Struct {
}; };
// EnvDamage is EnvDamage2 without a few bytes at the end. // EnvDamage is EnvDamage2 without a few bytes at the end.
// Size: 37 bytes // Size: 39 bytes
struct EnvDamage2_Struct { struct EnvDamage2_Struct {
/*0000*/ uint32 id; /*0000*/ uint32 id;
/*0004*/ uint16 unknown4; /*0004*/ uint16 unknown4;
@ -2877,7 +2877,8 @@ struct EnvDamage2_Struct {
/*0031*/ uint16 unknown31; // New to Underfoot - Seen 66 /*0031*/ uint16 unknown31; // New to Underfoot - Seen 66
/*0033*/ uint16 constant; // Always FFFF /*0033*/ uint16 constant; // Always FFFF
/*0035*/ uint16 unknown35; /*0035*/ uint16 unknown35;
/*0037*/ /*0037*/ uint16 unknown37;
/*0039*/
}; };
//Bazaar Stuff //Bazaar Stuff

View File

@ -141,6 +141,11 @@ Client::Client(EQStreamInterface* ieqs)
merc_timer(RuleI(Mercs, UpkeepIntervalMS)), merc_timer(RuleI(Mercs, UpkeepIntervalMS)),
ItemTickTimer(10000), ItemTickTimer(10000),
ItemQuestTimer(500), ItemQuestTimer(500),
anim_change_timer(100),
anon_toggle_timer(250),
afk_toggle_timer(250),
helm_toggle_timer(250),
light_update_timer(250),
m_Proximity(FLT_MAX, FLT_MAX, FLT_MAX), //arbitrary large number m_Proximity(FLT_MAX, FLT_MAX, FLT_MAX), //arbitrary large number
m_ZoneSummonLocation(-2.0f,-2.0f,-2.0f), m_ZoneSummonLocation(-2.0f,-2.0f,-2.0f),
m_AutoAttackPosition(0.0f, 0.0f, 0.0f, 0.0f), m_AutoAttackPosition(0.0f, 0.0f, 0.0f, 0.0f),

View File

@ -1465,6 +1465,11 @@ private:
Timer TrackingTimer; Timer TrackingTimer;
Timer RespawnFromHoverTimer; Timer RespawnFromHoverTimer;
Timer merc_timer; Timer merc_timer;
Timer anim_change_timer;
Timer anon_toggle_timer;
Timer afk_toggle_timer;
Timer helm_toggle_timer;
Timer light_update_timer;
glm::vec3 m_Proximity; glm::vec3 m_Proximity;

View File

@ -1838,9 +1838,9 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
if (loaditems) { /* Dont load if a length error occurs */ if (loaditems) { /* Dont load if a length error occurs */
BulkSendInventoryItems(); BulkSendInventoryItems();
/* Send stuff on the cursor which isnt sent in bulk */ /* Send stuff on the cursor which isnt sent in bulk */
for (auto iter = m_inv.cursor_begin(); iter != m_inv.cursor_end(); ++iter) { for (auto iter = m_inv.cursor_cbegin(); iter != m_inv.cursor_cend(); ++iter) {
/* First item cursor is sent in bulk inventory packet */ /* First item cursor is sent in bulk inventory packet */
if (iter == m_inv.cursor_begin()) if (iter == m_inv.cursor_cbegin())
continue; continue;
const ItemInst *inst = *iter; const ItemInst *inst = *iter;
SendItemPacket(MainCursor, inst, ItemPacketSummonItem); SendItemPacket(MainCursor, inst, ItemPacketSummonItem);
@ -5516,7 +5516,7 @@ void Client::Handle_OP_EnvDamage(const EQApplicationPacket *app)
if (damage < 0) if (damage < 0)
damage = 31337; damage = 31337;
if (admin >= minStatusToAvoidFalling && GetGM()){ if (admin >= minStatusToAvoidFalling && GetGM()) {
Message(13, "Your GM status protects you from %i points of type %i environmental damage.", ed->damage, ed->dmgtype); Message(13, "Your GM status protects you from %i points of type %i environmental damage.", ed->damage, ed->dmgtype);
SetHP(GetHP() - 1);//needed or else the client wont acknowledge SetHP(GetHP() - 1);//needed or else the client wont acknowledge
return; return;
@ -5526,11 +5526,11 @@ void Client::Handle_OP_EnvDamage(const EQApplicationPacket *app)
SetHP(GetHP() - 1);//needed or else the client wont acknowledge SetHP(GetHP() - 1);//needed or else the client wont acknowledge
return; return;
} }
else if (zone->GetZoneID() == 183 || zone->GetZoneID() == 184) {
else if (zone->GetZoneID() == 183 || zone->GetZoneID() == 184){ // Hard coded tutorial and load zones for no fall damage
return; return;
} }
else{ else {
SetHP(GetHP() - (damage * RuleR(Character, EnvironmentDamageMulipliter))); SetHP(GetHP() - (damage * RuleR(Character, EnvironmentDamageMulipliter)));
/* EVENT_ENVIRONMENTAL_DAMAGE */ /* EVENT_ENVIRONMENTAL_DAMAGE */
@ -12640,6 +12640,10 @@ void Client::Handle_OP_SpawnAppearance(const EQApplicationPacket *app)
else if (sa->type == AT_Anim) { else if (sa->type == AT_Anim) {
if (IsAIControlled()) if (IsAIControlled())
return; return;
if(!anim_change_timer.Check())
return;
if (sa->parameter == ANIM_STAND) { if (sa->parameter == ANIM_STAND) {
SetAppearance(eaStanding); SetAppearance(eaStanding);
playeraction = 0; playeraction = 0;
@ -12673,15 +12677,6 @@ void Client::Handle_OP_SpawnAppearance(const EQApplicationPacket *app)
SetFeigned(false); SetFeigned(false);
} }
// This is from old code
// I have no clue what it's for
/*
else if (sa->parameter == 0x05) {
// Illusion
std::cout << "Illusion packet recv'd:" << std::endl;
DumpPacket(app);
}
*/
else { else {
std::cerr << "Client " << name << " unknown apperance " << (int)sa->parameter << std::endl; std::cerr << "Client " << name << " unknown apperance " << (int)sa->parameter << std::endl;
return; return;
@ -12690,6 +12685,10 @@ void Client::Handle_OP_SpawnAppearance(const EQApplicationPacket *app)
entity_list.QueueClients(this, app, true); entity_list.QueueClients(this, app, true);
} }
else if (sa->type == AT_Anon) { else if (sa->type == AT_Anon) {
if(!anon_toggle_timer.Check()) {
return;
}
// For Anon/Roleplay // For Anon/Roleplay
if (sa->parameter == 1) { // Anon if (sa->parameter == 1) { // Anon
m_pp.anon = 1; m_pp.anon = 1;
@ -12711,13 +12710,18 @@ void Client::Handle_OP_SpawnAppearance(const EQApplicationPacket *app)
return; return;
} }
else if (sa->type == AT_AFK) { else if (sa->type == AT_AFK) {
this->AFK = (sa->parameter == 1); if(afk_toggle_timer.Check()) {
entity_list.QueueClients(this, app, true); AFK = (sa->parameter == 1);
entity_list.QueueClients(this, app, true);
}
} }
else if (sa->type == AT_Split) { else if (sa->type == AT_Split) {
m_pp.autosplit = (sa->parameter == 1); m_pp.autosplit = (sa->parameter == 1);
} }
else if (sa->type == AT_Sneak) { else if (sa->type == AT_Sneak) {
if(sneaking == 0)
return;
if (sa->parameter != 0) if (sa->parameter != 0)
{ {
if (!HasSkill(SkillSneak)) if (!HasSkill(SkillSneak))
@ -12729,7 +12733,7 @@ void Client::Handle_OP_SpawnAppearance(const EQApplicationPacket *app)
} }
return; return;
} }
this->sneaking = 0; sneaking = 0;
entity_list.QueueClients(this, app, true); entity_list.QueueClients(this, app, true);
} }
else if (sa->type == AT_Size) else if (sa->type == AT_Size)
@ -12741,7 +12745,7 @@ void Client::Handle_OP_SpawnAppearance(const EQApplicationPacket *app)
} }
else if (sa->type == AT_Light) // client emitting light (lightstone, shiny shield) else if (sa->type == AT_Light) // client emitting light (lightstone, shiny shield)
{ {
entity_list.QueueClients(this, app, false); //don't do anything with this
} }
else if (sa->type == AT_Levitate) else if (sa->type == AT_Levitate)
{ {
@ -12750,8 +12754,10 @@ void Client::Handle_OP_SpawnAppearance(const EQApplicationPacket *app)
} }
else if (sa->type == AT_ShowHelm) else if (sa->type == AT_ShowHelm)
{ {
m_pp.showhelm = (sa->parameter == 1); if(helm_toggle_timer.Check()) {
entity_list.QueueClients(this, app, true); m_pp.showhelm = (sa->parameter == 1);
entity_list.QueueClients(this, app, true);
}
} }
else { else {
std::cout << "Unknown SpawnAppearance type: 0x" << std::hex << std::setw(4) << std::setfill('0') << sa->type << std::dec std::cout << "Unknown SpawnAppearance type: 0x" << std::hex << std::setw(4) << std::setfill('0') << sa->type << std::dec

View File

@ -260,6 +260,13 @@ bool Client::Process() {
} }
} }
if(light_update_timer.Check()) {
UpdateEquipLightValue();
if(UpdateActiveLightValue()) {
SendAppearancePacket(AT_Light, GetActiveLightValue());
}
}
bool may_use_attacks = false; bool may_use_attacks = false;
/* /*
Things which prevent us from attacking: Things which prevent us from attacking:

View File

@ -2618,7 +2618,7 @@ void command_peekinv(Client *c, const Seperator *sep)
} }
else { else {
int cursorDepth = 0; int cursorDepth = 0;
for (auto it = targetClient->GetInv().cursor_begin(); (it != targetClient->GetInv().cursor_end()); ++it, ++cursorDepth) { for (auto it = targetClient->GetInv().cursor_cbegin(); (it != targetClient->GetInv().cursor_cend()); ++it, ++cursorDepth) {
inst_main = *it; inst_main = *it;
item_data = (inst_main == nullptr) ? nullptr : inst_main->GetItem(); item_data = (inst_main == nullptr) ? nullptr : inst_main->GetItem();
linker.SetItemInst(inst_main); linker.SetItemInst(inst_main);
@ -4284,31 +4284,49 @@ void command_goto(Client *c, const Seperator *sep)
void command_iteminfo(Client *c, const Seperator *sep) void command_iteminfo(Client *c, const Seperator *sep)
{ {
const ItemInst* inst = c->GetInv()[MainCursor]; auto inst = c->GetInv()[MainCursor];
if (!inst) { c->Message(13, "Error: You need an item on your cursor for this command"); }
if (!inst) auto item = inst->GetItem();
c->Message(13, "Error: You need an item on your cursor for this command"); if (!item) {
else { Log.Out(Logs::General, Logs::Inventory, "(%s) Command #iteminfo processed an item with no data pointer");
const Item_Struct* item = inst->GetItem(); c->Message(13, "Error: This item has no data reference");
c->Message(0, "ID: %i Name: %s", item->ID, item->Name);
c->Message(0, " Lore: %s ND: %i NS: %i Type: %i", (item->LoreFlag) ? "true":"false", item->NoDrop, item->NoRent, item->ItemClass);
c->Message(0, " IDF: %s Size: %i Weight: %i icon_id: %i Price: %i", item->IDFile, item->Size, item->Weight, item->Icon, item->Price);
if (c->Admin() >= 200)
c->Message(0, "MinStatus: %i", item->MinStatus);
if (item->ItemClass==ItemClassBook)
c->Message(0, " This item is a Book: %s", item->Filename);
else if (item->ItemClass==ItemClassContainer)
c->Message(0, " This item is a container with %i slots", item->BagSlots);
else {
c->Message(0, " equipableSlots: %u equipable Classes: %u", item->Slots, item->Classes);
c->Message(0, " Magic: %i SpellID: %i Proc Level: %i DBCharges: %i CurCharges: %i", item->Magic, item->Click.Effect, item->Click.Level, item->MaxCharges, inst->GetCharges());
c->Message(0, " EffectType: 0x%02x CastTime: %.2f", (uint8) item->Click.Type, (double) item->CastTime/1000);
c->Message(0, " Material: 0x%02x Color: 0x%08x Skill: %i", item->Material, item->Color, item->ItemType);
c->Message(0, " Required level: %i Required skill: %i Recommended level:%i", item->ReqLevel, item->RecSkill, item->RecLevel);
c->Message(0, " Skill mod: %i percent: %i", item->SkillModType, item->SkillModValue);
c->Message(0, " BaneRace: %i BaneBody: %i BaneDMG: %i", item->BaneDmgRace, item->BaneDmgBody, item->BaneDmgAmt);
}
} }
Client::TextLink linker;
linker.SetLinkType(linker.linkItemInst);
linker.SetItemInst(inst);
auto item_link = linker.GenerateLink();
c->Message(0, "*** Item Info for [%s] ***", item_link.c_str());
c->Message(0, ">> ID: %u, ItemUseType: %u, ItemClassType: %u", item->ID, item->ItemType, item->ItemClass);
c->Message(0, ">> IDFile: '%s', IconID: %u", item->IDFile, item->Icon);
c->Message(0, ">> Size: %u, Weight: %u, Price: %u, LDoNPrice: %u", item->Size, item->Weight, item->Price, item->LDoNPrice);
c->Message(0, ">> Material: 0x%02X, Color: 0x%08X, Tint: 0x%08X, Light: 0x%02X", item->Material, item->Color, inst->GetColor(), item->Light);
c->Message(0, ">> IsLore: %s, LoreGroup: %u, Lore: '%s'", (item->LoreFlag ? "TRUE" : "FALSE"), item->LoreGroup, item->Lore);
c->Message(0, ">> NoDrop: %u, NoRent: %u, NoPet: %u, NoTransfer: %u, FVNoDrop: %u",
item->NoDrop, item->NoRent, (uint8)item->NoPet, (uint8)item->NoTransfer, item->FVNoDrop);
if (item->ItemClass == ItemClassBook) {
c->Message(0, "*** This item is a Book (filename:'%s') ***", item->Filename);
}
else if (item->ItemClass == ItemClassContainer) {
c->Message(0, "*** This item is a Container (%u slots) ***", item->BagSlots);
}
else {
c->Message(0, "*** This item is Common ***");
c->Message(0, ">> Classes: %u, Races: %u, Slots: %u", item->Classes, item->Races, item->Slots);
c->Message(0, ">> ReqSkill: %u, ReqLevel: %u, RecLevel: %u", item->RecSkill, item->ReqLevel, item->RecLevel);
c->Message(0, ">> SkillModType: %u, SkillModValue: %i", item->SkillModType, item->SkillModValue);
c->Message(0, ">> BaneRaceType: %u, BaneRaceDamage: %u, BaneBodyType: %u, BaneBodyDamage: %i",
item->BaneDmgRace, item->BaneDmgRaceAmt, item->BaneDmgBody, item->BaneDmgAmt);
c->Message(0, ">> Magic: %s, SpellID: %i, ProcLevel: %u, Charges: %u, MaxCharges: %u",
(item->Magic ? "TRUE" : "FALSE"), item->Click.Effect, item->Click.Level, inst->GetCharges(), item->MaxCharges);
c->Message(0, ">> EffectType: 0x%02X, CastTime: %.2f", (uint8)item->Click.Type, ((double)item->CastTime / 1000));
}
if (c->Admin() >= 200)
c->Message(0, ">> MinStatus: %u", item->MinStatus);
} }
void command_uptime(Client *c, const Seperator *sep) void command_uptime(Client *c, const Seperator *sep)

View File

@ -361,8 +361,8 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob (
database.QueryDatabase(ss.str().c_str()); database.QueryDatabase(ss.str().c_str());
} }
auto start = client->GetInv().cursor_begin(); auto start = client->GetInv().cursor_cbegin();
auto finish = client->GetInv().cursor_end(); auto finish = client->GetInv().cursor_cend();
database.SaveCursor(client->CharacterID(), start, finish); database.SaveCursor(client->CharacterID(), start, finish);
client->CalcBonuses(); client->CalcBonuses();

View File

@ -73,7 +73,7 @@ public:
void SplitMoney(uint32 copper, uint32 silver, uint32 gold, uint32 platinum, Client *splitter = nullptr); void SplitMoney(uint32 copper, uint32 silver, uint32 gold, uint32 platinum, Client *splitter = nullptr);
inline void SetLeader(Mob* newleader){ leader=newleader; }; inline void SetLeader(Mob* newleader){ leader=newleader; };
inline Mob* GetLeader() { return leader; }; inline Mob* GetLeader() { return leader; };
const char* GetLeaderName() { return leader->GetName(); }; const char* GetLeaderName() { return membername[0]; };
void SendHPPacketsTo(Mob* newmember); void SendHPPacketsTo(Mob* newmember);
void SendHPPacketsFrom(Mob* newmember); void SendHPPacketsFrom(Mob* newmember);
bool UpdatePlayer(Mob* update); bool UpdatePlayer(Mob* update);

View File

@ -177,16 +177,16 @@ uint32 Client::NukeItem(uint32 itemnum, uint8 where_to_check) {
} }
bool Client::CheckLoreConflict(const Item_Struct* item) { bool Client::CheckLoreConflict(const Item_Struct* item)
if (!item) {
return false; if (!item) { return false; }
if (!(item->LoreFlag)) if (!item->LoreFlag) { return false; }
return false; if (item->LoreGroup == 0) { return false; }
if (item->LoreGroup == -1) // Standard lore items; look everywhere except the shared bank, return the result if (item->LoreGroup == 0xFFFFFFFF) // Standard lore items; look everywhere except the shared bank, return the result
return (m_inv.HasItem(item->ID, 0, ~invWhereSharedBank) != INVALID_INDEX); return (m_inv.HasItem(item->ID, 0, ~invWhereSharedBank) != INVALID_INDEX);
//If the item has a lore group, we check for other items with the same group and return the result // If the item has a lore group, we check for other items with the same group and return the result
return (m_inv.HasItemByLoreGroup(item->LoreGroup, ~invWhereSharedBank) != INVALID_INDEX); return (m_inv.HasItemByLoreGroup(item->LoreGroup, ~invWhereSharedBank) != INVALID_INDEX);
} }
@ -619,7 +619,7 @@ void Client::DropItem(int16 slot_id)
// Save client inventory change to database // Save client inventory change to database
if (slot_id == MainCursor) { if (slot_id == MainCursor) {
SendCursorBuffer(); SendCursorBuffer();
auto s = m_inv.cursor_begin(), e = m_inv.cursor_end(); auto s = m_inv.cursor_cbegin(), e = m_inv.cursor_cend();
database.SaveCursor(CharacterID(), s, e); database.SaveCursor(CharacterID(), s, e);
} else { } else {
database.SaveInventory(CharacterID(), nullptr, slot_id); database.SaveInventory(CharacterID(), nullptr, slot_id);
@ -680,20 +680,37 @@ int32 Client::GetAugmentIDAt(int16 slot_id, uint8 augslot) {
return INVALID_ID; return INVALID_ID;
} }
void Client::SendCursorBuffer() { void Client::SendCursorBuffer()
{
// Temporary work-around for the RoF+ Client Buffer // Temporary work-around for the RoF+ Client Buffer
// Instead of dealing with client moving items in cursor buffer, // Instead of dealing with client moving items in cursor buffer,
// we can just send the next item in the cursor buffer to the cursor. // we can just send the next item in the cursor buffer to the cursor.
if (GetClientVersion() >= ClientVersion::RoF) if (GetClientVersion() < ClientVersion::RoF) { return; }
{ if (GetInv().CursorEmpty()) { return; }
if (!GetInv().CursorEmpty())
{ auto test_inst = GetInv().GetCursorItem();
const ItemInst* inst = GetInv().GetCursorItem(); if (test_inst == nullptr) { return; }
if (inst) auto test_item = test_inst->GetItem();
{ if (test_item == nullptr) { return; }
SendItemPacket(MainCursor, inst, ItemPacketSummonItem);
} bool lore_pass = true;
} if (test_item->LoreGroup == 0xFFFFFFFF) {
lore_pass = (m_inv.HasItem(test_item->ID, 0, ~(invWhereSharedBank | invWhereCursor)) == INVALID_INDEX);
}
else if (test_item->LoreGroup != 0) {
lore_pass = (m_inv.HasItemByLoreGroup(test_item->LoreGroup, ~(invWhereSharedBank | invWhereCursor)) == INVALID_INDEX);
}
if (!lore_pass) {
Log.Out(Logs::General, Logs::Inventory, "(%s) Duplicate lore items are not allowed - destroying item %s(id:%u) on cursor",
GetName(), test_item->Name, test_item->ID);
Message_StringID(MT_LootMessages, 290);
parse->EventItem(EVENT_DESTROY_ITEM, this, test_inst, nullptr, "", 0);
DeleteItemInInventory(MainCursor);
SendCursorBuffer();
}
else {
SendItemPacket(MainCursor, test_inst, ItemPacketSummonItem);
} }
} }
@ -772,7 +789,7 @@ void Client::DeleteItemInInventory(int16 slot_id, int8 quantity, bool client_upd
const ItemInst* inst = nullptr; const ItemInst* inst = nullptr;
if (slot_id == MainCursor) { if (slot_id == MainCursor) {
auto s = m_inv.cursor_begin(), e = m_inv.cursor_end(); auto s = m_inv.cursor_cbegin(), e = m_inv.cursor_cend();
if(update_db) if(update_db)
database.SaveCursor(character_id, s, e); database.SaveCursor(character_id, s, e);
} }
@ -826,7 +843,7 @@ bool Client::PushItemOnCursor(const ItemInst& inst, bool client_update)
SendItemPacket(MainCursor, &inst, ItemPacketSummonItem); SendItemPacket(MainCursor, &inst, ItemPacketSummonItem);
} }
auto s = m_inv.cursor_begin(), e = m_inv.cursor_end(); auto s = m_inv.cursor_cbegin(), e = m_inv.cursor_cend();
return database.SaveCursor(CharacterID(), s, e); return database.SaveCursor(CharacterID(), s, e);
} }
@ -851,7 +868,7 @@ bool Client::PutItemInInventory(int16 slot_id, const ItemInst& inst, bool client
} }
if (slot_id == MainCursor) { if (slot_id == MainCursor) {
auto s = m_inv.cursor_begin(), e = m_inv.cursor_end(); auto s = m_inv.cursor_cbegin(), e = m_inv.cursor_cend();
return database.SaveCursor(this->CharacterID(), s, e); return database.SaveCursor(this->CharacterID(), s, e);
} }
else { else {
@ -870,7 +887,7 @@ void Client::PutLootInInventory(int16 slot_id, const ItemInst &inst, ServerLootI
SendLootItemInPacket(&inst, slot_id); SendLootItemInPacket(&inst, slot_id);
if (slot_id == MainCursor) { if (slot_id == MainCursor) {
auto s = m_inv.cursor_begin(), e = m_inv.cursor_end(); auto s = m_inv.cursor_cbegin(), e = m_inv.cursor_cend();
database.SaveCursor(this->CharacterID(), s, e); database.SaveCursor(this->CharacterID(), s, e);
} }
else { else {
@ -1009,7 +1026,7 @@ void Client::MoveItemCharges(ItemInst &from, int16 to_slot, uint8 type)
from.SetCharges(from.GetCharges() - charges_to_move); from.SetCharges(from.GetCharges() - charges_to_move);
SendLootItemInPacket(tmp_inst, to_slot); SendLootItemInPacket(tmp_inst, to_slot);
if (to_slot == MainCursor) { if (to_slot == MainCursor) {
auto s = m_inv.cursor_begin(), e = m_inv.cursor_end(); auto s = m_inv.cursor_cbegin(), e = m_inv.cursor_cend();
database.SaveCursor(this->CharacterID(), s, e); database.SaveCursor(this->CharacterID(), s, e);
} }
else { else {
@ -1320,10 +1337,33 @@ bool Client::SwapItem(MoveItem_Struct* move_in) {
return false; return false;
} }
// This could be expounded upon at some point to let the server know that
// the client has moved a buffered cursor item onto the active cursor -U
if (move_in->from_slot == move_in->to_slot) { // Item summon, no further processing needed if (move_in->from_slot == move_in->to_slot) { // Item summon, no further processing needed
if(RuleB(QueryServ, PlayerLogMoves)) { QSSwapItemAuditor(move_in); } // QS Audit if(RuleB(QueryServ, PlayerLogMoves)) { QSSwapItemAuditor(move_in); } // QS Audit
if (GetClientVersion() >= ClientVersion::RoF) { return true; } // Can't do RoF+
if (move_in->to_slot == MainCursor) {
auto test_inst = m_inv.GetItem(MainCursor);
if (test_inst == nullptr) { return true; }
auto test_item = test_inst->GetItem();
if (test_item == nullptr) { return true; }
if (!test_item->LoreFlag) { return true; }
bool lore_pass = true;
if (test_item->LoreGroup == 0xFFFFFFFF) {
lore_pass = (m_inv.HasItem(test_item->ID, 0, ~(invWhereSharedBank | invWhereCursor)) == INVALID_INDEX);
}
else if (test_item->LoreGroup != 0) {
lore_pass = (m_inv.HasItemByLoreGroup(test_item->LoreGroup, ~(invWhereSharedBank | invWhereCursor)) == INVALID_INDEX);
}
if (!lore_pass) {
Log.Out(Logs::General, Logs::Inventory, "(%s) Duplicate lore items are not allowed - destroying item %s(id:%u) on cursor",
GetName(), test_item->Name, test_item->ID);
Message_StringID(MT_LootMessages, 290);
parse->EventItem(EVENT_DESTROY_ITEM, this, test_inst, nullptr, "", 0);
DeleteItemInInventory(MainCursor, 0, true);
}
}
return true; return true;
} }
@ -1567,7 +1607,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) {
{ {
SendCursorBuffer(); SendCursorBuffer();
} }
auto s = m_inv.cursor_begin(), e = m_inv.cursor_end(); auto s = m_inv.cursor_cbegin(), e = m_inv.cursor_cend();
database.SaveCursor(character_id, s, e); database.SaveCursor(character_id, s, e);
} }
else else
@ -1726,7 +1766,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) {
{ {
SendCursorBuffer(); SendCursorBuffer();
} }
auto s = m_inv.cursor_begin(), e = m_inv.cursor_end(); auto s = m_inv.cursor_cbegin(), e = m_inv.cursor_cend();
database.SaveCursor(character_id, s, e); database.SaveCursor(character_id, s, e);
} }
else { else {
@ -1734,7 +1774,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) {
} }
if (dst_slot_id == MainCursor) { if (dst_slot_id == MainCursor) {
auto s = m_inv.cursor_begin(), e = m_inv.cursor_end(); auto s = m_inv.cursor_cbegin(), e = m_inv.cursor_cend();
database.SaveCursor(character_id, s, e); database.SaveCursor(character_id, s, e);
} }
else { else {
@ -2170,7 +2210,7 @@ void Client::RemoveNoRent(bool client_update)
} }
local.clear(); local.clear();
auto s = m_inv.cursor_begin(), e = m_inv.cursor_end(); auto s = m_inv.cursor_cbegin(), e = m_inv.cursor_cend();
database.SaveCursor(this->CharacterID(), s, e); database.SaveCursor(this->CharacterID(), s, e);
} }
} }
@ -2298,7 +2338,7 @@ void Client::RemoveDuplicateLore(bool client_update)
} }
local_2.clear(); local_2.clear();
auto s = m_inv.cursor_begin(), e = m_inv.cursor_end(); auto s = m_inv.cursor_cbegin(), e = m_inv.cursor_cend();
database.SaveCursor(this->CharacterID(), s, e); database.SaveCursor(this->CharacterID(), s, e);
} }
} }
@ -2826,9 +2866,9 @@ bool Client::InterrogateInventory(Client* requester, bool log, bool silent, bool
} }
int limbo = 0; int limbo = 0;
for (auto cursor_itr = m_inv.cursor_begin(); cursor_itr != m_inv.cursor_end(); ++cursor_itr, ++limbo) { for (auto cursor_itr = m_inv.cursor_cbegin(); cursor_itr != m_inv.cursor_cend(); ++cursor_itr, ++limbo) {
// m_inv.cursor_begin() is referenced as MainCursor in MapPossessions above // m_inv.cursor_begin() is referenced as MainCursor in MapPossessions above
if (cursor_itr == m_inv.cursor_begin()) if (cursor_itr == m_inv.cursor_cbegin())
continue; continue;
instmap[8000 + limbo] = *cursor_itr; instmap[8000 + limbo] = *cursor_itr;

View File

@ -1479,8 +1479,6 @@ static void BazaarAuditTrail(const char *seller, const char *buyer, const char *
database.QueryDatabase(query); database.QueryDatabase(query);
} }
void Client::BuyTraderItem(TraderBuy_Struct* tbs,Client* Trader,const EQApplicationPacket* app){ void Client::BuyTraderItem(TraderBuy_Struct* tbs,Client* Trader,const EQApplicationPacket* app){
if(!Trader) return; if(!Trader) return;
@ -1509,15 +1507,15 @@ void Client::BuyTraderItem(TraderBuy_Struct* tbs,Client* Trader,const EQApplicat
BuyItem->GetItem()->Name, BuyItem->IsStackable(), tbs->Quantity, BuyItem->GetCharges()); BuyItem->GetItem()->Name, BuyItem->IsStackable(), tbs->Quantity, BuyItem->GetCharges());
// If the item is not stackable, then we can only be buying one of them. // If the item is not stackable, then we can only be buying one of them.
if(!BuyItem->IsStackable()) if(!BuyItem->IsStackable())
outtbs->Quantity = tbs->Quantity; outtbs->Quantity = 1; // normally you can't send more than 1 here
else { else {
// Stackable items, arrows, diamonds, etc // Stackable items, arrows, diamonds, etc
int ItemCharges = BuyItem->GetCharges(); int32 ItemCharges = BuyItem->GetCharges();
// ItemCharges for stackables should not be <= 0 // ItemCharges for stackables should not be <= 0
if(ItemCharges <= 0) if(ItemCharges <= 0)
outtbs->Quantity = 1; outtbs->Quantity = 1;
// If the purchaser requested more than is in the stack, just sell them how many are actually in the stack. // If the purchaser requested more than is in the stack, just sell them how many are actually in the stack.
else if(ItemCharges < (int16)tbs->Quantity) else if(static_cast<uint32>(ItemCharges) < tbs->Quantity)
outtbs->Quantity = ItemCharges; outtbs->Quantity = ItemCharges;
else else
outtbs->Quantity = tbs->Quantity; outtbs->Quantity = tbs->Quantity;
@ -1609,7 +1607,6 @@ void Client::BuyTraderItem(TraderBuy_Struct* tbs,Client* Trader,const EQApplicat
safe_delete(outapp); safe_delete(outapp);
safe_delete(outapp2); safe_delete(outapp2);
} }
void Client::SendBazaarWelcome() void Client::SendBazaarWelcome()

View File

@ -195,11 +195,9 @@ void ZoneDatabase::UpdateSpawn2Timeleft(uint32 id, uint16 instance_id, uint32 ti
//if we pass timeleft as 0 that means we clear from respawn time //if we pass timeleft as 0 that means we clear from respawn time
//otherwise we update with a REPLACE INTO //otherwise we update with a REPLACE INTO
if(timeleft == 0) { if(timeleft == 0) {
std::string query = StringFormat("DELETE FROM respawn_times WHERE id=%lu " std::string query = StringFormat("DELETE FROM respawn_times WHERE id=%lu AND instance_id = %lu",(unsigned long)id, (unsigned long)instance_id);
"AND instance_id = %lu",(unsigned long)id, (unsigned long)instance_id);
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
if (!results.Success())
return; return;
} }