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.
1758 lines
56 KiB
1758 lines
56 KiB
-- local functions
|
|
local UnitName = UnitName;
|
|
local UnitIsDead = UnitIsDead;
|
|
local pairs = pairs;
|
|
local type = type;
|
|
local wipe = wipe;
|
|
local tonumber = tonumber;
|
|
local table_insert = table.insert;
|
|
local string_format = string.format;
|
|
local string_sub = string.sub;
|
|
local string_gsub = string.gsub;
|
|
local string_find = string.find;
|
|
local string_match = string.match;
|
|
local string_trim = strtrim;
|
|
local string_len = strlenutf8;
|
|
|
|
-- local variables
|
|
local _;
|
|
|
|
-- mainline or classic
|
|
local wowmainline = (WOW_PROJECT_ID == WOW_PROJECT_MAINLINE);
|
|
local wowclassic = (WOW_PROJECT_ID == WOW_PROJECT_CLASSIC);
|
|
local wowbcc = (WOW_PROJECT_ID == WOW_PROJECT_BURNING_CRUSADE_CLASSIC);
|
|
local wowwc = (WOW_PROJECT_ID == WOW_PROJECT_WRATH_CLASSIC);
|
|
local wowcc = (WOW_PROJECT_ID == WOW_PROJECT_CATACLYSM_CLASSIC);
|
|
|
|
-- libraries
|
|
Gnosis = LibStub("AceAddon-3.0"):NewAddon("Gnosis", "AceConsole-3.0", "AceEvent-3.0");
|
|
Gnosis.gui = LibStub("AceGUI-3.0");
|
|
Gnosis.comm = LibStub("AceComm-3.0");
|
|
Gnosis.lsm = LibStub("LibSharedMedia-3.0", 1);
|
|
Gnosis.smw = LibStub("AceGUISharedMediaWidgets-1.0");
|
|
Gnosis.range = LibStub("LibRangeCheck-2.0");
|
|
Gnosis.dialog = LibStub("LibDialog-1.0");
|
|
Gnosis.libs = LibStub("AceSerializer-3.0");
|
|
Gnosis.libc = LibStub("LibCompress");
|
|
|
|
-- classic only libraries
|
|
if (wowclassic) then
|
|
Gnosis.libclcno = LibStub("LibClassicCasterino");
|
|
Gnosis.libcldur = LibStub("LibClassicDurations");
|
|
Gnosis.libcldur:Register("Gnosis");
|
|
end
|
|
|
|
-- classic: use LibClassicCasterino casting functions
|
|
local UnitCastingInfo = UnitCastingInfo;
|
|
local UnitChannelInfo = UnitChannelInfo;
|
|
|
|
if (wowclassic and Gnosis.libclcno) then
|
|
UnitCastingInfo = function(unit)
|
|
return Gnosis.libclcno:UnitCastingInfo(unit);
|
|
end
|
|
|
|
UnitChannelInfo = function(unit)
|
|
return Gnosis.libclcno:UnitChannelInfo(unit);
|
|
end
|
|
end
|
|
|
|
if (wowbcc) then
|
|
UnitCastingInfo = function(unit)
|
|
local name, text, texture, startTimeMS, endTimeMS, isTradeSkill, castID, spellId = UnitCastingInfo(unit)
|
|
return name, text, texture, startTimeMS, endTimeMS, isTradeSkill, castID, nil, spellId
|
|
end
|
|
end
|
|
|
|
-- LibSharedMedia
|
|
if(Gnosis.lsm) then
|
|
-- statusbar textures
|
|
Gnosis.lsm:Register("statusbar", "Waterline", "Interface\\Addons\\Gnosis\\Textures\\Waterline");
|
|
Gnosis.lsm:Register("statusbar", "Gnosis_Plain", "Interface\\Addons\\Gnosis\\Textures\\Gnosis_Plain");
|
|
Gnosis.lsm:Register("statusbar", "Gnosis_Gradient", "Interface\\Addons\\Gnosis\\Textures\\Gnosis_Gradient");
|
|
|
|
-- fonts
|
|
Gnosis.lsm:Register("font", "Desyrel", "Interface\\Addons\\Gnosis\\Fonts\\DESYREL_.ttf");
|
|
Gnosis.lsm:Register("font", "Accidental Presidency", "Interface\\Addons\\Gnosis\\Fonts\\Accidental Presidency\\accid___.ttf");
|
|
|
|
-- sound files
|
|
Gnosis.lsm:Register("sound", "Gnosis_Coin", "Interface\\Addons\\Gnosis\\Sounds\\coin_dropped_on_wooden_floor.ogg");
|
|
Gnosis.lsm:Register("sound", "Gnosis_CompStart", "Interface\\Addons\\Gnosis\\Sounds\\Computer_Start-Up-Your_Mom-1280862923.ogg");
|
|
Gnosis.lsm:Register("sound", "Gnosis_Cuckoo", "Interface\\Addons\\Gnosis\\Sounds\\Cuckoo Clock-SoundBible.com-1776874523.ogg");
|
|
Gnosis.lsm:Register("sound", "Gnosis_Electric", "Interface\\Addons\\Gnosis\\Sounds\\Electrical_Sweep-Sweeper-1760111493.ogg");
|
|
Gnosis.lsm:Register("sound", "Gnosis_MusicBox", "Interface\\Addons\\Gnosis\\Sounds\\Music_Box-Big_Daddy-1389738694.ogg");
|
|
Gnosis.lsm:Register("sound", "Gnosis_Wharf", "Interface\\Addons\\Gnosis\\Sounds\\announcementonawharf.ogg");
|
|
end
|
|
|
|
-- generate configuration frames
|
|
function Gnosis:InitialConfig()
|
|
self.optCBsName = "Gnosis Castbars";
|
|
self.optCfgsName = "Gnosis Configurations";
|
|
|
|
self.optFrame = LibStub("AceConfigDialog-3.0"):AddToBlizOptions("Gnosis", self.L["AddonName"]);
|
|
self.optCBs = LibStub("AceConfigDialog-3.0"):AddToBlizOptions(self.optCBsName, Gnosis.L["TabCastbars"], "Gnosis");
|
|
LibStub("AceConfigDialog-3.0"):AddToBlizOptions("Gnosis Channeled Spells", Gnosis.L["TabChanneledSpells"], "Gnosis");
|
|
LibStub("AceConfigDialog-3.0"):AddToBlizOptions("Gnosis Combattext/Clip test", Gnosis.L["TabCTClipTest"], "Gnosis");
|
|
self.optCfgs = LibStub("AceConfigDialog-3.0"):AddToBlizOptions(self.optCfgsName, Gnosis.L["TabConfig"], "Gnosis");
|
|
end
|
|
|
|
function Gnosis:En(status)
|
|
if (status) then
|
|
-- enable addon
|
|
self.bGnosisEnabled = true;
|
|
|
|
if (self.bOptionsCreated) then
|
|
LibStub("AceConfig-3.0"):RegisterOptionsTable("Gnosis", self.opt);
|
|
LibStub("AceConfigRegistry-3.0"):RegisterOptionsTable("Gnosis Castbars", self.opt_cbs);
|
|
LibStub("AceConfigRegistry-3.0"):RegisterOptionsTable("Gnosis Channeled Spells", self.opt_css);
|
|
LibStub("AceConfigRegistry-3.0"):RegisterOptionsTable("Gnosis Combattext/Clip test", self.opt_ctclip);
|
|
LibStub("AceConfigRegistry-3.0"):RegisterOptionsTable("Gnosis Configurations", self.opt_configs);
|
|
else
|
|
LibStub("AceConfig-3.0"):RegisterOptionsTable("Gnosis", self.optunloaded_main);
|
|
LibStub("AceConfigRegistry-3.0"):RegisterOptionsTable("Gnosis Castbars", self.optunloaded);
|
|
LibStub("AceConfigRegistry-3.0"):RegisterOptionsTable("Gnosis Channeled Spells", self.optunloaded);
|
|
LibStub("AceConfigRegistry-3.0"):RegisterOptionsTable("Gnosis Combattext/Clip test", self.optunloaded);
|
|
LibStub("AceConfigRegistry-3.0"):RegisterOptionsTable("Gnosis Configurations", self.optunloaded);
|
|
end
|
|
|
|
self:RegisterEvents();
|
|
self:DefaultAllBars();
|
|
|
|
-- blizzard castbar
|
|
if (self.s.bHideBlizz) then
|
|
self:HideBlizzardCastbar(true);
|
|
end
|
|
-- mirror castbar
|
|
if (self.s.bHideMirror) then
|
|
self:HideBlizzardMirrorCastbar(true);
|
|
end
|
|
-- pet/vehicle castbar
|
|
if (self.s.bHidePetVeh) then
|
|
self:HideBlizzardPetCastbar(true);
|
|
end
|
|
-- unregister global mouse events
|
|
if (self.s.bUnregGlobalMouse) then
|
|
self:UnregisterGlobalMouseEvents();
|
|
end
|
|
|
|
-- scan table, fast lookup tablese
|
|
self:CreateCBTables();
|
|
-- trigger talent update event (gone with 5.04 sent too early)
|
|
self:PLAYER_TALENT_UPDATE();
|
|
|
|
-- resize interface options frame
|
|
if (self.s.bResizeOptions and (wowwc or wowcc)) then
|
|
InterfaceOptionsFrame:SetWidth(835);
|
|
end
|
|
else
|
|
-- disable addon
|
|
self.bGnosisEnabled = false;
|
|
|
|
if (self.bOptionsCreated) then
|
|
LibStub("AceConfig-3.0"):RegisterOptionsTable("Gnosis", self.optdisabled);
|
|
LibStub("AceConfigRegistry-3.0"):RegisterOptionsTable("Gnosis Castbars", self.optempty);
|
|
LibStub("AceConfigRegistry-3.0"):RegisterOptionsTable("Gnosis Channeled Spells", self.optempty);
|
|
LibStub("AceConfigRegistry-3.0"):RegisterOptionsTable("Gnosis Combattext/Clip test", self.optempty);
|
|
LibStub("AceConfigRegistry-3.0"):RegisterOptionsTable("Gnosis Configurations", self.optempty);
|
|
else
|
|
LibStub("AceConfig-3.0"):RegisterOptionsTable("Gnosis", self.optunloaded_main);
|
|
LibStub("AceConfigRegistry-3.0"):RegisterOptionsTable("Gnosis Castbars", self.optunloaded);
|
|
LibStub("AceConfigRegistry-3.0"):RegisterOptionsTable("Gnosis Channeled Spells", self.optunloaded);
|
|
LibStub("AceConfigRegistry-3.0"):RegisterOptionsTable("Gnosis Combattext/Clip test", self.optunloaded);
|
|
LibStub("AceConfigRegistry-3.0"):RegisterOptionsTable("Gnosis Configurations", self.optunloaded);
|
|
end
|
|
|
|
self:UnregisterEvents();
|
|
self:HideAllBars();
|
|
|
|
-- blizzard castbar
|
|
if (self.s.bHideBlizz) then
|
|
self:HideBlizzardCastbar(false);
|
|
end
|
|
-- mirror castbar
|
|
if (self.s.bHideMirror) then
|
|
self:HideBlizzardMirrorCastbar(false);
|
|
end
|
|
-- pet/vehicle castbar
|
|
if (self.s.bHidePetVeh) then
|
|
self:HideBlizzardPetCastbar(false);
|
|
end
|
|
|
|
-- scan table, fast lookup castbar and timer tables
|
|
self:ClearCBTables();
|
|
end
|
|
end
|
|
|
|
function Gnosis:OpenOptions()
|
|
if (not self.iofcalled) then
|
|
-- call twice the first time
|
|
if (wowmainline) or (wowwc) or (wowcc) then
|
|
Settings.OpenToCategory(Gnosis.optFrame.name);
|
|
else
|
|
InterfaceOptionsFrame_OpenToCategory(Gnosis.optFrame);
|
|
end
|
|
end
|
|
|
|
if (wowmainline) or (wowwc) or (wowcc) then
|
|
Settings.OpenToCategory(Gnosis.optFrame.name);
|
|
else
|
|
InterfaceOptionsFrame_OpenToCategory(Gnosis.optFrame);
|
|
end
|
|
self.iofcalled = true;
|
|
end
|
|
|
|
function Gnosis:OpenCfgOptions()
|
|
if (not self.iofcfgcalled) then
|
|
-- call twice the first time
|
|
if (wowmainline) then
|
|
Settings.OpenToCategory(Gnosis.optCfgs);
|
|
elseif (wowwc or wowcc) then
|
|
LibStub("AceConfigRegistry-3.0"):NotifyChange(Gnosis.optCfgsName);
|
|
else
|
|
InterfaceOptionsFrame_OpenToCategory(Gnosis.optCfgs);
|
|
end
|
|
end
|
|
|
|
if (wowmainline) then
|
|
Settings.OpenToCategory(Gnosis.optCfgs);
|
|
elseif (wowwc or wowcc) then
|
|
LibStub("AceConfigRegistry-3.0"):NotifyChange(Gnosis.optCfgsName);
|
|
else
|
|
InterfaceOptionsFrame_OpenToCategory(Gnosis.optCfgs);
|
|
end
|
|
self.iofcfgcalled = true;
|
|
end
|
|
|
|
function Gnosis:OpenCastbarOptions()
|
|
if (not self.iofcbcalled) then
|
|
-- call twice the first time
|
|
if (wowmainline) then
|
|
Settings.OpenToCategory(Gnosis.optCBs);
|
|
elseif (wowwc or wowcc) then
|
|
LibStub("AceConfigRegistry-3.0"):NotifyChange(Gnosis.optCBsName);
|
|
else
|
|
InterfaceOptionsFrame_OpenToCategory(Gnosis.optCBs);
|
|
end
|
|
end
|
|
|
|
if (wowmainline) then
|
|
Settings.OpenToCategory(Gnosis.optCBs);
|
|
elseif (wowwc or wowcc) then
|
|
LibStub("AceConfigRegistry-3.0"):NotifyChange(Gnosis.optCBsName);
|
|
else
|
|
InterfaceOptionsFrame_OpenToCategory(Gnosis.optCBs);
|
|
end
|
|
self.iofcbcalled = true;
|
|
end
|
|
|
|
function Gnosis:HideBlizzardCastbarIfStatusChange(status)
|
|
if (self.s.bHideBlizz ~= status) then
|
|
self.s.bHideBlizz = status;
|
|
self:HideBlizzardCastbar(self.s.bHideBlizz);
|
|
end
|
|
end
|
|
|
|
function Gnosis:HideBlizzardCastbar(status)
|
|
if (status) then -- hide castbar
|
|
for key, value in pairs(self.tBlizzCastbar) do
|
|
if(wowmainline and PlayerCastingBarFrame:IsEventRegistered(value)) then
|
|
table_insert(self.blizzcastbar, value);
|
|
PlayerCastingBarFrame:UnregisterEvent(value);
|
|
elseif(not wowmainline and CastingBarFrame:IsEventRegistered(value)) then
|
|
table_insert(self.blizzcastbar, value);
|
|
CastingBarFrame:UnregisterEvent(value);
|
|
end
|
|
end
|
|
|
|
if (#self.blizzcastbar > 0) then
|
|
if(not self.s.bHideAddonMsgs) then
|
|
self:Print(Gnosis.L["MsgDisBlizCB"]);
|
|
end
|
|
else
|
|
if(not self.s.bHideAddonMsgs) then
|
|
self:Print(Gnosis.L["MsgBlizCBIsDis"]);
|
|
end
|
|
end
|
|
else -- restore castbar events, it might not actually enable the blizzard castbar if another addon hides it
|
|
for key, value in pairs(self.blizzcastbar) do
|
|
if (wowmainline) then
|
|
PlayerCastingBarFrame:RegisterEvent(value);
|
|
else
|
|
CastingBarFrame:RegisterEvent(value);
|
|
end
|
|
end
|
|
|
|
if (#self.blizzcastbar > 0) then
|
|
if(not self.s.bHideAddonMsgs) then
|
|
self:Print(Gnosis.L["MsgBlizCBRestored"]);
|
|
end
|
|
end
|
|
self.blizzcastbar = {};
|
|
end
|
|
end
|
|
|
|
function Gnosis:HideBlizzardPetCastbarIfStatusChange(status)
|
|
if (status == nil) then
|
|
status = false;
|
|
end
|
|
|
|
if (self.s.bHidePetVeh ~= status) then
|
|
self.s.bHidePetVeh = status;
|
|
self:HideBlizzardPetCastbar(self.s.bHidePetVeh);
|
|
end
|
|
end
|
|
|
|
function Gnosis:HideBlizzardMirrorCastbarIfStatusChange(status)
|
|
if (self.s.bHideMirror ~= status) then
|
|
self.s.bHideMirror = status;
|
|
self:HideBlizzardMirrorCastbar(self.s.bHideMirror);
|
|
end
|
|
end
|
|
|
|
function Gnosis:HideBlizzardPetCastbar(status)
|
|
if (status) then -- hide pet castbar
|
|
for key, value in pairs(self.tBlizzCastbar) do
|
|
if(PetCastingBarFrame:IsEventRegistered(value)) then
|
|
table_insert(self.petcastbar, value);
|
|
PetCastingBarFrame:UnregisterEvent(value);
|
|
end
|
|
end
|
|
|
|
if (#self.petcastbar > 0) then
|
|
if(not self.s.bHideAddonMsgs) then
|
|
self:Print(Gnosis.L["MsgDisPetCB"]);
|
|
end
|
|
else
|
|
if(not self.s.bHideAddonMsgs) then
|
|
self:Print(Gnosis.L["MsgPetCBIsDis"]);
|
|
end
|
|
end
|
|
else -- restore pet castbar events, it might not actually enable the blizzard castbar if another addon hides it
|
|
for key, value in pairs(self.petcastbar) do
|
|
PetCastingBarFrame:RegisterEvent(value);
|
|
end
|
|
|
|
if (#self.petcastbar > 0) then
|
|
if(not self.s.bHideAddonMsgs) then
|
|
self:Print(Gnosis.L["MsgPetCBRestored"]);
|
|
end
|
|
end
|
|
|
|
self.petcastbar = {};
|
|
end
|
|
end
|
|
|
|
function Gnosis:HideBlizzardMirrorCastbar(status)
|
|
if (wowmainline and status) then
|
|
MirrorTimerContainer:Hide()
|
|
elseif (wowmainline) then
|
|
MirrorTimerContainer:Show()
|
|
elseif (status) then -- hide castbar
|
|
for key, value in pairs(self.tBlizzMirrorUiParent) do
|
|
if(UIParent:IsEventRegistered(value)) then
|
|
table_insert(self.blizzmirroruiparent, value);
|
|
UIParent:UnregisterEvent(value);
|
|
end
|
|
end
|
|
|
|
for key, value in pairs(self.tBlizzMirror123) do
|
|
if(MirrorTimer1:IsEventRegistered(value)) then
|
|
table_insert(self.blizzmirror1, value);
|
|
MirrorTimer1:UnregisterEvent(value);
|
|
end
|
|
if(MirrorTimer2:IsEventRegistered(value)) then
|
|
table_insert(self.blizzmirror2, value);
|
|
MirrorTimer2:UnregisterEvent(value);
|
|
end
|
|
if(MirrorTimer3:IsEventRegistered(value)) then
|
|
table_insert(self.blizzmirror3, value);
|
|
MirrorTimer3:UnregisterEvent(value);
|
|
end
|
|
end
|
|
|
|
MirrorTimer1:Hide();
|
|
MirrorTimer2:Hide();
|
|
MirrorTimer3:Hide();
|
|
|
|
if (#self.blizzmirroruiparent > 0) then
|
|
if(not self.s.bHideAddonMsgs) then
|
|
self:Print(Gnosis.L["MsgDisMirrCB"]);
|
|
end
|
|
else
|
|
if(not self.s.bHideAddonMsgs) then
|
|
self:Print(Gnosis.L["MsgMirrCBIsDis"]);
|
|
end
|
|
end
|
|
else -- restore mirror castbar events, it might not actually enable the blizzard mirror castbar if another addon hides it
|
|
for key, value in pairs(self.blizzmirroruiparent) do
|
|
UIParent:RegisterEvent(value);
|
|
end
|
|
for key, value in pairs(self.blizzmirror1) do
|
|
MirrorTimer1:RegisterEvent(value);
|
|
end
|
|
for key, value in pairs(self.blizzmirror2) do
|
|
MirrorTimer2:RegisterEvent(value);
|
|
end
|
|
for key, value in pairs(self.blizzmirror3) do
|
|
MirrorTimer3:RegisterEvent(value);
|
|
end
|
|
|
|
if (#self.blizzmirroruiparent > 0) then
|
|
if(not self.s.bHideAddonMsgs) then
|
|
self:Print(Gnosis.L["MsgMirrCBRestored"]);
|
|
end
|
|
end
|
|
|
|
self.blizzmirroruiparent = {};
|
|
self.blizzmirror1 = {};
|
|
self.blizzmirror2 = {};
|
|
self.blizzmirror3 = {};
|
|
end
|
|
end
|
|
|
|
function Gnosis:OnInitialize()
|
|
local unitkey = UnitName("player") .. " - " .. GetRealmName();
|
|
if (GnosisDB and GnosisDB.profiles and GnosisDB.profiles[unitkey] and
|
|
GnosisDB.profileKeys and GnosisDB.profileKeys[unitkey]) then
|
|
-- copy to new char only based profile (to heavily cut down on mem usage)
|
|
if (not GnosisChar) then GnosisChar = {}; end
|
|
if (not GnosisChar.profileKeys) then GnosisChar.profileKeys = {}; end
|
|
if (not GnosisChar.profiles) then GnosisChar.profiles = {}; end
|
|
GnosisChar.profileKeys[unitkey] = unitkey;
|
|
GnosisChar.profiles[unitkey] = self:deepcopy(GnosisDB.profiles[unitkey]);
|
|
GnosisDB.profileKeys[unitkey] = nil;
|
|
GnosisDB.profiles[unitkey] = nil;
|
|
|
|
-- fully remove from db if empty
|
|
if (self:tsize(GnosisDB.profiles) == 0) then
|
|
GnosisDB.profiles = nil;
|
|
end
|
|
if (self:tsize(GnosisDB.profileKeys) == 0) then
|
|
GnosisDB.profileKeys = nil;
|
|
end
|
|
end
|
|
|
|
-- remove character specific profile name in character specific configuration file
|
|
if (not GnosisCharConfig) then
|
|
GnosisCharConfig = {};
|
|
|
|
self.db = LibStub("AceDB-3.0"):New("GnosisChar", defaults);
|
|
if (self.db and self.db.profile and self:tsize(self.db.profile) > 0) then
|
|
-- copy AceDB profile to GnosisCharConfig
|
|
GnosisCharConfig = self:deepcopy(self.db.profile);
|
|
end
|
|
elseif (self:tsize(GnosisCharConfig) == 0) then
|
|
self.db = LibStub("AceDB-3.0"):New("GnosisChar", defaults);
|
|
if(self.db and self.db.profile and self:tsize(self.db.profile) > 0) then
|
|
-- copy AceDB profile to GnosisCharConfig
|
|
GnosisCharConfig = self:deepcopy(self.db.profile);
|
|
end
|
|
elseif (self:tsize(GnosisCharConfig) > 0 and GnosisChar) then
|
|
-- empty GnosisChar table (removing AceDB character specific profile)
|
|
wipe(GnosisChar);
|
|
GnosisChar = nil;
|
|
end
|
|
|
|
-- set link to GnosisCharConfig
|
|
self.s = GnosisCharConfig;
|
|
|
|
self:RegisterChatCommand("gnosis", "HandleChatCommand");
|
|
|
|
-- GameTooltip for scanning
|
|
self.tooltip = CreateFrame("GameTooltip", "GnosisGameTooltip", nil, "GameTooltipTemplate");
|
|
self.tooltip:SetOwner(WorldFrame, "ANCHOR_NONE");
|
|
end
|
|
|
|
function Gnosis:SetupHooks()
|
|
if (wowmainline) then
|
|
-- tradeskill hooking
|
|
|
|
if not (ProfessionsFrame) then
|
|
ProfessionsFrame_LoadUI()
|
|
end
|
|
hooksecurefunc(ProfessionsFrame.CraftingPage, "CreateInternal", function(_, recipeID, count, recipeLevel)
|
|
Gnosis.bNewTradeSkill = tonumber(count) and true or nil;
|
|
Gnosis.iLastTradeSkillCnt = tonumber(count);
|
|
end)
|
|
|
|
hooksecurefunc(C_TradeSkillUI, 'CloseTradeSkill', function()
|
|
Gnosis.bNewTradeSkill = nil;
|
|
Gnosis.iLastTradeSkillCnt = nil;
|
|
Gnosis:CloseAllTradeskillBars();
|
|
end)
|
|
|
|
elseif (wowclassic) or (wowbcc) or (wowwc) or (wowcc) then
|
|
-- tradeskill hooking
|
|
hooksecurefunc('DoTradeSkill', function(index, num)
|
|
Gnosis.bNewTradeSkill = tonumber(num) and true or nil;
|
|
Gnosis.iLastTradeSkillCnt = tonumber(num);
|
|
end
|
|
);
|
|
|
|
hooksecurefunc('CloseTradeSkill', function()
|
|
Gnosis.bNewTradeSkill = nil;
|
|
Gnosis.iLastTradeSkillCnt = nil;
|
|
Gnosis:CloseAllTradeskillBars();
|
|
end
|
|
);
|
|
end
|
|
|
|
-- SetCVar hook
|
|
hooksecurefunc('SetCVar', function(cv, val)
|
|
if(cv == "uiscale") then
|
|
Gnosis:UIScaleUpdate(); -- called when changing ui scale in the blizzard menu
|
|
end
|
|
end
|
|
);
|
|
|
|
-- SetItemRef hook
|
|
hooksecurefunc('SetItemRef', function(link, text, ...)
|
|
Gnosis:SetItemRef(link, text);
|
|
end
|
|
);
|
|
|
|
--[[
|
|
hooksecurefunc("ChatFrame_OnHyperlinkShow", function(frame, link, text, ...)
|
|
Gnosis:SetItemRef(link, text);
|
|
end
|
|
);
|
|
]]
|
|
end
|
|
|
|
function Gnosis:OnEnable()
|
|
-- set init values
|
|
self:StartupVariables();
|
|
|
|
-- setup hooks
|
|
self:SetupHooks();
|
|
|
|
-- load localization
|
|
if (not self.s.strLocale and self.LSet[GetLocale()]) then
|
|
self.s.strLocale = GetLocale();
|
|
elseif (not self.s.strLocale) then
|
|
self.s.strLocale = "default";
|
|
end
|
|
self:SetupLocale();
|
|
|
|
-- basic tables
|
|
self:OptCreateBasicTables();
|
|
|
|
-- set default saved variables
|
|
if (self.s.bAddonEn == nil) then
|
|
self.s.optver = self.optver;
|
|
end
|
|
for key, value in pairs(self.tDefaults) do
|
|
if (self.s[key] == nil) then
|
|
self.s[key] = value;
|
|
end
|
|
end
|
|
for key, value in pairs(self.tDefaults.ct) do
|
|
if (self.s.ct[key] == nil) then
|
|
self.s.ct[key] = value;
|
|
end
|
|
end
|
|
for key, value in pairs(self.tDefaults.configs) do
|
|
if (self.s.configs[key] == nil) then
|
|
self.s.configs[key] = value;
|
|
end
|
|
end
|
|
|
|
|
|
if (not self.s.bHideAddonMsgs) then
|
|
self:Print(self.title .. " " .. Gnosis.L["MsgLoaded"] .. " " .. (self.s.bAddonEn and Gnosis.L["MsgEn"] or Gnosis.L["MsgDis"]));
|
|
end
|
|
|
|
-- check castbar options
|
|
self:CheckStoredCastbarOptions();
|
|
|
|
-- upgrade character specific options version number?
|
|
if (self.s.optver < self.optver) then
|
|
self.s.optver = self.optver;
|
|
end
|
|
|
|
-- first start?
|
|
local bFirstStart = self:CheckForFirstStart();
|
|
|
|
-- create saved castbars
|
|
self:InitialCreateCastbars();
|
|
|
|
-- add channeled spells to table
|
|
self:SetupChanneledSpellsTable();
|
|
|
|
-- create castbar options table
|
|
if (self.s.bAutoCreateOptions or bFirstStart) then
|
|
self.bOptionsCreated = true;
|
|
|
|
self:CreateCastbarsOpt();
|
|
self:CreateChannelSpellsOpt();
|
|
self:OptCreateCTpage();
|
|
self:OptCreateConfigurations();
|
|
else
|
|
self.bOptionsCreated = false;
|
|
end
|
|
|
|
-- enable/disable addon
|
|
self:InitialConfig();
|
|
self:En(self.s.bAddonEn);
|
|
|
|
-- get player GUID
|
|
self.guid = UnitGUID("player");
|
|
|
|
-- enable AceComm-3.0 addon communication channel
|
|
self.comm:RegisterComm("GnosisComm", Gnosis.CommCb);
|
|
end
|
|
|
|
function Gnosis:CreateOptions()
|
|
if (not self.bOptionsCreated) then
|
|
self.bOptionsCreated = true;
|
|
self:CreateCastbarsOpt();
|
|
self:CreateChannelSpellsOpt();
|
|
self:OptCreateCTpage();
|
|
self:OptCreateConfigurations();
|
|
end
|
|
|
|
if (self.bGnosisEnabled) then
|
|
LibStub("AceConfig-3.0"):RegisterOptionsTable("Gnosis", self.opt);
|
|
LibStub("AceConfigRegistry-3.0"):RegisterOptionsTable("Gnosis Castbars", self.opt_cbs);
|
|
LibStub("AceConfigRegistry-3.0"):RegisterOptionsTable("Gnosis Channeled Spells", self.opt_css);
|
|
LibStub("AceConfigRegistry-3.0"):RegisterOptionsTable("Gnosis Combattext/Clip test", self.opt_ctclip);
|
|
LibStub("AceConfigRegistry-3.0"):RegisterOptionsTable("Gnosis Configurations", self.opt_configs);
|
|
else
|
|
LibStub("AceConfig-3.0"):RegisterOptionsTable("Gnosis", self.optdisabled);
|
|
LibStub("AceConfigRegistry-3.0"):RegisterOptionsTable("Gnosis Castbars", self.optempty);
|
|
LibStub("AceConfigRegistry-3.0"):RegisterOptionsTable("Gnosis Channeled Spells", self.optempty);
|
|
LibStub("AceConfigRegistry-3.0"):RegisterOptionsTable("Gnosis Combattext/Clip test", self.optempty);
|
|
LibStub("AceConfigRegistry-3.0"):RegisterOptionsTable("Gnosis Configurations", self.optempty);
|
|
end
|
|
end
|
|
|
|
function Gnosis:HandleChatCommand(cmd)
|
|
local subcmd = string_match(cmd, "(%w+)");
|
|
if (subcmd and subcmd == "reanchor") then
|
|
Gnosis:UIScaleUpdate();
|
|
elseif(subcmd and subcmd == "load") then
|
|
subcmd = string_match(cmd, "load (.+)");
|
|
subcmd = subcmd and string_trim(subcmd);
|
|
if(subcmd and string_len(subcmd) > 0) then
|
|
self:LoadConfig(subcmd, false, true, false, false);
|
|
end
|
|
else
|
|
local bar, text, cnt, spell, iscast;
|
|
bar, cmd = Gnosis:ExtractRegex(cmd, "bar=(%w+)", "bar=\"([^\"]+)\"");
|
|
text, cmd = Gnosis:ExtractRegex(cmd, "text=(%w+)", "text=\"([^\"]+)\"");
|
|
spell, cmd = Gnosis:ExtractRegex(cmd, "spell=(%w+)", "spell=\"([^\"]+)\"", true);
|
|
cnt, cmd = Gnosis:ExtractRegex(cmd, "time=([+-]?[0-9]*%.?[0-9]*)", "time=\"([+-]?[0-9]*%.?[0-9]*)\"", true);
|
|
iscast = string_match(cmd, ".*(cast).*");
|
|
|
|
if (bar and text and cnt) then
|
|
self:InjectTimer(bar, text, cnt, spell, iscast);
|
|
else
|
|
Gnosis:OpenOptions();
|
|
end
|
|
end
|
|
end
|
|
|
|
function Gnosis:RecreateAllBars()
|
|
self:HideAllBars();
|
|
|
|
wipe(self.castbars);
|
|
self:CheckStoredCastbarOptions();
|
|
self:InitialCreateCastbars();
|
|
end
|
|
|
|
function Gnosis:DefaultAllBars()
|
|
for key, value in pairs(self.s.cbconf) do
|
|
self:SetBarParams(key);
|
|
end
|
|
end
|
|
|
|
function Gnosis:HideAllBars()
|
|
wipe(self.activebars);
|
|
wipe(self.fadeoutbars);
|
|
|
|
for key, value in pairs(self.castbars) do
|
|
value:Hide();
|
|
end
|
|
end
|
|
|
|
function Gnosis:RegisterEvents()
|
|
local key, value;
|
|
|
|
for key, value in pairs(Gnosis.tCastbarEvents) do
|
|
if (wowclassic and self.libclcno) then
|
|
self.libclcno.RegisterCallback(Gnosis, value, value);
|
|
else
|
|
self:RegisterEvent(value);
|
|
end
|
|
end
|
|
|
|
for key, value in pairs(Gnosis.tMiscEvents) do
|
|
self:RegisterEvent(value);
|
|
end
|
|
|
|
for key, value in pairs(Gnosis.tMirrorEvents) do
|
|
self:RegisterEvent(value);
|
|
end
|
|
|
|
for key, value in pairs(Gnosis.tSwingEvents) do
|
|
self:RegisterEvent(value);
|
|
end
|
|
end
|
|
|
|
function Gnosis:UnregisterEvents()
|
|
local key, value;
|
|
|
|
for key, value in pairs(Gnosis.tCastbarEvents) do
|
|
if (wowclassic and self.libclcno) then
|
|
self.libclcno.UnregisterCallback(Gnosis, value, value);
|
|
else
|
|
self:UnregisterEvent(value);
|
|
end
|
|
end
|
|
|
|
for key, value in pairs(Gnosis.tMiscEvents) do
|
|
self:UnregisterEvent(value);
|
|
end
|
|
|
|
for key, value in pairs(Gnosis.tMirrorEvents) do
|
|
self:UnregisterEvent(value);
|
|
end
|
|
|
|
for key, value in pairs(Gnosis.tSwingEvents) do
|
|
self:UnregisterEvent(value);
|
|
end
|
|
end
|
|
|
|
function Gnosis:RemoveChanneledSpell(name)
|
|
if(self.s.channeledspells[name] ~= nil) then
|
|
self.s.channeledspells[name] = nil;
|
|
self:CreateChannelSpellsOpt();
|
|
end
|
|
end
|
|
|
|
function Gnosis:AddChanneledSpellByName(name, tickcount, bdoaddticks, bars, binit, baoe, school, bheal, iUpdate)
|
|
local tx = "";
|
|
if (name) then
|
|
if (bheal) then
|
|
if (baoe) then
|
|
tx = "col<0,1,0>(spellname) [tickscrits] +eh <oh> col<pre>dps HPShittext< Hits>crittext< Crits>ticktext< Ticks>";
|
|
else
|
|
tx = "col<0,1,0>(spellname - col<1,1,1>col<class>targetcol<cpre>col<pre>col<0,1,0>) [tickscrits] +eh <oh> col<pre>dps HPShittext< Hits>crittext< Crits>ticktext< Ticks>";
|
|
end
|
|
else
|
|
if (school) then
|
|
tx = "col<" .. school .. ">dmg col<pre>col<1,1,0>(spellname) [tickscrits]col<pre>clipped dps DPScliptext<(Clipped) >hittext< Hits>crittext< Crits>ticktext< Ticks>";
|
|
else
|
|
tx = "dmg col<1,1,0>(spellname) [tickscrits]col<pre>clipped dps DPScliptext<(Clipped) >hittext< Hits>crittext< Crits>ticktext< Ticks>";
|
|
end
|
|
end
|
|
|
|
local bStoredcliptest = false;
|
|
local bStoredcombattext = false;
|
|
|
|
-- update existing
|
|
if (iUpdate and self.s.channeledspells[name] and (self.s.channeledspells[name].iupdate == nil or self.s.channeledspells[name].iupdate < iUpdate)) then
|
|
bStoredcliptest = self.s.channeledspells[name] and self.s.channeledspells[name].bcliptest or false;
|
|
bStoredcombattext = self.s.channeledspells[name] and self.s.channeledspells[name].bcombattext or false;
|
|
tx = self.s.channeledspells[name] and self.s.channeledspells[name].ctstring or tx;
|
|
self.s.channeledspells[name] = nil;
|
|
end
|
|
|
|
-- do not overwrite (possibly user edited) entry
|
|
if (self.s.channeledspells[name] == nil) then
|
|
self.s.channeledspells[name] = {
|
|
ben = true,
|
|
ticks = tickcount,
|
|
baddticks = bdoaddticks,
|
|
bars = bars,
|
|
binit = binit,
|
|
baoe = baoe,
|
|
bticksound = false,
|
|
bcliptest = bStoredcliptest,
|
|
bcombattext = bStoredcombattext,
|
|
bicon = true,
|
|
bsticky = true,
|
|
fontsizeclip = 0,
|
|
fontsizenclip = 0,
|
|
ctstring = tx,
|
|
bhidenonplayer = bdoaddticks,
|
|
iupdate = iUpdate,
|
|
};
|
|
end
|
|
end
|
|
end
|
|
|
|
function Gnosis:AddChanneledSpellById(id, tickcount, bdoaddticks, bars, binit, baoe, school, bheal, iUpdate)
|
|
local name = GetSpellInfo(id);
|
|
|
|
self:AddChanneledSpellByName(name, tickcount, bdoaddticks, bars, binit, baoe, school, bheal, iUpdate);
|
|
end
|
|
|
|
function Gnosis:SetupChanneledSpellsTable()
|
|
-- spellid, #ticks, addticks, #shown ticks, first tick instant, multi mob (no clipping detection), spellschool, isheal, upgrade_num
|
|
|
|
-- priest
|
|
if not (wowmainline) then
|
|
self:AddChanneledSpellById(15407, 3, false, 4, false, false, "shadow", false, 4); -- mind flay
|
|
else
|
|
self:AddChanneledSpellById(15407, 6, false, 7, false, false, "shadow", false, 3); -- mind flay
|
|
end
|
|
self:AddChanneledSpellById(48045, 6, false, 7, false, true, "shadow", false, 3); -- mind sear
|
|
self:AddChanneledSpellById(47540, 3, false, 2, true, false, "holy", true, 1); -- penance, first tick instant
|
|
self:AddChanneledSpellById(64843, 4, false, 15, false, true, "holy", true, 4); -- divine hymn
|
|
|
|
-- mage
|
|
if not (wowmainline) then
|
|
self:AddChanneledSpellById(10, 8, false, 15, false, true, "frost", false, 2); -- blizzard
|
|
end
|
|
self:AddChanneledSpellById(5143, 5, false, 6, false, false, "arcane", false, 2); -- arcane missiles
|
|
self:AddChanneledSpellById(12051, 6, false, 7, true, false, "arcane", false, 2); -- evocation
|
|
|
|
-- warlock
|
|
if not (wowmainline) then
|
|
self:AddChanneledSpellById(689, 6, false, 15, false, false, "shadow", false, 3); -- drain life
|
|
self:AddChanneledSpellById(1120, 4, false, 5, false, false, "shadow", false, 4); -- drain soul
|
|
self:AddChanneledSpellById(4629, 6, false, 15, false, true, "fire", false, 3); -- rain of fire
|
|
else
|
|
self:AddChanneledSpellById(234153, 5, false, 6, false, false, "shadow", false, 3); -- drain life
|
|
self:AddChanneledSpellById(198590, 5, false, 6, false, false, "shadow", false, 4); -- drain soul
|
|
end
|
|
self:AddChanneledSpellById(755, 6, false, 6, false, false, "shadow", false, 3); -- health funnel
|
|
|
|
-- druid
|
|
self:AddChanneledSpellById(740, 4, false, 15, false, true, "nature", true, 3); -- tranquility
|
|
if not (wowmainline) then
|
|
self:AddChanneledSpellById(16914, 10, false, 15, false, true, "nature", false, 2); -- hurricane
|
|
end
|
|
|
|
-- monk
|
|
self:AddChanneledSpellById(113656, 20, false, 21, true, true, "physical", false, 1); -- fists of fury, first tick instant, aoe
|
|
self:AddChanneledSpellById(115175, 8, false, 9, false, false, "nature", true, 3); -- soothing mist
|
|
|
|
-- evoker
|
|
self:AddChanneledSpellById(356995, 4, false, 5, true, false, "spellfrost", false, 3); -- disintegrate, first tick instant
|
|
end
|
|
|
|
function Gnosis:CreateColorString(r, g, b, a)
|
|
if (not (tonumber(r) and tonumber(g) and tonumber(b) and tonumber (a))) then
|
|
return "";
|
|
end
|
|
|
|
local str = string_format("%.2f, %.2f, %.2f, %.2f", r, g, b, a);
|
|
return str;
|
|
end
|
|
|
|
function Gnosis:GetCoordinatesFromString(str)
|
|
str = str .. ",0.0,0.0"; -- append safety net, also default coordinate
|
|
|
|
local x, y = string_match(str, ".-([%+%-%.%d]+).-([%+%-%.%d]+)");
|
|
|
|
if (not(x and y and tonumber(x) and tonumber(y))) then
|
|
return 0.0, 0.0;
|
|
else
|
|
return tonumber(x), tonumber(y);
|
|
end
|
|
end
|
|
|
|
function Gnosis:ScreenPercentageToString(px, py)
|
|
local uis = UIParent:GetEffectiveScale();
|
|
local xm, ym = GetScreenWidth(), GetScreenHeight();
|
|
return string_format("%.2f, %.2f", px * xm * uis, py * ym * uis);
|
|
end
|
|
|
|
function Gnosis:StringToScreenPercentage(str)
|
|
str = str .. ",0.0,0.0"; -- append safety net, also default coordinate
|
|
|
|
local x, y = string_match(str, ".-([%+%-%.%d]+).-([%+%-%.%d]+)");
|
|
|
|
if (not(x and y and tonumber(x) and tonumber(y))) then
|
|
return 0.0, 0.0;
|
|
else
|
|
local uis = UIParent:GetEffectiveScale();
|
|
local xm, ym = GetScreenWidth(), GetScreenHeight();
|
|
return x / (xm*uis), y / (ym*uis);
|
|
end
|
|
end
|
|
|
|
function Gnosis:GetColorsFromString(str, dst)
|
|
str = str .. ",1.0,1.0,1.0,1.0"; -- append safety net (also default if illegal r,g,b values given
|
|
local r, g, b, a = string_match(
|
|
str,
|
|
".-([-+]?[0-9]*%.?[0-9]+).-([-+]?[0-9]*%.?[0-9]+).-([-+]?[0-9]*%.?[0-9]+).-([-+]?[0-9]*%.?[0-9]+)"
|
|
);
|
|
|
|
r, g, b, a = tonumber(r), tonumber(g), tonumber(b), tonumber(a);
|
|
if (not a) then
|
|
r, g, b, a = nil, nil, nil, nil;
|
|
end
|
|
|
|
if (dst and r) then
|
|
dst.r, dst.g, dst.b, dst.a = r, g, b, a;
|
|
end
|
|
|
|
return r, g, b, a;
|
|
end
|
|
|
|
local RCS_strClass = "";
|
|
local function ReplaceColorsStrings_GSubFunc(sub)
|
|
if (sub == "pre" or sub == "prev") then
|
|
return "|r";
|
|
elseif (sub == "cpre") then
|
|
return RCS_strClass and "|r" or "";
|
|
elseif (sub == "class" and not RCS_strClass) then
|
|
return "";
|
|
end
|
|
|
|
local colstr = (Gnosis.colSchools[sub] and Gnosis.colSchools[sub] or (
|
|
(sub == "class" and RCS_strClass) and Gnosis.colClasses[RCS_strClass] or sub
|
|
)) .. ",1.0,1.0,1.0,1.0";
|
|
local r, g, b, a = string_match(
|
|
colstr,".-([-+]?[0-9]*%.?[0-9]+).-([-+]?[0-9]*%.?[0-9]+).-([-+]?[0-9]*%.?[0-9]+).-([-+]?[0-9]*%.?[0-9]+)"
|
|
);
|
|
return string_format(
|
|
"|c%02x%02x%02x%02x",
|
|
tonumber(a) * 255,
|
|
tonumber(r) * 255,
|
|
tonumber(g) * 255,
|
|
tonumber(b) * 255
|
|
);
|
|
end
|
|
|
|
function Gnosis:ReplaceColorStrings(str, strClass)
|
|
-- new line
|
|
str = string_gsub(str, "\\n", "\n");
|
|
|
|
RCS_strClass = strClass;
|
|
return string_gsub(
|
|
str,
|
|
"col<([^>]*)>",
|
|
ReplaceColorsStrings_GSubFunc,
|
|
10
|
|
);
|
|
end
|
|
|
|
function Gnosis:GenerateCombattext(cc, cs, bClip)
|
|
-- substitute strings
|
|
local str = cs.ctstring;
|
|
local sub;
|
|
local clipped, hit, crit, tick;
|
|
|
|
-- spell school colors, format is col<r,g,b[,a]> or col<spellschool>
|
|
-- e.g. col<1.0,0.5,0.5,1.0>; col<shadow>
|
|
str = string_gsub(str, "col<prev>", "|r");
|
|
str = self:ReplaceColorStrings(str, cc.class);
|
|
|
|
-- clipped text
|
|
clipped = string_match(str, "cliptext<(.-)>");
|
|
clipped = clipped and clipped or "";
|
|
str = string_gsub(str, "cliptext<(.-)>", "");
|
|
hit = string_match(str, "hittext<(.-)>");
|
|
hit = hit and hit or "";
|
|
str = string_gsub(str, "hittext<(.-)>", "");
|
|
crit = string_match(str, "crittext<(.-)>");
|
|
crit = crit and crit or "";
|
|
str = string_gsub(str, "crittext<(.-)>", "");
|
|
tick = string_match(str, "ticktext<(.-)>");
|
|
tick = tick and tick or "";
|
|
str = string_gsub(str, "ticktext<(.-)>", "");
|
|
|
|
-- hits, crits, ticks, dmg, dps, clipped
|
|
local dpstime = (cc.freqtest and min(cc.freqtest-cc.starttime,cc.duration) or cc.duration) / 1000;
|
|
local tickscrits = string_format("%d%s", cc.ticks + cc.mastery, tick);
|
|
if (cc.crits > 0) then tickscrits = string_format("%s, %d%s", tickscrits, cc.crits, crit); end
|
|
|
|
str = string_gsub(str, "tickscrits", tickscrits);
|
|
str = string_gsub(str, "spellname", string_format("%s", cc.spell));
|
|
str = string_gsub(str, "hits", string_format("%d", cc.hits) .. hit);
|
|
str = string_gsub(str, "crits", string_format("%d", cc.crits) .. crit);
|
|
str = string_gsub(str, "ticks", string_format("%d", cc.ticks + cc.mastery) .. tick);
|
|
str = string_gsub(str, "dmg", string_format("%d", cc.dmg));
|
|
str = string_gsub(str, "dps", (dpstime > 0.02) and string_format("%d", cc.dmg / dpstime) or "1.#INF");
|
|
str = string_gsub(str, "eh", string_format("%d", cc.eh));
|
|
str = string_gsub(str, "oh", string_format("%d", cc.oh));
|
|
str = string_gsub(str, "target", cc.target or "");
|
|
if (bClip) then
|
|
str = string_gsub(str, "clipped", clipped);
|
|
else
|
|
str = string_gsub(str, "clipped", "");
|
|
end
|
|
|
|
-- string ready for combat text output
|
|
local strTex = nil;
|
|
local bSticky = nil;
|
|
if (cs.bicon) then strTex = cc.texture; end
|
|
if (cs.bsticky and bClip) then bSticky = true; end
|
|
|
|
-- font size
|
|
local fs = nil;
|
|
if (bClip and cs.fontsizeclip > 0) then
|
|
fs = cs.fontsizeclip;
|
|
elseif (not bClip and cs.fontsizenclip > 0) then
|
|
fs = cs.fontsizenclip;
|
|
end
|
|
|
|
if (self.s.ct.addon == "MSBT" and MikSBT and MikSBT.IsModDisabled() == nil) then
|
|
MikSBT.DisplayMessage(str, MikSBT.DISPLAYTYPE_OUTGOING, bSticky, nil, nil, nil, fs, nil, nil, strTex);
|
|
elseif (self.s.ct.addon == "SCT" and SCT and (cc.type or SCTD)) then
|
|
SCT:DisplayText(str, nil, bSticky, "damage", cc.type and SCT.FRAME2 or SCT.FRAME3, nil, nil, strTex);
|
|
elseif (self.s.ct.addon == "Parrot" and Parrot) then
|
|
Parrot:ShowMessage(str, "Outgoing", bSticky, 1, 1, 1, nil, fs, nil, strTex);
|
|
elseif (self.s.ct.addon == "Blizz" and tostring(SHOW_COMBAT_TEXT) ~= "0") then
|
|
CombatText_AddMessage(str, CombatText_StandardScroll, 1, 1, 1, bSticky, false);
|
|
end
|
|
end
|
|
|
|
-- clip test
|
|
function Gnosis:SetupChannelData()
|
|
local fCurTime = GetTime() * 1000.0;
|
|
local name, displayName, texture, startTime, endTime = UnitChannelInfo("player");
|
|
|
|
local cs = self.s.channeledspells[name];
|
|
if (cs and cs.ben and (cs.bcliptest or cs.bcombattext or cs.bticksound)) then
|
|
local cc = {};
|
|
local totalticks = cs.ticks;
|
|
local noninitticks = cs.binit and (totalticks-1) or totalticks;
|
|
|
|
if(cs.baddticks) then
|
|
-- estimate amount of ticks due to haste
|
|
local haste = UnitSpellHaste("player") / 100.0 + 1.0;
|
|
noninitticks = floor(noninitticks * haste + 0.5);
|
|
totalticks = cs.binit and (noninitticks+1) or noninitticks;
|
|
end
|
|
|
|
-- data
|
|
cc.spell = name;
|
|
cc.endtime = endTime;
|
|
cc.starttime = startTime;
|
|
cc.duration = endTime - startTime;
|
|
cc.channelticktime = (1 / noninitticks) * (endTime - startTime);
|
|
cc.maxticks = totalticks;
|
|
cc.testtime = endTime + self.s.wfcl;
|
|
cc.pushback = 0;
|
|
cc.dmg = 0;
|
|
cc.eh = 0;
|
|
cc.oh = 0;
|
|
cc.ticks = 0;
|
|
cc.hits = 0;
|
|
cc.crits = 0;
|
|
cc.mastery = 0;
|
|
cc.bcliptest = cs.bcliptest;
|
|
cc.baeo = cs.baoe;
|
|
cc.texture = texture;
|
|
cc.target = self.strLastTarget;
|
|
cc.class = self.strLastTargetClass;
|
|
cc.bticksound = cs.bticksound;
|
|
cc.lastticktime = nil;
|
|
|
|
-- ticks table
|
|
cc.tticks = {};
|
|
local idx = cc.maxticks;
|
|
for i = 1, cc.maxticks do
|
|
cc.tticks[idx] = endTime - (i-1) * cc.channelticktime;
|
|
idx = idx - 1;
|
|
end
|
|
|
|
if (self.curchannel) then
|
|
self.nextchannel = cc;
|
|
else
|
|
self.curchannel = cc;
|
|
end
|
|
end
|
|
end
|
|
|
|
function Gnosis:RequestClipTest()
|
|
local fCurTime = GetTime() * 1000.0;
|
|
|
|
local cc, nc = self.curchannel, self.nextchannel;
|
|
if (cc) then
|
|
cc.freqtest = cc.freqtest and min(cc.freqtest,fCurTime) or fCurTime;
|
|
cc.fforcedtest = cc.fforcedtest and min(cc.fforcedtest,fCurTime + self.s.wfcl) or (fCurTime + self.s.wfcl);
|
|
end
|
|
end
|
|
|
|
function Gnosis:UpdateClipTest()
|
|
local spell, _, _, startTime, endTime = UnitChannelInfo("player");
|
|
local cc = (self.nextchannel and self.nextchannel.spell == spell) and self.nextchannel or
|
|
((self.curchannel and self.curchannel.spell == spell) and self.curchannel or nil);
|
|
|
|
if (cc) then
|
|
local fspb = endTime - cc.endtime;
|
|
cc.endtime = endTime;
|
|
cc.testtime = cc.testtime + fspb;
|
|
|
|
if (fspb > 0) then
|
|
-- chain channeling
|
|
for i = 1, cc.maxticks do
|
|
cc.tticks[i] = cc.tticks[i] + fspb;
|
|
end
|
|
cc.duration = cc.duration + fspb;
|
|
elseif (fspb < 0) then
|
|
local max_ = cc.maxticks;
|
|
for i = 1, max_ do
|
|
if(cc.tticks[i] > cc.endtime) then
|
|
cc.tticks[i] = nil;
|
|
cc.maxticks = cc.maxticks - 1;
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function Gnosis:PlaySounds()
|
|
if (self.s.ct.bsound and self.s.ct.sound and SOUNDKIT[self.s.ct.sound]) then
|
|
PlaySound(SOUNDKIT[self.s.ct.sound], self.s.ct.channel and
|
|
self.tSoundChannels[self.s.ct.channel] or self.tSoundChannels[1]);
|
|
end
|
|
if (self.s.ct.bmusic and self.s.ct.music) then
|
|
PlaySoundFile(self.lsm:Fetch("sound", self.s.ct.music),
|
|
self.s.ct.channel and self.tSoundChannels[self.s.ct.channel] or self.tSoundChannels[1]);
|
|
end
|
|
if (self.s.ct.bfile and self.s.ct.file) then
|
|
PlaySoundFile(self.s.ct.file,
|
|
self.s.ct.channel and self.tSoundChannels[self.s.ct.channel] or self.tSoundChannels[1]);
|
|
end
|
|
end
|
|
|
|
function Gnosis:ClipTest(fCurTime)
|
|
local cc, nc = self.curchannel, self.nextchannel;
|
|
|
|
if (cc) then
|
|
local cs = self.s.channeledspells[cc.spell];
|
|
local bClip, bOutput = false, false;
|
|
|
|
if ((not cs.baoe and cc.ticks == cc.maxticks) or fCurTime >= cc.testtime) then
|
|
-- check spell out, no clipping
|
|
bOutput = true;
|
|
elseif (cc.fforcedtest and fCurTime >= cc.fforcedtest) then -- clip test requested
|
|
bOutput = true;
|
|
-- test for clipping
|
|
if (cs.bcliptest and not cs.baoe) then
|
|
if (cc.tticks[cc.ticks+1] and (cc.tticks[cc.ticks+1] - cc.freqtest) <= self.s.ctt) then
|
|
-- unintentional clipping detected, do not output as clip if player had no target when clip test was requested
|
|
local tarname = UnitName("target");
|
|
if((not nc or nc.spellname ~= cc.spellname) and tarname and not UnitIsDead("target")) then
|
|
bClip = true;
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
if (bOutput) then
|
|
-- play clip sound and output to combat text
|
|
if (bClip and cs.bcliptest and not cs.bticksound) then
|
|
self:PlaySounds();
|
|
end
|
|
|
|
if (cs.bcombattext and cc.ticks > 0) then
|
|
self:GenerateCombattext(cc, cs, bClip);
|
|
end
|
|
|
|
-- done, next channeled spell in queue
|
|
self.curchannel = nil;
|
|
self.curchannel = self.nextchannel;
|
|
self.nextchannel = nil;
|
|
end
|
|
|
|
elseif (nc) then
|
|
self.curchannel = nil;
|
|
self.curchannel = self.nextchannel;
|
|
self.nextchannel = nil;
|
|
end
|
|
end
|
|
|
|
function Gnosis:AddCustomBar(name, unit, width, height, scale, movefactor_y, movefactor_x, unlockicon)
|
|
local fScale = UIParent:GetScale();
|
|
local cfg;
|
|
|
|
if (self.s.cbconf[name]) then
|
|
self:RemoveCastbar(name);
|
|
end
|
|
|
|
self:OptCreateNewCastbar(name, unit);
|
|
|
|
cfg = self.s.cbconf[name];
|
|
|
|
cfg.scale = scale;
|
|
cfg.width = width;
|
|
cfg.height = height;
|
|
cfg.bIconUnlocked = unlockicon;
|
|
Gnosis:SetBarParams(name);
|
|
|
|
cfg.anchor.py = cfg.anchor.py + movefactor_y * (self.tCastbarDefaults.height/GetScreenHeight() + 0.01) * fScale;
|
|
cfg.anchor.px = cfg.anchor.px + movefactor_x * (self.tCastbarDefaults.height/GetScreenHeight()*2.5 + self.tCastbarDefaults.width/GetScreenWidth() + 0.01) * fScale;
|
|
self:AnchorBar(name);
|
|
end
|
|
|
|
function Gnosis:CreateCustomCastbarSet()
|
|
self:AddCustomBar("gn" .. self.L["CBSetPlayer"], "player", 300, 28, 1.0, 3, 0, true);
|
|
self:AddCustomBar("gn" .. self.L["CBSetTarget"], "target", 250, 20, 1.0, 1, 0, false);
|
|
self:AddCustomBar("gn" .. self.L["CBSetFocus"], "focus", 250, 20, 1.0, -1, 0, false);
|
|
self:AddCustomBar("gn" .. self.L["CBSetPet"], "pet", 250, 20, 1.0, -3, 0, false);
|
|
self:AddCustomBar("gn" .. self.L["CBSetMirror"], "mirror", 250, 20, 1.0, 6, 0, false);
|
|
end
|
|
|
|
function Gnosis:CreateGCDSwingTimers()
|
|
self:AddCustomBar("gn" .. self.L["CBSetGCD"], "gcd", 250, 3, 1.0, -5, 0);
|
|
self:AddCustomBar("gn" .. self.L["CBSetSwing"], "smr", 250, 3, 1.0, -6, 0);
|
|
|
|
local cfg = self.s.cbconf["gn" .. self.L["CBSetGCD"]];
|
|
cfg.border = 0;
|
|
cfg.colBar = { 0.85, 0.85, 0.85, 0.70 };
|
|
cfg.strNameFormat = "";
|
|
cfg.strTimeFormat = "";
|
|
cfg.iconside = "NONE";
|
|
self:SetBarParams("gn" .. self.L["CBSetGCD"]);
|
|
|
|
cfg = self.s.cbconf["gn" .. self.L["CBSetSwing"]];
|
|
cfg.border = 0;
|
|
cfg.colBar = { 0.85, 0.85, 0.85, 0.70 };
|
|
cfg.strNameFormat = "";
|
|
cfg.strTimeFormat = "r<1>";
|
|
cfg.fontsize_timer = 11;
|
|
cfg.coord.casttime.y = -9;
|
|
cfg.iconside = "NONE";
|
|
cfg.alignment = "FREE";
|
|
self:SetBarParams("gn" .. self.L["CBSetSwing"]);
|
|
end
|
|
|
|
function Gnosis:RedoLocalization()
|
|
self:SetupLocale();
|
|
-- recreate tables
|
|
self:OptCreateBasicTables();
|
|
self:CreateCastbarsOpt();
|
|
self:CreateChannelSpellsOpt();
|
|
self:OptCreateCTpage();
|
|
self:OptCreateConfigurations();
|
|
|
|
local hide = self.s.bHideAddonMsgs;
|
|
self.s.bHideAddonMsgs = true;
|
|
-- reload most of the addon for localization
|
|
self:En(false);
|
|
self:En(true);
|
|
self.s.bHideAddonMsgs = hide;
|
|
end
|
|
|
|
function Gnosis:tsize(t)
|
|
local i = 0;
|
|
if (t and type(t) == "table") then
|
|
for k, v in pairs(t) do
|
|
i = i + 1;
|
|
end
|
|
end
|
|
|
|
return i;
|
|
end
|
|
|
|
function Gnosis:CheckForFirstStart(bForce)
|
|
if (self.s.bAddonEn and (bForce or ((not Gnosis.s) or self:tsize(Gnosis.s.cbconf) == 0))) then
|
|
-- create window
|
|
local f = self.gui:Create("Window");
|
|
|
|
local _, uc = UnitClass("player");
|
|
if (UnitLevel("player") == 1 or (uc == "DEATHKNIGHT" and UnitLevel("player") == 55)) then
|
|
-- probably newly created char, don't release widget for OnClose callback,
|
|
-- otherwise window will be gone after the intro sequence
|
|
f:SetCallback("OnClose", function(w) end);
|
|
else
|
|
f:SetCallback("OnClose", function(w) Gnosis.gui:Release(w); end);
|
|
end
|
|
|
|
f:SetTitle(Gnosis.L["AddonName"]);
|
|
f:SetStatusText(Gnosis.L["IfCWAction"]);
|
|
f:SetLayout("Flow");
|
|
f:SetWidth(500);
|
|
f:SetFullHeight(true);
|
|
|
|
local h1 = self.gui:Create("Heading");
|
|
if ((not Gnosis.s) or self:tsize(Gnosis.s.cbconf) == 0) then
|
|
h1:SetText(Gnosis.L["IfNoCBs"]);
|
|
end
|
|
h1.width = "fill";
|
|
f:AddChild(h1);
|
|
|
|
local msg = self.gui:Create("Label");
|
|
msg:SetText(Gnosis.L["IfCCSString"]);
|
|
msg:SetFullWidth(true);
|
|
f:AddChild(msg);
|
|
|
|
local btnLCS = self.gui:Create("Button");
|
|
btnLCS:SetWidth(230);
|
|
btnLCS:SetText(Gnosis.L["IfCCSetup"]);
|
|
btnLCS:SetCallback("OnClick", function()
|
|
Gnosis:CreateCustomCastbarSet();
|
|
Gnosis:HideBlizzardCastbarIfStatusChange(true);
|
|
Gnosis:HideBlizzardMirrorCastbarIfStatusChange(true);
|
|
Gnosis:HideBlizzardPetCastbarIfStatusChange(true);
|
|
end
|
|
);
|
|
f:AddChild(btnLCS);
|
|
|
|
local btnLCS = self.gui:Create("Button");
|
|
btnLCS:SetWidth(230);
|
|
btnLCS:SetText(Gnosis.L["IfCCTimers"]);
|
|
btnLCS:SetCallback("OnClick", function()
|
|
Gnosis:CreateGCDSwingTimers();
|
|
end
|
|
);
|
|
f:AddChild(btnLCS);
|
|
|
|
if (self:tsize(GnosisConfigs) > 0) then
|
|
local h2 = self.gui:Create("Heading");
|
|
h2:SetText(Gnosis.L["IfConfigs"]);
|
|
h2.width = "fill";
|
|
f:AddChild(h2);
|
|
|
|
local msg2 = self.gui:Create("Label");
|
|
msg2:SetText(Gnosis.L["IfLFConigs"]);
|
|
msg2:SetFullWidth(true);
|
|
f:AddChild(msg2);
|
|
|
|
for key, value in pairs(GnosisConfigs) do
|
|
local butCfg = self.gui:Create("Button");
|
|
butCfg:SetWidth(230);
|
|
butCfg:SetText(key);
|
|
butCfg:SetCallback("OnClick", function()
|
|
Gnosis:LoadConfig(key, true, true, true, true);
|
|
end
|
|
);
|
|
f:AddChild(butCfg);
|
|
end
|
|
end
|
|
|
|
local h3 = self.gui:Create("Heading");
|
|
h3:SetText("");
|
|
h3.width = "fill";
|
|
f:AddChild(h3);
|
|
|
|
local btnGUI = self.gui:Create("Button");
|
|
btnGUI:SetWidth(230);
|
|
btnGUI:SetText(Gnosis.L["IfOpenGUI"]);
|
|
btnGUI:SetCallback("OnClick", function()
|
|
Gnosis:OpenOptions();
|
|
end
|
|
);
|
|
f:AddChild(btnGUI);
|
|
|
|
self.IntroFrame = f;
|
|
|
|
return true;
|
|
end
|
|
|
|
return false;
|
|
end
|
|
|
|
-- returns: embedded match, text before, text after, first match, last match
|
|
function Gnosis:ExtractEmbeddedString(str, first, last, dotrim)
|
|
-- check parameters
|
|
if (first and (type(first) ~= "string" or string_len(first) < 1)) then
|
|
return;
|
|
end
|
|
if (last and (type(last) ~= "string" or string_len(last) < 1)) then
|
|
return;
|
|
end
|
|
if (type(str) == "string") then
|
|
-- trim string (remove leading and trailing whitespace)
|
|
if (dotrim) then
|
|
str = string.trim(str);
|
|
end
|
|
else
|
|
return;
|
|
end
|
|
|
|
-- local variables
|
|
local first_found = nil;
|
|
local last_found = nil;
|
|
local cur = str;
|
|
local embedded = "";
|
|
local before = "";
|
|
local after = "";
|
|
local pattern_esc = "(\\)";
|
|
local pattern_first = first and ("(" .. first .. ")") or nil;
|
|
local pattern_last = last and ("(" .. last .. ")") or nil;
|
|
|
|
-- find first
|
|
if (pattern_first) then
|
|
local s, f, match_first = string_find(str, pattern_first);
|
|
|
|
if (match_first) then -- pattern_first
|
|
first_found = match_first;
|
|
before = string_sub(str, 1, s-1);
|
|
cur = string_sub(str, f+1);
|
|
else -- no match
|
|
return nil;
|
|
end
|
|
end
|
|
|
|
-- find last
|
|
while (true) do
|
|
local s1, f1, s2, f2, s3, f3, match_esc, match_last, new_match_first;
|
|
|
|
s1, f1, match_esc = string_find(cur, pattern_esc);
|
|
if (pattern_last) then
|
|
s2, f2, match_last = string_find(cur, pattern_last);
|
|
end
|
|
if (pattern_first) then
|
|
s3, f3, new_match_first = string_find(cur, pattern_first);
|
|
end
|
|
|
|
local bContinue = true;
|
|
-- matched both, pattern_esc < pattern_first?
|
|
if (new_match_first) then
|
|
local bNewMatch;
|
|
if (s1 and s2) then
|
|
bNewMatch = s3 < s1 and s3 < s2;
|
|
elseif (s1) then
|
|
bNewMatch = s3 < s1;
|
|
elseif (s2) then
|
|
bNewMatch = s3 < s2;
|
|
end
|
|
|
|
if (bNewMatch) then
|
|
-- found new beginning
|
|
first_found = new_match_first;
|
|
before = before .. string_sub(cur, 1, s3-1);
|
|
cur = string_sub(cur, f3+1);
|
|
bContinue = false;
|
|
end
|
|
end
|
|
|
|
if (bContinue) then
|
|
if (s1 and s2 and s1 < s2) then
|
|
match_last = nil;
|
|
end
|
|
|
|
if (match_last) then -- pattern_last
|
|
-- found substring ending
|
|
last_found = match_last;
|
|
embedded = embedded .. string_sub(cur, 1, s2-1);
|
|
after = string_sub(cur, f2+1);
|
|
return embedded, before, after, first_found, last_found;
|
|
elseif (match_esc) then -- pattern_esc
|
|
embedded = embedded .. string_sub(cur, 1, s1-1) .. string_sub(cur, s1+1, s1+1);
|
|
cur = string_sub(cur, s1+2);
|
|
else -- no match
|
|
-- did not find end of embedded string
|
|
if (last) then
|
|
return;
|
|
else
|
|
if (first_found) then
|
|
embedded = embedded .. cur;
|
|
end
|
|
|
|
if (string_len(embedded) > 0) then
|
|
return embedded, before, after, first_found;
|
|
else
|
|
return;
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- exchanges all chars in charsToEscape string with \char, don't forget % if "magic" character
|
|
function Gnosis:ExchangeEscapeSequenceChars(str, charsToEscape)
|
|
local pattern = "([" .. charsToEscape .. "])";
|
|
return string_gsub(str, pattern, "\\%1");
|
|
end
|
|
|
|
-- hook SetItemRef (import Gnosis bar via chatlink)
|
|
function Gnosis:SetItemRef(link, text)
|
|
-- remove text coloring
|
|
link = string_gsub(link, "\124c[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]", "");
|
|
link = string_gsub(link, "\124r", "");
|
|
text = string_gsub(text, "\124c[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]", "");
|
|
text = string_gsub(text, "\124r", "");
|
|
|
|
local s, f, name, server, barname;
|
|
if (link and text) then
|
|
s, f, name, server = link:find("^gnosis([^%s/]+)/(.+)$");
|
|
s, f, barname = text:find("%[[^:]+: (.-)%]\124h$");
|
|
end
|
|
|
|
if (name and server and barname) then
|
|
if (not IsShiftKeyDown()) then
|
|
Gnosis.comm:SendCommMessage("GnosisComm", "req:" .. barname, "WHISPER", name .. "-" .. server);
|
|
end
|
|
end
|
|
end
|
|
|
|
-- communication events
|
|
function Gnosis:CommCb(message, distribution, sender)
|
|
local s, f, barname = message:find("req:(.+)");
|
|
local hash, serial_tab;
|
|
|
|
local importname, before, after, match_first, match_last = Gnosis:ExtractEmbeddedString(message, "%[", "%]");
|
|
if (importname and string_len(after) > 0) then
|
|
s, f, hash, serial_tab = string_find(after, "(.-):(.+)$");
|
|
end
|
|
|
|
if (barname) then
|
|
-- request received, send bar via addon channel
|
|
if (Gnosis.s.cbconf[barname]) then
|
|
-- serialize table
|
|
local comp = Gnosis.libs:Serialize(Gnosis.s.cbconf[barname]);
|
|
-- compress and encode for communication via addon channel
|
|
local lc = Gnosis.libc;
|
|
comp = lc:Compress(comp);
|
|
comp = lc:GetAddonEncodeTable():Encode(comp);
|
|
-- generate 32bit hash
|
|
local comp_hash = lc:fcs32final(lc:fcs32update(lc:fcs32init(), comp));
|
|
-- complete message to send
|
|
local msg = "[" .. Gnosis:ExchangeEscapeSequenceChars(barname, "\\:%[%]") .. "]" .. comp_hash .. ":" .. comp;
|
|
|
|
-- send to sender of request
|
|
Gnosis.comm:SendCommMessage("GnosisComm", msg, distribution, sender);
|
|
end
|
|
elseif (importname and hash and serial_tab) then
|
|
-- bar data received
|
|
local lc = Gnosis.libc;
|
|
-- compute hash
|
|
local comp_hash = lc:fcs32final(lc:fcs32update(lc:fcs32init(), serial_tab));
|
|
|
|
-- check hash
|
|
if (comp_hash == tonumber(hash)) then
|
|
-- message ok, import
|
|
local ok;
|
|
-- decode string
|
|
local uncomp = lc:GetAddonEncodeTable():Decode(serial_tab);
|
|
-- decompress
|
|
uncomp = lc:Decompress(uncomp);
|
|
-- deserialize, uncomp holds original table afterwards
|
|
ok, uncomp = Gnosis.libs:Deserialize(uncomp);
|
|
|
|
if (ok) then
|
|
-- create import dialog
|
|
Gnosis.dialog:Register("GNOSIS_IMPORT_HYPERLINK",
|
|
{
|
|
text = sender .. " -> |cffdddd22" .. importname .. "|r\n\n" .. Gnosis.L["ImportFromHyperlink"],
|
|
buttons = {
|
|
{
|
|
text = Gnosis.L["Import"],
|
|
on_click = function(self)
|
|
Gnosis:ImportBarInit(importname);
|
|
Gnosis.s.cbconf[importname] = uncomp;
|
|
Gnosis:ImportBarFinalize(importname);
|
|
--InterfaceOptionsFrame_OpenToCategory(Gnosis.optCBs);
|
|
end,
|
|
},
|
|
(Gnosis.s.cbconf[importname] and {
|
|
text = Gnosis.L["ImportKeepPos"],
|
|
on_click = function(self)
|
|
Gnosis:ImportBarInit(importname);
|
|
local anchor = Gnosis.s.cbconf[importname].anchor;
|
|
Gnosis.s.cbconf[importname] = uncomp;
|
|
Gnosis.s.cbconf[importname].anchor = anchor;
|
|
Gnosis:ImportBarFinalize(importname);
|
|
--InterfaceOptionsFrame_OpenToCategory(Gnosis.optCBs);
|
|
end,
|
|
} or {}),
|
|
{
|
|
text = Gnosis.L["NoImport"],
|
|
on_click = function(self)
|
|
end,
|
|
},
|
|
},
|
|
hide_on_escape = false,
|
|
show_while_dead = true,
|
|
width = 420,
|
|
strata = 5,
|
|
}
|
|
);
|
|
|
|
Gnosis.dialog:Spawn("GNOSIS_IMPORT_HYPERLINK");
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local oldSetHyperlink = ItemRefTooltip.SetHyperlink;
|
|
function ItemRefTooltip:SetHyperlink(link, ...)
|
|
if (link and link:find("^gnosis")) then
|
|
return;
|
|
end
|
|
|
|
return oldSetHyperlink(self, link, ...);
|
|
end
|
|
|
|
local function exchangeHyperlink(_, _, msg, ...)
|
|
local msgToPrint = "";
|
|
|
|
while (true) do
|
|
local embedded, before, after, match_first = Gnosis:ExtractEmbeddedString(msg, "%[Gnosis:[^%s%-]+%-[^%s%:]+:", "]");
|
|
|
|
if (embedded) then
|
|
local s, f, name, server = string_find(match_first, "%[Gnosis:([^%s%-]+)%-([^%s%-]+):");
|
|
msgToPrint = msgToPrint .. before ..
|
|
"\124Hgnosis" .. name .. "/" .. server .. "\124h" ..
|
|
"\124cffdddd22[" .. name .. "\124r\124cffdddd22: " .. embedded .. "]\124r\124h";
|
|
|
|
msg = after;
|
|
else
|
|
msgToPrint = msgToPrint .. msg;
|
|
break;
|
|
end
|
|
end
|
|
|
|
return false, msgToPrint, ...;
|
|
end
|
|
|
|
ChatFrame_AddMessageEventFilter("CHAT_MSG_WHISPER", exchangeHyperlink);
|
|
ChatFrame_AddMessageEventFilter("CHAT_MSG_WHISPER_INFORM", exchangeHyperlink);
|
|
ChatFrame_AddMessageEventFilter("CHAT_MSG_BN_WHISPER", exchangeHyperlink);
|
|
ChatFrame_AddMessageEventFilter("CHAT_MSG_BN_WHISPER_INFORM", exchangeHyperlink);
|
|
ChatFrame_AddMessageEventFilter("CHAT_MSG_BN_CONVERSATION", exchangeHyperlink);
|
|
ChatFrame_AddMessageEventFilter("CHAT_MSG_SAY", exchangeHyperlink);
|
|
ChatFrame_AddMessageEventFilter("CHAT_MSG_YELL", exchangeHyperlink);
|
|
ChatFrame_AddMessageEventFilter("CHAT_MSG_GUILD", exchangeHyperlink);
|
|
ChatFrame_AddMessageEventFilter("CHAT_MSG_OFFICER", exchangeHyperlink);
|
|
ChatFrame_AddMessageEventFilter("CHAT_MSG_PARTY", exchangeHyperlink);
|
|
ChatFrame_AddMessageEventFilter("CHAT_MSG_PARTY_LEADER", exchangeHyperlink);
|
|
ChatFrame_AddMessageEventFilter("CHAT_MSG_RAID", exchangeHyperlink);
|
|
ChatFrame_AddMessageEventFilter("CHAT_MSG_RAID_LEADER", exchangeHyperlink);
|
|
ChatFrame_AddMessageEventFilter("CHAT_MSG_INSTANCE_CHAT", exchangeHyperlink);
|
|
ChatFrame_AddMessageEventFilter("CHAT_MSG_INSTANCE_CHAT_LEADER", exchangeHyperlink);
|
|
ChatFrame_AddMessageEventFilter("CHAT_MSG_CHANNEL", exchangeHyperlink);
|
|
|
|
local function repaste_hyperlink(self, link, text, ...)
|
|
-- remove text coloring
|
|
link = string_gsub(link, "\124c[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]", "");
|
|
link = string_gsub(link, "\124r", "");
|
|
text = string_gsub(text, "\124c[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]", "");
|
|
text = string_gsub(text, "\124r", "");
|
|
|
|
local s, f, name, server, barname;
|
|
if (link and text) then
|
|
s, f, name, server = link:find("^gnosis([^%s/]+)/(.+)$");
|
|
s, f, barname = text:find("%[[^:]+: (.-)%]\124h$");
|
|
end
|
|
|
|
if (name and server and barname and IsShiftKeyDown()) then
|
|
local link = "[Gnosis:" .. name .. "-" .. server .. ":" .. Gnosis:ExchangeEscapeSequenceChars(barname, "\\:%[%]") .. "]";
|
|
|
|
local eb = GetCurrentKeyBoardFocus();
|
|
if (eb) then
|
|
eb:Insert(link);
|
|
end
|
|
end
|
|
end
|
|
|
|
hooksecurefunc("ChatFrame_OnHyperlinkShow", repaste_hyperlink);
|
|
|
|
function Gnosis:ExportBarEncStr(key)
|
|
if (key and self.s.cbconf[key]) then
|
|
-- serialize table
|
|
local comp = self.libs:Serialize(self.s.cbconf[key]);
|
|
local len = string.len(comp); -- do not use utf8 version
|
|
-- compress and encode for communication via addon channel
|
|
local lc = Gnosis.libc;
|
|
comp = lc:Compress(comp);
|
|
comp = self:EncStr(comp);
|
|
-- generate 32bit hash
|
|
local comp_hash = lc:fcs32final(lc:fcs32update(lc:fcs32init(), comp));
|
|
-- complete message to send
|
|
local msg = "[" .. Gnosis:ExchangeEscapeSequenceChars(key, "\\:%[%]") .. ":" ..
|
|
comp_hash .. ":" .. len .. ":=" .. comp .. ";]";
|
|
|
|
return msg;
|
|
end
|
|
end
|
|
|
|
function Gnosis:ExtractAndImportEncStr(str)
|
|
local import, _;
|
|
local importname, before, after, match_first, match_last = Gnosis:ExtractEmbeddedString(str, "%[", ":%d+:%d+:=[0-9A-Za-z%#%*]+;%]");
|
|
|
|
if (importname) then
|
|
local lc = Gnosis.libc;
|
|
local s, f, hash, len, import = string_find(match_last, ":(%d+):(%d+):=([0-9A-Za-z%#%*]+);%]");
|
|
|
|
if (s) then
|
|
if (tonumber(hash) == lc:fcs32final(lc:fcs32update(lc:fcs32init(), import))) then
|
|
-- compress and encode for communication via addon channel
|
|
-- message ok, import
|
|
local ok;
|
|
-- decode string
|
|
local uncomp = Gnosis:DecStr(import, tonumber(len));
|
|
-- decompress
|
|
uncomp = lc:Decompress(uncomp);
|
|
-- deserialize, uncomp holds original table afterwards
|
|
ok, uncomp = Gnosis.libs:Deserialize(uncomp);
|
|
|
|
if (ok) then
|
|
-- create import dialog
|
|
Gnosis.dialog:Register("GNOSIS_IMPORT_ENCSTR",
|
|
{
|
|
text = "|cffdddd22" .. importname .. "|r\n\n" .. Gnosis.L["ImportFromHyperlink"],
|
|
buttons = {
|
|
{
|
|
text = Gnosis.L["Import"],
|
|
on_click = function(self)
|
|
Gnosis:ImportBarInit(importname);
|
|
Gnosis.s.cbconf[importname] = uncomp;
|
|
Gnosis:ImportBarFinalize(importname);
|
|
--InterfaceOptionsFrame_OpenToCategory(Gnosis.optCBs);
|
|
end,
|
|
},
|
|
Gnosis.s.cbconf[importname] and {
|
|
text = Gnosis.L["ImportKeepPos"],
|
|
on_click = function(self)
|
|
Gnosis:ImportBarInit(importname);
|
|
local anchor = Gnosis.s.cbconf[importname].anchor;
|
|
Gnosis.s.cbconf[importname] = uncomp;
|
|
Gnosis.s.cbconf[importname].anchor = anchor;
|
|
Gnosis:ImportBarFinalize(importname);
|
|
--InterfaceOptionsFrame_OpenToCategory(Gnosis.optCBs);
|
|
end,
|
|
} or {},
|
|
{
|
|
text = Gnosis.L["NoImport"],
|
|
on_click = function(self)
|
|
end,
|
|
},
|
|
},
|
|
on_hide = function(self)
|
|
-- LibDialog-1.0 bandaid
|
|
Gnosis.bDelayedEsc = true;
|
|
end,
|
|
hide_on_escape = false,
|
|
show_while_dead = true,
|
|
width = 420,
|
|
strata = 5,
|
|
}
|
|
);
|
|
|
|
Gnosis.dialog:Spawn("GNOSIS_IMPORT_ENCSTR");
|
|
end
|
|
return before .. after, true;
|
|
end
|
|
end
|
|
end
|
|
|
|
return str;
|
|
end
|
|
|
|
function Gnosis:ImportBarsFromStr(str)
|
|
local found;
|
|
|
|
-- import encoded bars
|
|
repeat
|
|
str, found = Gnosis:ExtractAndImportEncStr(str);
|
|
until (found == nil);
|
|
end
|
|
|
|
function Gnosis:UnregisterGlobalMouseEvents()
|
|
if (Gnosis.s.bUnregGlobalMouse) then
|
|
if (not UIParent:IsEventRegistered("GLOBAL_MOUSE_DOWN") and
|
|
not UIParent:IsEventRegistered("GLOBAL_MOUSE_DOWN")) then
|
|
if (not self.s.bHideAddonMsgs) then
|
|
self:Print(Gnosis.L["MsgUnregGlobalMouseNotReq"]);
|
|
end
|
|
else
|
|
UIParent:UnregisterEvent("GLOBAL_MOUSE_DOWN");
|
|
UIParent:UnregisterEvent("GLOBAL_MOUSE_UP");
|
|
|
|
if (not self.s.bHideAddonMsgs) then
|
|
self:Print(Gnosis.L["MsgUnregGlobalMouse"]);
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|