diff --git a/sql/mangos.sql b/sql/mangos.sql index f1e22a6ac..8c1e03d73 100644 --- a/sql/mangos.sql +++ b/sql/mangos.sql @@ -24,7 +24,7 @@ CREATE TABLE `db_version` ( `version` varchar(120) default NULL, `creature_ai_version` varchar(120) default NULL, `cache_id` int(10) default '0', - `required_9622_01_mangos_gameobject` bit(1) default NULL + `required_9636_01_mangos_item_template` bit(1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; -- @@ -2252,7 +2252,7 @@ CREATE TABLE `item_template` ( `GemProperties` mediumint(9) NOT NULL default '0', `RequiredDisenchantSkill` smallint(6) NOT NULL default '-1', `ArmorDamageModifier` float NOT NULL default '0', - `Duration` int(11) NOT NULL default '0' COMMENT 'Duration in seconds. Negative value means realtime, postive value ingame time', + `Duration` int(11) UNSIGNED DEFAULT '0' NOT NULL COMMENT 'Duration in seconds.', `ItemLimitCategory` smallint(6) NOT NULL default '0', `HolidayId` int(11) UNSIGNED DEFAULT '0' NOT NULL, `ScriptName` varchar(64) NOT NULL default '', diff --git a/sql/updates/9636_01_mangos_item_template.sql b/sql/updates/9636_01_mangos_item_template.sql new file mode 100644 index 000000000..cf72ec433 --- /dev/null +++ b/sql/updates/9636_01_mangos_item_template.sql @@ -0,0 +1,14 @@ +ALTER TABLE db_version CHANGE COLUMN required_9622_01_mangos_gameobject required_9636_01_mangos_item_template bit; + +ALTER TABLE item_template + CHANGE COLUMN NonConsumable ExtraFlags tinyint(1) UNSIGNED DEFAULT '0' NOT NULL; + +UPDATE item_template + SET ExtraFlags = ExtraFlags | 0x2 WHERE Duration < 0 ; + +UPDATE item_template + SET Duration = abs(Duration); + +ALTER TABLE item_template + CHANGE COLUMN Duration Duration int(11) UNSIGNED DEFAULT '0' NOT NULL; + diff --git a/sql/updates/Makefile.am b/sql/updates/Makefile.am index e43e04a01..a8f63ee8f 100644 --- a/sql/updates/Makefile.am +++ b/sql/updates/Makefile.am @@ -95,6 +95,7 @@ pkgdata_DATA = \ 9632_01_characters_characters.sql \ 9634_01_characters_corpse.sql \ 9635_01_characters_characters.sql \ + 9636_01_mangos_item_template.sql \ README ## Additional files to include when running 'make dist' @@ -170,4 +171,5 @@ EXTRA_DIST = \ 9632_01_characters_characters.sql \ 9634_01_characters_corpse.sql \ 9635_01_characters_characters.sql \ + 9636_01_mangos_item_template.sql \ README diff --git a/src/game/Item.cpp b/src/game/Item.cpp index 235f4a54b..94f344cf9 100644 --- a/src/game/Item.cpp +++ b/src/game/Item.cpp @@ -268,7 +268,7 @@ bool Item::Create( uint32 guidlow, uint32 itemid, Player const* owner) SetSpellCharges(i,itemProto->Spells[i].SpellCharges); SetUInt32Value(ITEM_FIELD_FLAGS, itemProto->Flags); - SetUInt32Value(ITEM_FIELD_DURATION, abs(itemProto->Duration)); + SetUInt32Value(ITEM_FIELD_DURATION, itemProto->Duration); return true; } @@ -403,20 +403,20 @@ bool Item::LoadFromDB(uint32 guid, uint64 owner_guid, QueryResult *result) } // update duration if need, and remove if not need - if((proto->Duration==0) != (GetUInt32Value(ITEM_FIELD_DURATION)==0)) + if ((proto->Duration == 0) != (GetUInt32Value(ITEM_FIELD_DURATION) == 0)) { - SetUInt32Value(ITEM_FIELD_DURATION,abs(proto->Duration)); + SetUInt32Value(ITEM_FIELD_DURATION, proto->Duration); need_save = true; } // set correct owner - if(owner_guid != 0 && GetOwnerGUID() != owner_guid) + if (owner_guid != 0 && GetOwnerGUID() != owner_guid) { SetOwnerGUID(owner_guid); need_save = true; } - if(need_save) // normal item changed state set not work at loading + if (need_save) // normal item changed state set not work at loading { std::ostringstream ss; ss << "UPDATE item_instance SET data = '"; diff --git a/src/game/ItemHandler.cpp b/src/game/ItemHandler.cpp index 19b2c13cc..ee099ee8b 100644 --- a/src/game/ItemHandler.cpp +++ b/src/game/ItemHandler.cpp @@ -418,7 +418,7 @@ void WorldSession::HandleItemQuerySingleOpcode( WorldPacket & recv_data ) data << pProto->GemProperties; data << pProto->RequiredDisenchantSkill; data << pProto->ArmorDamageModifier; - data << abs(pProto->Duration); // added in 2.4.2.8209, duration (seconds) + data << pProto->Duration; // added in 2.4.2.8209, duration (seconds) data << pProto->ItemLimitCategory; // WotLK, ItemLimitCategory data << pProto->HolidayId; // Holiday.dbc? SendPacket( &data ); diff --git a/src/game/ItemPrototype.h b/src/game/ItemPrototype.h index 4ee283117..ade69fb2b 100644 --- a/src/game/ItemPrototype.h +++ b/src/game/ItemPrototype.h @@ -469,6 +469,14 @@ inline uint8 ItemSubClassToDurabilityMultiplierId(uint32 ItemClass, uint32 ItemS return 0; } +enum ItemExtraFlags +{ + ITEM_EXTRA_NON_CONSUMABLE = 0x01, // use as additional flag to spellcharges_N negative values, item not expire at no chanrges + ITEM_EXTRA_REAL_TIME_DURATION = 0x02, // if set and have Duration time, then offline time included in counting, if not set then counted only in game time + + ITEM_EXTRA_ALL // all used flags, used for check DB data +}; + // GCC have alternative #pragma pack(N) syntax and old gcc version not support pack(push,N), also any gcc version not support it at some platform #if defined( __GNUC__ ) #pragma pack(1) @@ -578,7 +586,7 @@ struct ItemPrototype uint32 GemProperties; // id from GemProperties.dbc uint32 RequiredDisenchantSkill; float ArmorDamageModifier; - int32 Duration; // negative = realtime, positive = ingame time + uint32 Duration; // negative = realtime, positive = ingame time uint32 ItemLimitCategory; // id from ItemLimitCategory.dbc uint32 HolidayId; // id from Holidays.dbc uint32 ScriptId; @@ -586,7 +594,7 @@ struct ItemPrototype uint32 FoodType; uint32 MinMoneyLoot; uint32 MaxMoneyLoot; - uint32 NonConsumable; + uint32 ExtraFlags; // see ItemExtraFlags // helpers bool CanChangeEquipStateInCombat() const diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index aef5ab270..1fd0c16c9 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -2072,28 +2072,37 @@ void ObjectMgr::LoadItemPrototypes() const_cast(proto)->HolidayId = 0; } - if(proto->NonConsumable) + if(proto->ExtraFlags) { - if (proto->NonConsumable > 1) - { - sLog.outErrorDb("Item (Entry: %u) has wrong NonConsumable (%u), must be 0..1",i,proto->NonConsumable); - const_cast(proto)->NonConsumable = 1; - } + if (proto->ExtraFlags & ~ITEM_EXTRA_ALL) + sLog.outErrorDb("Item (Entry: %u) has wrong ExtraFlags (%u) with unused bits set",i,proto->ExtraFlags); - bool can_be_need = false; - for (int j = 0; j < MAX_ITEM_PROTO_SPELLS; ++j) + if (proto->ExtraFlags & ITEM_EXTRA_NON_CONSUMABLE) { - if(proto->Spells[j].SpellCharges < 0) + bool can_be_need = false; + for (int j = 0; j < MAX_ITEM_PROTO_SPELLS; ++j) { - can_be_need = true; - break; + if(proto->Spells[j].SpellCharges < 0) + { + can_be_need = true; + break; + } + } + + if (!can_be_need) + { + sLog.outErrorDb("Item (Entry: %u) has redundant non-consumable flag in ExtraFlags, item not have negative charges", i); + const_cast(proto)->ExtraFlags &= ~ITEM_EXTRA_NON_CONSUMABLE; } } - if (!can_be_need) + if (proto->ExtraFlags & ITEM_EXTRA_REAL_TIME_DURATION) { - sLog.outErrorDb("Item (Entry: %u) has redundant NonConsumable (%u), item not have negative charges",i,proto->NonConsumable); - const_cast(proto)->NonConsumable = 0; + if (proto->Duration == 0) + { + sLog.outErrorDb("Item (Entry: %u) has redundant real-time duration flag in ExtraFlags, item not have duration", i); + const_cast(proto)->ExtraFlags &= ~ITEM_EXTRA_REAL_TIME_DURATION; + } } } } diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 6eae83bd5..6ca2a8691 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -11863,7 +11863,7 @@ void Player::UpdateItemDuration(uint32 time, bool realtimeonly) Item* item = *itr; ++itr; // current element can be erased in UpdateDuration - if ((realtimeonly && item->GetProto()->Duration < 0) || !realtimeonly) + if ((realtimeonly && (item->GetProto()->ExtraFlags & ITEM_EXTRA_REAL_TIME_DURATION)) || !realtimeonly) item->UpdateDuration(this,time); } } diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index fc429ca49..10d1c5f13 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -3650,7 +3650,7 @@ void Spell::TakeCastItem() // item has limited charges if (proto->Spells[i].SpellCharges) { - if (proto->Spells[i].SpellCharges < 0 && !proto->NonConsumable) + if (proto->Spells[i].SpellCharges < 0 && !(proto->ExtraFlags & ITEM_EXTRA_NON_CONSUMABLE)) expendable = true; int32 charges = m_CastItem->GetSpellCharges(i); @@ -5557,7 +5557,7 @@ SpellCastResult Spell::CheckItems() { // CastItem will be used up and does not count as reagent int32 charges = m_CastItem->GetSpellCharges(s); - if (proto->Spells[s].SpellCharges < 0 && !proto->NonConsumable && abs(charges) < 2) + if (proto->Spells[s].SpellCharges < 0 && !(proto->ExtraFlags & ITEM_EXTRA_NON_CONSUMABLE) && abs(charges) < 2) { ++itemcount; break; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index cec523f42..551cabe0b 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "9635" + #define REVISION_NR "9636" #endif // __REVISION_NR_H__ diff --git a/src/shared/revision_sql.h b/src/shared/revision_sql.h index 0180f132e..ab52b04fa 100644 --- a/src/shared/revision_sql.h +++ b/src/shared/revision_sql.h @@ -1,6 +1,6 @@ #ifndef __REVISION_SQL_H__ #define __REVISION_SQL_H__ #define REVISION_DB_CHARACTERS "required_9635_01_characters_characters" - #define REVISION_DB_MANGOS "required_9622_01_mangos_gameobject" + #define REVISION_DB_MANGOS "required_9636_01_mangos_item_template" #define REVISION_DB_REALMD "required_9010_01_realmd_realmlist" #endif // __REVISION_SQL_H__