Index: src/game/BattleGround.cpp =================================================================== --- src/game/BattleGround.cpp (revision 4688) +++ src/game/BattleGround.cpp (working copy) @@ -791,7 +791,7 @@ data.lootid = 0; data.spawntimesecs = spawntime; data.animprogress = 100; - data.dynflags = 1; //there was 0, i have no idea why we should change it + data.go_state = 1; objmgr.AddGameobjectToGrid(guid, &data); m_bgobjects[type] = MAKE_GUID(guid, HIGHGUID_GAMEOBJECT); Index: src/game/GameObject.cpp =================================================================== --- src/game/GameObject.cpp (revision 4688) +++ src/game/GameObject.cpp (working copy) @@ -82,7 +82,7 @@ Object::RemoveFromWorld(); } -bool GameObject::Create(uint32 guidlow, uint32 name_id, uint32 mapid, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint32 animprogress, uint32 dynflags) +bool GameObject::Create(uint32 guidlow, uint32 name_id, uint32 mapid, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint32 animprogress, uint32 go_state) { Relocate(x,y,z,ang); SetMapId(mapid); @@ -132,11 +132,10 @@ SetUInt32Value (GAMEOBJECT_DISPLAYID, goinfo->displayId); - SetUInt32Value (GAMEOBJECT_STATE, 1); + SetUInt32Value (GAMEOBJECT_STATE, go_state); SetUInt32Value (GAMEOBJECT_TYPE_ID, goinfo->type); SetUInt32Value (GAMEOBJECT_ANIMPROGRESS, animprogress); - SetUInt32Value (GAMEOBJECT_DYN_FLAGS, dynflags); //Notify the map's instance data. //Only works if you create the object in it, not if it is moves to that map. @@ -424,7 +423,7 @@ data.lootid = lootid; data.spawntimesecs = m_spawnedByDefault ? m_respawnDelayTime : -(int32)m_respawnDelayTime; data.animprogress = GetUInt32Value (GAMEOBJECT_ANIMPROGRESS); - data.dynflags = GetUInt32Value (GAMEOBJECT_DYN_FLAGS); + data.go_state = GetUInt32Value (GAMEOBJECT_STATE); // updated in DB std::ostringstream ss; @@ -443,7 +442,7 @@ << lootid <<", " << m_respawnDelayTime << ", " << GetUInt32Value (GAMEOBJECT_ANIMPROGRESS) << ", " - << GetUInt32Value (GAMEOBJECT_DYN_FLAGS) << ")";; + << GetUInt32Value (GAMEOBJECT_STATE) << ")";; WorldDatabase.BeginTransaction(); WorldDatabase.PExecuteLog("DELETE FROM `gameobject` WHERE `guid` = '%u'", m_DBTableGuid); @@ -474,13 +473,13 @@ float rotation3 = data->rotation3; uint32 animprogress = data->animprogress; - uint32 dynflags = data->dynflags; + uint32 go_state = data->go_state; uint32 stored_guid = guid; if (InstanceId != 0) guid = objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT); SetInstanceId(InstanceId); - if (!Create(guid,entry, map_id, x, y, z, ang, rotation0, rotation1, rotation2, rotation3, animprogress, dynflags) ) + if (!Create(guid,entry, map_id, x, y, z, ang, rotation0, rotation1, rotation2, rotation3, animprogress, go_state) ) return false; m_DBTableGuid = stored_guid; @@ -578,3 +577,34 @@ objmgr.SaveGORespawnTime(m_DBTableGuid,GetInstanceId(),0); } } + +bool GameObject::ActivateToQuest( Player *pTarget)const +{ + uint32 entry = GetEntry(); + + if(!objmgr.IsGameObjectForQuests(entry)) + return false; + + QuestRelations const& qr = objmgr.mGOQuestRelations; + if(qr.find(entry)!=qr.end()) + return true; + + //QuestRelations const& qi = objmgr.mGOQuestInvolvedRelations; + //if(qi.find(entry)!=qi.end()) + // return true; + + LootStore::iterator tab = LootTemplates_Gameobject.find(entry); + if (tab != LootTemplates_Gameobject.end()) + { + for(LootStoreItemList::iterator item_iter = tab->second.begin(); item_iter != tab->second.end(); ++item_iter) + { + if(pTarget->HasQuestForItem(item_iter->itemid)) + return true; + } + } + + if (pTarget->HasQuestForGO(entry)) + return true; + + return false; +} Index: src/game/GameObject.h =================================================================== --- src/game/GameObject.h (revision 4688) +++ src/game/GameObject.h (working copy) @@ -89,7 +89,7 @@ uint32 lootid; int32 spawntimesecs; uint32 animprogress; - uint32 dynflags; + uint32 go_state; }; // GCC have alternative #pragma pack() syntax and old gcc version not support pack(pop), also any gcc version not support it at some paltform @@ -123,7 +123,7 @@ void AddToWorld(); void RemoveFromWorld(); - bool Create(uint32 guidlow, uint32 name_id, uint32 mapid, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint32 animprogress, uint32 dynflags); + bool Create(uint32 guidlow, uint32 name_id, uint32 mapid, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint32 animprogress, uint32 go_state); void Update(uint32 p_time); GameObjectInfo const* GetGOInfo() const; @@ -189,6 +189,7 @@ bool hasQuest(uint32 quest_id) const; bool hasInvolvedQuest(uint32 quest_id) const; + bool ActivateToQuest(Player *pTarget) const; bool isVisibleForInState(Player const* u, bool inVisibleList) const; Index: src/game/Level2.cpp =================================================================== --- src/game/Level2.cpp (revision 4688) +++ src/game/Level2.cpp (working copy) @@ -3053,7 +3053,7 @@ GameObject* pGameObj = new GameObject(chr); uint32 lowGUID = objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT); - if(!pGameObj->Create(lowGUID, goI->id, chr->GetMapId(), x, y, z, o, 0, 0, rot2, rot3, 0, 0)) + if(!pGameObj->Create(lowGUID, goI->id, chr->GetMapId(), x, y, z, o, 0, 0, rot2, rot3, 0, 1)) { delete pGameObj; return false; Index: src/game/Level3.cpp =================================================================== --- src/game/Level3.cpp (revision 4691) +++ src/game/Level3.cpp (working copy) @@ -80,6 +80,10 @@ sLog.outString( "Re-Loading Quests Relations..." ); objmgr.LoadQuestRelations(); SendGlobalSysMessage("DB tables `*_questrelation` and `*_involvedrelation` reloaded."); + + sLog.outString( "Re-Generate GameObject for quests..." ); + objmgr.GenerateGameObjectForQuests(); + return true; } @@ -160,19 +164,31 @@ return true; } -bool ChatHandler::HandleReloadGOQuestRelationsCommand(const char*) +bool ChatHandler::HandleReloadGOQuestRelationsCommand(const char* arg) { sLog.outString( "Loading Quests Relations... (`gameobject_questrelation`)" ); objmgr.LoadQuestRelationsHelper(objmgr.mGOQuestRelations,"gameobject_questrelation"); SendGlobalSysMessage("DB table `gameobject_questrelation` (gameobject quest givers) reloaded."); + + if(arg=="") + { + sLog.outString( "Re-Generate GameObject for quests..." ); + objmgr.GenerateGameObjectForQuests(); + } return true; } -bool ChatHandler::HandleReloadGOQuestInvRelationsCommand(const char*) +bool ChatHandler::HandleReloadGOQuestInvRelationsCommand(const char* arg) { sLog.outString( "Loading Quests Relations... (`gameobject_involvedrelation`)" ); objmgr.LoadQuestRelationsHelper(objmgr.mGOQuestInvolvedRelations,"gameobject_involvedrelation"); SendGlobalSysMessage("DB table `gameobject_involvedrelation` (gameobject quest takers) reloaded."); + + if(arg=="") + { + sLog.outString( "Re-Generate GameObject for quests..." ); + objmgr.GenerateGameObjectForQuests(); + } return true; } @@ -184,11 +200,17 @@ return true; } -bool ChatHandler::HandleReloadQuestTemplateCommand(const char*) +bool ChatHandler::HandleReloadQuestTemplateCommand(const char* arg) { sLog.outString( "Re-Loading Quest Templates..." ); objmgr.LoadQuests(); SendGlobalSysMessage("DB table `quest_templatea` (quest definitions) reloaded."); + + if(arg=="") + { + sLog.outString( "Re-Generate GameObject for quests..." ); + objmgr.GenerateGameObjectForQuests(); + } return true; } Index: src/game/Object.cpp =================================================================== --- src/game/Object.cpp (revision 4688) +++ src/game/Object.cpp (working copy) @@ -210,7 +210,7 @@ UpdateMask updateMask; updateMask.SetCount( m_valuesCount ); _SetCreateBits( &updateMask, target ); - _BuildValuesUpdate( &buf, &updateMask, target ); + _BuildValuesUpdate(updatetype, &buf, &updateMask, target ); data->AddUpdateBlock(buf); } @@ -250,7 +250,7 @@ updateMask.SetCount( m_valuesCount ); _SetUpdateBits( &updateMask, target ); - _BuildValuesUpdate( &buf, &updateMask, target ); + _BuildValuesUpdate(UPDATETYPE_VALUES, &buf, &updateMask, target ); data->AddUpdateBlock(buf); } @@ -477,8 +477,27 @@ } } -void Object::_BuildValuesUpdate(ByteBuffer * data, UpdateMask *updateMask, Player *target) const +void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask *updateMask, Player *target) const { + if(!target) + return; + + bool IsActivateToQuest = false; + if (updatetype == UPDATETYPE_CREATE_OBJECT || updatetype == UPDATETYPE_CREATE_OBJECT2) + { + if (isType(TYPE_GAMEOBJECT)) + { + if ( ((GameObject*)this)->ActivateToQuest(target)) + { + IsActivateToQuest = true; + updateMask->SetBit(GAMEOBJECT_DYN_FLAGS); + } + } + } + + //if(objmgr.IsGameObjectForQuests(GetEntry())) + // updateMask->SetBit(GAMEOBJECT_DYN_FLAGS); + WPAssert(updateMask && updateMask->GetCount() == m_valuesCount); *data << (uint8)updateMask->GetBlockCount(); @@ -515,6 +534,22 @@ } } } + else if(isType(TYPE_GAMEOBJECT)) // gameobject case + { + for( uint16 index = 0; index < m_valuesCount; index ++ ) + { + if( updateMask->GetBit( index ) ) + { + // send in current format (float as float, uint32 as uint32) + if (index == GAMEOBJECT_DYN_FLAGS && IsActivateToQuest) + { + *data << uint32(1); + } + else + *data << m_uint32Values[ index ]; + } + } + } else // other objects case (no special index checks) { for( uint16 index = 0; index < m_valuesCount; index ++ ) Index: src/game/Object.h =================================================================== --- src/game/Object.h (revision 4688) +++ src/game/Object.h (working copy) @@ -207,7 +207,7 @@ virtual void _SetCreateBits(UpdateMask *updateMask, Player *target) const; void _BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2 ) const; - void _BuildValuesUpdate( ByteBuffer *data, UpdateMask *updateMask, Player *target ) const; + void _BuildValuesUpdate(uint8 updatetype, ByteBuffer *data, UpdateMask *updateMask, Player *target ) const; uint16 m_objectType; Index: src/game/ObjectMgr.cpp =================================================================== --- src/game/ObjectMgr.cpp (revision 4691) +++ src/game/ObjectMgr.cpp (working copy) @@ -730,8 +730,8 @@ // 0 1 2 3 4 5 6 QueryResult *result = WorldDatabase.Query("SELECT `gameobject`.`guid`,`id`,`map`,`position_x`,`position_y`,`position_z`,`orientation`," - // 7 8 9 10 11 12 13 14 15 - "`rotation0`,`rotation1`,`rotation2`,`rotation3`,`loot`,`spawntimesecs`,`animprogress`,`dynflags`,`event` " + // 7 8 9 10 11 12 13 14 15 + "`rotation0`,`rotation1`,`rotation2`,`rotation3`,`loot`,`spawntimesecs`,`animprogress`,`state`,`event` " "FROM `gameobject` LEFT OUTER JOIN `game_event_gameobject` ON `gameobject`.`guid`=`game_event_gameobject`.`guid`"); if(!result) @@ -769,7 +769,7 @@ data.lootid = fields[11].GetUInt32(); data.spawntimesecs = fields[12].GetInt32(); data.animprogress = fields[13].GetUInt32(); - data.dynflags = fields[14].GetUInt32(); + data.go_state = fields[14].GetUInt32(); int16 gameEvent = fields[15].GetInt16(); if (gameEvent==0) // if not this is to be managed by GameEvent System @@ -5678,3 +5678,38 @@ m_LocalToIndex.push_back(loc); return m_LocalToIndex.size()-1; } + +void ObjectMgr::GenerateGameObjectForQuests() +{ + mGameObjectForQuestSet.clear(); // need for reload case + + for(QuestRelations::const_iterator itr = mGOQuestRelations.begin(); itr != mGOQuestRelations.end(); ++itr) + mGameObjectForQuestSet.insert(itr->first); + + for(QuestRelations::const_iterator itr = mGOQuestInvolvedRelations.begin(); itr != mGOQuestInvolvedRelations.end(); ++itr) + mGameObjectForQuestSet.insert(itr->first); + + for( QuestMap::const_iterator i = mQuestTemplates.begin( ); i != mQuestTemplates.end( ); ++i ) + { + Quest* qinfo = i->second; + if(!qinfo) + continue; + + for (int j = 0; j < QUEST_OBJECTIVES_COUNT; j++) + if(qinfo->ReqCreatureOrGOId[j] < 0) + mGameObjectForQuestSet.insert(((-1)*qinfo->ReqCreatureOrGOId[j])); + } + + for( LootStore::const_iterator go_i = LootTemplates_Gameobject.begin( ); go_i != LootTemplates_Gameobject.end( ); ++go_i ) + { + uint32 entry = go_i->first; + for(LootStoreItemList::const_iterator item_i = go_i->second.begin(); item_i != go_i->second.end(); ++item_i ) + { + if(item_i->questChanceOrGroup > 0) + { + mGameObjectForQuestSet.insert(entry); + break; + } + } + } +} Index: src/game/ObjectMgr.h =================================================================== --- src/game/ObjectMgr.h (revision 4688) +++ src/game/ObjectMgr.h (working copy) @@ -360,6 +360,7 @@ return 0; } bool IsTavernAreaTrigger(uint32 Trigger_ID) const { return mTavernAreaTriggerSet.count(Trigger_ID) != 0; } + bool IsGameObjectForQuests(uint32 entry) const { return mGameObjectForQuestSet.count(entry) != 0; } void AddGossipText(GossipText *pGText); GossipText *GetGossipText(uint32 Text_ID); @@ -472,6 +473,7 @@ void LoadAreaTriggerTeleports(); void LoadQuestAreaTriggers(); void LoadTavernAreaTriggers(); + void GenerateGameObjectForQuests(); void LoadSpellAffects(); void LoadSpellProcEvents(); @@ -754,6 +756,7 @@ typedef HM_NAMESPACE::hash_map QuestAreaTriggerMap; typedef HM_NAMESPACE::hash_map ItemTextMap; typedef std::set TavernAreaTriggerSet; + typedef std::set GameObjectForQuestSet; GroupSet mGroupSet; GuildSet mGuildSet; @@ -770,6 +773,7 @@ QuestAreaTriggerMap mQuestAreaTriggerMap; TavernAreaTriggerSet mTavernAreaTriggerSet; + GameObjectForQuestSet mGameObjectForQuestSet; GossipTextMap mGossipText; AreaTriggerMap mAreaTriggers; SpellTeleportMap mSpellTeleports; Index: src/game/Player.cpp =================================================================== --- src/game/Player.cpp (revision 4688) +++ src/game/Player.cpp (working copy) @@ -15520,3 +15520,32 @@ return sBattleGroundMgr.GetBattleGround(GetBattleGroundId()); } + +bool Player::HasQuestForGO(int32 GOId) +{ + for( QuestStatusMap::iterator i = mQuestStatus.begin( ); i != mQuestStatus.end( ); ++i ) + { + QuestStatusData qs=i->second; + if (qs.m_status == QUEST_STATUS_INCOMPLETE) + { + Quest const* qinfo = objmgr.GetQuestTemplate(i->first); + if(!qinfo) + continue; + + if(GetGroup() && GetGroup()->isRaidGroup() && qinfo->GetType() != QUEST_TYPE_RAID) + continue; + + for (int j = 0; j < QUEST_OBJECTIVES_COUNT; j++) + { + if (qinfo->ReqCreatureOrGOId[j]>=0) // skip and creature case + continue; + + uint32 quest_go_id = (-1)*qinfo->ReqCreatureOrGOId[j]; + + if(GOId == quest_go_id && qs.m_creatureOrGOcount[j] < qinfo->ReqCreatureOrGOCount[j]) + return true; + } + } + } + return false; +} Index: src/game/Player.h =================================================================== --- src/game/Player.h (revision 4688) +++ src/game/Player.h (working copy) @@ -1043,6 +1043,7 @@ void TalkedToCreature( uint32 entry, uint64 guid ); void MoneyChanged( uint32 value ); bool HasQuestForItem( uint32 itemid ); + bool HasQuestForGO(int32 GOId); bool CanShareQuest(uint32 quest_id); void SendQuestComplete( uint32 quest_id ); Index: src/game/SpellEffects.cpp =================================================================== --- src/game/SpellEffects.cpp (revision 4694) +++ src/game/SpellEffects.cpp (working copy) @@ -2918,7 +2918,7 @@ m_caster->GetClosePoint(x,y,z); if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id, target->GetMapId(), - x, y, z, target->GetOrientation(), 0, 0, 0, 0, 100, 0)) + x, y, z, target->GetOrientation(), 0, 0, 0, 0, 100, 1)) { delete pGameObj; return; @@ -3146,7 +3146,7 @@ m_caster->GetPositionX()+(unitTarget->GetPositionX()-m_caster->GetPositionX())/2 , m_caster->GetPositionY()+(unitTarget->GetPositionY()-m_caster->GetPositionY())/2 , m_caster->GetPositionZ(), - m_caster->GetOrientation(), 0, 0, 0, 0, 0, 0)) + m_caster->GetOrientation(), 0, 0, 0, 0, 0, 1)) { delete pGameObj; return; @@ -3449,7 +3449,7 @@ float x,y,z; m_caster->GetClosePoint(x,y,z); - if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), display_id,m_caster->GetMapId(), x, y, z, m_caster->GetOrientation(), 0, 0, rot2, rot3, 0, 0)) + if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), display_id,m_caster->GetMapId(), x, y, z, m_caster->GetOrientation(), 0, 0, rot2, rot3, 0, 1)) { delete pGameObj; return; @@ -3908,7 +3908,7 @@ GameObject* pGameObj = new GameObject(m_caster); if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), name_id,cMap, - fx, fy, fz, m_caster->GetOrientation(), 0, 0, 0, 0, 100, 0)) + fx, fy, fz, m_caster->GetOrientation(), 0, 0, 0, 0, 100, 1)) { delete pGameObj; return; Index: src/game/World.cpp =================================================================== --- src/game/World.cpp (revision 4688) +++ src/game/World.cpp (working copy) @@ -713,6 +713,9 @@ sLog.outString( "Loading InstanceTemplate" ); objmgr.LoadInstanceTemplate(); + sLog.outString( "Generate GameObject for quests..." ); + objmgr.GenerateGameObjectForQuests(); // must be after LoadQuests, LoadQuestRelations, and LoadLootTables + ///- Handle outdated emails (delete/return) sLog.outString( "Returning old mails..." ); objmgr.ReturnOrDeleteOldMails(false);