mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-15 23:20:36 +01:00
Core/Items: Implemented CreateTime item field and changed refund/soulbound trade timers to also count time offline
This commit is contained in:
@@ -2705,6 +2705,7 @@ CREATE TABLE `item_instance` (
|
||||
`randomBonusListId` int unsigned NOT NULL DEFAULT '0',
|
||||
`durability` smallint unsigned NOT NULL DEFAULT '0',
|
||||
`playedTime` int unsigned NOT NULL DEFAULT '0',
|
||||
`createTime` bigint NOT NULL DEFAULT '0',
|
||||
`text` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci,
|
||||
`battlePetSpeciesId` int unsigned NOT NULL DEFAULT '0',
|
||||
`battlePetBreedData` int unsigned NOT NULL DEFAULT '0',
|
||||
@@ -3723,7 +3724,8 @@ INSERT INTO `updates` VALUES
|
||||
('2023_11_09_00_characters.sql','1A3D7CA6890353DA55793FE8D925CC8C54965A69','ARCHIVED','2023-11-09 00:56:31',0),
|
||||
('2023_11_15_00_characters.sql','441E0F17DE3E3945307AC400DF86FCDF06C61653','ARCHIVED','2023-11-15 00:53:47',0),
|
||||
('2024_02_08_00_characters.sql','743A11042AA17CDBD5F3D510D24509A10838DB5A','ARCHIVED','2024-02-08 00:56:26',0),
|
||||
('2024_04_09_00_characters.sql','07AC79B4E489B1CD073852EC57D12939C2A1D4B1','RELEASED','2024-04-09 12:54:11',0);
|
||||
('2024_04_09_00_characters.sql','07AC79B4E489B1CD073852EC57D12939C2A1D4B1','RELEASED','2024-04-09 12:54:11',0),
|
||||
('2024_04_12_00_characters.sql','043E023F998DA77170C9D2D0162CAA340290B215','RELEASED','2024-04-12 00:23:51',0);
|
||||
/*!40000 ALTER TABLE `updates` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
ALTER TABLE `item_instance` ADD `createTime` bigint NOT NULL DEFAULT '0' AFTER `playedTime`;
|
||||
|
||||
UPDATE `item_instance` SET `createTime` = COALESCE(
|
||||
(SELECT LEAST(c.`logout_time`, GREATEST(c.`createTime`, c.`logout_time` -
|
||||
((c.`totaltime`-`playedTime`)
|
||||
/ GREATEST(c.`totaltime`, 1)
|
||||
* (c.`logout_time`-c.`createTime`)))) FROM `characters` c WHERE c.`guid`=`owner_guid`),
|
||||
UNIX_TIMESTAMP()
|
||||
);
|
||||
@@ -24,7 +24,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
|
||||
m_stmts.resize(MAX_CHARACTERDATABASE_STATEMENTS);
|
||||
|
||||
#define SelectItemInstanceContent "ii.guid, ii.itemEntry, ii.creatorGuid, ii.giftCreatorGuid, ii.count, ii.duration, ii.charges, ii.flags, ii.enchantments, ii.randomBonusListId, " \
|
||||
"ii.durability, ii.playedTime, ii.text, ii.battlePetSpeciesId, ii.battlePetBreedData, ii.battlePetLevel, ii.battlePetDisplayId, ii.context, ii.bonusListIDs, " \
|
||||
"ii.durability, ii.playedTime, ii.createTime, ii.text, ii.battlePetSpeciesId, ii.battlePetBreedData, ii.battlePetLevel, ii.battlePetDisplayId, ii.context, ii.bonusListIDs, " \
|
||||
"iit.itemModifiedAppearanceAllSpecs, iit.itemModifiedAppearanceSpec1, iit.itemModifiedAppearanceSpec2, iit.itemModifiedAppearanceSpec3, iit.itemModifiedAppearanceSpec4, iit.itemModifiedAppearanceSpec5, " \
|
||||
"iit.spellItemEnchantmentAllSpecs, iit.spellItemEnchantmentSpec1, iit.spellItemEnchantmentSpec2, iit.spellItemEnchantmentSpec3, iit.spellItemEnchantmentSpec4, iit.spellItemEnchantmentSpec5, " \
|
||||
"iit.secondaryItemModifiedAppearanceAllSpecs, iit.secondaryItemModifiedAppearanceSpec1, iit.secondaryItemModifiedAppearanceSpec2, iit.secondaryItemModifiedAppearanceSpec3, iit.secondaryItemModifiedAppearanceSpec4, iit.secondaryItemModifiedAppearanceSpec5, " \
|
||||
@@ -202,8 +202,8 @@ void CharacterDatabaseConnection::DoPrepareStatements()
|
||||
PrepareStatement(CHAR_DEL_ITEM_BOP_TRADE, "DELETE FROM item_soulbound_trade_data WHERE itemGuid = ? LIMIT 1", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_ITEM_BOP_TRADE, "INSERT INTO item_soulbound_trade_data VALUES (?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_REP_INVENTORY_ITEM, "REPLACE INTO character_inventory (guid, bag, slot, item) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_REP_ITEM_INSTANCE, "REPLACE INTO item_instance (itemEntry, owner_guid, creatorGuid, giftCreatorGuid, count, duration, charges, flags, enchantments, randomBonusListId, durability, playedTime, text, battlePetSpeciesId, battlePetBreedData, battlePetLevel, battlePetDisplayId, context, bonusListIDs, guid) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_ITEM_INSTANCE, "UPDATE item_instance SET itemEntry = ?, owner_guid = ?, creatorGuid = ?, giftCreatorGuid = ?, count = ?, duration = ?, charges = ?, flags = ?, enchantments = ?, randomBonusListId = ?, durability = ?, playedTime = ?, text = ?, battlePetSpeciesId = ?, battlePetBreedData = ?, battlePetLevel = ?, battlePetDisplayId = ?, context = ?, bonusListIDs = ? WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_REP_ITEM_INSTANCE, "REPLACE INTO item_instance (itemEntry, owner_guid, creatorGuid, giftCreatorGuid, count, duration, charges, flags, enchantments, randomBonusListId, durability, playedTime, createTime, text, battlePetSpeciesId, battlePetBreedData, battlePetLevel, battlePetDisplayId, context, bonusListIDs, guid) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_ITEM_INSTANCE, "UPDATE item_instance SET itemEntry = ?, owner_guid = ?, creatorGuid = ?, giftCreatorGuid = ?, count = ?, duration = ?, charges = ?, flags = ?, enchantments = ?, randomBonusListId = ?, durability = ?, playedTime = ?, createTime = ?, text = ?, battlePetSpeciesId = ?, battlePetBreedData = ?, battlePetLevel = ?, battlePetDisplayId = ?, context = ?, bonusListIDs = ? WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_ITEM_INSTANCE_ON_LOAD, "UPDATE item_instance SET duration = ?, flags = ?, durability = ? WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_ITEM_INSTANCE, "DELETE FROM item_instance WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_ITEM_INSTANCE_BY_OWNER, "DELETE FROM item_instance WHERE owner_guid = ?", CONNECTION_ASYNC);
|
||||
|
||||
@@ -529,12 +529,12 @@ void AuctionHouseMgr::LoadAuctions()
|
||||
}
|
||||
|
||||
Item* item = NewItemOrBag(proto);
|
||||
if (!item->LoadFromDB(itemGuid, ObjectGuid::Create<HighGuid::Player>(fields[51].GetUInt64()), fields, itemEntry))
|
||||
if (!item->LoadFromDB(itemGuid, ObjectGuid::Create<HighGuid::Player>(fields[52].GetUInt64()), fields, itemEntry))
|
||||
{
|
||||
delete item;
|
||||
continue;
|
||||
}
|
||||
uint32 auctionId = fields[52].GetUInt32();
|
||||
uint32 auctionId = fields[53].GetUInt32();
|
||||
itemsByAuction[auctionId].push_back(item);
|
||||
|
||||
++count;
|
||||
|
||||
@@ -452,7 +452,6 @@ Item::Item()
|
||||
m_container = nullptr;
|
||||
m_lootGenerated = false;
|
||||
mb_in_trade = false;
|
||||
m_lastPlayedTimeUpdate = GameTime::GetGameTime();
|
||||
|
||||
m_paidMoney = 0;
|
||||
m_paidExtendedCost = 0;
|
||||
@@ -493,6 +492,7 @@ bool Item::Create(ObjectGuid::LowType guidlow, uint32 itemId, ItemContext contex
|
||||
|
||||
SetExpiration(itemProto->GetDuration());
|
||||
SetCreatePlayedTime(0);
|
||||
SetCreateTime(GameTime::GetGameTime());
|
||||
SetContext(context);
|
||||
|
||||
if (itemProto->GetArtifactID())
|
||||
@@ -604,6 +604,7 @@ void Item::SaveToDB(CharacterDatabaseTransaction trans)
|
||||
stmt->setUInt32(++index, m_randomBonusListId);
|
||||
stmt->setUInt16(++index, m_itemData->Durability);
|
||||
stmt->setUInt32(++index, m_itemData->CreatePlayedTime);
|
||||
stmt->setInt64(++index, m_itemData->CreateTime);
|
||||
stmt->setString(++index, m_text);
|
||||
stmt->setUInt32(++index, GetModifier(ITEM_MODIFIER_BATTLE_PET_SPECIES_ID));
|
||||
stmt->setUInt32(++index, GetModifier(ITEM_MODIFIER_BATTLE_PET_BREED_DATA));
|
||||
@@ -826,21 +827,21 @@ void Item::SaveToDB(CharacterDatabaseTransaction trans)
|
||||
|
||||
bool Item::LoadFromDB(ObjectGuid::LowType guid, ObjectGuid ownerGuid, Field* fields, uint32 entry)
|
||||
{
|
||||
// 0 1 2 3 4 5 6 7 8 9 10 11 12
|
||||
// SELECT guid, itemEntry, creatorGuid, giftCreatorGuid, count, duration, charges, flags, enchantments, randomBonusListId, durability, playedTime, text,
|
||||
// 13 14 15 16 17 18
|
||||
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13
|
||||
// SELECT guid, itemEntry, creatorGuid, giftCreatorGuid, count, duration, charges, flags, enchantments, randomBonusListId, durability, playedTime, createTime, text,
|
||||
// 14 15 16 17 18 19
|
||||
// battlePetSpeciesId, battlePetBreedData, battlePetLevel, battlePetDisplayId, context, bonusListIDs,
|
||||
// 19 20 21 22 23 24
|
||||
// 20 21 22 23 24 25
|
||||
// itemModifiedAppearanceAllSpecs, itemModifiedAppearanceSpec1, itemModifiedAppearanceSpec2, itemModifiedAppearanceSpec3, itemModifiedAppearanceSpec4, itemModifiedAppearanceSpec5,
|
||||
// 25 26 27 28 29 30
|
||||
// 26 27 28 29 30 31
|
||||
// spellItemEnchantmentAllSpecs, spellItemEnchantmentSpec1, spellItemEnchantmentSpec2, spellItemEnchantmentSpec3, spellItemEnchantmentSpec4, spellItemEnchantmentSpec5,
|
||||
// 31 32 33
|
||||
// 32 33 34
|
||||
// secondaryItemModifiedAppearanceAllSpecs, secondaryItemModifiedAppearanceSpec1, secondaryItemModifiedAppearanceSpec2,
|
||||
// 34 35 36
|
||||
// 35 36 37
|
||||
// secondaryItemModifiedAppearanceSpec3, secondaryItemModifiedAppearanceSpec4, secondaryItemModifiedAppearanceSpec5,
|
||||
// 37 38 39 40 41 42 43 44 45 46 47 48
|
||||
// 38 39 40 41 42 43 44 45 46 47 48 49
|
||||
// gemItemId1, gemBonuses1, gemContext1, gemScalingLevel1, gemItemId2, gemBonuses2, gemContext2, gemScalingLevel2, gemItemId3, gemBonuses3, gemContext3, gemScalingLevel3
|
||||
// 49 50
|
||||
// 50 51
|
||||
// fixedScalingLevel, artifactKnowledgeLevel FROM item_instance
|
||||
|
||||
// create item before any checks for store correct guid
|
||||
@@ -901,16 +902,17 @@ bool Item::LoadFromDB(ObjectGuid::LowType guid, ObjectGuid ownerGuid, Field* fie
|
||||
}
|
||||
|
||||
SetCreatePlayedTime(fields[11].GetUInt32());
|
||||
SetText(fields[12].GetString());
|
||||
SetCreateTime(fields[12].GetInt64());
|
||||
SetText(fields[13].GetString());
|
||||
|
||||
SetModifier(ITEM_MODIFIER_BATTLE_PET_SPECIES_ID, fields[13].GetUInt32());
|
||||
SetModifier(ITEM_MODIFIER_BATTLE_PET_BREED_DATA, fields[14].GetUInt32());
|
||||
SetModifier(ITEM_MODIFIER_BATTLE_PET_LEVEL, fields[15].GetUInt16());
|
||||
SetModifier(ITEM_MODIFIER_BATTLE_PET_DISPLAY_ID, fields[16].GetUInt32());
|
||||
SetModifier(ITEM_MODIFIER_BATTLE_PET_SPECIES_ID, fields[14].GetUInt32());
|
||||
SetModifier(ITEM_MODIFIER_BATTLE_PET_BREED_DATA, fields[15].GetUInt32());
|
||||
SetModifier(ITEM_MODIFIER_BATTLE_PET_LEVEL, fields[16].GetUInt16());
|
||||
SetModifier(ITEM_MODIFIER_BATTLE_PET_DISPLAY_ID, fields[17].GetUInt32());
|
||||
|
||||
SetContext(ItemContext(fields[17].GetUInt8()));
|
||||
SetContext(ItemContext(fields[18].GetUInt8()));
|
||||
|
||||
std::vector<std::string_view> bonusListString = Trinity::Tokenize(fields[18].GetStringView(), ' ', false);
|
||||
std::vector<std::string_view> bonusListString = Trinity::Tokenize(fields[19].GetStringView(), ' ', false);
|
||||
std::vector<int32> bonusListIDs;
|
||||
bonusListIDs.reserve(bonusListString.size());
|
||||
for (std::string_view token : bonusListString)
|
||||
@@ -923,46 +925,46 @@ bool Item::LoadFromDB(ObjectGuid::LowType guid, ObjectGuid ownerGuid, Field* fie
|
||||
for (uint8 i = 0; i < m_itemData->SpellCharges.size() && i < _bonusData.EffectCount && i < tokens.size(); ++i)
|
||||
SetSpellCharges(i, Trinity::StringTo<int32>(tokens[i]).value_or(0));
|
||||
|
||||
SetModifier(ITEM_MODIFIER_TRANSMOG_APPEARANCE_ALL_SPECS, fields[19].GetUInt32());
|
||||
SetModifier(ITEM_MODIFIER_TRANSMOG_APPEARANCE_SPEC_1, fields[20].GetUInt32());
|
||||
SetModifier(ITEM_MODIFIER_TRANSMOG_APPEARANCE_SPEC_2, fields[21].GetUInt32());
|
||||
SetModifier(ITEM_MODIFIER_TRANSMOG_APPEARANCE_SPEC_3, fields[22].GetUInt32());
|
||||
SetModifier(ITEM_MODIFIER_TRANSMOG_APPEARANCE_SPEC_4, fields[23].GetUInt32());
|
||||
SetModifier(ITEM_MODIFIER_TRANSMOG_APPEARANCE_SPEC_5, fields[24].GetUInt32());
|
||||
SetModifier(ITEM_MODIFIER_TRANSMOG_APPEARANCE_ALL_SPECS, fields[20].GetUInt32());
|
||||
SetModifier(ITEM_MODIFIER_TRANSMOG_APPEARANCE_SPEC_1, fields[21].GetUInt32());
|
||||
SetModifier(ITEM_MODIFIER_TRANSMOG_APPEARANCE_SPEC_2, fields[22].GetUInt32());
|
||||
SetModifier(ITEM_MODIFIER_TRANSMOG_APPEARANCE_SPEC_3, fields[23].GetUInt32());
|
||||
SetModifier(ITEM_MODIFIER_TRANSMOG_APPEARANCE_SPEC_4, fields[24].GetUInt32());
|
||||
SetModifier(ITEM_MODIFIER_TRANSMOG_APPEARANCE_SPEC_5, fields[25].GetUInt32());
|
||||
|
||||
SetModifier(ITEM_MODIFIER_ENCHANT_ILLUSION_ALL_SPECS, fields[25].GetUInt32());
|
||||
SetModifier(ITEM_MODIFIER_ENCHANT_ILLUSION_SPEC_1, fields[26].GetUInt32());
|
||||
SetModifier(ITEM_MODIFIER_ENCHANT_ILLUSION_SPEC_2, fields[27].GetUInt32());
|
||||
SetModifier(ITEM_MODIFIER_ENCHANT_ILLUSION_SPEC_3, fields[28].GetUInt32());
|
||||
SetModifier(ITEM_MODIFIER_ENCHANT_ILLUSION_SPEC_4, fields[29].GetUInt32());
|
||||
SetModifier(ITEM_MODIFIER_ENCHANT_ILLUSION_SPEC_5, fields[30].GetUInt32());
|
||||
SetModifier(ITEM_MODIFIER_ENCHANT_ILLUSION_ALL_SPECS, fields[26].GetUInt32());
|
||||
SetModifier(ITEM_MODIFIER_ENCHANT_ILLUSION_SPEC_1, fields[27].GetUInt32());
|
||||
SetModifier(ITEM_MODIFIER_ENCHANT_ILLUSION_SPEC_2, fields[28].GetUInt32());
|
||||
SetModifier(ITEM_MODIFIER_ENCHANT_ILLUSION_SPEC_3, fields[29].GetUInt32());
|
||||
SetModifier(ITEM_MODIFIER_ENCHANT_ILLUSION_SPEC_4, fields[30].GetUInt32());
|
||||
SetModifier(ITEM_MODIFIER_ENCHANT_ILLUSION_SPEC_5, fields[31].GetUInt32());
|
||||
|
||||
SetModifier(ITEM_MODIFIER_TRANSMOG_SECONDARY_APPEARANCE_ALL_SPECS, fields[31].GetUInt32());
|
||||
SetModifier(ITEM_MODIFIER_TRANSMOG_SECONDARY_APPEARANCE_SPEC_1, fields[32].GetUInt32());
|
||||
SetModifier(ITEM_MODIFIER_TRANSMOG_SECONDARY_APPEARANCE_SPEC_2, fields[33].GetUInt32());
|
||||
SetModifier(ITEM_MODIFIER_TRANSMOG_SECONDARY_APPEARANCE_SPEC_3, fields[34].GetUInt32());
|
||||
SetModifier(ITEM_MODIFIER_TRANSMOG_SECONDARY_APPEARANCE_SPEC_4, fields[35].GetUInt32());
|
||||
SetModifier(ITEM_MODIFIER_TRANSMOG_SECONDARY_APPEARANCE_SPEC_5, fields[36].GetUInt32());
|
||||
SetModifier(ITEM_MODIFIER_TRANSMOG_SECONDARY_APPEARANCE_ALL_SPECS, fields[32].GetUInt32());
|
||||
SetModifier(ITEM_MODIFIER_TRANSMOG_SECONDARY_APPEARANCE_SPEC_1, fields[33].GetUInt32());
|
||||
SetModifier(ITEM_MODIFIER_TRANSMOG_SECONDARY_APPEARANCE_SPEC_2, fields[34].GetUInt32());
|
||||
SetModifier(ITEM_MODIFIER_TRANSMOG_SECONDARY_APPEARANCE_SPEC_3, fields[35].GetUInt32());
|
||||
SetModifier(ITEM_MODIFIER_TRANSMOG_SECONDARY_APPEARANCE_SPEC_4, fields[36].GetUInt32());
|
||||
SetModifier(ITEM_MODIFIER_TRANSMOG_SECONDARY_APPEARANCE_SPEC_5, fields[37].GetUInt32());
|
||||
|
||||
uint32 const gemFields = 4;
|
||||
ItemDynamicFieldGems gemData[MAX_GEM_SOCKETS];
|
||||
memset(gemData, 0, sizeof(gemData));
|
||||
for (uint32 i = 0; i < MAX_GEM_SOCKETS; ++i)
|
||||
{
|
||||
gemData[i].ItemId = fields[37 + i * gemFields].GetUInt32();
|
||||
std::vector<std::string_view> gemBonusListIDs = Trinity::Tokenize(fields[38 + i * gemFields].GetStringView(), ' ', false);
|
||||
gemData[i].ItemId = fields[38 + i * gemFields].GetUInt32();
|
||||
std::vector<std::string_view> gemBonusListIDs = Trinity::Tokenize(fields[39 + i * gemFields].GetStringView(), ' ', false);
|
||||
uint32 b = 0;
|
||||
for (std::string_view token : gemBonusListIDs)
|
||||
if (Optional<uint16> bonusListID = Trinity::StringTo<uint16>(token))
|
||||
gemData[i].BonusListIDs[b++] = *bonusListID;
|
||||
|
||||
gemData[i].Context = fields[39 + i * gemFields].GetUInt8();
|
||||
gemData[i].Context = fields[40 + i * gemFields].GetUInt8();
|
||||
if (gemData[i].ItemId)
|
||||
SetGem(i, &gemData[i], fields[40 + i * gemFields].GetUInt32());
|
||||
SetGem(i, &gemData[i], fields[41 + i * gemFields].GetUInt32());
|
||||
}
|
||||
|
||||
SetModifier(ITEM_MODIFIER_TIMEWALKER_LEVEL, fields[49].GetUInt32());
|
||||
SetModifier(ITEM_MODIFIER_ARTIFACT_KNOWLEDGE_LEVEL, fields[50].GetUInt32());
|
||||
SetModifier(ITEM_MODIFIER_TIMEWALKER_LEVEL, fields[50].GetUInt32());
|
||||
SetModifier(ITEM_MODIFIER_ARTIFACT_KNOWLEDGE_LEVEL, fields[51].GetUInt32());
|
||||
|
||||
// Enchants must be loaded after all other bonus/scaling data
|
||||
std::vector<std::string_view> enchantmentTokens = Trinity::Tokenize(fields[8].GetStringView(), ' ', false);
|
||||
@@ -1659,6 +1661,7 @@ Item* Item::CloneItem(uint32 count, Player const* player /*= nullptr*/) const
|
||||
newItem->ReplaceAllItemFlags(ItemFieldFlags(*m_itemData->DynamicFlags) & ~(ITEM_FIELD_FLAG_REFUNDABLE | ITEM_FIELD_FLAG_BOP_TRADEABLE));
|
||||
newItem->SetExpiration(m_itemData->Expiration);
|
||||
newItem->SetBonuses(m_itemData->ItemBonusKey->BonusListIDs);
|
||||
newItem->SetFixedLevel(GetModifier(ITEM_MODIFIER_TIMEWALKER_LEVEL));
|
||||
// player CAN be NULL in which case we must not update random properties because that accesses player's item update queue
|
||||
if (player)
|
||||
newItem->SetItemRandomBonusList(m_randomBonusListId);
|
||||
@@ -1860,44 +1863,14 @@ void Item::SetNotRefundable(Player* owner, bool changestate /*= true*/, Characte
|
||||
owner->GetSession()->GetCollectionMgr()->AddItemAppearance(this);
|
||||
}
|
||||
|
||||
void Item::UpdatePlayedTime(Player* owner)
|
||||
uint32 Item::GetPlayedTime() const
|
||||
{
|
||||
/* Here we update our played time
|
||||
We simply add a number to the current played time,
|
||||
based on the time elapsed since the last update hereof.
|
||||
*/
|
||||
// Get current played time
|
||||
uint32 current_playtime = m_itemData->CreatePlayedTime;
|
||||
// Calculate time elapsed since last played time update
|
||||
time_t curtime = GameTime::GetGameTime();
|
||||
uint32 elapsed = uint32(curtime - m_lastPlayedTimeUpdate);
|
||||
uint32 new_playtime = current_playtime + elapsed;
|
||||
// Check if the refund timer has expired yet
|
||||
if (new_playtime <= 2*HOUR)
|
||||
{
|
||||
// No? Proceed.
|
||||
// Update the data field
|
||||
SetCreatePlayedTime(new_playtime);
|
||||
// Flag as changed to get saved to DB
|
||||
SetState(ITEM_CHANGED, owner);
|
||||
// Speaks for itself
|
||||
m_lastPlayedTimeUpdate = curtime;
|
||||
return;
|
||||
}
|
||||
// Yes
|
||||
SetNotRefundable(owner);
|
||||
return *m_itemData->CreatePlayedTime;
|
||||
}
|
||||
|
||||
uint32 Item::GetPlayedTime()
|
||||
bool Item::IsRefundExpired() const
|
||||
{
|
||||
time_t curtime = GameTime::GetGameTime();
|
||||
uint32 elapsed = uint32(curtime - m_lastPlayedTimeUpdate);
|
||||
return *m_itemData->CreatePlayedTime + elapsed;
|
||||
}
|
||||
|
||||
bool Item::IsRefundExpired()
|
||||
{
|
||||
return (GetPlayedTime() > 2*HOUR);
|
||||
return *m_itemData->CreateTime + 2 * HOUR <= GameTime::GetGameTime();
|
||||
}
|
||||
|
||||
void Item::SetSoulboundTradeable(GuidSet const& allowedLooters)
|
||||
@@ -1923,7 +1896,7 @@ void Item::ClearSoulboundTradeable(Player* currentOwner)
|
||||
bool Item::CheckSoulboundTradeExpire()
|
||||
{
|
||||
// called from owner's update - GetOwner() MUST be valid
|
||||
if (m_itemData->CreatePlayedTime + 2*HOUR < GetOwner()->GetTotalPlayedTime())
|
||||
if (m_itemData->CreatePlayedTime + 4 * HOUR < GetOwner()->GetTotalPlayedTime())
|
||||
{
|
||||
ClearSoulboundTradeable(GetOwner());
|
||||
return true; // remove from tradeable list
|
||||
|
||||
@@ -309,6 +309,7 @@ class TC_GAME_API Item : public Object
|
||||
void SendTimeUpdate(Player* owner);
|
||||
void UpdateDuration(Player* owner, uint32 diff);
|
||||
void SetCreatePlayedTime(uint32 createPlayedTime) { SetUpdateFieldValue(m_values.ModifyValue(&Item::m_itemData).ModifyValue(&UF::ItemData::CreatePlayedTime), createPlayedTime); }
|
||||
void SetCreateTime(int64 createTime) { SetUpdateFieldValue(m_values.ModifyValue(&Item::m_itemData).ModifyValue(&UF::ItemData::CreateTime), createTime); }
|
||||
|
||||
// spell charges (signed but stored as unsigned)
|
||||
int32 GetSpellCharges(uint8 index/*0..5*/ = 0) const { return m_itemData->SpellCharges[index]; }
|
||||
@@ -363,9 +364,8 @@ class TC_GAME_API Item : public Object
|
||||
uint64 GetPaidMoney() const { return m_paidMoney; }
|
||||
uint32 GetPaidExtendedCost() const { return m_paidExtendedCost; }
|
||||
|
||||
void UpdatePlayedTime(Player* owner);
|
||||
uint32 GetPlayedTime();
|
||||
bool IsRefundExpired();
|
||||
uint32 GetPlayedTime() const;
|
||||
bool IsRefundExpired() const;
|
||||
|
||||
// Soulbound trade system
|
||||
void SetSoulboundTradeable(GuidSet const& allowedLooters);
|
||||
@@ -458,7 +458,6 @@ class TC_GAME_API Item : public Object
|
||||
ItemUpdateState uState;
|
||||
int16 uQueuePos;
|
||||
bool mb_in_trade; // true if item is currently in trade-window
|
||||
time_t m_lastPlayedTimeUpdate;
|
||||
ObjectGuid m_refundRecipient;
|
||||
uint64 m_paidMoney;
|
||||
uint32 m_paidExtendedCost;
|
||||
|
||||
@@ -3924,7 +3924,7 @@ void Player::DeleteFromDB(ObjectGuid playerguid, uint32 accountId, bool updateRe
|
||||
do
|
||||
{
|
||||
Field* fields = resultItems->Fetch();
|
||||
uint64 mailId = fields[44].GetUInt64();
|
||||
uint64 mailId = fields[53].GetUInt64();
|
||||
if (Item* mailItem = _LoadMailedItem(playerguid, nullptr, mailId, nullptr, fields, Trinity::Containers::MapGetValuePtr(additionalData, fields[0].GetUInt64())))
|
||||
itemsByMail[mailId].push_back(mailItem);
|
||||
|
||||
@@ -11545,19 +11545,19 @@ Item* Player::StoreNewItem(ItemPosCountVec const& pos, uint32 itemId, bool updat
|
||||
if (bonusListIDs)
|
||||
item->SetBonuses(*bonusListIDs);
|
||||
|
||||
item->SetFixedLevel(GetLevel());
|
||||
item->SetItemRandomBonusList(randomBonusListId);
|
||||
item->SetCreatePlayedTime(GetTotalPlayedTime());
|
||||
|
||||
item = StoreItem(pos, item, update);
|
||||
|
||||
ItemAddedQuestCheck(itemId, count, false);
|
||||
UpdateCriteria(CriteriaType::ObtainAnyItem, itemId, count);
|
||||
UpdateCriteria(CriteriaType::AcquireItem, itemId, count);
|
||||
|
||||
item->SetFixedLevel(GetLevel());
|
||||
item->SetItemRandomBonusList(randomBonusListId);
|
||||
|
||||
if (allowedLooters.size() > 1 && item->GetTemplate()->GetMaxStackSize() == 1 && item->IsSoulBound())
|
||||
{
|
||||
item->SetSoulboundTradeable(allowedLooters);
|
||||
item->SetCreatePlayedTime(GetTotalPlayedTime());
|
||||
AddTradeableItem(item);
|
||||
|
||||
// save data
|
||||
@@ -18804,19 +18804,23 @@ void Player::_LoadInventory(PreparedQueryResult result, PreparedQueryResult arti
|
||||
PreparedQueryResult azeriteItemMilestonePowersResult, PreparedQueryResult azeriteItemUnlockedEssencesResult,
|
||||
PreparedQueryResult azeriteEmpoweredItemResult, uint32 timeDiff)
|
||||
{
|
||||
// 0 1 2 3 4 5 6 7 8 9 10 11 12
|
||||
// SELECT guid, itemEntry, creatorGuid, giftCreatorGuid, count, duration, charges, flags, enchantments, randomPropertyId, durability, playedTime, text,
|
||||
// 13 14 15 16 17 18
|
||||
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13
|
||||
// SELECT guid, itemEntry, creatorGuid, giftCreatorGuid, count, duration, charges, flags, enchantments, randomBonusListId, durability, playedTime, createTime, text,
|
||||
// 14 15 16 17 18 19
|
||||
// battlePetSpeciesId, battlePetBreedData, battlePetLevel, battlePetDisplayId, context, bonusListIDs,
|
||||
// 19 20 21 22 23
|
||||
// itemModifiedAppearanceAllSpecs, itemModifiedAppearanceSpec1, itemModifiedAppearanceSpec2, itemModifiedAppearanceSpec3, itemModifiedAppearanceSpec4,
|
||||
// 24 25 26 27 28
|
||||
// spellItemEnchantmentAllSpecs, spellItemEnchantmentSpec1, spellItemEnchantmentSpec2, spellItemEnchantmentSpec3, spellItemEnchantmentSpec4,
|
||||
// 29 30 31 32 33 34 35 36 37 38 39 40
|
||||
// 20 21 22 23 24 25
|
||||
// itemModifiedAppearanceAllSpecs, itemModifiedAppearanceSpec1, itemModifiedAppearanceSpec2, itemModifiedAppearanceSpec3, itemModifiedAppearanceSpec4, itemModifiedAppearanceSpec5,
|
||||
// 26 27 28 29 30 31
|
||||
// spellItemEnchantmentAllSpecs, spellItemEnchantmentSpec1, spellItemEnchantmentSpec2, spellItemEnchantmentSpec3, spellItemEnchantmentSpec4, spellItemEnchantmentSpec5,
|
||||
// 32 33 34
|
||||
// secondaryItemModifiedAppearanceAllSpecs, secondaryItemModifiedAppearanceSpec1, secondaryItemModifiedAppearanceSpec2,
|
||||
// 35 36 37
|
||||
// secondaryItemModifiedAppearanceSpec3, secondaryItemModifiedAppearanceSpec4, secondaryItemModifiedAppearanceSpec5,
|
||||
// 38 39 40 41 42 43 44 45 46 47 48 49
|
||||
// gemItemId1, gemBonuses1, gemContext1, gemScalingLevel1, gemItemId2, gemBonuses2, gemContext2, gemScalingLevel2, gemItemId3, gemBonuses3, gemContext3, gemScalingLevel3
|
||||
// 41 42
|
||||
// 50 51
|
||||
// fixedScalingLevel, artifactKnowledgeLevel FROM item_instance
|
||||
// 43 44
|
||||
// 52 53
|
||||
// bag, slot
|
||||
// FROM character_inventory ci
|
||||
// JOIN item_instance ii ON ci.item = ii.guid
|
||||
@@ -18867,8 +18871,8 @@ void Player::_LoadInventory(PreparedQueryResult result, PreparedQueryResult arti
|
||||
azeriteEmpoweredItem->LoadAzeriteEmpoweredItemData(this, *addionalDataPtr->AzeriteEmpoweredItem);
|
||||
}
|
||||
|
||||
ObjectGuid bagGuid = fields[51].GetUInt64() ? ObjectGuid::Create<HighGuid::Item>(fields[51].GetUInt64()) : ObjectGuid::Empty;
|
||||
uint8 slot = fields[52].GetUInt8();
|
||||
ObjectGuid bagGuid = fields[52].GetUInt64() ? ObjectGuid::Create<HighGuid::Item>(fields[52].GetUInt64()) : ObjectGuid::Empty;
|
||||
uint8 slot = fields[53].GetUInt8();
|
||||
|
||||
GetSession()->GetCollectionMgr()->CheckHeirloomUpgrades(item);
|
||||
GetSession()->GetCollectionMgr()->AddItemAppearance(item);
|
||||
@@ -19082,10 +19086,10 @@ Item* Player::_LoadItem(CharacterDatabaseTransaction trans, uint32 zoneId, uint3
|
||||
}
|
||||
else if (item->IsRefundable())
|
||||
{
|
||||
if (item->GetPlayedTime() > (2 * HOUR))
|
||||
if (item->IsRefundExpired())
|
||||
{
|
||||
TC_LOG_DEBUG("entities.player.loading", "Player::_LoadInventory: player ({}, name: '{}') has item ({}) with expired refund time ({}). Deleting refund data and removing refundable flag.",
|
||||
GetGUID().ToString(), GetName(), item->GetGUID().ToString(), item->GetPlayedTime());
|
||||
GetGUID().ToString(), GetName(), item->GetGUID().ToString(), GetTotalPlayedTime() - item->GetPlayedTime());
|
||||
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_REFUND_INSTANCE);
|
||||
stmt->setUInt64(0, item->GetGUID().GetCounter());
|
||||
@@ -19208,7 +19212,7 @@ Item* Player::_LoadMailedItem(ObjectGuid const& playerGuid, Player* player, uint
|
||||
|
||||
Item* item = NewItemOrBag(proto);
|
||||
|
||||
ObjectGuid ownerGuid = fields[51].GetUInt64() ? ObjectGuid::Create<HighGuid::Player>(fields[51].GetUInt64()) : ObjectGuid::Empty;
|
||||
ObjectGuid ownerGuid = fields[52].GetUInt64() ? ObjectGuid::Create<HighGuid::Player>(fields[52].GetUInt64()) : ObjectGuid::Empty;
|
||||
if (!item->LoadFromDB(itemGuid, ownerGuid, fields, itemEntry))
|
||||
{
|
||||
TC_LOG_ERROR("entities.player", "Player::_LoadMailedItems: Item (GUID: {}) in mail ({}) doesn't exist, deleted from mail.", itemGuid, mailId);
|
||||
@@ -19297,7 +19301,7 @@ void Player::_LoadMail(PreparedQueryResult mailsResult, PreparedQueryResult mail
|
||||
do
|
||||
{
|
||||
Field* fields = mailItemsResult->Fetch();
|
||||
uint64 mailId = fields[52].GetUInt64();
|
||||
uint64 mailId = fields[53].GetUInt64();
|
||||
_LoadMailedItem(GetGUID(), this, mailId, mailById[mailId], fields, Trinity::Containers::MapGetValuePtr(additionalData, fields[0].GetUInt64()));
|
||||
} while (mailItemsResult->NextRow());
|
||||
}
|
||||
@@ -20599,10 +20603,10 @@ void Player::_SaveInventory(CharacterDatabaseTransaction trans)
|
||||
i_next = itr;
|
||||
++i_next;
|
||||
|
||||
Item* iPtr = GetItemByGuid(*itr);
|
||||
if (iPtr)
|
||||
if (Item* iPtr = GetItemByGuid(*itr))
|
||||
{
|
||||
iPtr->UpdatePlayedTime(this);
|
||||
if (iPtr->IsRefundable() && iPtr->IsRefundExpired())
|
||||
iPtr->SetNotRefundable(this);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
@@ -28609,8 +28613,8 @@ void Player::DeleteRefundReference(ObjectGuid it)
|
||||
|
||||
void Player::SendRefundInfo(Item* item)
|
||||
{
|
||||
// This function call unsets ITEM_FIELD_FLAG_REFUNDABLE if played time is over 2 hours.
|
||||
item->UpdatePlayedTime(this);
|
||||
if (item->IsRefundable() && item->IsRefundExpired())
|
||||
item->SetNotRefundable(this);
|
||||
|
||||
if (!item->IsRefundable())
|
||||
{
|
||||
@@ -28634,7 +28638,7 @@ void Player::SendRefundInfo(Item* item)
|
||||
|
||||
WorldPackets::Item::SetItemPurchaseData setItemPurchaseData;
|
||||
setItemPurchaseData.ItemGUID = item->GetGUID();
|
||||
setItemPurchaseData.PurchaseTime = GetTotalPlayedTime() - item->GetPlayedTime();
|
||||
setItemPurchaseData.PurchaseTime = item->m_itemData->CreatePlayedTime;
|
||||
setItemPurchaseData.Contents.Money = item->GetPaidMoney();
|
||||
|
||||
for (uint8 i = 0; i < MAX_ITEM_EXT_COST_ITEMS; ++i) // item cost data
|
||||
|
||||
@@ -377,7 +377,7 @@ void Guild::BankTab::LoadFromDB(Field* fields)
|
||||
|
||||
bool Guild::BankTab::LoadItemFromDB(Field* fields)
|
||||
{
|
||||
uint8 slotId = fields[53].GetUInt8();
|
||||
uint8 slotId = fields[54].GetUInt8();
|
||||
ObjectGuid::LowType itemGuid = fields[0].GetUInt64();
|
||||
uint32 itemEntry = fields[1].GetUInt32();
|
||||
if (slotId >= GUILD_BANK_MAX_SLOTS)
|
||||
@@ -2642,7 +2642,7 @@ void Guild::LoadBankTabFromDB(Field* fields)
|
||||
|
||||
bool Guild::LoadBankItemFromDB(Field* fields)
|
||||
{
|
||||
uint8 tabId = fields[52].GetUInt8();
|
||||
uint8 tabId = fields[53].GetUInt8();
|
||||
if (tabId >= _GetPurchasedTabsSize())
|
||||
{
|
||||
TC_LOG_ERROR("guild", "Invalid tab for item (GUID: {}, id: #{}) in guild bank, skipped.",
|
||||
|
||||
@@ -401,23 +401,23 @@ void GuildMgr::LoadGuilds()
|
||||
// Delete orphan guild bank items
|
||||
CharacterDatabase.DirectExecute("DELETE gbi FROM guild_bank_item gbi LEFT JOIN guild g ON gbi.guildId = g.guildId WHERE g.guildId IS NULL");
|
||||
|
||||
// 0 1 2 3 4 5 6 7 8 9 10 11 12
|
||||
// SELECT guid, itemEntry, creatorGuid, giftCreatorGuid, count, duration, charges, flags, enchantments, randomBonusListId, durability, playedTime, text,
|
||||
// 13 14 15 16 17 18
|
||||
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13
|
||||
// SELECT guid, itemEntry, creatorGuid, giftCreatorGuid, count, duration, charges, flags, enchantments, randomBonusListId, durability, playedTime, createTime, text,
|
||||
// 14 15 16 17 18 19
|
||||
// battlePetSpeciesId, battlePetBreedData, battlePetLevel, battlePetDisplayId, context, bonusListIDs,
|
||||
// 19 20 21 22 23 24
|
||||
// 20 21 22 23 24 25
|
||||
// itemModifiedAppearanceAllSpecs, itemModifiedAppearanceSpec1, itemModifiedAppearanceSpec2, itemModifiedAppearanceSpec3, itemModifiedAppearanceSpec4, itemModifiedAppearanceSpec5,
|
||||
// 25 26 27 28 29 30
|
||||
// 26 27 28 29 30 31
|
||||
// spellItemEnchantmentAllSpecs, spellItemEnchantmentSpec1, spellItemEnchantmentSpec2, spellItemEnchantmentSpec3, spellItemEnchantmentSpec4, spellItemEnchantmentSpec5,
|
||||
// 31 32 33
|
||||
// 32 33 34
|
||||
// secondaryItemModifiedAppearanceAllSpecs, secondaryItemModifiedAppearanceSpec1, secondaryItemModifiedAppearanceSpec2,
|
||||
// 34 35 36
|
||||
// 35 36 37
|
||||
// secondaryItemModifiedAppearanceSpec3, secondaryItemModifiedAppearanceSpec4, secondaryItemModifiedAppearanceSpec5,
|
||||
// 37 38 39 40 41 42 43 44 45 46 47 48
|
||||
// 38 39 40 41 42 43 44 45 46 47 48 49
|
||||
// gemItemId1, gemBonuses1, gemContext1, gemScalingLevel1, gemItemId2, gemBonuses2, gemContext2, gemScalingLevel2, gemItemId3, gemBonuses3, gemContext3, gemScalingLevel3
|
||||
// 49 50
|
||||
// 50 51
|
||||
// fixedScalingLevel, artifactKnowledgeLevel
|
||||
// 51 52 53
|
||||
// 52 53 54
|
||||
// guildid, TabId, SlotId FROM guild_bank_item gbi INNER JOIN item_instance ii ON gbi.item_guid = ii.guid
|
||||
|
||||
PreparedQueryResult result = CharacterDatabase.Query(CharacterDatabase.GetPreparedStatement(CHAR_SEL_GUILD_BANK_ITEMS));
|
||||
@@ -431,7 +431,7 @@ void GuildMgr::LoadGuilds()
|
||||
do
|
||||
{
|
||||
Field* fields = result->Fetch();
|
||||
uint64 guildId = fields[51].GetUInt64();
|
||||
uint64 guildId = fields[52].GetUInt64();
|
||||
|
||||
if (Guild* guild = GetGuildById(guildId))
|
||||
guild->LoadBankItemFromDB(fields);
|
||||
|
||||
@@ -134,7 +134,7 @@ void WorldSession::moveItems(Item* myItems[], Item* hisItems[])
|
||||
}
|
||||
|
||||
// adjust time (depends on /played)
|
||||
if (myItems[i]->IsBOPTradeable())
|
||||
if (*myItems[i]->m_itemData->CreatePlayedTime)
|
||||
myItems[i]->SetCreatePlayedTime(trader->GetTotalPlayedTime() - (_player->GetTotalPlayedTime() - myItems[i]->m_itemData->CreatePlayedTime));
|
||||
// store
|
||||
trader->MoveItemToInventory(traderDst, myItems[i], true, true);
|
||||
@@ -152,7 +152,7 @@ void WorldSession::moveItems(Item* myItems[], Item* hisItems[])
|
||||
}
|
||||
|
||||
// adjust time (depends on /played)
|
||||
if (hisItems[i]->IsBOPTradeable())
|
||||
if (*hisItems[i]->m_itemData->CreatePlayedTime)
|
||||
hisItems[i]->SetCreatePlayedTime(_player->GetTotalPlayedTime() - (trader->GetTotalPlayedTime() - hisItems[i]->m_itemData->CreatePlayedTime));
|
||||
// store
|
||||
_player->MoveItemToInventory(playerDst, hisItems[i], true, true);
|
||||
|
||||
Reference in New Issue
Block a user