Это с Легиона(Оф), есть подобное на 335?
Код:
local TimeToDie = LibStub('AceAddon-3.0'):NewAddon('TimeToDie', 'AceEvent-3.0', 'AceConsole-3.0')
_G.TimeToDie = TimeToDie

local SML = LibStub("LibSharedMedia-3.0")

-------		Initialization		-------

local UnitIsFriend = UnitIsFriend
local UnitHealth = UnitHealth
local GetTime = GetTime
local UnitHealthMax = UnitHealthMax
local UnitExists = UnitExists
local format = format
local ceil = ceil

local defaults = {
	profile = {
		enemy = true,
		target = false, -- false := 'target', true := 'focus'
		tot = false,
		timeFormat = '%d:%02d',
		algorithm = 'InitialMidpoints',

		frame = true,
		locked = false,
		font = defaultFont,
		size = 24,
		outline = '',
		r = 1,
		g = .82,
		b = 0,
		strata = 'LOW',
		justify = 'CENTER',

		p1 = 'CENTER',
		p2 = 'CENTER',
		x = 0,
		y = 0,
	}
}

function TimeToDie:OnInitialize()
	local db = LibStub('AceDB-3.0'):New('TimeToDieDB', defaults, 'Default')
	self.db = db
	local RegisterCallback = db.RegisterCallback
	RegisterCallback(self, 'OnProfileChanged', 'OnEnable')
	RegisterCallback(self, 'OnProfileCopied', 'OnEnable')
	RegisterCallback(self, 'OnProfileReset', 'OnEnable')

	self:RegisterOptions()
end

function TimeToDie:OnEnable()
	local profile = self.db.profile
	self:ApplySettings(profile)

	if profile.frame then
		self:UpdateFrame(profile)
	elseif self.frame then
		self.frame:Hide()
	end
end

function TimeToDie:OnDisable()
	if self.frame then self.frame:Hide() end
	self:DisableEventFrame()
end

-------		Event Functions		--------

local profileEnemy, profileTOT, eventFrame
local profileTarget -- := profile.target and 'focus' or 'target'
local profileTargetTarget
local currentTarget -- profileTarget or profileTagert..'target'
local dataobj
local timeFormat

local ProfileAlgorithm


local health0, time0 -- initial health and time point
local mhealth, mtime -- current midpoint

function TimeToDie:InitialMidpoints(event, unit, health)  --health is not passed from blizz
	if unit ~= currentTarget then return end

	health = health or UnitHealth(unit)

	if health == UnitHealthMax(unit) then
		dataobj.text, health0, time0, mhealth, mtime = nil
		return
	end

	local time = GetTime()

	if not health0 then
		health0, time0 = health, time
		mhealth, mtime = health, time
		return
	end

	mhealth = (mhealth + health) * .5
	mtime = (mtime + time) * .5

	if mhealth >= health0 then
		dataobj.text, health0, time0, mhealth, mtime = nil
	else
		time = health * (time0 - mtime) / (mhealth - health0)  -- projected time
		if time < 60 or timeFormat == 'seconds' then
			dataobj.text = ceil(time)
		else
			dataobj.text = format(timeFormat, 1/60 * time, time % 60)
		end
	end
end

local n -- number of points for averaging

-- x,y := time,health
-- health0, time0, mhealth, mtime := ysum, xsum, xysum, xxsum
function TimeToDie:LeastSquares(event, unit, health)  --health is not passed from blizz
	if unit ~= currentTarget then return end

	health = health or UnitHealth(unit)

	if health == UnitHealthMax(unit) then
		dataobj.text, n = nil
		return
	end

	local time = GetTime()

	if not n then
		n = 1
		time0, health0 = time, health
		mhealth = time * health
		mtime = time * time
		return
	end

	n = n + 1
	time0 = time0 + time
	health0 = health0 + health
	mhealth = mhealth + time * health
	mtime = mtime + time * time

   time = (health0 * mtime - mhealth * time0) / (health0 * time0 - mhealth * n) - time  -- projected time

	if time < 0 then
		dataobj.text, n = nil
	elseif time < 60 or timeFormat == 'seconds' then
		dataobj.text = ceil(time)
	else
		dataobj.text = format(timeFormat, 1/60 * time, time % 60)
	end
end

-- x,y := time,health
-- health0, time0, mhealth, mtime := ybar, xbar, xybar, xxbar
function TimeToDie:WeightedLeastSquares(event, unit, health)  --health is not passed from blizz
	if unit ~= currentTarget then return end

	health = health or UnitHealth(unit)

	if health == UnitHealthMax(unit) then
		dataobj.text, n = nil
		return
	end

	local time = GetTime()

	if not n then
		n = 1
		time0, health0 = time, health
		mhealth = time * health
		mtime = time * time
		return
	end

   time0 = (time0 + time) * .5
   health0 = (health0 + health) * .5
   mhealth = (mhealth + time * health) * .5
   mtime = (mtime + time * time) * .5

   time = (mtime * health0 - time0 * mhealth) / (time0 * health0 - mhealth) - time  -- projected time

	if time < 0 then
		dataobj.text, n = nil
	elseif time < 60 or timeFormat == 'seconds' then
		dataobj.text = ceil(time)
	else
		dataobj.text = format(timeFormat, 1/60 * time, time % 60)
	end
end

function TimeToDie:OnChange(event)
	dataobj.text, health0, time0, mhealth, mtime, n = nil

	currentTarget = profileTarget
	if profileEnemy and UnitIsFriend('player', currentTarget) then
		if profileTOT and UnitExists('player', profileTargetTarget) and not UnitIsFriend('player', profileTargetTarget) then
			currentTarget = profileTargetTarget
		else
			currentTarget = nil
			if eventFrame then eventFrame:Hide() end -- stops error in OnUpdate
		end
	end
end

local oldhealth = nil
local totalElapsed = 0
local function OnUpdate(self, elapsed)
	totalElapsed = totalElapsed + elapsed
	if totalElapsed < .1 then return end
	totalElapsed = 0

	local health = UnitHealth(currentTarget)
	if oldhealth ~= health then
		oldhealth = health
		ProfileAlgorithm(TimeToDie, 'UNIT_HEALTH', currentTarget, health)
	end
end

--unit := target, player, or nil (focus)
local function UNIT_TARGET(self, event, unit)
	if unit == 'player' then
		unit = 'target'
	elseif event == 'PLAYER_FOCUS_CHANGED' then
		unit = 'focus'
	end
	if unit == profileTarget then -- unit is now either 'target' or 'focus'
		TimeToDie:OnChange()
		if currentTarget and currentTarget ~= unit then --target == unit..'target'
			self:Show()
		else
			self:Hide()
		end
	end
end

function TimeToDie:EnableEventFrame()
	if not eventFrame then
		eventFrame = CreateFrame('Frame')
		self.eventFrame = eventFrame
		eventFrame:SetScript('OnEvent', UNIT_TARGET)
		eventFrame:SetScript('OnUpdate', OnUpdate)
	end
	eventFrame:Hide() -- turn off OnUpdate when changing options
	eventFrame:RegisterEvent('UNIT_TARGET') -- covers player, targettarget, and focustarget
	eventFrame:RegisterEvent('PLAYER_FOCUS_CHANGED')  -- covers focus
	--make a call in case targets are already set when enabled
	UNIT_TARGET(eventFrame, nil, profileTarget)
end

function TimeToDie:DisableEventFrame()
	if eventFrame then
		eventFrame:Hide()
		eventFrame:UnregisterAllEvents()
	end
end

function TimeToDie:ApplySettings(profile)
	self:UnregisterAllEvents()

	local algorithm = profile.algorithm
	self:RegisterEvent('UNIT_HEALTH', algorithm)
	ProfileAlgorithm = self[algorithm]

	timeFormat = profile.timeFormat
	profileEnemy = profile.enemy
	profileTOT = profile.tot

	if profile.target then
		profileTarget = 'focus'
		self:RegisterEvent('PLAYER_FOCUS_CHANGED', 'OnChange')
	else
		profileTarget = 'target'
		self:RegisterEvent('PLAYER_TARGET_CHANGED', 'OnChange')
	end

	if profileEnemy and profileTOT then
		profileTargetTarget = profileTarget..'target'
		self:EnableEventFrame()
	else
		self:DisableEventFrame()
		self:OnChange()  -- this is called from EnableEventFrame, so need one here
	end
end

function TimeToDie:UpdateFrame(profile)
	local frame = self.frame
	if not frame then
		frame = CreateFrame('Frame', nil, UIParent, 'TimeToDieFrameTemplate')
		self.frame = frame
	end
	local text = frame.text

	frame:ClearAllPoints()
	frame:SetPoint(profile.p1, UIParent, profile.p2, profile.x, profile.y)

	if profile.frame then
		frame:Show()
	else
		frame:Hide()
		profile.locked = true
	end

	if profile.locked then
		frame.bg:Hide()
		frame:EnableMouse(false)
		dataobj.text = nil
	else
		frame.bg:Show()
		frame:EnableMouse(true)
		dataobj.text = 'TimeToDie'
	end

	text:SetFont(SML:Fetch('font', profile.font), profile.size, profile.outline)
	text:SetTextColor(profile.r, profile.g, profile.b)

	frame:SetFrameStrata(profile.strata)
	text:SetJustifyH(profile.justify)
end

dataobj = LibStub:GetLibrary('LibDataBroker-1.1'):NewDataObject('TimeToDie', {
	type = 'data source',
	text = 'TTD',
	label = 'TTD',
	icon = 'Interface\\Icons\\Spell_Holy_BorrowedTime',
})
TimeToDie.dataobj = dataobj

--[===[@debug@
function TimeToDie:Debug(...)
	if not self.debugging then return end
	if not IsAddOnLoaded('Blizzard_DebugTools') then LoadAddOn('Blizzard_DebugTools') end
	EventTraceFrame:Show()
	EventTraceFrame_OnEvent(EventTraceFrame, ...)
end
--@end-debug@]===]