From 53abc61e4fde23c9d651bd702a6e5380b18310a4 Mon Sep 17 00:00:00 2001 From: Sidoine De Wispelaere Date: Mon, 13 Aug 2012 20:46:14 +0000 Subject: [PATCH] - code refactoring - added target option to AddIcon - better support for casting on focus git-svn-id: svn://svn.curseforge.net/wow/ovale/mainline/trunk@484 d5049fe3-3747-40f7-a4b5-f36d6801af5f --- Condition.lua | 1234 -------------------------- Locale-esES.lua | 4 + Ovale.lua | 2408 ++------------------------------------------------ Ovale.toc | 19 +- OvaleActionBar.lua | 108 +++ OvaleAura.lua | 269 ++++++ OvaleBestAction.lua | 616 +++++++++++++ OvaleCompile.lua | 74 +- OvaleCondition.lua | 1175 ++++++++++++++++++++++++ OvaleData.lua | 427 +++++++++ OvaleEnemies.lua | 65 ++ OvaleEquipement.lua | 9 +- OvaleFrame.lua | 323 +++---- OvaleFuture.lua | 306 +++++++ OvaleGUID.lua | 134 +++ OvaleIcone.lua | 65 +- OvaleIcone.xml | 2 +- OvaleOptions.lua | 481 ++++++++++ OvaleSpellDamage.lua | 35 + OvaleState.lua | 404 +++++++++ OvaleSwing.lua | 26 +- compiler.pl | 228 +++++ defaut/Pretre.lua | 6 +- 23 files changed, 4615 insertions(+), 3803 deletions(-) delete mode 100644 Condition.lua create mode 100644 Locale-esES.lua create mode 100644 OvaleActionBar.lua create mode 100644 OvaleAura.lua create mode 100644 OvaleBestAction.lua create mode 100644 OvaleCondition.lua create mode 100644 OvaleData.lua create mode 100644 OvaleEnemies.lua create mode 100644 OvaleFuture.lua create mode 100644 OvaleGUID.lua create mode 100644 OvaleOptions.lua create mode 100644 OvaleSpellDamage.lua create mode 100644 OvaleState.lua create mode 100644 compiler.pl diff --git a/Condition.lua b/Condition.lua deleted file mode 100644 index e976bd0..0000000 --- a/Condition.lua +++ /dev/null @@ -1,1234 +0,0 @@ -local LBCT = LibStub("LibBabble-CreatureType-3.0"):GetLookupTable() -local LRC = LibStub("LibRangeCheck-2.0", true) -local runes = {} -local runesCD = {} - -local runeType = -{ - blood = 1, - unholy = 2, - frost = 3, - death = 4 -} - -local totemType = -{ - ghoul = 1, - fire = 1, - earth = 2, - water = 3, - air = 4 -} - -local fearSpellList = nil -local stunSpellList = nil -local incapacitateSpellList = nil -local rootSpellList = nil - -local function buildRootSpellList() - if (rootSpellList) then - return - end - rootSpellList = {} - for k, v in pairs(Ovale.buffSpellList.fear) do - rootSpellList[v] = true - end -end - -local function buildStunSpellList() - if (stunSpellList) then - return - end - stunSpellList = {} - for k, v in pairs(Ovale.buffSpellList.stun) do - stunListList[v] = true - end -end - -local function buildIncapacitateSpellList() - if (incapacitateSpellList) then - return - end - incapacitateSpellList = {} - for k, v in pairs(Ovale.buffSpellList.incapacitate) do - incapacitateSpellList[v] = true - end -end - -local function buildFearSpellList() - if (fearSpellList) then - return - end - fearSpellList = {} - for k, v in pairs(Ovale.buffSpellList.fear) do - fearSpellList[v] = true - end -end - -local function isDebuffInList(list) - local i=1; - while (true) do - local name, rank, icon, count, debuffType, duration, expirationTime, unitCaster, isStealable, shouldConsolidate, spellId = UnitDebuff("player", i); - if (not name) then - break - end - if (list[spellId]) then - return true - end - i = i +1 - end - return false -end - -local function avecHate(temps, hate) - if not temps then - temps = 0 - end - if (not hate) then - return temps - elseif (hate == "spell") then - return temps/Ovale.spellHaste - elseif (hate == "melee") then - return temps/Ovale.meleeHaste - else - return temps - end -end - -local function compare(a, comparison, b) - if (comparison == "more") then - if (not b or (a~=nil and a>b)) then - return 0 - else - return nil - end - elseif comparison == "equal" then - if b == a then - return 0 - else - return nil - end - else - if (not a or (b~=nil and a expireTime then - otherAura[target] = nil - else - if expireTime > maxTime then - maxTime = expireTime - end - if not minTime or diff 0 then - runes[rune.type] = runes[rune.type] - 1 - if rune.cd > runesCD[rune.type] then - runesCD[rune.type] = rune.cd - end - elseif rune.cd < runesCD[rune.type] then - runesCD[rune.type] = rune.cd - end - end - end - - if not condition.nodeath then - for i=1,6 do - local rune = Ovale.state.rune[i] - if rune and rune.type == 4 then - for j=1,3 do - if runes[j]>0 then - runes[j] = runes[j] - 1 - if rune.cd > runesCD[j] then - runesCD[j] = rune.cd - end - break - elseif rune.cd < runesCD[j] then - runesCD[j] = rune.cd - break - end - end - end - end - end - - for i=1,4 do - if runes[i]> 0 then - return nil - end - if not maxCD or runesCD[i]>maxCD then - maxCD = runesCD[i] - end - end - return maxCD -end - -local lastEnergyValue = nil -local lastEnergyTime - -local function GetManaAndRate(withBerserker) - local _,className = UnitClass("player") - local current = Ovale.state.mana - if current~=lastEnergyValue then - lastEnergyValue = current - lastEnergyTime = Ovale.currentTime - end - - local rate - - if className == "ROGUE" or (className == "DRUID" and GetShapeshiftForm(true) == 3) then - rate = 10 * Ovale.meleeHaste - if (className == "ROGUE") then - local rush = Ovale:GetAura("player", "HELPFUL", 13750) - if rush.stacks>0 then - rate = rate * 2 - end - elseif withBerserker then - local berserk = Ovale:GetAura("player", "HELPFUL", 50334) - if berserk.stacks>0 then - mana = mana/2 - end - end - elseif className == "HUNTER" then - rate = 4 * Ovale.meleeHaste - else - rate = 0 - end - - return lastEnergyValue, lastEnergyTime, rate -end - -local function GetManaTime(mana, withBerserker) - local lastEnergyValue, lastEnergyTime, rate = GetManaAndRate(withBerserker) - - if rate > 0 then - local limit = math.ceil((mana - lastEnergyValue) / rate + lastEnergyTime) - return limit - else - if Ovale.state.mana>=mana then - return Ovale.currentTime-1 - else - return nil - end - end -end - - --- Recherche un aura sur la cible et récupère sa durée et le nombre de stacks --- return start, ending, stacks -local function GetTargetAura(condition, filter, target) - if (not target) then - target=condition.target - if (not target) then - target="target" - end - end - local stacks = condition.stacks - if not stacks then - stacks = 1 - end - local spellId = condition[1] - - - local aura - if type(spellId) == "number" then - aura = Ovale:GetAura(target, filter, spellId) - elseif Ovale.buffSpellList[spellId] then - for k,v in pairs(Ovale.buffSpellList[spellId]) do - local newAura = Ovale:GetAura(target, filter, v) - if not aura or newAura.stacks>aura.stacks then - aura = newAura - end - end - elseif spellId == "Magic" or spellId == "Disease" or spellId=="Curse" or spellId=="Poison" then - aura = Ovale:GetAura(target, filter, spellId) - else - Ovale:Print("ERROR: unknown buff "..spellId) - Ovale.bug = true - return 0,0 - end - - if Ovale.trace then - Ovale:Print("GetTargetAura = start=".. nilstring(aura.start) .. " end="..nilstring(aura.ending).." stacks=" ..nilstring(aura.stacks).."/"..stacks) - end - - if (not condition.mine or (aura.mine and condition.mine==1) or (not aura.mine and condition.mine==0)) and aura.stacks>=stacks then - local ending - if condition.forceduration then - if Ovale.spellInfo[spellId] and Ovale.spellInfo[spellId].duration then - ending = aura.start + Ovale.spellInfo[spellId].duration - else - ending = aura.start + condition.forceduration - end - else - ending = aura.ending - end - return aura.start, ending - else - return 0,0 - end -end - -local lastSaved = {} -local savedHealth = {} -local targetGUID = {} -local lastSPD = {} - -local function getTargetDead(target) - local second = math.floor(Ovale.maintenant) - if targetGUID[target] ~=UnitGUID(target) then - lastSaved[target] = nil - targetGUID[target] = UnitGUID(target) - savedHealth[target] = {} - end - local newHealth = UnitHealth(target) - if newHealth then - Ovale:Log("newHealth = " .. newHealth) - end - if UnitHealthMax(target)==1 then - Ovale:Log("Dummy, return in the future") - return nil - end - if second~=lastSaved[target] and targetGUID[target] then - lastSaved[target] = second - local mod10 = second % 10 - local prevHealth = savedHealth[target][mod10] - savedHealth[target][mod10] = newHealth - if prevHealth and prevHealth>newHealth then - lastSPD[target] = 10/(prevHealth-newHealth) - if lastSPD[target] > 0 then - Ovale:Log("dps = " .. (1/lastSPD[target])) - end - end - end - if not lastSPD[target] or lastSPD[target]<=0 then - return nil - end - -- Rough estimation - local duration = newHealth * lastSPD[target] - if duration < 10000 then - return Ovale.maintenant + duration - else - return nil - end -end - -Ovale.conditions= -{ - -- Test if a white hit just occured - -- 1 : maximum time after a white hit - -- Not useful anymore. No widely used spell reset swing timer anyway - --[[AfterWhiteHit = function(condition) - local debut = OvaleSwing.starttime - local fin = OvaleSwing.duration + debut - local maintenant = GetTime() - if (maintenant-debutcondition[2] then - return 0 - else - return nil - end - else - if condition[2]~=nil and minRange0 solar - Eclipse = function(condition) - return compare(Ovale.state.eclipse, condition[1], condition[2]) - end, - eclipse = function(condition) - return Ovale.state.eclipse - end, - EffectiveMana = function(condition) - local limit = GetManaTime(condition[2], true) - if condition[1]=="more" then - return limit, nil - else - return 0,limit - end - end, - effectiveMana = function(condition) - return GetManaAndRate(true) - end, - EndCastTime = function(condition) - local name, rank, icon, cost, isFunnel, powerType, castTime = Ovale:GetSpellInfoOrNil(condition[1]) - local actionCooldownStart, actionCooldownDuration, actionEnable = Ovale:GetComputedSpellCD(condition[1]) - local startCast = actionCooldownStart + actionCooldownDuration - if startCast0 then - local timeBefore = condition[2] or 0 - return 0, addTime(maxTime, -timeBefore) - end - return nil - end, - OtherAuraExpires = OtherDebuffExpires, - OtherAuraPresent = OtherDebuffPresent, - otherAura = function(condition) - local minTime, maxTime = getOtherAura(condition[1]) - return 0, maxTime, -1 - end, - Present = function(condition) - local present = UnitExists(getTarget(condition.target)) and not UnitIsDead(getTarget(condition.target)) - return testbool(present, condition[1]) - end, - -- Test if any player pet is present (or not) - -- 1 : "yes" or "no" - PetPresent = function(condition) - local present = UnitExists("pet") and not UnitIsDead("pet") - return testbool(present, condition[1]) - end, - -- Test the target level difference with the player - -- 1 : "less" or "more" - -- 2 : [target level]-[player level] limit - RelativeLevel = function(condition) - local difference - local target = getTarget(condition.target) - if UnitLevel(target) == -1 then - difference = 3 - else - difference = UnitLevel(target) - UnitLevel("player") - end - - return compare(difference, condition[1], condition[2]) - end, - remainingCastTime = function(condition) - local name, nameSubtext, text, texture, startTime, endTime, isTradeSkill, castID, notInterruptible = UnitCastingInfo(getTarget(condition.target)) - if not endTime then - return nil - end - return 0, endTime/1000, -1 - end, - Runes = function(condition) - return GetRune(condition) - end, - runes = function(condition) - local ret = GetRune(condition) - if not ret then - return nil - end - if ret < Ovale.maintenant then - ret = Ovale.maintenant - end - return 0, ret, -1 - end, - SoulShards = function(condition) - return compare(Ovale.state.shard, condition[1], condition[2]) - end, - soulShards = function(condition) - return Ovale.state.shard - end, - Speed = function(condition) - return compare(GetUnitSpeed(getTarget(condition.target))*100/7, condition[1], condition[2]) - end, - speed = function(condition) - return GetUnitSpeed(getTarget(condition.target))*100/7 - end, - spell = function(condition) - local actionCooldownStart, actionCooldownDuration, actionEnable = Ovale:GetComputedSpellCD(condition[1]) - return actionCooldownDuration, actionCooldownStart, -1 - end, - spellPower = function(condition) - return GetSpellBonusDamage(2), 0, 0 - end, - -- Test if the player is in a given stance - -- 1 : the stance - Stance = function(condition) - if (GetShapeshiftForm(true) == condition[1]) then - return 0 - else - return nil - end - end, - Stealthed = function(condition) - return testbool(IsStealthed(), condition[1]) - end, - -- Test how many talent points has been spent in a talent - -- 1 : the talent identifier (use /script print(Ovale.talentNameToId["Talent name"]) to retreive) - -- 2 : "more" or "less" - -- 3 : the limit - TalentPoints = function(condition) - if (not Ovale.listeTalentsRemplie) then - Ovale:RemplirListeTalents() - return nil - end - return compare(Ovale.pointsTalent[condition[1]], condition[2], condition[3]) - end, - talentPoints = function(condition) - if (not Ovale.listeTalentsRemplie) then - Ovale:RemplirListeTalents() - return nil - end - return Ovale.pointsTalent[condition[1]], 0, 0 - end, - -- Test if the target's target is the player (or is not) - -- 1 : "yes" (it should be the player) or "no" - TargetIsPlayer = function(condition) - return testbool(UnitIsUnit("player",getTarget(condition.target).."target"), condition[1]) - end, - Threat = function(condition) - local isTanking, status, threatpct = UnitDetailedThreatSituation("player", getTarget(condition.target)) - return compare(threatpct, condition[1], condition[2]) - end, - threat = function(condition) - local isTanking, status, threatpct = UnitDetailedThreatSituation("player", getTarget(condition.target)) - return threatpct - end, - TimeInCombat = function(condition) - if not Ovale.combatStartTime then - return nil - elseif condition[1] == "more" then - return Ovale.combatStartTime + condition[2] - else - return 0, Ovale.combatStartTime + condition[2] - end - end, - timeInCombat = function(condition) - return Ovale.maintenant - Ovale.combatStartTime, Ovale.maintenant, 1 - end, - timeToDie = function(condition) - return 0, getTargetDead(getTarget(condition.target)), -1 - end, - timeWithHaste = function(condition) - return avecHate(condition[1], "spell"),0,0 - end, - TotemExpires = function(condition) - if type(condition[1]) ~= "number" then - condition[1] = totemType[condition[1]] - end - - local haveTotem, totemName, startTime, duration = GetTotemInfo(condition[1]) - if not startTime then - return 0 - end - if (condition.totem and Ovale:GetSpellInfoOrNil(condition.totem)~=totemName) then - return 0 - end - return addTime(startTime + duration, -(condition[2] or 0)) - end, - TotemPresent = function(condition) - if type(condition[1]) ~= "number" then - condition[1] = totemType[condition[1]] - end - - local haveTotem, totemName, startTime, duration = GetTotemInfo(condition[1]) - if not startTime then - return nil - end - if (condition.totem and Ovale:GetSpellInfoOrNil(condition.totem)~=totemName) then - return nil - end - return startTime, startTime + duration - end, - Tracking = function(condition) - local what = Ovale:GetSpellInfoOrNil(condition[1]) - local numTrackingTypes = GetNumTrackingTypes() - local present = false - for i=1,numTrackingTypes do - local name, texture, active = GetTrackingInfo(i) - if name == what then - present = (active == 1) - break - end - end - return testbool(present, condition[2]) - end, - WeaponEnchantExpires = function(condition) - local hasMainHandEnchant, mainHandExpiration, mainHandCharges, hasOffHandEnchant, offHandExpiration, offHandCharges = GetWeaponEnchantInfo() - if (condition[1] == "mainhand") then - if (not hasMainHandEnchant) then - return 0 - end - mainHandExpiration = mainHandExpiration/1000 - if ((condition[2] or 0) >= mainHandExpiration) then - return 0 - else - return Ovale.maintenant + mainHandExpiration - condition[2] - end - else - if (not hasOffHandEnchant) then - return 0 - end - offHandExpiration = offHandExpiration/1000 - if ((condition[2] or 0) >= offHandExpiration) then - return 0 - else - return Ovale.maintenant + offHandExpiration - condition[2] - end - end - end, -} - -Ovale.conditions.health = Ovale.conditions.life -Ovale.conditions.Health = Ovale.conditions.Life -Ovale.conditions.healthPercent = Ovale.conditions.lifePercent -Ovale.conditions.HealthPercent = Ovale.conditions.LifePercent -Ovale.conditions.HealthMissing = Ovale.conditions.LifeMissing diff --git a/Locale-esES.lua b/Locale-esES.lua new file mode 100644 index 0000000..030c053 --- /dev/null +++ b/Locale-esES.lua @@ -0,0 +1,4 @@ +local L = LibStub:GetLibrary("AceLocale-3.0"):NewLocale("Ovale", "esES", false) +if not L then return end + +--@localization(locale="esES", format="lua_additive_table", same-key-is-true=true, handle-subnamespaces="concat")@ \ No newline at end of file diff --git a/Ovale.lua b/Ovale.lua index 4812bb2..5549ffc 100644 --- a/Ovale.lua +++ b/Ovale.lua @@ -1,26 +1,19 @@ -local L = LibStub("AceLocale-3.0"):GetLocale("Ovale") Ovale = LibStub("AceAddon-3.0"):NewAddon("Ovale", "AceEvent-3.0", "AceConsole-3.0") + +-- +local L = LibStub("AceLocale-3.0"):GetLocale("Ovale") local Recount = Recount local Skada = Skada +-- +-- --Default scripts (see "defaut" directory) Ovale.defaut = {} --The table of check boxes definition Ovale.casesACocher = {} ---key: spell name / value: action icon id -Ovale.actionSort = {} ---key: talentId / value: points in this talent -Ovale.pointsTalent = {} ---key: talentId / value: talent name (not used) -Ovale.talentIdToName = {} -Ovale.spellList = {} ---key: talent name / value: talent id -Ovale.talentNameToId = {} --allows to do some initialization the first time the addon is enabled Ovale.firstInit = false ---allows to fill the player talent tables on first use -Ovale.listeTalentsRemplie = false --the frame with the icons Ovale.frame = nil --check boxes GUI items @@ -31,235 +24,21 @@ Ovale.dropDowns = {} Ovale.masterNodes = nil --set it if there was a bug, traces will be enabled on next frame Ovale.bug = false +Ovale.traced = false --trace next script function calls Ovale.trace=false --in combat? Ovale.enCombat = false ---current computed spell haste. "2" means 2 times faster -Ovale.spellHaste = 1 ---current computed melee haste TODO: why I don't use character sheet value anyway? -Ovale.meleeHaste = 1 ---current auras -Ovale.aura = { player = {}, target = {}} ---allow to track the current target -Ovale.targetGUID = nil ---spell info from the current script (by spellId) -Ovale.spellInfo = {} ---track when a buff was applied (used for the old eclipse mechanism, maybe this could be removed?) -Ovale.buff = {} ---player class -Ovale.className = nil ---the state in the current frame ---TODO: really, the simulator should be in its own class -Ovale.state = {rune={}, cd = {}, counter={}} ---spells that count for scoring -Ovale.scoreSpell = {} ---tracks debuffs on the units that are not the current target -Ovale.otherAura = {} --score in current combat Ovale.score = 0 --maximal theoric score in current combat Ovale.maxScore = 0 ---increased at each frame, allows to know if the aura was updated this frame ---TODO: aura should be tracked using combat log events or something like that ---and it should be in its own class -Ovale.serial = 0 ---spell counter (see Counter function) -Ovale.counter = {} ---the spells that the player has casted but that did not reach their target ---the result is computed by the simulator, allowing to ignore lag or missile travel time -Ovale.lastSpell = {} ---the damage of the last spell or dot (by id) -Ovale.spellDamage = {} ---the attack power of the last spell -Ovale.lastSpellAP = {} -Ovale.lastSpellSP = {} -Ovale.lastSpellDM = {} -Ovale.damageMultiplier = 1 -Ovale.numberOfEnemies = nil -Ovale.enemies = {} -Ovale.refreshNeeded = false +Ovale.refreshNeeded = {} Ovale.compileOnItems = false - --- List haste buff that does not appear in the character sheet and that are not raid wide buffs -Ovale.selfHasteBuff = -{ - [53657] = 9, -- Judgement of the pure - [49016] = 20 -- Unholy Frenzy -} - --- List temporary damage multiplier -Ovale.selfDamageBuff = -{ - [5217] = 1.15, -- Tiger's fury - [57933] = 1.15 -- Tricks of the trade -} - -Ovale.buffSpellList = -{ - fear = - { - 5782, -- Fear - 5484, -- Howl of terror - 5246, -- Intimidating Shout - 8122, -- Psychic scream - }, - root = - { - 23694, -- Improved Hamstring - 339, -- Entangling Roots - 122, -- Frost Nova - 47168, -- Improved Wing Clip - }, - incapacitate = - { - 6770, -- Sap - 12540, -- Gouge - 20066, -- Repentance - }, - stun = - { - 5211, -- Bash - 44415, -- Blackout - 6409, -- Cheap Shot - 22427, -- Concussion Blow - 853, -- Hammer of Justice - 408, -- Kidney Shot - 46968, -- Shockwave - }, - strengthagility= - { - 6673, -- Battle Shout - 8076, -- Strength of Earth - 57330, -- Horn of Winter - 93435 --Roar of Courage (Cat, Spirit Beast) - }, - stamina = - { - 21562, -- Fortitude TODO: vérifier - 469, -- Commanding Shout - 6307, -- Blood Pact - 90364 -- Qiraji Fortitude - }, - lowerarmor= - { - 58567, -- Sunder Armor (x3) - 8647, -- Expose Armor - 91565, -- Faerie Fire (x3) - 35387, --Corrosive Spit (x3 Serpent) - 50498 --Tear Armor (x3 Raptor) - }, - magicaldamagetaken= - { - 65142, -- Ebon Plague - 60433, -- Earth and Moon - 93068, -- Master Poisoner - 1490, -- Curse of the Elements - 85547, -- Jinx 1 - 86105, -- Jinx 2 - 34889, --Fire Breath (Dragonhawk) - 24844 --Lightning Breath (Wind serpent) - }, - magicalcrittaken= - { - 17800, -- Shadow and Flame - 22959 -- Critical Mass - }, - physicaldamagetaken= - { - 30069, -- Blood Frenzy (rank 1) - 30070, -- Blood Frenzy (rank 2) - 81327, -- Brittle Bones (rank 1) - 81328, -- Brittle Bones (rank 2) - 58684, -- Savage Combat (rank 1) - 58683, -- Savage Combat (rank 2) - 55749, -- Acid Spit (Worm) - 50518, -- Ravage (Ravager) - }, - lowerphysicaldamage= - { - 99, -- Demoralizing Roar - 702, -- Curse of Weakness - 1160, -- Demoralizing Shout - 26017, -- Vindication - 81130, -- Scarlet Fever - 50256, --Demoralizing Roar (Bear) - 24423, -- Demoralizing Screech (Carrion Bird) - }, - meleeslow= - { - 55095, --Icy Touch - 58179, --Infected Wounds rank 1 - 58180, --Infected Wounds rank 2 - 68055, --Judgments of the just - 6343, --Thunderclap - 8042, --Earth Shock - 54404, --Dust Cloud (Tallstrider) - 90315, -- Tailspin (Fox) - }, - castslow = - { - 1714, --Curse of Tongues - 58604, --Lava Breath (Core Hound) - 50274, --Spore Cloud (Sporebat) - 5761, --Mind-numbing Poison - 73975, --Necrotic Strike - 31589 --Slow - }, - bleed= - { - 33876, --Mangle cat - 33878, --Mangle bear - 46856, -- Trauma rank 1 - 46857, -- Trauma rank 2 - 16511, --Hemorrhage - 50271, --Tendon Rip (Hyena) - 35290 --Gore (Boar) - }, - heroism= - { - 2825, --Bloodlust - 32182, --Heroism - 80353, --Time warp - 90355 -- Ancient Hysteria (Core Hound) - }, - meleehaste = - { - 8515, -- Windfury - 55610, -- Improved Icy Talons - 53290 -- Hunting Party - }, - spellhaste = - { - 24907, -- Moonkin aura - 2895, -- Wrath of Air Totem - 49868 -- Mind Quickening - }, - enrage = - { - 49016, -- Unholy Frenzy - 18499, -- Berserker Rage - 12292, -- Death Wish - 12880, -- Enrage (rank 1) - 14201, -- Enrage (rank 2) - 14202, -- Enrage (rank 3) - 5229, -- Enrage (Bear) - 52610, -- Savage Roar (Cat) - 76691, -- Vengeance (All Tank Specs) - }, - criticalstrike = - { - 51740, -- Elemental Oath - 51698, -- Honor Among Thieves (rank 1) - 51700, -- Honor Among Thieves (rank 2) - 51701, -- Honor Among Thieves (rank 3) - 17007, -- Leader of the Pack - 29801, -- Rampage - 24604, -- Furious Howl (Wolf) - 90309, -- Terrifying Roar (Devilsaur) - } -} - +Ovale.combatStartTime = nil +Ovale.needCompile = false +Ovale.listes = {} +-- --Key bindings BINDING_HEADER_OVALE = "Ovale" @@ -269,407 +48,9 @@ BINDING_NAME_OVALE_CHECKBOX2 = L["Inverser la boîte à cocher "].."(3)" BINDING_NAME_OVALE_CHECKBOX3 = L["Inverser la boîte à cocher "].."(4)" BINDING_NAME_OVALE_CHECKBOX4 = L["Inverser la boîte à cocher "].."(5)" ---GUI option -local options = -{ - type = "group", - args = - { - apparence = - { - name = L["Apparence"], - type = "group", - args = - { - combatUniquement = - { - order = 1, - type = "toggle", - name = L["En combat uniquement"], - get = function(info) - return Ovale.db.profile.apparence.enCombat - end, - set = function(info, v) - Ovale.db.profile.apparence.enCombat = v - Ovale:UpdateVisibility() - end, - width = "full" - }, - targetOnly = - { - order = 1.5, - type = "toggle", - name = L["Si cible uniquement"], - get = function(info) - return Ovale.db.profile.apparence.avecCible - end, - set = function(info, v) - Ovale.db.profile.apparence.avecCible = v - Ovale:UpdateVisibility() - end, - width = "full" - }, - iconScale = - { - order = 2, - type = "range", - name = L["Taille des icônes"], - desc = L["La taille des icônes"], - min = 0.1, max = 16, step = 0.1, - get = function(info) return Ovale.db.profile.apparence.iconScale end, - set = function(info,value) Ovale.db.profile.apparence.iconScale = value; Ovale:UpdateFrame() end - }, - secondIconScale = - { - order = 2.5, - type = "range", - name = L["Taille du second icône"], - min = 0.2, max = 1, step = 0.1, - get = function(info) return Ovale.db.profile.apparence.secondIconScale end, - set = function(info,value) Ovale.db.profile.apparence.secondIconScale = value; Ovale:UpdateFrame() end - }, - fontScale = - { - order = 3, - type = "range", - name = L["Taille des polices"], - desc = L["La taille des polices"], - min = 0.1, max = 2, step = 0.1, - get = function(info) return Ovale.db.profile.apparence.fontScale end, - set = function(info,value) Ovale.db.profile.apparence.fontScale = value; Ovale:UpdateFrame() end - }, - smallIconScale = - { - order = 4, - type = "range", - name = L["Taille des petites icônes"], - desc = L["La taille des petites icônes"], - min = 0.1, max = 16, step = 0.1, - get = function(info) return Ovale.db.profile.apparence.smallIconScale end, - set = function(info,value) Ovale.db.profile.apparence.smallIconScale = value; Ovale:UpdateFrame() end - }, - margin = - { - order = 5.5, - type = "range", - name = L["Marge entre deux icônes"], - min = -16, max = 64, step = 1, - get = function(info) return Ovale.db.profile.apparence.margin end, - set = function(info,value) Ovale.db.profile.apparence.margin = value; Ovale:UpdateFrame() end - }, - iconShiftX = - { - order = 5.6, - type = "range", - name = L["Décalage horizontal des options"], - min = -256, max = 256, step = 1, - get = function(info) return Ovale.db.profile.apparence.iconShiftX end, - set = function(info,value) Ovale.db.profile.apparence.iconShiftX = value; Ovale:UpdateFrame() end - }, - iconShiftY = - { - order = 5.7, - type = "range", - name = L["Décalage vertical des options"], - min = -256, max = 256, step = 1, - get = function(info) return Ovale.db.profile.apparence.iconShiftY end, - set = function(info,value) Ovale.db.profile.apparence.iconShiftY = value; Ovale:UpdateFrame() end - }, - raccourcis = - { - order = 6, - type = "toggle", - name = L["Raccourcis clavier"], - desc = L["Afficher les raccourcis clavier dans le coin inférieur gauche des icônes"], - get = function(info) return Ovale.db.profile.apparence.raccourcis end, - set = function(info, value) Ovale.db.profile.apparence.raccourcis = value end - }, - numeric = - { - order = 7, - type = "toggle", - name = L["Affichage numérique"], - desc = L["Affiche le temps de recharge sous forme numérique"], - get = function(info) return Ovale.db.profile.apparence.numeric end, - set = function(info, value) Ovale.db.profile.apparence.numeric = value end - }, - verrouille = - { - order = 8, - type = "toggle", - name = L["Verrouiller position"], - get = function(info) return Ovale.db.profile.apparence.verrouille end, - set = function(info, value) Ovale.db.profile.apparence.verrouille = value end - }, - vertical = - { - order = 9, - type = "toggle", - name = L["Vertical"], - get = function(info) return Ovale.db.profile.apparence.vertical end, - set = function(info, value) Ovale.db.profile.apparence.vertical = value; Ovale:UpdateFrame() end - }, - alpha = - { - order = 9.5, - type = "range", - name = L["Opacité des icônes"], - min = 0, max = 100, step = 5, - get = function(info) return Ovale.db.profile.apparence.alpha * 100 end, - set = function(info, value) Ovale.db.profile.apparence.alpha = value/100; Ovale.frame.frame:SetAlpha(value/100) end - }, - optionsAlpha = - { - order = 9.5, - type = "range", - name = L["Opacité des options"], - min = 0, max = 100, step = 5, - get = function(info) return Ovale.db.profile.apparence.optionsAlpha * 100 end, - set = function(info, value) Ovale.db.profile.apparence.optionsAlpha = value/100; Ovale.frame.content:SetAlpha(value/100) end - }, - predictif = - { - order = 10, - type = "toggle", - name = L["Prédictif"], - desc = L["Affiche les deux prochains sorts et pas uniquement le suivant"], - get = function(info) return Ovale.db.profile.apparence.predictif end, - set = function(info, value) Ovale.db.profile.apparence.predictif = value; Ovale:UpdateFrame() end - }, - moving = - { - order = 11, - type = "toggle", - name = L["Défilement"], - desc = L["Les icônes se déplacent"], - get = function(info) return Ovale.db.profile.apparence.moving end, - set = function(info, value) Ovale.db.profile.apparence.moving = value; Ovale:UpdateFrame() end - }, - hideEmpty = - { - order = 12, - type = "toggle", - name = L["Cacher bouton vide"], - get = function(info) return Ovale.db.profile.apparence.hideEmpty end, - set = function(info, value) Ovale.db.profile.apparence.hideEmpty = value; Ovale:UpdateFrame() end - }, - targetHostileOnly = - { - order = 13, - type = "toggle", - name = L["Cacher si cible amicale ou morte"], - get = function(info) return Ovale.db.profile.apparence.targetHostileOnly end, - set = function(info, value) Ovale.db.profile.apparence.targetHostileOnly = value; Ovale:UpdateFrame() end - }, - highlightIcon = - { - order = 14, - type = "toggle", - name = L["Illuminer l'icône"], - desc = L["Illuminer l'icône quand la technique doit être spammée"], - get = function(info) return Ovale.db.profile.apparence.highlightIcon end, - set = function(info, value) Ovale.db.profile.apparence.highlightIcon = value; Ovale:UpdateFrame() end - }, - clickThru = - { - order = 15, - type = "toggle", - name = L["Ignorer les clics souris"], - get = function(info) return Ovale.db.profile.apparence.clickThru end, - set = function(info, value) Ovale.db.profile.apparence.clickThru = value; Ovale:UpdateFrame() end - }, - latencyCorrection = - { - order = 16, - type = "toggle", - name = L["Correction de la latence"], - get = function(info) return Ovale.db.profile.apparence.latencyCorrection end, - set = function(info, value) Ovale.db.profile.apparence.latencyCorrection = value end - }, - hideVehicule = - { - order = 17, - type = "toggle", - name = L["Cacher dans les véhicules"], - get = function(info) return Ovale.db.profile.apparence.hideVehicule end, - set = function(info, value) Ovale.db.profile.apparence.hideVehicule = value end - }, - flashIcon = - { - order = 18, - type = "toggle", - name = L["Illuminer l'icône quand le temps de recharge est écoulé"], - get = function(info) return Ovale.db.profile.apparence.flashIcon end, - set = function(info, value) Ovale.db.profile.apparence.flashIcon = value; Ovale:UpdateFrame() end - }, - targetText = - { - order = 19, - type = "input", - name = L["Caractère de portée"], - desc = L["Ce caractère est affiché dans un coin de l'icône pour indiquer si la cible est à portée"], - get = function(info) return Ovale.db.profile.apparence.targetText end, - set = function(info, value) Ovale.db.profile.apparence.targetText = value; Ovale:UpdateFrame() end - } - } - }, - code = - { - name = L["Code"], - type = "group", - args = - { - code = - { - order = 1, - type = "input", - multiline = 15, - name = L["Code"], - get = function(info) - return string.gsub(Ovale.db.profile.code, "\t", " ") - end, - set = function(info,v) - Ovale.db.profile.code = v - Ovale.needCompile = true - end, - width = "full" - } - } - }, - actions = - { - name = "Actions", - type = "group", - args = - { - show = - { - order = -1, - type = "execute", - name = L["Afficher la fenêtre"], - guiHidden = true, - func = function() - Ovale.db.profile.display = true - Ovale:UpdateVisibility() - end - }, - hide = - { - order = -2, - type = "execute", - name = L["Cacher la fenêtre"], - guiHidden = true, - func = function() - Ovale.db.profile.display = false - Ovale.frame:Hide() - end - }, - config = - { - name = "Configuration", - type = "execute", - func = function() Ovale:AfficherConfig() end - }, - code = - { - name = "Code", - type = "execute", - func = function() Ovale:AfficherCode() end - }, - debug = - { - order = -3, - name = "Debug", - type = "execute", - func = function() - for i=1,10 do Ovale:Print(i.."="..UnitPower("player", i)) end - Ovale:Print(Ovale.state.eclipse) - end - }, - talent = - { - order = -4, - name = "List talent id", - type = "execute", - func = function() - for k,v in pairs(Ovale.talentNameToId) do - Ovale:Print(k.."="..v) - end - end - }, - targetbuff = - { - order = -5, - name = "List target buff and debuff spell id", - type = "execute", - func = function() - Ovale:DebugListAura("target", "HELPFUL") - Ovale:DebugListAura("target", "HARMFUL") - end - }, - buff = - { - order = -6, - name = "List player buff and debuff spell id", - type = "execute", - func = function() - Ovale:DebugListAura("player", "HELPFUL") - Ovale:DebugListAura("player", "HARMFUL") - end - }, - glyph = - { - order = -7, - name = "List player glyphs", - type = "execute", - func = function() - for i=1,GetNumGlyphs() do - local name, level, enabled, texture, spellId = GetGlyphInfo(i) - if spellId then Ovale:Print(name..": "..spellId.." ("..tostring(enabled)..")") end - end - end - }, - spell = - { - order = -8, - name = "List player spells", - type = "execute", - func = function() - local book=BOOKTYPE_SPELL - while true do - local i=1 - while true do - local skillType, spellId = GetSpellBookItemInfo(i, book) - if not spellId then - break - end - local spellName = GetSpellBookItemName(i, book) - Ovale:Print(spellName..": "..spellId) - i = i + 1 - end - if book == BOOKTYPE_SPELL then - book = BOOKTYPE_PET - else - break - end - end - end - } - } - } - } -} - -local function nilstring(text) - if text == nil then - return "nil" - else - return text - end -end - +-- function Ovale:Debug() - self:Print(self:DebugNode(self.masterNodes[1])) + self:Print(OvaleCompile:DebugNode(self.masterNodes[1])) end function Ovale:DebugListAura(target, filter) @@ -684,94 +65,28 @@ function Ovale:DebugListAura(target, filter) end end -function Ovale:OnInitialize() - self.AceConfig = LibStub("AceConfig-3.0"); - self.AceConfigDialog = LibStub("AceConfigDialog-3.0"); -end - -function Ovale:GetOtherAura(spellId) - if not self.otherAura[spellId] then - self.otherAura[spellId] = {} - end - return self.otherAura[spellId] -end - -function Ovale:WithHaste(temps, hate) - if not temps then - temps = 0 - end - if (not hate) then - return temps - elseif (hate == "spell") then - return temps/self.spellHaste - elseif (hate == "melee") then - return temps/self.meleeHaste - else - return temps - end -end - function Ovale:CompileAll() - if self.db.profile.code then - self.masterNodes = self:Compile(self.db.profile.code) - self.refreshNeeded = true + if OvaleOptions:GetProfile().code then + self.masterNodes = OvaleCompile:Compile(OvaleOptions:GetProfile().code) + self.refreshNeeded.player = true self:UpdateFrame() self.needCompile = false end end -function Ovale:HandleProfileChanges() - if self.firstInit then - if (self.db.profile.code) then - self.needCompile = true - end - end -end function Ovale:FirstInit() - self:RemplirActionIndexes() - self:RemplirListeTalents() - self:FillSpellList() - - local playerClass, englishClass = UnitClass("player") - self.className = englishClass - if self.className == "DEATHKNIGHT" then - for i=1,6 do - self.state.rune[i] = {} - end - end - self.playerGuid = UnitGUID("player") - - self:ChargerDefaut() - - self.frame = LibStub("AceGUI-3.0"):Create("OvaleFrame") - - self.frame:SetPoint("TOPLEFT",UIParent,"BOTTOMLEFT",self.db.profile.left,self.db.profile.top) - self.firstInit = true - - - options.args.profile = LibStub("AceDBOptions-3.0"):GetOptionsTable(self.db) - self.AceConfig:RegisterOptionsTable("Ovale", options.args.code) - self.AceConfig:RegisterOptionsTable("Ovale Actions", options.args.actions, "Ovale") - self.AceConfig:RegisterOptionsTable("Ovale Profile", options.args.profile) - self.AceConfig:RegisterOptionsTable("Ovale Apparence", options.args.apparence) - self.AceConfigDialog:AddToBlizOptions("Ovale", "Ovale") - self.AceConfigDialog:AddToBlizOptions("Ovale Profile", "Profile", "Ovale") - self.AceConfigDialog:AddToBlizOptions("Ovale Apparence", "Apparence", "Ovale") + OvaleData:FirstInit() - self.db.RegisterCallback( self, "OnNewProfile", "HandleProfileChanges" ) - self.db.RegisterCallback( self, "OnProfileReset", "HandleProfileChanges" ) - self.db.RegisterCallback( self, "OnProfileChanged", "HandleProfileChanges" ) - self.db.RegisterCallback( self, "OnProfileCopied", "HandleProfileChanges" ) + self.frame = LibStub("AceGUI-3.0"):Create("OvaleFrame") + local profile = OvaleOptions:GetProfile() - if self.db.profile.code then - self.needCompile = true - end + self.frame:SetPoint("TOPLEFT", UIParent, "BOTTOMLEFT", profile.left, profile.top) self:UpdateFrame() - if not Ovale.db.profile.display then + if not profile.display then self.frame:Hide() end end @@ -785,198 +100,32 @@ function Ovale:OnEnable() RegisterAddonMessagePrefix("Ovale") self:RegisterEvent("PLAYER_REGEN_ENABLED"); self:RegisterEvent("PLAYER_REGEN_DISABLED"); - self:RegisterEvent("SPELLS_CHANGED") - self:RegisterEvent("PLAYER_TALENT_UPDATE") - self:RegisterEvent("CHARACTER_POINTS_CHANGED") - self:RegisterEvent("ACTIONBAR_SLOT_CHANGED"); - self:RegisterEvent("UPDATE_BINDINGS"); - self:RegisterEvent("UNIT_AURA"); - self:RegisterEvent("ACTIONBAR_PAGE_CHANGED") - self:RegisterEvent("UNIT_SPELLCAST_INTERRUPTED") - self:RegisterEvent("UNIT_SPELLCAST_SUCCEEDED") - self:RegisterEvent("UNIT_SPELLCAST_START") - self:RegisterEvent("UNIT_SPELLCAST_CHANNEL_START") - self:RegisterEvent("UNIT_SPELLCAST_CHANNEL_STOP") self:RegisterEvent("PLAYER_TARGET_CHANGED") - self:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED") self:RegisterEvent("CHAT_MSG_ADDON") self:RegisterEvent("GLYPH_UPDATED") self:RegisterEvent("GLYPH_ADDED") self:RegisterEvent("UNIT_INVENTORY_CHANGED") - - self:UNIT_AURA("","player") - + self:UpdateVisibility() end function Ovale:OnDisable() -- Called when the addon is disabled - self:UnregisterEvent("UNIT_INVENTORY_CHANGED") - self:UnregisterEvent("ACTIONBAR_PAGE_CHANGED") - self:UnregisterEvent("PLAYER_REGEN_ENABLED") + self:UnregisterEvent("PLAYER_REGEN_ENABLED") self:UnregisterEvent("PLAYER_REGEN_DISABLED") - self:UnregisterEvent("PLAYER_TALENT_UPDATE") - self:UnregisterEvent("ACTIONBAR_SLOT_CHANGED") - self:UnregisterEvent("SPELLS_CHANGED") - self:UnregisterEvent("CHARACTER_POINTS_CHANGED") - self:UnregisterEvent("UPDATE_BINDINGS") - self:UnregisterEvent("UNIT_AURA") - self:UnregisterEvent("UNIT_SPELLCAST_CHANNEL_START") - self:UnregisterEvent("UNIT_SPELLCAST_CHANNEL_STOP") - self:UnregisterEvent("UNIT_SPELLCAST_SUCCEEDED") - self:UnregisterEvent("UNIT_SPELLCAST_START") self:UnregisterEvent("PLAYER_TARGET_CHANGED") - self:UnregisterEvent("COMBAT_LOG_EVENT_UNFILTERED") self:UnregisterEvent("CHAT_MSG_ADDON") self:UnregisterEvent("GLYPH_UPDATED") - self:UnregisterEvent("UNIT_SPELLCAST_INTERRUPTED") + self:UnregisterEvent("GLYPH_ADDED") + self:UnregisterEvent("UNIT_INVENTORY_CHANGED") self.frame:Hide() end -function Ovale:ACTIONBAR_SLOT_CHANGED(event, slot, unknown) - if (slot == 0) then - self:RemplirActionIndexes() - elseif (slot) then - -- on reçoit aussi si c'est une macro avec mouseover à chaque fois que la souris passe sur une cible! - self:RemplirActionIndex(tonumber(slot)) - end -end - -function Ovale:ACTIONBAR_PAGE_CHANGED() - -- self:RemplirActionIndexes() -end - -function Ovale:CHARACTER_POINTS_CHANGED() - self:RemplirListeTalents() --- self:Print("CHARACTER_POINTS_CHANGED") -end - -function Ovale:PLAYER_TALENT_UPDATE() - self:RemplirListeTalents() --- self:Print("PLAYER_TALENT_UPDATE") -end - ---The user learnt a new spell -function Ovale:SPELLS_CHANGED() - -- self:RemplirActionIndexes() - -- self:RemplirListeTalents() - self:FillSpellList() - self.needCompile = true -end - function Ovale:UNIT_INVENTORY_CHANGED() if self.compileOnItems then self.needCompile = true else - self.refreshNeeded = true - end -end - ---Called when the user changed his key bindings -function Ovale:UPDATE_BINDINGS() - self:RemplirActionIndexes() -end - ---Called for each combat log event -function Ovale:COMBAT_LOG_EVENT_UNFILTERED(event, ...) - local time, event, hideCaster, sourceGUID, sourceName, sourceFlags, sourceRaidFlags, destGUID, destName, destFlags, destRaidFlags = select(1, ...) - - if sourceGUID == self.playerGuid then - -- self:Print("event="..event.." source="..nilstring(sourceName).." destName="..nilstring(destName).." " ..GetTime()) - - if string.find(event, "SPELL_PERIODIC_DAMAGE")==1 or string.find(event, "SPELL_DAMAGE")==1 then - local spellId, spellName, spellSchool, amount = select(12, ...) - self.spellDamage[spellId] = amount - end - - --Called when a missile reached or missed its target - --Update lastSpell accordingly - --Do not use SPELL_CAST_SUCCESS because it is sent when the missile has not reached the target - - if - string.find(event, "SPELL_AURA_APPLIED")==1 - or string.find(event, "SPELL_AURA_REFRESH")==1 - or string.find(event, "SPELL_DAMAGE")==1 - or string.find(event, "SPELL_MISSED") == 1 - or string.find(event, "SPELL_CAST_SUCCESS") == 1 - or string.find(event, "SPELL_CAST_FAILED") == 1 then - local spellId, spellName = select(12, ...) - for i,v in ipairs(self.lastSpell) do - if (v.spellId == spellId or v.auraSpellId == spellId) and v.allowRemove then - if not v.channeled and (v.removeOnSuccess or - string.find(event, "SPELL_CAST_SUCCESS") ~= 1) then - table.remove(self.lastSpell, i) - self.refreshNeeded = true - --self:Print("LOG_EVENT on supprime "..spellId.." a "..GetTime()) - end - --self:Print(UnitDebuff("target", "Etreinte de l'ombre")) - break - end - end - end - if self.otherAurasEnabled then - --Track debuffs on units that are not the current target - if string.find(event, "SPELL_AURA_") == 1 then - local spellId, spellName, spellSchool, auraType = select(12, ...) - -- auraType == "DEBUFF" and - if self.spellInfo[spellId] and self.spellInfo[spellId].duration then - local otherDebuff = self:GetOtherAura(spellId) - if event == "SPELL_AURA_APPLIED" or event == "SPELL_AURA_REFRESH" then - otherDebuff[destGUID] = Ovale.maintenant + self:WithHaste(self.spellInfo[spellId].duration, self.spellInfo[spellId].durationhaste) - self.refreshNeeded = true - -- self:Print("ajout de "..spellName.." à "..destGUID) - elseif event == "SPELL_AURA_REMOVED" then - otherDebuff[destGUID] = nil - self.refreshNeeded = true - -- self:Print("suppression de "..spellName.." de "..destGUID) - end - end - end - end - --if string.find(event, "SWING")==1 then - -- self:Print(select(1, ...)) - --end - end - - if self.numberOfEnemies then - if event == "UNIT_DIED" then - for k,v in pairs(self.enemies) do - if k==destGUID then - self.enemies[v] = nil - self.numberOfEnemies = self.numberOfEnemies - 1 - self.refreshNeeded = true - --self:Print("enemy die") - end - end - elseif sourceFlags and not self.enemies[sourceGUID] and bit.band(sourceFlags, COMBATLOG_OBJECT_REACTION_HOSTILE)>0 - and bit.band(sourceFlags, COMBATLOG_OBJECT_AFFILIATION_OUTSIDER) > 0 and - destFlags and bit.band(destFlags, COMBATLOG_OBJECT_AFFILIATION_OUTSIDER) == 0 then - self.enemies[sourceGUID] = true - --self:Print("new ennemy source=".. sourceName) - self.numberOfEnemies = self.numberOfEnemies + 1 - self.refreshNeeded = true - elseif destGUID and not self.enemies[destGUID] and bit.band(destFlags, COMBATLOG_OBJECT_REACTION_HOSTILE)>0 - and bit.band(destFlags, COMBATLOG_OBJECT_AFFILIATION_OUTSIDER) > 0 and - sourceFlags and bit.band(sourceFlags, COMBATLOG_OBJECT_AFFILIATION_OUTSIDER) == 0 then - self.enemies[destGUID] = true - --self:Print("new ennemy dest=".. destName) - self.numberOfEnemies = self.numberOfEnemies + 1 - self.refreshNeeded = true - end - end - - if self.otherAurasEnabled then - if event == "UNIT_DIED" then - --Remove any dead unit from otherAura - for k,v in pairs(self.otherAura) do - for j,w in pairs(v) do - if j==destGUID then - v[j] = nil - self.refreshNeeded = true - end - end - end - end + self.refreshNeeded.player = true end end @@ -984,84 +133,10 @@ end --Used to update the visibility e.g. if the user chose --to hide Ovale if a friendly unit is targeted function Ovale:PLAYER_TARGET_CHANGED() - self.refreshNeeded = true + self.refreshNeeded.target = true self:UpdateVisibility() end ---Called when a new aura is added to an unit ---At this time it is not used to keep the aura list (may be used in the future for optimization) ---It is only used to update haste -function Ovale:UNIT_AURA(event, unit) - if unit == "player" or unit == "pet" then - local hateBase = GetCombatRatingBonus(18) - local hateCommune=0; - local hateSorts = 0; - local hateCaC = 0; - local hateHero = 0 - local hateClasse = 0 - local damageMultiplier = 1 - local i=1; - - if not self.buff[unit] then - self.buff[unit] = {} - end - - local buff = self.buff[unit] - - while true do - local name, rank, iconTexture, count, debuffType, duration, expirationTime, source, stealable, consolidate, spellId = UnitBuff(unit, i); - if (not name) then - break - end - if (not buff[spellId]) then - buff[spellId] = {} - end - buff[spellId].icon = iconTexture - buff[spellId].count = count - buff[spellId].duration = duration - buff[spellId].expirationTime = expirationTime - buff[spellId].source = source - if (not buff[spellId].present) then - buff[spellId].gain = Ovale.maintenant - end - buff[spellId].lastSeen = Ovale.maintenant - buff[spellId].present = true - - if unit == "player" then - if self.buffSpellList.spellhaste[spellId] then - hateSorts = 5 - elseif self.buffSpellList.meleehaste[spellId] then - hateCaC = 10 - elseif self.buffSpellList.heroism[spellId] then - hateHero = 30 - elseif self.selfHasteBuff[spellId] then - hateClasse = self.selfHasteBuff[spellId] - end - if self.selfDamageBuff[spellId] then - damageMultiplier = damageMultiplier * self.selfDamageBuff[spellId] - end - end - i = i + 1; - end - - for k,v in pairs(buff) do - if (v.lastSeen ~= Ovale.maintenant) then - v.present = false - end - end - - if unit == "player" then - self.spellHaste = 1 + (hateBase + hateCommune + hateSorts + hateHero + hateClasse)/100 - self.meleeHaste = 1 + (hateBase + hateCommune + hateCaC + hateHero + hateClasse)/100 - self.damageMultiplier = damageMultiplier - end - - self.refreshNeeded = true --- self.rangedHaste = hateBase + hateCommune + hateHero + hateClasse -- TODO ajouter le bidule du chasseur en spé bête --- print("spellHaste = "..self.spellHaste) - end -end - --Called when a glyph has been added --The script needs to be compiled function Ovale:GLYPH_ADDED(event) @@ -1074,184 +149,6 @@ function Ovale:GLYPH_UPDATED(event) self.needCompile = true end -function Ovale:GetNumberOfEnemies() - if not self.numberOfEnemies then - self.numberOfEnemies = 0 - end - return self.numberOfEnemies -end - -function Ovale:RemoveSpellFromList(spellId, lineId) - for i,v in ipairs(self.lastSpell) do - if v.lineId == lineId then - table.remove(self.lastSpell, i) - --self:Print("RemoveSpellFromList on supprime "..spellId) - break - end - end - self.refreshNeeded = true -end - ---Called if the player interrupted early his cast ---The spell is removed from the lastSpell table -function Ovale:UNIT_SPELLCAST_INTERRUPTED(event, unit, name, rank, lineId, spellId) - if unit == "player" then - --self:Print("UNIT_SPELLCAST_INTERRUPTED "..event.." name="..name.." lineId="..lineId.." spellId="..spellId.. " time="..GetTime()) - self:RemoveSpellFromList(spellId, lineId) - end -end - -function Ovale:UNIT_SPELLCAST_SUCCEEDED(event, unit, name, rank, lineId, spellId) - if unit == "player" then - --self:Print("UNIT_SPELLCAST_SUCCEEDED "..event.." name="..name.." lineId="..lineId.." spellId="..spellId.. " time="..GetTime()) - for i,v in ipairs(self.lastSpell) do - if v.lineId == lineId then - --Already added in UNIT_SPELLCAST_START - v.allowRemove = true - return - end - end - if not UnitChannelInfo("player") then - --A UNIT_SPELLCAST_SUCCEEDED is received when channeling a spell, with a different lineId! - local now = GetTime() - self:AddSpellToList(spellId, lineId, now, now, false, true) - end - end -end - -function Ovale:SendScoreToDamageMeter(name, guid, scored, scoreMax) - if Recount then - local source = Recount.db2.combatants[name] - if source then - Recount:AddAmount(source,"Ovale",scored) - Recount:AddAmount(source,"OvaleMax",scoreMax) - end - end - if Skada then - if not guid or not Skada.current or not Skada.total then return end - local player = Skada:get_player(Skada.current, guid, nil) - if not player then return end - if not player.ovale then player.ovale = 0 end - if not player.ovaleMax then player.ovaleMax = 0 end - player.ovale = player.ovale + scored - player.ovaleMax = player.ovaleMax + scoreMax - player = Skada:get_player(Skada.total, guid, nil) - player.ovale = player.ovale + scored - player.ovaleMax = player.ovaleMax + scoreMax - end -end - -function Ovale:AddSpellToList(spellId, lineId, startTime, endTime, channeled, allowRemove) - local newSpell = {} - newSpell.spellId = spellId - newSpell.lineId = lineId - newSpell.start = startTime - newSpell.stop = endTime - newSpell.channeled = channeled - newSpell.allowRemove = allowRemove - - self.lastSpellAP[spellId] = UnitAttackPower("player") - self.lastSpellSP[spellId] = GetSpellBonusDamage(2) - self.lastSpellDM[spellId] = self.damageMultiplier - self.lastSpell[#self.lastSpell+1] = newSpell - --self:Print("on ajoute "..spellId..": ".. newSpell.start.." to "..newSpell.stop.." ("..self.maintenant..")" ..#self.lastSpell) - - if self.spellInfo[spellId] then - local si = self.spellInfo[spellId] - - if si.aura then - for target, targetInfo in pairs(si.aura) do - for filter, filterInfo in pairs(targetInfo) do - for auraSpellId, spellData in pairs(filterInfo) do - if spellData and spellData ~= "refresh" and spellData > 0 then - newSpell.auraSpellId = auraSpellId - if target == "player" then - newSpell.removeOnSuccess = true - end - break - end - end - end - end - end - - --self:Print("spellInfo found") - if si and si.buffnocd and UnitBuff("player", GetSpellInfo(si.buffnocd)) then - newSpell.nocd = true - else - newSpell.nocd = false - end - --Increase or reset the counter that is used by the Counter function - if si.resetcounter then - self.counter[si.resetcounter] = 0 - --self:Print("reset counter "..si.resetcounter) - end - if si.inccounter then - local cname = si.inccounter - if not self.counter[cname] then - self.counter[cname] = 0 - end - self.counter[cname] = self.counter[cname] + 1 - --self:Print("inc counter "..cname.." to "..self.counter[cname]) - end - else - newSpell.removeOnSuccess = true - end - - if self.enCombat then - --self:Print(tostring(self.scoreSpell[spellId])) - if (not self.spellInfo[spellId] or not self.spellInfo[spellId].toggle) and self.scoreSpell[spellId] then - --Compute the player score - local scored = self.frame:GetScore(spellId) - --self:Print("Scored "..scored) - if scored~=nil then - self.score = self.score + scored - self.maxScore = self.maxScore + 1 - self:SendScoreToDamageMeter(UnitName("player"), UnitGUID("player"), scored, 1) - end - end - end - self.refreshNeeded = true -end - -function Ovale:GetCounterValue(id) - if self.state.counter[id] then - return self.state.counter[id] - elseif self.counter[id] then - return self.counter[id] - else - return 0 - end -end - -function Ovale:UNIT_SPELLCAST_CHANNEL_START(event, unit, name, rank, lineId, spellId) - if unit=="player" then - --self:Print("UNIT_SPELLCAST_CHANNEL_START "..event.." name="..name.." lineId="..lineId.." spellId="..spellId) - local _,_,_,_,startTime, endTime = UnitChannelInfo("player") - --self:Print("startTime = " ..startTime.." endTime = "..endTime) - self:AddSpellToList(spellId, lineId, startTime/1000, endTime/1000, true, false) - end -end - -function Ovale:UNIT_SPELLCAST_CHANNEL_STOP(event, unit, name, rank, lineId, spellId) - if unit == "player" then - --self:Print("UNIT_SPELLCAST_CHANNEL_STOP "..event.." name="..name.." lineId="..lineId.." spellId="..spellId) - self:RemoveSpellFromList(spellId, lineId) - end -end - ---Called when a spell started its cast -function Ovale:UNIT_SPELLCAST_START(event, unit, name, rank, lineId, spellId) - --self:Print("UNIT_SPELLCAST_START "..event.." name="..name.." lineId="..lineId.." spellId="..spellId) - if unit=="player" then - local _,_,_,_,startTime,endTime = UnitCastingInfo("player") - --local spell, rank, icon, cost, isFunnel, powerType, castTime, minRange, maxRange = GetSpellInfo(spellId) - --local startTime = GetTime() - --self:AddSpellToList(spellId, lineId, startTime, startTime + castTime/1000) - self:AddSpellToList(spellId, lineId, startTime/1000, endTime/1000, false, false) - end -end - function Ovale:CHAT_MSG_ADDON(event, prefix, msg, type, author) if prefix ~= "Ovale" then return end if type ~= "RAID" and type~= "PARTY" then return end @@ -1275,127 +172,29 @@ function Ovale:PLAYER_REGEN_DISABLED() self.enCombat = true self.score = 0 self.maxScore = 0 - self.combatStartTime = self.maintenant - if self.numberOfEnemies then - self.numberOfEnemies = 0 - self.enemies = {} - end + self.combatStartTime = OvaleState.maintenant self:UpdateVisibility() end -function Ovale:ChercherShortcut(id) --- ACTIONBUTTON1..12 => principale (1..12, 13..24, 73..108) --- MULTIACTIONBAR1BUTTON1..12 => bas gauche (61..72) --- MULTIACTIONBAR2BUTTON1..12 => bas droite (49..60) --- MULTIACTIONBAR3BUTTON1..12 => haut droit (25..36) --- MULTIACTIONBAR4BUTTON1..12 => haut gauche (37..48) - local name; - if (id<=24 or id>72) then - name = "ACTIONBUTTON"..(((id-1)%12)+1); - elseif (id<=36) then - name = "MULTIACTIONBAR3BUTTON"..(id-24); - elseif (id<=48) then - name = "MULTIACTIONBAR4BUTTON"..(id-36); - elseif (id<=60) then - name = "MULTIACTIONBAR2BUTTON"..(id-48); - else - name = "MULTIACTIONBAR1BUTTON"..(id-60); - end - local key = GetBindingKey(name); ---[[ if (not key) then - DEFAULT_CHAT_FRAME:AddMessage(id.."=>"..name.." introuvable") - else - DEFAULT_CHAT_FRAME:AddMessage(id.."=>"..name.."="..key) - end]] - return key; -end - -function Ovale:GetSpellInfoOrNil(spell) - if (spell) then - return GetSpellInfo(spell) - else - return nil - end -end - -function Ovale:RemplirActionIndex(i) - self.shortCut[i] = self:ChercherShortcut(i) - local actionText = GetActionText(i) - if actionText then - self.actionMacro[actionText] = i - else - local type, spellId = GetActionInfo(i); - if (type=="spell") then - self.actionSort[spellId] = i - elseif (type =="item") then - self.actionObjet[spellId] = i - end - end -end - -function Ovale:RemplirActionIndexes() - self.actionSort = {} - self.actionMacro = {} - self.actionObjet = {} - self.shortCut = {} - for i=1,120 do - self:RemplirActionIndex(i) - end -end - -function Ovale:FillSpellList() - self.spellList = {} - local book=BOOKTYPE_SPELL - while true do - local i=1 - while true do - local skillType, spellId = GetSpellBookItemInfo(i, book) - if not spellId then - break - end - if skillType~="FUTURESPELL" then - local spellName = GetSpellBookItemName(i, book) - self.spellList[spellId] = spellName - end - i = i + 1 - end - if book==BOOKTYPE_SPELL then - book = BOOKTYPE_PET - else - break - end - end -end - -function Ovale:RemplirListeTalents() - local numTabs = GetNumTalentTabs(); - for t=1, numTabs do - local numTalents = GetNumTalents(t); - for i=1, numTalents do - local nameTalent, icon, tier, column, currRank, maxRank = GetTalentInfo(t,i); - local link = GetTalentLink(t,i) - if link then - local a, b, talentId = string.find(link, "talent:(%d+)"); - talentId = tonumber(talentId) - self.talentIdToName[talentId] = nameTalent - self.talentNameToId[nameTalent] = talentId - self.pointsTalent[talentId] = currRank - self.listeTalentsRemplie = true - self.needCompile = true - end +function Ovale:SendScoreToDamageMeter(name, guid, scored, scoreMax) + if Recount then + local source = Recount.db2.combatants[name] + if source then + Recount:AddAmount(source,"Ovale",scored) + Recount:AddAmount(source,"OvaleMax",scoreMax) end end -end - -function Ovale:AddRune(time, type, value) - if value<0 then - for i=1,6 do - if (self.state.rune[i].type == type or self.state.rune[i].type==4)and self.state.rune[i].cd<=time then - self.state.rune[i].cd = time + 10 - end - end - else - + if Skada then + if not guid or not Skada.current or not Skada.total then return end + local player = Skada:get_player(Skada.current, guid, nil) + if not player then return end + if not player.ovale then player.ovale = 0 end + if not player.ovaleMax then player.ovaleMax = 0 end + player.ovale = player.ovale + scored + player.ovaleMax = player.ovaleMax + scoreMax + player = Skada:get_player(Skada.total, guid, nil) + player.ovale = player.ovale + scored + player.ovaleMax = player.ovaleMax + scoreMax end end @@ -1405,1066 +204,6 @@ function Ovale:Log(text) end end -function Ovale:GetAura(target, filter, spellId, forceduration) - if not self.aura[target] then - self.aura[target] = {} - end - if not self.aura[target][filter] then - self.aura[target][filter] = {} - end - if not self.aura[target][filter][spellId] then - self.aura[target][filter][spellId] = {} - end - local myAura = self.aura[target][filter][spellId] - if myAura.serial == Ovale.serial then - return myAura - end - - myAura.mine = false - myAura.start = nil - myAura.ending = nil - myAura.stacks = 0 - myAura.serial = Ovale.serial - - local i = 1 - - while (true) do - local name, rank, icon, count, debuffType, duration, expirationTime, unitCaster, isStealable, shouldConsolidate, thisSpellId = UnitAura(target, i, filter); - if not name then - break - end - if (unitCaster=="player" or not myAura.mine) and (spellId == thisSpellId or spellId == debuffType) then - myAura.mine = (unitCaster == "player") - myAura.start = expirationTime - duration - - if expirationTime>0 then - myAura.ending = expirationTime - else - myAura.ending = nil - end - if count and count>0 then - myAura.stacks = count - else - myAura.stacks = 1 - end - if myAura.mine then - break - end - end - i = i + 1; - end - return myAura -end - -function Ovale:GetCD(spellId) - if not spellId then - return nil - end - - if self.spellInfo[spellId] and self.spellInfo[spellId].cd then - local cdname - if self.spellInfo[spellId].sharedcd then - cdname = self.spellInfo[spellId].sharedcd - else - cdname = spellId - end - if not self.state.cd[cdname] then - self.state.cd[cdname] = {} - end - return self.state.cd[cdname] - else - return nil - end -end - -function Ovale:AddEclipse(endCast, spellId) - local newAura = self:GetAura("player", "HELPFUL", spellId) - newAura.start = endCast + 0.5 - newAura.stacks = 1 - newAura.ending = nil -end - --- Cast a spell in the simulator --- spellId : the spell id --- startCast : temps du cast --- endCast : fin du cast --- nextCast : temps auquel le prochain sort peut être lancé (>=endCast, avec le GCD) --- nocd : le sort ne déclenche pas son cooldown -function Ovale:AddSpellToStack(spellId, startCast, endCast, nextCast, nocd) - if not spellId then - return - end - - local newSpellInfo = self.spellInfo[spellId] - - --On enregistre les infos sur le sort en cours - self.attenteFinCast = nextCast - self.currentSpellId = spellId - self.startCast = startCast - self.endCast = endCast - --Temps actuel de la simulation : un peu après le dernier cast (ou maintenant si dans le passé) - if startCast>=self.maintenant then - self.currentTime = startCast+0.1 - else - self.currentTime = self.maintenant - end - - if Ovale.trace then - Ovale:Print("add spell "..spellId.." at "..startCast.." currentTime = "..self.currentTime.. " nextCast="..self.attenteFinCast .. " endCast="..endCast) - end - - --Effet du sort au moment du début du cast - --(donc si cast déjà commencé, on n'en tient pas compte) - if startCast >= self.maintenant then - if newSpellInfo then - if newSpellInfo.inccounter then - local id = newSpellInfo.inccounter - self.state.counter[id] = self:GetCounterValue(id) + 1 - end - - if newSpellInfo.resetcounter then - self.state.counter[newSpellInfo.resetcounter] = 0 - end - end - end - - --Effet du sort au moment où il est lancé - --(donc si il est déjà lancé, on n'en tient pas compte) - if endCast >= self.maintenant then - --Mana - local _, _, _, cost = GetSpellInfo(spellId) - if cost then - self.state.mana = self.state.mana - cost - end - - if newSpellInfo then - - if newSpellInfo.mana then - self.state.mana = self.state.mana - newSpellInfo.mana - end - - --Points de combo - if newSpellInfo.combo then - self.state.combo = self.state.combo + newSpellInfo.combo - if self.state.combo<0 then - self.state.combo = 0 - end - end - --Runes - if newSpellInfo.frost then - self:AddRune(startCast, 3, newSpellInfo.frost) - end - if newSpellInfo.death then - self:AddRune(startCast, 4, newSpellInfo.death) - end - if newSpellInfo.blood then - self:AddRune(startCast, 1, newSpellInfo.blood) - end - if newSpellInfo.unholy then - self:AddRune(startCast, 2, newSpellInfo.unholy) - end - if newSpellInfo.holy then - self.state.holy = self.state.holy + newSpellInfo.holy - if self.state.holy < 0 then - self.state.holy = 0 - elseif self.state.holy > 3 then - self.state.holy = 3 - end - end - if newSpellInfo.shard then - self.state.shard = self.state.shard + newSpellInfo.shard - if self.state.shard < 0 then - self.state.shard = 0 - elseif self.state.shard > 3 then - self.state.shard = 3 - end - end - end - end - - -- Effets du sort au moment où il atteint sa cible - if newSpellInfo then - -- Cooldown du sort - local cd = self:GetCD(spellId) - if cd then - cd.start = startCast - cd.duration = newSpellInfo.cd - --Pas de cooldown - if nocd then - cd.duration = 0 - end - --On vérifie si le buff "buffnocd" est présent, auquel cas le CD du sort n'est pas déclenché - if newSpellInfo.buffnocd and not nocd then - local buffAura = self:GetAura("player", "HELPFUL", newSpellInfo.buffnocd) - if self.traceAura then - if buffAura then - self:Print("buffAura stacks = "..buffAura.stacks.." start="..nilstring(buffAura.start).." ending = "..nilstring(buffAura.ending)) - self:Print("startCast = "..startCast) - else - self:Print("buffAura = nil") - end - self.traceAura = false - end - if buffAura and buffAura.stacks>0 and buffAura.start and buffAura.start<=startCast and (not buffAura.ending or buffAura.ending>startCast) then - cd.duration = 0 - end - end - if newSpellInfo.targetlifenocd and not nocd then - if UnitHealth("target")/UnitHealthMax("target")*100 100 then - self.state.eclipse = 100 - self:AddEclipse(endCast, 48517) - end - end - if newSpellInfo.starsurge then - local buffAura = self:GetAura("player", "HELPFUL", 48517) --Solar - if buffAura.stacks>0 then - self:Log("starsurge with solar buff = " .. (- newSpellInfo.starsurge)) - self.state.eclipse = self.state.eclipse - newSpellInfo.starsurge - else - buffAura = self:GetAura("player", "HELPFUL", 48518) --Lunar - if buffAura.stacks>0 then - self:Log("starsurge with lunar buff = " .. newSpellInfo.starsurge) - self.state.eclipse = self.state.eclipse + newSpellInfo.starsurge - elseif self.state.eclipse < 0 then - self:Log("starsurge with eclipse < 0 = " .. (- newSpellInfo.starsurge)) - self.state.eclipse = self.state.eclipse - newSpellInfo.starsurge - else - self:Log("starsurge with eclipse > 0 = " .. newSpellInfo.starsurge) - self.state.eclipse = self.state.eclipse + newSpellInfo.starsurge - end - end - if self.state.eclipse < -100 then - self.state.eclipse = -100 - self:AddEclipse(endCast, 48518) - elseif self.state.eclipse > 100 then - self.state.eclipse = 100 - self:AddEclipse(endCast, 48517) - end - end - - --Auras causés par le sort - if newSpellInfo.aura then - for target, targetInfo in pairs(newSpellInfo.aura) do - for filter, filterInfo in pairs(targetInfo) do - for auraSpellId, spellData in pairs(filterInfo) do - local newAura = self:GetAura(target, filter, auraSpellId) - newAura.mine = true - local duration = spellData - local stacks = duration - --Optionnellement, on va regarder la durée du buff - if auraSpellId and self.spellInfo[auraSpellId] and self.spellInfo[auraSpellId].duration then - duration = self.spellInfo[auraSpellId].duration - elseif stacks~="refresh" and stacks > 0 then - stacks = 1 - end - if stacks=="refresh" then - if newAura.ending then - newAura.ending = endCast + duration - end - elseif stacks<0 and newAura.ending then - --Buff are immediatly removed when the cast ended, do not need to do it again - if filter~="HELPFUL" or target~="player" or endCast>=Ovale.maintenant then - newAura.stacks = newAura.stacks + stacks - if Ovale.trace then - self:Print("removing one stack of "..auraSpellId.." because of ".. spellId.." to ".. newAura.stacks) - end - --Plus de stacks, on supprime l'aura - if newAura.stacks<=0 then - self:Log("Aura is completly removed") - newAura.stacks = 0 - newAura.ending = 0 - end - end - elseif newAura.ending and newAura.ending >= endCast then - newAura.ending = endCast + duration - newAura.stacks = newAura.stacks + stacks - else - newAura.start = endCast - newAura.ending = endCast + duration - newAura.stacks = stacks - end - if Ovale.trace then - if auraSpellId then - self:Print(spellId.." adding "..stacks.." aura "..auraSpellId.." to "..target.." "..filter.." "..newAura.start..","..newAura.ending) - else - self:Print("adding nil aura") - end - end - end - end - end - end - end -end - -function Ovale:InitAllActions() - self.maintenant = GetTime(); - self.gcd = self:GetGCD() -end - -function Ovale:InitCalculerMeilleureAction() - self.serial = self.serial + 1 - self.currentTime = Ovale.maintenant - self.currentSpellId = nil - self.attenteFinCast = Ovale.maintenant - self.state.combo = GetComboPoints("player") - self.state.mana = UnitPower("player") - self.state.shard = UnitPower("player", 7) - self.state.eclipse = UnitPower("player", 8) - self.state.holy = UnitPower("player", 9) - if self.className == "DEATHKNIGHT" then - for i=1,6 do - self.state.rune[i].type = GetRuneType(i) - local start, duration, runeReady = GetRuneCooldown(i) - if runeReady then - self.state.rune[i].cd = start - else - self.state.rune[i].cd = duration + start - if self.state.rune[i].cd<0 then - self.state.rune[i].cd = 0 - end - end - end - end - for k,v in pairs(self.state.cd) do - v.start = nil - v.duration = nil - v.enable = 0 - v.toggled = nil - end - - for k,v in pairs(self.state.counter) do - self.state.counter[k] = self.counter[k] - end - - for i,v in ipairs(self.lastSpell) do - if not self.spellInfo[v.spellId] or not self.spellInfo[v.spellId].toggle then - --[[local spell, rank, displayName, icon, startTime, endTime, isTradeSkill = UnitCastingInfo("player") - if spell and spell == v.name and startTime/1000 - v.start < 0.5 and v.stop~=endTime/1000 then - print("ancien = "..v.stop) - v.stop = endTime/1000 - print("changement de v.stop en "..v.stop.." "..v.start) - end]] - self:Log("self.maintenant = " ..self.maintenant.." spellId="..v.spellId.." v.stop="..v.stop) - if self.maintenant - v.stop < 5 then - self:AddSpellToStack(v.spellId, v.start, v.stop, v.stop, v.nocd) - else - --self:Print("Removing obsolete "..v.spellId) - table.remove(self.lastSpell, i) - end - end - end -end - -local function printTime(temps) - if (temps == nil) then - Ovale:Print("> nil") - else - Ovale:Print("> "..temps) - end -end - -function Ovale:GetGCD(spellId) - if spellId and self.spellInfo[spellId] then - if self.spellInfo[spellId].haste == "spell" then - local cd = self.spellInfo[spellId].gcd - if not cd then - cd = 1.5 - end - cd = cd / self.spellHaste - if (cd<1) then - cd = 1 - end - return cd - elseif self.spellInfo[spellId].gcd then - return self.spellInfo[spellId].gcd - end - end - - -- Default value - if self.className == "ROGUE" or (self.className == "DRUID" and GetShapeshiftForm(true) == 3) then - return 1.0 - elseif self.className == "MAGE" or self.className == "WARLOCK" or self.className == "PRIEST" or - (self.className == "DRUID" and GetShapeshiftForm(true) ~= 1) then - local cd = 1.5 / self.spellHaste - if (cd<1) then - cd = 1 - end - return cd - else - return 1.5 - end -end - ---Compute the spell Cooldown -function Ovale:GetComputedSpellCD(spellId) - local actionCooldownStart, actionCooldownDuration, actionEnable - local cd = self:GetCD(spellId) - if cd and cd.start then - actionCooldownStart = cd.start - actionCooldownDuration = cd.duration - actionEnable = cd.enable - else - actionCooldownStart, actionCooldownDuration, actionEnable = GetSpellCooldown(spellId) - -- Les chevaliers de la mort ont des infos fausses sur le CD quand ils n'ont plus les runes - -- On force à 1,5s ou 1s en présence impie - if self.className=="DEATHKNIGHT" and actionCooldownDuration==10 and - (not self.spellInfo[spellId] or self.spellInfo[spellId].cd~=10) then - local impie = GetSpellInfo(48265) - if impie and UnitBuff("player", impie) then - actionCooldownDuration=1 - else - actionCooldownDuration=1.5 - end - end - if self.spellInfo[spellId] and self.spellInfo[spellId].forcecd then - actionCooldownStart, actionCooldownDuration = GetSpellCooldown(self.spellInfo[spellId].forcecd) - end - end - return actionCooldownStart, actionCooldownDuration, actionEnable -end - -function Ovale:GetActionInfo(element) - if not element then - return nil - end - - local spellId = element.params[1] - local action - local actionTexture, actionInRange, actionCooldownStart, actionCooldownDuration, - actionUsable, actionShortcut, actionIsCurrent, actionEnable - - local target = element.params.target - if (not target) then - target = "target" - end - - if (element.func == "Spell" ) then - if not self.spellList[spellId] and not self.actionSort[spellId] then - self:Log("Spell "..spellId.." not learnt") - return nil - end - - --Get spell info - action = self.actionSort[spellId] - actionCooldownStart, actionCooldownDuration, actionEnable = self:GetComputedSpellCD(spellId) - - --if (not action or not GetActionTexture(action)) then - spellName = self.spellList[spellId] - if not spellName then - spellName = GetSpellInfo(spellId) - end - actionTexture = GetSpellTexture(spellId) - actionInRange = IsSpellInRange(spellName, target) - actionUsable = IsUsableSpell(spellId) - actionShortcut = nil - --end - elseif (element.func=="Macro") then - action = self.actionMacro[element.params[1]] - if action then - actionTexture = GetActionTexture(action) - actionInRange = IsActionInRange(action, target) - actionCooldownStart, actionCooldownDuration, actionEnable = GetActionCooldown(action) - actionUsable = IsUsableAction(action) - actionShortcut = self.shortCut[action] - actionIsCurrent = IsCurrentAction(action) - else - Ovale:Log("Unknown macro "..element.params[1]) - end - elseif (element.func=="Item") then - local itemId - if (type(element.params[1]) == "number") then - itemId = element.params[1] - else - local _,_,id = string.find(GetInventoryItemLink("player",GetInventorySlotInfo(element.params[1])) or "","item:(%d+):%d+:%d+:%d+") - if not id then - return nil - end - itemId = tonumber(id) - end - - if (Ovale.trace) then - self:Print("Item "..nilstring(itemId)) - end - - local spellName = GetItemSpell(itemId) - actionUsable = (spellName~=nil) - - action = self.actionObjet[itemId] - --if (not action or not GetActionTexture(action)) then - actionTexture = GetItemIcon(itemId) - actionInRange = IsItemInRange(itemId, target) - actionCooldownStart, actionCooldownDuration, actionEnable = GetItemCooldown(itemId) - actionShortcut = nil - actionIsCurrent = nil - --end - elseif element.func=="Texture" then - actionTexture = "Interface\\Icons\\"..element.params[1] - actionCooldownStart = Ovale.maintenant - actionCooldownDuration = 0 - actionEnable = 1 - actionUsable = true - end - - if action then - if actionUsable == nil then - actionUsable = IsUsableAction(action) - end - actionShortcut = self.shortCut[action] - actionIsCurrent = IsCurrentAction(action) - end - - local cd = self:GetCD(spellId) - if cd and cd.toggle then - actionIsCurrent = 1 - end - - return actionTexture, actionInRange, actionCooldownStart, actionCooldownDuration, - actionUsable, actionShortcut, actionIsCurrent, actionEnable, spellId, target, element.params.nored -end - -local function subTime(time1, duration) - if not time1 then - return nil - else - return time1 - duration - end -end - -local function addTime(time1, duration) - if not time1 then - return nil - else - return time1 + duration - end -end - -local function isBeforeEqual(time1, time2) - return time1 and (not time2 or time1<=time2) -end - -local function isBefore(time1, time2) - return time1 and (not time2 or time1=time2) -end - -local function isAfter(time1, time2) - return not time1 or (time2 and time1>time2) -end - -function Ovale:CalculerMeilleureAction(element) - if (self.bug and not self.trace) then - return nil - end - - if (not element) then - return nil - end - - --TODO: créer un objet par type au lieu de ce if else if tout moche - if (element.type=="function")then - if (element.func == "Spell" or element.func=="Macro" or element.func=="Item" or element.func=="Texture") then - local action - local actionTexture, actionInRange, actionCooldownStart, actionCooldownDuration, - actionUsable, actionShortcut, actionIsCurrent, actionEnable, spellId = self:GetActionInfo(element) - - if not actionTexture then - if (Ovale.trace) then - self:Print("Action "..element.params[1].." not found") - end - return nil - end - if element.params.usable==1 and not actionUsable then - if (Ovale.trace) then - self:Print("Action "..element.params[1].." not usable") - end - return nil - end - if spellId and self.spellInfo[spellId] and self.spellInfo[spellId].casttime then - element.castTime = self.spellInfo[spellId].casttime - elseif spellId then - local spell, rank, icon, cost, isFunnel, powerType, castTime = GetSpellInfo(spellId) - if castTime then - element.castTime = castTime/1000 - else - element.castTime = nil - end - else - element.castTime = 0 - end - --TODO: not useful anymore? - if (spellId and self.spellInfo[spellId] and self.spellInfo[spellId].toggle and actionIsCurrent) then - if (Ovale.trace) then - self:Print("Action "..element.params[1].." is current action") - end - return nil - end - if actionEnable and actionEnable>0 then - local restant - if (not actionCooldownDuration or actionCooldownStart==0) then - restant = self.currentTime - else - restant = actionCooldownDuration + actionCooldownStart - end - self:Log("restant = "..restant.." attenteFinCast="..nilstring(self.attenteFinCast)) - if restanttempsB then - diff = tempsA - tempsB - else - diff = tempsB - tempsA - end - Ovale:Log("diff returns "..diff) - return diff - elseif element.type == "fromuntil" then - self:Log("fromuntil") - local tempsA = Ovale:CalculerMeilleureAction(element.a) - if (tempsA==nil) then - if Ovale.trace then Ovale:Print(element.type.." return nil") end - return nil - end - local tempsB = Ovale:CalculerMeilleureAction(element.b) - if (tempsB==nil) then - if Ovale.trace then Ovale:Print(element.type.." return nil") end - return nil - end - Ovale:Log("fromuntil returns "..(tempsB - tempsA)) - return tempsB - tempsA - elseif element.type == "compare" then - self:Log("compare "..element.comparison) - local tempsA = Ovale:CalculerMeilleureAction(element.a) - local timeB = Ovale:CalculerMeilleureAction(element.time) - self:Log(nilstring(tempsA).." "..element.comparison.." "..nilstring(timeB)) - if element.comparison == "more" and (not tempsA or tempsA>timeB) then - if Ovale.trace then Ovale:Print(element.type.." return 0") end - return 0 - elseif element.comparison == "less" and tempsA and tempsA=timeB) then - if Ovale.trace then Ovale:Print(element.type.." return 0") end - return 0 - end - return nil - elseif element.type == "and" or element.type == "if" then - if (Ovale.trace) then - self:Print(element.type.." ["..element.nodeId.."]") - end - local startA, endA = Ovale:CalculerMeilleureAction(element.a) - if (startA==nil) then - if Ovale.trace then Ovale:Print(element.type.." return nil ["..element.nodeId.."]") end - return nil - end - if startA == endA then - if Ovale.trace then Ovale:Print(element.type.." return startA=endA ["..element.nodeId.."]") end - return nil - end - local startB, endB, prioriteB, elementB = Ovale:CalculerMeilleureAction(element.b) - if isAfter(startB, endA) or isAfter(startA, endB) then - if Ovale.trace then Ovale:Print(element.type.." return nil ["..element.nodeId.."]") end - return nil - end - if isBefore(startB, startA) then - startB = startA - end - if isAfter(endB, endA) then - endB = endA - end - if Ovale.trace then - Ovale:Print(element.type.." return "..nilstring(startB)..","..nilstring(endB).." ["..element.nodeId.."]") - end - return startB, endB, prioriteB, elementB - elseif element.type == "unless" then - if Ovale.trace then - self:Print(element.type) - end - local startA, endA = Ovale:CalculerMeilleureAction(element.a) - local startB, endB, prioriteB, elementB = Ovale:CalculerMeilleureAction(element.b) - - if isBeforeEqual(startA, startB) and isAfterEqual(endA, endB) then - if Ovale.trace then Ovale:Print(element.type.." return nil") end - return nil - end - - if isAfterEqual(startA, startB) and isBefore(endA, endB) then - if Ovale.trace then Ovale:Print(element.type.." return "..nilstring(endA)..","..nilstring(endB)) end - return endA, endB, prioriteB, elementB - end - - if isAfter(startA, startB) and isBefore(startA, endB) then - endB = startA - end - - if isAfter(endA, startB) and isBefore(endA, endB) then - startB = endA - end - - if Ovale.trace then Ovale:Print(element.type.." return "..nilstring(startB)..","..nilstring(endB)) end - return startB, endB, prioriteB, elementB - elseif (element.type == "or") then - if (Ovale.trace) then - self:Print(element.type) - end - - local startA, endA = Ovale:CalculerMeilleureAction(element.a) - local startB, endB = Ovale:CalculerMeilleureAction(element.b) - if isBefore(endA,self.currentTime) then - return startB,endB - elseif isBefore(endB,self.currentTime) then - return startA,endA - end - - if isBefore(endA,startB) then - return startA,endA - elseif isBefore(endB,startA) then - return startB,endB - end - - if isBefore(startA, startB) then - startB = startA - end - if isAfter(endA, endB) then - endB = endA - end - return startB, endB - elseif element.type == "operator" then - local startA, endA, prioA, elementA = self:CalculerMeilleureAction(element.a) - local startB, endB, prioB, elementB = self:CalculerMeilleureAction(element.b) - if not elementA or not elementB then - self:Log("operator " .. element.operator .. ": elementA or elementB is nil") - return nil - end - local a = elementA.value - local b = elementA.origin - local c = elementA.rate - local x = elementB.value - local y = elementB.origin - local z = elementB.rate - - if not a or not x or not b or not y then - self:Log("operator " .. element.operator .. ": a or x is nil") - return nil - end - - self:Log(a.."+(t-"..b..")*"..c.. element.operator..x.."+(t-"..y..")*"..z) - - local l, m, n - - if element.operator == "*" then - if c == 0 then - l = a*x - m = y - n = a*z - elseif z == 0 then - l = x*a; m = b; n = x*c - else - self:Print("ERROR: at least one value must be constant when multiplying") - self.bug = true - end - elseif element.operator == "+" then - if c+z == 0 then - l = a+x; m = 0; n = 0 - else - l = a+x; m = (b*c+y*z)/(c+z); n = c+z - end - elseif element.operator == '-' then - if c-z == 0 then - l = a-x; m = 0; n = 0 - else - l = a-x; m = (b*c-y*z)/(c-z); n = c-z - end - elseif element.operator == '/' then - if z == 0 then - l = a/x; m = b; n = c/x - else - self:Print("ERROR: second operator of / must be constant") - self.bug = true - end - elseif element.operator == '<' then - -- a + (t-b)*c = x + (t-y)*z - -- (t-b)*c - (t-y)*z = x - a - -- t*c - b*c - t*z + y*z = x - a - -- t*(c-z) = x - a + b*c + y*z - -- t = (x-a + b*c + y*z)/(c-z) - if c == z then - if a-b*c < x-y*z then - return 0 - else - return nil - end - else - local t = (x-a + b*c + y*z)/(c-z) - if c > z then - return 0, t - else - return t, nil - end - end - elseif element.operator == '>' then - if c == z then - self:Log("> with c==z") - if a-b*c > x-y*z then - self:Log("a>x") - return 0 - else - return nil - end - else - local t = (x-a + b*c + y*z)/(c-z) - if c < z then - return 0, t - else - return t, nil - end - end - end - if not element.result then - element.result = { type = "value" } - end - local result = element.result - result.value = l - result.origin = m - result.rate = n - self:Log("result = " .. l .." + "..m.."*"..n) - return startA, endA, 3, result - elseif element.type == "lua" then - local ret = loadstring(element.lua)() - self:Log("lua "..nilstring(ret)) - if not element.result then - element.result = { type = "value" } - end - local result = element.result - result.value = ret - result.origin = 0 - result.rate = 0 - return 0, nil, 3, result - elseif (element.type == "group") then - local meilleurTempsFils - local bestEnd - local meilleurePrioriteFils - local bestElement - local bestCastTime - - if (Ovale.trace) then - self:Print(element.type.." ["..element.nodeId.."]") - end - - if #element.nodes == 1 then - return Ovale:CalculerMeilleureAction(element.nodes[1]) - end - - for k, v in ipairs(element.nodes) do - local newStart, newEnd, priorite, nouveauElement = Ovale:CalculerMeilleureAction(v) - if newStart~=nil and newStart diff --git a/Ovale.toc b/Ovale.toc index afe973f..fa5ec41 100644 --- a/Ovale.toc +++ b/Ovale.toc @@ -3,7 +3,7 @@ ## Notes: Show the icon of the next spell to cast ## Notes-frFR: Affiche l'icône du prochain sort à lancer ## Author: Sidoine -## Version: 4.3.11 +## Version: 4.3.12 ## OptionalDeps: Ace3, Masque, Recount, Skada, LibBabble-CreatureType-3.0, LibRangeCheck-2.0 ## SavedVariables: OvaleDB ## SavedVariablesPerCharacter: OvaleDBPC @@ -15,6 +15,7 @@ embeds.xml Locale-frFR.lua Locale-deDE.lua Locale-enUS.lua +Locale-esES.lua Locale-itIT.lua Locale-koKR.lua Locale-ptBR.lua @@ -22,14 +23,24 @@ Locale-ruRU.lua Locale-zhCN.lua Locale-zhTW.lua Ovale.lua -Condition.lua +OvaleActionBar.lua +OvaleAura.lua +OvaleBestAction.lua +OvaleCompile.lua +OvaleCondition.lua +OvaleData.lua OvaleEquipement.lua +OvaleEnemies.lua +OvaleFrame.lua +OvaleFuture.lua +OvaleGUID.lua OvaleIcone.lua OvaleIcone.xml -OvaleFrame.lua -OvaleCompile.lua +OvaleOptions.lua OvaleRecount.lua OvaleSkada.lua +OvaleSpellDamage.lua +OvaleState.lua OvaleSwing.lua defaut\Chaman.lua defaut\Chasseur.lua diff --git a/OvaleActionBar.lua b/OvaleActionBar.lua new file mode 100644 index 0000000..8bd29da --- /dev/null +++ b/OvaleActionBar.lua @@ -0,0 +1,108 @@ +-- Keep data about the player action bars (key bindings mostly) +OvaleActionBar = LibStub("AceAddon-3.0"):NewAddon("OvaleActionBar", "AceEvent-3.0") + +-- +--key: spell name / value: action icon id +OvaleActionBar.actionSort = {} +OvaleActionBar.actionMacro = {} +OvaleActionBar.actionObjet = {} +OvaleActionBar.shortCut = {} +-- + +-- +function OvaleActionBar:OnEnable() + self:RegisterEvent("ACTIONBAR_SLOT_CHANGED") + self:RegisterEvent("UPDATE_BINDINGS") + self:FillActionIndexes() +end + +function OvaleActionBar:OnDisable() + self:UnregisterEvent("ACTIONBAR_SLOT_CHANGED") + self:UnregisterEvent("UPDATE_BINDINGS") +end + +function OvaleActionBar:ACTIONBAR_SLOT_CHANGED(event, slot, unknown) + if (slot == 0) then + self:FillActionIndexes() + elseif (slot) then + -- on reoit aussi si c'est une macro avec mouseover chaque fois que la souris passe sur une cible! + self:FillActionIndex(tonumber(slot)) + end +end + +--Called when the user changed his key bindings +function OvaleActionBar:UPDATE_BINDINGS() + self:FillActionIndexes() +end + +function OvaleActionBar:FillActionIndexes() + self.actionSort = {} + self.actionMacro = {} + self.actionObjet = {} + self.shortCut = {} + for i=1,120 do + self:FillActionIndex(i) + end +end + +function OvaleActionBar:FillActionIndex(i) + self.shortCut[i] = self:FindKeyBinding(i) + local actionText = GetActionText(i) + if actionText then + self.actionMacro[actionText] = i + else + local type, spellId = GetActionInfo(i); + if (type=="spell") then + self.actionSort[spellId] = i + elseif (type =="item") then + self.actionObjet[spellId] = i + end + end +end + +function OvaleActionBar:FindKeyBinding(id) +-- ACTIONBUTTON1..12 => principale (1..12, 13..24, 73..108) +-- MULTIACTIONBAR1BUTTON1..12 => bas gauche (61..72) +-- MULTIACTIONBAR2BUTTON1..12 => bas droite (49..60) +-- MULTIACTIONBAR3BUTTON1..12 => haut droit (25..36) +-- MULTIACTIONBAR4BUTTON1..12 => haut gauche (37..48) + local name; + if (id<=24 or id>72) then + name = "ACTIONBUTTON"..(((id-1)%12)+1); + elseif (id<=36) then + name = "MULTIACTIONBAR3BUTTON"..(id-24); + elseif (id<=48) then + name = "MULTIACTIONBAR4BUTTON"..(id-36); + elseif (id<=60) then + name = "MULTIACTIONBAR2BUTTON"..(id-48); + else + name = "MULTIACTIONBAR1BUTTON"..(id-60); + end + local key = GetBindingKey(name); +--[[ if (not key) then + DEFAULT_CHAT_FRAME:AddMessage(id.."=>"..name.." introuvable") + else + DEFAULT_CHAT_FRAME:AddMessage(id.."=>"..name.."="..key) + end]] + return key; +end + +-- Get the action id that match a spell id +function OvaleActionBar:GetForSpell(spellId) + return self.actionSort[spellId] +end + +-- Get the action id that match a macro id +function OvaleActionBar:GetForMacro(macroId) + return self.actionMacro[macroId] +end + +-- Get the action id that match an item id +function OvaleActionBar:GetForItem(itemId) + return self.actionObjet[itemId] +end + +function OvaleActionBar:GetBinding(actionId) + return self.shortCut[actionId] +end +-- diff --git a/OvaleAura.lua b/OvaleAura.lua new file mode 100644 index 0000000..ae0f3d4 --- /dev/null +++ b/OvaleAura.lua @@ -0,0 +1,269 @@ +-- This addon keep the list of all the aura for all the units +-- Fore each aura, it saves the state of the player when it was refreshed + +OvaleAura = LibStub("AceAddon-3.0"):NewAddon("OvaleAura", "AceEvent-3.0") + +-- +OvaleAura.aura = {} +OvaleAura.serial = 0 +OvaleAura.spellHaste = 1 +OvaleAura.meleeHaste = 1 +OvaleAura.damageMultiplier = 1 +OvaleAura.playerGUID = nil +-- + +-- Events +-- +function OvaleAura:OnEnable() + self.playerGUID = UnitGUID("player") + self:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED") +end + +function OvaleAura:OnDisable() + self:UnregisterEvent("COMBAT_LOG_EVENT_UNFILTERED") +end + +function OvaleAura:COMBAT_LOG_EVENT_UNFILTERED(event, ...) + local time, event, hideCaster, sourceGUID, sourceName, sourceFlags, sourceRaidFlags, destGUID, destName, destFlags, destRaidFlags = select(1, ...) + + if string.find(event, "SPELL_AURA_") == 1 then + local spellId, spellName, spellSchool, auraType = select(12, ...) + + local unitId = OvaleGUID:GetUnitId(destGUID) + + if unitId then + self:UpdateAuras(unitId, destGUID) + end + + if sourceGUID == self.playerGUID and (event == "SPELL_AURA_APPLIED" or event == "SPELL_AURA_REFRESH" or event == "SPELL_AURA_APPLIED_DOSE") then + local aura = self:GetAuraByGUID(destGUID, spellId, true) + if aura then + aura.spellHaste = self.spellHaste + end + end + end + + if event == "UNIT_DIED" then + self.aura[destGUID] = nil + local unitId = OvaleGUID:GetUnitId(destGUID) + if unitId then + Ovale.refreshNeeded[unitId] = true + end + end +end + +function OvaleAura:AddAura(unitGUID, spellId, unitCaster, icon, count, debuffType, duration, expirationTime, isStealable, name) + local auraList = self.aura[unitGUID] + + if not auraList[spellId] then + auraList[spellId] = {} + end + + local mine = (unitCaster == "player") + local aura + if mine then + if not auraList[spellId].mine then + auraList[spellId].mine = { gain = OvaleState.maintenant } + end + aura = auraList[spellId].mine + else + if not auraList[spellId].other then + auraList[spellId].other = { gain = OvaleState.maintenant } + end + aura = auraList[spellId].other + end + + aura.serial = self.serial + + if count == 0 then + count = 1 + end + + if not aura.ending or aura.ending < expirationTime or aura.stacks < count then + aura.icon = icon + aura.stacks = count + aura.debuffType = debuffType + if duration > 0 then + aura.duration = duration + aura.ending = expirationTime + else + aura.duration = nil + aura.ending = nil + end + aura.start = expirationTime - duration + aura.stealable = isStealable + aura.mine = mine + aura.source = unitCaster + aura.name = name + end +end + +-- Private methods +function OvaleAura:UpdateAuras(unitId, unitGUID) + self.serial = self.serial + 1 + + local hateBase + local hateCommune + local hateSorts + local hateCaC + local hateHero + local hateClasse + local damageMultiplier + + if unitId == "player" then + hateBase = GetCombatRatingBonus(18) + hateCommune = 0 + hateSorts = 0 + hateCaC = 0 + hateHero = 0 + hateClasse = 0 + damageMultiplier = 1 + end + + if not unitGUID then + unitGUID = UnitGUID(unitId) + end + + if not self.aura[unitGUID] then + self.aura[unitGUID] = {} + end + + local i = 1 + + local mode = "HELPFUL" + while (true) do + local name, rank, icon, count, debuffType, duration, expirationTime, unitCaster, isStealable, shouldConsolidate, spellId = UnitAura(unitId, i, mode) + if not name then + if mode == "HELPFUL" then + mode = "HARMFUL" + i = 1 + else + break + end + else + self:AddAura(unitGUID, spellId, unitCaster, icon, count, debuffType, duration, expirationTime, isStealable, name) + if debuffType then + -- TODO: not very clean + -- should be computed by OvaleState:GetAura + self:AddAura(unitGUID, debuffType, unitCaster, icon, count, debuffType, duration, expirationTime, isStealable, name) + end + + if unitId == "player" then + if OvaleData.buffSpellList.spellhaste[spellId] then + hateSorts = 5 + elseif OvaleData.buffSpellList.meleehaste[spellId] then + hateCaC = 10 + elseif OvaleData.buffSpellList.heroism[spellId] then + hateHero = 30 + elseif OvaleData.selfHasteBuff[spellId] then + hateClasse = OvaleData.selfHasteBuff[spellId] + end + if OvaleData.selfDamageBuff[spellId] then + damageMultiplier = damageMultiplier * OvaleData.selfDamageBuff[spellId] + end + end + i = i + 1 + end + end + + local auraList = self.aura[unitGUID] + --Removes expired aura + for spellId,whoseTable in pairs(auraList) do + for whose,aura in pairs(whoseTable) do + if aura.serial ~= self.serial then + -- Ovale:Print("Removing "..aura.name.." from "..whose .. " self.serial = " ..self.serial .. " aura.serial = " ..aura.serial) + whoseTable[whose] = nil + end + end + if not next(whoseTable) then + --Ovale:Print("Removing "..spellId) + auraList[spellId] = nil + end + end + + --Clear unit if all aura have been deleted + if not next(auraList) then + self.aura[unitGUID] = nil + end + + --Update player haste + if unitId == "player" then + self.spellHaste = 1 + (hateBase + hateCommune + hateSorts + hateHero + hateClasse)/100 + self.meleeHaste = 1 + (hateBase + hateCommune + hateCaC + hateHero + hateClasse)/100 + self.damageMultiplier = damageMultiplier + end + + Ovale.refreshNeeded[unitId] = true +end + +-- Public methods +function OvaleAura:GetAuraByGUID(guid, spellId, mine, unitId) + if not guid then + return nil + end + local auraTable = self.aura[guid] + if not auraTable then + if not unitId then + unitId = OvaleGUID:GetUnitId(guid) + end + if not unitId then + return nil + end + self:UpdateAuras(unitId, guid) + auraTable = self.aura[guid] + if not auraTable then + -- no aura on target + return nil + end + end + local aura = auraTable[spellId] + if not aura then return nil end + if mine or mine == 1 then + return aura.mine + elseif aura.other then + return aura.other + else + return aura.mine + end +end + +function OvaleAura:GetAura(unitId, spellId, mine) + return self:GetAuraByGUID(UnitGUID(unitId), spellId, mine, unitId) +end + +-- Look for the last of my aura on any targt that will expires. +-- Returns its expiration time +function OvaleAura:GetExpirationTimeOnAnyTarget(spellId) + local ending = nil + local starting = nil + + for unitId,auraTable in pairs(self.aura) do + if auraTable[spellId] then + local aura = auraTable[spellId].mine + if aura then + local newEnding = aura.ending + local newStarting = aura.start + if newStarting and (not staring or newStarting < starting) then + starting = newStarting + end + if newEnding and (not ending or newEnding > ending) then + ending = newEnding + end + end + end + end + return starting, ending +end + +function OvaleAura:Debug() + Ovale:Print("------") + for guid,auraTable in pairs(self.aura) do + Ovale:Print("***"..guid) + for spellId,whoseTable in pairs(auraTable) do + for whose,aura in pairs(whoseTable) do + Ovale:Print(guid.." "..whose.." "..spellId .. " "..aura.name .. " stacks ="..aura.stacks) + end + end + end +end +-- diff --git a/OvaleBestAction.lua b/OvaleBestAction.lua new file mode 100644 index 0000000..cccbe52 --- /dev/null +++ b/OvaleBestAction.lua @@ -0,0 +1,616 @@ +OvaleBestAction = {} + +-- +local function nilstring(text) + if text == nil then + return "nil" + else + return text + end +end + +local function printTime(temps) + if (temps == nil) then + Ovale:Print("> nil") + else + Ovale:Print("> "..temps) + end +end + +local function addTime(time1, duration) + if not time1 then + return nil + else + return time1 + duration + end +end + +local function isBeforeEqual(time1, time2) + return time1 and (not time2 or time1<=time2) +end + +local function isBefore(time1, time2) + return time1 and (not time2 or time1=time2) +end + +local function isAfter(time1, time2) + return not time1 or (time2 and time1>time2) +end +-- + +-- +function OvaleBestAction:StartNewAction() + OvaleState:Reset() + OvaleFuture:Apply() +end + +function OvaleBestAction:GetActionInfo(element) + if not element then + return nil + end + + local spellId = element.params[1] + local action + local actionTexture, actionInRange, actionCooldownStart, actionCooldownDuration, + actionUsable, actionShortcut, actionIsCurrent, actionEnable + + local target = element.params.target + if (not target) then + target = OvaleCondition.defaultTarget + end + + if (element.func == "Spell" ) then + action = OvaleActionBar:GetForSpell(spellId) + if not OvaleData.spellList[spellId] and not action then + Ovale:Log("Spell "..spellId.." not learnt") + return nil + end + + actionCooldownStart, actionCooldownDuration, actionEnable = OvaleData:GetComputedSpellCD(spellId) + + spellName = OvaleData.spellList[spellId] + if not spellName then + spellName = GetSpellInfo(spellId) + end + actionTexture = GetSpellTexture(spellId) + actionInRange = IsSpellInRange(spellName, target) + actionUsable = IsUsableSpell(spellId) + actionShortcut = nil + elseif (element.func=="Macro") then + action = OvaleActionBar:GetForMacro(element.params[1]) + if action then + actionTexture = GetActionTexture(action) + actionInRange = IsActionInRange(action, target) + actionCooldownStart, actionCooldownDuration, actionEnable = GetActionCooldown(action) + actionUsable = IsUsableAction(action) + actionShortcut = OvaleActionBar:GetBinding(action) + actionIsCurrent = IsCurrentAction(action) + else + Ovale:Log("Unknown macro "..element.params[1]) + end + elseif (element.func=="Item") then + local itemId + if (type(element.params[1]) == "number") then + itemId = element.params[1] + else + local _,_,id = string.find(GetInventoryItemLink("player",GetInventorySlotInfo(element.params[1])) or "","item:(%d+):%d+:%d+:%d+") + if not id then + return nil + end + itemId = tonumber(id) + end + + if (Ovale.trace) then + Ovale:Print("Item "..nilstring(itemId)) + end + + local spellName = GetItemSpell(itemId) + actionUsable = (spellName~=nil) + + action = OvaleActionBar:GetForItem(itemId) + actionTexture = GetItemIcon(itemId) + actionInRange = IsItemInRange(itemId, target) + actionCooldownStart, actionCooldownDuration, actionEnable = GetItemCooldown(itemId) + actionShortcut = nil + actionIsCurrent = nil + elseif element.func=="Texture" then + actionTexture = "Interface\\Icons\\"..element.params[1] + actionCooldownStart = OvaleState.maintenant + actionCooldownDuration = 0 + actionEnable = 1 + actionUsable = true + end + + if action then + if actionUsable == nil then + actionUsable = IsUsableAction(action) + end + actionShortcut = OvaleActionBar:GetBinding(action) + actionIsCurrent = IsCurrentAction(action) + end + + local cd = OvaleState:GetCD(spellId) + if cd and cd.toggle then + actionIsCurrent = 1 + end + + return actionTexture, actionInRange, actionCooldownStart, actionCooldownDuration, + actionUsable, actionShortcut, actionIsCurrent, actionEnable, spellId, target, element.params.nored +end + +function OvaleBestAction:Compute(element) + if (Ovale.bug and not Ovale.trace) then + return nil + end + + if (not element) then + return nil + end + + --TODO: crer un objet par type au lieu de ce if else if tout moche + if (element.type=="function")then + if (element.func == "Spell" or element.func=="Macro" or element.func=="Item" or element.func=="Texture") then + local action + local actionTexture, actionInRange, actionCooldownStart, actionCooldownDuration, + actionUsable, actionShortcut, actionIsCurrent, actionEnable, spellId = self:GetActionInfo(element) + + if not actionTexture then + if (Ovale.trace) then + Ovale:Print("Action "..element.params[1].." not found") + end + return nil + end + if element.params.usable==1 and not actionUsable then + if (Ovale.trace) then + Ovale:Print("Action "..element.params[1].." not usable") + end + return nil + end + if spellId and OvaleData.spellInfo[spellId] and OvaleData.spellInfo[spellId].casttime then + element.castTime = OvaleData.spellInfo[spellId].casttime + elseif spellId then + local spell, rank, icon, cost, isFunnel, powerType, castTime = GetSpellInfo(spellId) + if castTime then + element.castTime = castTime/1000 + else + element.castTime = nil + end + else + element.castTime = 0 + end + --TODO: not useful anymore? + if (spellId and OvaleData.spellInfo[spellId] and OvaleData.spellInfo[spellId].toggle and actionIsCurrent) then + if (Ovale.trace) then + Ovale:Print("Action "..element.params[1].." is current action") + end + return nil + end + if actionEnable and actionEnable>0 then + local restant + if (not actionCooldownDuration or actionCooldownStart==0) then + restant = OvaleState.currentTime + else + restant = actionCooldownDuration + actionCooldownStart + end + Ovale:Log("restant = "..restant.." attenteFinCast="..nilstring(OvaleState.attenteFinCast)) + if restanttempsB then + diff = tempsA - tempsB + else + diff = tempsB - tempsA + end + Ovale:Log("diff returns "..diff) + return diff + elseif element.type == "fromuntil" then + Ovale:Log("fromuntil") + local tempsA = self:Compute(element.a) + if (tempsA==nil) then + if Ovale.trace then Ovale:Print(element.type.." return nil") end + return nil + end + local tempsB = self:Compute(element.b) + if (tempsB==nil) then + if Ovale.trace then Ovale:Print(element.type.." return nil") end + return nil + end + Ovale:Log("fromuntil returns "..(tempsB - tempsA)) + return tempsB - tempsA + elseif element.type == "compare" then + Ovale:Log("compare "..element.comparison) + local tempsA = self:Compute(element.a) + local timeB = self:Compute(element.time) + Ovale:Log(nilstring(tempsA).." "..element.comparison.." "..nilstring(timeB)) + if element.comparison == "more" and (not tempsA or tempsA>timeB) then + if Ovale.trace then Ovale:Print(element.type.." return 0") end + return 0 + elseif element.comparison == "less" and tempsA and tempsA=timeB) then + if Ovale.trace then Ovale:Print(element.type.." return 0") end + return 0 + end + return nil + elseif element.type == "and" or element.type == "if" then + if (Ovale.trace) then + Ovale:Print(element.type.." ["..element.nodeId.."]") + end + local startA, endA = self:Compute(element.a) + if (startA==nil) then + if Ovale.trace then Ovale:Print(element.type.." return nil ["..element.nodeId.."]") end + return nil + end + if startA == endA then + if Ovale.trace then Ovale:Print(element.type.." return startA=endA ["..element.nodeId.."]") end + return nil + end + local startB, endB, prioriteB, elementB = self:Compute(element.b) + if isAfter(startB, endA) or isAfter(startA, endB) then + if Ovale.trace then Ovale:Print(element.type.." return nil ["..element.nodeId.."]") end + return nil + end + if isBefore(startB, startA) then + startB = startA + end + if isAfter(endB, endA) then + endB = endA + end + if Ovale.trace then + Ovale:Print(element.type.." return "..nilstring(startB)..","..nilstring(endB).." ["..element.nodeId.."]") + end + return startB, endB, prioriteB, elementB + elseif element.type == "unless" then + if Ovale.trace then + Ovale:Print(element.type) + end + local startA, endA = self:Compute(element.a) + local startB, endB, prioriteB, elementB = self:Compute(element.b) + + if isBeforeEqual(startA, startB) and isAfterEqual(endA, endB) then + if Ovale.trace then Ovale:Print(element.type.." return nil") end + return nil + end + + if isAfterEqual(startA, startB) and isBefore(endA, endB) then + if Ovale.trace then Ovale:Print(element.type.." return "..nilstring(endA)..","..nilstring(endB)) end + return endA, endB, prioriteB, elementB + end + + if isAfter(startA, startB) and isBefore(startA, endB) then + endB = startA + end + + if isAfter(endA, startB) and isBefore(endA, endB) then + startB = endA + end + + if Ovale.trace then Ovale:Print(element.type.." return "..nilstring(startB)..","..nilstring(endB)) end + return startB, endB, prioriteB, elementB + elseif (element.type == "or") then + if (Ovale.trace) then + Ovale:Print(element.type) + end + + local startA, endA = self:Compute(element.a) + local startB, endB = self:Compute(element.b) + if isBefore(endA,OvaleState.currentTime) then + return startB,endB + elseif isBefore(endB,OvaleState.currentTime) then + return startA,endA + end + + if isBefore(endA,startB) then + return startA,endA + elseif isBefore(endB,startA) then + return startB,endB + end + + if isBefore(startA, startB) then + startB = startA + end + if isAfter(endA, endB) then + endB = endA + end + return startB, endB + elseif element.type == "operator" then + local startA, endA, prioA, elementA = self:Compute(element.a) + local startB, endB, prioB, elementB = self:Compute(element.b) + if not elementA or not elementB then + Ovale:Log("operator " .. element.operator .. ": elementA or elementB is nil") + return nil + end + local a = elementA.value + local b = elementA.origin + local c = elementA.rate + local x = elementB.value + local y = elementB.origin + local z = elementB.rate + + if not a or not x or not b or not y then + Ovale:Log("operator " .. element.operator .. ": a or x is nil") + return nil + end + + Ovale:Log(a.."+(t-"..b..")*"..c.. element.operator..x.."+(t-"..y..")*"..z) + + local l, m, n + + if element.operator == "*" then + if c == 0 then + l = a*x + m = y + n = a*z + elseif z == 0 then + l = x*a; m = b; n = x*c + else + Ovale:Print("ERROR: at least one value must be constant when multiplying") + Ovale.bug = true + end + elseif element.operator == "+" then + if c+z == 0 then + l = a+x; m = 0; n = 0 + else + l = a+x; m = (b*c+y*z)/(c+z); n = c+z + end + elseif element.operator == '-' then + if c-z == 0 then + l = a-x; m = 0; n = 0 + else + l = a-x; m = (b*c-y*z)/(c-z); n = c-z + end + elseif element.operator == '/' then + if z == 0 then + l = a/x; m = b; n = c/x + else + Ovale:Print("ERROR: second operator of / must be constant") + Ovale.bug = true + end + elseif element.operator == '<' then + -- a + (t-b)*c = x + (t-y)*z + -- (t-b)*c - (t-y)*z = x - a + -- t*c - b*c - t*z + y*z = x - a + -- t*(c-z) = x - a + b*c + y*z + -- t = (x-a + b*c + y*z)/(c-z) + if c == z then + if a-b*c < x-y*z then + return 0 + else + return nil + end + else + local t = (x-a + b*c + y*z)/(c-z) + if c > z then + return 0, t + else + return t, nil + end + end + elseif element.operator == '>' then + if c == z then + Ovale:Log("> with c==z") + if a-b*c > x-y*z then + Ovale:Log("a>x") + return 0 + else + return nil + end + else + local t = (x-a + b*c + y*z)/(c-z) + if c < z then + return 0, t + else + return t, nil + end + end + end + if not element.result then + element.result = { type = "value" } + end + local result = element.result + result.value = l + result.origin = m + result.rate = n + Ovale:Log("result = " .. l .." + "..m.."*"..n) + return startA, endA, 3, result + elseif element.type == "lua" then + local ret = loadstring(element.lua)() + Ovale:Log("lua "..nilstring(ret)) + if not element.result then + element.result = { type = "value" } + end + local result = element.result + result.value = ret + result.origin = 0 + result.rate = 0 + return 0, nil, 3, result + elseif (element.type == "group") then + local meilleurTempsFils + local bestEnd + local meilleurePrioriteFils + local bestElement + local bestCastTime + + if (Ovale.trace) then + Ovale:Print(element.type.." ["..element.nodeId.."]") + end + + if #element.nodes == 1 then + return self:Compute(element.nodes[1]) + end + + for k, v in ipairs(element.nodes) do + local newStart, newEnd, priorite, nouveauElement = self:Compute(v) + if newStart~=nil and newStart diff --git a/OvaleCompile.lua b/OvaleCompile.lua index 68eaa4d..afc00ec 100644 --- a/OvaleCompile.lua +++ b/OvaleCompile.lua @@ -1,9 +1,14 @@ local L = LibStub("AceLocale-3.0"):GetLocale("Ovale") +OvaleCompile = {} + +-- local node={} local defines = {} local customFunctions = {} +-- +-- local function AddNode(newNode) node[#node+1] = newNode newNode.nodeId = #node @@ -48,12 +53,12 @@ local function HasGlyph(spellId) end local function HasTalent(talentId) - if not Ovale.listeTalentsRemplie then - Ovale:RemplirListeTalents() + if not OvaleData.listeTalentsRemplie then + OvaleData:RemplirListeTalents() end - if Ovale.listeTalentsRemplie then - if Ovale.pointsTalent[talentId]~=nil then - return Ovale.pointsTalent[talentId]>0 + if OvaleData.listeTalentsRemplie then + if OvaleData.pointsTalent[talentId]~=nil then + return OvaleData.pointsTalent[talentId]>0 else Ovale:Print("Unknown talent "..talentId) return false @@ -79,7 +84,7 @@ local function TestConditions(paramList) Ovale.casesACocher[cb] = {} end Ovale.casesACocher[cb].compile = true - if not Ovale.db.profile.check[cb] then + if not OvaleOptions:GetProfile().check[cb] then return false end end @@ -89,7 +94,7 @@ local function TestConditions(paramList) Ovale.casesACocher[cb] = {} end Ovale.casesACocher[cb].compile = true - if Ovale.db.profile.check[cb] then + if OvaleOptions:GetProfile().check[cb] then return false end end @@ -100,7 +105,7 @@ local function TestConditions(paramList) Ovale.listes[list] = { items = {}} end Ovale.listes[list].compile = true - if Ovale.db.profile.list[list] ~= key then + if OvaleOptions:GetProfile().list[list] ~= key then return false end end @@ -155,7 +160,7 @@ local function ParseSpellAddDebuff(params) local spellId = paramList[1] if spellId then paramList[1] = nil - Ovale:GetSpellInfo(spellId).aura.player.HARMFUL = paramList + OvaleData:GetSpellInfo(spellId).aura.player.HARMFUL = paramList end return "" end @@ -165,7 +170,7 @@ local function ParseSpellAddBuff(params) local spellId = paramList[1] if spellId then paramList[1] = nil - Ovale:GetSpellInfo(spellId).aura.player.HELPFUL = paramList + OvaleData:GetSpellInfo(spellId).aura.player.HELPFUL = paramList end return "" end @@ -175,7 +180,7 @@ local function ParseSpellAddTargetDebuff(params) local spellId = paramList[1] if spellId then paramList[1] = nil - Ovale:GetSpellInfo(spellId).aura.target.HARMFUL = paramList + OvaleData:GetSpellInfo(spellId).aura.target.HARMFUL = paramList end return "" end @@ -188,7 +193,7 @@ local function ParseSpellInfo(params) if not TestConditions(paramList) then return "" end - local spellInfo = Ovale:GetSpellInfo(spellId) + local spellInfo = OvaleData:GetSpellInfo(spellId) for k,v in pairs(paramList) do if k == "addduration" then spellInfo.duration = spellInfo.duration + v @@ -207,7 +212,7 @@ local function ParseScoreSpells(params) local spellId = tonumber(v) if spellId then --Ovale:Print("Add spell to score "..spellId) - Ovale.scoreSpell[spellId] = true + OvaleData.scoreSpell[spellId] = true else Ovale:Print("unknown spell "..v) end @@ -215,10 +220,10 @@ local function ParseScoreSpells(params) end local function ParseSpellList(name, params) - Ovale.buffSpellList[name] = {} + OvaleData.buffSpellList[name] = {} local i = 1 for v in string.gmatch(params, "(%d+)") do - Ovale.buffSpellList[name][i] = tonumber(v) + OvaleData.buffSpellList[name][i] = tonumber(v) i = i + 1 end end @@ -418,21 +423,10 @@ local function ParseAddIcon(params, text) return masterNode end -function Ovale:CompileInputs(text) - self.casesACocher = {} - self.listes = {} - self.defaultListes = {} - self.defaultCheck = {} - - text = string.gsub(text, "AddListItem%s*%(%s*(%w+)%s+(%w+)%s+\"(.-)\"%s*(.-)%s*%)", ParseAddListItem) - text = string.gsub(text, "AddCheckBox%s*%(%s*(%w+)%s+\"(.-)\"%s*(.-)%s*%)", ParseAddCheckBox) - return text -end - local function ParseCanStopChannelling(text) local spellId = tonumber(text) if spellId then - Ovale:GetSpellInfo(spellId).canStopChannelling = true + OvaleData:GetSpellInfo(spellId).canStopChannelling = true else Ovale:Print("CanStopChannelling with unknown spell "..spellId) end @@ -440,7 +434,7 @@ local function ParseCanStopChannelling(text) end local function ParseSpellName(text) - local spell = Ovale:GetSpellInfoOrNil(text) + local spell = OvaleData:GetSpellInfoOrNil(text) if (spell) then return '"'..spell..'"' else @@ -452,10 +446,21 @@ end local function ParseL(text) return '"'..L[text]..'"' end +-- -function Ovale:Compile(text) - self.compileOnItems = false - self.bug = false +-- +function OvaleCompile:CompileInputs(text) + Ovale.casesACocher = {} + Ovale.listes = {} + + text = string.gsub(text, "AddListItem%s*%(%s*(%w+)%s+(%w+)%s+\"(.-)\"%s*(.-)%s*%)", ParseAddListItem) + text = string.gsub(text, "AddCheckBox%s*%(%s*(%w+)%s+\"(.-)\"%s*(.-)%s*%)", ParseAddCheckBox) + return text +end + +function OvaleCompile:Compile(text) + Ovale.compileOnItems = false + Ovale.bug = false node = {} defines = {} @@ -476,7 +481,7 @@ function Ovale:Compile(text) text = string.gsub(text, "L%s*%(%s*(%w+)%s*%)", ParseL) -- Options diverses - Ovale:ResetSpellInfo() + OvaleData:ResetSpellInfo() text = string.gsub(text, "CanStopChannelling%s*%(%s*(%w+)%s*%)", ParseCanStopChannelling) text = string.gsub(text, "SpellAddBuff%s*%((.-)%)", ParseSpellAddBuff) text = string.gsub(text, "SpellAddDebuff%s*%((.-)%)", ParseSpellAddDebuff) @@ -511,7 +516,7 @@ function Ovale:Compile(text) return masterNodes end -function Ovale:DebugNode(node) +function OvaleCompile:DebugNode(node) local text if (not node) then return "#nil" @@ -557,4 +562,5 @@ function Ovale:DebugNode(node) end return text -end \ No newline at end of file +end +-- diff --git a/OvaleCondition.lua b/OvaleCondition.lua new file mode 100644 index 0000000..3c4cd50 --- /dev/null +++ b/OvaleCondition.lua @@ -0,0 +1,1175 @@ +OvaleCondition = {} + +-- + +local LBCT = LibStub("LibBabble-CreatureType-3.0"):GetLookupTable() +local LRC = LibStub("LibRangeCheck-2.0", true) +local runes = {} +local runesCD = {} + +local runeType = +{ + blood = 1, + unholy = 2, + frost = 3, + death = 4 +} + +local totemType = +{ + ghoul = 1, + fire = 1, + earth = 2, + water = 3, + air = 4 +} + +local lastSaved = {} +local savedHealth = {} +local targetGUID = {} +local lastSPD = {} + +-- + +-- +local function isDebuffInList(list) + local i=1; + while (true) do + local name, rank, icon, count, debuffType, duration, expirationTime, unitCaster, isStealable, shouldConsolidate, spellId = UnitDebuff("player", i); + if (not name) then + break + end + if (list[spellId]) then + return true + end + i = i +1 + end + return false +end + +local function avecHate(temps, hate) + if not temps then + temps = 0 + end + if (not hate) then + return temps + elseif (hate == "spell") then + return temps/OvaleAura.spellHaste + elseif (hate == "melee") then + return temps/OvaleAura.meleeHaste + else + return temps + end +end + +local function compare(a, comparison, b) + if (comparison == "more") then + if (not b or (a~=nil and a>b)) then + return 0 + else + return nil + end + elseif comparison == "equal" then + if b == a then + return 0 + else + return nil + end + else + if (not a or (b~=nil and a 0 then + runes[rune.type] = runes[rune.type] - 1 + if rune.cd > runesCD[rune.type] then + runesCD[rune.type] = rune.cd + end + elseif rune.cd < runesCD[rune.type] then + runesCD[rune.type] = rune.cd + end + end + end + + if not condition.nodeath then + for i=1,6 do + local rune = OvaleState.state.rune[i] + if rune and rune.type == 4 then + for j=1,3 do + if runes[j]>0 then + runes[j] = runes[j] - 1 + if rune.cd > runesCD[j] then + runesCD[j] = rune.cd + end + break + elseif rune.cd < runesCD[j] then + runesCD[j] = rune.cd + break + end + end + end + end + end + + for i=1,4 do + if runes[i]> 0 then + return nil + end + if not maxCD or runesCD[i]>maxCD then + maxCD = runesCD[i] + end + end + return maxCD +end + +local lastEnergyValue = nil +local lastEnergyTime + +local function GetManaAndRate(withBerserker) + local _,className = UnitClass("player") + local current = OvaleState.state.mana + if current~=lastEnergyValue then + lastEnergyValue = current + lastEnergyTime = OvaleState.currentTime + end + + local rate + + if className == "ROGUE" or (className == "DRUID" and GetShapeshiftForm(true) == 3) then + rate = 10 * OvaleAura.meleeHaste + if (className == "ROGUE") then + local rush = OvaleState:GetAura("player", 13750) + if rush and rush.stacks>0 then + rate = rate * 2 + end + elseif withBerserker then + local berserk = OvaleState:GetAura("player", 50334) + if berserk and berserk.stacks>0 then + mana = mana/2 + end + end + elseif className == "HUNTER" then + rate = 4 * OvaleAura.meleeHaste + else + rate = 0 + end + + return lastEnergyValue, lastEnergyTime, rate +end + +local function GetManaTime(mana, withBerserker) + local lastEnergyValue, lastEnergyTime, rate = GetManaAndRate(withBerserker) + + if rate > 0 then + local limit = math.ceil((mana - lastEnergyValue) / rate + lastEnergyTime) + return limit + else + if OvaleState.state.mana>=mana then + return OvaleState.currentTime-1 + else + return nil + end + end +end + + +-- Recherche un aura sur la cible et récupère sa durée et le nombre de stacks +-- return start, ending, stacks +local function GetTargetAura(condition, filter, target) + if (not target) then + target=condition.target + if (not target) then + target="target" + end + end + local stacks = condition.stacks + if not stacks then + stacks = 1 + end + local spellId = condition[1] + + local mine = (condition.mine == 1) + + local aura + if type(spellId) == "number" then + aura = OvaleState:GetAura(target, spellId, mine) + elseif OvaleData.buffSpellList[spellId] then + for k,v in pairs(OvaleData.buffSpellList[spellId]) do + local newAura = OvaleState:GetAura(target, v, mine) + if newAura and (not aura or newAura.stacks>aura.stacks) then + aura = newAura + end + end + elseif spellId == "Magic" or spellId == "Disease" or spellId=="Curse" or spellId=="Poison" then + aura = OvaleState:GetAura(target, spellId, mine) + else + Ovale:Print("ERROR: unknown buff "..spellId) + Ovale.bug = true + return 0,0 + end + + if not aura then + return 0,0 + end + + if Ovale.trace then + Ovale:Print("GetTargetAura = start=".. nilstring(aura.start) .. " end="..nilstring(aura.ending).." stacks=" ..nilstring(aura.stacks).."/"..stacks) + end + + if (not condition.mine or (aura.mine and condition.mine==1) or (not aura.mine and condition.mine==0)) and aura.stacks>=stacks then + local ending + if condition.forceduration then + if OvaleData.spellInfo[spellId] and OvaleData.spellInfo[spellId].duration then + ending = aura.start + OvaleData.spellInfo[spellId].duration + else + ending = aura.start + condition.forceduration + end + else + ending = aura.ending + end + return aura.start, ending + else + return 0,0 + end +end + +local function getTargetDead(target) + local second = math.floor(OvaleState.maintenant) + if targetGUID[target] ~=UnitGUID(target) then + lastSaved[target] = nil + targetGUID[target] = UnitGUID(target) + savedHealth[target] = {} + end + local newHealth = UnitHealth(target) + if newHealth then + Ovale:Log("newHealth = " .. newHealth) + end + if UnitHealthMax(target)==1 then + Ovale:Log("Dummy, return in the future") + return nil + end + if second~=lastSaved[target] and targetGUID[target] then + lastSaved[target] = second + local mod10 = second % 10 + local prevHealth = savedHealth[target][mod10] + savedHealth[target][mod10] = newHealth + if prevHealth and prevHealth>newHealth then + lastSPD[target] = 10/(prevHealth-newHealth) + if lastSPD[target] > 0 then + Ovale:Log("dps = " .. (1/lastSPD[target])) + end + end + end + if not lastSPD[target] or lastSPD[target]<=0 then + return nil + end + -- Rough estimation + local duration = newHealth * lastSPD[target] + if duration < 10000 then + return OvaleState.maintenant + duration + else + return nil + end +end +-- + +-- +OvaleCondition.conditions= +{ + -- Test if a white hit just occured + -- 1 : maximum time after a white hit + -- Not useful anymore. No widely used spell reset swing timer anyway + --[[AfterWhiteHit = function(condition) + local debut = OvaleSwing.starttime + local fin = OvaleSwing.duration + debut + local maintenant = GetTime() + if (maintenant-debutcondition[2] then + return 0 + else + return nil + end + else + if condition[2]~=nil and minRange0 solar + Eclipse = function(condition) + return compare(OvaleState.state.eclipse, condition[1], condition[2]) + end, + eclipse = function(condition) + return OvaleState.state.eclipse + end, + EffectiveMana = function(condition) + local limit = GetManaTime(condition[2], true) + if condition[1]=="more" then + return limit, nil + else + return 0,limit + end + end, + effectiveMana = function(condition) + return GetManaAndRate(true) + end, + EndCastTime = function(condition) + local name, rank, icon, cost, isFunnel, powerType, castTime = OvaleData:GetSpellInfoOrNil(condition[1]) + local actionCooldownStart, actionCooldownDuration, actionEnable = OvaleData:GetComputedSpellCD(condition[1]) + local startCast = actionCooldownStart + actionCooldownDuration + if startCast0 then + local timeBefore = condition[2] or 0 + return 0, addTime(maxTime, -timeBefore) + end + return nil + end, + OtherAuraExpires = OtherDebuffExpires, + OtherAuraPresent = OtherDebuffPresent, + otherAura = function(condition) + local minTime, maxTime = getOtherAura(condition[1]) + return 0, maxTime, -1 + end, + Present = function(condition) + local present = UnitExists(getTarget(condition.target)) and not UnitIsDead(getTarget(condition.target)) + return testbool(present, condition[1]) + end, + -- Test if any player pet is present (or not) + -- 1 : "yes" or "no" + PetPresent = function(condition) + local present = UnitExists("pet") and not UnitIsDead("pet") + return testbool(present, condition[1]) + end, + -- Test the target level difference with the player + -- 1 : "less" or "more" + -- 2 : [target level]-[player level] limit + RelativeLevel = function(condition) + local difference + local target = getTarget(condition.target) + if UnitLevel(target) == -1 then + difference = 3 + else + difference = UnitLevel(target) - UnitLevel("player") + end + + return compare(difference, condition[1], condition[2]) + end, + remainingCastTime = function(condition) + local name, nameSubtext, text, texture, startTime, endTime, isTradeSkill, castID, notInterruptible = UnitCastingInfo(getTarget(condition.target)) + if not endTime then + return nil + end + return 0, endTime/1000, -1 + end, + Runes = function(condition) + return GetRune(condition) + end, + runes = function(condition) + local ret = GetRune(condition) + if not ret then + return nil + end + if ret < OvaleState.maintenant then + ret = OvaleState.maintenant + end + return 0, ret, -1 + end, + SoulShards = function(condition) + return compare(OvaleState.state.shard, condition[1], condition[2]) + end, + soulShards = function(condition) + return OvaleState.state.shard + end, + Speed = function(condition) + return compare(GetUnitSpeed(getTarget(condition.target))*100/7, condition[1], condition[2]) + end, + speed = function(condition) + return GetUnitSpeed(getTarget(condition.target))*100/7 + end, + spell = function(condition) + local actionCooldownStart, actionCooldownDuration, actionEnable = OvaleData:GetComputedSpellCD(condition[1]) + return actionCooldownDuration, actionCooldownStart, -1 + end, + spellPower = function(condition) + return GetSpellBonusDamage(2), 0, 0 + end, + -- Test if the player is in a given stance + -- 1 : the stance + Stance = function(condition) + if (GetShapeshiftForm(true) == condition[1]) then + return 0 + else + return nil + end + end, + Stealthed = function(condition) + return testbool(IsStealthed(), condition[1]) + end, + -- Test how many talent points has been spent in a talent + -- 1 : the talent identifier (use /script print(OvaleData.talentNameToId["Talent name"]) to retreive) + -- 2 : "more" or "less" + -- 3 : the limit + TalentPoints = function(condition) + return compare(OvaleData:GetTalentPoints(condition[1]), condition[2], condition[3]) + end, + talentPoints = function(condition) + return OvaleData:GetTalentPoints(condition[1]), 0, 0 + end, + -- Test if the target's target is the player (or is not) + -- 1 : "yes" (it should be the player) or "no" + TargetIsPlayer = function(condition) + return testbool(UnitIsUnit("player",getTarget(condition.target).."target"), condition[1]) + end, + Threat = function(condition) + local isTanking, status, threatpct = UnitDetailedThreatSituation("player", getTarget(condition.target)) + return compare(threatpct, condition[1], condition[2]) + end, + threat = function(condition) + local isTanking, status, threatpct = UnitDetailedThreatSituation("player", getTarget(condition.target)) + return threatpct + end, + TimeInCombat = function(condition) + if not Ovale.combatStartTime then + return nil + elseif condition[1] == "more" then + return Ovale.combatStartTime + condition[2] + else + return 0, Ovale.combatStartTime + condition[2] + end + end, + timeInCombat = function(condition) + return OvaleState.maintenant - Ovale.combatStartTime, OvaleState.maintenant, 1 + end, + timeToDie = function(condition) + return 0, getTargetDead(getTarget(condition.target)), -1 + end, + timeWithHaste = function(condition) + return avecHate(condition[1], "spell"),0,0 + end, + TotemExpires = function(condition) + if type(condition[1]) ~= "number" then + condition[1] = totemType[condition[1]] + end + + local haveTotem, totemName, startTime, duration = GetTotemInfo(condition[1]) + if not startTime then + return 0 + end + if (condition.totem and OvaleData:GetSpellInfoOrNil(condition.totem)~=totemName) then + return 0 + end + return addTime(startTime + duration, -(condition[2] or 0)) + end, + TotemPresent = function(condition) + if type(condition[1]) ~= "number" then + condition[1] = totemType[condition[1]] + end + + local haveTotem, totemName, startTime, duration = GetTotemInfo(condition[1]) + if not startTime then + return nil + end + if (condition.totem and OvaleData:GetSpellInfoOrNil(condition.totem)~=totemName) then + return nil + end + return startTime, startTime + duration + end, + Tracking = function(condition) + local what = OvaleData:GetSpellInfoOrNil(condition[1]) + local numTrackingTypes = GetNumTrackingTypes() + local present = false + for i=1,numTrackingTypes do + local name, texture, active = GetTrackingInfo(i) + if name == what then + present = (active == 1) + break + end + end + return testbool(present, condition[2]) + end, + WeaponEnchantExpires = function(condition) + local hasMainHandEnchant, mainHandExpiration, mainHandCharges, hasOffHandEnchant, offHandExpiration, offHandCharges = GetWeaponEnchantInfo() + if (condition[1] == "mainhand") then + if (not hasMainHandEnchant) then + return 0 + end + mainHandExpiration = mainHandExpiration/1000 + if ((condition[2] or 0) >= mainHandExpiration) then + return 0 + else + return OvaleState.maintenant + mainHandExpiration - condition[2] + end + else + if (not hasOffHandEnchant) then + return 0 + end + offHandExpiration = offHandExpiration/1000 + if ((condition[2] or 0) >= offHandExpiration) then + return 0 + else + return OvaleState.maintenant + offHandExpiration - condition[2] + end + end + end, +} + +OvaleCondition.conditions.health = OvaleCondition.conditions.life +OvaleCondition.conditions.Health = OvaleCondition.conditions.Life +OvaleCondition.conditions.healthPercent = OvaleCondition.conditions.lifePercent +OvaleCondition.conditions.HealthPercent = OvaleCondition.conditions.LifePercent +OvaleCondition.conditions.HealthMissing = OvaleCondition.conditions.LifeMissing +OvaleCondition.defaultTarget = "target" + +-- diff --git a/OvaleData.lua b/OvaleData.lua new file mode 100644 index 0000000..65ec761 --- /dev/null +++ b/OvaleData.lua @@ -0,0 +1,427 @@ +OvaleData = LibStub("AceAddon-3.0"):NewAddon("OvaleData", "AceEvent-3.0") + +-- +OvaleData.spellList = {} +OvaleData.firstInit = false +OvaleData.className = nil +OvaleData.spellInfo = {} +--allows to fill the player talent tables on first use +OvaleData.listeTalentsRemplie = false +--key: talentId / value: points in this talent +OvaleData.pointsTalent = {} +--key: talentId / value: talent name (not used) +OvaleData.talentIdToName = {} +--key: talent name / value: talent id +OvaleData.talentNameToId = {} +--spell info from the current script (by spellId) +OvaleData.spellInfo = {} +--spells that count for scoring +OvaleData.scoreSpell = {} + +-- List haste buff that does not appear in the character sheet and that are not raid wide buffs +OvaleData.selfHasteBuff = +{ + [53657] = 9, -- Judgement of the pure + [49016] = 20 -- Unholy Frenzy +} + +-- List temporary damage multiplier +OvaleData.selfDamageBuff = +{ + [5217] = 1.15, -- Tiger's fury + [57933] = 1.15 -- Tricks of the trade +} + +OvaleData.buffSpellList = +{ + fear = + { + 5782, -- Fear + 5484, -- Howl of terror + 5246, -- Intimidating Shout + 8122, -- Psychic scream + }, + root = + { + 23694, -- Improved Hamstring + 339, -- Entangling Roots + 122, -- Frost Nova + 47168, -- Improved Wing Clip + }, + incapacitate = + { + 6770, -- Sap + 12540, -- Gouge + 20066, -- Repentance + }, + stun = + { + 5211, -- Bash + 44415, -- Blackout + 6409, -- Cheap Shot + 22427, -- Concussion Blow + 853, -- Hammer of Justice + 408, -- Kidney Shot + 46968, -- Shockwave + }, + strengthagility= + { + 6673, -- Battle Shout + 8076, -- Strength of Earth + 57330, -- Horn of Winter + 93435 --Roar of Courage (Cat, Spirit Beast) + }, + stamina = + { + 21562, -- Fortitude TODO: vérifier + 469, -- Commanding Shout + 6307, -- Blood Pact + 90364 -- Qiraji Fortitude + }, + lowerarmor= + { + 58567, -- Sunder Armor (x3) + 8647, -- Expose Armor + 91565, -- Faerie Fire (x3) + 35387, --Corrosive Spit (x3 Serpent) + 50498 --Tear Armor (x3 Raptor) + }, + magicaldamagetaken= + { + 65142, -- Ebon Plague + 60433, -- Earth and Moon + 93068, -- Master Poisoner + 1490, -- Curse of the Elements + 85547, -- Jinx 1 + 86105, -- Jinx 2 + 34889, --Fire Breath (Dragonhawk) + 24844 --Lightning Breath (Wind serpent) + }, + magicalcrittaken= + { + 17800, -- Shadow and Flame + 22959 -- Critical Mass + }, + physicaldamagetaken= + { + 30069, -- Blood Frenzy (rank 1) + 30070, -- Blood Frenzy (rank 2) + 81327, -- Brittle Bones (rank 1) + 81328, -- Brittle Bones (rank 2) + 58684, -- Savage Combat (rank 1) + 58683, -- Savage Combat (rank 2) + 55749, -- Acid Spit (Worm) + 50518, -- Ravage (Ravager) + }, + lowerphysicaldamage= + { + 99, -- Demoralizing Roar + 702, -- Curse of Weakness + 1160, -- Demoralizing Shout + 26017, -- Vindication + 81130, -- Scarlet Fever + 50256, --Demoralizing Roar (Bear) + 24423, -- Demoralizing Screech (Carrion Bird) + }, + meleeslow= + { + 55095, --Icy Touch + 58179, --Infected Wounds rank 1 + 58180, --Infected Wounds rank 2 + 68055, --Judgments of the just + 6343, --Thunderclap + 8042, --Earth Shock + 54404, --Dust Cloud (Tallstrider) + 90315, -- Tailspin (Fox) + }, + castslow = + { + 1714, --Curse of Tongues + 58604, --Lava Breath (Core Hound) + 50274, --Spore Cloud (Sporebat) + 5761, --Mind-numbing Poison + 73975, --Necrotic Strike + 31589 --Slow + }, + bleed= + { + 33876, --Mangle cat + 33878, --Mangle bear + 46856, -- Trauma rank 1 + 46857, -- Trauma rank 2 + 16511, --Hemorrhage + 50271, --Tendon Rip (Hyena) + 35290 --Gore (Boar) + }, + heroism= + { + 2825, --Bloodlust + 32182, --Heroism + 80353, --Time warp + 90355 -- Ancient Hysteria (Core Hound) + }, + meleehaste = + { + 8515, -- Windfury + 55610, -- Improved Icy Talons + 53290 -- Hunting Party + }, + spellhaste = + { + 24907, -- Moonkin aura + 2895, -- Wrath of Air Totem + 49868 -- Mind Quickening + }, + enrage = + { + 49016, -- Unholy Frenzy + 18499, -- Berserker Rage + 12292, -- Death Wish + 12880, -- Enrage (rank 1) + 14201, -- Enrage (rank 2) + 14202, -- Enrage (rank 3) + 5229, -- Enrage (Bear) + 52610, -- Savage Roar (Cat) + 76691, -- Vengeance (All Tank Specs) + }, + criticalstrike = + { + 51740, -- Elemental Oath + 51698, -- Honor Among Thieves (rank 1) + 51700, -- Honor Among Thieves (rank 2) + 51701, -- Honor Among Thieves (rank 3) + 17007, -- Leader of the Pack + 29801, -- Rampage + 24604, -- Furious Howl (Wolf) + 90309, -- Terrifying Roar (Devilsaur) + } +} +-- + +-- +local fearSpellList = nil +local stunSpellList = nil +local incapacitateSpellList = nil +local rootSpellList = nil +-- + +-- +function OvaleData:OnEnable() + self:FirstInit() + self:RegisterEvent("PLAYER_TALENT_UPDATE") + self:RegisterEvent("CHARACTER_POINTS_CHANGED") + self:RegisterEvent("SPELLS_CHANGED") +end + +function OvaleData:OnDisable() + self:UnregisterEvent("SPELLS_CHANGED") + self:UnregisterEvent("PLAYER_TALENT_UPDATE") + self:UnregisterEvent("CHARACTER_POINTS_CHANGED") +end + +function OvaleData:CHARACTER_POINTS_CHANGED() + self:RemplirListeTalents() +-- Ovale:Print("CHARACTER_POINTS_CHANGED") +end + +function OvaleData:PLAYER_TALENT_UPDATE() + self:RemplirListeTalents() +-- Ovale:Print("PLAYER_TALENT_UPDATE") +end + +--The user learnt a new spell +function OvaleData:SPELLS_CHANGED() + self:FillSpellList() + Ovale.needCompile = true +end + +function OvaleData:GetRootSpellList() + if rootSpellList then + return rootSpellList + end + rootSpellList = {} + for k, v in pairs(self.buffSpellList.fear) do + rootSpellList[v] = true + end + return rootSpellList +end + +function OvaleData:GetStunSpellList() + if stunSpellList then + return stunSpellList + end + stunSpellList = {} + for k, v in pairs(self.buffSpellList.stun) do + stunListList[v] = true + end + return stunSpellList +end + +function OvaleData:GetIncapacitateSpellList() + if incapacitateSpellList then + return incapacitateSpellList + end + incapacitateSpellList = {} + for k, v in pairs(self.buffSpellList.incapacitate) do + incapacitateSpellList[v] = true + end + return incapacitateSpellList +end + +function OvaleData:GetFearSpellList() + if fearSpellList then + return fearSpellList + end + fearSpellList = {} + for k, v in pairs(self.buffSpellList.fear) do + fearSpellList[v] = true + end + return fearSpellList +end + + +function OvaleData:GetSpellInfoOrNil(spell) + if (spell) then + return GetSpellInfo(spell) + else + return nil + end +end + +function OvaleData:FillSpellList() + self.spellList = {} + local book=BOOKTYPE_SPELL + while true do + local i=1 + while true do + local skillType, spellId = GetSpellBookItemInfo(i, book) + if not spellId then + break + end + if skillType~="FUTURESPELL" then + local spellName = GetSpellBookItemName(i, book) + self.spellList[spellId] = spellName + end + i = i + 1 + end + if book==BOOKTYPE_SPELL then + book = BOOKTYPE_PET + else + break + end + end +end + +function OvaleData:RemplirListeTalents() + local numTabs = GetNumTalentTabs(); + for t=1, numTabs do + local numTalents = GetNumTalents(t); + for i=1, numTalents do + local nameTalent, icon, tier, column, currRank, maxRank = GetTalentInfo(t,i); + local link = GetTalentLink(t,i) + if link then + local a, b, talentId = string.find(link, "talent:(%d+)"); + talentId = tonumber(talentId) + self.talentIdToName[talentId] = nameTalent + self.talentNameToId[nameTalent] = talentId + self.pointsTalent[talentId] = currRank + self.listeTalentsRemplie = true + Ovale.needCompile = true + end + end + end +end + +function OvaleData:FirstInit() + if self.firstInit then + return + end + + self.firstInit = true + + local playerClass, englishClass = UnitClass("player") + self.className = englishClass + + self:RemplirListeTalents() + self:FillSpellList() +end + +function OvaleData:GetTalentPoints(talentId) + if not self.listeTalentsRemplie then + self:RemplirListeTalents() + end + return self.pointsTalent[talentId] +end + +function OvaleData:GetSpellInfo(spellId) + if (not self.spellInfo[spellId]) then + self.spellInfo[spellId] = { aura = {player = {}, target = {}} } + end + return self.spellInfo[spellId] +end + +function OvaleData:ResetSpellInfo() + self.spellInfo = {} +end + +function OvaleData:GetGCD(spellId) + if spellId and self.spellInfo[spellId] then + if self.spellInfo[spellId].haste == "spell" then + local cd = self.spellInfo[spellId].gcd + if not cd then + cd = 1.5 + end + cd = cd / OvaleAura.spellHaste + if (cd<1) then + cd = 1 + end + return cd + elseif self.spellInfo[spellId].gcd then + return self.spellInfo[spellId].gcd + end + end + + -- Default value + if self.className == "ROGUE" or (self.className == "DRUID" and GetShapeshiftForm(true) == 3) then + return 1.0 + elseif self.className == "MAGE" or self.className == "WARLOCK" or self.className == "PRIEST" or + (self.className == "DRUID" and GetShapeshiftForm(true) ~= 1) then + local cd = 1.5 / OvaleAura.spellHaste + if (cd<1) then + cd = 1 + end + return cd + else + return 1.5 + end +end + + +--Compute the spell Cooldown +function OvaleData:GetComputedSpellCD(spellId) + local actionCooldownStart, actionCooldownDuration, actionEnable + local cd = OvaleState:GetCD(spellId) + if cd and cd.start then + actionCooldownStart = cd.start + actionCooldownDuration = cd.duration + actionEnable = cd.enable + else + actionCooldownStart, actionCooldownDuration, actionEnable = GetSpellCooldown(spellId) + -- Les chevaliers de la mort ont des infos fausses sur le CD quand ils n'ont plus les runes + -- On force à 1,5s ou 1s en présence impie + if self.className=="DEATHKNIGHT" and actionCooldownDuration==10 and + (not self.spellInfo[spellId] or self.spellInfo[spellId].cd~=10) then + local impie = GetSpellInfo(48265) + if impie and UnitBuff("player", impie) then + actionCooldownDuration=1 + else + actionCooldownDuration=1.5 + end + end + if self.spellInfo[spellId] and self.spellInfo[spellId].forcecd then + actionCooldownStart, actionCooldownDuration = GetSpellCooldown(self.spellInfo[spellId].forcecd) + end + end + return actionCooldownStart, actionCooldownDuration, actionEnable +end +-- diff --git a/OvaleEnemies.lua b/OvaleEnemies.lua new file mode 100644 index 0000000..322f346 --- /dev/null +++ b/OvaleEnemies.lua @@ -0,0 +1,65 @@ +-- Gather information about ennemies + +OvaleEnemies = LibStub("AceAddon-3.0"):NewAddon("OvaleEnemies", "AceEvent-3.0") + +-- +OvaleEnemies.numberOfEnemies = 0 +OvaleEnemies.enemies = {} +-- + +-- +-- Events +function OvaleEnemies:OnEnable() + self:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED") + self:RegisterEvent("PLAYER_REGEN_DISABLED") +end + +function OvaleEnemies:OnDisable() + self:UnregisterEvent("COMBAT_LOG_EVENT_UNFILTERED") + self:UnregisterEvent("PLAYER_REGEN_DISABLED") +end + +function OvaleEnemies:COMBAT_LOG_EVENT_UNFILTERED(event, ...) + local time, event, hideCaster, sourceGUID, sourceName, sourceFlags, sourceRaidFlags, destGUID, destName, destFlags, destRaidFlags = select(1, ...) + + if event == "UNIT_DIED" then + for k,v in pairs(self.enemies) do + if k==destGUID then + self.enemies[v] = nil + self.numberOfEnemies = self.numberOfEnemies - 1 + Ovale.refreshNeeded["player"] = true + --Ovale:Print("enemy die") + end + end + elseif sourceFlags and not self.enemies[sourceGUID] and bit.band(sourceFlags, COMBATLOG_OBJECT_REACTION_HOSTILE)>0 + and bit.band(sourceFlags, COMBATLOG_OBJECT_AFFILIATION_OUTSIDER) > 0 and + destFlags and bit.band(destFlags, COMBATLOG_OBJECT_AFFILIATION_OUTSIDER) == 0 then + self.enemies[sourceGUID] = true + --Ovale:Print("new ennemy source=".. sourceName) + self.numberOfEnemies = self.numberOfEnemies + 1 + Ovale.refreshNeeded["player"] = true + elseif destGUID and not self.enemies[destGUID] and bit.band(destFlags, COMBATLOG_OBJECT_REACTION_HOSTILE)>0 + and bit.band(destFlags, COMBATLOG_OBJECT_AFFILIATION_OUTSIDER) > 0 and + sourceFlags and bit.band(sourceFlags, COMBATLOG_OBJECT_AFFILIATION_OUTSIDER) == 0 then + self.enemies[destGUID] = true + --Ovale:Print("new ennemy dest=".. destName) + self.numberOfEnemies = self.numberOfEnemies + 1 + Ovale.refreshNeeded["player"] = true + end +end + +function OvaleEnemies:PLAYER_REGEN_DISABLED() + if self.numberOfEnemies then + self.numberOfEnemies = 0 + self.enemies = {} + end +end + +function OvaleEnemies:GetNumberOfEnemies() + if not self.numberOfEnemies then + self.numberOfEnemies = 0 + end + return self.numberOfEnemies +end +-- + diff --git a/OvaleEquipement.lua b/OvaleEquipement.lua index 5da7bed..7eead27 100644 --- a/OvaleEquipement.lua +++ b/OvaleEquipement.lua @@ -1,6 +1,10 @@ OvaleEquipement = LibStub("AceAddon-3.0"):NewAddon("OvaleEquipement", "AceEvent-3.0") +-- OvaleEquipement.nombre = {} +-- + +-- function OvaleEquipement:OnEnable() self:RegisterEvent("UNIT_INVENTORY_CHANGED") @@ -265,4 +269,7 @@ end function OvaleEquipement:PLAYER_ENTERING_WORLD(event) self:Refresh() -end \ No newline at end of file +end + +-- + diff --git a/OvaleFrame.lua b/OvaleFrame.lua index 6e45dff..e4f0121 100644 --- a/OvaleFrame.lua +++ b/OvaleFrame.lua @@ -1,60 +1,56 @@ -local AceGUI = LibStub("AceGUI-3.0") -local Masque = LibStub("Masque", true) - -local GetTime = GetTime - ----------------- --- Main Frame -- ----------------- ---[[ - Events : - OnClose - -]] +--inherits Frame do +-- + local AceGUI = LibStub("AceGUI-3.0") + local Masque = LibStub("Masque", true) + local GetTime = GetTime + local Type = "OvaleFrame" local Version = 7 +-- - local function frameOnClose(this) - this.obj:Fire("OnClose") +-- + local function frameOnClose(self) + self.obj:Fire("OnClose") end - local function closeOnClick(this) - this.obj:Hide() + local function closeOnClick(self) + self.obj:Hide() end - local function frameOnMouseDown(this) - if (not Ovale.db.profile.apparence.verrouille) then - this:StartMoving() + local function frameOnMouseDown(self) + if (not OvaleOptions:GetApparence().verrouille) then + self:StartMoving() AceGUI:ClearFocus() end end - local function ToggleOptions(this) - if (this.content:IsShown()) then - this.content:Hide() + local function ToggleOptions(self) + if (self.content:IsShown()) then + self.content:Hide() else - this.content:Show() + self.content:Show() end end - local function frameOnMouseUp(this) - this:StopMovingOrSizing() + local function frameOnMouseUp(self) + self:StopMovingOrSizing() + local profile = OvaleOptions:GetProfile() - if (Ovale.db.profile.left~=this:GetLeft() or Ovale.db.profile.top ~=this:GetTop()) then - Ovale.db.profile.left = this:GetLeft() - Ovale.db.profile.top = this:GetTop() + if (profile.left~=self:GetLeft() or profile.top ~=self:GetTop()) then + profile.left = self:GetLeft() + profile.top = self:GetTop() end end - local function frameOnEnter(this) - if (not Ovale.db.profile.apparence.verrouille) then - this.obj.barre:Show() - end + local function frameOnEnter(self) + if (not OvaleOptions:GetApparence().verrouille) then + self.obj.barre:Show() + end end - local function frameOnLeave(this) - this.obj.barre:Hide() + local function frameOnLeave(self) + self.obj.barre:Hide() end @@ -113,7 +109,7 @@ do -- print("sort "..spellId.." parfait") return 1 else - local lag = Ovale.maintenant - action.waitStart + local lag = OvaleState.maintenant - action.waitStart if lag>5 then -- print("sort "..spellId.." ignoré (>5s)") return nil @@ -135,8 +131,8 @@ do end local function OnUpdate(self) - if not Ovale.listeTalentsRemplie then - Ovale:RemplirListeTalents() + if not OvaleData.listeTalentsRemplie then + OvaleData:RemplirListeTalents() end if Ovale.needCompile then Ovale:CompileAll() @@ -144,110 +140,121 @@ do end local now = GetTime() - - if not Ovale.refreshNeeded and self.lastUpdate and now < self.lastUpdate + Ovale.db.profile.apparence.updateInterval then + local forceRefresh = not self.lastUpdate or (now > self.lastUpdate + OvaleOptions:GetApparence().updateInterval) + + if not next(Ovale.refreshNeeded) and not forceRefresh then return end - Ovale.refreshNeeded = false self.lastUpdate = now - Ovale:InitAllActions() + OvaleState:StartNewFrame() for k,node in pairs(Ovale.masterNodes) do - if Ovale.trace then - Ovale:Print("****Master Node "..k) - end - Ovale:InitCalculerMeilleureAction() - local start, ending, priorite, element = Ovale:CalculerMeilleureAction(node) - if start then - Ovale:Log("CalculerMeilleureAction start = "..start) - end - local action = self.actions[k] - if element and element.type == "value" then - local actionTexture - if node.params.texture then - actionTexture = GetSpellTexture(node.params.texture) - end - local value - if element.value and element.origin and element.rate then - value = element.value + (Ovale.maintenant - element.origin) * element.rate + local target = node.params.target or "target" + OvaleCondition.defaultTarget = target + + if forceRefresh or Ovale.refreshNeeded[target] or Ovale.refreshNeeded["player"] or Ovale.refreshNeeded["pet"] then + if Ovale.trace then + Ovale:Print("****Master Node "..k) end - action.icons[1]:SetValue(value, actionTexture) - if #action.icons > 1 then - action.icons[2]:Update(element, nil) + OvaleBestAction:StartNewAction() + local start, ending, priorite, element = OvaleBestAction:Compute(node) + if start then + Ovale:Log("Compute start = "..start) end - else - local actionTexture, actionInRange, actionCooldownStart, actionCooldownDuration, - actionUsable, actionShortcut, actionIsCurrent, actionEnable, spellId, actionTarget, noRed = Ovale:GetActionInfo(element) - if noRed then - start = actionCooldownStart + actionCooldownDuration - if start < Ovale.currentTime then - start = Ovale.currentTime + local action = self.actions[k] + if element and element.type == "value" then + local actionTexture + if node.params.texture then + actionTexture = GetSpellTexture(node.params.texture) end - end - - -- Dans le cas de canStopChannelling, on risque de demander d'interrompre le channelling courant, ce qui est stupide - if start and Ovale.currentSpellId and Ovale.attenteFinCast and spellId == Ovale.currentSpellId and start 1 then + action.icons[2]:Update(element, nil) end else - action.waitStart = nil - end - - if Ovale.db.profile.apparence.moving and action.icons[1].debutAction and action.icons[1].finAction then - local top=1-(Ovale.maintenant - action.icons[1].debutAction)/(action.icons[1].finAction-action.icons[1].debutAction) - if top<0 then - top = 0 - elseif top>1 then - top = 1 + local actionTexture, actionInRange, actionCooldownStart, actionCooldownDuration, + actionUsable, actionShortcut, actionIsCurrent, actionEnable, spellId, actionTarget, noRed = OvaleBestAction:GetActionInfo(element) + if noRed then + start = actionCooldownStart + actionCooldownDuration + if start < OvaleState.currentTime then + start = OvaleState.currentTime + end end - action.icons[1]:SetPoint("TOPLEFT",self.frame,"TOPLEFT",(action.left + top*action.dx)/action.scale,(action.top - top*action.dy)/action.scale) - if action.icons[2] then - action.icons[2]:SetPoint("TOPLEFT",self.frame,"TOPLEFT",(action.left + (top+1)*action.dx)/action.scale,(action.top - (top+1)*action.dy)/action.scale) + + -- Dans le cas de canStopChannelling, on risque de demander d'interrompre le channelling courant, ce qui est stupide + if start and OvaleState.currentSpellId and OvaleState.attenteFinCast and spellId == OvaleState.currentSpellId and start0 then - castTime = _castTime/1000 - end + + if (node.params.nocd and start~=nil and OvaleState.maintenantgcd) then - nextCast = start + castTime + else + action.waitStart = nil + end + + if OvaleOptions:GetApparence().moving and action.icons[1].debutAction and action.icons[1].finAction then + local top=1-(OvaleState.maintenant - action.icons[1].debutAction)/(action.icons[1].finAction-action.icons[1].debutAction) + if top<0 then + top = 0 + elseif top>1 then + top = 1 + end + action.icons[1]:SetPoint("TOPLEFT",self.frame,"TOPLEFT",(action.left + top*action.dx)/action.scale,(action.top - top*action.dy)/action.scale) + if action.icons[2] then + action.icons[2]:SetPoint("TOPLEFT",self.frame,"TOPLEFT",(action.left + (top+1)*action.dx)/action.scale,(action.top - (top+1)*action.dy)/action.scale) + end + end + + if (node.params.size ~= "small" and not node.params.nocd and OvaleOptions:GetApparence().predictif) then + if start then + local castTime=0 + if spellId then + local _, _, _, _, _, _, _castTime = GetSpellInfo(spellId) + if _castTime and _castTime>0 then + castTime = _castTime/1000 + end + end + local gcd = OvaleData:GetGCD(spellId) + local nextCast + if (castTime>gcd) then + nextCast = start + castTime + else + nextCast = start + gcd + end + if Ovale.trace then + Ovale:Print("****Second icon " .. start) + end + local spellTarget = element.params.target + if spellTarget == "target" or not spellTarget then + spellTarget = target + end + OvaleState:AddSpellToStack(spellId, start, start + castTime, nextCast, false, UnitGUID(spellTarget)) + start, ending, priorite, element = OvaleBestAction:Compute(node) + action.icons[2]:Update(element, start, OvaleBestAction:GetActionInfo(element)) else - nextCast = start + gcd - end - if Ovale.trace then - Ovale:Print("****Second icon " .. start) + action.icons[2]:Update(element, nil) end - Ovale:AddSpellToStack(spellId, start, start + castTime, nextCast) - start, ending, priorite, element = Ovale:CalculerMeilleureAction(node) - action.icons[2]:Update(element, start, Ovale:GetActionInfo(element)) - else - action.icons[2]:Update(element, nil) end end end end + + Ovale.refreshNeeded = {} if (not Ovale.bug) then Ovale.traced = false @@ -270,7 +277,7 @@ do end end - self.frame:EnableMouse(not Ovale.db.profile.apparence.clickThru) + self.frame:EnableMouse(not OvaleOptions:GetApparence().clickThru) local left = 0 local maxHeight = 0 @@ -283,7 +290,7 @@ do local BARRE = 8 - local margin = Ovale.db.profile.apparence.margin + local margin = OvaleOptions:GetApparence().margin for k,node in pairs(Ovale.masterNodes) do if not self.actions[k] then @@ -294,27 +301,27 @@ do local width, height, newScale local nbIcons if (node.params.size == "small") then - newScale = Ovale.db.profile.apparence.smallIconScale + newScale = OvaleOptions:GetApparence().smallIconScale width = newScale * 36 + margin height = newScale * 36 + margin nbIcons = 1 else - newScale = Ovale.db.profile.apparence.iconScale + newScale = OvaleOptions:GetApparence().iconScale width =newScale * 36 + margin height = newScale * 36 + margin - if Ovale.db.profile.apparence.predictif and node.params.type ~= "value" then + if OvaleOptions:GetApparence().predictif and node.params.type ~= "value" then nbIcons = 2 else nbIcons = 1 end end - if (top + height > Ovale.db.profile.apparence.iconScale * 36 + margin) then + if (top + height > OvaleOptions:GetApparence().iconScale * 36 + margin) then top = 0 left = maxWidth end action.scale = newScale - if (Ovale.db.profile.apparence.vertical) then + if (OvaleOptions:GetApparence().vertical) then action.left = top action.top = -left-BARRE-margin action.dx = width @@ -333,15 +340,15 @@ do local icon = action.icons[l] local scale = action.scale if l> 1 then - scale = scale * Ovale.db.profile.apparence.secondIconScale + scale = scale * OvaleOptions:GetApparence().secondIconScale end icon:SetPoint("TOPLEFT",self.frame,"TOPLEFT",(action.left + (l-1)*action.dx)/scale,(action.top - (l-1)*action.dy)/scale) icon:SetScale(scale) - icon:SetFontScale(Ovale.db.profile.apparence.fontScale) + icon:SetFontScale(OvaleOptions:GetApparence().fontScale) icon:SetParams(node.params) icon:SetHelp(node.params.help) - icon:SetRangeIndicator(Ovale.db.profile.apparence.targetText) - icon:EnableMouse(not Ovale.db.profile.apparence.clickThru) + icon:SetRangeIndicator(OvaleOptions:GetApparence().targetText) + icon:EnableMouse(not OvaleOptions:GetApparence().clickThru) icon.cdShown = (l == 1) if Masque then self.skinGroup:AddButton(icon) @@ -360,18 +367,18 @@ do end end - if (Ovale.db.profile.apparence.vertical) then + if (OvaleOptions:GetApparence().vertical) then self.barre:SetWidth(maxHeight - margin) self.barre:SetHeight(BARRE) - self.frame:SetWidth(maxHeight + Ovale.db.profile.apparence.iconShiftY) - self.frame:SetHeight(maxWidth+BARRE+margin + Ovale.db.profile.apparence.iconShiftX) - self.content:SetPoint("TOPLEFT",self.frame,"TOPLEFT",maxHeight + Ovale.db.profile.apparence.iconShiftX,Ovale.db.profile.apparence.iconShiftY) + self.frame:SetWidth(maxHeight + OvaleOptions:GetApparence().iconShiftY) + self.frame:SetHeight(maxWidth+BARRE+margin + OvaleOptions:GetApparence().iconShiftX) + self.content:SetPoint("TOPLEFT",self.frame,"TOPLEFT",maxHeight + OvaleOptions:GetApparence().iconShiftX,OvaleOptions:GetApparence().iconShiftY) else self.barre:SetWidth(maxWidth - margin) self.barre:SetHeight(BARRE) - self.frame:SetWidth(maxWidth) -- + Ovale.db.profile.apparence.iconShiftX - self.frame:SetHeight(maxHeight+BARRE+margin) -- + Ovale.db.profile.apparence.iconShiftY - self.content:SetPoint("TOPLEFT",self.frame,"TOPLEFT",maxWidth + Ovale.db.profile.apparence.iconShiftX,Ovale.db.profile.apparence.iconShiftY) + self.frame:SetWidth(maxWidth) -- + OvaleOptions:GetApparence().iconShiftX + self.frame:SetHeight(maxHeight+BARRE+margin) -- + OvaleOptions:GetApparence().iconShiftY + self.content:SetPoint("TOPLEFT",self.frame,"TOPLEFT",maxWidth + OvaleOptions:GetApparence().iconShiftX,OvaleOptions:GetApparence().iconShiftY) end end @@ -379,7 +386,6 @@ do local frame = CreateFrame("Frame",nil,UIParent) local self = {} - self.type = "Frame" self.Hide = Hide self.Show = Show @@ -392,17 +398,29 @@ do self.ToggleOptions = ToggleOptions self.OnUpdate = OnUpdate self.GetScore = GetScore - + +-- + self.type = "Frame" self.localstatus = {} self.actions = {} - - self.frame = frame + self.updateFrame = CreateFrame("Frame") + self.barre = self.frame:CreateTexture(); + self.content = CreateFrame("Frame",nil,frame) + if Masque then + self.skinGroup = Masque:Group("Ovale") + end + self.lastUpdate = nil + --Cheating with frame object which has an obj property + --TODO: Frame Class + self.obj = nil +-- + frame.obj = self frame:SetWidth(100) frame:SetHeight(100) frame:SetPoint("CENTER",UIParent,"CENTER",0,0) - if not Ovale.db.profile.apparence.clickThru then + if not OvaleOptions:GetApparence().clickThru then frame:EnableMouse() end frame:SetMovable(true) @@ -413,34 +431,29 @@ do frame:SetScript("OnLeave", frameOnLeave) -- frame:SetScript("OnUpdate", frameOnUpdate) frame:SetScript("OnHide",frameOnClose) - frame:SetAlpha(Ovale.db.profile.apparence.alpha) + frame:SetAlpha(OvaleOptions:GetApparence().alpha) - self.updateFrame = CreateFrame("Frame") self.updateFrame:SetScript("OnUpdate", frameOnUpdate) self.updateFrame.obj = self - self.barre = self.frame:CreateTexture(); self.barre:SetTexture(0,0.8,0) self.barre:SetPoint("TOPLEFT",0,0) self.barre:Hide() --Container Support - local content = CreateFrame("Frame",nil,frame) - self.content = content + local content = self.content content.obj = self content:SetWidth(200) content:SetHeight(100) content:Hide() - content:SetAlpha(Ovale.db.profile.apparence.optionsAlpha) + content:SetAlpha(OvaleOptions:GetApparence().optionsAlpha) AceGUI:RegisterAsContainer(self) - if Masque then - self.skinGroup = Masque:Group("Ovale") - end return self end +-- AceGUI:RegisterWidgetType(Type,Constructor,Version) end diff --git a/OvaleFuture.lua b/OvaleFuture.lua new file mode 100644 index 0000000..362c7bc --- /dev/null +++ b/OvaleFuture.lua @@ -0,0 +1,306 @@ +-- The travelling missiles or spells that have been cast but whose effects were not still not applied + +OvaleFuture = LibStub("AceAddon-3.0"):NewAddon("OvaleFuture", "AceEvent-3.0") + +-- +--spell counter (see Counter function) +OvaleFuture.counter = {} +--the spells that the player has casted but that did not reach their target +--the result is computed by the simulator, allowing to ignore lag or missile travel time +OvaleFuture.lastSpell = {} +--the attack power of the last spell +OvaleFuture.lastSpellAP = {} +OvaleFuture.lastSpellSP = {} +OvaleFuture.lastSpellDM = {} +OvaleFuture.playerGUID = nil +OvaleFuture.nextSpellTarget = nil +OvaleFuture.nextSpellLineID = nil +-- + +-- Events +-- +function OvaleFuture:OnEnable() + self.playerGUID = UnitGUID("player") + self:RegisterEvent("UNIT_SPELLCAST_INTERRUPTED") + self:RegisterEvent("UNIT_SPELLCAST_SUCCEEDED") + self:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED") + self:RegisterEvent("UNIT_SPELLCAST_START") + self:RegisterEvent("UNIT_SPELLCAST_CHANNEL_START") + self:RegisterEvent("UNIT_SPELLCAST_CHANNEL_STOP") + self:RegisterEvent("UNIT_SPELLCAST_SENT") +end + +function OvaleFuture:OnDisable() + self:UnregisterEvent("UNIT_SPELLCAST_SUCCEEDED") + self:UnregisterEvent("COMBAT_LOG_EVENT_UNFILTERED") + self:UnregisterEvent("UNIT_SPELLCAST_INTERRUPTED") + self:UnregisterEvent("UNIT_SPELLCAST_CHANNEL_START") + self:UnregisterEvent("UNIT_SPELLCAST_CHANNEL_STOP") + self:UnregisterEvent("UNIT_SPELLCAST_START") + self:UnregisterEvent("UNIT_SPELLCAST_SENT") +end + + +function OvaleFuture:UNIT_SPELLCAST_CHANNEL_START(event, unit, name, rank, lineId, spellId) + if unit=="player" then + --Ovale:Print("UNIT_SPELLCAST_CHANNEL_START "..event.." name="..name.." lineId="..lineId.." spellId="..spellId .. " " .. GetTime()) + local _,_,_,_,startTime, endTime = UnitChannelInfo("player") + --Ovale:Print("startTime = " ..startTime.." endTime = "..endTime) + self:AddSpellToList(spellId, lineId, startTime/1000, endTime/1000, true, false) + end +end + +function OvaleFuture:UNIT_SPELLCAST_CHANNEL_STOP(event, unit, name, rank, lineId, spellId) + if unit == "player" then + --Ovale:Print("UNIT_SPELLCAST_CHANNEL_STOP "..event.." name="..name.." lineId="..lineId.." spellId="..spellId) + self:RemoveSpellFromList(spellId, lineId) + end +end + +--Called when a spell started its cast +function OvaleFuture:UNIT_SPELLCAST_START(event, unit, name, rank, lineId, spellId) + --Ovale:Print("UNIT_SPELLCAST_START "..event.." name="..name.." lineId="..lineId.." spellId="..spellId .. " time=" .. GetTime()) + if unit=="player" then + local _,_,_,_,startTime,endTime = UnitCastingInfo("player") + --local spell, rank, icon, cost, isFunnel, powerType, castTime, minRange, maxRange = GetSpellInfo(spellId) + --local startTime = GetTime() + --self:AddSpellToList(spellId, lineId, startTime, startTime + castTime/1000) + self:AddSpellToList(spellId, lineId, startTime/1000, endTime/1000, false, false) + end +end + +--Called if the player interrupted early his cast +--The spell is removed from the lastSpell table +function OvaleFuture:UNIT_SPELLCAST_INTERRUPTED(event, unit, name, rank, lineId, spellId) + if unit == "player" then + --Ovale:Print("UNIT_SPELLCAST_INTERRUPTED "..event.." name="..name.." lineId="..lineId.." spellId="..spellId.. " time="..GetTime()) + self:RemoveSpellFromList(spellId, lineId) + end +end + +function OvaleFuture:UNIT_SPELLCAST_SENT(event, unit, spell, rank, target, lineId) + if unit == "player" then + local targetGUID = OvaleGUID.nameToGUID[target] + self.nextSpellTarget = targetGUID + self.nextSpellLineID = lineId + --Ovale:Print(target) + for i,v in ipairs(self.lastSpell) do + if v.lineId == lineId then + v.target = targetGUID + end + end + end +end + +function OvaleFuture:UNIT_SPELLCAST_SUCCEEDED(event, unit, name, rank, lineId, spellId) + if unit == "player" then + --Ovale:Print("UNIT_SPELLCAST_SUCCEEDED "..event.." name="..name.." lineId="..lineId.." spellId="..spellId.. " time="..GetTime()) + for i,v in ipairs(self.lastSpell) do + if v.lineId == lineId then + --Already added in UNIT_SPELLCAST_START + v.allowRemove = true + return + end + end + if not UnitChannelInfo("player") then + --A UNIT_SPELLCAST_SUCCEEDED is received when channeling a spell, with a different lineId! + local now = GetTime() + self:AddSpellToList(spellId, lineId, now, now, false, true) + end + end +end + +function OvaleFuture:COMBAT_LOG_EVENT_UNFILTERED(event, ...) + local time, event, hideCaster, sourceGUID, sourceName, sourceFlags, sourceRaidFlags, destGUID, destName, destFlags, destRaidFlags = select(1, ...) + + --[[ + Sequence of events: + - casting a spell that damages + SPELL_CAST_START + SPELL_DAMAGE + - casting a spell that misses + SPELL_CAST_START + SPELL_MISSED + - casting a spell then interrupting it + SPELL_CAST_START + SPELL_CAST_FAILED + - casting an instant damaging spell + SPELL_CAST_SUCCESS + SPELL_DAMAGE + - chanelling a damaging spell + SPELL_CAST_SUCCESS + SPELL_AURA_APPLIED + SPELL_PERIODIC_DAMAGE + SPELL_PERIODIC_DAMAGE + SPELL_PERIODIC_DAMAGE + (interruption does not generate an event) + - refreshing a buff + SPELL_AURA_REFRESH + SPELL_CAST_SUCCESS + - removing a buff + SPELL_AURA_REMOVED + - casting a buff + SPELL_AURA_APPLIED + SPELL_CAST_SUCCESS + -casting a DOT that misses + SPELL_CAST_SUCCESS + SPELL_MISSED + - casting a DOT that damages + SPELL_CAST_SUCESS + SPELL_AURA_APPLIED + SPELL_PERIODIC_DAMAGE + SPELL_PERIODIC_DAMAGE]] + + if sourceGUID == self.playerGUID then + --Called when a missile reached or missed its target + --Update lastSpell accordingly + --Do not use SPELL_CAST_SUCCESS because it is sent when the missile has not reached the target + + --Ovale:Print("SPELL_CAST_START " .. GetTime()) + --if string.find(event, "SPELL") == 1 then + -- local spellId, spellName = select(12, ...) + -- Ovale:Print(event .. " " ..spellName .. " " ..GetTime()) + --end + -- local spellId, spellName = select(12, ...) + -- for i,v in ipairs(self.lastSpell) do + + -- end + --end + + if + string.find(event, "SPELL_AURA_APPLIED")==1 + or string.find(event, "SPELL_AURA_REFRESH")==1 + or string.find(event, "SPELL_DAMAGE")==1 + or string.find(event, "SPELL_MISSED") == 1 + or string.find(event, "SPELL_CAST_SUCCESS") == 1 + or string.find(event, "SPELL_CAST_FAILED") == 1 then + local spellId, spellName = select(12, ...) + for i,v in ipairs(self.lastSpell) do + if (v.spellId == spellId or v.auraSpellId == spellId) and v.allowRemove then + if not v.channeled and (v.removeOnSuccess or + string.find(event, "SPELL_CAST_SUCCESS") ~= 1) then + table.remove(self.lastSpell, i) + Ovale.refreshNeeded["player"] = true + --Ovale:Print("LOG_EVENT on supprime "..spellId.." a "..GetTime()) + end + --Ovale:Print(UnitDebuff("target", "Etreinte de l'ombre")) + break + end + end + end + end + +end + +function OvaleFuture:AddSpellToList(spellId, lineId, startTime, endTime, channeled, allowRemove) + local newSpell = {} + newSpell.spellId = spellId + newSpell.lineId = lineId + newSpell.start = startTime + newSpell.stop = endTime + newSpell.channeled = channeled + newSpell.allowRemove = allowRemove + --TODO unable to know what is the real target + if lineId == self.nextSpellLineID and self.nextSpellTarget then + newSpell.target = self.nextSpellTarget + else + newSpell.target = UnitGUID("target") + end + + self.lastSpellAP[spellId] = UnitAttackPower("player") + self.lastSpellSP[spellId] = GetSpellBonusDamage(2) + self.lastSpellDM[spellId] = OvaleAura.damageMultiplier + self.lastSpell[#self.lastSpell+1] = newSpell + --Ovale:Print("on ajoute "..spellId..": ".. newSpell.start.." to "..newSpell.stop.." ("..OvaleState.maintenant..")" ..#self.lastSpell .. " " ..newSpell.target) + + if OvaleData.spellInfo[spellId] then + local si = OvaleData.spellInfo[spellId] + + if si.aura then + for target, targetInfo in pairs(si.aura) do + for filter, filterInfo in pairs(targetInfo) do + for auraSpellId, spellData in pairs(filterInfo) do + if spellData and spellData ~= "refresh" and spellData > 0 then + newSpell.auraSpellId = auraSpellId + if target == "player" then + newSpell.removeOnSuccess = true + end + break + end + end + end + end + end + + --Ovale:Print("spellInfo found") + if si and si.buffnocd and UnitBuff("player", GetSpellInfo(si.buffnocd)) then + newSpell.nocd = true + else + newSpell.nocd = false + end + --Increase or reset the counter that is used by the Counter function + if si.resetcounter then + self.counter[si.resetcounter] = 0 + --Ovale:Print("reset counter "..si.resetcounter) + end + if si.inccounter then + local cname = si.inccounter + if not self.counter[cname] then + self.counter[cname] = 0 + end + self.counter[cname] = self.counter[cname] + 1 + --Ovale:Print("inc counter "..cname.." to "..self.counter[cname]) + end + else + newSpell.removeOnSuccess = true + end + + if Ovale.enCombat then + --Ovale:Print(tostring(OvaleData.scoreSpell[spellId])) + if (not OvaleData.spellInfo[spellId] or not OvaleData.spellInfo[spellId].toggle) and OvaleData.scoreSpell[spellId] then + --Compute the player score + local scored = Ovale.frame:GetScore(spellId) + --Ovale:Print("Scored "..scored) + if scored~=nil then + Ovale.score = Ovale.score + scored + Ovale.maxScore = Ovale.maxScore + 1 + Ovale:SendScoreToDamageMeter(UnitName("player"), OvaleAura.playerGUID, scored, 1) + end + end + end + Ovale.refreshNeeded["player"] = true +end + + +function OvaleFuture:RemoveSpellFromList(spellId, lineId) + for i,v in ipairs(self.lastSpell) do + if v.lineId == lineId then + table.remove(self.lastSpell, i) + --Ovale:Print("RemoveSpellFromList on supprime "..spellId) + break + end + end + Ovale.refreshNeeded["player"] = true +end + +-- Apply the effects of travelling spells +function OvaleFuture:Apply() + for i,v in ipairs(self.lastSpell) do + if not OvaleData.spellInfo[v.spellId] or not OvaleData.spellInfo[v.spellId].toggle then + --[[local spell, rank, displayName, icon, startTime, endTime, isTradeSkill = UnitCastingInfo("player") + if spell and spell == v.name and startTime/1000 - v.start < 0.5 and v.stop~=endTime/1000 then + print("ancien = "..v.stop) + v.stop = endTime/1000 + print("changement de v.stop en "..v.stop.." "..v.start) + end]] + Ovale:Log("OvaleState.maintenant = " ..OvaleState.maintenant.." spellId="..v.spellId.." v.stop="..v.stop) + if OvaleState.maintenant - v.stop < 5 then + OvaleState:AddSpellToStack(v.spellId, v.start, v.stop, v.stop, v.nocd, v.target) + else + --Ovale:Print("Removing obsolete "..v.spellId) + table.remove(self.lastSpell, i) + end + end + end +end +-- diff --git a/OvaleGUID.lua b/OvaleGUID.lua new file mode 100644 index 0000000..9cfb869 --- /dev/null +++ b/OvaleGUID.lua @@ -0,0 +1,134 @@ +-- This addon translates a GUID to a target name +-- Usage: OvaleGUID:GetUnitId(guid) + +OvaleGUID = LibStub("AceAddon-3.0"):NewAddon("OvaleGUID", "AceEvent-3.0", "AceConsole-3.0") + +-- +OvaleGUID.unitId = {} +OvaleGUID.guid = {} +OvaleGUID.player = nil +OvaleGUID.nameToGUID = {} +OvaleGUID.nameToUnit = {} +-- + +-- +function OvaleGUID:OnEnable() + self:Update("player") + self:RegisterEvent("PLAYER_LOGIN") + self:RegisterEvent("UNIT_TARGET") + self:RegisterEvent("PARTY_MEMBERS_CHANGED") + self:RegisterEvent("RAID_ROSTER_UPDATE") + self:RegisterEvent("UNIT_PET") + self:RegisterEvent("ARENA_OPPONENT_UPDATE") + self:RegisterEvent("PLAYER_FOCUS_CHANGED") + self:RegisterEvent("UPDATE_MOUSEOVER_UNIT") + self:RegisterEvent("INSTANCE_ENCOUNTER_ENGAGE_UNIT") +end + +function OvaleGUID:OnDisable() + self:UnregisterEvent("PLAYER_LOGIN") + self:UnregisterEvent("UNIT_TARGET") + self:UnregisterEvent("PARTY_MEMBERS_CHANGED") + self:UnregisterEvent("RAID_ROSTER_UPDATE") + self:UnregisterEvent("UNIT_PET") + self:UnregisterEvent("ARENA_OPPONENT_UPDATE") + self:UnregisterEvent("PLAYER_FOCUS_CHANGED") + self:UnregisterEvent("UPDATE_MOUSEOVER_UNIT") + self:UnregisterEvent("INSTANCE_ENCOUNTER_ENGAGE_UNIT") +end + +function OvaleGUID:Update(unitId) + local guid = UnitGUID(unitId) + local previousGuid = self.guid[unitId] + if unitId == "player" then + self.player = guid + end + if previousGuid ~= guid then + if previousGuid then + self.unitId[previousGuid][unitId] = nil + if not next(self.unitId[previousGuid]) then + self.unitId[previousGuid] = nil + end + end + self.guid[unitId] = guid + if guid then + if not self.unitId[guid] then + self.unitId[guid] = {} + end + -- Ovale:Print("GUID "..guid.." is ".. unitId) + self.unitId[guid][unitId] = true + end + local name = UnitName(unitId) + if name and (not self.nameToGUID[name] or unitId == "target" + or self.nameToUnit[name] == "mouseover") then + self.nameToGUID[name] = guid + self.nameToUnit[name] = unitId + end + end +end + +function OvaleGUID:GetUnitId(guid) + local unitIdTable = self.unitId[guid] + if not unitIdTable then return nil end + return next(unitIdTable) +end + +function OvaleGUID:UpdateWithTarget(unitId) + self:Update(unitId) + self:Update(unitId.."target") +end + +function OvaleGUID:PLAYER_LOGIN(event) + self:Update("player") +end + +function OvaleGUID:UNIT_TARGET(event, unitId) + self:Update(unitId .. "target") +end + +function OvaleGUID:PARTY_MEMBERS_CHANGED(event) + for i=1, GetNumPartyMembers() do + self:UpdateWithTarget("party"..i) + self:UpdateWithTarget("partypet"..i) + end +end + +function OvaleGUID:RAID_ROSTER_UPDATE(event) + for i=1, GetNumRaidMembers() do + self:UpdateWithTarget("raid"..i) + self:UpdateWithTarget("raidpet"..i) + end +end + +function OvaleGUID:UNIT_PET(event, unitId) + if string.find(unitId, "party") == 0 then + local petId = "partypet" .. string.sub(unitId, 6) + self:UpdateWithTarget(petId) + elseif string.find(unitId, "raid") == 0 then + local petId = "raidpet" .. string.sub(unitId, 5) + self:UpdateWithTarget(petId) + elseif unitId == "player" then + self:UpdateWithTarget("pet") + end +end + +function OvaleGUID:ARENA_OPPONENT_UPDATE(event) + for i=1, 5 do + self:UpdateWithTarget("arena"..i) + end +end + +function OvaleGUID:PLAYER_FOCUS_CHANGED(event) + self:UpdateWithTarget("focus") +end + +function OvaleGUID:UPDATE_MOUSEOVER_UNIT(event) + self:UpdateWithTarget("mouseover") +end + +function OvaleGUID:INSTANCE_ENCOUNTER_ENGAGE_UNIT(event) + for i=1, 4 do + self:UpdateWithTarget("boss"..i) + end +end +-- diff --git a/OvaleIcone.lua b/OvaleIcone.lua index b92c677..af9b493 100644 --- a/OvaleIcone.lua +++ b/OvaleIcone.lua @@ -1,5 +1,8 @@ local L = LibStub("AceLocale-3.0"):GetLocale("Ovale") +--inherits ActionButtonTemplate + +-- local function SetValue(self, value, actionTexture) self.icone:Show() self.icone:SetTexture(actionTexture); @@ -29,15 +32,15 @@ local function Update(self, element, minAttente, actionTexture, actionInRange, a if (minAttente~=nil and actionTexture) then if (actionTexture~=self.actionCourante or self.ancienneAttente==nil or - (minAttente~=Ovale.maintenant and minAttente>self.ancienneAttente+0.01) or + (minAttente~=OvaleState.maintenant and minAttente>self.ancienneAttente+0.01) or (minAttente < self.finAction-0.01)) then if (actionTexture~=self.actionCourante or self.ancienneAttente==nil or - (minAttente~=Ovale.maintenant and minAttente>self.ancienneAttente+0.01)) then - self.debutAction = Ovale.maintenant + (minAttente~=OvaleState.maintenant and minAttente>self.ancienneAttente+0.01)) then + self.debutAction = OvaleState.maintenant end self.actionCourante = actionTexture self.finAction = minAttente - if (minAttente == Ovale.maintenant) then + if (minAttente == OvaleState.maintenant) then self.cd:Hide() else self.lastSound = nil @@ -48,7 +51,7 @@ local function Update(self, element, minAttente, actionTexture, actionInRange, a end end - if not Ovale.db.profile.apparence.flashIcon and minAttente<=Ovale.maintenant then + if not OvaleOptions:GetApparence().flashIcon and minAttente<=OvaleState.maintenant then self.cd:Hide() end @@ -65,21 +68,21 @@ local function Update(self, element, minAttente, actionTexture, actionInRange, a end local red - if (minAttente > actionCooldownStart + actionCooldownDuration + 0.01 and minAttente > Ovale.maintenant - and minAttente>Ovale.attenteFinCast) then + if (minAttente > actionCooldownStart + actionCooldownDuration + 0.01 and minAttente > OvaleState.maintenant + and minAttente>OvaleState.attenteFinCast) then self.icone:SetVertexColor(0.75,0.2,0.2) red = true else self.icone:SetVertexColor(1,1,1) end - --if (minAttente==Ovale.maintenant) then + --if (minAttente==OvaleState.maintenant) then --self.cd:Hide() --end if element.params.sound and not self.lastSound then local delay = element.params.soundtime or 0.5 - if Ovale.maintenant>=minAttente - delay then + if OvaleState.maintenant>=minAttente - delay then self.lastSound = element.params.sound -- print("Play" .. self.lastSound) PlaySoundFile(self.lastSound) @@ -87,10 +90,10 @@ local function Update(self, element, minAttente, actionTexture, actionInRange, a end -- La latence - if minAttente>Ovale.maintenant and Ovale.db.profile.apparence.highlightIcon and not red then + if minAttente>OvaleState.maintenant and OvaleOptions:GetApparence().highlightIcon and not red then local lag = 0.6 local newShouldClick - if minAttente Ovale.maintenant) then - self.remains:SetText(string.format("%.1f", minAttente - Ovale.maintenant)) + if ((OvaleOptions:GetApparence().numeric or self.params.text == "always") and minAttente > OvaleState.maintenant) then + self.remains:SetText(string.format("%.1f", minAttente - OvaleState.maintenant)) self.remains:Show() else self.remains:Hide() end -- Le raccourcis clavier - if (Ovale.db.profile.apparence.raccourcis) then + if (OvaleOptions:GetApparence().raccourcis) then self.shortcut:Show() self.shortcut:SetText(actionShortcut) else @@ -148,7 +151,7 @@ local function Update(self, element, minAttente, actionTexture, actionInRange, a self.shortcut:Hide() self.remains:Hide() self.focusText:Hide() - if Ovale.db.profile.apparence.hideEmpty then + if OvaleOptions:GetApparence().hideEmpty then self:Hide() else self:Show() @@ -177,6 +180,11 @@ local function SetFontScale(self, scale) self.aPortee:SetFont(self.fontName, self.fontHeight * self.fontScale, self.fontFlags) end +local function SetRangeIndicator(self, text) + self.aPortee:SetText(text) +end +-- + function OvaleIcone_OnClick(self) Ovale:ToggleOptions() self:SetChecked(0) @@ -204,26 +212,36 @@ function OvaleIcone_OnLeave(self) end end -local function SetRangeIndicator(self, text) - self.aPortee:SetText(text) -end - function OvaleIcone_OnLoad(self) local name = self:GetName() + +-- self.icone = _G[name.."Icon"] self.shortcut = _G[name.."HotKey"] self.remains = _G[name.."Name"] self.aPortee = _G[name.."Count"] - self.aPortee:SetText(Ovale.db.profile.apparence.targetText) + self.aPortee:SetText(OvaleOptions:GetApparence().targetText) self.cd = _G[name.."Cooldown"] self.normalTexture = _G[name.."NormalTexture"] - local fontName, fontHeight, fontFlags = self.shortcut:GetFont() self.fontName = fontName self.fontHeight = fontHeight self.fontFlags = fontFlags - self.focusText = self:CreateFontString(nil, "OVERLAY"); + self.cdShown = true + self.shouldClick = false + self.help = nil + self.spellId = nil + self.fontScale = nil + self.lastSound = nil + self.ancienneAttente = nil + self.finAction = nil + self.debutAction = nil + self.actionCourante = nil + self.params = nil +-- + + self.focusText:SetFontObject("GameFontNormal"); self.focusText:SetAllPoints(self); self.focusText:SetTextColor(1,1,1); @@ -237,8 +255,7 @@ function OvaleIcone_OnLoad(self) self.SetFontScale = SetFontScale self.SetRangeIndicator = SetRangeIndicator self.SetValue = SetValue - self.cdShown = true - if Ovale.db.profile.clickThru then + if OvaleOptions:GetProfile().clickThru then self:EnableMouse(false) end end diff --git a/OvaleIcone.xml b/OvaleIcone.xml index 06177d3..044555b 100644 --- a/OvaleIcone.xml +++ b/OvaleIcone.xml @@ -2,7 +2,7 @@ - OvaleIcone_OnLoad(self); + OvaleIcone_OnLoad(self) OvaleIcone_OnClick(self) OvaleIcone_OnEnter(self) OvaleIcone_OnLeave(self) diff --git a/OvaleOptions.lua b/OvaleOptions.lua new file mode 100644 index 0000000..08525d8 --- /dev/null +++ b/OvaleOptions.lua @@ -0,0 +1,481 @@ +-- Ovale options and UI + +OvaleOptions = LibStub("AceAddon-3.0"):NewAddon("OvaleOptions", "AceEvent-3.0", "AceConsole-3.0") + +-- +OvaleOptions.firstInit = false +OvaleOptions.db = nil +-- + +-- +local AceConfig = LibStub("AceConfig-3.0"); +local AceConfigDialog = LibStub("AceConfigDialog-3.0"); +local L = LibStub("AceLocale-3.0"):GetLocale("Ovale") + +--GUI option +local options = +{ + type = "group", + args = + { + apparence = + { + name = L["Apparence"], + type = "group", + args = + { + combatUniquement = + { + order = 1, + type = "toggle", + name = L["En combat uniquement"], + get = function(info) + return OvaleOptions.db.profile.apparence.enCombat + end, + set = function(info, v) + OvaleOptions.db.profile.apparence.enCombat = v + Ovale:UpdateVisibility() + end, + width = "full" + }, + targetOnly = + { + order = 1.5, + type = "toggle", + name = L["Si cible uniquement"], + get = function(info) + return OvaleOptions.db.profile.apparence.avecCible + end, + set = function(info, v) + OvaleOptions.db.profile.apparence.avecCible = v + Ovale:UpdateVisibility() + end, + width = "full" + }, + iconScale = + { + order = 2, + type = "range", + name = L["Taille des icônes"], + desc = L["La taille des icônes"], + min = 0.1, max = 16, step = 0.1, + get = function(info) return OvaleOptions.db.profile.apparence.iconScale end, + set = function(info,value) OvaleOptions.db.profile.apparence.iconScale = value; Ovale:UpdateFrame() end + }, + secondIconScale = + { + order = 2.5, + type = "range", + name = L["Taille du second icône"], + min = 0.2, max = 1, step = 0.1, + get = function(info) return OvaleOptions.db.profile.apparence.secondIconScale end, + set = function(info,value) OvaleOptions.db.profile.apparence.secondIconScale = value; Ovale:UpdateFrame() end + }, + fontScale = + { + order = 3, + type = "range", + name = L["Taille des polices"], + desc = L["La taille des polices"], + min = 0.1, max = 2, step = 0.1, + get = function(info) return OvaleOptions.db.profile.apparence.fontScale end, + set = function(info,value) OvaleOptions.db.profile.apparence.fontScale = value; Ovale:UpdateFrame() end + }, + smallIconScale = + { + order = 4, + type = "range", + name = L["Taille des petites icônes"], + desc = L["La taille des petites icônes"], + min = 0.1, max = 16, step = 0.1, + get = function(info) return OvaleOptions.db.profile.apparence.smallIconScale end, + set = function(info,value) OvaleOptions.db.profile.apparence.smallIconScale = value; Ovale:UpdateFrame() end + }, + margin = + { + order = 5.5, + type = "range", + name = L["Marge entre deux icônes"], + min = -16, max = 64, step = 1, + get = function(info) return OvaleOptions.db.profile.apparence.margin end, + set = function(info,value) OvaleOptions.db.profile.apparence.margin = value; Ovale:UpdateFrame() end + }, + iconShiftX = + { + order = 5.6, + type = "range", + name = L["Décalage horizontal des options"], + min = -256, max = 256, step = 1, + get = function(info) return OvaleOptions.db.profile.apparence.iconShiftX end, + set = function(info,value) OvaleOptions.db.profile.apparence.iconShiftX = value; Ovale:UpdateFrame() end + }, + iconShiftY = + { + order = 5.7, + type = "range", + name = L["Décalage vertical des options"], + min = -256, max = 256, step = 1, + get = function(info) return OvaleOptions.db.profile.apparence.iconShiftY end, + set = function(info,value) OvaleOptions.db.profile.apparence.iconShiftY = value; Ovale:UpdateFrame() end + }, + raccourcis = + { + order = 6, + type = "toggle", + name = L["Raccourcis clavier"], + desc = L["Afficher les raccourcis clavier dans le coin inférieur gauche des icônes"], + get = function(info) return OvaleOptions.db.profile.apparence.raccourcis end, + set = function(info, value) OvaleOptions.db.profile.apparence.raccourcis = value end + }, + numeric = + { + order = 7, + type = "toggle", + name = L["Affichage numérique"], + desc = L["Affiche le temps de recharge sous forme numérique"], + get = function(info) return OvaleOptions.db.profile.apparence.numeric end, + set = function(info, value) OvaleOptions.db.profile.apparence.numeric = value end + }, + verrouille = + { + order = 8, + type = "toggle", + name = L["Verrouiller position"], + get = function(info) return OvaleOptions.db.profile.apparence.verrouille end, + set = function(info, value) OvaleOptions.db.profile.apparence.verrouille = value end + }, + vertical = + { + order = 9, + type = "toggle", + name = L["Vertical"], + get = function(info) return OvaleOptions.db.profile.apparence.vertical end, + set = function(info, value) OvaleOptions.db.profile.apparence.vertical = value; Ovale:UpdateFrame() end + }, + alpha = + { + order = 9.5, + type = "range", + name = L["Opacité des icônes"], + min = 0, max = 100, step = 5, + get = function(info) return OvaleOptions.db.profile.apparence.alpha * 100 end, + set = function(info, value) OvaleOptions.db.profile.apparence.alpha = value/100; Ovale.frame.frame:SetAlpha(value/100) end + }, + optionsAlpha = + { + order = 9.5, + type = "range", + name = L["Opacité des options"], + min = 0, max = 100, step = 5, + get = function(info) return OvaleOptions.db.profile.apparence.optionsAlpha * 100 end, + set = function(info, value) OvaleOptions.db.profile.apparence.optionsAlpha = value/100; Ovale.frame.content:SetAlpha(value/100) end + }, + predictif = + { + order = 10, + type = "toggle", + name = L["Prédictif"], + desc = L["Affiche les deux prochains sorts et pas uniquement le suivant"], + get = function(info) return OvaleOptions.db.profile.apparence.predictif end, + set = function(info, value) OvaleOptions.db.profile.apparence.predictif = value; Ovale:UpdateFrame() end + }, + moving = + { + order = 11, + type = "toggle", + name = L["Défilement"], + desc = L["Les icônes se déplacent"], + get = function(info) return OvaleOptions.db.profile.apparence.moving end, + set = function(info, value) OvaleOptions.db.profile.apparence.moving = value; Ovale:UpdateFrame() end + }, + hideEmpty = + { + order = 12, + type = "toggle", + name = L["Cacher bouton vide"], + get = function(info) return OvaleOptions.db.profile.apparence.hideEmpty end, + set = function(info, value) OvaleOptions.db.profile.apparence.hideEmpty = value; Ovale:UpdateFrame() end + }, + targetHostileOnly = + { + order = 13, + type = "toggle", + name = L["Cacher si cible amicale ou morte"], + get = function(info) return OvaleOptions.db.profile.apparence.targetHostileOnly end, + set = function(info, value) OvaleOptions.db.profile.apparence.targetHostileOnly = value; Ovale:UpdateFrame() end + }, + highlightIcon = + { + order = 14, + type = "toggle", + name = L["Illuminer l'icône"], + desc = L["Illuminer l'icône quand la technique doit être spammée"], + get = function(info) return OvaleOptions.db.profile.apparence.highlightIcon end, + set = function(info, value) OvaleOptions.db.profile.apparence.highlightIcon = value; Ovale:UpdateFrame() end + }, + clickThru = + { + order = 15, + type = "toggle", + name = L["Ignorer les clics souris"], + get = function(info) return OvaleOptions.db.profile.apparence.clickThru end, + set = function(info, value) OvaleOptions.db.profile.apparence.clickThru = value; Ovale:UpdateFrame() end + }, + latencyCorrection = + { + order = 16, + type = "toggle", + name = L["Correction de la latence"], + get = function(info) return OvaleOptions.db.profile.apparence.latencyCorrection end, + set = function(info, value) OvaleOptions.db.profile.apparence.latencyCorrection = value end + }, + hideVehicule = + { + order = 17, + type = "toggle", + name = L["Cacher dans les véhicules"], + get = function(info) return OvaleOptions.db.profile.apparence.hideVehicule end, + set = function(info, value) OvaleOptions.db.profile.apparence.hideVehicule = value end + }, + flashIcon = + { + order = 18, + type = "toggle", + name = L["Illuminer l'icône quand le temps de recharge est écoulé"], + get = function(info) return OvaleOptions.db.profile.apparence.flashIcon end, + set = function(info, value) OvaleOptions.db.profile.apparence.flashIcon = value; Ovale:UpdateFrame() end + }, + targetText = + { + order = 19, + type = "input", + name = L["Caractère de portée"], + desc = L["Ce caractère est affiché dans un coin de l'icône pour indiquer si la cible est à portée"], + get = function(info) return OvaleOptions.db.profile.apparence.targetText end, + set = function(info, value) OvaleOptions.db.profile.apparence.targetText = value; Ovale:UpdateFrame() end + } + } + }, + code = + { + name = L["Code"], + type = "group", + args = + { + code = + { + order = 1, + type = "input", + multiline = 15, + name = L["Code"], + get = function(info) + return string.gsub(OvaleOptions.db.profile.code, "\t", " ") + end, + set = function(info,v) + OvaleOptions.db.profile.code = v + Ovale.needCompile = true + end, + width = "full" + } + } + }, + actions = + { + name = "Actions", + type = "group", + args = + { + show = + { + order = -1, + type = "execute", + name = L["Afficher la fenêtre"], + guiHidden = true, + func = function() + OvaleOptions.db.profile.display = true + Ovale:UpdateVisibility() + end + }, + hide = + { + order = -2, + type = "execute", + name = L["Cacher la fenêtre"], + guiHidden = true, + func = function() + OvaleOptions.db.profile.display = false + Ovale.frame:Hide() + end + }, + config = + { + name = "Configuration", + type = "execute", + func = function() Ovale:AfficherConfig() end + }, + code = + { + name = "Code", + type = "execute", + func = function() Ovale:AfficherCode() end + }, + debug = + { + order = -3, + name = "Debug", + type = "execute", + func = function() + for i=1,10 do Ovale:Print(i.."="..UnitPower("player", i)) end + Ovale:Print(OvaleState.state.eclipse) + end + }, + talent = + { + order = -4, + name = "List talent id", + type = "execute", + func = function() + for k,v in pairs(OvaleData.talentNameToId) do + Ovale:Print(k.."="..v) + end + end + }, + targetbuff = + { + order = -5, + name = "List target buff and debuff spell id", + type = "execute", + func = function() + Ovale:DebugListAura("target", "HELPFUL") + Ovale:DebugListAura("target", "HARMFUL") + end + }, + buff = + { + order = -6, + name = "List player buff and debuff spell id", + type = "execute", + func = function() + Ovale:DebugListAura("player", "HELPFUL") + Ovale:DebugListAura("player", "HARMFUL") + end + }, + glyph = + { + order = -7, + name = "List player glyphs", + type = "execute", + func = function() + for i=1,GetNumGlyphs() do + local name, level, enabled, texture, spellId = GetGlyphInfo(i) + if spellId then Ovale:Print(name..": "..spellId.." ("..tostring(enabled)..")") end + end + end + }, + spell = + { + order = -8, + name = "List player spells", + type = "execute", + func = function() + local book=BOOKTYPE_SPELL + while true do + local i=1 + while true do + local skillType, spellId = GetSpellBookItemInfo(i, book) + if not spellId then + break + end + local spellName = GetSpellBookItemName(i, book) + Ovale:Print(spellName..": "..spellId) + i = i + 1 + end + if book == BOOKTYPE_SPELL then + book = BOOKTYPE_PET + else + break + end + end + end + } + } + } + } +} +-- + +-- +function OvaleOptions:OnInitialize() + +end + +function OvaleOptions:FirstInit() + if self.firstInit then + return + end + + self.firstInit = true + + local localizedClass, englishClass = UnitClass("player") + self.db = LibStub("AceDB-3.0"):New("OvaleDB", + { + profile = + { + display = true, + code = Ovale.defaut[englishClass], + left = 500, + top = 500, + check = {}, + list = {}, + apparence = {enCombat=false, iconScale = 2, secondIconScale = 1, margin = 4, fontScale = 0.5, iconShiftX = 0, iconShiftY = 0, + smallIconScale=1, raccourcis=true, numeric=false, avecCible = false, + verrouille = false, vertical = false, predictif=false, highlightIcon = true, clickThru = false, + latencyCorrection=true, hideVehicule=false, flashIcon=true, targetText = "●", alpha = 1, + optionsAlpha = 1, updateInterval=0.1} + } + }) + + options.args.profile = LibStub("AceDBOptions-3.0"):GetOptionsTable(self.db) + AceConfig:RegisterOptionsTable("Ovale", options.args.code) + AceConfig:RegisterOptionsTable("Ovale Actions", options.args.actions, "Ovale") + AceConfig:RegisterOptionsTable("Ovale Profile", options.args.profile) + AceConfig:RegisterOptionsTable("Ovale Apparence", options.args.apparence) + + AceConfigDialog:AddToBlizOptions("Ovale", "Ovale") + AceConfigDialog:AddToBlizOptions("Ovale Profile", "Profile", "Ovale") + AceConfigDialog:AddToBlizOptions("Ovale Apparence", "Apparence", "Ovale") + + self.db.RegisterCallback( self, "OnNewProfile", "HandleProfileChanges" ) + self.db.RegisterCallback( self, "OnProfileReset", "HandleProfileChanges" ) + self.db.RegisterCallback( self, "OnProfileChanged", "HandleProfileChanges" ) + self.db.RegisterCallback( self, "OnProfileCopied", "HandleProfileChanges" ) + + if self.db.profile.code then + Ovale.needCompile = true + end +end + +function OvaleOptions:HandleProfileChanges() + if self.firstInit then + if (self.db.profile.code) then + Ovale.needCompile = true + end + end +end + +function OvaleOptions:OnEnable() + self:FirstInit() + +end + +function OvaleOptions:GetApparence() + self:FirstInit() + return self.db.profile.apparence +end + +function OvaleOptions:GetProfile() + self:FirstInit() + return self.db.profile +end + +-- diff --git a/OvaleSpellDamage.lua b/OvaleSpellDamage.lua new file mode 100644 index 0000000..6dea01a --- /dev/null +++ b/OvaleSpellDamage.lua @@ -0,0 +1,35 @@ +-- Add-on that registers how many damage made the last spell cast by the player + +OvaleSpellDamage = LibStub("AceAddon-3.0"):NewAddon("OvaleSpellDamage", "AceEvent-3.0") + +-- +OvaleSpellDamage.value = {} +OvaleSpellDamage.playerGUID = nil +-- + +-- Events +-- +function OvaleSpellDamage:OnEnable() + self.playerGUID = UnitGUID("player") + self:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED") +end + +function OvaleSpellDamage:OnDisable() + self:UnregisterEvent("COMBAT_LOG_EVENT_UNFILTERED") +end + +function OvaleSpellDamage:COMBAT_LOG_EVENT_UNFILTERED(event, ...) + local time, event, hideCaster, sourceGUID, sourceName, sourceFlags, sourceRaidFlags, destGUID, destName, destFlags, destRaidFlags = select(1, ...) + + if sourceGUID == self.playerGUID then + if string.find(event, "SPELL_PERIODIC_DAMAGE")==1 or string.find(event, "SPELL_DAMAGE")==1 then + local spellId, spellName, spellSchool, amount = select(12, ...) + self.value[spellId] = amount + end + end +end + +function OvaleSpellDamage:Get(spellId) + return self.value[spellId] +end +-- diff --git a/OvaleState.lua b/OvaleState.lua new file mode 100644 index 0000000..854c943 --- /dev/null +++ b/OvaleState.lua @@ -0,0 +1,404 @@ +-- Keep the current state in the simulation + +OvaleState = {} + +-- +--the state in the current frame +OvaleState.state = {rune={}, cd = {}, counter={}} +OvaleState.aura = {} +OvaleState.serial = 0 +for i=1,6 do + OvaleState.state.rune[i] = {} +end +--The spell being cast +OvaleState.currentSpellId = nil +--Allows to debug auras +OvaleState.traceAura = false +OvaleState.maintenant = nil +OvaleState.currentTime = nil +OvaleState.attenteFinCast = nil +OvaleState.startCast = nil +OvaleState.endCast = nil +OvaleState.gcd = 1.5 +-- + +-- +local UnitGUID = UnitGUID +-- + +-- +local function nilstring(text) + if text == nil then + return "nil" + else + return text + end +end +-- + +-- +function OvaleState:StartNewFrame() + self.maintenant = GetTime() + self.gcd = OvaleData:GetGCD() +end + +function OvaleState:Reset() + self.serial = self.serial + 1 + self.currentTime = self.maintenant + self.currentSpellId = nil + self.attenteFinCast = self.maintenant + self.state.combo = GetComboPoints("player") + self.state.mana = UnitPower("player") + self.state.shard = UnitPower("player", 7) + self.state.eclipse = UnitPower("player", 8) + self.state.holy = UnitPower("player", 9) + if OvaleData.className == "DEATHKNIGHT" then + for i=1,6 do + self.state.rune[i].type = GetRuneType(i) + local start, duration, runeReady = GetRuneCooldown(i) + if runeReady then + self.state.rune[i].cd = start + else + self.state.rune[i].cd = duration + start + if self.state.rune[i].cd<0 then + self.state.rune[i].cd = 0 + end + end + end + end + for k,v in pairs(self.state.cd) do + v.start = nil + v.duration = nil + v.enable = 0 + v.toggled = nil + end + + for k,v in pairs(self.state.counter) do + self.state.counter[k] = OvaleFuture.counter[k] + end +end + +-- Cast a spell in the simulator +-- spellId : the spell id +-- startCast : temps du cast +-- endCast : fin du cast +-- nextCast : temps auquel le prochain sort peut tre lanc (>=endCast, avec le GCD) +-- nocd : le sort ne dclenche pas son cooldown +function OvaleState:AddSpellToStack(spellId, startCast, endCast, nextCast, nocd, targetGUID) + if not spellId or not targetGUID then + return + end + + local newSpellInfo = OvaleData.spellInfo[spellId] + + --On enregistre les infos sur le sort en cours + self.attenteFinCast = nextCast + self.currentSpellId = spellId + self.startCast = startCast + self.endCast = endCast + --Temps actuel de la simulation : un peu aprs le dernier cast (ou maintenant si dans le pass) + if startCast>=self.maintenant then + self.currentTime = startCast+0.1 + else + self.currentTime = self.maintenant + end + + if Ovale.trace then + Ovale:Print("add spell "..spellId.." at "..startCast.." currentTime = "..self.currentTime.. " nextCast="..self.attenteFinCast .. " endCast="..endCast) + end + + --Effet du sort au moment du dbut du cast + --(donc si cast dj commenc, on n'en tient pas compte) + if startCast >= self.maintenant then + if newSpellInfo then + if newSpellInfo.inccounter then + local id = newSpellInfo.inccounter + self.state.counter[id] = self:GetCounterValue(id) + 1 + end + + if newSpellInfo.resetcounter then + self.state.counter[newSpellInfo.resetcounter] = 0 + end + end + end + + --Effet du sort au moment o il est lanc + --(donc si il est dj lanc, on n'en tient pas compte) + if endCast >= self.maintenant then + --Mana + local _, _, _, cost = GetSpellInfo(spellId) + if cost then + self.state.mana = self.state.mana - cost + end + + if newSpellInfo then + + if newSpellInfo.mana then + self.state.mana = self.state.mana - newSpellInfo.mana + end + + --Points de combo + if newSpellInfo.combo then + self.state.combo = self.state.combo + newSpellInfo.combo + if self.state.combo<0 then + self.state.combo = 0 + end + end + --Runes + if newSpellInfo.frost then + self:AddRune(startCast, 3, newSpellInfo.frost) + end + if newSpellInfo.death then + self:AddRune(startCast, 4, newSpellInfo.death) + end + if newSpellInfo.blood then + self:AddRune(startCast, 1, newSpellInfo.blood) + end + if newSpellInfo.unholy then + self:AddRune(startCast, 2, newSpellInfo.unholy) + end + if newSpellInfo.holy then + self.state.holy = self.state.holy + newSpellInfo.holy + if self.state.holy < 0 then + self.state.holy = 0 + elseif self.state.holy > 3 then + self.state.holy = 3 + end + end + if newSpellInfo.shard then + self.state.shard = self.state.shard + newSpellInfo.shard + if self.state.shard < 0 then + self.state.shard = 0 + elseif self.state.shard > 3 then + self.state.shard = 3 + end + end + end + end + + -- Effets du sort au moment o il atteint sa cible + if newSpellInfo then + -- Cooldown du sort + local cd = self:GetCD(spellId) + if cd then + cd.start = startCast + cd.duration = newSpellInfo.cd + --Pas de cooldown + if nocd then + cd.duration = 0 + end + --On vrifie si le buff "buffnocd" est prsent, auquel cas le CD du sort n'est pas dclench + if newSpellInfo.buffnocd and not nocd then + local buffAura = self:GetAura("player", newSpellInfo.buffnocd) + if self.traceAura then + if buffAura then + Ovale:Print("buffAura stacks = "..buffAura.stacks.." start="..nilstring(buffAura.start).." ending = "..nilstring(buffAura.ending)) + Ovale:Print("startCast = "..startCast) + else + Ovale:Print("buffAura = nil") + end + self.traceAura = false + end + if buffAura and buffAura.stacks>0 and buffAura.start and buffAura.start<=startCast and (not buffAura.ending or buffAura.ending>startCast) then + cd.duration = 0 + end + end + if newSpellInfo.targetlifenocd and not nocd then + --TODO + if UnitHealth("target")/UnitHealthMax("target")*100 100 then + self.state.eclipse = 100 + self:AddEclipse(endCast, 48517) + end + end + if newSpellInfo.starsurge then + local buffAura = self:GetAura("player", 48517) --Solar + if buffAura and buffAura.stacks>0 then + Ovale:Log("starsurge with solar buff = " .. (- newSpellInfo.starsurge)) + self.state.eclipse = self.state.eclipse - newSpellInfo.starsurge + else + buffAura = self:GetAura("player", 48518) --Lunar + if buffAura and buffAura.stacks>0 then + Ovale:Log("starsurge with lunar buff = " .. newSpellInfo.starsurge) + self.state.eclipse = self.state.eclipse + newSpellInfo.starsurge + elseif self.state.eclipse < 0 then + Ovale:Log("starsurge with eclipse < 0 = " .. (- newSpellInfo.starsurge)) + self.state.eclipse = self.state.eclipse - newSpellInfo.starsurge + else + Ovale:Log("starsurge with eclipse > 0 = " .. newSpellInfo.starsurge) + self.state.eclipse = self.state.eclipse + newSpellInfo.starsurge + end + end + if self.state.eclipse < -100 then + self.state.eclipse = -100 + self:AddEclipse(endCast, 48518) + elseif self.state.eclipse > 100 then + self.state.eclipse = 100 + self:AddEclipse(endCast, 48517) + end + end + + --Auras causs par le sort + if newSpellInfo.aura then + for target, targetInfo in pairs(newSpellInfo.aura) do + for filter, filterInfo in pairs(targetInfo) do + for auraSpellId, spellData in pairs(filterInfo) do + local newAura + if target == "target" then + newAura = self:NewAura(targetGUID, auraSpellId) + else + newAura = self:NewAura(UnitGUID(target), auraSpellId) + end + newAura.mine = true + local duration = spellData + local stacks = duration + --Optionnellement, on va regarder la dure du buff + if auraSpellId and OvaleData.spellInfo[auraSpellId] and OvaleData.spellInfo[auraSpellId].duration then + duration = OvaleData.spellInfo[auraSpellId].duration + elseif stacks~="refresh" and stacks > 0 then + stacks = 1 + end + if stacks=="refresh" then + if newAura.ending then + newAura.ending = endCast + duration + end + elseif stacks<0 and newAura.ending then + --Buff are immediatly removed when the cast ended, do not need to do it again + if filter~="HELPFUL" or target~="player" or endCast>=self.maintenant then + newAura.stacks = newAura.stacks + stacks + if Ovale.trace then + Ovale:Print("removing one stack of "..auraSpellId.." because of ".. spellId.." to ".. newAura.stacks) + end + --Plus de stacks, on supprime l'aura + if newAura.stacks<=0 then + Ovale:Log("Aura is completly removed") + newAura.stacks = 0 + newAura.ending = 0 + end + end + elseif newAura.ending and newAura.ending >= endCast then + newAura.ending = endCast + duration + newAura.stacks = newAura.stacks + stacks + else + newAura.start = endCast + newAura.ending = endCast + duration + newAura.stacks = stacks + end + if Ovale.trace then + if auraSpellId then + Ovale:Print(spellId.." adding "..stacks.." aura "..auraSpellId.." to "..target.." "..filter.." "..newAura.start..","..newAura.ending) + else + Ovale:Print("adding nil aura") + end + end + end + end + end + end + end +end + +function OvaleState:AddRune(time, type, value) + if value<0 then + for i=1,6 do + if (self.state.rune[i].type == type or self.state.rune[i].type==4)and self.state.rune[i].cd<=time then + self.state.rune[i].cd = time + 10 + end + end + else + + end +end + +function OvaleState:GetCounterValue(id) + if self.state.counter[id] then + return self.state.counter[id] + else + return 0 + end +end + +function OvaleState:GetCD(spellId) + if not spellId then + return nil + end + + if OvaleData.spellInfo[spellId] and OvaleData.spellInfo[spellId].cd then + local cdname + if OvaleData.spellInfo[spellId].sharedcd then + cdname = OvaleData.spellInfo[spellId].sharedcd + else + cdname = spellId + end + if not self.state.cd[cdname] then + self.state.cd[cdname] = {} + end + return self.state.cd[cdname] + else + return nil + end +end + +function OvaleState:AddEclipse(endCast, spellId) + local newAura = self:NewAura(OvaleGUID.player, spellId) + newAura.start = endCast + 0.5 + newAura.stacks = 1 + newAura.ending = nil +end + +function OvaleState:GetAura(target, spellId, mine) + local guid = UnitGUID(target) + + if self.aura[guid] and self.aura[guid][spellId] and self.aura[guid][spellId].serial == self.serial then + return self.aura[guid][spellId] + else + return OvaleAura:GetAuraByGUID(guid, spellId, mine, target) + end +end + +function OvaleState:GetExpirationTimeOnAnyTarget(spellId) + local starting, ending = OvaleAura:GetExpirationTimeOnAnyTarget(spellId) + for unitId,auraTable in pairs(self.aura) do + local aura = auraTable[spellId] + if aura and aura.serial == self.serial then + local newEnding = aura.ending + local newStarting = aura.start + if newStarting and (not staring or newStarting < starting) then + starting = newStarting + end + if newEnding and (not ending or newEnding > ending) then + ending = newEnding + end + end + end + return starting, ending +end + +function OvaleState:NewAura(guid, spellId) + if not self.aura[guid] then + self.aura[guid] = {} + end + if not self.aura[guid][spellId] then + self.aura[guid][spellId] = {} + end + local myAura = self.aura[guid][spellId] + myAura.serial = self.serial + myAura.mine = true + myAura.gain = self.currentTime + return myAura +end +-- diff --git a/OvaleSwing.lua b/OvaleSwing.lua index c372d67..37b410a 100644 --- a/OvaleSwing.lua +++ b/OvaleSwing.lua @@ -18,6 +18,22 @@ Modifed for Ovale ]] +OvaleSwing = LibStub("AceAddon-3.0"):NewAddon("OvaleSwing", "AceEvent-3.0") + +-- +OvaleSwing.ohNext = nil +OvaleSwing.dual = false +OvaleSwing.starttime = nil +OvaleSwing.duration = nil +OvaleSwing.ohStartTime = nil +OvaleSwing.ohDuration = nil +OvaleSwing.delay = nil +OvaleSwing.startdelay = nil +OvaleSwing.swingmode = nil + +-- + +-- local autoshotname = GetSpellInfo(75) local resetspells = { } @@ -31,11 +47,10 @@ local _, playerclass = UnitClass('player') local unpack = unpack local math_abs = math.abs local GetTime = GetTime - -OvaleSwing = LibStub("AceAddon-3.0"):NewAddon("OvaleSwing", "AceEvent-3.0") - local BOOKTYPE_SPELL = BOOKTYPE_SPELL +-- +-- function OvaleSwing:OnEnable() self.ohNext = false -- fired when autoattack is enabled/disabled. @@ -86,7 +101,7 @@ end function OvaleSwing:COMBAT_LOG_EVENT_UNFILTERED(event, timestamp, eventName, srcGUID, srcName, srcFlags, dstName, dstGUID, dstFlags, ...) if srcName == UnitName("player") then if eventName == "SWING_DAMAGE" or eventName == "SWING_MISSED" then - self:MeleeSwing(Ovale.maintenant) + self:MeleeSwing(OvaleState.maintenant) end end end @@ -108,7 +123,7 @@ end function OvaleSwing:UNIT_SPELLCAST_SUCCEEDED(event, unit, spell) if unit == "player" then if resetspells[spell] then - self:MeleeSwing(Ovale.maintenant) + self:MeleeSwing(OvaleState.maintenant) end if delayspells[spell] and self.startdelay then self.delay = GetTime() - self.startdelay @@ -203,3 +218,4 @@ function OvaleSwing:GetNext(which) end end end +-- diff --git a/compiler.pl b/compiler.pl new file mode 100644 index 0000000..2cfce11 --- /dev/null +++ b/compiler.pl @@ -0,0 +1,228 @@ +=c +-- +-- + +-- +-- + +-- +-- + +-- +-- + +-- +-- + +-- +-- +=cut + +$p{Skada}{current} = true; +$p{Skada}{total} = true; +$m{Skada}{NewModule} = true; +$m{Skada}{RemoveMode} = true; +$m{Skada}{get_player} = true; +$m{Skada}{AddMode} = true; + +$p{Recount}{db} = true; +$p{Recount}{db2} = true; +$m{Recount}{AddModeTooltip} = true; +$m{Recount}{AddAmount} = true; +$m{Recount}{AddSortedTooltipData} = true; + +$m{AceGUI}{RegisterWidgetType} = true; +$m{AceGUI}{RegisterAsContainer} = true; +$m{AceGUI}{ClearFocus} = true; + +$m{DEFAULT_CHAT_FRAME}{AddMessage} = true; + +$m{LRC}{GetRange} = true; + +$m{AceConfigDialog}{Open} = true; +$m{AceConfigDialog}{AddToBlizOptions} = true; +$m{AceConfigDialog}{SetDefaultSize} = true; + +$m{Masque}{Group} = true; + +$m{AceConfig}{RegisterOptionsTable} = true; + +$m{GameTooltip}{SetText} = true; +$m{GameTooltip}{ClearLines} = true; +$m{GameTooltip}{SetOwner} = true; +$m{GameTooltip}{AddDoubleLine} = true; +$m{GameTooltip}{Show} = true; +$m{GameTooltip}{Hide} = true; +$m{GameTooltip}{AddLine} = true; + +opendir(DIR, "."); +while (defined($r = readdir(DIR))) +{ + if ($r =~ m/(Ovale.*)\.lua$/) + { + my $class = $1; + open(F, "<", $r); + undef $/; + my $content = ; + close(F); + + my %psp = {}; + my %psm = {}; + my %pp = {}; + my %pm = {}; + + if ($content =~ m/--inherits (\w+)/) + { + if ($1 eq 'ActionButtonTemplate') + { + $m{$class}{Show} = true; + $m{$class}{Hide} = true; + $m{$class}{SetChecked} = true; + $m{$class}{CreateFontString} = true; + $m{$class}{RegisterForClicks} = true; + $m{$class}{EnableMouse} = true; + $m{$class}{GetName} = true; + } + if ($1 eq 'Frame') + { + $m{$class}{StartMoving} = true; + $m{$class}{StopMovingOrSizing} = true; + $m{$class}{GetLeft} = true; + $m{$class}{GetTop} = true; + } + } + + if ($content =~ m/$class\s*=\s*LibStub/) + { + $pm{'RegisterEvent'} = true; + $pm{'UnregisterEvent'} = true; + $m{$class}{Print} = true; + } + + if ($content =~ m/(.*)<\/private-static-properties>/s) + { + my $psp = $1; + while ($psp =~ m/local (\w+)\s*=/g) + { + $psp{$1} = true; + } + } + + if ($content =~ m/(.*)<\/private-static-methods>/s) + { + my $psm = $1; + while ($psm =~ m/local function (\w+)\s*=/g) + { + $psm{$1} = true; + } + } + + if ($content =~ m/(.*)<\/public-static-properties>/s) + { + my $sp = $1; + while ($sp =~ m/${class}\.(\w+)\s*=/g) + { + $sp{$class}{$1} = true; + } + } + + if ($content =~ m/(.*)<\/public-static-methods>/s) + { + my $sm = $1; + while ($sm =~ m/function\s+$class:(\w+)\s*\(/g) + { + $sm{$class}{$1} = true; + delete $m{$class}{$1} + } + } + + if ($content =~ m/(.*)<\/public-methods>/s) + { + my $m = $1; + while ($m =~ m/local function (\w+)\(self/g) + { + $m{$class}{$1} = true; + delete $sm{$class}{$1} + } + } + + if ($content =~ m/(.*)<\/public-properties>/s) + { + my $p = $1; + while ($p =~ m/self\.(\w+)/g) + { + $p{$class}{$1} = true; + } + } + + while ($content =~ m/\b([A-Z]\w+)\.(\w+)/g) + { + unless ($sp{$1}{$2} or $p{$1}{$2}) + { + $sp{$1}{$2} = $class; + } + } + + while ($content =~ m/\b([A-Z]\w+)\:(\w+)/g) + { + unless ($sm{$1}{$2} or $m{$1}{$2}) + { + $sm{$1}{$2} = $class; + } + } + + while ($content =~ m/self\.([a-z]\w*)/g) + { + #if ($class eq 'OvaleSwing') + #{ + # print $1," ",$sp{$class}{$1}," ",$pp{$1}, " ", $p{$class}{$1},"\n"; + #} + unless ($sp{$class}{$1} eq true or $pp{$1} eq true or $p{$class}{$1} eq true) + { + print "La classe $class ne contient pas la proprit $1\n"; + } + } + + while ($content =~ m/self\:(\w+)/g) + { + unless ($sm{$class}{$1} eq true or $pm{$1} eq true or $m{$class}{$1} eq true) + { + print "La classe $class ne contient pas la mthode $1\n"; + } + } + } +} + +for my $class (keys %sm) +{ + for my $method (keys %{$sm{$class}}) + { + unless ($sm{$class}{$method} eq true) + { + print "public static $class:$method $sm{$class}{$method}\n"; + } + } +} + +for my $class (keys %m) +{ + for my $method (keys %{$m{$class}}) + { + unless ($m{$class}{$method} eq true) + { + print "public $class:$method $m{$class}{$method}\n"; + } + } +} + +for my $class (keys %sp) +{ + for my $prop (keys %{$sp{$class}}) + { + unless ($sp{$class}{$prop} eq true) + { + print "public static $class.$prop $sp{$class}{$prop}\n"; + } + } +} + diff --git a/defaut/Pretre.lua b/defaut/Pretre.lua index 1f8f513..f3742b9 100644 --- a/defaut/Pretre.lua +++ b/defaut/Pretre.lua @@ -120,10 +120,10 @@ AddIcon help=mana mastery=3 } # Add Focus Target Monitor for Multi Dotting -AddIcon mastery=3 +AddIcon mastery=3 target=focus { - if TargetDebuffExpires(SHADOWWORDPAIN 1.5 mine=1 target=focus ) and TargetDeadIn(more 10) Spell(SHADOWWORDPAIN target=focus) - if TargetDebuffExpires(VAMPIRICTOUCH 3 mine=1 haste=spell target=focus) and TargetDeadIn(more 8) Spell(VAMPIRICTOUCH target=focus) + if TargetDebuffExpires(SHADOWWORDPAIN 1.5 mine=1) and TargetDeadIn(more 10) Spell(SHADOWWORDPAIN) + if TargetDebuffExpires(VAMPIRICTOUCH 3 mine=1 haste=spell) and TargetDeadIn(more 8) Spell(VAMPIRICTOUCH) } ]] -- 1.7.9.5