From 2b1a8004ba70bdcf077f78d700b10484d445f562 Mon Sep 17 00:00:00 2001 From: Gigatotem Date: Sun, 7 Oct 2012 13:44:05 +0200 Subject: Spells/Hunter: Readiness Fixes Readiness resetting the cooldown of Gift of the Naaru. Needs testing --- src/server/scripts/Spells/spell_hunter.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/server/scripts/Spells/spell_hunter.cpp b/src/server/scripts/Spells/spell_hunter.cpp index 9c922f2c6fb..9d0e084cfb8 100644 --- a/src/server/scripts/Spells/spell_hunter.cpp +++ b/src/server/scripts/Spells/spell_hunter.cpp @@ -32,6 +32,7 @@ enum HunterSpells { HUNTER_SPELL_READINESS = 23989, + DRAENEI_SPELL_GIFT_OF_THE_NAARU = 59543, HUNTER_SPELL_BESTIAL_WRATH = 19574, HUNTER_PET_SPELL_LAST_STAND_TRIGGERED = 53479, HUNTER_PET_HEART_OF_THE_PHOENIX = 55709, @@ -340,6 +341,7 @@ class spell_hun_readiness : public SpellScriptLoader spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER && spellInfo->Id != HUNTER_SPELL_READINESS && spellInfo->Id != HUNTER_SPELL_BESTIAL_WRATH && + spellInfo->Id != DRAENEI_SPELL_GIFT_OF_THE_NAARU && spellInfo->GetRecoveryTime() > 0) caster->RemoveSpellCooldown((itr++)->first, true); else -- cgit v1.2.3 From d49c2a5e4d66b1f4bd4bdff3d6ed92902e8565f8 Mon Sep 17 00:00:00 2001 From: tibbi Date: Sun, 7 Oct 2012 13:55:04 +0100 Subject: correct reputation converting at faction change --- src/server/game/Globals/ObjectMgr.cpp | 22 +++++++++ src/server/game/Globals/ObjectMgr.h | 2 + src/server/game/Handlers/CharacterHandler.cpp | 55 +++++++++++++++++++--- .../Database/Implementation/CharacterDatabase.cpp | 3 +- .../Database/Implementation/CharacterDatabase.h | 1 + 5 files changed, 75 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 95a27fd14e1..ea4386c4d41 100755 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -7590,6 +7590,28 @@ SpellScriptsBounds ObjectMgr::GetSpellScriptsBounds(uint32 spell_id) return SpellScriptsBounds(_spellScriptsStore.lower_bound(spell_id), _spellScriptsStore.upper_bound(spell_id)); } +// this allows calculating base reputations to offline players, just by race and class +int32 ObjectMgr::GetBaseReputation(FactionEntry const* factionEntry, uint8 race, uint32 playerClass) +{ + if (!factionEntry) + return 0; + + uint32 raceMask = (1 << (race - 1)); + uint32 classMask = (1 << (playerClass-1)); + + for (int i=0; i < 4; i++) + { + if ((factionEntry->BaseRepRaceMask[i] & raceMask || + (factionEntry->BaseRepRaceMask[i] == 0 && + factionEntry->BaseRepClassMask[i] != 0)) && + (factionEntry->BaseRepClassMask[i] & classMask || + factionEntry->BaseRepClassMask[i] == 0)) + return factionEntry->BaseRepValue[i]; + } + + return 0; +} + SkillRangeType GetSkillRangeType(SkillLineEntry const* pSkill, bool racial) { switch (pSkill->categoryId) diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h index bbd95e22685..81ca02af5d9 100755 --- a/src/server/game/Globals/ObjectMgr.h +++ b/src/server/game/Globals/ObjectMgr.h @@ -749,6 +749,8 @@ class ObjectMgr return NULL; } + int32 GetBaseReputation(FactionEntry const* factionEntry, uint8 race, uint32 playerClass); + RepSpilloverTemplate const* GetRepSpilloverTemplate(uint32 factionId) const { RepSpilloverTemplateContainer::const_iterator itr = _repSpilloverTemplateStore.find(factionId); diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index 5c603e46086..30bc6df0539 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -1625,11 +1625,23 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recv_data) uint32 lowGuid = GUID_LOPART(guid); - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_CLASS_LVL_AT_LOGIN); + // get the players old (at this moment current) race + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_RACE); + stmt->setUInt32(0, guid); + PreparedQueryResult result = CharacterDatabase.Query(stmt); + if (!result) + { + WorldPacket data(SMSG_CHAR_FACTION_CHANGE, 1); + data << uint8(CHAR_CREATE_ERROR); + SendPacket(&data); + return; + } + Field* fields = result->Fetch(); + uint8 oldRace = fields[0].GetUInt8(); + stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_CLASS_LVL_AT_LOGIN); stmt->setUInt32(0, lowGuid); - - PreparedQueryResult result = CharacterDatabase.Query(stmt); + result = CharacterDatabase.Query(stmt); if (!result) { @@ -1639,7 +1651,7 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recv_data) return; } - Field* fields = result->Fetch(); + fields = result->Fetch(); uint32 playerClass = uint32(fields[0].GetUInt8()); uint32 level = uint32(fields[1].GetUInt8()); uint32 at_loginFlags = fields[2].GetUInt16(); @@ -2004,15 +2016,44 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recv_data) uint32 reputation_alliance = it->first; uint32 reputation_horde = it->second; - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_REP_BY_FACTION); + // select old standing set in db + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_REP_BY_FACTION); + stmt->setUInt32(0, team == TEAM_ALLIANCE ? reputation_horde : reputation_alliance); + stmt->setUInt32(1, lowGuid); + PreparedQueryResult result = CharacterDatabase.Query(stmt); + + if (!result) + { + WorldPacket data(SMSG_CHAR_FACTION_CHANGE, 1); + data << uint8(CHAR_CREATE_ERROR); + SendPacket(&data); + return; + } + + Field* fields = result->Fetch(); + int32 oldDBRep = fields[0].GetInt32(); + FactionEntry const* factionEntry = sFactionStore.LookupEntry(team == TEAM_ALLIANCE ? reputation_horde : reputation_alliance); + + // old base reputation + int32 oldBaseRep = sObjectMgr->GetBaseReputation(factionEntry, oldRace, playerClass); + + // new base reputation + int32 newBaseRep = sObjectMgr->GetBaseReputation(sFactionStore.LookupEntry(team == TEAM_ALLIANCE ? reputation_alliance : reputation_horde), race, playerClass); + + // final reputation shouldnt change + int32 FinalRep = oldDBRep + oldBaseRep; + int32 newDBRep = FinalRep - newBaseRep; + + stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_REP_BY_FACTION); stmt->setUInt32(0, uint16(team == TEAM_ALLIANCE ? reputation_alliance : reputation_horde)); stmt->setUInt32(1, lowGuid); trans->Append(stmt); stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_REP_FACTION_CHANGE); stmt->setUInt16(0, uint16(team == TEAM_ALLIANCE ? reputation_alliance : reputation_horde)); - stmt->setUInt16(1, uint16(team == TEAM_ALLIANCE ? reputation_horde : reputation_alliance)); - stmt->setUInt32(2, lowGuid); + stmt->setInt32(1, newDBRep); + stmt->setUInt16(2, uint16(team == TEAM_ALLIANCE ? reputation_horde : reputation_alliance)); + stmt->setUInt32(3, lowGuid); trans->Append(stmt); } diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.cpp b/src/server/shared/Database/Implementation/CharacterDatabase.cpp index add782cf517..4396f67244a 100644 --- a/src/server/shared/Database/Implementation/CharacterDatabase.cpp +++ b/src/server/shared/Database/Implementation/CharacterDatabase.cpp @@ -497,8 +497,9 @@ void CharacterDatabaseConnection::DoPrepareStatements() PREPARE_STATEMENT(CHAR_UPD_CHAR_INVENTORY_FACTION_CHANGE, "UPDATE item_instance ii, character_inventory ci SET ii.itemEntry = ? WHERE ii.itemEntry = ? AND ci.guid = ? AND ci.item = ii.guid", CONNECTION_ASYNC); PREPARE_STATEMENT(CHAR_DEL_CHAR_SPELL_BY_SPELL, "DELETE FROM character_spell WHERE spell = ? AND guid = ?", CONNECTION_ASYNC); PREPARE_STATEMENT(CHAR_UPD_CHAR_SPELL_FACTION_CHANGE, "UPDATE character_spell SET spell = ? where spell = ? AND guid = ?", CONNECTION_ASYNC); + PREPARE_STATEMENT(CHAR_SEL_CHAR_REP_BY_FACTION, "SELECT standing FROM character_reputation WHERE faction = ? AND guid = ?", CONNECTION_SYNCH); PREPARE_STATEMENT(CHAR_DEL_CHAR_REP_BY_FACTION, "DELETE FROM character_reputation WHERE faction = ? AND guid = ?", CONNECTION_ASYNC); - PREPARE_STATEMENT(CHAR_UPD_CHAR_REP_FACTION_CHANGE, "UPDATE character_reputation SET faction = ? where faction = ? AND guid = ?", CONNECTION_ASYNC); + PREPARE_STATEMENT(CHAR_UPD_CHAR_REP_FACTION_CHANGE, "UPDATE character_reputation SET faction = ?, standing = ? WHERE faction = ? AND guid = ?", CONNECTION_ASYNC); PREPARE_STATEMENT(CHAR_UPD_CHAR_TITLES_FACTION_CHANGE, "UPDATE characters SET knownTitles = ? WHERE guid = ?", CONNECTION_ASYNC); PREPARE_STATEMENT(CHAR_RES_CHAR_TITLES_FACTION_CHANGE, "UPDATE characters SET chosenTitle = 0 WHERE guid = ?", CONNECTION_ASYNC); PREPARE_STATEMENT(CHAR_DEL_CHAR_SPELL_COOLDOWN, "DELETE FROM character_spell_cooldown WHERE guid = ?", CONNECTION_ASYNC); diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.h b/src/server/shared/Database/Implementation/CharacterDatabase.h index fedf0022fcc..95b059de95c 100644 --- a/src/server/shared/Database/Implementation/CharacterDatabase.h +++ b/src/server/shared/Database/Implementation/CharacterDatabase.h @@ -460,6 +460,7 @@ enum CharacterDatabaseStatements CHAR_UPD_CHAR_INVENTORY_FACTION_CHANGE, CHAR_DEL_CHAR_SPELL_BY_SPELL, CHAR_UPD_CHAR_SPELL_FACTION_CHANGE, + CHAR_SEL_CHAR_REP_BY_FACTION, CHAR_DEL_CHAR_REP_BY_FACTION, CHAR_UPD_CHAR_REP_FACTION_CHANGE, CHAR_UPD_CHAR_TITLES_FACTION_CHANGE, -- cgit v1.2.3 From 9835f4098f55d60436538839a1698ce5464ae290 Mon Sep 17 00:00:00 2001 From: tibbi Date: Sun, 7 Oct 2012 16:06:40 +0100 Subject: correcting SotA demolisher spawn, adding preparation buff to 2nd round too, lowering start height for attackers --- .../game/Battlegrounds/Zones/BattlegroundSA.cpp | 147 +++++++++++++-------- .../game/Battlegrounds/Zones/BattlegroundSA.h | 45 ++++--- 2 files changed, 119 insertions(+), 73 deletions(-) (limited to 'src') diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp index eae1c1e3545..35304bc9190 100755 --- a/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp @@ -74,7 +74,7 @@ bool BattlegroundSA::ResetObjs() uint32 atF = BG_SA_Factions[Attackers]; uint32 defF = BG_SA_Factions[Attackers ? TEAM_ALLIANCE : TEAM_HORDE]; - for (uint8 i = 0; i SetUInt32Value(GAMEOBJECT_FACTION, atF); } - //Player may enter BEFORE we set up bG - lets update his worldstates anyway... - UpdateWorldState(BG_SA_RIGHT_GY_HORDE, GraveyardStatus[BG_SA_RIGHT_CAPTURABLE_GY] == TEAM_HORDE?1:0); - UpdateWorldState(BG_SA_LEFT_GY_HORDE, GraveyardStatus[BG_SA_LEFT_CAPTURABLE_GY] == TEAM_HORDE?1:0); - UpdateWorldState(BG_SA_CENTER_GY_HORDE, GraveyardStatus[BG_SA_CENTRAL_CAPTURABLE_GY] == TEAM_HORDE?1:0); + //Player may enter BEFORE we set up BG - lets update his worldstates anyway... + UpdateWorldState(BG_SA_RIGHT_GY_HORDE, GraveyardStatus[BG_SA_RIGHT_CAPTURABLE_GY] == TEAM_HORDE ? 1 : 0); + UpdateWorldState(BG_SA_LEFT_GY_HORDE, GraveyardStatus[BG_SA_LEFT_CAPTURABLE_GY] == TEAM_HORDE ? 1 : 0); + UpdateWorldState(BG_SA_CENTER_GY_HORDE, GraveyardStatus[BG_SA_CENTRAL_CAPTURABLE_GY] == TEAM_HORDE ? 1 : 0); - UpdateWorldState(BG_SA_RIGHT_GY_ALLIANCE, GraveyardStatus[BG_SA_RIGHT_CAPTURABLE_GY] == TEAM_ALLIANCE?1:0); - UpdateWorldState(BG_SA_LEFT_GY_ALLIANCE, GraveyardStatus[BG_SA_LEFT_CAPTURABLE_GY] == TEAM_ALLIANCE?1:0); - UpdateWorldState(BG_SA_CENTER_GY_ALLIANCE, GraveyardStatus[BG_SA_CENTRAL_CAPTURABLE_GY] == TEAM_ALLIANCE?1:0); + UpdateWorldState(BG_SA_RIGHT_GY_ALLIANCE, GraveyardStatus[BG_SA_RIGHT_CAPTURABLE_GY] == TEAM_ALLIANCE ? 1 : 0); + UpdateWorldState(BG_SA_LEFT_GY_ALLIANCE, GraveyardStatus[BG_SA_LEFT_CAPTURABLE_GY] == TEAM_ALLIANCE ? 1 : 0); + UpdateWorldState(BG_SA_CENTER_GY_ALLIANCE, GraveyardStatus[BG_SA_CENTRAL_CAPTURABLE_GY] == TEAM_ALLIANCE ? 1 : 0); if (Attackers == TEAM_ALLIANCE) { @@ -254,6 +257,9 @@ bool BattlegroundSA::ResetObjs() if (Player* player = ObjectAccessor::FindPlayer(itr->first)) SendTransportInit(player); + // set status manually so preparation is cast correctly in 2nd round too + SetStatus(STATUS_WAIT_JOIN); + TeleportPlayers(); return true; } @@ -295,7 +301,8 @@ void BattlegroundSA::PostUpdateImpl(uint32 diff) InitSecondRound = false; SendMessageToAll(LANG_BG_SA_ROUND_TWO_ONE_MINUTE, CHAT_MSG_BG_SYSTEM_NEUTRAL); } - }else + } + else { UpdateWaitTimer -= diff; return; @@ -312,7 +319,7 @@ void BattlegroundSA::PostUpdateImpl(uint32 diff) ToggleTimer(); DemolisherStartState(false); Status = BG_SA_ROUND_ONE; - StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, (Attackers == TEAM_ALLIANCE)?23748:21702); + StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, (Attackers == TEAM_ALLIANCE) ? 23748 : 21702); } if (TotalTime >= BG_SA_BOAT_START) StartShips(); @@ -332,7 +339,12 @@ void BattlegroundSA::PostUpdateImpl(uint32 diff) ToggleTimer(); DemolisherStartState(false); Status = BG_SA_ROUND_TWO; - StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, (Attackers == TEAM_ALLIANCE)?23748:21702); + StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, (Attackers == TEAM_ALLIANCE) ? 23748 : 21702); + // status was set to STATUS_WAIT_JOIN manually for Preparation, set it back now + SetStatus(STATUS_IN_PROGRESS); + for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr) + if (Player* p = ObjectAccessor::FindPlayer(itr->first)) + p->RemoveAurasDueToSpell(SPELL_PREPARATION); } if (TotalTime >= 30000) { @@ -371,7 +383,6 @@ void BattlegroundSA::PostUpdateImpl(uint32 diff) { RoundScores[1].time = BG_SA_ROUNDLENGTH; RoundScores[1].winner = (Attackers == TEAM_ALLIANCE) ? TEAM_HORDE : TEAM_ALLIANCE; - if (RoundScores[0].time == RoundScores[1].time) EndBattleground(0); else if (RoundScores[0].time < RoundScores[1].time) @@ -411,7 +422,7 @@ void BattlegroundSA::FillInitialWorldStates(WorldPacket& data) data << uint32(BG_SA_BONUS_TIMER) << uint32(0); - data << uint32(BG_SA_HORDE_ATTACKS)<< horde_attacks; + data << uint32(BG_SA_HORDE_ATTACKS) << horde_attacks; data << uint32(BG_SA_ALLY_ATTACKS) << ally_attacks; //Time will be sent on first update... @@ -420,13 +431,13 @@ void BattlegroundSA::FillInitialWorldStates(WorldPacket& data) data << uint32(BG_SA_TIMER_SEC_TENS) << uint32(0); data << uint32(BG_SA_TIMER_SEC_DECS) << uint32(0); - data << uint32(BG_SA_RIGHT_GY_HORDE) << uint32(GraveyardStatus[BG_SA_RIGHT_CAPTURABLE_GY] == TEAM_HORDE?1:0); - data << uint32(BG_SA_LEFT_GY_HORDE) << uint32(GraveyardStatus[BG_SA_LEFT_CAPTURABLE_GY] == TEAM_HORDE?1:0); - data << uint32(BG_SA_CENTER_GY_HORDE) << uint32(GraveyardStatus[BG_SA_CENTRAL_CAPTURABLE_GY] == TEAM_HORDE?1:0); + data << uint32(BG_SA_RIGHT_GY_HORDE) << uint32(GraveyardStatus[BG_SA_RIGHT_CAPTURABLE_GY] == TEAM_HORDE ? 1 : 0); + data << uint32(BG_SA_LEFT_GY_HORDE) << uint32(GraveyardStatus[BG_SA_LEFT_CAPTURABLE_GY] == TEAM_HORDE ? 1 : 0); + data << uint32(BG_SA_CENTER_GY_HORDE) << uint32(GraveyardStatus[BG_SA_CENTRAL_CAPTURABLE_GY] == TEAM_HORDE ? 1 : 0); - data << uint32(BG_SA_RIGHT_GY_ALLIANCE) << uint32(GraveyardStatus[BG_SA_RIGHT_CAPTURABLE_GY] == TEAM_ALLIANCE?1:0); - data << uint32(BG_SA_LEFT_GY_ALLIANCE) << uint32(GraveyardStatus[BG_SA_LEFT_CAPTURABLE_GY] == TEAM_ALLIANCE?1:0); - data << uint32(BG_SA_CENTER_GY_ALLIANCE) << uint32(GraveyardStatus[BG_SA_CENTRAL_CAPTURABLE_GY] == TEAM_ALLIANCE?1:0); + data << uint32(BG_SA_RIGHT_GY_ALLIANCE) << uint32(GraveyardStatus[BG_SA_RIGHT_CAPTURABLE_GY] == TEAM_ALLIANCE ? 1 : 0); + data << uint32(BG_SA_LEFT_GY_ALLIANCE) << uint32(GraveyardStatus[BG_SA_LEFT_CAPTURABLE_GY] == TEAM_ALLIANCE ? 1 : 0); + data << uint32(BG_SA_CENTER_GY_ALLIANCE) << uint32(GraveyardStatus[BG_SA_CENTRAL_CAPTURABLE_GY] == TEAM_ALLIANCE ? 1 : 0); data << uint32(BG_SA_HORDE_DEFENCE_TOKEN) << ally_attacks; data << uint32(BG_SA_ALLIANCE_DEFENCE_TOKEN) << horde_attacks; @@ -450,9 +461,9 @@ void BattlegroundSA::AddPlayer(Player* player) player->CastSpell(player, 12438, true);//Without this player falls before boat loads... if (urand(0, 1)) - player->TeleportTo(607, 2682.936f, -830.368f, 50.0f, 2.895f, 0); + player->TeleportTo(607, 2682.936f, -830.368f, 15.0f, 2.895f, 0); else - player->TeleportTo(607, 2577.003f, 980.261f, 50.0f, 0.807f, 0); + player->TeleportTo(607, 2577.003f, 980.261f, 15.0f, 0.807f, 0); } else @@ -513,14 +524,18 @@ void BattlegroundSA::TeleportPlayers() player->ResetAllPowers(); player->CombatStopWithPets(true); + for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr) + if (Player* p = ObjectAccessor::FindPlayer(itr->first)) + p->CastSpell(p, SPELL_PREPARATION, true); + if (player->GetTeamId() == Attackers) { player->CastSpell(player, 12438, true); //Without this player falls before boat loads... if (urand(0, 1)) - player->TeleportTo(607, 2682.936f, -830.368f, 50.0f, 2.895f, 0); + player->TeleportTo(607, 2682.936f, -830.368f, 15.0f, 2.895f, 0); else - player->TeleportTo(607, 2577.003f, 980.261f, 50.0f, 0.807f, 0); + player->TeleportTo(607, 2577.003f, 980.261f, 15.0f, 0.807f, 0); } else player->TeleportTo(607, 1209.7f, -65.16f, 70.1f, 0.0f, 0); @@ -572,13 +587,13 @@ void BattlegroundSA::OverrideGunFaction() if (!BgCreatures[0]) return; - for (uint8 i = BG_SA_GUN_1; i <= BG_SA_GUN_10;i++) + for (uint8 i = BG_SA_GUN_1; i <= BG_SA_GUN_10; i++) { if (Creature* gun = GetBGCreature(i)) - gun->setFaction(BG_SA_Factions[Attackers? TEAM_ALLIANCE : TEAM_HORDE]); + gun->setFaction(BG_SA_Factions[Attackers ? TEAM_ALLIANCE : TEAM_HORDE]); } - for (uint8 i = BG_SA_DEMOLISHER_1; i <= BG_SA_DEMOLISHER_4;i++) + for (uint8 i = BG_SA_DEMOLISHER_1; i <= BG_SA_DEMOLISHER_4; i++) { if (Creature* dem = GetBGCreature(i)) dem->setFaction(BG_SA_Factions[Attackers]); @@ -590,6 +605,7 @@ void BattlegroundSA::DemolisherStartState(bool start) if (!BgCreatures[0]) return; + // set flags only for the demolishers on the beach, factory ones dont need it for (uint8 i = BG_SA_DEMOLISHER_1; i <= BG_SA_DEMOLISHER_4; i++) { if (Creature* dem = GetBGCreature(i)) @@ -636,6 +652,8 @@ void BattlegroundSA::DestroyGate(Player* player, GameObject* go) if (GateStatus[BG_SA_RED_GATE] == BG_SA_GATE_DESTROYED) rewardHonor = false; break; + default: + break; } if (i < 5) @@ -663,7 +681,7 @@ WorldSafeLocsEntry const* BattlegroundSA::GetClosestGraveYard(Player* player) safeloc = BG_SA_GYEntries[BG_SA_DEFENDER_LAST_GY]; closest = sWorldSafeLocsStore.LookupEntry(safeloc); - nearest = sqrt((closest->x - x)*(closest->x - x) + (closest->y - y)*(closest->y - y)+(closest->z - z)*(closest->z - z)); + nearest = sqrt((closest->x - x)*(closest->x - x) + (closest->y - y)*(closest->y - y) + (closest->z - z)*(closest->z - z)); for (uint8 i = BG_SA_RIGHT_CAPTURABLE_GY; i < BG_SA_MAX_GY; i++) { @@ -671,7 +689,7 @@ WorldSafeLocsEntry const* BattlegroundSA::GetClosestGraveYard(Player* player) continue; ret = sWorldSafeLocsStore.LookupEntry(BG_SA_GYEntries[i]); - dist = sqrt((ret->x - x)*(ret->x - x) + (ret->y - y)*(ret->y - y)+(ret->z - z)*(ret->z - z)); + dist = sqrt((ret->x - x)*(ret->x - x) + (ret->y - y)*(ret->y - y) + (ret->z - z)*(ret->z - z)); if (dist < nearest) { closest = ret; @@ -737,7 +755,7 @@ void BattlegroundSA::CaptureGraveyard(BG_SA_Graveyards i, Player* Source) case BG_SA_LEFT_CAPTURABLE_GY: flag = BG_SA_LEFT_FLAG; DelObject(flag); - AddObject(flag, (BG_SA_ObjEntries[flag] - (Source->GetTeamId() == TEAM_ALLIANCE ? 0:1)), + AddObject(flag, (BG_SA_ObjEntries[flag] - (Source->GetTeamId() == TEAM_ALLIANCE ? 0 : 1)), BG_SA_ObjSpawnlocs[flag][0], BG_SA_ObjSpawnlocs[flag][1], BG_SA_ObjSpawnlocs[flag][2], BG_SA_ObjSpawnlocs[flag][3], 0, 0, 0, 0, RESPAWN_ONE_DAY); @@ -746,8 +764,18 @@ void BattlegroundSA::CaptureGraveyard(BG_SA_Graveyards i, Player* Source) BG_SA_NpcSpawnlocs[npc][0], BG_SA_NpcSpawnlocs[npc][1], BG_SA_NpcSpawnlocs[npc][2], BG_SA_NpcSpawnlocs[npc][3]); - UpdateWorldState(BG_SA_LEFT_GY_ALLIANCE, (GraveyardStatus[i] == TEAM_ALLIANCE? 1:0)); - UpdateWorldState(BG_SA_LEFT_GY_HORDE, (GraveyardStatus[i] == TEAM_ALLIANCE? 0:1)); + for (uint8 j = BG_SA_DEMOLISHER_7; j <= BG_SA_DEMOLISHER_8; j++) + { + AddCreature(BG_SA_NpcEntries[j], j, (Attackers == TEAM_ALLIANCE ? TEAM_HORDE : TEAM_ALLIANCE), + BG_SA_NpcSpawnlocs[j][0], BG_SA_NpcSpawnlocs[j][1], + BG_SA_NpcSpawnlocs[j][2], BG_SA_NpcSpawnlocs[j][3], 600); + + if (Creature* dem = GetBGCreature(j)) + dem->setFaction(BG_SA_Factions[Attackers]); + } + + UpdateWorldState(BG_SA_LEFT_GY_ALLIANCE, (GraveyardStatus[i] == TEAM_ALLIANCE ? 1 : 0)); + UpdateWorldState(BG_SA_LEFT_GY_HORDE, (GraveyardStatus[i] == TEAM_ALLIANCE ? 0 : 1)); if (Source->GetTeamId() == TEAM_ALLIANCE) SendWarningToAll(LANG_BG_SA_A_GY_WEST); else @@ -756,7 +784,7 @@ void BattlegroundSA::CaptureGraveyard(BG_SA_Graveyards i, Player* Source) case BG_SA_RIGHT_CAPTURABLE_GY: flag = BG_SA_RIGHT_FLAG; DelObject(flag); - AddObject(flag, (BG_SA_ObjEntries[flag] - (Source->GetTeamId() == TEAM_ALLIANCE ? 0:1)), + AddObject(flag, (BG_SA_ObjEntries[flag] - (Source->GetTeamId() == TEAM_ALLIANCE ? 0 : 1)), BG_SA_ObjSpawnlocs[flag][0], BG_SA_ObjSpawnlocs[flag][1], BG_SA_ObjSpawnlocs[flag][2], BG_SA_ObjSpawnlocs[flag][3], 0, 0, 0, 0, RESPAWN_ONE_DAY); @@ -765,8 +793,18 @@ void BattlegroundSA::CaptureGraveyard(BG_SA_Graveyards i, Player* Source) BG_SA_NpcSpawnlocs[npc][0], BG_SA_NpcSpawnlocs[npc][1], BG_SA_NpcSpawnlocs[npc][2], BG_SA_NpcSpawnlocs[npc][3]); - UpdateWorldState(BG_SA_RIGHT_GY_ALLIANCE, (GraveyardStatus[i] == TEAM_ALLIANCE? 1:0)); - UpdateWorldState(BG_SA_RIGHT_GY_HORDE, (GraveyardStatus[i] == TEAM_ALLIANCE? 0:1)); + for (uint8 j = BG_SA_DEMOLISHER_5; j <= BG_SA_DEMOLISHER_6; j++) + { + AddCreature(BG_SA_NpcEntries[j], j, (Attackers == TEAM_ALLIANCE ? TEAM_HORDE : TEAM_ALLIANCE), + BG_SA_NpcSpawnlocs[j][0], BG_SA_NpcSpawnlocs[j][1], + BG_SA_NpcSpawnlocs[j][2], BG_SA_NpcSpawnlocs[j][3], 600); + + if (Creature* dem = GetBGCreature(j)) + dem->setFaction(BG_SA_Factions[Attackers]); + } + + UpdateWorldState(BG_SA_RIGHT_GY_ALLIANCE, (GraveyardStatus[i] == TEAM_ALLIANCE ? 1 : 0)); + UpdateWorldState(BG_SA_RIGHT_GY_HORDE, (GraveyardStatus[i] == TEAM_ALLIANCE ? 0 : 1)); if (Source->GetTeamId() == TEAM_ALLIANCE) SendWarningToAll(LANG_BG_SA_A_GY_EAST); else @@ -775,12 +813,12 @@ void BattlegroundSA::CaptureGraveyard(BG_SA_Graveyards i, Player* Source) case BG_SA_CENTRAL_CAPTURABLE_GY: flag = BG_SA_CENTRAL_FLAG; DelObject(flag); - AddObject(flag, (BG_SA_ObjEntries[flag] - (Source->GetTeamId() == TEAM_ALLIANCE ? 0:1)), + AddObject(flag, (BG_SA_ObjEntries[flag] - (Source->GetTeamId() == TEAM_ALLIANCE ? 0 : 1)), BG_SA_ObjSpawnlocs[flag][0], BG_SA_ObjSpawnlocs[flag][1], BG_SA_ObjSpawnlocs[flag][2], BG_SA_ObjSpawnlocs[flag][3], 0, 0, 0, 0, RESPAWN_ONE_DAY); - UpdateWorldState(BG_SA_CENTER_GY_ALLIANCE, (GraveyardStatus[i] == TEAM_ALLIANCE? 1:0)); - UpdateWorldState(BG_SA_CENTER_GY_HORDE, (GraveyardStatus[i] == TEAM_ALLIANCE? 0:1)); + UpdateWorldState(BG_SA_CENTER_GY_ALLIANCE, (GraveyardStatus[i] == TEAM_ALLIANCE ? 1 : 0)); + UpdateWorldState(BG_SA_CENTER_GY_HORDE, (GraveyardStatus[i] == TEAM_ALLIANCE ? 0 : 1)); if (Source->GetTeamId() == TEAM_ALLIANCE) SendWarningToAll(LANG_BG_SA_A_GY_SOUTH); else @@ -794,7 +832,11 @@ void BattlegroundSA::CaptureGraveyard(BG_SA_Graveyards i, Player* Source) void BattlegroundSA::EventPlayerUsedGO(Player* Source, GameObject* object) { - if (object->GetEntry() == BG_SA_ObjEntries[BG_SA_TITAN_RELIC] && GateStatus[BG_SA_ANCIENT_GATE] == BG_SA_GATE_DESTROYED && GateStatus[BG_SA_YELLOW_GATE] == BG_SA_GATE_DESTROYED && (GateStatus[BG_SA_PURPLE_GATE] == BG_SA_GATE_DESTROYED || GateStatus[BG_SA_RED_GATE] == BG_SA_GATE_DESTROYED) && (GateStatus[BG_SA_GREEN_GATE] == BG_SA_GATE_DESTROYED || GateStatus[BG_SA_BLUE_GATE] == BG_SA_GATE_DESTROYED)) + if (object->GetEntry() == BG_SA_ObjEntries[BG_SA_TITAN_RELIC] && + GateStatus[BG_SA_ANCIENT_GATE] == BG_SA_GATE_DESTROYED && + GateStatus[BG_SA_YELLOW_GATE] == BG_SA_GATE_DESTROYED && + (GateStatus[BG_SA_PURPLE_GATE] == BG_SA_GATE_DESTROYED || GateStatus[BG_SA_RED_GATE] == BG_SA_GATE_DESTROYED) && + (GateStatus[BG_SA_GREEN_GATE] == BG_SA_GATE_DESTROYED || GateStatus[BG_SA_BLUE_GATE] == BG_SA_GATE_DESTROYED)) { if (Source->GetTeamId() == Attackers) { @@ -872,7 +914,7 @@ void BattlegroundSA::EndBattleground(uint32 winner) void BattlegroundSA::UpdateDemolisherSpawns() { - for (uint8 i = BG_SA_DEMOLISHER_1; i <= BG_SA_DEMOLISHER_4; i++) + for (uint8 i = BG_SA_DEMOLISHER_1; i <= BG_SA_DEMOLISHER_8; i++) { if (BgCreatures[i]) { @@ -881,21 +923,16 @@ void BattlegroundSA::UpdateDemolisherSpawns() if (Demolisher->isDead()) { // Demolisher is not in list - if (DemoliserRespawnList.find(i)==DemoliserRespawnList.end()) + if (DemoliserRespawnList.find(i) == DemoliserRespawnList.end()) { - DemoliserRespawnList[i]=getMSTime()+30000; + DemoliserRespawnList[i] = getMSTime()+30000; } else { if (DemoliserRespawnList[i] < getMSTime()) { - uint8 gy = (i >= BG_SA_DEMOLISHER_3 ? 3 : 2); - if (GraveyardStatus[gy] == Attackers) - Demolisher->Relocate(BG_SA_NpcSpawnlocs[i + 11][0], BG_SA_NpcSpawnlocs[i + 11][1], - BG_SA_NpcSpawnlocs[i + 11][2], BG_SA_NpcSpawnlocs[i + 11][3]); - else - Demolisher->Relocate(BG_SA_NpcSpawnlocs[i][0], BG_SA_NpcSpawnlocs[i][1], - BG_SA_NpcSpawnlocs[i][2], BG_SA_NpcSpawnlocs[i][3]); + Demolisher->Relocate(BG_SA_NpcSpawnlocs[i][0], BG_SA_NpcSpawnlocs[i][1], + BG_SA_NpcSpawnlocs[i][2], BG_SA_NpcSpawnlocs[i][3]); Demolisher->Respawn(); DemoliserRespawnList.erase(i); diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundSA.h b/src/server/game/Battlegrounds/Zones/BattlegroundSA.h index 748db56dc77..6de3731da50 100755 --- a/src/server/game/Battlegrounds/Zones/BattlegroundSA.h +++ b/src/server/game/Battlegrounds/Zones/BattlegroundSA.h @@ -126,15 +126,19 @@ enum BG_SA_NPCs BG_SA_GUN_8, BG_SA_GUN_9, BG_SA_GUN_10, - BG_SA_DEMOLISHER_1, - BG_SA_DEMOLISHER_2, - BG_SA_DEMOLISHER_3, - BG_SA_DEMOLISHER_4, BG_SA_NPC_TRIGGER_1, BG_SA_NPC_TRIGGER_2, BG_SA_NPC_TRIGGER_3, BG_SA_NPC_TRIGGER_4, BG_SA_NPC_TRIGGER_5, + BG_SA_DEMOLISHER_1, + BG_SA_DEMOLISHER_2, + BG_SA_DEMOLISHER_3, + BG_SA_DEMOLISHER_4, + BG_SA_DEMOLISHER_5, + BG_SA_DEMOLISHER_6, + BG_SA_DEMOLISHER_7, + BG_SA_DEMOLISHER_8, BG_SA_NPC_SPARKLIGHT, BG_SA_NPC_RIGSPARK, BG_SA_MAXNPC @@ -160,17 +164,22 @@ uint32 const BG_SA_NpcEntries[BG_SA_MAXNPC] = NPC_ANTI_PERSONNAL_CANNON, NPC_ANTI_PERSONNAL_CANNON, NPC_ANTI_PERSONNAL_CANNON, - // 4 beach demolishers - NPC_DEMOLISHER_SA, - NPC_DEMOLISHER_SA, - NPC_DEMOLISHER_SA, - NPC_DEMOLISHER_SA, // Triggers 23472, 23472, 23472, 23472, 23472, + // 4 beach demolishers + NPC_DEMOLISHER_SA, + NPC_DEMOLISHER_SA, + NPC_DEMOLISHER_SA, + NPC_DEMOLISHER_SA, + // 4 factory demolishers + NPC_DEMOLISHER_SA, + NPC_DEMOLISHER_SA, + NPC_DEMOLISHER_SA, + NPC_DEMOLISHER_SA, // Used Demolisher Salesman NPC_RIGGER_SPARKLIGHT, NPC_GORGRIL_RIGSPARK @@ -189,25 +198,25 @@ float const BG_SA_NpcSpawnlocs[BG_SA_MAXNPC + BG_SA_DEMOLISHER_AMOUNT][4] = { 1249.634f, -224.189f, 66.72f, 0.635f }, { 1236.213f, 92.287f, 64.965f, 5.751f }, { 1215.11f, 57.772f, 64.739f, 5.78f }, - // Demolishers - { 1611.597656f, -117.270073f, 8.719355f, 2.513274f}, - { 1575.562500f, -158.421875f, 5.024450f, 2.129302f}, - { 1618.047729f, 61.424641f, 7.248210f, 3.979351f}, - { 1575.103149f, 98.873344f, 2.830360f, 3.752458f}, // Triggers { 1453.49f, -250.453f, 30.896f, 4.2883f}, { 1377.05f, 97.036f, 30.8605f, 2.46539f}, { 1186.05f, 58.8048f, 56.5491f, 2.75992f}, { 1042.83f, -72.839f, 84.8145f, 3.58615f}, { 1233.62f, -250.49f, 55.4036f, 3.7016f}, - // Npcs - { 1348.644165f, -298.786469f, 31.080130f, 1.710423f}, - { 1358.191040f, 195.527786f, 31.018187f, 4.171337f}, + // Demolishers + { 1611.597656f, -117.270073f, 8.719355f, 2.513274f}, + { 1575.562500f, -158.421875f, 5.024450f, 2.129302f}, + { 1618.047729f, 61.424641f, 7.248210f, 3.979351f}, + { 1575.103149f, 98.873344f, 2.830360f, 3.752458f}, // Demolishers 2 { 1371.055786f, -317.071136f, 35.007359f, 1.947460f}, { 1424.034912f, -260.195190f, 31.084425f, 2.820013f}, { 1353.139893f, 223.745438f, 35.265411f, 4.343684f}, - { 1404.809570f, 197.027237f, 32.046032f, 3.605401f} + { 1404.809570f, 197.027237f, 32.046032f, 3.605401f}, + // Npcs + { 1348.644165f, -298.786469f, 31.080130f, 1.710423f}, + { 1358.191040f, 195.527786f, 31.018187f, 4.171337f} }; enum BG_SA_Objects -- cgit v1.2.3 From 0aa63988654e2e436974615575ddb8bf2be9c8ab Mon Sep 17 00:00:00 2001 From: Retriman Date: Sun, 7 Oct 2012 11:51:56 -0400 Subject: Core/Misc: Not produce the error "can not do that while moving" to dismount. --- src/server/game/Spells/Auras/SpellAuraEffects.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index f28a02a52fc..4fa0468cf35 100755 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -2863,6 +2863,7 @@ void AuraEffect::HandleAuraAllowFlight(AuraApplication const* aurApp, uint8 mode { target->RemoveUnitMovementFlag(MOVEMENTFLAG_MASK_MOVING_FLY); target->GetMotionMaster()->MoveFall(); + target->m_movementInfo.SetFallTime(0); } Player* player = target->ToPlayer(); -- cgit v1.2.3 From 76d19ede4f9a315f85df3f458e69f13619547ba0 Mon Sep 17 00:00:00 2001 From: Retriman Date: Sun, 7 Oct 2012 14:36:53 -0400 Subject: Core/Misc: Shapeshift druid flying now displays an animation of falling. --- src/server/game/Spells/Auras/SpellAuraEffects.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index f28a02a52fc..a8b37581c19 100755 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -3254,9 +3254,8 @@ void AuraEffect::HandleAuraModIncreaseFlightSpeed(AuraApplication const* aurApp, target->SetCanFly(apply); if (!apply) { - target->RemoveUnitMovementFlag(MOVEMENTFLAG_FLYING); - target->AddUnitMovementFlag(MOVEMENTFLAG_FALLING); target->m_movementInfo.SetFallTime(0); + target->RemoveUnitMovementFlag(MOVEMENTFLAG_MASK_MOVING_FLY); } Player* player = target->ToPlayer(); -- cgit v1.2.3 From 3c2a5239805f37d2167377fa9c06e369b624c53b Mon Sep 17 00:00:00 2001 From: Retriman Date: Sun, 7 Oct 2012 14:46:29 -0400 Subject: Core/Spells:Ranged spells cant be parried or dodged. --- src/server/game/Entities/Unit/Unit.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 0a3876c6946..d60ad3899d8 100755 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -2302,6 +2302,9 @@ SpellMissInfo Unit::MeleeSpellHitResult(Unit* victim, SpellInfo const* spell) // Ranged attacks can only miss, resist and deflect if (attType == RANGED_ATTACK) { + canParry = false; + canDodge = false; + // only if in front if (victim->HasInArc(M_PI, this) || victim->HasAuraType(SPELL_AURA_IGNORE_HIT_DIRECTION)) { -- cgit v1.2.3 From 42d606a81bf347bb5bcd185d994a494c6c5dc986 Mon Sep 17 00:00:00 2001 From: Subv Date: Sun, 7 Oct 2012 19:02:59 -0500 Subject: Core/Spells: Fixed a crash caused by Beacon of Light. GroupReference sources should always be checked against NULL pointers. --- src/server/game/Entities/Unit/Unit.cpp | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 54559507cf4..7c59c8421ed 100755 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -6637,7 +6637,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere return false; triggered_spell_id = 0; Unit* beaconTarget = NULL; - if (this->GetTypeId() != TYPEID_PLAYER) + if (GetTypeId() != TYPEID_PLAYER) { beaconTarget = triggeredByAura->GetBase()->GetCaster(); if (beaconTarget == this || !(beaconTarget->GetAura(53563, victim->GetGUID()))) @@ -6647,23 +6647,24 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere } else { // Check Party/Raid Group - if (Group *group = this->ToPlayer()->GetGroup()) + if (Group* group = ToPlayer()->GetGroup()) { - for (GroupReference *itr = group->GetFirstMember(); itr != NULL; itr = itr->next()) + for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next()) { - Player* Member = itr->getSource(); - - // check if it was heal by paladin which casted this beacon of light - if (Member->GetAura(53563, victim->GetGUID())) + if (Player* member = itr->getSource()) { - // do not proc when target of beacon of light is healed - if (Member == this) - return false; + // check if it was heal by paladin which casted this beacon of light + if (member->GetAura(53563, victim->GetGUID())) + { + // do not proc when target of beacon of light is healed + if (member == this) + return false; - beaconTarget = Member; - basepoints0 = int32(damage); - triggered_spell_id = procSpell->IsRankOf(sSpellMgr->GetSpellInfo(635)) ? 53652 : 53654; - break; + beaconTarget = member; + basepoints0 = int32(damage); + triggered_spell_id = procSpell->IsRankOf(sSpellMgr->GetSpellInfo(635)) ? 53652 : 53654; + break; + } } } } @@ -6674,8 +6675,8 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere victim->CastCustomSpell(beaconTarget, triggered_spell_id, &basepoints0, NULL, NULL, true, 0, triggeredByAura); return true; } - else - return false; + + return false; } // Judgements of the Wise if (dummySpell->SpellIconID == 3017) -- cgit v1.2.3 From 4dc28e94204ca006b7f3593aba7fa058d427070e Mon Sep 17 00:00:00 2001 From: Subv Date: Sun, 7 Oct 2012 19:31:13 -0500 Subject: Core/SAI: Fixes crashes when using SMART_EVENT_[IC/OOC]_LOS It should also fix some wrong behaviors in scripts that use these events. --- src/server/game/AI/SmartScripts/SmartScript.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index f37ae4fa60e..49023b2d5b5 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -2821,9 +2821,10 @@ void SmartScript::InitTimer(SmartScriptHolder& e) case SMART_EVENT_UPDATE: case SMART_EVENT_UPDATE_IC: case SMART_EVENT_UPDATE_OOC: - case SMART_EVENT_OOC_LOS: - case SMART_EVENT_IC_LOS: RecalcTimer(e, e.event.minMaxRepeat.min, e.event.minMaxRepeat.max); + case SMART_EVENT_IC_LOS: + case SMART_EVENT_OOC_LOS: + RecalcTimer(e, e.event.los.cooldownMin, e.event.los.cooldownMax); break; default: e.active = true; -- cgit v1.2.3 From 0f166336caaf33eb01cffe19d5bb49f729d8d22d Mon Sep 17 00:00:00 2001 From: trickerer Date: Sun, 7 Oct 2012 19:42:06 -0500 Subject: Core/Entities: Do not create the model twice for a GameObject. Should fix #5218 (Still need to check) --- src/server/game/Entities/GameObject/GameObject.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index da6e4ef8407..c9874932e3e 100755 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -217,7 +217,6 @@ bool GameObject::Create(uint32 guidlow, uint32 name_id, Map* map, uint32 phaseMa SetDisplayId(goinfo->displayId); - m_model = GameObjectModel::Create(*this); // GAMEOBJECT_BYTES_1, index at 0, 1, 2 and 3 SetGoType(GameobjectTypes(goinfo->type)); SetGoState(go_state); -- cgit v1.2.3 From 5896da6689410f1c06ee86f8b093fb2d370eb84f Mon Sep 17 00:00:00 2001 From: tibbi Date: Mon, 8 Oct 2012 17:21:09 +0100 Subject: some optimization + adding level to CharacterNameData --- src/server/game/Globals/ObjectMgr.cpp | 13 ++++----- src/server/game/Globals/ObjectMgr.h | 2 +- src/server/game/Handlers/CharacterHandler.cpp | 40 +++++++++++---------------- src/server/game/Tools/PlayerDump.cpp | 4 ++- src/server/game/World/World.cpp | 16 +++++++++-- src/server/game/World/World.h | 4 ++- src/server/scripts/Commands/cs_character.cpp | 2 +- 7 files changed, 43 insertions(+), 38 deletions(-) (limited to 'src') diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index ea4386c4d41..b28f8be7805 100755 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -7591,7 +7591,7 @@ SpellScriptsBounds ObjectMgr::GetSpellScriptsBounds(uint32 spell_id) } // this allows calculating base reputations to offline players, just by race and class -int32 ObjectMgr::GetBaseReputation(FactionEntry const* factionEntry, uint8 race, uint32 playerClass) +int32 ObjectMgr::GetBaseReputation(FactionEntry const* factionEntry, uint8 race, uint8 playerClass) { if (!factionEntry) return 0; @@ -7599,13 +7599,12 @@ int32 ObjectMgr::GetBaseReputation(FactionEntry const* factionEntry, uint8 race, uint32 raceMask = (1 << (race - 1)); uint32 classMask = (1 << (playerClass-1)); - for (int i=0; i < 4; i++) + for (int i = 0; i < 4; i++) { - if ((factionEntry->BaseRepRaceMask[i] & raceMask || - (factionEntry->BaseRepRaceMask[i] == 0 && - factionEntry->BaseRepClassMask[i] != 0)) && - (factionEntry->BaseRepClassMask[i] & classMask || - factionEntry->BaseRepClassMask[i] == 0)) + if ((!factionEntry->BaseRepClassMask[i] || + factionEntry->BaseRepClassMask[i] & classMask) && + (!factionEntry->BaseRepRaceMask[i] || + factionEntry->BaseRepRaceMask[i] & raceMask)) return factionEntry->BaseRepValue[i]; } diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h index 81ca02af5d9..7871bbe3239 100755 --- a/src/server/game/Globals/ObjectMgr.h +++ b/src/server/game/Globals/ObjectMgr.h @@ -749,7 +749,7 @@ class ObjectMgr return NULL; } - int32 GetBaseReputation(FactionEntry const* factionEntry, uint8 race, uint32 playerClass); + int32 GetBaseReputation(FactionEntry const* factionEntry, uint8 race, uint8 playerClass); RepSpilloverTemplate const* GetRepSpilloverTemplate(uint32 factionId) const { diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index 30bc6df0539..91388d9bf11 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -660,7 +660,7 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, Characte std::string IP_str = GetRemoteAddress(); sLog->outInfo(LOG_FILTER_CHARACTER, "Account: %d (IP: %s) Create Character:[%s] (GUID: %u)", GetAccountId(), IP_str.c_str(), createInfo->Name.c_str(), newChar.GetGUIDLow()); sScriptMgr->OnPlayerCreate(&newChar); - sWorld->AddCharacterNameData(newChar.GetGUIDLow(), std::string(newChar.GetName()), newChar.getGender(), newChar.getRace(), newChar.getClass()); + sWorld->AddCharacterNameData(newChar.GetGUIDLow(), std::string(newChar.GetName()), newChar.getGender(), newChar.getRace(), newChar.getClass(), newChar.getLevel()); newChar.CleanupsBeforeDelete(); delete createInfo; @@ -1626,22 +1626,14 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recv_data) uint32 lowGuid = GUID_LOPART(guid); // get the players old (at this moment current) race - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_RACE); - stmt->setUInt32(0, guid); - PreparedQueryResult result = CharacterDatabase.Query(stmt); - if (!result) - { - WorldPacket data(SMSG_CHAR_FACTION_CHANGE, 1); - data << uint8(CHAR_CREATE_ERROR); - SendPacket(&data); - return; - } - Field* fields = result->Fetch(); - uint8 oldRace = fields[0].GetUInt8(); + CharacterNameData const* nameData = sWorld->GetCharacterNameData(lowGuid); + uint8 oldRace = nameData->m_race; + uint8 playerClass = nameData->m_class; + uint8 level = nameData->m_level; - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_CLASS_LVL_AT_LOGIN); + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_CLASS_LVL_AT_LOGIN); stmt->setUInt32(0, lowGuid); - result = CharacterDatabase.Query(stmt); + PreparedQueryResult result = CharacterDatabase.Query(stmt); if (!result) { @@ -1651,9 +1643,7 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recv_data) return; } - fields = result->Fetch(); - uint32 playerClass = uint32(fields[0].GetUInt8()); - uint32 level = uint32(fields[1].GetUInt8()); + Field* fields = result->Fetch(); uint32 at_loginFlags = fields[2].GetUInt16(); uint32 used_loginFlag = ((recv_data.GetOpcode() == CMSG_CHAR_RACE_CHANGE) ? AT_LOGIN_CHANGE_RACE : AT_LOGIN_CHANGE_FACTION); char const* knownTitlesStr = fields[3].GetCString(); @@ -2015,10 +2005,12 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recv_data) { uint32 reputation_alliance = it->first; uint32 reputation_horde = it->second; + uint32 newReputation = (team == TEAM_ALLIANCE) ? reputation_alliance : reputation_horde; + uint32 oldReputation = (team == TEAM_ALLIANCE) ? reputation_horde : reputation_alliance; // select old standing set in db PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_REP_BY_FACTION); - stmt->setUInt32(0, team == TEAM_ALLIANCE ? reputation_horde : reputation_alliance); + stmt->setUInt32(0, oldReputation); stmt->setUInt32(1, lowGuid); PreparedQueryResult result = CharacterDatabase.Query(stmt); @@ -2032,27 +2024,27 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recv_data) Field* fields = result->Fetch(); int32 oldDBRep = fields[0].GetInt32(); - FactionEntry const* factionEntry = sFactionStore.LookupEntry(team == TEAM_ALLIANCE ? reputation_horde : reputation_alliance); + FactionEntry const* factionEntry = sFactionStore.LookupEntry(oldReputation); // old base reputation int32 oldBaseRep = sObjectMgr->GetBaseReputation(factionEntry, oldRace, playerClass); // new base reputation - int32 newBaseRep = sObjectMgr->GetBaseReputation(sFactionStore.LookupEntry(team == TEAM_ALLIANCE ? reputation_alliance : reputation_horde), race, playerClass); + int32 newBaseRep = sObjectMgr->GetBaseReputation(sFactionStore.LookupEntry(newReputation), race, playerClass); // final reputation shouldnt change int32 FinalRep = oldDBRep + oldBaseRep; int32 newDBRep = FinalRep - newBaseRep; stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_REP_BY_FACTION); - stmt->setUInt32(0, uint16(team == TEAM_ALLIANCE ? reputation_alliance : reputation_horde)); + stmt->setUInt32(0, newReputation); stmt->setUInt32(1, lowGuid); trans->Append(stmt); stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_REP_FACTION_CHANGE); - stmt->setUInt16(0, uint16(team == TEAM_ALLIANCE ? reputation_alliance : reputation_horde)); + stmt->setUInt16(0, uint16(newReputation)); stmt->setInt32(1, newDBRep); - stmt->setUInt16(2, uint16(team == TEAM_ALLIANCE ? reputation_horde : reputation_alliance)); + stmt->setUInt16(2, uint16(oldReputation)); stmt->setUInt32(3, lowGuid); trans->Append(stmt); } diff --git a/src/server/game/Tools/PlayerDump.cpp b/src/server/game/Tools/PlayerDump.cpp index f6d0de28d28..ef516a0ba4f 100644 --- a/src/server/game/Tools/PlayerDump.cpp +++ b/src/server/game/Tools/PlayerDump.cpp @@ -457,6 +457,7 @@ DumpReturn PlayerDumpReader::LoadDump(const std::string& file, uint32 account, s uint8 gender = GENDER_NONE; uint8 race = RACE_NONE; uint8 playerClass = 0; + uint8 level = 1; SQLTransaction trans = CharacterDatabase.BeginTransaction(); while (!feof(fin)) @@ -531,6 +532,7 @@ DumpReturn PlayerDumpReader::LoadDump(const std::string& file, uint32 account, s race = uint8(atol(getnth(line, 4).c_str())); playerClass = uint8(atol(getnth(line, 5).c_str())); gender = uint8(atol(getnth(line, 6).c_str())); + level = uint8(atol(getnth(line, 7).c_str())); if (name == "") { // check if the original name already exists @@ -674,7 +676,7 @@ DumpReturn PlayerDumpReader::LoadDump(const std::string& file, uint32 account, s CharacterDatabase.CommitTransaction(trans); // in case of name conflict player has to rename at login anyway - sWorld->AddCharacterNameData(guid, name, gender, race, playerClass); + sWorld->AddCharacterNameData(guid, name, gender, race, playerClass, level); sObjectMgr->_hiItemGuid += items.size(); sObjectMgr->_mailId += mails.size(); diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index eef53e17774..06e8d3eccbe 100755 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -2937,7 +2937,7 @@ void World::LoadCharacterNameData() { sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading character name data"); - QueryResult result = CharacterDatabase.Query("SELECT guid, name, race, gender, class FROM characters WHERE deleteDate IS NULL"); + QueryResult result = CharacterDatabase.Query("SELECT guid, name, race, gender, class, level FROM characters WHERE deleteDate IS NULL"); if (!result) { sLog->outInfo(LOG_FILTER_SERVER_LOADING, "No character name data loaded, empty query"); @@ -2950,20 +2950,21 @@ void World::LoadCharacterNameData() { Field* fields = result->Fetch(); AddCharacterNameData(fields[0].GetUInt32(), fields[1].GetString(), - fields[3].GetUInt8() /*gender*/, fields[2].GetUInt8() /*race*/, fields[4].GetUInt8() /*class*/); + fields[3].GetUInt8() /*gender*/, fields[2].GetUInt8() /*race*/, fields[4].GetUInt8() /*class*/, fields[5].GetUInt8() /*level*/); ++count; } while (result->NextRow()); sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loaded name data for %u characters", count); } -void World::AddCharacterNameData(uint32 guid, std::string const& name, uint8 gender, uint8 race, uint8 playerClass) +void World::AddCharacterNameData(uint32 guid, std::string const& name, uint8 gender, uint8 race, uint8 playerClass, uint8 level) { CharacterNameData& data = _characterNameDataMap[guid]; data.m_name = name; data.m_race = race; data.m_gender = gender; data.m_class = playerClass; + data.m_level = level; } void World::UpdateCharacterNameData(uint32 guid, std::string const& name, uint8 gender /*= GENDER_NONE*/, uint8 race /*= RACE_NONE*/) @@ -2981,6 +2982,15 @@ void World::UpdateCharacterNameData(uint32 guid, std::string const& name, uint8 itr->second.m_race = race; } +void World::UpdateCharacterNameDataLevel(uint32 guid, uint8 level) +{ + std::map::iterator itr = _characterNameDataMap.find(guid); + if (itr == _characterNameDataMap.end()) + return; + + itr->second.m_level = level; +} + CharacterNameData const* World::GetCharacterNameData(uint32 guid) const { std::map::const_iterator itr = _characterNameDataMap.find(guid); diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h index 90bb82f1c2e..66b52549e93 100755 --- a/src/server/game/World/World.h +++ b/src/server/game/World/World.h @@ -538,6 +538,7 @@ struct CharacterNameData uint8 m_class; uint8 m_race; uint8 m_gender; + uint8 m_level; }; /// The World @@ -759,8 +760,9 @@ class World bool isEventKillStart; CharacterNameData const* GetCharacterNameData(uint32 guid) const; - void AddCharacterNameData(uint32 guid, std::string const& name, uint8 gender, uint8 race, uint8 playerClass); + void AddCharacterNameData(uint32 guid, std::string const& name, uint8 gender, uint8 race, uint8 playerClass, uint8 level); void UpdateCharacterNameData(uint32 guid, std::string const& name, uint8 gender = GENDER_NONE, uint8 race = RACE_NONE); + void UpdateCharacterNameDataLevel(uint32 guid, uint8 level); void DeleteCharaceterNameData(uint32 guid) { _characterNameDataMap.erase(guid); } uint32 GetCleaningFlags() const { return m_CleaningFlags; } diff --git a/src/server/scripts/Commands/cs_character.cpp b/src/server/scripts/Commands/cs_character.cpp index f5fbfa33cae..080b2416c9a 100644 --- a/src/server/scripts/Commands/cs_character.cpp +++ b/src/server/scripts/Commands/cs_character.cpp @@ -224,7 +224,7 @@ public: stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_NAME_DATA); stmt->setUInt32(0, delInfo.lowGuid); if (PreparedQueryResult result = CharacterDatabase.Query(stmt)) - sWorld->AddCharacterNameData(delInfo.lowGuid, delInfo.name, (*result)[2].GetUInt8(), (*result)[0].GetUInt8(), (*result)[1].GetUInt8()); + sWorld->AddCharacterNameData(delInfo.lowGuid, delInfo.name, (*result)[2].GetUInt8(), (*result)[0].GetUInt8(), (*result)[1].GetUInt8(), (*result)[2].GetUInt8()); } static void HandleCharacterLevel(Player* player, uint64 playerGuid, uint32 oldLevel, uint32 newLevel, ChatHandler* handler) -- cgit v1.2.3 From 405c3b09aa9fc9ea5750f0221d7f4974dd65b67f Mon Sep 17 00:00:00 2001 From: tibbi Date: Mon, 8 Oct 2012 17:29:02 +0100 Subject: adding a new prepared statement for selecting char at_login and titles --- src/server/game/Handlers/CharacterHandler.cpp | 6 +++--- src/server/shared/Database/Implementation/CharacterDatabase.cpp | 3 ++- src/server/shared/Database/Implementation/CharacterDatabase.h | 1 + 3 files changed, 6 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index 91388d9bf11..853e71fd732 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -1631,7 +1631,7 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recv_data) uint8 playerClass = nameData->m_class; uint8 level = nameData->m_level; - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_CLASS_LVL_AT_LOGIN); + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_AT_LOGIN_TITLES); stmt->setUInt32(0, lowGuid); PreparedQueryResult result = CharacterDatabase.Query(stmt); @@ -1644,9 +1644,9 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recv_data) } Field* fields = result->Fetch(); - uint32 at_loginFlags = fields[2].GetUInt16(); + uint32 at_loginFlags = fields[0].GetUInt16(); + char const* knownTitlesStr = fields[1].GetCString(); uint32 used_loginFlag = ((recv_data.GetOpcode() == CMSG_CHAR_RACE_CHANGE) ? AT_LOGIN_CHANGE_RACE : AT_LOGIN_CHANGE_FACTION); - char const* knownTitlesStr = fields[3].GetCString(); if (!sObjectMgr->GetPlayerInfo(race, playerClass)) { diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.cpp b/src/server/shared/Database/Implementation/CharacterDatabase.cpp index 4396f67244a..c29d8313c20 100644 --- a/src/server/shared/Database/Implementation/CharacterDatabase.cpp +++ b/src/server/shared/Database/Implementation/CharacterDatabase.cpp @@ -49,7 +49,7 @@ void CharacterDatabaseConnection::DoPrepareStatements() PREPARE_STATEMENT(CHAR_SEL_CHAR_RACE, "SELECT race FROM characters WHERE guid = ?", CONNECTION_SYNCH); PREPARE_STATEMENT(CHAR_SEL_CHAR_LEVEL, "SELECT level FROM characters WHERE guid = ?", CONNECTION_SYNCH); PREPARE_STATEMENT(CHAR_SEL_CHAR_ZONE, "SELECT zone FROM characters WHERE guid = ?", CONNECTION_SYNCH); - PREPARE_STATEMENT(CHAR_SEL_CHARACTER_NAME_DATA, "SELECT race, class, gender FROM characters WHERE guid = ?", CONNECTION_SYNCH); + PREPARE_STATEMENT(CHAR_SEL_CHARACTER_NAME_DATA, "SELECT race, class, gender, level FROM characters WHERE guid = ?", CONNECTION_SYNCH); PREPARE_STATEMENT(CHAR_SEL_CHAR_POSITION_XYZ, "SELECT map, position_x, position_y, position_z FROM characters WHERE guid = ?", CONNECTION_SYNCH); PREPARE_STATEMENT(CHAR_SEL_CHAR_POSITION, "SELECT position_x, position_y, position_z, orientation, map, taxi_path FROM characters WHERE guid = ?", CONNECTION_SYNCH); PREPARE_STATEMENT(CHAR_DEL_QUEST_STATUS_DAILY, "DELETE FROM character_queststatus_daily", CONNECTION_ASYNC); @@ -421,6 +421,7 @@ void CharacterDatabaseConnection::DoPrepareStatements() PREPARE_STATEMENT(CHAR_SEL_POOL_QUEST_SAVE, "SELECT quest_id FROM pool_quest_save WHERE pool_id = ?", CONNECTION_SYNCH); PREPARE_STATEMENT(CHAR_SEL_CHARACTER_AT_LOGIN, "SELECT at_login FROM characters WHERE guid = ?", CONNECTION_SYNCH); PREPARE_STATEMENT(CHAR_SEL_CHAR_CLASS_LVL_AT_LOGIN, "SELECT class, level, at_login, knownTitles FROM characters WHERE guid = ?", CONNECTION_SYNCH); + PREPARE_STATEMENT(CHAR_SEL_CHAR_AT_LOGIN_TITLES, "SELECT at_login, knownTitles FROM characters WHERE guid = ?", CONNECTION_SYNCH); PREPARE_STATEMENT(CHAR_SEL_INSTANCE, "SELECT data, completedEncounters FROM instance WHERE map = ? AND id = ?", CONNECTION_SYNCH); PREPARE_STATEMENT(CHAR_SEL_PET_SPELL_LIST, "SELECT DISTINCT pet_spell.spell FROM pet_spell, character_pet WHERE character_pet.owner = ? AND character_pet.id = pet_spell.guid AND character_pet.id <> ?", CONNECTION_SYNCH); PREPARE_STATEMENT(CHAR_SEL_CHAR_PET, "SELECT id FROM character_pet WHERE owner = ? AND id <> ?", CONNECTION_SYNCH); diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.h b/src/server/shared/Database/Implementation/CharacterDatabase.h index 95b059de95c..88018997e4b 100644 --- a/src/server/shared/Database/Implementation/CharacterDatabase.h +++ b/src/server/shared/Database/Implementation/CharacterDatabase.h @@ -384,6 +384,7 @@ enum CharacterDatabaseStatements CHAR_SEL_POOL_QUEST_SAVE, CHAR_SEL_CHARACTER_AT_LOGIN, CHAR_SEL_CHAR_CLASS_LVL_AT_LOGIN, + CHAR_SEL_CHAR_AT_LOGIN_TITLES, CHAR_SEL_INSTANCE, CHAR_SEL_PET_SPELL_LIST, CHAR_SEL_CHAR_PET, -- cgit v1.2.3 From 05eaf75501a69a4b9561ed245f07a4d0a7871f1d Mon Sep 17 00:00:00 2001 From: tibbi Date: Mon, 8 Oct 2012 20:02:11 +0100 Subject: adding forgotten UpdateCharacterNameDataLevel call --- src/server/game/Entities/Unit/Unit.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 54559507cf4..b499714e341 100755 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -13661,6 +13661,9 @@ void Unit::SetLevel(uint8 lvl) // group update if (GetTypeId() == TYPEID_PLAYER && ToPlayer()->GetGroup()) ToPlayer()->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_LEVEL); + + if (GetTypeId() == TYPEID_PLAYER) + sWorld->UpdateCharacterNameDataLevel(ToPlayer()->GetGUIDLow(), lvl); } void Unit::SetHealth(uint32 val) -- cgit v1.2.3 From 0620d2249131d681529f8a69f8bbec5e1773ad4d Mon Sep 17 00:00:00 2001 From: Subv Date: Mon, 8 Oct 2012 18:33:17 -0500 Subject: Core/SAI: Added a missing break. --- src/server/game/AI/SmartScripts/SmartScript.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index 49023b2d5b5..6097edf6641 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -2822,6 +2822,7 @@ void SmartScript::InitTimer(SmartScriptHolder& e) case SMART_EVENT_UPDATE_IC: case SMART_EVENT_UPDATE_OOC: RecalcTimer(e, e.event.minMaxRepeat.min, e.event.minMaxRepeat.max); + break; case SMART_EVENT_IC_LOS: case SMART_EVENT_OOC_LOS: RecalcTimer(e, e.event.los.cooldownMin, e.event.los.cooldownMax); -- cgit v1.2.3 From 2958f64ffcd10ca7ea6b10e0b70befa5df718930 Mon Sep 17 00:00:00 2001 From: kaelima Date: Tue, 9 Oct 2012 14:53:06 +0200 Subject: Scripts/Misc: Correct two wrong urand's (found by Aokromes) --- src/server/scripts/EasternKingdoms/ShadowfangKeep/shadowfang_keep.cpp | 2 +- src/server/scripts/Northrend/DraktharonKeep/boss_trollgore.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/server/scripts/EasternKingdoms/ShadowfangKeep/shadowfang_keep.cpp b/src/server/scripts/EasternKingdoms/ShadowfangKeep/shadowfang_keep.cpp index 676cd7be4f0..9ee3428c7dd 100644 --- a/src/server/scripts/EasternKingdoms/ShadowfangKeep/shadowfang_keep.cpp +++ b/src/server/scripts/EasternKingdoms/ShadowfangKeep/shadowfang_keep.cpp @@ -168,7 +168,7 @@ public: void Reset() { - uiDarkOffering = urand(290, 10); + uiDarkOffering = urand(200, 1000); } void UpdateAI(uint32 const uiDiff) diff --git a/src/server/scripts/Northrend/DraktharonKeep/boss_trollgore.cpp b/src/server/scripts/Northrend/DraktharonKeep/boss_trollgore.cpp index b6a4c40abdd..31b7787623c 100644 --- a/src/server/scripts/Northrend/DraktharonKeep/boss_trollgore.cpp +++ b/src/server/scripts/Northrend/DraktharonKeep/boss_trollgore.cpp @@ -86,7 +86,7 @@ public: uiConsumeTimer = 15*IN_MILLISECONDS; uiAuraCountTimer = 15500; uiCrushTimer = urand(1*IN_MILLISECONDS, 5*IN_MILLISECONDS); - uiInfectedWoundTimer = urand(60*IN_MILLISECONDS, 10*IN_MILLISECONDS); + uiInfectedWoundTimer = urand(10*IN_MILLISECONDS, 60*IN_MILLISECONDS); uiExplodeCorpseTimer = 3*IN_MILLISECONDS; uiSpawnTimer = urand(30*IN_MILLISECONDS, 40*IN_MILLISECONDS); -- cgit v1.2.3 From b75b6d33b02120e27b226a65c3d2a0641257cf8e Mon Sep 17 00:00:00 2001 From: Subv Date: Tue, 9 Oct 2012 22:50:02 -0500 Subject: Core/Achievements: Fixed achievements with ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA Closes #6339 --- src/server/game/Achievements/AchievementMgr.cpp | 10 +++++++++- src/server/game/Battlegrounds/Battleground.cpp | 1 + src/server/game/DataStores/DBCStructure.h | 3 ++- 3 files changed, 12 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/server/game/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp index b77de70c399..fe4bbea34fb 100755 --- a/src/server/game/Achievements/AchievementMgr.cpp +++ b/src/server/game/Achievements/AchievementMgr.cpp @@ -1596,6 +1596,13 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui break; } + case ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA: // This also behaves like ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA + { + // Check map id requirement + if (miscValue1 == achievementCriteria->win_arena.mapID) + SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE); + break; + } // std case: not exist in DBC, not triggered in code as result case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEALTH: case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_SPELLPOWER: @@ -1606,7 +1613,6 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui break; // FIXME: not triggered in code as result, need to implement case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_RAID: - case ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA: case ACHIEVEMENT_CRITERIA_TYPE_PLAY_ARENA: case ACHIEVEMENT_CRITERIA_TYPE_OWN_RANK: case ACHIEVEMENT_CRITERIA_TYPE_EARNED_PVP_TITLE: @@ -1749,6 +1755,8 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve return progress->counter >= achievementCriteria->use_lfg.dungeonsComplete; case ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS: return progress->counter >= achievementCriteria->get_killing_blow.killCount; + case ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA: + return achievementCriteria->win_arena.count && progress->counter >= achievementCriteria->win_arena.count; // handle all statistic-only criteria here case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND: case ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP: diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp index b33140a3419..8c1b3957b6d 100755 --- a/src/server/game/Battlegrounds/Battleground.cpp +++ b/src/server/game/Battlegrounds/Battleground.cpp @@ -856,6 +856,7 @@ void Battleground::EndBattleground(uint32 winner) // update achievement BEFORE personal rating update uint32 rating = player->GetArenaPersonalRating(winnerArenaTeam->GetSlot()); player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA, rating ? rating : 1); + player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA, GetMapId()); winnerArenaTeam->MemberWon(player, loserMatchmakerRating, winnerMatchmakerChange); } diff --git a/src/server/game/DataStores/DBCStructure.h b/src/server/game/DataStores/DBCStructure.h index e4ba3ebb12e..538a53344e8 100755 --- a/src/server/game/DataStores/DBCStructure.h +++ b/src/server/game/DataStores/DBCStructure.h @@ -221,7 +221,8 @@ struct AchievementCriteriaEntry // ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA = 32 struct { - uint32 mapID; // 3 Reference to Map.dbc + uint32 mapID; // 3 Reference to Map.dbc + uint32 count; // 4 Number of times that the arena must be won. } win_arena; // ACHIEVEMENT_CRITERIA_TYPE_PLAY_ARENA = 33 -- cgit v1.2.3 From 3e5af53bf75fdacdb8626e4fd95a5c889874a829 Mon Sep 17 00:00:00 2001 From: Subv Date: Tue, 9 Oct 2012 22:59:18 -0500 Subject: Core/Achievements: ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL doesn't require a killing blow anymore, only a honorable kill. Author: @tibbi Closes #6224 --- src/server/game/Entities/Player/Player.cpp | 7 +++++++ src/server/game/Entities/Unit/Unit.cpp | 6 ------ 2 files changed, 7 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 50f5fd4c978..9b2921b844d 100755 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -598,9 +598,16 @@ void KillRewarder::_RewardGroup() // 3.1.3. Reward each group member (even dead or corpse) within reward distance. for (GroupReference* itr = _group->GetFirstMember(); itr != NULL; itr = itr->next()) + { if (Player* member = itr->getSource()) + { if (member->IsAtGroupRewardDistance(_victim)) + { _RewardPlayer(member, isDungeon); + member->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL, 1, 0, _victim); + } + } + } } } } diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 76b9649f002..8fc519b2f4a 100755 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -703,14 +703,8 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam sLog->outDebug(LOG_FILTER_UNITS, "DealDamage: victim just died"); if (victim->GetTypeId() == TYPEID_PLAYER && victim != this) - { victim->ToPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_TOTAL_DAMAGE_RECEIVED, health); - // call before auras are removed - if (Player* killer = GetCharmerOrOwnerPlayerOrPlayerItself()) - killer->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL, 1, 0, victim); - } - Kill(victim, durabilityLoss); } else -- cgit v1.2.3 From ecc2362c69e24b2afc762bc32d11453d537a84fb Mon Sep 17 00:00:00 2001 From: Subv Date: Wed, 10 Oct 2012 09:25:25 -0500 Subject: Scripts/Commands: Fixed the command to restore a deleted character. Thanks @vlad852 --- src/server/scripts/Commands/cs_character.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/server/scripts/Commands/cs_character.cpp b/src/server/scripts/Commands/cs_character.cpp index 080b2416c9a..1f32368adfd 100644 --- a/src/server/scripts/Commands/cs_character.cpp +++ b/src/server/scripts/Commands/cs_character.cpp @@ -224,7 +224,7 @@ public: stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_NAME_DATA); stmt->setUInt32(0, delInfo.lowGuid); if (PreparedQueryResult result = CharacterDatabase.Query(stmt)) - sWorld->AddCharacterNameData(delInfo.lowGuid, delInfo.name, (*result)[2].GetUInt8(), (*result)[0].GetUInt8(), (*result)[1].GetUInt8(), (*result)[2].GetUInt8()); + sWorld->AddCharacterNameData(delInfo.lowGuid, delInfo.name, (*result)[2].GetUInt8(), (*result)[0].GetUInt8(), (*result)[1].GetUInt8(), (*result)[3].GetUInt8()); } static void HandleCharacterLevel(Player* player, uint64 playerGuid, uint32 oldLevel, uint32 newLevel, ChatHandler* handler) -- cgit v1.2.3 From 970009cb3b7e8a3ca0aa1107f70a76e9dc1ecb61 Mon Sep 17 00:00:00 2001 From: Subv Date: Wed, 10 Oct 2012 11:49:51 -0500 Subject: Core/Players: Remove the mute from the DB when the timer expires. --- src/server/game/Entities/Player/Player.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src') diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 9b2921b844d..0d31c40f3a1 100755 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -1579,6 +1579,16 @@ void Player::Update(uint32 p_time) // check every second if (now > m_Last_tick + 1) UpdateSoulboundTradeItems(); + + // If mute expired, remove it from the DB + if (GetSession()->m_muteTime && GetSession()->m_muteTime < now) + { + GetSession()->m_muteTime = 0; + PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_MUTE_TIME); + stmt->setInt64(0, 0); // Set the mute time to 0 + stmt->setUInt32(1, GetSession()->GetAccountId()); + LoginDatabase.Execute(stmt); + } if (!m_timedquests.empty()) { -- cgit v1.2.3 From c51f98483732022c87c641dd0feb12a0a401ef95 Mon Sep 17 00:00:00 2001 From: Subv Date: Wed, 10 Oct 2012 15:12:05 -0500 Subject: Core/Misc: Only remove auras in arenas for non-gm players. Closes #7559 --- src/server/game/Battlegrounds/Battleground.cpp | 29 ++++++++++++++------------ 1 file changed, 16 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp index 8c1b3957b6d..963fd5e2d07 100755 --- a/src/server/game/Battlegrounds/Battleground.cpp +++ b/src/server/game/Battlegrounds/Battleground.cpp @@ -523,20 +523,23 @@ inline void Battleground::_ProcessJoin(uint32 diff) player->RemoveAurasDueToSpell(SPELL_ARENA_PREPARATION); player->ResetAllPowers(); - // remove auras with duration lower than 30s - Unit::AuraApplicationMap & auraMap = player->GetAppliedAuras(); - for (Unit::AuraApplicationMap::iterator iter = auraMap.begin(); iter != auraMap.end();) + if (!player->isGameMaster()) { - AuraApplication * aurApp = iter->second; - Aura* aura = aurApp->GetBase(); - if (!aura->IsPermanent() - && aura->GetDuration() <= 30*IN_MILLISECONDS - && aurApp->IsPositive() - && (!(aura->GetSpellInfo()->Attributes & SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY)) - && (!aura->HasEffectType(SPELL_AURA_MOD_INVISIBILITY))) - player->RemoveAura(iter); - else - ++iter; + // remove auras with duration lower than 30s + Unit::AuraApplicationMap & auraMap = player->GetAppliedAuras(); + for (Unit::AuraApplicationMap::iterator iter = auraMap.begin(); iter != auraMap.end();) + { + AuraApplication * aurApp = iter->second; + Aura* aura = aurApp->GetBase(); + if (!aura->IsPermanent() + && aura->GetDuration() <= 30*IN_MILLISECONDS + && aurApp->IsPositive() + && (!(aura->GetSpellInfo()->Attributes & SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY)) + && (!aura->HasEffectType(SPELL_AURA_MOD_INVISIBILITY))) + player->RemoveAura(iter); + else + ++iter; + } } } -- cgit v1.2.3 From d02298509fc106b31009e8eb65cff2ae8ded583d Mon Sep 17 00:00:00 2001 From: Retriman Date: Thu, 11 Oct 2012 01:32:28 -0400 Subject: Core/Spell: *Barkskin can be used to stun and sleep. --- src/server/game/Spells/Spell.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 6b51f240b28..940bf7fdd1c 100755 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -5621,7 +5621,7 @@ SpellCastResult Spell::CheckCasterAuras() const break; } } - if (foundNotStun) + if (foundNotStun && m_spellInfo->Id != 22812) prevented_reason = SPELL_FAILED_STUNNED; } else -- cgit v1.2.3 From 923cad31f3972fa5388d492e99161e3234d8a78c Mon Sep 17 00:00:00 2001 From: Kandera Date: Thu, 11 Oct 2012 11:28:44 -0400 Subject: Wintergrasp: move keep banner spawns to db. fix invisible stalker position. --- .../world/2012_10_11_00_world_gameobject.sql | 92 +++++++++++++++++ .../game/Battlefield/Zones/BattlefieldWG.cpp | 23 ----- src/server/game/Battlefield/Zones/BattlefieldWG.h | 109 +++------------------ 3 files changed, 106 insertions(+), 118 deletions(-) create mode 100644 sql/updates/world/2012_10_11_00_world_gameobject.sql (limited to 'src') diff --git a/sql/updates/world/2012_10_11_00_world_gameobject.sql b/sql/updates/world/2012_10_11_00_world_gameobject.sql new file mode 100644 index 00000000000..0c08d9d5622 --- /dev/null +++ b/sql/updates/world/2012_10_11_00_world_gameobject.sql @@ -0,0 +1,92 @@ +SET @GUID = 74685; +SET @MAP = 571; +DELETE FROM `gameobject` WHERE (`id` IN (192254,192255,192269,192284,192285,192336,192338,192339,192349,192350,192351,192352,192353,192354,192355,192356,192357,192358,192359,192360,192361,192362,192363,192364,192366,192367,192368,192369,192370,192371,192372,192373,192374,192375,192378,192379,192416,192488,192501) AND `guid` != 67250) OR `guid` BETWEEN @GUID AND @GUID+87; +INSERT INTO `gameobject` (`guid`,`id`,`map`,`phaseMask`,`position_x`,`position_y`,`position_z`,`orientation`) VALUES +(@GUID+0, 192488, @MAP, 64, 5262.540039, 3047.949951, 432.054993, 3.106650), -- Flag on tower +(@GUID+1, 192501, @MAP, 128, 5262.540039, 3047.949951, 432.054993, 3.106650), -- Flag on tower +(@GUID+2, 192374, @MAP, 64, 5272.939941, 2976.550049, 444.492004, 3.124120), -- Flag on Wall Intersect +(@GUID+3, 192416, @MAP, 128, 5272.939941, 2976.550049, 444.492004, 3.124120), -- Flag on Wall Intersect +(@GUID+4, 192375, @MAP, 64, 5235.189941, 2941.899902, 444.278015, 1.588250), -- Flag on Wall Intersect +(@GUID+5, 192416, @MAP, 128, 5235.189941, 2941.899902, 444.278015, 1.588250), -- Flag on Wall Intersect +(@GUID+6, 192488, @MAP, 64, 5163.129883, 2952.590088, 433.502991, 1.535890), -- Flag on tower +(@GUID+7, 192501, @MAP, 128, 5163.129883, 2952.590088, 433.502991, 1.535890), -- Flag on tower +(@GUID+8, 192488, @MAP, 64, 5145.109863, 2935.000000, 433.385986, 3.141590), -- Flag on tower +(@GUID+9, 192501, @MAP, 128, 5145.109863, 2935.000000, 433.385986, 3.141590), -- Flag on tower +(@GUID+10, 192488, @MAP, 64, 5158.810059, 2883.129883, 431.618011, 3.141590), -- Flag on wall +(@GUID+11, 192416, @MAP, 128, 5158.810059, 2883.129883, 431.618011, 3.141590), -- Flag on wall +(@GUID+12, 192336, @MAP, 64, 5154.490234, 2862.149902, 445.011993, 3.141590), -- Flag on Wall Intersect +(@GUID+13, 192416, @MAP, 128, 5154.490234, 2862.149902, 445.011993, 3.141590), -- Flag on Wall Intersect +(@GUID+14, 192255, @MAP, 64, 5154.520020, 2853.310059, 409.183014, 3.141590), -- Flag on the floor +(@GUID+15, 192269, @MAP, 128, 5154.520020, 2853.310059, 409.183014, 3.141590), -- Flag on the floor +(@GUID+16, 192254, @MAP, 64, 5154.459961, 2828.939941, 409.188995, 3.141590), -- Flag on the floor +(@GUID+17, 192269, @MAP, 128, 5154.459961, 2828.939941, 409.188995, 3.141590), -- Flag on the floor +(@GUID+18, 192349, @MAP, 64, 5155.310059, 2820.739990, 444.979004, -3.13286), -- Flag on wall intersect +(@GUID+19, 192416, @MAP, 128, 5155.310059, 2820.739990, 444.979004, -3.13286), -- Flag on wall intersect +(@GUID+20, 192488, @MAP, 64, 5160.339844, 2798.610107, 430.769012, 3.141590), -- Flag on wall +(@GUID+21, 192416, @MAP, 128, 5160.339844, 2798.610107, 430.769012, 3.141590), -- Flag on wall +(@GUID+22, 192488, @MAP, 64, 5146.040039, 2747.209961, 433.584015, 3.071770), -- Flag on tower +(@GUID+23, 192501, @MAP, 128, 5146.040039, 2747.209961, 433.584015, 3.071770), -- Flag on tower +(@GUID+24, 192488, @MAP, 64, 5163.779785, 2729.679932, 433.394012, -1.58825), -- Flag on tower +(@GUID+25, 192501, @MAP, 128, 5163.779785, 2729.679932, 433.394012, -1.58825), -- Flag on tower +(@GUID+26, 192366, @MAP, 64, 5236.270020, 2739.459961, 444.992004, -1.59698), -- Flag on wall intersect +(@GUID+27, 192416, @MAP, 128, 5236.270020, 2739.459961, 444.992004, -1.59698), -- Flag on wall intersect +(@GUID+28, 192367, @MAP, 64, 5271.799805, 2704.870117, 445.183014, -3.13286), -- Flag on wall intersect +(@GUID+29, 192416, @MAP, 128, 5271.799805, 2704.870117, 445.183014, -3.13286), -- Flag on wall intersect +(@GUID+30, 192488, @MAP, 64, 5260.819824, 2631.800049, 433.324005, 3.054330), -- Flag on tower +(@GUID+31, 192501, @MAP, 128, 5260.819824, 2631.800049, 433.324005, 3.054330), -- Flag on tower +(@GUID+32, 192488, @MAP, 64, 5278.379883, 2613.830078, 433.408997, -1.58825), -- Flag on tower +(@GUID+33, 192501, @MAP, 128, 5278.379883, 2613.830078, 433.408997, -1.58825), -- Flag on tower +(@GUID+34, 192364, @MAP, 64, 5350.879883, 2622.719971, 444.686005, -1.57080), -- Flag on wall intersect +(@GUID+35, 192416, @MAP, 128, 5350.879883, 2622.719971, 444.686005, -1.57080), -- Flag on wall intersect +(@GUID+36, 192370, @MAP, 64, 5392.270020, 2639.739990, 435.330994, 1.509710), -- Flag on wall intersect +(@GUID+37, 192416, @MAP, 128, 5392.270020, 2639.739990, 435.330994, 1.509710), -- Flag on wall intersect +(@GUID+38, 192369, @MAP, 64, 5350.950195, 2640.360107, 435.407990, 1.570800), -- Flag on wall intersect +(@GUID+39, 192416, @MAP, 128, 5350.950195, 2640.360107, 435.407990, 1.570800), -- Flag on wall intersect +(@GUID+40, 192368, @MAP, 64, 5289.459961, 2704.679932, 435.875000, -0.01745), -- Flag on wall intersect +(@GUID+41, 192416, @MAP, 128, 5289.459961, 2704.679932, 435.875000, -0.01745), -- Flag on wall intersect +(@GUID+42, 192362, @MAP, 64, 5322.120117, 2763.610107, 444.973999, -1.55334), -- Flag on wall intersect +(@GUID+43, 192416, @MAP, 128, 5322.120117, 2763.610107, 444.973999, -1.55334), -- Flag on wall intersect +(@GUID+44, 192363, @MAP, 64, 5363.609863, 2763.389893, 445.023987, -1.54462), -- Flag on wall intersect +(@GUID+45, 192416, @MAP, 128, 5363.609863, 2763.389893, 445.023987, -1.54462), -- Flag on wall intersect +(@GUID+46, 192379, @MAP, 64, 5363.419922, 2781.030029, 435.763000, 1.570800), -- Flag on wall intersect +(@GUID+47, 192416, @MAP, 128, 5363.419922, 2781.030029, 435.763000, 1.570800), -- Flag on wall intersect +(@GUID+48, 192378, @MAP, 64, 5322.020020, 2781.129883, 435.811005, 1.570800), -- Flag on wall intersect +(@GUID+49, 192416, @MAP, 128, 5322.020020, 2781.129883, 435.811005, 1.570800), -- Flag on wall intersect +(@GUID+50, 192355, @MAP, 64, 5288.919922, 2820.219971, 435.721008, 0.017452), -- Flag on wall intersect +(@GUID+51, 192416, @MAP, 128, 5288.919922, 2820.219971, 435.721008, 0.017452), -- Flag on wall intersect +(@GUID+52, 192354, @MAP, 64, 5288.410156, 2861.790039, 435.721008, 0.017452), -- Flag on wall intersect +(@GUID+53, 192416, @MAP, 128, 5288.410156, 2861.790039, 435.721008, 0.017452), -- Flag on wall intersect +(@GUID+54, 192358, @MAP, 64, 5322.229980, 2899.429932, 435.808014, -1.58825), -- Flag on wall intersect +(@GUID+55, 192416, @MAP, 128, 5322.229980, 2899.429932, 435.808014, -1.58825), -- Flag on wall intersect +(@GUID+56, 192359, @MAP, 64, 5364.350098, 2899.399902, 435.838989, -1.57080), -- Flag on wall intersect +(@GUID+57, 192416, @MAP, 128, 5364.350098, 2899.399902, 435.838989, -1.57080), -- Flag on wall intersect +(@GUID+58, 192338, @MAP, 64, 5397.759766, 2873.080078, 455.460999, 3.106650), -- Flag on keep +(@GUID+59, 192416, @MAP, 128, 5397.759766, 2873.080078, 455.460999, 3.106650), -- Flag on keep +(@GUID+60, 192339, @MAP, 64, 5397.390137, 2809.330078, 455.343994, 3.106650), -- Flag on keep +(@GUID+61, 192416, @MAP, 128, 5397.390137, 2809.330078, 455.343994, 3.106650), -- Flag on keep +(@GUID+62, 192284, @MAP, 64, 5372.479980, 2862.500000, 409.049011, 3.141590), -- Flag on floor +(@GUID+63, 192269, @MAP, 128, 5372.479980, 2862.500000, 409.049011, 3.141590), -- Flag on floor +(@GUID+64, 192285, @MAP, 64, 5371.490234, 2820.800049, 409.177002, 3.141590), -- Flag on floor +(@GUID+65, 192269, @MAP, 128, 5371.490234, 2820.800049, 409.177002, 3.141590), -- Flag on floor +(@GUID+66, 192371, @MAP, 64, 5364.290039, 2916.939941, 445.330994, 1.579520), -- Flag on wall intersect +(@GUID+67, 192416, @MAP, 128, 5364.290039, 2916.939941, 445.330994, 1.579520), -- Flag on wall intersect +(@GUID+68, 192372, @MAP, 64, 5322.859863, 2916.949951, 445.153992, 1.562070), -- Flag on wall intersect +(@GUID+69, 192416, @MAP, 128, 5322.859863, 2916.949951, 445.153992, 1.562070), -- Flag on wall intersect +(@GUID+70, 192373, @MAP, 64, 5290.350098, 2976.560059, 435.221008, 0.017452), -- Flag on wall intersect +(@GUID+71, 192416, @MAP, 128, 5290.350098, 2976.560059, 435.221008, 0.017452), -- Flag on wall intersect +(@GUID+72, 192360, @MAP, 64, 5352.370117, 3037.090088, 435.252014, -1.57080), -- Flag on wall intersect +(@GUID+73, 192416, @MAP, 128, 5352.370117, 3037.090088, 435.252014, -1.57080), -- Flag on wall intersect +(@GUID+74, 192361, @MAP, 64, 5392.649902, 3037.110107, 433.713013, -1.52716), -- Flag on wall intersect +(@GUID+75, 192416, @MAP, 128, 5392.649902, 3037.110107, 433.713013, -1.52716), -- Flag on wall intersect +(@GUID+76, 192356, @MAP, 64, 5237.069824, 2757.030029, 435.795990, 1.518440), -- Flag on wall intersect +(@GUID+77, 192416, @MAP, 128, 5237.069824, 2757.030029, 435.795990, 1.518440), -- Flag on wall intersect +(@GUID+78, 192352, @MAP, 64, 5173.020020, 2820.929932, 435.720001, 0.017452), -- Flag on wall intersect +(@GUID+79, 192416, @MAP, 128, 5173.020020, 2820.929932, 435.720001, 0.017452), -- Flag on wall intersect +(@GUID+80, 192353, @MAP, 64, 5172.109863, 2862.570068, 435.721008, 0.017452), -- Flag on wall intersect +(@GUID+81, 192416, @MAP, 128, 5172.109863, 2862.570068, 435.721008, 0.017452), -- Flag on wall intersect +(@GUID+82, 192357, @MAP, 64, 5235.339844, 2924.340088, 435.040009, -1.57080), -- Flag on wall intersect +(@GUID+83, 192416, @MAP, 128, 5235.339844, 2924.340088, 435.040009, -1.57080), -- Flag on wall intersect +(@GUID+84, 192350, @MAP, 64, 5270.689941, 2861.780029, 445.058014, -3.11539), -- Flag on wall intersect +(@GUID+85, 192416, @MAP, 128, 5270.689941, 2861.780029, 445.058014, -3.11539), -- Flag on wall intersect +(@GUID+86, 192351, @MAP, 64, 5271.279785, 2820.159912, 445.200989, -3.13286), -- Flag on wall intersect +(@GUID+87, 192416, @MAP, 128, 5271.279785, 2820.159912, 445.200989, -3.13286); -- Flag on wall intersect diff --git a/src/server/game/Battlefield/Zones/BattlefieldWG.cpp b/src/server/game/Battlefield/Zones/BattlefieldWG.cpp index 119880bae8d..59dc6761583 100644 --- a/src/server/game/Battlefield/Zones/BattlefieldWG.cpp +++ b/src/server/game/Battlefield/Zones/BattlefieldWG.cpp @@ -188,29 +188,6 @@ bool BattlefieldWG::SetupBattlefield() go->SetUInt32Value(GAMEOBJECT_FACTION, WintergraspFaction[GetDefenderTeam()]); } - // Spawn banners in the keep - for (uint8 i = 0; i < WG_KEEPGAMEOBJECT_MAX; i++) - { - if (GameObject* go = SpawnGameObject(WGKeepGameObject[i].entryHorde, WGKeepGameObject[i].x, WGKeepGameObject[i].y, WGKeepGameObject[i].z, WGKeepGameObject[i].o)) - { - go->SetRespawnTime(GetDefenderTeam()? RESPAWN_ONE_DAY : RESPAWN_IMMEDIATELY); - m_KeepGameObject[1].insert(go); - } - if (GameObject* go = SpawnGameObject(WGKeepGameObject[i].entryAlliance, WGKeepGameObject[i].x, WGKeepGameObject[i].y, WGKeepGameObject[i].z, WGKeepGameObject[i].o)) - { - go->SetRespawnTime(GetDefenderTeam()? RESPAWN_IMMEDIATELY : RESPAWN_ONE_DAY); - m_KeepGameObject[0].insert(go); - } - } - - // Show defender banner in keep - for (GameObjectSet::const_iterator itr = m_KeepGameObject[GetDefenderTeam()].begin(); itr != m_KeepGameObject[GetDefenderTeam()].end(); ++itr) - (*itr)->SetRespawnTime(RESPAWN_IMMEDIATELY); - - // Hide attackant banner in keep - for (GameObjectSet::const_iterator itr = m_KeepGameObject[GetAttackerTeam()].begin(); itr != m_KeepGameObject[GetAttackerTeam()].end(); ++itr) - (*itr)->SetRespawnTime(RESPAWN_ONE_DAY); - UpdateCounterVehicle(true); return true; } diff --git a/src/server/game/Battlefield/Zones/BattlefieldWG.h b/src/server/game/Battlefield/Zones/BattlefieldWG.h index 323f7f2b13d..1af096a3180 100644 --- a/src/server/game/Battlefield/Zones/BattlefieldWG.h +++ b/src/server/game/Battlefield/Zones/BattlefieldWG.h @@ -440,10 +440,9 @@ uint32 const VehNumWorldState[] = { 3680, 3490 }; uint32 const MaxVehNumWorldState[] = { 3681, 3491 }; uint32 const ClockWorldState[] = { 3781, 4354 }; uint32 const WintergraspFaction[] = { 1732, 1735, 35 }; -float const WintergraspStalkerPos[] = { 0, 0, 0, 0 }; +float const WintergraspStalkerPos[] = { 4948.985f, 2937.789f, 550.5172f, 1.815142f }; uint8 const WG_MAX_OBJ = 32; -uint8 const WG_KEEPGAMEOBJECT_MAX = 44; uint8 const WG_MAX_TURRET = 15; uint8 const WG_MAX_KEEP_NPC = 39; uint8 const WG_MAX_OUTSIDE_NPC = 14; @@ -580,6 +579,19 @@ struct WintergraspBuildingSpawnData uint32 nameId; }; +struct WintergraspRebuildableBuildingData +{ + uint32 entry; + uint64 Guid + uint32 WorldState; + float x; + float y; + float z; + float o; + uint32 type; + uint32 nameId; +}; + const WintergraspBuildingSpawnData WGGameObjectBuilding[WG_MAX_OBJ] = { // Wall (Not spawned in db) @@ -628,99 +640,6 @@ const WintergraspBuildingSpawnData WGGameObjectBuilding[WG_MAX_OBJ] = { GO_WINTERGRASP_VAULT_GATE, 3773, 5397.11f, 2841.54f, 425.899f, 3.14159f, BATTLEFIELD_WG_OBJECTTYPE_DOOR_LAST, 0 }, }; - -// ********************************************************* -// **********Keep Element(GameObject,Creature)************** -// ********************************************************* - -// Keep gameobject -// 192488 : 10 in sql, 19 in header -// 192501 : 12 in sql, 17 in header -// 192416 : 1 in sql, 33 in header -// 192374 : 1 in sql, 1 in header -// 192375 : 1 in sql, 1 in header -// 192336 : 1 in sql, 1 in header -// 192255 : 1 in sql, 1 in header -// 192269 : 1 in sql, 7 in header -// 192254 : 1 in sql, 1 in header -// 192349 : 1 in sql, 1 in header -// 192366 : 1 in sql, 3 in header -// 192367 : 1 in sql, 1 in header -// 192364 : 1 in sql, 1 in header -// 192370 : 1 in sql, 1 in header -// 192369 : 1 in sql, 1 in header -// 192368 : 1 in sql, 1 in header -// 192362 : 1 in sql, 1 in header -// 192363 : 1 in sql, 1 in header -// 192379 : 1 in sql, 1 in header -// 192378 : 1 in sql, 1 in header -// 192355 : 1 in sql, 1 in header -// 192354 : 1 in sql, 1 in header -// 192358 : 1 in sql, 1 in header -// 192359 : 1 in sql, 1 in header -// 192338 : 1 in sql, 1 in header -// 192339 : 1 in sql, 1 in header -// 192284 : 1 in sql, 1 in header -// 192285 : 1 in sql, 1 in header -// 192371 : 1 in sql, 1 in header -// 192372 : 1 in sql, 1 in header -// 192373 : 1 in sql, 1 in header -// 192360 : 1 in sql, 1 in header -// 192361 : 1 in sql, 1 in header -// 192356 : 1 in sql, 1 in header -// 192352 : 1 in sql, 1 in header -// 192353 : 1 in sql, 1 in header -// 192357 : 1 in sql, 1 in header -// 192350 : 1 in sql, 1 in header -// 192351 : 1 in sql, 1 in header -const WintergraspObjectPositionData WGKeepGameObject[WG_KEEPGAMEOBJECT_MAX] = -{ - { 5262.540039f, 3047.949951f, 432.054993f, 3.106650f, 192488, 192501 }, // Flag on tower - { 5272.939941f, 2976.550049f, 444.492004f, 3.124120f, 192374, 192416 }, // Flag on Wall Intersect - { 5235.189941f, 2941.899902f, 444.278015f, 1.588250f, 192375, 192416 }, // Flag on Wall Intersect - { 5163.129883f, 2952.590088f, 433.502991f, 1.535890f, 192488, 192501 }, // Flag on tower - { 5145.109863f, 2935.000000f, 433.385986f, 3.141590f, 192488, 192501 }, // Flag on tower - { 5158.810059f, 2883.129883f, 431.618011f, 3.141590f, 192488, 192416 }, // Flag on wall - { 5154.490234f, 2862.149902f, 445.011993f, 3.141590f, 192336, 192416 }, // Flag on Wall Intersect - { 5154.520020f, 2853.310059f, 409.183014f, 3.141590f, 192255, 192269 }, // Flag on the floor - { 5154.459961f, 2828.939941f, 409.188995f, 3.141590f, 192254, 192269 }, // Flag on the floor - { 5155.310059f, 2820.739990f, 444.979004f, -3.13286f, 192349, 192416 }, // Flag on wall intersect - { 5160.339844f, 2798.610107f, 430.769012f, 3.141590f, 192488, 192416 }, // Flag on wall - { 5146.040039f, 2747.209961f, 433.584015f, 3.071770f, 192488, 192501 }, // Flag on tower - { 5163.779785f, 2729.679932f, 433.394012f, -1.58825f, 192488, 192501 }, // Flag on tower - { 5236.270020f, 2739.459961f, 444.992004f, -1.59698f, 192366, 192416 }, // Flag on wall intersect - { 5271.799805f, 2704.870117f, 445.183014f, -3.13286f, 192367, 192416 }, // Flag on wall intersect - { 5260.819824f, 2631.800049f, 433.324005f, 3.054330f, 192488, 192501 }, // Flag on tower - { 5278.379883f, 2613.830078f, 433.408997f, -1.58825f, 192488, 192501 }, // Flag on tower - { 5350.879883f, 2622.719971f, 444.686005f, -1.57080f, 192364, 192416 }, // Flag on wall intersect - { 5392.270020f, 2639.739990f, 435.330994f, 1.509710f, 192370, 192416 }, // Flag on wall intersect - { 5350.950195f, 2640.360107f, 435.407990f, 1.570800f, 192369, 192416 }, // Flag on wall intersect - { 5289.459961f, 2704.679932f, 435.875000f, -0.01745f, 192368, 192416 }, // Flag on wall intersect - { 5322.120117f, 2763.610107f, 444.973999f, -1.55334f, 192362, 192416 }, // Flag on wall intersect - { 5363.609863f, 2763.389893f, 445.023987f, -1.54462f, 192363, 192416 }, // Flag on wall intersect - { 5363.419922f, 2781.030029f, 435.763000f, 1.570800f, 192379, 192416 }, // Flag on wall intersect - { 5322.020020f, 2781.129883f, 435.811005f, 1.570800f, 192378, 192416 }, // Flag on wall intersect - { 5288.919922f, 2820.219971f, 435.721008f, 0.017452f, 192355, 192416 }, // Flag on wall intersect - { 5288.410156f, 2861.790039f, 435.721008f, 0.017452f, 192354, 192416 }, // Flag on wall intersect - { 5322.229980f, 2899.429932f, 435.808014f, -1.58825f, 192358, 192416 }, // Flag on wall intersect - { 5364.350098f, 2899.399902f, 435.838989f, -1.57080f, 192359, 192416 }, // Flag on wall intersect - { 5397.759766f, 2873.080078f, 455.460999f, 3.106650f, 192338, 192416 }, // Flag on keep - { 5397.390137f, 2809.330078f, 455.343994f, 3.106650f, 192339, 192416 }, // Flag on keep - { 5372.479980f, 2862.500000f, 409.049011f, 3.141590f, 192284, 192269 }, // Flag on floor - { 5371.490234f, 2820.800049f, 409.177002f, 3.141590f, 192285, 192269 }, // Flag on floor - { 5364.290039f, 2916.939941f, 445.330994f, 1.579520f, 192371, 192416 }, // Flag on wall intersect - { 5322.859863f, 2916.949951f, 445.153992f, 1.562070f, 192372, 192416 }, // Flag on wall intersect - { 5290.350098f, 2976.560059f, 435.221008f, 0.017452f, 192373, 192416 }, // Flag on wall intersect - { 5352.370117f, 3037.090088f, 435.252014f, -1.57080f, 192360, 192416 }, // Flag on wall intersect - { 5392.649902f, 3037.110107f, 433.713013f, -1.52716f, 192361, 192416 }, // Flag on wall intersect - { 5237.069824f, 2757.030029f, 435.795990f, 1.518440f, 192356, 192416 }, // Flag on wall intersect - { 5173.020020f, 2820.929932f, 435.720001f, 0.017452f, 192352, 192416 }, // Flag on wall intersect - { 5172.109863f, 2862.570068f, 435.721008f, 0.017452f, 192353, 192416 }, // Flag on wall intersect - { 5235.339844f, 2924.340088f, 435.040009f, -1.57080f, 192357, 192416 }, // Flag on wall intersect - { 5270.689941f, 2861.780029f, 445.058014f, -3.11539f, 192350, 192416 }, // Flag on wall intersect - { 5271.279785f, 2820.159912f, 445.200989f, -3.13286f, 192351, 192416 } // Flag on wall intersect -}; - const Position WGTurret[WG_MAX_TURRET] = { { 5391.19f, 3060.8f, 419.616f, 1.69557f }, -- cgit v1.2.3 From abe81119b44c5de7b5dcd23e6f4d5740cc2ea863 Mon Sep 17 00:00:00 2001 From: Nay Date: Fri, 12 Oct 2012 01:28:37 +0200 Subject: Core/Script: Fix item unusual compass. By Kaelima and Retriman Closes #8039 --- src/server/scripts/Spells/spell_item.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/server/scripts/Spells/spell_item.cpp b/src/server/scripts/Spells/spell_item.cpp index 0508d95a60b..ef810b50b6f 100644 --- a/src/server/scripts/Spells/spell_item.cpp +++ b/src/server/scripts/Spells/spell_item.cpp @@ -1844,7 +1844,7 @@ class spell_item_unusual_compass : public SpellScriptLoader { Unit* caster = GetCaster(); caster->SetOrientation(frand(0.0f, 62832.0f) / 10000.0f); - caster->SendMovementFlagUpdate(); + caster->SendMovementFlagUpdate(true); } void Register() -- cgit v1.2.3 From 948f9d11f21ad38f9b3410638da04838cb4a5361 Mon Sep 17 00:00:00 2001 From: Aokromes Date: Fri, 12 Oct 2012 04:32:14 +0300 Subject: Core/Battlefield: Compile Fix --- src/server/game/Battlefield/Zones/BattlefieldWG.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/server/game/Battlefield/Zones/BattlefieldWG.h b/src/server/game/Battlefield/Zones/BattlefieldWG.h index 1af096a3180..49ea25a5e04 100644 --- a/src/server/game/Battlefield/Zones/BattlefieldWG.h +++ b/src/server/game/Battlefield/Zones/BattlefieldWG.h @@ -582,7 +582,7 @@ struct WintergraspBuildingSpawnData struct WintergraspRebuildableBuildingData { uint32 entry; - uint64 Guid + uint64 Guid; uint32 WorldState; float x; float y; -- cgit v1.2.3 From 4a332082f9d9d4988858abd66664a7e15c890458 Mon Sep 17 00:00:00 2001 From: tibbi Date: Fri, 12 Oct 2012 13:47:57 +0100 Subject: renaming GetBaseReputation used for offline players --- src/server/game/Globals/ObjectMgr.cpp | 2 +- src/server/game/Globals/ObjectMgr.h | 2 +- src/server/game/Handlers/CharacterHandler.cpp | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index b28f8be7805..b884a369eeb 100755 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -7591,7 +7591,7 @@ SpellScriptsBounds ObjectMgr::GetSpellScriptsBounds(uint32 spell_id) } // this allows calculating base reputations to offline players, just by race and class -int32 ObjectMgr::GetBaseReputation(FactionEntry const* factionEntry, uint8 race, uint8 playerClass) +int32 ObjectMgr::GetBaseReputationOff(FactionEntry const* factionEntry, uint8 race, uint8 playerClass) { if (!factionEntry) return 0; diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h index 7871bbe3239..bfedd8cd8d0 100755 --- a/src/server/game/Globals/ObjectMgr.h +++ b/src/server/game/Globals/ObjectMgr.h @@ -749,7 +749,7 @@ class ObjectMgr return NULL; } - int32 GetBaseReputation(FactionEntry const* factionEntry, uint8 race, uint8 playerClass); + int32 GetBaseReputationOff(FactionEntry const* factionEntry, uint8 race, uint8 playerClass); RepSpilloverTemplate const* GetRepSpilloverTemplate(uint32 factionId) const { diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index 853e71fd732..396537c1304 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -2027,10 +2027,10 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recv_data) FactionEntry const* factionEntry = sFactionStore.LookupEntry(oldReputation); // old base reputation - int32 oldBaseRep = sObjectMgr->GetBaseReputation(factionEntry, oldRace, playerClass); + int32 oldBaseRep = sObjectMgr->GetBaseReputationOff(factionEntry, oldRace, playerClass); // new base reputation - int32 newBaseRep = sObjectMgr->GetBaseReputation(sFactionStore.LookupEntry(newReputation), race, playerClass); + int32 newBaseRep = sObjectMgr->GetBaseReputationOff(sFactionStore.LookupEntry(newReputation), race, playerClass); // final reputation shouldnt change int32 FinalRep = oldDBRep + oldBaseRep; -- cgit v1.2.3 From b06e9cfd41e11b8efed8c1e8abb7899b91897b8d Mon Sep 17 00:00:00 2001 From: Subv Date: Fri, 12 Oct 2012 09:33:34 -0500 Subject: Revert "Core/Entities: Do not create the model twice for a GameObject." This reverts commit 0f166336caaf33eb01cffe19d5bb49f729d8d22d. --- src/server/game/Entities/GameObject/GameObject.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index c9874932e3e..da6e4ef8407 100755 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -217,6 +217,7 @@ bool GameObject::Create(uint32 guidlow, uint32 name_id, Map* map, uint32 phaseMa SetDisplayId(goinfo->displayId); + m_model = GameObjectModel::Create(*this); // GAMEOBJECT_BYTES_1, index at 0, 1, 2 and 3 SetGoType(GameobjectTypes(goinfo->type)); SetGoState(go_state); -- cgit v1.2.3 From c8c4291c6f57616489f7d511595c07a63bd230bc Mon Sep 17 00:00:00 2001 From: Warpten Date: Fri, 12 Oct 2012 22:13:28 +0200 Subject: Core/Commands: Allow .modify money to take another parameter structure: Example uses: * .modify money 325g 25s 12c is the same as .modify money 3252512 * .modify money -12g is the same as .modify money -120000 * .modify money -12g 45s is the same as .modify money -115500 * .modify money 25c 18g is the same as .modify money 18g 25c --- src/server/scripts/Commands/cs_modify.cpp | 28 ++++++++++++++++------------ src/server/shared/Utilities/Util.cpp | 31 +++++++++++++++++++++++++++++++ src/server/shared/Utilities/Util.h | 2 ++ 3 files changed, 49 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/server/scripts/Commands/cs_modify.cpp b/src/server/scripts/Commands/cs_modify.cpp index a88c765c596..ff74ae83c20 100644 --- a/src/server/scripts/Commands/cs_modify.cpp +++ b/src/server/scripts/Commands/cs_modify.cpp @@ -1002,15 +1002,19 @@ public: if (handler->HasLowerSecurity(target, 0)) return false; - int32 addmoney = atoi((char*)args); + int32 moneyToAdd = 0; + if (strchr(args, 'g') || strchr(args, 's') || strchr(args, 'c')) + moneyToAdd = MoneyStringToMoney(std::string(args)); + else + moneyToAdd = atoi(args); - uint32 moneyuser = target->GetMoney(); + uint32 targetMoney = target->GetMoney(); - if (addmoney < 0) + if (moneyToAdd < 0) { - int32 newmoney = int32(moneyuser) + addmoney; + int32 newmoney = int32(targetMoney) + moneyToAdd; - sLog->outDebug(LOG_FILTER_GENERAL, handler->GetTrinityString(LANG_CURRENT_MONEY), moneyuser, addmoney, newmoney); + sLog->outDebug(LOG_FILTER_GENERAL, handler->GetTrinityString(LANG_CURRENT_MONEY), targetMoney, moneyToAdd, newmoney); if (newmoney <= 0) { handler->PSendSysMessage(LANG_YOU_TAKE_ALL_MONEY, handler->GetNameLink(target).c_str()); @@ -1024,25 +1028,25 @@ public: if (newmoney > MAX_MONEY_AMOUNT) newmoney = MAX_MONEY_AMOUNT; - handler->PSendSysMessage(LANG_YOU_TAKE_MONEY, abs(addmoney), handler->GetNameLink(target).c_str()); + handler->PSendSysMessage(LANG_YOU_TAKE_MONEY, abs(moneyToAdd), handler->GetNameLink(target).c_str()); if (handler->needReportToTarget(target)) - (ChatHandler(target)).PSendSysMessage(LANG_YOURS_MONEY_TAKEN, handler->GetNameLink().c_str(), abs(addmoney)); + (ChatHandler(target)).PSendSysMessage(LANG_YOURS_MONEY_TAKEN, handler->GetNameLink().c_str(), abs(moneyToAdd)); target->SetMoney(newmoney); } } else { - handler->PSendSysMessage(LANG_YOU_GIVE_MONEY, addmoney, handler->GetNameLink(target).c_str()); + handler->PSendSysMessage(LANG_YOU_GIVE_MONEY, moneyToAdd, handler->GetNameLink(target).c_str()); if (handler->needReportToTarget(target)) - (ChatHandler(target)).PSendSysMessage(LANG_YOURS_MONEY_GIVEN, handler->GetNameLink().c_str(), addmoney); + (ChatHandler(target)).PSendSysMessage(LANG_YOURS_MONEY_GIVEN, handler->GetNameLink().c_str(), moneyToAdd); - if (addmoney >=MAX_MONEY_AMOUNT) + if (moneyToAdd >= MAX_MONEY_AMOUNT) target->SetMoney(MAX_MONEY_AMOUNT); else - target->ModifyMoney(addmoney); + target->ModifyMoney(moneyToAdd); } - sLog->outDebug(LOG_FILTER_GENERAL, handler->GetTrinityString(LANG_NEW_MONEY), moneyuser, addmoney, target->GetMoney()); + sLog->outDebug(LOG_FILTER_GENERAL, handler->GetTrinityString(LANG_NEW_MONEY), targetMoney, moneyToAdd, target->GetMoney()); return true; } diff --git a/src/server/shared/Utilities/Util.cpp b/src/server/shared/Utilities/Util.cpp index 0897c8814ab..407d0704619 100755 --- a/src/server/shared/Utilities/Util.cpp +++ b/src/server/shared/Utilities/Util.cpp @@ -150,6 +150,37 @@ std::string secsToTimeString(uint64 timeInSecs, bool shortText, bool hoursOnly) return ss.str(); } +int32 MoneyStringToMoney(const std::string& moneyString) +{ + int32 money = 0; + + if (!(std::count(moneyString.begin(), moneyString.end(), 'g') == 1 || + std::count(moneyString.begin(), moneyString.end(), 's') == 1 || + std::count(moneyString.begin(), moneyString.end(), 'c') == 1)) + return 0; // Bad format + + Tokenizer tokens(moneyString, ' '); + for (Tokenizer::const_iterator itr = tokens.begin(); itr != tokens.end(); ++itr) + { + std::string tokenString(*itr); + uint32 gCount = std::count(tokenString.begin(), tokenString.end(), 'g'); + uint32 sCount = std::count(tokenString.begin(), tokenString.end(), 's'); + uint32 cCount = std::count(tokenString.begin(), tokenString.end(), 'c'); + if (gCount + sCount + cCount != 1) + return 0; + + uint32 amount = atoi(*itr); + if (gCount == 1) + money += amount * 100 * 100; + else if (sCount == 1) + money += amount * 100; + else if (cCount == 1) + money += amount; + } + + return money; +} + uint32 TimeStringToSecs(const std::string& timestring) { uint32 secs = 0; diff --git a/src/server/shared/Utilities/Util.h b/src/server/shared/Utilities/Util.h index f84e5155bb1..f46fc991cc7 100755 --- a/src/server/shared/Utilities/Util.h +++ b/src/server/shared/Utilities/Util.h @@ -66,6 +66,8 @@ private: void stripLineInvisibleChars(std::string &src); +int32 MoneyStringToMoney(const std::string& moneyString); + std::string secsToTimeString(uint64 timeInSecs, bool shortText = false, bool hoursOnly = false); uint32 TimeStringToSecs(const std::string& timestring); std::string TimeToTimestampStr(time_t t); -- cgit v1.2.3 From d28a62e579614a7d6be145a6acccbbfa0ae70026 Mon Sep 17 00:00:00 2001 From: MrSmite Date: Fri, 12 Oct 2012 16:48:33 -0400 Subject: Cleanup PetAI, remove unnecessary and broken JustDied(). Closes #7242 Thanks to Oiler2112 for suggestions and testing. --- src/server/game/AI/CoreAI/PetAI.cpp | 16 ++++++++++++++-- src/server/game/AI/CoreAI/PetAI.h | 2 -- src/server/scripts/World/npcs_special.cpp | 2 -- 3 files changed, 14 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/server/game/AI/CoreAI/PetAI.cpp b/src/server/game/AI/CoreAI/PetAI.cpp index 99cf1cda4fc..6802c109401 100755 --- a/src/server/game/AI/CoreAI/PetAI.cpp +++ b/src/server/game/AI/CoreAI/PetAI.cpp @@ -71,6 +71,8 @@ void PetAI::_stopAttack() } me->AttackStop(); + me->InterruptNonMeleeSpells(false); + me->SendMeleeAttackStop(); // Should stop pet's attack button from flashing me->GetCharmInfo()->SetIsCommandAttack(false); HandleReturnMovement(); } @@ -89,7 +91,8 @@ void PetAI::UpdateAI(const uint32 diff) m_updateAlliesTimer -= diff; // me->getVictim() can't be used for check in case stop fighting, me->getVictim() clear at Unit death etc. - if (me->getVictim()) + // Must also check if victim is alive + if (me->getVictim() && me->getVictim()->isAlive()) { // is only necessary to stop casting, the pet must not exit combat if (me->getVictim()->HasBreakableByDamageCrowdControlAura(me)) @@ -121,10 +124,16 @@ void PetAI::UpdateAI(const uint32 diff) if (nextTarget) AttackStart(nextTarget); else + { + me->GetCharmInfo()->SetIsCommandAttack(false); HandleReturnMovement(); + } } else + { + me->GetCharmInfo()->SetIsCommandAttack(false); HandleReturnMovement(); + } } else if (owner && !me->HasUnitState(UNIT_STATE_FOLLOW)) // no charm info and no victim HandleReturnMovement(); @@ -301,7 +310,7 @@ void PetAI::KilledUnit(Unit* victim) // Can't use _stopAttack() because that activates movement handlers and ignores // next target selection me->AttackStop(); - me->GetCharmInfo()->SetIsCommandAttack(false); + me->InterruptNonMeleeSpells(false); me->SendMeleeAttackStop(); // Stops the pet's 'Attack' button from flashing Unit* nextTarget = SelectNextTarget(); @@ -309,7 +318,10 @@ void PetAI::KilledUnit(Unit* victim) if (nextTarget) AttackStart(nextTarget); else + { + me->GetCharmInfo()->SetIsCommandAttack(false); HandleReturnMovement(); // Return + } } void PetAI::AttackStart(Unit* target) diff --git a/src/server/game/AI/CoreAI/PetAI.h b/src/server/game/AI/CoreAI/PetAI.h index 8e5311fa000..d7f1dca3fbf 100755 --- a/src/server/game/AI/CoreAI/PetAI.h +++ b/src/server/game/AI/CoreAI/PetAI.h @@ -32,8 +32,6 @@ class PetAI : public CreatureAI explicit PetAI(Creature* c); void EnterEvadeMode(); - void JustDied(Unit* /*who*/) { _stopAttack(); } - void UpdateAI(const uint32); static int Permissible(const Creature*); diff --git a/src/server/scripts/World/npcs_special.cpp b/src/server/scripts/World/npcs_special.cpp index 9ade37a1096..b8df77d0346 100644 --- a/src/server/scripts/World/npcs_special.cpp +++ b/src/server/scripts/World/npcs_special.cpp @@ -2121,8 +2121,6 @@ class npc_shadowfiend : public CreatureScript if (Unit* owner = me->ToTempSummon()->GetSummoner()) if (owner->HasAura(GLYPH_OF_SHADOWFIEND)) owner->CastSpell(owner, GLYPH_OF_SHADOWFIEND_MANA, true); - - PetAI::JustDied(killer); } }; -- cgit v1.2.3 From ae4f5f3deea6960d765f6b770a5f6adf7bac9881 Mon Sep 17 00:00:00 2001 From: Elron103 Date: Sat, 13 Oct 2012 00:43:20 +0200 Subject: Core/Spells: Fix power drain effect for heroic versions of spell 70759 (72015, 72016) - thanks to Shauren --- src/server/game/Spells/SpellMgr.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index ec7359a7ba4..fb39310aabe 100755 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -3486,6 +3486,10 @@ void SpellMgr::LoadDbcDataCorrections() case 71085: // Mana Void (periodic aura) spellInfo->DurationIndex = 9; // 30 seconds (missing) break; + case 72015: // Frostbolt Volley (only heroic) + case 72016: // Frostbolt Volley (only heroic) + spellInfo->EffectRadiusIndex[2] = 23; // 40 yards + break; case 70936: // Summon Suppressor (needs target selection script) spellInfo->EffectImplicitTargetA[0] = TARGET_UNIT_TARGET_ANY; spellInfo->EffectImplicitTargetB[0] = 0; -- cgit v1.2.3 From 6f0a8040d8d363064c7d4aa65d3b3d6f40796009 Mon Sep 17 00:00:00 2001 From: Nay Date: Sat, 13 Oct 2012 17:36:19 +0200 Subject: Core/SpellMgr: Replace magic number by constant MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Thanks 2010phenix --- src/server/game/Spells/SpellMgr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index fb39310aabe..7c2ea8fbe9f 100755 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -3488,7 +3488,7 @@ void SpellMgr::LoadDbcDataCorrections() break; case 72015: // Frostbolt Volley (only heroic) case 72016: // Frostbolt Volley (only heroic) - spellInfo->EffectRadiusIndex[2] = 23; // 40 yards + spellInfo->EffectRadiusIndex[2] = EFFECT_RADIUS_40_YARDS; break; case 70936: // Summon Suppressor (needs target selection script) spellInfo->EffectImplicitTargetA[0] = TARGET_UNIT_TARGET_ANY; -- cgit v1.2.3 From 8536b360a06fac25cef240bb080edd581c275d94 Mon Sep 17 00:00:00 2001 From: Subv Date: Tue, 16 Oct 2012 09:24:53 -0500 Subject: Core/Spells: Fix a possible crash in Light's Beacon when a player logged in with the aura. --- src/server/game/Entities/Unit/Unit.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index c1f7a5a1fe5..47449c2bf88 100755 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -6637,7 +6637,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere if (GetTypeId() != TYPEID_PLAYER) { beaconTarget = triggeredByAura->GetBase()->GetCaster(); - if (beaconTarget == this || !(beaconTarget->GetAura(53563, victim->GetGUID()))) + if (!beaconTarget || beaconTarget == this || !(beaconTarget->GetAura(53563, victim->GetGUID()))) return false; basepoints0 = int32(damage); triggered_spell_id = procSpell->IsRankOf(sSpellMgr->GetSpellInfo(635)) ? 53652 : 53654; -- cgit v1.2.3 From fba9c0a82eb61980ffd3c7a912be9479ccad011c Mon Sep 17 00:00:00 2001 From: Subv Date: Tue, 16 Oct 2012 09:39:56 -0500 Subject: Scripts/Halion: Fixed some warnings --- .../scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp index 64210e97122..6ba13014585 100644 --- a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp +++ b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp @@ -696,7 +696,7 @@ class npc_halion_controller : public CreatureScript halion->AI()->Talk(SAY_INTRO); break; case EVENT_TWILIGHT_MENDING: - if (Creature* halion = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_HALION))) + if (ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_HALION))) // Just check if physical Halion is spawned if (Creature* twilightHalion = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_TWILIGHT_HALION))) twilightHalion->CastSpell((Unit*)NULL, SPELL_TWILIGHT_MENDING, true); break; @@ -1115,7 +1115,7 @@ class npc_combustion_consumption : public CreatureScript struct npc_combustion_consumptionAI : public Scripted_NoMovementAI { npc_combustion_consumptionAI(Creature* creature) : Scripted_NoMovementAI(creature), - _summonerGuid(0), _instance(creature->GetInstanceScript()) + _instance(creature->GetInstanceScript()), _summonerGuid(0) { switch (me->GetEntry()) { -- cgit v1.2.3 From 88ddc9662ee811ab39fe22ec2c536f5af0f71e11 Mon Sep 17 00:00:00 2001 From: kaelima Date: Wed, 17 Oct 2012 00:43:57 +0200 Subject: Core/Battleground: Allow players to start capping flags stealthed or invisible - gameobject should remove the stealth/invis aura on use. --- src/server/game/Entities/Player/Player.cpp | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 0d31c40f3a1..0f01e6c129e 100755 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -23590,21 +23590,15 @@ bool Player::CanUseBattlegroundObject() // TODO : some spells gives player ForceReaction to one faction (ReputationMgr::ApplyForceReaction) // maybe gameobject code should handle that ForceReaction usage // BUG: sometimes when player clicks on flag in AB - client won't send gameobject_use, only gameobject_report_use packet - return (//InBattleground() && // in battleground - not need, check in other cases - //!IsMounted() && - not correct, player is dismounted when he clicks on flag - //player cannot use object when he is invulnerable (immune) - !isTotalImmune() && // not totally immune - //i'm not sure if these two are correct, because invisible players should get visible when they click on flag - !HasStealthAura() && // not stealthed - !HasInvisibilityAura() && // not invisible - !HasAura(SPELL_RECENTLY_DROPPED_FLAG) && // can't pickup - isAlive() // live player -); + // Note: Mount, stealth and invisibility will be removed when used + return (!isTotalImmune() && // Damage immune + !HasAura(SPELL_RECENTLY_DROPPED_FLAG) && // Still has recently held flag debuff + isAlive()); // Alive } bool Player::CanCaptureTowerPoint() { - return (!HasStealthAura() && // not stealthed + return (!HasStealthAura() && // not stealthed !HasInvisibilityAura() && // not invisible isAlive() // live player ); -- cgit v1.2.3 From 4ec23cdba5681808a3bc456b997a860d76b1ab16 Mon Sep 17 00:00:00 2001 From: kaelima Date: Wed, 17 Oct 2012 00:46:11 +0200 Subject: Core/PacketIO: Automatically set field count in SMSG_INIT_WORLD_STATES instead of manual switch. --- src/server/game/Entities/Player/Player.cpp | 93 ++---------------------------- 1 file changed, 6 insertions(+), 87 deletions(-) (limited to 'src') diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 0f01e6c129e..d22aba92f9e 100755 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -9053,7 +9053,6 @@ void Player::SendInitWorldStates(uint32 zoneid, uint32 areaid) { // data depends on zoneid/mapid... Battleground* bg = GetBattleground(); - uint16 NumberOfFields = 0; uint32 mapid = GetMapId(); OutdoorPvP* pvp = sOutdoorPvPMgr->GetOutdoorPvPToZoneId(zoneid); InstanceScript* instance = GetInstanceScript(); @@ -9061,94 +9060,12 @@ void Player::SendInitWorldStates(uint32 zoneid, uint32 areaid) sLog->outDebug(LOG_FILTER_NETWORKIO, "Sending SMSG_INIT_WORLD_STATES to Map: %u, Zone: %u", mapid, zoneid); - // may be exist better way to do this... - switch (zoneid) - { - case 0: - case 1: - case 4: - case 8: - case 10: - case 11: - case 12: - case 36: - case 38: - case 40: - case 41: - case 51: - case 267: - case 1519: - case 1537: - case 2257: - case 2918: - NumberOfFields = 8; - break; - case 139: - NumberOfFields = 41; - break; - case 1377: - NumberOfFields = 15; - break; - case 2597: - NumberOfFields = 83; - break; - case 3277: - NumberOfFields = 18; - break; - case 3358: - case 3820: - NumberOfFields = 40; - break; - case 3483: - NumberOfFields = 27; - break; - case 3518: - NumberOfFields = 39; - break; - case 3519: - NumberOfFields = 38; - break; - case 3521: - NumberOfFields = 37; - break; - case 3698: - case 3702: - case 3968: - case 4378: - case 3703: - NumberOfFields = 11; - break; - case 4384: - NumberOfFields = 30; - break; - case 4710: - NumberOfFields = 28; - break; - case 4812: // Icecrown Citadel - case 4100: // The Culling of Stratholme - NumberOfFields = 13; - break; - case 4987: // The Ruby Sanctum - NumberOfFields = 3; - break; - case 4273: // Ulduar - NumberOfFields = 10; - break; - case 4197: // Wintergrasp - /// Use the max here, and fill with zeros if missing. - NumberOfFields = 10 + WG_MAX_OBJ + WG_MAX_WORKSHOP; - break; - default: - NumberOfFields = 12; - break; - } - - WorldPacket data(SMSG_INIT_WORLD_STATES, (4+4+4+2+(NumberOfFields*8))); + WorldPacket data(SMSG_INIT_WORLD_STATES, (4+4+4+2+(12*8))); data << uint32(mapid); // mapid data << uint32(zoneid); // zone id data << uint32(areaid); // area id, new 2.1.0 size_t countPos = data.wpos(); - data << uint16(NumberOfFields); // count of uint64 blocks + data << uint16(0); // count of uint64 blocks data << uint32(0x8d8) << uint32(0x0); // 1 data << uint32(0x8d7) << uint32(0x0); // 2 data << uint32(0x8d6) << uint32(0x0); // 3 @@ -9711,8 +9628,6 @@ void Player::SendInitWorldStates(uint32 zoneid, uint32 areaid) bf->FillInitialWorldStates(data); break; } - else - data.put(countPos, 12); // No break here, intended. default: data << uint32(0x914) << uint32(0x0); // 7 @@ -9721,6 +9636,10 @@ void Player::SendInitWorldStates(uint32 zoneid, uint32 areaid) data << uint32(0x915) << uint32(0x0); // 10 break; } + + uint16 length = (data.wpos() - countPos) / 8; + data.put(countPos, length); + GetSession()->SendPacket(&data); SendBGWeekendWorldStates(); SendBattlefieldWorldStates(); -- cgit v1.2.3 From 98588aa19202c2d259fba0717f9c4a4feac32a0a Mon Sep 17 00:00:00 2001 From: kaelima Date: Wed, 17 Oct 2012 00:53:55 +0200 Subject: Core/Ticket: - Fully parse CMSG_GMTICKET_CREATE, use GmTicket::GetChatLog() to access the reporters chat log from this session (unused atm, possible useful to detect chat harassment) - Simplify SMSG_GMTICKET_GETTICKET and fix "category" field (renamed it same as in blizz LUA files) - Store response in DB --- .../2012_10_17_00_character_gm_tickets.sql | 3 + src/server/game/Handlers/TicketHandler.cpp | 44 +++++++++++- src/server/game/Tickets/TicketMgr.cpp | 79 ++++++++++------------ src/server/game/Tickets/TicketMgr.h | 7 +- .../Database/Implementation/CharacterDatabase.cpp | 4 +- 5 files changed, 90 insertions(+), 47 deletions(-) create mode 100644 sql/updates/characters/2012_10_17_00_character_gm_tickets.sql (limited to 'src') diff --git a/sql/updates/characters/2012_10_17_00_character_gm_tickets.sql b/sql/updates/characters/2012_10_17_00_character_gm_tickets.sql new file mode 100644 index 00000000000..c41df0c115d --- /dev/null +++ b/sql/updates/characters/2012_10_17_00_character_gm_tickets.sql @@ -0,0 +1,3 @@ +ALTER TABLE `gm_tickets` + ADD COLUMN `response` TEXT NOT NULL AFTER `comment`, + ADD COLUMN `haveTicket` TINYINT(3) UNSIGNED NOT NULL AFTER `viewed`; diff --git a/src/server/game/Handlers/TicketHandler.cpp b/src/server/game/Handlers/TicketHandler.cpp index d6675188f6e..7fcfbbbc23e 100755 --- a/src/server/game/Handlers/TicketHandler.cpp +++ b/src/server/game/Handlers/TicketHandler.cpp @@ -16,6 +16,7 @@ * with this program. If not, see . */ +#include "zlib.h" #include "Language.h" #include "WorldPacket.h" #include "Common.h" @@ -26,7 +27,7 @@ #include "WorldSession.h" #include "Util.h" -void WorldSession::HandleGMTicketCreateOpcode(WorldPacket & recv_data) +void WorldSession::HandleGMTicketCreateOpcode(WorldPacket& recvData) { // Don't accept tickets if the ticket queue is disabled. (Ticket UI is greyed out but not fully dependable) if (sTicketMgr->GetStatus() == GMTICKET_QUEUE_STATUS_DISABLED) @@ -42,7 +43,46 @@ void WorldSession::HandleGMTicketCreateOpcode(WorldPacket & recv_data) // Player must not have ticket if (!sTicketMgr->GetTicketByPlayer(GetPlayer()->GetGUID())) { - GmTicket* ticket = new GmTicket(GetPlayer(), recv_data); + GmTicket* ticket = new GmTicket(GetPlayer(), recvData); + + uint32 count; + std::list times; + uint32 decompressedSize; + std::string chatLog; + + recvData >> count; + + for (uint32 i = 0; i < count; i++) + { + uint32 time; + recvData >> time; + times.push_back(time); + } + + recvData >> decompressedSize; + + if (count && decompressedSize && decompressedSize < 0xFFFF) + { + uint32 pos = recvData.rpos(); + ByteBuffer dest; + dest.resize(decompressedSize); + + uLongf realSize = decompressedSize; + if (uncompress(const_cast(dest.contents()), &realSize, const_cast(recvData.contents() + pos), recvData.size() - pos) == Z_OK) + { + dest >> chatLog; + ticket->SetChatLog(times, chatLog); + } + else + { + sLog->outError(LOG_FILTER_NETWORKIO, "CMSG_GMTICKET_CREATE possibly corrupt. Uncompression failed."); + recvData.rfinish(); + return; + } + + recvData.rfinish(); // Will still have compressed data in buffer. + } + sTicketMgr->AddTicket(ticket); sTicketMgr->UpdateLastChange(); diff --git a/src/server/game/Tickets/TicketMgr.cpp b/src/server/game/Tickets/TicketMgr.cpp index 0a4682db759..51e17cb9076 100755 --- a/src/server/game/Tickets/TicketMgr.cpp +++ b/src/server/game/Tickets/TicketMgr.cpp @@ -31,45 +31,32 @@ inline float GetAge(uint64 t) { return float(time(NULL) - t) / DAY; } // GM ticket GmTicket::GmTicket() { } -GmTicket::GmTicket(Player* player, WorldPacket& recv_data) : _createTime(time(NULL)), _lastModifiedTime(time(NULL)), _closedBy(0), _assignedTo(0), _completed(false), _escalatedStatus(TICKET_UNASSIGNED) +GmTicket::GmTicket(Player* player, WorldPacket& recvData) : _createTime(time(NULL)), _lastModifiedTime(time(NULL)), _closedBy(0), _assignedTo(0), _completed(false), _escalatedStatus(TICKET_UNASSIGNED), _haveTicket(false) { _id = sTicketMgr->GenerateTicketId(); _playerName = player->GetName(); _playerGuid = player->GetGUID(); uint32 mapId; - recv_data >> mapId; // Map is sent as UInt32! + recvData >> mapId; // Map is sent as UInt32! _mapId = mapId; - recv_data >> _posX; - recv_data >> _posY; - recv_data >> _posZ; - recv_data >> _message; + recvData >> _posX; + recvData >> _posY; + recvData >> _posZ; + recvData >> _message; uint32 needResponse; - recv_data >> needResponse; - _needResponse = (needResponse == 17); // Requires GM response. 17 = true, 1 = false (17 is default) - uint8 unk1; - recv_data >> unk1; // Requests further GM interaction on a ticket to which a GM has already responded - - recv_data.rfinish(); - /* - recv_data >> uint32(count); // text lines - for (int i = 0; i < count; i++) - recv_data >> uint32(); - - if (something) - recv_data >> uint32(); - else - compressed uint32 + string; - */ + recvData >> needResponse; + _needResponse = (needResponse == 17); // Requires GM response. 17 = true, 1 = false (17 is default) + recvData >> _haveTicket; // Requests further GM interaction on a ticket to which a GM has already responded. Basically means "has a new ticket" } GmTicket::~GmTicket() { } bool GmTicket::LoadFromDB(Field* fields) { - // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - // ticketId, guid, name, message, createTime, mapId, posX, posY, posZ, lastModifiedTime, closedBy, assignedTo, comment, completed, escalated, viewed + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 + // ticketId, guid, name, message, createTime, mapId, posX, posY, posZ, lastModifiedTime, closedBy, assignedTo, comment, response, completed, escalated, viewed, haveTicket uint8 index = 0; _id = fields[ index].GetUInt32(); _playerGuid = MAKE_NEW_GUID(fields[++index].GetUInt32(), 0, HIGHGUID_PLAYER); @@ -84,9 +71,11 @@ bool GmTicket::LoadFromDB(Field* fields) _closedBy = fields[++index].GetInt32(); _assignedTo = MAKE_NEW_GUID(fields[++index].GetUInt32(), 0, HIGHGUID_PLAYER); _comment = fields[++index].GetString(); + _response = fields[++index].GetString(); _completed = fields[++index].GetBool(); _escalatedStatus = GMTicketEscalationStatus(fields[++index].GetUInt8()); _viewed = fields[++index].GetBool(); + _haveTicket = fields[++index].GetBool(); return true; } @@ -109,9 +98,11 @@ void GmTicket::SaveToDB(SQLTransaction& trans) const stmt->setInt32 (++index, GUID_LOPART(_closedBy)); stmt->setUInt32(++index, GUID_LOPART(_assignedTo)); stmt->setString(++index, _comment); + stmt->setString(++index, _response); stmt->setBool (++index, _completed); stmt->setUInt8 (++index, uint8(_escalatedStatus)); stmt->setBool (++index, _viewed); + stmt->setBool (++index, _haveTicket); CharacterDatabase.ExecuteOrAppend(trans, stmt); } @@ -125,6 +116,10 @@ void GmTicket::DeleteFromDB() void GmTicket::WritePacket(WorldPacket& data) const { + data << uint32(GMTICKET_STATUS_HASTEXT); + data << uint32(_id); + data << _message; + data << uint8(_haveTicket); data << GetAge(_lastModifiedTime); if (GmTicket* ticket = sTicketMgr->GetOldestOpenTicket()) data << GetAge(ticket->GetLastModifiedTime()); @@ -223,6 +218,20 @@ void GmTicket::TeleportTo(Player* player) const player->TeleportTo(_mapId, _posX, _posY, _posZ, 0.0f, 0); } +void GmTicket::SetChatLog(std::list time, std::string const& log) +{ + std::stringstream ss(log); + std::stringstream newss; + std::string line; + while (std::getline(ss, line)) + { + newss << secsToTimeString(time.front()) << ": " << line << "\n"; + time.pop_front(); + } + + _chatLog = newss.str(); +} + /////////////////////////////////////////////////////////////////////////////////////////////////// // Ticket manager TicketMgr::TicketMgr() : _status(true), _lastTicketId(0), _lastSurveyId(0), _openTicketCount(0), _lastChange(time(NULL)) { } @@ -365,26 +374,12 @@ void TicketMgr::ShowEscalatedList(ChatHandler& handler) const void TicketMgr::SendTicket(WorldSession* session, GmTicket* ticket) const { - uint32 status = GMTICKET_STATUS_DEFAULT; - std::string message; - if (ticket) - { - message = ticket->GetMessage(); - status = GMTICKET_STATUS_HASTEXT; - } - - WorldPacket data(SMSG_GMTICKET_GETTICKET, (4 + 4 + (ticket ? message.length() + 1 + 4 + 4 + 4 + 1 + 1 : 0))); - data << uint32(status); // standard 0x0A, 0x06 if text present - data << uint32(ticket ? ticket->GetId() : 0); // ticketID + WorldPacket data(SMSG_GMTICKET_GETTICKET, (ticket ? (4 + 4 + 1 + 4 + 4 + 4 + 1 + 1) : 4)); if (ticket) - { - data << message.c_str(); // ticket text - data << uint8(0x7); // ticket category; why is this hardcoded? does it make a diff re: client? - - // we've got the easy stuff done by now. - // Now we need to go through the client logic for displaying various levels of ticket load ticket->WritePacket(data); - } + else + data << uint32(GMTICKET_STATUS_DEFAULT); + session->SendPacket(&data); } diff --git a/src/server/game/Tickets/TicketMgr.h b/src/server/game/Tickets/TicketMgr.h index ecf315c059c..63837e39452 100755 --- a/src/server/game/Tickets/TicketMgr.h +++ b/src/server/game/Tickets/TicketMgr.h @@ -82,7 +82,7 @@ class GmTicket { public: GmTicket(); - explicit GmTicket(Player* player, WorldPacket& recv_data); + explicit GmTicket(Player* player, WorldPacket& recvData); ~GmTicket(); bool IsClosed() const { return _closedBy; } @@ -142,6 +142,9 @@ public: std::string FormatMessageString(ChatHandler& handler, bool detailed = false) const; std::string FormatMessageString(ChatHandler& handler, const char* szClosedName, const char* szAssignedToName, const char* szUnassignedName, const char* szDeletedName) const; + void SetChatLog(std::list time, std::string const& log); + std::string GetChatLog() const { return _chatLog; } + private: uint32 _id; uint64 _playerGuid; @@ -160,7 +163,9 @@ private: GMTicketEscalationStatus _escalatedStatus; bool _viewed; bool _needResponse; // TODO: find out the use of this, and then store it in DB + bool _haveTicket; std::string _response; + std::string _chatLog; // No need to store in db, will be refreshed every session client side }; typedef std::map GmTicketList; diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.cpp b/src/server/shared/Database/Implementation/CharacterDatabase.cpp index c29d8313c20..d9b517c098f 100644 --- a/src/server/shared/Database/Implementation/CharacterDatabase.cpp +++ b/src/server/shared/Database/Implementation/CharacterDatabase.cpp @@ -327,8 +327,8 @@ void CharacterDatabaseConnection::DoPrepareStatements() PREPARE_STATEMENT(CHAR_DEL_GO_RESPAWN_BY_INSTANCE, "DELETE FROM gameobject_respawn WHERE mapId = ? AND instanceId = ?", CONNECTION_ASYNC) // GM Tickets - PREPARE_STATEMENT(CHAR_SEL_GM_TICKETS, "SELECT ticketId, guid, name, message, createTime, mapId, posX, posY, posZ, lastModifiedTime, closedBy, assignedTo, comment, completed, escalated, viewed FROM gm_tickets", CONNECTION_SYNCH) - PREPARE_STATEMENT(CHAR_REP_GM_TICKET, "REPLACE INTO gm_tickets (ticketId, guid, name, message, createTime, mapId, posX, posY, posZ, lastModifiedTime, closedBy, assignedTo, comment, completed, escalated, viewed) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC) + PREPARE_STATEMENT(CHAR_SEL_GM_TICKETS, "SELECT ticketId, guid, name, message, createTime, mapId, posX, posY, posZ, lastModifiedTime, closedBy, assignedTo, comment, response, completed, escalated, viewed, haveTicket FROM gm_tickets", CONNECTION_SYNCH) + PREPARE_STATEMENT(CHAR_REP_GM_TICKET, "REPLACE INTO gm_tickets (ticketId, guid, name, message, createTime, mapId, posX, posY, posZ, lastModifiedTime, closedBy, assignedTo, comment, response, completed, escalated, viewed, haveTicket) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC) PREPARE_STATEMENT(CHAR_DEL_GM_TICKET, "DELETE FROM gm_tickets WHERE ticketId = ?", CONNECTION_ASYNC) PREPARE_STATEMENT(CHAR_DEL_PLAYER_GM_TICKETS, "DELETE FROM gm_tickets WHERE guid = ?", CONNECTION_ASYNC) -- cgit v1.2.3 From 290ddd64fe0f3ab66ce06da0bec5f1f6ea4988e7 Mon Sep 17 00:00:00 2001 From: durotar Date: Tue, 16 Oct 2012 19:30:33 -0500 Subject: Core/Script: Update creature_text for gnomeregan --- .../EasternKingdoms/Gnomeregan/gnomeregan.cpp | 130 ++++++++++++--------- .../EasternKingdoms/Gnomeregan/gnomeregan.h | 3 +- 2 files changed, 74 insertions(+), 59 deletions(-) (limited to 'src') diff --git a/src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.cpp b/src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.cpp index f1aa3d68bce..8b0774a4bd7 100644 --- a/src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.cpp +++ b/src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.cpp @@ -30,40 +30,41 @@ Script Data End */ #define GOSSIP_START_EVENT "I am ready to being" -enum eBlastmasterEmiShortfuse +enum BlastmasterEmi { GOSSIP_TEXT_EMI = 1693, - SAY_BLASTMASTER_0 = -1090000, - SAY_BLASTMASTER_1 = -1090001, - SAY_BLASTMASTER_2 = -1090002, - SAY_BLASTMASTER_3 = -1090003, - SAY_BLASTMASTER_4 = -1090004, - SAY_BLASTMASTER_5 = -1090005, - SAY_BLASTMASTER_6 = -1090006, - SAY_BLASTMASTER_7 = -1090007, - SAY_BLASTMASTER_8 = -1090008, - SAY_BLASTMASTER_9 = -1090009, - SAY_BLASTMASTER_10 = -1090010, - SAY_BLASTMASTER_11 = -1090011, - SAY_BLASTMASTER_12 = -1090012, - SAY_BLASTMASTER_13 = -1090013, - SAY_BLASTMASTER_14 = -1090014, - SAY_BLASTMASTER_15 = -1090015, - SAY_BLASTMASTER_16 = -1090016, - SAY_BLASTMASTER_17 = -1090017, - SAY_BLASTMASTER_18 = -1090018, - SAY_BLASTMASTER_19 = -1090019, - SAY_BLASTMASTER_20 = -1090020, - SAY_BLASTMASTER_21 = -1090021, - SAY_BLASTMASTER_22 = -1090022, - SAY_BLASTMASTER_23 = -1090023, - SAY_BLASTMASTER_24 = -1090024, - SAY_BLASTMASTER_25 = -1090025, - SAY_BLASTMASTER_26 = -1090026, - SAY_BLASTMASTER_27 = -1090027, - - SAY_GRUBBIS = -1090028 + SAY_BLASTMASTER_0 = 0, + SAY_BLASTMASTER_1 = 1, + SAY_BLASTMASTER_2 = 2, + SAY_BLASTMASTER_3 = 3, + SAY_BLASTMASTER_4 = 4, + SAY_BLASTMASTER_5 = 5, + SAY_BLASTMASTER_6 = 6, + SAY_BLASTMASTER_7 = 7, + SAY_BLASTMASTER_8 = 8, + SAY_BLASTMASTER_9 = 9, + SAY_BLASTMASTER_10 = 10, + SAY_BLASTMASTER_11 = 11, + SAY_BLASTMASTER_12 = 12, + SAY_BLASTMASTER_13 = 13, + SAY_BLASTMASTER_14 = 14, + SAY_BLASTMASTER_15 = 15, + SAY_BLASTMASTER_16 = 16, + SAY_BLASTMASTER_17 = 17, + SAY_BLASTMASTER_18 = 18, + SAY_BLASTMASTER_19 = 19, + SAY_BLASTMASTER_20 = 20, + SAY_BLASTMASTER_21 = 21, + SAY_BLASTMASTER_22 = 22, + SAY_BLASTMASTER_23 = 23, + SAY_BLASTMASTER_24 = 24, + SAY_BLASTMASTER_25 = 25, + SAY_BLASTMASTER_26 = 26, + SAY_BLASTMASTER_27 = 27, + SAY_BLASTMASTER_28 = 28, + + SAY_GRUBBIS = 0 }; const Position SpawnPosition[] = @@ -78,13 +79,16 @@ const Position SpawnPosition[] = {-552.534f, -110.012f, -153.577f, 0.747f}, {-550.708f, -116.436f, -153.103f, 0.679f}, {-554.030f, -115.983f, -152.635f, 0.695f}, - {-494.595f, -87.516f, 149.116f, 3.344f}, + {-494.595f, -87.516f, -149.116f, 3.344f}, {-493.349f, -90.845f, -148.882f, 3.717f}, {-491.995f, -87.619f, -148.197f, 3.230f}, {-490.732f, -90.739f, -148.091f, 3.230f}, {-490.554f, -89.114f, -148.055f, 3.230f}, {-495.240f, -90.808f, -149.493f, 3.238f}, - {-494.195f, -89.553f, -149.131f, 3.254f} + {-494.195f, -89.553f, -149.131f, 3.254f}, + {-511.3304f, -139.9622f, -152.4761f}, + {-510.6754f, -139.4371f, -152.6167f}, + {-511.8976f, -139.3562f, -152.4785f} }; class npc_blastmaster_emi_shortfuse : public CreatureScript @@ -305,7 +309,7 @@ public: break; case 14: SetInFace(false); - DoScriptText(SAY_BLASTMASTER_26, me); + Talk(SAY_BLASTMASTER_26); SetEscortPaused(true); NextStep(5000, false, 20); break; @@ -318,8 +322,8 @@ public: { case 1: SetEscortPaused(true); - DoScriptText(SAY_BLASTMASTER_0, me); - NextStep(1500, true); + Talk(SAY_BLASTMASTER_0); + NextStep(2000, true); break; case 2: if (!instance) @@ -368,7 +372,7 @@ public: me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[1], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[2], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[3], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); - DoScriptText(SAY_BLASTMASTER_19, me); + Talk(SAY_BLASTMASTER_19); break; case 4: if (GameObject* go = me->SummonGameObject(183410, -542.199f, -96.854f, -155.790f, 0, 0, 0, 0, 0, 1000)) @@ -381,7 +385,7 @@ public: me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[1], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[2], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); - DoScriptText(SAY_BLASTMASTER_15, me); + Talk(SAY_BLASTMASTER_15); break; case 6: me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[10], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); @@ -406,10 +410,15 @@ public: } break; case 9: - if (Creature* pGrubbis = me->SummonCreature(NPC_GRUBBIS, SpawnPosition[15], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000)) - DoScriptText(SAY_GRUBBIS, pGrubbis); + if (Creature* grubbis = me->SummonCreature(NPC_GRUBBIS, SpawnPosition[15], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000)) + grubbis->AI()->Talk(SAY_GRUBBIS); me->SummonCreature(NPC_CHOMPER, SpawnPosition[16], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); break; + case 10: + me->SummonGameObject(GO_RED_ROCKET, SpawnPosition[17].GetPositionX(), SpawnPosition[17].GetPositionY(), SpawnPosition[17].GetPositionZ(), 0.7504908f, 0, 0, 0, 0, 7200); + me->SummonGameObject(GO_RED_ROCKET, SpawnPosition[18].GetPositionX(), SpawnPosition[18].GetPositionY(), SpawnPosition[18].GetPositionZ(), 3.33359f, 0, 0, 0, 0, 7200); + me->SummonGameObject(GO_RED_ROCKET, SpawnPosition[19].GetPositionX(), SpawnPosition[19].GetPositionY(), SpawnPosition[19].GetPositionZ(), 3.961899f, 0, 0, 0, 0, 7200); + break; } } @@ -422,29 +431,29 @@ public: switch (uiPhase) { case 1: - DoScriptText(SAY_BLASTMASTER_1, me); - NextStep(1500, true); + Talk(SAY_BLASTMASTER_1); + NextStep(2000, true); break; case 2: SetEscortPaused(false); NextStep(0, false, 0); break; case 3: - DoScriptText(SAY_BLASTMASTER_2, me); + Talk(SAY_BLASTMASTER_2); SetEscortPaused(false); NextStep(0, false, 0); break; case 4: - DoScriptText(SAY_BLASTMASTER_3, me); + Talk(SAY_BLASTMASTER_3); NextStep(3000, true); break; case 5: - DoScriptText(SAY_BLASTMASTER_4, me); + Talk(SAY_BLASTMASTER_4); NextStep(3000, true); break; case 6: SetInFace(true); - DoScriptText(SAY_BLASTMASTER_5, me); + Talk(SAY_BLASTMASTER_5); Summon(1); if (instance) if (GameObject* go = GameObject::GetGameObject(*me, instance->GetData64(DATA_GO_CAVE_IN_RIGHT))) @@ -452,12 +461,12 @@ public: NextStep(3000, true); break; case 7: - DoScriptText(SAY_BLASTMASTER_6, me); + Talk(SAY_BLASTMASTER_6); SetEscortPaused(false); NextStep(0, false, 0); break; case 8: - me->HandleEmoteCommand(EMOTE_STATE_WORK); + me->HandleEmoteCommand(EMOTE_STATE_USE_STANDING); NextStep(25000, true); break; case 9: @@ -469,28 +478,28 @@ public: NextStep(0, false); break; case 11: - DoScriptText(SAY_BLASTMASTER_17, me); + Talk(SAY_BLASTMASTER_17); NextStep(5000, true); break; case 12: - DoScriptText(SAY_BLASTMASTER_18, me); + Talk(SAY_BLASTMASTER_18); NextStep(5000, true); break; case 13: - DoScriptText(SAY_BLASTMASTER_20, me); + Talk(SAY_BLASTMASTER_20); CaveDestruction(true); NextStep(8000, true); break; case 14: - DoScriptText(SAY_BLASTMASTER_21, me); + Talk(SAY_BLASTMASTER_21); NextStep(8500, true); break; case 15: - DoScriptText(SAY_BLASTMASTER_22, me); + Talk(SAY_BLASTMASTER_22); NextStep(2000, true); break; case 16: - DoScriptText(SAY_BLASTMASTER_23, me); + Talk(SAY_BLASTMASTER_23); SetInFace(false); if (instance) if (GameObject* go = GameObject::GetGameObject(*me, instance->GetData64(DATA_GO_CAVE_IN_LEFT))) @@ -499,7 +508,7 @@ public: break; case 17: SetEscortPaused(false); - DoScriptText(SAY_BLASTMASTER_24, me); + Talk(SAY_BLASTMASTER_24); Summon(6); NextStep(0, false); break; @@ -510,11 +519,11 @@ public: case 19: SetInFace(false); Summon(8); - DoScriptText(SAY_BLASTMASTER_25, me); + Talk(SAY_BLASTMASTER_25); NextStep(0, false); break; case 20: - DoScriptText(SAY_BLASTMASTER_27, me); + Talk(SAY_BLASTMASTER_27); NextStep(2000, true); break; case 21: @@ -523,7 +532,12 @@ public: break; case 22: CaveDestruction(false); - DoScriptText(SAY_BLASTMASTER_20, me); + Talk(SAY_BLASTMASTER_20); + NextStep(2000, true); + break; + case 23: + Summon(10); + Talk(SAY_BLASTMASTER_28); NextStep(0, false); break; } diff --git a/src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.h b/src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.h index a62cf9f9cae..068ba5d26af 100644 --- a/src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.h +++ b/src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.h @@ -21,7 +21,8 @@ enum eGameObjects { GO_CAVE_IN_LEFT = 146085, - GO_CAVE_IN_RIGHT = 146086 + GO_CAVE_IN_RIGHT = 146086, + GO_RED_ROCKET = 103820 }; enum eCreatures -- cgit v1.2.3 From e56ef015ab9fdd37b0a5fc811412458329a8e4bc Mon Sep 17 00:00:00 2001 From: durotar Date: Tue, 16 Oct 2012 19:51:57 -0500 Subject: Added some suggestions from Subv --- src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.cpp b/src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.cpp index 8b0774a4bd7..65dc6c37d8a 100644 --- a/src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.cpp +++ b/src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.cpp @@ -86,9 +86,9 @@ const Position SpawnPosition[] = {-490.554f, -89.114f, -148.055f, 3.230f}, {-495.240f, -90.808f, -149.493f, 3.238f}, {-494.195f, -89.553f, -149.131f, 3.254f}, - {-511.3304f, -139.9622f, -152.4761f}, - {-510.6754f, -139.4371f, -152.6167f}, - {-511.8976f, -139.3562f, -152.4785f} + {-511.3304f, -139.9622f, -152.4761f, 0.7504908f}, + {-510.6754f, -139.4371f, -152.6167f, 3.33359f}, + {-511.8976f, -139.3562f, -152.4785f, 3.961899f} }; class npc_blastmaster_emi_shortfuse : public CreatureScript @@ -415,9 +415,9 @@ public: me->SummonCreature(NPC_CHOMPER, SpawnPosition[16], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); break; case 10: - me->SummonGameObject(GO_RED_ROCKET, SpawnPosition[17].GetPositionX(), SpawnPosition[17].GetPositionY(), SpawnPosition[17].GetPositionZ(), 0.7504908f, 0, 0, 0, 0, 7200); - me->SummonGameObject(GO_RED_ROCKET, SpawnPosition[18].GetPositionX(), SpawnPosition[18].GetPositionY(), SpawnPosition[18].GetPositionZ(), 3.33359f, 0, 0, 0, 0, 7200); - me->SummonGameObject(GO_RED_ROCKET, SpawnPosition[19].GetPositionX(), SpawnPosition[19].GetPositionY(), SpawnPosition[19].GetPositionZ(), 3.961899f, 0, 0, 0, 0, 7200); + me->SummonGameObject(GO_RED_ROCKET, SpawnPosition[17].GetPositionX(), SpawnPosition[17].GetPositionY(), SpawnPosition[17].GetPositionZ(), SpawnPosition[17].GetOrientation(), 0, 0, 0, 0, 7200); + me->SummonGameObject(GO_RED_ROCKET, SpawnPosition[18].GetPositionX(), SpawnPosition[18].GetPositionY(), SpawnPosition[18].GetPositionZ(), SpawnPosition[18].GetOrientation(), 0, 0, 0, 0, 7200); + me->SummonGameObject(GO_RED_ROCKET, SpawnPosition[19].GetPositionX(), SpawnPosition[19].GetPositionY(), SpawnPosition[19].GetPositionZ(), SpawnPosition[19].GetOrientation(), 0, 0, 0, 0, 7200); break; } } -- cgit v1.2.3 From 27f091806a6f52f406837d188dd4171019bfa59b Mon Sep 17 00:00:00 2001 From: Subv Date: Tue, 16 Oct 2012 21:43:23 -0500 Subject: Core/SpellAreas: Changed the way quest_start and quest_end works. They now follow this rule: The player's quest status of quest_start must have the mask defined in quest_start_status in order for the spell to be applied/kept. The player's quest status of quest_end must _NOT_ have the mask defined in quest_end_status in order for the spell to be removed To generate the mask: Take the QuestStatus enum in QuestDef.h, use (1 << theValueYouWant) to obtain a mask and you can use | to combine masks. This expands the usage of the spell_area table, making possible to give a player an aura while he has a quest, but remove it as soon as the quest is completed (not rewarded). Feature request by @Svannon --- .../world/2012_10_16_00_world_spell_area.sql | 4 ++ src/server/game/Entities/Player/Player.cpp | 64 ++++++++-------------- src/server/game/Spells/SpellMgr.cpp | 44 +++++---------- src/server/game/Spells/SpellMgr.h | 6 +- 4 files changed, 46 insertions(+), 72 deletions(-) create mode 100644 sql/updates/world/2012_10_16_00_world_spell_area.sql (limited to 'src') diff --git a/sql/updates/world/2012_10_16_00_world_spell_area.sql b/sql/updates/world/2012_10_16_00_world_spell_area.sql new file mode 100644 index 00000000000..3dbc29d077f --- /dev/null +++ b/sql/updates/world/2012_10_16_00_world_spell_area.sql @@ -0,0 +1,4 @@ +ALTER TABLE `spell_area` ADD COLUMN `quest_start_status` INT(11) NOT NULL DEFAULT 64; -- default is QUEST_STATUS_REWARDED +ALTER TABLE `spell_area` ADD COLUMN `quest_end_status` INT(11) NOT NULL DEFAULT 11; -- default is QUEST_STATUS_COMPLETE | QUEST_STATUS_NONE | QUEST_STATUS_INCOMPLETE +UPDATE spell_area SET `quest_start_status` = (1 << 6) | (1 << 3) | (1 << 1) WHERE `quest_start_active` = 1; +ALTER TABLE spell_area DROP COLUMN `quest_start_active`; \ No newline at end of file diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index d22aba92f9e..501379228e2 100755 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -14980,19 +14980,6 @@ void Player::AddQuest(Quest const* quest, Object* questGiver) if (questGiver && quest->GetQuestStartScript() != 0) GetMap()->ScriptsStart(sQuestStartScripts, quest->GetQuestStartScript(), questGiver, this); - // Some spells applied at quest activation - SpellAreaForQuestMapBounds saBounds = sSpellMgr->GetSpellAreaForQuestMapBounds(quest_id, true); - if (saBounds.first != saBounds.second) - { - uint32 zone, area; - GetZoneAndAreaId(zone, area); - - for (SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr) - if (itr->second->autocast && itr->second->IsFitToRequirements(this, zone, area)) - if (!HasAura(itr->second->spellId)) - CastSpell(this, itr->second->spellId, true); - } - UpdateForQuestWorldObjects(); } @@ -15181,33 +15168,6 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver, UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT); UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST, quest->GetQuestId()); - uint32 zone = 0; - uint32 area = 0; - - // remove auras from spells with quest reward state limitations - SpellAreaForQuestMapBounds saEndBounds = sSpellMgr->GetSpellAreaForQuestEndMapBounds(quest_id); - if (saEndBounds.first != saEndBounds.second) - { - GetZoneAndAreaId(zone, area); - - for (SpellAreaForAreaMap::const_iterator itr = saEndBounds.first; itr != saEndBounds.second; ++itr) - if (!itr->second->IsFitToRequirements(this, zone, area)) - RemoveAurasDueToSpell(itr->second->spellId); - } - - // Some spells applied at quest reward - SpellAreaForQuestMapBounds saBounds = sSpellMgr->GetSpellAreaForQuestMapBounds(quest_id, false); - if (saBounds.first != saBounds.second) - { - if (!zone || !area) - GetZoneAndAreaId(zone, area); - - for (SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr) - if (itr->second->autocast && itr->second->IsFitToRequirements(this, zone, area)) - if (!HasAura(itr->second->spellId)) - CastSpell(this, itr->second->spellId, true); - } - //lets remove flag for delayed teleports SetCanDelayTeleport(false); } @@ -15750,6 +15710,30 @@ void Player::SetQuestStatus(uint32 quest_id, QuestStatus status) m_QuestStatusSave[quest_id] = true; } + uint32 zone = 0, area = 0; + + SpellAreaForQuestMapBounds saBounds = sSpellMgr->GetSpellAreaForQuestMapBounds(quest_id); + if (saBounds.first != saBounds.second) + { + GetZoneAndAreaId(zone, area); + + for (SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr) + if (itr->second->autocast && itr->second->IsFitToRequirements(this, zone, area)) + if (!HasAura(itr->second->spellId)) + CastSpell(this, itr->second->spellId, true); + } + + saBounds = sSpellMgr->GetSpellAreaForQuestEndMapBounds(quest_id); + if (saBounds.first != saBounds.second) + { + if (!zone || !area) + GetZoneAndAreaId(zone, area); + + for (SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr) + if (!itr->second->IsFitToRequirements(this, zone, area)) + RemoveAurasDueToSpell(itr->second->spellId); + } + UpdateForQuestWorldObjects(); } diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index 7c2ea8fbe9f..06f1187a833 100755 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -1061,12 +1061,9 @@ SpellAreaMapBounds SpellMgr::GetSpellAreaMapBounds(uint32 spell_id) const return SpellAreaMapBounds(mSpellAreaMap.lower_bound(spell_id), mSpellAreaMap.upper_bound(spell_id)); } -SpellAreaForQuestMapBounds SpellMgr::GetSpellAreaForQuestMapBounds(uint32 quest_id, bool active) const +SpellAreaForQuestMapBounds SpellMgr::GetSpellAreaForQuestMapBounds(uint32 quest_id) const { - if (active) - return SpellAreaForQuestMapBounds(mSpellAreaForActiveQuestMap.lower_bound(quest_id), mSpellAreaForActiveQuestMap.upper_bound(quest_id)); - else - return SpellAreaForQuestMapBounds(mSpellAreaForQuestMap.lower_bound(quest_id), mSpellAreaForQuestMap.upper_bound(quest_id)); + return SpellAreaForQuestMapBounds(mSpellAreaForQuestMap.lower_bound(quest_id), mSpellAreaForQuestMap.upper_bound(quest_id)); } SpellAreaForQuestMapBounds SpellMgr::GetSpellAreaForQuestEndMapBounds(uint32 quest_id) const @@ -1099,11 +1096,11 @@ bool SpellArea::IsFitToRequirements(Player const* player, uint32 newZone, uint32 return false; if (questStart) // not in expected required quest state - if (!player || ((!questStartCanActive || !player->IsActiveQuest(questStart)) && !player->GetQuestRewardStatus(questStart))) + if (!player || (((1 << player->GetQuestStatus(questStart)) & questStartStatus) == 0)) return false; if (questEnd) // not in expected forbidden quest state - if (!player || player->GetQuestRewardStatus(questEnd)) + if (!player || (((1 << player->GetQuestStatus(questEnd)) & questEndStatus) == 0)) return false; if (auraSpell) // not have expected aura @@ -2433,12 +2430,11 @@ void SpellMgr::LoadSpellAreas() mSpellAreaMap.clear(); // need for reload case mSpellAreaForQuestMap.clear(); - mSpellAreaForActiveQuestMap.clear(); mSpellAreaForQuestEndMap.clear(); mSpellAreaForAuraMap.clear(); - // 0 1 2 3 4 5 6 7 8 - QueryResult result = WorldDatabase.Query("SELECT spell, area, quest_start, quest_start_active, quest_end, aura_spell, racemask, gender, autocast FROM spell_area"); + // 0 1 2 3 4 5 6 7 8 9 + QueryResult result = WorldDatabase.Query("SELECT spell, area, quest_start, quest_start_status, quest_end_status, quest_end, aura_spell, racemask, gender, autocast FROM spell_area"); if (!result) { @@ -2457,12 +2453,13 @@ void SpellMgr::LoadSpellAreas() spellArea.spellId = spell; spellArea.areaId = fields[1].GetUInt32(); spellArea.questStart = fields[2].GetUInt32(); - spellArea.questStartCanActive = fields[3].GetBool(); - spellArea.questEnd = fields[4].GetUInt32(); - spellArea.auraSpell = fields[5].GetInt32(); - spellArea.raceMask = fields[6].GetUInt32(); - spellArea.gender = Gender(fields[7].GetUInt8()); - spellArea.autocast = fields[8].GetBool(); + spellArea.questStartStatus = fields[3].GetUInt32(); + spellArea.questEndStatus = fields[4].GetUInt32(); + spellArea.questEnd = fields[5].GetUInt32(); + spellArea.auraSpell = fields[6].GetInt32(); + spellArea.raceMask = fields[7].GetUInt32(); + spellArea.gender = Gender(fields[8].GetUInt8()); + spellArea.autocast = fields[9].GetBool(); if (SpellInfo const* spellInfo = GetSpellInfo(spell)) { @@ -2494,7 +2491,7 @@ void SpellMgr::LoadSpellAreas() continue; // duplicate by requirements - ok =false; + ok = false; break; } @@ -2524,12 +2521,6 @@ void SpellMgr::LoadSpellAreas() sLog->outError(LOG_FILTER_SQL, "Spell %u listed in `spell_area` have wrong end quest (%u) requirement", spell, spellArea.questEnd); continue; } - - if (spellArea.questEnd == spellArea.questStart && !spellArea.questStartCanActive) - { - sLog->outError(LOG_FILTER_SQL, "Spell %u listed in `spell_area` have quest (%u) requirement for start and end in same time", spell, spellArea.questEnd); - continue; - } } if (spellArea.auraSpell) @@ -2605,12 +2596,7 @@ void SpellMgr::LoadSpellAreas() // for search at quest start/reward if (spellArea.questStart) - { - if (spellArea.questStartCanActive) - mSpellAreaForActiveQuestMap.insert(SpellAreaForQuestMap::value_type(spellArea.questStart, sa)); - else - mSpellAreaForQuestMap.insert(SpellAreaForQuestMap::value_type(spellArea.questStart, sa)); - } + mSpellAreaForQuestMap.insert(SpellAreaForQuestMap::value_type(spellArea.questStart, sa)); // for search at quest start/reward if (spellArea.questEnd) diff --git a/src/server/game/Spells/SpellMgr.h b/src/server/game/Spells/SpellMgr.h index 9646bc9dabf..cec9d4650f5 100755 --- a/src/server/game/Spells/SpellMgr.h +++ b/src/server/game/Spells/SpellMgr.h @@ -495,7 +495,8 @@ struct SpellArea int32 auraSpell; // spell aura must be applied for spell apply)if possitive) and it must not be applied in other case uint32 raceMask; // can be applied only to races Gender gender; // can be applied only to gender - bool questStartCanActive; // if true then quest start can be active (not only rewarded) + uint32 questStartStatus; // QuestStatus that quest_start must have in order to keep the spell + uint32 questEndStatus; // QuestStatus that the quest_end must have in order to keep the spell (if the quest_end's status is different than this, the spell will be dropped) bool autocast; // if true then auto applied at area enter, in other case just allowed to cast // helpers @@ -681,7 +682,7 @@ class SpellMgr // Spell area SpellAreaMapBounds GetSpellAreaMapBounds(uint32 spell_id) const; - SpellAreaForQuestMapBounds GetSpellAreaForQuestMapBounds(uint32 quest_id, bool active) const; + SpellAreaForQuestMapBounds GetSpellAreaForQuestMapBounds(uint32 quest_id) const; SpellAreaForQuestMapBounds GetSpellAreaForQuestEndMapBounds(uint32 quest_id) const; SpellAreaForAuraMapBounds GetSpellAreaForAuraMapBounds(uint32 spell_id) const; SpellAreaForAreaMapBounds GetSpellAreaForAreaMapBounds(uint32 area_id) const; @@ -740,7 +741,6 @@ class SpellMgr EnchantCustomAttribute mEnchantCustomAttr; SpellAreaMap mSpellAreaMap; SpellAreaForQuestMap mSpellAreaForQuestMap; - SpellAreaForQuestMap mSpellAreaForActiveQuestMap; SpellAreaForQuestMap mSpellAreaForQuestEndMap; SpellAreaForAuraMap mSpellAreaForAuraMap; SpellAreaForAreaMap mSpellAreaForAreaMap; -- cgit v1.2.3 From ca276292dcce939d65649d434a08796269789901 Mon Sep 17 00:00:00 2001 From: kaelima Date: Wed, 17 Oct 2012 16:56:35 +0200 Subject: Core/BG: - Force removal of stealth and invisible auras when using gameobjects with type GAMEOBJECT_TYPE_FLAGSTAND and GAMEOBJECT_TYPE_FLAGDROP - Do not allow players to use unfriendly battleground objects (prevents flag cap with Nitro Boosts active for example) --- src/server/game/Entities/GameObject/GameObject.cpp | 12 ++++++++++-- src/server/game/Entities/Player/Player.cpp | 10 +++++++--- src/server/game/Entities/Player/Player.h | 2 +- src/server/game/Spells/Spell.cpp | 2 +- 4 files changed, 19 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index da6e4ef8407..59f68a0494f 100755 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -1522,14 +1522,18 @@ void GameObject::Use(Unit* user) Player* player = user->ToPlayer(); - if (player->CanUseBattlegroundObject()) + if (player->CanUseBattlegroundObject(this)) { // in battleground check Battleground* bg = player->GetBattleground(); if (!bg) return; + if (player->GetVehicle()) return; + + player->RemoveAurasByType(SPELL_AURA_MOD_STEALTH); + player->RemoveAurasByType(SPELL_AURA_MOD_INVISIBILITY); // BG flag click // AB: // 15001 @@ -1562,14 +1566,18 @@ void GameObject::Use(Unit* user) Player* player = user->ToPlayer(); - if (player->CanUseBattlegroundObject()) + if (player->CanUseBattlegroundObject(this)) { // in battleground check Battleground* bg = player->GetBattleground(); if (!bg) return; + if (player->GetVehicle()) return; + + player->RemoveAurasByType(SPELL_AURA_MOD_STEALTH); + player->RemoveAurasByType(SPELL_AURA_MOD_INVISIBILITY); // BG flag dropped // WS: // 179785 - Silverwing Flag diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 501379228e2..161fdc2be1d 100755 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -23488,10 +23488,14 @@ WorldObject* Player::GetViewpoint() const return NULL; } -bool Player::CanUseBattlegroundObject() +bool Player::CanUseBattlegroundObject(GameObject* gameobject) { - // TODO : some spells gives player ForceReaction to one faction (ReputationMgr::ApplyForceReaction) - // maybe gameobject code should handle that ForceReaction usage + FactionTemplateEntry const* playerFaction = getFactionTemplateEntry(); + FactionTemplateEntry const* faction = sFactionTemplateStore.LookupEntry(gameobject->GetUInt32Value(GAMEOBJECT_FACTION)); + + if (playerFaction && faction && !playerFaction->IsFriendlyTo(*faction)) + return false; + // BUG: sometimes when player clicks on flag in AB - client won't send gameobject_use, only gameobject_report_use packet // Note: Mount, stealth and invisibility will be removed when used return (!isTotalImmune() && // Damage immune diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 5670ca05a85..c417c73cdbc 100755 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -2237,7 +2237,7 @@ class Player : public Unit, public GridObject bool GetBGAccessByLevel(BattlegroundTypeId bgTypeId) const; bool isTotalImmunity(); - bool CanUseBattlegroundObject(); + bool CanUseBattlegroundObject(GameObject* gameobject); bool isTotalImmune(); bool CanCaptureTowerPoint(); diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 85a1d0d3c7f..295c8216b7f 100755 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -5210,7 +5210,7 @@ SpellCastResult Spell::CheckCast(bool strict) if (m_spellInfo->Id != 1842 || (m_targets.GetGOTarget() && m_targets.GetGOTarget()->GetGOInfo()->type != GAMEOBJECT_TYPE_TRAP)) if (m_caster->ToPlayer()->InBattleground() && // In Battleground players can use only flags and banners - !m_caster->ToPlayer()->CanUseBattlegroundObject()) + !m_caster->ToPlayer()->CanUseBattlegroundObject(m_targets.GetGOTarget())) return SPELL_FAILED_TRY_AGAIN; // get the lock entry -- cgit v1.2.3 From d0334bf94839301cda93f95913db8ea3f27c19cb Mon Sep 17 00:00:00 2001 From: Spp Date: Wed, 17 Oct 2012 14:19:59 +0200 Subject: Core/Dungeon Finder: Some optimizations. - Store teleport coordinates to avoid recalculations each time someone has to be teleported - Correct teleport error msg when player is charming or using vehicle - Internal changes in storage types - Proper code for missing achievement lock type - Better debug msgs - Trying to get rid of "Player*" and "Group*" inside LFGMgr as much as possible (Step 1) --- src/server/game/DataStores/DBCStores.cpp | 2 +- src/server/game/DataStores/DBCStores.h | 2 +- src/server/game/DataStores/DBCStructure.h | 4 +- src/server/game/DataStores/DBCfmt.h | 198 ++--- src/server/game/DungeonFinding/LFG.h | 33 +- src/server/game/DungeonFinding/LFGGroupData.cpp | 19 +- src/server/game/DungeonFinding/LFGGroupData.h | 5 +- src/server/game/DungeonFinding/LFGMgr.cpp | 893 ++++++++++++--------- src/server/game/DungeonFinding/LFGMgr.h | 185 +++-- src/server/game/DungeonFinding/LFGScripts.cpp | 20 +- src/server/game/Entities/Player/Player.cpp | 22 +- src/server/game/Entities/Player/Player.h | 1 + src/server/game/Globals/ObjectMgr.cpp | 3 +- src/server/game/Groups/Group.cpp | 2 +- src/server/game/Handlers/LFGHandler.cpp | 221 +++-- src/server/game/Maps/Map.cpp | 4 +- src/server/game/Server/Protocol/Opcodes.cpp | 2 +- src/server/game/Server/WorldSession.h | 13 +- src/server/game/Spells/SpellScript.h | 2 +- src/server/game/World/World.cpp | 5 +- .../scripts/Northrend/Nexus/Oculus/oculus.cpp | 2 +- src/server/scripts/Spells/spell_generic.cpp | 4 +- src/server/scripts/World/npcs_special.cpp | 2 +- 23 files changed, 935 insertions(+), 709 deletions(-) (limited to 'src') diff --git a/src/server/game/DataStores/DBCStores.cpp b/src/server/game/DataStores/DBCStores.cpp index 850c58bdf93..16595eb16dd 100755 --- a/src/server/game/DataStores/DBCStores.cpp +++ b/src/server/game/DataStores/DBCStores.cpp @@ -118,7 +118,7 @@ DBCStorage sItemRandomPropertiesStore(ItemRandomProp DBCStorage sItemRandomSuffixStore(ItemRandomSuffixfmt); DBCStorage sItemSetStore(ItemSetEntryfmt); -DBCStorage sLFGDungeonStore(LFGDungeonEntryfmt); +DBCStorage sLFGDungeonStore(LFGDungeonEntryfmt); DBCStorage sLiquidTypeStore(LiquidTypefmt); DBCStorage sLockStore(LockEntryfmt); diff --git a/src/server/game/DataStores/DBCStores.h b/src/server/game/DataStores/DBCStores.h index cd30ed587f8..f6fabb5a73d 100755 --- a/src/server/game/DataStores/DBCStores.h +++ b/src/server/game/DataStores/DBCStores.h @@ -120,7 +120,7 @@ extern DBCStorage sItemLimitCategoryStore; extern DBCStorage sItemRandomPropertiesStore; extern DBCStorage sItemRandomSuffixStore; extern DBCStorage sItemSetStore; -extern DBCStorage sLFGDungeonStore; +extern DBCStorage sLFGDungeonStore; extern DBCStorage sLiquidTypeStore; extern DBCStorage sLockStore; extern DBCStorage sMailTemplateStore; diff --git a/src/server/game/DataStores/DBCStructure.h b/src/server/game/DataStores/DBCStructure.h index 538a53344e8..2fc61e69fe2 100755 --- a/src/server/game/DataStores/DBCStructure.h +++ b/src/server/game/DataStores/DBCStructure.h @@ -1193,10 +1193,10 @@ struct ItemSetEntry uint32 required_skill_value; // 52 m_requiredSkillRank }; -struct LFGDungeonEntry +struct LFGDungeonEntryDbc { uint32 ID; // 0 - //char* name[16]; // 1-17 Name lang + char* name[16]; // 1-17 Name lang uint32 minlevel; // 18 uint32 maxlevel; // 19 uint32 reclevel; // 20 diff --git a/src/server/game/DataStores/DBCfmt.h b/src/server/game/DataStores/DBCfmt.h index 39f9009419e..0c2cc565b22 100755 --- a/src/server/game/DataStores/DBCfmt.h +++ b/src/server/game/DataStores/DBCfmt.h @@ -19,111 +19,111 @@ #ifndef TRINITY_DBCSFRM_H #define TRINITY_DBCSFRM_H -const char Achievementfmt[]="niixssssssssssssssssxxxxxxxxxxxxxxxxxxiixixxxxxxxxxxxxxxxxxxii"; +char const Achievementfmt[]="niixssssssssssssssssxxxxxxxxxxxxxxxxxxiixixxxxxxxxxxxxxxxxxxii"; const std::string CustomAchievementfmt="pppaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaapapaaaaaaaaaaaaaaaaaapp"; const std::string CustomAchievementIndex = "ID"; -const char AchievementCriteriafmt[]="niiiiiiiixxxxxxxxxxxxxxxxxiiiix"; -const char AreaTableEntryfmt[]="iiinixxxxxissssssssssssssssxiiiiixxx"; -const char AreaGroupEntryfmt[]="niiiiiii"; -const char AreaPOIEntryfmt[]="niiiiiiiiiiifffixixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxix"; -const char AreaTriggerEntryfmt[]="niffffffff"; -const char AuctionHouseEntryfmt[]="niiixxxxxxxxxxxxxxxxx"; -const char BankBagSlotPricesEntryfmt[]="ni"; -const char BarberShopStyleEntryfmt[]="nixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiii"; -const char BattlemasterListEntryfmt[]="niiiiiiiiixssssssssssssssssxiixx"; -const char CharStartOutfitEntryfmt[]="diiiiiiiiiiiiiiiiiiiiiiiiixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; -const char CharTitlesEntryfmt[]="nxssssssssssssssssxxxxxxxxxxxxxxxxxxi"; -const char ChatChannelsEntryfmt[]="nixssssssssssssssssxxxxxxxxxxxxxxxxxx"; +char const AchievementCriteriafmt[]="niiiiiiiixxxxxxxxxxxxxxxxxiiiix"; +char const AreaTableEntryfmt[]="iiinixxxxxissssssssssssssssxiiiiixxx"; +char const AreaGroupEntryfmt[]="niiiiiii"; +char const AreaPOIEntryfmt[]="niiiiiiiiiiifffixixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxix"; +char const AreaTriggerEntryfmt[]="niffffffff"; +char const AuctionHouseEntryfmt[]="niiixxxxxxxxxxxxxxxxx"; +char const BankBagSlotPricesEntryfmt[]="ni"; +char const BarberShopStyleEntryfmt[]="nixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiii"; +char const BattlemasterListEntryfmt[]="niiiiiiiiixssssssssssssssssxiixx"; +char const CharStartOutfitEntryfmt[]="diiiiiiiiiiiiiiiiiiiiiiiiixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; +char const CharTitlesEntryfmt[]="nxssssssssssssssssxxxxxxxxxxxxxxxxxxi"; +char const ChatChannelsEntryfmt[]="nixssssssssssssssssxxxxxxxxxxxxxxxxxx"; // ChatChannelsEntryfmt, index not used (more compact store) -const char ChrClassesEntryfmt[]="nxixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxixii"; -const char ChrRacesEntryfmt[]="nxixiixixxxxixssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxi"; -const char CinematicSequencesEntryfmt[]="nxxxxxxxxx"; -const char CreatureDisplayInfofmt[]="nixxfxxxxxxxxxxx"; -const char CreatureFamilyfmt[]="nfifiiiiixssssssssssssssssxx"; -const char CreatureModelDatafmt[]="nxxxfxxxxxxxxxxffxxxxxxxxxxx"; -const char CreatureSpellDatafmt[]="niiiixxxx"; -const char CreatureTypefmt[]="nxxxxxxxxxxxxxxxxxx"; -const char CurrencyTypesfmt[]="xnxi"; -const char DestructibleModelDatafmt[]="nxxixxxixxxixxxixxx"; -const char DungeonEncounterfmt[]="niixissssssssssssssssxx"; -const char DurabilityCostsfmt[]="niiiiiiiiiiiiiiiiiiiiiiiiiiiii"; -const char DurabilityQualityfmt[]="nf"; -const char EmotesEntryfmt[]="nxxiiix"; -const char EmotesTextEntryfmt[]="nxixxxxxxxxxxxxxxxx"; -const char FactionEntryfmt[]="niiiiiiiiiiiiiiiiiiffixssssssssssssssssxxxxxxxxxxxxxxxxxx"; -const char FactionTemplateEntryfmt[]="niiiiiiiiiiiii"; -const char GameObjectDisplayInfofmt[]="nsxxxxxxxxxxffffffx"; -const char GemPropertiesEntryfmt[]="nixxi"; -const char GlyphPropertiesfmt[]="niii"; -const char GlyphSlotfmt[]="nii"; -const char GtBarberShopCostBasefmt[]="f"; -const char GtCombatRatingsfmt[]="f"; -const char GtChanceToMeleeCritBasefmt[]="f"; -const char GtChanceToMeleeCritfmt[]="f"; -const char GtChanceToSpellCritBasefmt[]="f"; -const char GtChanceToSpellCritfmt[]="f"; -const char GtOCTClassCombatRatingScalarfmt[]="df"; -const char GtOCTRegenHPfmt[]="f"; -//const char GtOCTRegenMPfmt[]="f"; -const char GtRegenHPPerSptfmt[]="f"; -const char GtRegenMPPerSptfmt[]="f"; -const char Holidaysfmt[]="niiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiixxsiix"; -const char Itemfmt[]="niiiiiii"; -const char ItemBagFamilyfmt[]="nxxxxxxxxxxxxxxxxx"; -//const char ItemDisplayTemplateEntryfmt[]="nxxxxxxxxxxixxxxxxxxxxx"; -//const char ItemCondExtCostsEntryfmt[]="xiii"; -const char ItemExtendedCostEntryfmt[]="niiiiiiiiiiiiiix"; -const char ItemLimitCategoryEntryfmt[]="nxxxxxxxxxxxxxxxxxii"; -const char ItemRandomPropertiesfmt[]="nxiiixxssssssssssssssssx"; -const char ItemRandomSuffixfmt[]="nssssssssssssssssxxiiixxiiixx"; -const char ItemSetEntryfmt[]="dssssssssssssssssxiiiiiiiiiixxxxxxxiiiiiiiiiiiiiiiiii"; -const char LFGDungeonEntryfmt[]="nxxxxxxxxxxxxxxxxxiiiiiiiiixxixixxxxxxxxxxxxxxxxx"; -const char LiquidTypefmt[]="nxxixixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; -const char LockEntryfmt[]="niiiiiiiiiiiiiiiiiiiiiiiixxxxxxxx"; -const char MailTemplateEntryfmt[]="nxxxxxxxxxxxxxxxxxssssssssssssssssx"; -const char MapEntryfmt[]="nxixxssssssssssssssssxixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxixiffxiix"; -const char MapDifficultyEntryfmt[]="diisxxxxxxxxxxxxxxxxiix"; -const char MovieEntryfmt[]="nxx"; -const char OverrideSpellDatafmt[]="niiiiiiiiiix"; -const char QuestSortEntryfmt[]="nxxxxxxxxxxxxxxxxx"; -const char QuestXPfmt[]="niiiiiiiiii"; -const char QuestFactionRewardfmt[]="niiiiiiiiii"; -const char PvPDifficultyfmt[]="diiiii"; -const char RandomPropertiesPointsfmt[]="niiiiiiiiiiiiiii"; -const char ScalingStatDistributionfmt[]="niiiiiiiiiiiiiiiiiiiii"; -const char ScalingStatValuesfmt[]="iniiiiiiiiiiiiiiiiiiiiii"; -const char SkillLinefmt[]="nixssssssssssssssssxxxxxxxxxxxxxxxxxxixxxxxxxxxxxxxxxxxi"; -const char SkillLineAbilityfmt[]="niiiixxiiiiixx"; -const char SoundEntriesfmt[]="nxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; -const char SpellCastTimefmt[]="nixx"; -const char SpellDifficultyfmt[]="niiii"; +char const ChrClassesEntryfmt[]="nxixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxixii"; +char const ChrRacesEntryfmt[]="nxixiixixxxxixssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxi"; +char const CinematicSequencesEntryfmt[]="nxxxxxxxxx"; +char const CreatureDisplayInfofmt[]="nixxfxxxxxxxxxxx"; +char const CreatureFamilyfmt[]="nfifiiiiixssssssssssssssssxx"; +char const CreatureModelDatafmt[]="nxxxfxxxxxxxxxxffxxxxxxxxxxx"; +char const CreatureSpellDatafmt[]="niiiixxxx"; +char const CreatureTypefmt[]="nxxxxxxxxxxxxxxxxxx"; +char const CurrencyTypesfmt[]="xnxi"; +char const DestructibleModelDatafmt[]="nxxixxxixxxixxxixxx"; +char const DungeonEncounterfmt[]="niixissssssssssssssssxx"; +char const DurabilityCostsfmt[]="niiiiiiiiiiiiiiiiiiiiiiiiiiiii"; +char const DurabilityQualityfmt[]="nf"; +char const EmotesEntryfmt[]="nxxiiix"; +char const EmotesTextEntryfmt[]="nxixxxxxxxxxxxxxxxx"; +char const FactionEntryfmt[]="niiiiiiiiiiiiiiiiiiffixssssssssssssssssxxxxxxxxxxxxxxxxxx"; +char const FactionTemplateEntryfmt[]="niiiiiiiiiiiii"; +char const GameObjectDisplayInfofmt[]="nsxxxxxxxxxxffffffx"; +char const GemPropertiesEntryfmt[]="nixxi"; +char const GlyphPropertiesfmt[]="niii"; +char const GlyphSlotfmt[]="nii"; +char const GtBarberShopCostBasefmt[]="f"; +char const GtCombatRatingsfmt[]="f"; +char const GtChanceToMeleeCritBasefmt[]="f"; +char const GtChanceToMeleeCritfmt[]="f"; +char const GtChanceToSpellCritBasefmt[]="f"; +char const GtChanceToSpellCritfmt[]="f"; +char const GtOCTClassCombatRatingScalarfmt[]="df"; +char const GtOCTRegenHPfmt[]="f"; +//char const GtOCTRegenMPfmt[]="f"; +char const GtRegenHPPerSptfmt[]="f"; +char const GtRegenMPPerSptfmt[]="f"; +char const Holidaysfmt[]="niiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiixxsiix"; +char const Itemfmt[]="niiiiiii"; +char const ItemBagFamilyfmt[]="nxxxxxxxxxxxxxxxxx"; +//char const ItemDisplayTemplateEntryfmt[]="nxxxxxxxxxxixxxxxxxxxxx"; +//char const ItemCondExtCostsEntryfmt[]="xiii"; +char const ItemExtendedCostEntryfmt[]="niiiiiiiiiiiiiix"; +char const ItemLimitCategoryEntryfmt[]="nxxxxxxxxxxxxxxxxxii"; +char const ItemRandomPropertiesfmt[]="nxiiixxssssssssssssssssx"; +char const ItemRandomSuffixfmt[]="nssssssssssssssssxxiiixxiiixx"; +char const ItemSetEntryfmt[]="dssssssssssssssssxiiiiiiiiiixxxxxxxiiiiiiiiiiiiiiiiii"; +char const LFGDungeonEntryfmt[]="nssssssssssssssssiiiiiiiiixxixixxxxxxxxxxxxxxxxx"; +char const LiquidTypefmt[]="nxxixixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; +char const LockEntryfmt[]="niiiiiiiiiiiiiiiiiiiiiiiixxxxxxxx"; +char const MailTemplateEntryfmt[]="nxxxxxxxxxxxxxxxxxssssssssssssssssx"; +char const MapEntryfmt[]="nxixxssssssssssssssssxixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxixiffxiix"; +char const MapDifficultyEntryfmt[]="diisxxxxxxxxxxxxxxxxiix"; +char const MovieEntryfmt[]="nxx"; +char const OverrideSpellDatafmt[]="niiiiiiiiiix"; +char const QuestSortEntryfmt[]="nxxxxxxxxxxxxxxxxx"; +char const QuestXPfmt[]="niiiiiiiiii"; +char const QuestFactionRewardfmt[]="niiiiiiiiii"; +char const PvPDifficultyfmt[]="diiiii"; +char const RandomPropertiesPointsfmt[]="niiiiiiiiiiiiiii"; +char const ScalingStatDistributionfmt[]="niiiiiiiiiiiiiiiiiiiii"; +char const ScalingStatValuesfmt[]="iniiiiiiiiiiiiiiiiiiiiii"; +char const SkillLinefmt[]="nixssssssssssssssssxxxxxxxxxxxxxxxxxxixxxxxxxxxxxxxxxxxi"; +char const SkillLineAbilityfmt[]="niiiixxiiiiixx"; +char const SoundEntriesfmt[]="nxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; +char const SpellCastTimefmt[]="nixx"; +char const SpellDifficultyfmt[]="niiii"; const std::string CustomSpellDifficultyfmt="ppppp"; const std::string CustomSpellDifficultyIndex="id"; -const char SpellDurationfmt[]="niii"; -const char SpellEntryfmt[]="niiiiiiiiiiiixixiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiifxiiiiiiiiiiiiiiiiiiiiiiiiiiiifffiiiiiiiiiiiiiiiiiiiiifffiiiiiiiiiiiiiiifffiiiiiiiiiiiiixssssssssssssssssxssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiiiiiiiiiiixfffxxxiiiiixxfffxx"; +char const SpellDurationfmt[]="niii"; +char const SpellEntryfmt[]="niiiiiiiiiiiixixiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiifxiiiiiiiiiiiiiiiiiiiiiiiiiiiifffiiiiiiiiiiiiiiiiiiiiifffiiiiiiiiiiiiiiifffiiiiiiiiiiiiixssssssssssssssssxssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiiiiiiiiiiixfffxxxiiiiixxfffxx"; const std::string CustomSpellEntryfmt="papppppppppppapapaaaaaaaaaaapaaapapppppppaaaaapaapaaaaaaaaaaaaaaaaaappppppppppppppppppppppppppppppppppppaaaaaapppppppppaaapppppppppaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaappppppppapppaaaaappaaaaaaa"; const std::string CustomSpellEntryIndex = "Id"; -const char SpellFocusObjectfmt[]="nxxxxxxxxxxxxxxxxx"; -const char SpellItemEnchantmentfmt[]="nxiiiiiixxxiiissssssssssssssssxiiiiiii"; -const char SpellItemEnchantmentConditionfmt[]="nbbbbbxxxxxbbbbbbbbbbiiiiiXXXXX"; -const char SpellRadiusfmt[]="nfxf"; -const char SpellRangefmt[]="nffffixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; -const char SpellRuneCostfmt[]="niiii"; -const char SpellShapeshiftfmt[]="nxxxxxxxxxxxxxxxxxxiixiiixxiiiiiiii"; -const char StableSlotPricesfmt[] = "ni"; -const char SummonPropertiesfmt[] = "niiiii"; -const char TalentEntryfmt[]="niiiiiiiixxxxixxixxxxxx"; -const char TalentTabEntryfmt[]="nxxxxxxxxxxxxxxxxxxxiiix"; -const char TaxiNodesEntryfmt[]="nifffssssssssssssssssxii"; -const char TaxiPathEntryfmt[]="niii"; -const char TaxiPathNodeEntryfmt[]="diiifffiiii"; -const char TeamContributionPointsfmt[]="df"; -const char TotemCategoryEntryfmt[]="nxxxxxxxxxxxxxxxxxii"; -const char VehicleEntryfmt[]="niffffiiiiiiiifffffffffffffffssssfifiixx"; -const char VehicleSeatEntryfmt[]="niiffffffffffiiiiiifffffffiiifffiiiiiiiffiiiiixxxxxxxxxxxx"; -const char WMOAreaTableEntryfmt[]="niiixxxxxiixxxxxxxxxxxxxxxxx"; -const char WorldMapAreaEntryfmt[]="xinxffffixx"; -const char WorldMapOverlayEntryfmt[]="nxiiiixxxxxxxxxxx"; -const char WorldSafeLocsEntryfmt[]="nifffxxxxxxxxxxxxxxxxx"; +char const SpellFocusObjectfmt[]="nxxxxxxxxxxxxxxxxx"; +char const SpellItemEnchantmentfmt[]="nxiiiiiixxxiiissssssssssssssssxiiiiiii"; +char const SpellItemEnchantmentConditionfmt[]="nbbbbbxxxxxbbbbbbbbbbiiiiiXXXXX"; +char const SpellRadiusfmt[]="nfxf"; +char const SpellRangefmt[]="nffffixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; +char const SpellRuneCostfmt[]="niiii"; +char const SpellShapeshiftfmt[]="nxxxxxxxxxxxxxxxxxxiixiiixxiiiiiiii"; +char const StableSlotPricesfmt[] = "ni"; +char const SummonPropertiesfmt[] = "niiiii"; +char const TalentEntryfmt[]="niiiiiiiixxxxixxixxxxxx"; +char const TalentTabEntryfmt[]="nxxxxxxxxxxxxxxxxxxxiiix"; +char const TaxiNodesEntryfmt[]="nifffssssssssssssssssxii"; +char const TaxiPathEntryfmt[]="niii"; +char const TaxiPathNodeEntryfmt[]="diiifffiiii"; +char const TeamContributionPointsfmt[]="df"; +char const TotemCategoryEntryfmt[]="nxxxxxxxxxxxxxxxxxii"; +char const VehicleEntryfmt[]="niffffiiiiiiiifffffffffffffffssssfifiixx"; +char const VehicleSeatEntryfmt[]="niiffffffffffiiiiiifffffffiiifffiiiiiiiffiiiiixxxxxxxxxxxx"; +char const WMOAreaTableEntryfmt[]="niiixxxxxiixxxxxxxxxxxxxxxxx"; +char const WorldMapAreaEntryfmt[]="xinxffffixx"; +char const WorldMapOverlayEntryfmt[]="nxiiiixxxxxxxxxxx"; +char const WorldSafeLocsEntryfmt[]="nifffxxxxxxxxxxxxxxxxx"; #endif diff --git a/src/server/game/DungeonFinding/LFG.h b/src/server/game/DungeonFinding/LFG.h index 28498749af8..c00cc830ce8 100755 --- a/src/server/game/DungeonFinding/LFG.h +++ b/src/server/game/DungeonFinding/LFG.h @@ -20,13 +20,20 @@ #include "Common.h" +enum LFGEnum +{ + LFG_TANKS_NEEDED = 1, + LFG_HEALERS_NEEDED = 1, + LFG_DPS_NEEDED = 3 +}; + enum LfgRoles { - ROLE_NONE = 0x00, - ROLE_LEADER = 0x01, - ROLE_TANK = 0x02, - ROLE_HEALER = 0x04, - ROLE_DAMAGE = 0x08 + PLAYER_ROLE_NONE = 0x00, + PLAYER_ROLE_LEADER = 0x01, + PLAYER_ROLE_TANK = 0x02, + PLAYER_ROLE_HEALER = 0x04, + PLAYER_ROLE_DAMAGE = 0x08 }; enum LfgUpdateType @@ -73,7 +80,16 @@ enum LfgLockStatusType LFG_LOCKSTATUS_ATTUNEMENT_TOO_HIGH_LEVEL = 1002, LFG_LOCKSTATUS_QUEST_NOT_COMPLETED = 1022, LFG_LOCKSTATUS_MISSING_ITEM = 1025, - LFG_LOCKSTATUS_NOT_IN_SEASON = 1031 + LFG_LOCKSTATUS_NOT_IN_SEASON = 1031, + LFG_LOCKSTATUS_MISSING_ACHIEVEMENT = 1034 +}; + +/// Answer state (Also used to check compatibilites) +enum LfgAnswer +{ + LFG_ANSWER_PENDING = -1, + LFG_ANSWER_DENY = 0, + LFG_ANSWER_AGREE = 1 }; /// Dungeon and reason why player can't join @@ -84,7 +100,10 @@ struct LfgLockStatus }; typedef std::set LfgDungeonSet; -typedef std::map LfgLockMap; +typedef std::map LfgLockMap; typedef std::map LfgLockPartyMap; +typedef std::set LfgGuidSet; +typedef std::list LfgGuidList; +typedef std::map LfgRolesMap; #endif diff --git a/src/server/game/DungeonFinding/LFGGroupData.cpp b/src/server/game/DungeonFinding/LFGGroupData.cpp index 607389c5dbf..cbcb1d130bb 100644 --- a/src/server/game/DungeonFinding/LFGGroupData.cpp +++ b/src/server/game/DungeonFinding/LFGGroupData.cpp @@ -18,14 +18,16 @@ #include "LFG.h" #include "LFGGroupData.h" -LfgGroupData::LfgGroupData(): -m_State(LFG_STATE_NONE), m_OldState(LFG_STATE_NONE), m_Dungeon(0), -m_VotesNeeded(LFG_GROUP_KICK_VOTES_NEEDED), m_KicksLeft(LFG_GROUP_MAX_KICKS) -{ -} +LfgGroupData::LfgGroupData(): m_State(LFG_STATE_NONE), m_OldState(LFG_STATE_NONE), + m_Dungeon(0), m_KicksLeft(LFG_GROUP_MAX_KICKS) +{ } LfgGroupData::~LfgGroupData() +{ } + +bool LfgGroupData::IsLfgGroup() { + return m_OldState != LFG_STATE_NONE; } void LfgGroupData::SetState(LfgState state) @@ -36,7 +38,7 @@ void LfgGroupData::SetState(LfgState state) case LFG_STATE_DUNGEON: case LFG_STATE_FINISHED_DUNGEON: m_OldState = state; - // No break on purpose + // No break on purpose default: m_State = state; } @@ -71,11 +73,6 @@ uint32 LfgGroupData::GetDungeon(bool asId /* = true */) const return m_Dungeon; } -uint8 LfgGroupData::GetVotesNeeded() const -{ - return m_VotesNeeded; -} - uint8 LfgGroupData::GetKicksLeft() const { return m_KicksLeft; diff --git a/src/server/game/DungeonFinding/LFGGroupData.h b/src/server/game/DungeonFinding/LFGGroupData.h index 74570817698..359f7be7eee 100644 --- a/src/server/game/DungeonFinding/LFGGroupData.h +++ b/src/server/game/DungeonFinding/LFGGroupData.h @@ -23,7 +23,6 @@ enum LfgGroupEnum { LFG_GROUP_MAX_KICKS = 3, - LFG_GROUP_KICK_VOTES_NEEDED = 3 }; /** @@ -35,13 +34,13 @@ class LfgGroupData LfgGroupData(); ~LfgGroupData(); + bool IsLfgGroup(); // General void SetState(LfgState state); void RestoreState(); // Dungeon void SetDungeon(uint32 dungeon); // VoteKick - void SetVotesNeeded(uint8 votes); void DecreaseKicksLeft(); // General @@ -49,7 +48,6 @@ class LfgGroupData // Dungeon uint32 GetDungeon(bool asId = true) const; // VoteKick - uint8 GetVotesNeeded() const; uint8 GetKicksLeft() const; private: @@ -59,7 +57,6 @@ class LfgGroupData // Dungeon uint32 m_Dungeon; ///< Dungeon entry // Vote Kick - uint8 m_VotesNeeded; ///< Votes need to kick success uint8 m_KicksLeft; ///< Number of kicks left }; diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp index 2b425dffff0..1b4a2fcdda3 100755 --- a/src/server/game/DungeonFinding/LFGMgr.cpp +++ b/src/server/game/DungeonFinding/LFGMgr.cpp @@ -32,46 +32,25 @@ #include "Group.h" #include "Player.h" -LFGMgr::LFGMgr(): m_update(true), m_QueueTimer(0), m_lfgProposalId(1), -m_WaitTimeAvg(-1), m_WaitTimeTank(-1), m_WaitTimeHealer(-1), m_WaitTimeDps(-1), -m_NumWaitTimeAvg(0), m_NumWaitTimeTank(0), m_NumWaitTimeHealer(0), m_NumWaitTimeDps(0) -{ - m_update = sWorld->getBoolConfig(CONFIG_DUNGEON_FINDER_ENABLE); - if (m_update) - { - new LFGPlayerScript(); - new LFGGroupScript(); - - // Initialize dungeon cache - for (uint32 i = 0; i < sLFGDungeonStore.GetNumRows(); ++i) - { - LFGDungeonEntry const* dungeon = sLFGDungeonStore.LookupEntry(i); - if (dungeon && dungeon->type != LFG_TYPE_ZONE) - { - if (dungeon->type != LFG_TYPE_RANDOM) - m_CachedDungeonMap[dungeon->grouptype].insert(dungeon->ID); - m_CachedDungeonMap[0].insert(dungeon->ID); - } - } - } -} +LFGMgr::LFGMgr(): m_QueueTimer(0), m_lfgProposalId(1), + m_options(sWorld->getBoolConfig(CONFIG_DUNGEON_FINDER_ENABLE)), + m_WaitTimeAvg(-1), m_WaitTimeTank(-1), m_WaitTimeHealer(-1), m_WaitTimeDps(-1), + m_NumWaitTimeAvg(0), m_NumWaitTimeTank(0), m_NumWaitTimeHealer(0), m_NumWaitTimeDps(0), + m_lfgPlayerScript(new LFGPlayerScript()), m_lfgGroupScript(new LFGGroupScript()) +{ } LFGMgr::~LFGMgr() { for (LfgRewardMap::iterator itr = m_RewardMap.begin(); itr != m_RewardMap.end(); ++itr) delete itr->second; + delete m_lfgPlayerScript; + delete m_lfgGroupScript; for (LfgQueueInfoMap::iterator it = m_QueueInfoMap.begin(); it != m_QueueInfoMap.end(); ++it) delete it->second; for (LfgProposalMap::iterator it = m_Proposals.begin(); it != m_Proposals.end(); ++it) delete it->second; - - for (LfgPlayerBootMap::iterator it = m_Boots.begin(); it != m_Boots.end(); ++it) - delete it->second; - - for (LfgRoleCheckMap::iterator it = m_RoleChecks.begin(); it != m_RoleChecks.end(); ++it) - delete it->second; } void LFGMgr::_LoadFromDB(Field* fields, uint64 guid) @@ -122,6 +101,86 @@ void LFGMgr::_SaveToDB(uint64 guid, uint32 db_guid) CharacterDatabase.Execute(stmt); } +std::string LFGMgr::ConcatenateDungeons(LfgDungeonSet const& dungeons) +{ + std::string dungeonstr = ""; + if (!dungeons.empty()) + { + std::ostringstream o; + LfgDungeonSet::const_iterator it = dungeons.begin(); + o << (*it); + for (++it; it != dungeons.end(); ++it) + o << ", " << uint32(*it); + dungeonstr = o.str(); + } + return dungeonstr; +} + +std::string LFGMgr::GetRolesString(uint8 roles) +{ + std::string rolesstr = ""; + + if (roles & PLAYER_ROLE_TANK) + rolesstr.append("Tank"); + + if (roles & PLAYER_ROLE_HEALER) + { + if (!rolesstr.empty()) + rolesstr.append(", "); + rolesstr.append("Healer"); + } + + if (roles & PLAYER_ROLE_DAMAGE) + { + if (!rolesstr.empty()) + rolesstr.append(", "); + rolesstr.append("Dps"); + } + + if (roles & PLAYER_ROLE_LEADER) + { + if (!rolesstr.empty()) + rolesstr.append(", "); + rolesstr.append("Leader"); + } + + if (rolesstr.empty()) + rolesstr.append("None"); + + return rolesstr; +} + +char const * LFGMgr::GetStateString(LfgState state) +{ + switch (state) + { + case LFG_STATE_NONE: + return "None"; + break; + case LFG_STATE_ROLECHECK: + return "Rolecheck"; + break; + case LFG_STATE_QUEUED: + return "Queued"; + break; + case LFG_STATE_PROPOSAL: + return "Proposal"; + break; + case LFG_STATE_DUNGEON: + return "In Dungeon"; + break; + case LFG_STATE_BOOT: + return "Boot Player"; + break; + case LFG_STATE_FINISHED_DUNGEON: + return "Finished"; + break; + case LFG_STATE_RAIDBROWSER: + return "RaidBrowser"; + } + return "Error"; +} + /// Load rewards for completing dungeons void LFGMgr::LoadRewards() { @@ -155,7 +214,7 @@ void LFGMgr::LoadRewards() uint32 otherMoneyVar = fields[6].GetUInt32(); uint32 otherXPVar = fields[7].GetUInt32(); - if (!sLFGDungeonStore.LookupEntry(dungeonId)) + if (!GetLFGDungeon(dungeonId)) { sLog->outError(LOG_FILTER_SQL, "Dungeon %u specified in table `lfg_dungeon_rewards` does not exist!", dungeonId); continue; @@ -186,16 +245,50 @@ void LFGMgr::LoadRewards() sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u lfg dungeon rewards in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); } -void LFGMgr::LoadEntrancePositions() +LFGDungeonEntry const* LFGMgr::GetLFGDungeon(uint32 id) +{ + LFGDungeonMap::const_iterator itr = m_LfgDungeonMap.find(id); + if (itr != m_LfgDungeonMap.end()) + return &(itr->second); + + return NULL; +} + +LFGDungeonMap & LFGMgr::GetLFGDungeonMap() +{ + return m_LfgDungeonMap; +} + +void LFGMgr::LoadLFGDungeons(bool reload /* = false */) { uint32 oldMSTime = getMSTime(); - m_entrancePositions.clear(); + m_LfgDungeonMap.clear(); + + // Initialize Dungeon map with data from dbcs + for (uint32 i = 0; i < sLFGDungeonStore.GetNumRows(); ++i) + { + LFGDungeonEntryDbc const* dungeon = sLFGDungeonStore.LookupEntry(i); + if (!dungeon) + continue; + + switch (dungeon->type) + { + case LFG_TYPE_DUNGEON: + case LFG_TYPE_HEROIC: + case LFG_TYPE_RAID: + case LFG_TYPE_RANDOM: + m_LfgDungeonMap[dungeon->ID] = LFGDungeonEntry(dungeon); + break; + } + } + + // Fill teleport locations from DB QueryResult result = WorldDatabase.Query("SELECT dungeonId, position_x, position_y, position_z, orientation FROM lfg_entrances"); if (!result) { - sLog->outError(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 lfg entrance positions. DB table `lfg_entrances` is empty!"); + sLog->outError(LOG_FILTER_SQL, ">> Loaded 0 lfg entrance positions. DB table `lfg_entrances` is empty!"); return; } @@ -205,49 +298,85 @@ void LFGMgr::LoadEntrancePositions() { Field* fields = result->Fetch(); uint32 dungeonId = fields[0].GetUInt32(); - Position pos; - pos.m_positionX = fields[1].GetFloat(); - pos.m_positionY = fields[2].GetFloat(); - pos.m_positionZ = fields[3].GetFloat(); - pos.m_orientation = fields[4].GetFloat(); - m_entrancePositions[dungeonId] = pos; + LFGDungeonMap::iterator dungeonItr = m_LfgDungeonMap.find(dungeonId); + if (dungeonItr == m_LfgDungeonMap.end()) + { + sLog->outError(LOG_FILTER_SQL, "table `lfg_entrances` contains coordinates for wrong dungeon %u", dungeonId); + continue; + } + + LFGDungeonEntry& data = dungeonItr->second; + data.x = fields[1].GetFloat(); + data.y = fields[2].GetFloat(); + data.z = fields[3].GetFloat(); + data.o = fields[4].GetFloat(); + ++count; } while (result->NextRow()); sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u lfg entrance positions in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); + + // Fill all other teleport coords from areatriggers + for (LFGDungeonMap::iterator itr = m_LfgDungeonMap.begin(); itr != m_LfgDungeonMap.end(); ++itr) + { + LFGDungeonEntry& dungeon = itr->second; + // No teleport coords in database, load from areatriggers + if (dungeon.x == 0.0f && dungeon.y == 0.0f && dungeon.z == 0.0f) + { + AreaTrigger const* at = sObjectMgr->GetMapEntranceTrigger(dungeon.map); + if (!at) + { + sLog->outError(LOG_FILTER_LFG, "LFGMgr::LoadLFGDungeons: Failed to load dungeon %s, cant find areatrigger for map %u", dungeon.name.c_str(), dungeon.map); + continue; + } + + dungeon.map = at->target_mapId; + dungeon.x = at->target_X; + dungeon.y = at->target_Y; + dungeon.z = at->target_Z; + dungeon.o = at->target_Orientation; + } + + if (dungeon.type != LFG_TYPE_RANDOM) + m_CachedDungeonMap[dungeon.group].insert(dungeon.id); + m_CachedDungeonMap[0].insert(dungeon.id); + } + + if (reload) + { + m_CachedDungeonMap.clear(); + // Recalculate locked dungeons + for (LfgPlayerDataMap::const_iterator it = m_Players.begin(); it != m_Players.end(); ++it) + if (Player* player = ObjectAccessor::FindPlayer(it->first)) + InitializeLockedDungeons(player); + } } void LFGMgr::Update(uint32 diff) { - if (!m_update) + if (!m_options) return; - m_update = false; time_t currTime = time(NULL); // Remove obsolete role checks for (LfgRoleCheckMap::iterator it = m_RoleChecks.begin(); it != m_RoleChecks.end();) { LfgRoleCheckMap::iterator itRoleCheck = it++; - LfgRoleCheck* roleCheck = itRoleCheck->second; - if (currTime < roleCheck->cancelTime) + LfgRoleCheck& roleCheck = itRoleCheck->second; + if (currTime < roleCheck.cancelTime) continue; - roleCheck->state = LFG_ROLECHECK_MISSING_ROLE; + roleCheck.state = LFG_ROLECHECK_MISSING_ROLE; - for (LfgRolesMap::const_iterator itRoles = roleCheck->roles.begin(); itRoles != roleCheck->roles.end(); ++itRoles) + for (LfgRolesMap::const_iterator itRoles = roleCheck.roles.begin(); itRoles != roleCheck.roles.end(); ++itRoles) { uint64 guid = itRoles->first; - ClearState(guid); - if (Player* player = ObjectAccessor::FindPlayer(guid)) - { - player->GetSession()->SendLfgRoleCheckUpdate(roleCheck); - - if (itRoles->first == roleCheck->leader) - player->GetSession()->SendLfgJoinResult(LfgJoinResultData(LFG_JOIN_FAILED, LFG_ROLECHECK_MISSING_ROLE)); - } + ClearState(guid, "Remove Obsolete RoleCheck"); + SendLfgRoleCheckUpdate(guid, roleCheck); + if (guid == roleCheck.leader) + SendLfgJoinResult(guid, LfgJoinResultData(LFG_JOIN_FAILED, LFG_ROLECHECK_MISSING_ROLE)); } - delete roleCheck; m_RoleChecks.erase(itRoleCheck); } @@ -263,15 +392,16 @@ void LFGMgr::Update(uint32 diff) for (LfgPlayerBootMap::iterator it = m_Boots.begin(); it != m_Boots.end();) { LfgPlayerBootMap::iterator itBoot = it++; - LfgPlayerBoot* pBoot = itBoot->second; - if (pBoot->cancelTime < currTime) + LfgPlayerBoot& boot = itBoot->second; + if (boot.cancelTime < currTime) { - pBoot->inProgress = false; - for (LfgAnswerMap::const_iterator itVotes = pBoot->votes.begin(); itVotes != pBoot->votes.end(); ++itVotes) - if (Player* plrg = ObjectAccessor::FindPlayer(itVotes->first)) - if (plrg->GetGUID() != pBoot->victim) - plrg->GetSession()->SendLfgBootPlayer(pBoot); - delete pBoot; + boot.inProgress = false; + for (LfgAnswerMap::const_iterator itVotes = boot.votes.begin(); itVotes != boot.votes.end(); ++itVotes) + { + uint64 pguid = itVotes->first; + if (pguid != boot.victim) + SendLfgBootProposalUpdate(pguid, boot); + } m_Boots.erase(itBoot); } } @@ -317,7 +447,7 @@ void LFGMgr::Update(uint32 diff) } else player->GetSession()->SendLfgUpdatePlayer(LfgUpdateData(LFG_UPDATETYPE_PROPOSAL_BEGIN, GetSelectedDungeons(guid), GetComment(guid))); - player->GetSession()->SendLfgUpdateProposal(m_lfgProposalId, pProposal); + player->GetSession()->SendLfgUpdateProposal(m_lfgProposalId, *pProposal); } } @@ -346,24 +476,24 @@ void LFGMgr::Update(uint32 diff) } uint32 dungeonId = (*queue->dungeons.begin()); uint32 queuedTime = uint32(currTime - queue->joinTime); - uint8 role = ROLE_NONE; + uint8 role = PLAYER_ROLE_NONE; for (LfgRolesMap::const_iterator itPlayer = queue->roles.begin(); itPlayer != queue->roles.end(); ++itPlayer) role |= itPlayer->second; - role &= ~ROLE_LEADER; + role &= ~PLAYER_ROLE_LEADER; int32 waitTime = -1; switch (role) { - case ROLE_NONE: // Should not happen - just in case + case PLAYER_ROLE_NONE: // Should not happen - just in case waitTime = -1; break; - case ROLE_TANK: + case PLAYER_ROLE_TANK: waitTime = m_WaitTimeTank; break; - case ROLE_HEALER: + case PLAYER_ROLE_HEALER: waitTime = m_WaitTimeHealer; break; - case ROLE_DAMAGE: + case PLAYER_ROLE_DAMAGE: waitTime = m_WaitTimeDps; break; default: @@ -371,14 +501,13 @@ void LFGMgr::Update(uint32 diff) break; } + LfgQueueStatusData queueData(dungeonId, waitTime, m_WaitTimeAvg, m_WaitTimeTank, m_WaitTimeHealer, m_WaitTimeDps, queuedTime, queue->tanks, queue->healers, queue->dps); for (LfgRolesMap::const_iterator itPlayer = queue->roles.begin(); itPlayer != queue->roles.end(); ++itPlayer) - if (Player* player = ObjectAccessor::FindPlayer(itPlayer->first)) - player->GetSession()->SendLfgQueueStatus(dungeonId, waitTime, m_WaitTimeAvg, m_WaitTimeTank, m_WaitTimeHealer, m_WaitTimeDps, queuedTime, queue->tanks, queue->healers, queue->dps); + SendLfgQueueStatus(itPlayer->first, queueData); } } else m_QueueTimer += diff; - m_update = true; } /** @@ -441,68 +570,61 @@ bool LFGMgr::RemoveFromQueue(uint64 guid) @param[in] player Player we need to initialize the lock status map */ -void LFGMgr::InitializeLockedDungeons(Player* player) +void LFGMgr::InitializeLockedDungeons(Player* player, uint8 level /* = 0 */) { uint64 guid = player->GetGUID(); - uint8 level = player->getLevel(); + if (!level) + level = player->getLevel(); uint8 expansion = player->GetSession()->Expansion(); - LfgDungeonSet dungeons = GetDungeonsByRandom(0); + LfgDungeonSet const& dungeons = GetDungeonsByRandom(0); LfgLockMap lock; for (LfgDungeonSet::const_iterator it = dungeons.begin(); it != dungeons.end(); ++it) { - LFGDungeonEntry const* dungeon = sLFGDungeonStore.LookupEntry(*it); + LFGDungeonEntry const* dungeon = GetLFGDungeon(*it); if (!dungeon) // should never happen - We provide a list from sLFGDungeonStore continue; - AccessRequirement const* ar = sObjectMgr->GetAccessRequirement(dungeon->map, Difficulty(dungeon->difficulty)); - - LfgLockStatusType locktype = LFG_LOCKSTATUS_OK; + uint32 lockData = 0; if (dungeon->expansion > expansion) - locktype = LFG_LOCKSTATUS_INSUFFICIENT_EXPANSION; + lockData = LFG_LOCKSTATUS_INSUFFICIENT_EXPANSION; else if (DisableMgr::IsDisabledFor(DISABLE_TYPE_MAP, dungeon->map, player)) - locktype = LFG_LOCKSTATUS_RAID_LOCKED; + lockData = LFG_LOCKSTATUS_RAID_LOCKED; else if (dungeon->difficulty > DUNGEON_DIFFICULTY_NORMAL && player->GetBoundInstance(dungeon->map, Difficulty(dungeon->difficulty))) - { - //if (!player->GetGroup() || !player->GetGroup()->isLFGGroup() || GetDungeon(player->GetGroup()->GetGUID(), true) != dungeon->ID || GetState(player->GetGroup()->GetGUID()) != LFG_STATE_DUNGEON) - locktype = LFG_LOCKSTATUS_RAID_LOCKED; - } + lockData = LFG_LOCKSTATUS_RAID_LOCKED; else if (dungeon->minlevel > level) - locktype = LFG_LOCKSTATUS_TOO_LOW_LEVEL; + lockData = LFG_LOCKSTATUS_TOO_LOW_LEVEL; else if (dungeon->maxlevel < level) - locktype = LFG_LOCKSTATUS_TOO_HIGH_LEVEL; - else if (dungeon->flags & LFG_FLAG_SEASONAL) - { - if (HolidayIds holiday = sLFGMgr->GetDungeonSeason(dungeon->ID)) - if (!IsHolidayActive(holiday)) - locktype = LFG_LOCKSTATUS_NOT_IN_SEASON; - } - else if (locktype == LFG_LOCKSTATUS_OK && ar) + lockData = LFG_LOCKSTATUS_TOO_HIGH_LEVEL; + else if (dungeon->seasonal && !IsSeasonActive(dungeon->id)) + lockData = LFG_LOCKSTATUS_NOT_IN_SEASON; + else if (AccessRequirement const* ar = sObjectMgr->GetAccessRequirement(dungeon->map, Difficulty(dungeon->difficulty))) { if (ar->achievement && !player->HasAchieved(ar->achievement)) - locktype = LFG_LOCKSTATUS_RAID_LOCKED; // FIXME: Check the correct lock value + lockData = LFG_LOCKSTATUS_MISSING_ACHIEVEMENT; else if (player->GetTeam() == ALLIANCE && ar->quest_A && !player->GetQuestRewardStatus(ar->quest_A)) - locktype = LFG_LOCKSTATUS_QUEST_NOT_COMPLETED; + lockData = LFG_LOCKSTATUS_QUEST_NOT_COMPLETED; else if (player->GetTeam() == HORDE && ar->quest_H && !player->GetQuestRewardStatus(ar->quest_H)) - locktype = LFG_LOCKSTATUS_QUEST_NOT_COMPLETED; + lockData = LFG_LOCKSTATUS_QUEST_NOT_COMPLETED; else if (ar->item) { if (!player->HasItemCount(ar->item, 1) && (!ar->item2 || !player->HasItemCount(ar->item2, 1))) - locktype = LFG_LOCKSTATUS_MISSING_ITEM; + lockData = LFG_LOCKSTATUS_MISSING_ITEM; } else if (ar->item2 && !player->HasItemCount(ar->item2, 1)) - locktype = LFG_LOCKSTATUS_MISSING_ITEM; + lockData = LFG_LOCKSTATUS_MISSING_ITEM; } + /* TODO VoA closed if WG is not under team control (LFG_LOCKSTATUS_RAID_LOCKED) - locktype = LFG_LOCKSTATUS_TOO_LOW_GEAR_SCORE; - locktype = LFG_LOCKSTATUS_TOO_HIGH_GEAR_SCORE; - locktype = LFG_LOCKSTATUS_ATTUNEMENT_TOO_LOW_LEVEL; - locktype = LFG_LOCKSTATUS_ATTUNEMENT_TOO_HIGH_LEVEL; + lockData = LFG_LOCKSTATUS_TOO_LOW_GEAR_SCORE; + lockData = LFG_LOCKSTATUS_TOO_HIGH_GEAR_SCORE; + lockData = LFG_LOCKSTATUS_ATTUNEMENT_TOO_LOW_LEVEL; + lockData = LFG_LOCKSTATUS_ATTUNEMENT_TOO_HIGH_LEVEL; */ - if (locktype != LFG_LOCKSTATUS_OK) - lock[dungeon->Entry()] = locktype; + if (lockData) + lock[dungeon->Entry()] = lockData; } SetLockedDungeons(guid, lock); } @@ -517,10 +639,10 @@ void LFGMgr::InitializeLockedDungeons(Player* player) @param[in] dungeons Dungeons the player/group is applying for @param[in] comment Player selected comment */ -void LFGMgr::Join(Player* player, uint8 roles, const LfgDungeonSet& selectedDungeons, const std::string& comment) +void LFGMgr::JoinLfg(Player* player, uint8 roles, LfgDungeonSet& dungeons, const std::string& comment) { - if (!player || !player->GetSession() || selectedDungeons.empty()) - return; + if (!player || !player->GetSession() || dungeons.empty()) + return; Group* grp = player->GetGroup(); uint64 guid = player->GetGUID(); @@ -529,7 +651,6 @@ void LFGMgr::Join(Player* player, uint8 roles, const LfgDungeonSet& selectedDung PlayerSet players; uint32 rDungeonId = 0; bool isContinue = grp && grp->isLFGGroup() && GetState(gguid) != LFG_STATE_FINISHED_DUNGEON; - LfgDungeonSet dungeons = selectedDungeons; // Do not allow to change dungeon in the middle of a current dungeon if (isContinue) @@ -542,7 +663,7 @@ void LFGMgr::Join(Player* player, uint8 roles, const LfgDungeonSet& selectedDung LfgQueueInfoMap::iterator itQueue = m_QueueInfoMap.find(gguid); if (itQueue != m_QueueInfoMap.end()) { - LfgDungeonSet playerDungeons = GetSelectedDungeons(guid); + LfgDungeonSet const& playerDungeons = GetSelectedDungeons(guid); if (playerDungeons == dungeons) // Joining the same dungeons -- Send OK { LfgUpdateData updateData = LfgUpdateData(LFG_UPDATETYPE_ADDED_TO_QUEUE, dungeons, comment); @@ -652,25 +773,24 @@ void LFGMgr::Join(Player* player, uint8 roles, const LfgDungeonSet& selectedDung return; } - // FIXME - Raid browser not supported yet + SetComment(guid, comment); + if (isRaid) { sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::Join: [" UI64FMTD "] trying to join raid browser and it's disabled.", guid); return; } - SetComment(guid, comment); - + std::string debugNames = ""; if (grp) // Begin rolecheck { // Create new rolecheck - LfgRoleCheck* roleCheck = new LfgRoleCheck(); - roleCheck->cancelTime = time_t(time(NULL)) + LFG_TIME_ROLECHECK; - roleCheck->state = LFG_ROLECHECK_INITIALITING; - roleCheck->leader = guid; - roleCheck->dungeons = dungeons; - roleCheck->rDungeonId = rDungeonId; - m_RoleChecks[gguid] = roleCheck; + LfgRoleCheck& roleCheck = m_RoleChecks[gguid]; + roleCheck.cancelTime = time_t(time(NULL)) + LFG_TIME_ROLECHECK; + roleCheck.state = LFG_ROLECHECK_INITIALITING; + roleCheck.leader = guid; + roleCheck.dungeons = dungeons; + roleCheck.rDungeonId = rDungeonId; if (rDungeonId) { @@ -690,7 +810,10 @@ void LFGMgr::Join(Player* player, uint8 roles, const LfgDungeonSet& selectedDung SetState(pguid, LFG_STATE_ROLECHECK); if (!isContinue) SetSelectedDungeons(pguid, dungeons); - roleCheck->roles[pguid] = 0; + roleCheck.roles[pguid] = 0; + if (!debugNames.empty()) + debugNames.append(", "); + debugNames.append(plrg->GetName()); } } // Update leader role @@ -703,19 +826,14 @@ void LFGMgr::Join(Player* player, uint8 roles, const LfgDungeonSet& selectedDung pqInfo->joinTime = time_t(time(NULL)); pqInfo->roles[player->GetGUID()] = roles; pqInfo->dungeons = dungeons; - if (roles & ROLE_TANK) + if (roles & PLAYER_ROLE_TANK) --pqInfo->tanks; - else if (roles & ROLE_HEALER) + else if (roles & PLAYER_ROLE_HEALER) --pqInfo->healers; else --pqInfo->dps; m_QueueInfoMap[guid] = pqInfo; - // Send update to player - player->GetSession()->SendLfgJoinResult(joinData); - player->GetSession()->SendLfgUpdatePlayer(LfgUpdateData(LFG_UPDATETYPE_JOIN_PROPOSAL, dungeons, comment)); - SetState(gguid, LFG_STATE_QUEUED); - SetRoles(guid, roles); if (!isContinue) { if (rDungeonId) @@ -725,9 +843,22 @@ void LFGMgr::Join(Player* player, uint8 roles, const LfgDungeonSet& selectedDung } SetSelectedDungeons(guid, dungeons); } + // Send update to player + player->GetSession()->SendLfgJoinResult(joinData); + player->GetSession()->SendLfgUpdatePlayer(LfgUpdateData(LFG_UPDATETYPE_JOIN_PROPOSAL, dungeons, comment)); + SetState(gguid, LFG_STATE_QUEUED); + SetRoles(guid, roles); + debugNames.append(player->GetName()); AddToQueue(guid, uint8(player->GetTeam())); } - sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::Join: [" UI64FMTD "] joined with %u members. dungeons: %u", guid, grp ? grp->GetMembersCount() : 1, uint8(dungeons.size())); + + if (sLog->ShouldLog(LOG_FILTER_LFG, LOG_LEVEL_DEBUG)) + { + std::ostringstream o; + o << "LFGMgr::Join: [" << guid << "] joined (" << (grp ? "group" : "player") << ") Members: " << debugNames.c_str() + << ". Dungeons (" << uint32(dungeons.size()) << "): " << ConcatenateDungeons(dungeons); + sLog->outDebug(LOG_FILTER_LFG, "%s", o.str().c_str()); + } } /** @@ -737,7 +868,7 @@ void LFGMgr::Join(Player* player, uint8 roles, const LfgDungeonSet& selectedDung @param[in] player Player trying to leave (can be NULL) @param[in] grp Group trying to leave (default NULL) */ -void LFGMgr::Leave(Player* player, Group* grp /* = NULL*/) +void LFGMgr::LeaveLfg(Player* player, Group* grp /* = NULL*/) { if (!player && !grp) return; @@ -754,19 +885,19 @@ void LFGMgr::Leave(Player* player, Group* grp /* = NULL*/) LfgUpdateData updateData = LfgUpdateData(LFG_UPDATETYPE_REMOVED_FROM_QUEUE); if (grp) { - RestoreState(guid); + RestoreState(guid, "Leave queue"); for (GroupReference* itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) if (Player* plrg = itr->getSource()) { plrg->GetSession()->SendLfgUpdateParty(updateData); uint64 pguid = plrg->GetGUID(); - ClearState(pguid); + ClearState(pguid, "Leave queue"); } } else { player->GetSession()->SendLfgUpdatePlayer(updateData); - ClearState(guid); + ClearState(guid, "Leave queue"); } } break; @@ -941,7 +1072,7 @@ bool LFGMgr::CheckCompatibility(LfgGuidList check, LfgProposal*& pProposal) for (LfgRolesMap::const_iterator itRoles = it->second->roles.begin(); itRoles != it->second->roles.end(); ++itRoles) { // Assign new leader - if (itRoles->second & ROLE_LEADER && (!leader || urand(0, 1))) + if (itRoles->second & PLAYER_ROLE_LEADER && (!leader || urand(0, 1))) leader = itRoles->first; rolesMap[itRoles->first] = itRoles->second; @@ -961,8 +1092,7 @@ bool LFGMgr::CheckCompatibility(LfgGuidList check, LfgProposal*& pProposal) { for (PlayerSet::const_iterator itPlayer = players.begin(); itPlayer != players.end() && player; ++itPlayer) { - // Do not form a group with ignoring candidates - if (player->GetSocial()->HasIgnore((*itPlayer)->GetGUIDLow()) || (*itPlayer)->GetSocial()->HasIgnore(player->GetGUIDLow())) + if (HasIgnore((*itPlayer)->GetGUID(), player->GetGUID())) { sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::CheckCompatibility: (%s) Players [" UI64FMTD "] and [" UI64FMTD "] ignoring", strGuids.c_str(), (*itPlayer)->GetGUID(), player->GetGUID()); player = NULL; @@ -1021,11 +1151,11 @@ bool LFGMgr::CheckCompatibility(LfgGuidList check, LfgProposal*& pProposal) for (LfgRolesMap::const_iterator itPlayer = queue->roles.begin(); itPlayer != queue->roles.end(); ++itPlayer) { uint8 roles = itPlayer->second; - if ((roles & ROLE_TANK) && Tanks_Needed > 0) + if ((roles & PLAYER_ROLE_TANK) && Tanks_Needed > 0) --Tanks_Needed; - else if ((roles & ROLE_HEALER) && Healers_Needed > 0) + else if ((roles & PLAYER_ROLE_HEALER) && Healers_Needed > 0) --Healers_Needed; - else if ((roles & ROLE_DAMAGE) && Dps_Needed > 0) + else if ((roles & PLAYER_ROLE_DAMAGE) && Dps_Needed > 0) --Dps_Needed; } } @@ -1106,7 +1236,7 @@ bool LFGMgr::CheckCompatibility(LfgGuidList check, LfgProposal*& pProposal) @param[in] guid Player guid (0 = rolecheck failed) @param[in] roles Player selected roles */ -void LFGMgr::UpdateRoleCheck(uint64 gguid, uint64 guid /* = 0 */, uint8 roles /* = ROLE_NONE */) +void LFGMgr::UpdateRoleCheck(uint64 gguid, uint64 guid /* = 0 */, uint8 roles /* = PLAYER_ROLE_NONE */) { if (!gguid) return; @@ -1116,87 +1246,88 @@ void LFGMgr::UpdateRoleCheck(uint64 gguid, uint64 guid /* = 0 */, uint8 roles /* if (itRoleCheck == m_RoleChecks.end()) return; - LfgRoleCheck* roleCheck = itRoleCheck->second; - bool sendRoleChosen = roleCheck->state != LFG_ROLECHECK_DEFAULT && guid; + LfgRoleCheck& roleCheck = itRoleCheck->second; + bool sendRoleChosen = roleCheck.state != LFG_ROLECHECK_DEFAULT && guid; if (!guid) - roleCheck->state = LFG_ROLECHECK_ABORTED; - else if (roles < ROLE_TANK) // Player selected no role. - roleCheck->state = LFG_ROLECHECK_NO_ROLE; + roleCheck.state = LFG_ROLECHECK_ABORTED; + else if (roles < PLAYER_ROLE_TANK) // Player selected no role. + roleCheck.state = LFG_ROLECHECK_NO_ROLE; else { - roleCheck->roles[guid] = roles; + roleCheck.roles[guid] = roles; // Check if all players have selected a role - LfgRolesMap::const_iterator itRoles = roleCheck->roles.begin(); - while (itRoles != roleCheck->roles.end() && itRoles->second != ROLE_NONE) + LfgRolesMap::const_iterator itRoles = roleCheck.roles.begin(); + while (itRoles != roleCheck.roles.end() && itRoles->second != PLAYER_ROLE_NONE) ++itRoles; - if (itRoles == roleCheck->roles.end()) + if (itRoles == roleCheck.roles.end()) { // use temporal var to check roles, CheckGroupRoles modifies the roles - check_roles = roleCheck->roles; - roleCheck->state = CheckGroupRoles(check_roles) ? LFG_ROLECHECK_FINISHED : LFG_ROLECHECK_WRONG_ROLES; + check_roles = roleCheck.roles; + roleCheck.state = CheckGroupRoles(check_roles) ? LFG_ROLECHECK_FINISHED : LFG_ROLECHECK_WRONG_ROLES; } } uint8 team = 0; LfgDungeonSet dungeons; - if (roleCheck->rDungeonId) - dungeons.insert(roleCheck->rDungeonId); + if (roleCheck.rDungeonId) + dungeons.insert(roleCheck.rDungeonId); else - dungeons = roleCheck->dungeons; + dungeons = roleCheck.dungeons; - LfgJoinResultData joinData = LfgJoinResultData(LFG_JOIN_FAILED, roleCheck->state); - for (LfgRolesMap::const_iterator it = roleCheck->roles.begin(); it != roleCheck->roles.end(); ++it) + LfgJoinResultData joinData = LfgJoinResultData(LFG_JOIN_FAILED, roleCheck.state); + for (LfgRolesMap::const_iterator it = roleCheck.roles.begin(); it != roleCheck.roles.end(); ++it) { uint64 pguid = it->first; Player* plrg = ObjectAccessor::FindPlayer(pguid); if (!plrg) { - if (roleCheck->state == LFG_ROLECHECK_FINISHED) + if (roleCheck.state == LFG_ROLECHECK_FINISHED) SetState(pguid, LFG_STATE_QUEUED); - else if (roleCheck->state != LFG_ROLECHECK_INITIALITING) - ClearState(pguid); + else if (roleCheck.state != LFG_ROLECHECK_INITIALITING) + ClearState(pguid, "Offline while Rolecheck"); continue; } team = uint8(plrg->GetTeam()); if (!sendRoleChosen) - plrg->GetSession()->SendLfgRoleChosen(guid, roles); - plrg->GetSession()->SendLfgRoleCheckUpdate(roleCheck); - switch (roleCheck->state) + SendLfgRoleChosen(pguid, guid, roles); + + SendLfgRoleCheckUpdate(pguid, roleCheck); + switch (roleCheck.state) { case LFG_ROLECHECK_INITIALITING: continue; case LFG_ROLECHECK_FINISHED: SetState(pguid, LFG_STATE_QUEUED); - plrg->GetSession()->SendLfgUpdateParty(LfgUpdateData(LFG_UPDATETYPE_ADDED_TO_QUEUE, dungeons, GetComment(pguid))); + SendLfgUpdateParty(pguid, LfgUpdateData(LFG_UPDATETYPE_ADDED_TO_QUEUE, dungeons, GetComment(pguid))); break; default: - if (roleCheck->leader == pguid) - plrg->GetSession()->SendLfgJoinResult(joinData); - plrg->GetSession()->SendLfgUpdateParty(LfgUpdateData(LFG_UPDATETYPE_ROLECHECK_FAILED)); - ClearState(pguid); + if (roleCheck.leader == pguid) + SendLfgJoinResult(pguid, joinData); + SendLfgUpdateParty(pguid, LfgUpdateData(LFG_UPDATETYPE_ROLECHECK_FAILED)); + ClearState(pguid, "Role check Failed"); break; } } - if (roleCheck->state == LFG_ROLECHECK_FINISHED) + if (roleCheck.state == LFG_ROLECHECK_FINISHED) { SetState(gguid, LFG_STATE_QUEUED); LfgQueueInfo* pqInfo = new LfgQueueInfo(); pqInfo->joinTime = time_t(time(NULL)); - pqInfo->roles = roleCheck->roles; - pqInfo->dungeons = roleCheck->dungeons; + pqInfo->roles = roleCheck.roles; + pqInfo->dungeons = roleCheck.dungeons; // Set queue roles needed - As we are using check_roles will not have more that 1 tank, 1 healer, 3 dps for (LfgRolesMap::const_iterator it = check_roles.begin(); it != check_roles.end(); ++it) { uint8 roles2 = it->second; - if (roles2 & ROLE_TANK) + if (roles2 & PLAYER_ROLE_TANK) --pqInfo->tanks; - else if (roles2 & ROLE_HEALER) + else if (roles2 & PLAYER_ROLE_HEALER) --pqInfo->healers; else --pqInfo->dps; @@ -1210,12 +1341,9 @@ void LFGMgr::UpdateRoleCheck(uint64 gguid, uint64 guid /* = 0 */, uint8 roles /* } AddToQueue(gguid, team); } - - if (roleCheck->state != LFG_ROLECHECK_INITIALITING) + else if (roleCheck.state != LFG_ROLECHECK_INITIALITING) { - if (roleCheck->state != LFG_ROLECHECK_FINISHED) - RestoreState(gguid); - delete roleCheck; + RestoreState(gguid, "Rolecheck Failed"); m_RoleChecks.erase(itRoleCheck); } } @@ -1280,7 +1408,7 @@ void LFGMgr::GetCompatibleDungeons(LfgDungeonSet& dungeons, const PlayerSet& pla for (PlayerSet::const_iterator it = players.begin(); it != players.end() && !dungeons.empty(); ++it) { uint64 guid = (*it)->GetGUID(); - LfgLockMap cachedLockMap = GetLockedDungeons(guid); + LfgLockMap const& cachedLockMap = GetLockedDungeons(guid); for (LfgLockMap::const_iterator it2 = cachedLockMap.begin(); it2 != cachedLockMap.end() && !dungeons.empty(); ++it2) { uint32 dungeonId = (it2->first & 0x00FFFFFF); // Compare dungeon ids @@ -1314,21 +1442,21 @@ bool LFGMgr::CheckGroupRoles(LfgRolesMap& groles, bool removeLeaderFlag /*= true if (removeLeaderFlag) for (LfgRolesMap::iterator it = groles.begin(); it != groles.end(); ++it) - it->second &= ~ROLE_LEADER; + it->second &= ~PLAYER_ROLE_LEADER; for (LfgRolesMap::iterator it = groles.begin(); it != groles.end(); ++it) { - if (it->second == ROLE_NONE) + if (it->second == PLAYER_ROLE_NONE) return false; - if (it->second & ROLE_TANK) + if (it->second & PLAYER_ROLE_TANK) { - if (it->second != ROLE_TANK) + if (it->second != PLAYER_ROLE_TANK) { - it->second -= ROLE_TANK; + it->second -= PLAYER_ROLE_TANK; if (CheckGroupRoles(groles, false)) return true; - it->second += ROLE_TANK; + it->second += PLAYER_ROLE_TANK; } else if (tank == LFG_TANKS_NEEDED) return false; @@ -1336,14 +1464,14 @@ bool LFGMgr::CheckGroupRoles(LfgRolesMap& groles, bool removeLeaderFlag /*= true tank++; } - if (it->second & ROLE_HEALER) + if (it->second & PLAYER_ROLE_HEALER) { - if (it->second != ROLE_HEALER) + if (it->second != PLAYER_ROLE_HEALER) { - it->second -= ROLE_HEALER; + it->second -= PLAYER_ROLE_HEALER; if (CheckGroupRoles(groles, false)) return true; - it->second += ROLE_HEALER; + it->second += PLAYER_ROLE_HEALER; } else if (healer == LFG_HEALERS_NEEDED) return false; @@ -1351,14 +1479,14 @@ bool LFGMgr::CheckGroupRoles(LfgRolesMap& groles, bool removeLeaderFlag /*= true healer++; } - if (it->second & ROLE_DAMAGE) + if (it->second & PLAYER_ROLE_DAMAGE) { - if (it->second != ROLE_DAMAGE) + if (it->second != PLAYER_ROLE_DAMAGE) { - it->second -= ROLE_DAMAGE; + it->second -= PLAYER_ROLE_DAMAGE; if (CheckGroupRoles(groles, false)) return true; - it->second += ROLE_DAMAGE; + it->second += PLAYER_ROLE_DAMAGE; } else if (damage == LFG_DPS_NEEDED) return false; @@ -1426,7 +1554,7 @@ void LFGMgr::UpdateProposal(uint32 proposalId, uint64 guid, bool accept) if (!allAnswered) { for (LfgPlayerList::const_iterator it = players.begin(); it != players.end(); ++it) - (*it)->GetSession()->SendLfgUpdateProposal(proposalId, pProposal); + (*it)->GetSession()->SendLfgUpdateProposal(proposalId, *pProposal); } else { @@ -1454,7 +1582,7 @@ void LFGMgr::UpdateProposal(uint32 proposalId, uint64 guid, bool accept) } // Set the dungeon difficulty - LFGDungeonEntry const* dungeon = sLFGDungeonStore.LookupEntry(pProposal->dungeonId); + LFGDungeonEntry const* dungeon = GetLFGDungeon(pProposal->dungeonId); ASSERT(dungeon); // Create a new group (if needed) @@ -1466,7 +1594,7 @@ void LFGMgr::UpdateProposal(uint32 proposalId, uint64 guid, bool accept) uint64 pguid = player->GetGUID(); Group* group = player->GetGroup(); if (sendUpdate) - player->GetSession()->SendLfgUpdateProposal(proposalId, pProposal); + player->GetSession()->SendLfgUpdateProposal(proposalId, *pProposal); if (group) { @@ -1491,22 +1619,22 @@ void LFGMgr::UpdateProposal(uint32 proposalId, uint64 guid, bool accept) // Update timers uint8 role = GetRoles(pguid); - role &= ~ROLE_LEADER; + role &= ~PLAYER_ROLE_LEADER; switch (role) { - case ROLE_DAMAGE: + case PLAYER_ROLE_DAMAGE: { uint32 old_number = m_NumWaitTimeDps++; m_WaitTimeDps = int32((m_WaitTimeDps * old_number + waitTimesMap[player->GetGUID()]) / m_NumWaitTimeDps); break; } - case ROLE_HEALER: + case PLAYER_ROLE_HEALER: { uint32 old_number = m_NumWaitTimeHealer++; m_WaitTimeHealer = int32((m_WaitTimeHealer * old_number + waitTimesMap[player->GetGUID()]) / m_NumWaitTimeHealer); break; } - case ROLE_TANK: + case PLAYER_ROLE_TANK: { uint32 old_number = m_NumWaitTimeTank++; m_WaitTimeTank = int32((m_WaitTimeTank * old_number + waitTimesMap[player->GetGUID()]) / m_NumWaitTimeTank); @@ -1559,19 +1687,19 @@ void LFGMgr::UpdateProposal(uint32 proposalId, uint64 guid, bool accept) */ void LFGMgr::RemoveProposal(LfgProposalMap::iterator itProposal, LfgUpdateType type) { - LfgProposal* pProposal = itProposal->second; - pProposal->state = LFG_PROPOSAL_FAILED; + LfgProposal& proposal = *(itProposal->second); + proposal.state = LFG_PROPOSAL_FAILED; sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::RemoveProposal: Proposal %u, state FAILED, UpdateType %u", itProposal->first, type); // Mark all people that didn't answered as no accept if (type == LFG_UPDATETYPE_PROPOSAL_FAILED) - for (LfgProposalPlayerMap::const_iterator it = pProposal->players.begin(); it != pProposal->players.end(); ++it) + for (LfgProposalPlayerMap::const_iterator it = proposal.players.begin(); it != proposal.players.end(); ++it) if (it->second->accept == LFG_ANSWER_PENDING) it->second->accept = LFG_ANSWER_DENY; // Mark players/groups to be removed LfgGuidSet toRemove; - for (LfgProposalPlayerMap::const_iterator it = pProposal->players.begin(); it != pProposal->players.end(); ++it) + for (LfgProposalPlayerMap::const_iterator it = proposal.players.begin(); it != proposal.players.end(); ++it) { if (it->second->accept == LFG_ANSWER_AGREE) continue; @@ -1587,14 +1715,14 @@ void LFGMgr::RemoveProposal(LfgProposalMap::iterator itProposal, LfgUpdateType t uint8 team = 0; // Notify players - for (LfgProposalPlayerMap::const_iterator it = pProposal->players.begin(); it != pProposal->players.end(); ++it) + for (LfgProposalPlayerMap::const_iterator it = proposal.players.begin(); it != proposal.players.end(); ++it) { Player* player = ObjectAccessor::FindPlayer(it->first); if (!player) continue; team = uint8(player->GetTeam()); - player->GetSession()->SendLfgUpdateProposal(itProposal->first, pProposal); + player->GetSession()->SendLfgUpdateProposal(itProposal->first, proposal); Group* grp = player->GetGroup(); uint64 guid = player->GetGUID(); @@ -1613,10 +1741,10 @@ void LFGMgr::RemoveProposal(LfgProposalMap::iterator itProposal, LfgUpdateType t updateData.updateType = LFG_UPDATETYPE_REMOVED_FROM_QUEUE; sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::RemoveProposal: [" UI64FMTD "] in same group that someone that didn't accept. Removing from queue and compatible cache", guid); } - ClearState(guid); + ClearState(guid, "Proposal Fail (didn't accepted or in group with someone that didn't accept"); if (grp) { - RestoreState(gguid); + RestoreState(gguid, "Proposal Fail (someone in group didn't accepted)"); player->GetSession()->SendLfgUpdateParty(updateData); } else @@ -1641,11 +1769,11 @@ void LFGMgr::RemoveProposal(LfgProposalMap::iterator itProposal, LfgUpdateType t { uint64 guid = *it; RemoveFromQueue(guid); - pProposal->queues.remove(guid); + proposal.queues.remove(guid); } // Readd to queue - for (LfgGuidList::const_iterator it = pProposal->queues.begin(); it != pProposal->queues.end(); ++it) + for (LfgGuidList::const_iterator it = proposal.queues.begin(); it != proposal.queues.end(); ++it) { uint64 guid = *it; LfgGuidList& currentQueue = m_currentQueue[team]; @@ -1653,7 +1781,7 @@ void LFGMgr::RemoveProposal(LfgProposalMap::iterator itProposal, LfgUpdateType t AddToQueue(guid, team); //We have to add each GUID in newQueue to check for a new groups } - delete pProposal; + delete &proposal; m_Proposals.erase(itProposal); } @@ -1665,41 +1793,39 @@ void LFGMgr::RemoveProposal(LfgProposalMap::iterator itProposal, LfgUpdateType t @param[in] victim Victim guid @param[in] reason Kick reason */ -void LFGMgr::InitBoot(Group* grp, uint64 kicker, uint64 victim, std::string reason) +void LFGMgr::InitBoot(Group* grp, uint64 kicker, uint64 victim, std::string const& reason) { if (!grp) return; - uint64 gguid = grp->GetGUID(); + uint32 gguid = grp->GetLowGUID(); SetState(gguid, LFG_STATE_BOOT); - LfgPlayerBoot* pBoot = new LfgPlayerBoot(); - pBoot->inProgress = true; - pBoot->cancelTime = time_t(time(NULL)) + LFG_TIME_BOOT; - pBoot->reason = reason; - pBoot->victim = victim; - pBoot->votedNeeded = GetVotesNeeded(gguid); + LfgPlayerBoot& boot = m_Boots[gguid]; + boot.inProgress = true; + boot.cancelTime = time_t(time(NULL)) + LFG_TIME_BOOT; + boot.reason = reason; + boot.victim = victim; - // Set votes + LfgGuidSet players; for (GroupReference* itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) + if (Player* player = itr->getSource()) + players.insert(player->GetGUID()); + + // Set votes + for (LfgGuidSet::const_iterator itr = players.begin(); itr != players.end(); ++itr) { - if (Player* plrg = itr->getSource()) - { - uint64 guid = plrg->GetGUID(); - SetState(guid, LFG_STATE_BOOT); - if (guid == victim) - pBoot->votes[victim] = LFG_ANSWER_DENY; // Victim auto vote NO - else if (guid == kicker) - pBoot->votes[kicker] = LFG_ANSWER_AGREE; // Kicker auto vote YES - else - { - pBoot->votes[guid] = LFG_ANSWER_PENDING; // Other members need to vote - plrg->GetSession()->SendLfgBootPlayer(pBoot); - } - } + uint64 guid = (*itr); + SetState(guid, LFG_STATE_BOOT); + boot.votes[guid] = LFG_ANSWER_PENDING; } - m_Boots[grp->GetLowGUID()] = pBoot; + boot.votes[victim] = LFG_ANSWER_DENY; // Victim auto vote NO + boot.votes[kicker] = LFG_ANSWER_AGREE; // Kicker auto vote YES + + // Notify players + for (LfgGuidSet::const_iterator it = players.begin(); it != players.end(); ++it) + SendLfgBootProposalUpdate(*it, boot); } /** @@ -1714,25 +1840,23 @@ void LFGMgr::UpdateBoot(Player* player, bool accept) if (!grp) return; - uint32 bootId = grp->GetLowGUID(); + uint32 gguid = grp->GetLowGUID(); uint64 guid = player->GetGUID(); - LfgPlayerBootMap::iterator itBoot = m_Boots.find(bootId); + LfgPlayerBootMap::iterator itBoot = m_Boots.find(gguid); if (itBoot == m_Boots.end()) return; - LfgPlayerBoot* pBoot = itBoot->second; - if (!pBoot) - return; + LfgPlayerBoot& boot = itBoot->second; - if (pBoot->votes[guid] != LFG_ANSWER_PENDING) // Cheat check: Player can't vote twice + if (boot.votes[guid] != LFG_ANSWER_PENDING) // Cheat check: Player can't vote twice return; - pBoot->votes[guid] = LfgAnswer(accept); + boot.votes[guid] = LfgAnswer(accept); uint8 votesNum = 0; uint8 agreeNum = 0; - for (LfgAnswerMap::const_iterator itVotes = pBoot->votes.begin(); itVotes != pBoot->votes.end(); ++itVotes) + for (LfgAnswerMap::const_iterator itVotes = boot.votes.begin(); itVotes != boot.votes.end(); ++itVotes) { if (itVotes->second != LFG_ANSWER_PENDING) { @@ -1742,39 +1866,36 @@ void LFGMgr::UpdateBoot(Player* player, bool accept) } } - if (agreeNum == pBoot->votedNeeded || // Vote passed - votesNum == pBoot->votes.size() || // All voted but not passed - (pBoot->votes.size() - votesNum + agreeNum) < pBoot->votedNeeded) // Vote didnt passed + // if we don't have enough votes (agree or deny) do nothing + if (agreeNum < LFG_GROUP_KICK_VOTES_NEEDED && (votesNum - agreeNum) < LFG_GROUP_KICK_VOTES_NEEDED) + return; + + // Send update info to all players + boot.inProgress = false; + for (LfgAnswerMap::const_iterator itVotes = boot.votes.begin(); itVotes != boot.votes.end(); ++itVotes) { - // Send update info to all players - pBoot->inProgress = false; - for (LfgAnswerMap::const_iterator itVotes = pBoot->votes.begin(); itVotes != pBoot->votes.end(); ++itVotes) + uint64 pguid = itVotes->first; + if (pguid != boot.victim) { - uint64 pguid = itVotes->first; - if (pguid != pBoot->victim) - { - SetState(pguid, LFG_STATE_DUNGEON); - if (Player* plrg = ObjectAccessor::FindPlayer(pguid)) - plrg->GetSession()->SendLfgBootPlayer(pBoot); - } + SetState(pguid, LFG_STATE_DUNGEON); + SendLfgBootProposalUpdate(pguid, boot); } + } - uint64 gguid = grp->GetGUID(); - SetState(gguid, LFG_STATE_DUNGEON); - if (agreeNum == pBoot->votedNeeded) // Vote passed - Kick player + gguid = grp->GetGUID(); + SetState(gguid, LFG_STATE_DUNGEON); + if (agreeNum == LFG_GROUP_KICK_VOTES_NEEDED) // Vote passed - Kick player + { + Player::RemoveFromGroup(grp, boot.victim); + if (Player* victim = ObjectAccessor::FindPlayer(boot.victim)) { - Player::RemoveFromGroup(grp, pBoot->victim); - if (Player* victim = ObjectAccessor::FindPlayer(pBoot->victim)) - { - TeleportPlayer(victim, true, false); - SetState(pBoot->victim, LFG_STATE_NONE); - } - OfferContinue(grp); - DecreaseKicksLeft(gguid); + TeleportPlayer(victim, true, false); + SetState(boot.victim, LFG_STATE_NONE); } - delete pBoot; - m_Boots.erase(itBoot); + OfferContinue(grp); + DecreaseKicksLeft(gguid); } + m_Boots.erase(itBoot); } /** @@ -1788,8 +1909,20 @@ void LFGMgr::TeleportPlayer(Player* player, bool out, bool fromOpcode /*= false* { sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::TeleportPlayer: [" UI64FMTD "] is being teleported %s", player->GetGUID(), out ? "out" : "in"); - LfgTeleportError error = LFG_TELEPORTERROR_OK; Group* grp = player->GetGroup(); + uint64 gguid = grp->GetGUID(); + LFGDungeonEntry const* dungeon = GetLFGDungeon(GetDungeon(gguid)); + if (!dungeon || (out && player->GetMapId() != uint32(dungeon->map))) + return; + + if (out) + { + player->RemoveAurasDueToSpell(LFG_SPELL_LUCK_OF_THE_DRAW); + player->TeleportToBGEntryPoint(); + return; + } + + LfgTeleportError error = LFG_TELEPORTERROR_OK; if (!grp || !grp->isLFGGroup()) // should never happen, but just in case... error = LFG_TELEPORTERROR_INVALID_LOCATION; @@ -1799,33 +1932,21 @@ void LFGMgr::TeleportPlayer(Player* player, bool out, bool fromOpcode /*= false* error = LFG_TELEPORTERROR_FALLING; else if (player->IsMirrorTimerActive(FATIGUE_TIMER)) error = LFG_TELEPORTERROR_FATIGUE; + else if (player->GetVehicle()) + error = LFG_TELEPORTERROR_IN_VEHICLE; + else if (player->GetCharmGUID()) + error = LFG_TELEPORTERROR_CHARMING; else { - LFGDungeonEntry const* dungeon = sLFGDungeonStore.LookupEntry(GetDungeon(grp->GetGUID())); - - if (out) - { - // Player needs to be inside the LFG dungeon to be able to teleport out - if (dungeon && player->GetMapId() == uint32(dungeon->map)) - { - player->RemoveAurasDueToSpell(LFG_SPELL_LUCK_OF_THE_DRAW); - player->TeleportToBGEntryPoint(); - } - else - player->GetSession()->SendLfgTeleportError(LFG_TELEPORTERROR_DONT_REPORT); // Not sure which error message to send - - return; - } - if (!dungeon) error = LFG_TELEPORTERROR_INVALID_LOCATION; else if (player->GetMapId() != uint32(dungeon->map)) // Do not teleport players in dungeon to the entrance { - uint32 mapid = 0; - float x = 0; - float y = 0; - float z = 0; - float orientation = 0; + uint32 mapid = dungeon->map; + float x = dungeon->x; + float y = dungeon->y; + float z = dungeon->z; + float orientation = dungeon->o; if (!fromOpcode) { @@ -1844,32 +1965,6 @@ void LFGMgr::TeleportPlayer(Player* player, bool out, bool fromOpcode /*= false* } } - if (!mapid) - { - LfgEntrancePositionMap::const_iterator itr = m_entrancePositions.find(dungeon->ID); - if (itr != m_entrancePositions.end()) - { - mapid = dungeon->map; - x = itr->second.GetPositionX(); - y = itr->second.GetPositionY(); - z = itr->second.GetPositionZ(); - orientation = itr->second.GetOrientation(); - } - else if (AreaTrigger const* at = sObjectMgr->GetMapEntranceTrigger(dungeon->map)) - { - mapid = at->target_mapId; - x = at->target_X; - y = at->target_Y; - z = at->target_Z; - orientation = at->target_Orientation; - } - else - { - sLog->outError(LOG_FILTER_LFG, "LfgMgr::TeleportPlayer: Failed to teleport [" UI64FMTD "]: No areatrigger found for map: %u difficulty: %u", player->GetGUID(), dungeon->map, dungeon->difficulty); - error = LFG_TELEPORTERROR_INVALID_LOCATION; - } - } - if (error == LFG_TELEPORTERROR_OK) { if (!player->GetMap()->IsDungeon()) @@ -1881,10 +1976,7 @@ void LFGMgr::TeleportPlayer(Player* player, bool out, bool fromOpcode /*= false* player->CleanupAfterTaxiFlight(); } - if (player->TeleportTo(mapid, x, y, z, orientation)) - // FIXME - HACK - this should be done by teleport, when teleporting far - player->RemoveAurasByType(SPELL_AURA_MOUNTED); - else + if (!player->TeleportTo(mapid, x, y, z, orientation)) { error = LFG_TELEPORTERROR_INVALID_LOCATION; sLog->outError(LOG_FILTER_LFG, "LfgMgr::TeleportPlayer: Failed to teleport [" UI64FMTD "] to map %u: ", player->GetGUID(), mapid); @@ -1932,12 +2024,12 @@ void LFGMgr::RewardDungeonDoneFor(const uint32 dungeonId, Player* player) // Clear player related lfg stuff uint32 rDungeonId = (*GetSelectedDungeons(guid).begin()); - ClearState(guid); + ClearState(guid, "Dungeon Finished"); SetState(guid, LFG_STATE_FINISHED_DUNGEON); // Give rewards only if its a random or seasonal dungeon - LFGDungeonEntry const* dungeon = sLFGDungeonStore.LookupEntry(rDungeonId); - if (!dungeon || (dungeon->type != LFG_TYPE_RANDOM && !(dungeon->flags & LFG_FLAG_SEASONAL))) + LFGDungeonEntry const* dungeon = GetLFGDungeon(rDungeonId); + if (!dungeon || (dungeon->type != LFG_TYPE_RANDOM && !dungeon->seasonal)) { sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::RewardDungeonDoneFor: [" UI64FMTD "] dungeon %u is not random nor seasonal", guid, rDungeonId); return; @@ -1986,9 +2078,9 @@ void LFGMgr::RewardDungeonDoneFor(const uint32 dungeonId, Player* player) */ const LfgDungeonSet& LFGMgr::GetDungeonsByRandom(uint32 randomdungeon) { - LFGDungeonEntry const* dungeon = sLFGDungeonStore.LookupEntry(randomdungeon); - uint32 groupType = dungeon ? dungeon->grouptype : 0; - return m_CachedDungeonMap[groupType]; + LFGDungeonEntry const* dungeon = GetLFGDungeon(randomdungeon); + uint32 group = dungeon ? dungeon->group : 0; + return m_CachedDungeonMap[group]; } /** @@ -2021,7 +2113,7 @@ LfgReward const* LFGMgr::GetRandomDungeonReward(uint32 dungeon, uint8 level) */ LfgType LFGMgr::GetDungeonType(uint32 dungeonId) { - LFGDungeonEntry const* dungeon = sLFGDungeonStore.LookupEntry(dungeonId); + LFGDungeonEntry const* dungeon = GetLFGDungeon(dungeonId); if (!dungeon) return LFG_TYPE_NONE; @@ -2047,31 +2139,6 @@ std::string LFGMgr::ConcatenateGuids(LfgGuidList check) return o.str(); } -HolidayIds LFGMgr::GetDungeonSeason(uint32 dungeonId) -{ - HolidayIds holiday = HOLIDAY_NONE; - - switch (dungeonId) - { - case 285: - holiday = HOLIDAY_HALLOWS_END; - break; - case 286: - holiday = HOLIDAY_FIRE_FESTIVAL; - break; - case 287: - holiday = HOLIDAY_BREWFEST; - break; - case 288: - holiday = HOLIDAY_LOVE_IS_IN_THE_AIR; - break; - default: - break; - } - - return holiday; -} - LfgState LFGMgr::GetState(uint64 guid) { sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::GetState: [" UI64FMTD "]", guid); @@ -2123,35 +2190,45 @@ const LfgLockMap& LFGMgr::GetLockedDungeons(uint64 guid) uint8 LFGMgr::GetKicksLeft(uint64 guid) { - sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::GetKicksLeft: [" UI64FMTD "]", guid); - return m_Groups[guid].GetKicksLeft(); + uint8 kicks = m_Groups[guid].GetKicksLeft(); + sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::GetKicksLeft: [" UI64FMTD "] = %u", guid, kicks); + return kicks; } -uint8 LFGMgr::GetVotesNeeded(uint64 guid) +void LFGMgr::RestoreState(uint64 guid, char const *debugMsg) { - sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::GetVotesNeeded: [" UI64FMTD "]", guid); - return m_Groups[guid].GetVotesNeeded(); + LfgGroupData& data = m_Groups[guid]; + char const * const ps = GetStateString(data.GetState()); + sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::RestoreState: Group: [" UI64FMTD "] (%s), State: %s", guid, debugMsg, ps); + data.RestoreState(); } -void LFGMgr::RestoreState(uint64 guid) +void LFGMgr::ClearState(uint64 guid, char const *debugMsg) { - sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::RestoreState: [" UI64FMTD "]", guid); - m_Groups[guid].RestoreState(); -} - -void LFGMgr::ClearState(uint64 guid) -{ - sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::ClearState: [" UI64FMTD "]", guid); - m_Players[guid].ClearState(); + LfgPlayerData& data = m_Players[guid]; + char const * const ps = GetStateString(data.GetState()); + sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::ClearState: Player: [" UI64FMTD "] (%s) State: %s", guid, debugMsg, ps); + data.ClearState(); } void LFGMgr::SetState(uint64 guid, LfgState state) { - sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::SetState: [" UI64FMTD "] state %u", guid, state); if (IS_GROUP(guid)) - m_Groups[guid].SetState(state); + { + LfgGroupData& data = m_Groups[guid]; + char const * const ns = GetStateString(state); + char const * const ps = GetStateString(data.GetState()); + sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::SetState: Group: [" UI64FMTD "] newState: %s, previous: %s", guid, ns, ps); + data.SetState(state); + } else - m_Players[guid].SetState(state); + { + LfgPlayerData& data = m_Players[guid]; + char const * const ns = GetStateString(state); + char const * const ps = GetStateString(data.GetState()); + sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::SetState: Player: [" UI64FMTD "] newState: %s, previous: %s", guid, ns, ps); + data.SetState(state); + } } void LFGMgr::SetDungeon(uint64 guid, uint32 dungeon) @@ -2205,3 +2282,81 @@ void LFGMgr::RemoveGroupData(uint64 guid) if (it != m_Groups.end()) m_Groups.erase(it); } + +bool LFGMgr::HasIgnore(uint64 guid1, uint64 guid2) +{ + Player* plr1 = ObjectAccessor::FindPlayer(guid1); + Player* plr2 = ObjectAccessor::FindPlayer(guid2); + uint32 low1 = GUID_LOPART(guid1); + uint32 low2 = GUID_LOPART(guid2); + return plr1 && plr2 && (plr1->GetSocial()->HasIgnore(low2) || plr2->GetSocial()->HasIgnore(low1)); +} + +void LFGMgr::SendLfgRoleChosen(uint64 guid, uint64 pguid, uint8 roles) +{ + if (Player* player = ObjectAccessor::FindPlayer(guid)) + player->GetSession()->SendLfgRoleChosen(pguid, roles); +} + +void LFGMgr::SendLfgRoleCheckUpdate(uint64 guid, const LfgRoleCheck& roleCheck) +{ + if (Player* player = ObjectAccessor::FindPlayer(guid)) + player->GetSession()->SendLfgRoleCheckUpdate(roleCheck); +} + +void LFGMgr::SendLfgUpdatePlayer(uint64 guid, const LfgUpdateData& data) +{ + if (Player* player = ObjectAccessor::FindPlayer(guid)) + player->GetSession()->SendLfgUpdatePlayer(data); +} + +void LFGMgr::SendLfgUpdateParty(uint64 guid, const LfgUpdateData& data) +{ + if (Player* player = ObjectAccessor::FindPlayer(guid)) + player->GetSession()->SendLfgUpdateParty(data); +} + +void LFGMgr::SendLfgJoinResult(uint64 guid, const LfgJoinResultData& data) +{ + if (Player* player = ObjectAccessor::FindPlayer(guid)) + player->GetSession()->SendLfgJoinResult(data); +} + +void LFGMgr::SendLfgBootProposalUpdate(uint64 guid, const LfgPlayerBoot& boot) +{ + if (Player* player = ObjectAccessor::FindPlayer(guid)) + player->GetSession()->SendLfgBootProposalUpdate(boot); +} + +void LFGMgr::SendLfgUpdateProposal(uint64 guid, uint32 proposalId, const LfgProposal& proposal) +{ + if (Player* player = ObjectAccessor::FindPlayer(guid)) + player->GetSession()->SendLfgUpdateProposal(proposalId, proposal); +} + +void LFGMgr::SendLfgQueueStatus(uint64 guid, const LfgQueueStatusData& data) +{ + if (Player* player = ObjectAccessor::FindPlayer(guid)) + player->GetSession()->SendLfgQueueStatus(data); +} + +bool LFGMgr::IsLfgGroup(uint64 guid) +{ + return guid && IS_GROUP(guid) && m_Groups[guid].IsLfgGroup(); +} + +bool LFGMgr::IsSeasonActive(uint32 dungeonId) +{ + switch (dungeonId) + { + case 285: // The Headless Horseman + return IsHolidayActive(HOLIDAY_HALLOWS_END); + case 286: // The Frost Lord Ahune + return IsHolidayActive(HOLIDAY_FIRE_FESTIVAL); + case 287: // Coren Direbrew + return IsHolidayActive(HOLIDAY_BREWFEST); + case 288: // The Crown Chemical Co. + return IsHolidayActive(HOLIDAY_LOVE_IS_IN_THE_AIR); + } + return false; +} diff --git a/src/server/game/DungeonFinding/LFGMgr.h b/src/server/game/DungeonFinding/LFGMgr.h index 9937759741b..d4d35974604 100755 --- a/src/server/game/DungeonFinding/LFGMgr.h +++ b/src/server/game/DungeonFinding/LFGMgr.h @@ -21,24 +21,24 @@ #include "Common.h" #include #include "LFG.h" +#include "LFGGroupData.h" +#include "LFGPlayerData.h" -class LfgGroupData; -class LfgPlayerData; +class LFGPlayerScript; +class LFGGroupScript; class Group; class Player; -enum LFGenum +enum LFGMgrEnum { - LFG_TIME_ROLECHECK = 40*IN_MILLISECONDS, - LFG_TIME_BOOT = 2*MINUTE, - LFG_TIME_PROPOSAL = 2*MINUTE, - LFG_TANKS_NEEDED = 1, - LFG_HEALERS_NEEDED = 1, - LFG_DPS_NEEDED = 3, - LFG_QUEUEUPDATE_INTERVAL = 15*IN_MILLISECONDS, + LFG_TIME_ROLECHECK = 40 * IN_MILLISECONDS, + LFG_TIME_BOOT = 120, + LFG_TIME_PROPOSAL = 120, + LFG_QUEUEUPDATE_INTERVAL = 15 * IN_MILLISECONDS, LFG_SPELL_DUNGEON_COOLDOWN = 71328, LFG_SPELL_DUNGEON_DESERTER = 71041, - LFG_SPELL_LUCK_OF_THE_DRAW = 72221 + LFG_SPELL_LUCK_OF_THE_DRAW = 72221, + LFG_GROUP_KICK_VOTES_NEEDED = 3 }; enum LfgFlags @@ -52,11 +52,9 @@ enum LfgFlags /// Determines the type of instance enum LfgType { - LFG_TYPE_NONE = 0, // Internal use only + LFG_TYPE_NONE = 0, LFG_TYPE_DUNGEON = 1, LFG_TYPE_RAID = 2, - LFG_TYPE_QUEST = 3, - LFG_TYPE_ZONE = 4, LFG_TYPE_HEROIC = 5, LFG_TYPE_RANDOM = 6 }; @@ -72,13 +70,14 @@ enum LfgProposalState /// Teleport errors enum LfgTeleportError { - // 3, 7, 8 = "You can't do that right now" | 5 = No client reaction + // 7 = "You can't do that right now" | 5 = No client reaction LFG_TELEPORTERROR_OK = 0, // Internal use LFG_TELEPORTERROR_PLAYER_DEAD = 1, LFG_TELEPORTERROR_FALLING = 2, - LFG_TELEPORTERROR_DONT_REPORT = 3, + LFG_TELEPORTERROR_IN_VEHICLE = 3, LFG_TELEPORTERROR_FATIGUE = 4, - LFG_TELEPORTERROR_INVALID_LOCATION = 6 + LFG_TELEPORTERROR_INVALID_LOCATION = 6, + LFG_TELEPORTERROR_CHARMING = 8 // FIXME - It can be 7 or 8 (Need proper data) }; /// Queue join results @@ -116,42 +115,31 @@ enum LfgRoleCheckState LFG_ROLECHECK_NO_ROLE = 6 // Someone selected no role }; -/// Answer state (Also used to check compatibilites) -enum LfgAnswer -{ - LFG_ANSWER_PENDING = -1, - LFG_ANSWER_DENY = 0, - LFG_ANSWER_AGREE = 1 -}; - // Forward declaration (just to have all typedef together) +struct LFGDungeonEntry; struct LfgReward; -struct LfgLockStatus; struct LfgQueueInfo; struct LfgRoleCheck; struct LfgProposal; struct LfgProposalPlayer; struct LfgPlayerBoot; -typedef std::set LfgGuidSet; -typedef std::list LfgGuidList; typedef std::map LfgGuidListMap; typedef std::set PlayerSet; typedef std::list LfgPlayerList; typedef std::multimap LfgRewardMap; typedef std::pair LfgRewardMapBounds; typedef std::map LfgCompatibleMap; -typedef std::map LfgDungeonMap; -typedef std::map LfgRolesMap; +typedef std::map LfgCachedDungeonMap; typedef std::map LfgAnswerMap; -typedef std::map LfgRoleCheckMap; +typedef std::map LfgRoleCheckMap; typedef std::map LfgQueueInfoMap; typedef std::map LfgProposalMap; typedef std::map LfgProposalPlayerMap; -typedef std::map LfgPlayerBootMap; +typedef std::map LfgPlayerBootMap; typedef std::map LfgGroupDataMap; typedef std::map LfgPlayerDataMap; -typedef std::map LfgEntrancePositionMap; +typedef UNORDERED_MAP LFGDungeonMap; // Data needed by SMSG_LFG_JOIN_RESULT struct LfgJoinResultData @@ -167,7 +155,7 @@ struct LfgJoinResultData struct LfgUpdateData { LfgUpdateData(LfgUpdateType _type = LFG_UPDATETYPE_DEFAULT): updateType(_type), comment("") {} - LfgUpdateData(LfgUpdateType _type, const LfgDungeonSet& _dungeons, std::string _comment): + LfgUpdateData(LfgUpdateType _type, LfgDungeonSet const& _dungeons, std::string _comment): updateType(_type), dungeons(_dungeons), comment(_comment) {} LfgUpdateType updateType; @@ -175,6 +163,26 @@ struct LfgUpdateData std::string comment; }; +// Data needed by SMSG_LFG_QUEUE_STATUS +struct LfgQueueStatusData +{ + LfgQueueStatusData(uint32 _dungeonId = 0, int32 _waitTime = -1, int32 _waitTimeAvg = -1, int32 _waitTimeTank = -1, int32 _waitTimeHealer = -1, + int32 _waitTimeDps = -1, uint32 _queuedTime = 0, uint8 _tanks = 0, uint8 _healers = 0, uint8 _dps = 0) : + dungeonId(_dungeonId), waitTime(_waitTime), waitTimeAvg(_waitTimeAvg), waitTimeTank(_waitTimeTank), waitTimeHealer(_waitTimeHealer), + waitTimeDps(_waitTimeDps), queuedTime(_queuedTime), tanks(_tanks), healers(_healers), dps(_dps) {} + + uint32 dungeonId; + int32 waitTime; + int32 waitTimeAvg; + int32 waitTimeTank; + int32 waitTimeHealer; + int32 waitTimeDps; + uint32 queuedTime; + uint8 tanks; + uint8 healers; + uint8 dps; +}; + /// Reward info struct LfgReward { @@ -236,7 +244,6 @@ struct LfgProposal time_t cancelTime; ///< Time when we will cancel this proposal LfgGuidList queues; ///< Queue Ids to remove/readd LfgProposalPlayerMap players; ///< Players data - }; /// Stores all rolecheck info of a group that wants to join @@ -261,6 +268,33 @@ struct LfgPlayerBoot std::string reason; ///< kick reason }; +struct LFGDungeonEntry +{ + LFGDungeonEntry(): id(0), name(""), map(0), type(0), expansion(0), group(0), minlevel(0), + maxlevel(0), difficulty(REGULAR_DIFFICULTY), seasonal(false), x(0.0f), y(0.0f), z(0.0f), o(0.0f) + { } + LFGDungeonEntry(LFGDungeonEntryDbc const* dbc): id(dbc->ID), name(dbc->name[0]), map(dbc->map), + type(dbc->type), expansion(dbc->expansion), group(dbc->grouptype), + minlevel(dbc->minlevel), maxlevel(dbc->maxlevel), difficulty(Difficulty(dbc->difficulty)), + seasonal(dbc->flags & LFG_FLAG_SEASONAL), x(0.0f), y(0.0f), z(0.0f), o(0.0f) + { } + + uint32 id; + std::string name; + uint16 map; + uint8 type; + uint8 expansion; + uint8 group; + uint8 minlevel; + uint8 maxlevel; + Difficulty difficulty; + bool seasonal; + float x, y, z, o; + + // Helpers + uint32 Entry() const { return id + (type << 24); } +}; + class LFGMgr { friend class ACE_Singleton; @@ -274,57 +308,70 @@ class LFGMgr // Reward void LoadRewards(); - void RewardDungeonDoneFor(const uint32 dungeonId, Player* player); + void RewardDungeonDoneFor(uint32 const dungeonId, Player* player); LfgReward const* GetRandomDungeonReward(uint32 dungeon, uint8 level); // Queue - void Join(Player* player, uint8 roles, const LfgDungeonSet& dungeons, const std::string& comment); - void Leave(Player* player, Group* grp = NULL); + void JoinLfg(Player* player, uint8 roles, LfgDungeonSet& dungeons, std::string const& comment); + void LeaveLfg(Player* player, Group* grp = NULL); // Role Check - void UpdateRoleCheck(uint64 gguid, uint64 guid = 0, uint8 roles = ROLE_NONE); + void UpdateRoleCheck(uint64 gguid, uint64 guid = 0, uint8 roles = PLAYER_ROLE_NONE); // Proposals void UpdateProposal(uint32 proposalId, uint64 guid, bool accept); // Teleportation - void LoadEntrancePositions(); void TeleportPlayer(Player* player, bool out, bool fromOpcode = false); // Vote kick - void InitBoot(Group* grp, uint64 kguid, uint64 vguid, std::string reason); + void InitBoot(Group* grp, uint64 kguid, uint64 vguid, std::string const& reason); void UpdateBoot(Player* player, bool accept); void OfferContinue(Group* grp); - HolidayIds GetDungeonSeason(uint32 dungeonId); + void InitializeLockedDungeons(Player* player, uint8 level = 0); - void InitializeLockedDungeons(Player* player); + void SetRoles(uint64 guid, uint8 roles); + void SetComment(uint64 guid, std::string const& comment); + void SetState(uint64 guid, LfgState state); + void SetSelectedDungeons(uint64 guid, LfgDungeonSet const& dungeons); void _LoadFromDB(Field* fields, uint64 guid); void _SaveToDB(uint64 guid, uint32 db_guid); - void SetComment(uint64 guid, const std::string& comment); - const LfgLockMap& GetLockedDungeons(uint64 guid); - LfgState GetState(uint64 guid); - const LfgDungeonSet& GetSelectedDungeons(uint64 guid); - uint32 GetDungeon(uint64 guid, bool asId = true); - void SetState(uint64 guid, LfgState state); - void ClearState(uint64 guid); void RemovePlayerData(uint64 guid); void RemoveGroupData(uint64 guid); + + LfgLockMap const& GetLockedDungeons(uint64 guid); + LfgDungeonSet const& GetSelectedDungeons(uint64 guid); + uint32 GetDungeon(uint64 guid, bool asId = true); + LfgState GetState(uint64 guid); uint8 GetKicksLeft(uint64 gguid); - uint8 GetVotesNeeded(uint64 gguid); - bool IsTeleported(uint64 pguid); - void SetRoles(uint64 guid, uint8 roles); - void SetSelectedDungeons(uint64 guid, const LfgDungeonSet& dungeons); + bool IsLfgGroup(uint64 guid); + uint8 GetRoles(uint64 guid); + std::string const& GetComment(uint64 gguid); + bool IsTeleported(uint64 guid); + + static bool HasIgnore(uint64 guid1, uint64 guid2); + static void SendLfgQueueStatus(uint64 guid, LfgQueueStatusData const& data); + bool IsSeasonActive(uint32 dungeonId); + + static std::string ConcatenateDungeons(LfgDungeonSet const& dungeons); + static std::string GetRolesString(uint8 roles); + static char const * GetStateString(LfgState state); + + void LoadLFGDungeons(bool reload = false); + LFGDungeonEntry const* GetLFGDungeon(uint32 id); + LFGDungeonMap& GetLFGDungeonMap(); + + void ClearState(uint64 guid, char const *debugMsg); private: - uint8 GetRoles(uint64 guid); - const std::string& GetComment(uint64 gguid); - void RestoreState(uint64 guid); + void RestoreState(uint64 guid, char const *debugMsg); + void SetDungeon(uint64 guid, uint32 dungeon); - void SetLockedDungeons(uint64 guid, const LfgLockMap& lock); + void SetLockedDungeons(uint64 guid, LfgLockMap const& lock); void DecreaseKicksLeft(uint64 guid); // Queue @@ -338,20 +385,29 @@ class LFGMgr LfgProposal* FindNewGroups(LfgGuidList& check, LfgGuidList& all); bool CheckGroupRoles(LfgRolesMap &groles, bool removeLeaderFlag = true); bool CheckCompatibility(LfgGuidList check, LfgProposal*& pProposal); - void GetCompatibleDungeons(LfgDungeonSet& dungeons, const PlayerSet& players, LfgLockPartyMap& lockMap); + void GetCompatibleDungeons(LfgDungeonSet& dungeons, PlayerSet const& players, LfgLockPartyMap& lockMap); void SetCompatibles(std::string concatenatedGuids, bool compatibles); LfgAnswer GetCompatibles(std::string concatenatedGuids); void RemoveFromCompatibles(uint64 guid); // Generic - const LfgDungeonSet& GetDungeonsByRandom(uint32 randomdungeon); + LfgDungeonSet const& GetDungeonsByRandom(uint32 randomdungeon); LfgType GetDungeonType(uint32 dungeon); std::string ConcatenateGuids(LfgGuidList check); + void SendLfgBootProposalUpdate(uint64 guid, LfgPlayerBoot const& boot); + void SendLfgJoinResult(uint64 guid, LfgJoinResultData const& data); + void SendLfgRoleChosen(uint64 guid, uint64 pguid, uint8 roles); + void SendLfgRoleCheckUpdate(uint64 guid, LfgRoleCheck const& roleCheck); + void SendLfgUpdateParty(uint64 guid, LfgUpdateData const& data); + void SendLfgUpdatePlayer(uint64 guid, LfgUpdateData const& data); + void SendLfgUpdateProposal(uint64 guid, uint32 proposalId, LfgProposal const& proposal); + // General variables - bool m_update; ///< Doing an update? uint32 m_QueueTimer; ///< used to check interval of update uint32 m_lfgProposalId; ///< used as internal counter for proposals + uint32 m_options; ///< Stores config options + int32 m_WaitTimeAvg; ///< Average wait time to find a group queuing as multiple roles int32 m_WaitTimeTank; ///< Average wait time to find a group queuing as tank int32 m_WaitTimeHealer; ///< Average wait time to find a group queuing as healer @@ -360,10 +416,10 @@ class LFGMgr uint32 m_NumWaitTimeTank; ///< Num of players used to calc tank wait time uint32 m_NumWaitTimeHealer; ///< Num of players used to calc healers wait time uint32 m_NumWaitTimeDps; ///< Num of players used to calc dps wait time - LfgDungeonMap m_CachedDungeonMap; ///< Stores all dungeons by groupType - LfgEntrancePositionMap m_entrancePositions; ///< Stores special entrance positions + LfgCachedDungeonMap m_CachedDungeonMap; ///< Stores all dungeons by groupType // Reward System LfgRewardMap m_RewardMap; ///< Stores rewards for random dungeons + LFGDungeonMap m_LfgDungeonMap; // Queue LfgQueueInfoMap m_QueueInfoMap; ///< Queued groups LfgGuidListMap m_currentQueue; ///< Ordered list. Used to find groups @@ -376,6 +432,9 @@ class LFGMgr LfgPlayerBootMap m_Boots; ///< Current player kicks LfgPlayerDataMap m_Players; ///< Player data LfgGroupDataMap m_Groups; ///< Group data + + LFGPlayerScript *m_lfgPlayerScript; + LFGGroupScript *m_lfgGroupScript; }; #define sLFGMgr ACE_Singleton::instance() diff --git a/src/server/game/DungeonFinding/LFGScripts.cpp b/src/server/game/DungeonFinding/LFGScripts.cpp index 36f04b3020b..26686dbaa33 100644 --- a/src/server/game/DungeonFinding/LFGScripts.cpp +++ b/src/server/game/DungeonFinding/LFGScripts.cpp @@ -39,12 +39,12 @@ void LFGPlayerScript::OnLevelChanged(Player* player, uint8 /*oldLevel*/) void LFGPlayerScript::OnLogout(Player* player) { - sLFGMgr->Leave(player); + uint64 guid = player->GetGUID(); + sLFGMgr->LeaveLfg(player); LfgUpdateData updateData = LfgUpdateData(LFG_UPDATETYPE_REMOVED_FROM_QUEUE); player->GetSession()->SendLfgUpdateParty(updateData); player->GetSession()->SendLfgUpdatePlayer(updateData); - player->GetSession()->SendLfgUpdateSearch(false); - uint64 guid = player->GetGUID(); + player->GetSession()->SendLfgLfrList(false); // TODO - Do not remove, add timer before deleting sLFGMgr->RemovePlayerData(guid); } @@ -85,11 +85,11 @@ void LFGGroupScript::OnAddMember(Group* group, uint64 guid) // TODO - if group is queued and new player is added convert to rolecheck without notify the current players queued if (sLFGMgr->GetState(gguid) == LFG_STATE_QUEUED) - sLFGMgr->Leave(NULL, group); + sLFGMgr->LeaveLfg(NULL, group); if (sLFGMgr->GetState(guid) == LFG_STATE_QUEUED) if (Player* player = ObjectAccessor::FindPlayer(guid)) - sLFGMgr->Leave(player); + sLFGMgr->LeaveLfg(player); } void LFGGroupScript::OnRemoveMember(Group* group, uint64 guid, RemoveMethod method, uint64 kicker, char const* reason) @@ -102,7 +102,7 @@ void LFGGroupScript::OnRemoveMember(Group* group, uint64 guid, RemoveMethod meth if (sLFGMgr->GetState(gguid) == LFG_STATE_QUEUED) { // TODO - Do not remove, just remove the one leaving and rejoin queue with all other data - sLFGMgr->Leave(NULL, group); + sLFGMgr->LeaveLfg(NULL, group); } if (!group->isLFGGroup()) @@ -119,16 +119,14 @@ void LFGGroupScript::OnRemoveMember(Group* group, uint64 guid, RemoveMethod meth } uint32 state = sLFGMgr->GetState(gguid); - sLFGMgr->ClearState(guid); + sLFGMgr->ClearState(guid, "OnRemoveMember"); sLFGMgr->SetState(guid, LFG_STATE_NONE); if (Player* player = ObjectAccessor::FindPlayer(guid)) { if (method == GROUP_REMOVEMETHOD_LEAVE && sLFGMgr->GetState(gguid) != LFG_STATE_FINISHED_DUNGEON && sLFGMgr->GetDungeon(gguid, false)) player->CastSpell(player, LFG_SPELL_DUNGEON_DESERTER, true); - /* - else if (group->isLfgKickActive()) + //else if (state == LFG_STATE_BOOT) // Update internal kick cooldown of kicked - */ LfgUpdateData updateData = LfgUpdateData(LFG_UPDATETYPE_LEADER); player->GetSession()->SendLfgUpdateParty(updateData); @@ -176,5 +174,5 @@ void LFGGroupScript::OnInviteMember(Group* group, uint64 guid) return; sLog->outDebug(LOG_FILTER_LFG, "LFGScripts::OnInviteMember [" UI64FMTD "]: invite [" UI64FMTD "] leader [" UI64FMTD "]", gguid, guid, group->GetLeaderGUID()); - sLFGMgr->Leave(NULL, group); + sLFGMgr->LeaveLfg(NULL, group); } diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 161fdc2be1d..93a0580a866 100755 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -11901,7 +11901,7 @@ InventoryResult Player::CanRollForItemInLFG(ItemTemplate const* proto, WorldObje bool lootedObjectInDungeon = false; Map const* map = lootedObject->GetMap(); if (uint32 dungeonId = sLFGMgr->GetDungeon(GetGroup()->GetGUID(), true)) - if (LFGDungeonEntry const* dungeon = sLFGDungeonStore.LookupEntry(dungeonId)) + if (LFGDungeonEntry const* dungeon = sLFGMgr->GetLFGDungeon(dungeonId)) if (uint32(dungeon->map) == map->GetId() && dungeon->difficulty == uint32(map->GetDifficulty())) lootedObjectInDungeon = true; @@ -23261,7 +23261,7 @@ PartyResult Player::CanUninviteFromGroup() const if (state == LFG_STATE_BOOT) return ERR_PARTY_LFG_BOOT_IN_PROGRESS; - if (grp->GetMembersCount() <= sLFGMgr->GetVotesNeeded(gguid)) + if (grp->GetMembersCount() <= LFG_GROUP_KICK_VOTES_NEEDED) return ERR_PARTY_LFG_BOOT_TOO_FEW_PLAYERS; if (state == LFG_STATE_FINISHED_DUNGEON) @@ -23294,8 +23294,22 @@ PartyResult Player::CanUninviteFromGroup() const bool Player::isUsingLfg() { - uint64 guid = GetGUID(); - return sLFGMgr->GetState(guid) != LFG_STATE_NONE; + return sLFGMgr->GetState(GetGUID()) != LFG_STATE_NONE; +} + +bool Player::inRandomLfgDungeon() +{ + if (isUsingLfg()) + { + const LfgDungeonSet& dungeons = sLFGMgr->GetSelectedDungeons(GetGUID()); + if (!dungeons.empty()) + { + LFGDungeonEntry const* dungeon = sLFGMgr->GetLFGDungeon(*dungeons.begin()); + if (dungeon && (dungeon->type == LFG_TYPE_RANDOM || dungeon->seasonal)) + return true; + } + } + return false; } void Player::SetBattlegroundOrBattlefieldRaid(Group* group, int8 subgroup) diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index c417c73cdbc..9d80a17bc5e 100755 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -2356,6 +2356,7 @@ class Player : public Unit, public GridObject void RemoveAtLoginFlag(AtLoginFlags flags, bool persist = false); bool isUsingLfg(); + bool inRandomLfgDungeon(); typedef std::set DFQuestsDoneList; DFQuestsDoneList m_DFQuests; diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index b884a369eeb..17982a58061 100755 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -45,6 +45,7 @@ #include "ScriptMgr.h" #include "SpellScript.h" #include "PoolMgr.h" +#include "LFGMgr.h" ScriptMapMap sQuestEndScripts; ScriptMapMap sQuestStartScripts; @@ -5028,7 +5029,7 @@ void ObjectMgr::LoadInstanceEncounters() continue; } - if (lastEncounterDungeon && !sLFGDungeonStore.LookupEntry(lastEncounterDungeon)) + if (lastEncounterDungeon && !sLFGMgr->GetLFGDungeon(lastEncounterDungeon)) { sLog->outError(LOG_FILTER_SQL, "Table `instance_encounters` has an encounter %u (%s) marked as final for invalid dungeon id %u, skipped!", entry, dungeonEncounter->encounterName[0], lastEncounterDungeon); continue; diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp index 19ea3ff8174..f06225988d6 100755 --- a/src/server/game/Groups/Group.cpp +++ b/src/server/game/Groups/Group.cpp @@ -600,7 +600,7 @@ bool Group::RemoveMember(uint64 guid, const RemoveMethod &method /*= GROUP_REMOV if (isLFGGroup() && GetMembersCount() == 1) { Player* Leader = ObjectAccessor::FindPlayer(GetLeaderGUID()); - LFGDungeonEntry const* dungeon = sLFGDungeonStore.LookupEntry(sLFGMgr->GetDungeon(GetGUID())); + LFGDungeonEntry const* dungeon = sLFGMgr->GetLFGDungeon(sLFGMgr->GetDungeon(GetGUID())); if ((Leader && dungeon && Leader->isAlive() && Leader->GetMapId() != uint32(dungeon->map)) || !dungeon) { Disband(); diff --git a/src/server/game/Handlers/LFGHandler.cpp b/src/server/game/Handlers/LFGHandler.cpp index f5d5a0b67e2..59631618757 100755 --- a/src/server/game/Handlers/LFGHandler.cpp +++ b/src/server/game/Handlers/LFGHandler.cpp @@ -23,7 +23,6 @@ #include "LFGMgr.h" #include "ObjectMgr.h" #include "GroupMgr.h" -#include "GameEventMgr.h" #include "InstanceScript.h" void BuildPlayerLockDungeonBlock(WorldPacket& data, const LfgLockMap& lock) @@ -82,18 +81,19 @@ void WorldSession::HandleLfgJoinOpcode(WorldPacket& recv_data) std::string comment; recv_data >> comment; sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_LFG_JOIN [" UI64FMTD "] roles: %u, Dungeons: %u, Comment: %s", GetPlayer()->GetGUID(), roles, uint8(newDungeons.size()), comment.c_str()); - sLFGMgr->Join(GetPlayer(), uint8(roles), newDungeons, comment); + sLFGMgr->JoinLfg(GetPlayer(), uint8(roles), newDungeons, comment); } void WorldSession::HandleLfgLeaveOpcode(WorldPacket& /*recv_data*/) { Group* grp = GetPlayer()->GetGroup(); + uint64 guid = GetPlayer()->GetGUID(); - sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_LFG_LEAVE [" UI64FMTD "] in group: %u", GetPlayer()->GetGUID(), grp ? 1 : 0); + sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_LFG_LEAVE [" UI64FMTD "] in group: %u", guid, grp ? 1 : 0); // Check cheating - only leader can leave the queue if (!grp || grp->GetLeaderGUID() == GetPlayer()->GetGUID()) - sLFGMgr->Leave(GetPlayer(), grp); + sLFGMgr->LeaveLfg(GetPlayer(), grp); } void WorldSession::HandleLfgProposalResultOpcode(WorldPacket& recv_data) @@ -128,7 +128,7 @@ void WorldSession::HandleLfgSetCommentOpcode(WorldPacket& recv_data) std::string comment; recv_data >> comment; uint64 guid = GetPlayer()->GetGUID(); - sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_SET_LFG_COMMENT [" UI64FMTD "] comment: %s", guid, comment.c_str()); + sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_LFG_SET_COMMENT [" UI64FMTD "] comment: %s", guid, comment.c_str()); sLFGMgr->SetComment(guid, comment); } @@ -138,7 +138,8 @@ void WorldSession::HandleLfgSetBootVoteOpcode(WorldPacket& recv_data) bool agree; // Agree to kick player recv_data >> agree; - sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_LFG_SET_BOOT_VOTE [" UI64FMTD "] agree: %u", GetPlayer()->GetGUID(), agree ? 1 : 0); + uint64 guid = GetPlayer()->GetGUID(); + sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_LFG_SET_BOOT_VOTE [" UI64FMTD "] agree: %u", guid, agree ? 1 : 0); sLFGMgr->UpdateBoot(GetPlayer(), agree); } @@ -154,32 +155,24 @@ void WorldSession::HandleLfgTeleportOpcode(WorldPacket& recv_data) void WorldSession::HandleLfgPlayerLockInfoRequestOpcode(WorldPacket& /*recv_data*/) { uint64 guid = GetPlayer()->GetGUID(); - sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_LFD_PLAYER_LOCK_INFO_REQUEST [" UI64FMTD "]", guid); + sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_LFG_PLAYER_LOCK_INFO_REQUEST [" UI64FMTD "]", guid); // Get Random dungeons that can be done at a certain level and expansion LfgDungeonSet randomDungeons; uint8 level = GetPlayer()->getLevel(); uint8 expansion = GetPlayer()->GetSession()->Expansion(); - for (uint32 i = 0; i < sLFGDungeonStore.GetNumRows(); ++i) - { - LFGDungeonEntry const* dungeon = sLFGDungeonStore.LookupEntry(i); - if (dungeon && dungeon->expansion <= expansion && dungeon->minlevel <= level && level <= dungeon->maxlevel) - { - if (dungeon->flags & LFG_FLAG_SEASONAL) - { - if (HolidayIds holiday = sLFGMgr->GetDungeonSeason(dungeon->ID)) - if (!IsHolidayActive(holiday)) - continue; - } - else if (dungeon->type != LFG_TYPE_RANDOM) - continue; - randomDungeons.insert(dungeon->Entry()); - } + LFGDungeonMap& LfgDungeons = sLFGMgr->GetLFGDungeonMap(); + for (LFGDungeonMap::const_iterator itr = LfgDungeons.begin(); itr != LfgDungeons.end(); ++itr) + { + LFGDungeonEntry const& dungeon = itr->second; + if ((dungeon.type == LFG_TYPE_RANDOM || (dungeon.seasonal && sLFGMgr->IsSeasonActive(dungeon.id))) + && dungeon.expansion <= expansion && dungeon.minlevel <= level && level <= dungeon.maxlevel) + randomDungeons.insert(dungeon.Entry()); } // Get player locked Dungeons - LfgLockMap lock = sLFGMgr->GetLockedDungeons(guid); + LfgLockMap const& lock = sLFGMgr->GetLockedDungeons(guid); uint32 rsize = uint32(randomDungeons.size()); uint32 lsize = uint32(lock.size()); @@ -191,40 +184,37 @@ void WorldSession::HandleLfgPlayerLockInfoRequestOpcode(WorldPacket& /*recv_data { data << uint32(*it); // Dungeon Entry (id + type) LfgReward const* reward = sLFGMgr->GetRandomDungeonReward(*it, level); - Quest const* qRew = NULL; + Quest const* quest = NULL; uint8 done = 0; if (reward) { - qRew = sObjectMgr->GetQuestTemplate(reward->reward[0].questId); - if (qRew) + quest = sObjectMgr->GetQuestTemplate(reward->reward[0].questId); + if (quest) { - done = !GetPlayer()->CanRewardQuest(qRew, false); + done = !GetPlayer()->CanRewardQuest(quest, false); if (done) - qRew = sObjectMgr->GetQuestTemplate(reward->reward[1].questId); + quest = sObjectMgr->GetQuestTemplate(reward->reward[1].questId); } } - if (qRew) + + if (quest) { data << uint8(done); - data << uint32(qRew->GetRewOrReqMoney()); - data << uint32(qRew->XPValue(GetPlayer())); + data << uint32(quest->GetRewOrReqMoney()); + data << uint32(quest->XPValue(GetPlayer())); data << uint32(reward->reward[done].variableMoney); data << uint32(reward->reward[done].variableXP); - data << uint8(qRew->GetRewItemsCount()); - if (qRew->GetRewItemsCount()) + data << uint8(quest->GetRewItemsCount()); + if (quest->GetRewItemsCount()) { - ItemTemplate const* iProto = NULL; for (uint8 i = 0; i < QUEST_REWARDS_COUNT; ++i) - { - if (!qRew->RewardItemId[i]) - continue; - - iProto = sObjectMgr->GetItemTemplate(qRew->RewardItemId[i]); - - data << uint32(qRew->RewardItemId[i]); - data << uint32(iProto ? iProto->DisplayInfoID : 0); - data << uint32(qRew->RewardItemIdCount[i]); - } + if (uint32 itemId = quest->RewardItemId[i]) + { + ItemTemplate const* item = sObjectMgr->GetItemTemplate(itemId); + data << uint32(itemId); + data << uint32(item ? item->DisplayInfoID : 0); + data << uint32(quest->RewardItemIdCount[i]); + } } } else @@ -244,7 +234,7 @@ void WorldSession::HandleLfgPlayerLockInfoRequestOpcode(WorldPacket& /*recv_data void WorldSession::HandleLfgPartyLockInfoRequestOpcode(WorldPacket& /*recv_data*/) { uint64 guid = GetPlayer()->GetGUID(); - sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_LFD_PARTY_LOCK_INFO_REQUEST [" UI64FMTD "]", guid); + sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_LFG_PARTY_LOCK_INFO_REQUEST [" UI64FMTD "]", guid); Group* grp = GetPlayer()->GetGroup(); if (!grp) @@ -275,11 +265,11 @@ void WorldSession::HandleLfgPartyLockInfoRequestOpcode(WorldPacket& /*recv_data SendPacket(&data); } -void WorldSession::HandleLfrSearchOpcode(WorldPacket& recv_data) +void WorldSession::HandleLfrJoinOpcode(WorldPacket& recv_data) { uint32 entry; // Raid id to search recv_data >> entry; - sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_SEARCH_LFG_JOIN [" UI64FMTD "] dungeon entry: %u", GetPlayer()->GetGUID(), entry); + sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_LFG_LFR_JOIN [" UI64FMTD "] dungeon entry: %u", GetPlayer()->GetGUID(), entry); //SendLfrUpdateListOpcode(entry); } @@ -287,7 +277,7 @@ void WorldSession::HandleLfrLeaveOpcode(WorldPacket& recv_data) { uint32 dungeonId; // Raid id queue to leave recv_data >> dungeonId; - sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_SEARCH_LFG_LEAVE [" UI64FMTD "] dungeonId: %u", GetPlayer()->GetGUID(), dungeonId); + sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_LFG_LFR_LEAVE [" UI64FMTD "] dungeonId: %u", GetPlayer()->GetGUID(), dungeonId); //sLFGMgr->LeaveLfr(GetPlayer(), dungeonId); } @@ -397,45 +387,44 @@ void WorldSession::SendLfgRoleChosen(uint64 guid, uint8 roles) SendPacket(&data); } -void WorldSession::SendLfgRoleCheckUpdate(const LfgRoleCheck* pRoleCheck) +void WorldSession::SendLfgRoleCheckUpdate(const LfgRoleCheck& roleCheck) { - ASSERT(pRoleCheck); LfgDungeonSet dungeons; - if (pRoleCheck->rDungeonId) - dungeons.insert(pRoleCheck->rDungeonId); + if (roleCheck.rDungeonId) + dungeons.insert(roleCheck.rDungeonId); else - dungeons = pRoleCheck->dungeons; + dungeons = roleCheck.dungeons; sLog->outDebug(LOG_FILTER_NETWORKIO, "SMSG_LFG_ROLE_CHECK_UPDATE [" UI64FMTD "]", GetPlayer()->GetGUID()); - WorldPacket data(SMSG_LFG_ROLE_CHECK_UPDATE, 4 + 1 + 1 + dungeons.size() * 4 + 1 + pRoleCheck->roles.size() * (8 + 1 + 4 + 1)); + WorldPacket data(SMSG_LFG_ROLE_CHECK_UPDATE, 4 + 1 + 1 + dungeons.size() * 4 + 1 + roleCheck.roles.size() * (8 + 1 + 4 + 1)); - data << uint32(pRoleCheck->state); // Check result - data << uint8(pRoleCheck->state == LFG_ROLECHECK_INITIALITING); + data << uint32(roleCheck.state); // Check result + data << uint8(roleCheck.state == LFG_ROLECHECK_INITIALITING); data << uint8(dungeons.size()); // Number of dungeons if (!dungeons.empty()) { for (LfgDungeonSet::iterator it = dungeons.begin(); it != dungeons.end(); ++it) { - LFGDungeonEntry const* dungeon = sLFGDungeonStore.LookupEntry(*it); + LFGDungeonEntry const* dungeon = sLFGMgr->GetLFGDungeon(*it); data << uint32(dungeon ? dungeon->Entry() : 0); // Dungeon } } - data << uint8(pRoleCheck->roles.size()); // Players in group - if (!pRoleCheck->roles.empty()) + data << uint8(roleCheck.roles.size()); // Players in group + if (!roleCheck.roles.empty()) { // Leader info MUST be sent 1st :S - uint64 guid = pRoleCheck->leader; - uint8 roles = pRoleCheck->roles.find(guid)->second; + uint64 guid = roleCheck.leader; + uint8 roles = roleCheck.roles.find(guid)->second; data << uint64(guid); // Guid data << uint8(roles > 0); // Ready data << uint32(roles); // Roles Player* player = ObjectAccessor::FindPlayer(guid); data << uint8(player ? player->getLevel() : 0); // Level - for (LfgRolesMap::const_iterator it = pRoleCheck->roles.begin(); it != pRoleCheck->roles.end(); ++it) + for (LfgRolesMap::const_iterator it = roleCheck.roles.begin(); it != roleCheck.roles.end(); ++it) { - if (it->first == pRoleCheck->leader) + if (it->first == roleCheck.leader) continue; guid = it->first; @@ -465,30 +454,31 @@ void WorldSession::SendLfgJoinResult(const LfgJoinResultData& joinData) SendPacket(&data); } -void WorldSession::SendLfgQueueStatus(uint32 dungeon, int32 waitTime, int32 avgWaitTime, int32 waitTimeTanks, int32 waitTimeHealer, int32 waitTimeDps, uint32 queuedTime, uint8 tanks, uint8 healers, uint8 dps) +void WorldSession::SendLfgQueueStatus(const LfgQueueStatusData& queueData) { - sLog->outDebug(LOG_FILTER_NETWORKIO, "SMSG_LFG_QUEUE_STATUS [" UI64FMTD "] dungeon: %u - waitTime: %d - avgWaitTime: %d - waitTimeTanks: %d - waitTimeHealer: %d - waitTimeDps: %d - queuedTime: %u - tanks: %u - healers: %u - dps: %u", GetPlayer()->GetGUID(), dungeon, waitTime, avgWaitTime, waitTimeTanks, waitTimeHealer, waitTimeDps, queuedTime, tanks, healers, dps); + sLog->outDebug(LOG_FILTER_NETWORKIO, "SMSG_LFG_QUEUE_STATUS [" UI64FMTD "] dungeon: %u - waitTime: %d - avgWaitTime: %d - waitTimeTanks: %d - waitTimeHealer: %d - waitTimeDps: %d - queuedTime: %u - tanks: %u - healers: %u - dps: %u", + GetPlayer()->GetGUID(), queueData.dungeonId, queueData.waitTime, queueData.waitTimeAvg, queueData.waitTimeTank, queueData.waitTimeHealer, queueData.waitTimeDps, queueData.queuedTime, queueData.tanks, queueData.healers, queueData.dps); WorldPacket data(SMSG_LFG_QUEUE_STATUS, 4 + 4 + 4 + 4 + 4 +4 + 1 + 1 + 1 + 4); - data << uint32(dungeon); // Dungeon - data << int32(avgWaitTime); // Average Wait time - data << int32(waitTime); // Wait Time - data << int32(waitTimeTanks); // Wait Tanks - data << int32(waitTimeHealer); // Wait Healers - data << int32(waitTimeDps); // Wait Dps - data << uint8(tanks); // Tanks needed - data << uint8(healers); // Healers needed - data << uint8(dps); // Dps needed - data << uint32(queuedTime); // Player wait time in queue + data << uint32(queueData.dungeonId); // Dungeon + data << int32(queueData.waitTimeAvg); // Average Wait time + data << int32(queueData.waitTime); // Wait Time + data << int32(queueData.waitTimeTank); // Wait Tanks + data << int32(queueData.waitTimeHealer); // Wait Healers + data << int32(queueData.waitTimeDps); // Wait Dps + data << uint8(queueData.tanks); // Tanks needed + data << uint8(queueData.healers); // Healers needed + data << uint8(queueData.dps); // Dps needed + data << uint32(queueData.queuedTime); // Player wait time in queue SendPacket(&data); } -void WorldSession::SendLfgPlayerReward(uint32 rdungeonEntry, uint32 sdungeonEntry, uint8 done, const LfgReward* reward, const Quest* qRew) +void WorldSession::SendLfgPlayerReward(uint32 rdungeonEntry, uint32 sdungeonEntry, uint8 done, const LfgReward* reward, const Quest* quest) { - if (!rdungeonEntry || !sdungeonEntry || !qRew) + if (!rdungeonEntry || !sdungeonEntry || !quest) return; - uint8 itemNum = uint8(qRew ? qRew->GetRewItemsCount() : 0); + uint8 itemNum = uint8(quest ? quest->GetRewItemsCount() : 0); sLog->outDebug(LOG_FILTER_NETWORKIO, "SMSG_LFG_PLAYER_REWARD [" UI64FMTD "] rdungeonEntry: %u - sdungeonEntry: %u - done: %u", GetPlayer()->GetGUID(), rdungeonEntry, sdungeonEntry, done); WorldPacket data(SMSG_LFG_PLAYER_REWARD, 4 + 4 + 1 + 4 + 4 + 4 + 4 + 4 + 1 + itemNum * (4 + 4 + 4)); @@ -496,37 +486,33 @@ void WorldSession::SendLfgPlayerReward(uint32 rdungeonEntry, uint32 sdungeonEntr data << uint32(sdungeonEntry); // Dungeon Finished data << uint8(done); data << uint32(1); - data << uint32(qRew->GetRewOrReqMoney()); - data << uint32(qRew->XPValue(GetPlayer())); + data << uint32(quest->GetRewOrReqMoney()); + data << uint32(quest->XPValue(GetPlayer())); data << uint32(reward->reward[done].variableMoney); data << uint32(reward->reward[done].variableXP); data << uint8(itemNum); if (itemNum) { - ItemTemplate const* iProto = NULL; for (uint8 i = 0; i < QUEST_REWARDS_COUNT; ++i) - { - if (!qRew->RewardItemId[i]) - continue; - - iProto = sObjectMgr->GetItemTemplate(qRew->RewardItemId[i]); - - data << uint32(qRew->RewardItemId[i]); - data << uint32(iProto ? iProto->DisplayInfoID : 0); - data << uint32(qRew->RewardItemIdCount[i]); - } + if (uint32 itemId = quest->RewardItemId[i]) + { + ItemTemplate const* item = sObjectMgr->GetItemTemplate(itemId); + data << uint32(itemId); + data << uint32(item ? item->DisplayInfoID : 0); + data << uint32(quest->RewardItemIdCount[i]); + } } SendPacket(&data); } -void WorldSession::SendLfgBootPlayer(const LfgPlayerBoot* pBoot) +void WorldSession::SendLfgBootProposalUpdate(const LfgPlayerBoot& boot) { uint64 guid = GetPlayer()->GetGUID(); - LfgAnswer playerVote = pBoot->votes.find(guid)->second; + LfgAnswer playerVote = boot.votes.find(guid)->second; uint8 votesNum = 0; uint8 agreeNum = 0; - uint32 secsleft = uint8((pBoot->cancelTime - time(NULL)) / 1000); - for (LfgAnswerMap::const_iterator it = pBoot->votes.begin(); it != pBoot->votes.end(); ++it) + uint32 secsleft = uint8((boot.cancelTime - time(NULL)) / 1000); + for (LfgAnswerMap::const_iterator it = boot.votes.begin(); it != boot.votes.end(); ++it) { if (it->second != LFG_ANSWER_PENDING) { @@ -536,34 +522,31 @@ void WorldSession::SendLfgBootPlayer(const LfgPlayerBoot* pBoot) } } sLog->outDebug(LOG_FILTER_NETWORKIO, "SMSG_LFG_BOOT_PROPOSAL_UPDATE [" UI64FMTD "] inProgress: %u - didVote: %u - agree: %u - victim: [" UI64FMTD "] votes: %u - agrees: %u - left: %u - needed: %u - reason %s", - guid, uint8(pBoot->inProgress), uint8(playerVote != LFG_ANSWER_PENDING), uint8(playerVote == LFG_ANSWER_AGREE), pBoot->victim, votesNum, agreeNum, secsleft, pBoot->votedNeeded, pBoot->reason.c_str()); - WorldPacket data(SMSG_LFG_BOOT_PROPOSAL_UPDATE, 1 + 1 + 1 + 8 + 4 + 4 + 4 + 4 + pBoot->reason.length()); - data << uint8(pBoot->inProgress); // Vote in progress + guid, uint8(boot.inProgress), uint8(playerVote != LFG_ANSWER_PENDING), uint8(playerVote == LFG_ANSWER_AGREE), boot.victim, votesNum, agreeNum, secsleft, boot.votedNeeded, boot.reason.c_str()); + WorldPacket data(SMSG_LFG_BOOT_PROPOSAL_UPDATE, 1 + 1 + 1 + 8 + 4 + 4 + 4 + 4 + boot.reason.length()); + data << uint8(boot.inProgress); // Vote in progress data << uint8(playerVote != LFG_ANSWER_PENDING); // Did Vote data << uint8(playerVote == LFG_ANSWER_AGREE); // Agree - data << uint64(pBoot->victim); // Victim GUID + data << uint64(boot.victim); // Victim GUID data << uint32(votesNum); // Total Votes data << uint32(agreeNum); // Agree Count data << uint32(secsleft); // Time Left - data << uint32(pBoot->votedNeeded); // Needed Votes - data << pBoot->reason.c_str(); // Kick reason + data << uint32(boot.votedNeeded); // Needed Votes + data << boot.reason.c_str(); // Kick reason SendPacket(&data); } -void WorldSession::SendLfgUpdateProposal(uint32 proposalId, const LfgProposal* pProp) +void WorldSession::SendLfgUpdateProposal(uint32 proposalId, const LfgProposal& proposal) { - if (!pProp) - return; - uint64 guid = GetPlayer()->GetGUID(); - LfgProposalPlayerMap::const_iterator itPlayer = pProp->players.find(guid); - if (itPlayer == pProp->players.end()) // Player MUST be in the proposal + LfgProposalPlayerMap::const_iterator itPlayer = proposal.players.find(guid); + if (itPlayer == proposal.players.end()) // Player MUST be in the proposal return; LfgProposalPlayer* ppPlayer = itPlayer->second; uint32 pLowGroupGuid = ppPlayer->groupLowGuid; - uint32 dLowGuid = pProp->groupLowGuid; - uint32 dungeonId = pProp->dungeonId; + uint32 dLowGuid = proposal.groupLowGuid; + uint32 dungeonId = proposal.dungeonId; bool isSameDungeon = false; bool isContinue = false; Group* grp = dLowGuid ? sGroupMgr->GetGroupByGUID(dLowGuid) : NULL; @@ -575,8 +558,8 @@ void WorldSession::SendLfgUpdateProposal(uint32 proposalId, const LfgProposal* p isSameDungeon = GetPlayer()->GetGroup() == grp && isContinue; } - sLog->outDebug(LOG_FILTER_NETWORKIO, "SMSG_LFG_PROPOSAL_UPDATE [" UI64FMTD "] state: %u", GetPlayer()->GetGUID(), pProp->state); - WorldPacket data(SMSG_LFG_PROPOSAL_UPDATE, 4 + 1 + 4 + 4 + 1 + 1 + pProp->players.size() * (4 + 1 + 1 + 1 + 1 +1)); + sLog->outDebug(LOG_FILTER_NETWORKIO, "SMSG_LFG_PROPOSAL_UPDATE [" UI64FMTD "] state: %u", GetPlayer()->GetGUID(), proposal.state); + WorldPacket data(SMSG_LFG_PROPOSAL_UPDATE, 4 + 1 + 4 + 4 + 1 + 1 + proposal.players.size() * (4 + 1 + 1 + 1 + 1 +1)); if (!isContinue) // Only show proposal dungeon if it's continue { @@ -585,7 +568,7 @@ void WorldSession::SendLfgUpdateProposal(uint32 proposalId, const LfgProposal* p dungeonId = (*playerDungeons.begin()); } - if (LFGDungeonEntry const* dungeon = sLFGDungeonStore.LookupEntry(dungeonId)) + if (LFGDungeonEntry const* dungeon = sLFGMgr->GetLFGDungeon(dungeonId)) { dungeonId = dungeon->Entry(); @@ -606,13 +589,13 @@ void WorldSession::SendLfgUpdateProposal(uint32 proposalId, const LfgProposal* p } data << uint32(dungeonId); // Dungeon - data << uint8(pProp->state); // Result state + data << uint8(proposal.state); // Result state data << uint32(proposalId); // Internal Proposal ID data << uint32(completedEncounters); // Bosses killed data << uint8(isSameDungeon); // Silent (show client window) - data << uint8(pProp->players.size()); // Group size + data << uint8(proposal.players.size()); // Group size - for (itPlayer = pProp->players.begin(); itPlayer != pProp->players.end(); ++itPlayer) + for (itPlayer = proposal.players.begin(); itPlayer != proposal.players.end(); ++itPlayer) { ppPlayer = itPlayer->second; data << uint32(ppPlayer->role); // Role @@ -633,9 +616,9 @@ void WorldSession::SendLfgUpdateProposal(uint32 proposalId, const LfgProposal* p SendPacket(&data); } -void WorldSession::SendLfgUpdateSearch(bool update) +void WorldSession::SendLfgLfrList(bool update) { - sLog->outDebug(LOG_FILTER_NETWORKIO, "SMSG_LFG_UPDATE_SEARCH [" UI64FMTD "] update: %u", GetPlayer()->GetGUID(), update ? 1 : 0); + sLog->outDebug(LOG_FILTER_NETWORKIO, "SMSG_LFG_LFR_LIST [" UI64FMTD "] update: %u", GetPlayer()->GetGUID(), update ? 1 : 0); WorldPacket data(SMSG_LFG_UPDATE_SEARCH, 1); data << uint8(update); // In Lfg Queue? SendPacket(&data); @@ -667,8 +650,8 @@ void WorldSession::SendLfgTeleportError(uint8 err) /* void WorldSession::SendLfrUpdateListOpcode(uint32 dungeonEntry) { - sLog->outDebug(LOG_FILTER_PACKETIO, "SMSG_UPDATE_LFG_LIST [" UI64FMTD "] dungeon entry: %u", GetPlayer()->GetGUID(), dungeonEntry); - WorldPacket data(SMSG_UPDATE_LFG_LIST); + sLog->outDebug(LOG_FILTER_PACKETIO, "SMSG_LFG_UPDATE_LIST [" UI64FMTD "] dungeon entry: %u", GetPlayer()->GetGUID(), dungeonEntry); + WorldPacket data(SMSG_LFG_UPDATE_LIST); SendPacket(&data); } */ diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index bc524c720f7..c3c6befe2f9 100755 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -2468,8 +2468,8 @@ bool InstanceMap::AddPlayerToMap(Player* player) if (group && group->isLFGGroup()) if (uint32 dungeonId = sLFGMgr->GetDungeon(group->GetGUID(), true)) - if (LFGDungeonEntry const* dungeon = sLFGDungeonStore.LookupEntry(dungeonId)) - if (LFGDungeonEntry const* randomDungeon = sLFGDungeonStore.LookupEntry(*(sLFGMgr->GetSelectedDungeons(player->GetGUID()).begin()))) + if (LFGDungeonEntry const* dungeon = sLFGMgr->GetLFGDungeon(dungeonId)) + if (LFGDungeonEntry const* randomDungeon = sLFGMgr->GetLFGDungeon(*(sLFGMgr->GetSelectedDungeons(player->GetGUID()).begin()))) if (uint32(dungeon->map) == GetId() && dungeon->difficulty == uint32(GetDifficulty()) && randomDungeon->type == uint32(LFG_TYPE_RANDOM)) player->CastSpell(player, LFG_SPELL_LUCK_OF_THE_DRAW, true); } diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp index a229d3ed536..af2ff2c6d86 100755 --- a/src/server/game/Server/Protocol/Opcodes.cpp +++ b/src/server/game/Server/Protocol/Opcodes.cpp @@ -888,7 +888,7 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] = /*0x35B*/ { "SMSG_ARENA_TEAM_STATS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide }, /*0x35C*/ { "CMSG_LFG_JOIN", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgJoinOpcode }, /*0x35D*/ { "CMSG_LFG_LEAVE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgLeaveOpcode }, - /*0x35E*/ { "CMSG_SEARCH_LFG_JOIN", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLfrSearchOpcode }, + /*0x35E*/ { "CMSG_SEARCH_LFG_JOIN", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLfrJoinOpcode }, /*0x35F*/ { "CMSG_SEARCH_LFG_LEAVE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLfrLeaveOpcode }, /*0x360*/ { "SMSG_UPDATE_LFG_LIST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide }, /*0x361*/ { "SMSG_LFG_PROPOSAL_UPDATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide }, diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index bc9e6ac4298..3ff45bff3b1 100755 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -54,6 +54,7 @@ struct LfgJoinResultData; struct LfgLockStatus; struct LfgPlayerBoot; struct LfgProposal; +struct LfgQueueStatusData; struct LfgReward; struct LfgRoleCheck; struct LfgUpdateData; @@ -815,19 +816,19 @@ class WorldSession void HandleLfgProposalResultOpcode(WorldPacket& recv_data); void HandleLfgSetBootVoteOpcode(WorldPacket& recv_data); void HandleLfgTeleportOpcode(WorldPacket& recv_data); - void HandleLfrSearchOpcode(WorldPacket& recv_data); + void HandleLfrJoinOpcode(WorldPacket& recv_data); void HandleLfrLeaveOpcode(WorldPacket& recv_data); void SendLfgUpdatePlayer(const LfgUpdateData& updateData); void SendLfgUpdateParty(const LfgUpdateData& updateData); void SendLfgRoleChosen(uint64 guid, uint8 roles); - void SendLfgRoleCheckUpdate(const LfgRoleCheck* pRoleCheck); - void SendLfgUpdateSearch(bool update); + void SendLfgRoleCheckUpdate(const LfgRoleCheck& pRoleCheck); + void SendLfgLfrList(bool update); void SendLfgJoinResult(const LfgJoinResultData& joinData); - void SendLfgQueueStatus(uint32 dungeon, int32 waitTime, int32 avgWaitTime, int32 waitTimeTanks, int32 waitTimeHealer, int32 waitTimeDps, uint32 queuedTime, uint8 tanks, uint8 healers, uint8 dps); + void SendLfgQueueStatus(const LfgQueueStatusData& queueData); void SendLfgPlayerReward(uint32 rdungeonEntry, uint32 sdungeonEntry, uint8 done, const LfgReward* reward, const Quest *qRew); - void SendLfgBootPlayer(const LfgPlayerBoot* pBoot); - void SendLfgUpdateProposal(uint32 proposalId, const LfgProposal *pProp); + void SendLfgBootProposalUpdate(const LfgPlayerBoot& boot); + void SendLfgUpdateProposal(uint32 proposalId, const LfgProposal& proposal); void SendLfgDisabled(); void SendLfgOfferContinue(uint32 dungeonEntry); void SendLfgTeleportError(uint8 err); diff --git a/src/server/game/Spells/SpellScript.h b/src/server/game/Spells/SpellScript.h index c8126f8aaf3..b1a2097a8f9 100755 --- a/src/server/game/Spells/SpellScript.h +++ b/src/server/game/Spells/SpellScript.h @@ -586,7 +586,7 @@ class AuraScript : public _SpellScript uint8 _currentScriptState; bool _defaultActionPrevented; ScriptStateStore(uint8 currentScriptState, AuraApplication const* auraApplication, bool defaultActionPrevented) - : _currentScriptState(currentScriptState), _auraApplication(auraApplication), _defaultActionPrevented(defaultActionPrevented) + : _auraApplication(auraApplication), _currentScriptState(currentScriptState), _defaultActionPrevented(defaultActionPrevented) {} }; typedef std::stack ScriptStateStack; diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 06e8d3eccbe..35f991cd368 100755 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -1461,14 +1461,15 @@ void World::SetInitialWorldSettings() sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading Vehicle Accessories..."); sObjectMgr->LoadVehicleAccessories(); // must be after LoadCreatureTemplates() and LoadNPCSpellClickSpells() + sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading LFG entrance positions..."); + sLFGMgr->LoadLFGDungeons(); + sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading Dungeon boss data..."); sObjectMgr->LoadInstanceEncounters(); sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading LFG rewards..."); sLFGMgr->LoadRewards(); - sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading LFG entrance positions..."); - sLFGMgr->LoadEntrancePositions(); sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading SpellArea Data..."); // must be after quest load sSpellMgr->LoadSpellAreas(); diff --git a/src/server/scripts/Northrend/Nexus/Oculus/oculus.cpp b/src/server/scripts/Northrend/Nexus/Oculus/oculus.cpp index 39fff139b52..28595571a2f 100644 --- a/src/server/scripts/Northrend/Nexus/Oculus/oculus.cpp +++ b/src/server/scripts/Northrend/Nexus/Oculus/oculus.cpp @@ -232,7 +232,7 @@ public: { npc_verdisa_beglaristrasz_eternosAI(Creature* creature) : ScriptedAI(creature) { } - void MovementInform(uint32 type, uint32 id) + void MovementInform(uint32 /*type*/, uint32 id) { // When Belgaristraz finish his moving say grateful text if (me->GetEntry() == NPC_BELGARISTRASZ) diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp index 5cc31ad54e8..547cb3dba51 100644 --- a/src/server/scripts/Spells/spell_generic.cpp +++ b/src/server/scripts/Spells/spell_generic.cpp @@ -1581,12 +1581,12 @@ class spell_gen_luck_of_the_draw : public SpellScriptLoader } - LFGDungeonEntry const* randomDungeon = sLFGDungeonStore.LookupEntry(*itr); + LFGDungeonEntry const* randomDungeon = sLFGMgr->GetLFGDungeon(*itr); if (Group* group = owner->GetGroup()) if (Map const* map = owner->GetMap()) if (group->isLFGGroup()) if (uint32 dungeonId = sLFGMgr->GetDungeon(group->GetGUID(), true)) - if (LFGDungeonEntry const* dungeon = sLFGDungeonStore.LookupEntry(dungeonId)) + if (LFGDungeonEntry const* dungeon = sLFGMgr->GetLFGDungeon(dungeonId)) if (uint32(dungeon->map) == map->GetId() && dungeon->difficulty == uint32(map->GetDifficulty())) if (randomDungeon && randomDungeon->type == LFG_TYPE_RANDOM) return; // in correct dungeon diff --git a/src/server/scripts/World/npcs_special.cpp b/src/server/scripts/World/npcs_special.cpp index b8df77d0346..b291b9751b4 100644 --- a/src/server/scripts/World/npcs_special.cpp +++ b/src/server/scripts/World/npcs_special.cpp @@ -2115,7 +2115,7 @@ class npc_shadowfiend : public CreatureScript { npc_shadowfiendAI(Creature* creature) : PetAI(creature) {} - void JustDied(Unit* killer) + void JustDied(Unit* /*killer*/) { if (me->isSummon()) if (Unit* owner = me->ToTempSummon()->GetSummoner()) -- cgit v1.2.3 From 479d34d2a0e54c13160d8f52c37dbf691d14d933 Mon Sep 17 00:00:00 2001 From: Spp Date: Thu, 18 Oct 2012 14:31:28 +0200 Subject: Core/Dungeon Finder: Minor optimizations - Internal changes in store types - Remove of (Player *) and (Group *) From LFGMgr.cpp (step 2) --- .../world/2012_10_18_00_world_trinity_string.sql | 16 + src/server/game/DungeonFinding/LFG.h | 13 +- src/server/game/DungeonFinding/LFGGroupData.cpp | 42 +- src/server/game/DungeonFinding/LFGGroupData.h | 14 + src/server/game/DungeonFinding/LFGMgr.cpp | 700 +++++++++++---------- src/server/game/DungeonFinding/LFGMgr.h | 90 +-- src/server/game/DungeonFinding/LFGPlayerData.cpp | 38 +- src/server/game/DungeonFinding/LFGPlayerData.h | 22 +- src/server/game/DungeonFinding/LFGScripts.cpp | 92 +-- src/server/game/Handlers/LFGHandler.cpp | 103 ++- src/server/game/Miscellaneous/Language.h | 17 +- 11 files changed, 644 insertions(+), 503 deletions(-) create mode 100644 sql/updates/world/2012_10_18_00_world_trinity_string.sql (limited to 'src') diff --git a/sql/updates/world/2012_10_18_00_world_trinity_string.sql b/sql/updates/world/2012_10_18_00_world_trinity_string.sql new file mode 100644 index 00000000000..8d62174d868 --- /dev/null +++ b/sql/updates/world/2012_10_18_00_world_trinity_string.sql @@ -0,0 +1,16 @@ +REPLACE INTO `trinity_string` (`entry`, `content_default`, `content_loc1`, `content_loc2`, `content_loc3`, `content_loc4`, `content_loc5`, `content_loc6`, `content_loc7`, `content_loc8`) +VALUES + (11015, 'Error', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), + (11014, 'None', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), + (11013, 'Leader', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), + (11012, 'Dps', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), + (11011, 'Healer', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), + (11010, 'Tank', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), + (11009, 'Raid browser', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), + (11008, 'Finished dungeon', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), + (11007, 'In dungeon', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), + (11006, 'Vote kick', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), + (11005, 'Proposal', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), + (11004, 'Queued', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), + (11003, 'Role check', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), + (11002, 'None', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); diff --git a/src/server/game/DungeonFinding/LFG.h b/src/server/game/DungeonFinding/LFG.h index c00cc830ce8..abdb0ffa511 100755 --- a/src/server/game/DungeonFinding/LFG.h +++ b/src/server/game/DungeonFinding/LFG.h @@ -39,7 +39,7 @@ enum LfgRoles enum LfgUpdateType { LFG_UPDATETYPE_DEFAULT = 0, // Internal Use - LFG_UPDATETYPE_LEADER = 1, + LFG_UPDATETYPE_LEADER_UNK1 = 1, // FIXME: At group leave LFG_UPDATETYPE_ROLECHECK_ABORTED = 4, LFG_UPDATETYPE_JOIN_PROPOSAL = 5, LFG_UPDATETYPE_ROLECHECK_FAILED = 6, @@ -51,7 +51,7 @@ enum LfgUpdateType LFG_UPDATETYPE_PROPOSAL_BEGIN = 13, LFG_UPDATETYPE_CLEAR_LOCK_LIST = 14, LFG_UPDATETYPE_GROUP_MEMBER_OFFLINE = 15, - LFG_UPDATETYPE_GROUP_DISBAND = 16 + LFG_UPDATETYPE_GROUP_DISBAND_UNK16 = 16, // FIXME: Sometimes at group disband }; enum LfgState @@ -69,7 +69,6 @@ enum LfgState /// Instance lock types enum LfgLockStatusType { - LFG_LOCKSTATUS_OK = 0, // Internal use only LFG_LOCKSTATUS_INSUFFICIENT_EXPANSION = 1, LFG_LOCKSTATUS_TOO_LOW_LEVEL = 2, LFG_LOCKSTATUS_TOO_HIGH_LEVEL = 3, @@ -92,18 +91,12 @@ enum LfgAnswer LFG_ANSWER_AGREE = 1 }; -/// Dungeon and reason why player can't join -struct LfgLockStatus -{ - uint32 dungeon; ///< Dungeon Id - LfgLockStatusType lockstatus; ///< Lock type -}; - typedef std::set LfgDungeonSet; typedef std::map LfgLockMap; typedef std::map LfgLockPartyMap; typedef std::set LfgGuidSet; typedef std::list LfgGuidList; typedef std::map LfgRolesMap; +typedef std::map LfgGroupsMap; #endif diff --git a/src/server/game/DungeonFinding/LFGGroupData.cpp b/src/server/game/DungeonFinding/LFGGroupData.cpp index cbcb1d130bb..712ae5132b0 100644 --- a/src/server/game/DungeonFinding/LFGGroupData.cpp +++ b/src/server/game/DungeonFinding/LFGGroupData.cpp @@ -19,7 +19,7 @@ #include "LFGGroupData.h" LfgGroupData::LfgGroupData(): m_State(LFG_STATE_NONE), m_OldState(LFG_STATE_NONE), - m_Dungeon(0), m_KicksLeft(LFG_GROUP_MAX_KICKS) + m_Leader(0), m_Dungeon(0), m_KicksLeft(LFG_GROUP_MAX_KICKS) { } LfgGroupData::~LfgGroupData() @@ -34,9 +34,9 @@ void LfgGroupData::SetState(LfgState state) { switch (state) { + case LFG_STATE_FINISHED_DUNGEON: case LFG_STATE_NONE: case LFG_STATE_DUNGEON: - case LFG_STATE_FINISHED_DUNGEON: m_OldState = state; // No break on purpose default: @@ -49,6 +49,29 @@ void LfgGroupData::RestoreState() m_State = m_OldState; } +void LfgGroupData::AddPlayer(uint64 guid) +{ + m_Players.insert(guid); +} + +uint8 LfgGroupData::RemovePlayer(uint64 guid) +{ + LfgGuidSet::iterator it = m_Players.find(guid); + if (it != m_Players.end()) + m_Players.erase(it); + return uint8(m_Players.size()); +} + +void LfgGroupData::RemoveAllPlayers() +{ + m_Players.clear(); +} + +void LfgGroupData::SetLeader(uint64 guid) +{ + m_Leader = guid; +} + void LfgGroupData::SetDungeon(uint32 dungeon) { m_Dungeon = dungeon; @@ -65,6 +88,21 @@ LfgState LfgGroupData::GetState() const return m_State; } +LfgState LfgGroupData::GetOldState() const +{ + return m_OldState; +} + +const LfgGuidSet &LfgGroupData::GetPlayers() const +{ + return m_Players; +} + +uint64 LfgGroupData::GetLeader() const +{ + return m_Leader; +} + uint32 LfgGroupData::GetDungeon(bool asId /* = true */) const { if (asId) diff --git a/src/server/game/DungeonFinding/LFGGroupData.h b/src/server/game/DungeonFinding/LFGGroupData.h index 359f7be7eee..43cd64f97c3 100644 --- a/src/server/game/DungeonFinding/LFGGroupData.h +++ b/src/server/game/DungeonFinding/LFGGroupData.h @@ -35,18 +35,30 @@ class LfgGroupData ~LfgGroupData(); bool IsLfgGroup(); + // General void SetState(LfgState state); void RestoreState(); + void AddPlayer(uint64 guid); + uint8 RemovePlayer(uint64 guid); + void RemoveAllPlayers(); + void SetLeader(uint64 guid); + // Dungeon void SetDungeon(uint32 dungeon); + // VoteKick void DecreaseKicksLeft(); // General LfgState GetState() const; + LfgState GetOldState() const; + LfgGuidSet const& GetPlayers() const; + uint64 GetLeader() const; + // Dungeon uint32 GetDungeon(bool asId = true) const; + // VoteKick uint8 GetKicksLeft() const; @@ -54,6 +66,8 @@ class LfgGroupData // General LfgState m_State; ///< State if group in LFG LfgState m_OldState; ///< Old State + uint64 m_Leader; ///< Leader GUID + LfgGuidSet m_Players; ///< Players in group // Dungeon uint32 m_Dungeon; ///< Dungeon entry // Vote Kick diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp index 1b4a2fcdda3..af12ce93c65 100755 --- a/src/server/game/DungeonFinding/LFGMgr.cpp +++ b/src/server/game/DungeonFinding/LFGMgr.cpp @@ -34,8 +34,6 @@ LFGMgr::LFGMgr(): m_QueueTimer(0), m_lfgProposalId(1), m_options(sWorld->getBoolConfig(CONFIG_DUNGEON_FINDER_ENABLE)), - m_WaitTimeAvg(-1), m_WaitTimeTank(-1), m_WaitTimeHealer(-1), m_WaitTimeDps(-1), - m_NumWaitTimeAvg(0), m_NumWaitTimeTank(0), m_NumWaitTimeHealer(0), m_NumWaitTimeDps(0), m_lfgPlayerScript(new LFGPlayerScript()), m_lfgGroupScript(new LFGGroupScript()) { } @@ -121,64 +119,67 @@ std::string LFGMgr::GetRolesString(uint8 roles) std::string rolesstr = ""; if (roles & PLAYER_ROLE_TANK) - rolesstr.append("Tank"); + rolesstr.append(sObjectMgr->GetTrinityStringForDBCLocale(LANG_LFG_ROLE_TANK)); if (roles & PLAYER_ROLE_HEALER) { if (!rolesstr.empty()) rolesstr.append(", "); - rolesstr.append("Healer"); + rolesstr.append(sObjectMgr->GetTrinityStringForDBCLocale(LANG_LFG_ROLE_HEALER)); } if (roles & PLAYER_ROLE_DAMAGE) { if (!rolesstr.empty()) rolesstr.append(", "); - rolesstr.append("Dps"); + rolesstr.append(sObjectMgr->GetTrinityStringForDBCLocale(LANG_LFG_ROLE_DAMAGE)); } if (roles & PLAYER_ROLE_LEADER) { if (!rolesstr.empty()) rolesstr.append(", "); - rolesstr.append("Leader"); + rolesstr.append(sObjectMgr->GetTrinityStringForDBCLocale(LANG_LFG_ROLE_LEADER)); } if (rolesstr.empty()) - rolesstr.append("None"); + rolesstr.append(sObjectMgr->GetTrinityStringForDBCLocale(LANG_LFG_ROLE_NONE)); return rolesstr; } char const * LFGMgr::GetStateString(LfgState state) { + int32 entry = LANG_LFG_ERROR; switch (state) { case LFG_STATE_NONE: - return "None"; + entry = LANG_LFG_STATE_NONE; break; case LFG_STATE_ROLECHECK: - return "Rolecheck"; + entry = LANG_LFG_STATE_ROLECHECK; break; case LFG_STATE_QUEUED: - return "Queued"; + entry = LANG_LFG_STATE_QUEUED; break; case LFG_STATE_PROPOSAL: - return "Proposal"; + entry = LANG_LFG_STATE_PROPOSAL; break; case LFG_STATE_DUNGEON: - return "In Dungeon"; + entry = LANG_LFG_STATE_DUNGEON; break; case LFG_STATE_BOOT: - return "Boot Player"; + entry = LANG_LFG_STATE_BOOT; break; case LFG_STATE_FINISHED_DUNGEON: - return "Finished"; + entry = LANG_LFG_STATE_FINISHED_DUNGEON; break; case LFG_STATE_RAIDBROWSER: - return "RaidBrowser"; + entry = LANG_LFG_STATE_RAIDBROWSER; + break; } - return "Error"; + char const * const str = sObjectMgr->GetTrinityStringForDBCLocale(entry); + return str; } /// Load rewards for completing dungeons @@ -488,20 +489,22 @@ void LFGMgr::Update(uint32 diff) waitTime = -1; break; case PLAYER_ROLE_TANK: - waitTime = m_WaitTimeTank; + waitTime = m_waitTimesTank.time; break; case PLAYER_ROLE_HEALER: - waitTime = m_WaitTimeHealer; + waitTime = m_waitTimesHealer.time; break; case PLAYER_ROLE_DAMAGE: - waitTime = m_WaitTimeDps; + waitTime = m_waitTimesDps.time; break; default: - waitTime = m_WaitTimeAvg; + waitTime = m_waitTimesAvg.time; break; } - LfgQueueStatusData queueData(dungeonId, waitTime, m_WaitTimeAvg, m_WaitTimeTank, m_WaitTimeHealer, m_WaitTimeDps, queuedTime, queue->tanks, queue->healers, queue->dps); + LfgQueueStatusData queueData(dungeonId, waitTime, m_waitTimesAvg.time, m_waitTimesTank.time, + m_waitTimesHealer.time, m_waitTimesDps.time, queuedTime, + queue->tanks, queue->healers, queue->dps); for (LfgRolesMap::const_iterator itPlayer = queue->roles.begin(); itPlayer != queue->roles.end(); ++itPlayer) SendLfgQueueStatus(itPlayer->first, queueData); } @@ -648,7 +651,7 @@ void LFGMgr::JoinLfg(Player* player, uint8 roles, LfgDungeonSet& dungeons, const uint64 guid = player->GetGUID(); uint64 gguid = grp ? grp->GetGUID() : guid; LfgJoinResultData joinData; - PlayerSet players; + LfgGuidSet players; uint32 rDungeonId = 0; bool isContinue = grp && grp->isLFGGroup() && GetState(gguid) != LFG_STATE_FINISHED_DUNGEON; @@ -707,15 +710,16 @@ void LFGMgr::JoinLfg(Player* player, uint8 roles, LfgDungeonSet& dungeons, const else if (plrg->InBattleground() || plrg->InArena() || plrg->InBattlegroundQueue()) joinData.result = LFG_JOIN_USING_BG_SYSTEM; ++memberCount; - players.insert(plrg); + players.insert(plrg->GetGUID()); } } - if (memberCount != grp->GetMembersCount()) + + if (joinData.result == LFG_JOIN_OK && memberCount != grp->GetMembersCount()) joinData.result = LFG_JOIN_DISCONNECTED; } } else - players.insert(player); + players.insert(player->GetGUID()); // Check if all dungeons are valid bool isRaid = false; @@ -865,57 +869,52 @@ void LFGMgr::JoinLfg(Player* player, uint8 roles, LfgDungeonSet& dungeons, const Leaves Dungeon System. Player/Group is removed from queue, rolechecks, proposals or votekicks. Player or group needs to be not NULL and using Dungeon System - @param[in] player Player trying to leave (can be NULL) - @param[in] grp Group trying to leave (default NULL) + @param[in] guid Player or group guid */ -void LFGMgr::LeaveLfg(Player* player, Group* grp /* = NULL*/) +void LFGMgr::LeaveLfg(uint64 guid) { - if (!player && !grp) - return; - - uint64 guid = grp ? grp->GetGUID() : player->GetGUID(); LfgState state = GetState(guid); + uint64 gguid = IS_GROUP(guid) ? guid : GetGroup(guid); sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::Leave: [" UI64FMTD "]", guid); switch (state) { case LFG_STATE_QUEUED: + if (gguid) { - RemoveFromQueue(guid); - LfgUpdateData updateData = LfgUpdateData(LFG_UPDATETYPE_REMOVED_FROM_QUEUE); - if (grp) + RemoveFromQueue(gguid); + RestoreState(gguid, "Leave queue"); + const LfgGuidSet& players = GetPlayers(gguid); + for (LfgGuidSet::const_iterator it = players.begin(); it != players.end(); ++it) { - RestoreState(guid, "Leave queue"); - for (GroupReference* itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) - if (Player* plrg = itr->getSource()) - { - plrg->GetSession()->SendLfgUpdateParty(updateData); - uint64 pguid = plrg->GetGUID(); - ClearState(pguid, "Leave queue"); - } - } - else - { - player->GetSession()->SendLfgUpdatePlayer(updateData); + uint64 guid = (*it); ClearState(guid, "Leave queue"); + SendLfgUpdateParty(guid, LfgUpdateData(LFG_UPDATETYPE_REMOVED_FROM_QUEUE)); } } + else + { + RemoveFromQueue(guid); + SendLfgUpdatePlayer(guid, LfgUpdateData(LFG_UPDATETYPE_REMOVED_FROM_QUEUE)); + ClearState(guid, "Leave queue"); + } break; case LFG_STATE_ROLECHECK: - if (grp) - UpdateRoleCheck(guid); // No player to update role = LFG_ROLECHECK_ABORTED + if (gguid) + UpdateRoleCheck(gguid); // No player to update role = LFG_ROLECHECK_ABORTED break; case LFG_STATE_PROPOSAL: { // Remove from Proposals LfgProposalMap::iterator it = m_Proposals.begin(); + uint64 pguid = gguid == guid ? GetLeader(gguid) : guid; while (it != m_Proposals.end()) { - LfgProposalPlayerMap::iterator itPlayer = it->second->players.find(player ? player->GetGUID() : grp->GetLeaderGUID()); + LfgProposalPlayerMap::iterator itPlayer = it->second->players.find(pguid); if (itPlayer != it->second->players.end()) { // Mark the player/leader of group who left as didn't accept the proposal - itPlayer->second->accept = LFG_ANSWER_DENY; + itPlayer->second.accept = LFG_ANSWER_DENY; break; } ++it; @@ -931,21 +930,6 @@ void LFGMgr::LeaveLfg(Player* player, Group* grp /* = NULL*/) } } -/** - Sends the leader of a group the offer to continue popup - - @param[in] grp Group to send offer to -*/ -void LFGMgr::OfferContinue(Group* grp) -{ - if (grp) - { - uint64 gguid = grp->GetGUID(); - if (Player* leader = ObjectAccessor::FindPlayer(grp->GetLeaderGUID())) - leader->GetSession()->SendLfgOfferContinue(GetDungeon(gguid, false)); - } -} - /** Checks que main queue to try to form a Lfg group. Returns first match found (if any) @@ -1022,7 +1006,7 @@ bool LFGMgr::CheckCompatibility(LfgGuidList check, LfgProposal*& pProposal) uint8 numPlayers = 0; uint8 numLfgGroups = 0; - uint32 groupLowGuid = 0; + uint64 groupGuid = 0; LfgQueueInfoMap pqInfoMap; for (LfgGuidList::const_iterator it = check.begin(); it != check.end() && numLfgGroups < 2 && numPlayers <= MAXGROUPSIZE; ++it) { @@ -1039,12 +1023,11 @@ bool LFGMgr::CheckCompatibility(LfgGuidList check, LfgProposal*& pProposal) if (IS_GROUP(guid)) { - uint32 lowGuid = GUID_LOPART(guid); - if (Group* grp = sGroupMgr->GetGroupByGUID(lowGuid)) + if (Group* grp = sGroupMgr->GetGroupByGUID(GUID_LOPART(guid))) if (grp->isLFGGroup()) { if (!numLfgGroups) - groupLowGuid = lowGuid; + groupGuid = guid; ++numLfgGroups; } } @@ -1082,25 +1065,16 @@ bool LFGMgr::CheckCompatibility(LfgGuidList check, LfgProposal*& pProposal) if (rolesMap.size() != numPlayers) // Player in multiples queues! return false; - PlayerSet players; + LfgGuidSet players; for (LfgRolesMap::const_iterator it = rolesMap.begin(); it != rolesMap.end(); ++it) { - Player* player = ObjectAccessor::FindPlayer(it->first); - if (!player) - sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::CheckCompatibility: (%s) Warning! [" UI64FMTD "] offline! Marking as not compatibles!", strGuids.c_str(), it->first); - else - { - for (PlayerSet::const_iterator itPlayer = players.begin(); itPlayer != players.end() && player; ++itPlayer) - { - if (HasIgnore((*itPlayer)->GetGUID(), player->GetGUID())) - { - sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::CheckCompatibility: (%s) Players [" UI64FMTD "] and [" UI64FMTD "] ignoring", strGuids.c_str(), (*itPlayer)->GetGUID(), player->GetGUID()); - player = NULL; - } - } - if (player) - players.insert(player); - } + uint64 guid = it->first; + LfgRolesMap::const_iterator it2 = ++it; + for (; it2 != rolesMap.end(); ++it2) + if (HasIgnore(guid, it2->first)) + break; + if (it2 == rolesMap.end()) + players.insert(guid); } // if we dont have the same ammount of players then we have self ignoring candidates or different faction groups @@ -1159,17 +1133,15 @@ bool LFGMgr::CheckCompatibility(LfgGuidList check, LfgProposal*& pProposal) --Dps_Needed; } } - for (PlayerSet::const_iterator itPlayers = players.begin(); itPlayers != players.end(); ++itPlayers) + + for (LfgGuidSet::const_iterator itPlayers = players.begin(); itPlayers != players.end(); ++itPlayers) { for (LfgQueueInfoMap::const_iterator itQueue = pqInfoMap.begin(); itQueue != pqInfoMap.end(); ++itQueue) { - LfgQueueInfo* queue = itQueue->second; - if (!queue) - continue; - - for (LfgRolesMap::const_iterator itPlayer = queue->roles.begin(); itPlayer != queue->roles.end(); ++itPlayer) + if (LfgQueueInfo* queue = itQueue->second) { - if (*itPlayers == ObjectAccessor::FindPlayer(itPlayer->first)) + LfgRolesMap::const_iterator itPlayer = queue->roles.find(*itPlayers); + if (itPlayer != queue->roles.end()) { queue->tanks = Tanks_Needed; queue->healers = Healers_Needed; @@ -1178,6 +1150,7 @@ bool LFGMgr::CheckCompatibility(LfgGuidList check, LfgProposal*& pProposal) } } } + return true; } sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::CheckCompatibility: (%s) MATCH! Group formed", strGuids.c_str()); @@ -1193,36 +1166,37 @@ bool LFGMgr::CheckCompatibility(LfgGuidList check, LfgProposal*& pProposal) pProposal->cancelTime = time_t(time(NULL)) + LFG_TIME_PROPOSAL; pProposal->state = LFG_PROPOSAL_INITIATING; pProposal->queues = check; - pProposal->groupLowGuid = groupLowGuid; + pProposal->group = groupGuid; + pProposal->isNew = true; // Assign new roles to players and assign new leader - PlayerSet::const_iterator itPlayers = players.begin(); + LfgGuidSet::const_iterator itPlayers = players.begin(); if (!leader) { uint8 pos = uint8(urand(0, players.size() - 1)); for (uint8 i = 0; i < pos; ++i) ++itPlayers; - leader = (*itPlayers)->GetGUID(); + leader = *itPlayers; } pProposal->leader = leader; uint8 numAccept = 0; for (itPlayers = players.begin(); itPlayers != players.end(); ++itPlayers) { - uint64 guid = (*itPlayers)->GetGUID(); - LfgProposalPlayer* ppPlayer = new LfgProposalPlayer(); - if (Group* grp = (*itPlayers)->GetGroup()) + uint64 guid = *itPlayers; + LfgProposalPlayer& player = pProposal->players[guid]; + uint64 gguid = GetGroup(guid); + player.group = gguid; + if (gguid == groupGuid) { - ppPlayer->groupLowGuid = grp->GetLowGUID(); - if (grp->isLFGGroup()) // Player from existing group, autoaccept - { - ppPlayer->accept = LFG_ANSWER_AGREE; - ++numAccept; - } + player.accept = LFG_ANSWER_AGREE; + ++numAccept; } - ppPlayer->role = rolesMap[guid]; - pProposal->players[guid] = ppPlayer; + player.role = rolesMap[guid]; + if (pProposal->group && pProposal->group != gguid) + pProposal->isNew = false; } + if (numAccept == MAXGROUPSIZE) pProposal->state = LFG_PROPOSAL_SUCCESS; @@ -1270,7 +1244,6 @@ void LFGMgr::UpdateRoleCheck(uint64 gguid, uint64 guid /* = 0 */, uint8 roles /* } } - uint8 team = 0; LfgDungeonSet dungeons; if (roleCheck.rDungeonId) dungeons.insert(roleCheck.rDungeonId); @@ -1291,7 +1264,6 @@ void LFGMgr::UpdateRoleCheck(uint64 gguid, uint64 guid /* = 0 */, uint8 roles /* continue; } - team = uint8(plrg->GetTeam()); if (!sendRoleChosen) SendLfgRoleChosen(pguid, guid, roles); @@ -1333,6 +1305,7 @@ void LFGMgr::UpdateRoleCheck(uint64 gguid, uint64 guid /* = 0 */, uint8 roles /* --pqInfo->dps; } + uint8 team = GetTeam(guid); m_QueueInfoMap[gguid] = pqInfo; if (GetState(gguid) != LFG_STATE_NONE) { @@ -1402,12 +1375,12 @@ LfgAnswer LFGMgr::GetCompatibles(std::string key) @param[in] players Set of players to check their dungeon restrictions @param[out] lockMap Map of players Lock status info of given dungeons (Empty if dungeons is not empty) */ -void LFGMgr::GetCompatibleDungeons(LfgDungeonSet& dungeons, const PlayerSet& players, LfgLockPartyMap& lockMap) +void LFGMgr::GetCompatibleDungeons(LfgDungeonSet& dungeons, const LfgGuidSet& players, LfgLockPartyMap& lockMap) { lockMap.clear(); - for (PlayerSet::const_iterator it = players.begin(); it != players.end() && !dungeons.empty(); ++it) + for (LfgGuidSet::const_iterator it = players.begin(); it != players.end() && !dungeons.empty(); ++it) { - uint64 guid = (*it)->GetGUID(); + uint64 guid = (*it); LfgLockMap const& cachedLockMap = GetLockedDungeons(guid); for (LfgLockMap::const_iterator it2 = cachedLockMap.begin(); it2 != cachedLockMap.end() && !dungeons.empty(); ++it2) { @@ -1497,6 +1470,79 @@ bool LFGMgr::CheckGroupRoles(LfgRolesMap& groles, bool removeLeaderFlag /*= true return (tank + healer + damage) == uint8(groles.size()); } +/** + Makes a new group given a proposal + @param[in] proposal Proposal to get info from +*/ +void LFGMgr::MakeNewGroup(const LfgProposal& proposal) +{ + LfgGuidList players; + LfgGuidList playersToTeleport; + + for (LfgProposalPlayerMap::const_iterator it = proposal.players.begin(); it != proposal.players.end(); ++it) + { + uint64 guid = it->first; + if (guid == proposal.leader) + players.push_front(guid); + else + players.push_back(guid); + + if (GetGroup(guid) != proposal.group || GetState(proposal.group) == LFG_STATE_FINISHED_DUNGEON) + playersToTeleport.push_back(guid); + } + + // Set the dungeon difficulty + LFGDungeonEntry const* dungeon = GetLFGDungeon(proposal.dungeonId); + ASSERT(dungeon); + + Group* grp = proposal.group ? sGroupMgr->GetGroupByGUID(GUID_LOPART(proposal.group)) : NULL; + for (LfgGuidList::const_iterator it = players.begin(); it != players.end(); ++it) + { + uint64 pguid = (*it); + Player* player = ObjectAccessor::FindPlayer(pguid); + if (!player) + continue; + + Group* group = player->GetGroup(); + if (group && group != grp) + player->RemoveFromGroup(); + + if (!grp) + { + grp = new Group(); + grp->ConvertToLFG(); + grp->Create(player); + uint64 gguid = grp->GetGUID(); + SetState(gguid, LFG_STATE_PROPOSAL); + sGroupMgr->AddGroup(grp); + } + else if (group != grp) + grp->AddMember(player); + + grp->SetLfgRoles(pguid, proposal.players.find(pguid)->second.role); + SetState(pguid, LFG_STATE_DUNGEON); + + // Add the cooldown spell if queued for a random dungeon + if (dungeon->type == LFG_TYPE_RANDOM) + player->CastSpell(player, LFG_SPELL_DUNGEON_COOLDOWN, false); + } + + grp->SetDungeonDifficulty(Difficulty(dungeon->difficulty)); + uint64 gguid = grp->GetGUID(); + SetDungeon(gguid, dungeon->Entry()); + SetState(gguid, LFG_STATE_DUNGEON); + + _SaveToDB(gguid, grp->GetDbStoreId()); + + // Teleport Player + for (LfgGuidList::const_iterator it = playersToTeleport.begin(); it != playersToTeleport.end(); ++it) + if (Player* player = ObjectAccessor::FindPlayer(*it)) + TeleportPlayer(player, false); + + // Update group info + grp->SendUpdate(); +} + /** Update Proposal info with player answer @@ -1510,15 +1556,17 @@ void LFGMgr::UpdateProposal(uint32 proposalId, uint64 guid, bool accept) LfgProposalMap::iterator itProposal = m_Proposals.find(proposalId); if (itProposal == m_Proposals.end()) return; - LfgProposal* pProposal = itProposal->second; + + LfgProposal& proposal = *(itProposal->second); // Check if proposal have the current player - LfgProposalPlayerMap::iterator itProposalPlayer = pProposal->players.find(guid); - if (itProposalPlayer == pProposal->players.end()) + LfgProposalPlayerMap::iterator itProposalPlayer = proposal.players.find(guid); + if (itProposalPlayer == proposal.players.end()) return; - LfgProposalPlayer* ppPlayer = itProposalPlayer->second; - ppPlayer->accept = LfgAnswer(accept); + LfgProposalPlayer& player = itProposalPlayer->second; + player.accept = LfgAnswer(accept); + sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::UpdateProposal: Player [" UI64FMTD "] of proposal %u selected: %u", guid, proposalId, accept); if (!accept) { @@ -1526,157 +1574,77 @@ void LFGMgr::UpdateProposal(uint32 proposalId, uint64 guid, bool accept) return; } - LfgPlayerList players; - LfgPlayerList playersToTeleport; - // check if all have answered and reorder players (leader first) bool allAnswered = true; - for (LfgProposalPlayerMap::const_iterator itPlayers = pProposal->players.begin(); itPlayers != pProposal->players.end(); ++itPlayers) - { - if (Player* player = ObjectAccessor::FindPlayer(itPlayers->first)) - { - if (itPlayers->first == pProposal->leader) - players.push_front(player); - else - players.push_back(player); - - // Only teleport new players - Group* grp = player->GetGroup(); - uint64 gguid = grp ? grp->GetGUID() : 0; - if (!gguid || !grp->isLFGGroup() || GetState(gguid) == LFG_STATE_FINISHED_DUNGEON) - playersToTeleport.push_back(player); - } - - if (itPlayers->second->accept != LFG_ANSWER_AGREE) // No answer (-1) or not accepted (0) + for (LfgProposalPlayerMap::const_iterator itPlayers = proposal.players.begin(); itPlayers != proposal.players.end(); ++itPlayers) + if (itPlayers->second.accept != LFG_ANSWER_AGREE) // No answer (-1) or not accepted (0) allAnswered = false; - } if (!allAnswered) { - for (LfgPlayerList::const_iterator it = players.begin(); it != players.end(); ++it) - (*it)->GetSession()->SendLfgUpdateProposal(proposalId, *pProposal); - } - else - { - bool sendUpdate = pProposal->state != LFG_PROPOSAL_SUCCESS; - pProposal->state = LFG_PROPOSAL_SUCCESS; - time_t joinTime = time_t(time(NULL)); - std::map waitTimesMap; - // Save wait times before redoing groups - for (LfgPlayerList::const_iterator it = players.begin(); it != players.end(); ++it) + for (LfgProposalPlayerMap::const_iterator it = proposal.players.begin(); it != proposal.players.end(); ++it) { - LfgProposalPlayer* player = pProposal->players[(*it)->GetGUID()]; - uint32 lowgroupguid = (*it)->GetGroup() ? (*it)->GetGroup()->GetLowGUID() : 0; - if (player->groupLowGuid != lowgroupguid) - sLog->outError(LOG_FILTER_LFG, "LFGMgr::UpdateProposal: [" UI64FMTD "] group mismatch: actual (%u) - queued (%u)", (*it)->GetGUID(), lowgroupguid, player->groupLowGuid); - - uint64 guid2 = player->groupLowGuid ? MAKE_NEW_GUID(player->groupLowGuid, 0, HIGHGUID_GROUP) : (*it)->GetGUID(); - LfgQueueInfoMap::iterator itQueue = m_QueueInfoMap.find(guid2); - if (itQueue == m_QueueInfoMap.end()) - { - sLog->outError(LOG_FILTER_LFG, "LFGMgr::UpdateProposal: Queue info for guid [" UI64FMTD "] not found!", guid); - waitTimesMap[(*it)->GetGUID()] = -1; - } - else - waitTimesMap[(*it)->GetGUID()] = int32(joinTime - itQueue->second->joinTime); + uint64 guid = it->first; + SendLfgUpdateProposal(guid, proposalId, proposal); } + return; + } - // Set the dungeon difficulty - LFGDungeonEntry const* dungeon = GetLFGDungeon(pProposal->dungeonId); - ASSERT(dungeon); - - // Create a new group (if needed) - LfgUpdateData updateData = LfgUpdateData(LFG_UPDATETYPE_GROUP_FOUND); - Group* grp = pProposal->groupLowGuid ? sGroupMgr->GetGroupByGUID(pProposal->groupLowGuid) : NULL; - for (LfgPlayerList::const_iterator it = players.begin(); it != players.end(); ++it) - { - Player* player = (*it); - uint64 pguid = player->GetGUID(); - Group* group = player->GetGroup(); - if (sendUpdate) - player->GetSession()->SendLfgUpdateProposal(proposalId, *pProposal); - - if (group) - { - player->GetSession()->SendLfgUpdateParty(updateData); - if (group != grp) - player->RemoveFromGroup(); - } - else - player->GetSession()->SendLfgUpdatePlayer(updateData); - - if (!grp) - { - grp = new Group(); - grp->Create(player); - grp->ConvertToLFG(); - uint64 gguid = grp->GetGUID(); - SetState(gguid, LFG_STATE_PROPOSAL); - sGroupMgr->AddGroup(grp); - } - else if (group != grp) - grp->AddMember(player); - - // Update timers - uint8 role = GetRoles(pguid); - role &= ~PLAYER_ROLE_LEADER; - switch (role) - { - case PLAYER_ROLE_DAMAGE: - { - uint32 old_number = m_NumWaitTimeDps++; - m_WaitTimeDps = int32((m_WaitTimeDps * old_number + waitTimesMap[player->GetGUID()]) / m_NumWaitTimeDps); - break; - } - case PLAYER_ROLE_HEALER: - { - uint32 old_number = m_NumWaitTimeHealer++; - m_WaitTimeHealer = int32((m_WaitTimeHealer * old_number + waitTimesMap[player->GetGUID()]) / m_NumWaitTimeHealer); - break; - } - case PLAYER_ROLE_TANK: - { - uint32 old_number = m_NumWaitTimeTank++; - m_WaitTimeTank = int32((m_WaitTimeTank * old_number + waitTimesMap[player->GetGUID()]) / m_NumWaitTimeTank); - break; - } - default: - { - uint32 old_number = m_NumWaitTimeAvg++; - m_WaitTimeAvg = int32((m_WaitTimeAvg * old_number + waitTimesMap[player->GetGUID()]) / m_NumWaitTimeAvg); - break; - } - } + bool sendUpdate = proposal.state != LFG_PROPOSAL_SUCCESS; + proposal.state = LFG_PROPOSAL_SUCCESS; + time_t joinTime = time_t(time(NULL)); - m_teleport.push_back(pguid); - grp->SetLfgRoles(pguid, pProposal->players[pguid]->role); - SetState(pguid, LFG_STATE_DUNGEON); + LfgUpdateData updateData = LfgUpdateData(LFG_UPDATETYPE_GROUP_FOUND); + for (LfgProposalPlayerMap::const_iterator it = proposal.players.begin(); it != proposal.players.end(); ++it) + { + uint64 pguid = it->first; + uint64 gguid = it->second.group; + int32 waitTime = -1; + if (sendUpdate) + SendLfgUpdateProposal(pguid, proposalId, proposal); - // Add the cooldown spell if queued for a random dungeon - if (dungeon->type == LFG_TYPE_RANDOM) - player->CastSpell(player, LFG_SPELL_DUNGEON_COOLDOWN, false); + if (gguid) + { + SendLfgUpdateParty(pguid, updateData); } + else + SendLfgUpdatePlayer(pguid, updateData); - grp->SetDungeonDifficulty(Difficulty(dungeon->difficulty)); - uint64 gguid = grp->GetGUID(); - SetDungeon(gguid, dungeon->Entry()); - SetState(gguid, LFG_STATE_DUNGEON); - _SaveToDB(gguid, grp->GetDbStoreId()); + uint64 guid2 = gguid ? gguid : pguid; + LfgQueueInfoMap::iterator itQueue = m_QueueInfoMap.find(guid2); + if (itQueue != m_QueueInfoMap.end()) + waitTime = int32(joinTime - itQueue->second->joinTime); - // Remove players/groups from Queue - for (LfgGuidList::const_iterator it = pProposal->queues.begin(); it != pProposal->queues.end(); ++it) - RemoveFromQueue(*it); + // Update timers + uint8 role = GetRoles(pguid); + role &= ~PLAYER_ROLE_LEADER; + switch (role) + { + case PLAYER_ROLE_DAMAGE: + UpdateWaitTimeDps(waitTime); + break; + case PLAYER_ROLE_HEALER: + UpdateWaitTimeHealer(waitTime); + break; + case PLAYER_ROLE_TANK: + UpdateWaitTimeTank(waitTime); + break; + default: + UpdateWaitTimeAvg(waitTime); + break; + } - // Teleport Player - for (LfgPlayerList::const_iterator it = playersToTeleport.begin(); it != playersToTeleport.end(); ++it) - TeleportPlayer(*it, false); + m_teleport.push_back(pguid); + SetState(pguid, LFG_STATE_DUNGEON); + } - // Update group info - grp->SendUpdate(); + // Remove players/groups from Queue + for (LfgGuidList::const_iterator it = proposal.queues.begin(); it != proposal.queues.end(); ++it) + RemoveFromQueue(*it); - delete pProposal; - m_Proposals.erase(itProposal); - } + MakeNewGroup(proposal); + delete itProposal->second; + m_Proposals.erase(itProposal); } /** @@ -1693,45 +1661,38 @@ void LFGMgr::RemoveProposal(LfgProposalMap::iterator itProposal, LfgUpdateType t sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::RemoveProposal: Proposal %u, state FAILED, UpdateType %u", itProposal->first, type); // Mark all people that didn't answered as no accept if (type == LFG_UPDATETYPE_PROPOSAL_FAILED) - for (LfgProposalPlayerMap::const_iterator it = proposal.players.begin(); it != proposal.players.end(); ++it) - if (it->second->accept == LFG_ANSWER_PENDING) - it->second->accept = LFG_ANSWER_DENY; + for (LfgProposalPlayerMap::iterator it = proposal.players.begin(); it != proposal.players.end(); ++it) + if (it->second.accept == LFG_ANSWER_PENDING) + it->second.accept = LFG_ANSWER_DENY; // Mark players/groups to be removed LfgGuidSet toRemove; - for (LfgProposalPlayerMap::const_iterator it = proposal.players.begin(); it != proposal.players.end(); ++it) + for (LfgProposalPlayerMap::iterator it = proposal.players.begin(); it != proposal.players.end(); ++it) { - if (it->second->accept == LFG_ANSWER_AGREE) + if (it->second.accept == LFG_ANSWER_AGREE) continue; - uint64 guid = it->second->groupLowGuid ? MAKE_NEW_GUID(it->second->groupLowGuid, 0, HIGHGUID_GROUP) : it->first; + uint64 guid = it->second.group ? it->second.group : it->first; // Player didn't accept or still pending when no secs left - if (it->second->accept == LFG_ANSWER_DENY || type == LFG_UPDATETYPE_PROPOSAL_FAILED) + if (it->second.accept == LFG_ANSWER_DENY || type == LFG_UPDATETYPE_PROPOSAL_FAILED) { - it->second->accept = LFG_ANSWER_DENY; + it->second.accept = LFG_ANSWER_DENY; toRemove.insert(guid); } } - uint8 team = 0; // Notify players for (LfgProposalPlayerMap::const_iterator it = proposal.players.begin(); it != proposal.players.end(); ++it) { - Player* player = ObjectAccessor::FindPlayer(it->first); - if (!player) - continue; - - team = uint8(player->GetTeam()); - player->GetSession()->SendLfgUpdateProposal(itProposal->first, proposal); + uint64 guid = it->first; + uint64 gguid = it->second.group ? it->second.group : guid; - Group* grp = player->GetGroup(); - uint64 guid = player->GetGUID(); - uint64 gguid = it->second->groupLowGuid ? MAKE_NEW_GUID(it->second->groupLowGuid, 0, HIGHGUID_GROUP) : guid; + SendLfgUpdateProposal(guid, itProposal->first, proposal); if (toRemove.find(gguid) != toRemove.end()) // Didn't accept or in same group that someone that didn't accept { LfgUpdateData updateData; - if (it->second->accept == LFG_ANSWER_DENY) + if (it->second.accept == LFG_ANSWER_DENY) { updateData.updateType = type; sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::RemoveProposal: [" UI64FMTD "] didn't accept. Removing from queue and compatible cache", guid); @@ -1742,25 +1703,25 @@ void LFGMgr::RemoveProposal(LfgProposalMap::iterator itProposal, LfgUpdateType t sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::RemoveProposal: [" UI64FMTD "] in same group that someone that didn't accept. Removing from queue and compatible cache", guid); } ClearState(guid, "Proposal Fail (didn't accepted or in group with someone that didn't accept"); - if (grp) + if (gguid != guid) { RestoreState(gguid, "Proposal Fail (someone in group didn't accepted)"); - player->GetSession()->SendLfgUpdateParty(updateData); + SendLfgUpdateParty(guid, updateData); } else - player->GetSession()->SendLfgUpdatePlayer(updateData); + SendLfgUpdatePlayer(guid, updateData); } else { sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::RemoveProposal: Readding [" UI64FMTD "] to queue.", guid); SetState(guid, LFG_STATE_QUEUED); - if (grp) + if (gguid != guid) { SetState(gguid, LFG_STATE_QUEUED); - player->GetSession()->SendLfgUpdateParty(LfgUpdateData(LFG_UPDATETYPE_ADDED_TO_QUEUE, GetSelectedDungeons(guid), GetComment(guid))); + SendLfgUpdateParty(guid, LfgUpdateData(LFG_UPDATETYPE_ADDED_TO_QUEUE, GetSelectedDungeons(guid), GetComment(guid))); } else - player->GetSession()->SendLfgUpdatePlayer(LfgUpdateData(LFG_UPDATETYPE_ADDED_TO_QUEUE, GetSelectedDungeons(guid), GetComment(guid))); + SendLfgUpdatePlayer(guid, LfgUpdateData(LFG_UPDATETYPE_ADDED_TO_QUEUE, GetSelectedDungeons(guid), GetComment(guid))); } } @@ -1776,29 +1737,26 @@ void LFGMgr::RemoveProposal(LfgProposalMap::iterator itProposal, LfgUpdateType t for (LfgGuidList::const_iterator it = proposal.queues.begin(); it != proposal.queues.end(); ++it) { uint64 guid = *it; + uint8 team = GetTeam(guid); LfgGuidList& currentQueue = m_currentQueue[team]; currentQueue.push_front(guid); //Add GUID for high priority AddToQueue(guid, team); //We have to add each GUID in newQueue to check for a new groups } - delete &proposal; + delete itProposal->second; m_Proposals.erase(itProposal); } /** Initialize a boot kick vote - @param[in] grp Group the vote kicks belongs to + @param[in] gguid Group the vote kicks belongs to @param[in] kicker Kicker guid @param[in] victim Victim guid @param[in] reason Kick reason */ -void LFGMgr::InitBoot(Group* grp, uint64 kicker, uint64 victim, std::string const& reason) +void LFGMgr::InitBoot(uint64 gguid, uint64 kicker, uint64 victim, std::string const& reason) { - if (!grp) - return; - - uint32 gguid = grp->GetLowGUID(); SetState(gguid, LFG_STATE_BOOT); LfgPlayerBoot& boot = m_Boots[gguid]; @@ -1807,10 +1765,7 @@ void LFGMgr::InitBoot(Group* grp, uint64 kicker, uint64 victim, std::string cons boot.reason = reason; boot.victim = victim; - LfgGuidSet players; - for (GroupReference* itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) - if (Player* player = itr->getSource()) - players.insert(player->GetGUID()); + LfgGuidSet const& players = GetPlayers(gguid); // Set votes for (LfgGuidSet::const_iterator itr = players.begin(); itr != players.end(); ++itr) @@ -1831,18 +1786,15 @@ void LFGMgr::InitBoot(Group* grp, uint64 kicker, uint64 victim, std::string cons /** Update Boot info with player answer - @param[in] player Player who has answered + @param[in] guid Player who has answered @param[in] accept player answer */ -void LFGMgr::UpdateBoot(Player* player, bool accept) +void LFGMgr::UpdateBoot(uint64 guid, bool accept) { - Group* grp = player ? player->GetGroup() : NULL; - if (!grp) + uint64 gguid = GetGroup(guid); + if (!gguid) return; - uint32 gguid = grp->GetLowGUID(); - uint64 guid = player->GetGUID(); - LfgPlayerBootMap::iterator itBoot = m_Boots.find(gguid); if (itBoot == m_Boots.end()) return; @@ -1882,17 +1834,20 @@ void LFGMgr::UpdateBoot(Player* player, bool accept) } } - gguid = grp->GetGUID(); SetState(gguid, LFG_STATE_DUNGEON); if (agreeNum == LFG_GROUP_KICK_VOTES_NEEDED) // Vote passed - Kick player { - Player::RemoveFromGroup(grp, boot.victim); + if (Group* group = sGroupMgr->GetGroupByGUID(GUID_LOPART(gguid))) + Player::RemoveFromGroup(group, boot.victim); + if (Player* victim = ObjectAccessor::FindPlayer(boot.victim)) { TeleportPlayer(victim, true, false); SetState(boot.victim, LFG_STATE_NONE); } - OfferContinue(grp); + + if (Player* leader = ObjectAccessor::FindPlayer(sLFGMgr->GetLeader(gguid))) + leader->GetSession()->SendLfgOfferContinue(GetDungeon(gguid, false)); DecreaseKicksLeft(gguid); } m_Boots.erase(itBoot); @@ -2120,49 +2075,35 @@ LfgType LFGMgr::GetDungeonType(uint32 dungeonId) return LfgType(dungeon->type); } -/** - Given a list of guids returns the concatenation using | as delimiter - - @param[in] check list of guids - @returns Concatenated string -*/ -std::string LFGMgr::ConcatenateGuids(LfgGuidList check) -{ - if (check.empty()) - return ""; - - std::ostringstream o; - LfgGuidList::const_iterator it = check.begin(); - o << (*it); - for (++it; it != check.end(); ++it) - o << '|' << (*it); - return o.str(); -} - LfgState LFGMgr::GetState(uint64 guid) { - sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::GetState: [" UI64FMTD "]", guid); + LfgState state; if (IS_GROUP(guid)) - return m_Groups[guid].GetState(); + state = m_Groups[guid].GetState(); else - return m_Players[guid].GetState(); + state = m_Players[guid].GetState(); + + sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::GetState: [" UI64FMTD "] = %u", guid, state); + return state; } -uint32 LFGMgr::GetDungeon(uint64 guid, bool asId /*= true*/) +uint32 LFGMgr::GetDungeon(uint64 guid, bool asId /*= true */) { - sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::GetDungeon: [" UI64FMTD "] asId: %u", guid, asId); - return m_Groups[guid].GetDungeon(asId); + uint32 dungeon = m_Groups[guid].GetDungeon(asId); + sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::GetDungeon: [" UI64FMTD "] asId: %u = %u", guid, asId, dungeon); + return dungeon; } uint8 LFGMgr::GetRoles(uint64 guid) { - sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::GetRoles: [" UI64FMTD "]", guid); - return m_Players[guid].GetRoles(); + uint8 roles = m_Players[guid].GetRoles(); + sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::GetRoles: [" UI64FMTD "] = %u", guid, roles); + return roles; } const std::string& LFGMgr::GetComment(uint64 guid) { - sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::GetComment: [" UI64FMTD "]", guid); + sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::GetComment: [" UI64FMTD "] = %s", guid, m_Players[guid].GetComment().c_str()); return m_Players[guid].GetComment(); } @@ -2199,7 +2140,8 @@ void LFGMgr::RestoreState(uint64 guid, char const *debugMsg) { LfgGroupData& data = m_Groups[guid]; char const * const ps = GetStateString(data.GetState()); - sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::RestoreState: Group: [" UI64FMTD "] (%s), State: %s", guid, debugMsg, ps); + char const * const os = GetStateString(data.GetOldState()); + sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::RestoreState: Group: [" UI64FMTD "] (%s), State: %s, oldState: %s", guid, debugMsg, ps, os); data.RestoreState(); } @@ -2207,7 +2149,8 @@ void LFGMgr::ClearState(uint64 guid, char const *debugMsg) { LfgPlayerData& data = m_Players[guid]; char const * const ps = GetStateString(data.GetState()); - sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::ClearState: Player: [" UI64FMTD "] (%s) State: %s", guid, debugMsg, ps); + char const * const os = GetStateString(data.GetOldState()); + sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::ClearState: Player: [" UI64FMTD "] (%s) State: %s, oldState: %s", guid, debugMsg, ps, os); data.ClearState(); } @@ -2218,7 +2161,8 @@ void LFGMgr::SetState(uint64 guid, LfgState state) LfgGroupData& data = m_Groups[guid]; char const * const ns = GetStateString(state); char const * const ps = GetStateString(data.GetState()); - sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::SetState: Group: [" UI64FMTD "] newState: %s, previous: %s", guid, ns, ps); + char const * const os = GetStateString(data.GetOldState()); + sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::SetState: Group: [" UI64FMTD "] newState: %s, previous: %s, oldState: %s", guid, ns, ps, os); data.SetState(state); } else @@ -2226,7 +2170,8 @@ void LFGMgr::SetState(uint64 guid, LfgState state) LfgPlayerData& data = m_Players[guid]; char const * const ns = GetStateString(state); char const * const ps = GetStateString(data.GetState()); - sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::SetState: Player: [" UI64FMTD "] newState: %s, previous: %s", guid, ns, ps); + char const * const os = GetStateString(data.GetOldState()); + sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::SetState: Player: [" UI64FMTD "] newState: %s, previous: %s, oldState: %s", guid, ns, ps, os); data.SetState(state); } } @@ -2283,6 +2228,54 @@ void LFGMgr::RemoveGroupData(uint64 guid) m_Groups.erase(it); } +uint8 LFGMgr::GetTeam(uint64 guid) +{ + return m_Players[guid].GetTeam(); +} + +uint8 LFGMgr::RemovePlayerFromGroup(uint64 gguid, uint64 guid) +{ + return m_Groups[gguid].RemovePlayer(guid); +} + +void LFGMgr::AddPlayerToGroup(uint64 gguid, uint64 guid) +{ + m_Groups[gguid].AddPlayer(guid); +} + +void LFGMgr::SetLeader(uint64 gguid, uint64 leader) +{ + m_Groups[gguid].SetLeader(leader); +} + +void LFGMgr::SetTeam(uint64 guid, uint8 team) +{ + if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP)) + team = 0; + + m_Players[guid].SetTeam(team); +} + +uint64 LFGMgr::GetGroup(uint64 guid) +{ + return m_Players[guid].GetGroup(); +} + +void LFGMgr::SetGroup(uint64 guid, uint64 group) +{ + m_Players[guid].SetGroup(group); +} + +const LfgGuidSet& LFGMgr::GetPlayers(uint64 guid) +{ + return m_Groups[guid].GetPlayers(); +} + +uint64 LFGMgr::GetLeader(uint64 guid) +{ + return m_Groups[guid].GetLeader(); +} + bool LFGMgr::HasIgnore(uint64 guid1, uint64 guid2) { Player* plr1 = ObjectAccessor::FindPlayer(guid1); @@ -2360,3 +2353,50 @@ bool LFGMgr::IsSeasonActive(uint32 dungeonId) } return false; } + +void LFGMgr::UpdateWaitTimeAvg(int32 waitTime) +{ + LfgWaitTime &wt = m_waitTimesAvg; + uint32 old_number = wt.number++; + wt.time = int32((wt.time * old_number + waitTime) / wt.number); +} + +void LFGMgr::UpdateWaitTimeTank(int32 waitTime) +{ + LfgWaitTime &wt = m_waitTimesTank; + uint32 old_number = wt.number++; + wt.time = int32((wt.time * old_number + waitTime) / wt.number); +} + +void LFGMgr::UpdateWaitTimeHealer(int32 waitTime) +{ + LfgWaitTime &wt = m_waitTimesHealer; + uint32 old_number = wt.number++; + wt.time = int32((wt.time * old_number + waitTime) / wt.number); +} + +void LFGMgr::UpdateWaitTimeDps(int32 waitTime) +{ + LfgWaitTime &wt = m_waitTimesDps; + uint32 old_number = wt.number++; + wt.time = int32((wt.time * old_number + waitTime) / wt.number); +} + +/** + Given a list of guids returns the concatenation using | as delimiter + + @param[in] check list of guids + @returns Concatenated string +*/ +std::string LFGMgr::ConcatenateGuids(LfgGuidList check) +{ + if (check.empty()) + return ""; + + std::ostringstream o; + LfgGuidList::const_iterator it = check.begin(); + o << (*it); + for (++it; it != check.end(); ++it) + o << '|' << (*it); + return o.str(); +} \ No newline at end of file diff --git a/src/server/game/DungeonFinding/LFGMgr.h b/src/server/game/DungeonFinding/LFGMgr.h index d4d35974604..756f7094be6 100755 --- a/src/server/game/DungeonFinding/LFGMgr.h +++ b/src/server/game/DungeonFinding/LFGMgr.h @@ -21,6 +21,7 @@ #include "Common.h" #include #include "LFG.h" + #include "LFGGroupData.h" #include "LFGPlayerData.h" @@ -127,20 +128,28 @@ struct LfgPlayerBoot; typedef std::map LfgGuidListMap; typedef std::set PlayerSet; typedef std::list LfgPlayerList; +typedef std::map LfgCompatibleMap; +typedef std::map LfgQueueInfoMap; + typedef std::multimap LfgRewardMap; typedef std::pair LfgRewardMapBounds; -typedef std::map LfgCompatibleMap; typedef std::map LfgCachedDungeonMap; typedef std::map LfgAnswerMap; typedef std::map LfgRoleCheckMap; -typedef std::map LfgQueueInfoMap; typedef std::map LfgProposalMap; -typedef std::map LfgProposalPlayerMap; +typedef std::map LfgProposalPlayerMap; typedef std::map LfgPlayerBootMap; typedef std::map LfgGroupDataMap; typedef std::map LfgPlayerDataMap; typedef UNORDERED_MAP LFGDungeonMap; +struct LfgWaitTime +{ + LfgWaitTime(): time(-1), number(0) {} + int32 time; ///< Wait time + uint32 number; ///< Number of people used to get that wait time +}; + // Data needed by SMSG_LFG_JOIN_RESULT struct LfgJoinResultData { @@ -221,27 +230,26 @@ struct LfgQueueInfo /// Stores player data related to proposal to join struct LfgProposalPlayer { - LfgProposalPlayer(): role(0), accept(LFG_ANSWER_PENDING), groupLowGuid(0) {}; + LfgProposalPlayer(): role(0), accept(LFG_ANSWER_PENDING), group(0) { } uint8 role; ///< Proposed role LfgAnswer accept; ///< Accept status (-1 not answer | 0 Not agree | 1 agree) - uint32 groupLowGuid; ///< Original group guid (Low guid) 0 if no original group + uint64 group; ///< Original group guid. 0 if no original group }; /// Stores group data related to proposal to join struct LfgProposal { - LfgProposal(uint32 dungeon = 0): dungeonId(dungeon), state(LFG_PROPOSAL_INITIATING), groupLowGuid(0), leader(0), cancelTime(0) {} + LfgProposal(uint32 dungeon = 0): dungeonId(dungeon), state(LFG_PROPOSAL_INITIATING), + group(0), leader(0), cancelTime(0), encounters(0), isNew(true) + { } - ~LfgProposal() - { - for (LfgProposalPlayerMap::iterator it = players.begin(); it != players.end(); ++it) - delete it->second; - }; uint32 dungeonId; ///< Dungeon to join LfgProposalState state; ///< State of the proposal - uint32 groupLowGuid; ///< Proposal group (0 if new) + uint64 group; ///< Proposal group (0 if new) uint64 leader; ///< Leader guid. time_t cancelTime; ///< Time when we will cancel this proposal + uint32 encounters; ///< Dungeon Encounters + bool isNew; ///< Determines if it's new group or not LfgGuidList queues; ///< Queue Ids to remove/readd LfgProposalPlayerMap players; ///< Players data }; @@ -264,7 +272,6 @@ struct LfgPlayerBoot bool inProgress; ///< Vote in progress LfgAnswerMap votes; ///< Player votes (-1 not answer | 0 Not agree | 1 agree) uint64 victim; ///< Player guid to be kicked (can't vote) - uint8 votedNeeded; ///< Votes needed to kick the player std::string reason; ///< kick reason }; @@ -313,26 +320,33 @@ class LFGMgr // Queue void JoinLfg(Player* player, uint8 roles, LfgDungeonSet& dungeons, std::string const& comment); - void LeaveLfg(Player* player, Group* grp = NULL); + void LeaveLfg(uint64 guid); // Role Check void UpdateRoleCheck(uint64 gguid, uint64 guid = 0, uint8 roles = PLAYER_ROLE_NONE); + // Group Matching + static bool CheckGroupRoles(LfgRolesMap &groles, bool removeLeaderFlag = true); + void GetCompatibleDungeons(LfgDungeonSet& dungeons, LfgGuidSet const& players, LfgLockPartyMap& lockMap); + // Proposals + uint32 AddProposal(LfgProposal const& proposal); void UpdateProposal(uint32 proposalId, uint64 guid, bool accept); // Teleportation void TeleportPlayer(Player* player, bool out, bool fromOpcode = false); // Vote kick - void InitBoot(Group* grp, uint64 kguid, uint64 vguid, std::string const& reason); - void UpdateBoot(Player* player, bool accept); - void OfferContinue(Group* grp); + void InitBoot(uint64 gguid, uint64 kguid, uint64 vguid, std::string const& reason); + void UpdateBoot(uint64 guid, bool accept); void InitializeLockedDungeons(Player* player, uint8 level = 0); void SetRoles(uint64 guid, uint8 roles); void SetComment(uint64 guid, std::string const& comment); + void SetTeam(uint64 guid, uint8 team); + void SetGroup(uint64 guid, uint64 group); + void SetLeader(uint64 gguid, uint64 leader); void SetState(uint64 guid, LfgState state); void SetSelectedDungeons(uint64 guid, LfgDungeonSet const& dungeons); @@ -341,15 +355,20 @@ class LFGMgr void RemovePlayerData(uint64 guid); void RemoveGroupData(uint64 guid); + uint8 RemovePlayerFromGroup(uint64 gguid, uint64 guid); + void AddPlayerToGroup(uint64 gguid, uint64 guid); LfgLockMap const& GetLockedDungeons(uint64 guid); LfgDungeonSet const& GetSelectedDungeons(uint64 guid); uint32 GetDungeon(uint64 guid, bool asId = true); LfgState GetState(uint64 guid); uint8 GetKicksLeft(uint64 gguid); + uint64 GetLeader(uint64 guid); bool IsLfgGroup(uint64 guid); uint8 GetRoles(uint64 guid); std::string const& GetComment(uint64 gguid); + LfgGuidSet const& GetPlayers(uint64 guid); + bool IsTeleported(uint64 guid); static bool HasIgnore(uint64 guid1, uint64 guid2); @@ -368,6 +387,8 @@ class LFGMgr void ClearState(uint64 guid, char const *debugMsg); private: + uint8 GetTeam(uint64 guid); + uint64 GetGroup(uint64 guid); void RestoreState(uint64 guid, char const *debugMsg); void SetDungeon(uint64 guid, uint32 dungeon); @@ -380,21 +401,23 @@ class LFGMgr // Proposals void RemoveProposal(LfgProposalMap::iterator itProposal, LfgUpdateType type); + void MakeNewGroup(LfgProposal const& proposal); // Group Matching LfgProposal* FindNewGroups(LfgGuidList& check, LfgGuidList& all); - bool CheckGroupRoles(LfgRolesMap &groles, bool removeLeaderFlag = true); bool CheckCompatibility(LfgGuidList check, LfgProposal*& pProposal); - void GetCompatibleDungeons(LfgDungeonSet& dungeons, PlayerSet const& players, LfgLockPartyMap& lockMap); void SetCompatibles(std::string concatenatedGuids, bool compatibles); LfgAnswer GetCompatibles(std::string concatenatedGuids); - void RemoveFromCompatibles(uint64 guid); // Generic LfgDungeonSet const& GetDungeonsByRandom(uint32 randomdungeon); LfgType GetDungeonType(uint32 dungeon); std::string ConcatenateGuids(LfgGuidList check); - + void RemoveFromCompatibles(uint64 guid); + void UpdateWaitTimeAvg(int32 waitTime); + void UpdateWaitTimeTank(int32 waitTime); + void UpdateWaitTimeHealer(int32 waitTime); + void UpdateWaitTimeDps(int32 waitTime); void SendLfgBootProposalUpdate(uint64 guid, LfgPlayerBoot const& boot); void SendLfgJoinResult(uint64 guid, LfgJoinResultData const& data); void SendLfgRoleChosen(uint64 guid, uint64 pguid, uint8 roles); @@ -408,30 +431,27 @@ class LFGMgr uint32 m_lfgProposalId; ///< used as internal counter for proposals uint32 m_options; ///< Stores config options - int32 m_WaitTimeAvg; ///< Average wait time to find a group queuing as multiple roles - int32 m_WaitTimeTank; ///< Average wait time to find a group queuing as tank - int32 m_WaitTimeHealer; ///< Average wait time to find a group queuing as healer - int32 m_WaitTimeDps; ///< Average wait time to find a group queuing as dps - uint32 m_NumWaitTimeAvg; ///< Num of players used to calc avs wait time - uint32 m_NumWaitTimeTank; ///< Num of players used to calc tank wait time - uint32 m_NumWaitTimeHealer; ///< Num of players used to calc healers wait time - uint32 m_NumWaitTimeDps; ///< Num of players used to calc dps wait time LfgCachedDungeonMap m_CachedDungeonMap; ///< Stores all dungeons by groupType // Reward System LfgRewardMap m_RewardMap; ///< Stores rewards for random dungeons LFGDungeonMap m_LfgDungeonMap; - // Queue - LfgQueueInfoMap m_QueueInfoMap; ///< Queued groups - LfgGuidListMap m_currentQueue; ///< Ordered list. Used to find groups - LfgGuidListMap m_newToQueue; ///< New groups to add to queue - LfgCompatibleMap m_CompatibleMap; ///< Compatible dungeons - LfgGuidList m_teleport; ///< Players being teleported // Rolecheck - Proposal - Vote Kicks LfgRoleCheckMap m_RoleChecks; ///< Current Role checks LfgProposalMap m_Proposals; ///< Current Proposals LfgPlayerBootMap m_Boots; ///< Current player kicks LfgPlayerDataMap m_Players; ///< Player data LfgGroupDataMap m_Groups; ///< Group data + LfgGuidList m_teleport; ///< Players being teleported + + // Queue + LfgQueueInfoMap m_QueueInfoMap; ///< Queued groups + LfgGuidListMap m_currentQueue; ///< Ordered list. Used to find groups + LfgGuidListMap m_newToQueue; ///< New groups to add to queue + LfgCompatibleMap m_CompatibleMap; ///< Compatible dungeons + LfgWaitTime m_waitTimesAvg; ///< Average wait time to find a group queuing as multiple roles + LfgWaitTime m_waitTimesTank; ///< Average wait time to find a group queuing as tank + LfgWaitTime m_waitTimesHealer; ///< Average wait time to find a group queuing as healer + LfgWaitTime m_waitTimesDps; ///< Average wait time to find a group queuing as dps LFGPlayerScript *m_lfgPlayerScript; LFGGroupScript *m_lfgGroupScript; diff --git a/src/server/game/DungeonFinding/LFGPlayerData.cpp b/src/server/game/DungeonFinding/LFGPlayerData.cpp index 4a6e86ab966..6f030831342 100644 --- a/src/server/game/DungeonFinding/LFGPlayerData.cpp +++ b/src/server/game/DungeonFinding/LFGPlayerData.cpp @@ -17,8 +17,8 @@ #include "LFGPlayerData.h" -LfgPlayerData::LfgPlayerData(): -m_State(LFG_STATE_NONE), m_OldState(LFG_STATE_NONE), m_Roles(0), m_Comment("") +LfgPlayerData::LfgPlayerData(): m_State(LFG_STATE_NONE), m_OldState(LFG_STATE_NONE), + m_Team(0), m_Group(0), m_Roles(0), m_Comment("") {} LfgPlayerData::~LfgPlayerData() @@ -30,10 +30,10 @@ void LfgPlayerData::SetState(LfgState state) switch (state) { case LFG_STATE_NONE: - case LFG_STATE_DUNGEON: case LFG_STATE_FINISHED_DUNGEON: + case LFG_STATE_DUNGEON: m_OldState = state; - // No break on purpose + // No break on purpose default: m_State = state; } @@ -51,6 +51,16 @@ void LfgPlayerData::SetLockedDungeons(const LfgLockMap& lockStatus) m_LockedDungeons = lockStatus; } +void LfgPlayerData::SetTeam(uint8 team) +{ + m_Team = team; +} + +void LfgPlayerData::SetGroup(uint64 group) +{ + m_Group = group; +} + void LfgPlayerData::SetRoles(uint8 roles) { m_Roles = roles; @@ -66,21 +76,31 @@ void LfgPlayerData::SetSelectedDungeons(const LfgDungeonSet& dungeons) m_SelectedDungeons = dungeons; } -void LfgPlayerData::ClearSelectedDungeons() +LfgState LfgPlayerData::GetState() const { - m_SelectedDungeons.clear(); + return m_State; } -LfgState LfgPlayerData::GetState() const +LfgState LfgPlayerData::GetOldState() const { - return m_State; + return m_OldState; } -const LfgLockMap & LfgPlayerData::GetLockedDungeons() const +const LfgLockMap& LfgPlayerData::GetLockedDungeons() const { return m_LockedDungeons; } +uint8 LfgPlayerData::GetTeam() const +{ + return m_Team; +} + +uint64 LfgPlayerData::GetGroup() const +{ + return m_Group; +} + uint8 LfgPlayerData::GetRoles() const { return m_Roles; diff --git a/src/server/game/DungeonFinding/LFGPlayerData.h b/src/server/game/DungeonFinding/LFGPlayerData.h index e8bae1c5a0f..0682ad66698 100644 --- a/src/server/game/DungeonFinding/LFGPlayerData.h +++ b/src/server/game/DungeonFinding/LFGPlayerData.h @@ -18,7 +18,6 @@ #ifndef _LFGPLAYERDATA_H #define _LFGPLAYERDATA_H -#include "Common.h" #include "LFG.h" /** @@ -33,20 +32,26 @@ class LfgPlayerData // General void SetState(LfgState state); void ClearState(); - void SetLockedDungeons(const LfgLockMap& lock); + void SetLockedDungeons(LfgLockMap const& lock); + void SetTeam(uint8 team); + void SetGroup(uint64 group); + // Queue void SetRoles(uint8 roles); - void SetComment(const std::string& comment); + void SetComment(std::string const& comment); void SetSelectedDungeons(const LfgDungeonSet& dungeons); - void ClearSelectedDungeons(); // General LfgState GetState() const; - const LfgLockMap& GetLockedDungeons() const; + LfgState GetOldState() const; + LfgLockMap const& GetLockedDungeons() const; + uint8 GetTeam() const; + uint64 GetGroup() const; + // Queue uint8 GetRoles() const; - const std::string& GetComment() const; - const LfgDungeonSet& GetSelectedDungeons() const; + std::string const& GetComment() const; + LfgDungeonSet const& GetSelectedDungeons() const; private: // General @@ -54,6 +59,9 @@ class LfgPlayerData LfgState m_OldState; ///< Old State // Player LfgLockMap m_LockedDungeons; ///< Dungeons player can't do and reason + uint8 m_Team; ///< Player team - determines the queue to join + uint64 m_Group; ///< Original group of player when joined LFG + // Queue uint8 m_Roles; ///< Roles the player selected when joined LFG std::string m_Comment; ///< Player comment used when joined LFG diff --git a/src/server/game/DungeonFinding/LFGScripts.cpp b/src/server/game/DungeonFinding/LFGScripts.cpp index 26686dbaa33..76cc169f477 100644 --- a/src/server/game/DungeonFinding/LFGScripts.cpp +++ b/src/server/game/DungeonFinding/LFGScripts.cpp @@ -40,7 +40,7 @@ void LFGPlayerScript::OnLevelChanged(Player* player, uint8 /*oldLevel*/) void LFGPlayerScript::OnLogout(Player* player) { uint64 guid = player->GetGUID(); - sLFGMgr->LeaveLfg(player); + sLFGMgr->LeaveLfg(guid); LfgUpdateData updateData = LfgUpdateData(LFG_UPDATETYPE_REMOVED_FROM_QUEUE); player->GetSession()->SendLfgUpdateParty(updateData); player->GetSession()->SendLfgUpdatePlayer(updateData); @@ -52,6 +52,7 @@ void LFGPlayerScript::OnLogout(Player* player) void LFGPlayerScript::OnLogin(Player* player) { sLFGMgr->InitializeLockedDungeons(player); + sLFGMgr->SetTeam(player->GetGUID(), player->GetTeam()); // TODO - Restore LfgPlayerData and send proper status to player if it was in a group } @@ -69,73 +70,85 @@ LFGGroupScript::LFGGroupScript() : GroupScript("LFGGroupScript") void LFGGroupScript::OnAddMember(Group* group, uint64 guid) { uint64 gguid = group->GetGUID(); - if (!gguid) - return; + uint64 leader = group->GetLeaderGUID(); - sLog->outDebug(LOG_FILTER_LFG, "LFGScripts::OnAddMember [" UI64FMTD "]: added [" UI64FMTD "]", gguid, guid); - LfgUpdateData updateData = LfgUpdateData(LFG_UPDATETYPE_CLEAR_LOCK_LIST); - for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next()) + if (leader == guid) + { + sLog->outDebug(LOG_FILTER_LFG, "LFGScripts::OnAddMember [" UI64FMTD "]: added [" UI64FMTD "] leader " UI64FMTD "]", gguid, guid, leader); + sLFGMgr->SetLeader(gguid, guid); + } + else { - if (Player* plrg = itr->getSource()) + LfgState gstate = sLFGMgr->GetState(gguid); + LfgState state = sLFGMgr->GetState(guid); + sLog->outDebug(LOG_FILTER_LFG, "LFGScripts::OnAddMember [" UI64FMTD "]: added [" UI64FMTD "] leader " UI64FMTD "] gstate: %u, state: %u", gguid, guid, leader, gstate, state); + LfgUpdateData updateData = LfgUpdateData(LFG_UPDATETYPE_CLEAR_LOCK_LIST); + for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next()) { - plrg->GetSession()->SendLfgUpdatePlayer(updateData); - plrg->GetSession()->SendLfgUpdateParty(updateData); + if (Player* plrg = itr->getSource()) + { + plrg->GetSession()->SendLfgUpdatePlayer(updateData); + plrg->GetSession()->SendLfgUpdateParty(updateData); + } } - } - // TODO - if group is queued and new player is added convert to rolecheck without notify the current players queued - if (sLFGMgr->GetState(gguid) == LFG_STATE_QUEUED) - sLFGMgr->LeaveLfg(NULL, group); + if (state == LFG_STATE_QUEUED) + sLFGMgr->LeaveLfg(guid); - if (sLFGMgr->GetState(guid) == LFG_STATE_QUEUED) - if (Player* player = ObjectAccessor::FindPlayer(guid)) - sLFGMgr->LeaveLfg(player); + // TODO - if group is queued and new player is added convert to rolecheck without notify the current players queued + if (gstate == LFG_STATE_QUEUED) + sLFGMgr->LeaveLfg(gguid); + } + + sLFGMgr->SetGroup(guid, gguid); + sLFGMgr->AddPlayerToGroup(gguid, guid); } void LFGGroupScript::OnRemoveMember(Group* group, uint64 guid, RemoveMethod method, uint64 kicker, char const* reason) { uint64 gguid = group->GetGUID(); - if (!gguid || method == GROUP_REMOVEMETHOD_DEFAULT) - return; - sLog->outDebug(LOG_FILTER_LFG, "LFGScripts::OnRemoveMember [" UI64FMTD "]: remove [" UI64FMTD "] Method: %d Kicker: [" UI64FMTD "] Reason: %s", gguid, guid, method, kicker, (reason ? reason : "")); - if (sLFGMgr->GetState(gguid) == LFG_STATE_QUEUED) - { - // TODO - Do not remove, just remove the one leaving and rejoin queue with all other data - sLFGMgr->LeaveLfg(NULL, group); - } - if (!group->isLFGGroup()) + if (method == GROUP_REMOVEMETHOD_DEFAULT) return; - if (method == GROUP_REMOVEMETHOD_KICK) // Player have been kicked + LfgState state = sLFGMgr->GetState(gguid); + if (state == LFG_STATE_QUEUED) + sLFGMgr->LeaveLfg(gguid); // TODO - Remove the one leaving and rejoin group + + bool isLFG = group->isLFGGroup(); + + if (isLFG && method == GROUP_REMOVEMETHOD_KICK) // Player have been kicked { // TODO - Update internal kick cooldown of kicker std::string str_reason = ""; if (reason) str_reason = std::string(reason); - sLFGMgr->InitBoot(group, kicker, guid, str_reason); + sLFGMgr->InitBoot(gguid, kicker, guid, str_reason); return; } - uint32 state = sLFGMgr->GetState(gguid); sLFGMgr->ClearState(guid, "OnRemoveMember"); sLFGMgr->SetState(guid, LFG_STATE_NONE); + sLFGMgr->SetGroup(guid, 0); + sLFGMgr->RemovePlayerFromGroup(gguid, guid); + if (Player* player = ObjectAccessor::FindPlayer(guid)) { - if (method == GROUP_REMOVEMETHOD_LEAVE && sLFGMgr->GetState(gguid) != LFG_STATE_FINISHED_DUNGEON && sLFGMgr->GetDungeon(gguid, false)) + if (method == GROUP_REMOVEMETHOD_LEAVE && state == LFG_STATE_DUNGEON && + sLFGMgr->GetDungeon(gguid, false)) player->CastSpell(player, LFG_SPELL_DUNGEON_DESERTER, true); //else if (state == LFG_STATE_BOOT) // Update internal kick cooldown of kicked - LfgUpdateData updateData = LfgUpdateData(LFG_UPDATETYPE_LEADER); - player->GetSession()->SendLfgUpdateParty(updateData); - if (player->GetMap()->IsDungeon()) // Teleport player out the dungeon + player->GetSession()->SendLfgUpdateParty(LfgUpdateData(LFG_UPDATETYPE_LEADER_UNK1)); + if (isLFG && player->GetMap()->IsDungeon()) // Teleport player out the dungeon sLFGMgr->TeleportPlayer(player, true); } - if (state != LFG_STATE_FINISHED_DUNGEON)// Need more players to finish the dungeon - sLFGMgr->OfferContinue(group); + if (isLFG && state != LFG_STATE_FINISHED_DUNGEON) // Need more players to finish the dungeon + if (Player* leader = ObjectAccessor::FindPlayer(sLFGMgr->GetLeader(gguid))) + leader->GetSession()->SendLfgOfferContinue(sLFGMgr->GetDungeon(gguid, false)); } void LFGGroupScript::OnDisband(Group* group) @@ -149,20 +162,19 @@ void LFGGroupScript::OnDisband(Group* group) void LFGGroupScript::OnChangeLeader(Group* group, uint64 newLeaderGuid, uint64 oldLeaderGuid) { uint64 gguid = group->GetGUID(); - if (!gguid) - return; sLog->outDebug(LOG_FILTER_LFG, "LFGScripts::OnChangeLeader [" UI64FMTD "]: old [" UI64FMTD "] new [" UI64FMTD "]", gguid, newLeaderGuid, oldLeaderGuid); + sLFGMgr->SetLeader(gguid, newLeaderGuid); Player* player = ObjectAccessor::FindPlayer(newLeaderGuid); - LfgUpdateData updateData = LfgUpdateData(LFG_UPDATETYPE_LEADER); + LfgUpdateData updateData = LfgUpdateData(LFG_UPDATETYPE_LEADER_UNK1); if (player) player->GetSession()->SendLfgUpdateParty(updateData); player = ObjectAccessor::FindPlayer(oldLeaderGuid); if (player) { - updateData.updateType = LFG_UPDATETYPE_GROUP_DISBAND; + updateData.updateType = LFG_UPDATETYPE_GROUP_DISBAND_UNK16; player->GetSession()->SendLfgUpdateParty(updateData); } } @@ -170,9 +182,7 @@ void LFGGroupScript::OnChangeLeader(Group* group, uint64 newLeaderGuid, uint64 o void LFGGroupScript::OnInviteMember(Group* group, uint64 guid) { uint64 gguid = group->GetGUID(); - if (!gguid) - return; sLog->outDebug(LOG_FILTER_LFG, "LFGScripts::OnInviteMember [" UI64FMTD "]: invite [" UI64FMTD "] leader [" UI64FMTD "]", gguid, guid, group->GetLeaderGUID()); - sLFGMgr->LeaveLfg(NULL, group); + sLFGMgr->LeaveLfg(gguid); } diff --git a/src/server/game/Handlers/LFGHandler.cpp b/src/server/game/Handlers/LFGHandler.cpp index 59631618757..4f208d33bde 100755 --- a/src/server/game/Handlers/LFGHandler.cpp +++ b/src/server/game/Handlers/LFGHandler.cpp @@ -23,7 +23,6 @@ #include "LFGMgr.h" #include "ObjectMgr.h" #include "GroupMgr.h" -#include "InstanceScript.h" void BuildPlayerLockDungeonBlock(WorldPacket& data, const LfgLockMap& lock) { @@ -88,12 +87,13 @@ void WorldSession::HandleLfgLeaveOpcode(WorldPacket& /*recv_data*/) { Group* grp = GetPlayer()->GetGroup(); uint64 guid = GetPlayer()->GetGUID(); + uint64 gguid = grp ? grp->GetGUID() : guid; sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_LFG_LEAVE [" UI64FMTD "] in group: %u", guid, grp ? 1 : 0); // Check cheating - only leader can leave the queue if (!grp || grp->GetLeaderGUID() == GetPlayer()->GetGUID()) - sLFGMgr->LeaveLfg(GetPlayer(), grp); + sLFGMgr->LeaveLfg(gguid); } void WorldSession::HandleLfgProposalResultOpcode(WorldPacket& recv_data) @@ -140,7 +140,7 @@ void WorldSession::HandleLfgSetBootVoteOpcode(WorldPacket& recv_data) uint64 guid = GetPlayer()->GetGUID(); sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_LFG_SET_BOOT_VOTE [" UI64FMTD "] agree: %u", guid, agree ? 1 : 0); - sLFGMgr->UpdateBoot(GetPlayer(), agree); + sLFGMgr->UpdateBoot(guid, agree); } void WorldSession::HandleLfgTeleportOpcode(WorldPacket& recv_data) @@ -285,6 +285,8 @@ void WorldSession::SendLfgUpdatePlayer(const LfgUpdateData& updateData) { bool queued = false; bool extrainfo = false; + uint64 guid = GetPlayer()->GetGUID(); + uint8 size = uint8(updateData.dungeons.size()); switch (updateData.updateType) { @@ -301,9 +303,6 @@ void WorldSession::SendLfgUpdatePlayer(const LfgUpdateData& updateData) break; } - uint64 guid = GetPlayer()->GetGUID(); - uint8 size = uint8(updateData.dungeons.size()); - sLog->outDebug(LOG_FILTER_NETWORKIO, "SMSG_LFG_UPDATE_PLAYER [" UI64FMTD "] updatetype: %u", guid, updateData.updateType); WorldPacket data(SMSG_LFG_UPDATE_PLAYER, 1 + 1 + (extrainfo ? 1 : 0) * (1 + 1 + 1 + 1 + size * 4 + updateData.comment.length())); data << uint8(updateData.updateType); // Lfg Update type @@ -328,6 +327,8 @@ void WorldSession::SendLfgUpdateParty(const LfgUpdateData& updateData) bool join = false; bool extrainfo = false; bool queued = false; + uint64 guid = GetPlayer()->GetGUID(); + uint8 size = uint8(updateData.dungeons.size()); switch (updateData.updateType) { @@ -351,9 +352,6 @@ void WorldSession::SendLfgUpdateParty(const LfgUpdateData& updateData) break; } - uint64 guid = GetPlayer()->GetGUID(); - uint8 size = uint8(updateData.dungeons.size()); - sLog->outDebug(LOG_FILTER_NETWORKIO, "SMSG_LFG_UPDATE_PARTY [" UI64FMTD "] updatetype: %u", guid, updateData.updateType); WorldPacket data(SMSG_LFG_UPDATE_PARTY, 1 + 1 + (extrainfo ? 1 : 0) * (1 + 1 + 1 + 1 + 1 + size * 4 + updateData.comment.length())); data << uint8(updateData.updateType); // Lfg Update type @@ -522,7 +520,7 @@ void WorldSession::SendLfgBootProposalUpdate(const LfgPlayerBoot& boot) } } sLog->outDebug(LOG_FILTER_NETWORKIO, "SMSG_LFG_BOOT_PROPOSAL_UPDATE [" UI64FMTD "] inProgress: %u - didVote: %u - agree: %u - victim: [" UI64FMTD "] votes: %u - agrees: %u - left: %u - needed: %u - reason %s", - guid, uint8(boot.inProgress), uint8(playerVote != LFG_ANSWER_PENDING), uint8(playerVote == LFG_ANSWER_AGREE), boot.victim, votesNum, agreeNum, secsleft, boot.votedNeeded, boot.reason.c_str()); + guid, uint8(boot.inProgress), uint8(playerVote != LFG_ANSWER_PENDING), uint8(playerVote == LFG_ANSWER_AGREE), boot.victim, votesNum, agreeNum, secsleft, LFG_GROUP_KICK_VOTES_NEEDED, boot.reason.c_str()); WorldPacket data(SMSG_LFG_BOOT_PROPOSAL_UPDATE, 1 + 1 + 1 + 8 + 4 + 4 + 4 + 4 + boot.reason.length()); data << uint8(boot.inProgress); // Vote in progress data << uint8(playerVote != LFG_ANSWER_PENDING); // Did Vote @@ -531,87 +529,56 @@ void WorldSession::SendLfgBootProposalUpdate(const LfgPlayerBoot& boot) data << uint32(votesNum); // Total Votes data << uint32(agreeNum); // Agree Count data << uint32(secsleft); // Time Left - data << uint32(boot.votedNeeded); // Needed Votes + data << uint32(LFG_GROUP_KICK_VOTES_NEEDED); // Needed Votes data << boot.reason.c_str(); // Kick reason SendPacket(&data); } -void WorldSession::SendLfgUpdateProposal(uint32 proposalId, const LfgProposal& proposal) +void WorldSession::SendLfgUpdateProposal(uint32 proposalId, LfgProposal const& proposal) { uint64 guid = GetPlayer()->GetGUID(); - LfgProposalPlayerMap::const_iterator itPlayer = proposal.players.find(guid); - if (itPlayer == proposal.players.end()) // Player MUST be in the proposal - return; + uint64 gguid = proposal.players.find(guid)->second.group; + bool silent = !proposal.isNew && gguid == proposal.group; + uint32 dungeonEntry = proposal.dungeonId; - LfgProposalPlayer* ppPlayer = itPlayer->second; - uint32 pLowGroupGuid = ppPlayer->groupLowGuid; - uint32 dLowGuid = proposal.groupLowGuid; - uint32 dungeonId = proposal.dungeonId; - bool isSameDungeon = false; - bool isContinue = false; - Group* grp = dLowGuid ? sGroupMgr->GetGroupByGUID(dLowGuid) : NULL; - uint32 completedEncounters = 0; - if (grp) - { - uint64 gguid = grp->GetGUID(); - isContinue = grp->isLFGGroup() && sLFGMgr->GetState(gguid) != LFG_STATE_FINISHED_DUNGEON; - isSameDungeon = GetPlayer()->GetGroup() == grp && isContinue; - } - - sLog->outDebug(LOG_FILTER_NETWORKIO, "SMSG_LFG_PROPOSAL_UPDATE [" UI64FMTD "] state: %u", GetPlayer()->GetGUID(), proposal.state); + sLog->outDebug(LOG_FILTER_NETWORKIO, "SMSG_LFG_PROPOSAL_UPDATE [" UI64FMTD "] state: %u", guid, proposal.state); WorldPacket data(SMSG_LFG_PROPOSAL_UPDATE, 4 + 1 + 4 + 4 + 1 + 1 + proposal.players.size() * (4 + 1 + 1 + 1 + 1 +1)); - if (!isContinue) // Only show proposal dungeon if it's continue + // show random dungeon if player selected random dungeon and it's not lfg group + if (!silent) { - LfgDungeonSet playerDungeons = sLFGMgr->GetSelectedDungeons(guid); - if (playerDungeons.size() == 1) - dungeonId = (*playerDungeons.begin()); + LfgDungeonSet const& playerDungeons = sLFGMgr->GetSelectedDungeons(guid); + if (playerDungeons.find(proposal.dungeonId) == playerDungeons.end()) + dungeonEntry = (*playerDungeons.begin()); } - if (LFGDungeonEntry const* dungeon = sLFGMgr->GetLFGDungeon(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; - } - } - } - } + if (LFGDungeonEntry const* dungeon = sLFGMgr->GetLFGDungeon(dungeonEntry)) + dungeonEntry = dungeon->Entry(); - data << uint32(dungeonId); // Dungeon - data << uint8(proposal.state); // Result state - data << uint32(proposalId); // Internal Proposal ID - data << uint32(completedEncounters); // Bosses killed - data << uint8(isSameDungeon); // Silent (show client window) + data << uint32(dungeonEntry); // Dungeon + data << uint8(proposal.state); // Proposal state + data << uint32(proposalId); // Proposal ID + data << uint32(proposal.encounters); // encounters done + data << uint8(silent); // Show proposal window data << uint8(proposal.players.size()); // Group size - for (itPlayer = proposal.players.begin(); itPlayer != proposal.players.end(); ++itPlayer) + for (LfgProposalPlayerMap::const_iterator it = proposal.players.begin(); it != proposal.players.end(); ++it) { - ppPlayer = itPlayer->second; - data << uint32(ppPlayer->role); // Role - data << uint8(itPlayer->first == guid); // Self player - if (!ppPlayer->groupLowGuid) // Player not it a group + LfgProposalPlayer const& player = it->second; + data << uint32(player.role); // Role + data << uint8(it->first == guid); // Self player + if (!player.group) // Player not it a group { data << uint8(0); // Not in dungeon data << uint8(0); // Not same group } else { - data << uint8(ppPlayer->groupLowGuid == dLowGuid); // In dungeon (silent) - data << uint8(ppPlayer->groupLowGuid == pLowGroupGuid); // Same Group than player + data << uint8(player.group == proposal.group); // In dungeon (silent) + data << uint8(player.group == gguid); // Same Group than player } - data << uint8(ppPlayer->accept != LFG_ANSWER_PENDING); // Answered - data << uint8(ppPlayer->accept == LFG_ANSWER_AGREE); // Accepted + data << uint8(player.accept != LFG_ANSWER_PENDING); // Answered + data << uint8(player.accept == LFG_ANSWER_AGREE); // Accepted } SendPacket(&data); } diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h index 5893bbd6564..ee3be6f2b2d 100755 --- a/src/server/game/Miscellaneous/Language.h +++ b/src/server/game/Miscellaneous/Language.h @@ -1076,7 +1076,22 @@ enum TrinityStrings // Use for custom patches 11000-11999 LANG_AUTO_BROADCAST = 11000, - LANG_INVALID_REALMID = 11001 + LANG_INVALID_REALMID = 11001, + + LANG_LFG_STATE_NONE = 11002, + LANG_LFG_STATE_ROLECHECK = 11003, + LANG_LFG_STATE_QUEUED = 11004, + LANG_LFG_STATE_PROPOSAL = 11005, + LANG_LFG_STATE_BOOT = 11006, + LANG_LFG_STATE_DUNGEON = 11007, + LANG_LFG_STATE_FINISHED_DUNGEON = 11008, + LANG_LFG_STATE_RAIDBROWSER = 11009, + LANG_LFG_ROLE_TANK = 11010, + LANG_LFG_ROLE_HEALER = 11011, + LANG_LFG_ROLE_DAMAGE = 11012, + LANG_LFG_ROLE_LEADER = 11013, + LANG_LFG_ROLE_NONE = 11014, + LANG_LFG_ERROR = 11015, // NOT RESERVED IDS 12000-1999999999 // `db_script_string` table index 2000000000-2000009999 (MIN_DB_SCRIPT_STRING_ID-MAX_DB_SCRIPT_STRING_ID) -- cgit v1.2.3 From 4e8fa520c8aca831580fba9bf762486b9a9d7ed0 Mon Sep 17 00:00:00 2001 From: Spp Date: Fri, 19 Oct 2012 14:00:40 +0200 Subject: Core/Dungeon Finder: Move queue related code to its own class. - Use different queues for each team (or shared one if two-side interaction is enabled) - Some optimizations in matching algorithm --- src/server/game/DungeonFinding/LFGMgr.cpp | 709 ++++------------------- src/server/game/DungeonFinding/LFGMgr.h | 60 +- src/server/game/DungeonFinding/LFGPlayerData.cpp | 3 + src/server/game/DungeonFinding/LFGQueue.cpp | 539 +++++++++++++++++ src/server/game/DungeonFinding/LFGQueue.h | 139 +++++ src/server/game/DungeonFinding/LFGScripts.cpp | 46 +- src/server/game/Groups/Group.cpp | 2 +- src/server/game/Miscellaneous/SharedDefines.h | 7 +- 8 files changed, 817 insertions(+), 688 deletions(-) create mode 100644 src/server/game/DungeonFinding/LFGQueue.cpp create mode 100644 src/server/game/DungeonFinding/LFGQueue.h (limited to 'src') diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp index af12ce93c65..16fda8952ac 100755 --- a/src/server/game/DungeonFinding/LFGMgr.cpp +++ b/src/server/game/DungeonFinding/LFGMgr.cpp @@ -18,19 +18,18 @@ #include "Common.h" #include "SharedDefines.h" #include "DBCStores.h" -#include "Containers.h" #include "DisableMgr.h" #include "ObjectMgr.h" #include "SocialMgr.h" #include "LFGMgr.h" -#include "GroupMgr.h" -#include "GameEventMgr.h" #include "LFGScripts.h" #include "LFGGroupData.h" #include "LFGPlayerData.h" - +#include "LFGQueue.h" #include "Group.h" #include "Player.h" +#include "GroupMgr.h" +#include "GameEventMgr.h" LFGMgr::LFGMgr(): m_QueueTimer(0), m_lfgProposalId(1), m_options(sWorld->getBoolConfig(CONFIG_DUNGEON_FINDER_ENABLE)), @@ -43,12 +42,6 @@ LFGMgr::~LFGMgr() delete itr->second; delete m_lfgPlayerScript; delete m_lfgGroupScript; - - for (LfgQueueInfoMap::iterator it = m_QueueInfoMap.begin(); it != m_QueueInfoMap.end(); ++it) - delete it->second; - - for (LfgProposalMap::iterator it = m_Proposals.begin(); it != m_Proposals.end(); ++it) - delete it->second; } void LFGMgr::_LoadFromDB(Field* fields, uint64 guid) @@ -385,7 +378,7 @@ void LFGMgr::Update(uint32 diff) for (LfgProposalMap::iterator it = m_Proposals.begin(); it != m_Proposals.end();) { LfgProposalMap::iterator itRemove = it++; - if (itRemove->second->cancelTime < currTime) + if (itRemove->second.cancelTime < currTime) RemoveProposal(itRemove, LFG_UPDATETYPE_PROPOSAL_FAILED); } @@ -407,58 +400,37 @@ void LFGMgr::Update(uint32 diff) } } + uint32 lastProposalId = m_lfgProposalId; // Check if a proposal can be formed with the new groups being added - for (LfgGuidListMap::iterator it = m_newToQueue.begin(); it != m_newToQueue.end(); ++it) + for (LfgQueueMap::iterator it = m_Queues.begin(); it != m_Queues.end(); ++it) + if (uint8 newProposals = it->second.FindGroups()) + sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::Update: Found %u new groups in queue %u", newProposals, it->first); + + if (lastProposalId != m_lfgProposalId) { - uint8 queueId = it->first; - LfgGuidList& newToQueue = it->second; - LfgGuidList& currentQueue = m_currentQueue[queueId]; - LfgGuidList firstNew; - while (!newToQueue.empty()) + // FIXME lastProposalId ? lastProposalId +1 ? + for (LfgProposalMap::const_iterator itProposal = m_Proposals.find(m_lfgProposalId); itProposal != m_Proposals.end(); ++itProposal) { - uint64 frontguid = newToQueue.front(); - sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::Update: QueueId %u: checking [" UI64FMTD "] newToQueue(%u), currentQueue(%u)", queueId, frontguid, uint32(newToQueue.size()), uint32(currentQueue.size())); - firstNew.push_back(frontguid); - newToQueue.pop_front(); + uint32 proposalId = itProposal->first; + LfgProposal& proposal = m_Proposals[proposalId]; - LfgGuidList temporalList = currentQueue; - if (LfgProposal* pProposal = FindNewGroups(firstNew, temporalList)) // Group found! + uint64 guid = 0; + for (LfgProposalPlayerMap::const_iterator itPlayers = proposal.players.begin(); itPlayers != proposal.players.end(); ++itPlayers) { - // Remove groups in the proposal from new and current queues (not from queue map) - for (LfgGuidList::const_iterator itQueue = pProposal->queues.begin(); itQueue != pProposal->queues.end(); ++itQueue) + guid = itPlayers->first; + SetState(guid, LFG_STATE_PROPOSAL); + if (uint64 gguid = GetGroup(guid)) { - currentQueue.remove(*itQueue); - newToQueue.remove(*itQueue); + SetState(gguid, LFG_STATE_PROPOSAL); + SendLfgUpdateParty(guid, LfgUpdateData(LFG_UPDATETYPE_PROPOSAL_BEGIN, GetSelectedDungeons(guid), GetComment(guid))); } - m_Proposals[++m_lfgProposalId] = pProposal; - - uint64 guid = 0; - for (LfgProposalPlayerMap::const_iterator itPlayers = pProposal->players.begin(); itPlayers != pProposal->players.end(); ++itPlayers) - { - guid = itPlayers->first; - SetState(guid, LFG_STATE_PROPOSAL); - if (Player* player = ObjectAccessor::FindPlayer(itPlayers->first)) - { - Group* grp = player->GetGroup(); - if (grp) - { - uint64 gguid = grp->GetGUID(); - SetState(gguid, LFG_STATE_PROPOSAL); - player->GetSession()->SendLfgUpdateParty(LfgUpdateData(LFG_UPDATETYPE_PROPOSAL_BEGIN, GetSelectedDungeons(guid), GetComment(guid))); - } - else - player->GetSession()->SendLfgUpdatePlayer(LfgUpdateData(LFG_UPDATETYPE_PROPOSAL_BEGIN, GetSelectedDungeons(guid), GetComment(guid))); - player->GetSession()->SendLfgUpdateProposal(m_lfgProposalId, *pProposal); - } - } - - if (pProposal->state == LFG_PROPOSAL_SUCCESS) - UpdateProposal(m_lfgProposalId, guid, true); + else + SendLfgUpdatePlayer(guid, LfgUpdateData(LFG_UPDATETYPE_PROPOSAL_BEGIN, GetSelectedDungeons(guid), GetComment(guid))); + SendLfgUpdateProposal(guid, m_lfgProposalId, proposal); } - else - if (std::find(currentQueue.begin(), currentQueue.end(), frontguid) == currentQueue.end()) //already in queue? - currentQueue.push_back(frontguid); // Lfg group not found, add this group to the queue. - firstNew.clear(); + + if (proposal.state == LFG_PROPOSAL_SUCCESS) + UpdateProposal(proposalId, guid, true); } } @@ -466,108 +438,14 @@ void LFGMgr::Update(uint32 diff) if (m_QueueTimer > LFG_QUEUEUPDATE_INTERVAL) { m_QueueTimer = 0; - currTime = time(NULL); - for (LfgQueueInfoMap::const_iterator itQueue = m_QueueInfoMap.begin(); itQueue != m_QueueInfoMap.end(); ++itQueue) - { - LfgQueueInfo* queue = itQueue->second; - if (!queue) - { - sLog->outError(LOG_FILTER_LFG, "LFGMgr::Update: [" UI64FMTD "] queued with null queue info!", itQueue->first); - continue; - } - uint32 dungeonId = (*queue->dungeons.begin()); - uint32 queuedTime = uint32(currTime - queue->joinTime); - uint8 role = PLAYER_ROLE_NONE; - for (LfgRolesMap::const_iterator itPlayer = queue->roles.begin(); itPlayer != queue->roles.end(); ++itPlayer) - role |= itPlayer->second; - role &= ~PLAYER_ROLE_LEADER; - - int32 waitTime = -1; - switch (role) - { - case PLAYER_ROLE_NONE: // Should not happen - just in case - waitTime = -1; - break; - case PLAYER_ROLE_TANK: - waitTime = m_waitTimesTank.time; - break; - case PLAYER_ROLE_HEALER: - waitTime = m_waitTimesHealer.time; - break; - case PLAYER_ROLE_DAMAGE: - waitTime = m_waitTimesDps.time; - break; - default: - waitTime = m_waitTimesAvg.time; - break; - } - - LfgQueueStatusData queueData(dungeonId, waitTime, m_waitTimesAvg.time, m_waitTimesTank.time, - m_waitTimesHealer.time, m_waitTimesDps.time, queuedTime, - queue->tanks, queue->healers, queue->dps); - for (LfgRolesMap::const_iterator itPlayer = queue->roles.begin(); itPlayer != queue->roles.end(); ++itPlayer) - SendLfgQueueStatus(itPlayer->first, queueData); - } + time_t currTime = time(NULL); + for (LfgQueueMap::iterator it = m_Queues.begin(); it != m_Queues.end(); ++it) + it->second.UpdateQueueTimers(currTime); } else m_QueueTimer += diff; } -/** - Add a guid to the queue of guids to be added to main queue. It guid its already - in queue does nothing. If this function is called guid is not in the main queue - (No need to check it here) - - @param[in] guid Player or group guid to add to queue - @param[in] queueId Queue Id to add player/group to -*/ -void LFGMgr::AddToQueue(uint64 guid, uint8 queueId) -{ - if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP)) - queueId = 0; - - LfgGuidList& list = m_newToQueue[queueId]; - if (std::find(list.begin(), list.end(), guid) != list.end()) - sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::AddToQueue: [" UI64FMTD "] already in new queue. ignoring", guid); - else - { - list.push_back(guid); - sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::AddToQueue: [" UI64FMTD "] added to m_newToQueue (size: %u)", guid, uint32(list.size())); - } -} - -/** - Removes a guid from the main and new queues. - - @param[in] guid Player or group guid to add to queue - @return true if guid was found in main queue. -*/ -bool LFGMgr::RemoveFromQueue(uint64 guid) -{ - for (LfgGuidListMap::iterator it = m_currentQueue.begin(); it != m_currentQueue.end(); ++it) - it->second.remove(guid); - - for (LfgGuidListMap::iterator it = m_newToQueue.begin(); it != m_newToQueue.end(); ++it) - it->second.remove(guid); - - RemoveFromCompatibles(guid); - - LfgQueueInfoMap::iterator it = m_QueueInfoMap.find(guid); - if (it != m_QueueInfoMap.end()) - { - delete it->second; - m_QueueInfoMap.erase(it); - sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::RemoveFromQueue: [" UI64FMTD "] removed", guid); - return true; - } - else - { - sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::RemoveFromQueue: [" UI64FMTD "] not in queue", guid); - return false; - } - -} - /** Generate the dungeon lock map for a given player @@ -663,8 +541,8 @@ void LFGMgr::JoinLfg(Player* player, uint8 roles, LfgDungeonSet& dungeons, const } // Already in queue? - LfgQueueInfoMap::iterator itQueue = m_QueueInfoMap.find(gguid); - if (itQueue != m_QueueInfoMap.end()) + LfgState state = GetState(gguid); + if (state == LFG_STATE_QUEUED) { LfgDungeonSet const& playerDungeons = GetSelectedDungeons(guid); if (playerDungeons == dungeons) // Joining the same dungeons -- Send OK @@ -680,7 +558,10 @@ void LFGMgr::JoinLfg(Player* player, uint8 roles, LfgDungeonSet& dungeons, const return; } else // Remove from queue and rejoin - RemoveFromQueue(gguid); + { + LfgQueue& queue = GetQueue(gguid); + queue.RemoveFromQueue(gguid); + } } // Check player or group member restrictions @@ -825,18 +706,10 @@ void LFGMgr::JoinLfg(Player* player, uint8 roles, LfgDungeonSet& dungeons, const } else // Add player to queue { - // Queue player - LfgQueueInfo* pqInfo = new LfgQueueInfo(); - pqInfo->joinTime = time_t(time(NULL)); - pqInfo->roles[player->GetGUID()] = roles; - pqInfo->dungeons = dungeons; - if (roles & PLAYER_ROLE_TANK) - --pqInfo->tanks; - else if (roles & PLAYER_ROLE_HEALER) - --pqInfo->healers; - else - --pqInfo->dps; - m_QueueInfoMap[guid] = pqInfo; + LfgRolesMap rolesMap; + rolesMap[guid] = roles; + LfgQueue& queue = GetQueue(gguid); + queue.AddQueueData(guid, time_t(time(NULL)), dungeons, rolesMap); if (!isContinue) { @@ -853,7 +726,6 @@ void LFGMgr::JoinLfg(Player* player, uint8 roles, LfgDungeonSet& dungeons, const SetState(gguid, LFG_STATE_QUEUED); SetRoles(guid, roles); debugNames.append(player->GetName()); - AddToQueue(guid, uint8(player->GetTeam())); } if (sLog->ShouldLog(LOG_FILTER_LFG, LOG_LEVEL_DEBUG)) @@ -882,7 +754,8 @@ void LFGMgr::LeaveLfg(uint64 guid) case LFG_STATE_QUEUED: if (gguid) { - RemoveFromQueue(gguid); + LfgQueue& queue = GetQueue(gguid); + queue.RemoveFromQueue(gguid); RestoreState(gguid, "Leave queue"); const LfgGuidSet& players = GetPlayers(gguid); for (LfgGuidSet::const_iterator it = players.begin(); it != players.end(); ++it) @@ -894,7 +767,8 @@ void LFGMgr::LeaveLfg(uint64 guid) } else { - RemoveFromQueue(guid); + LfgQueue& queue = GetQueue(guid); + queue.RemoveFromQueue(guid); SendLfgUpdatePlayer(guid, LfgUpdateData(LFG_UPDATETYPE_REMOVED_FROM_QUEUE)); ClearState(guid, "Leave queue"); } @@ -910,8 +784,8 @@ void LFGMgr::LeaveLfg(uint64 guid) uint64 pguid = gguid == guid ? GetLeader(gguid) : guid; while (it != m_Proposals.end()) { - LfgProposalPlayerMap::iterator itPlayer = it->second->players.find(pguid); - if (itPlayer != it->second->players.end()) + LfgProposalPlayerMap::iterator itPlayer = it->second.players.find(pguid); + if (itPlayer != it->second.players.end()) { // Mark the player/leader of group who left as didn't accept the proposal itPlayer->second.accept = LFG_ANSWER_DENY; @@ -930,279 +804,6 @@ void LFGMgr::LeaveLfg(uint64 guid) } } -/** - Checks que main queue to try to form a Lfg group. Returns first match found (if any) - - @param[in] check List of guids trying to match with other groups - @param[in] all List of all other guids in main queue to match against - @return Pointer to proposal, if match is found -*/ -LfgProposal* LFGMgr::FindNewGroups(LfgGuidList& check, LfgGuidList& all) -{ - sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::FindNewGroup: (%s) - all(%s)", ConcatenateGuids(check).c_str(), ConcatenateGuids(all).c_str()); - - LfgProposal* pProposal = NULL; - if (check.empty() || check.size() > MAXGROUPSIZE || !CheckCompatibility(check, pProposal)) - return NULL; - - // Try to match with queued groups - while (!pProposal && !all.empty()) - { - check.push_back(all.front()); - all.pop_front(); - pProposal = FindNewGroups(check, all); - check.pop_back(); - } - return pProposal; -} - -/** - Check compatibilities between groups - - @param[in] check List of guids to check compatibilities - @param[out] pProposal Proposal found if groups are compatibles and Match - @return true if group are compatibles -*/ -bool LFGMgr::CheckCompatibility(LfgGuidList check, LfgProposal*& pProposal) -{ - if (pProposal) // Do not check anything if we already have a proposal - return false; - - std::string strGuids = ConcatenateGuids(check); - - if (check.size() > MAXGROUPSIZE || check.empty()) - { - sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::CheckCompatibility: (%s): Size wrong - Not compatibles", strGuids.c_str()); - return false; - } - - if (check.size() == 1 && IS_PLAYER_GUID(check.front())) // Player joining dungeon... compatible - return true; - - // Previously cached? - LfgAnswer answer = GetCompatibles(strGuids); - if (answer != LFG_ANSWER_PENDING) - { - sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::CheckCompatibility: (%s) compatibles (cached): %d", strGuids.c_str(), answer); - return bool(answer); - } - - // Check all but new compatiblitity - if (check.size() > 2) - { - uint64 frontGuid = check.front(); - check.pop_front(); - - // Check all-but-new compatibilities (New, A, B, C, D) --> check(A, B, C, D) - if (!CheckCompatibility(check, pProposal)) // Group not compatible - { - sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::CheckCompatibility: (%s) not compatibles (%s not compatibles)", strGuids.c_str(), ConcatenateGuids(check).c_str()); - SetCompatibles(strGuids, false); - return false; - } - check.push_front(frontGuid); - // all-but-new compatibles, now check with new - } - - uint8 numPlayers = 0; - uint8 numLfgGroups = 0; - uint64 groupGuid = 0; - LfgQueueInfoMap pqInfoMap; - for (LfgGuidList::const_iterator it = check.begin(); it != check.end() && numLfgGroups < 2 && numPlayers <= MAXGROUPSIZE; ++it) - { - uint64 guid = (*it); - LfgQueueInfoMap::iterator itQueue = m_QueueInfoMap.find(guid); - if (itQueue == m_QueueInfoMap.end() || GetState(guid) != LFG_STATE_QUEUED) - { - sLog->outError(LOG_FILTER_LFG, "LFGMgr::CheckCompatibility: [" UI64FMTD "] is not queued but listed as queued!", (*it)); - RemoveFromQueue(guid); - return false; - } - pqInfoMap[guid] = itQueue->second; - numPlayers += itQueue->second->roles.size(); - - if (IS_GROUP(guid)) - { - if (Group* grp = sGroupMgr->GetGroupByGUID(GUID_LOPART(guid))) - if (grp->isLFGGroup()) - { - if (!numLfgGroups) - groupGuid = guid; - ++numLfgGroups; - } - } - } - - if (check.size() == 1 && numPlayers != MAXGROUPSIZE) // Single group with less than MAXGROUPSIZE - Compatibles - return true; - - // Do not match - groups already in a lfgDungeon or too much players - if (numLfgGroups > 1 || numPlayers > MAXGROUPSIZE) - { - SetCompatibles(strGuids, false); - if (numLfgGroups > 1) - sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::CheckCompatibility: (%s) More than one Lfggroup (%u)", strGuids.c_str(), numLfgGroups); - else - sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::CheckCompatibility: (%s) Too much players (%u)", strGuids.c_str(), numPlayers); - return false; - } - - // ----- Player checks ----- - LfgRolesMap rolesMap; - uint64 leader = 0; - for (LfgQueueInfoMap::const_iterator it = pqInfoMap.begin(); it != pqInfoMap.end(); ++it) - { - for (LfgRolesMap::const_iterator itRoles = it->second->roles.begin(); itRoles != it->second->roles.end(); ++itRoles) - { - // Assign new leader - if (itRoles->second & PLAYER_ROLE_LEADER && (!leader || urand(0, 1))) - leader = itRoles->first; - - rolesMap[itRoles->first] = itRoles->second; - } - } - - if (rolesMap.size() != numPlayers) // Player in multiples queues! - return false; - - LfgGuidSet players; - for (LfgRolesMap::const_iterator it = rolesMap.begin(); it != rolesMap.end(); ++it) - { - uint64 guid = it->first; - LfgRolesMap::const_iterator it2 = ++it; - for (; it2 != rolesMap.end(); ++it2) - if (HasIgnore(guid, it2->first)) - break; - if (it2 == rolesMap.end()) - players.insert(guid); - } - - // if we dont have the same ammount of players then we have self ignoring candidates or different faction groups - // otherwise check if roles are compatible - if (players.size() != numPlayers || !CheckGroupRoles(rolesMap)) - { - if (players.size() == numPlayers) - sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::CheckCompatibility: (%s) Roles not compatible", strGuids.c_str()); - SetCompatibles(strGuids, false); - return false; - } - - // ----- Selected Dungeon checks ----- - // Check if there are any compatible dungeon from the selected dungeons - LfgDungeonSet compatibleDungeons; - - LfgQueueInfoMap::const_iterator itFirst = pqInfoMap.begin(); - for (LfgDungeonSet::const_iterator itDungeon = itFirst->second->dungeons.begin(); itDungeon != itFirst->second->dungeons.end(); ++itDungeon) - { - LfgQueueInfoMap::const_iterator itOther = itFirst; - ++itOther; - while (itOther != pqInfoMap.end() && itOther->second->dungeons.find(*itDungeon) != itOther->second->dungeons.end()) - ++itOther; - - if (itOther == pqInfoMap.end()) - compatibleDungeons.insert(*itDungeon); - } - LfgLockPartyMap lockMap; - GetCompatibleDungeons(compatibleDungeons, players, lockMap); - - if (compatibleDungeons.empty()) - { - SetCompatibles(strGuids, false); - return false; - } - SetCompatibles(strGuids, true); - - // ----- Group is compatible, if we have MAXGROUPSIZE members then match is found - if (numPlayers != MAXGROUPSIZE) - { - sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::CheckCompatibility: (%s) Compatibles but not match. Players(%u)", strGuids.c_str(), numPlayers); - uint8 Tanks_Needed = LFG_TANKS_NEEDED; - uint8 Healers_Needed = LFG_HEALERS_NEEDED; - uint8 Dps_Needed = LFG_DPS_NEEDED; - for (LfgQueueInfoMap::const_iterator itQueue = pqInfoMap.begin(); itQueue != pqInfoMap.end(); ++itQueue) - { - LfgQueueInfo* queue = itQueue->second; - for (LfgRolesMap::const_iterator itPlayer = queue->roles.begin(); itPlayer != queue->roles.end(); ++itPlayer) - { - uint8 roles = itPlayer->second; - if ((roles & PLAYER_ROLE_TANK) && Tanks_Needed > 0) - --Tanks_Needed; - else if ((roles & PLAYER_ROLE_HEALER) && Healers_Needed > 0) - --Healers_Needed; - else if ((roles & PLAYER_ROLE_DAMAGE) && Dps_Needed > 0) - --Dps_Needed; - } - } - - for (LfgGuidSet::const_iterator itPlayers = players.begin(); itPlayers != players.end(); ++itPlayers) - { - for (LfgQueueInfoMap::const_iterator itQueue = pqInfoMap.begin(); itQueue != pqInfoMap.end(); ++itQueue) - { - if (LfgQueueInfo* queue = itQueue->second) - { - LfgRolesMap::const_iterator itPlayer = queue->roles.find(*itPlayers); - if (itPlayer != queue->roles.end()) - { - queue->tanks = Tanks_Needed; - queue->healers = Healers_Needed; - queue->dps = Dps_Needed; - } - } - } - } - - return true; - } - sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::CheckCompatibility: (%s) MATCH! Group formed", strGuids.c_str()); - - // GROUP FORMED! - // TODO - Improve algorithm to select proper group based on Item Level - // Do not match bad tank and bad healer on same group - - // Select a random dungeon from the compatible list - // TODO - Select the dungeon based on group item Level, not just random - // Create a new proposal - pProposal = new LfgProposal(Trinity::Containers::SelectRandomContainerElement(compatibleDungeons)); - pProposal->cancelTime = time_t(time(NULL)) + LFG_TIME_PROPOSAL; - pProposal->state = LFG_PROPOSAL_INITIATING; - pProposal->queues = check; - pProposal->group = groupGuid; - pProposal->isNew = true; - - // Assign new roles to players and assign new leader - LfgGuidSet::const_iterator itPlayers = players.begin(); - if (!leader) - { - uint8 pos = uint8(urand(0, players.size() - 1)); - for (uint8 i = 0; i < pos; ++i) - ++itPlayers; - leader = *itPlayers; - } - pProposal->leader = leader; - - uint8 numAccept = 0; - for (itPlayers = players.begin(); itPlayers != players.end(); ++itPlayers) - { - uint64 guid = *itPlayers; - LfgProposalPlayer& player = pProposal->players[guid]; - uint64 gguid = GetGroup(guid); - player.group = gguid; - if (gguid == groupGuid) - { - player.accept = LFG_ANSWER_AGREE; - ++numAccept; - } - player.role = rolesMap[guid]; - if (pProposal->group && pProposal->group != gguid) - pProposal->isNew = false; - } - - if (numAccept == MAXGROUPSIZE) - pProposal->state = LFG_PROPOSAL_SUCCESS; - - return true; -} - /** Update the Role check info with the player selected role. @@ -1254,15 +855,6 @@ void LFGMgr::UpdateRoleCheck(uint64 gguid, uint64 guid /* = 0 */, uint8 roles /* for (LfgRolesMap::const_iterator it = roleCheck.roles.begin(); it != roleCheck.roles.end(); ++it) { uint64 pguid = it->first; - Player* plrg = ObjectAccessor::FindPlayer(pguid); - if (!plrg) - { - if (roleCheck.state == LFG_ROLECHECK_FINISHED) - SetState(pguid, LFG_STATE_QUEUED); - else if (roleCheck.state != LFG_ROLECHECK_INITIALITING) - ClearState(pguid, "Offline while Rolecheck"); - continue; - } if (!sendRoleChosen) SendLfgRoleChosen(pguid, guid, roles); @@ -1274,6 +866,7 @@ void LFGMgr::UpdateRoleCheck(uint64 gguid, uint64 guid /* = 0 */, uint8 roles /* continue; case LFG_ROLECHECK_FINISHED: SetState(pguid, LFG_STATE_QUEUED); + SetRoles(pguid, it->second); SendLfgUpdateParty(pguid, LfgUpdateData(LFG_UPDATETYPE_ADDED_TO_QUEUE, dungeons, GetComment(pguid))); break; default: @@ -1288,84 +881,13 @@ void LFGMgr::UpdateRoleCheck(uint64 gguid, uint64 guid /* = 0 */, uint8 roles /* if (roleCheck.state == LFG_ROLECHECK_FINISHED) { SetState(gguid, LFG_STATE_QUEUED); - LfgQueueInfo* pqInfo = new LfgQueueInfo(); - pqInfo->joinTime = time_t(time(NULL)); - pqInfo->roles = roleCheck.roles; - pqInfo->dungeons = roleCheck.dungeons; - - // Set queue roles needed - As we are using check_roles will not have more that 1 tank, 1 healer, 3 dps - for (LfgRolesMap::const_iterator it = check_roles.begin(); it != check_roles.end(); ++it) - { - uint8 roles2 = it->second; - if (roles2 & PLAYER_ROLE_TANK) - --pqInfo->tanks; - else if (roles2 & PLAYER_ROLE_HEALER) - --pqInfo->healers; - else - --pqInfo->dps; - } - - uint8 team = GetTeam(guid); - m_QueueInfoMap[gguid] = pqInfo; - if (GetState(gguid) != LFG_STATE_NONE) - { - LfgGuidList& currentQueue = m_currentQueue[team]; - currentQueue.push_front(gguid); - } - AddToQueue(gguid, team); + LfgQueue& queue = GetQueue(gguid); + queue.AddQueueData(gguid, time_t(time(NULL)), roleCheck.dungeons, roleCheck.roles); } else if (roleCheck.state != LFG_ROLECHECK_INITIALITING) - { RestoreState(gguid, "Rolecheck Failed"); - m_RoleChecks.erase(itRoleCheck); - } -} - -/** - Remove from cached compatible dungeons any entry that contains the given guid - @param[in] guid Guid to remove from compatible cache -*/ -void LFGMgr::RemoveFromCompatibles(uint64 guid) -{ - std::stringstream out; - out << guid; - std::string strGuid = out.str(); - - sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::RemoveFromCompatibles: Removing [" UI64FMTD "]", guid); - for (LfgCompatibleMap::iterator itNext = m_CompatibleMap.begin(); itNext != m_CompatibleMap.end();) - { - LfgCompatibleMap::iterator it = itNext++; - if (it->first.find(strGuid) != std::string::npos) // Found, remove it - m_CompatibleMap.erase(it); - } -} - -/** - Stores the compatibility of a list of guids - - @param[in] key String concatenation of guids (| used as separator) - @param[in] compatibles Compatibles or not -*/ -void LFGMgr::SetCompatibles(std::string key, bool compatibles) -{ - m_CompatibleMap[key] = LfgAnswer(compatibles); -} - -/** - Get the compatibility of a group of guids - - @param[in] key String concatenation of guids (| used as separator) - @return 1 (Compatibles), 0 (Not compatibles), -1 (Not set) -*/ -LfgAnswer LFGMgr::GetCompatibles(std::string key) -{ - LfgAnswer answer = LFG_ANSWER_PENDING; - LfgCompatibleMap::iterator it = m_CompatibleMap.find(key); - if (it != m_CompatibleMap.end()) - answer = it->second; - - return answer; + m_RoleChecks.erase(itRoleCheck); } /** @@ -1487,7 +1009,7 @@ void LFGMgr::MakeNewGroup(const LfgProposal& proposal) else players.push_back(guid); - if (GetGroup(guid) != proposal.group || GetState(proposal.group) == LFG_STATE_FINISHED_DUNGEON) + if (proposal.isNew || GetGroup(guid) != proposal.group) playersToTeleport.push_back(guid); } @@ -1520,7 +1042,6 @@ void LFGMgr::MakeNewGroup(const LfgProposal& proposal) grp->AddMember(player); grp->SetLfgRoles(pguid, proposal.players.find(pguid)->second.role); - SetState(pguid, LFG_STATE_DUNGEON); // Add the cooldown spell if queued for a random dungeon if (dungeon->type == LFG_TYPE_RANDOM) @@ -1543,6 +1064,12 @@ void LFGMgr::MakeNewGroup(const LfgProposal& proposal) grp->SendUpdate(); } +uint32 LFGMgr::AddProposal(LfgProposal const& proposal) +{ + m_Proposals[++m_lfgProposalId] = proposal; + return m_lfgProposalId; +} + /** Update Proposal info with player answer @@ -1557,7 +1084,7 @@ void LFGMgr::UpdateProposal(uint32 proposalId, uint64 guid, bool accept) if (itProposal == m_Proposals.end()) return; - LfgProposal& proposal = *(itProposal->second); + LfgProposal& proposal = itProposal->second; // Check if proposal have the current player LfgProposalPlayerMap::iterator itProposalPlayer = proposal.players.find(guid); @@ -1594,26 +1121,30 @@ void LFGMgr::UpdateProposal(uint32 proposalId, uint64 guid, bool accept) proposal.state = LFG_PROPOSAL_SUCCESS; time_t joinTime = time_t(time(NULL)); + LfgQueue& queue = GetQueue(guid); LfgUpdateData updateData = LfgUpdateData(LFG_UPDATETYPE_GROUP_FOUND); for (LfgProposalPlayerMap::const_iterator it = proposal.players.begin(); it != proposal.players.end(); ++it) { uint64 pguid = it->first; uint64 gguid = it->second.group; + uint32 dungeonId = (*GetSelectedDungeons(pguid).begin()); int32 waitTime = -1; if (sendUpdate) SendLfgUpdateProposal(pguid, proposalId, proposal); if (gguid) { + waitTime = int32((joinTime - queue.GetJoinTime(gguid)) / IN_MILLISECONDS); SendLfgUpdateParty(pguid, updateData); } else + { + waitTime = int32((joinTime - queue.GetJoinTime(pguid)) / IN_MILLISECONDS); SendLfgUpdatePlayer(pguid, updateData); - - uint64 guid2 = gguid ? gguid : pguid; - LfgQueueInfoMap::iterator itQueue = m_QueueInfoMap.find(guid2); - if (itQueue != m_QueueInfoMap.end()) - waitTime = int32(joinTime - itQueue->second->joinTime); + } + updateData.updateType = LFG_UPDATETYPE_REMOVED_FROM_QUEUE; + SendLfgUpdatePlayer(pguid, updateData); + SendLfgUpdateParty(pguid, updateData); // Update timers uint8 role = GetRoles(pguid); @@ -1621,16 +1152,16 @@ void LFGMgr::UpdateProposal(uint32 proposalId, uint64 guid, bool accept) switch (role) { case PLAYER_ROLE_DAMAGE: - UpdateWaitTimeDps(waitTime); + queue.UpdateWaitTimeDps(waitTime, dungeonId); break; case PLAYER_ROLE_HEALER: - UpdateWaitTimeHealer(waitTime); + queue.UpdateWaitTimeHealer(waitTime, dungeonId); break; case PLAYER_ROLE_TANK: - UpdateWaitTimeTank(waitTime); + queue.UpdateWaitTimeTank(waitTime, dungeonId); break; default: - UpdateWaitTimeAvg(waitTime); + queue.UpdateWaitTimeAvg(waitTime, dungeonId); break; } @@ -1640,10 +1171,9 @@ void LFGMgr::UpdateProposal(uint32 proposalId, uint64 guid, bool accept) // Remove players/groups from Queue for (LfgGuidList::const_iterator it = proposal.queues.begin(); it != proposal.queues.end(); ++it) - RemoveFromQueue(*it); + queue.RemoveFromQueue(*it); MakeNewGroup(proposal); - delete itProposal->second; m_Proposals.erase(itProposal); } @@ -1655,7 +1185,7 @@ void LFGMgr::UpdateProposal(uint32 proposalId, uint64 guid, bool accept) */ void LFGMgr::RemoveProposal(LfgProposalMap::iterator itProposal, LfgUpdateType type) { - LfgProposal& proposal = *(itProposal->second); + LfgProposal& proposal = itProposal->second; proposal.state = LFG_PROPOSAL_FAILED; sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::RemoveProposal: Proposal %u, state FAILED, UpdateType %u", itProposal->first, type); @@ -1725,11 +1255,12 @@ void LFGMgr::RemoveProposal(LfgProposalMap::iterator itProposal, LfgUpdateType t } } + LfgQueue& queue = GetQueue(proposal.players.begin()->first); // Remove players/groups from queue for (LfgGuidSet::const_iterator it = toRemove.begin(); it != toRemove.end(); ++it) { uint64 guid = *it; - RemoveFromQueue(guid); + queue.RemoveFromQueue(guid); proposal.queues.remove(guid); } @@ -1737,13 +1268,9 @@ void LFGMgr::RemoveProposal(LfgProposalMap::iterator itProposal, LfgUpdateType t for (LfgGuidList::const_iterator it = proposal.queues.begin(); it != proposal.queues.end(); ++it) { uint64 guid = *it; - uint8 team = GetTeam(guid); - LfgGuidList& currentQueue = m_currentQueue[team]; - currentQueue.push_front(guid); //Add GUID for high priority - AddToQueue(guid, team); //We have to add each GUID in newQueue to check for a new groups + queue.AddToQueue(guid); } - delete itProposal->second; m_Proposals.erase(itProposal); } @@ -1838,16 +1365,7 @@ void LFGMgr::UpdateBoot(uint64 guid, bool accept) if (agreeNum == LFG_GROUP_KICK_VOTES_NEEDED) // Vote passed - Kick player { if (Group* group = sGroupMgr->GetGroupByGUID(GUID_LOPART(gguid))) - Player::RemoveFromGroup(group, boot.victim); - - if (Player* victim = ObjectAccessor::FindPlayer(boot.victim)) - { - TeleportPlayer(victim, true, false); - SetState(boot.victim, LFG_STATE_NONE); - } - - if (Player* leader = ObjectAccessor::FindPlayer(sLFGMgr->GetLeader(gguid))) - leader->GetSession()->SendLfgOfferContinue(GetDungeon(gguid, false)); + Player::RemoveFromGroup(group, boot.victim, GROUP_REMOVEMETHOD_KICK_LFG); DecreaseKicksLeft(gguid); } m_Boots.erase(itBoot); @@ -2338,6 +1856,32 @@ bool LFGMgr::IsLfgGroup(uint64 guid) return guid && IS_GROUP(guid) && m_Groups[guid].IsLfgGroup(); } +LfgQueue& LFGMgr::GetQueue(uint64 guid) +{ + uint8 queueId = 0; + if (IS_GROUP(guid)) + { + const LfgGuidSet& players = GetPlayers(guid); + uint64 pguid = players.empty() ? 0 : (*players.begin()); + if (pguid) + queueId = GetTeam(pguid); + } + else + queueId = GetTeam(guid); + return m_Queues[queueId]; +} + +bool LFGMgr::AllQueued(const LfgGuidList& check) +{ + if (check.empty()) + return false; + + for (LfgGuidList::const_iterator it = check.begin(); it != check.end(); ++it) + if (GetState(*it) != LFG_STATE_QUEUED) + return false; + return true; +} + bool LFGMgr::IsSeasonActive(uint32 dungeonId) { switch (dungeonId) @@ -2353,50 +1897,3 @@ bool LFGMgr::IsSeasonActive(uint32 dungeonId) } return false; } - -void LFGMgr::UpdateWaitTimeAvg(int32 waitTime) -{ - LfgWaitTime &wt = m_waitTimesAvg; - uint32 old_number = wt.number++; - wt.time = int32((wt.time * old_number + waitTime) / wt.number); -} - -void LFGMgr::UpdateWaitTimeTank(int32 waitTime) -{ - LfgWaitTime &wt = m_waitTimesTank; - uint32 old_number = wt.number++; - wt.time = int32((wt.time * old_number + waitTime) / wt.number); -} - -void LFGMgr::UpdateWaitTimeHealer(int32 waitTime) -{ - LfgWaitTime &wt = m_waitTimesHealer; - uint32 old_number = wt.number++; - wt.time = int32((wt.time * old_number + waitTime) / wt.number); -} - -void LFGMgr::UpdateWaitTimeDps(int32 waitTime) -{ - LfgWaitTime &wt = m_waitTimesDps; - uint32 old_number = wt.number++; - wt.time = int32((wt.time * old_number + waitTime) / wt.number); -} - -/** - Given a list of guids returns the concatenation using | as delimiter - - @param[in] check list of guids - @returns Concatenated string -*/ -std::string LFGMgr::ConcatenateGuids(LfgGuidList check) -{ - if (check.empty()) - return ""; - - std::ostringstream o; - LfgGuidList::const_iterator it = check.begin(); - o << (*it); - for (++it; it != check.end(); ++it) - o << '|' << (*it); - return o.str(); -} \ No newline at end of file diff --git a/src/server/game/DungeonFinding/LFGMgr.h b/src/server/game/DungeonFinding/LFGMgr.h index 756f7094be6..1f9c9cf3b2c 100755 --- a/src/server/game/DungeonFinding/LFGMgr.h +++ b/src/server/game/DungeonFinding/LFGMgr.h @@ -21,7 +21,7 @@ #include "Common.h" #include #include "LFG.h" - +#include "LFGQueue.h" #include "LFGGroupData.h" #include "LFGPlayerData.h" @@ -125,31 +125,19 @@ struct LfgProposal; struct LfgProposalPlayer; struct LfgPlayerBoot; -typedef std::map LfgGuidListMap; -typedef std::set PlayerSet; -typedef std::list LfgPlayerList; -typedef std::map LfgCompatibleMap; -typedef std::map LfgQueueInfoMap; - +typedef std::map LfgQueueMap; typedef std::multimap LfgRewardMap; typedef std::pair LfgRewardMapBounds; typedef std::map LfgCachedDungeonMap; typedef std::map LfgAnswerMap; typedef std::map LfgRoleCheckMap; -typedef std::map LfgProposalMap; +typedef std::map LfgProposalMap; typedef std::map LfgProposalPlayerMap; typedef std::map LfgPlayerBootMap; typedef std::map LfgGroupDataMap; typedef std::map LfgPlayerDataMap; typedef UNORDERED_MAP LFGDungeonMap; -struct LfgWaitTime -{ - LfgWaitTime(): time(-1), number(0) {} - int32 time; ///< Wait time - uint32 number; ///< Number of people used to get that wait time -}; - // Data needed by SMSG_LFG_JOIN_RESULT struct LfgJoinResultData { @@ -215,18 +203,6 @@ struct LfgReward } }; -/// Stores player or group queue info -struct LfgQueueInfo -{ - LfgQueueInfo(): joinTime(0), tanks(LFG_TANKS_NEEDED), healers(LFG_HEALERS_NEEDED), dps(LFG_DPS_NEEDED) {}; - time_t joinTime; ///< Player queue join time (to calculate wait times) - uint8 tanks; ///< Tanks needed - uint8 healers; ///< Healers needed - uint8 dps; ///< Dps needed - LfgDungeonSet dungeons; ///< Selected Player/Group Dungeon/s - LfgRolesMap roles; ///< Selected Player Role/s -}; - /// Stores player data related to proposal to join struct LfgProposalPlayer { @@ -371,6 +347,7 @@ class LFGMgr bool IsTeleported(uint64 guid); + bool AllQueued(LfgGuidList const& check); static bool HasIgnore(uint64 guid1, uint64 guid2); static void SendLfgQueueStatus(uint64 guid, LfgQueueStatusData const& data); @@ -395,29 +372,15 @@ class LFGMgr void SetLockedDungeons(uint64 guid, LfgLockMap const& lock); void DecreaseKicksLeft(uint64 guid); - // Queue - void AddToQueue(uint64 guid, uint8 queueId); - bool RemoveFromQueue(uint64 guid); - // Proposals void RemoveProposal(LfgProposalMap::iterator itProposal, LfgUpdateType type); void MakeNewGroup(LfgProposal const& proposal); - // Group Matching - LfgProposal* FindNewGroups(LfgGuidList& check, LfgGuidList& all); - bool CheckCompatibility(LfgGuidList check, LfgProposal*& pProposal); - void SetCompatibles(std::string concatenatedGuids, bool compatibles); - LfgAnswer GetCompatibles(std::string concatenatedGuids); - // Generic + LfgQueue &GetQueue(uint64 guid); LfgDungeonSet const& GetDungeonsByRandom(uint32 randomdungeon); LfgType GetDungeonType(uint32 dungeon); - std::string ConcatenateGuids(LfgGuidList check); - void RemoveFromCompatibles(uint64 guid); - void UpdateWaitTimeAvg(int32 waitTime); - void UpdateWaitTimeTank(int32 waitTime); - void UpdateWaitTimeHealer(int32 waitTime); - void UpdateWaitTimeDps(int32 waitTime); + void SendLfgBootProposalUpdate(uint64 guid, LfgPlayerBoot const& boot); void SendLfgJoinResult(uint64 guid, LfgJoinResultData const& data); void SendLfgRoleChosen(uint64 guid, uint64 pguid, uint8 roles); @@ -431,6 +394,7 @@ class LFGMgr uint32 m_lfgProposalId; ///< used as internal counter for proposals uint32 m_options; ///< Stores config options + LfgQueueMap m_Queues; ///< Queues LfgCachedDungeonMap m_CachedDungeonMap; ///< Stores all dungeons by groupType // Reward System LfgRewardMap m_RewardMap; ///< Stores rewards for random dungeons @@ -443,16 +407,6 @@ class LFGMgr LfgGroupDataMap m_Groups; ///< Group data LfgGuidList m_teleport; ///< Players being teleported - // Queue - LfgQueueInfoMap m_QueueInfoMap; ///< Queued groups - LfgGuidListMap m_currentQueue; ///< Ordered list. Used to find groups - LfgGuidListMap m_newToQueue; ///< New groups to add to queue - LfgCompatibleMap m_CompatibleMap; ///< Compatible dungeons - LfgWaitTime m_waitTimesAvg; ///< Average wait time to find a group queuing as multiple roles - LfgWaitTime m_waitTimesTank; ///< Average wait time to find a group queuing as tank - LfgWaitTime m_waitTimesHealer; ///< Average wait time to find a group queuing as healer - LfgWaitTime m_waitTimesDps; ///< Average wait time to find a group queuing as dps - LFGPlayerScript *m_lfgPlayerScript; LFGGroupScript *m_lfgGroupScript; }; diff --git a/src/server/game/DungeonFinding/LFGPlayerData.cpp b/src/server/game/DungeonFinding/LFGPlayerData.cpp index 6f030831342..e5645f0f0aa 100644 --- a/src/server/game/DungeonFinding/LFGPlayerData.cpp +++ b/src/server/game/DungeonFinding/LFGPlayerData.cpp @@ -31,6 +31,9 @@ void LfgPlayerData::SetState(LfgState state) { case LFG_STATE_NONE: case LFG_STATE_FINISHED_DUNGEON: + m_Roles = 0; + m_SelectedDungeons.clear(); + // No break on purpose case LFG_STATE_DUNGEON: m_OldState = state; // No break on purpose diff --git a/src/server/game/DungeonFinding/LFGQueue.cpp b/src/server/game/DungeonFinding/LFGQueue.cpp new file mode 100644 index 00000000000..c1d89a16300 --- /dev/null +++ b/src/server/game/DungeonFinding/LFGQueue.cpp @@ -0,0 +1,539 @@ +/* + * Copyright (C) 2008-2012 TrinityCore + * + * This program is free software you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#include "ObjectDefines.h" +#include "Containers.h" +#include "DBCStructure.h" +#include "DBCStores.h" +#include "Group.h" +#include "LFGQueue.h" +#include "LFGMgr.h" +#include "Log.h" +#include "ObjectMgr.h" +#include "World.h" + +/** + Given a list of guids returns the concatenation using | as delimiter + + @param[in] check list of guids + @returns Concatenated string +*/ +std::string ConcatenateGuids(LfgGuidList const& check) +{ + if (check.empty()) + return ""; + + // need the guids in order to avoid duplicates + LfgGuidSet guids(check.begin(), check.end()); + + std::ostringstream o; + + LfgGuidSet::const_iterator it = guids.begin(); + o << (*it); + for (++it; it != guids.end(); ++it) + o << '|' << (*it); + + return o.str(); +} + +char const * GetCompatibleString(LfgCompatibility compatibles) +{ + switch (compatibles) + { + case LFG_COMPATIBILITY_PENDING: + return "Pending"; + case LFG_COMPATIBLES_BAD_STATES: + return "Compatibles (Bad States)"; + case LFG_COMPATIBLES_MATCH: + return "Match"; + case LFG_COMPATIBLES_WITH_LESS_PLAYERS: + return "Compatibles (Not enough players)"; + case LFG_INCOMPATIBLES_HAS_IGNORES: + return "Has ignores"; + case LFG_INCOMPATIBLES_MULTIPLE_LFG_GROUPS: + return "Multiple Lfg Groups"; + case LFG_INCOMPATIBLES_NO_DUNGEONS: + return "Incompatible dungeons"; + case LFG_INCOMPATIBLES_NO_ROLES: + return "Incompatible roles"; + case LFG_INCOMPATIBLES_TOO_MUCH_PLAYERS: + return "Too much players"; + case LFG_INCOMPATIBLES_WRONG_GROUP_SIZE: + return "Wrong group size"; + default: + return "Unknown"; + } +} + +void LfgQueue::AddToQueue(uint64 guid) +{ + LfgQueueDataMap::iterator itQueue = m_QueueDataMap.find(guid); + if (itQueue == m_QueueDataMap.end()) + { + sLog->outError(LOG_FILTER_LFG, "LfgQueue::AddToQueue: Queue data not found for [" UI64FMTD "]", guid); + return; + } + + AddToNewQueue(guid); +} + +void LfgQueue::RemoveFromQueue(uint64 guid) +{ + RemoveFromNewQueue(guid); + RemoveFromCurrentQueue(guid); + RemoveFromCompatibles(guid); + RemoveQueueData(guid); +} + +void LfgQueue::AddToNewQueue(uint64 guid) +{ + m_newToQueue.push_back(guid); +} + +void LfgQueue::RemoveFromNewQueue(uint64 guid) +{ + m_newToQueue.remove(guid); +} + +void LfgQueue::AddToCurrentQueue(uint64 guid) +{ + m_currentQueue.push_back(guid); +} + +void LfgQueue::RemoveFromCurrentQueue(uint64 guid) +{ + m_currentQueue.remove(guid); +} + +void LfgQueue::AddQueueData(uint64 guid, time_t joinTime, const LfgDungeonSet &dungeons, const LfgRolesMap &rolesMap) +{ + m_QueueDataMap[guid] = LfgQueueData(joinTime, dungeons, rolesMap); + AddToQueue(guid); +} + +void LfgQueue::RemoveQueueData(uint64 guid) +{ + LfgQueueDataMap::iterator it = m_QueueDataMap.find(guid); + if (it != m_QueueDataMap.end()) + m_QueueDataMap.erase(it); +} + +void LfgQueue::UpdateWaitTimeAvg(int32 waitTime, uint32 dungeonId) +{ + LfgWaitTime &wt = m_waitTimesAvg[dungeonId]; + uint32 old_number = wt.number++; + wt.time = int32((wt.time * old_number + waitTime) / wt.number); +} + +void LfgQueue::UpdateWaitTimeTank(int32 waitTime, uint32 dungeonId) +{ + LfgWaitTime &wt = m_waitTimesTank[dungeonId]; + uint32 old_number = wt.number++; + wt.time = int32((wt.time * old_number + waitTime) / wt.number); +} + +void LfgQueue::UpdateWaitTimeHealer(int32 waitTime, uint32 dungeonId) +{ + LfgWaitTime &wt = m_waitTimesHealer[dungeonId]; + uint32 old_number = wt.number++; + wt.time = int32((wt.time * old_number + waitTime) / wt.number); +} + +void LfgQueue::UpdateWaitTimeDps(int32 waitTime, uint32 dungeonId) +{ + LfgWaitTime &wt = m_waitTimesDps[dungeonId]; + uint32 old_number = wt.number++; + wt.time = int32((wt.time * old_number + waitTime) / wt.number); +} + +/** + Remove from cached compatible dungeons any entry that contains the given guid + + @param[in] guid Guid to remove from compatible cache +*/ +void LfgQueue::RemoveFromCompatibles(uint64 guid) +{ + std::stringstream out; + out << guid; + std::string strGuid = out.str(); + + sLog->outDebug(LOG_FILTER_LFG, "LfgQueue::RemoveFromCompatibles: Removing [" UI64FMTD "]", guid); + for (LfgCompatibleMap::iterator itNext = m_CompatibleMap.begin(); itNext != m_CompatibleMap.end();) + { + LfgCompatibleMap::iterator it = itNext++; + if (it->first.find(strGuid) != std::string::npos) // Found, remove it + m_CompatibleMap.erase(it); + } +} + + +/** + Stores the compatibility of a list of guids + + @param[in] key String concatenation of guids (| used as separator) + @param[in] compatibles type of compatibility +*/ +void LfgQueue::SetCompatibles(const std::string &key, LfgCompatibility compatibles) +{ + m_CompatibleMap[key] = compatibles; +} + +/** + Get the compatibility of a group of guids + + @param[in] key String concatenation of guids (| used as separator) + @return LfgCompatibility type of compatibility +*/ +LfgCompatibility LfgQueue::GetCompatibles(std::string const& key) +{ + LfgCompatibleMap::iterator it = m_CompatibleMap.find(key); + if (it != m_CompatibleMap.end()) + return it->second; + + return LFG_COMPATIBILITY_PENDING; +} + +uint8 LfgQueue::FindGroups() +{ + uint8 proposals = 0; + LfgGuidList firstNew; + while (!m_newToQueue.empty()) + { + uint64 frontguid = m_newToQueue.front(); + sLog->outDebug(LOG_FILTER_LFG, "LfgQueue::FindGroups: checking [" UI64FMTD "] newToQueue(%u), currentQueue(%u)", frontguid, uint32(m_newToQueue.size()), uint32(m_currentQueue.size())); + firstNew.clear(); + firstNew.push_back(frontguid); + RemoveFromNewQueue(frontguid); + + LfgGuidList temporalList = m_currentQueue; + LfgCompatibility compatibles = FindNewGroups(firstNew, temporalList); + + if (compatibles == LFG_COMPATIBLES_MATCH) + ++proposals; + else + AddToCurrentQueue(frontguid); // Lfg group not found, add this group to the queue. + } + return proposals; +} + +/** + Checks que main queue to try to form a Lfg group. Returns first match found (if any) + + @param[in] check List of guids trying to match with other groups + @param[in] all List of all other guids in main queue to match against + @return LfgCompatibility type of compatibility between groups +*/ +LfgCompatibility LfgQueue::FindNewGroups(LfgGuidList& check, LfgGuidList& all) +{ + std::string strGuids = ConcatenateGuids(check); + LfgCompatibility compatibles = GetCompatibles(strGuids); + + sLog->outDebug(LOG_FILTER_LFG, "LFGQueue::FindNewGroup: (%s): %s - all(%s)", strGuids.c_str(), GetCompatibleString(compatibles), ConcatenateGuids(all).c_str()); + if (compatibles == LFG_COMPATIBILITY_PENDING || compatibles == LFG_COMPATIBLES_BAD_STATES) // Not previously cached, calculate + compatibles = CheckCompatibility(check); + + if (compatibles != LFG_COMPATIBLES_WITH_LESS_PLAYERS) + return compatibles; + + // Try to match with queued groups + while (!all.empty()) + { + check.push_back(all.front()); + all.pop_front(); + LfgCompatibility subcompatibility = FindNewGroups(check, all); + if (subcompatibility == LFG_COMPATIBLES_MATCH) + return LFG_COMPATIBLES_MATCH; + check.pop_back(); + } + return compatibles; +} + +/** + Check compatibilities between groups. If group is Matched proposal will be created + + @param[in] check List of guids to check compatibilities + @return LfgCompatibility type of compatibility +*/ +LfgCompatibility LfgQueue::CheckCompatibility(LfgGuidList check) +{ + std::string strGuids = ConcatenateGuids(check); + LfgProposal proposal; + LfgDungeonSet proposalDungeons; + LfgGroupsMap proposalGroups; + LfgRolesMap proposalRoles; + + // Check for correct size + if (check.size() > MAXGROUPSIZE || check.empty()) + { + sLog->outDebug(LOG_FILTER_LFG, "LFGQueue::CheckCompatibility: (%s): Size wrong - Not compatibles", strGuids.c_str()); + return LFG_INCOMPATIBLES_WRONG_GROUP_SIZE; + } + + // Player joining alone always compatible + if (check.size() == 1 && IS_PLAYER_GUID(check.front())) + return LFG_COMPATIBLES_WITH_LESS_PLAYERS; + + // Check all-but-new compatiblitity + if (check.size() > 2) + { + uint64 frontGuid = check.front(); + check.pop_front(); + + // Check all-but-new compatibilities (New, A, B, C, D) --> check(A, B, C, D) + LfgCompatibility child_compatibles = CheckCompatibility(check); + if (child_compatibles < LFG_COMPATIBLES_WITH_LESS_PLAYERS) // Group not compatible + { + sLog->outDebug(LOG_FILTER_LFG, "LFGQueue::CheckCompatibility: (%s) child %s not compatibles", strGuids.c_str(), ConcatenateGuids(check).c_str()); + SetCompatibles(strGuids, child_compatibles); + return child_compatibles; + } + check.push_front(frontGuid); + } + + // Check if more than one LFG group and number of players joining + uint8 numPlayers = 0; + uint8 numLfgGroups = 0; + for (LfgGuidList::const_iterator it = check.begin(); it != check.end() && numLfgGroups < 2 && numPlayers <= MAXGROUPSIZE; ++it) + { + uint64 guid = (*it); + LfgQueueDataMap::iterator itQueue = m_QueueDataMap.find(guid); + if (itQueue == m_QueueDataMap.end()) + { + sLog->outError(LOG_FILTER_LFG, "LFGQueue::CheckCompatibility: [" UI64FMTD "] is not queued but listed as queued!", guid); + RemoveFromQueue(guid); + return LFG_COMPATIBILITY_PENDING; + } + + // Store group so we don't need to call Mgr to get it later (if it's player group will be 0 otherwise would have joined as group) + for (LfgRolesMap::const_iterator it2 = itQueue->second.roles.begin(); it2 != itQueue->second.roles.end(); ++it2) + proposalGroups[it2->first] = IS_GROUP(itQueue->first) ? itQueue->first : 0; + + numPlayers += itQueue->second.roles.size(); + + if (sLFGMgr->IsLfgGroup(guid)) + { + if (!numLfgGroups) + proposal.group = guid; + ++numLfgGroups; + } + } + + // Group with less that MAXGROUPSIZE members always compatible + if (check.size() == 1 && numPlayers != MAXGROUPSIZE) + { + sLog->outDebug(LOG_FILTER_LFG, "LFGQueue::CheckCompatibility: (%s) sigle group. Compatibles", strGuids.c_str()); + return LFG_COMPATIBLES_WITH_LESS_PLAYERS; + } + + if (numLfgGroups > 1) + { + sLog->outDebug(LOG_FILTER_LFG, "LFGQueue::CheckCompatibility: (%s) More than one Lfggroup (%u)", strGuids.c_str(), numLfgGroups); + SetCompatibles(strGuids, LFG_INCOMPATIBLES_MULTIPLE_LFG_GROUPS); + return LFG_INCOMPATIBLES_MULTIPLE_LFG_GROUPS; + } + + if (numPlayers > MAXGROUPSIZE) + { + sLog->outDebug(LOG_FILTER_LFG, "LFGQueue::CheckCompatibility: (%s) Too much players (%u)", strGuids.c_str(), numPlayers); + SetCompatibles(strGuids, LFG_INCOMPATIBLES_TOO_MUCH_PLAYERS); + return LFG_INCOMPATIBLES_TOO_MUCH_PLAYERS; + } + + // If it's single group no need to check for duplicate players, ignores, bad roles or bad dungeons as it's been checked before joining + if (check.size() > 1) + { + for (LfgGuidList::const_iterator it = check.begin(); it != check.end(); ++it) + { + const LfgRolesMap &roles = m_QueueDataMap[(*it)].roles; + for (LfgRolesMap::const_iterator itRoles = roles.begin(); itRoles != roles.end(); ++itRoles) + { + LfgRolesMap::const_iterator itPlayer; + for (itPlayer = proposalRoles.begin(); itPlayer != proposalRoles.end(); ++itPlayer) + { + if (itRoles->first == itPlayer->first) + sLog->outDebug(LOG_FILTER_LFG, "LFGQueue::CheckCompatibility: ERROR! Player multiple times in queue! [" UI64FMTD "]", itRoles->first); + else if (sLFGMgr->HasIgnore(itRoles->first, itPlayer->first)) + break; + } + if (itPlayer == proposalRoles.end()) + proposalRoles[itRoles->first] = itRoles->second; + } + } + + if (uint8 playersize = numPlayers - proposalRoles.size()) + { + sLog->outDebug(LOG_FILTER_LFG, "LFGQueue::CheckCompatibility: (%s) not compatible, %u players are ignoring each other", strGuids.c_str(), playersize); + SetCompatibles(strGuids, LFG_INCOMPATIBLES_HAS_IGNORES); + return LFG_INCOMPATIBLES_HAS_IGNORES; + } + + LfgRolesMap debugRoles = proposalRoles; // DEBUG + if (!LFGMgr::CheckGroupRoles(proposalRoles)) + { + std::ostringstream o; + for (LfgRolesMap::const_iterator it = debugRoles.begin(); it != debugRoles.end(); ++it) + o << ", " << it->first << ": " << sLFGMgr->GetRolesString(it->second); + + sLog->outDebug(LOG_FILTER_LFG, "LFGQueue::CheckCompatibility: (%s) Roles not compatible%s", strGuids.c_str(), o.str().c_str()); + SetCompatibles(strGuids, LFG_INCOMPATIBLES_NO_ROLES); + return LFG_INCOMPATIBLES_NO_ROLES; + } + + LfgGuidList::iterator itguid = check.begin(); + proposalDungeons = m_QueueDataMap[*itguid].dungeons; + std::ostringstream o; + o << ", " << *itguid << ": (" << sLFGMgr->ConcatenateDungeons(proposalDungeons) << ")"; + for (++itguid; itguid != check.end(); ++itguid) + { + LfgDungeonSet temporal; + LfgDungeonSet &dungeons = m_QueueDataMap[*itguid].dungeons; + o << ", " << *itguid << ": (" << sLFGMgr->ConcatenateDungeons(dungeons) << ")"; + std::set_intersection(proposalDungeons.begin(), proposalDungeons.end(), dungeons.begin(), dungeons.end(), std::inserter(temporal, temporal.begin())); + proposalDungeons = temporal; + } + + if (proposalDungeons.empty()) + { + sLog->outDebug(LOG_FILTER_LFG, "LFGQueue::CheckCompatibility: (%s) No compatible dungeons%s", strGuids.c_str(), o.str().c_str()); + SetCompatibles(strGuids, LFG_INCOMPATIBLES_NO_DUNGEONS); + return LFG_INCOMPATIBLES_NO_DUNGEONS; + } + } + else + { + uint64 gguid = *check.begin(); + const LfgQueueData &queue = m_QueueDataMap[gguid]; + proposalDungeons = queue.dungeons; + proposalRoles = queue.roles; + LFGMgr::CheckGroupRoles(proposalRoles); // assing new roles + } + + // Enough players? + if (numPlayers != MAXGROUPSIZE) + { + sLog->outDebug(LOG_FILTER_LFG, "LFGQueue::CheckCompatibility: (%s) Compatibles but not enough players(%u)", strGuids.c_str(), numPlayers); + SetCompatibles(strGuids, LFG_COMPATIBLES_WITH_LESS_PLAYERS); + return LFG_COMPATIBLES_WITH_LESS_PLAYERS; + } + + proposal.queues = check; + if (check.size() == 1) + { + for (LfgGroupsMap::const_iterator it = proposalGroups.begin(); it != proposalGroups.end(); ++it) + if (proposal.group && it->second != proposal.group) + proposal.isNew = false; + } + + if (!sLFGMgr->AllQueued(check)) + { + sLog->outDebug(LOG_FILTER_LFG, "LFGQueue::CheckCompatibility: (%s) Group MATCH but can't create proposal!", strGuids.c_str()); + SetCompatibles(strGuids, LFG_COMPATIBLES_BAD_STATES); + return LFG_COMPATIBLES_BAD_STATES; + } + + // Create a new proposal + proposal.cancelTime = time(NULL) + LFG_TIME_PROPOSAL; + proposal.state = LFG_PROPOSAL_INITIATING; + proposal.leader = 0; + proposal.dungeonId = Trinity::Containers::SelectRandomContainerElement(proposalDungeons); + + bool leader = false; + for (LfgRolesMap::const_iterator itRoles = proposalRoles.begin(); itRoles != proposalRoles.end(); ++itRoles) + { + // Assing new leader + if (itRoles->second & PLAYER_ROLE_LEADER) + { + if (!leader || !proposal.leader || urand(0, 1)) + proposal.leader = itRoles->first; + leader = true; + } + else if (!leader && (!proposal.leader || urand(0, 1))) + proposal.leader = itRoles->first; + + // Assing player data and roles + LfgProposalPlayer &data = proposal.players[itRoles->first]; + data.role = itRoles->second; + data.group = proposalGroups.find(itRoles->first)->second; + if (!proposal.isNew && data.group && data.group == proposal.group) // Player from existing group, autoaccept + data.accept = LFG_ANSWER_AGREE; + } + + // Mark proposal members as not queued (but not remove queue data) + for (LfgGuidList::const_iterator itQueue = proposal.queues.begin(); itQueue != proposal.queues.end(); ++itQueue) + { + uint64 guid = (*itQueue); + RemoveFromNewQueue(guid); + RemoveFromCurrentQueue(guid); + } + + sLFGMgr->AddProposal(proposal); + + sLog->outDebug(LOG_FILTER_LFG, "LFGQueue::CheckCompatibility: (%s) MATCH! Group formed", strGuids.c_str()); + SetCompatibles(strGuids, LFG_COMPATIBLES_MATCH); + return LFG_COMPATIBLES_MATCH; +} + +void LfgQueue::UpdateQueueTimers(time_t currTime) +{ + for (LfgQueueDataMap::const_iterator itQueue = m_QueueDataMap.begin(); itQueue != m_QueueDataMap.end(); ++itQueue) + { + const LfgQueueData &queueinfo = itQueue->second; + uint32 dungeonId = (*queueinfo.dungeons.begin()); + uint32 queuedTime = uint32(currTime - queueinfo.joinTime); + uint8 role = PLAYER_ROLE_NONE; + int32 waitTime = -1; + int32 wtTank = m_waitTimesTank[dungeonId].time; + int32 wtHealer = m_waitTimesHealer[dungeonId].time; + int32 wtDps = m_waitTimesDps[dungeonId].time; + int32 wtAvg = m_waitTimesAvg[dungeonId].time; + + for (LfgRolesMap::const_iterator itPlayer = queueinfo.roles.begin(); itPlayer != queueinfo.roles.end(); ++itPlayer) + role |= itPlayer->second; + role &= ~PLAYER_ROLE_LEADER; + + switch (role) + { + case PLAYER_ROLE_NONE: // Should not happen - just in case + waitTime = -1; + break; + case PLAYER_ROLE_TANK: + waitTime = wtTank; + break; + case PLAYER_ROLE_HEALER: + waitTime = wtHealer; + break; + case PLAYER_ROLE_DAMAGE: + waitTime = wtDps; + break; + default: + waitTime = wtAvg; + break; + } + + LfgQueueStatusData queueData(dungeonId, waitTime, wtAvg, wtTank, wtHealer, wtDps, queuedTime, queueinfo.tanks, queueinfo.healers, queueinfo.dps); + for (LfgRolesMap::const_iterator itPlayer = queueinfo.roles.begin(); itPlayer != queueinfo.roles.end(); ++itPlayer) + { + uint64 pguid = itPlayer->first; + LFGMgr::SendLfgQueueStatus(pguid, queueData); + } + } +} + +time_t LfgQueue::GetJoinTime(uint64 guid) +{ + return m_QueueDataMap[guid].joinTime; +} \ No newline at end of file diff --git a/src/server/game/DungeonFinding/LFGQueue.h b/src/server/game/DungeonFinding/LFGQueue.h new file mode 100644 index 00000000000..f08199d725a --- /dev/null +++ b/src/server/game/DungeonFinding/LFGQueue.h @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2008-2012 TrinityCore + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#ifndef _LFGQUEUE_H +#define _LFGQUEUE_H + +#include "LFG.h" + +enum LfgCompatibility +{ + LFG_COMPATIBILITY_PENDING, + LFG_INCOMPATIBLES_WRONG_GROUP_SIZE, + LFG_INCOMPATIBLES_TOO_MUCH_PLAYERS, + LFG_INCOMPATIBLES_MULTIPLE_LFG_GROUPS, + LFG_INCOMPATIBLES_HAS_IGNORES, + LFG_INCOMPATIBLES_NO_ROLES, + LFG_INCOMPATIBLES_NO_DUNGEONS, + LFG_COMPATIBLES_WITH_LESS_PLAYERS, // Values under this = not compatible (do not modify order) + LFG_COMPATIBLES_BAD_STATES, + LFG_COMPATIBLES_MATCH // Must be the last one +}; + +/// Stores player or group queue info +struct LfgQueueData +{ + LfgQueueData(): joinTime(time_t(time(NULL))), tanks(LFG_TANKS_NEEDED), + healers(LFG_HEALERS_NEEDED), dps(LFG_DPS_NEEDED) + { } + + LfgQueueData(time_t _joinTime, const LfgDungeonSet &_dungeons, const LfgRolesMap &_roles) + { + joinTime = _joinTime; + dungeons = _dungeons; + roles = _roles; + tanks = LFG_TANKS_NEEDED; + healers = LFG_HEALERS_NEEDED; + dps = LFG_DPS_NEEDED; + + for (LfgRolesMap::const_iterator it = roles.begin(); it != roles.end(); ++it) + { + uint8 role = it->second; + if (role & PLAYER_ROLE_TANK) + --tanks; + else if (role & PLAYER_ROLE_HEALER) + --healers; + else + --dps; + } + } + + time_t joinTime; ///< Player queue join time (to calculate wait times) + uint8 tanks; ///< Tanks needed + uint8 healers; ///< Healers needed + uint8 dps; ///< Dps needed + LfgDungeonSet dungeons; ///< Selected Player/Group Dungeon/s + LfgRolesMap roles; ///< Selected Player Role/s +}; + +struct LfgWaitTime +{ + LfgWaitTime(): time(-1), number(0) {} + int32 time; ///< Wait time + uint32 number; ///< Number of people used to get that wait time +}; + +typedef std::map LfgWaitTimesMap; +typedef std::map LfgCompatibleMap; +typedef std::map LfgQueueDataMap; + +/** + Stores all data related to queue +*/ +class LfgQueue +{ + public: + + // Add/Remove from queue + void AddToQueue(uint64 guid); + void RemoveFromQueue(uint64 guid); + void AddQueueData(uint64 guid, time_t joinTime, const LfgDungeonSet &dungeons, const LfgRolesMap &rolesMap); + void RemoveQueueData(uint64 guid); + + // Update Timers (when proposal success) + void UpdateWaitTimeAvg(int32 waitTime, uint32 dungeonId); + void UpdateWaitTimeTank(int32 waitTime, uint32 dungeonId); + void UpdateWaitTimeHealer(int32 waitTime, uint32 dungeonId); + void UpdateWaitTimeDps(int32 waitTime, uint32 dungeonId); + + // Update Queue timers + void UpdateQueueTimers(time_t currTime); + time_t GetJoinTime(uint64 guid); + + // Find new group + uint8 FindGroups(); + + // Just for debugging purposes + LfgCompatibleMap const& GetCompatibleMap(); + std::string DumpQueueInfo() const; + std::string DumpCompatibleInfo() const; + private: + void AddToNewQueue(uint64 guid); + void AddToCurrentQueue(uint64 guid); + void RemoveFromNewQueue(uint64 guid); + void RemoveFromCurrentQueue(uint64 guid); + + void SetCompatibles(std::string const& key, LfgCompatibility compatibles); + LfgCompatibility GetCompatibles(std::string const& key); + void RemoveFromCompatibles(uint64 guid); + + LfgCompatibility FindNewGroups(LfgGuidList& check, LfgGuidList& all); + LfgCompatibility CheckCompatibility(LfgGuidList check); + + // Queue + LfgQueueDataMap m_QueueDataMap; ///< Queued groups + LfgCompatibleMap m_CompatibleMap; ///< Compatible dungeons + + LfgWaitTimesMap m_waitTimesAvg; ///< Average wait time to find a group queuing as multiple roles + LfgWaitTimesMap m_waitTimesTank; ///< Average wait time to find a group queuing as tank + LfgWaitTimesMap m_waitTimesHealer; ///< Average wait time to find a group queuing as healer + LfgWaitTimesMap m_waitTimesDps; ///< Average wait time to find a group queuing as dps + LfgGuidList m_currentQueue; ///< Ordered list. Used to find groups + LfgGuidList m_newToQueue; ///< New groups to add to queue +}; + +#endif diff --git a/src/server/game/DungeonFinding/LFGScripts.cpp b/src/server/game/DungeonFinding/LFGScripts.cpp index 76cc169f477..10ce42da610 100644 --- a/src/server/game/DungeonFinding/LFGScripts.cpp +++ b/src/server/game/DungeonFinding/LFGScripts.cpp @@ -109,13 +109,6 @@ void LFGGroupScript::OnRemoveMember(Group* group, uint64 guid, RemoveMethod meth uint64 gguid = group->GetGUID(); sLog->outDebug(LOG_FILTER_LFG, "LFGScripts::OnRemoveMember [" UI64FMTD "]: remove [" UI64FMTD "] Method: %d Kicker: [" UI64FMTD "] Reason: %s", gguid, guid, method, kicker, (reason ? reason : "")); - if (method == GROUP_REMOVEMETHOD_DEFAULT) - return; - - LfgState state = sLFGMgr->GetState(gguid); - if (state == LFG_STATE_QUEUED) - sLFGMgr->LeaveLfg(gguid); // TODO - Remove the one leaving and rejoin group - bool isLFG = group->isLFGGroup(); if (isLFG && method == GROUP_REMOVEMETHOD_KICK) // Player have been kicked @@ -128,15 +121,26 @@ void LFGGroupScript::OnRemoveMember(Group* group, uint64 guid, RemoveMethod meth return; } - sLFGMgr->ClearState(guid, "OnRemoveMember"); + LfgState state = sLFGMgr->GetState(gguid); + + // If group is being formed after proposal success do nothing more + if (state == LFG_STATE_PROPOSAL && method == GROUP_REMOVEMETHOD_DEFAULT) + { + // LfgData: Remove player from group + sLFGMgr->SetGroup(guid, 0); + sLFGMgr->RemovePlayerFromGroup(gguid, guid); + return; + } + + sLFGMgr->LeaveLfg(guid); sLFGMgr->SetState(guid, LFG_STATE_NONE); sLFGMgr->SetGroup(guid, 0); - sLFGMgr->RemovePlayerFromGroup(gguid, guid); + uint8 players = sLFGMgr->RemovePlayerFromGroup(gguid, guid); if (Player* player = ObjectAccessor::FindPlayer(guid)) { if (method == GROUP_REMOVEMETHOD_LEAVE && state == LFG_STATE_DUNGEON && - sLFGMgr->GetDungeon(gguid, false)) + players >= LFG_GROUP_KICK_VOTES_NEEDED) player->CastSpell(player, LFG_SPELL_DUNGEON_DESERTER, true); //else if (state == LFG_STATE_BOOT) // Update internal kick cooldown of kicked @@ -165,24 +169,16 @@ void LFGGroupScript::OnChangeLeader(Group* group, uint64 newLeaderGuid, uint64 o sLog->outDebug(LOG_FILTER_LFG, "LFGScripts::OnChangeLeader [" UI64FMTD "]: old [" UI64FMTD "] new [" UI64FMTD "]", gguid, newLeaderGuid, oldLeaderGuid); sLFGMgr->SetLeader(gguid, newLeaderGuid); - Player* player = ObjectAccessor::FindPlayer(newLeaderGuid); - - LfgUpdateData updateData = LfgUpdateData(LFG_UPDATETYPE_LEADER_UNK1); - if (player) - player->GetSession()->SendLfgUpdateParty(updateData); - - player = ObjectAccessor::FindPlayer(oldLeaderGuid); - if (player) - { - updateData.updateType = LFG_UPDATETYPE_GROUP_DISBAND_UNK16; - player->GetSession()->SendLfgUpdateParty(updateData); - } } void LFGGroupScript::OnInviteMember(Group* group, uint64 guid) { uint64 gguid = group->GetGUID(); - - sLog->outDebug(LOG_FILTER_LFG, "LFGScripts::OnInviteMember [" UI64FMTD "]: invite [" UI64FMTD "] leader [" UI64FMTD "]", gguid, guid, group->GetLeaderGUID()); - sLFGMgr->LeaveLfg(gguid); + uint64 leader = group->GetLeaderGUID(); + sLog->outDebug(LOG_FILTER_LFG, "LFGScripts::OnInviteMember [" UI64FMTD "]: invite [" UI64FMTD "] leader [" UI64FMTD "]", gguid, guid, leader); + // No gguid == new group being formed + // No leader == after group creation first invite is new leader + // leader and no gguid == first invite after leader is added to new group (this is the real invite) + if (leader && !gguid) + sLFGMgr->LeaveLfg(leader); } diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp index f06225988d6..f4106730e49 100755 --- a/src/server/game/Groups/Group.cpp +++ b/src/server/game/Groups/Group.cpp @@ -523,7 +523,7 @@ bool Group::RemoveMember(uint64 guid, const RemoveMethod &method /*= GROUP_REMOV WorldPacket data; - if (method == GROUP_REMOVEMETHOD_KICK) + if (method == GROUP_REMOVEMETHOD_KICK || method == GROUP_REMOVEMETHOD_KICK_LFG) { data.Initialize(SMSG_GROUP_UNINVITE, 0); player->GetSession()->SendPacket(&data); diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h index 4f6ad917423..422385f406f 100755 --- a/src/server/game/Miscellaneous/SharedDefines.h +++ b/src/server/game/Miscellaneous/SharedDefines.h @@ -3399,9 +3399,10 @@ enum XPColorChar enum RemoveMethod { - GROUP_REMOVEMETHOD_DEFAULT = 0, - GROUP_REMOVEMETHOD_KICK = 1, - GROUP_REMOVEMETHOD_LEAVE = 2 + GROUP_REMOVEMETHOD_DEFAULT = 0, + GROUP_REMOVEMETHOD_KICK = 1, + GROUP_REMOVEMETHOD_LEAVE = 2, + GROUP_REMOVEMETHOD_KICK_LFG = 3 }; enum ActivateTaxiReply -- cgit v1.2.3 From 36806bf5b3a9abed467e23eb835a992df3ea0d50 Mon Sep 17 00:00:00 2001 From: Spp Date: Fri, 19 Oct 2012 17:36:24 +0200 Subject: Move LFG string out of Custom patch range --- .../world/2012_10_18_00_world_trinity_string.sql | 31 +++++++++++----------- src/server/game/DataStores/DBCfmt.h | 2 +- src/server/game/Miscellaneous/Language.h | 30 ++++++++++----------- 3 files changed, 32 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/sql/updates/world/2012_10_18_00_world_trinity_string.sql b/sql/updates/world/2012_10_18_00_world_trinity_string.sql index 8d62174d868..a12b20388eb 100644 --- a/sql/updates/world/2012_10_18_00_world_trinity_string.sql +++ b/sql/updates/world/2012_10_18_00_world_trinity_string.sql @@ -1,16 +1,17 @@ -REPLACE INTO `trinity_string` (`entry`, `content_default`, `content_loc1`, `content_loc2`, `content_loc3`, `content_loc4`, `content_loc5`, `content_loc6`, `content_loc7`, `content_loc8`) +DELETE FROM `trinity_string` WHERE `entry` IN (9986, 9987, 9989, 9990, 9991, 9992, 9993, 9994, 9995, 9996, 9997, 9998, 9999); +INSERT INTO `trinity_string` (`entry`, `content_default`, `content_loc1`, `content_loc2`, `content_loc3`, `content_loc4`, `content_loc5`, `content_loc6`, `content_loc7`, `content_loc8`) VALUES - (11015, 'Error', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), - (11014, 'None', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), - (11013, 'Leader', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), - (11012, 'Dps', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), - (11011, 'Healer', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), - (11010, 'Tank', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), - (11009, 'Raid browser', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), - (11008, 'Finished dungeon', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), - (11007, 'In dungeon', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), - (11006, 'Vote kick', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), - (11005, 'Proposal', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), - (11004, 'Queued', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), - (11003, 'Role check', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), - (11002, 'None', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + (9986, 'Error', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), + (9987, 'None', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), + (9988, 'Leader', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), + (9989, 'Dps', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), + (9990, 'Healer', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), + (9991, 'Tank', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), + (9992, 'Raid browser', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), + (9993, 'Finished dungeon', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), + (9994, 'In dungeon', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), + (9995, 'Vote kick', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), + (9996, 'Proposal', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), + (9997, 'Queued', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), + (9998, 'Role check', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), + (9999, 'None', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); diff --git a/src/server/game/DataStores/DBCfmt.h b/src/server/game/DataStores/DBCfmt.h index 0c2cc565b22..0fe82ea3311 100755 --- a/src/server/game/DataStores/DBCfmt.h +++ b/src/server/game/DataStores/DBCfmt.h @@ -77,7 +77,7 @@ char const ItemLimitCategoryEntryfmt[]="nxxxxxxxxxxxxxxxxxii"; char const ItemRandomPropertiesfmt[]="nxiiixxssssssssssssssssx"; char const ItemRandomSuffixfmt[]="nssssssssssssssssxxiiixxiiixx"; char const ItemSetEntryfmt[]="dssssssssssssssssxiiiiiiiiiixxxxxxxiiiiiiiiiiiiiiiiii"; -char const LFGDungeonEntryfmt[]="nssssssssssssssssiiiiiiiiixxixixxxxxxxxxxxxxxxxx"; +char const LFGDungeonEntryfmt[]="nssssssssssssssssxiiiiiiiiixxixixxxxxxxxxxxxxxxxx"; char const LiquidTypefmt[]="nxxixixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; char const LockEntryfmt[]="niiiiiiiiiiiiiiiiiiiiiiiixxxxxxxx"; char const MailTemplateEntryfmt[]="nxxxxxxxxxxxxxxxxxssssssssssssssssx"; diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h index ee3be6f2b2d..6868db35975 100755 --- a/src/server/game/Miscellaneous/Language.h +++ b/src/server/game/Miscellaneous/Language.h @@ -990,6 +990,21 @@ enum TrinityStrings LANG_WORLD_CLOSED = 7523, LANG_WORLD_OPENED = 7524, + LANG_LFG_STATE_NONE = 9986, + LANG_LFG_STATE_ROLECHECK = 9987, + LANG_LFG_STATE_QUEUED = 9988, + LANG_LFG_STATE_PROPOSAL = 9989, + LANG_LFG_STATE_BOOT = 9990, + LANG_LFG_STATE_DUNGEON = 9991, + LANG_LFG_STATE_FINISHED_DUNGEON = 9992, + LANG_LFG_STATE_RAIDBROWSER = 9993, + LANG_LFG_ROLE_TANK = 9994, + LANG_LFG_ROLE_HEALER = 9995, + LANG_LFG_ROLE_DAMAGE = 9996, + LANG_LFG_ROLE_LEADER = 9997, + LANG_LFG_ROLE_NONE = 9998, + LANG_LFG_ERROR = 9999, + // Use for not-in-offcial-sources patches // 10000-10999 // opvp hp @@ -1078,21 +1093,6 @@ enum TrinityStrings LANG_AUTO_BROADCAST = 11000, LANG_INVALID_REALMID = 11001, - LANG_LFG_STATE_NONE = 11002, - LANG_LFG_STATE_ROLECHECK = 11003, - LANG_LFG_STATE_QUEUED = 11004, - LANG_LFG_STATE_PROPOSAL = 11005, - LANG_LFG_STATE_BOOT = 11006, - LANG_LFG_STATE_DUNGEON = 11007, - LANG_LFG_STATE_FINISHED_DUNGEON = 11008, - LANG_LFG_STATE_RAIDBROWSER = 11009, - LANG_LFG_ROLE_TANK = 11010, - LANG_LFG_ROLE_HEALER = 11011, - LANG_LFG_ROLE_DAMAGE = 11012, - LANG_LFG_ROLE_LEADER = 11013, - LANG_LFG_ROLE_NONE = 11014, - LANG_LFG_ERROR = 11015, - // NOT RESERVED IDS 12000-1999999999 // `db_script_string` table index 2000000000-2000009999 (MIN_DB_SCRIPT_STRING_ID-MAX_DB_SCRIPT_STRING_ID) // For other tables maybe 2000010000-2147483647 (max index) -- cgit v1.2.3 From 67a03027ae6a2ea93904f1cc6652b6aa60ed8b07 Mon Sep 17 00:00:00 2001 From: Spp Date: Fri, 19 Oct 2012 17:47:51 +0200 Subject: Proper naming of LfgDungeon structures --- src/server/game/DataStores/DBCStores.cpp | 2 +- src/server/game/DataStores/DBCStores.h | 2 +- src/server/game/DataStores/DBCStructure.h | 2 +- src/server/game/DungeonFinding/LFGMgr.cpp | 22 +++++++++++----------- src/server/game/DungeonFinding/LFGMgr.h | 12 ++++++------ src/server/game/Entities/Player/Player.cpp | 4 ++-- src/server/game/Groups/Group.cpp | 2 +- src/server/game/Handlers/LFGHandler.cpp | 6 +++--- src/server/game/Maps/Map.cpp | 4 ++-- src/server/scripts/Spells/spell_generic.cpp | 4 ++-- 10 files changed, 30 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/server/game/DataStores/DBCStores.cpp b/src/server/game/DataStores/DBCStores.cpp index 16595eb16dd..850c58bdf93 100755 --- a/src/server/game/DataStores/DBCStores.cpp +++ b/src/server/game/DataStores/DBCStores.cpp @@ -118,7 +118,7 @@ DBCStorage sItemRandomPropertiesStore(ItemRandomProp DBCStorage sItemRandomSuffixStore(ItemRandomSuffixfmt); DBCStorage sItemSetStore(ItemSetEntryfmt); -DBCStorage sLFGDungeonStore(LFGDungeonEntryfmt); +DBCStorage sLFGDungeonStore(LFGDungeonEntryfmt); DBCStorage sLiquidTypeStore(LiquidTypefmt); DBCStorage sLockStore(LockEntryfmt); diff --git a/src/server/game/DataStores/DBCStores.h b/src/server/game/DataStores/DBCStores.h index f6fabb5a73d..cd30ed587f8 100755 --- a/src/server/game/DataStores/DBCStores.h +++ b/src/server/game/DataStores/DBCStores.h @@ -120,7 +120,7 @@ extern DBCStorage sItemLimitCategoryStore; extern DBCStorage sItemRandomPropertiesStore; extern DBCStorage sItemRandomSuffixStore; extern DBCStorage sItemSetStore; -extern DBCStorage sLFGDungeonStore; +extern DBCStorage sLFGDungeonStore; extern DBCStorage sLiquidTypeStore; extern DBCStorage sLockStore; extern DBCStorage sMailTemplateStore; diff --git a/src/server/game/DataStores/DBCStructure.h b/src/server/game/DataStores/DBCStructure.h index 2fc61e69fe2..20eab098add 100755 --- a/src/server/game/DataStores/DBCStructure.h +++ b/src/server/game/DataStores/DBCStructure.h @@ -1193,7 +1193,7 @@ struct ItemSetEntry uint32 required_skill_value; // 52 m_requiredSkillRank }; -struct LFGDungeonEntryDbc +struct LFGDungeonEntry { uint32 ID; // 0 char* name[16]; // 1-17 Name lang diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp index 16fda8952ac..a19034a76ec 100755 --- a/src/server/game/DungeonFinding/LFGMgr.cpp +++ b/src/server/game/DungeonFinding/LFGMgr.cpp @@ -239,7 +239,7 @@ void LFGMgr::LoadRewards() sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u lfg dungeon rewards in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); } -LFGDungeonEntry const* LFGMgr::GetLFGDungeon(uint32 id) +LFGDungeonData const* LFGMgr::GetLFGDungeon(uint32 id) { LFGDungeonMap::const_iterator itr = m_LfgDungeonMap.find(id); if (itr != m_LfgDungeonMap.end()) @@ -262,7 +262,7 @@ void LFGMgr::LoadLFGDungeons(bool reload /* = false */) // Initialize Dungeon map with data from dbcs for (uint32 i = 0; i < sLFGDungeonStore.GetNumRows(); ++i) { - LFGDungeonEntryDbc const* dungeon = sLFGDungeonStore.LookupEntry(i); + LFGDungeonEntry const* dungeon = sLFGDungeonStore.LookupEntry(i); if (!dungeon) continue; @@ -272,7 +272,7 @@ void LFGMgr::LoadLFGDungeons(bool reload /* = false */) case LFG_TYPE_HEROIC: case LFG_TYPE_RAID: case LFG_TYPE_RANDOM: - m_LfgDungeonMap[dungeon->ID] = LFGDungeonEntry(dungeon); + m_LfgDungeonMap[dungeon->ID] = LFGDungeonData(dungeon); break; } } @@ -299,7 +299,7 @@ void LFGMgr::LoadLFGDungeons(bool reload /* = false */) continue; } - LFGDungeonEntry& data = dungeonItr->second; + LFGDungeonData& data = dungeonItr->second; data.x = fields[1].GetFloat(); data.y = fields[2].GetFloat(); data.z = fields[3].GetFloat(); @@ -314,7 +314,7 @@ void LFGMgr::LoadLFGDungeons(bool reload /* = false */) // Fill all other teleport coords from areatriggers for (LFGDungeonMap::iterator itr = m_LfgDungeonMap.begin(); itr != m_LfgDungeonMap.end(); ++itr) { - LFGDungeonEntry& dungeon = itr->second; + LFGDungeonData& dungeon = itr->second; // No teleport coords in database, load from areatriggers if (dungeon.x == 0.0f && dungeon.y == 0.0f && dungeon.z == 0.0f) { @@ -462,7 +462,7 @@ void LFGMgr::InitializeLockedDungeons(Player* player, uint8 level /* = 0 */) for (LfgDungeonSet::const_iterator it = dungeons.begin(); it != dungeons.end(); ++it) { - LFGDungeonEntry const* dungeon = GetLFGDungeon(*it); + LFGDungeonData const* dungeon = GetLFGDungeon(*it); if (!dungeon) // should never happen - We provide a list from sLFGDungeonStore continue; @@ -1014,7 +1014,7 @@ void LFGMgr::MakeNewGroup(const LfgProposal& proposal) } // Set the dungeon difficulty - LFGDungeonEntry const* dungeon = GetLFGDungeon(proposal.dungeonId); + LFGDungeonData const* dungeon = GetLFGDungeon(proposal.dungeonId); ASSERT(dungeon); Group* grp = proposal.group ? sGroupMgr->GetGroupByGUID(GUID_LOPART(proposal.group)) : NULL; @@ -1384,7 +1384,7 @@ void LFGMgr::TeleportPlayer(Player* player, bool out, bool fromOpcode /*= false* Group* grp = player->GetGroup(); uint64 gguid = grp->GetGUID(); - LFGDungeonEntry const* dungeon = GetLFGDungeon(GetDungeon(gguid)); + LFGDungeonData const* dungeon = GetLFGDungeon(GetDungeon(gguid)); if (!dungeon || (out && player->GetMapId() != uint32(dungeon->map))) return; @@ -1501,7 +1501,7 @@ void LFGMgr::RewardDungeonDoneFor(const uint32 dungeonId, Player* player) SetState(guid, LFG_STATE_FINISHED_DUNGEON); // Give rewards only if its a random or seasonal dungeon - LFGDungeonEntry const* dungeon = GetLFGDungeon(rDungeonId); + LFGDungeonData const* dungeon = GetLFGDungeon(rDungeonId); if (!dungeon || (dungeon->type != LFG_TYPE_RANDOM && !dungeon->seasonal)) { sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::RewardDungeonDoneFor: [" UI64FMTD "] dungeon %u is not random nor seasonal", guid, rDungeonId); @@ -1551,7 +1551,7 @@ void LFGMgr::RewardDungeonDoneFor(const uint32 dungeonId, Player* player) */ const LfgDungeonSet& LFGMgr::GetDungeonsByRandom(uint32 randomdungeon) { - LFGDungeonEntry const* dungeon = GetLFGDungeon(randomdungeon); + LFGDungeonData const* dungeon = GetLFGDungeon(randomdungeon); uint32 group = dungeon ? dungeon->group : 0; return m_CachedDungeonMap[group]; } @@ -1586,7 +1586,7 @@ LfgReward const* LFGMgr::GetRandomDungeonReward(uint32 dungeon, uint8 level) */ LfgType LFGMgr::GetDungeonType(uint32 dungeonId) { - LFGDungeonEntry const* dungeon = GetLFGDungeon(dungeonId); + LFGDungeonData const* dungeon = GetLFGDungeon(dungeonId); if (!dungeon) return LFG_TYPE_NONE; diff --git a/src/server/game/DungeonFinding/LFGMgr.h b/src/server/game/DungeonFinding/LFGMgr.h index 1f9c9cf3b2c..39cdd390792 100755 --- a/src/server/game/DungeonFinding/LFGMgr.h +++ b/src/server/game/DungeonFinding/LFGMgr.h @@ -117,7 +117,7 @@ enum LfgRoleCheckState }; // Forward declaration (just to have all typedef together) -struct LFGDungeonEntry; +struct LFGDungeonData; struct LfgReward; struct LfgQueueInfo; struct LfgRoleCheck; @@ -136,7 +136,7 @@ typedef std::map LfgProposalPlayerMap; typedef std::map LfgPlayerBootMap; typedef std::map LfgGroupDataMap; typedef std::map LfgPlayerDataMap; -typedef UNORDERED_MAP LFGDungeonMap; +typedef UNORDERED_MAP LFGDungeonMap; // Data needed by SMSG_LFG_JOIN_RESULT struct LfgJoinResultData @@ -251,12 +251,12 @@ struct LfgPlayerBoot std::string reason; ///< kick reason }; -struct LFGDungeonEntry +struct LFGDungeonData { - LFGDungeonEntry(): id(0), name(""), map(0), type(0), expansion(0), group(0), minlevel(0), + LFGDungeonData(): id(0), name(""), map(0), type(0), expansion(0), group(0), minlevel(0), maxlevel(0), difficulty(REGULAR_DIFFICULTY), seasonal(false), x(0.0f), y(0.0f), z(0.0f), o(0.0f) { } - LFGDungeonEntry(LFGDungeonEntryDbc const* dbc): id(dbc->ID), name(dbc->name[0]), map(dbc->map), + LFGDungeonData(LFGDungeonEntry const* dbc): id(dbc->ID), name(dbc->name[0]), map(dbc->map), type(dbc->type), expansion(dbc->expansion), group(dbc->grouptype), minlevel(dbc->minlevel), maxlevel(dbc->maxlevel), difficulty(Difficulty(dbc->difficulty)), seasonal(dbc->flags & LFG_FLAG_SEASONAL), x(0.0f), y(0.0f), z(0.0f), o(0.0f) @@ -358,7 +358,7 @@ class LFGMgr static char const * GetStateString(LfgState state); void LoadLFGDungeons(bool reload = false); - LFGDungeonEntry const* GetLFGDungeon(uint32 id); + LFGDungeonData const* GetLFGDungeon(uint32 id); LFGDungeonMap& GetLFGDungeonMap(); void ClearState(uint64 guid, char const *debugMsg); diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 93a0580a866..e06463bf0aa 100755 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -11901,7 +11901,7 @@ InventoryResult Player::CanRollForItemInLFG(ItemTemplate const* proto, WorldObje bool lootedObjectInDungeon = false; Map const* map = lootedObject->GetMap(); if (uint32 dungeonId = sLFGMgr->GetDungeon(GetGroup()->GetGUID(), true)) - if (LFGDungeonEntry const* dungeon = sLFGMgr->GetLFGDungeon(dungeonId)) + if (LFGDungeonData const* dungeon = sLFGMgr->GetLFGDungeon(dungeonId)) if (uint32(dungeon->map) == map->GetId() && dungeon->difficulty == uint32(map->GetDifficulty())) lootedObjectInDungeon = true; @@ -23304,7 +23304,7 @@ bool Player::inRandomLfgDungeon() const LfgDungeonSet& dungeons = sLFGMgr->GetSelectedDungeons(GetGUID()); if (!dungeons.empty()) { - LFGDungeonEntry const* dungeon = sLFGMgr->GetLFGDungeon(*dungeons.begin()); + LFGDungeonData const* dungeon = sLFGMgr->GetLFGDungeon(*dungeons.begin()); if (dungeon && (dungeon->type == LFG_TYPE_RANDOM || dungeon->seasonal)) return true; } diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp index f4106730e49..11d9f502bab 100755 --- a/src/server/game/Groups/Group.cpp +++ b/src/server/game/Groups/Group.cpp @@ -600,7 +600,7 @@ bool Group::RemoveMember(uint64 guid, const RemoveMethod &method /*= GROUP_REMOV if (isLFGGroup() && GetMembersCount() == 1) { Player* Leader = ObjectAccessor::FindPlayer(GetLeaderGUID()); - LFGDungeonEntry const* dungeon = sLFGMgr->GetLFGDungeon(sLFGMgr->GetDungeon(GetGUID())); + LFGDungeonData const* dungeon = sLFGMgr->GetLFGDungeon(sLFGMgr->GetDungeon(GetGUID())); if ((Leader && dungeon && Leader->isAlive() && Leader->GetMapId() != uint32(dungeon->map)) || !dungeon) { Disband(); diff --git a/src/server/game/Handlers/LFGHandler.cpp b/src/server/game/Handlers/LFGHandler.cpp index 4f208d33bde..116afdf8c75 100755 --- a/src/server/game/Handlers/LFGHandler.cpp +++ b/src/server/game/Handlers/LFGHandler.cpp @@ -165,7 +165,7 @@ void WorldSession::HandleLfgPlayerLockInfoRequestOpcode(WorldPacket& /*recv_data LFGDungeonMap& LfgDungeons = sLFGMgr->GetLFGDungeonMap(); for (LFGDungeonMap::const_iterator itr = LfgDungeons.begin(); itr != LfgDungeons.end(); ++itr) { - LFGDungeonEntry const& dungeon = itr->second; + LFGDungeonData const& dungeon = itr->second; if ((dungeon.type == LFG_TYPE_RANDOM || (dungeon.seasonal && sLFGMgr->IsSeasonActive(dungeon.id))) && dungeon.expansion <= expansion && dungeon.minlevel <= level && level <= dungeon.maxlevel) randomDungeons.insert(dungeon.Entry()); @@ -403,7 +403,7 @@ void WorldSession::SendLfgRoleCheckUpdate(const LfgRoleCheck& roleCheck) { for (LfgDungeonSet::iterator it = dungeons.begin(); it != dungeons.end(); ++it) { - LFGDungeonEntry const* dungeon = sLFGMgr->GetLFGDungeon(*it); + LFGDungeonData const* dungeon = sLFGMgr->GetLFGDungeon(*it); data << uint32(dungeon ? dungeon->Entry() : 0); // Dungeon } } @@ -552,7 +552,7 @@ void WorldSession::SendLfgUpdateProposal(uint32 proposalId, LfgProposal const& p dungeonEntry = (*playerDungeons.begin()); } - if (LFGDungeonEntry const* dungeon = sLFGMgr->GetLFGDungeon(dungeonEntry)) + if (LFGDungeonData const* dungeon = sLFGMgr->GetLFGDungeon(dungeonEntry)) dungeonEntry = dungeon->Entry(); data << uint32(dungeonEntry); // Dungeon diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index c3c6befe2f9..51435d6df9b 100755 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -2468,8 +2468,8 @@ bool InstanceMap::AddPlayerToMap(Player* player) if (group && group->isLFGGroup()) if (uint32 dungeonId = sLFGMgr->GetDungeon(group->GetGUID(), true)) - if (LFGDungeonEntry const* dungeon = sLFGMgr->GetLFGDungeon(dungeonId)) - if (LFGDungeonEntry const* randomDungeon = sLFGMgr->GetLFGDungeon(*(sLFGMgr->GetSelectedDungeons(player->GetGUID()).begin()))) + if (LFGDungeonData const* dungeon = sLFGMgr->GetLFGDungeon(dungeonId)) + if (LFGDungeonData const* randomDungeon = sLFGMgr->GetLFGDungeon(*(sLFGMgr->GetSelectedDungeons(player->GetGUID()).begin()))) if (uint32(dungeon->map) == GetId() && dungeon->difficulty == uint32(GetDifficulty()) && randomDungeon->type == uint32(LFG_TYPE_RANDOM)) player->CastSpell(player, LFG_SPELL_LUCK_OF_THE_DRAW, true); } diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp index 547cb3dba51..519d79add6d 100644 --- a/src/server/scripts/Spells/spell_generic.cpp +++ b/src/server/scripts/Spells/spell_generic.cpp @@ -1581,12 +1581,12 @@ class spell_gen_luck_of_the_draw : public SpellScriptLoader } - LFGDungeonEntry const* randomDungeon = sLFGMgr->GetLFGDungeon(*itr); + LFGDungeonData const* randomDungeon = sLFGMgr->GetLFGDungeon(*itr); if (Group* group = owner->GetGroup()) if (Map const* map = owner->GetMap()) if (group->isLFGGroup()) if (uint32 dungeonId = sLFGMgr->GetDungeon(group->GetGUID(), true)) - if (LFGDungeonEntry const* dungeon = sLFGMgr->GetLFGDungeon(dungeonId)) + if (LFGDungeonData const* dungeon = sLFGMgr->GetLFGDungeon(dungeonId)) if (uint32(dungeon->map) == map->GetId() && dungeon->difficulty == uint32(map->GetDifficulty())) if (randomDungeon && randomDungeon->type == LFG_TYPE_RANDOM) return; // in correct dungeon -- cgit v1.2.3 From 0c909b2aed0686ad46a415cb5de1a2f446b35d57 Mon Sep 17 00:00:00 2001 From: Spp Date: Fri, 19 Oct 2012 21:35:51 +0200 Subject: Fix crash on shutdown after last DF changes --- src/server/game/DungeonFinding/LFGMgr.cpp | 15 +++++++++------ src/server/game/DungeonFinding/LFGMgr.h | 5 ----- 2 files changed, 9 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp index a19034a76ec..659986fb148 100755 --- a/src/server/game/DungeonFinding/LFGMgr.cpp +++ b/src/server/game/DungeonFinding/LFGMgr.cpp @@ -31,17 +31,20 @@ #include "GroupMgr.h" #include "GameEventMgr.h" -LFGMgr::LFGMgr(): m_QueueTimer(0), m_lfgProposalId(1), - m_options(sWorld->getBoolConfig(CONFIG_DUNGEON_FINDER_ENABLE)), - m_lfgPlayerScript(new LFGPlayerScript()), m_lfgGroupScript(new LFGGroupScript()) -{ } +LFGMgr::LFGMgr(): m_QueueTimer(0), m_lfgProposalId(1) +{ + m_options = sWorld->getBoolConfig(CONFIG_DUNGEON_FINDER_ENABLE); + if (m_options) + { + new LFGPlayerScript(); + new LFGGroupScript(); + } +} LFGMgr::~LFGMgr() { for (LfgRewardMap::iterator itr = m_RewardMap.begin(); itr != m_RewardMap.end(); ++itr) delete itr->second; - delete m_lfgPlayerScript; - delete m_lfgGroupScript; } void LFGMgr::_LoadFromDB(Field* fields, uint64 guid) diff --git a/src/server/game/DungeonFinding/LFGMgr.h b/src/server/game/DungeonFinding/LFGMgr.h index 39cdd390792..286e82386a7 100755 --- a/src/server/game/DungeonFinding/LFGMgr.h +++ b/src/server/game/DungeonFinding/LFGMgr.h @@ -25,8 +25,6 @@ #include "LFGGroupData.h" #include "LFGPlayerData.h" -class LFGPlayerScript; -class LFGGroupScript; class Group; class Player; @@ -406,9 +404,6 @@ class LFGMgr LfgPlayerDataMap m_Players; ///< Player data LfgGroupDataMap m_Groups; ///< Group data LfgGuidList m_teleport; ///< Players being teleported - - LFGPlayerScript *m_lfgPlayerScript; - LFGGroupScript *m_lfgGroupScript; }; #define sLFGMgr ACE_Singleton::instance() -- cgit v1.2.3