aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormegamage <none@none>2009-06-08 17:25:02 -0500
committermegamage <none@none>2009-06-08 17:25:02 -0500
commit4e130dcdfdd30b84fb5e0b0531c817c7b6c64ff9 (patch)
tree09f871f8eab58afe981e99fa74cef6bcf0777e7c
parent6578cce47133eb017a7ab6b14c91d6c5b80b226a (diff)
[7980] Implement item use target requirements store and check (new table `item_required_target`). Author: NoFantasy
Signed-off-by: VladimirMangos <vladimir@getmangos.com> * Also implement this table reload * Static Spell::SendCastResult function for call not from spell code. Can be also used in scripts where need send explicitly spell cast error to client. --HG-- branch : trunk
-rw-r--r--sql/mangos.sql23
-rw-r--r--sql/updates/3870_mangos_7980_01_world_item_required_target.sql9
-rw-r--r--src/game/Chat.cpp1
-rw-r--r--src/game/Chat.h1
-rw-r--r--src/game/Debugcmds.cpp7
-rw-r--r--src/game/Item.cpp30
-rw-r--r--src/game/Item.h21
-rw-r--r--src/game/Level3.cpp9
-rw-r--r--src/game/ObjectMgr.cpp100
-rw-r--r--src/game/ObjectMgr.h11
-rw-r--r--src/game/PetHandler.cpp14
-rw-r--r--src/game/Spell.cpp40
-rw-r--r--src/game/Spell.h1
-rw-r--r--src/game/SpellHandler.cpp22
-rw-r--r--src/game/World.cpp3
15 files changed, 257 insertions, 35 deletions
diff --git a/sql/mangos.sql b/sql/mangos.sql
index 346495436d3..5ff29d24fb4 100644
--- a/sql/mangos.sql
+++ b/sql/mangos.sql
@@ -23,7 +23,7 @@ DROP TABLE IF EXISTS `db_version`;
CREATE TABLE `db_version` (
`version` varchar(120) default NULL,
`creature_ai_version` varchar(120) default NULL,
- `required_7945_01_mangos_quest_template` bit(1) default NULL
+ `required_7980_01_mangos_item_required_target` bit(1) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes';
--
@@ -1659,6 +1659,27 @@ LOCK TABLES `item_loot_template` WRITE;
UNLOCK TABLES;
--
+-- Table structure for table `item_required_target`
+--
+
+DROP TABLE IF EXISTS `item_required_target`;
+CREATE TABLE `item_required_target` (
+ `entry` mediumint(8) unsigned NOT NULL,
+ `type` tinyint(3) unsigned NOT NULL default '0',
+ `targetEntry` mediumint(8) unsigned NOT NULL default '0',
+ UNIQUE KEY `entry_type_target` (`entry`,`type`,`targetEntry`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED
+
+--
+-- Dumping data for table `item_required_target`
+--
+
+LOCK TABLES `item_required_target` WRITE;
+/*!40000 ALTER TABLE `item_required_target` DISABLE KEYS */;
+/*!40000 ALTER TABLE `item_required_target` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
-- Table structure for table `item_template`
--
diff --git a/sql/updates/3870_mangos_7980_01_world_item_required_target.sql b/sql/updates/3870_mangos_7980_01_world_item_required_target.sql
new file mode 100644
index 00000000000..99ff65a5357
--- /dev/null
+++ b/sql/updates/3870_mangos_7980_01_world_item_required_target.sql
@@ -0,0 +1,9 @@
+-- ALTER TABLE db_version CHANGE COLUMN required_7945_01_mangos_quest_template required_7980_01_mangos_item_required_target bit;
+
+DROP TABLE IF EXISTS `item_required_target`;
+CREATE TABLE `item_required_target` (
+ `entry` mediumint(8) unsigned NOT NULL,
+ `type` tinyint(3) unsigned NOT NULL default '0',
+ `targetEntry` mediumint(8) unsigned NOT NULL default '0',
+ UNIQUE KEY `entry_type_target` (`entry`,`type`,`targetEntry`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED
diff --git a/src/game/Chat.cpp b/src/game/Chat.cpp
index 1722fd9602c..527406a76d1 100644
--- a/src/game/Chat.cpp
+++ b/src/game/Chat.cpp
@@ -447,6 +447,7 @@ ChatCommand * ChatHandler::getCommandTable()
{ "gameobject_scripts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadGameObjectScriptsCommand, "", NULL },
{ "item_enchantment_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadItemEnchantementsCommand, "", NULL },
{ "item_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesItemCommand, "", NULL },
+ { "item_required_target", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadItemRequiredTragetCommand, "", NULL },
{ "locales_achievement_reward", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLocalesAchievementRewardCommand,"", NULL },
{ "locales_creature", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLocalesCreatureCommand, "", NULL },
{ "locales_gameobject", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLocalesGameobjectCommand, "", NULL },
diff --git a/src/game/Chat.h b/src/game/Chat.h
index 0b8b076969b..6fbc9b30d34 100644
--- a/src/game/Chat.h
+++ b/src/game/Chat.h
@@ -359,6 +359,7 @@ class ChatHandler
bool HandleReloadGOQuestRelationsCommand(const char* args);
bool HandleReloadGOQuestInvRelationsCommand(const char* args);
bool HandleReloadItemEnchantementsCommand(const char* args);
+ bool HandleReloadItemRequiredTragetCommand(const char* args);
bool HandleReloadLocalesAchievementRewardCommand(const char* args);
bool HandleReloadLocalesCreatureCommand(const char* args);
bool HandleReloadLocalesGameobjectCommand(const char* args);
diff --git a/src/game/Debugcmds.cpp b/src/game/Debugcmds.cpp
index 196816fff02..2e432ab1c0f 100644
--- a/src/game/Debugcmds.cpp
+++ b/src/game/Debugcmds.cpp
@@ -43,7 +43,7 @@ bool ChatHandler::HandleDebugSendSpellFailCommand(const char* args)
return false;
char* px = strtok((char*)args, " ");
- if(!px)
+ if (!px)
return false;
uint8 failnum = (uint8)atoi(px);
@@ -56,14 +56,13 @@ bool ChatHandler::HandleDebugSendSpellFailCommand(const char* args)
char* p2 = strtok(NULL, " ");
uint8 failarg2 = p2 ? (uint8)atoi(p2) : 0;
-
WorldPacket data(SMSG_CAST_FAILED, 5);
data << uint8(0);
data << uint32(133);
data << uint8(failnum);
- if(p1 || p2)
+ if (p1 || p2)
data << uint32(failarg1);
- if(p2)
+ if (p2)
data << uint32(failarg2);
m_session->SendPacket(&data);
diff --git a/src/game/Item.cpp b/src/game/Item.cpp
index 36ddcd16828..06268f2fef7 100644
--- a/src/game/Item.cpp
+++ b/src/game/Item.cpp
@@ -776,6 +776,23 @@ bool Item::IsFitToSpellRequirements(SpellEntry const* spellInfo) const
return true;
}
+bool Item::IsTargetValidForItemUse(Unit* pUnitTarget)
+{
+ ItemRequiredTargetMapBounds bounds = objmgr.GetItemRequiredTargetMapBounds(GetProto()->ItemId);
+
+ if (bounds.first == bounds.second)
+ return true;
+
+ if (!pUnitTarget)
+ return false;
+
+ for(ItemRequiredTargetMap::const_iterator itr = bounds.first; itr != bounds.second; ++itr)
+ if(itr->second.IsFitToRequirements(pUnitTarget))
+ return true;
+
+ return false;
+}
+
void Item::SetEnchantment(EnchantmentSlot slot, uint32 id, uint32 duration, uint32 charges)
{
// Better lost small time at check in comparison lost time at item save to DB.
@@ -982,3 +999,16 @@ bool Item::IsBindedNotWith( Player const* player ) const
return objmgr.GetPlayerAccountIdByGUID(GetOwnerGUID()) != player->GetSession()->GetAccountId();
}
}
+
+bool ItemRequiredTarget::IsFitToRequirements( Unit* pUnitTarget ) const
+{
+ switch(m_uiType)
+ {
+ case ITEM_TARGET_TYPE_CREATURE:
+ return pUnitTarget->isAlive();
+ case ITEM_TARGET_TYPE_DEAD:
+ return !pUnitTarget->isAlive();
+ default:
+ return false;
+ }
+}
diff --git a/src/game/Item.h b/src/game/Item.h
index 30cf1a595cb..9cae8f67105 100644
--- a/src/game/Item.h
+++ b/src/game/Item.h
@@ -29,6 +29,7 @@
struct SpellEntry;
class Bag;
class QueryResult;
+class Unit;
struct ItemSetEffect
{
@@ -197,6 +198,24 @@ enum ItemUpdateState
ITEM_REMOVED = 3
};
+enum ItemRequiredTargetType
+{
+ ITEM_TARGET_TYPE_CREATURE = 1,
+ ITEM_TARGET_TYPE_DEAD = 2
+};
+
+#define MAX_ITEM_REQ_TARGET_TYPE 2
+
+struct ItemRequiredTarget
+{
+ ItemRequiredTarget(ItemRequiredTargetType uiType, uint32 uiTargetEntry) : m_uiType(uiType), m_uiTargetEntry(uiTargetEntry) {}
+ ItemRequiredTargetType m_uiType;
+ uint32 m_uiTargetEntry;
+
+ // helpers
+ bool IsFitToRequirements(Unit* pUnitTarget) const;
+};
+
bool ItemCanGoIntoBag(ItemPrototype const *proto, ItemPrototype const *pBagProto);
class TRINITY_DLL_SPEC Item : public Object
@@ -232,6 +251,7 @@ class TRINITY_DLL_SPEC Item : public Object
bool IsInTrade() const { return mb_in_trade; }
bool IsFitToSpellRequirements(SpellEntry const* spellInfo) const;
+ bool IsTargetValidForItemUse(Unit* pUnitTarget);
bool IsLimitedToAnotherMapOrZone( uint32 cur_mapId, uint32 cur_zoneId) const;
bool GemsFitSockets() const;
@@ -296,6 +316,7 @@ class TRINITY_DLL_SPEC Item : public Object
bool IsWeaponVellum() const { return GetProto()->IsWeaponVellum(); }
bool IsArmorVellum() const { return GetProto()->IsArmorVellum(); }
bool IsConjuredConsumable() const { return GetProto()->IsConjuredConsumable(); }
+
private:
uint8 m_slot;
Bag *m_container;
diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp
index fe8cca2da4b..77c81144d48 100644
--- a/src/game/Level3.cpp
+++ b/src/game/Level3.cpp
@@ -668,6 +668,7 @@ bool ChatHandler::HandleReloadAllItemCommand(const char*)
{
HandleReloadPageTextsCommand("a");
HandleReloadItemEnchantementsCommand("a");
+ HandleReloadItemRequiredTragetCommand("a");
return true;
}
@@ -1107,6 +1108,14 @@ bool ChatHandler::HandleReloadItemEnchantementsCommand(const char*)
return true;
}
+bool ChatHandler::HandleReloadItemRequiredTragetCommand(const char*)
+{
+ sLog.outString( "Re-Loading Item Required Targets Table..." );
+ objmgr.LoadItemRequiredTarget();
+ SendGlobalSysMessage("DB table `item_required_target` reloaded.");
+ return true;
+}
+
bool ChatHandler::HandleReloadGameObjectScriptsCommand(const char* arg)
{
if(sWorld.IsScriptScheduled())
diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp
index 8c0e5d6e1bd..350bf5d3a15 100644
--- a/src/game/ObjectMgr.cpp
+++ b/src/game/ObjectMgr.cpp
@@ -2117,6 +2117,106 @@ void ObjectMgr::LoadItemPrototypes()
}
}
+void ObjectMgr::LoadItemRequiredTarget()
+{
+ m_ItemRequiredTarget.clear(); // needed for reload case
+
+ uint32 count = 0;
+
+ QueryResult *result = WorldDatabase.Query("SELECT entry,type,targetEntry FROM item_required_target");
+
+ if (!result)
+ {
+ barGoLink bar(1);
+
+ bar.step();
+
+ sLog.outString();
+ sLog.outErrorDb(">> Loaded 0 ItemRequiredTarget. DB table `item_required_target` is empty.");
+ return;
+ }
+
+ barGoLink bar(result->GetRowCount());
+
+ do
+ {
+ Field *fields = result->Fetch();
+ bar.step();
+
+ uint32 uiItemId = fields[0].GetUInt32();
+ uint32 uiType = fields[1].GetUInt32();
+ uint32 uiTargetEntry = fields[2].GetUInt32();
+
+ ItemPrototype const* pItemProto = sItemStorage.LookupEntry<ItemPrototype>(uiItemId);
+
+ if (!pItemProto)
+ {
+ sLog.outErrorDb("Table `item_required_target`: Entry %u listed for TargetEntry %u does not exist in `item_template`.",uiItemId,uiTargetEntry);
+ continue;
+ }
+
+ bool bIsItemSpellValid = false;
+
+ for(int i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i)
+ {
+ if (SpellEntry const* pSpellInfo = sSpellStore.LookupEntry(pItemProto->Spells[i].SpellId))
+ {
+ if (pItemProto->Spells[i].SpellTrigger == ITEM_SPELLTRIGGER_ON_USE ||
+ pItemProto->Spells[i].SpellTrigger == ITEM_SPELLTRIGGER_ON_NO_DELAY_USE)
+ {
+ SpellScriptTarget::const_iterator lower = spellmgr.GetBeginSpellScriptTarget(pSpellInfo->Id);
+ SpellScriptTarget::const_iterator upper = spellmgr.GetEndSpellScriptTarget(pSpellInfo->Id);
+
+ if (lower != upper)
+ break;
+
+ if (pSpellInfo->EffectImplicitTargetA[i] == TARGET_UNIT_TARGET_ENEMY ||
+ pSpellInfo->EffectImplicitTargetB[i] == TARGET_UNIT_TARGET_ENEMY ||
+ pSpellInfo->EffectImplicitTargetA[i] == TARGET_UNIT_TARGET_ANY ||
+ pSpellInfo->EffectImplicitTargetB[i] == TARGET_UNIT_TARGET_ANY)
+ {
+ bIsItemSpellValid = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if (!bIsItemSpellValid)
+ {
+ sLog.outErrorDb("Table `item_required_target`: Spell used by item %u does not have implicit target TARGET_CHAIN_DAMAGE(6), TARGET_DUELVSPLAYER(25), already listed in `spell_script_target` or doesn't have item spelltrigger.",uiItemId);
+ continue;
+ }
+
+ if (!uiType || uiType > MAX_ITEM_REQ_TARGET_TYPE)
+ {
+ sLog.outErrorDb("Table `item_required_target`: Type %u for TargetEntry %u is incorrect.",uiType,uiTargetEntry);
+ continue;
+ }
+
+ if (!uiTargetEntry)
+ {
+ sLog.outErrorDb("Table `item_required_target`: TargetEntry == 0 for Type (%u).",uiType);
+ continue;
+ }
+
+ if (!sCreatureStorage.LookupEntry<CreatureInfo>(uiTargetEntry))
+ {
+ sLog.outErrorDb("Table `item_required_target`: creature template entry %u does not exist.",uiTargetEntry);
+ continue;
+ }
+
+ m_ItemRequiredTarget.insert(ItemRequiredTargetMap::value_type(uiItemId,ItemRequiredTarget(ItemRequiredTargetType(uiType),uiTargetEntry)));
+
+ ++count;
+ } while (result->NextRow());
+
+ delete result;
+
+ sLog.outString();
+ sLog.outString(">> Loaded %u Item required targets", count);
+}
+
void ObjectMgr::LoadPetLevelInfo()
{
// Loading levels data
diff --git a/src/game/ObjectMgr.h b/src/game/ObjectMgr.h
index ae1222cccfb..b8d282569f1 100644
--- a/src/game/ObjectMgr.h
+++ b/src/game/ObjectMgr.h
@@ -160,6 +160,8 @@ typedef UNORDERED_MAP<uint32,NpcOptionLocale> NpcOptionLocaleMap;
typedef UNORDERED_MAP<uint32,PointOfInterestLocale> PointOfInterestLocaleMap;
typedef std::multimap<uint32,uint32> QuestRelations;
+typedef std::multimap<uint32,ItemRequiredTarget> ItemRequiredTargetMap;
+typedef std::pair<ItemRequiredTargetMap::const_iterator, ItemRequiredTargetMap::const_iterator> ItemRequiredTargetMapBounds;
struct PetLevelInfo
{
@@ -534,6 +536,7 @@ class ObjectMgr
void LoadGameobjects();
void LoadGameobjectRespawnTimes();
void LoadItemPrototypes();
+ void LoadItemRequiredTarget();
void LoadItemLocales();
void LoadQuestLocales();
void LoadNpcTextLocales();
@@ -805,6 +808,12 @@ class ObjectMgr
uint32 GetScriptId(const char *name);
int GetOrNewIndexForLocale(LocaleConstant loc);
+
+ ItemRequiredTargetMapBounds GetItemRequiredTargetMapBounds(uint32 uiItemEntry) const
+ {
+ return ItemRequiredTargetMapBounds(m_ItemRequiredTarget.lower_bound(uiItemEntry),m_ItemRequiredTarget.upper_bound(uiItemEntry));
+ }
+
protected:
// first free id for selected id type
@@ -867,6 +876,8 @@ class ObjectMgr
ScriptNameMap m_scriptNames;
+ ItemRequiredTargetMap m_ItemRequiredTarget;
+
typedef std::vector<LocaleConstant> LocalForIndex;
LocalForIndex m_LocalForIndex;
diff --git a/src/game/PetHandler.cpp b/src/game/PetHandler.cpp
index 87c667f1e77..7547d125d9c 100644
--- a/src/game/PetHandler.cpp
+++ b/src/game/PetHandler.cpp
@@ -286,19 +286,7 @@ void WorldSession::HandlePetActionHelper(Unit *pet, uint64 guid1, uint16 spellid
else
{
if(pet->isPossessed())
- {
- WorldPacket data(SMSG_CAST_FAILED, (4+1+1));
- data << uint8(0) << uint32(spellid) << uint8(result);
- switch (result)
- {
- case SPELL_FAILED_REQUIRES_SPELL_FOCUS:
- data << uint32(spellInfo->RequiresSpellFocus);
- break;
- default:
- break;
- }
- SendPacket(&data);
- }
+ Spell::SendCastResult(GetPlayer(),spellInfo,0,result);
else
pet->SendPetCastFail(spellid, result);
diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp
index ebb3a355a95..8d9cf6e5265 100644
--- a/src/game/Spell.cpp
+++ b/src/game/Spell.cpp
@@ -3125,18 +3125,26 @@ void Spell::SendCastResult(SpellCastResult result)
if(((Player*)m_caster)->GetSession()->PlayerLoading()) // don't send cast results at loading time
return;
+ SendCastResult((Player*)m_caster,m_spellInfo,m_cast_count,result);
+}
+
+void Spell::SendCastResult(Player* caster, SpellEntry const* spellInfo, uint8 cast_count, SpellCastResult result)
+{
+ if(result == SPELL_CAST_OK)
+ return;
+
WorldPacket data(SMSG_CAST_FAILED, (4+1+1));
- data << uint8(m_cast_count); // single cast or multi 2.3 (0/1)
- data << uint32(m_spellInfo->Id);
+ data << uint8(cast_count); // single cast or multi 2.3 (0/1)
+ data << uint32(spellInfo->Id);
data << uint8(result); // problem
switch (result)
{
case SPELL_FAILED_REQUIRES_SPELL_FOCUS:
- data << uint32(m_spellInfo->RequiresSpellFocus);
+ data << uint32(spellInfo->RequiresSpellFocus);
break;
case SPELL_FAILED_REQUIRES_AREA:
// hardcode areas limitation case
- switch(m_spellInfo->Id)
+ switch(spellInfo->Id)
{
case 41617: // Cenarion Mana Salve
case 41619: // Cenarion Healing Salve
@@ -3155,26 +3163,26 @@ void Spell::SendCastResult(SpellCastResult result)
}
break;
case SPELL_FAILED_TOTEMS:
- if(m_spellInfo->Totem[0])
- data << uint32(m_spellInfo->Totem[0]);
- if(m_spellInfo->Totem[1])
- data << uint32(m_spellInfo->Totem[1]);
+ if(spellInfo->Totem[0])
+ data << uint32(spellInfo->Totem[0]);
+ if(spellInfo->Totem[1])
+ data << uint32(spellInfo->Totem[1]);
break;
case SPELL_FAILED_TOTEM_CATEGORY:
- if(m_spellInfo->TotemCategory[0])
- data << uint32(m_spellInfo->TotemCategory[0]);
- if(m_spellInfo->TotemCategory[1])
- data << uint32(m_spellInfo->TotemCategory[1]);
+ if(spellInfo->TotemCategory[0])
+ data << uint32(spellInfo->TotemCategory[0]);
+ if(spellInfo->TotemCategory[1])
+ data << uint32(spellInfo->TotemCategory[1]);
break;
case SPELL_FAILED_EQUIPPED_ITEM_CLASS:
- data << uint32(m_spellInfo->EquippedItemClass);
- data << uint32(m_spellInfo->EquippedItemSubClassMask);
- //data << uint32(m_spellInfo->EquippedItemInventoryTypeMask);
+ data << uint32(spellInfo->EquippedItemClass);
+ data << uint32(spellInfo->EquippedItemSubClassMask);
+ //data << uint32(spellInfo->EquippedItemInventoryTypeMask);
break;
default:
break;
}
- ((Player*)m_caster)->GetSession()->SendPacket(&data);
+ caster->GetSession()->SendPacket(&data);
}
void Spell::SendSpellStart()
diff --git a/src/game/Spell.h b/src/game/Spell.h
index 9d16a85ebcf..4bf032bbbd7 100644
--- a/src/game/Spell.h
+++ b/src/game/Spell.h
@@ -423,6 +423,7 @@ class Spell
void CheckSrc() { if(!m_targets.HasSrc()) m_targets.setSrc(m_caster); }
void CheckDst() { if(!m_targets.HasDst()) m_targets.setDestination(m_caster); }
+ static void SendCastResult(Player* caster, SpellEntry const* spellInfo, uint8 cast_count, SpellCastResult result);
void SendCastResult(SpellCastResult result);
void SendSpellStart();
void SendSpellGo();
diff --git a/src/game/SpellHandler.cpp b/src/game/SpellHandler.cpp
index 7e72fd4e749..62056a6806f 100644
--- a/src/game/SpellHandler.cpp
+++ b/src/game/SpellHandler.cpp
@@ -123,9 +123,29 @@ void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket)
}
SpellCastTargets targets;
- if(!targets.read(&recvPacket, pUser))
+ if (!targets.read(&recvPacket, pUser))
return;
+ targets.Update(pUser);
+
+ if (!pItem->IsTargetValidForItemUse(targets.getUnitTarget()))
+ {
+ // free greay item aftre use faul
+ pUser->SendEquipError(EQUIP_ERR_NONE, pItem, NULL);
+
+ // send spell error
+ if (SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellid))
+ {
+ // for implicit area/coord target spells
+ if(!targets.getUnitTarget())
+ Spell::SendCastResult(_player,spellInfo,cast_count,SPELL_FAILED_NO_VALID_TARGETS);
+ // for explicit target spells
+ else
+ Spell::SendCastResult(_player,spellInfo,cast_count,SPELL_FAILED_BAD_TARGETS);
+ }
+ return;
+ }
+
//Note: If script stop casting it must send appropriate data to client to prevent stuck item in gray state.
if(!Script->ItemUse(pUser,pItem,targets))
{
diff --git a/src/game/World.cpp b/src/game/World.cpp
index 7412a7a282c..5ab3c46a036 100644
--- a/src/game/World.cpp
+++ b/src/game/World.cpp
@@ -1252,6 +1252,9 @@ void World::SetInitialWorldSettings()
sLog.outString( "Loading SpellsScriptTarget...");
spellmgr.LoadSpellScriptTarget(); // must be after LoadCreatureTemplates and LoadGameobjectInfo
+ sLog.outString( "Loading ItemRequiredTarget...");
+ objmgr.LoadItemRequiredTarget();
+
sLog.outString( "Loading Creature Reputation OnKill Data..." );
objmgr.LoadReputationOnKill();