Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ----------------------------------------[[
- -- Initialization
- ----------------------------------------]]
- local version = select(4, GetBuildInfo())
- if version < 120000 then
- print('Preservation Stasis Tracker is designed only for Midnight.')
- return
- end
- local _, class = UnitClass("player")
- if class ~= "EVOKER" then return end
- -- ============================================
- -- DEBUG MODE: поставь false чтобы отключить дебаг
- -- ============================================
- local DEBUG = false
- if DEBUG then
- print("=== Preservation Stasis Tracker LOADED (DEBUG MODE) ===")
- end
- ----------------------------------------[[
- -- Display
- ----------------------------------------]]
- local stasisDisplay = CreateFrame("Frame", "PreservationStasisTrackerDisplay", UIParent)
- stasisDisplay:SetSize(120, 55)
- stasisDisplay:SetPoint("CENTER")
- stasisDisplay:SetClampedToScreen(true)
- stasisDisplay.icons = {}
- for i = 1, 3 do
- stasisDisplay.icons[i] = stasisDisplay:CreateTexture(nil, "BACKGROUND")
- stasisDisplay.icons[i]:SetSize(40, 40)
- stasisDisplay.icons[i]:SetTexture(134400)
- if i == 1 then
- stasisDisplay.icons[i]:SetPoint("BOTTOMLEFT", stasisDisplay, "BOTTOMLEFT")
- else
- stasisDisplay.icons[i]:SetPoint("LEFT", stasisDisplay.icons[i - 1], "RIGHT")
- end
- end
- stasisDisplay.bar = CreateFrame("StatusBar", nil, stasisDisplay)
- stasisDisplay.bar:SetFrameStrata("LOW")
- stasisDisplay.bar:SetSize(120, 15)
- stasisDisplay.bar:SetPoint("TOPLEFT", stasisDisplay, "TOPLEFT")
- stasisDisplay.bar:SetStatusBarTexture("Interface/Buttons/WHITE8x8")
- stasisDisplay.bar:SetStatusBarColor(0.2, 0.5, 0.4)
- stasisDisplay.bar:SetMinMaxValues(0, 30)
- stasisDisplay.bar:SetValue(15)
- stasisDisplay.barBackground = stasisDisplay.bar:CreateTexture(nil, 'BACKGROUND')
- stasisDisplay.barBackground:SetAllPoints(stasisDisplay.bar)
- stasisDisplay.barBackground:SetColorTexture(0, 0, 0, 1)
- stasisDisplay.text = stasisDisplay:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
- stasisDisplay.text:SetPoint("CENTER", stasisDisplay.bar, "CENTER")
- stasisDisplay.text:SetShadowColor(0, 0, 0, 1)
- stasisDisplay.text:SetShadowOffset(-1, -1)
- stasisDisplay.text:SetScale(1.2)
- stasisDisplay.text:SetText('15')
- local function ChangeIconSize(value, orientation, iconPadding)
- if not iconPadding then iconPadding = 0 end
- for i = 1, 3 do
- stasisDisplay.icons[i]:SetSize(value, value)
- end
- local width, height
- if orientation and orientation == 'Vertical' then
- width, height = value + 15, (value * 3) + iconPadding * 2
- stasisDisplay.bar:SetSize(15, height)
- else
- width, height = (value * 3) + iconPadding * 2, value + 15
- stasisDisplay.bar:SetSize(width, 15)
- end
- stasisDisplay:SetSize(width, height)
- PSTDB['iconSize'] = value
- end
- local function ShowExample()
- stasisDisplay.bar:SetValue(15)
- stasisDisplay:Show()
- for i = 1, 3 do
- stasisDisplay.icons[i]:SetTexture(134400)
- end
- end
- local function ChangeIconPadding(value, orientation, iconSize)
- if not iconSize then iconSize = 40 end
- local xPad, yPad, point, rel, barX, barY, width, height
- if orientation and orientation == 'Vertical' then
- xPad, yPad, point, rel, barX, barY = 0, value, 'BOTTOM', 'TOP', 15, ((iconSize * 3) + value * 2)
- width, height = iconSize + barX, barY
- else
- xPad, yPad, point, rel, barX, barY = value, 0, 'LEFT', 'RIGHT', ((iconSize * 3) + value * 2), 15
- width, height = barX, iconSize + barY
- end
- for i = 2, 3 do
- stasisDisplay.icons[i]:ClearAllPoints()
- stasisDisplay.icons[i]:SetPoint(point, stasisDisplay.icons[i - 1], rel, xPad, yPad)
- end
- stasisDisplay:SetSize(width, height)
- stasisDisplay.bar:SetSize(barX, barY)
- PSTDB['iconPadding'] = value
- end
- local function SetGrowDirection(direction, layout)
- local point, rel, padX, padY, barX, barY, width, height
- if direction == "Horizontal" then
- point, rel, padX, padY, barX, barY = "LEFT", "RIGHT", PSTDB[layout].iconPadding, 0, ((PSTDB[layout].iconSize * 3) + PSTDB[layout].iconPadding * 2), 15
- width, height = barX, PSTDB[layout].iconSize + barY
- stasisDisplay:SetSize(PSTDB[layout].iconSize * 3, PSTDB[layout].iconSize + 15)
- stasisDisplay.bar:ClearAllPoints()
- stasisDisplay.bar:SetPoint("TOPLEFT", stasisDisplay, "TOPLEFT")
- stasisDisplay.bar:SetOrientation('HORIZONTAL')
- elseif direction == "Vertical" then
- point, rel, padX, padY, barX, barY = "BOTTOM", "TOP", 0, PSTDB[layout].iconPadding, 15, ((PSTDB[layout].iconSize * 3) + PSTDB[layout].iconPadding * 2)
- width, height = PSTDB[layout].iconSize + barX, barY
- stasisDisplay:SetSize(PSTDB[layout].iconSize + 15, PSTDB[layout].iconSize * 3)
- stasisDisplay.bar:ClearAllPoints()
- stasisDisplay.bar:SetPoint("BOTTOMRIGHT", stasisDisplay, "BOTTOMRIGHT")
- stasisDisplay.bar:SetOrientation('VERTICAL')
- end
- stasisDisplay:SetSize(width, height)
- stasisDisplay.bar:SetSize(barX, barY)
- for i = 2, 3 do
- stasisDisplay.icons[i]:ClearAllPoints()
- stasisDisplay.icons[i]:SetPoint(point, stasisDisplay.icons[i - 1], rel, padX, padY)
- end
- end
- stasisDisplay:Hide()
- ----------------------------------------[[
- -- Functionality
- ----------------------------------------]]
- local spellList = {
- [370537] = 'Stasis Store',
- [370564] = 'Stasis Release',
- [361509] = 'Living Flame',
- [364343] = 'Echo',
- [360995] = 'Verdant Embrace',
- [366155] = 'Reversion',
- [1256581] = 'Merithras Blessing',
- [355913] = 'Emerald Blossom',
- [374251] = 'Cauterizing Flame',
- [360823] = 'Naturalize',
- [373861] = 'Temporal Anomaly',
- [1291636] = 'Temporal Barrier'
- }
- local empowers = {
- TTS = 370553,
- DreamBreath = {
- 355936,
- 382614
- },
- FireBreath = {
- 357208,
- 382266
- }
- }
- local currentState = {
- showing = false,
- storedSpells = 0,
- fillTime = nil,
- ticker = nil,
- tts = false,
- ttsStored = false
- }
- local function log(...)
- if DEBUG then
- print(...)
- end
- end
- local function StartStasis()
- log("[DEBUG] ========================================")
- log("[DEBUG] StartStasis() called")
- stasisDisplay:Show()
- currentState.storedSpells = 0
- currentState.showing = true
- stasisDisplay.text:SetText('')
- stasisDisplay.bar:SetValue(0)
- for i = 1, 3 do
- stasisDisplay.icons[i]:SetTexture(134400)
- end
- if currentState.ttsStored then
- log("[DEBUG] StartStasis: restoring tts from ttsStored")
- currentState.tts = true
- end
- log("[DEBUG] StartStasis: showing=true, tts=" .. tostring(currentState.tts))
- end
- local function ReleaseStasis()
- log("[DEBUG] ReleaseStasis() called")
- if currentState.ticker then
- currentState.ticker:Cancel()
- end
- currentState.showing = false
- stasisDisplay:Hide()
- end
- local function FillStasis()
- log("[DEBUG] FillStasis() called - all 3 spells stored")
- currentState.fillTime = GetTime()
- currentState.ticker = C_Timer.NewTicker(0.2, function()
- local timeLeft = currentState.fillTime + 30 - GetTime()
- if timeLeft <= 0 then
- ReleaseStasis()
- end
- stasisDisplay.text:SetText(math.floor(timeLeft))
- stasisDisplay.bar:SetValue(timeLeft)
- end)
- end
- local function AddSpell(spellId)
- local spellName = C_Spell.GetSpellInfo(spellId).name
- log(string.format("[DEBUG] >>> ADDSPELL: %s (ID: %d), storedSpells: %d -> %d", spellName, spellId, currentState.storedSpells, currentState.storedSpells + 1))
- currentState.storedSpells = currentState.storedSpells + 1
- if stasisDisplay.icons[currentState.storedSpells] then
- stasisDisplay.icons[currentState.storedSpells]:SetTexture(C_Spell.GetSpellTexture(spellId))
- end
- if currentState.storedSpells == 3 then
- FillStasis()
- end
- end
- function CancelAuraStasis()
- log("[DEBUG] CancelAuraStasis() manual call")
- ReleaseStasis()
- end
- -- Event Tracker Frame
- local castTracker = CreateFrame("Frame")
- castTracker:RegisterEvent("UNIT_SPELLCAST_SUCCEEDED")
- castTracker:RegisterEvent("UNIT_SPELLCAST_EMPOWER_STOP")
- castTracker:SetScript("OnEvent", function(self, event, ...)
- if event == "UNIT_SPELLCAST_SUCCEEDED" then
- local unit, _, spellId = ...
- local spellName = spellList[spellId] or (C_Spell.GetSpellInfo(spellId) and C_Spell.GetSpellInfo(spellId).name) or "Unknown"
- if DEBUG then
- print(string.format("[DEBUG] EVENT: SUCCEEDED | unit=%s | spell=%s (ID: %d) | showing=%s | stored=%d | tts=%s | ttsStored=%s",
- unit, spellName, spellId,
- tostring(currentState.showing),
- currentState.storedSpells,
- tostring(currentState.tts),
- tostring(currentState.ttsStored)))
- end
- -- Убрали issecretvalue полностью
- if unit == "player" then
- -- TTS обрабатывается ВСЕГДА, независимо от showing
- if spellId == empowers.TTS then
- log("[DEBUG] ACTION: TTS detected - setting ttsStored=true, tts=true")
- currentState.ttsStored = true
- currentState.tts = true
- end
- -- Обработка Dream Breath с TTS даже если Stasis не активен (сбрасываем флаги)
- if (spellId == empowers.DreamBreath[1] or spellId == empowers.DreamBreath[2]) and currentState.tts then
- log("[DEBUG] ACTION: Dream Breath with tts=true - clearing flags (tts=false, ttsStored=false)")
- currentState.tts = false
- currentState.ttsStored = false
- if currentState.showing then
- log("[DEBUG] ACTION: Stasis active, adding Dream Breath")
- AddSpell(spellId)
- else
- log("[DEBUG] ACTION: Stasis NOT active, just clearing flags (not adding)")
- end
- end
- -- Обработка Fire Breath с TTS даже если Stasis не активен (сбрасываем флаги, НЕ добавляем)
- if (spellId == empowers.FireBreath[1] or spellId == empowers.FireBreath[2]) and currentState.tts then
- log("[DEBUG] ACTION: Fire Breath with tts=true - clearing flags (tts=false, ttsStored=false) (NOT adding)")
- currentState.tts = false
- currentState.ttsStored = false
- end
- if not currentState.showing and spellList[spellId] == 'Stasis Store' then
- log("[DEBUG] ACTION: Stasis Store -> StartStasis()")
- StartStasis()
- elseif currentState.showing then
- if currentState.storedSpells < 3 then
- if spellList[spellId] then
- log("[DEBUG] ACTION: Recognized spell from list -> AddSpell()")
- AddSpell(spellId)
- elseif currentState.tts then
- if spellId == empowers.DreamBreath[1] or spellId == empowers.DreamBreath[2] then
- log("[DEBUG] ACTION: Dream Breath with tts=true -> AddSpell() and clear flags")
- currentState.tts = false
- currentState.ttsStored = false
- AddSpell(spellId)
- elseif spellId == empowers.FireBreath[1] or spellId == empowers.FireBreath[2] then
- log("[DEBUG] ACTION: Fire Breath with tts=true -> clearing flags (NOT adding)")
- currentState.tts = false
- currentState.ttsStored = false
- else
- log("[DEBUG] ACTION: Unknown spell with tts=true, ignoring")
- end
- else
- log("[DEBUG] ACTION: Spell not recognized (tts=false), ignoring")
- end
- elseif spellList[spellId] == 'Stasis Release' then
- log("[DEBUG] ACTION: Stasis Release -> ReleaseStasis()")
- ReleaseStasis()
- else
- log("[DEBUG] ACTION: Stasis full, ignoring")
- end
- end
- end
- elseif event == "UNIT_SPELLCAST_EMPOWER_STOP" then
- local unit, _, spellId, success = ...
- local spellName = spellId and C_Spell.GetSpellInfo(spellId) and C_Spell.GetSpellInfo(spellId).name or "Unknown"
- if DEBUG then
- print(string.format("[DEBUG] EVENT: EMPOWER_STOP | unit=%s | spell=%s (ID: %d) | success=%s | showing=%s | stored=%d | tts=%s | ttsStored=%s",
- unit, spellName, spellId, tostring(success),
- tostring(currentState.showing),
- currentState.storedSpells,
- tostring(currentState.tts),
- tostring(currentState.ttsStored)))
- end
- -- Убрали issecretvalue полностью
- if unit == "player" then
- if success and (spellId == empowers.DreamBreath[1] or spellId == empowers.DreamBreath[2]) then
- if not currentState.tts then
- log("[DEBUG] ACTION: EMPOWER_STOP Dream Breath -> AddSpell()")
- AddSpell(spellId)
- else
- log("[DEBUG] ACTION: EMPOWER_STOP Dream Breath - SKIPPING because tts=true")
- end
- end
- else
- if DEBUG and unit ~= "player" then
- log("[DEBUG] ACTION: EMPOWER_STOP ignoring (unit=" .. tostring(unit) .. ")")
- end
- end
- end
- end)
- ----------------------------------------[[
- -- Options
- ----------------------------------------]]
- local optionsFrame = CreateFrame('Frame')
- optionsFrame:RegisterEvent("PLAYER_LOGIN")
- optionsFrame:SetScript("OnEvent", function()
- PSTDB = PSTDB or {}
- local defaultData = {
- point = 'CENTER',
- x = 0,
- y = 0,
- iconSize = 40,
- growDirection = 'Horizontal',
- iconPadding = 0,
- color = { r = 0.2, g = 0.5, b = 0.4}
- }
- local function displayPositionChanged(frame, layout, point, x, y)
- PSTDB[layout].point = point
- PSTDB[layout].x = x
- PSTDB[layout].y = y
- end
- local LEM = LibStub('LibEditMode')
- LEM:RegisterCallback('enter', function()
- ShowExample()
- end)
- LEM:RegisterCallback('exit', function()
- stasisDisplay:Hide()
- end)
- LEM:RegisterCallback('layout', function(layout)
- if not PSTDB[layout] then
- PSTDB[layout] = CopyTable(defaultData)
- end
- stasisDisplay:ClearAllPoints()
- stasisDisplay:SetPoint(PSTDB[layout].point, PSTDB[layout].x, PSTDB[layout].y)
- stasisDisplay.bar:SetStatusBarColor(PSTDB[layout].color.r, PSTDB[layout].color.g, PSTDB[layout].color.b)
- ChangeIconSize(PSTDB[layout].iconSize, PSTDB[layout].growDirection, PSTDB[layout].iconPadding)
- SetGrowDirection(PSTDB[layout].growDirection, layout)
- ChangeIconPadding(PSTDB[layout].iconPadding, PSTDB[layout].growDirection, PSTDB[layout].iconSize)
- end)
- LEM:AddFrame(stasisDisplay, displayPositionChanged, defaultData)
- LEM:AddFrameSettings(stasisDisplay, {
- {
- name = 'Icon Size',
- kind = LEM.SettingType.Slider,
- default = defaultData.iconSize,
- get = function(layout)
- return PSTDB[layout].iconSize
- end,
- set = function(layout, value)
- PSTDB[layout].iconSize = value
- ChangeIconSize(value, PSTDB[layout].growDirection, PSTDB[layout].iconPadding)
- end,
- minValue = 20,
- maxValue = 60,
- valueStep = 1
- },
- {
- name = 'Icon Padding',
- kind = LEM.SettingType.Slider,
- default = defaultData.iconPadding,
- get = function(layout)
- return PSTDB[layout].iconPadding
- end,
- set = function(layout, value)
- PSTDB[layout].iconPadding = value
- ChangeIconPadding(value, PSTDB[layout].growDirection, PSTDB[layout].iconSize)
- end,
- minValue = -5,
- maxValue = 5,
- valueStep = 1
- },
- {
- name = 'Grow Direction',
- kind = LEM.SettingType.Dropdown,
- default = defaultData.growDirection,
- get = function(layout)
- return PSTDB[layout].growDirection
- end,
- set = function(layout, value)
- PSTDB[layout].growDirection = value
- SetGrowDirection(value, layout)
- end,
- values = {
- { text = 'Horizontal' },
- { text = 'Vertical' }
- }
- },
- {
- name = 'Bar Color',
- kind = LEM.SettingType.ColorPicker,
- default = CreateColor(defaultData.color.r, defaultData.color.g, defaultData.color.b),
- get = function(layout)
- return CreateColor(PSTDB[layout].color.r, PSTDB[layout].color.g, PSTDB[layout].color.b)
- end,
- set = function(layout, color)
- local colorDataR, colorDataG, colorDataB = color:GetRGB()
- PSTDB[layout].color = { r = colorDataR, g = colorDataG, b = colorDataB }
- stasisDisplay.bar:SetStatusBarColor(colorDataR, colorDataG, colorDataB)
- end
- }
- })
- end)
Advertisement
Add Comment
Please, Sign In to add comment