diff --git a/.pkgmeta b/.pkgmeta new file mode 100644 index 0000000..b69b217 --- /dev/null +++ b/.pkgmeta @@ -0,0 +1,14 @@ +package-as: Ovale + +externals: + Libs/AceAddon-3.0: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceAddon-3.0 + Libs/AceConfig-3.0: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceConfig-3.0 + Libs/AceConsole-3.0: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceConsole-3.0 + Libs/AceDB-3.0: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceDB-3.0 + Libs/AceDBOptions-3.0: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceDBOptions-3.0 + Libs/AceGUI-3.0: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceGUI-3.0 + Libs/AceEvent-3.0: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceEvent-3.0 + Libs/AceLocale-3.0: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceLocale-3.0 + Libs/LibStub: svn://svn.wowace.com/wow/ace3/mainline/trunk/LibStub + + \ No newline at end of file diff --git a/Condition.lua b/Condition.lua new file mode 100644 index 0000000..fc80373 --- /dev/null +++ b/Condition.lua @@ -0,0 +1,279 @@ +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 + else + if (not a or (b~=nil and a<b)) then + return 0 + else + return nil + end + end +end + +local function testbool(a, condition) + if (condition == "yes") then + if (a) then + return 0 + else + return nil + end + else + if (not a) then + return 0 + else + return nil + end + end +end + +Ovale.conditions= +{ + -- Test if a white hit just occured + -- 1 : maximum time after a white hit + AfterWhiteHit = function(condition) + local debut = OvaleSwing.starttime + local fin = OvaleSwing.duration + debut + local maintenant = GetTime() + if (maintenant-debut<condition[1]) then + return 0 + elseif (maintenant<fin-0.1) then + return fin-maintenant + else + return 0.1 + end + end, + -- Test how many armor set parts are equiped by the player + -- 1 : set number + -- 2 : "more" or "less" + -- 3 : limit + ArmorSetParts = function(condition) + local nombre = 0 + if (OvaleEquipement.nombre[condition[1]]) then + nombre = OvaleEquipement.nombre[condition[1]] + end + return compare(nombre, condition[2], condition[3]) + end, + -- Test if a buff will expire on the player after a given time + -- 1 : buff spell id + -- 2 : expiration time + BuffExpires = function(condition) + local buffName = Ovale:GetSpellInfoOrNil(condition[1]) + i=1; + while (true) do + local name, rank, icon, count, debuffType, duration, expirationTime, isMine, isStealable = UnitBuff("player", i); + if (not name) then + break + end + if (name == buffName) then + local timeLeft = expirationTime - Ovale.maintenant + if (timeLeft<condition[2]) then + return 0 + else + return timeLeft-condition[2] + end + end + i = i + 1; + end + return 0 + end, + -- Test if a buff is active + -- 1 : the buff spell id + BuffPresent = function(condition) + if (not condition[1]) then + return nil + end + local buffName, buffRank, buffIcon = Ovale:GetSpellInfoOrNil(condition[1]) + i=1; + while (true) do + local name, rank, icon, count, debuffType, duration, expirationTime, isMine, isStealable = UnitBuff("player", i); + if (not name) then + break + end + if (name == buffName and icon==buffIcon) then + return 0 + end + i = i + 1; + end + return nil + end, + -- Test if a list of checkboxes is off + -- 1,... : the checkboxes names + CheckBoxOff = function(condition) + for k,v in pairs(condition) do + if (Ovale:IsChecked(v)) then + return nil + end + end + return 0 + end, + -- Test if a list of checkboxes is on + -- 1,... : the checkboxes names + CheckBoxOn = function(condition) + for k,v in pairs(condition) do + if (not Ovale:IsChecked(v)) then + return nil + end + end + return 0 + end, + -- Test how many combo points a feral druid or a rogue has + -- 1 : "less" or "more" + -- 2 : the limit + ComboPoints = function(condition) + local points = GetComboPoints("player") + return compare(points, condition[1], condition[2]) + end, + -- Test if the player life is bellow/above a given value in percent + -- 1 : "less" or "more" + -- 2 : the limit, in percent + LifePercent = function(condition) + return compare(UnitHealth("player")/UnitHealthMax("player"), condition[1], condition[2]/100) + end, + -- Test if a list item is selected + -- 1 : the list name + -- 2 : the item name + List = function(condition) + if (condition[1]) then + if (Ovale:GetListValue(condition[1]) == condition[2]) then + return 0 + end + end + return nil + end, + -- Test if the player mana is above/bellow a given value + -- 1 : "less" or "more" + -- 2 : the mana/energy/rage... limit + Mana = function(condition) + return compare(UnitPower("player"), condition[1], condition[2]) + 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 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, + -- 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, + -- Test the target classification + -- 1 : normal, elite, or worldboss + TargetClassification = function(condition) + local classification = UnitClassification("target"); + if (classification == "rareelite") then + classification = "elite" + elseif (classification == "rare") then + classification = "normal" + end + + if (condition[1]==classification) then + return 0 + else + return nil + end + end, + -- Test if a debuff will expire on the target after a given time, or if there is less than the + -- given number of stacks (if stackable) + -- 1 : buff spell id + -- 2 : expiration time + -- stacks : how many stacks + -- mine : 1 means that if the debuff is not ours, the debuff is ignored + TargetDebuffExpires = function(condition) + local debuffName = Ovale:GetSpellInfoOrNil(condition[1]) + i=1; + while (true) do + local name, rank, icon, count, debuffType, duration, expirationTime, isMine, isStealable = UnitDebuff("target", i); + if (not name) then + break + end + if (not condition.mine or isMine) then + if (name == debuffName) then + local timeLeft = expirationTime - Ovale.maintenant + if (timeLeft<condition[2]) then + return 0 + elseif (count~=0 and condition.stacks and count<condition.stacks) then + return 0 + else + return timeLeft-condition[2] + end + end + end + i = i + 1; + end + return 0 + end, + -- Test if a debuff is present on the target + -- 1 : debuff spell id + -- stacks : how many stacks + -- mine : 1 means that the debuff must be yours + TargetDebuffPresent = function(condition) + local debuffName = Ovale:GetSpellInfoOrNil(condition[1]) + i=1; + while (true) do + local name, rank, icon, count, debuffType, duration, expirationTime, isMine, isStealable = UnitDebuff("target", i); + if (not name) then + break + end + if (not condition.mine or isMine) then + if (name == debuffName) then + local timeLeft = expirationTime - Ovale.maintenant + if (count~=0 and condition.stacks) then + if (count<condition.stacks) then + return nil + else + return 0 + end + else + return 0 + end + end + end + i = i + 1; + end + return 0 + end, + -- Test if the target life is bellow/above a given value in percent + -- 1 : "less" or "more" + -- 2 : the limit, in percents + TargetLifePercent = function(condition) + return compare(UnitHealth("target")/UnitHealthMax("target"), condition[1], condition[2]/100) + end, + -- Test the target level difference with the player + -- 1 : "less" or "more" + -- 2 : [target level]-[player level] limit + TargetRelativeLevel = function(condition) + local difference + if (UnitLevel("target") == -1) then + difference = 3 + else + difference = UnitLevel("target") - UnitLevel("player") + end + + return compare(difference, condition[1], condition[2]) + end, + -- Test if the target's target is the player (or is not) + -- 1 : "yes" (it should be the player) or "no" + TargetTargetIsPlayer = function(condition) + return testbool(UnitIsUnit("player","targettarget"), condition[1]) + end +} \ No newline at end of file diff --git a/Locale-frFR.lua b/Locale-frFR.lua new file mode 100644 index 0000000..b777878 --- /dev/null +++ b/Locale-frFR.lua @@ -0,0 +1,3 @@ +local AceLocale = LibStub:GetLibrary("AceLocale-3.0") +local L = AceLocale:NewLocale("Ovale", "frFR",true) +if not L then return end diff --git a/Ovale.lua b/Ovale.lua new file mode 100644 index 0000000..23c5d04 --- /dev/null +++ b/Ovale.lua @@ -0,0 +1,640 @@ +local L = LibStub("AceLocale-3.0"):GetLocale("Ovale") + +Ovale = LibStub("AceAddon-3.0"):NewAddon("Ovale", "AceEvent-3.0", "AceConsole-3.0") + +Ovale.defaut = {} +Ovale.action = {} +Ovale.listeSorts = {} +Ovale.casesACocher = {} +Ovale.actionSort = {} +Ovale.listeFormes = {} +Ovale.listeTalents = {} +Ovale.pointsTalent = {} +Ovale.talentIdToName = {} +Ovale.talentNameToId = {} +Ovale.firstInit = false +Ovale.Inferieur = 1 +Ovale.Superieur = 2 +Ovale.retourPriorite = 0 +Ovale.retourAction = nil +Ovale.listeTalentsRemplie = false +Ovale.frame = nil +Ovale.checkBoxes = {} +Ovale.dropDowns = {} +Ovale.masterNode = nil +Ovale.bug = false + +Ovale.arbre = {} + +-- Ovale.trace=true +local nouvelleCondition +local nouveauSort + +local options = +{ + type = "group", + args = + { + code = + { + name = "Code", + type = "group", + args = + { + code = + { + order = 2, + type = "input", + multiline = 20, + name = "Code", + get = function(info) + return Ovale.db.profile.code + end, + set = function(info,v) + Ovale.db.profile.code = v + -- Ovale:Print("code change") + end, + width = "full" + }, + compiler = + { + order = 1, + type = "execute", + name = "Compiler", + func = function() + Ovale.masterNode = Ovale:Compile(Ovale.db.profile.code) + -- Ovale:Print(Ovale:DebugNode(Ovale.masterNode)) + end + } + } + } + } +} + +function Ovale:OnInitialize() + self.AceConfig = LibStub("AceConfig-3.0"); + self.AceConfigDialog = LibStub("AceConfigDialog-3.0"); +end + +function Ovale:ACTIONBAR_SLOT_CHANGED(event, slot, unknown) + if (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:CHARACTER_POINTS_CHANGED() + self:RemplirListeTalents() +end + +function Ovale:SPELLS_CHANGED() + self:RemplirListeSorts(); + self:RemplirListeFormes() + self:RemplirActionIndexes() + self:RemplirListeTalents() +end + +function Ovale:UPDATE_BINDINGS() + self:RemplirActionIndexes() +end + +function Ovale:HandleProfileChanges() + if (self.firstInit) then + if (self.db.profile.code) then + self.masterNode = self:Compile(self.db.profile.code) + end + end +end + +function Ovale:FirstInit() + self:RemplirListeSorts() + self:RemplirListeFormes() + self:RemplirActionIndexes() + self:RemplirListeTalents() + -- self:InitEcranOption() + + local playerClass, englishClass = UnitClass("player") + if (englishClass == "ROGUE") then + self.gcd = 1 + else + self.gcd = 1.5 + end + -- OvaleFrame_Update(OvaleFrame) + -- OvaleFrame:Show() + + self:ChargerDefaut() + + self.frame = LibStub("AceGUI-3.0"):Create("OvaleFrame") + + self.frame:SetWidth(64) + self.frame:SetHeight(64) + self.frame:SetPoint("TOPLEFT",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, "Ovale") + self.AceConfig:RegisterOptionsTable("Ovale Profile", options.args.profile) + + self.AceConfigDialog:AddToBlizOptions("Ovale", "Ovale") + self.AceConfigDialog:AddToBlizOptions("Ovale Profile", "Profile", "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 + self.masterNode = self:Compile(self.db.profile.code) + end + + --self:UpdateFrame() + + self:Test() +end + +function Ovale:OnEnable() + -- Called when the addon is enabled + self:RegisterEvent("PLAYER_REGEN_ENABLED"); + self:RegisterEvent("PLAYER_REGEN_DISABLED"); + self:RegisterEvent("SPELLS_CHANGED") + self:RegisterEvent("CHARACTER_POINTS_CHANGED") + self:RegisterEvent("ACTIONBAR_SLOT_CHANGED"); + self:RegisterEvent("UPDATE_BINDINGS"); + + if (not self.firstInit) then + self:FirstInit() + end + +end + +function Ovale:PLAYER_REGEN_ENABLED() +end + +function Ovale:PLAYER_REGEN_DISABLED() +end + +function Ovale:OnDisable() + -- Called when the addon is disabled + self:UnregisterEvent("PLAYER_REGEN_ENABLED") + self:UnregisterEvent("PLAYER_REGEN_DISABLED") + self:UnregisterEvent("ACTIONBAR_SLOT_CHANGED") + self:UnregisterEvent("SPELLS_CHANGED") + self:UnregisterEvent("CHARACTER_POINTS_CHANGED") + self:UnregisterEvent("UPDATE_BINDINGS") + self.frame:Hide() +end + +function Ovale_GetNomAction(i) + local actionText = GetActionText(i); + local text; + if (actionText) then + text = "Macro "..actionText; + else + local type, id = GetActionInfo(i); + if (type=="spell") then + if (id~=0) then + local spellName, spellRank = GetSpellName(id, BOOKTYPE_SPELL); + text = "Sort ".. spellName; + if (spellRank and spellRank~="") then + text = text .. " ("..spellRank..")" + end + end + elseif (type =="item") then + local itemName = GetItemInfo(id) + text = "Objet "..itemName + else + if (type) then + text = type; + if (id) then + text = text.." "..id; + end + end + end + end + return text +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:GetSpellIdByName(name) + if (not name) then + return nil + end + local link = GetSpellLink(name); + if (not link) then + -- self:Print(name.." introuvable"); + return nil; + end + local a, b, spellId = string.find(link, "spell:(%d+)"); + return tonumber(spellId); +end + +function Ovale:GetSpellIdRangMax(spellId) + return self:GetSpellIdByName(GetSpellInfo(spellId)) +end + +function Ovale:GetSpellIdByNameAndRank(name,rank) + if (not name or not rank) then + return nil + end + local link = GetSpellLink(name.."("..rank..")"); + if (not link) then + -- self:Print(name.."("..rank..")".." introuvable"); + return nil; + end + local a, b, spellId = string.find(link, "spell:(%d+)"); + return tonumber(spellId); +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, id = GetActionInfo(i); + if (type=="spell") then + if (id~=0) then + local spellName, spellRank = GetSpellName(id, BOOKTYPE_SPELL); + self.actionSort[spellName] = i + end + elseif (type =="item") then + self.actionObjet[id] = 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:RemplirListeFormes() + self.listeFormes[0] = "Humanoïde"; + local index=1; + while true do + local icon, name, active, castable = GetShapeshiftFormInfo(index); + if not icon then + break; + end + Ovale.listeFormes[index] = name; + index = index + 1 + end +end + +function Ovale:RemplirListeSorts() + local sorts = {}; + local name, texture, offset, numSpells = GetSpellTabInfo(1); + local i=numSpells+1; + while true do + local spellName, spellRank = GetSpellName(i, BOOKTYPE_SPELL) + if not spellName then + break + end + -- DEFAULT_CHAT_FRAME:AddMessage(spellName); + local nom = spellName; + local a, b, numeroRang = string.find(spellRank, "(%d+)"); + --if (not numeroRang or tonumber(numeroRang)==1) then + Ovale.listeSorts[nom] = nom; + --else + --end + i = i+1; + end +end + +function Ovale:RemplirListeTalents() + local numTabs = GetNumTalentTabs(); + self.listeTalents = {} + for t=1, numTabs do + local numTalents = GetNumTalents(t); + for i=1, numTalents do + local nameTalent, icon, tier, column, currRank, maxRank= GetTalentInfo(t,i); + self.listeTalents[nameTalent] = nameTalent + local link = GetTalentLink(t,i) + local a, b, talentId = string.find(link, "talent:(%d+)"); + -- self:Print("talent = "..nameTalent.." id = ".. talentId) + talentId = tonumber(talentId) + self.talentIdToName[talentId] = nameTalent + self.talentNameToId[nameTalent] = talentId + self.pointsTalent[talentId] = currRank + self.listeTalentsRemplie = true + end + end +end + +function Ovale:ChercherBouton(sort) + if (not sort) then + return nil + end + local nom = GetSpellInfo(tonumber(sort)) + for i=1,120 do + local type, id = GetActionInfo(i); + if (type=="spell") then + local spellName, spellRank = GetSpellName(id, BOOKTYPE_SPELL); + if (spellName == nom) then + return i + end + end + end +end + +function Ovale:CalculerMeilleureAction(element) + if (self.bug and not self.trace) then + return nil + end + + if (not element) then + return nil + end + + self.retourAction = nil + self.retourPriorite = nil + + if (element.type=="function")then + if (element.func == "Spell" or element.func=="Macro" or element.func=="Item") then + local action + if (element.func == "Spell" ) then + local sort = self:GetSpellInfoOrNil(element.params[1]) + action = self.actionSort[sort] + elseif (element.func=="Macro") then + action = self.actionMacro[element.params[1]] + elseif (element.func=="Item") then + action = self.actionObjet[element.params[1]] + end + if (not action) then + if (Ovale.trace) then + self:Print("Action "..element.params[1].." not found") + end + return nil + end + if (element.params.usable==1 and not IsUsableAction(action)) then + if (Ovale.trace) then + self:Print("Action "..element.params[1].." not usable") + end + return nil + end + if (element.params.doNotRepeat==1 and IsCurrentAction(action)) then + if (Ovale.trace) then + self:Print("Action "..element.params[1].." is current action") + end + return nil + end + local start, duration, enable = GetActionCooldown(action) + local restant + if (enable>0) then + if (not duration or start==0) then + restant = 0 + else + restant = duration - (self.maintenant - start); + end + if (Ovale.trace) then + self:Print("Action "..element.params[1].." remains "..restant) + end + self.retourAction = action + self.retourPriorite = element.params.priority + if (not self.retourPriorite) then + self.retourPriorite = 3 + end + return restant + else + if (Ovale.trace) then + self:Print("Action "..element.params[1].." not enabled") + end + return nil + end + else + local classe = Ovale.conditions[element.func] + if (not classe) then + self.bug = true + self:Print("Function "..element.func.." not found") + return nil + end + local temps = classe(element.params) + + if (Ovale.trace) then + if (temps==nil) then + self:Print("Function "..element.func.." returned nil") + else + self:Print("Function "..element.func.." returned "..temps) + end + end + + if (temps == nil) then + return nil + end + return temps + end + elseif (element.type == "and" or element.type == "if") then + if (Ovale.trace) then + self:Print(element.type) + end + local tempsA = Ovale:CalculerMeilleureAction(element.a) + if (tempsA==nil) then + return nil + end + local tempsB = Ovale:CalculerMeilleureAction(element.b) + if (tempsB==nil) then + return nil + end + if (tempsB>tempsA) then + return tempsB + else + return tempsA + end + elseif (element.type == "unless") then + if (Ovale.trace) then + self:Print(element.type) + end + local tempsA = Ovale:CalculerMeilleureAction(element.a) + if (tempsA~=nil) then + return nil + end + local tempsB = Ovale:CalculerMeilleureAction(element.b) + return tempsB + elseif (element.type == "or") then + if (Ovale.trace) then + self:Print(element.type) + end + + local tempsA = Ovale:CalculerMeilleureAction(element.a) + local tempsB = Ovale:CalculerMeilleureAction(element.b) + if (tempsB==nil or tempsB>tempsA) then + return tempsA + else + return tempsB + end + elseif (element.type == "group") then + local meilleurFils + local meilleurTempsFils + local meilleurePrioriteFils + + if (Ovale.trace) then + self:Print(element.type) + end + + for k, v in ipairs(element.nodes) do + local nouveauTemps = Ovale:CalculerMeilleureAction(v) + local action = self.retourAction + local priorite = self.retourPriorite + if (nouveauTemps) then + local remplacer + if (not meilleurTempsFils) then + remplacer = true + else + -- temps maximum entre le nouveau sort et le précédent + local maxEcart + if (priorite and not meilleurePrioriteFils) then + self.bug = true + self:Print("meilleurePrioriteFils nil and priorite not nil") + return nil + end + if (priorite and priorite > meilleurePrioriteFils) then + -- Si le nouveau sort est plus prioritaire que le précédent, on le lance + -- même si on doit attendre jusqu'à gcd secondes de plus + maxEcart = self.gcd + elseif (priorite and priorite < meilleurePrioriteFils) then + -- A l'inverse, si il est moins prioritaire que le précédent, on ne le lance + -- que si il se lance au moins 1,5s avant + maxEcart = -self.gcd + else + maxEcart = 0 + end + if (nouveauTemps-meilleurTempsFils < maxEcart) then + remplacer = true + end + end + if (remplacer) then + meilleurTempsFils = nouveauTemps + meilleurFils = action + meilleurePrioriteFils = priorite + end + end + end + + if (meilleurFils) then + if (Ovale.trace) then + self:Print("Best action "..meilleurFils.." remains "..meilleurTempsFils) + end + self.retourPriorite = meilleurePrioriteFils + self.retourAction = meilleurFils + return meilleurTempsFils + else + return nil + end + end +end + +function Ovale:ChargerDefaut() + local localizedClass, englishClass = UnitClass("player") + + self.db = LibStub("AceDB-3.0"):New("OvaleDB", + { + profile = + { + code = Ovale.defaut[englishClass], + left = 0, + top = 0, + check = {}, + list = {} + } + }) +end + +function Ovale:AfficherConfig() + self.AceConfigDialog:SetDefaultSize("Ovale", 500, 550) + self.AceConfigDialog:Open("Ovale", configFrame) +end + +local function OnCheckBoxValueChanged(widget) + Ovale.db.profile.check[widget.userdata.k] = widget:GetValue() +end + +local function OnDropDownValueChanged(widget) + Ovale.db.profile.list[widget.userdata.k] = widget.value +end + +function Ovale:UpdateFrame() + self.frame:ReleaseChildren() + + self.checkBoxes = {} + + for k,v in pairs(self.casesACocher) do + self.checkBoxes[k] = LibStub("AceGUI-3.0"):Create("CheckBox"); + self.frame:AddChild(self.checkBoxes[k]) + self.checkBoxes[k]:SetLabel(v) + if (self.db.profile.check[k]) then + self.checkBoxes[k]:SetValue(self.db.profile.check[k]); + end + self.checkBoxes[k].userdata.k = k + self.checkBoxes[k]:SetCallback("OnValueChanged",OnCheckBoxValueChanged) + end + + self.dropDowns = {} + + if (self.listes) then + for k,v in pairs(self.listes) do + self.dropDowns[k] = LibStub("AceGUI-3.0"):Create("Dropdown"); + self.dropDowns[k]:SetList(v) + if (self.db.profile.list[k]) then + self.dropDowns[k]:SetValue(self.db.profile.list[k]); + end + self.dropDowns[k].userdata.k = k + self.dropDowns[k]:SetCallback("OnValueChanged",OnDropDownValueChanged) + self.frame:AddChild(self.dropDowns[k]) + end + end +end + +function Ovale:IsChecked(v) + return self.checkBoxes[v] and self.checkBoxes[v]:GetValue() +end + +function Ovale:GetListValue(v) + return self.dropDowns[v] and self.dropDowns[v].value +end + +function Ovale:Test() + this.node = {} + +end \ No newline at end of file diff --git a/Ovale.toc b/Ovale.toc new file mode 100644 index 0000000..8a68d85 --- /dev/null +++ b/Ovale.toc @@ -0,0 +1,31 @@ +## Interface: 30000 +## Title: Ovale +## Notes: Affiche l'icône du prochain sort à lancer +## Author: Sidoine +## Version: 0.1 +## OptionalDeps: Ace3 +## SavedVariables: OvaleDB +## SavedVariablesPerCharacter: OvaleDBPC +## X-Category: Combat +## X-Embeds: Ace3 + +embeds.xml + +Locale-frFR.lua +Ovale.lua +Condition.lua +OvaleIcone.lua +OvaleIcone.xml +OvaleFrame.lua +OvaleSwing.lua +OvaleCompile.lua +defaut\Chaman.lua +defaut\Chasseur.lua +defaut\Demoniste.lua +defaut\Druide.lua +defaut\Guerrier.lua +defaut\Mage.lua +defaut\Paladin.lua +defaut\Pretre.lua +defaut\Voleur.lua + diff --git a/OvaleCompile.lua b/OvaleCompile.lua new file mode 100644 index 0000000..5067920 --- /dev/null +++ b/OvaleCompile.lua @@ -0,0 +1,183 @@ +local node={} +local defines = {} + +local function ParseFunction(func, params) + local paramList = {} + for k,v in string.gmatch(params, "(%w+)=(%w+)") do + if (string.match(v,"^%-?%d+%.?%d*$")) then + v = tonumber(v) + end + paramList[k] = v + end + params = string.gsub(params,"%w+=%w+","") + local n=0 + for w in string.gmatch(params, "%w+") do + if (string.match(w,"^%-?%d+%.?%d*$")) then + w = tonumber(w) + end + paramList[n+1] = w + n=n+1 + end + local newNode = { type="function", func=func, params=paramList} + node[#node+1] = newNode + return "node"..#node +end + +local function ParseIf(a, b) + local newNode = {type="if", a=node[tonumber(a)], b=node[tonumber(b)]} + node[#node+1] = newNode + return "node"..#node +end + +local function ParseUnless(a, b) + local newNode = {type="unless", a=node[tonumber(a)], b=node[tonumber(b)]} + node[#node+1] = newNode + return "node"..#node +end + +local function ParseAnd(a,b) + local newNode = {type="and", a=node[tonumber(a)], b=node[tonumber(b)]} + node[#node+1] = newNode + return "node"..#node +end + +local function ParseOr(a,b) + local newNode = {type="or", a=node[tonumber(a)], b=node[tonumber(b)]} + node[#node+1] = newNode + return "node"..#node +end + +local function ParseGroup(text) + text = string.gsub(text, "if%s+node(%d+)%s+node(%d+)",ParseIf) + text = string.gsub(text, "unless%s+node(%d+)%s+node(%d+)",ParseUnless) + local nodes={} + + for w in string.gmatch(text, "node(%d+)") do + nodes[#nodes+1] = node[tonumber(w)] + end + + text = string.gsub(text, "node%d+", "") + + if (string.match(text,"[^ ]")) then + Ovale:Print("syntax error:"..text) + return nil + end + + local newNode = {type="group", nodes=nodes} + node[#node+1] = newNode + return "node"..#node +end + +local function subtest(text, pattern, func) + while (1==1) do + local was = text + text = string.gsub(text, pattern, func) + if (was == text) then + break + end + end + return text +end + +local function ParseAddListItem(list,item,text) + if (not Ovale.listes[list]) then + Ovale.listes[list] = {} + end + Ovale.listes[list][item] = text + return "" +end + +local function ParseAddCheckBox(item, text) + Ovale.casesACocher[item] = text + return "" +end + +local function ParseDefine(key, value) + defines[key] = value + return "" +end + +function Ovale:CompileInputs(text) + self.casesACocher = {} + self.listes = {} + + text = string.gsub(text, "AddListItem%s*%(%s*(%w+)%s+(%w+)%s+\"(.-)\"%s*%)", ParseAddListItem) + text = string.gsub(text, "AddCheckBox%s*%(%s*(%w+)%s+\"(.-)\"%s*%)", ParseAddCheckBox) + + self:UpdateFrame() + return text +end + +function Ovale:Compile(text) + self.bug = false + node = {} + defines = {} + + text = string.gsub(text, "#.-\n","") + + text = string.gsub(text, "Define%s*%(%s*(%w+)%s+(%w+)%s*%)", ParseDefine) + + for k,v in pairs(defines) do + text = string.gsub(text, "([^%w])"..k.."([^%w])", "%1"..v.."%2") + end + + text = self:CompileInputs(text) + + text = string.gsub(text, "\n", " ") + text = string.gsub(text, "%s+", " ") + + text = string.gsub(text, "(%w+)%s*%((.-)%)", ParseFunction) + text = subtest(text, "node(%d+)%s+and%s+node(%d+)", ParseAnd) + text = subtest(text, "node(%d+)%s+or%s+node(%d+)", ParseOr) + + text = subtest(text, "{([^{}]*)}", ParseGroup) + + text = ParseGroup(text) + local masterNode + if (text) then + masterNode = string.match(text, "node(%d+)") + end + if (not masterNode) then + self:Print("no master node") + return nil + end + text = string.gsub(text, "node%d+", "", 1) + if (string.match(text,"[^ ]")) then + self:Print("syntax error:"..text) + return nil + end + masterNode = node[tonumber(masterNode)] + return masterNode +end + +function Ovale:DebugNode(node) + local text + if (not node) then + return "#nil" + end + if (node.type == "group") then + text = "{" + for k,n in ipairs(node.nodes) do + text = text .. self:DebugNode(n) .. " " + end + text = text .. "}\n" + elseif (node.type == "function") then + text = node.func.."(" + for k,p in pairs(node.params) do + text = text .. k.."=" .. p .. " " + end + text = text .. ")" + elseif (node.type == "if") then + text = "if "..self:DebugNode(node.a).." "..self:DebugNode(node.b) + elseif (node.type == "unless") then + text = "unless "..self:DebugNode(node.a).." "..self:DebugNode(node.b) + elseif (node.type == "and") then + text = self:DebugNode(node.a).." and "..self:DebugNode(node.b) + elseif (node.type == "or") then + text = self:DebugNode(node.a).." and "..self:DebugNode(node.b) + else + text = "#unknown node type#" + end + + return text +end \ No newline at end of file diff --git a/OvaleFrame.lua b/OvaleFrame.lua new file mode 100644 index 0000000..c70e59a --- /dev/null +++ b/OvaleFrame.lua @@ -0,0 +1,267 @@ +local AceGUI = LibStub("AceGUI-3.0") + +---------------- +-- Main Frame -- +---------------- +--[[ + Events : + OnClose + +]] +do + local Type = "OvaleFrame" + local Version = 7 + + local FrameBackdrop = { + bgFile="Interface\\DialogFrame\\UI-DialogBox-Background", + edgeFile="Interface\\DialogFrame\\UI-DialogBox-Border", + tile = true, tileSize = 32, edgeSize = 32, + insets = { left = 8, right = 8, top = 8, bottom = 8 } + } + + local function frameOnClose(this) + this.obj:Fire("OnClose") + end + + local function closeOnClick(this) + this.obj:Hide() + end + + local function frameOnMouseDown(this) + this:StartMoving() + AceGUI:ClearFocus() + end + + local function titleOnMouseDown(this) + AceGUI:ClearFocus() + end + + local function frameOnMouseUp(this) + this:StopMovingOrSizing() + Ovale.db.profile.left = this:GetLeft() + Ovale.db.profile.top = this:GetTop() + end + + local function titleOnMouseUp(this) + --[[ local frame = this:GetParent() + frame:StopMovingOrSizing() + local self = frame.obj + local status = self.status or self.localstatus + status.width = frame:GetWidth() + status.height = frame:GetHeight() + status.top = frame:GetTop() + status.left = frame:GetLeft() ]]-- + end + + local function sizerseOnMouseDown(this) + this:GetParent():StartSizing("BOTTOMRIGHT") + AceGUI:ClearFocus() + end + + local function sizersOnMouseDown(this) + this:GetParent():StartSizing("BOTTOM") + AceGUI:ClearFocus() + end + + local function sizereOnMouseDown(this) + this:GetParent():StartSizing("RIGHT") + AceGUI:ClearFocus() + end + + local function sizerOnMouseUp(this) + this:GetParent():StopMovingOrSizing() + end + + local function SetTitle(self,title) + self.titletext:SetText(title) + end + + local function SetStatusText(self,text) + self.statustext:SetText(text) + end + + local function Hide(self) + self.frame:Hide() + end + + local function Show(self) + self.frame:Show() + end + + local function OnAcquire(self) + self.frame:SetParent(UIParent) + self.frame:SetFrameStrata("FULLSCREEN_DIALOG") + self:ApplyStatus() + end + + local function OnRelease(self) + self.status = nil + for k in pairs(self.localstatus) do + self.localstatus[k] = nil + end + end + + -- called to set an external table to store status in + local function SetStatusTable(self, status) + assert(type(status) == "table") + self.status = status + self:ApplyStatus() + end + + local function ApplyStatus(self) + local status = self.status or self.localstatus + local frame = self.frame + self:SetWidth(status.width or 700) + self:SetHeight(status.height or 500) + if status.top and status.left then + frame:SetPoint("TOP",UIParent,"BOTTOM",0,status.top) + frame:SetPoint("LEFT",UIParent,"LEFT",status.left,0) + else + frame:SetPoint("CENTER",UIParent,"CENTER") + end + end + + local function OnWidthSet(self, width) + local content = self.content + local contentwidth = width - 34 + if contentwidth < 0 then + contentwidth = 0 + end + content:SetWidth(contentwidth) + content.width = contentwidth + end + + + local function OnHeightSet(self, height) + local content = self.content + local contentheight = height - 57 + if contentheight < 0 then + contentheight = 0 + end + content:SetHeight(contentheight) + content.height = contentheight + end + + local function Constructor() + local frame = CreateFrame("Frame",nil,UIParent) + local self = {} + self.type = "Frame" + + self.Hide = Hide + self.Show = Show + self.SetTitle = SetTitle + self.OnRelease = OnRelease + self.OnAcquire = OnAcquire + self.SetStatusText = SetStatusText + self.SetStatusTable = SetStatusTable + self.ApplyStatus = ApplyStatus + self.OnWidthSet = OnWidthSet + self.OnHeightSet = OnHeightSet + + self.localstatus = {} + + self.frame = frame + frame.obj = self + frame:SetWidth(100) + frame:SetHeight(100) + frame:SetPoint("CENTER",UIParent,"CENTER",0,0) + frame:EnableMouse() + frame:SetMovable(true) + frame:SetResizable(true) + frame:SetFrameStrata("FULLSCREEN_DIALOG") + frame:SetScript("OnMouseDown", frameOnMouseDown) + -- title:SetScript("OnMouseDown",titleOnMouseDown) + frame:SetScript("OnMouseUp", frameOnMouseUp) + + --[[frame:SetBackdrop(FrameBackdrop) + frame:SetBackdropColor(0,0,0,1)]]-- + frame:SetScript("OnHide",frameOnClose) + frame:SetMinResize(400,200) + frame:SetToplevel(true) + + self.icone = CreateFrame("Frame",nil,frame,"OvaleIcone"); + self.icone:SetPoint("TOPLEFT",frame,"TOPLEFT",0,0) + self.icone:SetWidth(64) + self.icone:SetHeight(64) + self.icone:Show(); + + --Container Support + local content = CreateFrame("Frame",nil,frame) + self.content = content + content.obj = self + content:SetPoint("TOPLEFT",frame,"TOPLEFT",64,0) + content:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT",0,0) + + AceGUI:RegisterAsContainer(self) + + return self + end + + AceGUI:RegisterWidgetType(Type,Constructor,Version) +end + + + +--[[ +function OvaleFrame_OnLoad(self) + self.icone = CreateFrame("Frame",nil,self,"OvaleIcone"); + self.icone:SetAllPoints(self) + self.icone:Show(); + + --self.cases = {} + --local case = CreateFrame("Button", "OvaleCheck", self) + --case:SetPoint("TOPLEFT", 0, 0) + --self.cases[#self.cases] = case + self.checkBoxes = {} + + self.dropDowns = {}; + local tf = LibStub("AceGUI-3.0"):Create("Frame") + tf:SetWidth(200) + tf:SetHeight(200) + local tl = LibStub("AceGUI-3.0"):Create("Label") + tl:SetText("Anfangstext") + local ti = LibStub("AceGUI-3.0"):Create("Icon") + ti:SetHeight(50) + ti:SetWidth(50) + + tf:AddChild(tl) + tf:AddChild(ti) +end + +function OvaleFrame_Update(self) + for v,k in pairs(self.checkBoxes) do + k:Hide() + end + + for v,k in pairs(Ovale.casesACocher) do + if (not self.checkBoxes[v]) then + self.checkBoxes[v] = OvaleFrame_CreateCheckBox(self, v) + end + self.checkBoxes[v]:Show() + self.checkBoxes[v].text:SetText(k) + end + +end + + +-- Idem. Liste déroulante + + + + + +function OvaleFrame_OnUpdate(self) + +end +function OvaleFrame_OnMouseDown(self,button) + if ( button == "LeftButton") then + self:StartMoving(); + end +end + +function OvaleFrame_OnMouseUp(self, button) + if ( button == "LeftButton" ) then + self:StopMovingOrSizing(); + end +end +]]-- \ No newline at end of file diff --git a/OvaleFrame.xml b/OvaleFrame.xml new file mode 100644 index 0000000..1b70ed4 --- /dev/null +++ b/OvaleFrame.xml @@ -0,0 +1,56 @@ +<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/ ..\..\FrameXML\UI.xsd"> + <Frame name="OvaleFrame" parent="UIParent" movable="true" hidden="false"> + <Anchors> + <Anchor point="TOPLEFT" relativeTo="UIParent"> + <Offset> + <AbsDimension x="200" y="-100"/> + </Offset> + </Anchor> + </Anchors> + <Size> + <AbsDimension x="64" y="64"/> + </Size> + <!-- + <Layers> + <Layer level="ARTWORK"> + <FontString name="$parent_Title" inherits="GameFontNormal" hidden="false" text="RaidStatus"> + <Anchors> + <Anchor point="TOP"> + <Offset> + <AbsDimension x="0" y="-5"/> + </Offset> + </Anchor> + </Anchors> + <Size> + <AbsDimension x="300" y="50"/> + </Size> + </FontString> + </Layer> + </Layers> + --> + <Scripts> + <OnMouseDown>OvaleFrame_OnMouseDown(self,button);</OnMouseDown> + <OnMouseUp>OvaleFrame_OnMouseUp(self,button);</OnMouseUp> + <OnLoad>OvaleFrame_OnLoad(self);</OnLoad> + <!-- <OnEvent>OvaleFrame_OnEvent(self,event);</OnEvent>--> + <OnUpdate>OvaleFrame_OnUpdate(self);</OnUpdate> + </Scripts> + <Frames> + <Button name="$parentOption" text="$parentType"> + <Size> + <AbsDimension x="15" y="15" /> + </Size> + <Anchors> + <Anchor point="TOPRIGHT" relativePoint="TOPLEFT" /> + </Anchors> + <Scripts> + <OnLoad> + self:SetNormalTexture("Interface\\Icons\\INV_Misc_Wrench_01") + self:SetHighlightTexture("Interface\\Buttons\\ButtonHilight-Square") + </OnLoad> + <OnClick>Ovale:AfficherConfig()</OnClick> + </Scripts> + </Button> + </Frames> + </Frame> +</Ui> diff --git a/OvaleIcone.lua b/OvaleIcone.lua new file mode 100644 index 0000000..271df91 --- /dev/null +++ b/OvaleIcone.lua @@ -0,0 +1,106 @@ +function OvaleIcone_OnUpdate(self) + Ovale.maintenant = GetTime(); + + if (not Ovale.bug) then + Ovale.traced = false + end + + local minAttente = Ovale:CalculerMeilleureAction(Ovale.masterNode) + local meilleureAction = Ovale.retourAction + + if (Ovale.trace) then + Ovale.trace=false + Ovale.traced = true + end + + if (Ovale.bug and not Ovale.traced) then + Ovale.trace = true + end + + if (minAttente~=nil and meilleureAction) then + + -- On attend que le sort courant soit fini + local spell, rank, displayName, icon, startTime, endTime, isTradeSkill = UnitCastingInfo("player") + if (spell) then + local attenteFinCast = endTime/1000 - Ovale.maintenant + if (attenteFinCast > minAttente) then + minAttente = attenteFinCast + end + end + + local spell, rank, displayName, icon, startTime, endTime, isTradeSkill = UnitChannelInfo("player") + if (spell) then + local attenteFinCast = endTime/1000 - Ovale.maintenant + if (attenteFinCast > minAttente) then + minAttente = attenteFinCast + end + end + + if (meilleureAction~=self.actionCourante or self.ancienneAttente==nil or + (minAttente~=0 and minAttente>self.ancienneAttente+0.01)) then + self.actionCourante = meilleureAction + self.debutAction = Ovale.maintenant + end + + self.ancienneAttente = minAttente + + -- L'icône avec le cooldown + self.icone:Show() + self.icone:SetTexture(GetActionTexture(meilleureAction)); + + if (IsUsableAction(meilleureAction)) then + self.icone:SetAlpha(1.0) + else + self.icone:SetAlpha(0.25) + end + + if (minAttente~=0) then + self.cd:SetCooldown(self.debutAction, minAttente+(Ovale.maintenant-self.debutAction)); + end + + -- Le raccourcis clavier + self.shortcut:Show() + self.shortcut:SetText(Ovale.shortCut[meilleureAction]) + + -- L'indicateur de portée + self.aPortee:Show() + if (IsActionInRange(meilleureAction,"target")==1) then + self.aPortee:SetTexture(1,1,1) + self.aPortee:Show() + elseif (IsActionInRange(meilleureAction,"target")==0) then + self.aPortee:SetTexture(1,0,0) + self.aPortee:Show() + else + self.aPortee:Hide() + end + else + self.icone:Hide() + self.aPortee:Hide() + self.shortcut:Hide() + end +end + + +function OvaleIcone_OnLoad(self) + self.icone = self:CreateTexture(); + self.icone:SetDrawLayer("ARTWORK"); + self.icone:SetAllPoints(self); + self.icone:Show(); + + self.shortcut = self:CreateFontString(nil, "OVERLAY"); + self.shortcut:SetFontObject("GameFontHighlightLarge"); + self.shortcut:SetPoint("BOTTOMLEFT",0,0); + self.shortcut:SetText("A"); + self.shortcut:SetTextColor(1,1,1); + self.shortcut:Show(); + + self.aPortee = self:CreateTexture(); + self.aPortee:SetDrawLayer("OVERLAY") + self.aPortee:SetPoint("TOPRIGHT",self,"TOPRIGHT",-4,-4); + self.aPortee:SetHeight(self:GetHeight()/6); + self.aPortee:SetWidth(self:GetWidth()/6); + self.aPortee:SetTexture(0,0,1); + + self.cd = CreateFrame("Cooldown",nil,self,nil); + self.cd:SetAllPoints(self); +end diff --git a/OvaleIcone.xml b/OvaleIcone.xml new file mode 100644 index 0000000..f49f422 --- /dev/null +++ b/OvaleIcone.xml @@ -0,0 +1,12 @@ +<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/ ..\..\FrameXML\UI.xsd"> + + <Frame name="OvaleIcone" virtual="true" hidden="false"> + <Size> + <AbsDimension x="64" y="64"/> + </Size> + <Scripts> + <OnUpdate>OvaleIcone_OnUpdate(self);</OnUpdate> + <OnLoad>OvaleIcone_OnLoad(self);</OnLoad> + </Scripts> + </Frame> +</Ui> diff --git a/OvaleSwing.lua b/OvaleSwing.lua new file mode 100644 index 0000000..1937d1f --- /dev/null +++ b/OvaleSwing.lua @@ -0,0 +1,148 @@ +--[[ + Copyright (C) 2006-2007 Nymbia + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + Modifed for Ovale +]] + +local autoshotname = GetSpellInfo(75) +local resetspells = { + [GetSpellInfo(845)] = true, -- Cleave + [GetSpellInfo(78)] = true, -- Heroic Strike + [GetSpellInfo(6807)] = true, -- Maul + [GetSpellInfo(2973)] = true, -- Raptor Strike + [GetSpellInfo(1464)] = true, -- Slam +} +local resetautoshotspells = { + [GetSpellInfo(19434)] = true, -- Aimed Shot +} +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") + +OvaleSwing.swingmode=nil -- nil is none, 0 is meleeing, 1 is autoshooting +OvaleSwing.starttime=0 +OvaleSwing.duration=0 + +local BOOKTYPE_SPELL = BOOKTYPE_SPELL + +function OvaleSwing:OnEnable() + -- fired when autoattack is enabled/disabled. + self:RegisterEvent("PLAYER_ENTER_COMBAT") + self:RegisterEvent("PLAYER_LEAVE_COMBAT") + -- fired when autoshot (or autowand) is enabled/disabled + self:RegisterEvent("START_AUTOREPEAT_SPELL") + self:RegisterEvent("STOP_AUTOREPEAT_SPELL") + + self:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED") + + self:RegisterEvent("UNIT_SPELLCAST_SUCCEEDED") + + self:RegisterEvent("UNIT_ATTACK") +end + +function OvaleSwing:OnDisable() +end + +function OvaleSwing:PLAYER_ENTER_COMBAT() + local _,_,offhandlow, offhandhigh = UnitDamage('player') + if math_abs(offhandlow - offhandhigh) <= 0.1 or playerclass == "DRUID" then + self.swingmode = 0 -- shouldn't be dual-wielding + end +end + +function OvaleSwing:PLAYER_LEAVE_COMBAT() + if not self.swingmode or self.swingmode == 0 then + self.swingmode = nil + end +end + +function OvaleSwing:START_AUTOREPEAT_SPELL() + self.swingmode = 1 +end + +function OvaleSwing:STOP_AUTOREPEAT_SPELL() + if not self.swingmode or self.swingmode == 1 then + self.swingmode = nil + end +end + +-- blizzard screws that global up, double usage in CombatLog.lua and GlobalStrings.lua, so we create it ourselves +local COMBATLOG_FILTER_ME = bit.bor( + COMBATLOG_OBJECT_AFFILIATION_MINE or 0x00000001, + COMBATLOG_OBJECT_REACTION_FRIENDLY or 0x00000010, + COMBATLOG_OBJECT_CONTROL_PLAYER or 0x00000100, + COMBATLOG_OBJECT_TYPE_PLAYER or 0x00000400 + ) + +do + local swordspecproc = false + function OvaleSwing:COMBAT_LOG_EVENT_UNFILTERED(timestamp, event, srcGUID, srcName, srcFlags, dstName, dstGUID, dstFlags, ...) + if (event == "SPELL_EXTRA_ATTACKS") and (select(2, ...) == "Sword Specialization") + and (bit.band(srcFlags, COMBATLOG_FILTER_ME) == COMBATLOG_FILTER_ME) then + swordspecproc = true + elseif (event == "SWING_DAMAGE" or event == "SWING_MISSED") + and (bit.band(srcFlags, COMBATLOG_FILTER_ME) == COMBATLOG_FILTER_ME) + and self.swingmode == 0 then + if (swordspecproc) then + swordspecproc = false + else + self:MeleeSwing() + end + end + end +end + +function OvaleSwing:UNIT_SPELLCAST_SUCCEEDED(unit, spell) + if self.swingmode == 0 then + if resetspells[spell] then + self:MeleeSwing() + end + elseif self.swingmode == 1 then + if spell == autoshotname then + self:Shoot() + end + end + if resetautoshotspells[spell] then + self.swingmode = 1 + self:Shoot() + end +end + +function OvaleSwing:UNIT_ATTACK(unit) + if unit == 'player' then + if not self.swingmode then + return + elseif self.swingmode == 0 then + self.duration = UnitAttackSpeed('player') + else + self.duration = UnitRangedDamage('player') + end + end +end + +function OvaleSwing:MeleeSwing() + self.duration = UnitAttackSpeed('player') + self.starttime = GetTime() +end + +function OvaleSwing:Shoot() + self.duration = UnitRangedDamage('player') + self.starttime = GetTime() +end diff --git a/defaut/Chaman.lua b/defaut/Chaman.lua new file mode 100644 index 0000000..e69de29 diff --git a/defaut/Chasseur.lua b/defaut/Chasseur.lua new file mode 100644 index 0000000..e69de29 diff --git a/defaut/Demoniste.lua b/defaut/Demoniste.lua new file mode 100644 index 0000000..957d537 --- /dev/null +++ b/defaut/Demoniste.lua @@ -0,0 +1,46 @@ +Ovale.defaut["WARLOCK"]= +[[AddListItem(curse recklessness "Malédiction de témérité") +AddListItem(curse elements "Malédiction des éléments") +AddListItem(curse agony "Malédiction d'agonie") +AddListItem(curse doom "Malédiction funeste") +AddListItem(curse tongues "Malédiction des langages") +AddListItem(curse weakness "Malédiction de faiblesse") + +Define(CURSERECKLESSNESS 704) +Define(CURSEELEMENTS 1490) +Define(CURSEAGONY 980) +Define(CURSEDOOM 603) +Define(CURSETONGUES 1714) +Define(CURSEWEAKNESS 702) +Define(SHIPHONLIFE 18265) +Define(UNSTABLEAFFLICTION 30108) +Define(CORRUPTION 172) +Define(TALENTUNSTABLEAFFLICTION 1670) +Define(TALENTSHADOWBOLT 944) +Define(IMMOLATE 348) +Define(TALENTIMMOLATE 961) +Define(TALENTEMBERSTORM 966) +Define(SOULFIRE 6353) +Define(SHADOWBOLT 686) +Define(HAUNT 48181) +Define(TALENTBACKDRAFT 1888) +Define(CONFLAGRATE 17962) + + +if List(curse recklessness) and TargetDebuffExpires(CURSERECKLESSNESS 2) Spell(CURSERECKLESSNESS) +if List(curse elements) and TargetDebuffExpires(CURSEELEMENTS 2) Spell(CURSEELEMENTS) +if List(curse doom) and TargetDebuffExpires(CURSEDOOM 0 mine=1) Spell(CURSEDOOM) +if List(curse tongues) and TargetDebuffExpires(CURSETONGUES 2) Spell(CURSETONGUES) +if List(curse weakness) and TargetDebuffExpires(CURSEWEAKNESS 2) Spell(CURSEWEAKNESS) +if TargetDebuffExpires(HAUNT 1.5 mine=1) Spell(HAUNT doNotRepeat=1) +if List(curse agony) and TargetDebuffExpires(CURSEAGONY 0 mine=1) Spell(CURSEAGONY) +if TargetDebuffExpires(SHIPHONLIFE 0 mine=1) Spell(SHIPHONLIFE) +if TargetDebuffExpires(UNSTABLEAFFLICTION 1.5 mine=1) Spell(UNSTABLEAFFLICTION doNotRepeat=1) +if TargetDebuffExpires(CORRUPTION 0 mine=1) Spell(CORRUPTION) +if TalentPoints(TALENTBACKDRAFT more 0) and TargetDebuffExpires(IMMOLATE 3 mine=1) + and TargetDebuffPresent(IMMOLATE mine=1) Spell(CONFLAGRATE doNotRepeat=1) +if TargetDebuffExpires(IMMOLATE 1.5 mine=1) Spell(IMMOLATE doNotRepeat=1) + +if TalentPoints(TALENTEMBERSTORM more 0) Spell(SOULFIRE) +Spell(SHADOWBOLT) +]] diff --git a/defaut/Druide.lua b/defaut/Druide.lua new file mode 100644 index 0000000..a780839 --- /dev/null +++ b/defaut/Druide.lua @@ -0,0 +1,69 @@ +Ovale.defaut["DRUID"] = +[[AddCheckBox(multi "Multicible") +AddCheckBox(blood "Saignement") +AddCheckBox(demo "Rugissement démoralisant") +AddCheckBox(lucioles "Lucioles") + +Define(FAERIEFIRE 770) +Define(FAERIEFERAL 16857) +Define(MANGLEBEAR 33878) +Define(DEMOROAR 99) +Define(SWIPE 779) +Define(LACERATE 33745) +Define(MAUL 6807) +Define(RIP 1079) +Define(MANGLECAT 33876) +Define(SHRED 5221) +Define(INSECTSWARM 27013) +Define(MOONFIRE 8921) +Define(STARFIRE 2912) +Define(WRATH 5176) +Define(ECLIPSESTARFIRE 48518) +Define(ECLIPSEWRATH 48517) +Define(TIGERSFURY 5217) + +if Stance(1) +{ + if CheckBoxOn(lucioles) and TargetDebuffExpires(FAERIEFERAL 2) + Spell(FAERIEFERAL) + + Spell(MANGLEBEAR) + + if CheckBoxOn(demo) and TargetDebuffExpires(DEMOROAR 2) + Spell(DEMOROAR) + + if CheckBoxOn(multi) Spell(SWIPE) + + if CheckBoxOn(blood) and Mana(more 10) Spell(LACERATE) + if Mana(more 50) Spell(MAUL doNotRepeat=1) +} + +if Stance(3) +{ + if CheckBoxOn(lucioles) and TargetDebuffExpires(FAERIEFERAL 2) + Spell(FAERIEFERAL) + + Spell(TIGERSFURY) + + if ComboPoints(more 4) and Mana(more 70) + Spell(RIP) + + if ComboPoints(less 5) + { + if TargetDebuffExpires(MANGLECAT 0) Spell(MANGLECAT) + Spell(SHRED) + } +} + +unless Stance(1) or Stance(3) +{ + if CheckBoxOn(lucioles) and TargetDebuffExpires(FAERIEFIRE 2) + Spell(FAERIEFIRE) + + if TargetDebuffExpires(INSECTSWARM 0) Spell(INSECTSWARM) + if TargetDebuffExpires(MOONFIRE 0) Spell(MOONFIRE) + unless BuffPresent(ECLIPSEWRATH) + Spell(STARFIRE) + Spell(WRATH) +} +]] diff --git a/defaut/Guerrier.lua b/defaut/Guerrier.lua new file mode 100644 index 0000000..f4688ec --- /dev/null +++ b/defaut/Guerrier.lua @@ -0,0 +1,91 @@ +Ovale.defaut["WARRIOR"] = +[[AddCheckBox(multi "Multicible") +AddCheckBox(demo "Cri démoralisant") +AddCheckBox(tourbillon "Tourbillon") +AddListItem(cri aucun "Aucun cri") +AddListItem(cri guerre "Cri de guerre") +AddListItem(cri commandement "Cri de commandement") + +Define(THUNDERCLAP 6343) +Define(SHOCKWAVE 46968) +Define(DEMOSHOUT 1160) +Define(COMMANDSHOUT 469) +Define(BATTLESHOUT 2048) +Define(REVENGE 6572) +Define(SHIELDSLAM 23922) +Define(DEVASTATE 20243) +Define(VICTORY 34428) +Define(EXECUTE 5308) +Define(BLOODTHIRST 23881) +Define(WHIRLWIND 1680) +Define(SLAMBUFF 46916) +Define(SLAM 1464) +Define(MORTALSTRIKE 12294) +Define(SLAMTALENT 2233) +Define(CLEAVE 845) +Define(HEROICSTRIKE 78) +Define(SUNDER 7386) + +if List(cri commandement) and BuffExpires(COMMANDSHOUT 3) + Spell(COMMANDSHOUT) + +if List(cri guerre) and BuffExpires(BATTLESHOUT 3) + Spell(BATTLESHOUT) + +if TargetClassification(worldboss) and CheckBoxOn(demo) + and TargetDebuffExpires(DEMOSHOUT 2) + Spell(DEMOSHOUT) + +if Stance(2) #Defense +{ + if TargetClassification(worldboss) and TargetDebuffExpires(THUNDERCLAP 2) + Spell(THUNDERCLAP) + + if CheckBoxOn(multi) + { + Spell(THUNDERCLAP) + Spell(SHOCKWAVE) + } + + Spell(REVENGE usable=1) + Spell(SHIELDSLAM) + + if Mana(more 10) Spell(DEVASTATE priority=2) +} + +if Stance(3) #berserker +{ + Spell(VICTORY usable=1) + + if TargetLifePercent(less 20) Spell(EXECUTE) + + Spell(BLOODTHIRST) + if CheckBoxOn(tourbillon) Spell(WHIRLWIND) + if BuffPresent(SLAMBUFF) Spell(SLAM) + Spell(MORTALSTRIKE) + Spell(DEVASTATE) + + if Talent(SLAMTALENT more 1) and AfterWhiteHit(0.2) + Spell(SLAM) + + #todo execute par talent +} + +if Stance(1) #combat +{ + Spell(VICTORY usable=1) + if TargetLifePercent(less 20) Spell(EXECUTE) + Spell(MORTALSTRIKE) + Spell(DEVASTATE) + + #todo +} + +if Mana(more 50) +{ + if CheckBoxOn(multi) Spell(CLEAVE doNotRepeat=1) + if CheckBoxOff(multi) Spell(HEROICSTRIKE doNotRepeat=1) +} + +if TargetDebuffExpires(SUNDER 5 stacks=5) Spell(SUNDER) +]] diff --git a/defaut/Mage.lua b/defaut/Mage.lua new file mode 100644 index 0000000..e69de29 diff --git a/defaut/Paladin.lua b/defaut/Paladin.lua new file mode 100644 index 0000000..51d0875 --- /dev/null +++ b/defaut/Paladin.lua @@ -0,0 +1,31 @@ +Ovale.defaut["PALADIN"] = +[[AddListItem(sceau piete "Sceau de piété") +AddListItem(sceau autorite "Sceau d'autorité") +AddListItem(sceau martyr "Sceau de martyr/sang") +AddListItem(sceau vengeance "Sceau de vengeance/corruption") +AddListItem(jugement lumiere "Jugement de lumière") +AddListItem(jugement sagesse "Jugement de sagesse") +AddCheckBox(consecration "Consécration") +AddCheckBox(tempete "Tempête divine") + +if List(sceau piete) and BuffExpires(21084 3) Spell(21084) +if List(sceau autorite) and BuffExpires(20375 3) Spell(20375) +if List(sceau martyr) +{ + if BuffExpires(53720 3) Spell(53720) + if BuffExpires(31892 3) Spell(31892) +} +if List(sceau vengeance) +{ + if BuffExpires(31801 3) Spell(31801) + if BuffExpires(53736 3) Spell(53736) +} +if List(jugement lumiere) Spell(20271) +if List(jugement sagesse) Spell(53408) +if TargetLifePercent(less 20) Spell(24275) +Spell(35395) #Inquisition +if CheckBoxOn(tempete) Spell(53385) +if CheckBoxOn(consecration) Spell(26573) +Spell(20473) #Horion sacré +if BuffPresent(59578) Spell(19750 priority=2)]] + \ No newline at end of file diff --git a/defaut/Pretre.lua b/defaut/Pretre.lua new file mode 100644 index 0000000..e5596bc --- /dev/null +++ b/defaut/Pretre.lua @@ -0,0 +1,32 @@ +Ovale.defaut["PRIEST"] = +[[AddCheckBox(etreinte "Étreinte vampirique") +AddCheckBox(mort "Mot de l'ombre : Mort") + +# Mot de pouvoir : Robustesse +if BuffExpires(1243 5) and BuffExpires(21562 5) Spell(1243) +# Forme d'ombre +if BuffExpires(15473 0) Spell(15473) + +if CheckBoxOn(etreinte) and TargetDebuffExpires(15286 0 mine=1) + Spell(15286 doNotRepeat=1) + +#toucher vampirique +if TargetDebuffExpires(34914 1 mine=1) + Spell(34914 doNotRepeat=1) + +#mot de l'ombre : douleur +if TargetDebuffExpires(589 0 mine=1) + Spell(589) + +if TalentPoints(1181 less 1) # Fureur divine + Spell(8092) # Attaque mentale + +if CheckBoxOn(mort) and LifePercent(more 95) Spell(32379) + +Spell(15407) #Fouet mental + +if TargetDebuffExpires(14914 0 mine=1) + Spell(14914) #Flammes sacrées + +Spell(585) # châtiment +]] diff --git a/defaut/Voleur.lua b/defaut/Voleur.lua new file mode 100644 index 0000000..e69de29 diff --git a/embeds.xml b/embeds.xml new file mode 100644 index 0000000..e343580 --- /dev/null +++ b/embeds.xml @@ -0,0 +1,14 @@ +<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/ +..\FrameXML\UI.xsd"> + + <Script file="Libs\LibStub\LibStub.lua"/> + <Include file="Libs\AceLocale-3.0\AceLocale-3.0.xml" /> + <Include file="Libs\AceAddon-3.0\AceAddon-3.0.xml" /> + <Include file="Libs\AceDB-3.0\AceDB-3.0.xml" /> + <Include file="Libs\AceDBOptions-3.0\AceDBOptions-3.0.xml" /> + <Include file="Libs\AceConsole-3.0\AceConsole-3.0.xml" /> + <Include file="Libs\AceEvent-3.0\AceEvent-3.0.xml" /> + <Include file="Libs\AceGUI-3.0\AceGUI-3.0.xml" /> + <Include file="Libs\AceConfig-3.0\AceConfig-3.0.xml" /> + +</Ui>