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

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)