Quantcast

* Gutted for modular rewrite

James Whitehead II [12-29-06 - 11:41]
* Gutted for modular rewrite
Filename
Localization.enUS.lua
PerfectRaid.lua
PerfectRaid.toc
PerfectRaid_Aggro.lua
PerfectRaid_Buffs.lua
PerfectRaid_Range.lua
diff --git a/Localization.enUS.lua b/Localization.enUS.lua
new file mode 100644
index 0000000..3db9c96
--- /dev/null
+++ b/Localization.enUS.lua
@@ -0,0 +1,2 @@
+PerfectRaidLocals = {
+}
diff --git a/PerfectRaid.lua b/PerfectRaid.lua
index a84af93..c3f5507 100644
--- a/PerfectRaid.lua
+++ b/PerfectRaid.lua
@@ -18,7 +18,7 @@

   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHsqsANTABILITY AND FITNESS FOR
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
@@ -31,29 +31,19 @@

 local frames = {}
 local unavail = {}
-local aggro = {}

-local L
-local utils = DongleStub("DongleUtils")
+local L = PerfectRaidLocals
 PerfectRaid = DongleStub("Dongle"):New("PerfectRaid")
-PerfectRaid.frames = frames

 function PerfectRaid:Initialize()
 	self.defaults = {
 		profile = {
-			headers = {},
-			buffs = {},
-			positions = {},
-			simple = {
-				voffset = 15,
-				titles = true,
-			},
-			mode = "advanced",
+			headers = {
+			},
 		},
 	}

 	self.db = self:InitializeDB("PerfectRaidDB", self.defaults)
-	L = self.LOCALS

 	if not ClickCastFrames then
 		ClickCastFrames = {}
@@ -72,19 +62,6 @@ function PerfectRaid:Enable()
 	self:RegisterEvent("UNIT_MAXRAGE", "UNIT_MAXMANA")
 	self:RegisterEvent("UNIT_MAXENERGY", "UNIT_MAXMANA")
 	self:RegisterEvent("UNIT_MAXFOCUS", "UNIT_MAXMANA")
-	self:RegisterEvent("UNIT_AURA")
-	self:RegisterEvent("RAID_TARGET_UPDATE")
-
-	local mode = self.db.profile.mode
-	if mode == "singleclass" then
-		self:CreateSingleColumn()
-	elseif mode == "singlegroup" then
-		self:CreateSingleColumn("group")
-	elseif mode == "double" then
-		self:CreateDoubleColumn()
-	elseif mode == "advanced" then
-		self:CreateRaidHeaders()
-	end

 	-- Register slash command
 	self.cmd = self:InitializeSlashCommand("PerfectRaid Options", "PERFECTRAID", "praid", "perfectraid")
@@ -94,97 +71,12 @@ function PerfectRaid:Enable()
 	self:RAID_ROSTER_UPDATE()
 end

-function PerfectRaid:CreateSingleColumn(sort)
-	self.column = self.column or {}
-	local column = self.column
-
-	local classes = {"Warrior","Priest","Druid","Shaman","Paladin","Rogue","Mage","Warlock","Hunter"}
-	local voffset = self.db.profile.simple.voffset * -1
-	local titles = self.db.profile.simple.titles
-
-	if sort == "group" then
-		classes = {"Group 1","Group 2","Group 3","Group 4","Group 5","Group 6","Group 7","Group8"}
-	end
-
-	for i=1,#classes do
-		local filter
-		if sort == "group" then
-			filter = string.sub(classes[i], -1, -1)
-		else
-			filter = string.upper(classes[i])
-		end
-		local title = titles and classes[i] or nil
-
-		if not column[i] then
-			column[i] = self:CreateRaidFrame("PRColumn"..i, title, filter, nil, column[1])
-			column[i]:Show()
-		else
-			self:ChangeRaidFrame("PRColumn"..i, title, filter, nil, column[1])
-			column[i]:Show()
-			column[i]:ClearAllPoints()
-		end
-	end
-
-	self:RestorePosition("PRColumn1")
-
-	for i=2,#classes do
-		self.column[i].locked = true
-		self.column[i]:SetPoint("TOP", self.column[i-1], "BOTTOM", 0, voffset)
-	end
-
-	if GetNumRaidMembers() <= 0 then
-		for i,frame in ipairs(column) do
-			frame:Hide()
-		end
-	end
-end
-
-function PerfectRaid:CreateDoubleColumn()
-	self.column = self.column or {}
-	local column = self.column
-
-	local voffset = self.db.profile.simple.voffset * -1
-	local titles = self.db.profile.simple.titles
-	local classes = {"Group 1","Group 2","Group 3","Group 4","Group 5","Group 6","Group 7","Group8"}
-
-	for i=1,#classes do
-		local filter = string.sub(classes[i], -1, -1)
-		local title = titles and classes[i] or nil
-
-		if not column[i] then
-			column[i] = self:CreateRaidFrame("PRColumn"..i, title, filter, nil, column[1])
-			column[i]:Show()
-		else
-			self:ChangeRaidFrame("PRColumn"..i, title, filter, nil, column[1])
-			column[i]:Show()
-			column[i]:ClearAllPoints()
-		end
-	end
-
-	self:RestorePosition("PRColumn1")
-
-	for i=2,4 do
-		column[i].locked = true
-		column[i]:SetPoint("TOP", column[i-1], "BOTTOM", 0, voffset)
-	end
-	column[5]:SetPoint("TOPLEFT", column[1], "TOPRIGHT", 50, 0)
-	for i=6,8 do
-		column[i].locked = true
-		column[i]:SetPoint("TOP", column[i-1], "BOTTOM", 0, voffset)
-	end
-	if GetNumRaidMembers() <= 0 then
-		for i,frame in ipairs(column) do
-			frame:Hide()
-		end
-	end
-end
-
 function PerfectRaid:CreateRaidHeaders()
 	local list = self.db.profile.headers
 	self.headers = self.headers or {}

 	local inraid = GetNumRaidMembers() > 0
-
+	self:Print("Checking", #list, "headers")
 	for i=1,#list do
 		local entry = list[i]
 		local name = "PRHeader"..i
@@ -291,31 +183,6 @@ function PerfectRaid:CreateRaidFrame(name, title, filter, strict, dragparent)
 	return frame
 end

-function PerfectRaid:CreatePartyFrame()
-	-- Create the player frame first, in case we need it
-
-	local frame = CreateFrame("Frame", "PRaidPartyHeader", UIParent, "SecurePartyHeaderTemplate")
-	frame:SetAttribute("point", "TOP")
-	frame:SetAttribute("template", "SecureUnitButtonTemplate")
-	frame:SetAttribute("templateType", "Button")
-	frame:SetAttribute("nameList", UnitName("player"))
-	frame:SetAttribute("dragparent", frame)
-	frame:SetAttribute("yOffset", -2)
-
-	frame.initialConfigFunction = PerfectRaid.ConfigureButton
-	frame:SetPoint("CENTER", 0, 0)
-	frame:SetMovable(true)
-	frame:SetClampedToScreen(true)
-
-	local frame = CreateFrame("Button", "PRaidPlayerFrame", PRaidPartyHeader, "SecureUnitButtonTemplate")
-	PerfectRaid.ConfigureButton(frame)
-	frame:SetAttribute("unit", "player")
-	frame:SetAttribute("dragparent", PRaidPartyHeader)
-	frame:SetPoint("BOTTOM", PRaidPartyHeader, "TOP", 0, 2)
-
-	PRaidPartyHeader:Show()
-end
-
 function PerfectRaid:GetColoredName(unit)
 	local class = select(2, UnitClass(unit)) or "WARRIOR"
 	local color = RAID_CLASS_COLORS[class]
@@ -326,31 +193,20 @@ function PerfectRaid:UNIT_HEALTH(event, unit)
 	if not frames[unit] then return end
 	local health = UnitHealth(unit)
 	local max = UnitHealthMax(unit)
+
 	-- Hack to fix api issue
 	if max < health then max = health end
 	local deficit = max - health
 	local perc = UnitHealthMax(unit) / health
 	local class = select(2, UnitClass(unit))
 	local perc = (health/max) or 0
-	local aggro = aggro[unit] >= 15

-	if aggro then
-		if deficit > 999 then
-			deficit = string.format("|cFFFF1111%.1fk|r", deficit / 1000)
-		elseif deficit == 0 then
-			deficit = "|cFFFF1111Aggro|r"
-		else
-			deficit = string.format("|cFFFF1111%d|r", deficit)
-		end
-	else
-		if deficit > 999 then
-			deficit = string.format("%.1fk", deficit / 1000)
-		elseif deficit == 0 then
-			deficit = ""
-		end
+	if deficit > 999 then
+		deficit = string.format("%.1fk", deficit / 1000)
+	elseif deficit == 0 then
+		deficit = ""
 	end

-
 	if UnitIsDead(unit) or UnitIsGhost(unit) or not UnitIsConnected(unit) then
 		local status

@@ -375,15 +231,10 @@ function PerfectRaid:UNIT_HEALTH(event, unit)
 	else
 		if unavail[unit] then
 			for frame in pairs(frames[unit]) do
-				local color = frame.classcolor
---				frame.healthbar:SetStatusBarColor(color.r, color.g, color.b)
-				frame.healthbar:SetStatusBarColor(utils.GetHPSeverity(perc))
 				frame.healthbar:SetMinMaxValues(0, UnitHealthMax(unit))
 				frame.healthbar:SetValue(UnitHealth(unit))
-				frame:SetBackdropBorderColor(color.r, color.g, color.b)

 				local color = frame.manacolor
-				frame.manabar:SetStatusBarColor(color.r, color.g, color.b)
 				frame.manabar:SetMinMaxValues(0, UnitManaMax(unit))
 				frame.manabar:SetValue(UnitMana(unit))

@@ -395,7 +246,6 @@ function PerfectRaid:UNIT_HEALTH(event, unit)
 		for frame in pairs(frames[unit]) do
 			local class = select(2, UnitClass(unit))
 			frame.healthbar:SetValue(health)
-			frame.healthbar:SetStatusBarColor(utils.GetHPSeverity(perc))
 			frame.status:SetText(deficit)
 		end
 	end
@@ -463,12 +313,9 @@ local function OnShow(frame)

 	frames[unit] = frames[unit] or {}
 	frames[unit][frame] = true
-	aggro[unit] = 0

 	self:UNIT_HEALTH(nil, unit)
 	self:UNIT_MANA(nil, unit)
-	self:UNIT_AURA(nil, unit)
-	self:RAID_TARGET_UPDATE(nil, unit)
 end

 local function OnHide(frame)
@@ -491,12 +338,14 @@ local function OnAttributeChanged(frame, name, value)
 		local visible = nil
 		for i=1,num do
 			local button = parent:GetAttribute("child"..i)
-			if button:IsShown() then visible = true end
+			if button and button:IsShown() then visible = true end
 		end
-		if not visible then
-			parent.title:Hide()
-		else
-			parent.title:Show()
+		if parent.title then
+			if not visible then
+				parent.title:Hide()
+			else
+				parent.title:Show()
+			end
 		end
 	end
 end
@@ -592,247 +441,212 @@ function PerfectRaid:RAID_ROSTER_UPDATE()
 	if self.moving then
 		self.moving:StopMovingOrSizing()
 	end
-
-	-- Lets check for party leader
-	for unit in pairs(frames) do
-		local leader = UnitIsPartyLeader(unit)
-		local looter = select(2, GetLootMethod()) == unit
-		if leader and looter then looter = false end
-
-		for frame in pairs(frames[unit]) do
-			if leader then
-				frame.leadericon:SetWidth(16)
-			else
-				frame.leadericon:SetWidth(0.1)
-			end
-			if looter then
-				frame.looticon:SetWidth(16)
-			else
-				frame.looticon:SetWidth(0.1)
-			end
-		end
-	end
 end

-local buffcache = {}
-local work = {}
-function PerfectRaid:UNIT_AURA(event, unit)
-	if not frames[unit] then return end
-	for k,v in pairs(buffcache) do buffcache[k] = nil end
-
-	for i=1,40 do
-		local name,rank,texture,count = UnitBuff(unit, i)
-		if not name then break end
-		buffcache[name] = (buffcache[name] or 0) + 1
-	end
-
-	for i=1,40 do
-		local name,rank,texture,count = UnitDebuff(unit, i)
-		if not name then break end
-		buffcache[name] = (buffcache[name] or 0) + 1
+function PerfectRaid:ShowOptions()
+	if not PROptions then
+		self:CreateOptions()
 	end
+	if PROptions:IsVisible() then
+		PROptions:Show()
+	else
+		PROptions:Hide()
+	end
+end

-	for k,v in pairs(work) do work[k] = nil end
+local menuItems = {}
+function PerfectRaid:CreateOptions()
+	local frame = self:CreateFrame("PROptions", UIParent)
+	frame:SetHeight(250)
+	frame:SetWidth(400)
+	frame:SetPoint("CENTER", 0, 0)

-	local buffs = self.db.profile.buffs
-	for i,entry in ipairs(buffs) do
-		local checkcond = false
-		local num = buffcache[entry.buffname]
-		if entry.missing then
-			if not buffcache[entry.buffname] and not buffcache[entry.groupbuff or "nil"] then
-				checkcond = true
-			end
-		else
-			if buffcache[entry.buffname] or buffcache[entry.groupbuff or "nil"] then
-				checkcond = true
-			end
-		end
-
-		local conds = self.conditions
-		if checkcond then
-			for i,name in pairs(entry.cond) do
-				if conds[name] and conds[name](unit) then
-					if num and num > 1 then
-						table.insert(work, entry.colortext .. "(" .. num .. ")")
-					else
-						table.insert(work, entry.colortext)
-					end
-				end
-			end
-		end
-	end
+	local frame = self:CreateFrame("PROptionsMenu", PROptions)
+	frame:SetWidth(150)
+	frame:SetPoint("TOPRIGHT", PROptions, "TOPLEFT", 0, 0)
+	frame:SetPoint("BOTTOMRIGHT", PROptions, "BOTTOMLEFT", 0, 0)

-	local status = strjoin(" ", unpack(work))
-	for frame in pairs(frames[unit]) do
-		frame.aura:SetText(status)
-	end
+	local frame = CreateFrame("Frame", "PROptions_General", PROptions)
+	self:AddMenuItem("General Options", 1, PROptions_General)
+
+	self:CreateFrameEditor()
 end

-function PerfectRaid:RAID_TARGET_UPDATE(event, unit)
-	if not frames[unit] then return end
-	local index = GetRaidTargetIndex(unit)
-	if not index then
-		for frame in pairs(frames[unit]) do
-			frame.raidicon:SetWidth(0.1)
-		end
-	else
-		for frame in pairs(frames[unit]) do
-			SetRaidTargetIconTexture(frame.raidicon, index)
-			frame.raidicon:SetWidth(16)
-		end
-	end
+function PerfectRaid:CreateFrame(name, parent)
+	local frame = CreateFrame("Frame", name, parent)
+	frame:SetBackdrop(GameTooltip:GetBackdrop())
+	frame:SetBackdropColor(0,0,0)
+	return frame
 end

-function PerfectRaid:ShowOptions()
-	if not PROptions then
-		self:CreateOptions()
-	end
+local function sortFunction(a,b)
+	return a.order < b.order
+end

-	if PROptions:IsVisible() then
-		PROptions:Hide()
-	else
-		PROptions:Show()
+local OnClick = function(button)
+	if PROptions.current then
+		PROptions.current:Hide()
+		PROptions.lastButton:SetChecked(nil)
+	end
+	button.frame:SetAllPoints(PROptions)
+	button.frame:Show()
+	PROptions.current = button.frame
+	PROptions.lastButton = button
+end
+
+local buttons = {}
+function PerfectRaid:AddMenuItem(name, order, frame)
+	local num = #menuItems + 1
+	local button = CreateFrame("CheckButton", "PRMenuItem"..num, PROptionsMenu)
+	button:SetHeight(20)
+	button:SetWidth(140)
+	button:SetHighlightTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight")
+	button:SetCheckedTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight")
+	button:SetScript("OnClick", OnClick)
+
+	local texture = button:CreateTexture(nil, "BACKGROUND")
+	texture:SetTexture(0,0,0,0.8)
+	texture:SetAllPoints()
+
+	local label = button:CreateFontString(nil, "OVERLAY")
+	label:SetFontObject(GameFontNormalSmall)
+	label:SetPoint("CENTER")
+	label:SetJustifyH("CENTER")
+	label:SetText(name)
+	button.label = label
+
+	buttons[num] = button
+
+	local entry = {}
+	entry.name = name
+	entry.order = order
+	entry.frame = frame
+
+	table.insert(menuItems, entry)
+
+	-- Re-order the menu items
+	table.sort(menuItems, sortFunction)
+	for idx,entry in ipairs(menuItems) do
+		local button = buttons[idx]
+		button.label:SetText(entry.name)
+		button.frame = entry.frame
+	end
+
+	PRMenuItem1:SetPoint("TOP", 0, -7)
+	for i=2,#menuItems do
+		local button = buttons[i]
+		button:SetPoint("TOP", buttons[i-1], "BOTTOM", 0, -2)
 	end
 end

-local class = select(2, UnitClass("player"))
-local spells = {
-	DRUID = "Healing Touch",
-	SHAMAN = "Healing Wave",
-	PRIEST = "Lesser Heal",
-	PALADIN = "Holy Light",
-}
-
-local rangespell = spells[class]
-
-local victims = {}
-local targets = {}
-local flashing = {}
-
-if rangespell then
-	local elapsed = 0
-	function PerfectRaid.OnUpdate(frame, arg1)
-		elapsed = elapsed + arg1
-		if elapsed >= 0.5 then
-			if rangespell then
-				for unit,tbl in pairs(frames) do
-					local range = IsSpellInRange(rangespell, unit) == 1
-					local alpha = range and 1.0 or 0.3
-					for frame in pairs(tbl) do
-						if not flashing[frame] then
-							frame:SetAlpha(alpha)
-						end
-					end
-				end
-			end
-
-			-- Aggro check
-			for unit,tbl in pairs(frames) do
-				if not targets[unit] then
-					targets[unit] = unit.."target"
-					victims[unit] = unit.."targettarget"
-					aggro[unit] = 0
-				end
-
-				local target = targets[unit]
-				local victim = victims[unit]
-				if UnitIsUnit(victim, unit) and UnitCanAttack(unit, target) then
-					-- unit is being targeted by a hostile mob
-					if aggro[unit] < 20 then
-						local val = aggro[unit]
-						if val >= 5 and val <= 10 then
-							PerfectRaid:UNIT_HEALTH(nil, unit)
-						end
-						aggro[unit] = val + 10
-					end
-				end
-
-				-- Aggro decay (thanks BanzaiLib)
-				if aggro[unit] >= 5 then
-					aggro[unit] = aggro[unit] - 5
-				end
-
-				if aggro[unit] >= 15 then
-					showaggro(unit)
-				end
-
-				local name = UnitName(unit)
-			end
+function PerfectRaid:CreateFrameEditor()
+	local frame = CreateFrame("Frame", "PROptions_Frames")
+	self:AddMenuItem("Frame Editor", 2, PROptions_Frames)

-			elapsed = 0
-		end
+	frame.entries = {}
+
+	local NUM_ENTRIES = 9
+	local selected,Entry_OnClick
+
+	for i=1,NUM_ENTRIES do
+		local button = CreateFrame("CheckButton", nil, frame)
+		button:SetHeight(20)
+		frame.entries[i] = button
+
+		button.idx = i
+		button.desc = button:CreateFontString(nil, "OVERLAY")
+		button.desc:SetFontObject(GameFontNormalSmall)
+		button.desc:SetPoint("LEFT", 0, 0)
+		button.desc:SetText("Description: " .. i)
+		button:SetHighlightTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight")
+		button:SetCheckedTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight")
+		button:SetScript("OnClick", Entry_OnClick)
 	end
+
+	frame.entries[1]:SetPoint("TOPLEFT", 8, -5)
+	frame.entries[1]:SetPoint("TOPRIGHT", -28, -5)

-	local frame = CreateFrame("Frame", "PRUpdateFrame")
-	frame:SetScript("OnUpdate", PerfectRaid.OnUpdate)
-end
+	for i=2,NUM_ENTRIES do
+		frame.entries[i]:SetPoint("TOPLEFT", frame.entries[i-1], "BOTTOMLEFT", 0, -2)
+		frame.entries[i]:SetPoint("TOPRIGHT", frame.entries[i-1], "BOTTOMRIGHT", 0, -2)
+	end

-function showaggro(unit)
-	if true then return end
-	for frame in pairs(frames[unit]) do
-		local name = frame:GetName()
-		local texture = frame.healthbar.aggro
-		if not texture then
-			local bar = frame.healthbar
-			texture = frame.healthbar:CreateTexture(name.."Aggro", "ARTWORK")
-			texture:SetTexture("Interface\\AddOns\\PerfectRaid\\images\\smooth")
-			texture:SetAllPoints(bar)
-			frame.healthbar.aggro = texture
-		end
-		texture:SetVertexColor(1,0,0)
-		UIFrameFlash(texture, 0.4, 0.4, 2, nil, 0.1, 0.1)
+	local OnEnter = function(button)
+		button:SetBackdropBorderColor(1,1,1)
 	end
-end

-local textures = {}
-local handlers = {}
-function flashbar(frame, length, wait)
-	if not textures[frame] then
-		texture = frame:CreateTexture(nil, "ARTWORK")
-		texture:SetTexture("Interface\\AddOns\\PerfectRaid\\images\\smooth")
-		texture:SetPoint("TOPLEFT", 0, 0)
-		texture:SetPoint("BOTTOMLEFT", 0, 0)
-		textures[frame] = texture
+	local OnLeave = function(button)
+		button:SetBackdropBorderColor(0.3, 0.3, 0.3)
 	end
-
-	frame.fadeLength = length or 0.4
-	frame.fadeTime = 0
-	frame.waitLength = wait or 0.1
-	frame.waitTime = 0
-	frame.waitHalf = true
-
-	if not handlers[frame] then
-		local function handler(frame, arg1)
-			frame.fadeTime = frame.fadeTime + arg1
-			local half = frame.fadeLength / 2
-			if frame.fadeTime < half then
-				-- We're fading out
-				local alpha = 1 - (frame.fadeTime / half)
-				frame:SetAlpha(alpha)
-			elseif frame.fadeTime <= frame.fadeLength then
-				if frame.waitHalf then
-					frame.fadeTime = frame.fadeTime - arg1
-					frame.waitTime = frame.waitTime + arg1
-					if frame.waitTime >= frame.waitLength then
-						frame.waitHalf = false
-					end
-				else
-					local alpha = (frame.fadeTime - half) / half
-					frame:SetAlpha(alpha)
-				end
-			else
-				frame.waitTime = frame.waitTime + arg1
-				if frame.waitTime >= frame.waitLength then
-					frame.fadeTime = 0
-					frame.waitTime = 0
-					frame.waitHalf = true
-				end
-			end
+
+	local createButton = function(name)
+		local button = CreateFrame("Button", "PROptions_Frames_"..name, PROptions_Frames)
+		button:SetHeight(30)
+		button:SetWidth(80)
+		button:SetBackdrop(GameTooltip:GetBackdrop())
+		button:SetBackdropColor(0,0,0)
+		button:SetBackdropBorderColor(0.3, 0.3, 0.3)
+		button:SetScript("OnEnter", OnEnter)
+		button:SetScript("OnLeave", OnLeave)
+
+		button.label = button:CreateFontString(nil, "ARTWORK")
+		button.label:SetFontObject(GameFontNormalSmall)
+		button.label:SetPoint("CENTER")
+		button.label:SetText(name)
+		button.enableText = name
+		return button
+	end
+
+	local button_new = createButton("New")
+	button_new:SetPoint("BOTTOMLEFT", 8, 5)
+
+	local button_edit = createButton("Edit")
+	button_edit:SetPoint("LEFT", button_new, "RIGHT", 5, 0)
+
+	local button_delete = createButton("Delete")
+	button_delete:SetPoint("LEFT", button_edit, "RIGHT", 5, 0)
+
+	PROptions_Frames:SetScript("OnShow", function(frame)
+		for idx,entry in ipairs(frame.entries) do
+			entry:SetChecked(nil)
+		end
+		selected = nil
+		button_edit:Disable()
+		button_delete:Disable()
+	end)
+
+	PROptions_Frames:GetScript("OnShow")(PROptions_Frames)
+
+	Entry_OnClick = function(button)
+		if selected then
+			frame.entries[selected]:SetChecked(nil)
 		end
-		handlers[frame] = handler
+		button:SetChecked(true)
+		selected = button.idx
+		button_edit:Enable()
+		button_delete:Enable()
 	end

-	frame:SetScript("OnUpdate", handlers[frame])
-end
+	for idx,button in ipairs(frame.entries) do
+		button:SetScript("OnClick", Entry_OnClick)
+	end

---flashbar(PlayerFrame, 2, 1)
\ No newline at end of file
+	-- Create the scroll frame
+	local scrollframe = CreateFrame("ScrollFrame", "PROptions_Frames_Scroll", PROptions_Frames, "FauxScrollFrameTemplate")
+	scrollframe:SetPoint("TOPLEFT", frame.entries[1], "TOPLEFT", 0, 0)
+	scrollframe:SetPoint("BOTTOMRIGHT", frame.entries[NUM_ENTRIES], "BOTTOMRIGHT", 0, 0)
+
+	local texture = scrollframe:CreateTexture(nil, "BACKGROUND")
+	texture:SetTexture("Interface\\ChatFrame\\ChatFrameBackground")
+	texture:SetPoint("TOPLEFT", scrollframe, "TOPRIGHT", 14, 0)
+	texture:SetPoint("BOTTOMRIGHT", 23, 0)
+	texture:SetVertexColor(0,0,0,0.3)
+
+	local texture = scrollframe:CreateTexture(nil, "BACKGROUND")
+	texture:SetTexture("Interface\\ChatFrame\\ChatFrameBackground")
+	texture:SetPoint("TOPLEFT", scrollframe, "TOPRIGHT", 4, 0)
+	texture:SetPoint("BOTTOMRIGHT", 14,0)
+	texture:SetVertexColor(0,0,0,0.3)
+end
+
+PerfectRaid:CreateOptions()
diff --git a/PerfectRaid.toc b/PerfectRaid.toc
index 1ba7880..27b7e58 100644
--- a/PerfectRaid.toc
+++ b/PerfectRaid.toc
@@ -4,10 +4,9 @@
 ## Notes: Simply powerful raid and party frames
 ## SavedVariables: PerfectRaidDB
 ## OptionalDeps: Dongle
-
 Dongle.lua
 DongleUtils.lua
 PerfectRaid.xml
 PerfectRaid.lua
-PerfectRaidOptions.lua
-Localization.en.lua
+
+
diff --git a/PerfectRaid_Aggro.lua b/PerfectRaid_Aggro.lua
new file mode 100644
index 0000000..41794d1
--- /dev/null
+++ b/PerfectRaid_Aggro.lua
@@ -0,0 +1,172 @@
+--[[-------------------------------------------------------------------------
+  Copyright (c) 2006, Jim Whitehead II <cladhaire@gmail.com>
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions are
+  met:
+
+      * Redistributions of source code must retain the above copyright
+        notice, this list of conditions and the following disclaimer.
+      * Redistributions in binary form must reproduce the above
+        copyright notice, this list of conditions and the following
+        disclaimer in the documentation and/or other materials provided
+        with the distribution.
+      * Neither the name of PerfectRaid nor the names of its contributors
+        may be used to endorse or promote products derived from this software
+        without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------]]
+
+local class = select(2, UnitClass("player"))
+local spells = {
+	DRUID = "Healing Touch",
+	SHAMAN = "Healing Wave",
+	PRIEST = "Lesser Heal",
+	PALADIN = "Holy Light",
+}
+
+local rangespell = spells[class]
+
+local victims = {}
+local targets = {}
+local flashing = {}
+
+if rangespell then
+	local elapsed = 0
+	function PerfectRaid.OnUpdate(frame, arg1)
+		elapsed = elapsed + arg1
+		if elapsed >= 0.5 then
+			if rangespell then
+				for unit,tbl in pairs(frames) do
+					local range = IsSpellInRange(rangespell, unit) == 1
+					local alpha = range and 1.0 or 0.3
+					for frame in pairs(tbl) do
+						if not flashing[frame] then
+							frame:SetAlpha(alpha)
+						end
+					end
+				end
+			end
+
+			-- Aggro check
+			for unit,tbl in pairs(frames) do
+				if not targets[unit] then
+					targets[unit] = unit.."target"
+					victims[unit] = unit.."targettarget"
+					aggro[unit] = 0
+				end
+
+				local target = targets[unit]
+				local victim = victims[unit]
+				if UnitIsUnit(victim, unit) and UnitCanAttack(unit, target) then
+					-- unit is being targeted by a hostile mob
+					if aggro[unit] < 20 then
+						local val = aggro[unit]
+						if val >= 5 and val <= 10 then
+							PerfectRaid:UNIT_HEALTH(nil, unit)
+						end
+						aggro[unit] = val + 10
+					end
+				end
+
+				-- Aggro decay (thanks BanzaiLib)
+				if aggro[unit] >= 5 then
+					aggro[unit] = aggro[unit] - 5
+				end
+
+				if aggro[unit] >= 15 then
+					showaggro(unit)
+				end
+
+				local name = UnitName(unit)
+			end
+
+			elapsed = 0
+		end
+	end
+
+	local frame = CreateFrame("Frame", "PRUpdateFrame")
+	frame:SetScript("OnUpdate", PerfectRaid.OnUpdate)
+end
+
+function showaggro(unit)
+	if true then return end
+	for frame in pairs(frames[unit]) do
+		local name = frame:GetName()
+		local texture = frame.healthbar.aggro
+		if not texture then
+			local bar = frame.healthbar
+			texture = frame.healthbar:CreateTexture(name.."Aggro", "ARTWORK")
+			texture:SetTexture("Interface\\AddOns\\PerfectRaid\\images\\smooth")
+			texture:SetAllPoints(bar)
+			frame.healthbar.aggro = texture
+		end
+		texture:SetVertexColor(1,0,0)
+		UIFrameFlash(texture, 0.4, 0.4, 2, nil, 0.1, 0.1)
+	end
+end
+
+local textures = {}
+local handlers = {}
+function flashbar(frame, length, wait)
+	if not textures[frame] then
+		texture = frame:CreateTexture(nil, "ARTWORK")
+		texture:SetTexture("Interface\\AddOns\\PerfectRaid\\images\\smooth")
+		texture:SetPoint("TOPLEFT", 0, 0)
+		texture:SetPoint("BOTTOMLEFT", 0, 0)
+		textures[frame] = texture
+	end
+
+	frame.fadeLength = length or 0.4
+	frame.fadeTime = 0
+	frame.waitLength = wait or 0.1
+	frame.waitTime = 0
+	frame.waitHalf = true
+
+	if not handlers[frame] then
+		local function handler(frame, arg1)
+			frame.fadeTime = frame.fadeTime + arg1
+			local half = frame.fadeLength / 2
+			if frame.fadeTime < half then
+				-- We're fading out
+				local alpha = 1 - (frame.fadeTime / half)
+				frame:SetAlpha(alpha)
+			elseif frame.fadeTime <= frame.fadeLength then
+				if frame.waitHalf then
+					frame.fadeTime = frame.fadeTime - arg1
+					frame.waitTime = frame.waitTime + arg1
+					if frame.waitTime >= frame.waitLength then
+						frame.waitHalf = false
+					end
+				else
+					local alpha = (frame.fadeTime - half) / half
+					frame:SetAlpha(alpha)
+				end
+			else
+				frame.waitTime = frame.waitTime + arg1
+				if frame.waitTime >= frame.waitLength then
+					frame.fadeTime = 0
+					frame.waitTime = 0
+					frame.waitHalf = true
+				end
+			end
+		end
+		handlers[frame] = handler
+	end
+
+	frame:SetScript("OnUpdate", handlers[frame])
+end
+
+--flashbar(PlayerFrame, 2, 1)
\ No newline at end of file
diff --git a/PerfectRaid_Buffs.lua b/PerfectRaid_Buffs.lua
new file mode 100644
index 0000000..24112f3
--- /dev/null
+++ b/PerfectRaid_Buffs.lua
@@ -0,0 +1,84 @@
+--[[-------------------------------------------------------------------------
+  Copyright (c) 2006, Jim Whitehead II <cladhaire@gmail.com>
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions are
+  met:
+
+      * Redistributions of source code must retain the above copyright
+        notice, this list of conditions and the following disclaimer.
+      * Redistributions in binary form must reproduce the above
+        copyright notice, this list of conditions and the following
+        disclaimer in the documentation and/or other materials provided
+        with the distribution.
+      * Neither the name of PerfectRaid nor the names of its contributors
+        may be used to endorse or promote products derived from this software
+        without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------]]
+
+local buffcache = {}
+local work = {}
+function PerfectRaid:UNIT_AURA(event, unit)
+	if not frames[unit] then return end
+	for k,v in pairs(buffcache) do buffcache[k] = nil end
+
+	for i=1,40 do
+		local name,rank,texture,count = UnitBuff(unit, i)
+		if not name then break end
+		buffcache[name] = (buffcache[name] or 0) + 1
+	end
+
+	for i=1,40 do
+		local name,rank,texture,count = UnitDebuff(unit, i)
+		if not name then break end
+		buffcache[name] = (buffcache[name] or 0) + 1
+	end
+
+	for k,v in pairs(work) do work[k] = nil end
+
+	local buffs = self.db.profile.buffs
+	for i,entry in ipairs(buffs) do
+		local checkcond = false
+		local num = buffcache[entry.buffname]
+		if entry.missing then
+			if not buffcache[entry.buffname] and not buffcache[entry.groupbuff or "nil"] then
+				checkcond = true
+			end
+		else
+			if buffcache[entry.buffname] or buffcache[entry.groupbuff or "nil"] then
+				checkcond = true
+			end
+		end
+
+		local conds = self.conditions
+		if checkcond then
+			for i,name in pairs(entry.cond) do
+				if conds[name] and conds[name](unit) then
+					if num and num > 1 then
+						table.insert(work, entry.colortext .. "(" .. num .. ")")
+					else
+						table.insert(work, entry.colortext)
+					end
+				end
+			end
+		end
+	end
+
+	local status = strjoin(" ", unpack(work))
+	for frame in pairs(frames[unit]) do
+		frame.aura:SetText(status)
+	end
+end
diff --git a/PerfectRaid_Range.lua b/PerfectRaid_Range.lua
new file mode 100644
index 0000000..41794d1
--- /dev/null
+++ b/PerfectRaid_Range.lua
@@ -0,0 +1,172 @@
+--[[-------------------------------------------------------------------------
+  Copyright (c) 2006, Jim Whitehead II <cladhaire@gmail.com>
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions are
+  met:
+
+      * Redistributions of source code must retain the above copyright
+        notice, this list of conditions and the following disclaimer.
+      * Redistributions in binary form must reproduce the above
+        copyright notice, this list of conditions and the following
+        disclaimer in the documentation and/or other materials provided
+        with the distribution.
+      * Neither the name of PerfectRaid nor the names of its contributors
+        may be used to endorse or promote products derived from this software
+        without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------]]
+
+local class = select(2, UnitClass("player"))
+local spells = {
+	DRUID = "Healing Touch",
+	SHAMAN = "Healing Wave",
+	PRIEST = "Lesser Heal",
+	PALADIN = "Holy Light",
+}
+
+local rangespell = spells[class]
+
+local victims = {}
+local targets = {}
+local flashing = {}
+
+if rangespell then
+	local elapsed = 0
+	function PerfectRaid.OnUpdate(frame, arg1)
+		elapsed = elapsed + arg1
+		if elapsed >= 0.5 then
+			if rangespell then
+				for unit,tbl in pairs(frames) do
+					local range = IsSpellInRange(rangespell, unit) == 1
+					local alpha = range and 1.0 or 0.3
+					for frame in pairs(tbl) do
+						if not flashing[frame] then
+							frame:SetAlpha(alpha)
+						end
+					end
+				end
+			end
+
+			-- Aggro check
+			for unit,tbl in pairs(frames) do
+				if not targets[unit] then
+					targets[unit] = unit.."target"
+					victims[unit] = unit.."targettarget"
+					aggro[unit] = 0
+				end
+
+				local target = targets[unit]
+				local victim = victims[unit]
+				if UnitIsUnit(victim, unit) and UnitCanAttack(unit, target) then
+					-- unit is being targeted by a hostile mob
+					if aggro[unit] < 20 then
+						local val = aggro[unit]
+						if val >= 5 and val <= 10 then
+							PerfectRaid:UNIT_HEALTH(nil, unit)
+						end
+						aggro[unit] = val + 10
+					end
+				end
+
+				-- Aggro decay (thanks BanzaiLib)
+				if aggro[unit] >= 5 then
+					aggro[unit] = aggro[unit] - 5
+				end
+
+				if aggro[unit] >= 15 then
+					showaggro(unit)
+				end
+
+				local name = UnitName(unit)
+			end
+
+			elapsed = 0
+		end
+	end
+
+	local frame = CreateFrame("Frame", "PRUpdateFrame")
+	frame:SetScript("OnUpdate", PerfectRaid.OnUpdate)
+end
+
+function showaggro(unit)
+	if true then return end
+	for frame in pairs(frames[unit]) do
+		local name = frame:GetName()
+		local texture = frame.healthbar.aggro
+		if not texture then
+			local bar = frame.healthbar
+			texture = frame.healthbar:CreateTexture(name.."Aggro", "ARTWORK")
+			texture:SetTexture("Interface\\AddOns\\PerfectRaid\\images\\smooth")
+			texture:SetAllPoints(bar)
+			frame.healthbar.aggro = texture
+		end
+		texture:SetVertexColor(1,0,0)
+		UIFrameFlash(texture, 0.4, 0.4, 2, nil, 0.1, 0.1)
+	end
+end
+
+local textures = {}
+local handlers = {}
+function flashbar(frame, length, wait)
+	if not textures[frame] then
+		texture = frame:CreateTexture(nil, "ARTWORK")
+		texture:SetTexture("Interface\\AddOns\\PerfectRaid\\images\\smooth")
+		texture:SetPoint("TOPLEFT", 0, 0)
+		texture:SetPoint("BOTTOMLEFT", 0, 0)
+		textures[frame] = texture
+	end
+
+	frame.fadeLength = length or 0.4
+	frame.fadeTime = 0
+	frame.waitLength = wait or 0.1
+	frame.waitTime = 0
+	frame.waitHalf = true
+
+	if not handlers[frame] then
+		local function handler(frame, arg1)
+			frame.fadeTime = frame.fadeTime + arg1
+			local half = frame.fadeLength / 2
+			if frame.fadeTime < half then
+				-- We're fading out
+				local alpha = 1 - (frame.fadeTime / half)
+				frame:SetAlpha(alpha)
+			elseif frame.fadeTime <= frame.fadeLength then
+				if frame.waitHalf then
+					frame.fadeTime = frame.fadeTime - arg1
+					frame.waitTime = frame.waitTime + arg1
+					if frame.waitTime >= frame.waitLength then
+						frame.waitHalf = false
+					end
+				else
+					local alpha = (frame.fadeTime - half) / half
+					frame:SetAlpha(alpha)
+				end
+			else
+				frame.waitTime = frame.waitTime + arg1
+				if frame.waitTime >= frame.waitLength then
+					frame.fadeTime = 0
+					frame.waitTime = 0
+					frame.waitHalf = true
+				end
+			end
+		end
+		handlers[frame] = handler
+	end
+
+	frame:SetScript("OnUpdate", handlers[frame])
+end
+
+--flashbar(PlayerFrame, 2, 1)
\ No newline at end of file