From 11b234ce7c2ff720a9e5abe835c4e3ac387312ad Mon Sep 17 00:00:00 2001 From: "Johnny C. Lam" Date: Sat, 28 Sep 2013 12:49:32 +0000 Subject: [PATCH] Refactor OvaleData module. - Move the spellbook/talent/glyph-handling to a new module OvaleSpellBook. - Move methods closer to the place where they are mostly used: - :GetTickLength() moved to OvaleAura. - :GetDuration() moved to OvaleState, with simplifications. - Simplify OvaleData into a module without dependencies that can be used as a global data store for other modules where needed. git-svn-id: svn://svn.curseforge.net/wow/ovale/mainline/trunk@1034 d5049fe3-3747-40f7-a4b5-f36d6801af5f --- Ovale.toc | 3 +- OvaleAura.lua | 31 +++++- OvaleBestAction.lua | 6 +- OvaleCompile.lua | 24 ++-- OvaleCondition.lua | 34 +++--- OvaleData.lua | 304 +-------------------------------------------------- OvaleFrame.lua | 3 +- OvaleFuture.lua | 14 ++- OvaleIcone.lua | 6 +- OvaleOptions.lua | 13 +-- OvaleSpellBook.lua | 242 ++++++++++++++++++++++++++++++++++++++++ OvaleState.lua | 105 ++++++++++++++++-- compiler.pl | 1 + 13 files changed, 424 insertions(+), 362 deletions(-) create mode 100644 OvaleSpellBook.lua diff --git a/Ovale.toc b/Ovale.toc index b91a774..762d809 100644 --- a/Ovale.toc +++ b/Ovale.toc @@ -31,6 +31,7 @@ Ovale.lua # Modules with no dependencies OvaleActionBar.lua +OvaleData.lua OvaleEnemies.lua OvaleEquipement.lua OvaleGUID.lua @@ -40,12 +41,12 @@ OvalePoolGC.lua OvaleQueue.lua OvaleRecount.lua OvaleSkada.lua +OvaleSpellBook.lua OvaleStance.lua # OvaleDamageTaken.lua OvalePaperDoll.lua # -OvaleData.lua OvaleScripts.lua defaut\Chaman.lua defaut\Chasseur.lua diff --git a/OvaleAura.lua b/OvaleAura.lua index 3139ba6..4bcca3c 100644 --- a/OvaleAura.lua +++ b/OvaleAura.lua @@ -144,7 +144,7 @@ local function UnitGainedAura(guid, spellId, filter, casterGUID, icon, count, de -- Only set the initial tick information for new auras. if not existingAura then aura.ticksSeen = 0 - aura.tick = OvaleData:GetTickLength(spellId) + aura.tick = self:GetTickLength(spellId) end -- Determine whether to snapshot player stats for the aura or to keep the existing stats. local lastSpellcast = Ovale.lastSpellcast @@ -279,6 +279,7 @@ end -- Update the tick length of an aura using event timestamps from the combat log. local function UpdateAuraTick(guid, spellId, timestamp) + local self = OvaleAura local aura, filter if self_aura[guid] then local serial = self_serial[guid] @@ -304,7 +305,7 @@ local function UpdateAuraTick(guid, spellId, timestamp) if not aura.lastTickTime then -- For some reason, there was no lastTickTime information recorded, -- so approximate the tick time using the player's current stats. - tick = OvaleData:GetTickLength(spellId) + tick = self:GetTickLength(spellId) ticksSeen = 0 else -- Tick times tend to vary about the "true" value by a up to a few @@ -561,6 +562,32 @@ function OvaleAura:GetAuraOnAnyTarget(spellId, filter, mine, excludingGUID) return start, ending, count end +function OvaleAura:GetTickLength(spellId) + local si + if type(spellId) == "number" then + si = OvaleData.spellInfo[spellId] + elseif OvaleData.buffSpellList[spellId] then + for auraId in pairs(OvaleData.buffSpellList[spellId]) do + si = OvaleData.spellInfo[auraId] + if si then break end + end + end + if si then + local tick = si.tick or 3 + local hasteMultiplier = 1 + if si.haste then + if si.haste == "spell" then + hasteMultiplier = OvalePaperDoll:GetSpellHasteMultiplier() + elseif si.haste == "melee" then + hasteMultiplier = OvalePaperDoll:GetMeleeHasteMultiplier() + end + return tick / hasteMultiplier + else + return tick + end + end +end + function OvaleAura:Debug() self_pool:Debug() self_aura_pool:Debug() diff --git a/OvaleBestAction.lua b/OvaleBestAction.lua index 85bb08e..80f9740 100644 --- a/OvaleBestAction.lua +++ b/OvaleBestAction.lua @@ -18,6 +18,7 @@ local OvaleCondition = Ovale.OvaleCondition local OvaleData = Ovale.OvaleData local OvaleEquipement = Ovale.OvaleEquipement local OvalePaperDoll = Ovale.OvalePaperDoll +local OvaleSpellBook = Ovale.OvaleSpellBook local OvaleStance = Ovale.OvaleStance local OvaleState = Ovale.OvaleState @@ -755,7 +756,7 @@ function OvaleBestAction:GetActionInfo(element) if (element.func == "spell" ) then action = OvaleActionBar:GetForSpell(spellId) - if not OvaleData.spellList[spellId] and not action then + if not OvaleSpellBook:IsKnownSpell(spellId) and not action then Ovale:Logf("Spell %s not learnt", spellId) return nil end @@ -788,9 +789,8 @@ function OvaleBestAction:GetActionInfo(element) end end - local spellName = OvaleData:GetSpellName(spellId) actionTexture = actionTexture or API_GetSpellTexture(spellId) - actionInRange = API_IsSpellInRange(spellName, target) + actionInRange = API_IsSpellInRange(OvaleSpellBook:GetSpellName(spellId), target) actionUsable = API_IsUsableSpell(spellId) actionShortcut = nil elseif (element.func=="macro") then diff --git a/OvaleCompile.lua b/OvaleCompile.lua index cef8867..b9d51af 100644 --- a/OvaleCompile.lua +++ b/OvaleCompile.lua @@ -21,6 +21,7 @@ local OvaleOptions = Ovale.OvaleOptions local OvalePaperDoll = Ovale.OvalePaperDoll local OvalePool = Ovale.OvalePool local OvaleScripts = Ovale.OvaleScripts +local OvaleSpellBook = Ovale.OvaleSpellBook local OvaleStance = Ovale.OvaleStance local ipairs = ipairs @@ -103,23 +104,16 @@ local function ParseParameters(params) end local function HasTalent(talentId) - if not OvaleData.listeTalentsRemplie then - OvaleData:RemplirListeTalents() - end - if OvaleData.listeTalentsRemplie then - if OvaleData.pointsTalent[talentId]~=nil then - return OvaleData.pointsTalent[talentId]>0 - else - Ovale:FormatPrint("Unknown talent %s", talentId) - return false - end + if OvaleSpellBook:IsKnownTalent(talentId) then + return OvaleSpellBook:GetTalentPoints(talentId) > 0 else + Ovale:FormatPrint("Unknown talent %s", talentId) return false end end local function TestConditions(paramList) - if paramList.glyph and not OvaleData.glyphs[paramList.glyph] then + if paramList.glyph and not OvaleSpellBook:IsActiveGlyph(paramList.glyph) then return false end if paramList.mastery and OvalePaperDoll.specialization ~= paramList.mastery then @@ -131,7 +125,7 @@ local function TestConditions(paramList) return false end end - if paramList.if_spell and not OvaleData.spellList[paramList.if_spell] then + if paramList.if_spell and not OvaleSpellBook:IsKnownSpell(paramList.if_spell) then return false end if paramList.talent and not HasTalent(paramList.talent) then @@ -247,7 +241,7 @@ local function ParseFunction(prefix, func, params) -- is a variant of a spell with the same name as one already in the -- spellbook. If it is, then add that variant spell ID to our spellList. if OvaleCondition.spellbookConditions[func] then - if not OvaleData.spellList[spellId] and not self_missingSpellList[spellId] then + if not OvaleSpellBook:IsKnownSpell(spellId) and not self_missingSpellList[spellId] then local spellName if type(spellId) == "number" then spellName = API_GetSpellInfo(spellId) @@ -682,7 +676,7 @@ end local function ParseSpellName(text) local spellId = tonumber(text) - local spell = OvaleData:GetSpellName(spellId) + local spell = OvaleSpellBook:GetSpellName(spellId) if spell then return '"' .. spell .. '"' else @@ -802,7 +796,7 @@ local function CompileScript(text) -- Add any missing spells found while compiling the script into the spellbook. for k, v in pairs(self_missingSpellList) do - OvaleData.spellList[k] = v + OvaleSpellBook:AddSpell(k, v) end end -- diff --git a/OvaleCondition.lua b/OvaleCondition.lua index 40babff..68a6449 100644 --- a/OvaleCondition.lua +++ b/OvaleCondition.lua @@ -26,6 +26,7 @@ local OvaleFuture = Ovale.OvaleFuture local OvaleGUID = Ovale.OvaleGUID local OvaleLatency = Ovale.OvaleLatency local OvalePaperDoll = Ovale.OvalePaperDoll +local OvaleSpellBook = Ovale.OvaleSpellBook local OvaleSpellDamage = Ovale.OvaleSpellDamage local OvaleStance = Ovale.OvaleStance local OvaleState = Ovale.OvaleState @@ -116,7 +117,7 @@ local function IsSameSpell(spellIdA, spellIdB, spellNameB) if spellIdB then return spellIdA == spellIdB elseif spellIdA and spellNameB then - return OvaleData:GetSpellName(spellIdA) == spellNameB + return OvaleSpellBook:GetSpellName(spellIdA) == spellNameB else return false end @@ -1093,7 +1094,7 @@ OvaleCondition.conditions.casting = function(condition) return nil elseif spellId == "harmful" then if not castSpellName then - castSpellName = OvaleData:GetSpellName(castSpellId) + castSpellName = OvaleSpellBook:GetSpellName(castSpellId) end if API_IsHarmfulSpell(castSpellName) then return start, ending @@ -1102,7 +1103,7 @@ OvaleCondition.conditions.casting = function(condition) end elseif spellId == "helpful" then if not castSpellName then - castSpellName = OvaleData:GetSpellName(castSpellId) + castSpellName = OvaleSpellBook:GetSpellName(castSpellId) end if API_IsHelpfulSpell(castSpellName) then return start, ending @@ -1639,7 +1640,7 @@ end -- Spell(savage_roar) OvaleCondition.conditions.glyph = function(condition) - return TestBoolean(OvaleData.glyphs[condition[1]], condition[2]) + return TestBoolean(OvaleSpellBook:IsActiveGlyph(condition[1]), condition[2]) end --- Test if the player has full control, i.e., isn't feared, charmed, etc. @@ -1852,7 +1853,7 @@ end -- Spell(kick) OvaleCondition.conditions.inrange = function(condition) - local spellName = OvaleData:GetSpellName(condition[1]) + local spellName = OvaleSpellBook:GetSpellName(condition[1]) return TestBoolean(API_IsSpellInRange(spellName, GetTarget(condition)) == 1,condition[2]) end @@ -2948,7 +2949,7 @@ OvaleCondition.conditions.critchance = OvaleCondition.conditions.spellcritchance -- Spell(guardian_of_ancient_kings_retribution) OvaleCondition.conditions.spellknown = function(condition) - return TestBoolean(OvaleData.spellList[condition[1]], condition[2]) + return TestBoolean(OvaleSpellBook:IsKnownSpell(condition[1]), condition[2]) end OvaleCondition.spellbookConditions.spellknown = true @@ -3021,17 +3022,18 @@ OvaleCondition.spellbookConditions.spellchargecooldown = true -- Spell(devouring_plague) OvaleCondition.conditions.spellcooldown = function(condition) - if type(condition[1]) == "string" then - local sharedCd = OvaleState.state.cd[condition[1]] + local spellId = condition[1] + if type(spellId) == "string" then + local sharedCd = OvaleState.state.cd[spellId] if sharedCd then return 0, nil, sharedCd.duration, sharedCd.start, -1 else return nil end - elseif not OvaleData.spellList[condition[1]] then + elseif not OvaleSpellBook:IsKnownSpell(spellId) then return 0, nil, 0, OvaleState.currentTime + 3600, -1 else - local actionCooldownStart, actionCooldownDuration, actionEnable = OvaleState:GetComputedSpellCD(condition[1]) + local actionCooldownStart, actionCooldownDuration, actionEnable = OvaleState:GetComputedSpellCD(spellId) return 0, nil, actionCooldownDuration, actionCooldownStart, -1 end end @@ -3152,7 +3154,7 @@ end -- if TalentPoints(blood_tap_talent) Spell(blood_tap) OvaleCondition.conditions.talentpoints = function(condition) - return Compare(OvaleData:GetTalentPoints(condition[1]), condition[2], condition[3]) + return Compare(OvaleSpellBook:GetTalentPoints(condition[1]), condition[2], condition[3]) end --- Test if the player is the in-game target of the target. @@ -3240,7 +3242,7 @@ OvaleCondition.conditions.ticks = function(condition) numTicks = floor(duration / tick + 0.5) end else - duration, tick, numTicks = OvaleData:GetDuration(condition[1], OvaleState.state.combo, OvaleState.state.holy) + duration, tick, numTicks = OvaleState:GetDuration(condition[1]) end if numTicks then return Compare(numTicks, condition[2], condition[3]) @@ -3307,7 +3309,7 @@ OvaleCondition.conditions.ticktime = function(condition) local start, ending = GetAura(condition, self_auraFound) local tick = self_auraFound.tick if not tick then - tick = OvaleData:GetTickLength(condition[1]) + tick = OvaleAura:GetTickLength(condition[1]) end if tick then return Compare(tick, condition[2], condition[3]) @@ -3457,7 +3459,7 @@ OvaleCondition.conditions.totemexpires = function(condition) if not startTime then return 0 end - if condition.totem and OvaleData:GetSpellName(condition.totem) ~= totemName then + if condition.totem and OvaleSpellBook:GetSpellName(condition.totem) ~= totemName then return 0 end return AddToTime(startTime + duration, -(condition[2] or 0)) @@ -3485,7 +3487,7 @@ OvaleCondition.conditions.totempresent = function(condition) if not startTime then return nil end - if condition.totem and OvaleData:GetSpellName(condition.totem) ~= totemName then + if condition.totem and OvaleSpellBook:GetSpellName(condition.totem) ~= totemName then return nil end return startTime, startTime + duration @@ -3495,7 +3497,7 @@ end -- 1: the spell id -- return bool OvaleCondition.conditions.tracking = function(condition) - local what = OvaleData:GetSpellName(condition[1]) + local what = OvaleSpellBook:GetSpellName(condition[1]) local numTrackingTypes = API_GetNumTrackingTypes() local present = false for i = 1, numTrackingTypes do diff --git a/OvaleData.lua b/OvaleData.lua index 5e79a41..4280f5e 100644 --- a/OvaleData.lua +++ b/OvaleData.lua @@ -9,31 +9,13 @@ --]]-------------------------------------------------------------------- local _, Ovale = ... -local OvaleData = Ovale:NewModule("OvaleData", "AceEvent-3.0") +local OvaleData = {} Ovale.OvaleData = OvaleData -- -local OvalePaperDoll = Ovale.OvalePaperDoll -local OvaleStance = Ovale.OvaleStance - local floor = math.floor -local ipairs = ipairs local pairs = pairs -local tinsert = table.insert -local tonumber = tonumber -local tostring = tostring -local tsort = table.sort -local wipe = table.wipe -local API_GetNumGlyphSockets = GetNumGlyphSockets -local API_GetGlyphSocketInfo = GetGlyphSocketInfo local API_GetSpellCooldown = GetSpellCooldown -local API_GetSpellBookItemInfo = GetSpellBookItemInfo -local API_GetSpellBookItemName = GetSpellBookItemName -local API_GetSpellInfo = GetSpellInfo -local API_GetSpellTabInfo = GetSpellTabInfo -local API_GetTalentInfo = GetTalentInfo -local API_HasPetSpells = HasPetSpells -local BOOKTYPE_SPELL, BOOKTYPE_PET = BOOKTYPE_SPELL, BOOKTYPE_PET local SPELL_POWER_ALTERNATE_POWER = SPELL_POWER_ALTERNATE_POWER local SPELL_POWER_BURNING_EMBERS = SPELL_POWER_BURNING_EMBERS local SPELL_POWER_CHI = SPELL_POWER_CHI @@ -75,18 +57,7 @@ self_buffNoSnapshotSpellList = -- -- -OvaleData.spellList = {} OvaleData.itemList = {} ---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 = {} ---active glyphs: self.glyphs[glyphId] is true if the given glyphId is active -OvaleData.glyphs = {} --spell info from the current script (by spellId) OvaleData.spellInfo = {} --spells that count for scoring @@ -110,6 +81,11 @@ OvaleData.power = } OvaleData.secondaryPower = {"rage", "focus", "shards", "holy", "chi", "shadoworbs", "burningembers", "demonicfury"} OvaleData.powerType = {} +do + for k,v in pairs(OvaleData.power) do + OvaleData.powerType[v.id] = k + end +end OvaleData.buffSpellList = { @@ -308,123 +284,6 @@ OvaleData.buffSpellList.heroism = OvaleData.buffSpellList.burst_haste -- -- -function OvaleData:OnInitialize() - for k,v in pairs(self.power) do - self.powerType[v.id] = k - end -end - -function OvaleData:OnEnable() - self:RegisterEvent("ACTIVE_TALENT_GROUP_CHANGED", "Update") - self:RegisterEvent("CHARACTER_POINTS_CHANGED", "RemplirListeTalents") - self:RegisterEvent("GLYPH_ADDED", "UpdateGlyphs") - self:RegisterEvent("GLYPH_DISABLED", "UpdateGlyphs") - self:RegisterEvent("GLYPH_ENABLED", "UpdateGlyphs") - self:RegisterEvent("GLYPH_REMOVED", "UpdateGlyphs") - self:RegisterEvent("GLYPH_UPDATED", "UpdateGlyphs") - self:RegisterEvent("PLAYER_ALIVE", "Update") - self:RegisterEvent("PLAYER_ENTERING_WORLD", "Update") - self:RegisterEvent("PLAYER_TALENT_UPDATE", "RemplirListeTalents") - self:RegisterEvent("SPELLS_CHANGED", "FillSpellList") - self:RegisterEvent("UNIT_PET", "FillPetSpellList") -end - -function OvaleData:OnDisable() - self:UnregisterEvent("ACTIVE_TALENT_GROUP_CHANGED") - self:UnregisterEvent("CHARACTER_POINTS_CHANGED") - self:UnregisterEvent("GLYPH_ADDED") - self:UnregisterEvent("GLYPH_DISABLED") - self:UnregisterEvent("GLYPH_ENABLED") - self:UnregisterEvent("GLYPH_REMOVED") - self:UnregisterEvent("GLYPH_UPDATED") - self:UnregisterEvent("PLAYER_ALIVE") - self:UnregisterEvent("PLAYER_ENTERING_WORLD") - self:UnregisterEvent("PLAYER_TALENT_UPDATE") - self:UnregisterEvent("SPELLS_CHANGED") - self:UnregisterEvent("UNIT_PET") -end - -function OvaleData:Update() - self:RemplirListeTalents() - self:UpdateGlyphs() - self:FillSpellList() -end - -function OvaleData:GetSpellName(spellId) - if not spellId then return nil end - return self.spellList[spellId] or API_GetSpellInfo(spellId) -end - -function OvaleData:FillPetSpellList() - --TODO pas moyen d'avoir le nombre de skills pour le pet - local book=BOOKTYPE_PET - local numSpells, _ = API_HasPetSpells() - if not numSpells then return end - local i=1 - while i <= numSpells do - local skillType, spellId = API_GetSpellBookItemInfo(i, book) - if skillType~="FUTURESPELL" and spellId then - local spellName = API_GetSpellBookItemName(i, book) - self.spellList[spellId] = spellName - end - i = i + 1 - end -end - -function OvaleData:FillSpellList() - self.spellList = {} - - --TODO pas moyen d'avoir le nombre de skills pour le pet - local book=BOOKTYPE_SPELL - local name, texture, offset, numSpells, isGuild = API_GetSpellTabInfo(2) - - numSpells = numSpells + offset - - local i=1 - while i <= numSpells do - local skillType, spellId = API_GetSpellBookItemInfo(i, book) - if skillType~="FUTURESPELL" and spellId then - local spellName = API_GetSpellBookItemName(i, book) - self.spellList[spellId] = spellName - end - i = i + 1 - end - self:FillPetSpellList() - self:SendMessage("Ovale_SpellsChanged") -end - -function OvaleData:RemplirListeTalents() - local talentId = 1 - local talentsChanged = false - while true do - local name, texture, tier, column, selected, available = API_GetTalentInfo(talentId) - if not name then - break - end - talentId = tonumber(talentId) - self.talentIdToName[talentId] = name - self.talentNameToId[name] = talentId - if selected then - self.pointsTalent[talentId] = 1 - else - self.pointsTalent[talentId] = 0 - end - self.listeTalentsRemplie = true - talentsChanged = true - talentId = talentId + 1 - end - if talentsChanged then - self:SendMessage("Ovale_TalentsChanged") - end -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] = @@ -436,17 +295,6 @@ function OvaleData:GetSpellInfo(spellId) return self.spellInfo[spellId] end -function OvaleData:UpdateGlyphs() - wipe(self.glyphs) - for i = 1, API_GetNumGlyphSockets() do - local enabled, _, _, glyphSpell, _ = API_GetGlyphSocketInfo(i) - if enabled and glyphSpell then - self.glyphs[glyphSpell] = true - end - end - self:SendMessage("Ovale_GlyphsChanged") -end - function OvaleData:ResetSpellInfo() self.spellInfo = {} end @@ -461,45 +309,6 @@ function OvaleData:NeedNewSnapshot(auraSpellId, spellId) return true end -function OvaleData:GetGCD(spellId) - if spellId and self.spellInfo[spellId] then - local si = self.spellInfo[spellId] - if si.haste then - local cd = si.gcd or 1.5 - if si.haste == "melee" then - cd = cd / OvalePaperDoll:GetMeleeHasteMultiplier() - elseif si.haste == "spell" then - cd = cd / OvalePaperDoll:GetSpellHasteMultiplier() - end - if cd < 1 then - cd = 1 - end - return cd - elseif si.gcd then - return si.gcd - end - end - - -- Default value - local class = OvalePaperDoll.class - if class == "DEATHKNIGHT" or class == "ROGUE" - or (class == "MONK" - and (OvaleStance:IsStance("monk_stance_of_the_sturdy_ox") - or OvaleStance:IsStance("monk_stance_of_the_fierce_tiger"))) - or (class == "DRUID" and OvaleStance:IsStance("druid_cat_form")) then - return 1.0 - elseif class == "MAGE" or class == "WARLOCK" or class == "PRIEST" or - (class == "DRUID" and not OvaleStance:IsStance("druid_bear_form")) then - local cd = 1.5 / OvalePaperDoll:GetSpellHasteMultiplier() - if cd < 1 then - cd = 1 - end - return cd - else - return 1.5 - end -end - --Compute the spell Cooldown function OvaleData:GetSpellCD(spellId) local actionCooldownStart, actionCooldownDuration, actionEnable = API_GetSpellCooldown(spellId) @@ -541,105 +350,4 @@ function OvaleData:GetDamage(spellId, attackpower, spellpower, mainHandWeaponDam end return damage end - --- Returns the duration, tick length, and number of ticks of an aura. -function OvaleData:GetDuration(spellId, combo, holy) - local si - if type(spellId) == "number" then - si = self.spellInfo[spellId] - elseif OvaleData.buffSpellList[spellId] then - for auraId in pairs(OvaleData.buffSpellList[spellId]) do - si = self.spellInfo[auraId] - if si then - spellId = auraId - break - end - end - end - if si and si.duration then - local duration = si.duration - combo = combo or 0 - holy = holy or 1 - if si.adddurationcp then - duration = duration + si.adddurationcp * combo - end - if si.adddurationholy then - duration = duration + si.adddurationholy * (holy - 1) - end - if si.tick then -- DoT - --DoT duration is tick * numberOfTicks. - local tick = self:GetTickLength(spellId) - local numTicks = floor(duration / tick + 0.5) - duration = tick * numTicks - return duration, tick, numTicks - end - return duration - else - return nil - end -end - -function OvaleData:GetTickLength(spellId) - local si - if type(spellId) == "number" then - si = self.spellInfo[spellId] - elseif OvaleData.buffSpellList[spellId] then - for auraId in pairs(OvaleData.buffSpellList[spellId]) do - si = self.spellInfo[auraId] - if si then break end - end - end - if si then - local tick = si.tick or 3 - local hasteMultiplier = 1 - if si.haste then - if si.haste == "spell" then - hasteMultiplier = OvalePaperDoll:GetSpellHasteMultiplier() - elseif si.haste == "melee" then - hasteMultiplier = OvalePaperDoll:GetMeleeHasteMultiplier() - end - return tick / hasteMultiplier - else - return tick - end - else - return nil - end -end - --- Print out the list of active glyphs in alphabetical order. -function OvaleData:DebugGlyphs() - local array = {} - for glyphId in pairs(self.glyphs) do - tinsert(array, self:GetSpellName(glyphId) .. ": " .. glyphId) - end - tsort(array) - for _, v in ipairs(array) do - Ovale:Print(v) - end -end - --- Print out the list of known spells in alphabetical order. -function OvaleData:DebugSpellList() - local array = {} - for k, v in pairs(self.spellList) do - tinsert(array, v .. ": " .. k) - end - tsort(array) - for _, v in ipairs(array) do - Ovale:Print(v) - end -end - --- Print out the list of talents in alphabetical order. -function OvaleData:DebugTalents() - local array = {} - for name, id in pairs(self.talentNameToId) do - tinsert(array, name .. " = " .. id) - end - tsort(array) - for _, v in ipairs(array) do - Ovale:Print(v) - end -end -- diff --git a/OvaleFrame.lua b/OvaleFrame.lua index 4926ffd..ffaa159 100644 --- a/OvaleFrame.lua +++ b/OvaleFrame.lua @@ -18,7 +18,6 @@ do local OvaleBestAction = Ovale.OvaleBestAction local OvaleCompile = Ovale.OvaleCompile local OvaleCondition = Ovale.OvaleCondition - local OvaleData = Ovale.OvaleData local OvaleGUID = Ovale.OvaleGUID local OvaleOptions = Ovale.OvaleOptions local OvaleState = Ovale.OvaleState @@ -257,7 +256,7 @@ do castTime = _castTime/1000 end end - local gcd = OvaleData:GetGCD(spellId) + local gcd = OvaleState:GetGCD(spellId) local nextCast if (castTime>gcd) then nextCast = start + castTime diff --git a/OvaleFuture.lua b/OvaleFuture.lua index cc08ee1..d450862 100644 --- a/OvaleFuture.lua +++ b/OvaleFuture.lua @@ -21,6 +21,7 @@ local OvaleData = Ovale.OvaleData local OvaleGUID = Ovale.OvaleGUID local OvalePaperDoll = Ovale.OvalePaperDoll local OvalePool = Ovale.OvalePool +local OvaleSpellBook = Ovale.OvaleSpellBook local ipairs = ipairs local pairs = pairs @@ -76,7 +77,7 @@ local function TracePrintf(spellId, ...) if self.traceSpellList then local name = spellId if type(spellId) == "number" then - name = OvaleData:GetSpellName(spellId) + name = OvaleSpellBook:GetSpellName(spellId) end if self.traceSpellList[spellId] or self.traceSpellList[name] then local now = API_GetTime() @@ -132,13 +133,14 @@ local function AddSpellToQueue(spellId, lineId, startTime, endTime, channeled, a spellcast.allowRemove = allowRemove -- Set the target from the data taken from UNIT_SPELLCAST_SENT if it's the same spellcast. - if lineId == self_lastLineID and OvaleData:GetSpellName(spellId) == self_lastSpell then + local spellName = OvaleSpellBook:GetSpellName(spellId) + if lineId == self_lastLineID and spellName == self_lastSpell then spellcast.target = self_lastTarget else spellcast.target = API_UnitGUID("target") end TracePrintf(spellId, " AddSpellToQueue: %s (%d), lineId=%d, startTime=%f, endTime=%f, target=%s", - OvaleData:GetSpellName(spellId), spellId, lineId, startTime, endTime, spellcast.target) + spellName, spellId, lineId, startTime, endTime, spellcast.target) -- Snapshot the current stats for the spellcast. OvalePaperDoll:SnapshotStats(spellcast) @@ -196,7 +198,7 @@ local function RemoveSpellFromQueue(spellId, lineId) local self = OvaleFuture for index, spellcast in ipairs(self_activeSpellcast) do if spellcast.lineId == lineId then - TracePrintf(spellId, " RemoveSpellFromQueue: %s (%d)", OvaleData:GetSpellName(spellId), spellId) + TracePrintf(spellId, " RemoveSpellFromQueue: %s (%d)", OvaleSpellBook:GetSpellName(spellId), spellId) tremove(self_activeSpellcast, index) self_pool:Release(spellcast) break @@ -234,7 +236,7 @@ local function UpdateLastSpellInfo(spellcast) OvalePaperDoll:SnapshotStats(spellcast) spellcast.damageMultiplier = GetDamageMultiplier(spellId) TracePrintf(spellId, " Updated spell info for %s (%d) to snapshot from %f.", - OvaleData:GetSpellName(spellId), spellId, spellcast.snapshotTime) + OvaleSpellBook:GetSpellName(spellId), spellId, spellcast.snapshotTime) end end @@ -501,7 +503,7 @@ function OvaleFuture:Debug() Ovale:Print("No spells in flight!") end for _, spellcast in ipairs(self_activeSpellcast) do - Ovale:FormatPrint(" %s (%d), lineId=%s", OvaleData:GetSpellName(spellcast.spellId), spellcast.spellId, spellcast.lineId) + Ovale:FormatPrint(" %s (%d), lineId=%s", OvaleSpellBook:GetSpellName(spellcast.spellId), spellcast.spellId, spellcast.lineId) end end -- diff --git a/OvaleIcone.lua b/OvaleIcone.lua index e4234aa..a1960c7 100644 --- a/OvaleIcone.lua +++ b/OvaleIcone.lua @@ -14,8 +14,8 @@ local _, Ovale = ... -- local L = Ovale.L -local OvaleData = Ovale.OvaleData local OvaleOptions = Ovale.OvaleOptions +local OvaleSpellBook = Ovale.OvaleSpellBook local OvaleState = Ovale.OvaleState local strfind = string.find @@ -203,7 +203,7 @@ local function SetParams(self, params, secure) Ovale:FormatPrint("%stype%s", prefix, suffix) self:SetAttribute(prefix .. "type" .. suffix, "spell") self:SetAttribute("unit", self.params.target or "target") - self:SetAttribute(k, OvaleData.spellList[v]) + self:SetAttribute(k, OvaleSpellBook:GetSpellName(v)) self.actionButton = true end end @@ -235,7 +235,7 @@ function OvaleIcone_OnEnter(self) GameTooltip:SetText(L[self.help]) end if self.spellId then - GameTooltip:AddLine(OvaleData:GetSpellName(self.spellId), 0.5, 1, 0.75) + GameTooltip:AddLine(OvaleSpellBook:GetSpellName(self.spellId), 0.5, 1, 0.75) end if next(Ovale.casesACocher) or next(Ovale.listes) then GameTooltip:AddLine(L["Cliquer pour afficher/cacher les options"],1,1,1) diff --git a/OvaleOptions.lua b/OvaleOptions.lua index a5c9825..f33cf17 100644 --- a/OvaleOptions.lua +++ b/OvaleOptions.lua @@ -18,6 +18,7 @@ Ovale.OvaleOptions = OvaleOptions local L = Ovale.L local OvalePaperDoll = Ovale.OvalePaperDoll local OvaleScripts = Ovale.OvaleScripts +local OvaleSpellBook = Ovale.OvaleSpellBook local strgmatch = string.gmatch local strgsub = string.gsub @@ -607,9 +608,7 @@ local self_options = order = -4, name = "List talent id", type = "execute", - func = function() - if Ovale.OvaleData then Ovale.OvaleData:DebugTalents() end - end + func = function() OvaleSpellBook:DebugTalents() end }, targetbuff = { @@ -642,18 +641,14 @@ local self_options = order = -7, name = "List player glyphs", type = "execute", - func = function() - if Ovale.OvaleData then Ovale.OvaleData:DebugGlyphs() end - end + func = function() OvaleSpellBook:DebugGlyphs() end }, spell = { order = -8, name = "List player spells", type = "execute", - func = function() - if Ovale.OvaleData then Ovale.OvaleData:DebugSpellList() end - end + func = function() OvaleSpellBook:DebugSpells() end }, stance = { diff --git a/OvaleSpellBook.lua b/OvaleSpellBook.lua new file mode 100644 index 0000000..76edf26 --- /dev/null +++ b/OvaleSpellBook.lua @@ -0,0 +1,242 @@ +--[[-------------------------------------------------------------------- + Ovale Spell Priority + Copyright (C) 2012 Sidoine + Copyright (C) 2012, 2013 Johnny C. Lam + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License in the LICENSE + file accompanying this program. +--]]-------------------------------------------------------------------- + +-- This addon tracks the player's active spells, talents, and glyphs. + +local _, Ovale = ... +local OvaleSpellBook = Ovale:NewModule("OvaleSpellBook", "AceEvent-3.0") +Ovale.OvaleSpellBook = OvaleSpellBook + +-- +local ipairs = ipairs +local pairs = pairs +local tinsert = table.insert +local tostring = tostring +local tsort = table.sort +local wipe = table.wipe +local API_GetNumGlyphSockets = GetNumGlyphSockets +local API_GetGlyphSocketInfo = GetGlyphSocketInfo +local API_GetSpellBookItemInfo = GetSpellBookItemInfo +local API_GetSpellBookItemName = GetSpellBookItemName +local API_GetSpellInfo = GetSpellInfo +local API_GetSpellTabInfo = GetSpellTabInfo +local API_GetTalentInfo = GetTalentInfo +local API_HasPetSpells = HasPetSpells +local BOOKTYPE_PET = BOOKTYPE_PET +local BOOKTYPE_SPELL = BOOKTYPE_SPELL + +-- spell[spellId] = spellName +self_spell = {} +-- talent[talentId] = talentName +self_talent = {} +-- talentPoints[talentId] = 0 or 1 +self_talentPoints = {} +-- glyph[glyphSpellId] = glyphName +self_glyph = {} +-- + +-- +local function PrintTableValues(tbl) + local array = {} + for k, v in pairs(tbl) do + tinsert(array, tostring(v) .. ": " .. tostring(k)) + end + tsort(array) + for _, v in ipairs(array) do + Ovale:Print(v) + end +end +-- + +-- +function OvaleSpellBook:OnEnable() + self:RegisterEvent("ACTIVE_TALENT_GROUP_CHANGED", "Update") + self:RegisterEvent("CHARACTER_POINTS_CHANGED", "UpdateTalents") + self:RegisterEvent("GLYPH_ADDED", "UpdateGlyphs") + self:RegisterEvent("GLYPH_DISABLED", "UpdateGlyphs") + self:RegisterEvent("GLYPH_ENABLED", "UpdateGlyphs") + self:RegisterEvent("GLYPH_REMOVED", "UpdateGlyphs") + self:RegisterEvent("GLYPH_UPDATED", "UpdateGlyphs") + self:RegisterEvent("PLAYER_ALIVE", "Update") + self:RegisterEvent("PLAYER_ENTERING_WORLD", "Update") + self:RegisterEvent("PLAYER_TALENT_UPDATE", "UpdateTalents") + self:RegisterEvent("SPELLS_CHANGED", "UpdateSpells") + self:RegisterEvent("UNIT_PET") +end + +function OvaleSpellBook:OnDisable() + self:UnregisterEvent("ACTIVE_TALENT_GROUP_CHANGED") + self:UnregisterEvent("CHARACTER_POINTS_CHANGED") + self:UnregisterEvent("GLYPH_ADDED") + self:UnregisterEvent("GLYPH_DISABLED") + self:UnregisterEvent("GLYPH_ENABLED") + self:UnregisterEvent("GLYPH_REMOVED") + self:UnregisterEvent("GLYPH_UPDATED") + self:UnregisterEvent("PLAYER_ALIVE") + self:UnregisterEvent("PLAYER_ENTERING_WORLD") + self:UnregisterEvent("PLAYER_TALENT_UPDATE") + self:UnregisterEvent("SPELLS_CHANGED") + self:UnregisterEvent("UNIT_PET") +end + +-- Update spells if the player's pet is summoned or dismissed. +function OvaleSpellBook:UNIT_PET(unitId) + if unitId == "player" then + UpdateSpells() + end +end + +function OvaleSpellBook:Update() + self:UpdateTalents() + self:UpdateGlyphs() + self:UpdateSpells() +end + +-- Update the player's talents by scanning the talent tab for the active specialization. +-- Store the number of points assigned to each talent. +function OvaleSpellBook:UpdateTalents() + wipe(self_talent) + wipe(self_talentPoints) + + local name, selected + local i = 1 + while true do + name, _, _, _, selected, _ = API_GetTalentInfo(i) + if not name then break end + self_talent[i] = name + if selected then + self_talentPoints[i] = 1 + else + self_talentPoints[i] = 0 + end + i = i + 1 + end + self:SendMessage("Ovale_TalentsChanged") +end + +-- Update the player's glyphs by scanning the glyph socket tab for the active specialization. +function OvaleSpellBook:UpdateGlyphs() + wipe(self_glyph) + + local enabled, glyphSpell + for i = 1, API_GetNumGlyphSockets() do + enabled, _, _, glyphSpell, _ = API_GetGlyphSocketInfo(i) + if enabled and glyphSpell then + self_glyph[glyphSpell] = API_GetSpellInfo(glyphSpell) + end + end + self:SendMessage("Ovale_GlyphsChanged") +end + +-- Update the player's spells by scanning the first two tabs of the spellbook. +function OvaleSpellBook:UpdateSpells() + wipe(self_spell) + + local name, _, offset, numSpells = API_GetSpellTabInfo(2) + if name then + local skillType, spellId + local spellName + for i = 1, offset + numSpells do + skillType, spellId = API_GetSpellBookItemInfo(i, BOOKTYPE_SPELL) + if spellId and skillType ~= "FUTURESPELL" then + spellName = API_GetSpellBookItemName(i, BOOKTYPE_SPELL) + self_spell[spellId] = spellName + end + end + end + self:UpdatePetSpells() + self:SendMessage("Ovale_SpellsChanged") +end + +-- Update the player's pet spells by scanning the pet spellbook. +function OvaleSpellBook:UpdatePetSpells() + local hasPetSpells = API_HasPetSpells() + if hasPetSpells then + local skillType, spellId + local spellName + local i = 1 + while true do + skillType, spellId = API_GetSpellBookItemInfo(i, BOOKTYPE_PET) + if not spellId then break end + if skillType ~= "FUTURESPELL" then + spellName = API_GetSpellBookItemName(i, BOOKTYPE_PET) + self_spell[spellId] = spellName + end + i = i + 1 + end + end +end + +function OvaleSpellBook:GetSpellName(spellId) + if spellId then + local name = self_spell[spellId] + if not name then + name = API_GetSpellInfo(spellId) + end + return name + end +end + +function OvaleSpellBook:GetTalentPoints(talentId) + local points = 0 + if talentId and self_talentPoints[talentId] then + points = self_talentPoints[talentId] + end + return points +end + +function OvaleSpellBook:AddSpell(spellId, name) + if spellId and name then + self_spell[spellId] = name + end +end + +-- Returns true if the given glyph spell Id is an active glyph in the player's glyph tab. +function OvaleSpellBook:IsActiveGlyph(glyphId) + if glyphId and self_glyph[glyphId] then + return true + else + return false + end +end + +-- Returns true if the given spellId is found in the player's list of known spells. +function OvaleSpellBook:IsKnownSpell(spellId) + if spellId and self_spell[spellId] then + return true + else + return false + end +end + +-- Returns true if the given talentId is found in the player's talent tree. +function OvaleSpellBook:IsKnownTalent(talentId) + if talentId and self_talentPoints[talentId] then + return true + else + return false + end +end + +-- Print out the list of active glyphs in alphabetical order. +function OvaleSpellBook:DebugGlyphs() + PrintTableValues(self_glyph) +end + +-- Print out the list of known spells in alphabetical order. +function OvaleSpellBook:DebugSpells() + PrintTableValues(self_spell) +end + +-- Print out the list of talents in alphabetical order. +function OvaleSpellBook:DebugTalents() + PrintTableValues(self_talent) +end +-- \ No newline at end of file diff --git a/OvaleState.lua b/OvaleState.lua index 3674339..483815a 100644 --- a/OvaleState.lua +++ b/OvaleState.lua @@ -22,6 +22,7 @@ local OvaleEquipement = Ovale.OvaleEquipement local OvaleFuture = Ovale.OvaleFuture local OvaleGUID = Ovale.OvaleGUID local OvalePaperDoll = Ovale.OvalePaperDoll +local OvaleSpellBook = Ovale.OvaleSpellBook local OvaleStance = Ovale.OvaleStance local floor = math.floor @@ -91,7 +92,7 @@ end -- function OvaleState:StartNewFrame() self.maintenant = API_GetTime() - self.gcd = OvaleData:GetGCD() + self.gcd = self:GetGCD() end function OvaleState:UpdatePowerRates() @@ -114,7 +115,7 @@ function OvaleState:UpdatePowerRates() energyRegen = energyRegen / 1.4 end -- Ascension (monk): increases energy regen by 15%. - if OvaleData:GetTalentPoints(8) > 0 then + if OvaleSpellBook:GetTalentPoints(8) > 0 then energyRegen = energyRegen * 1.15 end -- Stance of the Sturdy Ox (brewmaster monk): increases Energy regeneration by 10%. @@ -272,8 +273,8 @@ function OvaleState:ApplySpell(spellId, startCast, endCast, nextCast, nocd, targ if si.eclipsedir then energy = energy * direction end - -- Eclipse energy generated is doubled if not in an Eclipse state with Euphoria. - if OvaleData.spellList[81062] + -- Euphoria: While not in an Eclipse state, your spells generate double the normal amount of Solar or Lunar energy. + if OvaleSpellBook:IsKnownSpell(81062) and not self:GetAura("player", LUNAR_ECLIPSE, "HELPFUL", true) and not self:GetAura("player", SOLAR_ECLIPSE, "HELPFUL", true) then energy = energy * 2 @@ -396,7 +397,7 @@ function OvaleState:ApplySpell(spellId, startCast, endCast, nextCast, nocd, targ -- Set the duration to the proper length if it's a DoT. if auraSpellInfo and auraSpellInfo.duration then - duration = OvaleData:GetDuration(auraSpellId, self.state.combo, self.state.holy) + duration = self:GetDuration(auraSpellId) end -- If aura is specified with a duration, then assume stacks == 1. @@ -427,7 +428,7 @@ function OvaleState:ApplySpell(spellId, startCast, endCast, nextCast, nocd, targ -- Add new duration after the next tick is complete. local remainingTicks = floor((oldEnding - endCast) / oldTick) newAura.ending = (oldEnding - oldTick * remainingTicks) + duration - newAura.tick = OvaleData:GetTickLength(auraSpellId) + newAura.tick = OvaleAura:GetTickLength(auraSpellId) -- Re-snapshot stats for the DoT. OvalePaperDoll:SnapshotStats(newAura, stats) newAura.damageMultiplier = self:GetDamageMultiplier(auraSpellId) @@ -453,7 +454,7 @@ function OvaleState:ApplySpell(spellId, startCast, endCast, nextCast, nocd, targ newAura.start = endCast newAura.ending = endCast + duration if isDoT then - newAura.tick = OvaleData:GetTickLength(auraSpellId) + newAura.tick = OvaleAura:GetTickLength(auraSpellId) OvalePaperDoll:SnapshotStats(newAura, stats) newAura.damageMultiplier = self:GetDamageMultiplier(auraSpellId) end @@ -486,6 +487,61 @@ function OvaleState:GetCounterValue(id) end end +-- Return the GCD after the given spellId is cast. +-- If no spellId is given, then returns the GCD after a "yellow-hit" ability has been cast. +function OvaleState:GetGCD(spellId) + -- Use SpellInfo() information if available. + if spellId and OvaleData.spellInfo[spellId] then + local si = OvaleData.spellInfo[spellId] + if si.haste then + local cd = si.gcd or 1.5 + if si.haste == "melee" then + cd = cd / OvalePaperDoll:GetMeleeHasteMultiplier() + elseif si.haste == "spell" then + cd = cd / OvalePaperDoll:GetSpellHasteMultiplier() + end + if cd < 1 then + cd = 1 + end + return cd + elseif si.gcd then + return si.gcd + end + end + + -- Default value. + local class = OvalePaperDoll.class + local isCaster = false + if class == "DRUID" and not (OvaleStance:IsStance("druid_bear_form") or OvaleStance:IsStance("druid_cat_form")) then + isCaster = true + elseif class == "MAGE" then + isCaster = true + elseif class == "PRIEST" then + isCaster = true + elseif class == "SHAMAN" then + isCaster = true + elseif class == "WARLOCK" then + isCaster = true + end + if isCaster then + local cd = 1.5 / OvalePaperDoll:GetSpellHasteMultiplier() + if cd < 1 then + cd = 1 + end + return cd + elseif class == "DEATHKNIGHT" then + return 1.0 + elseif class == "DRUID" and OvaleStance:IsStance("druid_cat_form") then + return 1.0 + elseif class == "MONK" then + return 1.0 + elseif class == "ROGUE" then + return 1.0 + else + return 1.5 + end +end + function OvaleState:GetCD(spellId) if not spellId then return nil @@ -742,6 +798,41 @@ function OvaleState:GetRunesCooldown(blood, frost, unholy, death, nodeath) return maxCD end +-- Returns the duration, tick length, and number of ticks of an aura. +function OvaleState:GetDuration(auraSpellId) + local si + if type(auraSpellId) == "number" then + si = OvaleData.spellInfo[auraSpellId] + elseif OvaleData.buffSpellList[auraSpellId] then + for spellId in pairs(OvaleData.buffSpellList[auraSpellId]) do + si = OvaleData.spellInfo[spellId] + if si then + auraSpellId = spellId + break + end + end + end + if si and si.duration then + local duration = si.duration + local combo = self.state.combo or 0 + local holy = self.state.holy or 1 + if si.adddurationcp then + duration = duration + si.adddurationcp * combo + end + if si.adddurationholy then + duration = duration + si.adddurationholy * (holy - 1) + end + if si.tick then -- DoT + --DoT duration is tick * numTicks. + local tick = OvaleAura:GetTickLength(auraSpellId) + local numTicks = floor(duration / tick + 0.5) + duration = tick * numTicks + return duration, tick, numTicks + end + return duration + end +end + -- Print out the levels of each power type in the current state. function OvaleState:DebugPower() for powerType in pairs(OvaleData.power) do diff --git a/compiler.pl b/compiler.pl index a521919..54f3a53 100644 --- a/compiler.pl +++ b/compiler.pl @@ -92,6 +92,7 @@ $p{Skada}{total} = true; $sp{Ovale}{OvaleBestAction} = true; $sp{Ovale}{OvaleCondition} = true; +$sp{Ovale}{OvaleData} = true; $sp{Ovale}{OvaleQueue} = true; $sp{Ovale}{OvalePool} = true; $sp{Ovale}{OvalePoolGC} = true; -- 1.7.9.5