local POSSESSION_HALO_TEMPLATE = "ZO_PossessionHaloTexture" ZO_UnitVisualizer_PossessionModule = ZO_UnitAttributeVisualizerModuleBase:Subclass() function ZO_UnitVisualizer_PossessionModule:New(...) return ZO_UnitAttributeVisualizerModuleBase.New(self, ...) end function ZO_UnitVisualizer_PossessionModule:Initialize(layoutData) self.layoutData = layoutData end local function ResetControl(control) control:SetHidden(true) control:SetParent(nil) control:ClearAnchors() end local function ApplyPlatformStyleToPossessionObject(object, glow) ApplyTemplateToControl(object.possessionHaloTexture, ZO_GetPlatformTemplate(POSSESSION_HALO_TEMPLATE)) ApplyTemplateToControl(object.possessionHaloGlow, ZO_GetPlatformTemplate(glow)) end do local g_possessionPool local function OnPlayControllingTimeline(animation) animation.owner:NotifyTakingControlOf(animation.bar) end local function ReleaseTimeline(animation) animation.owner:NotifyEndingControlOf(animation.bar) animation.pool:ReleaseObject(animation.key) end local function ReleaseTimelineIfReversed(animation) if animation:IsPlayingBackward() then ReleaseTimeline(animation) else animation.owner:NotifyEndingControlOf(animation.bar) end end function ZO_UnitVisualizer_PossessionModule:GetOrCreatePossessionPool() if not g_possessionPool then local function OnPossessionFadeStopped(animation) if animation:IsPlayingBackward() then animation.loopingAnimation:Stop() else animation.owner:NotifyEndingControlOf(animation.bar) end end local function CreatePossession(pool) local id = pool:GetNextControlId() -- create halo anim controls local possessionHaloTextureName = POSSESSION_HALO_TEMPLATE..self.layoutData.type..id local possessionHaloGlowName = self.layoutData.possessionHaloGlowTemplate..id local possessionHaloTexture = CreateControlFromVirtual(possessionHaloTextureName, GuiRoot, POSSESSION_HALO_TEMPLATE) local possessionHaloGlow = CreateControlFromVirtual(possessionHaloGlowName, GuiRoot, self.layoutData.possessionHaloGlowTemplate) local fadeAnimation = ANIMATION_MANAGER:CreateTimelineFromVirtual("PossessionFadeAnimation", possessionHaloTexture) fadeAnimation:GetLastAnimation():SetAnimatedControl(possessionHaloGlow) fadeAnimation:SetHandler("OnPlay", OnPlayControllingTimeline) fadeAnimation:SetHandler("OnStop", OnPossessionFadeStopped) local loopingAnimation = ANIMATION_MANAGER:CreateTimelineFromVirtual("PossessionHaloAnimation", possessionHaloTexture) fadeAnimation.loopingAnimation = loopingAnimation loopingAnimation:SetHandler("OnStop", ReleaseTimeline) return { possessionHaloTexture = possessionHaloTexture, possessionHaloGlow = possessionHaloGlow, fadeAnimation = fadeAnimation, loopingAnimation = loopingAnimation } end local function Reset(container) ResetControl(container.possessionHaloTexture) ResetControl(container.possessionHaloGlow) end g_possessionPool = ZO_ObjectPool:New(CreatePossession, Reset) end return g_possessionPool end end function ZO_UnitVisualizer_PossessionModule:GetInitialStatValue(stat, attribute, powerType) return self:GetInitialValueAndMarkMostRecent(ATTRIBUTE_VISUAL_POSSESSION, stat, attribute, powerType) end function ZO_UnitVisualizer_PossessionModule:CreateInfoTable(control, stat, attribute, power, playPossessionAnimation) if control then local value = self:GetInitialStatValue(stat, attribute, power) return { value = value, lastValue = value, playPossessionAnimation = playPossessionAnimation, barSizeState = ATTRIBUTE_BAR_STATE_NORMAL } end return nil end function ZO_UnitVisualizer_PossessionModule:OnAdded(healthBarControl, magickaBarControl, staminaBarControl) self.barControls = { [ATTRIBUTE_HEALTH] = healthBarControl, } if IsPlayerActivated() then self:InitializeBarValues() end EVENT_MANAGER:RegisterForEvent("ZO_UnitVisualizer_PossessionModule" .. self:GetModuleId(), EVENT_PLAYER_ACTIVATED, function() self:InitializeBarValues() end) end function ZO_UnitVisualizer_PossessionModule:InitializeBarValues() local healthBarControl = self.barControls[ATTRIBUTE_HEALTH] if self.barInfo == nil then self.barInfo = { [ATTRIBUTE_HEALTH] = self:CreateInfoTable(healthBarControl, STAT_MITIGATION, ATTRIBUTE_HEALTH, COMBAT_MECHANIC_FLAGS_HEALTH, self.PlayPossessionAnimation), } else self.barInfo[ATTRIBUTE_HEALTH].value = self:GetInitialStatValue(STAT_MITIGATION, ATTRIBUTE_HEALTH, COMBAT_MECHANIC_FLAGS_HEALTH) end for attribute, bar in pairs(self.barControls) do self:OnValueChanged(bar, self.barInfo[attribute], ANIMATION_INSTANT) end end function ZO_UnitVisualizer_PossessionModule:OnUnitChanged() self:InitializeBarValues() end function ZO_UnitVisualizer_PossessionModule:IsUnitVisualRelevant(visualType, stat, attribute, powerType) if visualType == ATTRIBUTE_VISUAL_POSSESSION then return self.barInfo and self.barInfo[attribute] ~= nil end return false end function ZO_UnitVisualizer_PossessionModule:OnUnitAttributeVisualAdded(visualType, stat, attribute, powerType, value) self.barInfo[attribute].value = self.barInfo[attribute].value + value self:OnValueChanged(self.barControls[attribute], self.barInfo[attribute]) end function ZO_UnitVisualizer_PossessionModule:OnUnitAttributeVisualUpdated(visualType, stat, attribute, powerType, oldValue, newValue) self.barInfo[attribute].value = self.barInfo[attribute].value + (newValue - oldValue) self:OnValueChanged(self.barControls[attribute], self.barInfo[attribute]) end function ZO_UnitVisualizer_PossessionModule:OnUnitAttributeVisualRemoved(visualType, stat, attribute, powerType, value) self.barInfo[attribute].value = self.barInfo[attribute].value - value self:OnValueChanged(self.barControls[attribute], self.barInfo[attribute]) end function ZO_UnitVisualizer_PossessionModule:PlayPossessionAnimation(bar, info, instant) local pool = self:GetOrCreatePossessionPool() local container, key = pool:AcquireObject() ApplyPlatformStyleToPossessionObject(container, self.layoutData.possessionHaloGlowTemplate) -- create bar overlay control if not info.barOverlayControl then local barOverlayControlName = "$(parent)PossessionOverlayContainer"..self.layoutData.type info.barOverlayControl = CreateControlFromVirtual(barOverlayControlName, bar, self.layoutData.overlayContainerTemplate) end local possessionHaloTexture = container.possessionHaloTexture local possessionHaloGlow = container.possessionHaloGlow local loopingAnimation = container.loopingAnimation local fadeAnimation = container.fadeAnimation loopingAnimation.key = key loopingAnimation.owner = self:GetOwner() loopingAnimation.pool = pool loopingAnimation.bar = bar fadeAnimation.owner = self:GetOwner() fadeAnimation.bar = bar fadeAnimation.instant = instant info.barOverlayControl:SetParent(bar) info.barOverlayControl:SetHidden(false) info.barOverlayControl:SetAnchor(TOPLEFT, bar, TOPLEFT, self.layoutData.overlayLeftOffset, self.layoutData.overlayTopOffset) info.barOverlayControl:SetAnchor(BOTTOMRIGHT, bar, BOTTOMRIGHT, self.layoutData.overlayRightOffset, self.layoutData.overlayBottomOffset) possessionHaloTexture:SetParent(bar) possessionHaloTexture:SetHidden(false) possessionHaloTexture:SetAnchor(LEFT, bar, LEFT, -80, 0) possessionHaloTexture:SetAnchor(RIGHT, bar, RIGHT, 80, 0) possessionHaloGlow:SetParent(bar) possessionHaloGlow:SetHidden(false) possessionHaloGlow:SetAnchor(LEFT, bar, LEFT, -18) possessionHaloGlow:SetAnchor(RIGHT, bar, RIGHT, 18) loopingAnimation:PlayFromStart() fadeAnimation:PlayFromStart() return fadeAnimation end function ZO_UnitVisualizer_PossessionModule:OnValueChanged(bar, info, stat, instant) local value = info.value local lastValue = info.lastValue info.lastValue = value if value < 0 then if info.currentAnimation then info.currentAnimation.instant = instant if lastValue > 0 then ZO_Animation_PlayBackwardOrInstantlyToStart(info.currentAnimation, instant) if instant then bar.bgContainer:SetAlpha(1) end else if instant then info.currentAnimation:PlayInstantlyToEnd() end return -- already playing the correct animation end end info.currentAnimation = info.playPossessionAnimation(self, bar, info, instant) elseif value > 0 then if info.currentAnimation then info.currentAnimation.instant = instant if lastValue < 0 then ZO_Animation_PlayBackwardOrInstantlyToStart(info.currentAnimation, instant) else if instant then info.currentAnimation:PlayInstantlyToEnd() end return -- already playing the correct animation end end info.currentAnimation = info.playPossessionAnimation(self, bar, info, instant) else if info.currentAnimation then info.currentAnimation.instant = instant ZO_Animation_PlayBackwardOrInstantlyToStart(info.currentAnimation, instant) if instant and lastValue > 0 then bar.bgContainer:SetAlpha(1) end info.currentAnimation = nil ResetControl(info.barOverlayControl) end end end function ZO_UnitVisualizer_PossessionModule:ApplyPlatformStyle() local pool = self:GetOrCreatePossessionPool() local activeObjects = pool:GetActiveObjects() for _, object in pairs(activeObjects) do ApplyPlatformStyleToPossessionObject(object, self.layoutData.possessionHaloGlowTemplate) end end