Skip to content

Instantly share code, notes, and snippets.

@Konctantin Konctantin/main.lua
Created Jun 28, 2014

Embed
What would you like to do?
yanitta
ABILITY_TABLE = { };
EVENT_MODS = { };
LOSS_TABLE = { };
NOTIFY_CAST_TABLE = { };
LAST_TARGET = 0;
-- Константы горячих клавиш
mkLeftShift = 1;
mkLeftControl = 2;
mkLeftAlt = 3;
mkRightShift = 4;
mkRightControl = 5;
mkRightAlt = 6;
-- Ауры, которые позволяют произносить заклинания на ходу
moving_spell_table = {
97128, -- Опаляющее перо (Алисразор)
79206, -- Благосклонность предков (Шанам)
110806, -- Благосклонность предков (Друид: Симбиоз)
108839, -- Плавучая льдина
};
-- Возвращает, есть ли один из перечисленных бафов на персонаже
-- Возвращает:
-- Имя эффекта
-- Количество стаков
-- Оставшееся время действия
-- value1, value2, value3 - Величина эффекта
-- Параметры:
-- unit - Цель ("palyer", "target", "focus", "mouseover")
-- {...} - перечень бафов
-- filter - фильтр
function HasBuff(unit, spellId, filter)
local spell_table = { };
if type(spellId) == "table" then
spell_table = spellId;
elseif type(spellId) == "number" then
spell_table = { spellId };
end
for _,spell_id in ipairs(spell_table) do
local spellName, spellRank = GetSpellInfo(spell_id);
if spellName then
-- name, rank, icon, count, dispelType, duration, expires, caster, isStealable, shouldConsolidate, spellID, canApplyAura, isBossDebuff, value1, value2, value3
local name,_,_,count,_,_,expires,_,_,_,_,_,_,value1,value2,value3 = UnitBuff(unit, spellName, spellRank, filter);
if name then
local rem = min(max((expires or 0) - (GetTime() - (AddonFrame.ping or 0)), 0), 0xffff);
return name, count, rem, value1, value2, value3;
end
end
end
return nil, 0, 0, nil, 0, 0;
end
-- Возвращает, есть ли один из перечисленных дебафов на персонаже
-- Возвращает:
-- Имя эффекта
-- Количество стаков
-- Оставшееся время действия
-- value1, value2, value3 - Величина эффекта
-- Параметры:
-- unit - Цель ("palyer", "target", "focus", "mouseover")
-- {...} - перечень дебафов
-- filter - фильтр
function HasDebuff(unit, spellId, filter)
local spell_table = { };
if type(spellId) == "table" then
spell_table = spellId;
elseif type(spellId) == "number" then
spell_table = { spellId };
end
for _,spell_id in ipairs(spell_table) do
local spellName, spellRank = GetSpellInfo(spell_id);
if spellName then
-- name, rank, icon, count, dispelType, duration, expires, caster, isStealable, shouldConsolidate, spellID, canApplyAura, isBossDebuff, value1, value2, value3
local name,_,_,count,_,_,expires,_,_,_,_,_,_,value1,value2,value3 = UnitDebuff(unit, spellName, spellRank, filter);
if name then
local rem = min(max((expires or 0) - (GetTime() - (AddonFrame.ping or 0)), 0), 0xffff);
return name, count, rem, value1, value2, value3;
end
end
end
return nil, 0, 0, nil, 0, 0;
end
-- Вызвращает время до восстановления заклинания
-- Параметр: ид заклинания
function SpellCD(m_spell)
local start, duration = GetSpellCooldown(m_spell);
local cooldown = duration + start - GetTime();
return cooldown > 0 and cooldown - (AddonFrame.ping or 0) or 0;
end
-- Проверка, двигается ли игрок, за исключением бафов, которые дают возможность кастровать на ходу
-- на пример: Опаляющее перо (Алисразор), Благосклонность предков (Шанам)
function IsMoving()
for _, spell in ipairs(moving_spell_table) do
local name,rank = GetSpellInfo(spell);
if name and UnitAura("player", name, rank, nil) then
return;
end
end
return GetUnitSpeed("player") ~= 0 or IsFalling();
end
-- Проверка на нахождение персонажа за спиной цели
function IsBehind(sec)
return (GetTime() - (AddonFrame.LastNotBehindTime or 0)) > (sec or 1);
end
-- Проверка на нахождение цели в зоне видимости персонажа
function IsNotLineOfSight(unit, sec)
local rec = LOSS_TABLE[UnitGUID(unit)];
return rec and (GetTime() - rec.ctime) <= (sec or 1);
end
-- возвращает текущее значение здоровья в процентах
function HealthByPercent(m_target)
return UnitExists(m_target) and 100 * (UnitHealth(m_target) or 1) / (UnitHealthMax(m_target) or 1) or 0;
end
-- возвращает текущее значение ресурса (мана, энергия, фокус, ярость ...) в процентах
function PowerByPercent(m_target, m_powertype)
return UnitExists(m_target) and 100 * (UnitPower(m_target, m_powertype) or 1) / (UnitPowerMax(m_target, m_powertype) or 1) or 0;
end
-- Проверка, была ли зажата клавиша модификатор mk*
function IsModKeyDown(m_key)
if not GetCurrentKeyBoardFocus() then
return (m_key == mkLeftShift and IsLeftShiftKeyDown() ) or
(m_key == mkLeftControl and IsLeftControlKeyDown() ) or
(m_key == mkLeftAlt and IsLeftAltKeyDown() ) or
(m_key == mkRightShift and IsRightShiftKeyDown() ) or
(m_key == mkRightAlt and IsRightAltKeyDown() ) or
(m_key == mkRightControl and IsRightControlKeyDown());
end
end
-- Возвращает дистанцию между двумя игроками
function GetDistance(unit1, unit2)
local lvl, a1, b1, a2, b2 = GetCurrentMapDungeonLevel();
if not (a1 and b1 and a2 and b2) then
lvl, a1, y1, a2, y2 = GetCurrentMapZone();
end
if a1 and b1 and a2 and b2 then
local x1, y1 = GetPlayerMapPosition(unit1);
local x2, y2 = GetPlayerMapPosition(unit2);
local dX = ((x1 - x2) * abs(a2 - a1)) ^ 2;
local dY = ((y1 - y2) * abs(b2 - b1)) ^ 2;
return sqrt(dX + dY);
end
end
-- Проверка, имеется ли у персонажа указанный символ
function HasGlyph(glyphid)
for slot = 1, 6 do
if select(4, GetGlyphSocketInfo(slot)) == glyphid then
return slot;
end
end
end
-- Использование предмета в инвентаре
-- Если предмет (перчатка, тринька, пояс и т.п) юзабелен и не имеет КД - имитируем клик правой кн. мыши.
function UseItemBySlot(slotId)
local start, duration, enable = GetInventoryItemCooldown("player", slotId);
if duration == 0 and enable == 1 then
UseInventoryItem(slotId);
end
end
-- Использование предмета в инвентаре по его ID
function UseItemById(itemId)
local count = GetItemCount(itemId);
if (count or 0) > 0 then
local start,duration,enable = GetItemCooldown(itemId);
if start == 0 and duration == 0 and enable then
UseItemByName(itemId);
end
end
end
-- Возвращает ID юнита
function UnitId(unit)
return tonumber((UnitGUID(unit) or "0x0000000000000000"):sub(-12, -9), 16);
end
-- Проверяет, надо ли сбивать заклинание текущему юниту.
function CheckInterrupt(unit, sec)
-- чтение заклинания прерываем только перед окончанием каста.
local name,_,_,_,startTime,endTime,isTrade,_,notInterruptible = UnitCastingInfo(unit);
if name and not (notInterruptible or isTrade) then
if (((endTime / 1000) - GetTime()) - AddonFrame.ping) <= (sec or 1) then
return true;
end
end
-- канальное заклинание прерываем сразу.
local name,_,_,_,_,_,isTrade,notInterruptible = UnitChannelInfo(unit);
if name and not (notInterruptible or isTrade) then
return true;
end
end
-- Проверяет наличие исступления.
function CheckEnrage(unit)
if UnitCanAttack("player", unit) then
for i = 1, 40 do
local name,_,_,_,dispelType = UnitBuff(unit, i);
if not name then
return;
-- Исступление отображается как пустая строка
elseif dispelType == "" then
return true;
end
end
end
end
-----------------------------------------------
-- HEAL --
-----------------------------------------------
MAIN_CLASS_SPELL = 0;
FORCE_IN_COMBAT = nil;
DISPELL_TABLE = { -- Магия Яд Болезнь Проклятие
PRIEST_HEAL = { Magic = true, Poison = nil , Disease = true, Curse = nil },
PRIEST_NONE = { Magic = nil , Poison = nil , Disease = true, Curse = nil },
DRUID_HEAL = { Magic = true, Poison = true, Disease = nil , Curse = true },
DRUID_NONE = { Magic = nil , Poison = true, Disease = nil , Curse = true },
DRUID_SIMBIOS = { Magic = nil , Poison = true, Disease = true, Curse = true },
PALADIN_HEAL = { Magic = true, Poison = true, Disease = true, Curse = nil },
PALADIN_NONE = { Magic = nil , Poison = true, Disease = true, Curse = nil },
MONK_HEAL = { Magic = true, Poison = true, Disease = true, Curse = nil },
MONK_NONE = { Magic = nil , Poison = true, Disease = true, Curse = nil },
SHAMAN_HEAL = { Magic = true, Poison = nil , Disease = nil , Curse = true },
SHAMAN_NONE = { Magic = nil , Poison = nil , Disease = nil , Curse = nil },
MAGE_NONE = { Magic = nil , Poison = nil , Disease = nil , Curse = true },
};
-- Добавляет в таблицу "members" указанного юнита, при этом делая проверки (возможность лечить)
function InsertNewUnitToHeallersTable(unit)
if UnitExists(unit)
and not UnitIsDeadOrGhost(unit)
and not UnitIsCorpse(unit)
and UnitHealth(unit) > 100
and UnitCanAssist(unit, "player")
and IsSpellInRange(GetSpellInfo(MAIN_CLASS_SPELL), unit) == 1
and not IsNotLineOfSight(unit) then
for _,member in ipairs(members) do
if UnitGUID(member.Unit) == UnitGUID(unit) then
return;
end
end
table.insert(members, { Unit = unit, IsInMyParty = false });
end
end
-- в эту функцию добавляем логику по особому поведению в рейдах
-- на пример, если есть какой-то дебаф, который надо выхиливать.
function CheckInstanseLogic(member)
-- Осада Огриммара: Малкорок
-- Отхил не проходит, надо настакивать щит под дебафом
-- по этому просто занижаем реальное здоровье.
if HasDebuff(member.Unit, 142861) then
if HasDebuff(member.Unit, 142863) then -- красный
member.HP = 50;
elseif HasDebuff(member.Unit, 142864) then -- желтый
member.HP = 80;
elseif HasDebuff(member.Unit, 142865) then -- зеленый
member.HP = 100;
else -- без щита
member.HP = min(member.HP, 50);
end
-- Престол гроз: Тортос (Кристальная оболочка)
elseif HasDebuff(member.Unit, 137633) then
if not HasDebuff(member.Unit, 140701) then
member.HP = min(member.HP, 50);
end
-- Престол гроз: Наложницы блезнецы (Дебаф: Чудовище из кошмаров)
elseif HasDebuff(member.Unit, 137341) then
member.DontHeal = true;
end
end
-- логика развеивания заклинаний, тут добавляем условия, которые запрещают развеивать дебафы
function DontDispell(debuffId, member)
-- ша гордыни: диспелим "Слово тьмы: Погибель" только с дебафом "Дар титанов"
-- После "Освобождения" Дар титанов больше не кидается, поэтому диспелим по КД
if debuffId == 144351 then
if not HasDebuff("player", 144359) and HealthByPercent("boss1") > 30 then
-- Если на нас много порчи - не диспелим
if UnitPower("player", SPELL_POWER_ALTERNATE_POWER) > 50 then
return true;
end
end
-- Глубиний
elseif debuffId == 143579 then
if select(2, HasDebuff(member.Unit, 143579)) < 3 then
return true;
end
-- Блуждающая энергия: надо диспелить когда возле цели разсеивания нету других игроков
-- elseif debuffId == 142913 then
-- for i,member2 in ipairs(members) do
-- if not UnitIsUnit("player", member2.Unit) then
-- if (GetDistance(member.Unit, member2.Unit) or 0) < 8 then
-- return true;
-- end
-- end
-- end
-- Прикосновение скверны (треш перед боссом Ша гордыни)
-- Диспелятся сразу все дебафы, а при диспеле наносится урон.
elseif debuffId == 149207 then
return true;
end
end
-- Возвращает юнита, с которого надо диспелить (с наибольшим количеством стаков)
-- Параметр dispeller_type - Указывает тип диспеллера ( "NONE", "HEAL", "SIMBIOS")
-- По умолчанию: "NONE"
-- Возвращает: unit, count или nil - если диспелить нечего.
function GetDispellInfo(dispeller_type)
local dispeller = dispeller_type or "NONE";
local d_class = select(2, UnitClass("player"));
local c_rec = DISPELL_TABLE[d_class.."_"..dispeller];
if not c_rec then return end
local dispellTable = { };
for _,member in ipairs(members) do
for index = 1, 40 do
local name,_,_,count,dispelType,duration,expires,_,_,_,debuffId = UnitDebuff(member.Unit, index);
if not name then break end
if c_rec[dispelType] and not DontDispell(debuffId, member) then
table.insert(dispellTable, { Unit = member.Unit, Count = count, HP = member.HP });
end
end
end
if #dispellTable > 0 then
if #dispellTable > 1 then
table.sort(dispellTable, function(A, B)
return A.Count > B.Count;
end);
end
return dispellTable[1].Unit, dispellTable;
end
end
-- Формирует таблицу "members" которая содержит юнитов нуждающихся в лечении.
-- при формировании происходят проверки: (доступность + рейдовая логика)
-- сформированная таблица будет отсортирована по наименьшему здоровью.
function FillPartyTables(standartSpellId)
-- Обнуляем все хиловские глобальные переменные.
FORCE_IN_COMBAT = false;
MAIN_CLASS_SPELL = standartSpellId;
LowHP = { };
members = { { Unit = "player", IsInMyParty = true } };
for i = 95, 10, -5 do
LowHP["H"..i] = 0;
end
local prefix = "party";
if IsInRaid() then
prefix = "raid";
elseif IsInArenaTeam() then
prefix = "arena";
end
for index = 1, GetNumGroupMembers() do
local unit = prefix..index;
if UnitExists(unit)
and not UnitIsCorpse(unit)
and not UnitIsUnit("player", unit)
and UnitIsConnected(unit)
and not UnitIsEnemy("player", unit)
and not UnitIsDeadOrGhost(unit)
and UnitInRange(unit)
and not IsNotLineOfSight(unit) then
table.insert(members, { Unit = unit, IsInMyParty = true });
end
end
-- отхил дружественной цели по mouseover/target/focus
InsertNewUnitToHeallersTable("target");
InsertNewUnitToHeallersTable("focus");
InsertNewUnitToHeallersTable("mouseover");
-- Обновляем статы игроков из пати/рейда
for index = #members, 1, -1 do
local member = members[index];
if UnitAffectingCombat(member.Unit) then
FORCE_IN_COMBAT = true;
end
member.IsTank = UnitGroupRolesAssigned(member.Unit) == "TANK";
member.Agro = UnitThreatSituation(member.Unit) or 0;
local max_hp = UnitHealthMax(member.Unit) or 0;
local inc_hp = UnitGetIncomingHeals(member.Unit) or 0;
local cur_hp = UnitHealth(member.Unit) or 0;
member.IncHeal = 100 * inc_hp / max_hp;
member.HP = 100 * (cur_hp + inc_hp) / max_hp;
-- логика по особому поведению в рейдах
CheckInstanseLogic(member);
-- подсчет количества персонажей с определенным уровнем здоровья (95-10) с шагом в -5
-- не учитываем цели, которые хилить нельзя
if not member.DontHeal then
for i = 95, 10, -5 do
if member.HP <= i then
LowHP["H"..i] = LowHP["H"..i] + 1;
end
end
end
-- удаляем из талицы юнит, которого нельзя хилить
if member.DontHeal then
table.remove(members, index);
end
end
-- сортируем таблицы по наименьшему количеству ХР
if #members > 1 then
table.sort(members, function(x, y) return x.HP < y.HP; end);
elseif #members == 0 then
members = {{ Unit = "none", Agro = 0, HP = 100, IncHeal = 0 }};
end
end
---------------------------------------
-- CORE --
---------------------------------------
function CheckKnownAbility(ability)
local spellName = GetSpellInfo(ability.SpellId);
ability.IsKnown = false;
-- Основная проверка
if IsPlayerSpell(ability.SpellId)
or IsSpellKnown(ability.SpellId) or IsSpellKnown(ability.SpellId, true)
or IsTalentSpell(spellName) then
ability.IsKnown = true;
return;
end
if GetSpecialization() then
-- Проверка на доступность заклинания по уровню и специализиции
local spellList = { GetSpecializationSpells(GetSpecialization()) };
local lvl = UnitLevel("player");
for i = 1, #spellList, 2 do
if spellList[i] == ability.SpellId and lvl > (spellList[i+1] or 0) then
ability.IsKnown = true;
return;
end
end
end
-- Есть заклинания, которые имеют одинаковое название и разные Id
local spellId = select(2, GetSpellBookItemInfo(spellName));
if spellId and ability.SpellId ~= spellId then
print(string.format("|cff15bd05Заклинание: %s Id %d -> %d|r", spellName, ability.SpellId, spellId));
ability.SpellId = spellId;
ability.IsKnown = true;
end
end
-- Проверяем доступность заклинаний
function CheckAllSpells()
if type(ABILITY_TABLE) == "table" then
for _,ability in ipairs(ABILITY_TABLE) do
if ability.SpellId > 0 then
CheckKnownAbility(ability);
end
end
end
end
function CheckAndCastAbility(ability, target)
if ability.IsCheckInCombat and not (FORCE_IN_COMBAT or UnitAffectingCombat("player")) then
return;
end
if ability.SetRecastDelay
and ability.Guid == UnitGUID(target) and ability.LastCastingTime >= GetTime() then
return;
end
local spellInfo = GetSpellInfo(ability.SpellId);
if ability.SpellId < 1 then
return ability.Func(ability, target);
elseif not (ability.IsKnown and IsUsableSpell(spellInfo)) then
return;
end
local start, duration, enable = GetSpellCooldown(ability.SpellId);
if enable == 1 and ((duration + start) - GetTime()) > AddonFrame.ping then
return;
end
local castPing = (AddonFrame.ping * 1000);
if not ability.CancelCasting then
local endTime = select(6, UnitCastingInfo("player")) or 0;
if (endTime - (GetTime() * 1000)) >= castPing then
return;
end
end
if not ability.DropChanel then
local endTime = select(6, UnitChannelInfo("player")) or 0;
if (endTime - (GetTime() * 1000)) >= castPing then
return;
end
end
if (ability.IsMovingCheck == "notmoving" and IS_MOVING)
or (ability.IsMovingCheck == "moving" and not IS_MOVING) then
return;
end
local result = ability.Func(ability, target);
if not result then
return;
elseif type(result) == "string" then
target = result;
end
if target ~= "none" and target ~= "player" and target ~= "mouselocation" then
if not UnitExists(target) then
return;
elseif SpellHasRange(spellInfo) and IsSpellInRange(spellInfo, target) == 0 then
return;
elseif IsHelpfulSpell(spellInfo) and not UnitIsFriend("player", target) then
return;
elseif IsHarmfulSpell(spellInfo) and UnitIsFriend("player", target) then
return;
elseif not UnitIsFriend("player", target) then
if UnitIsDeadOrGhost(target) or not UnitCanAttack("player", target) then
return;
end
end
end
if ability.CancelCasting or ability.DropChanel then
SpellStopCasting();
end
if target == "mouselocation" then
CastSpellByName(spellInfo, nil);
CameraOrSelectOrMoveStart();
CameraOrSelectOrMoveStop();
CastSpellByName(spellInfo, nil);
elseif target == "none" then
LAST_TARGET = UnitGUID("player");
CastSpellByName(spellInfo, nil);
else
LAST_TARGET = UnitGUID(target);
CastSpellByName(spellInfo, target);
end
return true;
end
function ChangeRotation(rotation)
--assert(type(AddonFrame) ~= "table",
-- '\"AddonFrame\" не существует в текущем контексте');
if not AddonFrame then return end;
if AddonFrame.CurentRotation and (not rotation or rotation == AddonFrame.CurentRotation) then
AddonFrame.CurentRotation = nil;
AddonFrame:UnregisterAllEvents();
AddonFrame.print("|cfff5360cРотация отключена.|r", true);
PlaySound("PAPERDOLLCLOSE", "Master");
elseif rotation then
AddonFrame:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED");
AddonFrame:RegisterEvent("PLAYER_ENTERING_WORLD");
AddonFrame:RegisterEvent("PLAYER_LOGOUT");
AddonFrame:RegisterEvent("WORLD_MAP_UPDATE");
AddonFrame:RegisterEvent("MODIFIER_STATE_CHANGED");
AddonFrame:RegisterEvent("SPELLS_CHANGED");
AddonFrame.CurentRotation = rotation;
AddonFrame.print("|cff15bd05Ротация: |r|cff6f0a9a"..rotation.."|r|cff15bd05 - Включена.|r", true);
PlaySound("PAPERDOLLOPEN", "Master");
CheckAllSpells();
end
end
function AddonFrame_OnEvent(self, event, ...)
if event == "PLAYER_ENTERING_WORLD" then
self:Show();
CheckAllSpells();
elseif event == "PLAYER_LOGOUT" then
ChangeRotation();
elseif event == "WORLD_MAP_UPDATE" then
LOSS_TABLE = { };
elseif event == "SPELLS_CHANGED" then
CheckAllSpells();
elseif event == "COMBAT_LOG_EVENT_UNFILTERED" then
local timestamp, subEvent, hideCaster,
sourceGUID,srcName, sourceFlags,sourceFlags2,
destGUID, destName, destFlags, destFlags2,
spellId, spellName,spellSchool, param15 = ...;
if subEvent == "SPELL_CAST_SUCCESS" and sourceGUID == UnitGUID("player") then
if NOTIFY_CAST_TABLE[spellId] then
print(NOTIFY_CAST_TABLE[spellId]);
end
for _,ability in ipairs(ABILITY_TABLE) do
for _,target in ipairs(ability.TargetList) do
if spellId == ability.SpellId and UnitGUID(target) == destGUID then
ability.Guid = destGUID,
ability.LastCastingTime = GetTime() + 1000,
end
end
end
elseif subEvent == "SPELL_CAST_START" and sourceGUID == UnitGUID("player") then
for _,ability in ipairs(ABILITY_TABLE) do
for _,target in ipairs(ability.TargetList) do
if spellId == ability.SpellId and UnitGUID(target) == destGUID then
ability.Guid = destGUID,
ability.LastCastingTime = GetTime() + 1000 + (select(7, GetSpellInfo(spellId)) or 0),
end
end
end
elseif subEvent == "SPELL_CAST_FAILED" and sourceGUID == UnitGUID("player") then
if param15 == SPELL_FAILED_LINE_OF_SIGHT then
LOSS_TABLE[destGUID] = { ctime = GetTime(), cspell = spellId };
end
for _,ability in ipairs(ABILITY_TABLE) do
for _,target in ipairs(ability.TargetList) do
if spellId == ability.SpellId and UnitGUID(target) == destGUID then
ability.Guid = nil;
ability.LastCastingTime = 0;
if param15 == SPELL_FAILED_NOT_BEHIND then
ability.LastNotBehindTime = GetTime();
end
end
end
end
end
end
if type(EVENT_MODS[event]) == "function" then
EVENT_MODS[event](...);
end
end
function AddonFrame_OnUpdate(self, elapsed)
if type(ABILITY_TABLE) == "table" and GetTime() >= (AddonFrame.LastTime or 0) then
if AddonFrame.CurentRotation and not UnitIsDeadOrGhost("player") and not UnitIsAFK("player") then
IS_MOVING = IsMoving();
AddonFrame.ping = select(4, GetNetStats()) / 1000;
for _,ability in ipairs(ABILITY_TABLE) do
for _,target in ipairs(ability.TargetList) do
if CheckAndCastAbility(ability, target) then
break;
end
end
end
end
AddonFrame.LastTime = GetTime() + 0.2;
end
if (AddonFrame.Duration or 0) < GetTime() then
AddonFrame.Msg:SetText("");
end
end
if type(AddonFrame) == "table" then
AddonFrame:UnregisterAllEvents();
end
if type(AddonFrame) ~= "table" then
AddonFrame = CreateFrame("Frame");
AddonFrame:SetScript("OnUpdate", AddonFrame_OnUpdate);
AddonFrame:SetScript("OnEvent", AddonFrame_OnEvent);
AddonFrame:SetHeight(300);
AddonFrame:SetWidth(600);
AddonFrame.Msg = AddonFrame:CreateFontString(nil, "BACKGROUND", "PVPInfoTextFont");
AddonFrame.Msg:SetAllPoints();
AddonFrame.print = function(msg, con)
AddonFrame.Msg:SetText(msg);
if con then print(msg) end
AddonFrame.Duration = GetTime() + 5;
end
AddonFrame:SetPoint("CENTER", 0, 200);
AddonFrame:Show();
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.