BiaoGe 团队成员互相查看蓝龙(世界BOSS)CD 的实现原理

蓝龙CD同步_实现原理

本文说明 BiaoGe 插件(titan / 60 服版本)如何实现团队成员在团队中互相查看彼此的世界BOSS CD,包括蓝龙(艾索雷葛斯 / Azuregos)。涉及的核心文件是 Core/Module/WorldBossCD.lua,数据来源在 Core/Module/RoleOverview.lua,BOSS 定义与编号在 Core/DB/DB.luaCore/DB/DB_BossName.lua

1. 功能定位

WorldBossCD.lua 文件头部有 if not BG.IsTitan then return end,说明该功能只在 titan(60 服)版本启用。它提供一个”团员世界BossCD”面板:在团队中,每个成员都能看到其他队友对各世界BOSS(蓝龙、卡扎克、末日行者、末日领主卡扎克)是”有CD”还是”无CD”。蓝龙在列表里排第一位,对应 bossID = 116

2. 本地数据来源

插件先用 RoleOverview 扫描玩家自己的世界BOSS锁定状态。在 Core/Module/RoleOverview.lua 中,针对 titan 版本会遍历 GetNumSavedWorldBosses() / GetSavedWorldBossInfo(),把有CD的世界BOSS写入 BiaoGe.RaidCD[realmID][player],并打上 isWorldBoss = true 标记,其中蓝龙的 fbId = 116(即 GetSavedWorldBossInfo 在该服返回的世界BOSS保存ID):

if BG.IsTitan then
    for i = 1, GetNumSavedWorldBosses() do
        local name, bossID, resettime = GetSavedWorldBossInfo(i)
        if bossID then
            local a = {
                player = player,
                colorplayer = colorplayer,
                fbId = bossID,
                num = 0,
                resettime = resettime,
                endtime = resettime + time,
                isWorldBoss = true,
            }
            tinsert(cd, a)
            worldBossText = worldBossText .. bossID
        end
    end
end

相关 BOSS 定义:

  • Core/DB/DB_BossName.lua(第 397–410 行)定义了 titan 世界BOSS列表,第一个 艾索雷葛斯(即蓝龙),其后为卡扎克、末日行者、末日领主卡扎克。
  • Core/DB/DB.lua(第 397–403 行)定义了 BG.worldBossNpcID = {6109 蓝龙, 12397 卡扎克, 17711 末日行者, 18728 末日领主卡扎克},这是另一套 NPC id,只用于 Loot.lua 击杀后按 GUID 自动存战利品,与本文 CD 同步使用的保存ID 116 是不同的编号体系,不要混淆。

3. 把自己的 CD 广播给团队

WorldBossCD.lua 中的 GetWorldBossCDMsg() 遍历本地 RaidCD,把所有 isWorldBoss 的 BOSS 汇总成消息 cd^bossID:num,bossID:num,(有CD为1,无CD为0)。ns.SendMyWorldBossCD() 通过 ChatThrottleLib:SendAddonMessage 以插件频道广播给整个团队:

function GetWorldBossCDMsg()
    if BiaoGe[FBCD][realmID][player] then
        for k, v in pairs(BiaoGe[FBCD][realmID][player]) do
            if v.isWorldBoss then
                local bossID = v.fbId
                bossInfo[bossID] = 1
            end
        end
    end
    local msg = "cd^"
    for bossID, num in pairs(bossInfo) do
        msg = msg .. bossID .. ":" .. num .. ","
    end
    return msg
end

function ns.SendMyWorldBossCD()
    ChatThrottleLib:SendAddonMessage("NORMAL", "BiaoGeWorldBoss", GetWorldBossCDMsg(), "RAID")
end

广播触发的时机有三处:

  • GROUP_ROSTER_UPDATE 事件:进团或团队人数增加时(带节流判断 CanSend_WorldCD(),人数不增不重复发)。
  • RoleOverview.lua 中,当检测到本地世界BOSS文本变化(如刚打完蓝龙,从无CD变成有CD)且处于团队中时,立即补发一次。
  • 登录 4 秒后发一条 VersionCheck,向团队询问谁装了插件。

4. 接收队友的 CD

每个成员都监听 CHAT_MSG_ADDON 事件,前缀为 "BiaoGeWorldBoss",频道为 "RAID"。收到 VersionCheck 就回发自己的CD;收到 cd^... 则按 bossID:num 解析,存入 BG.worldBossRaidCD[sender][bossID](以发送者名字归类的共享表),随后刷新该队友对应的按钮:

BG.RegisterEvent("CHAT_MSG_ADDON", function(self, event, ...)
    local prefix, msg, distType, _, sender = ...
    if prefix == "BiaoGeWorldBoss" and distType == "RAID" then
        if msg == "VersionCheck" and sender ~= player then
            ns.SendMyWorldBossCD()
        elseif msg:find("cd%^") then
            BG.worldBossRaidCD[sender] = BG.worldBossRaidCD[sender] or {}
            local _, info = strsplit("^", msg)
            if info then
                for _, v in ipairs({ strsplit(",", info) }) do
                    local bossID, cd = strsplit(":", v)
                    bossID = tonumber(bossID)
                    cd = tonumber(cd)
                    if bossID and cd and BG.worldBossRaidCD[sender][bossID] ~= 1 then
                        BG.worldBossRaidCD[sender][bossID] = cd
                    end
                end
            end
            BG.After(.2, function()
                BG.worldBossCDFrame:UpdateFrame(sender)
            end)
        end
    end
end)

5. 显示给团队成员

面板 worldBossCDFrame 为团队 1~40 人各生成一个按钮,调用 GetWorldBossCDText(name) 查询 BG.worldBossRaidCD[name][当前选中的bossID](默认选中蓝龙 116),显示结果:

  • 返回 1 → 红底”有CD”;
  • 返回 0 → 绿底”无CD”;
  • 其它(nil,通常是对方没装插件或还没收到数据)→ 灰底”未知”。
function GetWorldBossCDText(name)
    if IsInRaid(1) then
        return BG.raidBiaoGeVersion[name] and BG.worldBossRaidCD[name] and BG.worldBossRaidCD[name][GetBossIDByIndex()] or nil
    else
        return BG.worldBossRaidCD[name] and BG.worldBossRaidCD[name][GetBossIDByIndex()] or nil
    end
end

顶部下拉框可切换查看哪个世界BOSS(蓝龙=116 / 卡扎克=117 / 末日行者=119 / 末日领主=118),并实时统计”无CD人数 / 团队总人数”。

6. 关键设计点

  • 只有双方都装了 BiaoGe 才能在团队里互相看到:团队内显示额外要求 BG.raidBiaoGeVersion[name] 存在(对方回了 VersionCheck 且版本号已知),否则显示”未知”。
  • 同步完全走游戏内置的插件通信(SendAddonMessage + CHAT_MSG_ADDON,频道 RAID),不需要任何外部服务器,数据随团队进出实时更新。
  • 数据以玩家名为 key 在 BG.worldBossRaidCD 中聚合,UI 只是把这份共享表渲染成每人的有/无CD标签。
  • 队友看到的状态 100% 取决于你广播出去的 cd^bossID:num 中的数值,与你自己本地 RaidCD 是否真的打过无关。

总结

完整数据流为:本地用 GetSavedWorldBossInfo 拿到自己蓝龙等世界BOSS的CD → 通过 RAID 插件频道把自己的 cd^bossID:num 广播出去 → 队友 CHAT_MSG_ADDON 收到后按名字存进共享表 BG.worldBossRaidCD → 面板逐人渲染”有CD/无CD”,从而实现团队成员互相查看蓝龙CD。