Trinitycore: [3.3.5] Suggestion: Disable Quest Sharing and Ready Check in Battlegrounds

Created on 16 Mar 2019  ·  17Comments  ·  Source: TrinityCore/TrinityCore

Given the fact that some people can abuse quest sharing in Battlegrounds and they can be pretty annoying with that, I suggest disabling quest sharing in Battlegrounds altogether.

I've done a few tests and so far it's working as intended

diff --git a/src/server/game/Handlers/QuestHandler.cpp b/src/server/game/Handlers/QuestHandler.cpp
index 952a084e4c..6c10a2f820 100644
--- a/src/server/game/Handlers/QuestHandler.cpp
+++ b/src/server/game/Handlers/QuestHandler.cpp
@@ -598,6 +598,12 @@ void WorldSession::HandlePushQuestToParty(WorldPacket& recvPacket)
             continue;
         }

+        if (sender->CanShareQuest(questId) && sender->InBattleground()) // mindsear: Disable Quest sharing in Battlegrounds
+        {
+            sender->GetSession()->SendNotification("You cannot share quests in Battlegrounds");
+            continue; 
+        }
+
         if (receiver->GetPlayerSharingQuest())
         {
             sender->SendPushToPartyResponse(receiver, QUEST_PARTY_MSG_BUSY);
diff --git a/src/server/scripts/Custom/custom_script_loader.cpp b/src/server/scripts/C

Also, removing QUEST_FLAGS_PARTY_ACCEPT from Empty Stables quest (7027=Alliance quest, 7001 = Horde quest):

UPDATE `world`.`quest_template` SET `Flags` = 64 WHERE `ID` IN (7027, 7001);

Also, Ready Check can be spammed in Battlegrounds by raid leaders.

diff --git a/src/server/game/Handlers/GroupHandler.cpp b/src/server/game/Handlers/GroupHandler.cpp
index 536cc86098..f6fa7a46b0 100644
--- a/src/server/game/Handlers/GroupHandler.cpp
+++ b/src/server/game/Handlers/GroupHandler.cpp
@@ -695,6 +695,12 @@ void WorldSession::HandleRaidReadyCheckOpcode(WorldPacket& recvData)
             return;
         /********************/

+        if (group->IsLeader(GetPlayer()->GetGUID()) && _player->InBattleground()) // mindsear: Disable "Ready Check" in Battlegrounds
+        {
+            _player->GetSession()->SendNotification("You cannot use that option in Battlegrounds");
+            return;
+        }
+
         // everything's fine, do it
         WorldPacket data(MSG_RAID_READY_CHECK, 8);
         data << GetPlayer()->GetGUID();
Invalid-IncompleteDatOrNotTrinityCore

Most helpful comment

Some BG quests like: https://woehead.way-of-elendil.fr/?quest=8114 and https://woehead.way-of-elendil.fr/?quest=7368 are sharable so disabling the sharing in BG without the possibility to choose is not an option.

Since quests will be disabled in BGs only, they can be shared outside a battleground.

I will try to find a solution as suggested by Tkrokli. Thanks.

All 17 comments

This issue is not considered valid because of the following reasons:

  • No proper commit hash (revision)

Please read http://bit.ly/tc-issuetracker-and-you and add the missing information to this issue. Thanks.

You must open a PR with this, and better to have it with a config option.

Just disable? No, thats not blizzlike

What is the purpose of sharing quests in battlegrounds anyway? Other than abusing this option and annoy other players just so they cannot play their game without someone spamming quest share.

Edit:
Also, "Ready Check" can be spammed by raid leaders in battlegrounds. What is the purpose of "Ready Check" in bg's ?

You are probably better off posting/sharing or making a Pull Request for this idea in https://github.com/TrinityCore/TrinityCoreCustomChanges , since https://github.com/TrinityCore/TrinityCore/ is committed to keeping the source code blizzlike (if possible).


edit: I agree with the idea, even though I haven't experienced this problem myself, but it should be configurable.
I can see how much it has been asked for in the Blizzard WoW forums based on Google search results.

It may not be blizzlike, but they are still bugs that can be abused.
I call them blizzlike flaws.

Sure, I have no problem seeing the issue and agree that it should be solved.
It will be much more welcome in the TrinityCoreCustomChanges project, though.

Some BG quests like: https://woehead.way-of-elendil.fr/?quest=8114 and https://woehead.way-of-elendil.fr/?quest=7368 are sharable so disabling the sharing in BG without the possibility to choose is not an option.

@mindsear : if you are able to come up with a solution to allow individual players to block incoming quest sharing instead of hardcode-blocking it for all, it would be more interesting in this project (even more so if configurable).

Some BG quests like: https://woehead.way-of-elendil.fr/?quest=8114 and https://woehead.way-of-elendil.fr/?quest=7368 are sharable so disabling the sharing in BG without the possibility to choose is not an option.

Since quests will be disabled in BGs only, they can be shared outside a battleground.

I will try to find a solution as suggested by Tkrokli. Thanks.

no, since https://woehead.way-of-elendil.fr/?quest=7368 can be only taken inside bg. if someone spams you, ignore it.

what happens if you ignore the player ? is quest sharing ignored in that case ?

I haven't tested yet, but I think /ignore <player name> only affects chat interaction.

BTW, could anyone who are able to replicate the quest spam situation consider testing the addon posted by Choonster <Corvus Canis> on this Blizz forum page?

Filterer.toc

## Title: Filterer
## Interface: 40300
## Notes: Consolidates raid join messages and automatically declines shared quests that you don't want.
## Author: Choonster
## SavedVariables: FILTERER_QUESTIDS, FILTERER_FILTEREDQUESTS

chat.lua
quest.lua

chat.lua

local addon, ns = ...
ns.prefix = "|cff33ff99Filterer:"
------------------
--Chat Filtering--
------------------
-- This section is based on Blizzard's WorldStateFrame.lua join/leave message consolidation filters.

do
    -- Locale-specific strings.
    -- Most of the European languages should make sense, but Russian and the three Asian languages (zhTW, zhCN, koKR) involved some guesswork.
    -- esES/esMX and ptPT/ptBR share translations.
    local locale = GetLocale()
    if locale == "zhTW" then
        ERR_PLAYERLIST_JOINED_RAID = "%d個玩家加入了團隊:%s"
        ERR_PLAYERS_JOINED_RAID_D  = "%d個玩家加入了團隊。"
    elseif locale == "zhCN" then
        ERR_PLAYERLIST_JOINED_RAID = "%d名玩家加入了团队:%s"
        ERR_PLAYERS_JOINED_RAID_D  = "%d名玩家加入了团队。"
    elseif locale == "koKR" then
        ERR_PLAYERLIST_JOINED_RAID = "%d명의 플레이어공격대에 참여했습니다. %s"
        ERR_PLAYERS_JOINED_RAID_D  = "%d명의 플레이어공격대에 참여했습니다."
    elseif locale == "ruRU" then
        ERR_PLAYERLIST_JOINED_RAID = "%d |4игрок вступил:игрока вступило:игроков вступило; рейдовой группе: %s";
        ERR_PLAYERS_JOINED_RAID_D  = "%d |4игрок вступил:игрока вступило:игроков вступило; рейдовой группе."
    elseif locale == "frFR" then
        ERR_PLAYERLIST_JOINED_RAID = "%d joueurs ont rejoint le groupe de raid : %s"
        ERR_PLAYERS_JOINED_RAID_D  = "%d joueurs ont rejoint le groupe de raid."
    elseif locale == "deDE" then
        ERR_PLAYERLIST_JOINED_RAID = "%d Spieler sind der Schlachtzug beigetreten: %s"
        ERR_PLAYERS_JOINED_RAID_D  = "%d Spieler sind der Schlachtzug beigetreten."
    elseif locale == "esES" or locale == "esMX" then
        ERR_PLAYERLIST_JOINED_RAID = "%d jugadores se han unido a grupo de banda: %s"
        ERR_PLAYERS_JOINED_RAID_D  = "%d jugadores se han unido a grupo de banda."
    elseif locale == "ptPT" or locale == "ptBR" then
        ERR_PLAYERLIST_JOINED_RAID = "%d jogadores juntaram-se à grupo de raide: %s"
        ERR_PLAYERS_JOINED_RAID_D  = "%d jogadores juntaram-se à grupo de raide."
    else
        ERR_PLAYERLIST_JOINED_RAID = "%d players have joined the raid group: %s"
        ERR_PLAYERS_JOINED_RAID_D  = "%d players have joined the raid group."
    end
end

-- local ERR_PLAYERLIST_JOINED_RAID, ERR_PLAYERS_JOINED_RAID_D, ERR_RAID_MEMBER_ADDED_S = ERR_PLAYERLIST_JOINED_RAID, ERR_PLAYERS_JOINED_RAID_D, ERR_RAID_MEMBER_ADDED_S

local frame = CreateFrame("Frame")
ns.frame = frame
local lastupdate = 0
local THROTTLE = 5

local GLOBALS = {
    "ERR_RAID_MEMBER_ADDED_S", -- "%s has joined the raid group."
}

local FILTERED = {}
local ADDED_PLAYERS = {}

local chatString;
for _, str in next, GLOBALS do
    chatString = _G[str];
    if chatString then
        chatString = chatString:gsub("%[", "%%[")
        chatString = chatString:gsub("%]", "%%]")
        chatString = chatString:gsub("%%s", "(.-)")
        tinsert(FILTERED, chatString)
    end
end

local function filterFunc(self, event, message)
    local _, instanceType = IsInInstance()
    if instanceType == "pvp" then return end -- If we're in a BG, let the WorldStateFrame chat filter handle the join/leave messages
    for i, str in next, FILTERED do
        playerName = message:match(str)
        if ( playerName ) then
            -- Trim realm names
            playerName = playerName:match("([^%-]+)%-?.*")
            ADDED_PLAYERS[playerName] = true
            return true
        end
    end
end

frame:SetScript("OnUpdate", function(self, elapsed)
    lastupdate = lastupdate + elapsed
    if lastupdate >= THROTTLE then
        local addedPlayers, playerString = 0;
        for i in next, ADDED_PLAYERS do
            if ( not playerString ) then
                playerString = i;
            else
                playerString = playerString .. PLAYER_LIST_DELIMITER .. i;
            end

            addedPlayers = addedPlayers + 1;
        end

        if ( addedPlayers > 0 ) then
            local info = ChatTypeInfo["SYSTEM"];
            if ( addedPlayers > 1 and addedPlayers <= 3 ) then
                DEFAULT_CHAT_FRAME:AddMessage(ERR_PLAYERLIST_JOINED_RAID:format(addedPlayers, playerString), info.r, info.g, info.b, info.id);
            elseif ( addedPlayers > 3 ) then
                DEFAULT_CHAT_FRAME:AddMessage(ERR_PLAYERS_JOINED_RAID_D:format(addedPlayers), info.r, info.g, info.b, info.id);
            else
                DEFAULT_CHAT_FRAME:AddMessage(ERR_RAID_MEMBER_ADDED_S:format(playerString), info.r, info.g, info.b, info.id);
            end

            for i in next, ADDED_PLAYERS do
                ADDED_PLAYERS[i] = nil;
            end
        end
    end
end)

frame:SetScript("OnEvent", function(self, event, ...)
    self[event](self, ...)
end)

frame:RegisterEvemt("RAID_ROSTER_UPDATE")

function frame:RAID_ROSTER_UPDATE()
    if GetNumRaidMembers() > 0 and select(2, IsInInstance()) ~= "pvp" then
        ChatFrame_AddMessageEventFilter("CHAT_MSG_SYSTEM", filterFunc)
        self:Show()
    else
        ChatFrame_RemoveMessageEventFilter("CHAT_MSG_SYSTEM", filterFunc)
        self:Hide()
    end
end

quest.lua

local addon, ns = ...
local frame = ns.frame
local prefix = ns.prefix
ns.frame, ns.prefix = nil, nil
local latestTitle, latestID;

--------------------------
--Shared Quest Filtering--
--------------------------
local ID_TO_TITLE, TITLE_TO_ID, FILTERED_QUESTS;

frame:RegisterEvent("ADDON_LOADED")
frame:RegisterEvent("QUEST_DETAIL")
frame:RegisterEvent("PLAYER_LOGOUT")

function frame:ADDON_LOADED()
    TITLE_TO_ID = {}
    ID_TO_TITLE = setmetatable({}, {
        __index = FILTERER_QUESTIDS,
        __newindex = function(tab, id, title)
            FILTERER_QUESTIDS[id] = title
            TITLE_TO_ID[title] = id
        end
    })
    for id, title in pairs(FILTERER_QUESTIDS) do
        TITLE_TO_ID[title] = id
    end
    FILTERED_QUESTS = FILTERER_FILTEREDQUESTS or {}
end

function frame:QUEST_DETAIL()
    latestTitle = GetTitleText()
    latestID = GetQuestID()
    ID_TO_TITLE[latestID] = latestTitle
    if UnitName("npc") == UnitName("player") and (FILTERED_QUESTS[latestID] or FILTERED_QUESTS[latestTitle]) then -- If the quest is shared, the name of the "npc" unit is the player's name.
        AbandonQuest()
        print(prefix, ("Quest abandoned: %s."):format(latestTitle))
    end
end

function frame:PLAYER_LOGOUT()
    FILTERER_FILTEREDQUESTS = FILTERED_QUESTS
end

-- Dynamically-generated indenting strings. Takes a numeric index n and returns a string of 4n spaces.
-- Results are automatically cached for future lookup.
local TABSPACE = "    "
local indent = setmetatable({}, {
    __index = function(tab, key)
        key = tonumber(key)
        if not key then return end

        local s = ""
        for i = 1, key do
            s = s .. TABSPACE
        end
        rawset(tab, key, s)
        return s
    end
})

local function printhelp()
    print(prefix, "|cffff0000/filterquest|r or |cffff0000/fq cmd quest|r")
    print(indent[1], "|cffff0000add||remove quest|r -- Adds/removes a quest from the blacklist.")
    print(indent[2], "Blacklisted quests will be automatically declined when shared. |cffff0000quest|r can be a quest ID (from Wowhead), a quest title (case sensitive) or |cffff0000current|r to use the most recent quest viewed.")
    print(indent[1], "|cffff0000list|r -- List the currently filtered quests.")
end

SLASH_FILTERQUEST1, SLASH_FILTERQUEST2 = "/filterquest", "/fq"
function SlashCmdList.FILTERQUEST(input)
    local cmd, quest = input:match("^%s*(%a+)%s*(.*)%s*$")
    cmd = cmd:lower()
    local questNum = tonumber(quest) or TITLE_TO_ID[quest]

    if cmd == "add" then
        local addedID, addedTitle;
        if quest:lower() == "current" then
            if latestTitle and latestID then
                FILTERED_QUESTS[latestTitle] = true
                FILTERED_QUESTS[latestID] = true
                print(prefix, ("Added quest %s (ID %s) to the blacklist."):format(latestTitle, latestID))
            else
                print("No quest has been viewed yet. Try a specific title or ID.")
            end
        else
            if questNum then
                FILTERED_QUESTS[questNum] = true
                addedID = questNum
                addedTitle = ID_TO_TITLE[questNum] or "<Unknown Title>"
            elseif quest ~= "" then
                FILTERED_QUESTS[quest] = true
                addedTitle = quest
                addedID = TITLE_TO_ID[quest] or "unknown"
            else
                return printhelp()
            end         
        end
        print(prefix, ("Added quest %s (ID %s) to the blacklist."):format(addedTitle, addedID))
    elseif cmd == "remove" then
        local removedID, removedTitle;
        if quest:lower() == "current" and (latestTitle and latestID) then
            FILTERED_QUESTS[latestTitle] = nil
            FILTERED_QUESTS[latestID] = nil
        else
            if questNum then
                FILTERED_QUESTS[questNum] = nil
                removedID = questNum
                removedTitle = ID_TO_TITLE[questNum] or "<Unknown Title>"
            elseif quest ~= "" then
                FILTERED_QUESTS[quest] = nil
                removedTitle = quest
                removedID = TITLE_TO_ID[quest] or "unknown"
            else
                return printhelp()
            end
            print(prefix, ("Removed quest %s (ID %s) from the blacklist."):format(removedTitle, removedID))
        end
    elseif cmd == "list" then
        print(prefix, "Filtered quests")
        for quest in pairs(FILTERED_QUESTS) do
            local id, title;
            if type(quest) == "number" then
                id = quest
                title = ID_TO_TITLE[questNum] or "<Unknown Title>"
            else
                title = quest
                id = TITLE_TO_ID[quest] or "unknown"
            end
            print(("%s (ID %s)"):format(title, id))
        end
    else
        printhelp()
    end
end

no, since https://woehead.way-of-elendil.fr/?quest=7368 can be only taken inside bg. if someone spams you, ignore it.

With my suggested modification, every player can take quests in Battlegrounds, more specifically, Alterac Valley.

Tested: Unfortunately, /ignore <player name> doesn't work in this case.

I will test that addon. Thanks.
Edit: That addon doesn't work in this case.


We can either add this modification to ignore command or make a command to disable questshare / enable questshare for every player to be able to use.
I need a little help with this, because I don't know how to do it.

Adding a setting to make /ignore ignore quest sharing should be quite easy

I don't understand how to make it work with opcodes.
Or there may be an easier option to achieve that?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

DDuarte picture DDuarte  ·  3Comments

Lopfest picture Lopfest  ·  3Comments

Teppic1 picture Teppic1  ·  3Comments

Rochet2 picture Rochet2  ·  3Comments

besplash picture besplash  ·  3Comments