implemented maw of lorkahj features by kyoma

René Welbers [03-11-16 - 15:58]
implemented maw of lorkahj features by kyoma
 updated api version
Filename
BuffsDebuffs.lua
RaidNotifier.lua
RaidNotifier.txt
UIs.lua
lang/de.lua
lang/en.lua
diff --git a/BuffsDebuffs.lua b/BuffsDebuffs.lua
index dd57dc6..ec90e62 100644
--- a/BuffsDebuffs.lua
+++ b/BuffsDebuffs.lua
@@ -49,8 +49,67 @@ maelstrom.stage7_poison[73866] = true -- poison explode
 maelstrom.stage9_synergy = 67359


+-- ---------------------------------------------------
+-- Veteran Maw of Lorkhaj ----------------------------
+-- ---------------------------------------------------
+local maw_lorkhaj = {}
+
+--Zhaj'hassa the Forgotten
+--   Curse
+maw_lorkhaj.zhajBoss_curseability  = 76049
+maw_lorkhaj.zhajBoss_curseduration = 20000 --TODO: verify this
+--   Glyphs
+maw_lorkhaj.zhajBoss_glyphability  = 57525
+maw_lorkhaj.zhajBoss_glyphcooldown = 25000
+maw_lorkhaj.zhajBoss_knownGlyphs = {}
+maw_lorkhaj.zhajBoss_glyphs = {
+	{x=0.55496829748154, y=0.29175475239754},
+	{x=0.56342494487762, y=0.25405216217041},
+	{x=0.60077518224716, y=0.24876673519611},
+	{x=0.62297391891479, y=0.26250880956650},
+	{x=0.64059197902679, y=0.29774489998817},
+	{x=0.62508809566498, y=0.32699084281921},
+}
+
+
+--False Moon Twins, S’Kinrai and Vashai
+--   Holy Aspect
+maw_lorkhaj.twinBoss_holyaspect = {}
+maw_lorkhaj.twinBoss_holyaspect[59472] = true
+maw_lorkhaj.twinBoss_holyaspect[59474] = true
+maw_lorkhaj.twinBoss_holyaspect[59534] = true
+maw_lorkhaj.twinBoss_holyaspect[59535] = true
+maw_lorkhaj.twinBoss_holyaspect[59536] = true
+maw_lorkhaj.twinBoss_holyaspect[59537] = true
+maw_lorkhaj.twinBoss_holyaspect[59538] = true
+maw_lorkhaj.twinBoss_holyaspectname = GetAbilityName(59472) --for debugging
+--  Shadow Aspect
+maw_lorkhaj.twinBoss_shadowaspect = {}
+maw_lorkhaj.twinBoss_shadowaspect[59523] = true
+maw_lorkhaj.twinBoss_shadowaspect[59524] = true
+maw_lorkhaj.twinBoss_shadowaspect[59527] = true
+maw_lorkhaj.twinBoss_shadowaspect[59528] = true
+maw_lorkhaj.twinBoss_shadowaspect[59529] = true
+maw_lorkhaj.twinBoss_shadowaspect[59629] = true
+maw_lorkhaj.twinBoss_shadowaspect[59639] = false -- actually seems to be the ability that REMOVES the shadow aspect (maybe also holy?)
+maw_lorkhaj.twinBoss_shadowaspect[59465] = true
+maw_lorkhaj.twinBoss_shadowaspectname = GetAbilityName(59523) --for debugging
+--  Conversion
+maw_lorkhaj.twinBoss_holyconversion = {}
+maw_lorkhaj.twinBoss_holyconversion[75460] = true
+maw_lorkhaj.twinBoss_holyconversion[75456] = true
+maw_lorkhaj.twinBoss_shadowconversion = {}
+maw_lorkhaj.twinBoss_shadowconversion[59698] = true
+maw_lorkhaj.twinBoss_shadowconversion[59699] = true
+
+
+--of interest:
+--#59640=Lunar Aspect
+--#59719=Remove Aspects
+
+
 -- add ids back to global
-RaidNotifier.BuffsDebuffs.maelstrom = maelstrom
+RaidNotifier.BuffsDebuffs.maw_lorkhaj = maw_lorkhaj

 -- ---------------------------------------------------
 -- BuffFood ------------------------------------------
diff --git a/RaidNotifier.lua b/RaidNotifier.lua
index 7796015..2ec3051 100644
--- a/RaidNotifier.lua
+++ b/RaidNotifier.lua
@@ -3,11 +3,11 @@ local LAM = LibStub:GetLibrary("LibAddonMenu-2.0")

 RaidNotifier = RaidNotifier or {}

-RaidNotifier.name		   = 'RaidNotifier'
-RaidNotifier.slash		   = '/rn'
-RaidNotifier.version	   = '1.3.7'
-RaidNotifier.versionDB	   = 1
-RaidNotifier.loaded	       = false
+RaidNotifier.name            = 'RaidNotifier'
+RaidNotifier.slash           = '/rn'
+RaidNotifier.version         = '1.3.8'
+RaidNotifier.versionDB       = 2
+RaidNotifier.loaded           = false
 RaidNotifier.author        = 'silentgecko'
 RaidNotifier.savedVarsName = 'RNVars'

@@ -21,6 +21,9 @@ RaidNotifier.variables = {
         stage7_poison  = true,
         stage9_synergy = true,
     },
+    mawLorkhaj = {
+        twinBoss_aspects = 4,
+    },
     general = {
         buffFood_reminder = true,
         buffFood_reminder_interval = 60,
@@ -45,7 +48,10 @@ RaidNotifier.tempVars = {
         maelstrom = {
             stage7_poison  = 0,
             stage9_synergy = 0,
-        }
+        },
+        maw_lorkhaj = {
+            twinBoss_aspect = 0,
+        },
     },
     last_ping = 0,
 }
@@ -61,6 +67,17 @@ local function CreateSettingsMenu()
         registerForRefresh = false,
     }

+    local choices = {
+        maw_lorkhaj = {
+            twinBoss_aspect = {
+                GetString(RAIDNOTIFIER_SETTINGS_MAWLORKHAJ_TWIN_ASPECTS_OFF),
+                GetString(RAIDNOTIFIER_SETTINGS_MAWLORKHAJ_TWIN_ASPECTS_MINIMAL),
+                GetString(RAIDNOTIFIER_SETTINGS_MAWLORKHAJ_TWIN_ASPECTS_NORMAL),
+                GetString(RAIDNOTIFIER_SETTINGS_MAWLORKHAJ_TWIN_ASPECTS_FULL),
+            },
+        },
+    }
+
     self.optionsData = {
         {
             type = "description",
@@ -93,6 +110,7 @@ local function CreateSettingsMenu()
             default = 60,
             width = "full",
         },
+        -- Maelstrom Arena
         {
             type = "header",
             name = GetString(RAIDNOTIFIER_SETTINGS_SANCTUM_HEADER),
@@ -147,6 +165,29 @@ local function CreateSettingsMenu()
             end,
         },

+        -- Maw of Lorkhaj
+        {
+            type = "header",
+            name = GetString(RAIDNOTIFIER_SETTINGS_MAWLORKHAJ_HEADER),
+        },
+        {
+            type = "dropdown",
+            name = GetString(RAIDNOTIFIER_SETTINGS_MAWLORKHAJ_TWIN_ASPECTS),
+            tooltip = GetString(RAIDNOTIFIER_SETTINGS_MAWLORKHAJ_TWIN_ASPECTS_TT),
+            choices = choices.maw_lorkhaj.twinBoss_aspect,
+            getFunc = function()
+                return choices.maw_lorkhaj.twinBoss_aspect[RaidNotifier.savedVariables.mawLorkhaj.twinBoss_aspect]
+            end,
+            setFunc = function(value)
+                for i, str in ipairs(choices.maw_lorkhaj.twinBoss_aspect) do
+                    if value == str then
+                        RaidNotifier.savedVariables.mawLorkhaj.twinBoss_aspect = i
+                    end
+                end
+            end,
+            default = 4
+        },
+
         {
             type = "header",
             name = GetString(RAIDNOTIFIER_SETTINGS_DEBUG_HEADER),
@@ -166,7 +207,6 @@ local function CreateSettingsMenu()
     LAM:RegisterOptionControls("RaidNotifierPanel", self.optionsData)
 end

-
 ---------Passing saved variables to the labels at initialize-------
 function RaidNotifier.Initialize(_, addonName)
     local self = RaidNotifier
@@ -181,13 +221,14 @@ function RaidNotifier.Initialize(_, addonName)

     EVENT_MANAGER:RegisterForEvent(self.name, EVENT_RAID_TRIAL_STARTED,  RaidNotifier.addEventListeners)
     EVENT_MANAGER:RegisterForEvent(self.name, EVENT_RAID_TRIAL_COMPLETE, RaidNotifier.removeEventListeners)
-    EVENT_MANAGER:RegisterForEvent(self.name, EVENT_RAID_TRIAL_FAILED,   RaidNotifier.removeEventListeners)
+    --EVENT_MANAGER:RegisterForEvent(self.name, EVENT_RAID_TRIAL_FAILED,   RaidNotifier.removeEventListeners)

     if IsRaidInProgress() then
         self.addEventListeners()
     else
         self.removeEventListeners()
     end
+
 end

 -- Add Events
@@ -206,21 +247,341 @@ function RaidNotifier.addEventListeners()
         EVENT_MANAGER:RegisterForEvent(self.name .. "_SANCTUM", EVENT_EFFECT_CHANGED, self.sanctumDebuffs)
     end

+    if raidId == 5 then
+         --for some weird reason only the initial coloring shows up in EVENT_EFFECT_CHANGED, the changing of colors does NOT show up AT ALL :/
+        EVENT_MANAGER:RegisterForEvent(self.name .. "_MAWLORKHAJ", EVENT_COMBAT_EVENT, self.mawLorkhajCombat)  --EVENT_MANAGER:RegisterForEvent(self.name .. "_MAWLORKHAJ", EVENT_EFFECT_CHANGED, self.mawLorkhajDebuffs)
+    end
+
     -- add maelstrom
     if raidId == 6 then
         EVENT_MANAGER:RegisterForEvent(self.name .. "_MAELSTROM", EVENT_EFFECT_CHANGED, self.maelstromDebuffs)
     end
 end

+
 -- Remove all Events
 function RaidNotifier.removeEventListeners()
     local self   = RaidNotifier

-    EVENT_MANAGER:UnregisterForEvent(self.name .. "_BUFFFOOD",  EVENT_EFFECT_CHANGED)
-    EVENT_MANAGER:UnregisterForEvent(self.name .. "_SANCTUM",   EVENT_EFFECT_CHANGED)
-    EVENT_MANAGER:UnregisterForEvent(self.name .. "_MAELSTROM", EVENT_EFFECT_CHANGED)
-    EVENT_MANAGER:UnregisterForEvent(self.name .. "_PINGS",     EVENT_MAP_PING)
+    EVENT_MANAGER:UnregisterForEvent(self.name .. "_BUFFFOOD",   EVENT_EFFECT_CHANGED)
+    EVENT_MANAGER:UnregisterForEvent(self.name .. "_SANCTUM",    EVENT_EFFECT_CHANGED)
+    EVENT_MANAGER:UnregisterForEvent(self.name .. "_MAELSTROM",  EVENT_EFFECT_CHANGED)
+    EVENT_MANAGER:UnregisterForEvent(self.name .. "_MAWLORKHAJ", EVENT_COMBAT_EVENT) --EVENT_MANAGER:UnregisterForEvent(self.name .. "_MAWLORKHAJ", EVENT_EFFECT_CHANGED)
+    EVENT_MANAGER:UnregisterForEvent(self.name .. "_PINGS",      EVENT_MAP_PING)
+end
+
+--[[
+local hud
+
+
+function RaidNotifier.StartGlyphTimer(index, cooldown)
+    if not hud.glyphWindow then return end
+
+    local glyph = hud.glyphWindow.glyphs[index]
+    if not glyph then return end
+
+    glyph.timer:SetText(ZO_FormatTimeMilliseconds(cooldown, TIME_FORMAT_STYLE_DESCRIPTIVE_MINIMAL_SHOW_TENTHS_SECS))
+    glyph.start = GetFrameTimeMilliseconds()
+    glyph.cooldown = cooldown
+    glyph.timer:SetHidden(false)
+    glyph.glow:SetHidden(true)
+
+    if hud.glyphWindow:IsHidden() then hud.glyphWindow:SetHidden(false) end
+end
+
+function RaidNotifier.StopGlyphTimer(index)
+    if not hud.glyphWindow then return end
+
+    local glyph = hud.glyphWindow.glyphs[index]
+    if not glyph then return end
+
+    glyph.timer:SetHidden(true)
+    glyph.start = 0
+    glyph.glow:SetHidden(false)
+
+    if hud.glyphWindow:IsHidden() then hud.glyphWindow:SetHidden(false) end
+end
+
+function RaidNotifier.UpdateGlyphWindowHandler()
+    if not hud.glyphWindow then return end
+
+    for i, glyph in ipairs(hud.glyphWindow.glyphs) do
+        if glyph.start > 0 then
+            local duration = glyph.start + glyph.cooldown - GetFrameTimeMilliseconds()
+            if duration <= 0 then
+                glyph.start = 0
+                glyph.timer:SetHidden(true)
+                glyph.glow:SetHidden(false)
+            else
+                glyph.timer:SetText(ZO_FormatTimeMilliseconds(duration, TIME_FORMAT_STYLE_DESCRIPTIVE_MINIMAL_SHOW_TENTHS_SECS))
+            end
+        end
+    end
+
+end
+
+function RaidNotifier.SetupGlyphWindow(size, pos, numGlyphs, glyphLayout)
+    local self = RaidNotifier
+
+    if not hud then
+        hud = WINDOW_MANAGER:CreateTopLevelWindow(self.name .. "_HUD")
+        hud:SetAnchor(TOPLEFT, guiRoot, TOPLEFT, 0, 0)
+    end
+
+    if not hud.glyphWindow then
+        hud.glyphWindow = WINDOW_MANAGER:CreateControlFromVirtual(nil, hud, "ZO_DefaultBackdrop")
+        hud.glyphWindow:SetHidden(false)
+    end
+    hud.glyphWindow:SetDimensions(unpack(size))
+    hud.glyphWindow:ClearAnchors()
+    hud.glyphWindow:SetAnchor(TOPLEFT, hud, TOPLEFT, unpack(pos))
+    local window = hud.glyphWindow
+
+    local function CreateGlyph(parent, size)
+        local glyph = WINDOW_MANAGER:CreateControl(nil, parent, CT_CONTROL)
+        glyph:SetAnchor(TOPLEFT, parent, TOPLEFT, 0, 0)
+        glyph:SetDimensions(size, size)
+
+        glyph.bg = WINDOW_MANAGER:CreateControl(nil, glyph, CT_TEXTURE)
+        glyph.bg:SetDimensions(size, size)
+        glyph.bg:SetAnchor(CENTER, glyph, CENTER)
+        glyph.bg:SetTexture("RaidNotifier/assets/glyph_background.dds")
+
+        glyph.glow = WINDOW_MANAGER:CreateControl(nil, glyph.bg, CT_TEXTURE)
+        glyph.glow:SetDimensions(size, size)
+        glyph.glow:SetAnchor(CENTER, glyph.bg, CENTER)
+        glyph.glow:SetTexture("RaidNotifier/assets/glyph_glow.dds")
+
+        glyph.timer = WINDOW_MANAGER:CreateControl(nil, glyph.bg, CT_LABEL)
+        glyph.timer:SetAnchor(CENTER, glyph.bg, CENTER)
+        glyph.timer:SetFont("ZoFontWinH4")
+        glyph.timer:SetText("15s")
+        glyph.timer:SetHidden(true)
+        glyph.start = 0
+
+        glyph:SetHidden(true)
+        return glyph
+    end
+
+    window.glyphs = {}
+    for i=1, numGlyphs do
+        if not window.glyphs[i] then
+            window.glyphs[i] = CreateGlyph(window, 58)
+        end
+        local glyph = window.glyphs[i]
+        local x, y, bg, glow = unpack(glyphLayout[i])
+        glyph:ClearAnchors()
+        glyph:SetAnchor(CENTER, window, CENTER, x*size[1]*0.5/100, y*size[2]*0.5/100)
+        if bg ~= nil then
+            glyph.bg:SetTexture("RaidNotifier/assets/"..bg)
+        end
+        if glow ~= nil then
+            glyph.glow:SetTexture("RaidNotifier/assets/"..glow)
+        end
+        glyph:SetHidden(false)
+    end
+end
+
+--/script EVENT_MANAGER:RegisterForEvent("TMP42", EVENT_COMBAT_EVENT,  RaidNotifier.mawLorkhajCombat) RaidNotifier.createHud()
+
+
+zo_callLater(function() EVENT_MANAGER:RegisterForEvent("TMP42", EVENT_COMBAT_EVENT,  RaidNotifier.mawLorkhajCombat) RaidNotifier.createHud() end, 2000)
+
+function RaidNotifier.createHud()
+    local self = RaidNotifier
+
+    local ui = self.UIs.maw_lorkhaj
+    self.SetupGlyphWindow(ui.window_size, ui.window_pos, ui.zhajBoss_numGlyphs, ui.zhajBoss_glyphLayout)
+    EVENT_MANAGER:RegisterForUpdate(self.name, ui.update_interval, self.UpdateGlyphWindowHandler)
+
+    --EVENT_MANAGER:RegisterForUpdate(self.name, 100, GlyphUpdateHandler)
+end
+
+function RaidNotifier.mawLorkhajFindGlyph(glyphId, glyphs, knownGlyphs, allowNew)
+
+    local self = RaidNotifier
+    if not knownGlyphs[glyphId] then
+        if not allowNew then return 0 end
+
+        local lowest = {distance=9999, index=0, data=nil}
+        for index, data in ipairs(glyphs) do
+            for p=1, GetGroupSize() do
+                if IsUnitOnline("group"..p) then
+                    local pX, pY = GetMapPlayerPosition("group"..p)
+                    if (data.index == nil) then --only check unknown glyphs
+                        local x, y = data.x, data.y
+                        local distance = math.sqrt((pX-x)*(pX-x)+(pY-y)*(pY-y)) * 1000
+                        if (distance < lowest.distance) then
+                            --d("Unit="..("group"..p)..", Disance="..distance..", Index="..index)
+                            lowest.distance=distance
+                            lowest.index=index
+                            lowest.data=data
+                        end
+                    end
+                end
+            end
+        end
+        if lowest.distance < 8 and lowest.index > 0 then
+            --d("Within target distance!")
+            lowest.data.index = lowest.index
+            knownGlyphs[glyphId] = lowest.index
+            return lowest.index
+        else
+            return 0
+        end
+    else
+        return knownGlyphs[glyphId]
+    end
+end
+--]]
+
+
+
+function RaidNotifier.mawLorkhajCombat(_, result, isError, abilityName, _, _, sourceName, sourceType, targetName, targetType, _, _, _, _, sourceUnitId, targetUnitId, abilityId)
+
+    local self = RaidNotifier
+    -- remove event listener, the api won't get it on zoning
+    if IsRaidInProgress() == false then
+        self.removeEventListeners()
+        return
+    end
+    local buffsDebuffs = self.BuffsDebuffs.maw_lorkhaj
+
+
+    --Zhaj'hassa the Forgotten
+    --[[
+    if (abilityId == buffsDebuffs.zhajBoss_glyphability) then
+        local findNew = (result == 2250) --only scan for new glyph when effect/glyph is used by the player, NOT when it respawns
+        local glyphIndex = self.mawLorkhajFindGlyph(targetUnitId, buffsDebuffs.zhajBoss_glyphs, buffsDebuffs.zhajBoss_knownGlyphs, findNew)
+        if (result == 2245) then --(change == EFFECT_RESULT_GAINED)
+            self.StopGlyphTimer(glyphIndex)
+        elseif (result == 2250) then --(change == EFFECT_RESULT_FADED)
+            self.StartGlyphTimer(glyphIndex, buffsDebuffs.zhajBoss_glyphcooldown)
+        end
+    elseif (abilityId == buffsDebuffs.zhajBoss_curseability) then
+        local glyphIndex = 7
+        if (result == 2245) then --(change == EFFECT_RESULT_GAINED)
+            self.StartGlyphTimer(glyphIndex, buffsDebuffs.zhajBoss_curseduration)
+        elseif (result == 2250) then --(change == EFFECT_RESULT_FADED)
+            self.StopGlyphTimer(glyphIndex)
+        end
+    end
+    --]]
+
+
+    -- False Moon Twins, S’Kinrai and Vashai
+    if (targetType == COMBAT_UNIT_TYPE_PLAYER) then
+        -- debugging for now, I might have missed an abilityId
+        if (abilityName == buffsDebuffs.twinBoss_holyaspectname) then
+            if (buffsDebuffs.twinBoss_holyaspect[abilityId] == nil) then
+                self.debug("Unknown Holy Aspect: ", abilityId)
+                abilityId = 59472
+                self.debug("Holy Aspect: ", abilityId)
+            end
+        elseif (abilityName == buffsDebuffs.twinBoss_shadowaspectname) then
+            if (buffsDebuffs.twinBoss_shadowaspect[abilityId] == nil) then
+                self.debug("Unknown Shadow Aspect: ", abilityId)
+                abilityId = 59523
+                self.debug("Shadow Aspect: ", abilityId)
+            end
+        end
+        --]]
+
+        local alert = nil
+        if (buffsDebuffs.twinBoss_holyaspect[abilityId]) then
+            if self.savedVariables.mawLorkhaj.twinBoss_aspect > 1 then
+                alert = RAIDNOTIFIER_ALERTS_MAWLORKHAJ_HOLY_ASPECT
+            end
+        elseif (buffsDebuffs.twinBoss_shadowaspect[abilityId]) then
+            if self.savedVariables.mawLorkhaj.twinBoss_aspect > 1 then
+                alert = RAIDNOTIFIER_ALERTS_MAWLORKHAJ_SHADOW_ASPECT
+            end
+        elseif (buffsDebuffs.twinBoss_holyconversion[abilityId]) then
+            if (sourceName ~= "") then      --will be name of one of the bosses
+                --conversion just started
+                if self.savedVariables.mawLorkhaj.twinBoss_aspect > 0 then
+                    alert = RAIDNOTIFIER_ALERTS_MAWLORKHAJ_HOLY_CONVERSION
+                end
+            else
+                --conversion ended
+                if self.savedVariables.mawLorkhaj.twinBoss_aspect > 2 then
+                    alert = RAIDNOTIFIER_ALERTS_MAWLORKHAJ_HOLY_ASPECT
+                end
+            end
+        elseif (buffsDebuffs.twinBoss_shadowconversion[abilityId]) then
+            if (sourceName ~= "") then      --will be name of one of the bosses
+                --conversion just started
+                if self.savedVariables.mawLorkhaj.twinBoss_aspect > 0 then
+                    alert = RAIDNOTIFIER_ALERTS_MAWLORKHAJ_SHADOW_CONVERSION
+                end
+            else
+                --conversion ended
+                if self.savedVariables.mawLorkhaj.twinBoss_aspect > 2 then
+                    alert = RAIDNOTIFIER_ALERTS_MAWLORKHAJ_SHADOW_ASPECT
+                end
+            end
+        end
+
+        if (alert ~= nil) then
+            local currentTime = GetTimeStamp()
+            local lastNotify  = self.tempVars.last_notify.maw_lorkhaj.twinBoss_aspect
+            local timeDiff = GetDiffBetweenTimeStamps(currentTime, lastNotify)
+            if timeDiff > 5 then
+                self.tempVars.last_notify.maw_lorkhaj.twinBoss_aspect = currentTime
+                CENTER_SCREEN_ANNOUNCE:AddMessage(2, CSA_EVENT_COMBINED_TEXT, SOUNDS.CHAMPION_POINTS_COMMITTED, GetString(alert), nil, nil, nil, nil, nil, 2000)
+            end
+        end
+    end
+
+end
+
+-- Maw of Lorkhaj Events
+--[[
+function RaidNotifier.mawLorkhajDebuffs(_, change, _, name, unitTag, _, _, _, _, _, _, _, _, _, unitId, abilityId)
+
+    -- only take care of player
+    --if (unitTag ~= 'player') then return end
+
+    local self = RaidNotifier
+    -- remove event listener, the api won't get it on zoning
+    if IsRaidInProgress() == false then
+        self.removeEventListeners()
+        return
+    end
+
+    local buffsDebuffs = self.BuffsDebuffs.maw_lorkhaj
+    if (buffsDebuffs.zhajBoss_glyphs[unitId] > 0 and abilityId == buffsDebuffs.zhajBoss_glyphability) then
+        if (change == EFFECT_RESULT_GAINED) then
+            d("Glyph"..buffsDebuffs.zhajBoss_glyphs[unitId].." respawned")
+        elseif (change == EFFECT_RESULT_FADED) then
+            d("Glyph"..buffsDebuffs.zhajBoss_glyphs[unitId].." used")
+        end
+    end
+
+    -- only notice on effect added
+    if (change == EFFECT_RESULT_GAINED) then
+
+        -- Maw of Lorkhaj - Twin Boss Holy/Shadow Aspect (aka, "the color stuff")
+--        if self.savedVariables.maw_lorkhaj.twinBoss_aspect then
+            -- only notify when the last one is at least 10 seconds, use one stamp
+            -- for both the initial aspect as well as the aspect conversion
+            --local currentTime = GetTimeStamp()
+            --local lastNotify  = self.tempVars.last_notify.maw_lorkhaj.twinBoss_aspect
+            --local timeDiff = GetDiffBetweenTimeStamps(currentTime, lastNotify)
+            --if (buffsDebuffs.twinBoss_holyaspect[abilityId]) and timeDiff > 5 then
+            --    self.tempVars.last_notify.maw_lorkhaj.twinBoss_aspect = currentTime
+            --    CENTER_SCREEN_ANNOUNCE:AddMessage(2, CSA_EVENT_COMBINED_TEXT, SOUNDS.CHAMPION_POINTS_COMMITTED, GetString(RAIDNOTIFIER_ALERTS_MAWLORKHAJ_HOLY_ASPECT), nil, nil, nil, nil, nil, 2000)
+            --end
+            --if (buffsDebuffs.twinBoss_shadowaspect[abilityId]) and timeDiff > 5 then
+            --    self.tempVars.last_notify.maw_lorkhaj.twinBoss_aspect = currentTime
+            --    CENTER_SCREEN_ANNOUNCE:AddMessage(2, CSA_EVENT_COMBINED_TEXT, SOUNDS.CHAMPION_POINTS_COMMITTED, GetString(RAIDNOTIFIER_ALERTS_MAWLORKHAJ_SHADOW_ASPECT), nil, nil, nil, nil, nil, 2000)
+            --end
+
+--        end
+
+    end
 end
+--]]


 -- Sanctum Ophidia Events
diff --git a/RaidNotifier.txt b/RaidNotifier.txt
index d9459a8..a528124 100644
--- a/RaidNotifier.txt
+++ b/RaidNotifier.txt
@@ -1,8 +1,8 @@
 ## Title: |cEFEBBERaidNotifier|r
 ## Description: Displays on-screen notifications on different events during trials.
 ## Author: |c009ad6silentgecko|r
-## Version: 1.3.7
-## APIVersion: 100013
+## Version: 1.3.8
+## APIVersion: 100014
 ## SavedVariables: RNVars
 ## OptionalDependsOn: LibAddonMenu-2.0

diff --git a/UIs.lua b/UIs.lua
new file mode 100644
index 0000000..bea563b
--- /dev/null
+++ b/UIs.lua
@@ -0,0 +1,27 @@
+RaidNotifier = RaidNotifier or {}
+RaidNotifier.UIs = {}
+
+-- ---------------------------------------------------
+-- Veteran Maw of Lorkhaj ----------------------------
+-- ---------------------------------------------------
+local maw_lorkhaj = {}
+
+-- global
+maw_lorkhaj.window_size = {240, 200}
+maw_lorkhaj.window_pos  = {300, 200}
+maw_lorkhaj.update_interval = 100 -- every 0.1 seconds
+
+--Zhaj'hassa the Forgotten
+maw_lorkhaj.zhajBoss_numGlyphs   = 7 -- six actual glyphs + one special curse glyph
+maw_lorkhaj.zhajBoss_glyphLayout = { -- x & y anchor for each glyph, uses a percentage together with the window size
+	{  75, -30 },
+	{  65,  15 },
+	{  25,  50 },
+	{ -25,  50 },
+	{ -65,  15 },
+	{ -75, -30 },
+	{0, 0, "white_circle.dds", "dummy.dds"}, --special curse 'glyph'
+}
+
+-- add ids back to global
+RaidNotifier.UIs.maw_lorkhaj = maw_lorkhaj
\ No newline at end of file
diff --git a/lang/de.lua b/lang/de.lua
index 6e751c3..35ad498 100644
--- a/lang/de.lua
+++ b/lang/de.lua
@@ -24,6 +24,14 @@ L.Settings_Maelstrom_Stage7_Poison_TT    = 'Zeigt dir eine Benachrichtigung, wen
 L.Settings_Maelstrom_Stage9_Synergy      = 'Ebene 9: Spektrale Explosion (Synergie)'
 L.Settings_Maelstrom_Stage9_Synergy_TT   = 'Zeigt dir eine Benachrichtigung, wenn du in Ebene 9 (Theater der Verzweiflung) 3 (goldene) Geister gesammelt und die Synergie auslösen kannst.'

+L.Settings_MawLorkhaj_Header                 = 'Veteran Schlund des Lorkhaj'
+L.Settings_MawLorkhaj_Twin_Aspects           = 'Zwillingsaspekte'
+L.Settings_MawLorkhaj_Twin_Aspects_TT        = 'Zeigt dir eine Benachrichtigung, wenn du den Heiligen oder Schatten Aspekt bei den falschen Mondzwillingen bekommst.\n\n   Die komplette Benachrichtigung zeigt dir, wenn du mit der Umwandlung beginnst und wenn sie beendet ist.\n   Die normale Benachrichtigung zeigt dir wenn du einen Aspekt bekommst und wenn du dich umwandelst.\n   Die minimale Benachrichtigung warnt dich nur wenn du die Aspekte wechselst.'
+L.Settings_MawLorkhaj_Twin_Aspects_Off       = 'Aus'
+L.Settings_MawLorkhaj_Twin_Aspects_Full      = 'Komplett'
+L.Settings_MawLorkhaj_Twin_Aspects_Normal    = 'Normal'
+L.Settings_MawLorkhaj_Twin_Aspects_Minimal   = 'Minimal'
+
 L.Settings_Debug_Header                  = 'Debug'
 L.Settings_Debug                         = 'Debug einschalten'
 L.Settings_Debug_TT                      = 'Zeigt an bestimmten Stellen Debug Informationen im Chat an.'
@@ -42,6 +50,11 @@ L.Alerts_Maelstrom_Stage9_Synergy   = '|c23afe7Spektrale Explosion|r bereit! Syn
 L.Alerts_General_No_Bufffood        = 'Du hast kein Bufffood genommen!'
 L.Alerts_General_Bufffood_Minutes   = 'Dein Bufffood "<<1>>" läuft in |cbd0000<<2>>|r Minuten aus!'

+L.Alerts_MawLorkhaj_Holy_Aspect      = 'Du hast den |cFEFF7FHeiligen|r Aspekt!'
+L.Alerts_MawLorkhaj_Shadow_Aspect    = 'Du hast den |c000055Schatten|r Aspekt!'
+L.Alerts_MawLorkhaj_Holy_Conversion     = 'Umwandlung zum |cFEFF7FHeiligen|r Aspekt!'
+L.Alerts_MawLorkhaj_Shadow_Conversion   = 'Umwandlung zum |c000055Schatten|r Aspekt!'
+
 for k, v in pairs(L) do
     local string = "RAIDNOTIFIER_" .. string.upper(k)
     ZO_CreateStringId(string, v)
diff --git a/lang/en.lua b/lang/en.lua
index e4c8590..86eb7a6 100644
--- a/lang/en.lua
+++ b/lang/en.lua
@@ -22,7 +22,15 @@ L.Settings_Maelstrom_Header              = 'Veteran Maelstrom Arena'
 L.Settings_Maelstrom_Stage7_Poison       = 'Stage 7: Poison'
 L.Settings_Maelstrom_Stage7_Poison_TT    = 'Alerts you when you got poisoned in Stage 7 (Vault of Umbrage).'
 L.Settings_Maelstrom_Stage9_Synergy      = 'Stage 9: Spectral Explosion (Synergy)'
-L.Settings_Maelstrom_Stage9_Synergy_TT   = 'Alerts you when you got the Synergy in Stage 9 (Theater of Despair) after you picked ab 3 (golden) Ghosts.'
+L.Settings_Maelstrom_Stage9_Synergy_TT   = 'Alerts you when you got the Synergy in Stage 9 (Theater of Despair) after you picked up 3 (golden) Ghosts.'
+
+L.Settings_MawLorkhaj_Header                 = 'Veteran Maw of Lorkhaj'
+L.Settings_MawLorkhaj_Twin_Aspects           = 'Twin Aspects'
+L.Settings_MawLorkhaj_Twin_Aspects_TT        = 'Alerts when you get the holy or shadow aspect at the False Moon Twins.\n\n   Full alerts you when you get an aspect, when you are starting to convert to an aspect and when the conversion is complete.\n   Normal alerts you when you get an aspect and when you are converting.\n   Minimal only alerts you when you are converting.'
+L.Settings_MawLorkhaj_Twin_Aspects_Off       = 'Off'
+L.Settings_MawLorkhaj_Twin_Aspects_Full      = 'Full'
+L.Settings_MawLorkhaj_Twin_Aspects_Normal    = 'Normal'
+L.Settings_MawLorkhaj_Twin_Aspects_Minimal   = 'Minimal'

 L.Settings_Debug_Header                  = 'Debug'
 L.Settings_Debug                         = 'Turn debug on'
@@ -42,6 +50,12 @@ L.Alerts_Maelstrom_Stage9_Synergy   = '|c23afe7Spectral Explosion|r ready! Use t
 L.Alerts_General_No_Bufffood        = 'You have taken no bufffood!'
 L.Alerts_General_Bufffood_Minutes   = 'Your "<<1>>" bufffood runs out in |cbd0000<<2>>|r minutes!'

+L.Alerts_MawLorkhaj_Holy_Aspect      = 'You have the |cFEFF7FHoly|r Aspect!'
+L.Alerts_MawLorkhaj_Shadow_Aspect    = 'You have the |c000055Shadow|r Aspect!'
+
+L.Alerts_MawLorkhaj_Holy_Conversion     = 'Converting to the |cFEFF7FHoly|r Aspect!'
+L.Alerts_MawLorkhaj_Shadow_Conversion   = 'Converting to the |c000055Shadow|r Aspect!'
+
 for k, v in pairs(L) do
     local string = "RAIDNOTIFIER_" .. string.upper(k)
     ZO_CreateStringId(string, v)