wow状态监测插件

This commit is contained in:
王鹏
2026-03-18 09:30:49 +08:00
parent b7719b377d
commit ebdfadcdd7
3 changed files with 419 additions and 0 deletions

233
LogicBeacon/LogicBeacon.lua Normal file
View File

@@ -0,0 +1,233 @@
--[[
LogicBeacon - 多状态像素编码器
在屏幕角落显示横向像素条,每个像素对应一个游戏状态,
供外部 Python 等脚本截取小区域即可获取完整状态机。
]]
-- 配置8个状态位1个白色锚点 + 7个数据位
local PIXEL_SIZE = 10
local STATUS_COUNT = 8
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
-- 升级:至少 8 个状态位(含目标位+后勤位+坐标朝向)
LogicBeaconDB.statusCount = math.max(LogicBeaconDB.statusCount or 0, 8)
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~8]=数据位)
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
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
)
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 查看命令。")

View File

@@ -0,0 +1,8 @@
## Interface: 30300
## Title: LogicBeacon
## Notes: 屏幕角落像素条,用颜色编码游戏状态
## Author: LogicBeacon
## Version: 1.0.0
## SavedVariablesPerCharacter: LogicBeaconDB
LogicBeacon.lua

View File

@@ -0,0 +1,178 @@
[
[
35.81,
47.16
],
[
35.43,
47.54
],
[
35.07,
47.91
],
[
34.81,
48.4
],
[
34.81,
48.91
],
[
34.81,
49.43
],
[
35.05,
49.91
],
[
35.42,
50.27
],
[
35.79,
50.62
],
[
36.01,
51.07
],
[
36.11,
51.57
],
[
36.2,
52.09
],
[
36.2,
52.63
],
[
36.19,
53.15
],
[
36.18,
53.66
],
[
36.18,
54.17
],
[
36.17,
54.69
],
[
36.16,
55.21
],
[
36.15,
55.73
],
[
36.15,
56.26
],
[
36.14,
56.76
],
[
36.3,
57.25
],
[
36.83,
57.33
],
[
37.29,
57.12
],
[
37.39,
56.57
],
[
37.4,
56.05
],
[
37.38,
55.54
],
[
37.32,
55.01
],
[
37.27,
54.49
],
[
37.25,
53.96
],
[
37.23,
53.46
],
[
37.21,
52.94
],
[
37.19,
52.41
],
[
37.17,
51.9
],
[
37.1,
51.4
],
[
36.96,
50.86
],
[
36.79,
50.34
],
[
36.62,
49.82
],
[
36.49,
49.28
],
[
36.39,
48.77
],
[
36.3,
48.27
],
[
36.2,
47.77
],
[
36.09,
47.28
],
[
35.81,
47.16
]
]