--[[ File NAME: TitanLootType.lua DESC: This Titan plugin will show group type and loot type in the button text. A roll tracker is used to show rolls in party to help make passing out loot and chests. This is a simplistic roll helper! It is NOT intended as a loot tracker! On right-click it will show the normal Titan options. The left-click it will depend whether the user is group leader or loot master : if not leader a /roll will be done. if leader the tracker window will pop, giving them additional options - Start : Start a new roll - Remind : Nag those who have not rolled with a whisper - Results : State the results Once a leader initiates a roll, the tracker will pop for other Titan users who are using LootType. :DESC --]] TitanPanelLootType = {} -- declare name space local LT = TitanPanelLootType -- save some typing... -- ******************************** Constants ******************************* local TITAN_LOOTTYPE_ID = "LootType"; local _G = getfenv(0); local L = LibStub("AceLocale-3.0"):GetLocale("TitanClassic", true) local TitanLootMethod = {}; local updateTable = {TITAN_LOOTTYPE_ID, TITAN_PANEL_UPDATE_ALL}; TitanLootMethod["freeforall"] = {text = L["TITAN_LOOTTYPE_FREE_FOR_ALL"]}; TitanLootMethod["roundrobin"] = {text = L["TITAN_LOOTTYPE_ROUND_ROBIN"]}; TitanLootMethod["master"] = {text = L["TITAN_LOOTTYPE_MASTER_LOOTER"]}; TitanLootMethod["group"] = {text = L["TITAN_LOOTTYPE_GROUP_LOOT"]}; TitanLootMethod["needbeforegreed"] = {text = L["TITAN_LOOTTYPE_NEED_BEFORE_GREED"]}; --TitanLootMethod["personalloot"] = {text = L["TITAN_LOOTTYPE_PERSONAL"]}; local TOCNAME = "TitanClassicLootType" local Track = {} -- High level constants Track.IconDice= "Interface\\Buttons\\UI-GroupLoot-Dice-Up" --Track.IconGreed= "Interface\\Buttons\\UI-GroupLoot-Coin-Up" Track.IconPass= "Interface\\Buttons\\UI-GroupLoot-Pass-Up" Track.IconLoot= "Interface\\GroupFrame\\UI-Group-MasterLooter" Track.TxtEscapePicture="|T%s:0|t" Track.TxtEscapeIcon="|T%s:0:0:0:0:64:64:4:60:4:60|t" -- These are encoded 'messages' this addon searches for to start and end the roll process Track.MSGPREFIX="Titan LootType Roller: " -- also frame title Track.MSGPREFIX_START=Track.MSGPREFIX..">>: " Track.MSGPREFIX_END =Track.MSGPREFIX.."<<: " Track.MSGPREFIX_CLOSE=Track.MSGPREFIX.."__: " -- This will be debugged real-time so put the debug on 'switches' -- Also useful when debugging 'solo' LT.Debug = { -- Used when creating dummy player list (see flags) or solo debug to get 'self' -- And debug output on = false, show = { -- for LootDebug messages events = false, -- show debug for events players = false, -- show debug for players -- nil will show regardless }, flags = { -- solo debug force_leader = false, force_master = false, force_loot_master = false, -- These 3 are used when creating dummy player list WITH 'on' = true add_players = false, is_raid = false, is_party = false, }, } --[[ The commands (use WoWLua addon) below will - set debug depending on what you want to test - create a player list (via GetPlayerList on start roll) to play with AND add_players is true is_raid will make a 40 player list... is_party will make a 5 player list if neither makes you a group of 1 - update rolls to check various errors conditions TitanPanelLootType.Debug.on = true TitanPanelLootType.Debug.flags.is_raid = true TitanPanelLootType.Debug.show.players = true TitanPanelLootType.Debug.show.events = true TitanPanelLootType.AddAllRollsDebug() TitanPanelLootType.AddRollDebug("raid6", "999", "1", "1000") --]] -- ******************************** Variables ******************************* -- ******************************** Functions ******************************* --[[ local NAME: LootDebug DESC: Set the Tian bars and plugins to the selected scale then adjust other frames as needed. VAR: msg - message to be output VAR: mtype - the type of message OUT: None --]] local function LootDebug (msg, mtype) local show = false if mtype == nil then show = true -- just show it elseif mtype == "events" and LT.Debug.show.events then show = true elseif mtype == "players" and LT.Debug.show.players then show = true end if show then -- DEFAULT_CHAT_FRAME:AddMessage((msg or "nyl")) TitanDebug((msg or "nyl")) -- do not 'crash' if a nil is received end end -- Tools for the tracker local Tool = {} Tool.IconClassTexture="Interface\\GLUES\\CHARACTERCREATE\\UI-CHARACTERCREATE-CLASSES" Tool.IconClassTextureWithoutBorder="Interface\\WorldStateFrame\\ICONS-CLASSES" Tool.IconClassTextureCoord=CLASS_ICON_TCOORDS Tool.IconClass={ ["WARRIOR"]= "|TInterface\\WorldStateFrame\\ICONS-CLASSES:0:0:0:0:256:256:0:64:0:64|t", ["MAGE"]= "|TInterface\\WorldStateFrame\\ICONS-CLASSES:0:0:0:0:256:256:64:128:0:64|t", ["ROGUE"]= "|TInterface\\WorldStateFrame\\ICONS-CLASSES:0:0:0:0:256:256:128:192:0:64|t", ["DRUID"]= "|TInterface\\WorldStateFrame\\ICONS-CLASSES:0:0:0:0:256:256:192:256:0:64|t", ["HUNTER"]= "|TInterface\\WorldStateFrame\\ICONS-CLASSES:0:0:0:0:256:256:0:64:64:128|t", ["SHAMAN"]= "|TInterface\\WorldStateFrame\\ICONS-CLASSES:0:0:0:0:256:256:64:128:64:128|t", ["PRIEST"]= "|TInterface\\WorldStateFrame\\ICONS-CLASSES:0:0:0:0:256:256:128:192:64:128|t", ["WARLOCK"]= "|TInterface\\WorldStateFrame\\ICONS-CLASSES:0:0:0:0:256:256:192:256:64:128|t", ["PALADIN"]= "|TInterface\\WorldStateFrame\\ICONS-CLASSES:0:0:0:0:256:256:0:64:128:192|t", } Tool.IconClassBig={ ["WARRIOR"]= "|TInterface\\WorldStateFrame\\ICONS-CLASSES:18:18:-4:4:256:256:0:64:0:64|t", ["MAGE"]= "|TInterface\\WorldStateFrame\\ICONS-CLASSES:18:18:-4:4:256:256:64:128:0:64|t", ["ROGUE"]= "|TInterface\\WorldStateFrame\\ICONS-CLASSES:18:18:-4:4:256:256:128:192:0:64|t", ["DRUID"]= "|TInterface\\WorldStateFrame\\ICONS-CLASSES:18:18:-4:4:256:256:192:256:0:64|t", ["HUNTER"]= "|TInterface\\WorldStateFrame\\ICONS-CLASSES:18:18:-4:4:256:256:0:64:64:128|t", ["SHAMAN"]= "|TInterface\\WorldStateFrame\\ICONS-CLASSES:18:18:-4:4:256:256:64:128:64:128|t", ["PRIEST"]= "|TInterface\\WorldStateFrame\\ICONS-CLASSES:18:18:-4:4:256:256:128:192:64:128|t", ["WARLOCK"]= "|TInterface\\WorldStateFrame\\ICONS-CLASSES:18:18:-4:4:256:256:192:256:64:128|t", ["PALADIN"]= "|TInterface\\WorldStateFrame\\ICONS-CLASSES:18:18:-4:4:256:256:0:64:128:192|t", } Tool.RaidIconNames=ICON_TAG_LIST Tool.RaidIcon={ "|TInterface\\TargetingFrame\\UI-RaidTargetingIcon_1:0|t", -- [1] "|TInterface\\TargetingFrame\\UI-RaidTargetingIcon_2:0|t", -- [2] "|TInterface\\TargetingFrame\\UI-RaidTargetingIcon_3:0|t", -- [3] "|TInterface\\TargetingFrame\\UI-RaidTargetingIcon_4:0|t", -- [4] "|TInterface\\TargetingFrame\\UI-RaidTargetingIcon_5:0|t", -- [5] "|TInterface\\TargetingFrame\\UI-RaidTargetingIcon_6:0|t", -- [6] "|TInterface\\TargetingFrame\\UI-RaidTargetingIcon_7:0|t", -- [7] "|TInterface\\TargetingFrame\\UI-RaidTargetingIcon_8:0|t", -- [8] } Tool.Classes=CLASS_SORT_ORDER Tool.ClassName=LOCALIZED_CLASS_NAMES_MALE Tool.ClassColor=RAID_CLASS_COLORS Tool.ButtonFontObj = {} Tool.Font = "" Tool.FontSize = "" --[[ local NAME: Tool.CreatePattern DESC: Set the Tian bars and plugins to the selected scale then adjust other frames as needed. VAR: pattern - string to be parsed VAR: maximize - do min or max substitution OUT: None --]] function Tool.CreatePattern(pattern,maximize) pattern = string.gsub(pattern, "[%(%)%-%+%[%]]", "%%%1") if not maximize then pattern = string.gsub(pattern, "%%s", "(.-)") else pattern = string.gsub(pattern, "%%s", "(.+)") end pattern = string.gsub(pattern, "%%d", "%(%%d-%)") if not maximize then pattern = string.gsub(pattern, "%%%d%$s", "(.-)") else pattern = string.gsub(pattern, "%%%d%$s", "(.+)") end pattern = string.gsub(pattern, "%%%d$d", "%(%%d-%)") --pattern = string.gsub(pattern, "%[", "%|H%(%.%-%)%[") --pattern = string.gsub(pattern, "%]", "%]%|h") return pattern end --[[ local NAME: Sizing routines DESC: These allow the frame to be resized as needed. OUT: None --]] local ResizeCursor local SizingStop=function(self,button) self:GetParent():StopMovingOrSizing() if self.GPI_DoStop then self.GPI_DoStop(self:GetParent()) end end local SizingStart=function(self,button) self:GetParent():StartSizing(self.GPI_SIZETYPE) if self.GPI_DoStart then self.GPI_DoStart(self:GetParent()) end end local SizingEnter=function(self) if not (GetCursorInfo()) then ResizeCursor:Show() ResizeCursor.Texture:SetTexture(self.GPI_Cursor) ResizeCursor.Texture:SetRotation(math.rad(self.GPI_Rotation),0.5,0.5) end end local SizingLeave=function(self,button) ResizeCursor:Hide() end local sizecount=0 local CreateSizeBorder=function(frame,name,a1,x1,y1,a2,x2,y2,cursor,rot,OnStart,OnStop) local FrameSizeBorder sizecount=sizecount+1 FrameSizeBorder=CreateFrame("Frame",(frame:GetName() or TOCNAME..sizecount).."_size_"..name,frame) FrameSizeBorder:SetPoint("TOPLEFT", frame, a1, x1, y1) FrameSizeBorder:SetPoint("BOTTOMRIGHT", frame, a2, x2,y2 ) FrameSizeBorder.GPI_SIZETYPE=name FrameSizeBorder.GPI_Cursor = cursor FrameSizeBorder.GPI_Rotation = rot FrameSizeBorder.GPI_DoStart=OnStart FrameSizeBorder.GPI_DoStop=OnStop FrameSizeBorder:SetScript("OnMouseDown", SizingStart) FrameSizeBorder:SetScript("OnMouseUp", SizingStop) FrameSizeBorder:SetScript("OnEnter", SizingEnter) FrameSizeBorder:SetScript("OnLeave", SizingLeave) return FrameSizeBorder end local ResizeCursor_Update=function(self) local X, Y = GetCursorPosition() local Scale = self:GetEffectiveScale() self:SetPoint("CENTER", UIParent, "BOTTOMLEFT", X / Scale, Y / Scale) end function Tool.EnableSize(frame,border,OnStart,OnStop) if not ResizeCursor then ResizeCursor = CreateFrame("Frame", nil, UIParent) ResizeCursor:Hide() ResizeCursor:SetWidth(24) ResizeCursor:SetHeight(24) ResizeCursor:SetFrameStrata("TOOLTIP") ResizeCursor.Texture = ResizeCursor:CreateTexture() ResizeCursor.Texture:SetAllPoints() ResizeCursor:SetScript("OnUpdate", ResizeCursor_Update) end border=border or 8 frame:EnableMouse(true) frame:SetResizable(true) path= "Interface\\AddOns\\".. TOCNAME .. "\\Resize\\" CreateSizeBorder(frame,"BOTTOM","BOTTOMLEFT", border, border, "BOTTOMRIGHT", -border, 0,"Interface\\CURSOR\\UI-Cursor-SizeLeft",45,OnStart,OnStop) CreateSizeBorder(frame,"TOP","TOPLEFT", border, 0, "TOPRIGHT", -border, -border,"Interface\\CURSOR\\UI-Cursor-SizeLeft",45,OnStart,OnStop) CreateSizeBorder(frame,"LEFT","TOPLEFT", 0,-border, "BOTTOMLEFT", border, border,"Interface\\CURSOR\\UI-Cursor-SizeRight",45,OnStart,OnStop) CreateSizeBorder(frame,"RIGHT","TOPRIGHT",-border,-border, "BOTTOMRIGHT", 0, border,"Interface\\CURSOR\\UI-Cursor-SizeRight",45,OnStart,OnStop) CreateSizeBorder(frame,"TOPLEFT","TOPLEFT", 0,0, "TOPLEFT", border, -border,"Interface\\CURSOR\\UI-Cursor-SizeRight",0,OnStart,OnStop) CreateSizeBorder(frame,"BOTTOMLEFT","BOTTOMLEFT", 0,0, "BOTTOMLEFT", border, border, "Interface\\CURSOR\\UI-Cursor-SizeLeft",0,OnStart,OnStop) CreateSizeBorder(frame,"TOPRIGHT","TOPRIGHT", 0,0, "TOPRIGHT", -border, -border, "Interface\\CURSOR\\UI-Cursor-SizeLeft",0,OnStart,OnStop) CreateSizeBorder(frame,"BOTTOMRIGHT","BOTTOMRIGHT", 0,0, "BOTTOMRIGHT", -border, border, "Interface\\CURSOR\\UI-Cursor-SizeRight",0,OnStart,OnStop) end --[[ local NAME: Moving routines DESC: These allow the frame to be moved as needed. OUT: None --]] local function MovingStart(self) self:StartMoving() end local function MovingStop(self) self:StopMovingOrSizing() if self._GPIPRIVAT_MovingStopCallback then self._GPIPRIVAT_MovingStopCallback(self) end end function Tool.EnableMoving(frame,callback) frame:SetMovable(true) frame:EnableMouse(true) frame:RegisterForDrag("LeftButton") frame:SetScript("OnDragStart",MovingStart) frame:SetScript("OnDragStop",MovingStop) frame._GPIPRIVAT_MovingStopCallback=callback end function Tool.SetButtonFont(button) -- Just Return. This changed WAY too much... --[[ if button then local font_instance = button:GetNormalFontObject() if font_instance then font_instance:SetFont(Tool.Font, Tool.FontSize, nil) else TitanDebug("SetButtonFont" .." "..(button:GetName() or "nyl") .." no font instance" ) end else TitanDebug("SetButtonFont" .." "..(button or "nyl") .." no button!?" ) end --]] -- button:SetFont(Tool.Font, Tool.FontSize, nil) end --[[ local NAME: Tool routines DESC: Such as split, color, combine. OUT: None --]] function Tool.Split(inputstr, sep) if sep == nil then sep = "%s" end local t={} for str in string.gmatch(inputstr, "([^"..sep.."]+)") do if tContains(t, str)==false then table.insert(t, str) end end return t end function Tool.RGBtoEscape(r, g, b,a) if type(r)=="table" then a=r.a g=r.g b=r.b r=r.r end r = r~=nil and r <= 1 and r >= 0 and r or 1 g = g~=nil and g <= 1 and g >= 0 and g or 1 b = b~=nil and b <= 1 and b >= 0 and b or 1 a = a~=nil and a <= 1 and a >= 0 and a or 1 return string.format("|c%02x%02x%02x%02x", a*255, r*255, g*255, b*255) -- return "" end function Tool.Combine(t,sep,first,last) if type(t)~="table" then return "" end sep=sep or " " first=first or 1 last= last or #t local ret="" for i=first,last do ret=ret..sep..tostring(t[i]) end return string.sub(ret,string.len(sep)+1) end -- Routines for the 'track' rolls feature --[[ local NAME: IsRoll DESC: Determine if the roll is valid. VAR: roll - string VAR: low - low end VAR: high - high end OUT: valid_roll - true / false OUT: valid_bounds - true / false OUT: ro - numeric roll OUT: lo - numeric low OUT: hi - numeric high --]] local function IsRoll(roll,low,high) local lo = tonumber(low) local hi = tonumber(high) local ro = tonumber(roll) local valid_roll = false local valid_bounds = false if (lo == 1 and hi == 100) then valid_bounds = true end if (ro >= 0) and (ro <= 100) then -- allows a pass as valid valid_roll = true end if valid_bounds then -- all is good else -- for now roll is invalid, treat as a pass valid_roll = false ro = 0 end local str = " >>" .." vr'"..tostring(valid_roll).."'" .." vb'"..tostring(valid_bounds).."'" .." r'"..tostring(ro).."'" .." l'"..tostring(lo).."'" .." h'"..tostring(hi).."'" LootDebug (str, "players") return valid_roll, valid_bounds, ro, lo, hi end --[[ local NAME: GetPlayer DESC: Get name, class, guild rank (if in same guild) a the given player. VAR: id - id of player OUT: name - name of the player OUT: rank - guild rank OUT: englishClass - English class name --]] local function GetPlayer(id) local name=GetUnitName(id) local localizedClass, englishClass, classIndex = UnitClass(id) local rank="" if IsInGuild() and UnitIsInMyGuild(id) then rank="<".. GuildControlGetRankName( C_GuildInfo.GetGuildRankOrder( UnitGUID(id) ) )..">" else local guildName, guildRankName, guildRankIndex, realm = GetGuildInfo(id) if guildName and guildRankName then rank="<"..guildName.." / "..guildRankName..">" end end return name, rank, englishClass end --[[ local NAME: IsLead DESC: Determine whether the player is the leader of the group. VAR: None OUT: true / false --]] local function IsLead() --[[ lootmethod, masterlooterPartyID, masterlooterRaidID = GetLootMethod() lootmethod String (LootMethod) - One of 'freeforall', 'roundrobin', 'master', 'group', 'needbeforegreed'. Appears to be 'freeforall' if you are not grouped.: At least as of 7.3 the possible return values appear to be "freeforall", "master", "group" and "personalloot". "roundrobin" and "needbeforegreed" appear to be deprecated. masterlooterPartyID Number - Returns 0 if player is the mater looter, 1-4 if party member is master looter (corresponding to party1-4) and nil if the master looter isn't in the player's party or master looting is not used. masterlooterRaidID Number - Returns index of the master looter in the raid (corresponding to a raidX unit), or nil if the player is not in a raid or master looting is not used. raidIndex = UnitInRaid("unit") raidIndex of "unit" if he is in your raid group, otherwise nil. isTrue = UnitInParty("arg1") inGroup = IsInGroup([groupType]) isTrue = UnitIsGroupLeader("unit"[, groupType]) isLeader = IsRaidLeader() isLeader = UnitIsGroupLeader("unit" or "player name") -- may need in later patches? --]] --[[ if IsInRaid() and IsRaidLeader() then return true end if IsInGroup() and UnitIsGroupLeader("player") then return true end --]] if UnitIsGroupLeader("player") then return true end -- The way this flows is both leader AND master looter will have the extra buttons local lootmethod, masterlooterPartyID, masterlooterRaidID = GetLootMethod() if lootmethod == "master" then if IsInRaid() and (masterlooterRaidID == UnitInRaid("player")) then return true end if IsInGroup() and (masterlooterPartyID == UnitInParty("player")) then return true end end if LT.Debug.flags.force_leader then return true end if LT.Debug.flags.force_master then return true end return false end --[[ local NAME: Track.GetPlayerList DESC: Collect name, class, and guild rank (if in same guild) of players in the group. This routine will generate group lists (5 or 40) for debug based on debug flags. :DESC VAR: unsort - if true sort by class then name OUT: ret - indexed table of players in the group OUT: retName - table of player names pointing into ret --]] local function OutPlayer(player) if LT.Debug.on then -- if player then TitanDebug("GetPlayerList:" .." p'"..(player.name or "nyl").."'" .." r'"..(player.rank or "nyl").."'" .." c'"..(player.class or "nyl").."'" ) end end end function Track.GetPlayerList(unsort) local count,start local prefix local ret={} local retName={} if IsInRaid() or LT.Debug.flags.is_raid then prefix="raid" count=MAX_RAID_MEMBERS start=1 elseif IsInGroup() or LT.Debug.flags.is_group then prefix="party" count=MAX_PARTY_MEMBERS start=0 else prefix="solo" count=0 start=0 end if LT.Debug.on then -- safety... if LT.Debug.flags.add_players then -- player list has already been created, just return elseif prefix == "solo" then local name, rank, englishClass = GetPlayer("player") if name~=nil then local entry={ ["name"]=name, ["rank"]=rank, ["class"]=englishClass, } tinsert(ret,entry) retName[name]=entry end else local class = 0 for index = start,count do local guildName, guildRankName, guildRankIndex, realm local id if index>0 then id=prefix..index if class >= 9 then class = 1 else class = class + 1 end else id="player" end -- handle name and class local name = id local localizedClass, englishClass, classIndex if index == 0 then -- get the real player info localizedClass, englishClass, classIndex = UnitClass(id) elseif class == 1 then englishClass = "WARRIOR" elseif class == 2 then englishClass = "PALADIN" elseif class == 3 then englishClass = "HUNTER" elseif class == 4 then englishClass = "ROGUE" elseif class == 5 then englishClass = "PRIEST" elseif class == 6 then englishClass = "MAGE" elseif class == 7 then englishClass = "WARLOCK" elseif class == 8 then englishClass = "DRUID" elseif class == 9 then englishClass = "WARRIOR" end -- Guild section assume this works... :) local rank="" if name~=nil then local entry={ ["name"]=name, ["rank"]=rank, ["class"]=englishClass, } tinsert(ret,entry) retName[name]=entry OutPlayer(entry) end end end else -- normal operation for index = start,count do local guildName, guildRankName, guildRankIndex, realm local id if index>0 then id=prefix..index else id="player" end if UnitInParty(id) then local name, rank, englishClass = GetPlayer(id) if name~=nil then local entry={ ["name"]=name, ["rank"]=rank, ["class"]=englishClass, } tinsert(ret,entry) retName[name]=entry OutPlayer(entry) end end end end if unsort then sort(ret,function(a,b) return (a.class<b.class or (a.class==b.class and a.name < b.name)) end) end return ret,retName end --[[ local NAME: Track.GetAutoChannel DESC: Select the channel type depending on the type of group the player is in. :DESC VAR: None OUT: channel - String for SendChatMessage --]] function Track.GetAutoChannel() -- Return an appropriate channel in order of preference: /raid, /p, /s local channel if IsInRaid() then channel = "RAID" elseif IsInGroup() then channel = "PARTY" else channel = "SAY" end return channel end --[[ local NAME: Track.AddChat DESC: Send the message to the channel type depending on the type of group the player is in. :DESC VAR: msg - string message to send OUT: None --]] function Track.AddChat(msg) if msg~=nil and msg~="" then if IsInGroup() or IsInRaid() then SendChatMessage(msg , Track.GetAutoChannel()) else DEFAULT_CHAT_FRAME:AddMessage(msg ,Track.DB.ColorChat.r ,Track.DB.ColorChat.g ,Track.DB.ColorChat.b ,Track.DB.ColorChat.a) end end end --[[ local NAME: Track.SaveAnchors DESC: Save where the window is and its size. :DESC VAR: None OUT: None --]] function Track.SaveAnchors() Track.DB.X = TitanPanelLootTypeMainWindow:GetLeft() Track.DB.Y = TitanPanelLootTypeMainWindow:GetTop() Track.DB.Width = TitanPanelLootTypeMainWindow:GetWidth() Track.DB.Height = TitanPanelLootTypeMainWindow:GetHeight() end --[[ local NAME: Track.ShowWindow DESC: - Enable buttons - Show window - Update the player list with any rolls :DESC VAR: None OUT: None --]] function Track.ShowWindow() if IsLead() then TitanPanelLootTypeFrameClearButton:Enable() TitanPanelLootTypeFrameAnnounceButton:Enable() TitanPanelLootTypeFrameNotRolledButton:Enable() else TitanPanelLootTypeFrameClearButton:Disable() TitanPanelLootTypeFrameAnnounceButton:Disable() TitanPanelLootTypeFrameNotRolledButton:Disable() end TitanPanelLootTypeMainWindow:Show() Track.UpdateRollList() end --[[ local NAME: Track.ResetWindow DESC: - Reset window to default position and size :DESC VAR: None OUT: None --]] function Track.ResetWindow() TitanPanelLootTypeMainWindow:ClearAllPoints() TitanPanelLootTypeMainWindow:SetPoint("Center", UIParent, "Center", 0, 0) TitanPanelLootTypeMainWindow:SetWidth(200) TitanPanelLootTypeMainWindow:SetHeight(200) Track.SaveAnchors() Track.ShowWindow() end --[[ local NAME: Track.HideWindow DESC: - Hide the main tracker window :DESC VAR: None OUT: None --]] function Track.HideWindow() TitanPanelLootTypeMainWindow:Hide() end --[[ local NAME: Track.Init DESC: - Initialize variables - Get last position and size of main frame - Register for needed events :DESC VAR: None OUT: None --]] function Track.Init() -- Add color Track.DB.ColorChat = {a=1,r=1,g=1,b=1} Track.DB.ColorNormal = {a=1,r=1,g=1,b=1} Track.DB.ColorCheat = {a=1,r=1,g=.8,b=.8} Track.DB.ColorGuild = {a=1,r=.2,g=1,b=.2} Track.DB.ColorInfo = {a=1,r=.6,g=.6,b=.6} Track.DB.ColorScroll = {a=1,r=.8,g=.8,b=.8} -- For now, hard code some options Track.DB.ClearOnStart = true Track.DB.OpenOnStart = true Track.DB.ShowNotRolled = true Track.DB.ShowGuildRank = true Track.DB.tie_breaker = 0 Track.rollArray = {} Track.rollNames = {} Track.allRolled = false -- TitanPanelLootTypeMainWindow:SetMinResize(194,170) TitanPanelLootTypeMainWindow:SetMinResize(225,250) local x, y, w, h = Track.DB.X, Track.DB.Y, Track.DB.Width, Track.DB.Height if not x or not y or not w or not h then Track.SaveAnchors() else TitanPanelLootTypeMainWindow:ClearAllPoints() TitanPanelLootTypeMainWindow:SetPoint("TOPLEFT", UIParent, "BOTTOMLEFT", x, y) TitanPanelLootTypeMainWindow:SetWidth(w) TitanPanelLootTypeMainWindow:SetHeight(h) end -- using strings from GlobalStrings.lua Track.PatternRoll = Tool.CreatePattern(RANDOM_ROLL_RESULT) local media = LibStub("LibSharedMedia-3.0") local newfont = media:Fetch("font", TitanPanelGetVar("FontName")) Tool.Font = newfont Tool.FontSize = TitanPanelGetVar("FontSize") -- TitanPanelLootTypeMainWindowTitle:SetFont(Tool.Font, Tool.FontSize) TitanPanelLootTypeMainWindowTitle:SetText( string.format(Track.TxtEscapePicture,Track.IconDice) .." "..Track.MSGPREFIX ) Tool.SetButtonFont(TitanPanelLootTypeFrameRollButton) -- sets all buttons... TitanPanelLootTypeFrameRollButton:SetText(string.format(Track.TxtEscapePicture,Track.IconDice).. L["BtnRoll"]) TitanPanelLootTypeFramePassButton:SetText(string.format(Track.TxtEscapePicture,Track.IconPass)..L["BtnPass"]) TitanPanelLootTypeFrameAnnounceButton:SetText(L["BtnAnnounce"]) TitanPanelLootTypeFrameNotRolledButton:SetText(L["BtnNotRolled"]) TitanPanelLootType.ResizeButtons() TitanPanelLootTypeFrameClearButton:SetText(L["BtnClear"]) Tool.EnableSize (TitanPanelLootTypeMainWindow, 8, nil, Track.SaveAnchors) Tool.EnableMoving (TitanPanelLootTypeMainWindow, Track.SaveAnchors) TitanPanelLootTypeFrame:Show() local str = ".Init" .." register for events" LootDebug (str, "events") -- Should be ready for events we are interested in TitanPanelLootTypeButton:RegisterEvent("CHAT_MSG_SYSTEM", TitanPanelLootTypeButton_OnEvent) TitanPanelLootTypeButton:RegisterEvent("CHAT_MSG_PARTY", TitanPanelLootTypeButton_OnEvent) TitanPanelLootTypeButton:RegisterEvent("CHAT_MSG_PARTY_LEADER", TitanPanelLootTypeButton_OnEvent) TitanPanelLootTypeButton:RegisterEvent("CHAT_MSG_RAID", TitanPanelLootTypeButton_OnEvent) TitanPanelLootTypeButton:RegisterEvent("CHAT_MSG_RAID_LEADER", TitanPanelLootTypeButton_OnEvent) end --[[ local NAME: Track.Close DESC: - Stop the - Get last position and size of main frame - Register for needed events :DESC VAR: None OUT: None --]] function Track.Close() Track.DB.RollInProcess = false Track.HideWindow() if Track.DB.ClearOnClose then Track.ClearRolls() end end --[[ local NAME: Track.Event_CHAT_MSG_SYSTEM DESC: - Monitor system chat for player rolls; add the roll when one is found :DESC VAR: arg1 - the message sent OUT: None --]] function Track.Event_CHAT_MSG_SYSTEM (arg1) local str = "Event_CHAT_MSG_SYSTEM" .." m'"..tostring(arg1).."'" LootDebug (str, "events") if Track.DB.RollInProcess then for name, roll, low, high in string.gmatch(arg1, Track.PatternRoll) do --print(".."..name.." "..roll.." "..low.." "..high) Track.AddRoll(name,roll,low,high) end end end --[[ local NAME: Track.Event_Generic_CHAT_MSG DESC: - Monitor general chat for: - a pass ('pass' or localized version) - Roll start - Roll end :DESC VAR: msg - the message sent VAR: name - player that sent the message OUT: None --]] function Track.Event_Generic_CHAT_MSG(msg,name) local str = "Event_Generic_CHAT_MSG" .." '"..tostring(name).."'" .." m'"..tostring(roll).."'" LootDebug (str, "events") -- prevent 'random' rolls from popping windows if Track.DB.RollInProcess then if msg == L["TextPass"] or msg == "pass" then name=Tool.Split(name, "-")[1] Track.AddRoll(name,"0","1","100") end end -- Assume a 'leader' requested a roll so pop the window if string.sub(msg,1,string.len(Track.MSGPREFIX_START))==Track.MSGPREFIX_START then Track.DB.RollInProcess = true if Track.DB.ClearOnStart then Track.ClearRolls() end if Track.DB.OpenOnStart then Track.ShowWindow() end end -- Check for the 'end' of the roll if string.sub(msg,1,string.len(Track.MSGPREFIX_END))==Track.MSGPREFIX_END then Track.DB.RollInProcess = false if Track.DB.ClearOnStart then Track.ClearRolls() end end -- Check for the 'close' of the roll if string.sub(msg,1,string.len(Track.MSGPREFIX_CLOSE))==Track.MSGPREFIX_CLOSE then Track.Close() end end --[[ local NAME: Track.AddRoll DESC: Process the roll the player made - A pass has a roll of "0" - Only the first roll is marked as valid / invalid - The number of rolls is saved (Count) - A running number (tie_breaker) is added to ensure the first arrived of a tie wins; stored in Place - Always show the main frame to ensure it pops, no harm if already shown :DESC VAR: name - player that sent the roll VAR: roll - player roll - string VAR: low - low value player used - string VAR: high - high player used - string OUT: None --]] function Track.AddRoll(name,roll,low,high) local act = "nyl" local valid = false local valid_ro, valid_bounds, ro, lo, hi = IsRoll(roll,low,high) -- numeric if Track.rollNames[name]==nil then Track.DB.tie_breaker = Track.DB.tie_breaker + 1 -- only count the first roll for each player act = "insert" Track.rollNames[name] = Track.rollNames[name] and Track.rollNames[name] + 1 or 1 -- mark player as having rolled table.insert(Track.rollArray, { Name = name, Roll = ro, Low = lo, High = hi, Count = Track.rollNames[name], Place = Track.DB.tie_breaker, Valid_roll = valid_ro, Valid_bounds = valid_bounds, }) local str = "AddRoll >>" .." '"..tostring(act).."'" .." '"..tostring(name).."'" .." r'"..tostring(roll).."'" .." l'"..tostring(low).."'" .." h'"..tostring(high).."'" .." #'"..tostring(Track.rollNames[name]).."'" LootDebug (str, "players") else -- check for re-rolls. >1 if rolled before act = "update" Track.rollNames[name] = Track.rollNames[name] and Track.rollNames[name] + 1 or 1 -- mark player as having rolled again for i,p in ipairs(Track.rollArray) do if p.Name == name then -- Only first roll is valid, Ignore additional rolls but count them for display p.Count = Track.rollNames[name] local str = "AddRoll >>" .." '"..tostring(act).."'" .." '"..tostring(name).."'" .." r'"..tostring(roll).."'" .." l*'"..tostring(low).."'" .." h*'"..tostring(high).."'" .." #*'"..tostring(Track.rollNames[name]).."'" LootDebug (str, "players") end end end Track.ShowWindow() end --[[ local NAME: Track.SortRolls DESC: Sort ascending by name then place :DESC VAR: a - player a roll info VAR: b - player b roll info OUT: true / false --]] function Track.SortRolls(a, b) -- return a.Roll < b.Roll if a.Roll ~= b.Roll then return a.Roll < b.Roll elseif a.Roll == b.Roll then return a.Place > b.Place end end --[[ local NAME: Track.SortRollsRev DESC: Sort descending by name then place :DESC VAR: a - player a roll info VAR: b - player b roll info OUT: true / false --]] function Track.SortRollsRev(a, b) -- return a.Roll > b.Roll if a.Roll ~= b.Roll then return a.Roll > b.Roll elseif a.Roll == b.Roll then return a.Place < b.Place end end --[[ local NAME: Track.FormatRollText DESC: Format the given roll for display :DESC VAR: roll - numeric VAR: party - player list VAR: partyName - given player list entry OUT: String to use --]] function Track.FormatRollText(roll, party, partyName) local colorTied= Tool.RGBtoEscape(Track.DB.ColorNormal) local colorCheat=((roll.Low ~= 1 or roll.High ~= 100) or (roll.Count > 1)) and Tool.RGBtoEscape(Track.DB.ColorCheat) or colorTied local txtRange=(not roll.Valid_bounds) and format(" (%d-%d)", roll.Low, roll.High) or "" local colorName local iconClass local colorRank=Tool.RGBtoEscape(Track.DB.ColorGuild) local rank="" if partyName[roll.Name] and partyName[roll.Name].class then colorName="|c"..RAID_CLASS_COLORS[partyName[roll.Name].class].colorStr iconClass=Tool.IconClass[partyName[roll.Name].class] end if colorName==nil or Track.DB.ColorName==false then colorName=colorCheat end if iconClass==nil or Track.DB.ShowClassIcon==false then iconClass="" end if Track.DB.ColorName==false then colorRank=colorCheat end if Track.DB.ShowGuildRank and partyName[roll.Name] and partyName[roll.Name].rank then rank=" "..partyName[roll.Name].rank end local txtCount=roll.Count > 1 and format(" [%d]", roll.Count) or "" return "|Hplayer:"..roll.Name.."|h".. string.format("%3d",roll.Roll)..": ".. iconClass..colorName.. roll.Name ..colorRank.. rank.."|r ".. colorCheat..txtRange.."|r ".. colorCheat..txtCount.."|h".. -- colorCheat..roll.Place.."|h".. "\n" end --[[ local NAME: Track.UpdateRollList DESC: Create the player list for display including rolls, 'cheats', guild rank (if in same guild) Rolls are above the line; no rolls yet are below the line :DESC VAR: None OUT: None --]] function Track.UpdateRollList() local rollText = "" local party,partyName = Track.GetPlayerList() table.sort(Track.rollArray, Track.SortRolls) -- format and print rolls, check for ties for i, roll in pairs(Track.rollArray) do rollText=Track.FormatRollText(roll,party,partyName) .. rollText end --if IsInGroup() or IsInRaid() then rollText = rollText.. Tool.RGBtoEscape(Track.DB.ColorInfo) .. L["TxtLine"] .. "\n" local gtxt=Tool.RGBtoEscape(Track.DB.ColorInfo) local missClasses={} allRolled=true for i,p in ipairs(party) do if Track.rollNames[p.name]==nil or Track.rollNames[p.name]==0 then local iconClass=Tool.IconClass[partyName[p.name].class] local rank="" if iconClass==nil or Track.DB.ShowClassIcon==false then iconClass="" else missClasses[partyName[p.name].class]=missClasses[partyName[p.name].class] and missClasses[partyName[p.name].class]+1 or 1 end if Track.DB.ShowGuildRank and partyName[p.name] and partyName[p.name].rank then rank=" "..partyName[p.name].rank end gtxt = gtxt.. "|Hplayer:"..p.name.."|h".. iconClass .. p.name ..rank .."|h\n" allRolled=false end end local ctxt="" if IsInRaid() then local isHorde=(UnitFactionGroup("player"))=="Horde" for i,class in pairs (Tool.Classes) do --for class,count in pairs(missClasses) do if not(isHorde and class=="PALADIN") and not(not isHorde and class=="SHAMAN") then ctxt=ctxt..Tool.IconClass[class]..(missClasses[class] or 0).." " end end if ctxt~="" then ctxt=ctxt.."\n" .. L["TxtLine"] .. "\n" end end if LT.Debug.on then -- TitanDebug("UpdateRollList" .." '"..(rollText or "nyl").."'" .." '"..(ctxt or "nyl").."'" .." '"..(gtxt or "nyl").."'" ) end rollText=rollText..ctxt..gtxt LootDebug (rollText, "rolls") --end -- RollTrackerRollText:SetFont(Tool.Font, Tool.FontSize) RollTrackerRollText:SetText(rollText) -- TitanPanelLootTypeFrameStatusText:SetFont(Tool.Font, Tool.FontSize) TitanPanelLootTypeFrameStatusText:SetText(string.format(L["MsgNbRolls"], table.getn(Track.rollArray))) -- TitanPanelLootTypeFrameClearButton:SetFont(Tool.Font, Tool.FontSize) TitanPanelLootTypeFrameClearButton:SetText(L["BtnClear"]) end --[[ local NAME: Track.ClearRolls DESC: Clear the player list of any rolls rolls :DESC VAR: None OUT: None --]] function Track.ClearRolls() if #Track.rollArray>0 then Track.rollArray = {} Track.rollNames = {} end Track.DB.tie_breaker = 0 Track.UpdateRollList() end --[[ local NAME: Track.NotRolled DESC: - Send a nag message via whisper to players who have not rolled - Send a message to group that reminders were sent - Only an IsLead can do this! :DESC VAR: None OUT: None --]] function Track.NotRolled () if IsLead() then local party,partyName = Track.GetPlayerList() local names="" local group = "" if IsInRaid() then group = L["RaidPass"] elseif IsInGroup() then group = L["PartyPass"] else group = "" end for i,p in ipairs(party) do if Track.rollNames[p.name]==nil or Track.rollNames[p.name]==0 then SendChatMessage(Track.MSGPREFIX .. L["NotRolledNag"]..group, WHISPER, nil, p.name) names = "send" end end if names == "send" then Track.AddChat(Track.MSGPREFIX .. L["MsgNotRolled"]) end end end --[[ local NAME: Track.StartRoll DESC: - Pop the main frame - Clear all rolls for a new set - Start a new roll process - Send a message to the group of a new roll - Only an IsLead can do this! :DESC VAR: None OUT: None --]] function Track.StartRoll () Track.ShowWindow() Track.ClearRolls() Track.DB.RollInProcess = true Track.AddChat(Track.MSGPREFIX_START .. "{circle} "..string.format(L["MsgStart"],L["TextPass"])) Track.AddChat(L["MsgBar"]) end --[[ local NAME: Track.RollAnnounce DESC: - Send a message to the group of the winner - Stop the roll process so new rolls are not processed - Only an IsLead can do this! :DESC VAR: None OUT: None --]] function Track.RollAnnounce() local winName="" local winRoll = 0 local addPrefix="" local msg="" local list={} table.sort(Track.rollArray, Track.SortRollsRev) for i, roll in pairs(Track.rollArray) do local str = "AddRoll >>" .." '"..roll.Name.."'" .." r'"..tostring(roll.Roll).."'" LootDebug (str, "players") if roll.Valid_roll then winName= roll.Name winRoll= roll.Roll break -- sort breaks ties, grab first one end end if winName == "" then msg= Track.MSGPREFIX_END .. addPrefix .. "{circle} No winners" else msg= Track.MSGPREFIX_END .. addPrefix .. "{circle} ".. string.format(L["MsgAnnounce"] ,winName, winRoll) end Track.AddChat(msg) Track.DB.RollInProcess = false end --[[ TitanPanelLootType NAME: TitanPanelLootType.ResizeButtons DESC: Determine the size of the buttons so they fill the line on the main frame. VAR: None OUT: None --]] function TitanPanelLootType.ResizeButtons() local w = TitanPanelLootTypeFrameHelperButton:GetWidth() TitanPanelLootTypeFrameRollButton:SetWidth(w/2) TitanPanelLootTypeFramePassButton:SetWidth(w/2) if Track.DB.ShowNotRolled then TitanPanelLootTypeFrameAnnounceButton:SetWidth(w/3) TitanPanelLootTypeFrameClearButton:SetWidth(w/3) TitanPanelLootTypeFrameNotRolledButton:Show() else TitanPanelLootTypeFrameAnnounceButton:SetWidth(w/2) TitanPanelLootTypeFrameClearButton:SetWidth(w/2) TitanPanelLootTypeFrameNotRolledButton:Hide() end end --[[ TitanPanelLootType NAME: TitanPanelLootType.BtnClose DESC: On click of the main frame 'X': Close the main frame; clear rolls; end current roll process VAR: None OUT: None --]] function TitanPanelLootType.BtnClose() Track.Close() if IsLead() then Track.AddChat(Track.MSGPREFIX_CLOSE..L["MsgClosing"]) end end --[[ TitanPanelLootType NAME: TitanPanelLootType.BtnRoll DESC: On click of the main frame Roll: Send the roll to be processed VAR: None OUT: None --]] function TitanPanelLootType.BtnRoll() RandomRoll(1, 100) end --[[ TitanPanelLootType NAME: TitanPanelLootType.BtnPass DESC: On click of the main frame Pass: Send the pass to be processed VAR: None OUT: None --]] function TitanPanelLootType.BtnPass() Track.AddChat(L["TextPass"]) --[[ Note: When in solo debug mode, this just does a /say pass which is NOT picked up by an event. This only monitors party & raid chat... --]] end --[[ TitanPanelLootType NAME: TitanPanelLootType.BtnClearRolls DESC: On click of the main frame Clear: - Clear all rolls - Start a new roll process - Only an IsLead can do this! This handled by enable / disable of buttons when the main frame is created. :DESC VAR: None OUT: None --]] function TitanPanelLootType.BtnClearRolls() if #Track.rollArray>0 then Track.ClearRolls() if Track.DB.CloseOnClear then Track.HideWindow() end end Track.StartRoll() end --[[ TitanPanelLootType NAME: TitanPanelLootType.BtnAnnounce DESC: On click of the main frame "start": - Start a new roll process - Only an IsLead can do this! This handled by enable / disable of buttons when the main frame is created. :DESC VAR: None OUT: None --]] function TitanPanelLootType.BtnAnnounce(button) Track.RollAnnounce() if Track.DB.ClearOnAnnounce then Track.ClearRolls() end if Track.DB.CloseOnAnnounce then Track.HideWindow() end end --[[ TitanPanelLootType NAME: TitanPanelLootType.BtnNotRolled DESC: On click of the main frame "remind": - Call the routine to nag those who have not rolled - Only an IsLead can do this! This handled by enable / disable of buttons when the main frame is created. :DESC VAR: None OUT: None --]] function TitanPanelLootType.BtnNotRolled() Track.NotRolled() end -- Debug!!! function TitanPanelLootType.AddAllRollsDebug() -- rolls for all players local party,partyName = Track.GetPlayerList() -- walk the player list, adding rolls for i,p in ipairs(party) do -- 0 (zero) allows a 'pass' Track.AddRoll(p.name, tostring(random(0,100)), "1", "100") end -- Now show the results Track.UpdateRollList() end function TitanPanelLootType.AddRollDebug(...) -- single roll Track.AddRoll(...) end --[[ TitanPanelLootType NAME: TitanPanelLootTypeButton_OnLoad DESC: On load of this addon: - Get Titan registry values - Get addon saved variable values :DESC VAR: None OUT: None --]] function TitanPanelLootTypeButton_OnLoad(self) self.registry = { id = TITAN_LOOTTYPE_ID, category = "Built-ins", version = TITAN_VERSION, menuText = L["TITAN_LOOTTYPE_MENU_TEXT"], buttonTextFunction = "TitanPanelLootTypeButton_GetButtonText", tooltipTitle = L["TITAN_LOOTTYPE_TOOLTIP"], tooltipTextFunction = "TitanPanelLootTypeButton_GetTooltipText", icon = "Interface\\AddOns\\TitanClassicLootType\\TitanClassicLootType", iconWidth = 16, controlVariables = { ShowIcon = true, ShowLabelText = true, ShowRegularText = false, ShowColoredText = false, DisplayOnRightSide = false }, savedVariables = { ShowIcon = 1, ShowLabelText = 1, RandomRoll = 100, DB = {}, -- ShowDungeonDiff = false, -- DungeonDiffType = "AUTO", } }; self:RegisterEvent("PLAYER_ENTERING_WORLD", TitanPanelLootTypeButton_OnEvent) self:RegisterEvent("GROUP_ROSTER_UPDATE"); self:RegisterEvent("RAID_ROSTER_UPDATE"); self:RegisterEvent("PARTY_LOOT_METHOD_CHANGED"); self:RegisterEvent("CHAT_MSG_SYSTEM"); if not TitanClassicLootTypeSaved then -- first time or clean install Track.DB = {} else Track.DB = TitanClassicLootTypeSaved end end --[[ TitanPanelLootType NAME: TitanPanelLootTypeButton_OnEvent DESC: Parse events registered to plugin and act on them VAR: None OUT: None --]] function TitanPanelLootTypeButton_OnEvent(self, event, ...) LootDebug (event, "events") -- could generate a lot of messages... if (event == "CHAT_MSG_SYSTEM") then Track.Event_CHAT_MSG_SYSTEM (...) end if (event == "CHAT_MSG_PARTY") then Track.Event_Generic_CHAT_MSG(...) end if (event == "CHAT_MSG_PARTY_LEADER") then Track.Event_Generic_CHAT_MSG(...) end if (event == "CHAT_MSG_RAID") then Track.Event_Generic_CHAT_MSG(...) end if (event == "CHAT_MSG_RAID_LEADER") then Track.Event_Generic_CHAT_MSG(...) end if (event == "PLAYER_ENTERING_WORLD") then Track.Init() end TitanPanelPluginHandle_OnUpdate(updateTable) end --[[ TitanPanelLootType NAME: TitanPanelLootTypeButton_GetButtonText DESC: Determine loot type and then display on button VAR: None OUT: None --]] function TitanPanelLootTypeButton_GetButtonText(id) local lootTypeText, lootThreshold, color -- if (GetNumSubgroupMembers() > 0) or (GetNumGroupMembers() > 0) then if IsInRaid() or IsInGroup() then lootTypeText = TitanLootMethod[GetLootMethod()].text; lootThreshold = GetLootThreshold(); color = _G["ITEM_QUALITY_COLORS"][lootThreshold]; else lootTypeText = _G["SOLO"]; color = _G["GRAY_FONT_COLOR"]; end return L["TITAN_LOOTTYPE_BUTTON_LABEL"], TitanUtils_GetColoredText(lootTypeText, color); end --[[ TitanPanelLootType NAME: TitanPanelLootTypeButton_GetTooltipText DESC: Prepare the tool tip text. The tool tip is determined by whether the player is in a group or not. :DESC VAR: None OUT: None --]] function TitanPanelLootTypeButton_GetTooltipText() -- if (GetNumSubgroupMembers() > 0) or (GetNumGroupMembers() > 0) then if IsInRaid() or IsInGroup() then local lootTypeText = TitanLootMethod[GetLootMethod()].text; local lootThreshold = GetLootThreshold(); local itemQualityDesc = _G["ITEM_QUALITY"..lootThreshold.."_DESC"]; local color = _G["ITEM_QUALITY_COLORS"][lootThreshold]; return "".. _G["LOOT_METHOD"]..": \t"..TitanUtils_GetHighlightText(lootTypeText).."\n".. _G["LOOT_THRESHOLD"]..": \t"..TitanUtils_GetColoredText(itemQualityDesc, color).."\n".. TitanUtils_GetGreenText(L["TITAN_LOOTTYPE_TOOLTIP_HINT1"]).."\n" -- ..TitanUtils_GetGreenText(L["TITAN_LOOTTYPE_TOOLTIP_HINT2"]) else return --TitanUtils_GetNormalText(_G["ERR_NOT_IN_GROUP"]).."\n".. TitanUtils_GetGreenText(L["TITAN_LOOTTYPE_TOOLTIP_HINT1"]).."\n" -- TitanUtils_GetGreenText(L["TITAN_LOOTTYPE_TOOLTIP_HINT2"]); end end --[[ TitanPanelLootType NAME: TitanPanelRightClickMenu_PrepareLootTypeMenu DESC: Display rightclick menu options. :DESC VAR: None OUT: None --]] function TitanPanelRightClickMenu_PrepareLootTypeMenu() local info = {}; TitanPanelRightClickMenu_AddTitle(TitanPlugins[TITAN_LOOTTYPE_ID].menuText); info = {}; info.notCheckable = true TitanPanelRightClickMenu_AddToggleIcon(TITAN_LOOTTYPE_ID); TitanPanelRightClickMenu_AddToggleLabelText(TITAN_LOOTTYPE_ID); TitanPanelRightClickMenu_AddSpacer(); TitanPanelRightClickMenu_AddCommand(L["TITAN_PANEL_MENU_HIDE"], TITAN_LOOTTYPE_ID, TITAN_PANEL_MENU_FUNC_HIDE); end --[[ TitanPanelLootType NAME: TitanPanelLootTypeButton_OnClick DESC: On left click: If isLead then start a new roll If not isLead then do a roll :DESC VAR: None OUT: None --]] function TitanPanelLootTypeButton_OnClick(self, button) if button == "LeftButton" then if IsLead() then TitanPanelLootType.BtnClearRolls() else RandomRoll(1, 100) end end end