mirror of
https://github.com/EQEmu/Server.git
synced 2026-03-15 15:12:25 +00:00
Merge git://github.com/EQEmu/Server into Development
This commit is contained in:
commit
9aac1b0081
@ -1,5 +1,14 @@
|
||||
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 ==
|
||||
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
|
||||
|
||||
@ -506,6 +506,7 @@ int16 Inventory::HasItem(uint32 item_id, uint8 quantity, uint8 where)
|
||||
return slot_id;
|
||||
}
|
||||
|
||||
// Behavioral change - Limbo is no longer checked due to improper handling of return value
|
||||
if (where & invWhereCursor) {
|
||||
// Check cursor queue
|
||||
slot_id = _HasItem(m_cursor, item_id, quantity);
|
||||
@ -552,6 +553,7 @@ int16 Inventory::HasItemByUse(uint8 use, uint8 quantity, uint8 where)
|
||||
return slot_id;
|
||||
}
|
||||
|
||||
// Behavioral change - Limbo is no longer checked due to improper handling of return value
|
||||
if (where & invWhereCursor) {
|
||||
// Check cursor queue
|
||||
slot_id = _HasItemByUse(m_cursor, use, quantity);
|
||||
@ -597,6 +599,7 @@ int16 Inventory::HasItemByLoreGroup(uint32 loregroup, uint8 where)
|
||||
return slot_id;
|
||||
}
|
||||
|
||||
// Behavioral change - Limbo is no longer checked due to improper handling of return value
|
||||
if (where & invWhereCursor) {
|
||||
// Check cursor queue
|
||||
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)) {
|
||||
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) {
|
||||
return Inventory::CalcSlotId(iter->first, b_iter->first);
|
||||
}
|
||||
@ -1071,13 +1074,10 @@ int Inventory::GetSlotByItemInstCollection(const std::map<int16, ItemInst*> &col
|
||||
return -1;
|
||||
}
|
||||
|
||||
void Inventory::dumpItemCollection(const std::map<int16, ItemInst*> &collection) {
|
||||
iter_inst it;
|
||||
iter_contents itb;
|
||||
ItemInst* inst = nullptr;
|
||||
|
||||
for (it = collection.begin(); it != collection.end(); ++it) {
|
||||
inst = it->second;
|
||||
void Inventory::dumpItemCollection(const std::map<int16, ItemInst*> &collection)
|
||||
{
|
||||
for (auto it = collection.cbegin(); it != collection.cend(); ++it) {
|
||||
auto inst = it->second;
|
||||
if (!inst || !inst->GetItem())
|
||||
continue;
|
||||
|
||||
@ -1088,14 +1088,13 @@ void Inventory::dumpItemCollection(const std::map<int16, ItemInst*> &collection)
|
||||
}
|
||||
}
|
||||
|
||||
void Inventory::dumpBagContents(ItemInst *inst, iter_inst *it) {
|
||||
iter_contents itb;
|
||||
|
||||
void Inventory::dumpBagContents(ItemInst *inst, std::map<int16, ItemInst*>::const_iterator *it)
|
||||
{
|
||||
if (!inst || !inst->IsType(ItemClassContainer))
|
||||
return;
|
||||
|
||||
// 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;
|
||||
if (!baginst || !baginst->GetItem())
|
||||
continue;
|
||||
@ -1110,7 +1109,7 @@ void Inventory::dumpBagContents(ItemInst *inst, iter_inst *it) {
|
||||
// Internal Method: Retrieves item within an inventory bucket
|
||||
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()) {
|
||||
return it->second;
|
||||
}
|
||||
@ -1123,6 +1122,8 @@ ItemInst* Inventory::_GetItem(const std::map<int16, ItemInst*>& bucket, int16 sl
|
||||
// Assumes item has already been allocated
|
||||
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 (inst == nullptr) {
|
||||
//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; }
|
||||
|
||||
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;
|
||||
if (bag_inst == nullptr) { continue; }
|
||||
|
||||
@ -1235,7 +1236,7 @@ int16 Inventory::_HasItem(ItemInstQueue& iqueue, uint32 item_id, uint8 quantity)
|
||||
|
||||
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;
|
||||
if (inst == nullptr) { continue; }
|
||||
|
||||
@ -1252,7 +1253,7 @@ int16 Inventory::_HasItem(ItemInstQueue& iqueue, uint32 item_id, uint8 quantity)
|
||||
|
||||
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;
|
||||
if (bag_inst == nullptr) { continue; }
|
||||
|
||||
@ -1267,6 +1268,9 @@ int16 Inventory::_HasItem(ItemInstQueue& iqueue, uint32 item_id, uint8 quantity)
|
||||
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;
|
||||
@ -1289,7 +1293,7 @@ int16 Inventory::_HasItemByUse(std::map<int16, ItemInst*>& bucket, uint8 use, ui
|
||||
|
||||
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;
|
||||
if (bag_inst == nullptr) { continue; }
|
||||
|
||||
@ -1309,7 +1313,7 @@ int16 Inventory::_HasItemByUse(ItemInstQueue& iqueue, uint8 use, uint8 quantity)
|
||||
{
|
||||
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;
|
||||
if (inst == nullptr) { continue; }
|
||||
|
||||
@ -1321,7 +1325,7 @@ int16 Inventory::_HasItemByUse(ItemInstQueue& iqueue, uint8 use, uint8 quantity)
|
||||
|
||||
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;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
// We only check the visible cursor due to lack of queue processing ability (client allows duplicate in limbo)
|
||||
break;
|
||||
}
|
||||
|
||||
return INVALID_INDEX;
|
||||
@ -1355,7 +1362,7 @@ int16 Inventory::_HasItemByLoreGroup(std::map<int16, ItemInst*>& bucket, uint32
|
||||
|
||||
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;
|
||||
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
|
||||
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;
|
||||
if (inst == nullptr) { continue; }
|
||||
|
||||
@ -1395,7 +1402,7 @@ int16 Inventory::_HasItemByLoreGroup(ItemInstQueue& iqueue, uint32 loregroup)
|
||||
|
||||
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;
|
||||
if (bag_inst == nullptr) { continue; }
|
||||
|
||||
@ -1410,6 +1417,9 @@ int16 Inventory::_HasItemByLoreGroup(ItemInstQueue& iqueue, uint32 loregroup)
|
||||
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;
|
||||
@ -1505,8 +1515,7 @@ ItemInst::ItemInst(const ItemInst& copy)
|
||||
m_attuned=copy.m_attuned;
|
||||
m_merchantcount=copy.m_merchantcount;
|
||||
// Copy container contents
|
||||
iter_contents it;
|
||||
for (it=copy.m_contents.begin(); it!=copy.m_contents.end(); ++it) {
|
||||
for (auto it = copy.m_contents.begin(); it != copy.m_contents.end(); ++it) {
|
||||
ItemInst* inst_old = it->second;
|
||||
ItemInst* inst_new = nullptr;
|
||||
|
||||
@ -1676,7 +1685,7 @@ bool ItemInst::IsAugmentSlotAvailable(int32 augtype, uint8 slot) const
|
||||
// Retrieve item inside container
|
||||
ItemInst* ItemInst::GetItem(uint8 index) const
|
||||
{
|
||||
iter_contents it = m_contents.find(index);
|
||||
auto it = m_contents.find(index);
|
||||
if (it != m_contents.end()) {
|
||||
return it->second;
|
||||
}
|
||||
@ -1739,7 +1748,7 @@ void ItemInst::ClearByFlags(byFlagSetting is_nodrop, byFlagSetting is_norent)
|
||||
// TODO: This needs work...
|
||||
|
||||
// Destroy container contents
|
||||
iter_contents cur, end, del;
|
||||
std::map<uint8, ItemInst*>::const_iterator cur, end, del;
|
||||
cur = m_contents.begin();
|
||||
end = m_contents.end();
|
||||
for (; cur != end;) {
|
||||
|
||||
@ -33,9 +33,6 @@ class EvolveInfo; // Stores information about an evolving item family
|
||||
#include <list>
|
||||
#include <map>
|
||||
|
||||
// Helper typedefs
|
||||
typedef std::map<int16, ItemInst*>::const_iterator iter_inst;
|
||||
typedef std::map<uint8, ItemInst*>::const_iterator iter_contents;
|
||||
|
||||
namespace ItemField
|
||||
{
|
||||
@ -86,8 +83,8 @@ public:
|
||||
// Public Methods
|
||||
/////////////////////////
|
||||
|
||||
inline std::list<ItemInst*>::const_iterator begin() { return m_list.begin(); }
|
||||
inline std::list<ItemInst*>::const_iterator end() { return m_list.end(); }
|
||||
inline std::list<ItemInst*>::const_iterator cbegin() { return m_list.cbegin(); }
|
||||
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 bool empty() { return m_list.empty(); }
|
||||
@ -140,8 +137,8 @@ public:
|
||||
ItemInst* GetItem(int16 slot_id) 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_end() { return m_cursor.end(); }
|
||||
inline std::list<ItemInst*>::const_iterator cursor_cbegin() { return m_cursor.cbegin(); }
|
||||
inline std::list<ItemInst*>::const_iterator cursor_cend() { return m_cursor.cend(); }
|
||||
|
||||
inline int CursorSize() { return m_cursor.size(); }
|
||||
inline bool CursorEmpty() { return m_cursor.empty(); }
|
||||
@ -227,7 +224,7 @@ protected:
|
||||
|
||||
int GetSlotByItemInstCollection(const std::map<int16, ItemInst*> &collection, ItemInst *inst);
|
||||
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
|
||||
ItemInst* _GetItem(const std::map<int16, ItemInst*>& bucket, int16 slot_id) const;
|
||||
@ -425,8 +422,8 @@ protected:
|
||||
//////////////////////////
|
||||
// Protected Members
|
||||
//////////////////////////
|
||||
iter_contents _begin() { return m_contents.begin(); }
|
||||
iter_contents _end() { return m_contents.end(); }
|
||||
std::map<uint8, ItemInst*>::const_iterator _cbegin() { return m_contents.cbegin(); }
|
||||
std::map<uint8, ItemInst*>::const_iterator _cend() { return m_contents.cend(); }
|
||||
|
||||
friend class Inventory;
|
||||
|
||||
|
||||
@ -2865,7 +2865,7 @@ struct SetRunMode_Struct {
|
||||
};
|
||||
|
||||
// EnvDamage is EnvDamage2 without a few bytes at the end.
|
||||
// Size: 37 bytes
|
||||
// Size: 39 bytes
|
||||
struct EnvDamage2_Struct {
|
||||
/*0000*/ uint32 id;
|
||||
/*0004*/ uint16 unknown4;
|
||||
@ -2877,7 +2877,8 @@ struct EnvDamage2_Struct {
|
||||
/*0031*/ uint16 unknown31; // New to Underfoot - Seen 66
|
||||
/*0033*/ uint16 constant; // Always FFFF
|
||||
/*0035*/ uint16 unknown35;
|
||||
/*0037*/
|
||||
/*0037*/ uint16 unknown37;
|
||||
/*0039*/
|
||||
};
|
||||
|
||||
//Bazaar Stuff
|
||||
|
||||
@ -141,6 +141,11 @@ Client::Client(EQStreamInterface* ieqs)
|
||||
merc_timer(RuleI(Mercs, UpkeepIntervalMS)),
|
||||
ItemTickTimer(10000),
|
||||
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_ZoneSummonLocation(-2.0f,-2.0f,-2.0f),
|
||||
m_AutoAttackPosition(0.0f, 0.0f, 0.0f, 0.0f),
|
||||
|
||||
@ -1465,6 +1465,11 @@ private:
|
||||
Timer TrackingTimer;
|
||||
Timer RespawnFromHoverTimer;
|
||||
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;
|
||||
|
||||
|
||||
@ -1838,9 +1838,9 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
||||
if (loaditems) { /* Dont load if a length error occurs */
|
||||
BulkSendInventoryItems();
|
||||
/* 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 */
|
||||
if (iter == m_inv.cursor_begin())
|
||||
if (iter == m_inv.cursor_cbegin())
|
||||
continue;
|
||||
const ItemInst *inst = *iter;
|
||||
SendItemPacket(MainCursor, inst, ItemPacketSummonItem);
|
||||
@ -5516,7 +5516,7 @@ void Client::Handle_OP_EnvDamage(const EQApplicationPacket *app)
|
||||
if (damage < 0)
|
||||
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);
|
||||
SetHP(GetHP() - 1);//needed or else the client wont acknowledge
|
||||
return;
|
||||
@ -5526,11 +5526,11 @@ void Client::Handle_OP_EnvDamage(const EQApplicationPacket *app)
|
||||
SetHP(GetHP() - 1);//needed or else the client wont acknowledge
|
||||
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;
|
||||
}
|
||||
else{
|
||||
else {
|
||||
SetHP(GetHP() - (damage * RuleR(Character, EnvironmentDamageMulipliter)));
|
||||
|
||||
/* EVENT_ENVIRONMENTAL_DAMAGE */
|
||||
@ -12640,6 +12640,10 @@ void Client::Handle_OP_SpawnAppearance(const EQApplicationPacket *app)
|
||||
else if (sa->type == AT_Anim) {
|
||||
if (IsAIControlled())
|
||||
return;
|
||||
|
||||
if(!anim_change_timer.Check())
|
||||
return;
|
||||
|
||||
if (sa->parameter == ANIM_STAND) {
|
||||
SetAppearance(eaStanding);
|
||||
playeraction = 0;
|
||||
@ -12673,15 +12677,6 @@ void Client::Handle_OP_SpawnAppearance(const EQApplicationPacket *app)
|
||||
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 {
|
||||
std::cerr << "Client " << name << " unknown apperance " << (int)sa->parameter << std::endl;
|
||||
return;
|
||||
@ -12690,6 +12685,10 @@ void Client::Handle_OP_SpawnAppearance(const EQApplicationPacket *app)
|
||||
entity_list.QueueClients(this, app, true);
|
||||
}
|
||||
else if (sa->type == AT_Anon) {
|
||||
if(!anon_toggle_timer.Check()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// For Anon/Roleplay
|
||||
if (sa->parameter == 1) { // Anon
|
||||
m_pp.anon = 1;
|
||||
@ -12711,13 +12710,18 @@ void Client::Handle_OP_SpawnAppearance(const EQApplicationPacket *app)
|
||||
return;
|
||||
}
|
||||
else if (sa->type == AT_AFK) {
|
||||
this->AFK = (sa->parameter == 1);
|
||||
entity_list.QueueClients(this, app, true);
|
||||
if(afk_toggle_timer.Check()) {
|
||||
AFK = (sa->parameter == 1);
|
||||
entity_list.QueueClients(this, app, true);
|
||||
}
|
||||
}
|
||||
else if (sa->type == AT_Split) {
|
||||
m_pp.autosplit = (sa->parameter == 1);
|
||||
}
|
||||
else if (sa->type == AT_Sneak) {
|
||||
if(sneaking == 0)
|
||||
return;
|
||||
|
||||
if (sa->parameter != 0)
|
||||
{
|
||||
if (!HasSkill(SkillSneak))
|
||||
@ -12729,7 +12733,7 @@ void Client::Handle_OP_SpawnAppearance(const EQApplicationPacket *app)
|
||||
}
|
||||
return;
|
||||
}
|
||||
this->sneaking = 0;
|
||||
sneaking = 0;
|
||||
entity_list.QueueClients(this, app, true);
|
||||
}
|
||||
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)
|
||||
{
|
||||
entity_list.QueueClients(this, app, false);
|
||||
//don't do anything with this
|
||||
}
|
||||
else if (sa->type == AT_Levitate)
|
||||
{
|
||||
@ -12750,8 +12754,10 @@ void Client::Handle_OP_SpawnAppearance(const EQApplicationPacket *app)
|
||||
}
|
||||
else if (sa->type == AT_ShowHelm)
|
||||
{
|
||||
m_pp.showhelm = (sa->parameter == 1);
|
||||
entity_list.QueueClients(this, app, true);
|
||||
if(helm_toggle_timer.Check()) {
|
||||
m_pp.showhelm = (sa->parameter == 1);
|
||||
entity_list.QueueClients(this, app, true);
|
||||
}
|
||||
}
|
||||
else {
|
||||
std::cout << "Unknown SpawnAppearance type: 0x" << std::hex << std::setw(4) << std::setfill('0') << sa->type << std::dec
|
||||
|
||||
@ -260,6 +260,13 @@ bool Client::Process() {
|
||||
}
|
||||
}
|
||||
|
||||
if(light_update_timer.Check()) {
|
||||
UpdateEquipLightValue();
|
||||
if(UpdateActiveLightValue()) {
|
||||
SendAppearancePacket(AT_Light, GetActiveLightValue());
|
||||
}
|
||||
}
|
||||
|
||||
bool may_use_attacks = false;
|
||||
/*
|
||||
Things which prevent us from attacking:
|
||||
|
||||
@ -2618,7 +2618,7 @@ void command_peekinv(Client *c, const Seperator *sep)
|
||||
}
|
||||
else {
|
||||
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;
|
||||
item_data = (inst_main == nullptr) ? nullptr : inst_main->GetItem();
|
||||
linker.SetItemInst(inst_main);
|
||||
@ -4284,31 +4284,49 @@ void command_goto(Client *c, const Seperator *sep)
|
||||
|
||||
void command_iteminfo(Client *c, const Seperator *sep)
|
||||
{
|
||||
const ItemInst* inst = c->GetInv()[MainCursor];
|
||||
|
||||
if (!inst)
|
||||
c->Message(13, "Error: You need an item on your cursor for this command");
|
||||
else {
|
||||
const Item_Struct* item = inst->GetItem();
|
||||
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);
|
||||
}
|
||||
auto inst = c->GetInv()[MainCursor];
|
||||
if (!inst) { c->Message(13, "Error: You need an item on your cursor for this command"); }
|
||||
auto item = inst->GetItem();
|
||||
if (!item) {
|
||||
Log.Out(Logs::General, Logs::Inventory, "(%s) Command #iteminfo processed an item with no data pointer");
|
||||
c->Message(13, "Error: This item has no data reference");
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
@ -361,8 +361,8 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob (
|
||||
database.QueryDatabase(ss.str().c_str());
|
||||
}
|
||||
|
||||
auto start = client->GetInv().cursor_begin();
|
||||
auto finish = client->GetInv().cursor_end();
|
||||
auto start = client->GetInv().cursor_cbegin();
|
||||
auto finish = client->GetInv().cursor_cend();
|
||||
database.SaveCursor(client->CharacterID(), start, finish);
|
||||
|
||||
client->CalcBonuses();
|
||||
|
||||
@ -73,7 +73,7 @@ public:
|
||||
void SplitMoney(uint32 copper, uint32 silver, uint32 gold, uint32 platinum, Client *splitter = nullptr);
|
||||
inline void SetLeader(Mob* newleader){ leader=newleader; };
|
||||
inline Mob* GetLeader() { return leader; };
|
||||
const char* GetLeaderName() { return leader->GetName(); };
|
||||
const char* GetLeaderName() { return membername[0]; };
|
||||
void SendHPPacketsTo(Mob* newmember);
|
||||
void SendHPPacketsFrom(Mob* newmember);
|
||||
bool UpdatePlayer(Mob* update);
|
||||
|
||||
@ -177,16 +177,16 @@ uint32 Client::NukeItem(uint32 itemnum, uint8 where_to_check) {
|
||||
}
|
||||
|
||||
|
||||
bool Client::CheckLoreConflict(const Item_Struct* item) {
|
||||
if (!item)
|
||||
return false;
|
||||
if (!(item->LoreFlag))
|
||||
return false;
|
||||
bool Client::CheckLoreConflict(const Item_Struct* item)
|
||||
{
|
||||
if (!item) { return false; }
|
||||
if (!item->LoreFlag) { 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);
|
||||
|
||||
//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);
|
||||
}
|
||||
|
||||
@ -619,7 +619,7 @@ void Client::DropItem(int16 slot_id)
|
||||
// Save client inventory change to database
|
||||
if (slot_id == MainCursor) {
|
||||
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);
|
||||
} else {
|
||||
database.SaveInventory(CharacterID(), nullptr, slot_id);
|
||||
@ -680,20 +680,37 @@ int32 Client::GetAugmentIDAt(int16 slot_id, uint8 augslot) {
|
||||
return INVALID_ID;
|
||||
}
|
||||
|
||||
void Client::SendCursorBuffer() {
|
||||
void Client::SendCursorBuffer()
|
||||
{
|
||||
// Temporary work-around for the RoF+ Client 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.
|
||||
if (GetClientVersion() >= ClientVersion::RoF)
|
||||
{
|
||||
if (!GetInv().CursorEmpty())
|
||||
{
|
||||
const ItemInst* inst = GetInv().GetCursorItem();
|
||||
if (inst)
|
||||
{
|
||||
SendItemPacket(MainCursor, inst, ItemPacketSummonItem);
|
||||
}
|
||||
}
|
||||
if (GetClientVersion() < ClientVersion::RoF) { return; }
|
||||
if (GetInv().CursorEmpty()) { return; }
|
||||
|
||||
auto test_inst = GetInv().GetCursorItem();
|
||||
if (test_inst == nullptr) { return; }
|
||||
auto test_item = test_inst->GetItem();
|
||||
if (test_item == nullptr) { return; }
|
||||
|
||||
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;
|
||||
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)
|
||||
database.SaveCursor(character_id, s, e);
|
||||
}
|
||||
@ -826,7 +843,7 @@ bool Client::PushItemOnCursor(const ItemInst& inst, bool client_update)
|
||||
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);
|
||||
}
|
||||
|
||||
@ -851,7 +868,7 @@ bool Client::PutItemInInventory(int16 slot_id, const ItemInst& inst, bool client
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
else {
|
||||
@ -870,7 +887,7 @@ void Client::PutLootInInventory(int16 slot_id, const ItemInst &inst, ServerLootI
|
||||
SendLootItemInPacket(&inst, slot_id);
|
||||
|
||||
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);
|
||||
}
|
||||
else {
|
||||
@ -1009,7 +1026,7 @@ void Client::MoveItemCharges(ItemInst &from, int16 to_slot, uint8 type)
|
||||
from.SetCharges(from.GetCharges() - charges_to_move);
|
||||
SendLootItemInPacket(tmp_inst, to_slot);
|
||||
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);
|
||||
}
|
||||
else {
|
||||
@ -1320,10 +1337,33 @@ bool Client::SwapItem(MoveItem_Struct* move_in) {
|
||||
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(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;
|
||||
}
|
||||
|
||||
@ -1567,7 +1607,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) {
|
||||
{
|
||||
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);
|
||||
}
|
||||
else
|
||||
@ -1726,7 +1766,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) {
|
||||
{
|
||||
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);
|
||||
}
|
||||
else {
|
||||
@ -1734,7 +1774,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) {
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
else {
|
||||
@ -2170,7 +2210,7 @@ void Client::RemoveNoRent(bool client_update)
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -2298,7 +2338,7 @@ void Client::RemoveDuplicateLore(bool client_update)
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -2826,9 +2866,9 @@ bool Client::InterrogateInventory(Client* requester, bool log, bool silent, bool
|
||||
}
|
||||
|
||||
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
|
||||
if (cursor_itr == m_inv.cursor_begin())
|
||||
if (cursor_itr == m_inv.cursor_cbegin())
|
||||
continue;
|
||||
|
||||
instmap[8000 + limbo] = *cursor_itr;
|
||||
|
||||
@ -1479,8 +1479,6 @@ static void BazaarAuditTrail(const char *seller, const char *buyer, const char *
|
||||
database.QueryDatabase(query);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Client::BuyTraderItem(TraderBuy_Struct* tbs,Client* Trader,const EQApplicationPacket* app){
|
||||
|
||||
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());
|
||||
// If the item is not stackable, then we can only be buying one of them.
|
||||
if(!BuyItem->IsStackable())
|
||||
outtbs->Quantity = tbs->Quantity;
|
||||
outtbs->Quantity = 1; // normally you can't send more than 1 here
|
||||
else {
|
||||
// Stackable items, arrows, diamonds, etc
|
||||
int ItemCharges = BuyItem->GetCharges();
|
||||
int32 ItemCharges = BuyItem->GetCharges();
|
||||
// ItemCharges for stackables should not be <= 0
|
||||
if(ItemCharges <= 0)
|
||||
outtbs->Quantity = 1;
|
||||
// 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;
|
||||
else
|
||||
outtbs->Quantity = tbs->Quantity;
|
||||
@ -1609,7 +1607,6 @@ void Client::BuyTraderItem(TraderBuy_Struct* tbs,Client* Trader,const EQApplicat
|
||||
|
||||
safe_delete(outapp);
|
||||
safe_delete(outapp2);
|
||||
|
||||
}
|
||||
|
||||
void Client::SendBazaarWelcome()
|
||||
|
||||
@ -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
|
||||
//otherwise we update with a REPLACE INTO
|
||||
if(timeleft == 0) {
|
||||
std::string query = StringFormat("DELETE FROM respawn_times WHERE id=%lu "
|
||||
"AND instance_id = %lu",(unsigned long)id, (unsigned long)instance_id);
|
||||
std::string query = StringFormat("DELETE FROM respawn_times WHERE id=%lu AND instance_id = %lu",(unsigned long)id, (unsigned long)instance_id);
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user