diff options
| author | Shauren <shauren.trinity@gmail.com> | 2011-02-03 22:20:40 +0100 |
|---|---|---|
| committer | Shauren <shauren.trinity@gmail.com> | 2011-02-03 22:20:40 +0100 |
| commit | c2b0bcbd6c8155812857523681cd787059cd9bf9 (patch) | |
| tree | b325612ecdddbb1235c676a862435c83374f95cf /src/server/game | |
| parent | 7ea8bad07f64ed5886130fcc8016c0c72a32758e (diff) | |
Core/Instances: Implemented DungeonEncounter.dbc for creating completed encounters mask to use in packets
Core/Dungeon Finder: Implemented new way of giving random dungeon rewards, linked to DungeonEncounter.dbc
Diffstat (limited to 'src/server/game')
| -rwxr-xr-x | src/server/game/Achievements/AchievementMgr.cpp | 4 | ||||
| -rwxr-xr-x | src/server/game/DataStores/DBCStores.cpp | 8 | ||||
| -rwxr-xr-x | src/server/game/DataStores/DBCStores.h | 3 | ||||
| -rwxr-xr-x | src/server/game/DataStores/DBCStructure.h | 12 | ||||
| -rwxr-xr-x | src/server/game/DataStores/DBCfmt.h | 1 | ||||
| -rwxr-xr-x | src/server/game/DungeonFinding/LFGMgr.cpp | 71 | ||||
| -rwxr-xr-x | src/server/game/DungeonFinding/LFGMgr.h | 3 | ||||
| -rwxr-xr-x | src/server/game/Entities/Player/Player.cpp | 11 | ||||
| -rwxr-xr-x | src/server/game/Globals/ObjectMgr.cpp | 78 | ||||
| -rwxr-xr-x | src/server/game/Globals/ObjectMgr.h | 32 | ||||
| -rwxr-xr-x | src/server/game/Instances/InstanceSaveMgr.cpp | 19 | ||||
| -rwxr-xr-x | src/server/game/Instances/InstanceScript.cpp | 35 | ||||
| -rwxr-xr-x | src/server/game/Instances/InstanceScript.h | 14 | ||||
| -rwxr-xr-x | src/server/game/Maps/Map.cpp | 3 | ||||
| -rwxr-xr-x | src/server/game/Server/Protocol/Handlers/LFGHandler.cpp | 24 | ||||
| -rwxr-xr-x | src/server/game/Spells/Spell.cpp | 12 | ||||
| -rwxr-xr-x | src/server/game/World/World.cpp | 2 |
17 files changed, 227 insertions, 105 deletions
diff --git a/src/server/game/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp index 327b4360292..228af5838df 100755 --- a/src/server/game/Achievements/AchievementMgr.cpp +++ b/src/server/game/Achievements/AchievementMgr.cpp @@ -38,7 +38,6 @@ #include "BattlegroundAB.h" #include "Map.h" #include "InstanceScript.h" -#include "LFGMgr.h" namespace Trinity { @@ -1548,9 +1547,6 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui if (IsCompletedAchievement(*itr)) CompletedAchievement(*itr); } - - if (const uint32 dungeonId = sLFGMgr->GetDungeonIdForAchievement(achievement->ID)) - sLFGMgr->RewardDungeonDoneFor(dungeonId, GetPlayer()); } } diff --git a/src/server/game/DataStores/DBCStores.cpp b/src/server/game/DataStores/DBCStores.cpp index 021e5f9d62e..07d0ec037e3 100755 --- a/src/server/game/DataStores/DBCStores.cpp +++ b/src/server/game/DataStores/DBCStores.cpp @@ -75,6 +75,7 @@ DBCStorage <CreatureSpellDataEntry> sCreatureSpellDataStore(CreatureSpellDatafmt DBCStorage <CreatureTypeEntry> sCreatureTypeStore(CreatureTypefmt); DBCStorage <CurrencyTypesEntry> sCurrencyTypesStore(CurrencyTypesfmt); +DBCStorage <DungeonEncounterEntry> sDungeonEncounterStore(DungeonEncounterfmt); DBCStorage <DurabilityQualityEntry> sDurabilityQualityStore(DurabilityQualityfmt); DBCStorage <DurabilityCostsEntry> sDurabilityCostsStore(DurabilityCostsfmt); @@ -246,7 +247,7 @@ void LoadDBCStores(const std::string& dataPath) uint32 oldMSTime = getMSTime(); std::string dbcPath = dataPath+"dbc/"; - const uint32 DBCFilesCount = 91; + const uint32 DBCFilesCount = 92; StoreProblemList bad_dbc_files; uint32 availableDbcLocales = 0xFFFFFFFF; @@ -287,6 +288,7 @@ void LoadDBCStores(const std::string& dataPath) LoadDBC(availableDbcLocales,bad_dbc_files,sCreatureSpellDataStore, dbcPath,"CreatureSpellData.dbc"); LoadDBC(availableDbcLocales,bad_dbc_files,sCreatureTypeStore, dbcPath,"CreatureType.dbc"); LoadDBC(availableDbcLocales,bad_dbc_files,sCurrencyTypesStore, dbcPath,"CurrencyTypes.dbc"); + LoadDBC(availableDbcLocales,bad_dbc_files,sDungeonEncounterStore, dbcPath,"DungeonEncounter.dbc"); LoadDBC(availableDbcLocales,bad_dbc_files,sDurabilityCostsStore, dbcPath,"DurabilityCosts.dbc"); LoadDBC(availableDbcLocales,bad_dbc_files,sDurabilityQualityStore, dbcPath,"DurabilityQuality.dbc"); LoadDBC(availableDbcLocales,bad_dbc_files,sEmotesStore, dbcPath,"Emotes.dbc"); @@ -581,12 +583,8 @@ void LoadDBCStores(const std::string& dataPath) LoadDBC(availableDbcLocales,bad_dbc_files,sVehicleSeatStore, dbcPath,"VehicleSeat.dbc"); LoadDBC(availableDbcLocales,bad_dbc_files,sWMOAreaTableStore, dbcPath,"WMOAreaTable.dbc"); for(uint32 i = 0; i < sWMOAreaTableStore.GetNumRows(); ++i) - { if(WMOAreaTableEntry const* entry = sWMOAreaTableStore.LookupEntry(i)) - { sWMOAreaInfoByTripple.insert(WMOAreaInfoByTripple::value_type(WMOAreaTableTripple(entry->rootId, entry->adtId, entry->groupId), entry)); - } - } LoadDBC(availableDbcLocales,bad_dbc_files,sWorldMapAreaStore, dbcPath,"WorldMapArea.dbc"); LoadDBC(availableDbcLocales,bad_dbc_files,sWorldMapOverlayStore, dbcPath,"WorldMapOverlay.dbc"); LoadDBC(availableDbcLocales,bad_dbc_files,sWorldSafeLocsStore, dbcPath,"WorldSafeLocs.dbc"); diff --git a/src/server/game/DataStores/DBCStores.h b/src/server/game/DataStores/DBCStores.h index fbd61153509..3b7a5764281 100755 --- a/src/server/game/DataStores/DBCStores.h +++ b/src/server/game/DataStores/DBCStores.h @@ -26,8 +26,8 @@ #include <list> typedef std::list<uint32> SimpleFactionsList; - SimpleFactionsList const* GetFactionTeamList(uint32 faction); + char* GetPetName(uint32 petfamily, uint32 dbclang); uint32 GetTalentSpellCost(uint32 spellId); TalentSpellPos const* GetTalentSpellPos(uint32 spellId); @@ -84,6 +84,7 @@ extern DBCStorage <CreatureFamilyEntry> sCreatureFamilyStore; extern DBCStorage <CreatureSpellDataEntry> sCreatureSpellDataStore; extern DBCStorage <CreatureTypeEntry> sCreatureTypeStore; extern DBCStorage <CurrencyTypesEntry> sCurrencyTypesStore; +extern DBCStorage <DungeonEncounterEntry> sDungeonEncounterStore; extern DBCStorage <DurabilityCostsEntry> sDurabilityCostsStore; extern DBCStorage <DurabilityQualityEntry> sDurabilityQualityStore; extern DBCStorage <EmotesEntry> sEmotesStore; diff --git a/src/server/game/DataStores/DBCStructure.h b/src/server/game/DataStores/DBCStructure.h index ef09795d731..3ece8f93e39 100755 --- a/src/server/game/DataStores/DBCStructure.h +++ b/src/server/game/DataStores/DBCStructure.h @@ -784,6 +784,18 @@ struct CurrencyTypesEntry uint32 BitIndex; // 3 bit index in PLAYER_FIELD_KNOWN_CURRENCIES (1 << (index-1)) }; +struct DungeonEncounterEntry +{ + uint32 id; // 0 unique id + uint32 mapId; // 1 map id + uint32 difficulty; // 2 instance mode + //uint32 unk0; // 3 + uint32 encounterIndex; // 4 encounter index for creating completed mask + char* encounterName[16]; // 5-20 encounter name + //uint32 nameFlags; // 21 + //uint32 unk1; // 22 +}; + struct DurabilityCostsEntry { uint32 Itemlvl; // 0 diff --git a/src/server/game/DataStores/DBCfmt.h b/src/server/game/DataStores/DBCfmt.h index a6d3f8e983a..89495b786dd 100755 --- a/src/server/game/DataStores/DBCfmt.h +++ b/src/server/game/DataStores/DBCfmt.h @@ -41,6 +41,7 @@ const char CreatureFamilyfmt[]="nfifiiiiixssssssssssssssssxx"; const char CreatureSpellDatafmt[]="niiiixxxx"; const char CreatureTypefmt[]="nxxxxxxxxxxxxxxxxxx"; const char CurrencyTypesfmt[]="xnxi"; +const char DungeonEncounterfmt[]="niixissssssssssssssssxx"; const char DurabilityCostsfmt[]="niiiiiiiiiiiiiiiiiiiiiiiiiiiii"; const char DurabilityQualityfmt[]="nf"; const char EmotesEntryfmt[]="nxxiiix"; diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp index 97b31a37cf1..d7a329737a6 100755 --- a/src/server/game/DungeonFinding/LFGMgr.cpp +++ b/src/server/game/DungeonFinding/LFGMgr.cpp @@ -71,61 +71,6 @@ LFGMgr::~LFGMgr() delete it->second; } -/// Load achievement <-> encounter associations -void LFGMgr::LoadDungeonEncounters() -{ - uint32 oldMSTime = getMSTime(); - - m_EncountersByAchievement.clear(); - - QueryResult result = WorldDatabase.Query("SELECT achievementId, dungeonId FROM lfg_dungeon_encounters"); - - if (!result) - { - - sLog->outString(); - sLog->outErrorDb(">> Loaded 0 dungeon encounter lfg associations. DB table `lfg_dungeon_encounters` is empty!"); - return; - } - - uint32 count = 0; - - Field* fields = NULL; - do - { - fields = result->Fetch(); - uint32 achievementId = fields[0].GetUInt32(); - uint32 dungeonId = fields[1].GetUInt32(); - - if (AchievementEntry const* achievement = sAchievementStore.LookupEntry(achievementId)) - { - if (!(achievement->flags & ACHIEVEMENT_FLAG_COUNTER)) - { - sLog->outErrorDb("Achievement %u specified in table `lfg_dungeon_encounters` is not a statistic!", achievementId); - continue; - } - } - else - { - sLog->outErrorDb("Achievement %u specified in table `lfg_dungeon_encounters` does not exist!", achievementId); - continue; - } - - if (!sLFGDungeonStore.LookupEntry(dungeonId)) - { - sLog->outErrorDb("Dungeon %u specified in table `lfg_dungeon_encounters` does not exist!", dungeonId); - continue; - } - - m_EncountersByAchievement[achievementId] = dungeonId; - ++count; - } while (result->NextRow()); - - sLog->outString(">> Loaded %u dungeon encounter lfg associations in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); - sLog->outString(); -} - - /// Load rewards for completing dungeons void LFGMgr::LoadRewards() { @@ -1730,7 +1675,6 @@ void LFGMgr::TeleportPlayer(Player* plr, bool out, bool fromOpcode /*= false*/) if (!fromOpcode) { - // Select a player inside to be teleported to for (GroupReference* itr = grp->GetFirstMember(); itr != NULL && !mapid; itr = itr->next()) { @@ -1923,21 +1867,6 @@ LfgType LFGMgr::GetDungeonType(uint32 dungeonId) } /** - Given a Achievement id returns the related dungeon id - - @param[in] achievementId Achievement id - @returns dungeon id -*/ -uint32 LFGMgr::GetDungeonIdForAchievement(uint32 achievementId) -{ - std::map<uint32, uint32>::iterator itr = m_EncountersByAchievement.find(achievementId); - if (itr != m_EncountersByAchievement.end()) - return itr->second; - - return 0; -}; - -/** Given a list of guids returns the concatenation using | as delimiter @param[in] check list of guids diff --git a/src/server/game/DungeonFinding/LFGMgr.h b/src/server/game/DungeonFinding/LFGMgr.h index 775c1e05837..493bed3305b 100755 --- a/src/server/game/DungeonFinding/LFGMgr.h +++ b/src/server/game/DungeonFinding/LFGMgr.h @@ -262,10 +262,8 @@ class LFGMgr void Update(uint32 diff); // Reward - void LoadDungeonEncounters(); void LoadRewards(); void RewardDungeonDoneFor(const uint32 dungeonId, Player* player); - uint32 GetDungeonIdForAchievement(uint32 achievementId); LfgReward const* GetRandomDungeonReward(uint32 dungeon, uint8 level); // Queue @@ -348,7 +346,6 @@ class LFGMgr LfgDungeonMap m_CachedDungeonMap; ///< Stores all dungeons by groupType // Reward System LfgRewardMap m_RewardMap; ///< Stores rewards for random dungeons - std::map<uint32, uint32> m_EncountersByAchievement;///< Stores dungeon ids associated with achievements (for rewards) // Queue LfgQueueInfoMap m_QueueInfoMap; ///< Queued groups LfgGuidListMap m_currentQueue; ///< Ordered list. Used to find groups diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 29d1d136687..a6a8e9a6bb0 100755 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -68,6 +68,7 @@ #include "WeatherMgr.h" #include "LFGMgr.h" #include "CharacterDatabaseCleaner.h" +#include "InstanceScript.h" #include <cmath> #define ZONE_UPDATE_INTERVAL (1*IN_MILLISECONDS) @@ -17709,6 +17710,10 @@ InstancePlayerBind* Player::BindToInstance(InstanceSave *save, bool permanent, b void Player::BindToInstance() { + // Player left the instance + if (_pendingBind->GetInstanceId() != GetInstanceId()) + return; + WorldPacket data(SMSG_INSTANCE_SAVE_CREATED, 4); data << uint32(0); GetSession()->SendPacket(&data); @@ -22116,6 +22121,12 @@ bool Player::RewardPlayerAndGroupAtKill(Unit* pVictim) KilledMonster(pVictim->ToCreature()->GetCreatureInfo(), pVictim->GetGUID()); } } + + // Credit encounter in instance + if (pVictim->GetTypeId() == TYPEID_UNIT && GetMap()->IsDungeon()) + if (InstanceScript* instance = pVictim->GetInstanceScript()) + instance->UpdateEncounterState(ENCOUNTER_CREDIT_KILL_CREATURE, pVictim->GetEntry(), pVictim); + return xp || honored_kill; } diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 013c8afe6e8..940f3c5ad1a 100755 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -5553,6 +5553,84 @@ void ObjectMgr::LoadInstanceTemplate() sLog->outString(); } +void ObjectMgr::LoadInstanceEncounters() +{ + uint32 oldMSTime = getMSTime(); + + QueryResult result = WorldDatabase.Query("SELECT entry, creditType, creditEntry, lastEncounterDungeon FROM instance_encounters"); + if (!result) + { + sLog->outErrorDb(">> Loaded 0 instance encounters, table is empty!"); + sLog->outString(); + return; + } + + uint32 count = 0; + std::map<uint32, DungeonEncounterEntry const*> dungeonLastBosses; + do + { + Field* fields = result->Fetch(); + uint32 entry = fields[0].GetUInt32(); + DungeonEncounterEntry const* dungeonEncounter = sDungeonEncounterStore.LookupEntry(entry); + if (!dungeonEncounter) + { + sLog->outErrorDb("Table `instance_encounters` has an invalid encounter id %u, skipped!", entry); + continue; + } + + uint8 creditType = fields[1].GetUInt8(); + uint32 creditEntry = fields[2].GetUInt32(); + + switch (creditType) + { + case ENCOUNTER_CREDIT_KILL_CREATURE: + if (!GetCreatureInfo(creditEntry)) + { + sLog->outErrorDb("Table `instance_encounters` has an invalid creature (entry %u) linked to the encounter %u (%s), skipped!", creditEntry, entry, dungeonEncounter->encounterName[0]); + continue; + } + break; + case ENCOUNTER_CREDIT_CAST_SPELL: + if (!sSpellStore.LookupEntry(creditEntry)) + { + sLog->outErrorDb("Table `instance_encounters` has an invalid spell (entry %u) linked to the encounter %u (%s), skipped!", creditEntry, entry, dungeonEncounter->encounterName[0]); + continue; + } + break; + default: + sLog->outErrorDb("Table `instance_encounters` has an invalid credit type (%u) for encounter %u (%s), skipped!", creditType, entry, dungeonEncounter->encounterName[0]); + continue; + } + + uint32 lastEncounterDungeon = fields[3].GetUInt32(); + + if (lastEncounterDungeon && !sLFGDungeonStore.LookupEntry(lastEncounterDungeon)) + { + sLog->outErrorDb("Table `instance_encounters` has an encounter %u (%s) marked as final for invalid dungeon id %u, skipped!", entry, dungeonEncounter->encounterName[0], lastEncounterDungeon); + continue; + } + + std::map<uint32, DungeonEncounterEntry const*>::const_iterator itr = dungeonLastBosses.find(lastEncounterDungeon); + if (lastEncounterDungeon) + { + if (itr != dungeonLastBosses.end()) + { + sLog->outErrorDb("Table `instance_encounters` specified encounter %u (%s) as last encounter but %u (%s) is already marked as one, skipped!", entry, dungeonEncounter->encounterName[0], itr->second->id, itr->second->encounterName[0]); + continue; + } + + dungeonLastBosses[lastEncounterDungeon] = dungeonEncounter; + } + + DungeonEncounterList& encounters = mDungeonEncounters[MAKE_PAIR32(dungeonEncounter->mapId, dungeonEncounter->difficulty)]; + encounters.push_back(new DungeonEncounter(dungeonEncounter, EncounterCreditType(creditType), creditEntry, lastEncounterDungeon)); + ++count; + } while (result->NextRow()); + + sLog->outString(">> Loaded %u instance encounters in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); + sLog->outString(); +} + GossipText const *ObjectMgr::GetGossipText(uint32 Text_ID) const { GossipTextMap::const_iterator itr = mGossipText.find(Text_ID); diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h index 4efbbc7e5f0..13d3a3ec418 100755 --- a/src/server/game/Globals/ObjectMgr.h +++ b/src/server/game/Globals/ObjectMgr.h @@ -557,7 +557,27 @@ struct LanguageDesc }; extern LanguageDesc lang_description[LANGUAGES_COUNT]; - LanguageDesc const* GetLanguageDescByID(uint32 lang); +LanguageDesc const* GetLanguageDescByID(uint32 lang); + +enum EncounterCreditType +{ + ENCOUNTER_CREDIT_KILL_CREATURE = 0, + ENCOUNTER_CREDIT_CAST_SPELL = 1, +}; + +struct DungeonEncounter +{ + DungeonEncounter(DungeonEncounterEntry const* _dbcEntry, EncounterCreditType _creditType, uint32 _creditEntry, uint32 _lastEncounterDungeon) + : dbcEntry(_dbcEntry), creditType(_creditType), creditEntry(_creditEntry), lastEncounterDungeon(_lastEncounterDungeon) { } + + DungeonEncounterEntry const* dbcEntry; + EncounterCreditType creditType; + uint32 creditEntry; + uint32 lastEncounterDungeon; +}; + +typedef std::list<DungeonEncounter const*> DungeonEncounterList; +typedef UNORDERED_MAP<uint32,DungeonEncounterList> DungeonEncounterMap; class PlayerDumpReader; @@ -796,6 +816,14 @@ class ObjectMgr return NULL; } + DungeonEncounterList const* GetDungeonEncounterList(uint32 mapId, Difficulty difficulty) + { + UNORDERED_MAP<uint32, DungeonEncounterList>::const_iterator itr = mDungeonEncounters.find(MAKE_PAIR32(mapId, difficulty)); + if (itr != mDungeonEncounters.end()) + return &itr->second; + return NULL; + } + void LoadGuilds(); void LoadArenaTeams(); void LoadGroups(); @@ -884,6 +912,7 @@ class ObjectMgr void LoadGossipMenuItemsLocales(); void LoadPointOfInterestLocales(); void LoadInstanceTemplate(); + void LoadInstanceEncounters(); void LoadMailLevelRewards(); void LoadVehicleAccessories(); void LoadVehicleScaling(); @@ -1253,6 +1282,7 @@ class ObjectMgr AreaTriggerMap mAreaTriggers; AreaTriggerScriptMap mAreaTriggerScripts; AccessRequirementMap mAccessRequirements; + DungeonEncounterMap mDungeonEncounters; RepRewardRateMap m_RepRewardRateMap; RepOnKillMap mRepOnKill; diff --git a/src/server/game/Instances/InstanceSaveMgr.cpp b/src/server/game/Instances/InstanceSaveMgr.cpp index 4c2f8117ba7..ad385a7334d 100755 --- a/src/server/game/Instances/InstanceSaveMgr.cpp +++ b/src/server/game/Instances/InstanceSaveMgr.cpp @@ -165,20 +165,27 @@ void InstanceSave::SaveToDB() { // save instance data too std::string data; + uint32 completedEncounters = 0; - Map *map = sMapMgr->FindMap(GetMapId(),m_instanceid); + Map *map = sMapMgr->FindMap(GetMapId(), m_instanceid); if (map) { ASSERT(map->IsDungeon()); - if (InstanceScript *iData = ((InstanceMap*)map)->GetInstanceScript()) + if (InstanceScript *instanceScript = ((InstanceMap*)map)->GetInstanceScript()) { - data = iData->GetSaveData(); - if (!data.empty()) - CharacterDatabase.escape_string(data); + data = instanceScript->GetSaveData(); + completedEncounters = instanceScript->GetCompletedEncounterMask(); } } - CharacterDatabase.PExecute("INSERT INTO instance VALUES ('%u', '%u', '%u', '%u', '%s')", m_instanceid, GetMapId(), (uint32)GetResetTimeForDB(), GetDifficulty(), data.c_str()); + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_ADD_INSTANCE_SAVE); + stmt->setUInt32(0, m_instanceid); + stmt->setUInt16(1, GetMapId()); + stmt->setUInt32(2, uint32(GetResetTimeForDB())); + stmt->setUInt8(3, uint8(GetDifficulty())); + stmt->setUInt32(4, completedEncounters); + stmt->setString(5, data); + CharacterDatabase.Execute(stmt); } time_t InstanceSave::GetResetTimeForDB() diff --git a/src/server/game/Instances/InstanceScript.cpp b/src/server/game/Instances/InstanceScript.cpp index 348ff7a766c..231d6ab6667 100755 --- a/src/server/game/Instances/InstanceScript.cpp +++ b/src/server/game/Instances/InstanceScript.cpp @@ -24,14 +24,19 @@ #include "Creature.h" #include "CreatureAI.h" #include "Log.h" +#include "LFGMgr.h" void InstanceScript::SaveToDB() { std::string data = GetSaveData(); if (data.empty()) return; - CharacterDatabase.escape_string(data); - CharacterDatabase.PExecute("UPDATE instance SET data = '%s' WHERE id = '%d'", data.c_str(), instance->GetInstanceId()); + + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPDATE_INSTANCE_DATA); + stmt->setUInt32(0, GetCompletedEncounterMask()); + stmt->setString(1, data); + stmt->setUInt32(2, instance->GetInstanceId()); + CharacterDatabase.Execute(stmt); } void InstanceScript::HandleGameObject(uint64 GUID, bool open, GameObject *go) @@ -427,3 +432,29 @@ void InstanceScript::SendEncounterUnit(uint32 type, Unit* unit /*= NULL*/, uint8 instance->SendToPlayers(&data); } + +void InstanceScript::UpdateEncounterState(EncounterCreditType type, uint32 creditEntry, Unit* source) +{ + DungeonEncounterList const* encounters = sObjectMgr->GetDungeonEncounterList(instance->GetId(), instance->GetDifficulty()); + if (!encounters) + return; + + for (DungeonEncounterList::const_iterator itr = encounters->begin(); itr != encounters->end(); ++itr) + { + if ((*itr)->creditType == type && (*itr)->creditEntry == creditEntry) + { + completedEncounters |= 1 << (*itr)->dbcEntry->encounterIndex; + sLog->outDebug("Instance %s (instanceId %u) completed encounter %s", instance->GetMapName(), instance->GetInstanceId(), (*itr)->dbcEntry->encounterName[0]); + if (uint32 dungeonId = (*itr)->lastEncounterDungeon) + { + Map::PlayerList const& players = instance->GetPlayers(); + if (!players.isEmpty()) + for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i) + if (Player* player = i->getSource()) + if (!source || player->IsAtGroupRewardDistance(source)) + sLFGMgr->RewardDungeonDoneFor(dungeonId, player); + } + return; + } + } +} diff --git a/src/server/game/Instances/InstanceScript.h b/src/server/game/Instances/InstanceScript.h index 5e293eee0ca..2ba81c963a4 100755 --- a/src/server/game/Instances/InstanceScript.h +++ b/src/server/game/Instances/InstanceScript.h @@ -21,6 +21,7 @@ #include "ZoneScript.h" #include "World.h" +#include "ObjectMgr.h" //#include "GameObject.h" //#include "Map.h" @@ -124,7 +125,8 @@ class InstanceScript : public ZoneScript { public: - explicit InstanceScript(Map *map) : instance(map) {} + explicit InstanceScript(Map* map) : instance(map), completedEncounters(0) {} + virtual ~InstanceScript() {} Map *instance; @@ -196,9 +198,14 @@ class InstanceScript : public ZoneScript // Checks boss requirements (one boss required to kill other) virtual bool CheckRequiredBosses(uint32 /*bossId*/, Player const* /*player*/ = NULL) const { return true; } + // Checks encounter state at kill/spellcast + void UpdateEncounterState(EncounterCreditType type, uint32 creditEntry, Unit* source); + + // Used only during loading + void SetCompletedEncountersMask(uint32 newMask) { completedEncounters = newMask; } + // Returns completed encounters mask for packets - // NOTE: MUST USE ENCOUNTER IDS FROM DungeonEncounter.dbc 4th column - virtual uint32 GetCompletedEncounterMask() const { return 0; } + uint32 GetCompletedEncounterMask() const { return completedEncounters; } void SendEncounterUnit(uint32 type, Unit* unit = NULL, uint8 param1 = 0, uint8 param2 = 0); @@ -219,6 +226,7 @@ class InstanceScript : public ZoneScript std::vector<BossInfo> bosses; DoorInfoMap doors; MinionInfoMap minions; + uint32 completedEncounters; // completed encounter mask, bit indexes are DungeonEncounter.dbc boss numbers, used for packets }; #endif diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index c4187ff626f..1e2e55a7cde 100755 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -2425,11 +2425,12 @@ void InstanceMap::CreateInstanceData(bool load) if (load) { // TODO: make a global storage for this - QueryResult result = CharacterDatabase.PQuery("SELECT data FROM instance WHERE map = '%u' AND id = '%u'", GetId(), i_InstanceId); + QueryResult result = CharacterDatabase.PQuery("SELECT data, completedEncounters FROM instance WHERE map = '%u' AND id = '%u'", GetId(), i_InstanceId); if (result) { Field* fields = result->Fetch(); std::string data = fields[0].GetString(); + i_data->SetCompletedEncountersMask(fields[1].GetUInt32()); if (data != "") { sLog->outDebug("Loading instance data for `%s` with id %u", sObjectMgr->GetScriptName(i_script_id), i_InstanceId); diff --git a/src/server/game/Server/Protocol/Handlers/LFGHandler.cpp b/src/server/game/Server/Protocol/Handlers/LFGHandler.cpp index 2ac129973a9..ac8ce189f4b 100755 --- a/src/server/game/Server/Protocol/Handlers/LFGHandler.cpp +++ b/src/server/game/Server/Protocol/Handlers/LFGHandler.cpp @@ -22,7 +22,7 @@ #include "Group.h" #include "LFGMgr.h" #include "ObjectMgr.h" - +#include "InstanceScript.h" void BuildPlayerLockDungeonBlock(WorldPacket& data, const LfgLockMap& lock) { @@ -555,6 +555,7 @@ void WorldSession::SendLfgUpdateProposal(uint32 proposalId, const LfgProposal* p bool isSameDungeon = false; bool isContinue = false; Group* grp = dLowGuid ? sObjectMgr->GetGroupByGUID(dLowGuid) : NULL; + uint32 completedEncounters = 0; if (grp) { uint64 gguid = grp->GetGUID(); @@ -571,12 +572,31 @@ void WorldSession::SendLfgUpdateProposal(uint32 proposalId, const LfgProposal* p if (playerDungeons.size() == 1) dungeonId = (*playerDungeons.begin()); } + if (LFGDungeonEntry const* dungeon = sLFGDungeonStore.LookupEntry(dungeonId)) + { dungeonId = dungeon->Entry(); + + // Select a player inside to be get completed encounters from + if (grp) + { + for (GroupReference* itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) + { + Player* groupMember = itr->getSource(); + if (groupMember && groupMember->GetMapId() == uint32(dungeon->map)) + { + if (InstanceScript* instance = groupMember->GetInstanceScript()) + completedEncounters = instance->GetCompletedEncounterMask(); + break; + } + } + } + } + data << uint32(dungeonId); // Dungeon data << uint8(pProp->state); // Result state data << uint32(proposalId); // Internal Proposal ID - data << uint32(0); // Bosses killed - FIXME + data << uint32(completedEncounters); // Bosses killed data << uint8(isSameDungeon); // Silent (show client window) data << uint8(pProp->players.size()); // Group size diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 2cc6d08c0be..f0ecb5307b6 100755 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -51,6 +51,7 @@ #include "ConditionMgr.h" #include "DisableMgr.h" #include "SpellScript.h" +#include "InstanceScript.h" #define SPELL_CHANNEL_UPDATE_INTERVAL (1 * IN_MILLISECONDS) @@ -3717,16 +3718,17 @@ void Spell::finish(bool ok) // triggered spell pointer can be not set in some cases // this is needed for proper apply of triggered spell mods m_caster->ToPlayer()->SetSpellModTakingSpell(this, true); - } - // Take mods after trigger spell (needed for 14177 to affect 48664) - // mods are taken only on succesfull cast and independantly from targets of the spell - if (m_caster->GetTypeId() == TYPEID_PLAYER) - { + // Take mods after trigger spell (needed for 14177 to affect 48664) + // mods are taken only on succesfull cast and independantly from targets of the spell m_caster->ToPlayer()->RemoveSpellMods(this); m_caster->ToPlayer()->SetSpellModTakingSpell(this, false); } + if (m_caster->GetTypeId() == TYPEID_UNIT) + if (InstanceScript* instance = m_caster->GetInstanceScript()) + instance->UpdateEncounterState(ENCOUNTER_CREDIT_CAST_SPELL, m_spellInfo->Id, m_caster); + // Stop Attack for some spells if (m_spellInfo->Attributes & SPELL_ATTR0_STOP_ATTACK_TARGET) m_caster->AttackStop(); diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 08193860413..ab5071a18bd 100755 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -1403,7 +1403,7 @@ void World::SetInitialWorldSettings() sGameEventMgr->LoadFromDB(); // TODOLEAK: add scopes sLog->outString("Loading Dungeon boss data..."); - sLFGMgr->LoadDungeonEncounters(); + sObjectMgr->LoadInstanceEncounters(); sLog->outString("Loading LFG rewards..."); sLFGMgr->LoadRewards(); |
