You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
318 lines
11 KiB
318 lines
11 KiB
|
5 years ago
|
--========================================================--
|
||
|
|
-- Scorpio UnitFrame API --
|
||
|
|
-- --
|
||
|
|
-- Author : kurapica125@outlook.com --
|
||
|
|
-- Create Date : 2020/11/25 --
|
||
|
|
--========================================================--
|
||
|
|
|
||
|
|
--========================================================--
|
||
|
|
Scorpio "Scorpio.Secure.UnitFrame.API" "1.0.0"
|
||
|
|
--========================================================--
|
||
|
|
|
||
|
|
namespace "Scorpio.Secure.UnitFrame"
|
||
|
|
|
||
|
|
import "System.Reactive"
|
||
|
|
import "System.Toolset"
|
||
|
|
|
||
|
|
------------------------------------------------------------
|
||
|
|
-- Simple Unit API --
|
||
|
|
------------------------------------------------------------
|
||
|
|
local _UnitNameSubject = Subject()
|
||
|
|
|
||
|
|
__SystemEvent__()
|
||
|
|
function UNIT_NAME_UPDATE(unit)
|
||
|
|
_UnitNameSubject:OnNext(unit)
|
||
|
|
end
|
||
|
|
|
||
|
|
__SystemEvent__()
|
||
|
|
function GROUP_ROSTER_UPDATE()
|
||
|
|
_UnitNameSubject:OnNext("any")
|
||
|
|
end
|
||
|
|
|
||
|
|
__Static__()
|
||
|
|
function Wow.Unit()
|
||
|
|
return Wow.FromUnitEvent()
|
||
|
|
end
|
||
|
|
|
||
|
|
__Static__() __AutoCache__()
|
||
|
|
function Wow.UnitName(withServer)
|
||
|
|
return Wow.FromUnitEvent(_UnitNameSubject):Next():Map(withServer and function(unit) return GetUnitName(unit, true) end or GetUnitName)
|
||
|
|
end
|
||
|
|
|
||
|
|
__Static__() __AutoCache__()
|
||
|
|
function Wow.UnitColor()
|
||
|
|
return Wow.FromUnitEvent(_UnitNameSubject):Next():Map(function(unit)
|
||
|
|
local _, cls = UnitClass(unit)
|
||
|
|
return Color[cls or "PALADIN"]
|
||
|
|
end)
|
||
|
|
end
|
||
|
|
|
||
|
|
__Static__() __AutoCache__()
|
||
|
|
function Wow.UnitExtendColor(withThreat)
|
||
|
|
local scolor = Color(1, 1, 1)
|
||
|
|
return Wow.FromUnitEvent("UNIT_FACTION", "UNIT_THREAT_SITUATION_UPDATE"):Map(function(unit)
|
||
|
|
if not UnitIsPlayer(unit) then
|
||
|
|
if UnitIsTapDenied(unit) then return Color.RUNES end
|
||
|
|
|
||
|
|
if withThreat and UnitCanAttack("player", unit) then
|
||
|
|
local threat = UnitThreatSituation("player", unit)
|
||
|
|
if threat and threat > 0 then
|
||
|
|
scolor.r, scolor.g, scolor.b = GetThreatStatusColor(threat)
|
||
|
|
return scolor
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
scolor.r, scolor.g, scolor.b = UnitSelectionColor(unit, true)
|
||
|
|
return scolor
|
||
|
|
end
|
||
|
|
local _, cls = UnitClass(unit)
|
||
|
|
return Color[cls or "PALADIN"]
|
||
|
|
end)
|
||
|
|
end
|
||
|
|
|
||
|
|
-- Unit Level API
|
||
|
|
__Static__()
|
||
|
|
function Wow.UnitLevel(format)
|
||
|
|
format = format or "%s"
|
||
|
|
local unknownFormat = format:gsub("%%%w+", "%%s")
|
||
|
|
return Wow.FromUnitEvent(Wow.FromEvent("PLAYER_LEVEL_UP"):Map(function(level) return "player", level end))
|
||
|
|
:Map(Scorpio.IsRetail and function(unit, level)
|
||
|
|
level = level or UnitLevel(unit)
|
||
|
|
if level and level > 0 then
|
||
|
|
if UnitIsWildBattlePet(unit) or UnitIsBattlePetCompanion(unit) then
|
||
|
|
level = UnitBattlePetLevel(unit)
|
||
|
|
end
|
||
|
|
return strformat(format, level)
|
||
|
|
else
|
||
|
|
return strformat(unknownFormat, "???")
|
||
|
|
end
|
||
|
|
end or function(unit, level)
|
||
|
|
level = level or UnitLevel(unit)
|
||
|
|
if level and level > 0 then
|
||
|
|
return strformat(format, level)
|
||
|
|
else
|
||
|
|
return strformat(unknownFormat, "???")
|
||
|
|
end
|
||
|
|
end)
|
||
|
|
end
|
||
|
|
|
||
|
|
__Static__() __AutoCache__()
|
||
|
|
function Wow.UnitClassification()
|
||
|
|
return Wow.FromUnitEvent("UNIT_CLASSIFICATION_CHANGED"):Map(UnitClassification)
|
||
|
|
end
|
||
|
|
|
||
|
|
__Static__() __AutoCache__()
|
||
|
|
function Wow.UnitClassificationColor()
|
||
|
|
return Wow.UnitClassification():Map(function(class)
|
||
|
|
if class == "elite" then
|
||
|
|
return Color.YELLOW
|
||
|
|
elseif class == "rare" then
|
||
|
|
return Color.WHITE
|
||
|
|
elseif class == "rareelite" then
|
||
|
|
return Color.CYAN
|
||
|
|
elseif class == "worldboss" then
|
||
|
|
return Color.RAGE
|
||
|
|
else
|
||
|
|
return Color.NORMAL
|
||
|
|
end
|
||
|
|
end)
|
||
|
|
end
|
||
|
|
|
||
|
|
__Static__() __Arguments__{ ColorType/nil }
|
||
|
|
function Wow.UnitLevelColor(default)
|
||
|
|
return Wow.FromUnitEvent(Wow.FromEvent("PLAYER_LEVEL_UP"):Map(function(level) return "player", level end))
|
||
|
|
:Map(function(unit, level)
|
||
|
|
if not level and UnitCanAttack("player", unit) then
|
||
|
|
return GetQuestDifficultyColor(UnitLevel(unit) or 99)
|
||
|
|
end
|
||
|
|
return default or Color.NORMAL
|
||
|
|
end)
|
||
|
|
end
|
||
|
|
|
||
|
|
-- The Aura API
|
||
|
|
__Static__() __AutoCache__()
|
||
|
|
function Wow.UnitAura()
|
||
|
|
return Wow.FromUnitEvent("UNIT_AURA"):Next()
|
||
|
|
end
|
||
|
|
|
||
|
|
__Static__() __AutoCache__()
|
||
|
|
function Wow.UnitTotem()
|
||
|
|
return Wow.FromUnitEvent(Wow.FromEvent("PLAYER_TOTEM_UPDATE"):Map("=>'player'"))
|
||
|
|
end
|
||
|
|
|
||
|
|
-- Unit State API
|
||
|
|
__Static__() __AutoCache__()
|
||
|
|
function Wow.UnitIsDisconnected()
|
||
|
|
return Wow.FromUnitEvent("UNIT_HEALTH", "UNIT_CONNECTION"):Next():Map(function(unit) return not UnitIsConnected(unit) end)
|
||
|
|
end
|
||
|
|
|
||
|
|
__Static__() __AutoCache__()
|
||
|
|
function Wow.UnitIsTarget()
|
||
|
|
return Wow.FromUnitEvent(Wow.FromEvent("PLAYER_TARGET_CHANGED"):Map("=>'any'")):Map(function(unit) return UnitIsUnit(unit, "target") end)
|
||
|
|
end
|
||
|
|
|
||
|
|
__Static__() __AutoCache__()
|
||
|
|
function Wow.UnitIsPlayer()
|
||
|
|
return Wow.FromUnitEvent(_UnitNameSubject):Map(function(unit) return UnitIsUnit(unit, "player") end)
|
||
|
|
end
|
||
|
|
|
||
|
|
__Static__() __AutoCache__()
|
||
|
|
function Wow.UnitNotPlayer()
|
||
|
|
return Wow.FromUnitEvent(_UnitNameSubject):Map(function(unit) return not UnitIsUnit(unit, "player") end)
|
||
|
|
end
|
||
|
|
|
||
|
|
__Static__() __AutoCache__()
|
||
|
|
function Wow.PlayerInCombat()
|
||
|
|
local subject = BehaviorSubject()
|
||
|
|
Continue(function(subject)
|
||
|
|
while true do
|
||
|
|
local status = UnitAffectingCombat("player") or false
|
||
|
|
subject:OnNext(status)
|
||
|
|
|
||
|
|
NextEvent(status and "PLAYER_REGEN_ENABLED" or "PLAYER_REGEN_DISABLED")
|
||
|
|
end
|
||
|
|
end, subject)
|
||
|
|
return subject
|
||
|
|
end
|
||
|
|
|
||
|
|
__Static__() __AutoCache__()
|
||
|
|
function Wow.UnitIsResurrect()
|
||
|
|
local subject = Subject()
|
||
|
|
|
||
|
|
Wow.FromEvent("INCOMING_RESURRECT_CHANGED"):Subscribe(function(unit)
|
||
|
|
subject:OnNext(unit)
|
||
|
|
|
||
|
|
if UnitHasIncomingResurrection(unit) then
|
||
|
|
Next(function()
|
||
|
|
-- Avoid the event not fired when the unit is already resurrected
|
||
|
|
while UnitHasIncomingResurrection(unit) do Delay(1) end
|
||
|
|
subject:OnNext(unit)
|
||
|
|
end)
|
||
|
|
end
|
||
|
|
end)
|
||
|
|
|
||
|
|
return Wow.FromUnitEvent(subject):Map(function(unit) return UnitHasIncomingResurrection(unit) end)
|
||
|
|
end
|
||
|
|
|
||
|
|
__Static__() __AutoCache__()
|
||
|
|
function Wow.UnitRaidTargetIndex()
|
||
|
|
return Wow.FromUnitEvent(Wow.FromEvent("RAID_TARGET_UPDATE"):Map("=>'any'")):Map(GetRaidTargetIndex)
|
||
|
|
end
|
||
|
|
|
||
|
|
__Static__() __AutoCache__()
|
||
|
|
function Wow.UnitThreatLevel()
|
||
|
|
return Wow.FromUnitEvent("UNIT_THREAT_SITUATION_UPDATE"):Map(function(unit)
|
||
|
|
return UnitIsPlayer(unit) and UnitThreatSituation(unit) or 0
|
||
|
|
end)
|
||
|
|
end
|
||
|
|
|
||
|
|
__Static__() __AutoCache__()
|
||
|
|
function Wow.UnitGroupRoster()
|
||
|
|
return Wow.FromUnitEvent(_UnitNameSubject):Map(function(unit)
|
||
|
|
if IsInRaid() and not UnitHasVehicleUI(unit) then
|
||
|
|
if GetPartyAssignment('MAINTANK', unit) then
|
||
|
|
return "MAINTANK"
|
||
|
|
elseif GetPartyAssignment('MAINASSIST', unit) then
|
||
|
|
return "MAINASSIST"
|
||
|
|
else
|
||
|
|
return "NONE"
|
||
|
|
end
|
||
|
|
else
|
||
|
|
return "NONE"
|
||
|
|
end
|
||
|
|
end)
|
||
|
|
end
|
||
|
|
|
||
|
|
__Static__() __AutoCache__()
|
||
|
|
function Wow.UnitGroupRosterVisible()
|
||
|
|
return Wow.UnitGroupRoster():Map(function(assign) return assign and assign ~= "NONE" or false end)
|
||
|
|
end
|
||
|
|
|
||
|
|
__Static__() __AutoCache__()
|
||
|
|
function Wow.UnitRole()
|
||
|
|
return Wow.FromUnitEvent(Wow.FromEvent("GROUP_ROSTER_UPDATE", "PLAYER_ROLES_ASSIGNED"):Map("=>'any'")):Map(UnitGroupRolesAssigned or Toolset.fakefunc)
|
||
|
|
end
|
||
|
|
|
||
|
|
__Static__() __AutoCache__()
|
||
|
|
function Wow.UnitRoleVisible()
|
||
|
|
return Wow.UnitRole():Map(function(role) return role and role ~= "NONE" or false end)
|
||
|
|
end
|
||
|
|
|
||
|
|
__Static__() __AutoCache__()
|
||
|
|
function Wow.UnitIsLeader()
|
||
|
|
return Wow.FromUnitEvent(Wow.FromEvent("GROUP_ROSTER_UPDATE", "PARTY_LEADER_CHANGED"):Map("=>'any'")):Map(function(unit)
|
||
|
|
return (UnitInParty(unit) or UnitInRaid(unit)) and UnitIsGroupLeader(unit) or false
|
||
|
|
end)
|
||
|
|
end
|
||
|
|
|
||
|
|
__Static__() __AutoCache__()
|
||
|
|
function Wow.UnitInRange()
|
||
|
|
return Wow.FromUnitEvent(Observable.Interval(0.5):Map("=>'any'")):Map(function(unit)
|
||
|
|
return UnitIsUnit(unit, "player") or not (UnitInParty(unit) or UnitInRaid(unit)) or UnitInRange(unit)
|
||
|
|
end)
|
||
|
|
end
|
||
|
|
|
||
|
|
------------------------------------------------------------
|
||
|
|
-- READY CHECK --
|
||
|
|
------------------------------------------------------------
|
||
|
|
local _ReadyChecking = 0
|
||
|
|
local _ReadyCheckSubject = Subject()
|
||
|
|
local _ReadyCheckConfirmSubject = Subject()
|
||
|
|
|
||
|
|
__SystemEvent__() __Async__()
|
||
|
|
function READY_CHECK()
|
||
|
|
_ReadyChecking = 1
|
||
|
|
_ReadyCheckSubject:OnNext("any")
|
||
|
|
|
||
|
|
if "READY_CHECK_FINISHED" == Wait("READY_CHECK_FINISHED", "PLAYER_REGEN_DISABLED") then
|
||
|
|
_ReadyChecking = 2
|
||
|
|
_ReadyCheckConfirmSubject:OnNext("any")
|
||
|
|
|
||
|
|
Wait(8, "PLAYER_REGEN_DISABLED")
|
||
|
|
end
|
||
|
|
|
||
|
|
_ReadyChecking = 0
|
||
|
|
_ReadyCheckSubject:OnNext("any")
|
||
|
|
end
|
||
|
|
|
||
|
|
__SystemEvent__()
|
||
|
|
function READY_CHECK_CONFIRM()
|
||
|
|
_ReadyCheckConfirmSubject:OnNext("any")
|
||
|
|
end
|
||
|
|
|
||
|
|
__Static__() __AutoCache__()
|
||
|
|
function Wow.UnitReadyCheckVisible()
|
||
|
|
return Wow.FromUnitEvent(_ReadyCheckSubject):Map(function() return _ReadyChecking > 0 end)
|
||
|
|
end
|
||
|
|
|
||
|
|
__Static__() __AutoCache__()
|
||
|
|
function Wow.UnitReadyCheck()
|
||
|
|
return Wow.FromUnitEvent(_ReadyCheckConfirmSubject):Map(function(unit)
|
||
|
|
if _ReadyChecking == 0 then return end
|
||
|
|
|
||
|
|
local state = GetReadyCheckStatus(unit)
|
||
|
|
return _ReadyChecking == 2 and state == "waiting" and "notready" or state
|
||
|
|
end)
|
||
|
|
end
|
||
|
|
|
||
|
|
------------------------------------------------------------
|
||
|
|
-- Wow Classic --
|
||
|
|
------------------------------------------------------------
|
||
|
|
if Scorpio.IsRetail then return end
|
||
|
|
|
||
|
|
_Parent.UnitHasVehicleUI = _G.UnitHasVehicleUI or Toolset.fakefunc
|
||
|
|
_Parent.GetThreatStatusColor = _G.GetThreatStatusColor or function (index) if index == 3 then return 1, 0, 0 elseif index == 2 then return 1, 0.6, 0 elseif index == 1 then return 1, 1, 0.47 else return 0.69, 0.69, 0.69 end end
|
||
|
|
|
||
|
|
if Scorpio.IsBCC then return end
|
||
|
|
|
||
|
|
--- Try Get LibClassicDurations
|
||
|
|
pcall(LoadAddOn, "LibClassicDurations")
|
||
|
|
|
||
|
|
local ok, LibClassicDurations = pcall(_G.LibStub, "LibClassicDurations")
|
||
|
|
if not (ok and LibClassicDurations) then return end
|
||
|
|
|
||
|
|
LibClassicDurations:Register("Scorpio") -- tell library it's being used and should start working
|
||
|
|
_Parent.UnitAura = LibClassicDurations.UnitAuraWithBuffs
|
||
|
|
|
||
|
|
LibClassicDurations.RegisterCallback("Scorpio", "UNIT_BUFF", function(event, unit) return FireSystemEvent("UNIT_AURA", unit) end)
|