Skip to content

Instantly share code, notes, and snippets.

@Friday-The13-rus
Last active September 6, 2021 17:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Friday-The13-rus/7b56b74e880db7aa7ab2b2c02911845c to your computer and use it in GitHub Desktop.
Save Friday-The13-rus/7b56b74e880db7aa7ab2b2c02911845c to your computer and use it in GitHub Desktop.
Added companion support
PlayerRoleIndicator = PlayerRoleIndicator or {}
PlayerRoleIndicator.name = "PlayerRoleIndicator"
PlayerRoleIndicator.version = "1.3.0"
PlayerRoleIndicator.variableVersion = 11
PlayerRoleIndicator.roleSwitch = {}
PlayerRoleIndicator.groupSize = 24
PlayerRoleIndicator.noteNum = 5
local noteId = PlayerRoleIndicator.noteNum
local LCM = LibCustomMenu
PlayerRoleIndicator.default = {
iconSize = 48,
yOffsetDead = 50,
yOffsetAlive = 325,
showShade = true,
shadeColour = {r = (100/255), g = 0, b = (160/255), a = 1},
useRezColour = true,
rezPendingColour = {r = 1, g = 1, b = 1, a = 0.25},
rezingColour = {r = 1, g = 1, b = 1, a = 0.25},
useNote = true,
noteSize = 1,
notePos = {x = 0, y = 0},
noteUseAccountName = false,
noteDuration = 3,
noteUseIcon = true,
noteRez = true,
useCustom = true,
customNum = 0,
customRole = {},
customDefault = {
name = "Custom role",
show = false,
showOnAlive = false,
texturePath = "/esoui/art/compass/groupmember.dds",
colourAlive = {r = 1, g = 1, b = 1, a = 1},
colourDead = {r = 1, g = 1, b = 1, a = 1},
players = {}
},
leader = {
show = false,
showOnAlive = false,
texturePath = "/esoui/art/compass/groupleader.dds",
colourAlive = {r = 1, g = 1, b = 1, a = 1},
colourDead = {r = 1, g = 1, b = 1, a = 1},
},
dps = {
show = false,
showOnAlive = false,
texturePath = "/esoui/art/tutorial/gamepad/gp_lfg_dps.dds",
colourAlive = {r = 1, g = 1, b = 1, a = 1},
colourDead = {r = 1, g = 1, b = 1, a = 1},
},
tank = {
show = true,
showOnAlive = false,
texturePath = "/esoui/art/tutorial/gamepad/gp_lfg_tank.dds",
colourAlive = {r = 1, g = 1, b = 1, a = 1},
colourDead = {r = 1, g = 1, b = 1, a = 1},
},
healer = {
show = true,
showOnAlive = false,
texturePath = "/esoui/art/tutorial/gamepad/gp_lfg_healer.dds",
colourAlive = {r = 1, g = 1, b = 1, a = 1},
colourDead = {r = 1, g = 1, b = 1, a = 1},
},
companion = {
show = true,
showOnAlive = false,
texturePath = "/esoui/art/compass/groupmember.dds",
colourAlive = {r = 1, g = 1, b = 1, a = 1},
colourDead = {r = 1, g = 1, b = 1, a = 1},
},
}
--Emulates a C-style switch, should have better performance than if-else chains
function PlayerRoleIndicator.UpdateRoleSwitch()
PlayerRoleIndicator.roleSwitch = {
[LFG_ROLE_TANK] = {
show = PlayerRoleIndicator.savedVariables.tank.show,
showOnAlive = PlayerRoleIndicator.savedVariables.tank.showOnAlive,
sv = PlayerRoleIndicator.savedVariables.tank
},
[LFG_ROLE_HEAL] = {
show = PlayerRoleIndicator.savedVariables.healer.show,
showOnAlive = PlayerRoleIndicator.savedVariables.healer.showOnAlive,
sv = PlayerRoleIndicator.savedVariables.healer
},
[LFG_ROLE_DPS] = {
show = PlayerRoleIndicator.savedVariables.dps.show,
showOnAlive = PlayerRoleIndicator.savedVariables.dps.showOnAlive,
sv = PlayerRoleIndicator.savedVariables.dps
},
["Leader"] = {
show = PlayerRoleIndicator.savedVariables.leader.show,
showOnAlive = PlayerRoleIndicator.savedVariables.leader.showOnAlive,
sv = PlayerRoleIndicator.savedVariables.leader
},
["companion"] = {
show = PlayerRoleIndicator.savedVariables.companion.show,
showOnAlive = PlayerRoleIndicator.savedVariables.companion.showOnAlive,
sv = PlayerRoleIndicator.savedVariables.companion
},
[LFG_ROLE_INVALID] = {
show = false,
showOnAlive = false,
sv = {
texturePath = "",
colourAlive = {r = 1, g = 1, b = 1, a = 0},
colourDead = {r = 1, g = 1, b = 1, a = 0},
}
}
}
end
function PlayerRoleIndicator.GetRole(unitTag)
if IsGroupCompanionUnitTag(unitTag) or unitTag == "companion" then
return PlayerRoleIndicator.roleSwitch["companion"]
end
local customRole = nil
for _, value in ipairs(PlayerRoleIndicator.savedVariables.customRole) do
for index, playerName in ipairs(value.players) do
if playerName == GetUnitDisplayName(unitTag) then
customRole = value
break
end
end
if customRole then break end
end
local role = nil
if customRole then
role = {}
role.name = customRole.name
role.show = customRole.show
role.showOnAlive = customRole.showOnAlive
role.sv = {
texturePath = customRole.texturePath,
colourAlive = customRole.colourAlive,
colourDead = customRole.colourDead,
}
elseif (AreUnitsEqual(GetGroupLeaderUnitTag(), unitTag) and PlayerRoleIndicator.roleSwitch["Leader"].show) then
role = PlayerRoleIndicator.roleSwitch["Leader"]
else role = PlayerRoleIndicator.roleSwitch[GetGroupMemberSelectedRole(unitTag)] end
return role
end
function PlayerRoleIndicator.UnitChecks(unitTag)
if HasActiveCompanion() and (IsGroupCompanionUnitTag(unitTag) or unitTag == "companion") then
return true
end
if (not DoesUnitExist(unitTag)) then return false end
if AreUnitsEqual("player", unitTag) then return false end
if (not IsUnitPlayer(unitTag)) then return false end
if (not IsUnitOnline(unitTag)) then return false end
if (not IsUnitGrouped(unitTag)) then return false end
if (not IsGroupMemberInSameInstanceAsPlayer(unitTag) or not IsGroupMemberInSameWorldAsPlayer(unitTag) or IsGroupMemberInRemoteRegion(unitTag)) then return false end
return true
end
function PlayerRoleIndicator.UpdateIconVisual(unitTag, role)
if (not PlayerRoleIndicator.UnitChecks(unitTag)) then return end
local c = PlayerRoleIndicatorWindow:GetNamedChild(unitTag)
local sv = PlayerRoleIndicator.savedVariables
c:SetDimensions(sv.iconSize, sv.iconSize)
if role.show then
c:SetTexture(role.sv.texturePath)
for i = 1, GetNumBuffs(unitTag), 1 do
local buffName = GetUnitBuffInfo(unitTag, i)
if ((buffName == "Shadow of the Fallen") and sv.showShade) then
c:SetColor(sv.shadeColour.r, sv.shadeColour.g, sv.shadeColour.b, sv.shadeColour.a)
return
end
end
if IsUnitDead(unitTag) then
if IsUnitBeingResurrected(unitTag) then
c:SetColor(sv.rezingColour.r, sv.rezingColour.g, sv.rezingColour.b, sv.rezingColour.a)
elseif DoesUnitHaveResurrectPending(unitTag) then
c:SetColor(sv.rezPendingColour.r, sv.rezPendingColour.g, sv.rezPendingColour.b, sv.rezPendingColour.a)
else c:SetColor(role.sv.colourDead.r, role.sv.colourDead.g, role.sv.colourDead.b, role.sv.colourDead.a) end
elseif role.showOnAlive then
c:SetColor(role.sv.colourAlive.r, role.sv.colourAlive.g, role.sv.colourAlive.b, role.sv.colourAlive.a)
end
end
end
function PlayerRoleIndicator.UpdateAllIconVisuals()
for i = 1, PlayerRoleIndicator.groupSize, 1 do
local unitTag = string.format("group%u", i)
local role = PlayerRoleIndicator.GetRole(unitTag)
PlayerRoleIndicator.UpdateIconVisual(unitTag, role)
end
if HasActiveCompanion() then
local unitTag = "companion"
local role = PlayerRoleIndicator.GetRole(unitTag)
PlayerRoleIndicator.UpdateIconVisual(unitTag, role)
end
end
function PlayerRoleIndicator.UpdateAllNoteSize()
if PlayerRoleIndicatorWindowNotePanel:IsMouseEnabled() then return end
PlayerRoleIndicatorWindowNotePanel:SetAnchor(TOPLEFT, PlayerRoleIndicatorWindow, TOPLEFT, PlayerRoleIndicator.savedVariables.notePos.x, PlayerRoleIndicator.savedVariables.notePos.y)
for i = 1, PlayerRoleIndicator.noteNum, 1 do
local label = PlayerRoleIndicatorWindowNotePanel:GetNamedChild(string.format("Note%u", i))
label:SetScale(PlayerRoleIndicator.savedVariables.noteSize)
local textHeight = label:GetTextHeight()
label:SetAnchor(TOPLEFT, labelPanel, TOPLEFT, textHeight * PlayerRoleIndicator.savedVariables.noteSize, textHeight * (i-1) * 1.25 * PlayerRoleIndicator.savedVariables.noteSize)
local labelIcon = label:GetNamedChild("Icon")
labelIcon:SetDimensions(textHeight, textHeight)
labelIcon:SetAnchor(TOPRIGHT, label, TOPLEFT, textHeight * -0.25, 0)
end
end
function PlayerRoleIndicator.ShowNote(event, unitTag, isDead)
if not PlayerRoleIndicator.savedVariables.useNote then return end
if PlayerRoleIndicatorWindowNotePanel:IsMouseEnabled() then return end
if not PlayerRoleIndicator.UnitChecks(unitTag) then return end
local role = PlayerRoleIndicator.GetRole(unitTag)
if not role.show then return end
if ((not role.showOnAlive) and (not isDead)) then return end
local name = {}
if PlayerRoleIndicator.savedVariables.noteUseAccountName then
name = GetUnitDisplayName(unitTag)
else name = GetUnitName(unitTag) end
local colour = {}
local text = {}
if isDead then
colour.r = role.sv.colourDead.r
colour.g = role.sv.colourDead.g
colour.b = role.sv.colourDead.b
colour.a = role.sv.colourDead.a
text = string.format("%s has died", name)
else
colour.r = role.sv.colourAlive.r
colour.g = role.sv.colourAlive.g
colour.b = role.sv.colourAlive.b
colour.a = role.sv.colourAlive.a
text = string.format("%s has been resurrected", name)
end
local texturePath = {}
if PlayerRoleIndicator.savedVariables.noteUseIcon then
texturePath = role.sv.texturePath
else texturePath = "" end
noteId = noteId + 1
local label = PlayerRoleIndicatorWindowNotePanel:GetNamedChild("Note1")
local labelIcon = label:GetNamedChild("Icon")
local colourBuffer = {}
local textBuffer = ""
local widthBuffer = nil
local texturePathBuffer = ""
local hiddenBuffer = true
local IdBuffer = nil
local tempColour = {}
tempColour.r, tempColour.g, tempColour.b, tempColour.a = label:GetColor()
local tempText = label:GetText()
local tempWidth = label:GetTextWidth()
local tempTexturePath = labelIcon:GetTextureFileName()
local tempHidden = label:IsHidden()
local tempId = label:GetId()
for i = 1, (PlayerRoleIndicator.noteNum - 1), 1 do
local currentLabel = PlayerRoleIndicatorWindowNotePanel:GetNamedChild(string.format("Note%u", i))
local currentLabelIcon = currentLabel:GetNamedChild("Icon")
local nextLabel = PlayerRoleIndicatorWindowNotePanel:GetNamedChild(string.format("Note%u", (i + 1)))
local nextLabelIcon = nextLabel:GetNamedChild("Icon")
colourBuffer.r, colourBuffer.g, colourBuffer.b, colourBuffer.a = nextLabel:GetColor()
textBuffer = nextLabel:GetText()
widthBuffer = nextLabel:GetStringWidth(textBuffer)
texturePathBuffer = nextLabelIcon:GetTextureFileName()
hiddenBuffer = nextLabel:IsHidden()
IdBuffer = nextLabel:GetId()
nextLabel:SetColor(tempColour.r, tempColour.g, tempColour.b, tempColour.a)
nextLabel:SetText(tempText)
nextLabel:SetWidth(tempWidth)
nextLabel:SetId(tempId)
nextLabel:SetHidden(tempHidden)
nextLabelIcon:SetTexture(tempTexturePath)
if tempTexturePath == "" then nextLabelIcon:SetHidden(true)
else
nextLabelIcon:SetColor(tempColour.r, tempColour.g, tempColour.b, tempColour.a)
nextLabelIcon:SetHidden(tempHidden)
end
tempColour.r = colourBuffer.r
tempColour.g = colourBuffer.g
tempColour.b = colourBuffer.b
tempColour.a = colourBuffer.a
tempText = textBuffer
tempWidth = widthBuffer
tempTexturePath = texturePathBuffer
tempHidden = hiddenBuffer
tempId = IdBuffer
end
label:SetId(noteId)
label:SetColor(colour.r, colour.g, colour.b, colour.a)
label:SetText(text)
label:SetWidth(label:GetStringWidth(text))
label:SetHidden(false)
labelIcon:SetTexture(texturePath)
if texturePath == "" then labelIcon:SetHidden(true)
else
labelIcon:SetColor(colour.r, colour.g, colour.b, colour.a)
labelIcon:SetHidden(false)
end
local id = noteId
zo_callLater(function() PlayerRoleIndicator.HideNote(id) end, PlayerRoleIndicator.savedVariables.noteDuration*1000)
end
function PlayerRoleIndicator.HideNote(id)
if PlayerRoleIndicatorWindowNotePanel:IsMouseEnabled() then return end
for i = 1, PlayerRoleIndicator.noteNum, 1 do
local label = PlayerRoleIndicatorWindowNotePanel:GetNamedChild(string.format("Note%u", i))
if label:GetId() == id then
local alpha = label:GetAlpha()
if alpha > 0.1 then
label:SetAlpha(alpha - 0.1)
zo_callLater(function() PlayerRoleIndicator.HideNote(id) end, 100)
else
label:SetHidden(true)
end
break
end
end
end
function PlayerRoleIndicator.PlayerLeftGroup()
for i = 1, PlayerRoleIndicator.groupSize, 1 do
local unitTag = string.format("group%u", i)
PlayerRoleIndicatorWindow:GetNamedChild(unitTag):SetHidden(true)
end
end
function PlayerRoleIndicator.CompanionStateChanged(eventCode, newState, oldState)
local INACTIVE_COMPANION_STATES =
{
[COMPANION_STATE_INACTIVE] = true,
[COMPANION_STATE_BLOCKED_PERMANENT] = true,
[COMPANION_STATE_BLOCKED_TEMPORARY] = true,
[COMPANION_STATE_HIDDEN] = true,
[COMPANION_STATE_INITIALIZING] = true,
}
if INACTIVE_COMPANION_STATES[newState] then
PlayerRoleIndicator.CompanionDeactivated()
end
end
function PlayerRoleIndicator.PlayerActivated()
if not IsUnitGrouped("player") then
PlayerRoleIndicator.PlayerLeftGroup()
end
if not HasActiveCompanion() then
PlayerRoleIndicator.CompanionDeactivated()
end
end
function PlayerRoleIndicator.CompanionDeactivated()
PlayerRoleIndicatorWindow:GetNamedChild("companion"):SetHidden(true)
end
function PlayerRoleIndicator.UpdateForUnit(unitTag, camMatrixInv, screenX, screenY)
if (not PlayerRoleIndicator.UnitChecks(unitTag)) then return true end
local role = PlayerRoleIndicator.GetRole(unitTag)
if not role.show then return true end
if ((not role.showOnAlive) and (not IsUnitDead(unitTag))) then return true end
--Gets the units world postion and adds height offset
local _, worldX, worldY, worldZ = GetUnitRawWorldPosition(unitTag)
if (IsUnitDead(unitTag)) then worldY = worldY + PlayerRoleIndicator.savedVariables.yOffsetDead
else worldY = worldY + PlayerRoleIndicator.savedVariables.yOffsetAlive end
local mtx = matrix:new(1,4,0)
mtx[1][1] = worldX
mtx[1][2] = worldY
mtx[1][3] = worldZ
mtx[1][4] = 1
mtx = matrix.mul(mtx, camMatrixInv)
local distance = mtx[1][3]
if (mtx[1][3] <= 0) then return true end
PlayerRoleIndicator.UpdateIconVisual(unitTag, role)
local worldWidth, worldHeight = GetWorldDimensionsOfViewFrustumAtDepth(distance)
local UIUnitsPerWorldUnitX, UIUnitsPerWorldUnitY = screenX/worldWidth, screenY/worldHeight
local x = mtx[1][1] * UIUnitsPerWorldUnitX
local y = -mtx[1][2] * UIUnitsPerWorldUnitY
local w = PlayerRoleIndicatorWindow
local c = w:GetNamedChild(unitTag)
c:SetAnchor(CENTER, w, CENTER, x, y)
return false
end
function PlayerRoleIndicator.UpdateIndicators()
if not IsUnitGrouped("player") and not HasActiveCompanion() then return end
--Gets the direction vectors of the camera and the world position of the camera
--They are then put into a matrix and inverted
--The inverted matrix is used to convert world position into a local position with the camera as the origin, and the cameras direction vectors as axis
local RenderSpace = PlayerRoleIndicator.RenderSpace
Set3DRenderSpaceToCurrentCamera(RenderSpace:GetName())
local cameraX, cameraY, cameraZ = GuiRender3DPositionToWorldPosition(RenderSpace:Get3DRenderSpaceOrigin())
local forwardX, forwardY, forwardZ = RenderSpace:Get3DRenderSpaceForward()
local rightX, rightY, rightZ = RenderSpace:Get3DRenderSpaceRight()
local upX, upY, upZ = RenderSpace:Get3DRenderSpaceUp()
local camMatrix = matrix:new(4,4,0)
camMatrix[1][1] = rightX
camMatrix[1][2] = rightY
camMatrix[1][3] = rightZ
camMatrix[1][4] = 0
camMatrix[2][1] = upX
camMatrix[2][2] = upY
camMatrix[2][3] = upZ
camMatrix[2][4] = 0
camMatrix[3][1] = forwardX
camMatrix[3][2] = forwardY
camMatrix[3][3] = forwardZ
camMatrix[3][4] = 0
camMatrix[4][1] = cameraX
camMatrix[4][2] = cameraY
camMatrix[4][3] = cameraZ
camMatrix[4][4] = 1
local camMatrixInv = matrix.invert(camMatrix)
local screenX, screenY = GuiRoot:GetDimensions()
if IsUnitGrouped("player") then
for i=1, PlayerRoleIndicator.groupSize, 1 do
local unitTag = string.format("group%u", i)
local hidden = PlayerRoleIndicator.UpdateForUnit(unitTag, camMatrixInv, screenX, screenY)
PlayerRoleIndicatorWindow:GetNamedChild(unitTag):SetHidden(hidden)
end
end
if HasActiveCompanion() then
local unitTag = "companion"
local hidden = PlayerRoleIndicator.UpdateForUnit(unitTag, camMatrixInv, screenX, screenY)
PlayerRoleIndicatorWindow:GetNamedChild(unitTag):SetHidden(hidden)
end
end
function PlayerRoleIndicator.intialize(eventCode, name)
if name ~= PlayerRoleIndicator.name then return end
PlayerRoleIndicator.savedVariables = ZO_SavedVars:NewAccountWide("PlayerRoleIndicatorVars", PlayerRoleIndicator.variableVersion, nil, PlayerRoleIndicator.default, GetWorldName())
PlayerRoleIndicator.CreateSettingsWindow()
--Hides icons when scene is changed
local function stateChange(oldState, newState)
if (newState == SCENE_SHOWN) then
if PlayerRoleIndicatorWindow:IsHidden() then
PlayerRoleIndicatorWindow:SetHidden(false)
end
end
end
PlayerRoleIndicator.fragment = ZO_HUDFadeSceneFragment:New(PlayerRoleIndicatorWindow)
HUD_SCENE:AddFragment(PlayerRoleIndicator.fragment)
HUD_SCENE:RegisterCallback("StateChange", stateChange)
HUD_UI_SCENE:AddFragment(PlayerRoleIndicator.fragment)
PlayerRoleIndicator.RenderSpace = CreateControl(string.format("%sRenderSpace", PlayerRoleIndicator.name), GuiRoot, CT_CONTROL)
PlayerRoleIndicator.RenderSpace:Create3DRenderSpace()
for i=1, PlayerRoleIndicator.groupSize, 1 do
local unitTag = string.format("group%u", i)
PlayerRoleIndicatorWindow:CreateControl(string.format("$(parent)%s", unitTag),CT_TEXTURE)
local c = PlayerRoleIndicatorWindow:GetNamedChild(unitTag)
c:SetAnchor(CENTER, PlayerRoleIndicatorWindow, CENTER, 0, 0)
c:SetMouseEnabled(false)
c:SetHidden(true)
end
do
local unitTag = "companion"
PlayerRoleIndicatorWindow:CreateControl(string.format("$(parent)%s", unitTag),CT_TEXTURE)
local c = PlayerRoleIndicatorWindow:GetNamedChild(unitTag)
c:SetAnchor(CENTER, PlayerRoleIndicatorWindow, CENTER, 0, 0)
c:SetMouseEnabled(false)
c:SetHidden(true)
end
local labelPanel = PlayerRoleIndicatorWindow:CreateControl("$(parent)NotePanel", CT_CONTROL)
labelPanel:SetAnchor(TOPLEFT, PlayerRoleIndicatorWindow, TOPLEFT, PlayerRoleIndicator.savedVariables.notePos.x, PlayerRoleIndicator.savedVariables.notePos.y)
labelPanel:SetResizeToFitDescendents(true)
labelPanel:SetMouseEnabled(false)
labelPanel:SetMovable(false)
labelPanel:SetHidden(false)
for i=1, PlayerRoleIndicator.noteNum, 1 do
local label = labelPanel:CreateControl(string.format("$(parent)Note%u", i), CT_LABEL)
label:SetId(i)
label:SetFont("ZoFontWinH1")
label:SetText("Unit has died")
label:SetWidth(label:GetStringWidth("Unit has died"))
label:SetScale(PlayerRoleIndicator.savedVariables.noteSize)
local textHeight = label:GetTextHeight()
label:SetAnchor(TOPLEFT, labelPanel, TOPLEFT, textHeight * PlayerRoleIndicator.savedVariables.noteSize, textHeight * (i-1) * 1.25 * PlayerRoleIndicator.savedVariables.noteSize)
label:SetMouseEnabled(false)
label:SetHidden(true)
local labelIcon = label:CreateControl("$(parent)Icon", CT_TEXTURE)
labelIcon:SetDimensions(textHeight, textHeight)
labelIcon:SetTexture("/esoui/art/tutorial/gamepad/gp_lfg_dps.dds")
labelIcon:SetAnchor(TOPRIGHT, label, TOPLEFT, textHeight * -0.25, 0)
labelIcon:SetMouseEnabled(false)
labelIcon:SetHidden(true)
end
PlayerRoleIndicator.UpdateRoleSwitch()
PlayerRoleIndicator.UpdateAllIconVisuals()
ZO_PreHook(GROUP_LIST, "ShowMenu", function(control)
local mouseOverControl = WINDOW_MANAGER:GetMouseOverControl()
local data = ZO_ScrollList_GetData(mouseOverControl)
if not data then
mouseOverControl = mouseOverControl:GetParent()
data = ZO_ScrollList_GetData(mouseOverControl)
end
if data then
for _, value in ipairs(PlayerRoleIndicator.savedVariables.customRole) do
if value.show then
local playerIndex = 0
for index, playerName in ipairs(value.players) do
if playerName == data.displayName then playerIndex = index end
end
if playerIndex == 0 then
AddCustomMenuItem(string.format("Add to %s", value.name), function()
table.insert(value.players, data.displayName)
GROUP_LIST:RefreshData()
end)
else AddCustomMenuItem(string.format("Remove from %s", value.name), function()
table.remove(value.players, playerIndex)
GROUP_LIST:RefreshData()
end)
end
end
end
end
end)
ZO_PostHook(GROUP_LIST, "RefreshData", function()
if not IsUnitGrouped("player") then return end
local control = ZO_GroupList:GetNamedChild("List"):GetNamedChild("Contents")
for i=1, control:GetNumChildren(), 1 do
local icon = control:GetChild(i):GetNamedChild("Leader"):GetNamedChild("Icon")
local data = ZO_ScrollList_GetData(control:GetChild(i))
if not data then
data = ZO_ScrollList_GetData(control)
end
if (data and icon) then
if data.leader then
icon:SetTexture("/esoui/art/lfg/lfg_leader_icon.dds")
icon:SetColor(1, 1, 1, 1)
icon:SetHidden(false)
else icon:SetHidden(true) end
for _, value in ipairs(PlayerRoleIndicator.savedVariables.customRole) do
if value.show then
local playerIndex = nil
for index, playerName in ipairs(value.players) do
if playerName == data.displayName then playerIndex = index end
end
if playerIndex then
icon:SetHidden(false)
icon:SetTexture(value.texturePath)
icon:SetColor(value.colourAlive.r, value.colourAlive.g, value.colourAlive.b, value.colourAlive.a)
break
end
end
end
end
end
end)
EVENT_MANAGER:RegisterForUpdate("PlayerRoleIndicatorUpdateIndicators", 10, PlayerRoleIndicator.UpdateIndicators)
EVENT_MANAGER:RegisterForEvent("PlayerRoleIndicatorPlayerLeftGroup", EVENT_GROUP_MEMBER_LEFT, PlayerRoleIndicator.PlayerLeftGroup)
EVENT_MANAGER:RegisterForEvent("PlayerRoleIndicatorShowNote", EVENT_UNIT_DEATH_STATE_CHANGED, PlayerRoleIndicator.ShowNote)
EVENT_MANAGER:AddFilterForEvent("PlayerRoleIndicatorPlayerLeftGroup", EVENT_GROUP_MEMBER_LEFT, REGISTER_FILTER_UNIT_TAG, "player")
EVENT_MANAGER:AddFilterForEvent("PlayerRoleIndicatorShowNote", EVENT_UNIT_DEATH_STATE_CHANGED, REGISTER_FILTER_UNIT_TAG_PREFIX, "group")
EVENT_MANAGER:RegisterForEvent("PlayerRoleIndicator", EVENT_ACTIVE_COMPANION_STATE_CHANGED, PlayerRoleIndicator.CompanionStateChanged)
EVENT_MANAGER:RegisterForEvent("PlayerRoleIndicator", EVENT_PLAYER_ACTIVATED, PlayerRoleIndicator.PlayerActivated)
EVENT_MANAGER:UnregisterForEvent(PlayerRoleIndicator.name, EVENT_ADD_ON_LOADED)
end
EVENT_MANAGER:RegisterForEvent(PlayerRoleIndicator.name, EVENT_ADD_ON_LOADED, PlayerRoleIndicator.intialize)
PlayerRoleIndicator = PlayerRoleIndicator or {}
local LAM2 = LibAddonMenu2
local noteVisable = false
function PlayerRoleIndicator.createSubmenu(role, roleSV, roleDefault)
local submenu = {
[1] = {
type = "checkbox",
name = string.format("Show icon above %s", role),
getFunc = function() return roleSV.show end,
setFunc = function(newValue)
roleSV.show = newValue
PlayerRoleIndicator.UpdateRoleSwitch()
PlayerRoleIndicator.UpdateAllIconVisuals()
end,
default = roleDefault.show,
},
[2] = {
type = "checkbox",
name = string.format("Show icon above alive %s", role),
getFunc = function() return roleSV.showOnAlive end,
setFunc = function(newValue)
roleSV.showOnAlive = newValue
PlayerRoleIndicator.UpdateRoleSwitch()
PlayerRoleIndicator.UpdateAllIconVisuals()
end,
disabled = function() return not roleSV.show end,
default = roleDefault.showOnAlive,
},
[3] = {
type = "colorpicker",
name = string.format("Colour of alive %s icons", role),
getFunc = function() return roleSV.colourAlive.r, roleSV.colourAlive.g, roleSV.colourAlive.b, roleSV.colourAlive.a end,
setFunc = function(r,g,b,a)
roleSV.colourAlive.r = r
roleSV.colourAlive.g = g
roleSV.colourAlive.b = b
roleSV.colourAlive.a = a
PlayerRoleIndicator.UpdateRoleSwitch()
PlayerRoleIndicator.UpdateAllIconVisuals()
end,
disabled = function() return not (roleSV.show and roleSV.showOnAlive) end,
default = {r = roleDefault.colourAlive.r, g = roleDefault.colourAlive.g, b = roleDefault.colourAlive.b, a = roleDefault.colourAlive.a},
},
[4] = {
type = "colorpicker",
name = string.format("Colour of dead %s icons", role),
getFunc = function() return roleSV.colourDead.r, roleSV.colourDead.g, roleSV.colourDead.b, roleSV.colourDead.a end,
setFunc = function(r,g,b,a)
roleSV.colourDead.r = r
roleSV.colourDead.g = g
roleSV.colourDead.b = b
roleSV.colourDead.a = a
PlayerRoleIndicator.UpdateRoleSwitch()
PlayerRoleIndicator.UpdateAllIconVisuals()
end,
disabled = function() return not roleSV.show end,
default = {r = roleDefault.colourDead.r, g = roleDefault.colourDead.g, b = roleDefault.colourDead.b, a = roleDefault.colourDead.a},
},
[5] = {
type = "iconpicker",
name = string.format("Icon to use for %s", role),
choices = {
"/esoui/art/tutorial/gamepad/gp_lfg_tank.dds",
"/esoui/art/tutorial/gamepad/gp_lfg_healer.dds",
"/esoui/art/tutorial/gamepad/gp_lfg_dps.dds",
"/esoui/art/tutorial/gamepad/gp_lfg_ava.dds",
"/esoui/art/tutorial/gamepad/gp_lfg_normaldungeon.dds",
"/esoui/art/tutorial/gamepad/gp_lfg_trial.dds",
"/esoui/art/tutorial/gamepad/gp_lfg_veteranldungeon.dds",
"/esoui/art/tutorial/gamepad/gp_lfg_world.dds",
"/esoui/art/tutorial/gamepad/gp_crowns.dds",
"/esoui/art/tutorial/gamepad/gp_bonusicon_emperor.dds",
"/esoui/art/compass/groupleader.dds",
"/esoui/art/compass/groupmember.dds",
},
maxColumns = 3,
visibleRows = 4,
iconSize = 32,
getFunc = function() return roleSV.texturePath end,
setFunc = function(newValue)
roleSV.texturePath = newValue
PlayerRoleIndicator.UpdateRoleSwitch()
PlayerRoleIndicator.UpdateAllIconVisuals()
end,
disabled = function() return not roleSV.show end,
default = roleDefault.texturePath,
},
}
return submenu
end
function PlayerRoleIndicator.createCustomRoles()
local submenu = {
[1] = {
type = "checkbox",
name = "Use custom roles",
getFunc = function() return PlayerRoleIndicator.savedVariables.useCustom end,
setFunc = function(newValue) PlayerRoleIndicator.savedVariables.useCustom = newValue end,
default = PlayerRoleIndicator.default.useCustom,
},
[2] = {
type = "slider",
name = "Number of custom roles",
getFunc = function() return PlayerRoleIndicator.savedVariables.customNum end,
setFunc = function(newValue)
if newValue > PlayerRoleIndicator.savedVariables.customNum then
for i = (PlayerRoleIndicator.savedVariables.customNum + 1), newValue, 1 do
PlayerRoleIndicator.savedVariables.customRole[i] = PlayerRoleIndicator.default.customDefault
end
elseif newValue < PlayerRoleIndicator.savedVariables.customNum then
for i = PlayerRoleIndicator.savedVariables.customNum, (newValue + 1), -1 do
table.remove(PlayerRoleIndicator.savedVariables.customRole, i)
end
end
PlayerRoleIndicator.savedVariables.customNum = newValue
end,
min = 0,
max = 10,
disabled = function() return not PlayerRoleIndicator.savedVariables.useCustom end,
requiresReload = true,
default = PlayerRoleIndicator.default.customNum,
},
}
local controlBuffer = {}
for _,value in ipairs(PlayerRoleIndicator.savedVariables.customRole) do
local control = PlayerRoleIndicator.createSubmenu(value.name, value, PlayerRoleIndicator.default.customDefault)
local nameCEditBox = {
type = "editbox",
name = "Name of custom role",
getFunc = function() return value.name end,
setFunc = function(newValue) value.name = newValue end,
isMultiline = false,
requiresReload = true,
default = PlayerRoleIndicator.default.customDefault.name,
}
table.insert(control, 1, nameCEditBox)
local resetButton = {
type = "button",
name = "Clear players",
func = function() value.players = {} end,
tooltip = "Will remove all players from this role.",
}
table.insert(control, resetButton)
controlBuffer = {
type = "submenu",
name = value.name,
icon = value.texturePath,
controls = control,
disabled = function() return not PlayerRoleIndicator.savedVariables.useCustom end,
}
table.insert(submenu, controlBuffer)
end
return submenu
end
function PlayerRoleIndicator.CreateSettingsWindow()
local panelData = {
type = "panel",
name = "Player role indicator",
displayName = "Player role indicator",
author = "|c18fff9Parietic|r",
version = PlayerRoleIndicator.version,
website = "https://www.esoui.com/downloads/info2703-PlayerRoleIndicator.html",
feedback = "https://www.esoui.com/downloads/info2703-PlayerRoleIndicator.html#comments",
slashCommand = "/pri",
registerForRefresh = true,
registerForDefaults = true,
}
local cntrlOptionsPanel = LAM2:RegisterAddonPanel("Player_role_indicator", panelData)
local optionsData = {
[1] = {
type = "slider",
name = "Icon size",
getFunc = function() return PlayerRoleIndicator.savedVariables.iconSize end,
setFunc = function(newValue)
PlayerRoleIndicator.savedVariables.iconSize = newValue
PlayerRoleIndicator.UpdateRoleSwitch()
PlayerRoleIndicator.UpdateAllIconVisuals()
end,
min = 1,
max = 128,
default = PlayerRoleIndicator.default.iconSize,
},
[2] = {
type = "slider",
name = "Dead player icon offset",
getFunc = function() return PlayerRoleIndicator.savedVariables.yOffsetDead end,
setFunc = function(newValue) PlayerRoleIndicator.savedVariables.yOffsetDead = newValue end,
min = 0,
max = 500,
tooltip = "The vertical offset for the icon displayed over dead players.",
default = PlayerRoleIndicator.default.yOffsetDead,
},
[3] = {
type = "slider",
name = "Alive player icon offset",
getFunc = function() return PlayerRoleIndicator.savedVariables.yOffsetAlive end,
setFunc = function(newValue) PlayerRoleIndicator.savedVariables.yOffsetAlive = newValue end,
min = 0,
max = 500,
tooltip = "The vertical offset for the icon displayed over alive players.",
default = PlayerRoleIndicator.default.yOffsetAlive,
},
[4] = {
type = "checkbox",
name = "Use different colours for players resurrection status",
getFunc = function() return PlayerRoleIndicator.savedVariables.useRezColour end,
setFunc = function(newValue)
PlayerRoleIndicator.savedVariables.useRezColour = newValue
PlayerRoleIndicator.UpdateAllIconVisuals()
end,
default = PlayerRoleIndicator.default.useRezColour,
},
[5] = {
type = "colorpicker",
name = "Colour of players with resurrection pending",
getFunc = function()
local colour = PlayerRoleIndicator.savedVariables.rezPendingColour
return colour.r, colour.g, colour.b, colour.a
end,
setFunc = function(r,g,b,a)
local colour = PlayerRoleIndicator.savedVariables.rezPendingColour
colour.r = r
colour.g = g
colour.b = b
colour.a = a
PlayerRoleIndicator.UpdateAllIconVisuals()
end,
disabled = function() return not PlayerRoleIndicator.savedVariables.useRezColour end,
default = {
r = PlayerRoleIndicator.default.rezPendingColour.r,
g = PlayerRoleIndicator.default.rezPendingColour.g,
b = PlayerRoleIndicator.default.rezPendingColour.b,
a = PlayerRoleIndicator.default.rezPendingColour.a
},
},
[6] = {
type = "colorpicker",
name = "Colour of players being resurrected",
getFunc = function()
local colour = PlayerRoleIndicator.savedVariables.rezingColour
return colour.r, colour.g, colour.b, colour.a
end,
setFunc = function(r,g,b,a)
local colour = PlayerRoleIndicator.savedVariables.rezingColour
colour.r = r
colour.g = g
colour.b = b
colour.a = a
PlayerRoleIndicator.UpdateAllIconVisuals()
end,
disabled = function() return not PlayerRoleIndicator.savedVariables.useRezColour end,
default = {
r = PlayerRoleIndicator.default.rezingColour.r,
g = PlayerRoleIndicator.default.rezingColour.g,
b = PlayerRoleIndicator.default.rezingColour.b,
a = PlayerRoleIndicator.default.rezingColour.a
},
},
[7] = {
type = "submenu",
name = "Notifications",
icon = "/esoui/art/tutorial/gamepad/achievement_categoryicon_quests.dds",
controls = {
[1] = {
type = "description",
text = "Gives a notification on screen when a group member dies or is resurrected." ..
"\n\nIcon, colour and if it should be showed for X role is taken from the respected role settings."
},
[2] = {
type = "checkbox",
name = "Use notifications",
getFunc = function() return PlayerRoleIndicator.savedVariables.useNote end,
setFunc = function(newValue) PlayerRoleIndicator.savedVariables.useNote = newValue end,
default = PlayerRoleIndicator.default.useNote,
},
[3] = {
type = "checkbox",
name = "Unlock and show notification panel",
getFunc = function() return noteVisable end,
setFunc = function(newValue)
local c = PlayerRoleIndicatorWindowNotePanel
c:SetMouseEnabled(newValue)
c:SetMovable(newValue)
for i = 1, PlayerRoleIndicator.noteNum, 1 do
local label = c:GetNamedChild(string.format("Note%u", i))
local labelIcon = label:GetNamedChild("Icon")
label:SetHidden(not newValue)
labelIcon:SetHidden(not newValue)
end
if not newValue then
PlayerRoleIndicator.savedVariables.notePos.x = c:GetLeft()
PlayerRoleIndicator.savedVariables.notePos.y = c:GetTop()
PlayerRoleIndicator.UpdateAllNoteSize()
end
noteVisable = newValue
end,
disabled = function() return not PlayerRoleIndicator.savedVariables.useNote end,
default = false,
},
[4] = {
type = "slider",
name = "Notification scale",
getFunc = function() return PlayerRoleIndicator.savedVariables.noteSize end,
setFunc = function(newValue)
PlayerRoleIndicator.savedVariables.noteSize = newValue
PlayerRoleIndicator.UpdateAllNoteSize()
end,
min = 0.1,
max = 4,
step = 0.1,
decimals = 1,
disabled = function() return not PlayerRoleIndicator.savedVariables.useNote end,
default = PlayerRoleIndicator.default.noteSize,
},
[5] = {
type = "slider",
name = "Notification duration",
getFunc = function() return PlayerRoleIndicator.savedVariables.noteDuration end,
setFunc = function(newValue) PlayerRoleIndicator.savedVariables.noteDuration = newValue end,
min = 1,
max = 10,
disabled = function() return not PlayerRoleIndicator.savedVariables.useNote end,
default = PlayerRoleIndicator.default.noteDuration,
},
[6] = {
type = "checkbox",
name = "Use account name",
getFunc = function() return PlayerRoleIndicator.savedVariables.noteUseAccountName end,
setFunc = function(newValue) PlayerRoleIndicator.savedVariables.noteUseAccountName = newValue end,
disabled = function() return not PlayerRoleIndicator.savedVariables.useNote end,
default = PlayerRoleIndicator.default.noteUseAccountName,
},
[7] = {
type = "checkbox",
name = "Use role icon in notification",
getFunc = function() return PlayerRoleIndicator.savedVariables.noteUseIcon end,
setFunc = function(newValue) PlayerRoleIndicator.savedVariables.noteUseIcon = newValue end,
disabled = function() return not PlayerRoleIndicator.savedVariables.useNote end,
default = PlayerRoleIndicator.default.noteUseIcon,
},
},
},
[8] = {
type = "submenu",
name = "leader",
icon = "/esoui/art/compass/groupleader.dds",
controls = PlayerRoleIndicator.createSubmenu("leader", PlayerRoleIndicator.savedVariables.leader, PlayerRoleIndicator.default.leader),
},
[9] = {
type = "submenu",
name = "tanks",
icon = "/esoui/art/tutorial/gamepad/gp_lfg_tank.dds",
controls = PlayerRoleIndicator.createSubmenu("tanks", PlayerRoleIndicator.savedVariables.tank, PlayerRoleIndicator.default.tank),
},
[10] = {
type = "submenu",
name = "healers",
icon = "/esoui/art/tutorial/gamepad/gp_lfg_healer.dds",
controls = PlayerRoleIndicator.createSubmenu("healers", PlayerRoleIndicator.savedVariables.healer, PlayerRoleIndicator.default.healer),
},
[11] = {
type = "submenu",
name = "damage dealers",
icon = "/esoui/art/tutorial/gamepad/gp_lfg_dps.dds",
controls = PlayerRoleIndicator.createSubmenu("damage dealers", PlayerRoleIndicator.savedVariables.dps, PlayerRoleIndicator.default.dps),
},
[12] = {
type = "submenu",
name = "companion",
icon = "/esoui/art/compass/groupmember.dds",
controls = PlayerRoleIndicator.createSubmenu("companion", PlayerRoleIndicator.savedVariables.companion, PlayerRoleIndicator.default.companion),
},
[13] = {
type = "submenu",
name = "Custom roles",
icon = "/esoui/art/tutorial/gamepad/gp_lfg_world.dds",
controls = PlayerRoleIndicator.createCustomRoles(),
},
[14] = {
type = "submenu",
name = "Shadow of the Fallen",
icon = GetAbilityIcon(102271), --Icon for "Shadow of the Fallen" buff
tooltip = "Settings for the veteran Cloudrest shade on death mechanic.",
controls = {
[1] = {
type = "description",
text = "When a player dies while fighting Z'Maja in veteran Cloudrest a shade will spawn. " ..
"This shade must be killed before you can resurrect the fallen player." ..
"\n\nThese are the settings relating to this mechanic, if a player is down and their shade is alive the icon above them will reflect this via a colour change when enabled.",
},
[2] = {
type = "checkbox",
name = "Enable colour indicator for Shadow of the Fallen",
getFunc = function() return PlayerRoleIndicator.savedVariables.showShade end,
setFunc = function(newValue)
PlayerRoleIndicator.savedVariables.showShade = newValue
PlayerRoleIndicator.UpdateRoleSwitch()
PlayerRoleIndicator.UpdateAllIconVisuals()
end,
default = PlayerRoleIndicator.default.showShade,
},
[3] = {
type = "colorpicker",
name = "Colour of icon while shade is alive",
getFunc = function() return
PlayerRoleIndicator.savedVariables.shadeColour.r,
PlayerRoleIndicator.savedVariables.shadeColour.g,
PlayerRoleIndicator.savedVariables.shadeColour.b,
PlayerRoleIndicator.savedVariables.shadeColour.a
end,
setFunc = function(r,g,b,a)
PlayerRoleIndicator.savedVariables.shadeColour.r = r
PlayerRoleIndicator.savedVariables.shadeColour.g = g
PlayerRoleIndicator.savedVariables.shadeColour.b = b
PlayerRoleIndicator.savedVariables.shadeColour.a = a
end,
default = {
r = PlayerRoleIndicator.default.shadeColour.r,
g = PlayerRoleIndicator.default.shadeColour.g,
b = PlayerRoleIndicator.default.shadeColour.b,
a = PlayerRoleIndicator.default.shadeColour.a
},
},
},
},
}
LAM2:RegisterOptionControls("Player_role_indicator", optionsData)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment