Go to most recent revision | Compare with Previous | Blame | View Log
local addon = CreateFrame("Frame","ChatIcons") local TEXTURE_LINK_FORMAT_FORMAT = "|T%%s:%d:%d:0:%d|t" local TEXTURE_LINK_FORMAT local ITEM_LINK_PATTERN = "|c%x%x%x%x%x%x%x%x|Hitem:(%d+):%-?%d+:%-?%d+:%-?%d+:%-?%d+:%-?%d+:%-?%d+:%-?%d+:?-?%d*|h" local SPELL_LINK_PATTERN = "|c%x%x%x%x%x%x%x%x|Hspell:(%d+)|h" local PLAYER_LINK_PATTERN = "|Hplayer:([^|:]+)" local ACHIEVEMENT_LINK_PATTERN = "|Hachievement:(%d+):[%x:-]+|h" -- lazy, I know. Shoot me. local classIcons, raceIcons local EXAMPLE_TEXT = "|Hplayer:CHAT_ICONS_FAKE_NAME_LINK|h[Medihv]|h says: I farmed |cff1eff00|Hitem:21884:0:0:0:0:0:0:0|h[Primal Fire]|h|r for weeks to make my " .. "\124cffa335ee\124Hitem:21848:0:0:0:0:0:0:0\124h[Spellfire Robe]\124h\124r. Man, I thought my |cff71d5ff|Hspell:133|h[Fireball]|h|r hit *so* " .. "hard back then." function addon:OnEvent(event,...) local h = self[event] if type(h) == "function" then h(self,event,...) end end function addon:PLAYER_LOGIN() self:HookChatFrames() self.db = ChatIconsDB self.name = "ChatIcons" self.okay = function() self:ApplyTempOptions() end self.cancel = function() self:ResetTempOptions() end self.default = function() self:ResetOptions() self:ResetTempOptions() if self:IsVisible() then self:Hide() self:Show() end end InterfaceOptions_AddCategory(self) InterfaceOptionsFrame:HookScript("OnHide",self.cancel) self:UpdateTextureLinkFormat() end local function addmsg(...) addon:AddMsgHook(...) end function addon:HookChatFrames() if not self.hooks then self.hooks = {} end local n = "ChatFrame" for i=1,7 do local cf = getglobal(n..i) self.hooks[cf] = cf.AddMessage cf.AddMessage = addmsg end end local function parseMessage(s,iconFormat,pattern,geticon) local matchStart,matchEnd,match = s:find(pattern) while match do local icon = geticon(match) local iconlength = 0 if icon then local iconstring = iconFormat:format(icon) iconlength = #iconstring s = s:sub(1,matchStart - 1) .. iconstring .. s:sub(matchStart) end matchStart,matchEnd,match = s:find(pattern,matchEnd + iconlength) end return s end local function getSpellIcon(id) local _,_,icon = GetSpellInfo(id) return icon end local function getPlayerInfo(name) if name == "CHAT_ICONS_FAKE_NAME_LINK" then return "HUMAN_MALE","MAGE" else if UnitName(name) then local _,race = UnitRace(name) local gender = UnitSex(name) == 3 and "FEMALE" or "MALE" local _,class = UnitClass(name) return race:upper().."_"..gender,class else for i=1,GetNumGuildMembers(true) do local n,_,_,_,_,_,_,_,_,_,class = GetGuildRosterInfo(i) if name == n then return "UNKNOWN",class end end end end end local function getPlayerClassIcon(name) local _,class = getPlayerInfo(name) return classIcons[class] end local function getPlayerRaceIcon(name) return raceIcons[(getPlayerInfo(name))] end local function getAchievementIcon(id) return select(10,GetAchievementInfo(id)) end function addon:ProcessMessage(msg,textureFormat,example) local db = example and self.tempDB or self.db if db.items then msg = parseMessage(msg,textureFormat,ITEM_LINK_PATTERN,GetItemIcon) end if db.spells then msg = parseMessage(msg,textureFormat,SPELL_LINK_PATTERN,getSpellIcon) end if db.achievements then msg = parseMessage(msg,textureFormat,ACHIEVEMENT_LINK_PATTERN,getAchievementIcon) end if example or event == "CHAT_MSG_PARTY" or event == "CHAT_MSG_RAID" or event == "CHAT_MSG_GUILD" then --if db.race then msg = parseMessage(msg,textureFormat,PLAYER_LINK_PATTERN,getPlayerRaceIcon) end if db.class then msg = parseMessage(msg,textureFormat,PLAYER_LINK_PATTERN,getPlayerClassIcon) end end return msg end function addon:AddMsgHook(frame,s,...) if s then s = self:ProcessMessage(s,TEXTURE_LINK_FORMAT) end self.hooks[frame](frame,s,...) end function addon:OnShow() self:ResetTempOptions() if not self.builtGui then self:BuildWidgetMethods() self:BuildGuiOptions() end end function addon:UpdateTextureLinkFormat() local db = self.db local size = db.autosize and 0 or db.size TEXTURE_LINK_FORMAT = TEXTURE_LINK_FORMAT_FORMAT:format(size,size,db.offset) end function addon:ResetTempOptions() if not self.tempDB then self.tempDB = {} end for k,v in pairs(self.db) do self.tempDB[k] = v end end function addon:ResetOptions() ChatIconsDB = { items = true, spells = true, -- race = false, class = false, size = 12, offset = -3, autosize = true, exampleFontSize = 14, } self.db = ChatIconsDB end function addon:ApplyTempOptions() for k,v in pairs(self.tempDB) do self.db[k] = v end self:UpdateTextureLinkFormat() end local createCheckButton, checkbutton_PostClick, widget_OnShow, slider_Disable, slider_Enable, widget_SetDependency function addon:BuildGuiOptions() local t = self:CreateFontString(nil,"ARTWORK","GameFontNormalLarge") t:SetText("ChatIcons") t:SetPoint("TOPLEFT",16,-16) self.title = t t = self:CreateFontString(nil,"ARTWORK","GameFontHighlightSmall") t:SetText("Adds icons to your chat frames.") t:SetPoint("TOPLEFT",self.title,"BOTTOMLEFT",0,0) t:SetPoint("RIGHT",-32,0) t:SetHeight(32) t:SetJustifyH("LEFT") self.subtext = t self.itemIcons = createCheckButton("Item Icons","items","Item icons are added next to item links in chat.","TOPLEFT",self.subtext,"BOTTOMLEFT",-2,-8) self.spellIcons = createCheckButton("Spell Icons","spells","Spell icons are added next to spell links in chat.","TOPLEFT",self.itemIcons,"BOTTOMLEFT",0,-8) self.classIcons = createCheckButton("Player Class Icons","class","Class icons are added next to players' names when they speak in party, raid or guild chat.","TOPLEFT",self.spellIcons,"BOTTOMLEFT",0,-8) self.achIcons = createCheckButton("Achievement Icons","achievements","Achievement icons are added next to achievement links in chat.","TOPLEFT",self.classIcons,"BOTTOMLEFT",0,-8) --self.raceIcons = createCheckButton("Player Race Icons","race","Race icons are added next to players' names when they speak in party, raid or guild chat.","TOPLEFT",self.classIcons,"BOTTOMLEFT",0,-8) --self.moneyIcons = createCheckButton("Coin Icons","money","","TOPLEFT",self.classIcons,"BOTTOMLEFT",0,-8) self.autosize = createCheckButton("Use Icon Auto-Sizing","autosize","Icons are sized to be the same height as the surrounding text.","TOPRIGHT",self.subtext,"BOTTOMRIGHT",-110,-8) local iconSize = createSlider("Icon Size","size",5,30,"Sets the width and height of the icons that appear in chat.","TOPLEFT",self.autosize,"BOTTOMLEFT",3,-20) iconSize:SetDependency(self.autosize,true) self.iconSize = iconSize self.verticalOffset = createSlider("Vertical Offset","offset",-15,15,"Sets the vertical offset of the icon in pixels from the top.","TOPLEFT",self.iconSize,"BOTTOMLEFT",0,-32) local e = CreateFrame("Frame",nil,self) e:SetWidth(357) e:SetHeight(100) e:SetPoint("BOTTOMLEFT",15,50) e:SetBackdrop(GameTooltip:GetBackdrop()) -- lol, cheater e:SetBackdropColor(0,0,0,.5) e:SetBackdropBorderColor(0.5,0.5,0.5,.5) self.exampleBox = e t = self:CreateFontString(nil,"ARTWORK","GameFontNormal") t:SetText("Example Text") t:SetPoint("BOTTOMLEFT",e,"TOPLEFT",4,0) t = e:CreateFontString(nil,"ARTWORK","GameFontHighlight") t:SetPoint("TOPLEFT",5,-5) t:SetPoint("BOTTOMRIGHT",-10,10) t:SetJustifyH("LEFT") t:SetJustifyV("TOP") self.exampleText = t self.exampleTextFontSize = createSlider("Example Text Font Size","exampleFontSize",7,25,"Sets the font size used in the example text.","TOPLEFT",t,"BOTTOMLEFT",0,-24) self.builtGui = true end function addon:UpdateExamples() if not self.exampleText then return end local db = self.tempDB local size = db.autosize and 0 or db.size local format = TEXTURE_LINK_FORMAT_FORMAT:format(size,size,db.offset) self.format = format local t = self.exampleText local font,size,flags = t:GetFont() t:SetFont(font,db.exampleFontSize,flags) self.exampleText:SetText(self:ProcessMessage(EXAMPLE_TEXT,format,true)) end function addon:BuildWidgetMethods() checkbutton_PostClick = function(b) local value = b:GetChecked() self.tempDB[b.option] = value and true or false -- to force a value into the database when nil is returned self:UpdateExamples() if b.dependentWidgets then for _,widget in pairs(b.dependentWidgets) do widget:OnDependencyValueChanged(value) end end end slider_Disable = function(s) s:EnableMouse(false) local c = GRAY_FONT_COLOR s.text:SetTextColor(c.r, c.g, c.b) s.valueText:Hide() s.lowText:SetTextColor(c.r, c.g, c.b) s.highText:SetTextColor(c.r, c.g, c.b) s.thumb:Hide() end slider_Enable = function(s) local c = HIGHLIGHT_FONT_COLOR s.text:SetTextColor(c.r, c.g, c.b) s.valueText:Show() local c = NORMAL_FONT_COLOR s.lowText:SetTextColor(c.r, c.g, c.b) s.highText:SetTextColor(c.r, c.g, c.b) s:EnableMouse(true) s.thumb:Show() end slider_OnValueChanged = function(s) local value = s:GetValue() s.valueText:SetText(value) self.tempDB[s.option] = value self:UpdateExamples() end widget_OnShow = function(w) w:SetValue(self.tempDB[w.option]) end widget_SetDependency = function(w,parent,invert) if not parent.dependentWidgets then parent.dependentWidgets = {} end w.invertDependency = invert table.insert(parent.dependentWidgets,w) w:OnDependencyValueChanged(parent:GetValue()) end widget_OnDependencyValueChanged = function(w,value) if w.invertDependency then value = not value end if value then w:Enable() else w:Disable() end end end local function setupWidget(widget,name,option,tooltipText,...) local text = getglobal(widget:GetName().."Text") -- ew text:SetText(name) widget.text = text widget:SetPoint(...) widget.tooltipText = tooltipText widget.option = option widget.SetDependency = widget_SetDependency widget.OnDependencyValueChanged = widget_OnDependencyValueChanged widget:SetScript("OnShow",widget_OnShow) widget_OnShow(widget) end createCheckButton = function(name,option,tooltipText,...) local b = CreateFrame("CheckButton","ChatIcons - "..name,addon,"InterfaceOptionsCheckButtonTemplate") b.SetValue = b.SetChecked b.GetValue = b.GetChecked b:SetScript("PostClick",checkbutton_PostClick) setupWidget(b,name,option,tooltipText,...) b:SetHitRectInsets(0,-b.text:GetWidth(),0,0) return b end createSlider = function(name,option,min,max,tooltipText,...) local s = CreateFrame("Slider","ChatIcons - "..name,addon,"OptionsSliderTemplate") local t = s:CreateFontString(nil,"ARTWORK","GameFontHighlightSmall") t:SetPoint("TOP",s,"BOTTOM") s.valueText = t t = getglobal(s:GetName() .. "Low") -- ew t:SetText(min) s.lowText = t t = getglobal(s:GetName() .. "High") -- ew t:SetText(max) s.highText = t s.thumb = getglobal(s:GetName() .. "Thumb") -- ew s.Enable = slider_Enable s.Disable = slider_Disable s:SetScript("OnValueChanged",slider_OnValueChanged) s:SetMinMaxValues(min,max) s:SetValueStep(1) setupWidget(s,name,option,tooltipText,...) return s end classIcons = { DEATHKNIGHT = "Interface\\Icons\\Spell_Deathknight\\ClassIcon" DRUID = "Interface\\Icons\\INV_Misc_MonsterClaw_04", WARLOCK = "Interface\\Icons\\Spell_Nature_FaerieFire", HUNTER = "Interface\\Icons\\INV_Weapon_Bow_07", MAGE = "Interface\\Icons\\INV_Staff_13", PRIEST = "Interface\\Icons\\INV_Staff_30", WARRIOR = "Interface\\Icons\\INV_Sword_27", SHAMAN = "Interface\\Icons\\Spell_Nature_BloodLust", PALADIN = "Interface\\AddOns\\ChatIcons\\images\\UI-CharacterCreate-Classes_Paladin", ROGUE = "Interface\\AddOns\\ChatIcons\\images\\UI-CharacterCreate-Classes_Rogue", } --[[raceIcons = { HUMAN_MALE = "Interface\\AddOns\\ChatIcons\\images\\UI-CharacterCreate-Races_Human-Male", HUMAN_FEMALE = "Interface\\AddOns\\ChatIcons\\images\\UI-CharacterCreate-Races_Human-Female", GNOME_MALE = "Interface\\AddOns\\ChatIcons\\images\\UI-CharacterCreate-Races_Gnome-Male", GNOME_FEMALE = "Interface\\AddOns\\ChatIcons\\images\\UI-CharacterCreate-Races_Gnome-Female", DWARF_MALE = "Interface\\AddOns\\ChatIcons\\images\\UI-CharacterCreate-Races_Dwart-Male", DWARF_FEMALE = "Interface\\AddOns\\ChatIcons\\images\\UI-CharacterCreate-Races_Dwarf-Female", NIGHTELF_MALE = "Interface\\AddOns\\ChatIcons\\images\\UI-CharacterCreate-Races_NightElf-Male", NIGHTELF_FEMALE = "Interface\\AddOns\\ChatIcons\\images\\UI-CharacterCreate-Races_NightElf-Female", DRAENEI_MALE = "Interface\\AddOns\\ChatIcons\\images\\UI-CharacterCreate-Races_Draenei-Male", DRAENEI_FEMALE = "Interface\\AddOns\\ChatIcons\\images\\UI-CharacterCreate-Races_Draenei-Female", UNDEAD_MALE = "Interface\\AddOns\\ChatIcons\\images\\UI-CharacterCreate-Races_Undaed-Male", UNDEAD_FEMALE = "Interface\\AddOns\\ChatIcons\\images\\UI-CharacterCreate-Races_Undead-Female", ORC_MALE = "Interface\\AddOns\\ChatIcons\\images\\UI-CharacterCreate-Races_Orc-Male", ORC_FEMALE = "Interface\\AddOns\\ChatIcons\\images\\UI-CharacterCreate-Races_Orc-Female", TROLL_MALE = "Interface\\AddOns\\ChatIcons\\images\\UI-CharacterCreate-Races_Troll-Male", TROLL_FEMALE = "Interface\\AddOns\\ChatIcons\\images\\UI-CharacterCreate-Races_Troll-Female", TAUREN_MALE = "Interface\\AddOns\\ChatIcons\\images\\UI-CharacterCreate-Races_Tauren-Male", TAUREN_FEMALE = "Interface\\AddOns\\ChatIcons\\images\\UI-CharacterCreate-Races_Tauren-Female", BLOODELF_MALE = "Interface\\AddOns\\ChatIcons\\images\\UI-CharacterCreate-Races_BloodElf-Male", BLOODELF_FEMALE = "Interface\\AddOns\\ChatIcons\\images\\UI-CharacterCreate-Races_BloodElf-Female", } ]] addon:SetScript("OnShow",addon.OnShow) addon:SetScript("OnEvent",addon.OnEvent) addon:RegisterEvent("PLAYER_LOGIN") addon:ResetOptions()