Created
June 28, 2014 06:23
-
-
Save Konctantin/74d0b2667abe89873a4c to your computer and use it in GitHub Desktop.
yanitta
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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