-- Locally bound frame cache local frameCache = CT_RA_Cache; -- CT_RA_CustomOnClickFunction -- Set this variable (CT_RA_CustomOnClickFunction) in your own mod to your function to handle OnClicks. -- Two arguments are passed, button and raidid. -- Button is a string that refers to the mouse button pressed, "LeftButton" or "RightButton". -- Raidid is a string with the unit id, such as "raid1". -- Example: function MyFunction(button, raidid) doStuff(); end -- CT_RA_CustomOnClickFunction = MyFunction; -- Note! If the function returns true, the default CTRA behaviour will not be called. -- If it returns false or nil, the default behaviour will be called. -- Variables CHAT_MSG_CTRAID = "CTRaid"; CT_RA_Squelch = 0; CT_RA_Comm_MessageQueue = { }; CT_RA_Level = 0; CT_RA_Stats = { { { } } }; CT_RA_PTargets = { }; CT_RA_BuffsToCure = { }; CT_RA_BuffsToRecast = { }; CT_RA_RaidParticipant = nil; -- Used to see what player participated in the raid on this account CT_RA_Auras = { ["buffs"] = { }, ["debuffs"] = { } }; CT_RA_LastSend = nil; CT_RA_ClassPositions = { [CT_RA_WARRIOR] = 1, [CT_RA_DRUID] = 2, [CT_RA_MAGE] = 3, [CT_RA_WARLOCK] = 4, [CT_RA_ROGUE] = 5, [CT_RA_HUNTER] = 6, [CT_RA_PRIEST] = 7, [CT_RA_PALADIN] = 8, [CT_RA_SHAMAN] = 8 }; CT_RA_Emergency_RaidHealth = { }; CT_RA_Emergency_Units = { }; CT_RA_LastSent = { }; CT_RA_BuffTimeLeft = { }; CT_RA_ResFrame_Options = { }; CT_RA_CurrPlayerName = ""; CT_RA_NumRaidMembers = 0; ChatTypeGroup["CTRAID"] = { "CHAT_MSG_CTRAID" }; ChatTypeInfo["CTRAID"] = { sticky = 0 }; tinsert(OtherMenuChatTypeGroups, "CTRAID"); CHAT_CTRAID_GET = ""; CT_RA_ChatInfo = { ["Default"] = { ["r"] = 1.0, ["g"] = 0.5, ["b"] = 0, ["show"] = { "ChatFrame1" } } }; CT_oldFCF_Tab_OnClick = FCF_Tab_OnClick; function CT_newFCF_Tab_OnClick(button) CT_oldFCF_Tab_OnClick(button); if ( button == "RightButton" ) then local frameName = "ChatFrame" .. this:GetID(); local frame = getglobal(frameName); local info = CT_RA_ChatInfo["Default"]; if ( CT_RA_ChatInfo[UnitName("player")] ) then info = CT_RA_ChatInfo[UnitName("player")]; end for k, v in info["show"] do if ( v == frameName ) then local y = 1; while ( frame.messageTypeList[y] ) do y = y + 1; end frame.messageTypeList[y] = "CTRAID"; end end end end FCF_Tab_OnClick = CT_newFCF_Tab_OnClick; CT_oldFCF_SetChatTypeColor = FCF_SetChatTypeColor; function CT_newFCF_SetChatTypeColor() CT_oldFCF_SetChatTypeColor(); if ( UIDROPDOWNMENU_MENU_VALUE == "CTRAID" ) then local r,g,b = ColorPickerFrame:GetColorRGB(); local chatInfo = CT_RA_ChatInfo[UnitName("player")]; local chatTypeInfo = ChatTypeInfo["CTRAID"]; if ( not chatInfo ) then CT_RA_ChatInfo[UnitName("player")] = CT_RA_ChatInfo["Default"]; end chatInfo.r = r; chatInfo.g = g; chatInfo.b = b; chatTypeInfo.r = r; chatTypeInfo.g = g; chatTypeInfo.b = b; end end FCF_SetChatTypeColor = CT_newFCF_SetChatTypeColor; CT_oldFCF_CancelFontColorSettings = FCF_CancelFontColorSettings; function CT_newFCF_CancelFontColorSettings(prev) CT_oldFCF_CancelFontColorSettings(prev); if ( prev.r and UIDROPDOWNMENU_MENU_VALUE == "CTRAID" ) then local chatInfo = CT_RA_ChatInfo[UnitName("player")]; local chatTypeInfo = ChatTypeInfo["CTRAID"]; if ( not chatInfo ) then CT_RA_ChatInfo[UnitName("player")] = CT_RA_ChatInfo["Default"]; end chatInfo.r = prev.r; chatInfo.g = prev.g; chatInfo.b = prev.b; chatTypeInfo.r = prev.r; chatTypeInfo.g = prev.g; chatTypeInfo.b = prev.b; end end FCF_CancelFontColorSettings = CT_newFCF_CancelFontColorSettings; CT_oldFCFMessageTypeDropDown_OnClick = FCFMessageTypeDropDown_OnClick; function CT_newFCFMessageTypeDropDown_OnClick() CT_oldFCFMessageTypeDropDown_OnClick(); if ( not CT_RA_ChatInfo[UnitName("player")] ) then CT_RA_ChatInfo[UnitName("player")] = CT_RA_ChatInfo["Default"]; end if ( this.value == "CTRAID" ) then local chatInfo = CT_RA_ChatInfo[UnitName("player")]; local chatTypeInfo = ChatTypeInfo["CTRAID"]; local currChatFrame = FCF_GetCurrentChatFrame():GetName(); if ( UIDropDownMenuButton_GetChecked() ) then for k, v in chatInfo["show"] do if ( v == currChatFrame ) then chatInfo["show"][k] = nil; break; end end else tinsert(chatInfo["show"], currChatFrame); end end end FCFMessageTypeDropDown_OnClick = CT_newFCFMessageTypeDropDown_OnClick; function CT_RA_ShowHideWindows() local tempOptions = CT_RAMenu_Options["temp"]; if ( tempOptions["HiddenGroups"] ) then tempOptions["ShowGroups"] = tempOptions["HiddenGroups"]; tempOptions["HiddenGroups"] = nil; local num = 0; for k, v in tempOptions["ShowGroups"] do num = num + 1; getglobal("CT_RAOptionsGroupCB" .. k):SetChecked(1); end if ( num > 0 ) then CT_RACheckAllGroups:SetChecked(1); else CT_RACheckAllGroups:SetChecked(nil); end else tempOptions["HiddenGroups"] = tempOptions["ShowGroups"]; tempOptions["ShowGroups"] = { }; for i = 1, 8, 1 do getglobal("CT_RAOptionsGroupCB" .. i):SetChecked(nil); end CT_RACheckAllGroups:SetChecked(nil); end CT_RA_UpdateRaidGroup(0); end function CT_RA_SetGroup() local tempOptions = CT_RAMenu_Options["temp"]; tempOptions["ShowGroups"][this.id] = this:GetChecked(); local num = 0; for k, v in tempOptions["ShowGroups"] do num = num + 1; end if ( num > 0 ) then CT_RACheckAllGroups:SetChecked(1); else CT_RACheckAllGroups:SetChecked(nil); end CT_RA_UpdateRaidGroup(0); end function CT_RA_CheckAllGroups() local tempOptions = CT_RAMenu_Options["temp"]; if ( not tempOptions["ShowGroups"] ) then tempOptions["ShowGroups"] = { }; end for i = 1, 8, 1 do tempOptions["ShowGroups"][i] = this:GetChecked(); getglobal("CT_RAOptionsGroupCB" .. i):SetChecked(this:GetChecked()); end CT_RA_UpdateRaidGroup(0); end function CT_RA_ParseEvent(event) local nick, sMsg, msg; if ( event == "CHAT_MSG_ADDON" ) then nick, sMsg = arg4, arg2; else nick, sMsg = arg2, arg1; end local numRaidMembers = GetNumRaidMembers(); local name, rank, subgroup, level, class, fileName, zone, online, isDead, raidid, frame; for i = 1, numRaidMembers, 1 do if ( UnitName("raid" .. i) == nick ) then raidid = i; name, rank, subgroup, level, class, fileName, zone, online, isDead = GetRaidRosterInfo(i); frame = getglobal("CT_RAMember"..i); break; end end local playerName = UnitName("player"); local unitStats = CT_RA_Stats[nick]; local ctraChannel = CT_RA_Channel; if ( name and not unitStats ) then CT_RA_Stats[nick] = { ["Buffs"] = { }, ["Debuffs"] = { }, ["Position"] = { } }; unitStats = CT_RA_Stats[nick]; end if ( ( event == "CHAT_MSG_RAID" or event == "CHAT_MSG_RAID_LEADER" ) and type(sMsg) == "string" ) then if ( frame ) then -- We have a valid frame msg = gsub(sMsg, "%%", "%%%%"); if ( stats and raidid ) then if ( arg6 and not unitStats[arg6] and ( arg6 == "AFK" or arg6 == "DND" ) ) then unitStats[arg6] = { 1, 0 }; CT_RA_UpdateUnitDead(frame); elseif ( arg2 == name and ( not arg6 or arg6 == "" ) and ( unitStats["DND"] or unitStats["AFK"] ) ) then unitStats["DND"] = nil; unitStats["AFK"] = nil; CT_RA_UpdateUnitDead(frame); end end if ( rank and rank < 1 and CT_RA_Squelch and CT_RA_Squelch > 0 ) then if ( CT_RA_Level >= 1 and CT_RA_IsSendingWithVersion(1.468) ) then SendChatMessage(" Quiet mode is enabled in the raid. Please be quiet. " .. floor(CT_RA_Squelch) .. " seconds remaining.", "WHISPER", nil, name); end return; end if ( rank and rank >= 1 and string.find(sMsg, " Disbanding raid on request by (.+)") ) then LeaveParty(); return; end if ( rank >= 1 ) then if ( name ~= playerName and sMsg == " Quiet mode is over." ) then if ( CT_RA_Squelch > 0 ) then CT_RA_Squelch = 0; CT_RA_Print(" Quiet mode has been disabled by " .. name .. ".", 1, 0.5, 0); end elseif ( name ~= playerName and sMsg == " Quiet mode, no talking." ) then if ( CT_RA_Squelch == 0 ) then CT_RA_Squelch = 5*60; CT_RA_Print(" Quiet Mode has been enabled by " .. name .. ".", 1, 0.5, 0); end end return; end end elseif ( event == "CHAT_MSG_WHISPER" and type(sMsg) == "string" ) then local tempOptions = CT_RAMenu_Options["temp"]; if ( tempOptions["KeyWord"] and strlower(sMsg) == strlower(tempOptions["KeyWord"]) ) then local temp = arg2; if ( numRaidMembers == 40 or ( GetNumPartyMembers() == 4 and numRaidMembers == 0 ) ) then CT_RA_Print(" Player '|c00FFFFFF" .. temp .. "|r' requested invite, group is currently full.", 1, 0.5, 0); SendChatMessage(" The group is currently full.", "WHISPER", nil, temp); else CT_RA_Print(" Invited '|c00FFFFFF" .. temp .. "|r' by Keyword Inviting.", 1, 0.5, 0); InviteByName(temp); CT_RA_UpdateFrame.lastInvite = 1; CT_RA_UpdateFrame.inviteName = temp; end else local _, _, secRem = string.find(sMsg, " Quiet mode is enabled in the raid%. Please be quiet%. (%d+) seconds remaining%."); if ( secRem and CT_RA_Squelch == 0 ) then if ( rank >= 1 ) then CT_RA_Squelch = tonumber(secRem); CT_RA_Print(" Quiet Mode has been enabled for " .. secRem .. " seconds by " .. name .. ".", 1, 0.5, 0); end end end elseif ( event == "CHAT_MSG_WHISPER_INFORM" ) then if ( arg1 == " You are already grouped." ) then CT_RA_Print(" Informed '|c00FFFFFF" .. arg2 .. "|r' that he or she is already grouped.", 1, 0.5, 0); end elseif ( event == "CHAT_MSG_COMBAT_FRIENDLY_DEATH" ) then if ( not CT_RAMenu_Options["temp"]["HideTankNotifications"] ) then local _, _, name = string.find(sMsg, CT_RA_TANKHASDIEDREGEXP); if ( name ) then for k, v in CT_RA_MainTanks do if ( v == name ) then CT_RA_WarningFrame:AddMessage("TANK " .. name .. " HAS DIED!", 1, 0, 0, 1, UIERRORS_HOLD_TIME); PlaySoundFile("Sound\\interface\\igQuestFailed.wav"); break; end end end end elseif ( strsub(event, 1, 15) == "CHAT_MSG_SYSTEM" and type(sMsg) == "string" ) then local useless, useless, plr = string.find(sMsg, CT_RA_HASLEFTRAIDREGEXP); if ( CT_RA_RaidParticipant and plr and plr ~= CT_RA_RaidParticipant ) then CT_RA_CurrPositions[plr] = nil; CT_RA_Stats[plr] = nil; for k, v in CT_RA_MainTanks do if ( v == plr ) then CT_RA_MainTanks[k] = nil; CT_RATarget.MainTanks[k] = nil; break; end end elseif ( string.find(sMsg, CT_RA_HASJOINEDRAIDREGEXP) ) then if ( CT_RA_Level >= 2 ) then local useless, useless, plr = string.find(sMsg, CT_RA_HASJOINEDRAIDREGEXP); if ( plr and CT_RATab_AutoPromotions[plr] ) then PromoteToAssistant(plr); CT_RA_Print(" Auto-Promoted |c00FFFFFF" .. plr .. "|r.", 1, 0.5, 0); end end elseif ( string.find(sMsg, CT_RA_AFKMESSAGE) or sMsg == MARKED_AFK ) then local _, _, msg = string.find(sMsg, CT_RA_AFKMESSAGE); if ( msg and msg ~= DEFAULT_AFK_MESSAGE ) then if ( strlen(msg) > 20 ) then msg = strsub(msg, 1, 20) .. "..."; end CT_RA_AddMessage("AFK " .. msg); else CT_RA_AddMessage("AFK"); end elseif ( string.find(sMsg, CT_RA_DNDMESSAGE) ) then local _, _, msg = string.find(sMsg, CT_RA_DNDMESSAGE); if ( msg and msg ~= DEFAULT_DND_MESSAGE ) then if ( strlen(msg) > 20 ) then msg = strsub(msg, 1, 20) .. "..."; end CT_RA_AddMessage("DND " .. msg); else CT_RA_AddMessage("DND"); end elseif ( sMsg == CLEARED_AFK ) then CT_RA_AddMessage("UNAFK"); elseif ( sMsg == CLEARED_DND ) then CT_RA_AddMessage("UNDND"); end elseif ( event == "CHAT_MSG_ADDON" and arg1 == "CTRA" and arg3 == "RAID" ) then if ( frame ) then -- Unit is in raid local eventtype = strsub(event, 10); local info = ChatTypeInfo[eventtype]; event = "CHAT_MSG_CTRAID"; if ( arg6 and not unitStats[arg6] and ( arg6 == "AFK" or arg6 == "DND" ) ) then unitStats[arg6] = { 1, 0 }; CT_RA_UpdateUnitDead(frame); elseif ( ( not arg6 or arg6 == "" ) and ( unitStats["DND"] or unitStats["AFK"] ) ) then unitStats["DND"] = nil; unitStats["AFK"] = nil; CT_RA_UpdateUnitDead(frame); end if ( not sMsg ) then return; end local msg = string.gsub(sMsg, "%$", "s"); msg = string.gsub(msg, "§", "S"); if ( strsub(msg, strlen(msg)-7) == " ...hic!") then msg = strsub(msg, 1, strlen(msg)-8); end local tempUpdate, message; if ( string.find(msg, "#") ) then local arr = CT_RA_Split(msg, "#"); for k, v in arr do tempUpdate, message = CT_RA_ParseMessage(name, v); if ( message ) then CT_RA_Print(message, 1, 0.5, 0); end if ( tempUpdate ) then for k, v in tempUpdate do tinsert(update, v); end end end else tempUpdate, message = CT_RA_ParseMessage(name, msg); if ( message ) then CT_RA_Print(message, 1, 0.5, 0); end if ( tempUpdate ) then for k, v in tempUpdate do tinsert(update, v); end end end if ( type(update) == "table" ) then for k, v in update do if ( type(v) == "number" ) then CT_RA_UpdateUnitStatus(getglobal("CT_RAMember" .. v)); else for i = 1, GetNumRaidMembers(), 1 do local uName = UnitName("raid" .. i); if ( uName and uName == v ) then CT_RA_UpdateUnitStatus(getglobal("CT_RAMember" .. i)); break; end end end end end end elseif ( event == "CHAT_MSG_PARTY" ) then if ( frame ) then if ( arg6 and not unitStats[arg6] and ( arg6 == "AFK" or arg6 == "DND" ) ) then unitStats[arg6] = { 1, 0 }; CT_RA_UpdateUnitDead(frame); elseif ( ( not arg6 or arg6 == "" ) and ( unitStats["DND"] or unitStats["AFK"] ) ) then unitStats["DND"] = nil; unitStats["AFK"] = nil; CT_RA_UpdateUnitDead(frame); end end end end CT_RA_oldChatFrame_OnEvent = ChatFrame_OnEvent; function CT_RA_newChatFrame_OnEvent(event) if ( strsub(event, 1, 13) == "CHAT_MSG_RAID" ) then local tempOptions = CT_RAMenu_Options["temp"]; local name, rank; for i = 1, GetNumRaidMembers(), 1 do name, rank = GetRaidRosterInfo(i); if ( name == arg2 ) then if ( rank and rank < 1 and CT_RA_Squelch > 0 ) then return; end break; end end if ( not rank ) then rank = 0; end if ( rank >= 1 and ( arg1 == " Quiet mode, no talking." or arg1 == " Quiet mode is over." ) ) then return; end local useless, useless, chan = string.find(gsub(arg1, "%%", "%%%%"), "^ This is an automatic message sent by CT_RaidAssist. Channel changed to: (.+)$"); if ( chan ) then return; end if ( rank == 2 and ( not tempOptions["leaderColor"] or tempOptions["leaderColor"].enabled ) ) then CT_RA_oldAddMessage = this.AddMessage; this.AddMessage = CT_RA_newAddMessage; CT_RA_oldChatFrame_OnEvent(event); this.AddMessage = CT_RA_oldAddMessage; return; end elseif ( event == "CHAT_MSG_WHISPER" ) then local tempOptions = CT_RAMenu_Options["temp"]; if ( ( tempOptions["KeyWord"] and strlower(arg1) == strlower(tempOptions["KeyWord"]) ) or arg1 == " Quiet mode is enabled in the raid. Please be quiet." ) then return; end elseif ( strsub(event, 1, 16) == "CHAT_MSG_CHANNEL" and CT_RA_Channel and arg9 and strlower(arg9) == strlower(CT_RA_Channel) ) then local type = strsub(event, 10); if ( type ~= "CHANNEL_LIST" and type ~= "SYSTEM" ) then return; end end CT_RA_oldChatFrame_OnEvent(event); end ChatFrame_OnEvent = CT_RA_newChatFrame_OnEvent; function CT_RA_newAddMessage(obj, msg, r, g, b) local tempOptions = CT_RAMenu_Options["temp"]; local newR, newG, newB = 1, 1, 0; if ( tempOptions["leaderColor"] ) then newR, newG, newB = tempOptions["leaderColor"].r, tempOptions["leaderColor"].g, tempOptions["leaderColor"].b; end return CT_RA_oldAddMessage(obj, string.gsub(msg, "(|Hplayer:.-|h%[)([%w]+)(%])", "%1|c00" .. CT_RA_RGBToHex(newR, newG, newB) .. "%2|r%3"), r, g, b); end function CT_RA_ParseMessage(nick, msg) local tempOptions = CT_RAMenu_Options["temp"]; local useless, val1, val2, val3, val4, frame, raidid, rank, update; local numRaidMembers = GetNumRaidMembers(); local playerName = UnitName("player"); for i = 1, numRaidMembers, 1 do if ( UnitName("raid" .. i) == nick ) then raidid = i; useless, rank = GetRaidRosterInfo(i); frame = getglobal("CT_RAMember"..i); break; end end if ( not raidid or not frame ) then return; end local unitStats = CT_RA_Stats[nick]; if ( not unitStats ) then if ( not update ) then update = { }; end CT_RA_Stats[nick] = { ["Buffs"] = { }, ["Debuffs"] = { }, ["Position"] = { } }; unitStats = CT_RA_Stats[nick]; tinsert(update, raidid); end unitStats["Reporting"] = 1; -- Check buff renewal useless, useless, val1, val2, val3 = string.find(msg, "^RN ([^%s]+) ([^%s]+) ([^%s]+)$"); -- timeleft(1), id(2), num(3) if ( tonumber(val1) and tonumber(val2) and tonumber(val3) ) then -- Buffs local buff; for k, v in tempOptions["BuffArray"] do if ( tonumber(val2) == v["index"] ) then buff = v; break; end end if ( not buff and tonumber(val2) == -1 ) then buff = { ["show"] = 1, ["name"] = CT_RA_FEIGNDEATH[CT_RA_GetLocale()] }; elseif ( not buff ) then return update; end local name = buff["name"]; if ( type(name) == "table" ) then if ( tonumber(val3) ) then name = name[tonumber(val3)]; else return update; end end local text = CT_RA_BuffTextures[name]; if ( not name or not text ) then return update; end unitStats["Buffs"][name] = { text[1], tonumber(val1) }; return update; end -- Check status requests if ( msg == "SR" ) then if ( unitStats ) then unitStats["Buffs"] = { }; unitStats["Debuffs"] = { }; table.setn(unitStats["Buffs"], 0); table.setn(unitStats["Debuffs"], 0); end CT_RA_ScanPartyAuras("raid" .. raidid); CT_RA_UpdateFrame.scheduleUpdate = 8; CT_RA_UpdateFrame.scheduleMTUpdate = 8; return update; end if ( strsub(msg, 1, 2) == "S " ) then for str in string.gfind(msg, " B [^%s]+ [^%s]+ [^#]+ #") do useless, useless, val1, val3, val2 = string.find(str, "B ([^%s]+) ([^%s]+) (.+) #"); if ( val1 and val2 and val3 ) then unitStats["Buffs"][val2] = { val1, tonumber(val3) }; CT_RA_UpdateUnitBuffs(unitStats["Buffs"], frame, nick); end end return update; end if ( strsub(msg, 1, 3) == "MS " ) then if ( rank >= 1 ) then if ( tempOptions["PlayRSSound"] ) then PlaySoundFile("Sound\\Doodad\\BellTollNightElf.wav"); end CT_RAMessageFrame:AddMessage(nick .. ": " .. strsub(msg, 3), tempOptions["DefaultAlertColor"].r, tempOptions["DefaultAlertColor"].g, tempOptions["DefaultAlertColor"].b, 1.0, UIERRORS_HOLD_TIME); end return update; end useless, useless, val1 = string.find(msg, "^V ([%d%.]+)$"); if ( tonumber(val1) ) then unitStats["Version"] = tonumber(val1); return update; end if ( strsub(msg, 1, 4) == "SET " ) then local useless, useless, num, name = string.find(msg, "^SET (%d+) (.+)$"); if ( num and name ) then if ( rank >= 1 ) then for k, v in CT_RA_MainTanks do if ( v == name ) then CT_RA_MainTanks[k] = nil; CT_RATarget.MainTanks[k] = nil; end end local mtID = 0; for i = 1, numRaidMembers, 1 do if ( UnitName("raid" .. i) == name ) then mtID = i; break; end end CT_RA_MainTanks[tonumber(num)] = name; CT_RATarget.MainTanks[tonumber(num)] = { mtID, name }; CT_RATarget_UpdateInfoBox(); CT_RATarget_UpdateStats(); CT_RAOptions_Update(); CT_RA_UpdateMTs(); end end return update; end if ( strsub(msg, 1, 2) == "R " ) then local useless, useless, name = string.find(msg, "^R (.+)$"); if ( name ) then for k, v in CT_RA_MainTanks do if ( v == name ) then for i = 1, GetNumRaidMembers(), 1 do local user, rank, subgroup, level, class, fileName, zone, online, isDead = GetRaidRosterInfo(i); if ( rank >= 1 and user == nick ) then CT_RA_MainTanks[k] = nil; CT_RATarget.MainTanks[k] = nil; CT_RA_UpdateMTs(); CT_RAOptions_Update(); return update; end end end end end return update; end if ( msg == "DB" ) then if ( rank >= 1 ) then CT_RA_Print(" Disbanding raid on request by '|c00FFFFFF" .. nick .. "|r'.", 1, 0.5, 0); LeaveParty(); end return update; end if ( msg == "RESSED" ) then unitStats["Ressed"] = 1; CT_RA_UpdateUnitDead(frame); return update; end if ( msg == "NORESSED" ) then unitStats["Ressed"] = nil; CT_RA_UpdateUnitDead(frame); return update; end if ( msg == "CANRES" ) then unitStats["Ressed"] = 2; CT_RA_UpdateUnitDead(frame); return update; end if ( strsub(msg, 1, 3) == "RES" ) then if ( msg == "RESNO" ) then CT_RA_Ressers[nick] = nil; else local _, _, player = string.find(msg, "^RES (.+)$"); if ( player ) then CT_RA_Ressers[nick] = player; end end CT_RA_UpdateResFrame(); return update; end -- Check ready if ( msg == "CHECKREADY" ) then if ( rank >= 1 ) then CT_RA_CheckReady_Person = nick; if ( nick ~= playerName ) then PlaySoundFile("Sound\\interface\\levelup2.wav"); CT_RA_ReadyFrame:Show(); end end return update; elseif ( ( msg == "READY" or msg == "NOTREADY" ) and CT_RA_CheckReady_Person == playerName ) then if ( msg == "READY" ) then unitStats["notready"] = nil; else unitStats["notready"] = 2; end local all_ready = true; local nobody_ready = true; for k, v in CT_RA_Stats do if ( v["notready"] ) then all_ready = false; if ( v["notready"] == 1 ) then nobody_ready = false; end end end if ( all_ready ) then CT_RA_Print(" Everybody is ready.", 1, 1, 0); elseif ( not all_ready and nobody_ready ) then CT_RA_UpdateFrame.readyTimer = 0.1; end CT_RA_UpdateUnitDead(frame); return update; end -- Check Rly if ( msg == "CHECKRLY" ) then if ( rank >= 1 ) then CT_RA_CheckRly_Person = nick; if ( nick ~= UnitName("player") ) then PlaySoundFile("Sound\\interface\\levelup2.wav"); CT_RA_RlyFrame:Show(); end end return update; elseif ( ( msg == "YARLY" or msg == "NORLY" ) and CT_RA_CheckRly_Person == playerName ) then if ( msg == "YARLY" ) then unitStats["rly"] = nil; else unitStats["rly"] = 1; end local all_ready = true; local nobody_ready = true; for k, v in CT_RA_Stats do if ( v["rly"] ) then all_ready = false; if ( v["rly"] == 1 ) then nobody_ready = false; end end end if ( all_ready ) then CT_RA_Print(" Ya rly.", 1, 1, 0); elseif ( not all_ready and nobody_ready ) then CT_RA_UpdateFrame.rlyTimer = 0.1; end CT_RA_UpdateUnitDead(frame); return update; end -- Check AFK if ( msg == "AFK" ) then unitStats["AFK"] = { 1, 0 }; CT_RA_UpdateUnitDead(frame); return update; elseif ( msg == "UNAFK" ) then unitStats["AFK"] = nil; CT_RA_UpdateUnitDead(frame); return update; elseif ( msg == "DND" ) then unitStats["DND"] = { 1, 0 }; CT_RA_UpdateUnitDead(frame); return update; elseif ( msg == "UNDND" ) then unitStats["DND"] = nil; CT_RA_UpdateUnitDead(frame); return update; elseif ( strsub(msg, 1, 3) == "AFK" ) then -- With reason unitStats["AFK"] = { strsub(msg, 5), 0 }; CT_RA_UpdateUnitDead(frame); return update; elseif ( strsub(msg, 1, 3) == "DND" ) then -- With reason unitStats["DND"] = { strsub(msg, 5), 0 }; CT_RA_UpdateUnitDead(frame); return update; end -- Check duration if ( msg == "DURC" ) then if ( rank == 0 ) then return; end local currDur, maxDur, brokenItems = CT_RADurability_GetDurability(); CT_RA_AddMessage("DUR " .. currDur .. " " .. maxDur .. " " .. brokenItems .. " " .. nick); return update; elseif ( string.find(msg, "^DUR ") ) then local _, _, currDur, maxDur, brokenItems, callPerson = string.find(msg, "^DUR (%d+) (%d+) (%d+) ([^%s]+)$"); if ( currDur and maxDur and brokenItems and callPerson == playerName ) then currDur, maxDur = tonumber(currDur), tonumber(maxDur); local name, rank, subgroup, level, class, fileName, zone, online, isDead = GetRaidRosterInfo(raidid); CT_RADurability_Add(nick, "|c00FFFFFF" .. floor((currDur/maxDur)*100+0.5) .. "%|r (|c00FFFFFF" .. brokenItems .. " broken items|r)", fileName, floor((currDur/maxDur)*100+0.5)); end return update; end -- Check resists (Thanks Sudo!) if ( msg == "RSTC" ) then if ( rank == 0 ) then return update; end if ( tempOptions["DisableQuery"] ) then CT_RA_AddMessage("RST -1 " .. nick); else local resistStr = ""; for i = 2, 6, 1 do local _, res, _, _ = UnitResistance("player", i); resistStr = resistStr .. " " .. res; end CT_RA_AddMessage("RST" .. resistStr .. " " .. nick); end return update; elseif ( string.find(msg, "^RST ") ) then local name, rank, subgroup, level, class, fileName, zone, online, isDead = GetRaidRosterInfo(raidid); local _, _, plrName = string.find(msg, "^RST %-1 ([^%s]+)$"); if ( plrName and plrName == playerName ) then CT_RADurability_Add(nick, "|c00FFFFFFDisabled Queries|r", fileName, -1, -1, -1, -1, -1); else local _, _, FR, NR, FRR, SR, AR, callPerson = string.find(msg, "^RST (%d+) (%d+) (%d+) (%d+) (%d+) ([^%s]+)$"); if ( FR and callPerson == playerName ) then CT_RADurability_Add(nick, "", fileName, tonumber(FR), tonumber(NR), tonumber(FRR), tonumber(SR), tonumber(AR) ); end end return update; end -- Check reagents if ( msg == "REAC" ) then if ( rank == 0 ) then return update; end local numItems = CT_RAReagents_GetReagents(); if ( numItems and numItems >= 0 ) then CT_RA_AddMessage("REA " .. numItems .. " " .. nick); end return update; elseif ( string.find(msg, "^REA ") ) then local _, _, numItems, callPerson = string.find(msg, "^REA ([^%s]+) ([^%s]+)$"); if ( numItems and callPerson and callPerson == playerName ) then local classes = { [CT_RA_PRIEST] = CT_REG_PRIEST, [CT_RA_MAGE] = CT_REG_MAGE, [CT_RA_DRUID] = CT_REG_DRUID, [CT_RA_WARLOCK] = CT_REG_WARLOCK, [CT_RA_PALADIN] = CT_REG_PALADIN, [CT_RA_SHAMAN] = CT_REG_SHAMAN }; local name, rank, subgroup, level, class, fileName, zone, online, isDead = GetRaidRosterInfo(raidid); if ( numItems ~= "1" ) then CT_RADurability_Add(nick, "|c00FFFFFF" .. numItems .. "|r " .. classes[UnitClass("raid"..raidid)] .. "s", fileName, numItems); else CT_RADurability_Add(nick, "|c00FFFFFF" .. numItems .. "|r " .. classes[UnitClass("raid"..raidid)], fileName, numItems ); end end return update; end -- Check items if ( string.find(msg, "^ITMC ") ) then local _, _, itemName = string.find(msg, "^ITMC (.+)$"); if ( itemName ) then if ( rank == 0 ) then return; end if ( tempOptions["DisableQuery"] ) then CT_RA_AddMessage("ITM " .. -1 .. " " .. itemName .. " " .. nick); else local numItems = CT_RAItem_GetItems(itemName); if ( numItems and numItems > 0 ) then CT_RA_AddMessage("ITM " .. numItems .. " " .. itemName .. " " .. nick); end end end return update; elseif ( string.find(msg, "^ITM ") ) then local _, _, numItems, itemName, callPerson = string.find(msg, "^ITM ([-%d]+) (.+) ([^%s]+)$"); if ( numItems and itemName and callPerson and callPerson == UnitName("player") ) then local name, rank, subgroup, level, class, fileName, zone, online, isDead = GetRaidRosterInfo(raidid); if ( numItems == "-1" ) then CT_RADurability_Add(nick, "|c00FFFFFFDisabled Queries|r", fileName, "0", class); elseif ( numItems ~= "1" ) then CT_RADurability_Add(nick, "|c00FFFFFF" .. numItems .. "|r " .. itemName .. "s", fileName, numItems); else CT_RADurability_Add(nick, "|c00FFFFFF" .. numItems .. "|r " .. itemName, fileName, numItems); end end return update; end -- Check cooldowns if ( string.find(msg, "^CD %d+ %d+$") ) then local _, _, num, cooldown = string.find(msg, "^CD (%d+) (%d+)$"); if ( num == "1" ) then unitStats["Rebirth"] = tonumber(cooldown)*60; elseif ( num == "2" ) then unitStats["Reincarnation"] = tonumber(cooldown)*60; elseif ( num == "3" ) then unitStats["Soulstone"] = tonumber(cooldown)*60; end return update; end -- Assist requests if ( string.find(msg, "^ASSISTME (.+)$") ) then if ( rank >= 1 ) then local _, _, name = string.find(msg, "^ASSISTME (.+)$"); if ( name and name == playerName ) then CT_RATarget.assistPerson = { nick, 20 }; ShowUIPanel(CT_RA_AssistFrame); end end return update; elseif ( string.find(msg, "^STOPASSIST (.+)$") ) then if ( rank >= 1 ) then local _, _, name = string.find(msg, "^STOPASSIST (.+)$"); if ( name and name == playerName ) then HideUIPanel(CT_RA_AssistFrame); end end return update; end -- Vote local _, _, question = string.find(msg, "^VOTE (.+)$"); if ( question ) then if ( rank >= 1 ) then CT_RA_VotePerson = { nick, 0, 0, question }; if ( nick ~= playerName ) then PlaySoundFile("Sound\\interface\\levelup2.wav"); CT_RA_VoteFrame.question = question; CT_RA_VoteFrame:Show(); end end return update; elseif ( ( msg == "VOTEYES" or msg == "VOTENO" ) and CT_RA_VotePerson and CT_RA_VotePerson[1] == playerName ) then if ( msg == "VOTEYES" ) then CT_RA_VotePerson[2] = CT_RA_VotePerson[2] + 1; elseif ( msg == "VOTENO" ) then CT_RA_VotePerson[3] = CT_RA_VotePerson[3] + 1; end return update; end return update; end -- Send messages function CT_RA_AddMessage(msg) tinsert(CT_RA_Comm_MessageQueue, msg); end function CT_RA_SendMessage(msg) if ( GetNumRaidMembers() == 0 ) then return; end -- Mod should be disabled if not in raid SendAddonMessage("CTRA", msg, "RAID"); end function CT_RA_OnEvent(event) if ( event == "PLAYER_LEAVING_WORLD" ) then CT_RAFrame.disableEvents = true; return; elseif ( CT_RAFrame.disableEvents and event ~= "PLAYER_ENTERING_WORLD" ) then return; elseif ( event == "PLAYER_ENTERING_WORLD" or event == "RAID_ROSTER_UPDATE" ) then CT_RAFrame.disableEvents = nil; local numRaidMembers = GetNumRaidMembers(); local playerName = UnitName("player"); local tempOptions = CT_RAMenu_Options["temp"]; if ( event == "RAID_ROSTER_UPDATE" ) then if ( numRaidMembers == 0 ) then CT_RA_MainTanks = { }; CT_RA_PTargets = { }; CT_RATarget.MainTanks = { }; CT_RA_Stats = { }; CT_RA_ButtonIndexes = { }; CT_RA_Emergency_UpdateHealth(); CT_RA_UpdateMTs(); CT_RA_UpdatePTs(); CT_RAMetersFrame:Hide(); elseif ( CT_RA_NumRaidMembers == 0 and numRaidMembers > 0 ) then CT_RA_UpdateFrame.SS = 10; if ( CT_RA_UpdateFrame.time ) then CT_RA_UpdateFrame.time = nil; end if ( not CT_RA_HasJoinedRaid ) then CT_RA_Print(" First raid detected. Thanks for using CT_RaidAssist!", 1, 0.5, 0); end CT_RA_PartyMembers = { }; CT_RA_HasJoinedRaid = 1; if ( CT_RA_Squelch > 0 ) then CT_RA_Print(" Quiet Mode has been automatically disabled (joined raid).", 1, 0.5, 0); CT_RA_Squelch = 0; end end CT_RA_CheckGroups(); end if ( numRaidMembers > 0 ) then if ( tempOptions["StatusMeters"] and tempOptions["StatusMeters"]["Show"] ) then CT_RAMetersFrame:Show(); else CT_RAMetersFrame:Hide(); end if ( tempOptions["ShowMonitor"] ) then CT_RA_ResFrame:Show(); else CT_RA_ResFrame:Hide(); end else CT_RA_ResFrame:Hide(); CT_RAMetersFrame:Hide(); end CT_RAOptions_Update(); if ( CT_RA_NumRaidMembers ~= numRaidMembers ) then for i = 1, numRaidMembers, 1 do local uId = "raid" .. i; local uName = UnitName(uId); if ( uName and CT_RA_Stats[uName] ) then table.setn(CT_RA_Stats[uName]["Debuffs"], 0); end CT_RA_ScanPartyAuras(uId); end CT_RA_UpdateRaidGroup(0); if ( CT_RA_NumRaidMembers == 0 and CT_RA_Level >= 2 ) then local lootid = ( CT_RATab_DefaultLootMethod or -1 ); if ( lootid == 1 ) then SetLootMethod("freeforall"); elseif ( lootid == 2 ) then SetLootMethod("roundrobin"); elseif ( lootid == 3 ) then SetLootMethod("master", playerName); elseif ( lootid == 4 ) then SetLootMethod("group"); elseif ( lootid == 5 ) then SetLootMethod("needbeforegreed"); end for i = 1, numRaidMembers, 1 do local name, rank = GetRaidRosterInfo(i); if ( name ~= playerName and rank < 1 and CT_RATab_AutoPromotions[name] ) then PromoteToAssistant(name); CT_RA_Print(" Auto-Promoted |c00FFFFFF" .. name .. "|r.", 1, 0.5, 0); end end end else CT_RA_UpdateRaidGroup(3); end CT_RA_NumRaidMembers = numRaidMembers; if ( not CT_RA_Channel and GetGuildInfo("player") ) then CT_RA_Channel = "CT" .. string.gsub(GetGuildInfo("player"), "[^%w]", ""); end if ( event == "PLAYER_ENTERING_WORLD" ) then if ( CT_RA_RaidParticipant ) then if ( CT_RA_RaidParticipant ~= playerName ) then CT_RA_Stats = { { } }; CT_RA_MainTanks = { }; CT_RA_PTargets = { }; CT_RATarget.MainTanks = { }; CT_RA_ButtonIndexes = { }; end end CT_RA_RaidParticipant = playerName; -- Add chat frame stuff local info = CT_RA_ChatInfo[playerName]; local chatTypeInfo = ChatTypeInfo["CTRAID"]; if ( not info ) then info = CT_RA_ChatInfo["Default"]; end chatTypeInfo.r = info.r; chatTypeInfo.g = info.g; chatTypeInfo.b = info.b; end elseif ( event == "UNIT_HEALTH" or event == "UNIT_MAXHEALTH" ) then local _, _, id = string.find(arg1, "^raid(%d+)$"); if ( id ) then local frame = getglobal("CT_RAMember" .. id); local name, hCurr, hMax = UnitName(arg1), UnitHealth(arg1), UnitHealthMax(arg1); local hpp = ( hCurr or 1 ) / ( hMax or 1 ); local stats = CT_RA_Stats[name]; if ( name ) then if ( not stats ) then CT_RA_Stats[name] = { ["Buffs"] = { }, ["Debuffs"] = { }, ["Position"] = { } }; stats = CT_RA_Stats[name]; end if ( UnitIsDead(arg1) or UnitIsGhost(arg1) ) then CT_RA_ScanPartyAuras(arg1); if ( not stats["Dead"] ) then stats["Dead"] = 1; end CT_RA_UpdateUnitDead(frame); elseif ( stats["Dead"] ) then if ( hCurr > 0 and not UnitIsGhost(arg1) ) then stats["Dead"] = nil; end CT_RA_UpdateUnitDead(frame); else stats["Dead"] = nil; if ( not frame.hpp or frame.hpp ~= floor(hpp*100) ) then CT_RA_UpdateUnitHealth(frame); end end if ( CT_RA_Emergency_Units[name] or ( not CT_RA_EmergencyFrame.maxPercent or hpp < CT_RA_EmergencyFrame.maxPercent ) ) then CT_RA_Emergency_UpdateHealth(); end end elseif ( ( GetNumRaidMembers() == 0 and ( arg1 == "player" or string.find(arg1, "^party%d+$") ) ) ) then if ( CT_RA_Emergency_Units[UnitName(arg1)] or ( not CT_RA_EmergencyFrame.maxPercent or ( hpp and hpp < CT_RA_EmergencyFrame.maxPercent ) ) ) then CT_RA_Emergency_UpdateHealth(); end end return; elseif ( event == "UNIT_AURA" and GetNumRaidMembers() > 0 ) then if ( string.find(arg1, "^raid%d+$") ) then CT_RA_ScanPartyAuras(arg1); end elseif ( event == "UNIT_MANA" or event == "UNIT_MAXMANA" or event == "UNIT_RAGE" or event == "UNIT_MAXRAGE" or event == "UNIT_ENERGY" or event == "UNIT_MAXENERGY" ) then local _, _, id = string.find(arg1, "^raid(%d+)$"); if ( id ) then CT_RA_UpdateUnitMana(getglobal("CT_RAMember" .. id)); end return; elseif ( event == "UI_ERROR_MESSAGE" or event == "UI_INFO_MESSAGE" ) then if ( CT_RA_LastCast and (GetTime()-CT_RA_LastCast) <= 0.1 ) then if ( CT_RA_LastCastType == "debuff" ) then tinsert(CT_RA_BuffsToCure, 1, CT_RA_LastCastSpell); else tinsert(CT_RA_BuffsToRecast, 1, CT_RA_LastCastSpell); end CT_RA_LastCast = nil; CT_RA_LastCastSpell = nil; end elseif ( event == "SPELLCAST_START" ) then CT_RA_CurrCastSpell = arg1; elseif ( event == "SPELLCAST_INTERRUPTED" or event == "SPELLCAST_FAILED" ) then CT_RA_CurrCastSpell = nil; elseif ( event == "SPELLCAST_STOP" and CT_RA_CurrCastSpell ) then if ( CT_RA_CurrCastSpell == CT_RA_REBIRTH ) then CT_RA_AddMessage("CD 1 30"); elseif ( CT_RA_CurrCastSpell == CT_RA_SOULSTONERESURRECTION ) then CT_RA_AddMessage("CD 3 30"); end CT_RA_CurrCastSpell = nil; elseif ( event == "PLAYER_TARGET_CHANGED" ) then CT_RA_UpdateResFrame(); end end CT_RA_oldUseSoulstone = UseSoulstone; function CT_RA_newUseSoulstone() local text = HasSoulstone(); if ( text and text == "Reincarnation" ) then local cooldown; for i = 1, GetNumTalentTabs(), 1 do for y = 1, GetNumTalents(i), 1 do local name, _, _, _, currRank = GetTalentInfo(i, y); if ( name == "Improved Reincarnation" ) then cooldown = 60 - (currRank*10); break; end end if ( cooldown ) then break; end end if ( not cooldown ) then cooldown = 60; end CT_RA_AddMessage("CD 2 " .. cooldown); end CT_RA_oldUseSoulstone(); end UseSoulstone = CT_RA_newUseSoulstone; ----------------------------------------------------- -- Update Functions -- ----------------------------------------------------- -- Update health function CT_RA_UpdateUnitHealth(frame) local tempOptions = CT_RAMenu_Options["temp"]; if ( not frame.group or not tempOptions["ShowGroups"][frame.group.id] ) then return; end local id = "raid" .. frame.id; local maxHealth = UnitHealthMax(id); local percent = floor(UnitHealth(id) / maxHealth * 100); local name = UnitName(id); if ( not name and tempOptions["SORTTYPE"] == "virtual" ) then percent = 100; maxHealth = 100; name = "Virtual " .. frame.id; end frame.hpp = percent; local updateDead = frame.status; if ( percent and percent > 0 ) then -- Commonly used values local defaultAlpha = tempOptions.DefaultAlpha; if ( defaultAlpha and defaultAlpha < 1 ) then frame:SetAlpha(math.max(math.min(defaultAlpha+(1-(percent/100))*(1-defaultAlpha), 1), defaultAlpha)); else frame:SetAlpha(1); end local showHP = tempOptions["ShowHP"]; local memberHeight = tempOptions["MemberHeight"]; local framePercent = frame.Percent; local frameHPBar = frame.HPBar; local stats = CT_RA_Stats[name]; if ( stats and stats["Ressed"] ) then stats["Ressed"] = nil; updateDead = 1; end if ( percent > 100 ) then percent = 100; end frameHPBar:SetValue(percent); if ( showHP and showHP == 1 and maxHealth and memberHeight == 40 ) then framePercent:SetText(floor(percent/100*maxHealth) .. "/" .. maxHealth); elseif ( showHP and showHP == 2 and memberHeight == 40 ) then framePercent:SetText(percent .. "%"); elseif ( showHP and showHP == 3 and memberHeight == 40 ) then if ( maxHealth ) then local diff = floor(percent/100*maxHealth)-maxHealth; if ( diff == 0 ) then diff = ""; end framePercent:SetText(diff); else framePercent:SetText(percent-100 .. "%"); end else framePercent:Hide(); end local hppercent = percent/100; local r, g; if ( hppercent > 0.5 and hppercent <= 1) then g = 1; r = (1.0 - hppercent) * 2; elseif ( hppercent >= 0 and hppercent <= 0.5 ) then r = 1.0; g = hppercent * 2; else r = 0; g = 1; end frameHPBar:SetStatusBarColor(r, g, 0); frame.HPBG:SetVertexColor(r, g, 0, tempOptions["BGOpacity"]); end local isDead; if ( updateDead ) then CT_RA_UpdateUnitDead(frame, 1); end end -- Update status function CT_RA_UpdateUnitStatus(frame) local tempOptions = CT_RAMenu_Options["temp"]; if ( not frame.group or not tempOptions["ShowGroups"][frame.group.id] ) then return; end local frameName = frame.name; local id = frame.id; local castFrame = frame.CastFrame; local name, rank, subgroup, level, class, fileName, zone, online, isDead = GetRaidRosterInfo(id); if ( not name and tempOptions["SORTTYPE"] == "virtual" ) then name, rank, subgroup, level, class, fileName, zone, online, isDead = "Virtual " .. id, 0, floor((id-1)/5)+1, 60, CT_RA_PRIEST, "PRIEST", "Emerald Dream", 1, nil; end local height = tempOptions["MemberHeight"]; if ( ( ( class == CT_RA_WARRIOR or class == CT_RA_ROGUE ) and tempOptions["HideRP"] ) or ( class ~= CT_RA_WARRIOR and class ~= CT_RA_ROGUE and tempOptions["HideMP"] ) ) then height = height - 4; end if ( tempOptions["HideBorder"] ) then if ( height == 28 ) then frame.BuffButton1:SetPoint("TOPRIGHT", frameName, "TOPRIGHT", -5, -5); frame.DebuffButton1:SetPoint("TOPRIGHT", frameName, "TOPRIGHT", -5, -5); else frame.BuffButton1:SetPoint("TOPRIGHT", frameName, "TOPRIGHT", -5, -3); frame.DebuffButton1:SetPoint("TOPRIGHT", frameName, "TOPRIGHT", -5, -3); end frame:SetBackdropBorderColor(1, 1, 1, 0); frame.Percent:SetPoint("TOP", frameName, "TOP", 2, -16); frame.HPBar:SetPoint("TOPLEFT", frameName, "TOPLEFT", 10, -19); frame.HPBG:SetPoint("TOPLEFT", frameName, "TOPLEFT", 10, -19); castFrame:SetWidth(85); if ( not online ) then frame:SetHeight(37); castFrame:SetHeight(37); else frame:SetHeight(height-3); castFrame:SetHeight(height-3); end else frame:SetBackdropBorderColor(1, 1, 1, 1); frame.BuffButton1:SetPoint("TOPRIGHT", frameName, "TOPRIGHT", -5, -5); frame.DebuffButton1:SetPoint("TOPRIGHT", frameName, "TOPRIGHT", -5, -5); frame.HPBar:SetPoint("TOPLEFT", frameName, "TOPLEFT", 10, -22); frame.HPBG:SetPoint("TOPLEFT",frameName, "TOPLEFT", 10, -22); frame.Percent:SetPoint("TOP", frameName, "TOP", 2, -18); castFrame:SetWidth(90); if ( not online ) then frame:SetHeight(40); castFrame:SetHeight(40); else frame:SetHeight(height); castFrame:SetHeight(height); end end if ( height == 32 or height == 28 ) then frame.HPBar:Hide(); frame.HPBG:Hide(); frame.Percent:Hide(); else frame.HPBar:Show(); frame.HPBG:Show(); end stats = CT_RA_Stats[name]; if ( frame.group and tempOptions["ShowGroups"][frame.group.id] ) then frame:Show(); end frame.Name:SetText(name); CT_RA_UpdateUnitDead(frame); if ( stats ) then CT_RA_UpdateUnitBuffs(stats["Buffs"], frame, name); end if ( online ) then CT_RA_UpdateUnitHealth(frame, 1); CT_RA_UpdateUnitMana(frame); if ( stats ) then CT_RA_UpdateUnitBuffs(stats["Buffs"], frame, name); end end end function CT_RA_CanShowInfo(id) local tempOptions = CT_RAMenu_Options["temp"]; local stats = CT_RA_Stats[UnitName(id)]; local showHP, hasFD, isRessed, isNotReady, showAFK, isDead; local hp = tempOptions["ShowHP"]; showHP = ( hp and hp <= 3 ); hasFD = ( stats and stats["FD"] ); isRessed = ( stats and stats["Ressed"] ); isNotReady = ( stats and stats["notready"] ); showAFK = ( tempOptions["ShowAFK"] and stats and stats["AFK"] ); isDead = ( ( stats and stats["Dead"] ) or UnitIsDead(id) or UnitIsGhost(id) ); if ( showHP and not hasFD and not isRessed and not isNotReady and not showAFK and not isDead ) then return true; else return nil; end end -- Update mana function CT_RA_UpdateUnitMana(frame) local tempOptions = CT_RAMenu_Options["temp"]; if ( not frame.group or not tempOptions["ShowGroups"][frame.group.id] ) then return; end local id = "raid" .. frame.id; local percent; if ( not UnitExists(id) and tempOptions["SORTTYPE"] == "virtual" ) then percent = 100; else percent = floor(UnitMana(id) / UnitManaMax(id) * 100); end frame.MPBar:SetValue(percent); end -- Update buffs function CT_RA_UpdateUnitBuffs(buffs, frame, nick) local tempOptions = CT_RAMenu_Options["temp"]; if ( not frame.group or not tempOptions["ShowGroups"][frame.group.id] ) then return; end local num = 1; if ( buffs ) then if ( not tempOptions["ShowDebuffs"] or tempOptions["ShowBuffsDebuffed"] ) then for key, val in tempOptions["BuffArray"] do local name; if ( type(val["name"]) == "table" ) then if ( buffs[val["name"][1]] ) then name = val["name"][1]; elseif ( buffs[val["name"][2]] ) then name = val["name"][2]; end elseif ( buffs[val["name"]] ) then name = val["name"]; end if ( name ) then if ( num <= 4 and val["show"] ~= -1 ) then -- Change 4 to number of buffs local button = frame["BuffButton"..num]; frameCache[button].Icon:SetTexture("Interface\\Icons\\" .. CT_RA_BuffTextures[name][1]); button.name = name; button.owner = nick; button.texture = CT_RA_BuffTextures[name][1]; button:Show(); num = num + 1; end end end end end for i = num, 4, 1 do -- Change 4 to number of buffs frame["BuffButton"..i]:Hide(); end local stats = CT_RA_Stats[nick]; if ( stats ) then CT_RA_UpdateUnitDebuffs(stats["Debuffs"], frame); end end function CT_RA_UpdateUnitDead(frame, didUpdateHealth) local tempOptions = CT_RAMenu_Options["temp"]; if ( not frame.group or not tempOptions["ShowGroups"][frame.group.id] ) then return; end local raidid = "raid" .. frame.id; local name, rank, subgroup, level, class, fileName, zone, online, dead = GetRaidRosterInfo(frame.id); if ( not name and tempOptions["SORTTYPE"] == "virtual" ) then name, rank, subgroup, level, class, fileName, zone, online, isDead = "Virtual " .. frame.id, 0, floor((frame.id-1)/5)+1, 60, CT_RA_PRIEST, "PRIEST", "Emerald Dream", 1, nil; end local color = RAID_CLASS_COLORS[fileName]; if ( color ) then frame.Name:SetTextColor(color.r, color.g, color.b); end local stats, isFD, isDead = CT_RA_Stats[name], false, false; if ( UnitIsGhost(raidid) or UnitIsDead(raidid) ) then isFD = CT_RA_CheckFD(name, raidid) if ( isFD == 0 ) then isDead = 1; -- Scan buffs&debuffs on death CT_RA_ScanPartyAuras(raidid); end end local height = tempOptions["MemberHeight"]; if ( ( ( class == CT_RA_WARRIOR or class == CT_RA_ROGUE ) and tempOptions["HideRP"] ) or ( class ~= CT_RA_WARRIOR and class ~= CT_RA_ROGUE and tempOptions["HideMP"] ) ) then height = height - 4; end if ( not online ) then if ( tempOptions["HideOffline"] ) then frame:Hide(); end for i = 1, 4, 1 do if ( i <= 2 ) then frame["DebuffButton"..i]:Hide(); end frame["BuffButton"..i]:Hide(); end frame:SetBackdropColor(0.3, 0.3, 0.3, 1); if ( tempOptions["HideBorder"] ) then frame:SetHeight(37); else frame:SetHeight(40); end if ( name ) then if ( not stats ) then CT_RA_Stats[name] = { ["Buffs"] = { }, ["Debuffs"] = { }, ["Position"] = { }, }; stats = CT_RA_Stats[name]; end if ( not stats["Offline"] ) then stats["Offline"] = 1; end end frame.status = "offline"; frame.Status:SetText("OFFLINE"); frame.Status:Show(); frame.HPBar:Hide(); frame.HPBG:Hide(); frame.Percent:Hide(); frame.MPBar:Hide(); frame.MPBG:Hide(); frame:SetAlpha(1); return; elseif ( stats and stats["notready"] ) then frame.Status:Show(); if ( tempOptions["HideBorder"] ) then frame:SetHeight(37); else frame:SetHeight(40); end if ( stats["notready"] == 1 ) then frame.status = "noreply"; frame.Status:SetText("No Reply"); frame:SetBackdropColor(0.45, 0.45, 0.45, 1); else frame.status = "notready"; frame.Status:SetText("Not Ready"); frame:SetBackdropColor(0.8, 0.45, 0.45, 1); end frame.HPBar:Hide(); frame.HPBG:Hide(); frame.Percent:Hide(); frame.MPBar:Hide(); frame.MPBG:Hide(); frame:SetAlpha(1); elseif ( isFD == 1 ) then frame.status = "feigndeath"; frame.Status:Show(); frame.Status:SetText("Feign Death"); frame:SetBackdropColor(0.3, 0.3, 0.3, 1); if ( tempOptions["HideBorder"] and ( ( ( class == CT_RA_WARRIOR or class == CT_RA_ROGUE ) and tempOptions["HideRP"] ) or ( class ~= CT_RA_WARRIOR and class ~= CT_RA_ROGUE and tempOptions["HideMP"] ) ) ) then frame:SetHeight(height+3); end frame.HPBar:Hide(); frame.HPBG:Hide(); frame.Percent:Hide(); frame.MPBar:Hide(); frame.MPBG:Hide(); frame:SetAlpha(1); elseif ( isFD == 2 ) then frame.status = "spiritofredemption"; frame.Status:Show(); frame.Status:SetText("SoR"); frame:SetBackdropColor(0.3, 0.3, 0.3, 1); if ( tempOptions["HideBorder"] and ( ( ( class == CT_RA_WARRIOR or class == CT_RA_ROGUE ) and tempOptions["HideRP"] ) or ( class ~= CT_RA_WARRIOR and class ~= CT_RA_ROGUE and tempOptions["HideMP"] ) ) ) then frame:SetHeight(height+3); end frame.HPBar:Hide(); frame.HPBG:Hide(); frame.Percent:Hide(); frame.MPBar:Hide(); frame.MPBG:Hide(); frame:SetAlpha(1); elseif ( stats and stats["Ressed"] ) then frame.status = "resurrected"; frame.Status:Show(); frame:SetBackdropColor(0.3, 0.3, 0.3, 1); if ( tempOptions["HideBorder"] ) then frame:SetHeight(37); else frame:SetHeight(40); end if ( stats["Ressed"] == 1 ) then frame.Status:SetText("Resurrected"); elseif ( stats["Ressed"] == 2 ) then frame.Status:SetText("SS Available"); end frame.HPBar:Hide(); frame.HPBG:Hide(); frame.Percent:Hide(); frame.MPBar:Hide(); frame.MPBG:Hide(); frame:SetAlpha(1); elseif ( isDead ) then frame.status = "dead"; for i = 1, 4, 1 do if ( i <= 2 ) then frame["DebuffButton"..i]:Hide(); end frame["BuffButton"..i]:Hide(); end frame.Status:Show(); frame:SetBackdropColor(0.3, 0.3, 0.3, 1); if ( tempOptions["HideBorder"] ) then frame:SetHeight(37); else frame:SetHeight(40); end frame.Status:SetText("DEAD"); frame.HPBar:Hide(); frame.HPBG:Hide(); frame.Percent:Hide(); frame.MPBar:Hide(); frame.MPBG:Hide(); frame:SetAlpha(1); elseif ( stats and stats["AFK"] and tempOptions["ShowAFK"] ) then frame.status = "afk"; frame.Status:Show(); frame:SetBackdropColor(0.3, 0.3, 0.3, 1); if ( tempOptions["HideBorder"] ) then frame:SetHeight(37); else frame:SetHeight(40); end frame.Status:SetText("AFK"); frame.HPBar:Hide(); frame.HPBG:Hide(); frame.Percent:Hide(); frame.MPBar:Hide(); frame.MPBG:Hide(); frame:SetAlpha(1); else if ( frame.status and not didUpdateHealth ) then CT_RA_UpdateUnitHealth(frame); end local canShowInfo = CT_RA_CanShowInfo("raid"..frame.id); frame.status = nil; frame:SetBackdropColor(tempOptions["DefaultColor"].r, tempOptions["DefaultColor"].g, tempOptions["DefaultColor"].b, tempOptions["DefaultColor"].a); if ( tempOptions["MemberHeight"] == 40 ) then frame.HPBar:Show(); frame.HPBG:Show(); if ( canShowInfo ) then frame.Percent:Show(); else frame.Percent:Hide(); end end if ( tempOptions["HideBorder"] ) then frame:SetHeight(height-3); else frame:SetHeight(height); end if ( class == CT_RA_WARRIOR ) then frame.MPBar:SetStatusBarColor(1, 0, 0); frame.MPBG:SetVertexColor(1, 0, 0, tempOptions["BGOpacity"]); elseif ( class == CT_RA_ROGUE ) then frame.MPBar:SetStatusBarColor(1, 1, 0); frame.MPBG:SetVertexColor(1, 1, 0, tempOptions["BGOpacity"]); else frame.MPBar:SetStatusBarColor(0, 0, 1); frame.MPBG:SetVertexColor(0, 0, 1, tempOptions["BGOpacity"]); end frame.Status:Hide(); if ( ( ( class == CT_RA_WARRIOR or class == CT_RA_ROGUE ) and not tempOptions["HideRP"] ) or ( class ~= CT_RA_WARRIOR and class ~= CT_RA_ROGUE and not tempOptions["HideMP"] ) ) then frame.MPBar:Show(); frame.MPBG:Show(); if ( canShowInfo ) then frame.Percent:Show(); else frame.Percent:Hide(); end else frame.MPBar:Hide(); frame.MPBG:Hide(); end end if ( stats ) then stats["Offline"] = nil; end end -- Update debuffs function CT_RA_UpdateUnitDebuffs(debuffs, frame) local tempOptions = CT_RAMenu_Options["temp"]; if ( not frame.group or not tempOptions["ShowGroups"][frame.group.id] ) then return; end local num = 1; if ( tempOptions["ShowBuffsDebuffed"] ) then num = 2; end local name, rank, subgroup, level, class, fileName, zone, online, isDead = GetRaidRosterInfo(frame.id); local stats, setbg = CT_RA_Stats[name], 0; if ( name and stats and online and not UnitIsGhost("raid" .. frame.id) and ( not UnitIsDead("raid" .. frame.id) or stats["FD"] ) ) then if ( not frame.status ) then local defaultColors = tempOptions["DefaultColor"]; frame:SetBackdropColor(defaultColors.r, defaultColors.g, defaultColors.b, defaultColors.a); end if ( debuffs ) then for key, val in tempOptions["DebuffColors"] do for k, v in debuffs do local en, de, fr; if ( type(val["type"]) == "table" ) then en = val["type"]["en"]; de = val["type"]["de"]; fr = val["type"]["fr"]; else en = val["type"]; end if ( ( ( en and en == v[1] ) or ( de and de == v[1] ) or ( fr and fr == v[1] ) ) and val["id"] ~= -1 ) then if ( tempOptions["ShowBuffsDebuffed"] and num >= 1 ) then local button = frame["DebuffButton"..num]; frameCache[button].Icon:SetTexture("Interface\\Icons\\" ..v[3]); button.name = k; button.owner = name; button.texture = v[3]; button:Show(); num = num - 1; elseif ( not tempOptions["ShowBuffsDebuffed"] and tempOptions["ShowDebuffs"] and num <= 2 ) then local button = frame["DebuffButton"..num]; frameCache[button].Icon:SetTexture("Interface\\Icons\\" ..v[3]); button.name = k; button.owner = name; button.texture = v[3]; button:Show(); num = num + 1; end if ( setbg == 0 and not frame.status ) then frame:SetBackdropColor(val.r, val.g, val.b, val.a); setbg = 1; end end end end end if ( tempOptions["ShowBuffsDebuffed"] ) then if ( num < 1 ) then for i = 1, 4, 1 do frame["BuffButton"..i]:Hide(); end end for i = num, 1, -1 do frame["DebuffButton"..i]:Hide(); end else for i = num, 2, 1 do frame["DebuffButton"..i]:Hide(); end end end end -- Get info function CT_RA_SortClassArray(arr) local classValues = { [CT_RA_WARRIOR] = 8, [CT_RA_PALADIN] = 7, [CT_RA_DRUID] = 6, [CT_RA_MAGE] = 5, [CT_RA_WARLOCK] = 4, [CT_RA_ROGUE] = 3, [CT_RA_HUNTER] = 2, [CT_RA_PRIEST] = 1, [CT_RA_SHAMAN] = 0 }; local limit, st, j, temp, swapped; limit = getn(arr); st = 0; while ( st < limit ) do swapped = false; st = st + 1; limit = limit - 1; local val, val1; for j = st, limit, 1 do if ( arr[j]["class"] ) then val = classValues[arr[j]["class"]]; else val = 0; end if ( arr[j+1]["class"] ) then val1 = classValues[arr[j+1]["class"]]; else val1 = 0; end if ( val < val1 ) then temp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = temp; swapped = true; end end if ( not swapped ) then return arr; end swapped = false; for j=limit, st, -1 do if ( arr[j]["class"] ) then val = classValues[arr[j]["class"]]; else val = 0; end if ( arr[j+1]["class"] ) then val1 = classValues[arr[j+1]["class"]]; else val1 = 0; end if ( val < val1 ) then temp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = temp; swapped = true; end end if ( not swapped ) then return arr; end end return arr; end function CT_RA_UpdateMT(raidid, mtid, frame, height, key, val) local tempOptions = CT_RAMenu_Options["temp"]; local framecast = frame.CastFrame; local frameName = frame.name; if ( not tempOptions["ShowMTTT"] or ( UnitIsUnit(mtid, raidid .. "target") or tempOptions["HideColorChange"] ) ) then local defaultColors = tempOptions.DefaultColor; frame:SetBackdropColor(defaultColors.r, defaultColors.g, defaultColors.b, defaultColors.a); else frame:SetBackdropColor(1, 0, 0, 1); end if ( tempOptions["HideBorder"] ) then frame.Percent:SetPoint("TOP", frameName, "TOPLEFT", 47, -16); frame:SetBackdropBorderColor(1, 1, 1, 0); frame.HPBar:SetPoint("TOPLEFT", frameName, "TOPLEFT", 10, -19); frame.HPBG:SetPoint("TOPLEFT", frameName, "TOPLEFT", 10, -19); frame:SetHeight(height-3); frame.height = height-3; framecast:SetHeight(height-3); framecast:SetWidth(85); else frame:SetBackdropBorderColor(1, 1, 1, 1); frame.HPBar:SetPoint("TOPLEFT", frameName, "TOPLEFT", 10, -22); frame.HPBG:SetPoint("TOPLEFT", frameName, "TOPLEFT", 10, -22); frame.Percent:SetPoint("TOP", frameName, "TOPLEFT", 47, -18); frame:SetHeight(height); frame.height = height; framecast:SetHeight(height); framecast:SetWidth(90); end if ( raidid and UnitExists(raidid) and strlen(UnitName(raidid) or "") > 0 ) then local health, healthmax, mana, manamax = UnitHealth(raidid), UnitHealthMax(raidid), UnitMana(raidid), UnitManaMax(raidid); frame.Name:SetHeight(15); frame.Status:Hide(); frame.HPBar:Show(); frame.HPBG:Show(); frame.MPBar:Show(); frame.MPBG:Show(); frame.Name:Show(); local manaType = UnitPowerType(raidid); if ( ( manaType == 0 and not tempOptions["HideMP"] ) or ( manaType > 0 and not tempOptions["HideRP"] and UnitIsPlayer(raidid) ) ) then local manaTbl = ManaBarColor[manaType]; frame.MPBar:SetStatusBarColor(manaTbl.r, manaTbl.g, manaTbl.b); frame.MPBG:SetVertexColor(manaTbl.r, manaTbl.g, manaTbl.b, tempOptions["BGOpacity"]); if ( tempOptions["HideBorder"] ) then frame:SetHeight(37); frame.height = 37; framecast:SetHeight(37); else frame:SetHeight(40); frame.height = 40; framecast:SetHeight(40); end frame.MPBar:SetMinMaxValues(0, manamax); frame.MPBar:SetValue(mana); else frame.MPBar:Hide(); frame.MPBG:Hide(); if ( tempOptions["HideBorder"] ) then frame:SetHeight(33); frame.height = 33; framecast:SetHeight(33); else frame:SetHeight(36); frame.height = 36; framecast:SetHeight(36); end end if ( health and healthmax and not UnitIsDead(raidid) and not UnitIsGhost(raidid) ) then if ( tempOptions["ShowHP"] and tempOptions["ShowHP"] <= 4 ) then frame.Percent:Show(); else frame.Percent:Hide(); end frame.HPBar:SetMinMaxValues(0, healthmax); frame.HPBar:SetValue(health); frame.Percent:SetText(floor(health/healthmax*100+0.5) .. "%"); local percent = health/healthmax; if ( percent >= 0 and percent <= 1 ) then local r, g; if ( percent > 0.5 ) then g = 1; r = (1.0 - percent) * 2; else r = 1; g = percent * 2; end frame.HPBar:SetStatusBarColor(r, g, 0); frame.HPBG:SetVertexColor(r, g, 0, tempOptions["BGOpacity"]); end elseif ( UnitIsDead(raidid) or UnitIsGhost(raidid) ) then frame.HPBar:Hide(); frame.HPBG:Hide(); frame.Percent:Hide(); frame.MPBar:Hide(); frame.MPBG:Hide(); frame.Status:Show(); frame.Status:SetText("DEAD"); else frame.HPBar:Hide(); frame.HPBG:Hide(); end frame.Name:SetText(UnitName(raidid)); if ( UnitCanAttack("player", raidid) ) then frame.Name:SetTextColor(1, 0.5, 0); else frame.Name:SetTextColor(0.5, 1, 0); end frame.CastFrame.unitName = UnitName(raidid); else frame.Percent:Hide(); frame.HPBar:Hide(); frame.HPBG:Hide(); frame.MPBar:Hide(); frame.MPBG:Hide(); frame.Status:Hide(); frame.Name:SetText(val .. "'s Target"); frame.Name:SetHeight(30); frame.Name:SetTextColor(1, 0.82, 0); end end function CT_RA_UpdateMTs() local tempOptions = CT_RAMenu_Options["temp"]; CT_RAMTGroupGroupName:SetText("MT Targets"); CT_RAMTGroup:Hide(); CT_RAMTGroupGroupName:Hide(); for i = 1, 10, 1 do local mem = getglobal("CT_RAMTGroupMember" .. i); mem:Hide(); mem:ClearAllPoints(); if ( i > 1 ) then local above = "CT_RAMTGroupMember" .. (i-1); if ( tempOptions["HideBorder"] ) then if ( tempOptions["HideSpace"] ) then if ( tempOptions["ShowReversed"] ) then mem:SetPoint("BOTTOMLEFT", above, "TOPLEFT", 0, -10); else mem:SetPoint("TOPLEFT", above, "BOTTOMLEFT", 0, 10); end else if ( tempOptions["ShowReversed"] ) then mem:SetPoint("BOTTOMLEFT", above, "TOPLEFT", 0, -7); else mem:SetPoint("TOPLEFT", above, "BOTTOMLEFT", 0, 7); end end else if ( tempOptions["ShowReversed"] ) then mem:SetPoint("BOTTOMLEFT", above, "TOPLEFT", 0, -5); else mem:SetPoint("TOPLEFT", above, "BOTTOMLEFT", 0, 4); end end else if ( tempOptions["ShowReversed"] ) then mem:SetPoint("BOTTOMLEFT", "CT_RAMTGroup", "TOPLEFT", 0, -15); else mem:SetPoint("TOPLEFT", "CT_RAMTGroup", "TOPLEFT", 0, -20); end end end if ( GetNumRaidMembers() == 0 or tempOptions["HideMTs"] ) then CT_RAMTGroupDrag:Hide(); return; end local hide = true; for key, val in CT_RA_MainTanks do if ( key <= ( tempOptions["ShowNumMTs"] or 10 ) ) then local height = tempOptions["MemberHeight"]; if ( tempOptions["HideMP"] ) then height = height - 4; end local frame = getglobal("CT_RAMTGroupMember" .. key); local frameParent = frame.frameParent; local raidid, mtid; for i = 1, GetNumRaidMembers(), 1 do if ( UnitName("raid" .. i) == CT_RA_MainTanks[key] ) then raidid = "raid" .. i .. "target"; mtid = "raid" .. i; break; end end if ( raidid and mtid ) then local name, hppercent, mppercent = UnitName(raidid), UnitHealth(raidid)/UnitHealthMax(raidid), UnitMana(raidid)/UnitManaMax(raidid); if ( name ~= ( frame.unitName or "" ) or hppercent ~= ( frame.hppercent or -1 ) or mppercent ~= ( frame.mppercent or -1 ) or not UnitIsConnected(raidid) ) then if ( not UnitIsConnected(raidid) ) then frame.unitName = nil; frame.hppercent = nil; frame.mppercent = nil; else frame.unitName = name; frame.hppercent = hppercent; frame.mppercent = mppercent; end CT_RA_UpdateMT(raidid, mtid, frame, height, key, val); end frame:Show(); frameParent:Show(); end if ( not tempOptions["HideNames"] ) then frameCache[frameParent].GroupName:Show(); else frameCache[frameParent].GroupName:Hide(); end if ( not tempOptions["LockGroups"] ) then hide = false; CT_RAMTGroupDrag:Show(); end end end if ( hide ) then CT_RAMTGroupDrag:Hide(); end CT_RA_UpdateMTTTs(); end function CT_RA_UpdatePT(raidid, frame, height, key, val) local tempOptions = CT_RAMenu_Options["temp"]; local framecast = getglobal("CT_RAPTGroupMember" .. key .. "CastFrame"); local frameName = frame.name; frame:SetBackdropColor(tempOptions["DefaultColor"]["r"], tempOptions["DefaultColor"]["g"], tempOptions["DefaultColor"]["b"], tempOptions["DefaultColor"]["a"]); if ( tempOptions["HideBorder"] ) then frame.Percent:SetPoint("TOP", frameName, "TOPLEFT", 47, -16); frame:SetBackdropBorderColor(1, 1, 1, 0); frame.HPBar:SetPoint("TOPLEFT", frameName, "TOPLEFT", 10, -19); frame.HPBG:SetPoint("TOPLEFT", frameName, "TOPLEFT", 10, -19); frame:SetHeight(height-3); frame.height = height-3; framecast:SetHeight(height-3); framecast:SetWidth(85); else frame:SetBackdropBorderColor(1, 1, 1, 1); frame.HPBar:SetPoint("TOPLEFT", frameName, "TOPLEFT", 10, -22); frame.HPBG:SetPoint("TOPLEFT", frameName, "TOPLEFT", 10, -22); frame.Percent:SetPoint("TOP", frameName, "TOPLEFT", 47, -18); frame:SetHeight(height); frame.height = height; framecast:SetHeight(height); framecast:SetWidth(90); end if ( raidid and UnitExists(raidid) and strlen(UnitName(raidid) or "") > 0 ) then local health, healthmax, mana, manamax = UnitHealth(raidid), UnitHealthMax(raidid), UnitMana(raidid), UnitManaMax(raidid); frame.Name:SetHeight(15); frame.Status:Hide(); frame.HPBar:Show(); frame.HPBG:Show(); frame.MPBar:Show(); frame.MPBG:Show(); frame.Name:Show(); local manaType = UnitPowerType(raidid); if ( ( manaType == 0 and not tempOptions["HideMP"] ) or ( manaType > 0 and not tempOptions["HideRP"] and UnitIsPlayer(raidid) ) ) then local manaTbl = ManaBarColor[manaType]; getglobal(frame:GetName() .. "MPBar"):SetStatusBarColor(manaTbl.r, manaTbl.g, manaTbl.b); getglobal(frame:GetName() .. "MPBG"):SetVertexColor(manaTbl.r, manaTbl.g, manaTbl.b, tempOptions["BGOpacity"]); if ( tempOptions["HideBorder"] ) then frame:SetHeight(37); frame.height = 37; framecast:SetHeight(37); else frame:SetHeight(40); frame.height = 40; framecast:SetHeight(40); end frame.MPBar:SetMinMaxValues(0, manamax); frame.MPBar:SetValue(mana); else frame.MPBar:Hide(); frame.MPBG:Hide(); if ( tempOptions["HideBorder"] ) then frame:SetHeight(33); frame.height = 33 framecast:SetHeight(33); else frame:SetHeight(36); frame.height = 36; framecast:SetHeight(36); end end if ( health and healthmax and not UnitIsDead(raidid) and not UnitIsGhost(raidid) and UnitIsConnected(raidid) ) then if ( tempOptions["ShowHP"] and tempOptions["ShowHP"] <= 4 ) then frame.Percent:Show(); else frame.Percent:Hide(); end frame.HPBar:SetMinMaxValues(0, healthmax); frame.HPBar:SetValue(health); frame.Percent:SetText(floor(health/healthmax*100+0.5) .. "%"); local percent = health/healthmax; if ( percent >= 0 and percent <= 1 ) then local r, g; if ( percent > 0.5 ) then g = 1; r = (1.0 - percent) * 2; else r = 1; g = percent * 2; end frame.HPBar:SetStatusBarColor(r, g, 0); frame.HPBG:SetVertexColor(r, g, 0, tempOptions["BGOpacity"]); end elseif ( not UnitIsConnected(raidid) ) then frame.HPBar:Hide(); frame.HPBG:Hide(); frame.Percent:Hide(); frame.MPBar:Hide(); frame.MPBG:Hide(); frame.Status:Show(); frame.Status:SetText("OFFLINE"); elseif ( UnitIsDead(raidid) or UnitIsGhost(raidid) ) then frame.HPBar:Hide(); frame.HPBG:Hide(); frame.Percent:Hide(); frame.MPBar:Hide(); frame.MPBG:Hide(); frame.Status:Show(); local isFD = CT_RA_CheckFD(UnitName(raidid), raidid); if ( isFD == 1 ) then frame.Status:SetText("Feign Death"); elseif ( isFD == 2 ) then frame.Status:SetText("SoR"); else frame.Status:SetText("DEAD"); end else frame.HPBar:Hide(); frame.HPBG:Hide(); end frame.Name:SetText(UnitName(raidid)); frame.Name:SetTextColor(0.5, 1, 0); frame.CastFrame.unitName = UnitName(raidid); else frame.Percent:Hide(); frame.HPBar:Hide(); frame.HPBG:Hide(); frame.MPBar:Hide(); frame.MPBG:Hide(); frame.Status:Hide(); frame.Name:SetText(val); frame.Name:SetHeight(30); frame.Name:SetTextColor(1, 0.82, 0); end end function CT_RA_UpdatePTs() local tempOptions = CT_RAMenu_Options["temp"]; CT_RAPTGroupGroupName:SetText("PTargets"); CT_RAPTGroup:Hide(); CT_RAPTGroupGroupName:Hide(); for i = 1, 10, 1 do local mem = getglobal("CT_RAPTGroupMember" .. i); mem:Hide(); mem:ClearAllPoints(); if ( i > 1 ) then local above = "CT_RAPTGroupMember" .. (i-1); if ( tempOptions["HideBorder"] ) then if ( tempOptions["HideSpace"] ) then if ( tempOptions["ShowReversed"] ) then mem:SetPoint("BOTTOMLEFT", above, "TOPLEFT", 0, -10); else mem:SetPoint("TOPLEFT", above, "BOTTOMLEFT", 0, 10); end else if ( tempOptions["ShowReversed"] ) then mem:SetPoint("BOTTOMLEFT", above, "TOPLEFT", 0, -7); else mem:SetPoint("TOPLEFT", above, "BOTTOMLEFT", 0, 7); end end else if ( tempOptions["ShowReversed"] ) then mem:SetPoint("BOTTOMLEFT", above, "TOPLEFT", 0, -5); else mem:SetPoint("TOPLEFT", above, "BOTTOMLEFT", 0, 4); end end else if ( tempOptions["ShowReversed"] ) then mem:SetPoint("BOTTOMLEFT", "CT_RAPTGroup", "TOPLEFT", 0, -15); else mem:SetPoint("TOPLEFT", "CT_RAPTGroup", "TOPLEFT", 0, -20); end end end if ( GetNumRaidMembers() == 0 or not CT_RA_PTargets ) then CT_RAPTGroupDrag:Hide(); return; end local hide = true; for key, val in CT_RA_PTargets do if ( key <= 10 ) then local height = tempOptions["MemberHeight"]; if ( tempOptions["HideMP"] ) then height = height - 4; end local frame = getglobal("CT_RAPTGroupMember" .. key); local frameParent = frame.frameParent; local raidid; for i = 1, GetNumRaidMembers(), 1 do if ( UnitName("raid" .. i) == CT_RA_PTargets[key] ) then raidid = "raid" .. i; break; end end if ( raidid ) then local name, hppercent, mppercent = UnitName(raidid), UnitHealth(raidid)/UnitHealthMax(raidid), UnitMana(raidid)/UnitManaMax(raidid); if ( name ~= ( frame.unitName or "" ) or hppercent ~= ( frame.hppercent or -1 ) or mppercent ~= ( frame.mppercent or -1 ) or not UnitIsConnected(raidid) ) then if ( not UnitIsConnected(raidid) ) then frame.unitName = nil; frame.hppercent = nil; frame.mppercent = nil; else frame.unitName = name; frame.hppercent = hppercent; frame.mppercent = mppercent; end CT_RA_UpdatePT(raidid, frame, height, key, val); end frame:Show(); frame:GetParent():Show(); end if ( not tempOptions["HideNames"] ) then frameCache[frameParent].GroupName:Show(); else frameCache[frameParent].GroupName:Hide(); end if ( not tempOptions["LockGroups"] ) then hide = false; CT_RAPTGroupDrag:Show(); end end end if ( hide ) then CT_RAPTGroupDrag:Hide(); end CT_RA_UpdatePTTs(); end function CT_RA_UpdatePTT(raidid, frame, height, key, val) local tempOptions = CT_RAMenu_Options["temp"]; local frameParent = frame.frameParent; local currHeight = frameParent:GetHeight(); local frameName = frame.name; if ( tempOptions["HideBorder"] ) then frame.Percent:SetPoint("TOP", frameName, "TOPLEFT", 47, -16); frame.HPBar:SetPoint("TOPLEFT", frameName, "TOPLEFT", 10, -19); frame.HPBG:SetPoint("TOPLEFT", frameName, "TOPLEFT", 10, -19); frame:SetHeight(height-3); frame.theight = height-3; else frame.Percent:SetPoint("TOP", frameName, "TOPLEFT", 47, -18); frame:SetHeight(height); frame.theight = height; end if ( raidid and UnitExists(raidid) and UnitIsConnected(raidid) ) then frameParent:SetBackdropColor(tempOptions["DefaultColor"].r, tempOptions["DefaultColor"].g, tempOptions["DefaultColor"].b, tempOptions["DefaultColor"].a); local health, healthmax, mana, manamax = UnitHealth(raidid), UnitHealthMax(raidid), UnitMana(raidid), UnitManaMax(raidid); frame.CastFrame.id = raidid; frame.Name:SetHeight(12); frame.Status:Hide(); frame.HPBar:Show(); frame.HPBG:Show(); frame.MPBar:Show(); frame.MPBG:Show(); frame.Name:Show(); local manaType = UnitPowerType(raidid); if ( ( manaType == 0 and not tempOptions["HideMP"] ) or ( manaType > 0 and not tempOptions["HideRP"] and UnitIsPlayer(raidid) ) ) then local manaTbl = ManaBarColor[manaType]; getglobal(frame:GetName() .. "MPBar"):SetStatusBarColor(manaTbl.r, manaTbl.g, manaTbl.b); getglobal(frame:GetName() .. "MPBG"):SetVertexColor(manaTbl.r, manaTbl.g, manaTbl.b, tempOptions["BGOpacity"]); if ( tempOptions["HideBorder"] ) then frame:SetHeight(37); frame.theight = 37; frame.CastFrame:SetHeight(37); else frame:SetHeight(40); frame.theight = 37; frame.CastFrame:SetHeight(40); end frame.MPBar:SetMinMaxValues(0, manamax); frame.MPBar:SetValue(mana); else frame.MPBar:Hide(); frame.MPBG:Hide(); if ( tempOptions["HideBorder"] ) then frame:SetHeight(33); frame.theight = 33; frame.CastFrame:SetHeight(33); else frame:SetHeight(36); frame.theight = 36; frame.CastFrame:SetHeight(36); end end if ( health and healthmax and not UnitIsDead(raidid) and not UnitIsGhost(raidid) ) then if ( tempOptions["ShowHP"] and tempOptions["ShowHP"] <= 4 ) then frame.Percent:Show(); else frame.Percent:Hide(); end frame.HPBar:SetMinMaxValues(0, healthmax); frame.HPBar:SetValue(health); frame.Percent:SetText(floor(health/healthmax*100+0.5) .. "%"); local percent = health/healthmax; if ( percent >= 0 and percent <= 1 ) then local r, g; if ( percent > 0.5 ) then g = 1; r = (1.0 - percent) * 2; else r = 1; g = percent * 2; end frame.HPBar:SetStatusBarColor(r, g, 0); frame.HPBG:SetVertexColor(r, g, 0, tempOptions["BGOpacity"]); end elseif ( UnitIsDead(raidid) or UnitIsGhost(raidid) ) then frame.HPBar:Hide(); frame.HPBG:Hide(); frame.Percent:Hide(); frame.MPBar:Hide(); frame.MPBG:Hide(); frame.Status:Show(); frame.Status:SetText("DEAD"); else frame.HPBar:Hide(); frame.HPBG:Hide(); end frame.Name:SetText(UnitName(raidid)); if ( UnitCanAttack("player", raidid) ) then frame.Name:SetTextColor(1, 0.5, 0); else frame.Name:SetTextColor(0.5, 1, 0); end if ( frame:GetHeight() > currHeight ) then frame:GetParent():SetHeight(frame:GetHeight()); frameParent.CastFrame:SetHeight(frame:GetHeight()); end else local defaultColors = tempOptions["DefaultColor"]; frameParent:SetBackdropColor(defaultColors.r, defaultColors.g, defaultColors.b, defaultColors.a); frame:SetBackdropColor(defaultColors.r, defaultColors.g, defaultColors.b, defaultColors.a); frame.Percent:Hide(); frame.HPBar:Hide(); frame.HPBG:Hide(); frame.MPBar:Hide(); frame.MPBG:Hide(); frame.Status:Hide(); frame.Name:SetText(""); frame.Name:SetTextColor(1, 0.82, 0); frame.Name:SetHeight(30); end end function CT_RA_UpdatePTTs() local tempOptions = CT_RAMenu_Options["temp"]; for key, val in CT_RA_PTargets do if ( key <= 10 ) then local height = tempOptions["MemberHeight"]; if ( tempOptions["HideMP"] ) then height = height - 4; end local frameParent = getglobal("CT_RAPTGroupMember"..key); local frame = frameParent.MTTT; if ( tempOptions["ShowPTT"] ) then local raidid; for i = 1, GetNumRaidMembers(), 1 do if ( UnitName("raid" .. i) == CT_RA_PTargets[key] ) then raidid = "raid" .. i .. "target"; break; end end if ( raidid ) then frame:Show(); local name, hppercent, mppercent = UnitName(raidid), UnitHealth(raidid)/UnitHealthMax(raidid), UnitMana(raidid)/UnitManaMax(raidid); if ( frame.theight and frame.theight > ( frameParent.height or 0 ) and name ) then frameParent:SetHeight(frame.theight); elseif ( not frame.theight ) then name = nil; -- Force an update end if ( name ~= ( frame.unitName or "" ) or hppercent ~= ( frame.hppercent or -1 ) or mppercent ~= ( frame.mppercent or -1 ) or not UnitIsConnected(raidid) ) then if ( not UnitIsConnected(raidid) ) then frame.unitName = nil; frame.hppercent = nil; frame.mppercent = nil; else frame.unitName = name; frame.hppercent = hppercent; frame.mppercent = mppercent; end CT_RA_UpdatePTT(raidid, frame, height, key, val); end end frameParent:SetWidth(165); CT_RAPTGroupMember1:ClearAllPoints(); if ( tempOptions["ShowReversed"] ) then CT_RAPTGroupMember1:SetPoint("BOTTOMLEFT", "CT_RAPTGroup", "TOPLEFT", -35, -15); else CT_RAPTGroupMember1:SetPoint("TOPLEFT", "CT_RAPTGroup", "TOPLEFT", -35, -20); end else frame:Hide(); frameParent:SetWidth(90); CT_RAPTGroupMember1:ClearAllPoints(); if ( tempOptions["ShowReversed"] ) then CT_RAPTGroupMember1:SetPoint("BOTTOMLEFT", "CT_RAPTGroup", "TOPLEFT", 0, -15); else CT_RAPTGroupMember1:SetPoint("TOPLEFT", "CT_RAPTGroup", "TOPLEFT", 0, -20); end end end end end function CT_RA_AssistMTTT(button) local id = this.id; if ( not id ) then return; end local stopDefaultBehaviour; if ( type(CT_RA_CustomOnClickFunction) == "function" ) then stopDefaultBehaviour = CT_RA_CustomOnClickFunction(button, id); end if ( not stopDefaultBehaviour ) then if ( SpellIsTargeting() ) then SpellTargetUnit(id); else TargetUnit(id); end end end function CT_RA_UpdateMTTT(raidid, mtid, frame, height, key, val) local tempOptions = CT_RAMenu_Options["temp"]; local frameParent = frame.frameParent; local currHeight = frameParent:GetHeight(); local frameName = frame.name; if ( tempOptions["HideBorder"] ) then frame.Percent:SetPoint("TOP", frameName, "TOPLEFT", 47, -16); frame.HPBar:SetPoint("TOPLEFT", frameName, "TOPLEFT", 10, -19); frame.HPBG:SetPoint("TOPLEFT", frameName, "TOPLEFT", 10, -19); frame:SetHeight(height-3); frame.theight = height-3; else frame.Percent:SetPoint("TOP", frameName, "TOPLEFT", 47, -18); frame:SetHeight(height); frame.height = height; end if ( raidid and UnitExists(raidid) ) then if ( not UnitIsUnit(mtid, raidid) and not tempOptions["HideColorChange"] ) then frame:GetParent():SetBackdropColor(1, 0, 0, 1); else local defaultColors = tempOptions.DefaultColor; frame:GetParent():SetBackdropColor(defaultColors.r, defaultColors.g, defaultColors.b, defaultColors.a); end local health, healthmax, mana, manamax = UnitHealth(raidid), UnitHealthMax(raidid), UnitMana(raidid), UnitManaMax(raidid); frame.CastFrame.id = raidid; frame.Name:SetHeight(12); frame.Status:Hide(); frame.HPBar:Show(); frame.HPBG:Show(); frame.MPBar:Show(); frame.MPBG:Show(); frame.Name:Show(); local manaType = UnitPowerType(raidid); if ( ( manaType == 0 and not tempOptions["HideMP"] ) or ( manaType > 0 and not tempOptions["HideRP"] and UnitIsPlayer(raidid) ) ) then local manaTbl = ManaBarColor[manaType]; getglobal(frame:GetName() .. "MPBar"):SetStatusBarColor(manaTbl.r, manaTbl.g, manaTbl.b); getglobal(frame:GetName() .. "MPBG"):SetVertexColor(manaTbl.r, manaTbl.g, manaTbl.b, tempOptions["BGOpacity"]); if ( tempOptions["HideBorder"] ) then frame:SetHeight(37); frame.theight = 37; frame.CastFrame:SetHeight(37); else frame:SetHeight(40); frame.theight = 40; frame.CastFrame:SetHeight(40); end frame.MPBar:SetMinMaxValues(0, manamax); frame.MPBar:SetValue(mana); else frame.MPBar:Hide(); frame.MPBG:Hide(); if ( tempOptions["HideBorder"] ) then frame:SetHeight(33); frame.theight = 33; frame.CastFrame:SetHeight(33); else frame:SetHeight(36); frame.theight = 36; frame.CastFrame:SetHeight(36); end end if ( health and healthmax and not UnitIsDead(raidid) and not UnitIsGhost(raidid) ) then if ( tempOptions["ShowHP"] and tempOptions["ShowHP"] <= 4 ) then frame.Percent:Show(); else frame.Percent:Hide(); end frame.HPBar:SetMinMaxValues(0, healthmax); frame.HPBar:SetValue(health); frame.Percent:SetText(floor(health/healthmax*100+0.5) .. "%"); local percent = health/healthmax; if ( percent >= 0 and percent <= 1 ) then local r, g; if ( percent > 0.5 ) then g = 1; r = (1.0 - percent) * 2; else r = 1; g = percent * 2; end frame.HPBar:SetStatusBarColor(r, g, 0); frame.HPBG:SetVertexColor(r, g, 0, tempOptions["BGOpacity"]); end elseif ( UnitIsDead(raidid) or UnitIsGhost(raidid) ) then frame.HPBar:Hide(); frame.HPBG:Hide(); frame.Percent:Hide(); frame.MPBar:Hide(); frame.MPBG:Hide(); frame.Status:Show(); frame.Status:SetText("DEAD"); else frame.HPBar:Hide(); frame.HPBG:Hide(); end frame.Name:SetText(UnitName(raidid)); if ( UnitCanAttack("player", raidid) ) then frame.Name:SetTextColor(1, 0.5, 0); else getglobal(frame:GetName() .. "Name"):SetTextColor(0.5, 1, 0); end if ( frame:GetHeight() > currHeight ) then frameParent:SetHeight(frame:GetHeight()); frameParent.CastFrame:SetHeight(frame:GetHeight()); end else local defaultColors = tempOptions.DefaultColor; frame:GetParent():SetBackdropColor(defaultColors.r, defaultColors.g, defaultColors.b, defaultColors.a); frame:SetBackdropColor(defaultColors.r, defaultColors.g, defaultColors.b, defaultColors.a); frame.Percent:Hide(); frame.HPBar:Hide(); frame.HPBG:Hide(); frame.MPBar:Hide(); frame.MPBG:Hide(); frame.Status:Hide(); frame.Name:SetText(""); frame.Name:SetTextColor(1, 0.82, 0); frame.Name:SetHeight(30); end end function CT_RA_UpdateMTTTs() local tempOptions = CT_RAMenu_Options["temp"]; for key, val in CT_RA_MainTanks do if ( key <= ( tempOptions["ShowNumMTs"] or 10 ) ) then local height = tempOptions["MemberHeight"]; if ( tempOptions["HideMP"] ) then height = height - 4; end local frameParent = getglobal("CT_RAMTGroupMember"..key); local frame = frameParent.MTTT if ( tempOptions["ShowMTTT"] and not tempOptions["HideMTs"] ) then if ( CT_RA_MainTanks[key] ) then local raidid, mtid; for i = 1, GetNumRaidMembers(), 1 do if ( UnitName("raid" .. i) == CT_RA_MainTanks[key] ) then raidid = "raid" .. i .. "targettarget"; mtid = "raid" .. i; break; end end if ( raidid and mtid ) then frame:Show(); local name, hppercent, mppercent = UnitName(raidid), UnitHealth(raidid)/UnitHealthMax(raidid), UnitMana(raidid)/UnitManaMax(raidid); if ( frame.theight and frame.theight > ( frameParent.height or 0 ) and name ) then frameParent:SetHeight(frame.theight); elseif ( not frame.theight ) then name = nil; -- Force an update end if ( name ~= ( frame.unitName or "" ) or hppercent ~= ( frame.hppercent or -1 ) or mppercent ~= ( frame.mppercent or -1 ) or not UnitIsConnected(raidid) ) then if ( not UnitIsConnected(raidid) ) then frame.unitName = nil; frame.hppercent = nil; frame.mppercent = nil; else frame.unitName = name; frame.hppercent = hppercent; frame.mppercent = mppercent; end if ( name == UnitName("player") and not UnitIsPlayer(mtid .. "target") ) then local isMT; for k, v in CT_RA_MainTanks do if ( v == UnitName("player") ) then isMT = 1; break; end end if ( not isMT and not CT_RA_UpdateFrame.hasAggroAlert and tempOptions["AggroNotifier"] ) then CT_RA_UpdateFrame.hasAggroAlert = 15; CT_RA_WarningFrame:AddMessage("AGGRO FROM " .. UnitName(mtid .. "target") .. "!", 1, 0, 0, 1, UIERRORS_HOLD_TIME); if ( tempOptions["AggroNotifierSound"] ) then PlaySoundFile("Sound\\Spells\\PVPFlagTakenHorde.wav"); end end end CT_RA_UpdateMTTT(raidid, mtid, frame, height, key, val); end end end frameParent:SetWidth(165); CT_RAMTGroupMember1:ClearAllPoints(); if ( tempOptions["ShowReversed"] ) then CT_RAMTGroupMember1:SetPoint("BOTTOMLEFT", "CT_RAMTGroup", "TOPLEFT", -35, -15); else CT_RAMTGroupMember1:SetPoint("TOPLEFT", "CT_RAMTGroup", "TOPLEFT", -35, -20); end else frame:Hide(); frameParent:SetWidth(90); CT_RAMTGroupMember1:ClearAllPoints(); if ( tempOptions["ShowReversed"] ) then CT_RAMTGroupMember1:SetPoint("BOTTOMLEFT", "CT_RAMTGroup", "TOPLEFT", 0, -15); else CT_RAMTGroupMember1:SetPoint("TOPLEFT", "CT_RAMTGroup", "TOPLEFT", 0, -20); end end end end end function CT_RA_UpdateGroupVisibility(num, noStatusUpdate) local tempOptions = CT_RAMenu_Options["temp"]; local group = getglobal("CT_RAGroup" .. num); local drag = getglobal("CT_RAGroupDrag" .. num); if ( not tempOptions["ShowGroups"] or not tempOptions["ShowGroups"][num] or ( GetNumRaidMembers() == 0 and tempOptions["SORTTYPE"] ~= "virtual" ) or not group.next ) then group:Hide(); drag:Hide(); elseif ( group.next ) then if ( tempOptions["LockGroups"] ) then drag:Hide(); else drag:Show(); end if ( tempOptions["HideNames"] ) then frameCache[group].GroupName:Hide(); else frameCache[group].GroupName:Show(); end group:Show(); end while ( group.next ) do if ( tempOptions["ShowGroups"] and tempOptions["ShowGroups"][num] ) then if ( not noStatusUpdate ) then CT_RA_UpdateUnitStatus(group.next); end group.next:Show(); else group.next:Hide(); end group = group.next; end end function CT_RA_UpdateVisibility(noStatusUpdate) for i = 1, 8, 1 do CT_RA_UpdateGroupVisibility(i, noStatusUpdate); end if ( CT_RA_MainTanks ) then CT_RA_UpdateMTs(); end if ( CT_RA_PTargets ) then CT_RA_UpdatePTs(); end end function CT_RA_UpdateRaidGroup(updateType) local tempOptions = CT_RAMenu_Options["temp"]; local sortType = tempOptions["SORTTYPE"]; if ( sortType == "group" ) then CT_RA_SortByGroup(); elseif ( sortType == "custom" ) then CT_RA_SortByCustom(); elseif ( sortType == "class" ) then CT_RA_SortByClass(); elseif ( sortType == "virtual" ) then CT_RA_SortByVirtual(1); end local numRaidMembers = GetNumRaidMembers(); local name, rank, subgroup, level, class, fileName, zone, online, isDead; for i=1, MAX_RAID_MEMBERS do if ( i <= numRaidMembers or sortType == "virtual" ) then local unitid = "raid" .. i; name, rank, subgroup, level, class, fileName, zone, online, isDead = GetRaidRosterInfo(i); if ( not name and sortType == "virtual" ) then name, rank, subgroup, level, class, fileName, zone, online, isDead = "Virtual " .. i, 0, floor((i-1)/5)+1, 60, CT_RA_PRIEST, "PRIEST", "Emerald Dream", 1, nil; end if ( UnitIsDead(unitid) or UnitIsGhost(unitid) ) then isDead = 1; end -- Set Rank if ( name == UnitName("player") ) then if ( rank >= 2 and CT_RA_Level and CT_RA_Level < 2 ) then -- Check if we have to auto-promote people for j = 1, numRaidMembers, 1 do local pName, pRank = GetRaidRosterInfo(j); if ( pRank < 1 and pName and CT_RATab_AutoPromotions and CT_RATab_AutoPromotions[pName] ) then PromoteToAssistant(pName); CT_RA_Print(" Auto-Promoted |c00FFFFFF" .. pName .. "|r.", 1, 0.5, 0); end end end CT_RA_Level = rank; end local button = getglobal("CT_RAMember" .. i); local buttoncast = button.CastFrame; local group = button.group; if ( group ) then if ( tempOptions["ShowGroups"] and tempOptions["ShowGroups"][group.id] ) then button.Name:SetText(name); button.CastFrame.unitName = name; if ( sortType ~= "virtual" or not updateType or updateType == 0 ) then if ( button.update or updateType == 0 ) then CT_RA_UpdateUnitStatus(button); else CT_RA_UpdateUnitDead(button); local stats = CT_RA_Stats[name]; if ( updateType == 2 and stats ) then CT_RA_UpdateUnitBuffs(stats["Buffs"], button, name); end end button.update = nil; else CT_RA_UpdateUnitDead(button); end end end else local btn = getglobal("CT_RAMember"..i); btn:Hide(); btn.next = nil; end end CT_RA_UpdateVisibility(1); end function CT_RA_MemberFrame_OnEnter() local tempOptions = CT_RAMenu_Options["temp"]; if ( SpellIsTargeting() ) then SetCursor("CAST_CURSOR"); end local parent = this.frameParent; local id = parent.id; if ( strsub(parent.name, 1, 12) == "CT_RAMTGroup" ) then local name; if ( CT_RA_MainTanks[id] ) then name = CT_RA_MainTanks[id]; end for i = 1, GetNumRaidMembers(), 1 do local memberName = GetRaidRosterInfo(i); if ( name == memberName ) then id = i; break; end end elseif ( strsub(parent.name, 1, 12) == "CT_RAPTGroup" ) then local name; if ( CT_RA_PTargets[id] ) then name = CT_RA_PTargets[id]; end for i = 1, GetNumRaidMembers(), 1 do local memberName = GetRaidRosterInfo(i); if ( name == memberName ) then id = i; break; end end end local unitid = "raid"..id; if ( SpellIsTargeting() and not SpellCanTargetUnit(unitid) ) then SetCursor("CAST_ERROR_CURSOR"); end if ( tempOptions["HideTooltip"] ) then return; end local xp = "LEFT"; local yp = "BOTTOM"; local xthis, ythis = this:GetCenter(); local xui, yui = UIParent:GetCenter(); if ( xthis < xui ) then xp = "RIGHT"; end if ( ythis < yui ) then yp = "TOP"; end GameTooltip:SetOwner(this, "ANCHOR_" .. yp .. xp); local name, rank, subgroup, level, class, fileName, zone, online, isDead = GetRaidRosterInfo(id); local stats = CT_RA_Stats[name]; local isVirtual; if ( not name and tempOptions["SORTTYPE"] == "virtual" ) then isVirtual = 1; name, level = "Virtual " .. id, 60; end local version = stats; if ( version ) then version = version["Version"]; end if ( name == UnitName("player") ) then zone = GetRealZoneText(); version = CT_RA_VersionNumber; end local color = RAID_CLASS_COLORS[fileName]; if ( not color ) then color = { ["r"] = 1, ["g"] = 1, ["b"] = 1 }; end GameTooltip:AddDoubleLine(name, level, color.r, color.g, color.b, 1, 1, 1); if ( UnitRace(unitid) and class ) then GameTooltip:AddLine(UnitRace(unitid) .. " " .. class, 1, 1, 1); end GameTooltip:AddLine(zone, 1, 1, 1); if ( not version and not isVirtual ) then if ( not stats or not stats["Reporting"] ) then GameTooltip:AddLine("No CTRA Found", 0.7, 0.7, 0.7); else GameTooltip:AddLine("CTRA <1.077", 1, 1, 1); end elseif ( not isVirtual ) then GameTooltip:AddLine("CTRA " .. version, 1, 1, 1); end if ( stats and stats["AFK"] ) then if ( type(stats["AFK"][1]) == "string" ) then GameTooltip:AddLine("AFK: " .. stats["AFK"][1]); end GameTooltip:AddLine("AFK for " .. CT_RA_FormatTime(stats["AFK"][2])); elseif ( CT_RA_Stats[name] and stats["DND"] ) then if ( type(stats["DND"][1]) == "string" ) then GameTooltip:AddLine("DND: " .. stats["DND"][1]); end GameTooltip:AddLine("DND for " .. CT_RA_FormatTime(stats["DND"][2])); end if ( stats and stats["Offline"] ) then GameTooltip:AddLine("Offline for " .. CT_RA_FormatTime(stats["Offline"])); elseif ( stats and stats["FD"] ) then if ( stats["FD"] < 360 ) then GameTooltip:AddLine("Dying in " .. CT_RA_FormatTime(360-stats["FD"])); end elseif ( stats and stats["Dead"] ) then if ( stats["Dead"] < 360 and not UnitIsGhost(unitid) ) then GameTooltip:AddLine("Releasing in " .. CT_RA_FormatTime(360-stats["Dead"])); else GameTooltip:AddLine("Dead for " .. CT_RA_FormatTime(stats["Dead"])); end end if ( stats and stats["Rebirth"] and stats["Rebirth"] > 0 ) then GameTooltip:AddLine("Rebirth up in: " .. CT_RA_FormatTime(stats["Rebirth"])); elseif ( stats and stats["Reincarnation"] and stats["Reincarnation"] > 0 ) then GameTooltip:AddLine("Ankh up in: " .. CT_RA_FormatTime(stats["Reincarnation"])); elseif ( stats and stats["Soulstone"] and stats["Soulstone"] > 0 ) then GameTooltip:AddLine("Soulstone up in: " .. CT_RA_FormatTime(stats["Soulstone"])); end GameTooltip:Show(); CT_RA_CurrentMemberFrame = this; end function CT_RA_FormatTime(num) num = floor(num + 0.5); local hour, min, sec, str = 0, 0, 0, ""; hour = floor(num/3600); min = floor(mod(num, 3600)/60); sec = mod(num, 60); if ( hour > 0 ) then str = hour .. "h"; end if ( min > 0 ) then if ( strlen(str) > 0 ) then str = str .. ", "; end str = str .. min .. "m"; end if ( sec > 0 or strlen(str) == 0 ) then if ( strlen(str) > 0 ) then str = str .. ", "; end str = str .. sec .. "s"; end return str; end function CT_RA_Drag_OnEnter() CT_RAMenuHelp_SetTooltip(); GameTooltip:SetText("Click to drag"); end function CT_RA_RecastBuffButton() if ( this.owner and this.name and this.type == "BUFF" ) then local spell = CT_RA_ClassSpells[this.name]; if ( spell ) then local targetName = UnitName("target"); for i = 1, GetNumRaidMembers(), 1 do local uId = "raid"..i; if ( UnitName(uId) == this.owner ) then TargetUnit(uId); break; end end local newTargetName = UnitName("target"); if ( newTargetName == this.owner ) then CastSpell(spell["spell"], spell["tab"]+1); end if ( newTargetName ~= targetName ) then TargetLastTarget(); end end return; elseif ( this.owner and this.name and this.type == "DEBUFF" ) then local stats = CT_RA_Stats[this.owner]; if ( stats ) then local debuff = stats["Debuffs"][this.name]; if ( debuff ) then for i = 1, GetNumRaidMembers(), 1 do if ( UnitName("raid" .. i) == this.owner ) then CT_RADebuff_CureTarget(debuff[1], this.name, "raid" .. i); return; end end end end end end function CT_RA_BuffButton_OnEnter() if ( CT_RA_LockPosition ) then return; end CT_RAMenuHelp_SetTooltip(); local left, secure; local stats = CT_RA_Stats[this.owner]; if ( stats and stats["Buffs"][this.name] and stats["Buffs"][this.name][2] ) then left = stats["Buffs"][this.name][2]; if ( stats["Reporting"] and ( stats["Version"] or 0 ) >= 1.38 ) then secure = 1; end end if ( this.name and left ) then local str; if ( left >= 60 ) then secs = mod(left, 60); mins = (left-secs)/60; else mins = 0; secs = left; end if ( mins < 0 ) then mins = "00"; elseif ( mins < 10 ) then mins = "0" .. mins; end if ( secs < 0 ) then secs = "00"; elseif ( secs < 10 ) then secs = "0" .. secs; end if ( not secure ) then GameTooltip:SetText(this.name .. " (" .. mins .. ":" .. secs .. "?)"); else GameTooltip:SetText(this.name .. " (" .. mins .. ":" .. secs .. ")"); end elseif ( this.name ) then GameTooltip:SetText(this.name); end end function CT_RA_AssistMT(id) if ( CT_RA_MainTanks[id] ) then for i = 1, GetNumRaidMembers(), 1 do local uId = "raid" .. i; if ( UnitName(uId) == CT_RA_MainTanks[id] ) then AssistUnit(uId); return; end end end end function CT_RA_TargetMT(id) if ( CT_RA_MainTanks[id] ) then for i = 1, GetNumRaidMembers(), 1 do local uId = "raid" .. i; if ( UnitName(uId) == CT_RA_MainTanks[id] ) then TargetUnit(uId); return; end end end end function CT_RA_AssistPT(id) if ( CT_RA_PTargets[id] ) then for i = 1, GetNumRaidMembers(), 1 do local uId = "raid" .. i; if ( UnitName(uId) == CT_RA_PTargets[id] ) then AssistUnit(uId); return; end end end end function CT_RA_TargetPT(id) if ( CT_RA_PTargets[id] ) then for i = 1, GetNumRaidMembers(), 1 do local uId = "raid" .. i; if ( UnitName(uId) == CT_RA_PTargets[id] ) then TargetUnit(uId); return; end end end end function CT_RA_MemberFrame_OnClick(button) local parent = this.frameParent; local id = parent.id; local unitid = "raid" .. id; if ( strsub(parent.name, 1, 12) == "CT_RAMTGroup" ) then for i = 1, GetNumRaidMembers(), 1 do local uId = "raid" .. i; if ( UnitName(uId) == CT_RA_MainTanks[id] ) then AssistUnit(uId); return; end end elseif ( strsub(parent.name, 1, 12) == "CT_RAPTGroup" ) then for i = 1, GetNumRaidMembers(), 1 do local uId = "raid" .. i; if ( UnitName(uId) == CT_RA_PTargets[id] ) then TargetUnit(uId); return; end end end local stopDefaultBehaviour; if ( type(CT_RA_CustomOnClickFunction) == "function" ) then stopDefaultBehaviour = CT_RA_CustomOnClickFunction(button, unitid); end if ( not stopDefaultBehaviour ) then if ( SpellIsTargeting() ) then SpellTargetUnit(unitid); else TargetUnit(unitid); end end end function CT_RA_SendStatus() CT_RA_Auras = { ["buffs"] = { }, ["debuffs"] = { } }; -- Reset everything so every buff & debuff is treated as new CT_RA_AddMessage("V " .. CT_RA_VersionNumber); end function CT_RA_AddToQueue(type, nick, name) tinsert(CT_RA_BuffsToCure, { ["type"] = type, ["nick"] = nick, ["name"] = name }); end function CT_RA_GetDebuff() return tremove(CT_RA_BuffsToCure); end function CT_RA_GetCure(school) local arr = { [CT_RA_PRIEST] = { [CT_RA_MAGIC] = CT_RA_DISPELMAGIC, [CT_RA_DISEASE] = { CT_RA_CUREDISEASE, CT_RA_ABOLISHDISEASE } }, [CT_RA_SHAMAN] = { [CT_RA_DISEASE] = CT_RA_CUREDISEASE, [CT_RA_POISON] = CT_RA_CUREPOISON }, [CT_RA_DRUID] = { [CT_RA_CURSE] = CT_RA_REMOVECURSE, [CT_RA_POISON] = { CT_RA_CUREPOISON, CT_RA_ABOLISHPOISON } }, [CT_RA_MAGE] = { [CT_RA_CURSE] = CT_RA_REMOVELESSERCURSE }, [CT_RA_PALADIN] = { [CT_RA_MAGIC] = CT_RA_CLEANSE, [CT_RA_POISON] = { CT_RA_PURIFY, CT_RA_CLEANSE }, [CT_RA_DISEASE] = { CT_RA_PURIFY, CT_RA_CLEANSE } } }; local playerArr = arr[UnitClass("player")]; if ( playerArr and playerArr[school] ) then local tmp = playerArr[school]; if ( type(tmp) == "table" ) then for i = getn(tmp), 1, -1 do if ( CT_RA_ClassSpells[tmp[i]] ) then return tmp[i]; end end return nil; else if ( CT_RA_ClassSpells[tmp] ) then return tmp; else return nil; end end end return nil; end function CT_RA_UpdateRaidGroupColors() local tempOptions = CT_RAMenu_Options["temp"]; local defaultColors = tempOptions["DefaultColor"]; local r, g, b, a = defaultColors.r, defaultColors.g, defaultColors.b, defaultColors.a; for y = 1, 40, 1 do local frame = getglobal("CT_RAMember" .. y); if ( y <= 5 ) then local mt = getglobal("CT_RAMTGroupMember" .. y); mt:SetBackdropColor(r, g, b, a); mt.Percent:SetTextColor(r, g, b); mt = getglobal("CT_RAPTGroupMember" .. y); mt:SetBackdropColor(r, g, b, a); mt.Percent:SetTextColor(r, g, b); end if ( not frame.status ) then frame:SetBackdropColor(r, g, b, a); end frame.Percent:SetTextColor(r, g, b); local name = UnitName("raid"..y); if ( CT_RA_Stats[name] ) then CT_RA_UpdateUnitBuffs(CT_RA_Stats[name]["Buffs"], frame, name); end end end function CT_RA_UpdateRaidGroupColors() local tempOptions = CT_RAMenu_Options["temp"]; for y = 1, 40, 1 do if ( y <= 5 ) then getglobal("CT_RAMTGroupMember" .. y):SetBackdropColor(tempOptions["DefaultColor"].r, tempOptions["DefaultColor"].g, tempOptions["DefaultColor"].b, tempOptions["DefaultColor"].a); getglobal("CT_RAMTGroupMember" .. y .. "Percent"):SetTextColor(tempOptions["PercentColor"].r, tempOptions["PercentColor"].g, tempOptions["PercentColor"].b); end if ( not getglobal("CT_RAMember" .. y).status ) then getglobal("CT_RAMember" .. y):SetBackdropColor(tempOptions["DefaultColor"].r, tempOptions["DefaultColor"].g, tempOptions["DefaultColor"].b, tempOptions["DefaultColor"].a); end getglobal("CT_RAMember" .. y .. "Percent"):SetTextColor(tempOptions["PercentColor"].r, tempOptions["PercentColor"].g, tempOptions["PercentColor"].b); if ( CT_RA_Stats[UnitName("raid"..y)] ) then CT_RA_UpdateUnitBuffs(CT_RA_Stats[UnitName("raid"..y)]["Buffs"], getglobal("CT_RAMember"..y), UnitName("raid"..y)); end end end function CT_RA_UpdateRaidMovability() local tempOptions = CT_RAMenu_Options["temp"]; for i = 1, 8, 1 do if ( tempOptions["LockGroups"] or not tempOptions["ShowGroups"] or not tempOptions["ShowGroups"][i] ) then getglobal("CT_RAGroupDrag" .. i):Hide(); else if ( getglobal("CT_RAGroup" .. i).next ) then getglobal("CT_RAGroupDrag" .. i):Show(); end end end if ( tempOptions["LockGroups"] or not tempOptions["ShowMTs"] or tempOptions["HideMTs"] ) then getglobal("CT_RAMTGroupDrag"):Hide(); else for i = 1, 10, 1 do if ( CT_RA_MainTanks[i] ) then CT_RAMTGroupDrag:Show(); break; else CT_RAMTGroupDrag:Hide(); end end end end function CT_RA_AddToBuffQueue(name, nick) tinsert(CT_RA_BuffsToRecast, { ["name"] = name, ["nick"] = nick }); end function CT_RA_GetBuff() return tremove(CT_RA_BuffsToRecast); end function CT_RA_RecastLastBuff() local tempOptions = CT_RAMenu_Options["temp"]; local buff = CT_RA_GetBuff(); while ( buff ) do if ( CT_RA_Stats[UnitName(buff["nick"])] and CT_RA_Stats[UnitName(buff["nick"])]["Buffs"][buff["name"]] ) then buff = CT_RA_GetBuff(); else CT_RA_LastCastSpell = buff; CT_RA_LastCast = GetTime(); CT_RA_LastCastType = "buff"; local couldNotCast; local i, targetunit, targetname; if ( tempOptions["MaintainTarget"] ) then -- Check parties if ( UnitExists("target") ) then for i = 1, 40, 1 do if ( UnitIsUnit("raid" ..i, "target") ) then targetunit = "raid" .. i; break; end end if ( UnitIsUnit("target", "pet" ) ) then targetunit = "pet"; elseif ( UnitIsUnit("target", "player" ) ) then targetunit = "player"; elseif ( not UnitCanAttack("player", "target") ) then targetunit = "friend"; targetname = UnitName("target"); else targetunit = "lastenemy"; end end TargetUnit(buff["nick"]); if ( not UnitIsUnit("target", buff["nick"]) ) then if ( targetunit ) then if ( targetunit == "lastenemy" ) then TargetLastEnemy(); elseif ( targetunit == "friend" ) then TargetByName(targetname); else TargetUnit(targetunit); end else ClearTarget(); end return; end else TargetUnit(buff["nick"]); end if ( buff["name"] and CT_RA_ClassSpells[buff["name"]] ) then if ( UnitIsUnit("target", buff["nick"]) ) then CastSpell(CT_RA_ClassSpells[buff["name"]]["spell"], CT_RA_ClassSpells[buff["name"]]["tab"]+1); end if ( SpellIsTargeting() and not SpellCanTargetUnit(buff["nick"]) ) then SpellStopTargeting(); couldNotCast = 1; elseif ( SpellIsTargeting() and SpellCanTargetUnit(buff["nick"]) ) then SpellStopTargeting(); tinsert(CT_RA_BuffsToRecast, 1, buff); end end if ( targetunit and tempOptions["MaintainTarget"] ) then if ( targetunit == "lastenemy" ) then TargetLastEnemy(); elseif ( targetunit == "friend" ) then TargetByName(targetname); else TargetUnit(targetunit); end elseif ( tempOptions["MaintainTarget"] ) then ClearTarget(); end break; end buff = couldNotCast; end end function CT_RA_Print(msg, r, g, b) if ( SIMPLE_CHAT == "1" ) then DEFAULT_CHAT_FRAME:AddMessage(msg, r, g, b); else local oldArgs = { event, this, arg1, arg2, arg3, arg4, arg6 }; event = "CHAT_MSG_CTRAID"; arg1 = msg; arg2, arg3, arg4, arg6 = "", "", "", ""; local info = CT_RA_ChatInfo[UnitName("player")]; if ( not info ) then info = CT_RA_ChatInfo["Default"]; end for i = 1, 7, 1 do for k, v in info["show"] do local frameName = "ChatFrame" .. i; if ( v == frameName ) then this = getglobal(frameName); CT_RA_oldChatFrame_OnEvent(event); break; end end end event, this, arg1, arg2, arg3, arg4, arg6 = oldArgs[1], oldArgs[2], oldArgs[3], oldArgs[4], oldArgs[5], oldArgs[6], oldArgs[7]; end end function CT_RA_SubSortByName() local tempOptions = CT_RAMenu_Options["temp"]; -- Sort the name of the players in the raid. -- Returns an array containing raid roster numbers in player name sequence, followed by unfilled player slots. -- Thanks to Dargen of Eternal Keggers for this function local temp; local subsort = {}; local count; local name; count = GetNumRaidMembers(); if ( not tempOptions["SubSortByName"] ) then for i = 1, MAX_RAID_MEMBERS, 1 do subsort[i] = {}; subsort[i][1] = i; end return subsort; end local playerName = UnitName("player"); for i = 1, MAX_RAID_MEMBERS, 1 do subsort[i] = {}; subsort[i][1] = i; if ( i <= count ) then name = UnitName("raid" .. i); if ( not name ) then name = playerName; end if ((name == nil) or (name == UNKNOWNOBJECT) or (name == UKNOWNBEING)) then name = ""; end subsort[i][2] = name; else subsort[i][2] = ""; end end local swap; for j = 1, count - 1, 1 do swap = false; for i = 1, count - j, 1 do if ( subsort[i][2] > subsort[i+1][2] ) then -- Swap temp = subsort[i]; subsort[i] = subsort[i+1]; subsort[i+1] = temp; swap = true; end end if ( not swap ) then break; end end return subsort; end function CT_RA_SortByClass() local tempOptions = CT_RAMenu_Options["temp"]; CT_RA_SetSortType("class"); CT_RA_ButtonIndexes = { }; CT_RA_CurrPositions = { }; local groupnum = 1; local membernum = 1; for k, v in CT_RA_ClassPositions do if ( k ~= CT_RA_SHAMAN or ( UnitFactionGroup("player") and UnitFactionGroup("player") == "Horde" ) ) then getglobal("CT_RAOptionsGroup" .. v .. "Label"):SetText(k); end end for i = 1, 40, 1 do if ( i <= 8 ) then getglobal("CT_RAGroup" .. i).next = nil; getglobal("CT_RAGroup" .. i).num = 0; end getglobal("CT_RAMember" .. i).next = nil; end local subsort = CT_RA_SubSortByName(); for j = 1, GetNumRaidMembers(), 1 do i = subsort[j][1]; local name, rank, subgroup, level, class, fileName, zone, online, isDead = GetRaidRosterInfo(i); if ( class and CT_RA_ClassPositions[class] ) then local group = getglobal("CT_RAGroup" .. CT_RA_ClassPositions[class]); if ( name ) then CT_RA_CurrPositions[name] = { CT_RA_ClassPositions[class], i }; end local button = getglobal("CT_RAMember" .. i); getglobal(group:GetName() .. "GroupName"):SetText(class); local modifier = 0.5; if ( not online ) then modifier = 0.3; end getglobal("CT_RAOptionsGroupButton" .. i .."Texture"):SetVertexColor(modifier, modifier, modifier); getglobal("CT_RAOptionsGroupButton" .. i .."Rank"):SetTextColor(modifier, modifier, modifier); getglobal("CT_RAOptionsGroupButton" .. i .."Name"):SetTextColor(modifier, modifier, modifier); getglobal("CT_RAOptionsGroupButton" .. i .."Level"):SetTextColor(modifier, modifier, modifier); getglobal("CT_RAOptionsGroupButton" .. i .."Class"):SetTextColor(modifier, modifier, modifier); if ( not tempOptions["HideOffline"] or online ) then button:ClearAllPoints(); local new, newName; if ( group.next and group.next ~= button ) then new = group; while ( new.next ) do if ( new.next ) then new = new.next; end end newName = new.name; group.num = group.num + 1; if ( tempOptions["ShowHorizontal"] ) then if ( tempOptions["HideBorder"] ) then if ( tempOptions["HideSpace"] ) then button:SetPoint("LEFT", newName, "RIGHT", -10, 0); else button:SetPoint("LEFT", newName, "RIGHT", -8, 0); end else button:SetPoint("LEFT", newName, "RIGHT", -2, 0); end else if ( tempOptions["HideBorder"] ) then if ( tempOptions["HideSpace"] ) then if ( tempOptions["ShowReversed"] ) then button:SetPoint("BOTTOMLEFT", newName, "TOPLEFT", 0, -10); else button:SetPoint("TOPLEFT", newName, "BOTTOMLEFT", 0, 10); end else if ( tempOptions["ShowReversed"] ) then button:SetPoint("BOTTOMLEFT", newName, "TOPLEFT", 0, -7); else button:SetPoint("TOPLEFT", newName, "BOTTOMLEFT", 0, 7); end end else if ( tempOptions["ShowReversed"] ) then button:SetPoint("BOTTOMLEFT", newName, "TOPLEFT", 0, -5); else button:SetPoint("TOPLEFT", newName, "BOTTOMLEFT", 0, 4); end end end else group.num = 1; new = group; button:ClearAllPoints(); if ( tempOptions["ShowReversed"] ) then button:SetPoint("BOTTOMLEFT", group:GetName(), "TOPLEFT", 0, -15); else button:SetPoint("TOPLEFT", group:GetName(), "TOPLEFT", 0, -20); end end new.next = button; button.group = group; end end end end function CT_RA_SortByGroup() local tempOptions = CT_RAMenu_Options["temp"]; CT_RA_SetSortType("group"); CT_RA_ButtonIndexes = { }; CT_RA_CurrPositions = { }; local groupnum = 1; local membernum = 1; for i = 1, 40, 1 do if ( i <= 8 ) then local group = getglobal("CT_RAGroup"..i); group.next = nil; group.num = 0; local label = getglobal("CT_RAOptionsGroup" .. i .. "Label"); if ( label ) then label:SetText("Group " .. i); end end getglobal("CT_RAMember" .. i).next = nil; end local subsort = CT_RA_SubSortByName(); for j = 1, GetNumRaidMembers(), 1 do i = subsort[j][1]; local name, rank, subgroup, level, class, fileName, zone, online, isDead = GetRaidRosterInfo(i); if ( ( not tempOptions["HideOffline"] or online ) and ( CT_RA_Stats[name] or not tempOptions["HideNA"] ) ) then local groupid = subgroup; if ( name and CT_RA_CurrPositions[name] ) then groupid = CT_RA_CurrPositions[name][1]; elseif ( name ) then CT_RA_CurrPositions[name] = { subgroup, j }; end local group = getglobal("CT_RAGroup" .. groupid); frameCache[group].GroupName:SetText("Group " .. subgroup); local text = getglobal("CT_RAOptionsGroupButton" .. i .."Texture"); if ( text ) then text:SetVertexColor(1.0, 1.0, 1.0); end local button = getglobal("CT_RAMember" .. i); local new, newName; button:ClearAllPoints(); if ( group.next and group.next ~= button ) then new = group; while ( new.next ) do if ( new.next ) then new = new.next; end end newName = new.name; group.num = group.num + 1; if ( tempOptions["ShowHorizontal"] ) then if ( tempOptions["HideBorder"] ) then if ( tempOptions["HideSpace"] ) then button:SetPoint("LEFT", newName, "RIGHT", -10, 0); else button:SetPoint("LEFT", newName, "RIGHT", -8, 0); end else button:SetPoint("LEFT", newName, "RIGHT", -2, 0); end else if ( tempOptions["HideBorder"] ) then if ( tempOptions["HideSpace"] ) then if ( tempOptions["ShowReversed"] ) then button:SetPoint("BOTTOMLEFT", newName, "TOPLEFT", 0, -10); else button:SetPoint("TOPLEFT", newName, "BOTTOMLEFT", 0, 10); end else if ( tempOptions["ShowReversed"] ) then button:SetPoint("BOTTOMLEFT", newName, "TOPLEFT", 0, -7); else button:SetPoint("TOPLEFT", newName, "BOTTOMLEFT", 0, 7); end end else if ( tempOptions["ShowReversed"] ) then button:SetPoint("BOTTOMLEFT", newName, "TOPLEFT", 0, -5); else button:SetPoint("TOPLEFT", newName, "BOTTOMLEFT", 0, 4); end end end else group.num = 1; new = group; button:ClearAllPoints(); if ( tempOptions["ShowReversed"] ) then button:SetPoint("BOTTOMLEFT", group.name, "TOPLEFT", 0, -15); else button:SetPoint("TOPLEFT", group.name, "TOPLEFT", 0, -20); end end new.next = button; button.group = group; end end end function CT_RA_SortByVirtual(updateStatus) local tempOptions = CT_RAMenu_Options["temp"]; CT_RA_SetSortType("virtual"); local groupnum = 1; local membernum = 1; local availableSlots = { [1] = 0, [2] = 0, [3] = 0, [4] = 0, [5] = 0, [6] = 0, [7] = 0, [8] = 0 }; for i = 1, 40, 1 do if ( i <= GetNumRaidMembers() ) then local name, rank, subgroup, level, class, fileName, zone, online, isDead = GetRaidRosterInfo(i); availableSlots[subgroup] = availableSlots[subgroup] + 1; end if ( i <= 8 ) then local group = getglobal("CT_RAGroup"..i); group.next = nil; group.num = 0; local label = getglobal("CT_RAOptionsGroup" .. i .. "Label"); if ( label ) then label:SetText("Virtual " .. i); end end getglobal("CT_RAMember" .. i).next = nil; end local subsort = CT_RA_SubSortByName(); for j = 1, 40, 1 do local i = subsort[j][1]; local name, rank, subgroup, level, class, fileName, zone, online, isDead = GetRaidRosterInfo(i); local isVirtual; if ( not name ) then isVirtual = 1; name, rank, level, class, fileName, zone, online, isDead = "Virtual " .. i, 0, 60, CT_RA_PRIEST, "PRIEST", "Emerald Dream", 1, nil; for i = 1, 8, 1 do if ( availableSlots[i] < 5 ) then availableSlots[i] = availableSlots[i] + 1; subgroup = i; break; end end end local groupid = subgroup; local group = getglobal("CT_RAGroup" .. groupid); frameCache[group].GroupName:SetText("Virtual " .. subgroup); local text = getglobal("CT_RAOptionsGroupButton" .. i .."Texture"); if ( text ) then text:SetVertexColor(1.0, 1.0, 1.0); end local button = getglobal("CT_RAMember" .. i); local new, newName; if ( group.next and group.next ~= button ) then new = group; while ( new.next ) do new = new.next; end newName = new.name; group.num = group.num + 1; button:ClearAllPoints(); if ( tempOptions["ShowHorizontal"] ) then if ( tempOptions["HideBorder"] ) then if ( tempOptions["HideSpace"] ) then button:SetPoint("LEFT", newName, "RIGHT", -10, 0); else button:SetPoint("LEFT", newName, "RIGHT", -8, 0); end else button:SetPoint("LEFT", newName, "RIGHT", -2, 0); end else if ( tempOptions["HideBorder"] ) then if ( tempOptions["HideSpace"] ) then if ( tempOptions["ShowReversed"] ) then button:SetPoint("BOTTOMLEFT", newName, "TOPLEFT", 0, -10); else button:SetPoint("TOPLEFT", newName, "BOTTOMLEFT", 0, 10); end else if ( tempOptions["ShowReversed"] ) then button:SetPoint("BOTTOMLEFT", newName, "TOPLEFT", 0, -7); else button:SetPoint("TOPLEFT", newName, "BOTTOMLEFT", 0, 7); end end else if ( tempOptions["ShowReversed"] ) then button:SetPoint("BOTTOMLEFT", newName, "TOPLEFT", 0, -5); else button:SetPoint("TOPLEFT", newName, "BOTTOMLEFT", 0, 4); end end end else group.num = 1; new = group; button:ClearAllPoints(); if ( tempOptions["ShowReversed"] ) then button:SetPoint("BOTTOMLEFT", group.name, "TOPLEFT", 0, -15); else button:SetPoint("TOPLEFT", group.name, "TOPLEFT", 0, -20); end end new.next = button; button.group = group; group:Show(); CT_RA_UpdateGroupVisibility(groupid, 1); if ( not updateStatus ) then CT_RA_UpdateUnitStatus(button); end end end function CT_RA_SortByCustom() local tempOptions = CT_RAMenu_Options["temp"]; tempOptions["SORTTYPE"] = "custom"; local groupnum = 1; local membernum = 1; for i = 1, 40, 1 do if ( i <= 8 ) then local group = getglobal("CT_RAGroup" .. i); group.next = nil; group.num = 0; local label = getglobal("CT_RAOptionsGroup" .. i .. "Label"); if ( label ) then label:SetText("Custom " .. i); end end getglobal("CT_RAMember" .. i).next = nil; end local subsort = CT_RA_SubSortByName(); for j = 1, GetNumRaidMembers(), 1 do local i = subsort[j][1]; local name, rank, subgroup, level, class, fileName, zone, online, isDead = GetRaidRosterInfo(i); local text = getglobal("CT_RAOptionsGroupButton" .. i .."Texture"); if ( text ) then text:SetVertexColor(1.0, 1.0, 1.0); end if ( ( not tempOptions["HideOffline"] or online ) and ( CT_RA_Stats[name] or not tempOptions["HideNA"] ) ) then if ( name and CT_RA_CurrPositions[name] ) then subgroup = CT_RA_CurrPositions[name][1]; elseif ( name ) then for y = 1, 8, 1 do local group = getglobal("CT_RAGroup" .. y); if ( not group.num or group.num < 5 ) then subgroup = y; CT_RA_CurrPositions[name] = { y, j }; break; end end end if ( name ) then local group = getglobal("CT_RAGroup" .. subgroup); local button = getglobal("CT_RAMember" .. i); frameCache[group].GroupName:SetText("Custom " .. subgroup); button:ClearAllPoints(); local new, newName; if ( group.next and group.next ~= button ) then new = group; while ( new.next ) do if ( new.next ) then new = new.next; end end newName = new.name; group.num = group.num + 1; button:ClearAllPoints(); if ( tempOptions["ShowHorizontal"] ) then if ( tempOptions["HideBorder"] ) then if ( tempOptions["HideSpace"] ) then button:SetPoint("LEFT", newName, "RIGHT", -10, 0); else button:SetPoint("LEFT", newName, "RIGHT", -8, 0); end else button:SetPoint("LEFT", newName, "RIGHT", -2, 0); end else if ( tempOptions["HideBorder"] ) then if ( tempOptions["HideSpace"] ) then if ( tempOptions["ShowReversed"] ) then button:SetPoint("BOTTOMLEFT", newName, "TOPLEFT", 0, -10); else button:SetPoint("TOPLEFT", newName, "BOTTOMLEFT", 0, 10); end else if ( tempOptions["ShowReversed"] ) then button:SetPoint("BOTTOMLEFT", newName, "TOPLEFT", 0, -7); else button:SetPoint("TOPLEFT", newName, "BOTTOMLEFT", 0, 7); end end else if ( tempOptions["ShowReversed"] ) then button:SetPoint("BOTTOMLEFT", newName, "TOPLEFT", 0, -5); else button:SetPoint("TOPLEFT", newName, "BOTTOMLEFT", 0, 4); end end end else group.num = 1; new = group; button:ClearAllPoints(); if ( tempOptions["ShowReversed"] ) then button:SetPoint("BOTTOMLEFT", group.name, "TOPLEFT", 0, -15); else button:SetPoint("TOPLEFT", group.name, "TOPLEFT", 0, -20); end end new.next = button; button.group = group; end end end end function CT_RA_LinkDrag(frame, drag, point, relative, x, y) frame:ClearAllPoints(); frame:SetPoint(point, drag:GetName(), relative, x, y); end CT_RA_ConvertedRaid = 1; CT_RA_HasInvited = { }; local CT_RA_GameTooltip_ClearMoney; local function CT_RA_MoneyToggle() if( CT_RA_GameTooltip_ClearMoney ) then GameTooltip_ClearMoney = CT_RA_GameTooltip_ClearMoney; CT_RA_GameTooltip_ClearMoney = nil; else CT_RA_GameTooltip_ClearMoney = GameTooltip_ClearMoney; GameTooltip_ClearMoney = CT_RA_GameTooltipFunc_ClearMoney; end end function CT_RA_GameTooltipFunc_ClearMoney() end function CT_RA_GetBuffIndex(name, filter) local i = 0; local buffIndex, untilCancelled = GetPlayerBuff(i, filter); while ( buffIndex ~= -1 ) do CT_RA_MoneyToggle(); CT_RATooltip:SetPlayerBuff(buffIndex); CT_RA_MoneyToggle(); local tooltipName = CT_RATooltipTextLeft1:GetText(); if ( tooltipName and name == tooltipName ) then return buffIndex; end i = i + 1; buffIndex, untilCancelled = GetPlayerBuff(i, filter); end return nil; end function CT_RA_UpdateFrame_OnUpdate(elapsed) if ( this.showDialog ) then this.showDialog = this.showDialog - elapsed; if ( this.showDialog <= 0 ) then if ( CT_RAChanges_DisplayDialog ) then CT_RAChanges_DisplayDialog(); end this.showDialog = nil; end end if ( this.lastInvite ) then this.lastInvite = this.lastInvite - elapsed; if ( this.lastInvite <= 0 ) then this.lastInvite = nil; this.inviteName = nil; end end if ( this.invite ) then this.invite = this.invite - elapsed; if ( this.invite <= 0 ) then if ( not CT_RA_ConvertedRaid ) then GuildRoster(); CT_RA_ConvertedRaid = 1; ConvertToRaid(); this.invite = 3; else CT_RA_InviteGuild(CT_RA_MinLevel, CT_RA_MaxLevel); this.invite = nil; end end end if ( this.startinviting ) then this.startinviting = this.startinviting - elapsed; if ( this.startinviting <= 0 ) then this.startinviting = nil; CT_RA_HasInvited = { }; if ( GetNumRaidMembers() == 0 ) then CT_RA_ConvertedRaid = nil; else CT_RA_ConvertedRaid = 1; end local inZone = ""; if ( CT_RA_ZoneInvite ) then inZone = " from " .. GetRealZoneText(); end local numInvites = CT_RA_InviteGuild(CT_RA_MinLevel, CT_RA_MaxLevel); if ( CT_RA_MinLevel == CT_RA_MaxLevel ) then CT_RA_Print(" " .. numInvites .. " Guild Members of level |c00FFFFFF" .. CT_RA_MinLevel .. "|r have been invited" .. inZone .. ".", 1, 0.5, 0); else CT_RA_Print(" " .. numInvites .. " Guild Members of levels |c00FFFFFF" .. CT_RA_MinLevel .. "|r to |c00FFFFFF" .. CT_RA_MaxLevel .. "|r have been invited" .. inZone .. ".", 1, 0.5, 0); end end end if ( this.closeroster ) then this.closeroster = this.closeroster - elapsed; if ( this.closeroster <= 0 ) then HideUIPanel(FriendsFrame); this.closeroster = nil; end end if ( this.joinchan ) then this.joinchan = this.joinchan - elapsed; if ( this.joinchan <= 0 ) then CT_RA_Channel = this.newchan; CT_RA_Join(CT_RA_Channel); this.joinchan = nil; this.newchan = nil; end end -- Only run the ones below if we're in a raid. if ( CT_RA_NumRaidMembers == 0 ) then return; end this.mouseOverUpdate = this.mouseOverUpdate - elapsed; if ( this.mouseOverUpdate <= 0 ) then this.mouseOverUpdate = 0.1; if ( CT_RA_CurrentMemberFrame ) then local parent = CT_RA_CurrentMemberFrame.frameParent; if ( SpellIsTargeting() and ( strsub(parent.name, 1, 12) == "CT_RAMTGroup" or SpellCanTargetUnit("raid" .. parent.id) ) ) then SetCursor("CAST_CURSOR"); elseif ( SpellIsTargeting() ) then SetCursor("CAST_ERROR_CURSOR"); end end end if ( this.hasAggroAlert ) then this.hasAggroAlert = this.hasAggroAlert - elapsed; if ( this.hasAggroAlert <= 0 ) then this.hasAggroAlert = nil; end end this.updateAFK = this.updateAFK + elapsed; if ( this.updateAFK >= 1 ) then this.updateAFK = this.updateAFK - 1; for k, v in CT_RA_Stats do if ( v["AFK"] ) then v["AFK"][2] = v["AFK"][2] + 1; end if ( v["DND"] ) then v["DND"][2] = v["DND"][2] + 1; end if ( v["Dead"] ) then v["Dead"] = v["Dead"] + 1; end if ( v["Offline"] ) then v["Offline"] = v["Offline"] + 1; end if ( v["FD"] ) then v["FD"] = v["FD"] + 1; end if ( v["Rebirth"] ) then v["Rebirth"] = v["Rebirth"] - 1; end if ( v["Reincarnation"] ) then v["Reincarnation"] = v["Reincarnation"] - 1; end if ( v["Soulstone"] ) then v["Soulstone"] = v["Soulstone"] - 1; end end end this.update = this.update + elapsed; if ( this.update >= 1 ) then for k, v in CT_RA_BuffTimeLeft do local buffIndex, buffTimeLeft, buffName; buffIndex = CT_RA_GetBuffIndex(k, "HELPFUL"); if ( buffIndex ) then buffTimeLeft = GetPlayerBuffTimeLeft(buffIndex); if ( buffTimeLeft ) then if ( abs(CT_RA_BuffTimeLeft[k]-buffTimeLeft) >= 2 ) then local index, num; for key, val in CT_RAMenu_Options["temp"]["BuffArray"] do if ( type(val["name"]) == "table" ) then if ( k == val["name"][1] ) then buffName = k; index, num = key, 1; break; elseif ( k == val["name"][2] ) then buffName = k; index, num = key, 2; break; end elseif ( val["name"] == k ) then buffName = k; index, num = key, 0; break; end end if ( not index and not num ) then if ( k == CT_RA_FEIGNDEATH[CT_RA_GetLocale()] ) then buffName = CT_RA_FEIGNDEATH[CT_RA_GetLocale()]; index, num = 0, 0; end end if ( index and num ) then local playerName = UnitName("player"); local stats = CT_RA_Stats[playerName]; if ( not stats ) then CT_RA_Stats[playerName] = { ["Buffs"] = { }, ["Debuffs"] = { }, ["Position"] = { } }; stats = CT_RA_Stats[playerName]; end stats["Buffs"][buffName] = { string.find(GetPlayerBuffTexture(buffIndex), "([%w_&]+)$"), floor(buffTimeLeft+0.5) }; CT_RA_AddMessage("RN " .. floor(buffTimeLeft+0.5) .. " " .. index .. " " .. num); end end CT_RA_BuffTimeLeft[k] = buffTimeLeft; end end end for k, v in CT_RA_Stats do if ( v["Buffs"] ) then for key, val in v["Buffs"] do if ( type(val) == "table" and val[2] ) then val[2] = val[2] - 1; end end end end this.update = this.update - 1; end if ( this.time ) then this.time = this.time - elapsed; if ( this.time <= 0 ) then if ( CT_RA_Channel ) then this.time = nil; CT_RA_AddMessage("SR"); if ( CT_RA_VersionNumber ) then CT_RA_AddMessage("V " .. CT_RA_VersionNumber); end else this.time = 5; end end if ( this.SS ) then this.SS = nil; end end if ( this.SS ) then this.SS = this.SS - elapsed; if ( this.SS <= 0 ) then if ( CT_RA_Channel ) then this.SS = nil; CT_RA_AddMessage("SR"); if ( CT_RA_VersionNumber ) then CT_RA_AddMessage("V " .. CT_RA_VersionNumber); end else this.SS = 5; end end end if ( this.scheduleUpdate ) then this.scheduleUpdate = this.scheduleUpdate - elapsed; if ( this.scheduleUpdate <= 0 ) then if ( CT_RA_InCombat ) then this.scheduleUpdate = 1; else this.scheduleUpdate = nil; for i = 1, GetNumRaidMembers(), 1 do if ( UnitIsUnit("raid" .. i, "player") ) then local useless, useless, subgroup = GetRaidRosterInfo(i); this.updateDelay = subgroup; return; end end end end end if ( this.scheduleMTUpdate ) then this.scheduleMTUpdate = this.scheduleMTUpdate - elapsed; if ( this.scheduleMTUpdate <= 0 ) then this.scheduleMTUpdate = nil; if ( CT_RA_IsSendingWithVersion(1.08) ) then for k, v in CT_RA_MainTanks do CT_RA_AddMessage("SET " .. k .. " " .. v); end end end end if ( this.updateDelay ) then this.updateDelay = this.updateDelay - elapsed; if ( this.updateDelay <= 0 ) then this.updateDelay = nil; CT_RA_SendStatus(); CT_RA_UpdateRaidGroup(1); end end if ( this.voteTimer ) then this.voteTimer = this.voteTimer - elapsed; if ( this.voteTimer <= 0 ) then if ( CT_RA_VotePerson ) then local numCount = 0; for i = 1, GetNumRaidMembers(), 1 do if ( UnitIsConnected("raid" .. i) ) then numCount = numCount + 1; end end local noVotes = numCount-(CT_RA_VotePerson[2]+CT_RA_VotePerson[3]+1); local yesPercent, noPercent, noVotePercent = 0, 0, 0; if ( CT_RA_VotePerson[2] > 0 ) then yesPercent = floor(CT_RA_VotePerson[2]/(CT_RA_VotePerson[2]+CT_RA_VotePerson[3]+noVotes)*100+0.5); end if ( CT_RA_VotePerson[3] > 0 ) then noPercent = floor(CT_RA_VotePerson[3]/(CT_RA_VotePerson[2]+CT_RA_VotePerson[3]+noVotes)*100+0.5); end if ( yesPercent+noPercent < 100 ) then noVotePercent = 100-(yesPercent+noPercent); end CT_RA_Print(" Vote results for \"|c00FFFFFF" .. CT_RA_VotePerson[4] .. "|r\": |c00FFFFFF" .. CT_RA_VotePerson[2] .. "|r (|c00FFFFFF" .. yesPercent .. "%|r) Yes / |c00FFFFFF" .. CT_RA_VotePerson[3] .. "|r (|c00FFFFFF" .. noPercent .. "%|r) No / |c00FFFFFF" .. noVotes .. "|r (|c00FFFFFF" .. noVotePercent .. "%|r) did not vote.", 1, 0.5, 0); SendChatMessage(" Vote results for \"" .. CT_RA_VotePerson[4] .. "\": " .. CT_RA_VotePerson[2] .. " (" .. yesPercent .. "%) Yes / " .. CT_RA_VotePerson[3] .. " (" .. noPercent .. "%) No / " .. noVotes .. " (" .. noVotePercent .. "%) did not vote.", "RAID"); CT_RA_VotePerson = nil; end this.voteTimer = nil; end end if ( this.readyTimer ) then this.readyTimer = this.readyTimer - elapsed; if ( this.readyTimer <= 0 ) then CT_RA_CheckReady_Person = nil; this.readyTimer = nil; local numNotReady, numAfk = 0, 0 local notReadyString, afkString = "", ""; for k, v in CT_RA_Stats do if ( v["notready"] and v["notready"] == 2 ) then numNotReady = numNotReady + 1; if ( strlen(notReadyString) > 0 ) then notReadyString = notReadyString .. ", "; end notReadyString = notReadyString .. "|c00FFFFFF" .. k .. "|r"; elseif ( v["notready"] and v["notready"] == 1 ) then numAfk = numAfk + 1; if ( strlen(afkString) > 0 ) then afkString = afkString .. ", "; end afkString = afkString .. "|c00FFFFFF" .. k .. "|r"; end CT_RA_Stats[k]["notready"] = nil; end if ( numNotReady > 0 ) then if ( numNotReady == 1 ) then CT_RA_Print(" " .. notReadyString .. " is not ready.", 1, 1, 0); elseif ( numNotReady >= 8 ) then CT_RA_Print(" |c00FFFFFF" .. numNotReady .. "|r raid members are not ready.", 1, 1, 0); else CT_RA_Print(" |c00FFFFFF" .. numNotReady .. "|r raid members (" .. notReadyString .. ") are not ready.", 1, 1, 0); end CT_RA_UpdateRaidGroup(1); end if ( numAfk > 0 ) then if ( numAfk == 1 ) then CT_RA_Print(" " ..afkString .. " is away from keyboard.", 1, 1, 0); elseif ( numAfk >= 8 ) then CT_RA_Print(" |c00FFFFFF" .. numAfk.. "|r raid members are away from keyboard.", 1, 1, 0); else CT_RA_Print(" |c00FFFFFF" .. numAfk .. "|r raid members (" .. afkString .. ") are away from keyboard.", 1, 1, 0); end CT_RA_UpdateRaidGroup(1); end end end if ( this.rlyTimer ) then this.rlyTimer = this.rlyTimer - elapsed; if ( this.rlyTimer <= 0 ) then this.rlyTimer = nil; local numNotReady, numAfk = 0, 0 local notReadyString, afkString = "", ""; for k, v in CT_RA_Stats do if ( v["rly"] and v["rly"] == 2 ) then numNotReady = numNotReady + 1; if ( strlen(notReadyString) > 0 ) then notReadyString = notReadyString .. ", "; end notReadyString = notReadyString .. "|c00FFFFFF" .. k .. "|r"; elseif ( v["rly"] and v["rly"] == 1 ) then numAfk = numAfk + 1; if ( strlen(afkString) > 0 ) then afkString = afkString .. ", "; end afkString = afkString .. "|c00FFFFFF" .. k .. "|r"; end CT_RA_Stats[k]["rly"] = nil; end if ( numNotReady > 0 ) then if ( numNotReady == 1 ) then CT_RA_Print(" " .. notReadyString .. " says |c00FFFFFFNO WAI!|r.", 1, 1, 0); elseif ( numNotReady >= 8 ) then CT_RA_Print(" |c00FFFFFF" .. numNotReady .. "|r raid members say |c00FFFFFFNO WAI!|r.", 1, 1, 0); else CT_RA_Print(" |c00FFFFFF" .. numNotReady .. "|r raid members (" .. notReadyString .. ") say |c00FFFFFFNO WAI!|r.", 1, 1, 0); end CT_RA_UpdateRaidGroup(1); end if ( numAfk > 0 ) then if ( numAfk == 1 ) then CT_RA_Print(" " ..afkString .. " says nothing.", 1, 1, 0); elseif ( numAfk >= 8 ) then CT_RA_Print(" |c00FFFFFF" .. numAfk.. "|r raid members say nothing.", 1, 1, 0); else CT_RA_Print(" |c00FFFFFF" .. numAfk .. "|r raid members (" .. afkString .. ") say nothing.", 1, 1, 0); end CT_RA_UpdateRaidGroup(1); end end end if ( CT_RA_Squelch > 0 ) then CT_RA_Squelch = CT_RA_Squelch - elapsed; if ( CT_RA_Squelch <= 0 ) then CT_RA_Squelch = 0; CT_RA_Print(" Quiet Mode has been automatically disabled (timed out).", 1, 0.5, 0); end end if ( this.updateMT ) then this.updateMT = this.updateMT - elapsed; if ( this.updateMT <= 0 ) then this.updateMT = 0.25; CT_RA_UpdateMTs(); CT_RA_UpdatePTs(); end end for k, v in CT_RA_CurrDebuffs do CT_RA_CurrDebuffs[k][1] = CT_RA_CurrDebuffs[k][1] - elapsed; if ( CT_RA_CurrDebuffs[k][1] < 0 ) then local _, _, name, dType = string.find(k, "^([^@]+)@(.+)$"); local msg = ""; if ( GetBindingKey("CT_CUREDEBUFF") and CT_RA_GetCure(dType) ) then msg = " Press '|c00FFFFFF" .. GetBindingText(GetBindingKey("CT_CUREDEBUFF"), "KEY_") .. "|r' to cure"; end if ( name == dType ) then dType = ""; else dType = " (|c00FFFFFF" .. dType .. "|r)"; end if ( CT_RA_CurrDebuffs[k][2] == 1 ) then CT_RA_Print(" |c00FFFFFF" .. CT_RA_CurrDebuffs[k][4] .. "|r has been debuffed by '|c00FFFFFF" .. name .. "|r'" .. dType .. msg .. ".", 1, 0.5, 0); else CT_RA_Print(" |c00FFFFFF" .. CT_RA_CurrDebuffs[k][2] .. "|r players have been debuffed by '|c00FFFFFF" .. name .. "|r'" .. dType .. msg .. ".", 1, 0.5, 0); end CT_RA_CurrDebuffs[k] = nil; end end end function CT_RA_UpdateFrame_OnEvent(event) if ( event == "PARTY_MEMBERS_CHANGED" ) then if ( not CT_RA_ConvertedRaid ) then this.invite = 3; end elseif ( event == "CHAT_MSG_SYSTEM" ) then local _, _, name = string.find(arg1, "^([^%s]+) is already in a group%.$"); if ( name and this.inviteName and this.inviteName == name ) then this.inviteName = nil; this.lastInvite = nil; SendChatMessage(" You are already grouped.", "WHISPER", nil, name); end end end function CT_RA_InviteGuild(min, max) local offline = GetGuildRosterShowOffline(); local selection = GetGuildRosterSelection(); SetGuildRosterShowOffline(0); SetGuildRosterSelection(0); GetGuildRosterInfo(0); local inviteBeforeRaid = 4-GetNumPartyMembers(); local numInvites = 0; local numGuildMembers = GetNumGuildMembers(); CT_RA_UpdateFrame.closeroster = 2; local RealZoneText = GetRealZoneText(); if (RealZoneText == nil) then RealZoneText = "?"; end local playerName = UnitName("player"); for i = 1, numGuildMembers, 1 do local name, rank, rankIndex, level, class, zone, note, officernote, online, status = GetGuildRosterInfo(i); if ( level >= min and level <= max and name ~= playerName and not CT_RA_HasInvited[i] and online ) then if ( zone == nil ) then zone = "???"; end if ( not CT_RA_ZoneInvite or ( CT_RA_ZoneInvite and zone == RealZoneText ) ) then CT_RA_HasInvited[i] = 1; InviteByName(name); numInvites = numInvites + 1; if ( numInvites == inviteBeforeRaid and not CT_RA_ConvertedRaid ) then CT_RA_UpdateFrame.invite = 1.5; break; end end end end SetGuildRosterShowOffline(offline); SetGuildRosterSelection(selection); return numInvites; end function CT_RA_ProcessMessages(elapsed) if ( this.flush ) then this.flush = this.flush - elapsed; if ( this.flush <= 0 ) then this.flush = 1; this.numMessagesSent = 0; end end if ( this.elapsed ) then this.elapsed = this.elapsed - elapsed; if ( this.elapsed <= 0 ) then if ( getn(CT_RA_Comm_MessageQueue) > 0 and this.numMessagesSent < 4 ) then CT_RA_SendMessageQueue(); end this.elapsed = 0.1; end end end function CT_RA_SendMessageQueue() local retstr = ""; local numSent = 0; for key, val in CT_RA_Comm_MessageQueue do if ( strlen(retstr)+strlen(val)+1 > 255 ) then CT_RA_SendMessage(retstr, 1); this.numMessagesSent = this.numMessagesSent + 1; tremove(CT_RA_Comm_MessageQueue, key); if ( this.numMessagesSent == 4 ) then return; end retstr = ""; end if ( retstr ~= "" ) then retstr = retstr .. "#"; end retstr = retstr .. val; end if ( retstr ~= "" ) then CT_RA_SendMessage(retstr, 1); this.numMessagesSent = this.numMessagesSent + 1; end CT_RA_Comm_MessageQueue = { }; end function CT_RA_Split(msg, char) local arr = { }; while (string.find(msg, char) ) do local iStart, iEnd = string.find(msg, char); tinsert(arr, strsub(msg, 1, iStart-1)); msg = strsub(msg, iEnd+1, strlen(msg)); end if ( strlen(msg) > 0 ) then tinsert(arr, msg); end return arr; end function CT_RA_IsSendingWithVersion(version) local playerName = UnitName("player"); local names = { }; if ( not CT_RA_Level or CT_RA_Level < 1 ) then return nil; end for i = 1, GetNumRaidMembers(), 1 do local name, rank, subgroup, level, class, fileName = GetRaidRosterInfo(i); local stats = CT_RA_Stats[name]; if ( rank >= 1 and name ~= playerName and stats and stats["Version"] and stats["Version"] >= version and name < playerName ) then return nil; end end return 1; end function CT_RA_ScanPartyAuras(unit) local name = UnitName(unit); if ( not name ) then return; end local id = string.gsub(unit, "^raid(%d+)$", "%1"); local stats = CT_RA_Stats[name]; if ( not stats ) then CT_RA_Stats[name] = { ["Buffs"] = { }, ["Debuffs"] = { }, ["Position"] = { } }; stats = CT_RA_Stats[name]; CT_RA_ScanUnitBuffs(unit, name, id); CT_RA_ScanUnitDebuffs(unit, name, id); CT_RA_UpdateUnitBuffs(CT_RA_Stats[name]["Buffs"], getglobal("CT_RAMember" .. id), name); else local num, numDebuffs, debuff = 0, 0, UnitDebuff(unit, 1); numDebuffs, debuff = 0, UnitDebuff(unit, 1); while ( debuff ) do numDebuffs = numDebuffs + 1; debuff = UnitDebuff(unit, numDebuffs+1); end if ( getn(CT_RA_Stats[name]["Debuffs"]) ~= numDebuffs ) then -- Debuffs CT_RA_ScanUnitDebuffs(unit, name, id); else CT_RA_ScanUnitBuffs(unit, name, id); local isFD = CT_RA_CheckFD(name, "raid" .. id); if ( isFD > 0 ) then CT_RA_UpdateUnitDead(getglobal("CT_RAMember" .. id)); end end CT_RA_UpdateUnitBuffs(CT_RA_Stats[name]["Buffs"], getglobal("CT_RAMember" .. id), name); end end function CT_RA_CheckFD(name, unit) local class = UnitClass(unit); if ( class ~= CT_RA_HUNTER and class ~= CT_RA_PRIEST ) then return 0; end local hasFD = 0; local num, buff = 0, UnitBuff(unit, 1); while ( buff ) do if ( buff == "Interface\\Icons\\Ability_Rogue_FeignDeath" ) then hasFD = 1; break; elseif ( buff == "Interface\\Icons\\Spell_Holy_GreaterHeal" ) then hasFD = 2; break; end num = num + 1; buff = UnitBuff(unit, num+1); end return hasFD; end function CT_RA_ScanUnitBuffs(unit, name, id) local tempOptions = CT_RAMenu_Options["temp"]; local oldAuras = { }; local stats = CT_RA_Stats[name]["Buffs"]; for k, v in stats do oldAuras[k] = 1; end table.setn(stats, 0); local num, buff = 0, UnitBuff(unit, 1); local duplicateTextures = { ["Interface\\Icons\\Spell_Nature_Regeneration"] = true, ["Interface\\Icons\\Spell_Nature_LightningShield"] = true }; while ( buff ) do num = num + 1; local buffName; -- Only check matching if it's not used by anything else if ( not duplicateTextures[buff] ) then for k, v in CT_RA_BuffTextures do if ( "Interface\\Icons\\" .. v[1] == buff ) then buffName = k; break; end end else CT_RATooltip:SetOwner(WorldFrame, "ANCHOR_NONE"); CT_RATooltipTextLeft1:SetText(""); CT_RATooltip:SetUnitBuff(unit, num); local tooltipName = CT_RATooltipTextLeft1:GetText(); if ( strlen(tooltipName or "") > 0 and CT_RA_BuffTextures[tooltipName] ) then buffName = tooltipName; end end if ( buffName ) then local buffT = CT_RA_BuffTextures[buffName]; if ( not stats[buffName] ) then stats[buffName] = { buff, buffT[2] }; if ( UnitIsUnit(unit, "player") ) then CT_RA_BuffTimeLeft[buffName] = buffT[2]; end end table.setn(stats, getn(stats)+1); oldAuras[buffName] = nil; end buff = UnitBuff(unit, num+1); end for k, v in oldAuras do stats[k] = nil; local buffTbl; for key, val in tempOptions["BuffArray"] do if ( k == val["name"] ) then buffTbl = val; break; end end if ( buffTbl ) then local uId = "raid" .. id; if ( not UnitIsDead(uId) and UnitIsVisible(uId) and not tempOptions["NotifyDebuffs"]["hidebuffs"] and k ~= CT_RA_POWERWORDSHIELD and k ~= CT_RA_ADMIRALSHAT ) then if ( buffTbl["show"] ~= -1 ) then local currPos = CT_RA_CurrPositions[name]; if ( currPos ) then if ( tempOptions["NotifyDebuffs"][currPos[1]] and tempOptions["NotifyDebuffsClass"][CT_RA_ClassPositions[UnitClass("raid" .. currPos[2])]] ) then if ( CT_RA_ClassSpells and CT_RA_ClassSpells[k] and GetBindingKey("CT_RECASTRAIDBUFF") ) then if ( GetBindingKey("CT_RECASTRAIDBUFF") ) then CT_RA_AddToBuffQueue(k, uId); CT_RA_Print(" '|c00FFFFFF" .. name .. "|r's '|c00FFFFFF" .. k .. "|r' has faded. Press '|c00FFFFFF" .. GetBindingText(GetBindingKey("CT_RECASTRAIDBUFF"), "KEY_") .. "|r' to recast.", 1, 0.5, 0); else CT_RA_Print(" '|c00FFFFFF" .. name .. "|r's '|c00FFFFFF" .. k .. "|r' has faded.", 1, 0.5, 0); end end end end end end end end end function CT_RA_ScanUnitDebuffs(unit, name, id) local tempOptions = CT_RAMenu_Options["temp"]; local oldAuras = { }; local stats = CT_RA_Stats[name]["Debuffs"]; for k, v in stats do oldAuras[k] = 1; end table.setn(stats, 0); local num, debuff = 0, UnitDebuff(unit, 1); while ( debuff ) do table.setn(stats, getn(stats)+1); num = num + 1; local debuffName; CT_RATooltip:SetOwner(WorldFrame, "ANCHOR_NONE"); CT_RATooltipTextLeft1:SetText(""); CT_RATooltipTextRight1:SetText(""); CT_RATooltip:SetUnitDebuff(unit, num); local tooltipName, dType = CT_RATooltipTextLeft1:GetText(), CT_RATooltipTextRight1:GetText(); if ( tooltipName and strlen(tooltipName) > 0 ) then debuffName = tooltipName; end if ( debuffName ) then oldAuras[debuffName] = nil; if ( not stats[debuffName] ) then if ( debuffName == CT_RA_WEAKENEDSOUL ) then dType = CT_RA_WEAKENEDSOUL; elseif ( debuffName == CT_RA_RECENTLYBANDAGED ) then dType = CT_RA_RECENTLYBANDAGED; end local debuffType; for k, v in tempOptions["DebuffColors"] do if ( dType == v["type"] ) then debuffType = v; break; end end if ( debuffType ) then local uId = "raid" .. id; stats[debuffName] = { dType, 0, gsub(debuff, "^Interface\\Icons\\(.+)$", "%1") }; if ( CastParty_AddDebuff ) then CastParty_AddDebuff(uId, dType); end if ( tempOptions["NotifyDebuffs"]["main"] and debuffName ~= CT_RA_RECENTLYBANDAGED and debuffName ~= CT_RA_MINDVISION and debuffType["id"] ~= -1 ) then local currPos = CT_RA_CurrPositions[name]; if ( currPos ) then if ( tempOptions["NotifyDebuffs"][currPos[1]] and tempOptions["NotifyDebuffsClass"][CT_RA_ClassPositions[UnitClass(uId)]] ) then CT_RA_AddToQueue(dType, uId); CT_RA_AddDebuffMessage(debuffName, dType, name); end end end end end end debuff = UnitDebuff(unit, num+1); end for k, v in oldAuras do stats[k] = nil; end end function CT_RA_ShowHideDebuffs() local tempOptions = CT_RAMenu_Options["temp"]; tempOptions["ShowDebuffs"] = not tempOptions["ShowDebuffs"]; if ( tempOptions["ShowDebuffs"] ) then UIDropDownMenu_SetSelectedID(CT_RAMenuFrameBuffsBuffsDropDown, 2); CT_RAMenuFrameBuffsBuffsDropDownText:SetText("Show debuffs"); elseif ( tempOptions["ShowBuffsDebuffed"] ) then UIDropDownMenu_SetSelectedID(CT_RAMenuFrameBuffsBuffsDropDown, 3); CT_RAMenuFrameBuffsBuffsDropDownText:SetText("Show buffs until debuffed"); else UIDropDownMenu_SetSelectedID(CT_RAMenuFrameBuffsBuffsDropDown, 1); CT_RAMenuFrameBuffsBuffsDropDownText:SetText("Show buffs"); end CT_RA_UpdateRaidGroup(2); end -- Thanks to Darco for the idea & some of the code CT_RA_OldChatFrame_OnEvent = ChatFrame_OnEvent; function CT_RA_NewChatFrame_OnEvent(event) if ( event == "CHAT_MSG_SYSTEM" ) then local iStart, iEnd, sName, iID, iDays, iHours, iMins, iSecs = string.find(arg1, "(.+) %(ID=(%w+)%): (%d+)d (%d+)h (%d+)m (%d+)s"); if ( sName ) then local table = date("*t"); table["sec"] = table["sec"] + (tonumber(iDays) * 86400) + (tonumber(iHours) * 3600) + (tonumber(iMins) * 60) + iSecs; arg1 = arg1 .. " ("..date("%A %b %d, %I:%M%p", time(table)) .. ")"; end elseif ( event == "CHAT_MSG_WHISPER_INFORM" ) then if ( arg1 == " You are already grouped." or string.find(arg1, " Quiet mode is enabled in the raid%. Please be quiet%. %d+ seconds remaining%.") ) then return; end end CT_RA_OldChatFrame_OnEvent(event); end ChatFrame_OnEvent = CT_RA_NewChatFrame_OnEvent; local oldDialogs = { }; oldDialogs["RESURRECTSHOW"] = StaticPopupDialogs["RESURRECT"].OnShow; oldDialogs["RESURRECT_NO_SICKNESSSHOW"] = StaticPopupDialogs["RESURRECT_NO_SICKNESS"].OnShow; oldDialogs["RESURRECT_NO_TIMERSHOW"] = StaticPopupDialogs["RESURRECT_NO_TIMER"].OnShow; oldDialogs["DEATHSHOW"] = StaticPopupDialogs["DEATH"].OnShow; StaticPopupDialogs["RESURRECT"].OnShow = function() oldDialogs["RESURRECTSHOW"]() CT_RA_AddMessage("RESSED") end; StaticPopupDialogs["RESURRECT_NO_SICKNESS"].OnShow = function() oldDialogs["RESURRECT_NO_SICKNESSSHOW"]() CT_RA_AddMessage("RESSED") end; StaticPopupDialogs["RESURRECT_NO_TIMER"].OnShow = function() oldDialogs["RESURRECT_NO_TIMERSHOW"]() CT_RA_AddMessage("RESSED") end; StaticPopupDialogs["RESURRECT"].OnHide = function() CT_RA_AddMessage("NORESSED") end; StaticPopupDialogs["RESURRECT_NO_SICKNESS"].OnHide = function() CT_RA_AddMessage("NORESSED") end; StaticPopupDialogs["RESURRECT_NO_TIMER"].OnHide = function() if ( not StaticPopup_FindVisible("DEATH") ) then CT_RA_AddMessage("NORESSED") end end; StaticPopupDialogs["DEATH"].OnShow = function() oldDialogs["DEATHSHOW"]() if ( HasSoulstone() ) then CT_RA_AddMessage("CANRES") end end; CT_RA_OldStaticPopup_OnShow = StaticPopup_OnShow; function CT_RA_NewStaticPopup_OnShow() if ( this.which and strsub(this.which, 1, 9) == "RESURRECT" ) then CT_RA_AddMessage("RESSED"); end CT_RA_OldStaticPopup_OnShow(); end StaticPopup_OnShow = CT_RA_NewStaticPopup_OnShow; function CT_RA_ResFrame_DropDown_OnClick() local tempOptions = CT_RAMenu_Options["temp"]; if ( this.id == 2 ) then tempOptions["LockMonitor"] = not tempOptions["LockMonitor"]; elseif ( this.id == 4 ) then tempOptions["ShowMonitor"] = nil; CT_RA_ResFrame:Hide(); end end function CT_RA_ResFrame_InitButtons() local tempOptions = CT_RAMenu_Options["temp"]; local dropdown, info; if ( UIDROPDOWNMENU_OPEN_MENU ) then dropdown = getglobal(UIDROPDOWNMENU_OPEN_MENU); else dropdown = this; end info = {}; info.text = "Resurrection Monitor"; info.isTitle = 1; info.justifyH = "CENTER"; info.notCheckable = 1; UIDropDownMenu_AddButton(info); info = { }; if ( tempOptions["LockMonitor"] ) then info.text = "Unlock Window"; else info.text = "Lock Window"; end info.notCheckable = 1; info.func = CT_RA_ResFrame_DropDown_OnClick; UIDropDownMenu_AddButton(info); info = { }; info.text = "Background Color"; info.hasColorSwatch = 1; info.hasOpacity = 1; if ( tempOptions["RMBG"] ) then info.r = ( tempOptions["RMBG"].r ); info.g = ( tempOptions["RMBG"].g ); info.b = ( tempOptions["RMBG"].b ); info.opacity = ( tempOptions["RMBG"].a ); else info.r = 0; info.g = 0; info.b = 1; info.opacity = 0.5; end info.notClickable = 1; info.swatchFunc = CT_RA_ResFrame_DropDown_SwatchFunc; info.opacityFunc = CT_RA_ResFrame_DropDown_OpacityFunc; info.cancelFunc = CT_RA_ResFrame_DropDown_CancelFunc; info.notCheckable = 1; UIDropDownMenu_AddButton(info); info = { }; info.text = "Hide"; info.notCheckable = 1; info.func = CT_RA_ResFrame_DropDown_OnClick; UIDropDownMenu_AddButton(info); end function CT_RA_ResFrame_DropDown_SwatchFunc() local tempOptions = CT_RAMenu_Options["temp"]; local r, g, b = ColorPickerFrame:GetColorRGB(); if ( not tempOptions["RMBG"] ) then tempOptions["RMBG"] = { ["r"] = r, ["g"] = g, ["b"] = b, ["a"] = 0 }; else tempOptions["RMBG"]["r"] = r; tempOptions["RMBG"]["g"] = g; tempOptions["RMBG"]["b"] = b; end CT_RA_ResFrame:SetBackdropColor(r, g, b, tempOptions["RMBG"]["a"]); CT_RA_ResFrame:SetBackdropBorderColor(1, 1, 1, tempOptions["RMBG"]["a"]); end function CT_RA_ResFrame_DropDown_OpacityFunc() local tempOptions = CT_RAMenu_Options["temp"]; local r, g, b = 1, 1, 1; if ( tempOptions["RMBG"] ) then r, g, b = tempOptions["RMBG"].r, tempOptions["RMBG"].g, tempOptions["RMBG"].b; end local a = OpacitySliderFrame:GetValue(); tempOptions["RMBG"]["a"] = a; CT_RA_ResFrame:SetBackdropColor(r, g, b, a); CT_RA_ResFrame:SetBackdropBorderColor(1, 1, 1, a); end function CT_RA_ResFrame_DropDown_CancelFunc(val) local tempOptions = CT_RAMenu_Options["temp"]; tempOptions["RMBG"] = { ["r"] = val.r, ["g"] = val.g, ["b"] = val.b, ["a"] = val.opacity }; CT_RA_ResFrame:SetBackdropColor(val.r, val.g, val.b, val.opacity); CT_RA_ResFrame:SetBackdropBorderColor(1, 1, 1, val.opacity); end function CT_RA_ResFrame_OnLoad() UIDropDownMenu_Initialize(this, CT_RA_ResFrame_InitButtons, "MENU"); end function CT_RA_SendReady() CT_RA_AddMessage("READY"); end function CT_RA_SendNotReady() CT_RA_AddMessage("NOTREADY"); end function CT_RA_SendYes() CT_RA_AddMessage("VOTEYES"); end function CT_RA_SendNo() CT_RA_AddMessage("VOTENO"); end function CT_RA_SendRly() CT_RA_AddMessage("YARLY"); end function CT_RA_SendNoRly() CT_RA_AddMessage("NORLY"); end function CT_RA_ReadyFrame_OnUpdate(elapsed) if ( this.hide ) then this.hide = this.hide - elapsed; if ( this.hide <= 0 ) then this:Hide(); end end end function CT_RA_ToggleGroupSort(skipCustom) local tempOptions = CT_RAMenu_Options["temp"]; if ( tempOptions["SORTTYPE"] == "group" ) then CT_RA_SetSortType("class"); elseif ( tempOptions["SORTTYPE"] == "class" and not skipCustom ) then CT_RA_SetSortType("custom"); else CT_RA_SetSortType("group"); end CT_RA_UpdateRaidGroup(3); CT_RA_UpdateMTs(); CT_RA_UpdatePTs(); CT_RAOptions_Update(); end function CT_RA_SetSortType(sort_type) local tempOptions = CT_RAMenu_Options["temp"]; if ( sort_type == "class" ) then tempOptions["SORTTYPE"] = "class"; if ( CT_RAMenuFrameGeneralMiscDropDown and CT_RAMenuFrame:IsVisible() ) then UIDropDownMenu_SetSelectedID(CT_RAMenuFrameGeneralMiscDropDown, 2); end if ( CT_RAMenuFrameGeneralMiscDropDownText ) then CT_RAMenuFrameGeneralMiscDropDownText:SetText("Class"); end elseif ( sort_type == "custom" ) then tempOptions["SORTTYPE"] = "custom"; if ( CT_RAMenuFrameGeneralMiscDropDown and CT_RAMenuFrame:IsVisible() ) then UIDropDownMenu_SetSelectedID(CT_RAMenuFrameGeneralMiscDropDown, 3); end if ( CT_RAMenuFrameGeneralMiscDropDownText ) then CT_RAMenuFrameGeneralMiscDropDownText:SetText("Custom"); end elseif ( sort_type == "virtual" ) then tempOptions["SORTTYPE"] = "virtual"; if ( CT_RAMenuFrameGeneralMiscDropDown and CT_RAMenuFrame:IsVisible() ) then UIDropDownMenu_SetSelectedID(CT_RAMenuFrameGeneralMiscDropDown, 4); end if ( CT_RAMenuFrameGeneralMiscDropDownText ) then CT_RAMenuFrameGeneralMiscDropDownText:SetText("Virtual"); end else tempOptions["SORTTYPE"] = "group"; if ( CT_RAMenuFrameGeneralMiscDropDown and CT_RAMenuFrame:IsVisible() ) then UIDropDownMenu_SetSelectedID(CT_RAMenuFrameGeneralMiscDropDown, 1); end if ( CT_RAMenuFrameGeneralMiscDropDownText ) then CT_RAMenuFrameGeneralMiscDropDownText:SetText("Group"); end end end function CT_RA_DragAllWindows(start) local id = this:GetID(); if ( start ) then local group = getglobal("CT_RAGroupDrag" .. id); local x, y = group:GetLeft(), group:GetTop(); if ( not x or not y ) then return; end for i = 1, 8, 1 do if ( i ~= id ) then local oGroup = getglobal("CT_RAGroup" .. i); local oX, oY = oGroup:GetLeft(), oGroup:GetTop(); if ( oX and oY ) then oGroup:ClearAllPoints(); oGroup:SetPoint("TOPLEFT", "CT_RAGroupDrag" .. id, "TOPLEFT", oX-x, oY-y); end end end else for i = 1, 8, 1 do if ( i ~= id ) then local oGroup = getglobal("CT_RAGroupDrag" .. id); local oX, oY = oGroup:GetLeft(), oGroup:GetTop(); if ( oX and oY ) then oGroup:ClearAllPoints(); oGroup:SetPoint("TOPLEFT", "UIParent", "TOPLEFT", oX, oY-UIParent:GetTop()); end end end end end function CT_RA_CheckGroups() if ( GetNumRaidMembers() == 0 ) then return; end local numPartyMembers = GetNumPartyMembers(); if ( not CT_RA_PartyMembers ) then CT_RA_PartyMembers = { }; if ( UnitName("party" .. numPartyMembers) ) then for i = 1, numPartyMembers, 1 do CT_RA_PartyMembers[UnitName("party"..i)] = i; end end return; end local joined, left, numleft, numjoin = "", "", 0, 0; if ( not UnitName("party" .. numPartyMembers) and numPartyMembers > 0 ) then CT_RA_PartyMembers = { }; return; end for i = 1, numPartyMembers, 1 do local uName = UnitName("party" .. i); if ( uName and not CT_RA_PartyMembers[uName] ) then if ( numjoin > 0 ) then joined = joined .. "|r, |c00FFFFFF"; end joined = joined .. uName; numjoin = numjoin + 1; end CT_RA_PartyMembers[uName] = nil; end for k, v in CT_RA_PartyMembers do if ( numleft > 0 ) then left = left .. "|r, |c00FFFFFF"; end left = left .. k; numleft = numleft + 1; end local tempOptions = CT_RAMenu_Options["temp"]; if ( tempOptions["NotifyGroupChange"] and ( numjoin > 0 or numleft > 0 ) ) then if ( tempOptions["NotifyGroupChangeSound"] ) then PlaySoundFile("Sound\\Spells\\Thorns.wav"); end if ( numjoin > 1 ) then CT_RA_Print(" |c00FFFFFF" .. joined .. "|r have joined your party.", 1, 0.5, 0); elseif ( numjoin == 1 ) then CT_RA_Print(" |c00FFFFFF" .. joined .. "|r has joined your party.", 1, 0.5, 0); end if ( numleft > 1 ) then CT_RA_Print(" |c00FFFFFF" .. left .. "|r have left your party.", 1, 0.5, 0); elseif ( numleft == 1 ) then CT_RA_Print(" |c00FFFFFF" .. left .. "|r has left your party.", 1, 0.5, 0); end end CT_RA_PartyMembers = { }; for i = 1, numPartyMembers, 1 do local uName = UnitName("party" .. i); if ( uName ) then CT_RA_PartyMembers[uName] = 1; end end end function CT_RA_Emergency_UpdateHealth() local tempOptions = CT_RAMenu_Options["temp"]; local numRaidMembers = GetNumRaidMembers(); if ( not tempOptions["ShowEmergency"] or ( numRaidMembers == 0 and not tempOptions["ShowEmergencyOutsideRaid"] ) ) then CT_RA_EmergencyFrame:Hide(); return; else CT_RA_EmergencyFrame:Show(); end for i = 1, 5, 1 do CT_RA_EmergencyFrame["frame"..i]:Hide(); end CT_RA_EmergencyFrame.maxPercent = nil; local healthThreshold = tempOptions["EMThreshold"]; if ( not healthThreshold ) then healthThreshold = 0.9; end CT_RA_Emergency_Units = { }; local health; if ( not tempOptions["ShowEmergencyParty"] and GetNumRaidMembers() > 0 ) then health = CT_RA_Emergency_RaidHealth; health = { }; local numMembers = GetNumRaidMembers(); for i = 1, numMembers, 1 do local uId = "raid" .. i; local curr, max = UnitHealth(uId), UnitHealthMax(uId); if ( curr and max and curr/max <= healthThreshold ) then tinsert(health, { curr, max, uId, i, curr/max }); end end else health = { }; for i = 1, GetNumPartyMembers(), 1 do local uId = "party" .. i; local curr, max = UnitHealth(uId), UnitHealthMax(uId); if ( curr and max and curr/max <= healthThreshold) then tinsert(health, { curr, max, uId, nil, curr/max }); end end local curr, max = UnitHealth("player"), UnitHealthMax("player"); if ( curr/max <= healthThreshold ) then tinsert(health, { curr, max, "player", nil, curr/max }); end end table.sort( health, function(v1, v2) return v1[5] < v2[5]; end ); CT_RA_EmergencyFrameTitle:Show(); CT_RA_EmergencyFrameDrag:Show(); local nextFrame = 0; for k, v in health do if ( not UnitIsDead(v[3]) and not UnitIsGhost(v[3]) and UnitIsConnected(v[3]) and UnitIsVisible(v[3]) and ( not CT_RA_Stats[UnitName(v[3])] or not CT_RA_Stats[UnitName(v[3])]["Dead"] ) and ( not tempOptions["EMClasses"] or not tempOptions["EMClasses"][UnitClass(v[3])] ) ) then local name, rank, subgroup, level, class, fileName; local obj = CT_RA_EmergencyFrame["frame" .. (nextFrame+1)]; if ( GetNumRaidMembers() > 0 and not tempOptions["ShowEmergencyParty"] and v[4] ) then name, rank, subgroup, level, class, fileName = GetRaidRosterInfo(v[4]); local colors = RAID_CLASS_COLORS[fileName]; if ( colors ) then obj.Name:SetTextColor(colors.r, colors.g, colors.b); end else obj.Name:SetTextColor(1, 1, 1); end if ( not subgroup or not tempOptions["EMGroups"] or not tempOptions["EMGroups"][subgroup] ) then nextFrame = nextFrame + 1; obj:Show(); CT_RA_EmergencyFrame.maxPercent = v[5]; CT_RA_Emergency_Units[UnitName(v[3])] = 1; obj.ClickFrame.unitid = v[3]; obj.HPBar:SetMinMaxValues(0, v[2]); obj.HPBar:SetValue(v[1]); obj.Name:SetText(UnitName(v[3])); obj.Deficit:SetText(v[1]-v[2]); if ( UnitIsUnit(v[3], "player") ) then obj.HPBar:SetStatusBarColor(1, 0, 0); obj.HPBG:SetVertexColor(1, 0, 0, tempOptions["BGOpacity"]); elseif ( UnitInParty(v[3]) ) then obj.HPBar:SetStatusBarColor(0, 1, 1); obj.HPBG:SetVertexColor(0, 1, 1, tempOptions["BGOpacity"]); else obj.HPBar:SetStatusBarColor(0, 1, 0); obj.HPBG:SetVertexColor(0, 1, 0, tempOptions["BGOpacity"]); end end end if ( nextFrame == 5 ) then break; end end end function CT_RA_Emergency_TargetMember(num) local obj = CT_RA_EmergencyFrame["frame"..num]; if ( obj:IsVisible() and obj.ClickFrame.unitid ) then TargetUnit(obj.ClickFrame.unitid); end end function CT_RA_Emergency_OnEnter() if ( SpellIsTargeting() ) then SetCursor("CAST_CURSOR"); elseif ( not SpellCanTargetUnit(this.unitid) and SpellIsTargeting() ) then SetCursor("CAST_ERROR_CURSOR"); end end function CT_RA_Emergency_OnUpdate(elapsed) this.update = this.update - elapsed; if ( this.update <= 0 ) then this.update = 0.1; if ( this.cursor ) then if ( SpellIsTargeting() and SpellCanTargetUnit(this.unitid) ) then SetCursor("CAST_CURSOR"); elseif ( SpellIsTargeting() ) then SetCursor("CAST_ERROR_CURSOR"); end end end end function CT_RA_Emergency_DropDown_OnLoad() UIDropDownMenu_Initialize(this, CT_RA_Emergency_DropDown_Initialize, "MENU"); end function CT_RA_Emergency_DropDown_Initialize() local tempOptions = CT_RAMenu_Options["temp"]; local dropdown, info; if ( UIDROPDOWNMENU_OPEN_MENU ) then dropdown = getglobal(UIDROPDOWNMENU_OPEN_MENU); else dropdown = this; end if ( UIDROPDOWNMENU_MENU_VALUE == "Classes" ) then info = {}; info.text = "Classes"; info.isTitle = 1; info.notCheckable = 1; UIDropDownMenu_AddButton(info, UIDROPDOWNMENU_MENU_LEVEL); for k, v in CT_RA_ClassPositions do if ( ( k ~= CT_RA_SHAMAN or ( UnitFactionGroup("player") and UnitFactionGroup("player") == "Horde" ) ) and ( k ~= CT_RA_PALADIN or ( UnitFactionGroup("player") and UnitFactionGroup("player") == "Alliance" ) ) ) then info = {}; info.text = k; info.value = k; info.func = CT_RA_Emergency_DropDown_OnClick; info.checked = ( not tempOptions["EMClasses"] or not tempOptions["EMClasses"][k] ); info.keepShownOnClick = 1; info.tooltipTitle = "Toggle Class"; info.tooltipText = "Toggles displaying the selected class, allowing you to hide certain classes from the Emergency Monitor."; UIDropDownMenu_AddButton(info, UIDROPDOWNMENU_MENU_LEVEL); end end return; end if ( UIDROPDOWNMENU_MENU_VALUE == "Groups" ) then info = {}; info.text = "Groups"; info.isTitle = 1; info.notCheckable = 1; UIDropDownMenu_AddButton(info, UIDROPDOWNMENU_MENU_LEVEL); for i = 1, 8, 1 do info = {}; info.text = "Group " .. i; info.value = i; info.func = CT_RA_Emergency_DropDown_OnClick; info.checked = ( not tempOptions["EMGroups"] or not tempOptions["EMGroups"][i] ); info.keepShownOnClick = 1; info.tooltipTitle = "Toggle Group"; info.tooltipText = "Toggles displaying the selected group, allowing you to hide certain groups from the Emergency Monitor."; UIDropDownMenu_AddButton(info, UIDROPDOWNMENU_MENU_LEVEL); end return; end info = {}; info.text = "Emergency Monitor"; info.isTitle = 1; info.notCheckable = 1; UIDropDownMenu_AddButton(info); info = {}; info.text = "Classes"; info.hasArrow = 1; info.notCheckable = 1; UIDropDownMenu_AddButton(info); info = {}; info.text = "Groups"; info.hasArrow = 1; info.notCheckable = 1; UIDropDownMenu_AddButton(info); info = { }; info.text = "Background Color"; info.hasColorSwatch = 1; info.hasOpacity = 1; if ( tempOptions["EMBG"] ) then info.r = ( tempOptions["EMBG"].r ); info.g = ( tempOptions["EMBG"].g ); info.b = ( tempOptions["EMBG"].b ); info.opacity = ( tempOptions["EMBG"].a ); else info.r = 0; info.g = 0; info.b = 1; info.opacity = 0; end info.notClickable = 1; info.swatchFunc = CT_RA_Emergency_DropDown_SwatchFunc; info.opacityFunc = CT_RA_Emergency_DropDown_OpacityFunc; info.cancelFunc = CT_RA_Emergency_DropDown_CancelFunc; info.notCheckable = 1; UIDropDownMenu_AddButton(info); end function CT_RA_Emergency_DropDown_SwatchFunc() local tempOptions = CT_RAMenu_Options["temp"]; local r, g, b = ColorPickerFrame:GetColorRGB(); if ( not tempOptions["EMBG"] ) then tempOptions["EMBG"] = { ["r"] = r, ["g"] = g, ["b"] = b, ["a"] = 0 }; else tempOptions["EMBG"]["r"] = r; tempOptions["EMBG"]["g"] = g; tempOptions["EMBG"]["b"] = b; end CT_RA_EmergencyFrame:SetBackdropColor(r, g, b, tempOptions["EMBG"]["a"]); CT_RA_EmergencyFrame:SetBackdropBorderColor(1, 1, 1, tempOptions["EMBG"]["a"]); end function CT_RA_Emergency_DropDown_OpacityFunc() local tempOptions = CT_RAMenu_Options["temp"]; local r, g, b = 1, 1, 1; if ( tempOptions["EMBG"] ) then r, g, b = tempOptions["EMBG"].r, tempOptions["EMBG"].g, tempOptions["EMBG"].b; end local a = OpacitySliderFrame:GetValue(); tempOptions["EMBG"]["a"] = a; CT_RA_EmergencyFrame:SetBackdropColor(r, g, b, a); CT_RA_EmergencyFrame:SetBackdropBorderColor(1, 1, 1, a); end function CT_RA_Emergency_DropDown_CancelFunc(val) local tempOptions = CT_RAMenu_Options["temp"]; tempOptions["EMBG"] = { ["r"] = val.r, ["g"] = val.g, ["b"] = val.b, ["a"] = val.opacity }; CT_RA_EmergencyFrame:SetBackdropColor(val.r, val.g, val.b, val.opacity); CT_RA_EmergencyFrame:SetBackdropBorderColor(1, 1, 1, val.opacity); end function CT_RA_Emergency_DropDown_OnClick() local tempOptions = CT_RAMenu_Options["temp"]; if ( UIDROPDOWNMENU_MENU_VALUE == "Classes" ) then if ( not tempOptions["EMClasses"] ) then tempOptions["EMClasses"] = { }; end tempOptions["EMClasses"][this.value] = not tempOptions["EMClasses"][this.value]; CT_RA_Emergency_UpdateHealth(); elseif ( UIDROPDOWNMENU_MENU_VALUE == "Groups" ) then if ( not tempOptions["EMGroups"] ) then tempOptions["EMGroups"] = { }; end tempOptions["EMGroups"][this.value] = not tempOptions["EMGroups"][this.value]; CT_RA_Emergency_UpdateHealth(); end end function CT_RA_Emergency_ToggleDropDown() local left, top = this:GetCenter(); local uileft, uitop = UIParent:GetCenter(); if ( left > uileft ) then CT_RA_EmergencyFrameDropDown.point = "TOPRIGHT"; CT_RA_EmergencyFrameDropDown.relativePoint = "BOTTOMLEFT"; else CT_RA_EmergencyFrameDropDown.point = "TOPLEFT"; CT_RA_EmergencyFrameDropDown.relativePoint = "BOTTOMRIGHT"; end CT_RA_EmergencyFrameDropDown.relativeTo = this:GetName(); ToggleDropDownMenu(1, nil, CT_RA_EmergencyFrameDropDown); end -- RADurability stuff function CT_RADurability_GetDurability() local currDur, maxDur, brokenItems = 0, 0, 0; local itemIds = { 1, 2, 3, 5, 6, 7, 8, 9, 10, 16, 17, 18 }; for k, v in itemIds do CT_RADurationTooltip:ClearLines(); CT_RADurationTooltip:SetInventoryItem("player", v); for i = 1, CT_RADurationTooltip:NumLines(), 1 do local useless, useless, sMin, sMax = string.find(getglobal("CT_RADurationTooltipTextLeft" .. i):GetText() or "", CT_RA_DURABILITY); if ( sMin and sMax ) then local iMin, iMax = tonumber(sMin), tonumber(sMax); if ( iMin == 0 ) then brokenItems = brokenItems + 1; end currDur = currDur + iMin; maxDur = maxDur + iMax; break; end end end return currDur, maxDur, brokenItems; end function CT_RAReagents_GetReagents() local numItems = 0; local classes = { [CT_RA_PRIEST] = {CT_REG_PRIEST , CT_REG_PRIEST_SPELL}, [CT_RA_MAGE] = { CT_REG_MAGE , CT_REG_MAGE_SPELL }, [CT_RA_DRUID] = { CT_REG_DRUID ,CT_REG_DRUID_SPELL }, [CT_RA_WARLOCK] = { CT_REG_WARLOCK }, [CT_RA_PALADIN] = { CT_REG_PALADIN, CT_REG_PALADIN_SPELL }, [CT_RA_SHAMAN] = { CT_REG_SHAMAN, CT_REG_SHAMAN_SPELL } }; local plClass = classes[UnitClass("player")]; if ( not plClass or ( plClass[2] and not CT_RA_ClassSpells[plClass[2]] ) ) then return; end for i = 0, 4, 1 do for y = 1, MAX_CONTAINER_ITEMS, 1 do local link = GetContainerItemLink(i, y); if ( link ) then local _, _, name = string.find(link, "%[(.+)%]"); if ( name ) then if ( plClass and plClass[1] == name ) then local texture, itemCount, locked, quality, readable = GetContainerItemInfo(i,y); numItems = numItems + itemCount; end end end end end return numItems; end function CT_RAItem_GetItems(itemName) local numItems = 0; for i = 0, 4, 1 do for y = 1, MAX_CONTAINER_ITEMS, 1 do local link = GetContainerItemLink(i, y); if ( link ) then local _, _, name = string.find(link, "%[(.+)%]"); if ( name == itemName ) then local texture, itemCount, locked, quality, readable = GetContainerItemInfo(i,y); numItems = numItems + itemCount; end end end end return numItems; end CT_RADurability_Shown = { }; CT_RADurability_Sorting = { ["curr"] = 4, [3] = { "a", "a" }, [4] = { "a", "a" } }; tinsert(UISpecialFrames, "CT_RA_DurabilityFrame"); function CT_RADurability_Add(name, info, fileName, ...) local tbl = { name, info, fileName }; for i = 1, arg.n, 1 do tinsert(tbl, ( tonumber(arg[i]) or arg[i] )); end tinsert(CT_RADurability_Shown, tbl); CT_RADurability_Sort(CT_RADurability_Sorting["curr"], 1); CT_RADurability_Update(); end function CT_RADurability_Sort(sortBy, maintain) if ( CT_RADurability_Sorting["curr"] ~= sortBy ) then CT_RADurability_Sorting[sortBy][1] = CT_RADurability_Sorting[sortBy][2]; end CT_RADurability_Sorting["curr"] = sortBy; if ( CT_RADurability_Sorting[sortBy][1] == "a" ) then if ( not maintain ) then CT_RADurability_Sorting[sortBy][1] = "b"; end else if ( not maintain ) then CT_RADurability_Sorting[sortBy][1] = "a"; end end if ( CT_RADurability_Sorting[sortBy][1] == "b" ) then table.sort(CT_RADurability_Shown, function(t1, t2) if (t1[sortBy] == t2[sortBy] ) then if ( t1[3] == t2[3] ) then return t1[1] < t2[1] else return t1[3] < t2[3] end else return t1[sortBy] < t2[sortBy] end end ); else table.sort(CT_RADurability_Shown, function(t1, t2) if (t1[sortBy] == t2[sortBy] ) then if ( t1[3] == t2[3] ) then return t1[1] < t2[1] else return t1[3] < t2[3] end else return t1[sortBy] > t2[sortBy] end end ); end CT_RADurability_Update(); end function CT_RADurability_Update() local numEntries = getn(CT_RADurability_Shown); FauxScrollFrame_Update(CT_RA_DurabilityFrameScrollFrame, numEntries, 19, 20); for i = 1, 19, 1 do local button = getglobal("CT_RA_DurabilityFramePlayer" .. i); local index = i + FauxScrollFrame_GetOffset(CT_RA_DurabilityFrameScrollFrame); if ( index <= numEntries ) then if ( numEntries <= 19 ) then button:SetWidth(275); else button:SetWidth(253); end if ( CT_RA_DurabilityFrame.type ~= "RARST" or numEntries <= 19 ) then CT_RA_DurabilityFrameScrollFrame:SetPoint("TOPLEFT", "CT_RA_DurabilityFrame", "TOPLEFT", 19, -27); getglobal(button:GetName() .. "Resist1"):SetPoint("LEFT", button:GetName(), "LEFT", 127, 0); CT_RA_DurabilityFrameNameTab:SetWidth(135); else CT_RA_DurabilityFrameScrollFrame:SetPoint("TOPLEFT", "CT_RA_DurabilityFrame", "TOPLEFT", 19, -32); getglobal(button:GetName() .. "Resist1"):SetPoint("LEFT", button:GetName(), "LEFT", 110, 0); CT_RA_DurabilityFrameNameTab:SetWidth(118); end button:Show(); getglobal(button:GetName() .. "Name"):SetText(CT_RADurability_Shown[index][1]); local color = RAID_CLASS_COLORS[CT_RADurability_Shown[index][3]]; if ( color ) then getglobal(button:GetName() .. "Name"):SetTextColor(color.r, color.g, color.b); end getglobal(button:GetName() .. "Info"):SetText(CT_RADurability_Shown[index][2]); for i = 1, 5, 1 do if ( CT_RA_DurabilityFrame.type == "RARST" and CT_RADurability_Shown[index][3+i] ~= -1 ) then getglobal(button:GetName() .. "Resist" .. i):SetText(CT_RADurability_Shown[index][3+i]); getglobal(button:GetName() .. "Resist" .. i):Show(); else getglobal(button:GetName() .. "Resist" .. i):Hide(); end end else button:Hide(); end end end CT_RA_CurrDebuffs = { }; function CT_RA_AddDebuffMessage(name, dType, player) if ( not dType ) then return; end if ( CT_RADebuff_IgnoreDebuffs[name] ) then return; end if ( CT_RA_CurrDebuffs[name .. "@" .. dType] ) then if ( not CT_RA_CurrDebuffs[name .. "@" .. dType][3][player] ) then CT_RA_CurrDebuffs[name .. "@" .. dType][3][player] = 1; CT_RA_CurrDebuffs[name .. "@" .. dType][2] = CT_RA_CurrDebuffs[name .. "@" .. dType][2] + 1; CT_RA_CurrDebuffs[name .. "@" .. dType][1] = 0.4; end else CT_RA_CurrDebuffs[name .. "@" .. dType] = { 0.4, 1, { [player] = 1 }, player }; end end function CT_RA_RGBToHex(r, g, b) return format("%.2x%.2x%.2x", floor(r*255), floor(g*255), floor(b*255)); end CT_RA_oldRaidFrame_LoadUI = RaidFrame_LoadUI; function RaidFrame_LoadUI() CT_RA_oldRaidFrame_LoadUI(); RaidFrameDropDown_Initialize = CT_RATab_newRaidFrameDropDown_Initialize; end