You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1101 lines
39 KiB

-- module independent variables --
----------------------------------
local addon,ns = ...;
local C,L,I=ns.LC.color,ns.L,ns.I;
-- module own local variables and local cached functions --
-----------------------------------------------------------
local name = "Guild"; -- GUILD L["ModDesc-Guild"]
local ttName,ttName2,ttColumns,ttColumns2,tt,tt2,module = name.."TT", name.."TT2",10,2;
local pattern_FRIEND_OFFLINE = ERR_FRIEND_OFFLINE_S:gsub("%%s","(.*)"):trim();
local pattern_FRIEND_ONLINE = ERR_FRIEND_ONLINE_SS:gsub("[\124:%[%]]","#"):gsub("%%s","(.*)"):trim();
local knownMemberRaces = {}; -- filled by updateBroker
local memberLevels = {}; -- filled by updateBroker
local memberIndex = {}; -- filled by updateBroker
local membersOnline = {}; -- filled by createTooltip
local applicants = {}; -- filled by createTooltip
local tradeskills = {}; -- filled by updateTradeSkills
local bnetFriends = {}; -- filled by updateBattleNetFriends
local flags = {}; -- filled by module.onenter
local ttHooks = {} -- filled by module.onenter
local applScroll = {step=0,stepWidth=3,numLines=5,lines={},lineCols={},slider=false,regionColor={1,.5,0,.15}};
local membScroll = {step=0,stepWidth=5,numLines=15,lines={},lineCols={},slider=false,regionColor={1,.82,0,.11}};
local tradeSkillLock,tradeSkillsUpdateDelay,chatNotificationEnabled,frame = false,0;
local icon_arrow_right = "|T"..ns.icon_arrow_right..":0|t";
local triggerLockTradeSkill,triggerLockRequestUpdate = false,false
local CanViewOfficerNote = CanViewOfficerNote or C_GuildInfo.CanViewOfficerNote;
local BACKDROP_SLIDER_8_8 = BACKDROP_SLIDER_8_8 or { -- classic
bgFile = "Interface\\Buttons\\UI-SliderBar-Background",
edgeFile = "Interface\\Buttons\\UI-SliderBar-Border",
tile = true,
tileEdge = true,
tileSize = 8,
edgeSize = 8,
insets = { left = 3, right = 3, top = 6, bottom = 6 },
};
-- register icon names and default files --
-------------------------------------------
I[name] = {iconfile=135026,coords={0.05,0.95,0.05,0.95}} --IconName::Guild--
-- some local functions --
--------------------------
local function CanUpdateApplicants()
return (IsGuildLeader() or C_GuildInfo.IsGuildOfficer()) and C_ClubFinder.IsEnabled();
end
local function RequestGuildRosterUpdate()
if triggerLockRequestUpdate then return end
triggerLockRequestUpdate = true
if GuildRoster then
GuildRoster(); -- for classic // trigger GUILD_ROSTER_UPDATE
else
C_GuildInfo.GuildRoster(); -- trigger GUILD_ROSTER_UPDATE
RequestGuildChallengeInfo(); -- trigger GUILD_CHALLENGE_UPDATED
end
C_Timer.After(0.1,function() triggerLockRequestUpdate = false end)
end
local function GetApplicants()
if CanUpdateApplicants() then
local guildClubId = C_Club.GetGuildClubId();
if guildClubId then
return (C_ClubFinder.ReturnClubApplicantList(guildClubId) or {});
end
end
return {};
end
local function updateTradeSkills()
if not IsInGuild() then wipe(tradeskills); return; end
if (GuildRosterFrame~=nil and GuildRosterFrame:IsShown()) then return; end
if tradeSkillLock then return end
tradeSkillLock = true;
local skillID,isCollapsed,iconTexture,headerName,numOnline,numVisible,numPlayers,playerName,playerFullName,class,online,zone,skill,classFileName,isMobile,isAway,_
local headers = {};
local header = {};
local collapsed = {};
-- 1. run...
local num = GetNumGuildTradeSkill();
for index=num, 1, -1 do
skillID,isCollapsed,_,headerName = GetGuildTradeSkillInfo(index);
if headerName and isCollapsed then
tinsert(collapsed,skillID);
ExpandGuildTradeSkillHeader(skillID);
end
end
-- 2. run...
local tmp,skillHeader = {},{};
local num = GetNumGuildTradeSkill();
for index=1, num do
skillID,isCollapsed,iconTexture,headerName,_,_,_,_,playerFullName,_,_,_,skill,classFileName = GetGuildTradeSkillInfo(index);
if headerName then
skillHeader = {headerName,iconTexture,skillID};
elseif playerFullName then
if tmp[playerFullName]==nil then
tmp[playerFullName]={};
end
tinsert(
tmp[playerFullName],
{
skillHeader[1],
skillHeader[2] or ns.icon_fallback,
skill,
skillHeader[3] or skillID
}
);
end
end
tradeskills = tmp;
-- 3. run... collapse prev. expanded skills
for i=1, #collapsed do
CollapseGuildTradeSkillHeader(collapsed[i]);
end
tradeSkillLock = false;
end
local function updateBattleNetFriends()
if ns.client_version<2 then
return;
end
wipe(bnetFriends);
if BNConnected() then
for i=1, (BNGetNumFriends()) do
local accountInfo = ns.C_BattleNet_GetFriendAccountInfo(i);
if accountInfo and accountInfo.accountName and accountInfo.gameAccountInfo and accountInfo.gameAccountInfo.clientProgram=="WoW" and accountInfo.gameAccountInfo.playerGuid then
bnetFriends[accountInfo.gameAccountInfo.playerGuid] = accountInfo.accountName;
end
end
end
end
local function updateBroker()
local txt = {};
if IsInGuild() then
local numMobile,numMembers,numMembersOnline = 0,GetNumGuildMembers();
for i=1, numMembers do
local mFullName,mRank,mRankIndex,mLevel,mClassLocale,mZone,mNote,mOfficerNote,mOnline,mIsAway,mClassFile,_,_,mIsMobile,_,mStanding,mGUID = GetGuildRosterInfo(i);
local mName, mRealm = strsplit("-",mFullName,2);
-- race names; must be cached by request GetPlayerInfoByGUID. That could take same time.
if ns.profile[name].showRace and not knownMemberRaces[mGUID] then
local _, _, mRaceName = GetPlayerInfoByGUID(mGUID);
if mRaceName then
knownMemberRaces[mGUID] = mRaceName;
end
end
if mIsMobile and mOnline then
numMobile = numMobile + 1;
end
-- levelup notification
if ns.profile[name].showMembersLevelUp and memberLevels[mGUID]~=nil and memberLevels[mGUID]~=mLevel then
ns:print( C(mClassFile,mName) .." ".. C("green",L["has reached Level %d."]:format(mLevel)) );
end
memberLevels[mGUID] = mLevel;
-- for on/off notification
memberIndex[mFullName] = i;
end
if ns.profile[name].showApplicantsBroker and C_ClubFinder and C_ClubFinder.ReturnClubApplicantList then
local applicants = GetApplicants();
if #applicants>0 then
tinsert(txt, C("orange",#applicants));
end
end
if ns.client_version>2 and ns.profile[name].showMobileChatterBroker then
tinsert(txt, C("ltblue",numMobile));
end
tinsert(txt,C("green",numMembersOnline));
if ns.profile[name].showTotalMembersBroker then
tinsert(txt,C("green",numMembers));
end
else
tinsert(txt,L["No guild"]);
end
(ns.LDB:GetDataObjectByName(module.ldbName) or {}).text = table.concat(txt,"/");
end
local function GetMemberRecipes(self,info)
GetGuildMemberRecipes(info.name,info.id);
end
local function memberInviteOrWhisper(self,memberIndex)
local mFullName,_,_,_,_,_,_,_,mOnline,_,_,_,_,mIsMobile,_,_,mGUID = GetGuildRosterInfo(memberIndex);
if IsAltKeyDown() then
if mIsMobile then
ns:print(L["GuildErrorInviteMobile"]);
elseif not mOnline then
ns:print(L["GuildErrorInviteOffline"]);
elseif C_PartyInfo.InviteUnit then
C_PartyInfo.InviteUnit(mFullName);
elseif InviteUnit then
InviteUnit(mFullName);
else
ns:print(L["GuildErrorInviteMissingFunction"]);
end
elseif mOnline then
SetItemRef("player:"..mFullName, ("|Hplayer:%1$s|h[%1$s]|h"):format(mFullName), "LeftButton");
else
ns:print(L["GuildErrorWhisperOffline"]);
end
end
local function showApplication(self,appIndex)
if IsInGuild() then
if (not GuildFrame) then
GuildFrame_LoadUI();
end
if (not GuildFrame:IsShown()) then
ShowUIPanel(GuildFrame)
end
if (not GuildInfoFrameApplicantsContainer:IsVisible()) then
GuildFrameTab5:Click();
GuildInfoFrameTab3:Click();
end
SetGuildApplicantSelection(appIndex);
GuildInfoFrameApplicants_Update();
end
end
local function guildChallengeLineColor(bool)
if bool then
return 1,1,1, 0,1,0;
end
return 1,1,1, 1,1,1;
end
local function createTooltip3(parent,sel)
GameTooltip:SetOwner(parent, "ANCHOR_NONE");
GameTooltip:SetPoint(ns.GetTipAnchor(parent,"horizontal",tt));
local show = false;
if sel=="info" then
GameTooltip:SetText(GUILD_INFORMATION);
GameTooltip:AddLine(" ");
local info = strtrim(GetGuildInfoText() or "");
if info=="" then
info = EMPTY;
else
info = ns.scm(info);
end
GameTooltip:AddLine(info,1,1,1,true);
show = true;
elseif sel=="challenges" then
GameTooltip:AddLine(GUILD_CHALLENGE_LABEL,1,0.82,0);
local order,numChallenges = {1,4,2,3},GetNumGuildChallenges();
for i = 1, numChallenges do
local orderIndex = order[i] or i;
local index, current, max, gold, maxGold = GetGuildChallengeInfo(orderIndex);
if index then
GameTooltip:AddLine(" ");
local goldSum,goldPerRun = "",GetMoneyString(maxGold * COPPER_PER_SILVER * SILVER_PER_GOLD);
GameTooltip:AddDoubleLine(
C("ltblue",_G["GUILD_CHALLENGE_TYPE"..index]),
("%d/%d"):format(current,max),
guildChallengeLineColor(current==max)
);
GameTooltip:AddDoubleLine(
goldPerRun,
goldSum,
1,1,1, 1,1,1
);
end
end
show = true;
end
GameTooltip:Show();
end
local function createTooltip2(self,memberIndex)
local tsName, tsIcon, tsValue, tsID = 1,2,3,4;
local mFullName,mRank,mRankIndex,mLevel,mClassLocale,mZone,mNote,mOfficerNote,mOnline,mIsAway,mClassFile,_,_,mIsMobile,_,mStanding,mGUID = GetGuildRosterInfo(memberIndex);
local mName, mRealm = strsplit("-",mFullName,2);
local s,t,_ = "";
local realm = mRealm or "";
tt2 = ns.acquireTooltip(
{ttName2, ttColumns2, "LEFT","RIGHT"},
{true,true},
{self, "horizontal", tt}
);
if tt2.lines~=nil then tt2:Clear(); end
tt2:AddHeader(C("dkyellow",NAME), C(mClassFile,ns.scm(mName)));
tt2:AddSeparator();
if type(realm)=="string" and realm:len()>0 then
local _,_realm = ns.LRI:GetRealmInfo(realm);
if _realm then realm = _realm; end
end
tt2:AddLine(C("ltblue",L["Realm"]),C("dkyellow",ns.scm(realm)));
if ns.profile[name].showRaceInTT2 then
local mRaceName = knownMemberRaces[mGUID];
if not mRaceName then
_, _, mRaceName = GetPlayerInfoByGUID(mGUID);
if mRaceName then
knownMemberRaces[mGUID] = mRaceName;
end
end
if mRaceName then
tt2:AddLine(C("ltblue",RACE),mRaceName);
end
end
if ns.profile[name].showZoneInTT2 then
tt2:AddLine(C("ltblue",ZONE),mZone);
end
if ns.profile[name].showNotesInTT2 then
tt2:AddLine(C("ltblue",LABEL_NOTE),ns.scm(mNote));
end
if ns.profile[name].showONotesInTT2 then
if mOfficerNote=="" then
tt2:AddLine(C("ltblue",OFFICER_NOTE_COLON),C("gray","<"..EMPTY..">"));
else
tt2:AddLine(C("ltblue",OFFICER_NOTE_COLON),ns.scm(mOfficerNote));
end
end
if ns.profile[name].showRankInTT2 then
tt2:AddLine(C("ltblue",RANK),ns.scm(mRank));
end
if ns.profile[name].showProfessionsInTT2 and tradeskills[mFullName] then
t=tradeskills[mFullName][1];
tt2:AddLine(C("ltblue",TRADE_SKILLS),t[tsName].." |T"..t[tsIcon]..":0|t");
if tradeskills[mFullName][2] then
t=tradeskills[mFullName][2];
tt2:AddLine(" ", t[tsName].." |T"..t[tsIcon]..":0|t");
end
end
tt2:AddSeparator(1,0,0,0,0);
ns.roundupTooltip(tt2);
end
local function ttAddApplicant(lineIndex,applicantInfo)
if not (tt and tt.key and tt.key==ttName) then return end -- interrupt processing on close tooltip
local roles = {};
local isDps,isHealer,isTank = false,false,false;
for _, specID in ipairs(applicantInfo.specIds) do
local role = GetSpecializationRoleByID(specID);
if role=="DAMAGER" and not isDps then
isDps = true;
tinsert(roles,DAMAGER);
elseif role=="HEALER" and not isHealer then
isHealer = true;
tinsert(roles,HEALER);
elseif role=="TANK" and not isTank then
isTank = true;
tinsert(roles,TANK);
end
end
local localizedClass, englishClass, localizedRace, englishRace, sex, playerName, realm = GetPlayerInfoByGUID(applicantInfo.playerGUID);
tt:SetCell(lineIndex,1,applicantInfo.level);
local toonName = C(englishClass, ns.scm(playerName)) .. ns.showRealmName(name,realm);
if ns.profile[name].showBattleTag and bnetFriends[applicantInfo.playerGUID] then
toonName = toonName.." "..C("ltblue","("..ns.scm(bnetFriends[applicantInfo.playerGUID]..")"));
end
tt:SetCell(lineIndex,2,toonName);
tt:SetCell(lineIndex,3,table.concat(roles,", "));
tt:SetCell(lineIndex,4,date("%Y-%m-%d",applicantInfo.lastUpdatedTime+(86400*30)));
tt:SetCell(lineIndex,5,(strlen(applicantInfo.message)>0 and ns.scm(ns.strCut(applicantInfo.message,60)) or C("gray","<"..EMPTY..">")),nil,nil,ttColumns-5);
--tt:SetLineScript(lineIndex,"OnMouseUp",showApplication,applicantIndex);
end
local function ttAddMember(lineIndex,memberIndex)
if not (tt and tt.key and tt.key==ttName) then return end -- interrupt processing on close tooltip
local tsName, tsIcon, tsValue, tsID = 1,2,3,4;
local mFullName,mRank,mRankIndex,mLevel,mClassLocale,mZone,mNote,mOfficerNote,mOnline,mIsAway,mClassFile,_,_,mIsMobile,_,mStanding,mGUID = GetGuildRosterInfo(memberIndex);
local mName, mRealm = strsplit("-",mFullName,2);
if not (tt and tt.key and tt.key==ttName) then return end
local offColor = nil;
if not mOnline then
offColor = "gray";
end
local status;
if mIsMobile then
status = (mIsAway==2 and MOBILE_BUSY_ICON) or (mIsAway==1 and MOBILE_AWAY_ICON) or ChatFrame_GetMobileEmbeddedTexture(73/255, 177/255, 73/255)
else
status = ("|T%s:0|t"):format(_G["FRIENDS_TEXTURE_" .. ((mIsAway==1 and "AFK") or (mIsAway==2 and "DND") or "ONLINE")]);
end
local cellIndex = 3;
-- level
tt:SetCell(lineIndex,1,mLevel);
-- status / member name / realm
local status_name = status .. " " .. C(offColor or mClassFile,ns.scm(mName)) .. ns.showRealmName(name,mRealm,offColor);
if ns.profile[name].showBattleTag and bnetFriends[mGUID] then
status_name = status_name.." "..C(offColor or "ltblue","("..ns.scm(bnetFriends[mGUID]..")"));
end
tt:SetCell(lineIndex,2,status_name);
-- race name
if flags.showRace then
-- race names; must be cached by request GetPlayerInfoByGUID. That could take same time.
local mRaceName = knownMemberRaces[mGUID];
if not mRaceName then
_, _, mRaceName = GetPlayerInfoByGUID(mGUID);
if mRaceName then
knownMemberRaces[mGUID] = mRaceName;
end
end
if offColor then
mRaceName = C(offColor,mRaceName);
end
tt:SetCell(lineIndex,cellIndex,mRaceName or "");
cellIndex = cellIndex + 1;
end
-- zone
if flags.showZone then
local color = offColor or (mIsMobile and not mOnline and "cyan") or false;
local Zone = mZone or "?";
if color then
Zone = C(color,Zone);
end
--if mIsMobile and not mOnline then
-- Zone=C(offColor or "cyan",REMOTE_CHAT);
--end
tt:SetCell(lineIndex,cellIndex,Zone);
cellIndex = cellIndex + 1;
end
-- notes
if flags.showNotes then
local str = ns.scm(mNote);
tt:SetCell(lineIndex,cellIndex,offColor and C(offColor,str) or str);
cellIndex = cellIndex + 1;
end
-- officer notes
if flags.showONotes and CanViewOfficerNote() then -- extend if
local str = ns.scm(mOfficerNote)
tt:SetCell(lineIndex,cellIndex,offColor and C(offColor,str) or str);
cellIndex = cellIndex + 1;
end
-- rank
if flags.showRank then
local rankID="";
if flags.showRank and flags.showRankID then
rankID = " "..C("gray","("..mRankIndex..")");
end
tt:SetCell(lineIndex,cellIndex,C(offColor or (mRankIndex==0 and "green") or "white",ns.scm(mRank))..rankID);
cellIndex = cellIndex + 1;
end
-- professions / trade skills
if flags.showProfessions and tradeskills[mFullName] then
if tradeskills[mFullName][1] then
tt:SetCell(lineIndex,cellIndex,"|T"..tradeskills[mFullName][1][tsIcon]..":0|t");
tt:SetCellScript(lineIndex, cellIndex, "OnMouseUp", GetMemberRecipes,{name=mFullName,id=tradeskills[mFullName][1][4]});
cellIndex = cellIndex + 1;
end
if tradeskills[mFullName][2] then
tt:SetCell(lineIndex,cellIndex,"|T"..tradeskills[mFullName][2][tsIcon]..":0|t");
tt:SetCellScript(lineIndex, cellIndex, "OnMouseUp", GetMemberRecipes,{name=mFullName,id=tradeskills[mFullName][2][4]});
cellIndex = cellIndex + 1;
end
end
if mFullName==ns.player.name_realm_short then
tt:SetLineColor(lineIndex, .5, .5, .5);
else
tt:SetLineColor(lineIndex, 0, 0, 0, 0);
end
tt:SetLineScript(lineIndex, "OnMouseUp", memberInviteOrWhisper, memberIndex);
if ns.profile[name].showZoneInTT2 or ns.profile[name].showNotesInTT2 or ns.profile[name].showONotesInTT2 or ns.profile[name].showRankInTT2 or ns.profile[name].showProfessionsInTT2 then
tt:SetLineScript(lineIndex,"OnEnter",createTooltip2,memberIndex);
end
end
local ttScrollList
local function slider_OnValueChanged()
-- TODO: need content
end
function ttScrollList(delta,tbl) -- executed by createTooltip and ttWheelHook
local scrollInfo,target,new = membScroll,"Members",false;
scrollInfo.numLines = ns.profile[name].numMembersScroll;
if tbl==applicants then
scrollInfo,target = applScroll,"Applicants";
end
local start,stop,numEntries = 0,scrollInfo.numLines,#tbl;
local maxSteps = ceil(numEntries/scrollInfo.stepWidth)-floor(scrollInfo.numLines/scrollInfo.stepWidth);
if delta == 0 then
wipe(scrollInfo.lines);
scrollInfo.step,new = 0,true;
if not scrollInfo.slider then
-- create scroll region
local scrollRegion = CreateFrame("Frame",addon.."Guild"..target.."ScrollRegion",tt,BackdropTemplateMixin and "BackdropTemplate");
scrollInfo.region = scrollRegion;
scrollRegion:SetBackdrop({bgFile="interface/buttons/white8x8"});
scrollRegion:SetBackdropColor(unpack(ns.profile[name].showTableBackground and scrollInfo.regionColor or {0,0,0,0}));
scrollRegion:SetFrameLevel(tt:GetFrameLevel()+1);
scrollRegion:SetScript("OnMouseWheel",function(self,delta)
ttScrollList(-delta, tbl);
end);
scrollRegion:EnableMouseWheel(true);
-- create slider
local slider = CreateFrame("Slider",addon.."Guild"..target.."ScrollSlider",tt,BackdropTemplateMixin and "BackdropTemplate");
scrollInfo.slider = slider;
slider.parent = scrollInfo;
slider:SetOrientation("VERTICAL");
slider:SetBackdrop(BACKDROP_SLIDER_8_8);
slider:SetThumbTexture([[Interface\Buttons\UI-SliderBar-Button-Vertical]]);
slider:SetWidth(12)
slider:SetMinMaxValues(0, 1)
slider:SetValueStep(1)
slider:SetValue(0)
slider:SetScript("OnValueChanged", slider_OnValueChanged);
end
else
local newStep = scrollInfo.step + (delta==true and 0 or delta);
if newStep>maxSteps or numEntries<=scrollInfo.numLines or newStep<0 then
return; -- update not necessary
end
scrollInfo.step = newStep;
start = newStep*scrollInfo.stepWidth;
stop = start+scrollInfo.numLines;
end
-- clear lines
if stop>numEntries then
for i=1, #scrollInfo.lines do
local line = scrollInfo.lines[i];
for cell in pairs(tt.lines[line].cells) do
tt:SetCell(line,cell);
end
end
end
-- set lines
local lineIndex = 1;
for i=1+start, stop do
if tbl[i] then
local line = scrollInfo.lines[lineIndex];
if not line then
line = tt:AddLine();
scrollInfo.lines[lineIndex] = line;
end
if tbl==applicants then
ttAddApplicant(line,tbl[i]);
else
ttAddMember(line,tbl[i]);
end
lineIndex = lineIndex + 1;
end
end
-- update scroll region
if scrollInfo.lines and #scrollInfo.lines>0 then
scrollInfo.region:SetParent(tt);
scrollInfo.region:SetPoint("TOPLEFT",tt.lines[ scrollInfo.lines[1]-2 ],-4,2);
scrollInfo.region:SetPoint("BOTTOMRIGHT",tt.lines[ scrollInfo.lines[#scrollInfo.lines] ],4,-2);
scrollInfo.region:SetFrameLevel(tt:GetFrameLevel()+1);
scrollInfo.region:Show();
scrollInfo.region.hidden = nil;
end
if new and maxSteps>1 then
-- update slider
scrollInfo.slider:SetParent(tt);
scrollInfo.slider:SetPoint("TOPRIGHT",tt.lines[ scrollInfo.lines[1] ],"TOPRIGHT",0,4);
scrollInfo.slider:SetPoint("BOTTOMRIGHT",tt.lines[ scrollInfo.lines[#scrollInfo.lines] ],"BOTTOMRIGHT",0,-4);
scrollInfo.slider:SetFrameLevel(tt.lines[1]:GetFrameLevel()+1);
scrollInfo.slider:SetMinMaxValues(0,maxSteps);
scrollInfo.slider:Show();
scrollInfo.slider.hidden = nil;
end
scrollInfo.slider:SetValue(scrollInfo.step);
end
local function createTooltip(tt,update)
if not (tt and tt.key and tt.key==ttName) then return end -- don't override other LibQTip tooltips...
if tt.lines~=nil then tt:Clear(); end
if (not IsInGuild()) then
tt:AddHeader(C("dkyellow",GUILD));
tt:AddSeparator();
tt:AddLine(C("ltgray",ERR_GUILD_PLAYER_NOT_IN_GUILD));
ns.roundupTooltip(tt);
return;
end
updateBattleNetFriends();
local gName, gDesc, pStanding, pStandingMin, pStandingMax, pStandingValue, pStandingText
if GetGuildFactionInfo then
gName, gDesc, pStanding, pStandingMin, pStandingMax, pStandingValue = GetGuildFactionInfo();
pStandingText = _G["FACTION_STANDING_LABEL"..pStanding];
else -- for classic
gName = GetGuildInfo("player")
end
local _,_,_,gRealm = GetGuildInfo("player");
if gRealm==nil then
gRealm=ns.realm;
end
local numMembers, numMembersOnline = GetNumGuildMembers();
-- HEADER
local l = tt:AddHeader();
tt:SetCell(l,1,C("dkyellow",GUILD) .. " " .. C("green",ns.scm(gName)) .. ns.scm(ns.showRealmName(name,gRealm)), nil,"LEFT",ttColumns);
tt:AddSeparator(4,0,0,0,0);
-- MOTD
local sep=false;
if (ns.profile[name].showMOTD) then
local l = tt:AddLine(C("ltblue",MOTD_COLON));
local motd,color = strtrim(GetGuildRosterMOTD() or ""),"ltgreen";
if motd=="" then
motd,color = EMPTY,"gray"
elseif ns.profile.GeneralOptions.scm then
motd = "***********" -- shorter
else
-- motd = ns.scm(ns.strWrap(motd,56),true)
end
tt:SetCell(l, 2, C(color,motd), nil, nil, 0, nil, nil, nil, 220);
-- SetSell(lineNum, colNum, value, font, justification, colSpan, provider, leftPadding, rightPadding, maxWidth, minWidth, ...)
sep = true;
end
-- PLAYER STANDING
if ns.profile[name].showRep and pStandingValue then
local l = tt:AddLine(C("ltblue",REPUTATION_ABBR..HEADER_COLON));
if pStandingMax-pStandingMin>0 then
pStandingText = ("%s: (%d/%d)"):format(pStandingText, pStandingValue-pStandingMin, pStandingMax-pStandingMin);
end
tt:SetCell(l,2,pStandingText, nil, nil, 0);
sep=true;
end
-- guild info
if ns.profile[name].showInfo then
local l = tt:AddLine();
tt:SetCell(l,1,C("ltblue",GUILD_INFORMATION),nil,"LEFT",ttColumns-1);
tt:SetCell(l,ttColumns,icon_arrow_right,nil,"RIGHT");
tt:SetLineScript(l,"OnEnter",createTooltip3,"info");
tt:SetLineScript(l,"OnLeave",GameTooltip_Hide);
sep=true;
end
-- CHALLENGES
if ns.profile[name].showChallenges and ns.client_version>=6 then
local l = tt:AddLine();
tt:SetCell(l,1,C("ltblue",GUILD_CHALLENGE_LABEL),nil,"LEFT",ttColumns-1);
tt:SetCell(l,ttColumns,icon_arrow_right,nil,"RIGHT");
tt:SetLineScript(l,"OnEnter",createTooltip3,"challenges");
tt:SetLineScript(l,"OnLeave",GameTooltip_Hide);
sep = true;
end
if sep then
tt:AddSeparator(4,0,0,0,0);
end
-- applicants
if ns.profile[name].showApplicants and C_ClubFinder and C_ClubFinder.ReturnClubApplicantList then
applicants = GetApplicants();
if #applicants>0 then
local line,column = tt:AddLine(
C("orange",LEVEL),
C("orange",L["Applicant"]),
C("orange",COMMUNITY_MEMBER_LIST_DROP_DOWN_ROLES),
C("orange",RAID_INSTANCE_EXPIRES_EXPIRED),
C("orange",COMMENT)
);
tt:AddSeparator();
ttScrollList(0,applicants);
tt:AddLine(" ");
end
end
-- member list header line
local titles = {
C("ltyellow",LEVEL), -- [1]
C("ltyellow",CHARACTER), -- [2]
};
if flags.showRace then
tinsert(titles,C("ltyellow",RACE));
end
if flags.showZone then
tinsert(titles,C("ltyellow",ZONE));
end
if flags.showNotes then
tinsert(titles,C("ltyellow",COMMUNITIES_ROSTER_COLUMN_TITLE_NOTE));
end
if flags.showONotes and CanViewOfficerNote() then -- extend if
tinsert(titles,C("ltyellow",OFFICER_NOTE_COLON));
end
if flags.showRank then
tinsert(titles,C("ltyellow",RANK));
end
local l=tt:AddLine(unpack(titles));
if flags.showProfessions then
tt:SetCell(l,#titles+1,C("ltyellow",TRADE_SKILLS), nil,nil,2); -- [8,9]
end
tt:SetCell(l,ttColumns," ");
tt:AddSeparator();
wipe(membersOnline);
for i=1, numMembers do
local mFullName,mRank,mRankIndex,mLevel,mClassLocale,mZone,mNote,mOfficerNote,mOnline,mIsAway,mClassFile,_,_,mIsMobile,_,mStanding,mGUID = GetGuildRosterInfo(i);
if mOnline then
tinsert(membersOnline,i);
end
end
ttScrollList(0,membersOnline);
if (ns.profile.GeneralOptions.showHints) then
tt:AddSeparator(4,0,0,0,0);
if (ns.profile[name].showApplicants) and applicants and #applicants>0 then
local l = tt:AddLine();
tt:SetCell(l,1,C("orange",L["MouseBtn"]).." || "..C("green","Guild applications"),nil,"LEFT",ttColumns);
end
if (ttColumns>4) then
local l = tt:AddLine();
tt:SetCell(l,1,C("ltblue",L["MouseBtn"]).." || "..C("green",WHISPER) .." - ".. C("ltblue",L["ModKeyA"].."+"..L["MouseBtn"]).." || "..C("green",TRAVEL_PASS_INVITE),nil,"LEFT",ttColumns);
else
local l = tt:AddLine();
tt:SetCell(l,1,C("ltblue",L["MouseBtn"]).." || "..C("green",WHISPER),nil,"LEFT",ttColumns);
local l = tt:AddLine();
tt:SetCell(l,1,C("ltblue",L["ModKeyA"].."+"..L["MouseBtn"]).." || "..C("green",TRAVEL_PASS_INVITE),nil,"LEFT",ttColumns);
end
if (module.clickHints) then
local steps,t1,t2=1,{},{};
if (ttColumns>4) then
steps=2;
end
for i=1, #module.clickHints, steps do
if (ttColumns>4) then
t2 = {};
if (module.clickHints[i]) then tinsert(t2,module.clickHints[i]); end
if (module.clickHints[i+1]) then tinsert(t2,module.clickHints[i+1]); end
tinsert(t1,table.concat(t2," - "));
else
if (module.clickHints[i]) then
tinsert(t1,module.clickHints[i]);
end
end
end
for i,v in ipairs(t1) do
tt:SetCell(tt:AddLine(),1,v,nil,"LEFT",ttColumns);
end
end
end
if not update then
ns.roundupTooltip(tt);
end
end
local function hideScrollElements()
for _,si in ipairs({applScroll,membScroll})do
if si.region and not si.region.hidden then
si.region:ClearAllPoints();
si.region:SetParent(frame);
si.region:Hide();
si.region.hidden = true
end
if si.slider and not si.slider.hidden then
si.slider:ClearAllPoints();
si.slider:SetParent(frame);
si.slider:Hide();
si.slider.hidden = true
end
end
end
local function ttOnShowHook(self)
if tt and tt.key==ttName then return end
hideScrollElements(); -- force hide of scroll elements if tooltip owned by another addon or module
end
local function ttOnHideHook(self)
if tt and tt~=self and tt.key~=ttName then return end
-- LibQTip reuse tooltips and it is a good practice.
-- This should respect foreign addon tooltips ;-) after bypassing LibQTips HookScript blocker.
-- The blocker is good and should stay. A good reminder not to be too careless about using HookScript.
hideScrollElements();
end
-- module functions and variables --
------------------------------------
module = {
events = {
"PLAYER_LOGIN",
"PLAYER_GUILD_UPDATE",
--"GUILD_MOTD",
--"GUILD_RANKS_UPDATE",
"GUILD_ROSTER_UPDATE",
--"CHAT_MSG_SYSTEM",
},
config_defaults = {
enabled = true,
-- guild
showRep = true,
showMOTD = true,
showChallenges = true,
showInfo = true,
-- guild members
showRealmNames = true,
showRace = true, showRaceInTT2 = false,
showZone = true, showZoneInTT2 = false,
showNotes = true, showNotesInTT2 = false,
showONotes = true, showONotesInTT2 = false,
showRank = true, showRankInTT2 = false,
showRankID = false,
showProfessions = true, showProfessionsInTT2 = false,
showBattleTag = true,
showTableBackground = true,
numMembersScroll = 15,
-- misc
showApplicants = true,
showApplicantsBroker = true,
showMobileChatter = true,
showMobileChatterBroker = true,
showTotalMembersBroker = true,
--splitTables = false, -- deprecated
showMembersLevelUp = true,
showMembersNotes = false,
showMembersOffNotes = false
},
clickOptionsRename = {
["guild"] = "1_open_guild",
["menu"] = "2_open_menu"
},
clickOptions = {
["guild"] = "Guild",
["menu"] = "OptionMenu"
}
}
if ns.client_version<5 then
module.config_defaults.showONotes = false
module.config_defaults.showONotesInTT2 = false
module.config_defaults.showProfessions = false
module.config_defaults.showProfessionsInTT2 = false
module.config_defaults.showApplicants = false
module.config_defaults.showApplicantsBroker = false
module.config_defaults.showTableBackground = false;
end
ns.ClickOpts.addDefaults(module,{
guild = "_LEFT",
menu = "_RIGHT"
});
function module.options()
return {
broker = {
showApplicantsBroker = { type="toggle", order=1, name=L["Applicants"], desc=L["Show applicants on broker button"], hidden=ns.IsClassicClient },
showMobileChatterBroker = { type="toggle", order=2, name=L["Mobile app user"], desc=L["Show count of mobile chatter on broker button"] },
showTotalMembersBroker = { type="toggle", order=3, name=L["Total members count"], desc=L["Show total members count on broker button"] },
},
tooltip1 = {
name = L["Main tooltip options"],
order = 2,
showRep = { type="toggle", order= 1, name=GUILD_REPUTATION, desc=L["Enable/Disable the display of Guild Reputation in tooltip"] },
showMOTD = { type="toggle", order= 2, name=L["Guild MotD"], desc=L["Show Guild Message of the Day in tooltip"] },
showInfo = { type="toggle", order= 3, name=GUILD_INFORMATION, desc=L["GuildShowInfoDesc"], hidden=ns.IsClassicClient },
showChallenges = { type="toggle", order= 4, name=GUILD_CHALLENGE_LABEL, desc=L["GuildShowChallengesDesc"], hidden=ns.IsClassicClient },
showRealmNames = 20,
showRace = { type="toggle", order=21, name=RACE, desc=L["Show race from guild members in tooltip"]},
showZone = { type="toggle", order=22, name=ZONE, desc=L["Show current zone from guild members in tooltip"]},
showNotes = { type="toggle", order=23, name=L["Notes"], desc=L["Show notes from guild members in tooltip"]},
showONotes = { type="toggle", order=24, name=OFFICER_NOTE_COLON, desc=L["Show officer notes from guild members in tooltip. (This option will be ignored if you have not permission to read the officer notes)"], hidden=ns.IsClassicClient},
showRank = { type="toggle", order=25, name=RANK, desc=L["Show rank name from guild members in tooltip"]},
showRankID = { type="toggle", order=26, name=RANK.."ID", desc=L["Show rank id from guild members in tooltip"]},
showProfessions = { type="toggle", order=27, name=TRADE_SKILLS, desc=L["Show professions from guild members in tooltip"], hidden=ns.IsClassicClient },
showApplicants = { type="toggle", order=28, name=L["Applicants"], desc=L["Show applicants in tooltip"], hidden=ns.IsClassicClient },
showMobileChatter = { type="toggle", order=29, name=L["Mobile app user"], desc=L["Show mobile chatter in tooltip (Armory App users)"] },
--splitTables = { type="toggle", order=30, name=L["Separate mobile app user"], desc=L["Display mobile chatter with own table in tooltip"] }, -- deprecated
showBattleTag = { type="toggle", order=31, name=BATTLETAG, desc=L["Append the BattleTag of your friends to the character name"], hidden=ns.IsClassicClient },
showTableBackground={ type="toggle", order=32, name=L["GuildTableBg"], desc=L["GuildTableBgDesc"], hidden=ns.IsClassicClient },
numMembersScroll = { type="range", order=33, name=L["NumMembersScroll"], desc=L["NumMembersScrollDesc"], min=15, max=80, step=1},
},
tooltip2 = {
name = L["Secondary tooltip options"],
order = 3,
desc = { type="description", order=1, name=L["The secondary tooltip will be displayed by moving the mouse over a guild member in main tooltip. The tooltip will be displayed if one of the following options activated."], fontSize="medium"},
showRaceInTT2 = { type="toggle", order=2, name=RACE, desc=L["Show race from guild member"]},
showZoneInTT2 = { type="toggle", order=2, name=ZONE, desc=L["Show current zone from guild member"]},
showNotesInTT2 = { type="toggle", order=3, name=L["Notes"], desc=L["Show notes from guild member"]},
showONotesInTT2 = { type="toggle", order=4, name=OFFICER_NOTE_COLON, desc=L["Show officer notes from guild member"], hidden=ns.IsClassicClient},
showRankInTT2 = { type="toggle", order=5, name=RANK, desc=L["Show rank from guild member"]},
showProfessionsInTT2 = { type="toggle", order=6, name=TRADE_SKILLS, desc=L["Show professions from guild member"], hidden=ns.IsClassicClient}
},
misc = {
order = 4,
showMembersLevelUp = { type="toggle", order=1, name=L["Show level up notification"], desc=L["Show guild member level up notification in chat frame. (This is not a gratulation bot!)"]},
showMembersNotes = { type="toggle", order=2, name=L["Show notes in login"], desc=L["Display member notes in chat window after his/her login message"] },
showMembersOffNotes = { type="toggle", order=3, name=L["Show off. notes on login"], desc=L["Display member officer notes in chat window after his/her login message"] },
},
},
{
showProfessions=true
}
end
-- function module.init() end
function module.onevent(self,event,msg,...)
if event=="BE_UPDATE_CFG" and msg and msg:find("^ClickOpt") then
ns.ClickOpts.update(name);
elseif event=="BE_UPDATE_CFG" and msg=="showTableBackground" then
local hide = nil;
if not ns.profile[name].showTableBackground then
hide = {0,0,0,0};
end
if applScroll.region then
applScroll.region:SetBackdropColor(unpack(hide or applScroll.regionColor));
end
if membScroll.region then
membScroll.region:SetBackdropColor(unpack(hide or membScroll.regionColor));
end
elseif event=="PLAYER_LOGIN" or (ns.eventPlayerEnteredWorld and not self.IsLoaded) then
self.IsLoaded = true;
frame = self;
if C_GuildInfo and C_GuildInfo.GuildRoster then
if ns.client_version>=7 then
self:RegisterEvent("GUILD_TRADESKILL_UPDATE");
end
if C_ClubFinder and C_ClubFinder.RequestApplicantList then
--self:RegisterEvent("CLUB_FINDER_RECRUITS_UPDATED");
self:RegisterEvent("CLUB_FINDER_RECRUIT_LIST_CHANGED");
if CanUpdateApplicants() then
C_ClubFinder.RequestSubscribedClubPostingIDs(); -- init clubfinder recuits list
C_ClubFinder.RequestApplicantList(Enum.ClubFinderRequestType.Guild); -- trigger CLUB_FINDER_RECRUITS_UPDATED
end
end
end
RequestGuildRosterUpdate();
elseif event=="GUILD_TRADESKILL_UPDATE" and not triggerLockTradeSkill then
-- will be triggered 30 times and more in one second
triggerLockTradeSkill = true
C_Timer.After(0.15,function() updateTradeSkills(); triggerLockTradeSkill=false end)
elseif event=="CHAT_MSG_SYSTEM" and (ns.profile[name].showMembersNotes or ns.profile[name].showMembersOffNotes) then
-- update online status; GUILD_ROSTER_UPDATE/GetGuildRosterInfo trigger too slow real updates
local state,member = "online",msg:gsub("[\124:%[%]]","#"):match(pattern_FRIEND_ONLINE);
if not member then
state,member = "offline",msg:match(pattern_FRIEND_OFFLINE);
end
if member and not member:find("-") then
member = member.."-"..ns.realm_short;
end
if member and memberIndex[member] then
-- On/Off post notes of guild members in general chat.
local mFullName,_,_,_,_,_,mNote,mOfficerNote,mOnline,_,mClassFile,_,_,mIsMobile = GetGuildRosterInfo(memberIndex[member]);
local mName = strsplit("-",mFullName,2);
local txt={};
if ns.profile[name].showMembersNotes then
local str = strtrim(mNote);
if str:len()>0 then
tinsert(txt,C("ltgray",NOTE_COLON).." "..C("ltblue",str));
end
end
if ns.profile[name].showMembersOffNotes then
local str = strtrim(mOfficerNote);
if str:len()>0 then
tinsert(txt,C("ltgray",GUILD_OFFICERNOTES_LABEL).." "..C("ltblue",str));
end
end
if #txt>0 then
local mobileIcon = "";
if mIsMobile then
mobileIcon = ChatFrame_GetMobileEmbeddedTexture(73/255, 177/255, 73/255)
end
tinsert(txt,1,C("ltgray",LFG_LIST_GUILD_MEMBER)..CHAT_HEADER_SUFFIX..C(mClassFile,mName).." "..mobileIcon);
C_Timer.After(0.1,function()
-- should prevent display this line before blizzards message
ns:print(true,table.concat(txt," || "));
end);
end
end
else -- on events -- BE_DUMMY_EVENT / PLAYER_GUILD_UPDATE / GUILD_ROSTER_UPDATE / CLUB_FINDER_RECRUIT_LIST_CHANGED
if event=="BE_DUMMY_EVENT" or chatNotificationEnabled==nil then
-- toggle events
local doChatNotification = (ns.profile[name].showMembersNotes or ns.profile[name].showMembersOffNotes);
if chatNotificationEnabled~=doChatNotification then
chatNotificationEnabled=doChatNotification;
if doChatNotification then
self:RegisterEvent("CHAT_MSG_SYSTEM");
else
self:UnregisterEvent("CHAT_MSG_SYSTEM");
end
end
end
if event=="GUILD_ROSTER_UPDATE" and msg==true then
RequestGuildRosterUpdate();
return;
end
updateBroker();
end
end
function module.onenter(self)
if (ns.tooltipChkOnShowModifier(false)) then return; end
local ttAlignings = {"LEFT"};
ttColumns = 1;
local inGuild = IsInGuild();
if inGuild then
ttAlignings = {
"RIGHT", -- level
"LEFT" -- name
};
wipe(flags);
if ns.profile[name].showRace then
tinsert(ttAlignings,"LEFT"); -- race
flags.showRace=true;
end
if ns.profile[name].showZone then
tinsert(ttAlignings,"CENTER"); -- zone
flags.showZone=true;
end
if ns.profile[name].showNotes then
tinsert(ttAlignings,"LEFT"); -- notes
flags.showNotes=true;
end
if ns.profile[name].showONotes and CanViewOfficerNote() then -- extend if
tinsert(ttAlignings,"LEFT"); -- onotes
flags.showONotes=true;
end
if ns.profile[name].showRank then
tinsert(ttAlignings,"LEFT"); -- rank
flags.showRank=true;
end
if ns.profile[name].showProfessions then
tinsert(ttAlignings,"CENTER"); -- professions 1
tinsert(ttAlignings,"CENTER"); -- professions 2
flags.showProfessions=true;
end
tinsert(ttAlignings,"RIGHT"); -- arrow right
ttColumns = #ttAlignings;
if ns.profile[name].showApplicants then
ttColumns = max(ttColumns,5); -- min 5 cols for applicants
end
end
tt = ns.acquireTooltip({ttName, ttColumns,unpack(ttAlignings)},{false},{self});
createTooltip(tt);
if inGuild then
if not ttHooks[tt] then
ttHooks[tt] = true;
self.HookScript(tt,"OnHide",ttOnHideHook);
self.HookScript(tt,"OnShow",ttOnShowHook);
end
end
end
-- function module.onleave(self) end
-- function module.onclick(self,button) end
-- function module.ondblclick(self,button) end
-- final module registration --
-------------------------------
ns.modules[name] = module;