Files
wow/LogicBeacon/LogicBeacon.lua

285 lines
8.6 KiB
Lua
Raw Permalink Normal View History

2026-03-18 09:30:49 +08:00
--[[
LogicBeacon -
Python
]]
-- 配置10个状态位1个白色锚点 + 9个数据位
2026-03-18 09:30:49 +08:00
local PIXEL_SIZE = 10
local STATUS_COUNT = 10
2026-03-18 09:30:49 +08:00
local ADDON_NAME = "LogicBeacon"
-- 默认配置(可被 SavedVariables 覆盖)
local defaults = {
pixelSize = PIXEL_SIZE,
statusCount = STATUS_COUNT,
point = "TOPLEFT",
x = 10, -- 整体向右偏移 10 像素
y = 0,
scale = 1,
locked = false,
}
-- 确保每角色存储存在
LogicBeaconDB = LogicBeaconDB or {}
for k, v in pairs(defaults) do
if LogicBeaconDB[k] == nil then
LogicBeaconDB[k] = v
end
end
-- 升级:至少 10 个状态位(含跟随信号)
LogicBeaconDB.statusCount = math.max(LogicBeaconDB.statusCount or 0, 10)
2026-03-18 09:30:49 +08:00
local db = LogicBeaconDB
-- 主框架
local f = CreateFrame("Frame", "LogicBeaconFrame", UIParent)
local totalW = db.pixelSize * db.statusCount
local totalH = db.pixelSize
f:SetSize(totalW, totalH)
f:SetScale(db.scale)
f:SetPoint(db.point, UIParent, db.point, db.x, db.y)
f:SetFrameStrata("TOOLTIP")
f:SetClampedToScreen(true)
-- 背景底色(防止半透明干扰)
local bg = f:CreateTexture(nil, "BACKGROUND")
bg:SetAllPoints()
bg:SetColorTexture(0, 0, 0, 1)
-- 像素纹理([1]=锚点 [2~10]=数据位)
2026-03-18 09:30:49 +08:00
local pixels = {}
for i = 1, db.statusCount do
local tex = f:CreateTexture(nil, "OVERLAY")
tex:SetSize(db.pixelSize, db.pixelSize)
tex:SetPoint("LEFT", f, "LEFT", (i - 1) * db.pixelSize, 0)
pixels[i] = tex
end
-- 后勤位:背包空格、装备耐久、死亡/灵魂状态
local function GetLogisticsInfo()
-- 1. 检查背包空格 (0 - 100+)
local freeSlots = 0
for i = 0, 4 do
local numFree = GetContainerNumFreeSlots(i)
freeSlots = freeSlots + numFree
end
-- 2. 检查装备最低耐久度 (0.0 - 1.0)
local minDurability = 1
for i = 1, 18 do
local current, maximum = GetInventoryItemDurability(i)
if current and maximum and maximum > 0 then
minDurability = math.min(minDurability, current / maximum)
end
end
-- 3. 死亡状态 (0:存活, 0.5:死尸, 1.0:灵魂)
local dState = 0
if UnitIsGhost("player") then
dState = 1.0
elseif UnitIsDead("player") then
dState = 0.5
end
return freeSlots, minDurability, dState
end
-- 地图坐标(现代 C_Map API返回 0~1 比例)
local function GetPlayerCoords()
local mapID = C_Map.GetBestMapForUnit("player")
if mapID then
local mapPos = C_Map.GetPlayerMapPosition(mapID, "player")
if mapPos then
return mapPos:GetXY()
end
end
return 0, 0
end
-- 专门用于计算飞行信号的函数R 通道0 未上马 / 0.5 可起飞需按空格 / 1.0 已在飞)
local function GetFlightSignal()
local isMounted = IsMounted()
local isFlying = IsFlying()
local canFly = IsFlyableArea()
if not isMounted then
return 0
end
if isMounted and canFly and not isFlying then
if not UnitAffectingCombat("player") and IsOutdoors() then
return 0.5
end
end
if isMounted and isFlying then
return 1.0
end
return 0
end
-- 专门用于计算跟随信号的函数R 通道0 未组队 / 0.5 需补跟随 / 1.0 跟随中)
local function GetFollowSignal()
if not IsInGroup() then
return 0
end
local leader = "party1"
if IsFollowing() then
return 1.0
else
if UnitExists(leader) and UnitIsVisible(leader) then
return 0.5
end
end
return 0
end
2026-03-18 09:30:49 +08:00
f:SetScript("OnUpdate", function()
-- [1] 锚点:永远纯白 (255, 255, 255)
pixels[1]:SetColorTexture(1, 1, 1)
-- [2] 血量:红色通道
local hp = UnitHealth("player") / math.max(1, UnitHealthMax("player"))
local targetHp = UnitHealth("target") / math.max(1, UnitHealthMax("target"))
pixels[2]:SetColorTexture(hp, targetHp, 0)
-- [3] 法力/能量:蓝色通道
local mp = UnitPower("player") / math.max(1, UnitPowerMax("player"))
pixels[3]:SetColorTexture(0, 0, mp)
-- [4] 战斗状态:绿色通道 (255=战斗中)
if UnitAffectingCombat("player") then
pixels[4]:SetColorTexture(0, 1, 0)
else
pixels[4]:SetColorTexture(0, 0, 0)
end
-- [5] 目标状态:红色通道 (255=有敌对目标)
-- 逻辑:可以攻击 AND 目标不是玩家 AND 不是灰名怪 AND 不是玩家宠物
if UnitCanAttack("player", "target") and not UnitIsPlayer("target") and not UnitIsTapDenied("target") and not UnitPlayerControlled("target") then
-- 只有满足这三个条件,才输出“有效目标”信号(红色)
pixels[5]:SetColorTexture(1, 0, 0)
else
-- 只要其中一个条件不满足(比如怪被抢了,或者是玩家),就输出黑色
pixels[5]:SetColorTexture(0, 0, 0)
end
-- [6] 综合后勤与死亡位
local free, repair, dead = GetLogisticsInfo()
-- R: 空格数 (0-1Python *255 还原)
-- G: 耐久度 (0-1)
-- B: 死亡状态 (0=存活, 0.5=死尸, 1.0=灵魂)
pixels[6]:SetColorTexture(free / 255, repair, dead)
-- [7][8] 地图坐标与朝向C_Map 现代 API0~1 比例)
local mapX, mapY = GetPlayerCoords()
local facing = GetPlayerFacing() or 0
-- [7] XR=整数部分(×100)G=小数部分B=朝向/2π
pixels[7]:SetColorTexture(
math.floor(mapX * 100) / 255,
math.floor((mapX * 10000) % 100) / 255,
facing / 6.28318
)
-- [8] YR=整数部分(×100)G=小数部分B=预留
pixels[8]:SetColorTexture(
math.floor(mapY * 100) / 255,
math.floor((mapY * 10000) % 100) / 255,
0
)
-- [9] R=飞行信号 GetFlightSignal()G=上马(1/0)B=可飞区域 IsFlyableArea()
local fSignal = GetFlightSignal()
local mountedSig = IsMounted() and 1 or 0
local canFlySig = IsFlyableArea() and 1 or 0
pixels[9]:SetColorTexture(fSignal, mountedSig, canFlySig, 1)
-- [10] R=跟随信号0 / 0.5 需补跟随 / 1.0 跟随中)
local followSig = GetFollowSignal()
pixels[10]:SetColorTexture(followSig, 0, 0, 1)
2026-03-18 09:30:49 +08:00
end)
-- 可拖动
f:SetMovable(not db.locked)
f:EnableMouse(not db.locked)
f:RegisterForDrag("LeftButton")
f:SetScript("OnDragStart", function()
if not db.locked then
f:StartMoving()
end
end)
f:SetScript("OnDragStop", function()
f:StopMovingOrSizing()
local _, _, _, x, y = f:GetPoint(1)
db.x = x
db.y = y
end)
-- 右键菜单:锁定/解锁、重置位置
local menu = CreateFrame("Frame", "LogicBeaconMenu", f, "UIDropDownMenuTemplate")
f:SetScript("OnMouseDown", function(_, button)
if button == "RightButton" then
local menuList = {
{
text = db.locked and "解锁位置" or "锁定位置",
func = function()
db.locked = not db.locked
f:SetMovable(not db.locked)
f:EnableMouse(not db.locked)
end,
},
{
text = "重置到左上角",
func = function()
db.point = "TOPLEFT"
db.x = 10
db.y = 0
f:ClearAllPoints()
f:SetPoint(db.point, UIParent, db.point, db.x, db.y)
end,
},
}
EasyMenu(menuList, menu, "cursor", 0, 0, "MENU")
end
end)
-- 登录完成后确保显示
local event = CreateFrame("Frame")
event:RegisterEvent("PLAYER_LOGIN")
event:SetScript("OnEvent", function()
f:Show()
end)
-- Slash 命令
SlashCmdList["LOGICBEACON"] = function(msg)
msg = msg:lower():gsub("^%s*(.-)%s*$", "%1")
if msg == "lock" or msg == "锁定" then
db.locked = true
f:SetMovable(false)
f:EnableMouse(false)
print("|cff00ff00[LogicBeacon]|r 已锁定")
elseif msg == "unlock" or msg == "解锁" then
db.locked = false
f:SetMovable(true)
f:EnableMouse(true)
print("|cff00ff00[LogicBeacon]|r 已解锁")
elseif msg == "reset" or msg == "重置" then
db.point, db.x, db.y = "TOPLEFT", 10, 0
f:ClearAllPoints()
f:SetPoint(db.point, UIParent, db.point, db.x, db.y)
print("|cff00ff00[LogicBeacon]|r 已重置到左上角")
else
print("|cff00ff00[LogicBeacon]|r 用法: /lb lock|unlock|reset (锁定|解锁|重置位置)")
end
end
SLASH_LOGICBEACON1 = "/lb"
SLASH_LOGICBEACON2 = "/logicbeacon"
print("|cff00ff00[LogicBeacon]|r 已加载。右键像素条可锁定/重置,/lb 查看命令。")