Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Radar = {}
- HolyNovaIcon = {};
- local currentMap = {}
- currentMap.height = 500
- currentMap.width = 500
- -- Colors Initialization
- local Colors = {}
- Colors.green = {}
- Colors.green.r = 0.309803922
- Colors.green.g = 0.674509804
- Colors.green.b = 0.043137255
- Colors.yellow = {}
- Colors.yellow.r = 0.674509804
- Colors.yellow.g = 0.592156863
- Colors.yellow.b = 0.043137255
- Colors.orange = {}
- Colors.orange.r = 0.674509804
- Colors.orange.g = 0.325490196
- Colors.orange.b = 0.043137255
- Colors.red = {}
- Colors.red.r = 0.674509804
- Colors.red.g = 0.145098039
- Colors.red.b = 0.043137255
- Colors.BAD = {}
- Colors.BAD.r = 0.674509804
- Colors.BAD.g = 0.145098039
- Colors.BAD.b = 0.043137255
- Colors.GOOD = {}
- Colors.GOOD.r = 0.309803922
- Colors.GOOD.g = 0.674509804
- Colors.GOOD.b = 0.043137255
- -- Values that will be setted in a configuration file/menu
- RadarSize = 300 -- Square radar Height and Width
- -- This Global will keep all dots frames, so change them to update the radar
- local dots = {}
- SLASH_HOLYSONAR1 = '/hn'
- function SlashCmdList.HOLYSONAR(msg, editbox) -- 4.
- if msg == "radar" then
- -- Toggles Radar Visibility on /hn radar
- if Radar:IsVisible() then
- Radar:Hide()
- else
- Radar:Show()
- end
- elseif msg == "icon" then
- -- Toggles Icon Visibility on /hn icon
- if HolyNovaIcon:IsVisible() then
- HolyNovaIcon:Hide()
- else
- HolyNovaIcon:Show()
- end
- else
- -- Toggles Icon Visibility on both
- if HolyNovaIcon:IsVisible() then
- HolyNovaIcon:Hide()
- Radar:Hide()
- else
- HolyNovaIcon:Show()
- Radar:Show()
- end
- end
- end
- -- Holy Nova Icon With text initialization!
- local function newHNIcon()
- -- Create the main frame
- local IconFrame = CreateFrame("Frame", "HolyNovaTargets", UIParent)
- IconFrame:SetFrameStrata("DIALOG")
- IconFrame:SetPoint("CENTER", -400, 0)
- IconFrame:SetSize(64,64)
- IconFrame:EnableMouse(false)
- -- Set Holy Nova Icon Texture
- local iconTexture = IconFrame:CreateTexture(nil,"BACKGROUND")
- iconTexture:SetAllPoints(IconFrame)
- iconTexture:SetTexture("Interface\\Icons\\Spell_Holy_HolyNova.blp")
- -- Overlay on the icon to display a "Good/Bad" effect
- local overlay = IconFrame:CreateTexture("ARTWORK")
- overlay:SetAllPoints()
- -- Start with BAD Color
- overlay:SetTexture(Colors.BAD.r, Colors.BAD.g, Colors.BAD.b)
- overlay:SetAlpha(0.2)
- overlay:Show()
- IconFrame.overlay = overlay
- -- Text to display amount if people around
- local iconText = IconFrame:CreateFontString();
- iconText:SetFont("Fonts\\FRIZQT__.TTF", 18, "OUTLINE, MONOCHROME")
- iconText:SetText("0")
- iconText:SetTextColor(1,1,1)
- iconText:SetPoint("CENTER",IconFrame,"CENTER",0,0)
- IconFrame.text = iconText
- IconFrame:Show()
- return IconFrame
- end
- -- Radar Frame initialization code!
- local function newRadar()
- local radarFrame = CreateFrame("Frame", "LifeRadar", UIParent)
- radarFrame:SetFrameStrata("DIALOG")
- radarFrame:SetPoint("CENTER", 400, 0)
- radarFrame:SetHeight(RadarSize)
- radarFrame:SetWidth(RadarSize)
- radarFrame:EnableMouse(false) -- Click through
- radarFrame:SetToplevel(true)
- -- Transparent Black background
- local bg = radarFrame:CreateTexture(nil, "BACKGROUND")
- bg:SetAllPoints(radarFrame)
- bg:SetBlendMode("BLEND")
- bg:SetTexture(0, 0, 0, 0.3)
- radarFrame.background = bg
- -- I've used DBM circle, it looks pretty
- -- You can create another one and import it
- local circle = radarFrame:CreateTexture(nil, "ARTWORK")
- circle:SetSize(RadarSize, RadarSize)
- circle:SetPoint("CENTER")
- circle:SetTexture("Interface\\AddOns\\DBM-Core\\textures\\radar_circle.blp")
- circle:SetBlendMode("ADD")
- circle:SetVertexColor(0, 1, 0)
- -- Store the background circle on the variable, so we can change it's color
- radarFrame.circle = circle
- -- Player arrow, not needed, but looks good for reference
- local player = radarFrame:CreateTexture(nil, "OVERLAY")
- player:SetSize(32, 32)
- player:SetTexture("Interface\\Minimap\\MinimapArrow.blp")
- player:SetBlendMode("ADD")
- player:SetPoint("CENTER")
- -- Max Raid size is 40, so 40 frames (Dots) created should be enough
- for i = 1, 40 do
- local dot = radarFrame:CreateTexture(nil, "OVERLAY")
- dot:SetSize(20, 20)
- -- X,Y coords, You can start them on 0
- -- TOPLEFT is the "Anchor", so x and y are 'how maby pixels of distance the frame is from the anchor'
- dot:SetPoint("TOPLEFT", i*5, i*-5)
- -- PartyRaidBlips is a 'big' image containing a lot of textures, that include class icons, markeers, etc.
- dot:SetTexture("Interface\\Minimap\\PartyRaidBlips")
- -- You have to remap the texture in order to "zoom" on a specific texture
- -- Here I zoomed on the Priest one (just a white dot), just to get a nice looking circle without having to make a new texture
- dot:SetTexCoord(0.5, 0.625, 0, 0.25)
- -- Here you can set the dot color using RGBA, so the icon original color is irrelevant
- -- It'll desaturate it and colorize
- -- Randomized for fun
- dot:SetVertexColor(math.random(),math.random(),math.random(),1)
- -- All dots start hidden, so you can dot:Show() them after
- dot:Hide()
- dots[i] = dot
- end
- -- Frame starts hidden
- radarFrame:Show()
- return radarFrame
- end
- -- Map methods
- local function getUnitMapPosition(unit)
- SetMapToCurrentZone()
- local relative_x, relative_y = GetPlayerMapPosition(unit)
- return currentMap.width*relative_x, currentMap.height*relative_y
- end
- local function updateCurrentMap()
- -- Try custom map size first
- SetMapToCurrentZone()
- local mapName = GetMapInfo()
- local floor, a1, b1, c1, d1 = GetCurrentMapDungeonLevel()
- -- failed, try Blizzard's map size
- if not (a1 and b1 and c1 and d1) then
- local zoneIndex, a2, b2, c2, d2 = GetCurrentMapZone()
- a1, b1, c1, d1 = a2, b2, c2, d2
- end
- if not (a1 and b1 and c1 and d1) then return end
- currentMap.height = abs(d1-b1)
- currentMap.width = abs(c1-a1)
- end
- -- Straight line distance from 2 coordinates
- local function getDistance(x1, y1, x2, y2)
- local xx = x2 - x1
- local yy = y2 - y1
- return sqrt(xx*xx + yy*yy)
- end
- -- Just to make things more readable
- local function getDistanceByUnits(unit1,unit2)
- return getDistance(unit1.x,unit1.y,unit2.x,unit2.y)
- end
- -- Health Percent and Health Deficit methods
- local function getHealthPct(unit)
- local maxHp = UnitHealthMax(unit)
- local currentHp = UnitHealth(unit)
- if maxHp == 0 then
- maxHp = 1
- end
- if currentHp == 0 then
- currentHp = 1
- end
- local pctHp = currentHp/maxHp
- return pctHp
- end
- local function getHealthDeficit(unit)
- local healthDeficit = UnitHealthMax(unit) - UnitHealth(unit)
- return healthDeficit
- end
- local function getDeficitColor(HP)
- if(HP >= 0.95) then
- return Colors.green
- elseif(HP < 0.95 and HP >= 0.75) then
- return Colors.yellow
- elseif(HP < 0.75 and HP >= 0.50) then
- return Colors.orange
- elseif(HP < 0.50) then
- return Colors.red
- end
- end
- -- Generates a table containing all valid players for healing
- -- Dead and disconnected units are not taken in account, player is also not on the list
- local function getValidPlayerList()
- -- If not in a group, return an empty table
- local groupSize = GetNumGroupMembers()
- if groupSize == 0 then
- return {}
- end
- -- Resets our current playerList
- local playerList = {}
- -- Check if we're on a party or raid
- local prefix = "raid"
- if not IsInRaid() then
- prefix = "party"
- -- Party unit ids does not include the player! (Only goes from 1 to 4)
- groupSize = groupSize - 1
- end
- -- Player data:
- local player = {}
- player.x, player.y = getUnitMapPosition("player")
- -- Iterate through all players
- local k = 1
- for i = 1, groupSize do
- -- Create a new Unit
- local newUnit = {}
- newUnit.unitId = prefix .. i
- -- Check if Valid Unit - Not Dead, not the player and actually exists (UnitName doesn't return nil)
- if not UnitIsDeadOrGhost(newUnit.unitId) and not UnitIsUnit(newUnit.unitId,"player") and UnitName(newUnit.unitId) then
- -- Name for debugging purpouses, not used
- newUnit.name = UnitName(newUnit.unitId)
- -- Store Unit Health Deficit
- newUnit.healthDeficit = getHealthDeficit(newUnit.unitId)
- newUnit.healthPct = getHealthPct(newUnit.unitId)
- -- Store Unit Coordinates, to display on the radar
- newUnit.x, newUnit.y = getUnitMapPosition(newUnit.unitId)
- -- Store Unit distance from player
- newUnit.distance = getDistanceByUnits(player,newUnit)
- -- Store the Player itself on the table
- -- Insert is not working on WoD beta, so doing normal k+1 thing - NOT GOOD
- playerList[k] = newUnit
- k = k + 1
- end
- end
- return playerList
- end
- local function updateData(playerList,radius)
- local player = {}
- player.x, player.y = getUnitMapPosition("player")
- -- Holy Nova Heal amount - TBD
- local HolyNovaAmount = 5000
- -- 1 = No overheal is allowed, 0 = Full overheal is allowed
- local HolyNovaOverhealCoheficient = 1
- --local string = ""
- local last = 1
- local playersInRange = 0
- for i,unit in ipairs(playerList) do
- --string = string .. unit.name.. "/"..unit.unitId..": "..unit.distance.."\n"
- -- Check if player HP deficit is higher than the holy nova amount and overheal treshold for being considered in range
- if unit.healthDeficit > HolyNovaAmount*HolyNovaOverhealCoheficient then
- if unit.distance <= radius*1.1 then
- playersInRange = playersInRange + 1
- end
- end
- -- Get a dot
- local dot = dots[i]
- -- Get its color based on player Health percent
- local color = getDeficitColor(unit.healthPct)
- dot:SetVertexColor(color.r,color.g,color.b,1)
- -- Now we have to calculate where the point will be in the radar
- -- To make things easier, let's get the distance between the player x,y and the current unit x,y
- -- This is considering the player is in the center of the radar
- -- Calculate Distances in yards
- local dist_x = unit.x - player.x
- local dist_y = unit.y - player.y
- -- Normalize it to pixels
- -- How much does 1 yard is in pixels for our radar size? RadarRadius/Measuring radius
- -- Radius is doubled because we're considering the diameter here
- local radarSize = tonumber(Radar:GetHeight())
- local yardInPixel = (radarSize/(radius*2))
- -- Multiply it so we get the values in pixel
- local radar_x = dist_x*yardInPixel
- local radar_y = dist_y*yardInPixel
- -- Since we considered the player is in the center, we set the anchor to the center of the radar
- -- and place our offsets for x and y as calculated
- -- Need to clear point always
- dot:ClearAllPoints();
- dot:SetPoint("CENTER", radar_x, radar_y)
- -- Point should be visible only if it's inside the radar
- -- Remember, the anchor is the center point so it should go from "-150 to 150" if the Width/Height is 300
- -- This considers a square only, should make one to collide with the actual circle
- --local bound1, bound2 = Radar:GetWidth()/-2, Radar:GetWidth()/2
- --if radar_x > bound1 and radar_x < bound2 and radar_y > bound1 and radar_y < bound2 then
- --dot:Show()
- --else
- --dot:Hide()
- --end
- -- Use this instead to show only inside radar CIRCLE
- if unit.distance <= radius then
- dot:Show()
- else
- dot:Hide()
- end
- -- If this is the last, then everything beyond should be hidden (see below)
- last = i + 1
- end
- HolyNovaIcon.text:SetText(playersInRange)
- --HolyNovaIcon.text:SetText(string)
- local overlay = HolyNovaIcon.overlay
- if playersInRange > 4 then
- overlay:SetTexture(Colors.GOOD.r, Colors.GOOD.g, Colors.GOOD.b)
- else
- overlay:SetTexture(Colors.BAD.r, Colors.BAD.g, Colors.BAD.b)
- end
- -- Hide all dots that are beyond our group size
- for i = last, 40 do
- local dot = dots[i]
- dot:Hide()
- end
- end
- local tickTime = 0.05 --call range checking function ever tickTime seconds
- local targetTime = 0
- local total = 0
- local function onUpdate(self,elapsed)
- total = total + elapsed
- -- Radius in yards
- local radius = 12
- if total >= tickTime then
- -- Should not be called so often, better make an event for it
- updateCurrentMap()
- local playerList = getValidPlayerList()
- updateData(playerList,radius)
- total = 0
- targetTime = tickTime
- end
- end
- Radar = newRadar()
- HolyNovaIcon = newHNIcon()
- Radar:SetScript("OnUpdate", onUpdate)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement