From b69046bcec07cd0c849e83db1e7b761c8dd50049 Mon Sep 17 00:00:00 2001 From: rawoil Date: Thu, 17 Jun 2021 18:19:00 +0800 Subject: [PATCH] add swing support --- oUF_Simple/core/functions.lua | 22 ++ oUF_Simple/core/style.lua | 1 + oUF_Simple/modules/oUF_Swing.lua | 527 ++++++++++++++++++++++++++++++++++++++ oUF_Simple/oUF_Simple.toc | 1 + oUF_SimpleConfig/player.lua | 8 + 5 files changed, 559 insertions(+) create mode 100644 oUF_Simple/modules/oUF_Swing.lua diff --git a/oUF_Simple/core/functions.lua b/oUF_Simple/core/functions.lua index 6151c16..7e01aa6 100644 --- a/oUF_Simple/core/functions.lua +++ b/oUF_Simple/core/functions.lua @@ -183,6 +183,28 @@ local function CreateAltPowerBar(self) end L.F.CreateAltPowerBar = CreateAltPowerBar +--CreateSwing +local function CreateSwing(self) + if not self.cfg.swing or not self.cfg.swing.enabled then return end + --statusbar + local s = CreateFrame("Frame", nil, self.Power) + s.texture = L.C.textures.statusbar + s.textureBG = L.C.textures.statusbarBG + s.color = self.cfg.swing.color + s.colorBG = self.cfg.swing.colorBG + s.disableRanged = self.cfg.swing.disableRanged + s.disableMelee = self.cfg.swing.disableMelee + --bg + local bg = s:CreateTexture(nil, "BACKGROUND") + -- bg:SetTexture(L.C.textures.statusbar) + -- bg:SetColorTexture() + bg:SetAllPoints() + s.bg = bg + s:SetAllPoints() + return s +end +L.F.CreateSwing = CreateSwing + --CreateAbsorbBar local function CreateAbsorbBar(self) --like health the absorb bar cannot be disabled diff --git a/oUF_Simple/core/style.lua b/oUF_Simple/core/style.lua index 92067c5..d21ccf3 100644 --- a/oUF_Simple/core/style.lua +++ b/oUF_Simple/core/style.lua @@ -32,6 +32,7 @@ local function CreateStyle(self) -- self.rClassBar = L.F.CreateClassBar(self) -- self.AlternativePower = L.F.CreateAltPowerBar(self) -- self.AdditionalPower = L.F.CreateAdditionalPowerBar(self) + self.Swing = L.F.CreateSwing(self) self.Debuffs = L.F.CreateDebuffs(self) self.Buffs = L.F.CreateBuffs(self) self.RaidTargetIndicator = L.F.CreateRaidMark(self) diff --git a/oUF_Simple/modules/oUF_Swing.lua b/oUF_Simple/modules/oUF_Swing.lua new file mode 100644 index 0000000..81377d4 --- /dev/null +++ b/oUF_Simple/modules/oUF_Swing.lua @@ -0,0 +1,527 @@ +------------------------ +-- oUF_Swing, by p3lim +-- NDui MOD +------------------------- +local A, L = ... +local oUF = L.oUF or oUF +if not oUF then return end + +local strfind = string.find +local GetTime = GetTime +local GetInventoryItemID = GetInventoryItemID +local UnitAttackSpeed = UnitAttackSpeed +local UnitRangedDamage = UnitRangedDamage +local CombatLogGetCurrentEventInfo = CombatLogGetCurrentEventInfo +local UnitGUID = UnitGUID +local IsPlayerMoving = IsPlayerMoving +local UnitCastingInfo = UnitCastingInfo + +local meleeing, rangeing, lasthit +local MainhandID = GetInventoryItemID("player", 16) +local OffhandID = GetInventoryItemID("player", 17) +local RangedID = GetInventoryItemID("player", 18) +local AUTO_CAST_TIME = .65 +local delayTime = 0 + +local function SwingStopped(element) + local bar = element.__owner + local swing = bar.Twohand + local swingMH = bar.Mainhand + local swingOH = bar.Offhand + + if swing:IsShown() then return end + if swingMH:IsShown() then return end + if swingOH:IsShown() then return end + + bar:Hide() +end + +local function UpdateBarMinMaxValues(self) + self:SetMinMaxValues(0, self.max - self.min) +end + +local function UpdateBarValue(self, value) + self:SetValue(value) + + if self.Text then + if self.__owner.OverrideText then + self.__owner.OverrideText(self, value) + else + local decimal = rangeing and "%.2f" or "%.1f" + self.Text:SetFormattedText(decimal, self.max - self.min - value) + end + end +end + +local function delayUpdate(self) + local now = GetTime() + local isMoving = IsPlayerMoving() + if not isMoving then + local elapsed = now - delayTime + if elapsed > AUTO_CAST_TIME then + delayTime = 0 + self:Hide() + self:SetScript("OnUpdate", nil) + meleeing = false + rangeing = false + else + UpdateBarValue(self, elapsed + self.swingTime) + end + else + delayTime = now + UpdateBarValue(self, self.swingTime) + end +end + +local OnDurationUpdate +do + local checkelapsed = 0 + local slamelapsed = 0 + local slamtime = 0 + local slam = GetSpellInfo(1464) + function OnDurationUpdate(self, elapsed) + local now = GetTime() + + if meleeing then + if checkelapsed > .02 then + -- little hack for detecting melee stop + -- improve... dw sucks at this point -.- + if lasthit + self.speed + slamtime < now then + self:Hide() + self:SetScript("OnUpdate", nil) + SwingStopped(self) + meleeing = false + rangeing = false + end + checkelapsed = 0 + else + checkelapsed = checkelapsed + elapsed + end + end + + local spell = UnitCastingInfo("player") + if slam == spell then + -- slamelapsed: time to add for one slam + slamelapsed = slamelapsed + elapsed + -- slamtime: needed for meleeing hack (see some lines above) + slamtime = slamtime + elapsed + else + -- after slam + if slamelapsed ~= 0 then + self.min = self.min + slamelapsed + self.max = self.max + slamelapsed + slamelapsed = 0 + end + + local currentValue = now - self.min + local swingTime = self.max - self.min - AUTO_CAST_TIME + local isMoving = IsPlayerMoving() + + if rangeing and currentValue >= swingTime and isMoving then + self.swingTime = swingTime + self:SetScript("OnUpdate", delayUpdate) + else + if now > self.max then + if meleeing then + if lasthit then + self.min = self.max + self.max = self.max + self.speed + UpdateBarMinMaxValues(self) + slamtime = 0 + end + else + delayTime = 0 + self:Hide() + self:SetScript("OnUpdate", nil) + meleeing = false + rangeing = false + end + else + UpdateBarValue(self, currentValue) + end + end + + self.__owner.bg:SetShown(rangeing) + end + end +end + +local function MeleeChange(self, _, unit) + if unit ~= "player" then return end + if not meleeing then return end + + local bar = self.Swing + local swing = bar.Twohand + local swingMH = bar.Mainhand + local swingOH = bar.Offhand + + local NewMainhandID = GetInventoryItemID("player", 16) + local NewOffhandID = GetInventoryItemID("player", 17) + local now = GetTime() + local mhspeed, ohspeed = UnitAttackSpeed("player") + + if MainhandID ~= NewMainhandID or OffhandID ~= NewOffhandID then + if ohspeed then + swing:Hide() + swing:SetScript("OnUpdate", nil) + + swingMH.min = now + swingMH.max = swingMH.min + mhspeed + swingMH.speed = mhspeed + swingMH:Show() + UpdateBarMinMaxValues(swingMH) + swingMH:SetScript("OnUpdate", OnDurationUpdate) + + swingOH.min = now + swingOH.max = swingOH.min + ohspeed + swingOH.speed = ohspeed + if mhspeed ~= ohspeed then + swingOH:Show() + UpdateBarMinMaxValues(swingOH) + swingOH:SetScript("OnUpdate", OnDurationUpdate) + else + swingOH:Hide() + swingOH:SetScript("OnUpdate", nil) + end + else + swing.min = now + swing.max = swing.min + mhspeed + swing.speed = mhspeed + swing:Show() + UpdateBarMinMaxValues(swing) + swing:SetScript("OnUpdate", OnDurationUpdate) + + swingMH:Hide() + swingMH:SetScript("OnUpdate", nil) + swingOH:Hide() + swingOH:SetScript("OnUpdate", nil) + end + + lasthit = now + MainhandID = NewMainhandID + OffhandID = NewOffhandID + else + if ohspeed then + if swingMH.speed and swingMH.speed ~= mhspeed then + local percentage = ((swingMH.max or 10) - now) / (swingMH.speed) + swingMH.min = now - mhspeed * (1 - percentage) + swingMH.max = now + mhspeed * percentage + UpdateBarMinMaxValues(swingMH) + swingMH.speed = mhspeed + end + if swingOH.speed and swingOH.speed ~= ohspeed then + local percentage = ((swingOH.max or 10)- now) / (swingOH.speed) + swingOH.min = now - ohspeed * (1 - percentage) + swingOH.max = now + ohspeed * percentage + UpdateBarMinMaxValues(swingOH) + swingOH.speed = ohspeed + end + else + if swing.max and swing.speed ~= mhspeed then + local percentage = (swing.max - now) / (swing.speed) + swing.min = now - mhspeed * (1 - percentage) + swing.max = now + mhspeed * percentage + UpdateBarMinMaxValues(swing) + swing.speed = mhspeed + end + end + end +end + +local function RangedChange(self, _, unit) + if unit ~= "player" then return end + if not rangeing then return end + + local bar = self.Swing + local swing = bar.Twohand + + local NewRangedID = GetInventoryItemID("player", 18) + local now = GetTime() + local speed = UnitRangedDamage("player") + + if RangedID ~= NewRangedID then + swing.speed = UnitRangedDamage(unit) + swing.min = now + swing.max = swing.min + swing.speed + swing:Show() + UpdateBarMinMaxValues(swing) + swing:SetScript("OnUpdate", OnDurationUpdate) + else + if swing.speed ~= speed then + local percentage = (swing.max - now) / (swing.speed) + swing.min = now - speed * (1 - percentage) + swing.max = now + speed * percentage + swing.speed = speed + end + end +end + +local function Ranged(self, _, unit, _, spellID) + if unit ~= "player" then return end + if spellID ~= 75 and spellID ~= 5019 then return end + + local bar = self.Swing + local swing = bar.Twohand + local swingMH = bar.Mainhand + local swingOH = bar.Offhand + + meleeing = false + rangeing = true + bar:Show() + + swing.speed = UnitRangedDamage(unit) + swing.min = GetTime() + swing.max = swing.min + swing.speed + swing:Show() + UpdateBarMinMaxValues(swing) + swing:SetScript("OnUpdate", OnDurationUpdate) + bar.bg:SetWidth(AUTO_CAST_TIME / (swing.max - swing.min) * bar:GetWidth()) + + swingMH:Hide() + swingMH:SetScript("OnUpdate", nil) + swingOH:Hide() + swingOH:SetScript("OnUpdate", nil) +end + +local function Melee(self) + local _, subevent, _, GUID = CombatLogGetCurrentEventInfo() + if GUID ~= UnitGUID("player") then return end + if not strfind(subevent, "SWING") then return end + + local bar = self.Swing + local swing = bar.Twohand + local swingMH = bar.Mainhand + local swingOH = bar.Offhand + + -- calculation of new hits is in OnDurationUpdate + -- workaround, cant differ between mainhand and offhand hits + local now = GetTime() + + if not meleeing then + bar:Show() + swing:Hide() + swingMH:Hide() + swingOH:Hide() + + swing:SetScript("OnUpdate", nil) + swingMH:SetScript("OnUpdate", nil) + swingOH:SetScript("OnUpdate", nil) + + local mhspeed, ohspeed = UnitAttackSpeed("player") + if ohspeed then + swingMH.min = now + swingMH.max = swingMH.min + mhspeed + swingMH.speed = mhspeed + swingMH:Show() + UpdateBarMinMaxValues(swingMH) + swingMH:SetScript("OnUpdate", OnDurationUpdate) + + swingOH.min = now + swingOH.max = swingOH.min + ohspeed + swingOH.speed = ohspeed + if mhspeed ~= ohspeed then + swingOH:Show() + UpdateBarMinMaxValues(swingOH) + swingOH:SetScript("OnUpdate", OnDurationUpdate) + end + else + swing.min = now + swing.max = swing.min + mhspeed + swing.speed = mhspeed + swing:Show() + UpdateBarMinMaxValues(swing) + swing:SetScript("OnUpdate", OnDurationUpdate) + end + + meleeing = true + rangeing = false + end + + lasthit = now +end + +local function ParryHaste(self) + local _, subevent, _, _, _, _, tarGUID, _, missType = CombatLogGetCurrentEventInfo() + + if tarGUID ~= UnitGUID("player") then return end + if not meleeing then return end + if not strfind(subevent, "MISSED") then return end + if missType ~= "PARRY" then return end + + local bar = self.Swing + local swing = bar.Twohand + local swingMH = bar.Mainhand + local swingOH = bar.Offhand + + local _, dualwield = UnitAttackSpeed("player") + local now = GetTime() + + -- needed calculations, so the timer doesnt jump on parryhaste + if dualwield then + local percentage = (swingMH.max - now) / swingMH.speed + + if percentage > .6 then + swingMH.max = now + swingMH.speed * .6 + swingMH.min = now - (swingMH.max - now) * percentage / (1 - percentage) + UpdateBarMinMaxValues(swingMH) + elseif percentage > .2 then + swingMH.max = now + swingMH.speed * .2 + swingMH.min = now - (swingMH.max - now) * percentage / (1 - percentage) + UpdateBarMinMaxValues(swingMH) + end + + percentage = (swingOH.max - now) / swingOH.speed + + if percentage > .6 then + swingOH.max = now + swingOH.speed * .6 + swingOH.min = now - (swingOH.max - now) * percentage / (1 - percentage) + UpdateBarMinMaxValues(swingOH) + elseif percentage > .2 then + swingOH.max = now + swingOH.speed * .2 + swingOH.min = now - (swingOH.max - now) * percentage / (1 - percentage) + UpdateBarMinMaxValues(swingOH) + end + else + local percentage = (swing.max - now) / swing.speed + + if percentage > .6 then + swing.max = now + swing.speed * .6 + swing.min = now - (swing.max - now) * percentage / (1 - percentage) + UpdateBarMinMaxValues(swing) + elseif percentage > .2 then + swing.max = now + swing.speed * .2 + swing.min = now - (swing.max - now) * percentage / (1 - percentage) + UpdateBarMinMaxValues(swing) + end + end +end + +local function Ooc(self) + local bar = self.Swing + -- strange behaviour sometimes... + meleeing = false + rangeing = false + + if not bar.hideOoc then return end + bar:Hide() + bar.Twohand:Hide() + bar.Mainhand:Hide() + bar.Offhand:Hide() +end + +local function Enable(self, unit) + local bar = self.Swing + + if bar and unit == "player" then + local normTex = bar.texture or [=[Interface\TargetingFrame\UI-StatusBar]=] + local bgTex = bar.textureBG or [=[Interface\TargetingFrame\UI-StatusBar]=] + local r, g, b, a, r2, g2, b2, a2 + + if bar.color then + r, g, b, a = unpack(bar.color) + else + r, g, b, a = 1, 1, 1, 1 + end + + if bar.colorBG then + r2, g2, b2, a2 = unpack(bar.colorBG) + else + r2, g2, b2, a2 = 0, 0, 0, 1 + end + + if not bar.Twohand then + bar.Twohand = CreateFrame("StatusBar", nil, bar) + bar.Twohand:SetPoint("TOPLEFT", bar, "TOPLEFT", 0, 0) + bar.Twohand:SetPoint("BOTTOMRIGHT", bar, "BOTTOMRIGHT", 0, 0) + bar.Twohand:SetStatusBarTexture(normTex) + bar.Twohand:SetStatusBarColor(r, g, b, a) + bar.Twohand:SetFrameLevel(20) + bar.Twohand:Hide() + bar.Twohand.bg = bar.Twohand:CreateTexture(nil, "BACKGROUND") + bar.Twohand.bg:SetAllPoints(bar.Twohand) + bar.Twohand.bg:SetTexture(bgTex) + bar.Twohand.bg:SetVertexColor(r2, g2, b2, a2) + end + bar.Twohand.__owner = bar + + if not bar.Mainhand then + bar.Mainhand = CreateFrame("StatusBar", nil, bar) + bar.Mainhand:SetPoint("TOPLEFT", bar, "TOPLEFT", 0, 0) + bar.Mainhand:SetPoint("BOTTOMRIGHT", bar, "RIGHT", 0, 0) + bar.Mainhand:SetStatusBarTexture(normTex) + bar.Mainhand:SetStatusBarColor(r, g, b, a) + bar.Mainhand:SetFrameLevel(20) + bar.Mainhand:Hide() + bar.Mainhand.bg = bar.Mainhand:CreateTexture(nil, "BACKGROUND") + bar.Mainhand.bg:SetAllPoints(bar.Mainhand) + bar.Mainhand.bg:SetTexture(bgTex) + bar.Mainhand.bg:SetVertexColor(r2, g2, b2, a2) + end + bar.Mainhand.__owner = bar + + if not bar.Offhand then + bar.Offhand = CreateFrame("StatusBar", nil, bar) + bar.Offhand:SetPoint("TOPLEFT", bar, "LEFT", 0, 0) + bar.Offhand:SetPoint("BOTTOMRIGHT", bar, "BOTTOMRIGHT", 0, 0) + bar.Offhand:SetStatusBarTexture(normTex) + bar.Offhand:SetStatusBarColor(r, g, b, a) + bar.Offhand:SetFrameLevel(20) + bar.Offhand:Hide() + bar.Offhand.bg = bar.Offhand:CreateTexture(nil, "BACKGROUND") + bar.Offhand.bg:SetAllPoints(bar.Offhand) + bar.Offhand.bg:SetTexture(bgTex) + bar.Offhand.bg:SetVertexColor(r2, g2, b2, a2) + end + bar.Offhand.__owner = bar + + if bar.Text then + bar.Twohand.Text = bar.Text + bar.Twohand.Text:SetParent(bar.Twohand) + end + if bar.TextMH then + bar.Mainhand.Text = bar.TextMH + bar.Mainhand.Text:SetParent(bar.Mainhand) + end + if bar.TextOH then + bar.Offhand.Text = bar.TextOH + bar.Offhand.Text:SetParent(bar.Offhand) + end + if bar.OverrideText then + bar.Twohand.OverrideText = bar.OverrideText + bar.Mainhand.OverrideText = bar.OverrideText + bar.Offhand.OverrideText = bar.OverrideText + end + if not bar.disableRanged then + self:RegisterEvent("UNIT_SPELLCAST_SUCCEEDED", Ranged) + self:RegisterEvent("UNIT_RANGEDDAMAGE", RangedChange) + end + if not bar.disableMelee then + self:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED", Melee, true) + self:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED", ParryHaste, true) + self:RegisterEvent("UNIT_ATTACK_SPEED", MeleeChange) + end + self:RegisterEvent("PLAYER_REGEN_ENABLED", Ooc, true) + + return true + end +end + +local function Disable(self) + local bar = self.Swing + if bar then + if not bar.disableRanged then + self:UnregisterEvent("UNIT_SPELLCAST_SUCCEEDED", Ranged) + self:UnregisterEvent("UNIT_RANGEDDAMAGE", RangedChange) + end + if not bar.disableMelee then + self:UnregisterEvent("COMBAT_LOG_EVENT_UNFILTERED", Melee) + self:UnregisterEvent("COMBAT_LOG_EVENT_UNFILTERED", ParryHaste) + self:UnregisterEvent("UNIT_ATTACK_SPEED", MeleeChange) + end + self:UnregisterEvent("PLAYER_REGEN_ENABLED", Ooc) + + bar:Hide() + end +end + +oUF:AddElement("Swing", nil, Enable, Disable) \ No newline at end of file diff --git a/oUF_Simple/oUF_Simple.toc b/oUF_Simple/oUF_Simple.toc index 8fe567e..248ed3d 100644 --- a/oUF_Simple/oUF_Simple.toc +++ b/oUF_Simple/oUF_Simple.toc @@ -7,6 +7,7 @@ ## modules\rAbsorbBar.lua ## modules\rClassBar.lua modules\oUF_DebuffHighlight.lua +modules\oUF_Swing.lua core\init.lua core\functions.lua diff --git a/oUF_SimpleConfig/player.lua b/oUF_SimpleConfig/player.lua index 869f350..fa8f6ec 100644 --- a/oUF_SimpleConfig/player.lua +++ b/oUF_SimpleConfig/player.lua @@ -68,6 +68,14 @@ L.C.player = { font = L.C.fonts.expressway, }, }, + --swing + swing = { + enabled = true, + color = {1,0.7,0,0.5}, + colorBG = {0,0,0,0}, + disableRanged = false, + disableMelee = false, + }, --raidmark raidmark = { enabled = true, -- 1.7.9.5