From ded52a83830c23908aac5782a32a0ea8527c9b71 Mon Sep 17 00:00:00 2001 From: Tercio Jose Date: Tue, 11 Jul 2023 19:10:52 -0300 Subject: [PATCH] ToC Updates --- Details.toc | 2 +- plugins/Details_Compare2/Details_Compare2.toc | 2 +- .../Details_DataStorage.toc | 2 +- .../Details_EncounterDetails/Definitions.lua | 585 ++ .../Details_EncounterDetails-Wrath.toc | 8 +- .../Details_EncounterDetails.lua | 2443 +---- .../Details_EncounterDetails.toc | 10 +- .../Details_EncounterDetails_Wrath.toc | 8 +- .../ED_Definitions.lua | 8 + .../Libs/DF/.gitignore | 11 + .../Libs/DF/DFPixelUtil.lua | 66 + .../Libs/DF/LibDFramework-1.0.toc | 5 + .../Libs/DF/addon.lua | 132 + .../Libs/DF/auras.lua | 1282 +++ .../Libs/DF/button.lua | 1358 +++ .../Libs/DF/button.xml | 3 + .../Libs/DF/charts.examples.lua | 109 + .../Libs/DF/charts.lua | 884 ++ .../Libs/DF/colors.lua | 184 + .../Libs/DF/containers.lua | 565 + .../Libs/DF/cooltip.lua | 3651 +++++++ .../Libs/DF/cooltip.xml | 5 + .../Libs/DF/dropdown.lua | 1359 +++ .../Libs/DF/dropdown.xml | 4 + .../Libs/DF/embeds.xml | 18 + .../Libs/DF/externals.lua | 116 + .../Details_EncounterDetails/Libs/DF/fw.lua | 5378 ++++++++++ .../Libs/DF/header.lua | 686 ++ .../Details_EncounterDetails/Libs/DF/help.lua | 123 + .../Details_EncounterDetails/Libs/DF/icon.lua | 487 + .../Libs/DF/iteminfo.lua | 27 + .../Libs/DF/label.lua | 341 + .../Libs/DF/languages.lua | 1661 +++ .../Details_EncounterDetails/Libs/DF/load.xml | 40 + .../Details_EncounterDetails/Libs/DF/math.lua | 176 + .../Libs/DF/mixins.lua | 965 ++ .../Libs/DF/normal_bar.lua | 861 ++ .../Libs/DF/normal_bar.xml | 3 + .../Libs/DF/panel.lua | 9304 +++++++++++++++++ .../Libs/DF/panel.xml | 3 + .../Libs/DF/picture.lua | 346 + .../Libs/DF/pictureedit.lua | 607 ++ .../Libs/DF/savedvars.lua | 219 + .../Libs/DF/schedules.lua | 73 + .../Libs/DF/scripting.lua | 132 + .../Libs/DF/scrollbar.lua | 233 + .../Libs/DF/slider.lua | 1432 +++ .../Libs/DF/spells.lua | 1519 +++ .../Libs/DF/split_bar.lua | 810 ++ .../Libs/DF/split_bar.xml | 3 + .../Libs/DF/tabcontainer.lua | 422 + .../Libs/DF/textentry.lua | 1127 ++ .../Libs/DF/textentry.xml | 3 + .../Libs/DF/timebar.lua | 462 + .../Libs/DF/tutorial_alert.xml | 2 + .../Details_EncounterDetails/Libs/DF/util.lua | 24 + .../LibLuaServer/LuaServerDefinitions.lua | 401 + plugins/Details_EncounterDetails/embeds.xml | 3 - plugins/Details_EncounterDetails/frames.lua | 3424 +----- .../Details_EncounterDetails/frames_auras.lua | 419 + .../Details_EncounterDetails/frames_chart.lua | 698 ++ .../Details_EncounterDetails/frames_emote.lua | 361 + .../frames_phases.lua | 471 + .../frames_summary.lua | 1267 +++ .../Details_RaidCheck/Details_RaidCheck.toc | 2 +- plugins/Details_Streamer/Details_Streamer.toc | 2 +- .../Details_TinyThreat/Details_TinyThreat.toc | 3 +- plugins/Details_Vanguard/Details_Vanguard.toc | 2 +- 68 files changed, 42484 insertions(+), 4858 deletions(-) create mode 100644 plugins/Details_EncounterDetails/Definitions.lua create mode 100644 plugins/Details_EncounterDetails/ED_Definitions.lua create mode 100644 plugins/Details_EncounterDetails/Libs/DF/.gitignore create mode 100644 plugins/Details_EncounterDetails/Libs/DF/DFPixelUtil.lua create mode 100644 plugins/Details_EncounterDetails/Libs/DF/LibDFramework-1.0.toc create mode 100644 plugins/Details_EncounterDetails/Libs/DF/addon.lua create mode 100644 plugins/Details_EncounterDetails/Libs/DF/auras.lua create mode 100644 plugins/Details_EncounterDetails/Libs/DF/button.lua create mode 100644 plugins/Details_EncounterDetails/Libs/DF/button.xml create mode 100644 plugins/Details_EncounterDetails/Libs/DF/charts.examples.lua create mode 100644 plugins/Details_EncounterDetails/Libs/DF/charts.lua create mode 100644 plugins/Details_EncounterDetails/Libs/DF/colors.lua create mode 100644 plugins/Details_EncounterDetails/Libs/DF/containers.lua create mode 100644 plugins/Details_EncounterDetails/Libs/DF/cooltip.lua create mode 100644 plugins/Details_EncounterDetails/Libs/DF/cooltip.xml create mode 100644 plugins/Details_EncounterDetails/Libs/DF/dropdown.lua create mode 100644 plugins/Details_EncounterDetails/Libs/DF/dropdown.xml create mode 100644 plugins/Details_EncounterDetails/Libs/DF/embeds.xml create mode 100644 plugins/Details_EncounterDetails/Libs/DF/externals.lua create mode 100644 plugins/Details_EncounterDetails/Libs/DF/fw.lua create mode 100644 plugins/Details_EncounterDetails/Libs/DF/header.lua create mode 100644 plugins/Details_EncounterDetails/Libs/DF/help.lua create mode 100644 plugins/Details_EncounterDetails/Libs/DF/icon.lua create mode 100644 plugins/Details_EncounterDetails/Libs/DF/iteminfo.lua create mode 100644 plugins/Details_EncounterDetails/Libs/DF/label.lua create mode 100644 plugins/Details_EncounterDetails/Libs/DF/languages.lua create mode 100644 plugins/Details_EncounterDetails/Libs/DF/load.xml create mode 100644 plugins/Details_EncounterDetails/Libs/DF/math.lua create mode 100644 plugins/Details_EncounterDetails/Libs/DF/mixins.lua create mode 100644 plugins/Details_EncounterDetails/Libs/DF/normal_bar.lua create mode 100644 plugins/Details_EncounterDetails/Libs/DF/normal_bar.xml create mode 100644 plugins/Details_EncounterDetails/Libs/DF/panel.lua create mode 100644 plugins/Details_EncounterDetails/Libs/DF/panel.xml create mode 100644 plugins/Details_EncounterDetails/Libs/DF/picture.lua create mode 100644 plugins/Details_EncounterDetails/Libs/DF/pictureedit.lua create mode 100644 plugins/Details_EncounterDetails/Libs/DF/savedvars.lua create mode 100644 plugins/Details_EncounterDetails/Libs/DF/schedules.lua create mode 100644 plugins/Details_EncounterDetails/Libs/DF/scripting.lua create mode 100644 plugins/Details_EncounterDetails/Libs/DF/scrollbar.lua create mode 100644 plugins/Details_EncounterDetails/Libs/DF/slider.lua create mode 100644 plugins/Details_EncounterDetails/Libs/DF/spells.lua create mode 100644 plugins/Details_EncounterDetails/Libs/DF/split_bar.lua create mode 100644 plugins/Details_EncounterDetails/Libs/DF/split_bar.xml create mode 100644 plugins/Details_EncounterDetails/Libs/DF/tabcontainer.lua create mode 100644 plugins/Details_EncounterDetails/Libs/DF/textentry.lua create mode 100644 plugins/Details_EncounterDetails/Libs/DF/textentry.xml create mode 100644 plugins/Details_EncounterDetails/Libs/DF/timebar.lua create mode 100644 plugins/Details_EncounterDetails/Libs/DF/tutorial_alert.xml create mode 100644 plugins/Details_EncounterDetails/Libs/DF/util.lua create mode 100644 plugins/Details_EncounterDetails/Libs/LibLuaServer/LuaServerDefinitions.lua create mode 100644 plugins/Details_EncounterDetails/frames_auras.lua create mode 100644 plugins/Details_EncounterDetails/frames_chart.lua create mode 100644 plugins/Details_EncounterDetails/frames_emote.lua create mode 100644 plugins/Details_EncounterDetails/frames_phases.lua create mode 100644 plugins/Details_EncounterDetails/frames_summary.lua diff --git a/Details.toc b/Details.toc index a5584ad8..207acd23 100644 --- a/Details.toc +++ b/Details.toc @@ -1,4 +1,4 @@ -## Interface: 100100 +## Interface: 100105 ## Title: Details! Damage Meter ## Notes: Essential tool to impress that chick in your raid. ## SavedVariables: _detalhes_global, __details_backup diff --git a/plugins/Details_Compare2/Details_Compare2.toc b/plugins/Details_Compare2/Details_Compare2.toc index a2957dad..889f631c 100644 --- a/plugins/Details_Compare2/Details_Compare2.toc +++ b/plugins/Details_Compare2/Details_Compare2.toc @@ -1,4 +1,4 @@ -## Interface: 100100 +## Interface: 100105 ## Title: Details!: Compare 2.0 ## Notes: Replace the Compare tab in the player breakdown window. ## RequiredDeps: Details diff --git a/plugins/Details_DataStorage/Details_DataStorage.toc b/plugins/Details_DataStorage/Details_DataStorage.toc index 9b7a0df4..1e565ca3 100644 --- a/plugins/Details_DataStorage/Details_DataStorage.toc +++ b/plugins/Details_DataStorage/Details_DataStorage.toc @@ -1,4 +1,4 @@ -## Interface: 100100 +## Interface: 100105 ## Title: Details!: Storage ## Notes: Stores information for Details! Damage Meter ## DefaultState: Enabled diff --git a/plugins/Details_EncounterDetails/Definitions.lua b/plugins/Details_EncounterDetails/Definitions.lua new file mode 100644 index 00000000..2454053b --- /dev/null +++ b/plugins/Details_EncounterDetails/Definitions.lua @@ -0,0 +1,585 @@ + + +---@alias plugintype +---| "SOLO" +---| "RAID" +---| "TOOLBAR" +---| "STATUSBAR" + +---@alias detailsevent +---| "DETAILS_INSTANCE_OPEN" +---| "DETAILS_INSTANCE_CLOSE" +---| "DETAILS_INSTANCE_SIZECHANGED" +---| "DETAILS_INSTANCE_STARTRESIZE" +---| "DETAILS_INSTANCE_ENDRESIZE" +---| "DETAILS_INSTANCE_STARTSTRETCH" +---| "DETAILS_INSTANCE_ENDSTRETCH" +---| "DETAILS_INSTANCE_CHANGESEGMENT" +---| "DETAILS_INSTANCE_CHANGEATTRIBUTE" +---| "DETAILS_INSTANCE_CHANGEMODE" +---| "DETAILS_INSTANCE_NEWROW" +---| "DETAILS_OPTIONS_MODIFIED" +---| "DETAILS_DATA_RESET" +---| "DETAILS_DATA_SEGMENTREMOVED" +---| "COMBAT_ENCOUNTER_START" +---| "COMBAT_ENCOUNTER_END" +---| "COMBAT_PLAYER_ENTER" +---| "COMBAT_PLAYER_LEAVE" +---| "COMBAT_PLAYER_TIMESTARTED" +---| "COMBAT_BOSS_WIPE" +---| "COMBAT_BOSS_DEFEATED" +---| "COMBAT_BOSS_FOUND" +---| "COMBAT_INVALID" +---| "COMBAT_PREPOTION_UPDATED" +---| "COMBAT_CHARTTABLES_CREATING" +---| "COMBAT_CHARTTABLES_CREATED" +---| "COMBAT_ENCOUNTER_PHASE_CHANGED" +---| "COMBAT_ARENA_START" +---| "COMBAT_ARENA_END" +---| "COMBAT_MYTHICDUNGEON_START" +---| "COMBAT_MYTHICDUNGEON_END" +---| "GROUP_ONENTER" +---| "GROUP_ONLEAVE" +---| "ZONE_TYPE_CHANGED" +---| "REALM_CHANNEL_ENTER" +---| "REALM_CHANNEL_LEAVE" +---| "COMM_EVENT_RECEIVED" +---| "COMM_EVENT_SENT" +---| "UNIT_SPEC" +---| "UNIT_TALENTS" +---| "PLAYER_TARGET" +---| "DETAILS_PROFILE_APPLYED" + +---@alias containertype number this container type is the number used to identify the actorcontainer type when using combat:GetContainer(containertype), can be 1, 2, 3, or 4. + +---@alias actorclass string this is the class of the actor, can be "WARRIOR", "PALADIN", "HUNTER", "ROGUE", "PRIEST", "DEATHKNIGHT", "SHAMAN", "MAGE", "WARLOCK", "MONK", "DRUID", "DEMONHUNTER" +---@alias actorspec number this is the specID of the actor +---@alias uniquecombatid number a unique ID to point to a single combat, each character has its ID counter, use with Details:DoesCombatWithUIDExists(); Details:GetCombatByUID(); retrive with combat:GetCombatUID() + +---@class petinfo : table +---@field key1 ownername +---@field key2 guid +---@field key3 unixtime +---@field key4 boolean +---@field key5 petname +---@field key6 guid + +---@class details +---@field SpellTableMixin spelltablemixin +---@field GetInstance fun(self: details) : instance +---@field GetWindow fun(self: details) : instance this is an alias of GetInstance +---@field GetCombat fun(self: details) : combat +---@field GetSpellSchoolFormatedName fun(self: details, spellschool: spellschool) : string +---@field CommaValue fun(self: details, number: number) : string +---@field CreateEventListener fun(self: details) : table + +---@class detailseventlistener : table +---@field RegisterEvent fun(self: detailseventlistener, event: detailsevent, callback: function) +---@field UnregisterEvent fun(self: detailseventlistener, event: detailsevent) + +---@class deathtable : table +---@field key1 any[] what happened to the player before death +---@field key2 number unix time +---@field key3 string player name +---@field key4 string player class +---@field key5 number max health +---@field key6 string time of death as string +---@field dead boolean just a boolean to indicate this is a death table +---@field last_cooldown {key1: unixtime, key2: spellid} +---@field dead_at combattime +---@field spec specializationid + +---@class customspellinfo : {name: string, isPassive: boolean, itemId: number, icon: string|number} +---@class customiteminfo: {itemId: number, isPassive: boolean} +---@class savedspelldata : {key1: number, key2: string, key3: number} +---@class alternatepowertable : {last: number, total: number} + +---@class combat : table +---@field bIsClosed boolean if true the combat is closed (passed by the EndCombat() function) +---@field __destroyedBy string +---@field amountCasts {[string]: table} +---@field instance_type instancetype "raid" or "party" or "pvp" or "arena" or "none" or "scenario" +---@field end_time number +---@field start_time number +---@field combat_counter number +---@field is_trash boolean while in raid this is set to true if the combat isn't raid boss, in dungeon this is set to true if the combat isn't a boss or if the dungeon isn't a mythic+ +---@field raid_roster table [unitName] = unitGUID +---@field overall_added boolean is true when the combat got added into the overall combat +---@field is_mythic_dungeon_trash boolean +---@field is_mythic_dungeon_run_id number +---@field is_mythic_dungeon_segment boolean +---@field trinketProcs table> +---@field alternate_power table +---@field totals {key1: table, key2: table, key3: table, key3: table} +---@field totals_grupo {key1: table, key2: table, key3: table, key3: table} +---@field __destroyed boolean +---@field PhaseData table +---@field is_boss table +---@field is_world_trash_combat boolean when true this combat is a regular combat done in the world, not in a dungeon, raid, battleground, arena, ... +---@field player_last_events table record the latest events of each player, latter used to build the death log +---@field GetCombatUID fun(combat: combat) : uniquecombatid +---@field GetTimeData fun(combat: combat, dataName: string) : table +---@field GetPhases fun(combat: combat) : table +---@field GetCombatTime fun(combat) : number +---@field GetDeaths fun(combat) : table --get the table which contains the deaths of the combat +---@field GetStartTime fun(combat: combat) : number +---@field SetStartTime fun(combat: combat, time: number) +---@field GetEndTime fun(combat: combat) : number +---@field GetDifficulty fun(combat: combat) : number return the dungeon or raid difficulty for boss fights +---@field GetEncounterCleuID fun(combat: combat) : number return the encounterId for boss fights, this number is gotten from the ENCOUNTER_START event +---@field GetBossInfo fun(combat: combat) : table a table containing many informations about the boss fight +---@field SetEndTime fun(combat: combat, time: number) +---@field CopyDeathsFrom fun(combat1: combat, combat2: combat, bMythicPlus: boolean) copy the deaths from combat2 to combat1, use true on bMythicPlus if the combat is from a mythic plus run +---@field GetContainer fun(combat: combat, containerType: containertype) : actorcontainer get an actorcontainer, containerType can be 1 for damage, 2 heal, 3 resources, 4 utility +---@field GetSpellCastAmount fun(combat: combat, actorName: string, spellName: string) : number get the amount of times a spell was casted +---@field RemoveActorFromSpellCastTable fun(combat: combat, actorName: string) +---@field GetSpellCastTable fun(combat: combat, actorName: string|nil) : table +---@field GetSpellUptime fun(combat: combat, actorName: string, spellId: number, auraType: string|nil) : number get the uptime of a buff or debuff +---@field GetActor fun(combat: combat, containerType: number, playerName: string) : actor +---@field CreateAlternatePowerTable fun(combat: combat, actorName: string) : alternatepowertable +---@field GetCombatNumber fun(combat: combat) : number get a unique number representing the combatId, each combat has a unique number +---@field SetDate fun(combat: combat, startDate: string, endDate: string) set the start and end date of the combat, format: "H:M:S" +---@field GetDate fun(combat: combat) : string, string get the start and end date of the combat, format: "H:M:S" +---@field GetRoster fun(combat: combat) : table get the roster of the combat, the table contains the names of the players in the combat +---@field InstanceType fun(combat: combat) : string get the instance type of the combat, can be "raid" or "party" or "pvp" or "arena" or "none" +---@field IsTrash fun(combat: combat) : boolean is true if the combat is a trash combat + +---@class actorcontainer : table contains two tables _ActorTable and _NameIndexTable, the _ActorTable contains the actors, the _NameIndexTable contains the index of the actors in the _ActorTable, making quick to reorder them without causing overhead +---@field need_refresh boolean when true the container is dirty and needs to be refreshed +---@field _ActorTable table array of actors +---@field _NameIndexTable table [actorName] = actorIndex in the _ActorTable, actorcontainer:Remap() refreshes the _NameIndexTable +---@field GetActor fun(container: actorcontainer, actorName: string) get an actor by its name +---@field GetSpellSource fun(container: actorcontainer, spellId: number) get the first actor found which casted the spell +---@field GetAmount fun(container: actorcontainer, actorName: string, key: string) get the amount of actor[key] +---@field GetTotal fun(container: actorcontainer, key: string) get the total amount of actor[key] for all actors +---@field GetTotalOnRaid fun(container: actorcontainer, key: string, combat: combat) get the total amount of actor[key] only for the actors which are in the raid +---@field GetActorTable fun(container: actorcontainer) get the table which contains the actors +---@field ListActors fun(container: actorcontainer) usage: for index, actorObject in container:ListActors() do +---@field RemoveActor fun(container: actorcontainer, actor: actor) remove an actor from the container +---@field GetType fun(container: actorcontainer) : number get the container type, 1 for damage, 2 for heal, 3 for energy, 4 for utility +---@field Remap fun(container: actorcontainer) refreshes the _NameIndexTable part of the container +---@field Cleanup fun(container: actorcontainer) remove all destroyed actors from the container + +---@class spellcontainer : table +---@field _ActorTable table store [spellId] = spelltable +---@field GetSpell fun(container: spellcontainer, spellId: number) get a spell by its id, does not create if not found +---@field ListActors fun(container: spellcontainer) : any, any usage: for spellId, spelltable in container:ListActors() do +---@field ListSpells fun(container: spellcontainer) : any, any usage: for spellId, spelltable in container:ListActors() do +---@field HasTwoOrMoreSpells fun(container: spellcontainer) : boolean return true if the container has two or more spells +---@field GetOrCreateSpell fun(self: spellcontainer, spellId: number, bCanCreateSpellIfMissing: boolean|nil, cleuToken: string|nil) : spelltable + +---@class friendlyfiretable : table +---@field total number total amount of friendly fire caused by the actor +---@field spells table spellId = total + +---@class spelltable : table +---@field uptime number +---@field total number +---@field spellschool number +---@field counter number amount of hits +---@field c_amt number critical hits by a damage or heal spell +---@field c_min number min damage or healing done by critical hits of the spell +---@field c_max number min damage or healing done by critical hits of the spell +---@field c_total number total damage or heal made by critical hits of the spell +---@field n_amt number normal hits by a damage or heal spell +---@field n_min number min damage or healing done by normal hits of the spell +---@field n_max number min damage or healing done by normal hits of the spell +---@field n_total number total damage or heal made by normal hits of the spell +---@field targets table store the [target name] = total value +---@field targets_overheal table +---@field targets_absorbs table +---@field extra table store extra data +---@field id number --spellid +---@field is_shield boolean --true if the spell is a shield +---@field successful_casted number successful casted times (only for enemies) +---@field g_amt number glacing hits +---@field g_dmg number +---@field r_amt number --resisted +---@field r_dmg number +---@field b_amt number --blocked +---@field b_dmg number +---@field a_amt number --absorved +---@field a_dmg number +---@field e_total number +---@field e_amt number +---@field e_lvl table +---@field e_dmg table +---@field e_heal table +---@field isReflection boolean +---@field totalabsorb number healing absorbed +---@field absorbed number damage absorbed by shield | healing absorbed by buff or debuff +---@field overheal number +---@field totaldenied number + +---@class targettable : {[string]: number} + +---@class actor : table +---@field owner actor +---@field tipo number the container type +---@field ownerName string name of the owner of the pet, a pet without an owner is considered an orphan and be suitable for garbage collection +---@field pets table +---@field arena_enemy boolean if true the actor is an enemy in an arena match +---@field dps_started boolean if true the actor started to do damage or healing +---@field start_time unixtime when this actor started to be tracked +---@field end_time number when this actor stopped to be tracked, end_time - start_time is the activity time of the actor +---@field displayName string actor name shown in the regular window +---@field pvp boolean indicates if the actor is a part of a pvp match +---@field flag_original number original actor flag from what was received in the combat log +---@field debuff_uptime_spells table +---@field buff_uptime_spells table +---@field spells spellcontainer +---@field aID number|string actorID is a realm-playername or npcID +---@field spellicon number|string +---@field cooldowns_defensive_spells table +---@field nome string name of the actor +---@field isTank boolean if true the player had the spec TANK during the combat +---@field serial string +---@field spec number +---@field grupo boolean +---@field fight_component boolean +---@field boss_fight_component boolean +---@field pvp_component boolean +---@field boss boolean +---@field last_event unixtime +---@field total_without_pet number +---@field total number +---@field targets targettable +---@field GetSpell fun(actor: actor, spellId: number) : spelltable +---@field BuildSpellTargetFromBreakdownSpellData fun(actor: actor, bkSpellData: spelltableadv) : table +---@field BuildSpellTargetFromSpellTable fun(actor: actor, spellTable: spelltable) : table +---@field raid_targets table +---@field IsPlayer fun(actor: actor) : boolean return true if the actor is controlled by a player +---@field IsPetOrGuardian fun(actor: actor) : boolean return true if the actor is a pet or guardian +---@field IsGroupPlayer fun(actor: actor) : boolean return true if the actor is a player in the group (or was in the group during the combat) +---@field GetSpellContainer fun(actor: actor, containerType: "debuff"|"buff"|"spell"|"cooldowns"|"dispel") : spellcontainer +---@field Class fun(actor: actor) : string get the ingame class of the actor +---@field Spec fun(actor: actor) : string get the ingame spec of the actor +---@field Name fun(actor: actor) : string get the name of the actor +---@field Tempo fun(actor: actor) : number get the activity or effective time of the actor +---@field GetPets fun(actor: actor) : table get a table with all pet names that belong to the player +---@field GetSpellList fun(actor: actor) : table +---@field GetSpellContainerNames fun(container: actorcontainer) : string[] get the table which contains the names of the spell containers + +---@class actordamage : actor +---@field friendlyfire_total number +---@field friendlyfire table +---@field damage_taken number amount of damage the actor took during the segment +---@field damage_from table store the name of the actors which damaged the actor, format: [actorName] = true +---@field totalabsorbed number amount of damage dealt by the actor by got absorbed by the target, this is a "ABSORB" type of miss but still counts as damage done + +---@class actorheal : actor +---@field healing_taken number amount of healing the actor took during the segment +---@field totalover number amount of healing that was overhealed +---@field totalabsorb number amount of healing that was absorbed +---@field heal_enemy_amt number amount of healing done to enemies this included enemy to enemy heals +---@field totaldenied number amount of healing that was denied by the target - from cleu event SPELL_HEAL_ABSORBED +---@field totalover_without_pet number amount of healing that was overhealed without the pet healing +---@field healing_from table store the name of the actors which healed the actor, format: [actorName] = true +---@field heal_enemy table store the amount of healing done by each spell that landed into an enemy, format: [spellId] = healing done +---@field targets_overheal table [targetName] = overheal +---@field targets_absorbs table [targetName] = absorbs + +---@class actorresource : actor +---@field powertype number power type of the actor +---@field alternatepower number alternate power of the actor + +---@class actorutility : actor +---@field cc_break number amount of times the actor broke a cc +---@field interrupt number amount of times the actor interrupted a spell +---@field ress number amount of times the actor ressed a player +---@field dead number amount of times the actor died +---@field cooldowns_defensive number amount of times the actor used a defensive cooldown +---@field buff_uptime number amount of time the actor had a buff +---@field debuff_uptime number amount of time the actor had a debuff +---@field cc_done number amount of times the actor applyed a crowdcontrol on a target +---@field cc_done_targets table [targetName] = amount of times the actor cc'd the target +---@field cc_done_spells spellcontainer +---@field dispell number amount of times the actor dispelled a buff or debuff +---@field dispell_spells spellcontainer +---@field dispell_targets table [targetName] = amount +---@field dispell_oque table [spellId] = amount, amount of times the actor dispelled the spellId + +--interrupt_targets interrupt_spells interrompeu_oque +--cc_break_targets cc_break_spells cc_break_oque + + +---@class segmentid : number +---@class instanceid : number +---@class attributeid : number +---@class modeid : number + +---@class instance : table +---@field segmento segmentid +---@field showing combat +---@field meu_id instanceid +---@field is_interacting boolean +---@field modo modeid +---@field atributo attributeid +---@field sub_atributo attributeid +---@field ativa boolean +---@field freezed boolean +---@field sub_atributo_last table +---@field row_info table +---@field GetSize fun(instance: instance) : width, height +---@field GetInstanceGroup fun() : table +---@field GetCombat fun(instance: instance) +---@field ChangeIcon fun(instance: instance) +---@field CheckIntegrity fun(instance: instance) +---@field SetMode fun(instance: instance, mode: modeid) +---@field GetMode fun(instance: instance) : modeid +---@field IsInteracting fun(instance: instance) : boolean +---@field IsLowerInstance fun(instance: instance) : boolean +---@field IsEnabled fun(instance: instance) : boolean +---@field GetId fun(instance: instance) : instanceid +---@field GetSegmentId fun(instance: instance) : segmentid +---@field RefreshCombat fun(instance: instance) +---@field Freeze fun(instance: instance) +---@field UnFreeze fun(instance: instance) +---@field SetSegment fun(instance: instance, segment: segmentid, force: boolean|nil) +---@field GetDisplay fun(instance: instance) : attributeid, attributeid +---@field ResetWindow fun(instance: instance, resetType: number|nil, segmentId: segmentid|nil) +---@field RefreshData fun(instance: instance, force: boolean|nil) +---@field RefreshWindow fun(instance: instance, force: boolean|nil) + +---@class trinketdata : table +---@field itemName string +---@field spellName string +---@field lastActivation number +---@field lastPlayerName string +---@field totalCooldownTime number +---@field activations number +---@field lastCombatId number +---@field minTime number +---@field maxTime number +---@field averageTime number + +---@class tabframe : frame this is the tab frame object for the breakdown window + +---@class breakdownwindow : frame +---@field shownPluginObject table +---@field BreakdownSideMenuFrame frame frame attached to the left or right side of the breakdown window +---@field BreakdownPluginSelectionFrame frame frame which has buttons to select a plugin to show in the breakdown window +---@field BreakdownTabsFrame frame where the tab buttons are located (parent frame) +---@field RegisteredPluginButtons button[] table which contains plugins buttons that are registered to the breakdown window +---@field RegisterPluginButton fun(button: button) register a plugin button to the breakdown window +---@field GetShownPluginObject fun() : table get the plugin object that is currently shown in the breakdown window + + +---@class breakdownscrolldata : table +---@field totalValue number total done by the actor +---@field combatTime number +---@field [spelltableadv] spelltableadv indexed part of the table + +---@class headercolumndatasaved : {enabled: boolean, width: number, align: string} + +---@class breakdownexpandbutton : button +---@field texture texture + +---@class breakdownspellscrollframe : df_scrollboxmixin, scrollframe +---@field Header df_headerframe +---@field RefreshMe fun(scrollFrame: breakdownspellscrollframe, data: table|nil) +---@field SortKey string +---@field SortOrder string + +---@class breakdowntargetscrollframe : df_scrollboxmixin, scrollframe +---@field Header df_headerframe +---@field RefreshMe fun(scrollFrame: breakdowntargetscrollframe, data: table|nil) + +---@class breakdowngenericscrollframe : df_scrollboxmixin, scrollframe +---@field Header df_headerframe +---@field RefreshMe fun(scrollFrame: breakdowngenericscrollframe, data: table|nil) + +---@class breakdownphasescrollframe : df_scrollboxmixin, scrollframe +---@field Header df_headerframe +---@field RefreshMe fun(scrollFrame: breakdownphasescrollframe, data: table|nil) + +---@class breakdownphasebar : button, df_headerfunctions +---@field index number +---@field Icon texture +---@field InLineTexts fontstring[] +---@field statusBar breakdownspellbarstatusbar + +---@class breakdowngenericbar : button, df_headerfunctions +---@field index number +---@field rank number +---@field name string +---@field percent number +---@field amount number +---@field total number +---@field actorName string +---@field Icon texture +---@field InLineTexts fontstring[] +---@field statusBar breakdownspellbarstatusbar +---@field bIsFromLeftScroll boolean +---@field bIsFromRightScroll boolean + +---@class breakdowntargetbar : button, df_headerfunctions +---@field index number +---@field rank number +---@field name string +---@field percent number +---@field amount number +---@field total number +---@field actorName string +---@field bkTargetData breakdowntargettable +---@field Icon texture +---@field InLineTexts fontstring[] +---@field statusBar breakdownspellbarstatusbar + +---@class breakdownspellbar : button, df_headerfunctions +---@field index number +---@field rank number +---@field spellId number +---@field name string +---@field combatTime number +---@field perSecond number +---@field percent number +---@field amountCasts number +---@field average number +---@field castAverage number +---@field onMouseUpTime number GetTime() of when the spellbar got OnMouseUp event +---@field cursorPosX number mouse position when the spellbar got OnMouseDown event +---@field cursorPosY number mouse position when the spellbar got OnMouseDown event +---@field spellTable spelltable +---@field bkSpellData spelltableadv +---@field statusBar breakdownspellbarstatusbar +---@field expandButton breakdownexpandbutton +---@field spellIconFrame frame +---@field spellIcon texture +---@field targetsSquareFrame breakdowntargetframe +---@field targetsSquareTexture texture +---@field overlayTexture texture +---@field bIsExpandedSpell boolean +---@field ExpandedChildren breakdownspellbar[] store the spellbars which are expanded from this spellbar (spellbars shown when the expand button is pressed) +---@field InLineTexts fontstring[] + +---@class breakdownspellbarstatusbar : statusbar +---@field backgroundTexture texture +---@field overlayTexture texture +---@field highlightTexture texture + +---spelltableadv is similar to spelltable but allow custom members, methods and any modification isn't save to saved variables +---@class spelltableadv : spelltable, spelltablemixin +---@field expanded boolean if is true the show the nested spells +---@field spellTables spelltable[] +---@field nestedData bknesteddata[] +---@field bCanExpand boolean +---@field expandedIndex number +---@field bIsExpanded boolean +---@field statusBarValue number +---@field npcId npcid +---@field actorName string --when showing an actor header, this is the actor name +---@field bIsActorHeader boolean if this is true, the spellbar is an actor header, which is a bar with the actor name with the actor spells nested +---@field actorIcon textureid|texturepath + +---@class bknesteddata : {spellId: number, spellTable: spelltable, actorName: string, value: number, bIsActorHeader: boolean} fills .nestedData table in spelltableadv, used to store the nested spells data, 'value' is set when the breakdown sort the values by the selected header + +---@class breakdowntargetframe : frame +---@field spellId number +---@field bkSpellData spelltableadv +---@field spellTable spelltable +---@field texture texture +---@field bIsMainLine boolean + +---@class breakdowntargettablelist : breakdowntargettable[] +---@field totalValue number +---@field totalValueOverheal number +---@field combatTime number + +---@class breakdowntargettable : table +---@field name string +---@field total number +---@field overheal number|nil +---@field absorbed number|nil +---@field statusBarValue number + +---@class breakdownspelldatalist : spelltableadv[] +---@field totalValue number +---@field combatTime number + +---@class breakdownspellstab : tabframe +---@field SpellScrollFrame breakdownspellscrollframe +---@field SpellBlockFrame breakdownspellblockframe + +---@class breakdownspellblockframe : frame container for the spellblocks in the breakdown window +---@field SpellBlocks breakdownspellblock[] array of spellblocks +---@field blocksInUse number number of blocks currently in use +---@field UpdateBlocks fun(self: breakdownspellblockframe) update the blocks +---@field ClearBlocks fun(self: breakdownspellblockframe) clear all blocks +---@field GetBlock fun(self: breakdownspellblockframe, index: number) : breakdownspellblock return the block at the index +---@field GetBlocksInUse fun(self: breakdownspellblockframe) : number return the number of blocks currently in use +---@field GetBlocksAmount fun(self: breakdownspellblockframe) : number return the total blocks created +---@field ShowEmptyBlock fun(self: breakdownspellblockframe, index: number) show the empty block + +---@class breakdownspellblock : statusbar breakdownspellblock object which is created inside the breakdownspellblockframe +---@field Lines breakdownspellblockline[] +---@field reportButton button +---@field overlay texture +---@field statusBarTexture texture +---@field sparkTexture texture +---@field gradientTexture texture +---@field backgroundTexture texture +---@field GetLine fun(self: breakdownspellblock, index: number) : breakdownspellblockline +---@field GetLines fun(self: breakdownspellblock) : breakdownspellblockline, breakdownspellblockline, breakdownspellblockline +---@field SetColor fun(self: breakdownspellblock, r: any, g: number|nil, b: number|nil, a: number|nil) + +---@class breakdownspellblockline : frame a line inside a breakdownspellblock, there's 3 of them in each breakdownspellblock +---@field leftText fontstring +---@field centerText fontstring +---@field rightText fontstring + +---@class breakdownspelltab +---@field selectedSpellBar breakdownspellbar +---@field TabFrame breakdownspellstab +---@field mainAttribute number +---@field subAttribute number +---@field TargetScrollFrame breakdowntargetscrollframe +---@field PhaseScrollFrame breakdownphasescrollframe +---@field GenericScrollFrameLeft breakdowngenericscrollframe +---@field GenericScrollFrameRight breakdowngenericscrollframe +---@field SpellContainerFrame df_framecontainer +---@field BlocksContainerFrame df_framecontainer +---@field TargetsContainerFrame df_framecontainer +---@field PhaseContainerFrame df_framecontainer +---@field GenericContainerFrameLeft df_framecontainer +---@field GenericContainerFrameRight df_framecontainer +---@field GetActor fun() : actor +---@field GetCombat fun() : combat +---@field GetInstance fun() : instance +---@field GetSpellScrollFrame fun() : breakdownspellscrollframe +---@field GetSpellBlockFrame fun() : breakdownspellblockframe +---@field GetTargetScrollFrame fun() : breakdowntargetscrollframe +---@field GetSpellScrollContainer fun() : df_framecontainer +---@field GetSpellBlockContainer fun() : df_framecontainer +---@field GetTargetScrollContainer fun() : df_framecontainer +---@field OnProfileChange fun() +---@field UpdateHeadersSettings fun(containerType: string) +---@field BuildHeaderTable fun(containerType: string) : {name: string, width: number, text: string, align: string}[] +---@field SelectSpellBar fun(spellBar: breakdownspellbar) +---@field UnSelectSpellBar fun() +---@field GetSelectedSpellBar fun() : breakdownspellbar +---@field HasSelectedSpellBar fun() : boolean +---@field OnShownTab fun() +---@field OnCreateTabCallback fun(tabButton: button, tabFrame: frame) +---@field CreateSpellBlock fun(spellBlockContainer: breakdownspellblockframe, index: number) : breakdownspellblock +---@field CreateSpellBlockContainer fun(tabFrame: tabframe) : breakdownspellblockframe +---@field UpdateShownSpellBlock fun() +---@field CreateTargetContainer fun(tabFrame: tabframe) : breakdowntargetscrollframe +---@field CreateGenericContainers fun(tabFrame: tabframe) : breakdowngenericscrollframe, breakdowngenericscrollframe +---@field CreateSpellScrollContainer fun(tabFrame: tabframe) : breakdownspellscrollframe +---@field CreateTargetBar fun(self: breakdowntargetscrollframe, index: number) : breakdowntargetbar +---@field CreateSpellBar fun(self: breakdownspellscrollframe, index: number) : breakdownspellbar + +---@class timemachine : table +---@field Ticker fun() runs each second and check if actors are performing damage and healing actions, if the actor isn't, stop the activity time of that actor +---@field Start fun() start the time machine, called once from the start.lua +---@field Cleanup fun() check for actors with __destroyed flag and remove them from the time machine +---@field Restart fun() reset all data inside the time machine +---@field AddActor fun(actor: actor) add the actor to the time machine +---@field RemoveActor fun(actor: actor) remove the actor from the time machine +---@field StopTime fun(actor: actor) stop the time of the actor +---@field SetOrGetPauseState fun(actor: actor, bPause: boolean|nil) : boolean|nil set or get the pause state of the actor, if bPause is nil, then it will return the current pause state + +---@class details222 : table +---@field TimeMachine timemachine + diff --git a/plugins/Details_EncounterDetails/Details_EncounterDetails-Wrath.toc b/plugins/Details_EncounterDetails/Details_EncounterDetails-Wrath.toc index 7f5397b4..b6f4cd7a 100644 --- a/plugins/Details_EncounterDetails/Details_EncounterDetails-Wrath.toc +++ b/plugins/Details_EncounterDetails/Details_EncounterDetails-Wrath.toc @@ -8,6 +8,10 @@ enUS.lua ptBR.lua -frames.lua -Details_EncounterDetails.lua \ No newline at end of file +Details_EncounterDetails.lua +frames_chart.lua +frames_emote.lua +frames_phases.lua +frames_summary.lua +frames.lua \ No newline at end of file diff --git a/plugins/Details_EncounterDetails/Details_EncounterDetails.lua b/plugins/Details_EncounterDetails/Details_EncounterDetails.lua index 09099502..7aa3ada3 100644 --- a/plugins/Details_EncounterDetails/Details_EncounterDetails.lua +++ b/plugins/Details_EncounterDetails/Details_EncounterDetails.lua @@ -1,2120 +1,792 @@ -local AceLocale = LibStub ("AceLocale-3.0") -local Loc = AceLocale:GetLocale ("Details_EncounterDetails") -local Graphics = LibStub:GetLibrary("LibGraph-2.0") -local _ + +local addonId, edTable = ... +local AceLocale = LibStub("AceLocale-3.0") +local Loc = AceLocale:GetLocale("Details_EncounterDetails") +local Details = Details +local _ + +local openAtStartup = "false" local isDebug = false -local function DebugMessage (...) +local function DebugMessage(...) if (isDebug) then - print ("|cFFFFFF00EBreakDown|r:", ...) + print("|cFFFFFF00EBreakDown|r:", ...) end end ---> Needed locals -local _GetTime = GetTime --> wow api local -local _UFC = UnitAffectingCombat --> wow api local -local _IsInRaid = IsInRaid --> wow api local -local _IsInGroup = IsInGroup --> wow api local -local _UnitAura = UnitAura --> wow api local -local _GetSpellInfo = Details.getspellinfo --> wow api local -local _CreateFrame = CreateFrame --> wow api local -local _GetTime = GetTime --> wow api local -local _GetCursorPosition = GetCursorPosition --> wow api local -local _GameTooltip = GameTooltip --> wow api local +local PLUGIN_REAL_NAME = "DETAILS_PLUGIN_ENCOUNTER_DETAILS" +edTable.PluginAbsoluteName = PLUGIN_REAL_NAME + +local _GetSpellInfo = Details.getspellinfo --wow api local +local CreateFrame = CreateFrame --wow api local +local GetTime = GetTime --wow api local +local GetCursorPosition = GetCursorPosition --wow api local +local GameTooltip = GameTooltip --wow api local local GameCooltip = GameCooltip2 -local _math_floor = math.floor --> lua library local -local _cstr = string.format --> lua library local -local _ipairs = ipairs --> lua library local -local _pairs = pairs --> lua library local -local _table_sort = table.sort --> lua library local -local _table_insert = table.insert --> lua library local -local _unpack = unpack --> lua library local -local _bit_band = bit.band +local ipairs = ipairs +local pairs = pairs +local bitBand = bit.band -local CONST_FONT_SIZE = 10 +--create the plugin object +local encounterDetails = Details:NewPluginObject("Details_EncounterDetails", DETAILSPLUGIN_ALWAYSENABLED) +table.insert(UISpecialFrames, "Details_EncounterDetails") +edTable.PluginObject = encounterDetails ---> Create the plugin Object -local EncounterDetails = Details:NewPluginObject ("Details_EncounterDetails", DETAILSPLUGIN_ALWAYSENABLED) -tinsert (UISpecialFrames, "Details_EncounterDetails") ---> Main Frame -local EncounterDetailsFrame = EncounterDetails.Frame -EncounterDetailsFrame.DefaultBarHeight = 20 -EncounterDetailsFrame.CooltipStatusbarAlpha = .65 -EncounterDetailsFrame.DefaultBarTexture = "Interface\\AddOns\\Details\\images\\bar_serenity" +EncounterDetailsGlobal = encounterDetails --[[GLOBAL]] -EncounterDetails:SetPluginDescription ("Raid encounters summary, show basic stuff like dispels, interrupts and also graphic charts, boss emotes and the Weakaura Creation Tool.") +edTable.defaultBackgroundColor = {0.5, 0.5, 0.5, 0.3} +edTable.defaultBackgroundColor_OnEnter = {0.5, 0.5, 0.5, 0.7} +edTable.defaultBackdrop = {bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tileSize = 64, tile = true} ---> container types -local class_type_damage = Details.atributos.dano --> damage -local class_type_misc = Details.atributos.misc --> misc ---> main combat object +local edFrame = encounterDetails.Frame +edFrame.DefaultBarHeight = 20 +edFrame.CooltipStatusbarAlpha = .834 +edFrame.DefaultBarTexture = "Interface\\AddOns\\Details\\images\\bar_serenity" +edFrame.encounterSummaryWidgets = {} +encounterDetails:SetPluginDescription("Raid encounters summary, show basic stuff like dispels, interrupts and also graphic charts, boss emotes and the Weakaura Creation Tool.") + +--main combat object local _combat_object -local sort_by_name = function (t1, t2) return t1.nome < t2.nome end +encounterDetails.name = "Encounter Breakdown" +encounterDetails.debugmode = false -local CLASS_ICON_TCOORDS = _G.CLASS_ICON_TCOORDS - -EncounterDetails.name = "Encounter Breakdown" -EncounterDetails.debugmode = false - -function EncounterDetails:FormatCooltipSettings() - GameCooltip:SetType ("tooltip") - GameCooltip:SetOption ("StatusBarTexture", [[Interface\AddOns\Details\images\bar_serenity]]) - GameCooltip:SetOption ("StatusBarHeightMod", 0) - GameCooltip:SetOption ("FixedWidth", 280) - GameCooltip:SetOption ("TextSize", 11) - GameCooltip:SetOption ("LeftBorderSize", -4) - GameCooltip:SetOption ("RightBorderSize", 5) - GameCooltip:SetOption ("ButtonsYMod", 0) - GameCooltip:SetOption ("YSpacingMod", -1) +function encounterDetails:FormatCooltipSettings() + GameCooltip:SetType("tooltip") + GameCooltip:SetOption("StatusBarTexture", [[Interface\AddOns\Details\images\bar_serenity]]) + GameCooltip:SetOption("StatusBarHeightMod", 0) + GameCooltip:SetOption("FixedWidth", 280) + GameCooltip:SetOption("TextSize", 11) + GameCooltip:SetOption("LeftBorderSize", -4) + GameCooltip:SetOption("RightBorderSize", 5) + GameCooltip:SetOption("ButtonsYMod", 0) + GameCooltip:SetOption("YSpacingMod", -1) end -EncounterDetails.CooltipLineHeight = 18 +encounterDetails.CooltipLineHeight = 18 -local ability_type_table = { - [0x1] = "|cFF00FF00"..Loc ["STRING_HEAL"].."|r", - [0x2] = "|cFF710000"..Loc ["STRING_LOWDPS"].."|r", - [0x4] = "|cFF057100"..Loc ["STRING_LOWHEAL"].."|r", - [0x8] = "|cFFd3acff"..Loc ["STRING_VOIDZONE"].."|r", - [0x10] = "|cFFbce3ff"..Loc ["STRING_DISPELL"].."|r", - [0x20] = "|cFFffdc72"..Loc ["STRING_INTERRUPT"].."|r", - [0x40] = "|cFFd9b77c"..Loc ["STRING_POSITIONING"].."|r", - [0x80] = "|cFFd7ff36"..Loc ["STRING_RUNAWAY"].."|r", - [0x100] = "|cFF9a7540"..Loc ["STRING_TANKSWITCH"] .."|r", - [0x200] = "|cFFff7800"..Loc ["STRING_MECHANIC"].."|r", - [0x400] = "|cFFbebebe"..Loc ["STRING_CROWDCONTROL"].."|r", - [0x800] = "|cFF6e4d13"..Loc ["STRING_TANKCOOLDOWN"].."|r", - [0x1000] = "|cFFffff00"..Loc ["STRING_KILLADD"].."|r", - [0x2000] = "|cFFff9999"..Loc ["STRING_SPREADOUT"].."|r", - [0x4000] = "|cFFffff99"..Loc ["STRING_STOPCAST"].."|r", - [0x8000] = "|cFFffff99"..Loc ["STRING_FACING"].."|r", - [0x10000] = "|cFFffff99"..Loc ["STRING_STACK"].."|r", - -} +--main object frame functions +local function CreatePluginFrames(data) + --saved data if any + encounterDetails.data = data or {} ---> main object frame functions -local function CreatePluginFrames (data) - - --> catch Details! main object - local _detalhes = Details - local DetailsFrameWork = _detalhes.gump + --record if button is shown + encounterDetails.showing = false - --> saved data if any - EncounterDetails.data = data or {} - --> record if button is shown - EncounterDetails.showing = false - --> record if boss window is open or not - EncounterDetails.window_open = false - EncounterDetails.combat_boss_found = false - - --> OnEvent Table - function EncounterDetails:OnDetailsEvent (event, ...) - - --> when main frame became hide - if (event == "HIDE") then --> plugin hidded, disabled + --record if boss window is open or not + encounterDetails.window_open = false + encounterDetails.combat_boss_found = false + + --OnEvent Table + function encounterDetails:OnDetailsEvent(event, ...) + --when main frame became hide + if (event == "HIDE") then --plugin hidded, disabled self.open = false - - --> when main frame is shown on screen - elseif (event == "SHOW") then --> plugin hidded, disabled + + --when main frame is shown on screen + elseif (event == "SHOW") then --plugin hidded, disabled self.open = true - EncounterDetails:RefreshScale() - - --> when details finish his startup and are ready to work + encounterDetails:RefreshScale() + + --when details finish his startup and are ready to work elseif (event == "DETAILS_STARTED") then + if (openAtStartup) then + C_Timer.After(0.1, function() + --Details:OpenPlugin('Encounter Breakdown') + end) + end - --> check if details are in combat, if not check if the last fight was a boss fight - if (not EncounterDetails:IsInCombat()) then - --> get the current combat table - _combat_object = EncounterDetails:GetCombat() - --> check if was a boss fight - EncounterDetails:WasEncounter() + --check if details are in combat, if not check if the last fight was a boss fight + if (not encounterDetails:IsInCombat()) then + --get the current combat table + _combat_object = encounterDetails:GetCombat() + --check if was a boss fight + encounterDetails:WasEncounter() end - - local damage_done_func = function (support_table, time_table, tick_second) - local current_total_damage = _detalhes.tabela_vigente.totals_grupo[1] - local current_damage = current_total_damage - support_table.last_damage - time_table [tick_second] = current_damage - if (current_damage > support_table.max_damage) then - support_table.max_damage = current_damage - time_table.max_damage = current_damage - end - support_table.last_damage = current_total_damage - end - + local string_damage_done_func = [[ - - -- this script takes the current combat and request the total of damage done by the group. - - -- first lets take the current combat and name it "current_combat". - local current_combat = _detalhes:GetCombat ("current") --> getting the current combat - - -- now lets ask the combat for the total damage done by the raide group. - local total_damage = current_combat:GetTotal ( DETAILS_ATTRIBUTE_DAMAGE, nil, DETAILS_TOTALS_ONLYGROUP ) - - -- checks if the result is valid - if (not total_damage) then - return 0 - end - - -- with the number in hands, lets finish the code returning the amount - return total_damage + --get the current combat + local currentCombat = Details:GetCurrentCombat() + --total damage done by the raid group + local raidGroupDamageDone = currentCombat:GetTotal(DETAILS_ATTRIBUTE_DAMAGE, nil, DETAILS_TOTALS_ONLYGROUP) + return raidGroupDamageDone or 0 ]] - - --_detalhes:TimeDataRegister ("Raid Damage Done", damage_done_func, {last_damage = 0, max_damage = 0}, "Encounter Details", "v1.0", [[Interface\ICONS\Ability_DualWield]], true) - _detalhes:TimeDataRegister ("Raid Damage Done", string_damage_done_func, nil, "Encounter Details", "v1.0", [[Interface\ICONS\Ability_DualWield]], true, true) - - if (EncounterDetails.db.show_icon == 4) then - EncounterDetails:ShowIcon() - elseif (EncounterDetails.db.show_icon == 5) then - EncounterDetails:AutoShowIcon() - end - - --EncounterDetails:CreateCallbackListeners() - - elseif (event == "COMBAT_PLAYER_ENTER") then --> combat started - if (EncounterDetails.showing and EncounterDetails.db.hide_on_combat) then - --EncounterDetails:HideIcon() - EncounterDetails:CloseWindow() - end - - EncounterDetails.current_whisper_table = {} - - elseif (event == "COMBAT_PLAYER_LEAVE") then - --> combat leave and enter always send current combat table - _combat_object = select (1, ...) - --> check if was a boss fight - EncounterDetails:WasEncounter() - if (EncounterDetails.combat_boss_found) then - EncounterDetails.combat_boss_found = false - end - if (EncounterDetails.db.show_icon == 5) then - EncounterDetails:AutoShowIcon() + Details:TimeDataRegister("Raid Damage Done", string_damage_done_func, nil, "Encounter Details", "v1.0", [[Interface\ICONS\Ability_DualWield]], true, true) + + if (encounterDetails.db.show_icon == 4) then + encounterDetails:ShowIcon() + elseif (encounterDetails.db.show_icon == 5) then + encounterDetails:AutoShowIcon() end - local whisper_table = EncounterDetails.current_whisper_table - if (whisper_table and _combat_object.is_boss and _combat_object.is_boss.name) then - whisper_table.boss = _combat_object.is_boss.name - tinsert (EncounterDetails.boss_emotes_table, 1, whisper_table) - - if (#EncounterDetails.boss_emotes_table > EncounterDetails.db.max_emote_segments) then - table.remove (EncounterDetails.boss_emotes_table, EncounterDetails.db.max_emote_segments+1) + elseif (event == "COMBAT_PLAYER_ENTER") then --combat started + if (encounterDetails.showing and encounterDetails.db.hide_on_combat) then + --EncounterDetails:HideIcon() + encounterDetails:CloseWindow() + end + + encounterDetails.current_whisper_table = {} + + elseif (event == "COMBAT_PLAYER_LEAVE") then + --combat leave and enter always send current combat table + _combat_object = select(1, ...) + --check if was a boss fight + encounterDetails:WasEncounter() + + if (encounterDetails.combat_boss_found) then + encounterDetails.combat_boss_found = false + end + + if (encounterDetails.db.show_icon == 5) then + encounterDetails:AutoShowIcon() + end + + local chartName = "Raid Damage Done" + local combatUniquieID = _combat_object:GetCombatNumber() + local chartData = _combat_object:GetTimeData(chartName) + + if (chartData) then + EncounterDetailsDB.chartData[combatUniquieID] = EncounterDetailsDB.chartData[combatUniquieID] or {} + EncounterDetailsDB.chartData[combatUniquieID][chartName] = chartData + --store when this chart was created to cleanup later + chartData.__time = time() + --remove the time data from the combat object + _combat_object:EraseTimeData(chartName) + end + + local whisperTable = encounterDetails.current_whisper_table + if (whisperTable and _combat_object.is_boss and _combat_object.is_boss.name) then + whisperTable.boss = _combat_object.is_boss.name + table.insert(encounterDetails.boss_emotes_table, 1, whisperTable) + + if (#encounterDetails.boss_emotes_table > encounterDetails.db.max_emote_segments) then + table.remove(encounterDetails.boss_emotes_table, encounterDetails.db.max_emote_segments+1) end end - + elseif (event == "COMBAT_BOSS_FOUND") then - EncounterDetails.combat_boss_found = true - if (EncounterDetails.db.show_icon == 5) then - EncounterDetails:AutoShowIcon() + encounterDetails.combat_boss_found = true + if (encounterDetails.db.show_icon == 5) then + encounterDetails:AutoShowIcon() end elseif (event == "DETAILS_DATA_RESET") then - if (_G.DetailsRaidDpsGraph) then - _G.DetailsRaidDpsGraph:ResetData() + if (encounterDetails.chartPanel) then + encounterDetails.chartPanel:Reset() end - if (EncounterDetails.db.show_icon == 5) then - EncounterDetails:AutoShowIcon() + + if (encounterDetails.db.show_icon == 5) then + encounterDetails:AutoShowIcon() end - --EncounterDetails:HideIcon() - EncounterDetails:CloseWindow() - + + encounterDetails:CloseWindow() + --drop last combat table - EncounterDetails.LastSegmentShown = nil - - if (DetailsRaidDpsGraph) then - DetailsRaidDpsGraph.combat = nil - end - + encounterDetails.LastSegmentShown = nil + --wipe emotes - table.wipe (EncounterDetails.boss_emotes_table) - + table.wipe(encounterDetails.boss_emotes_table) + elseif (event == "GROUP_ONENTER") then - if (EncounterDetails.db.show_icon == 2) then - EncounterDetails:ShowIcon() + if (encounterDetails.db.show_icon == 2) then + encounterDetails:ShowIcon() end - + elseif (event == "GROUP_ONLEAVE") then - if (EncounterDetails.db.show_icon == 2) then - EncounterDetails:HideIcon() + if (encounterDetails.db.show_icon == 2) then + encounterDetails:HideIcon() end - + elseif (event == "ZONE_TYPE_CHANGED") then - if (EncounterDetails.db.show_icon == 1) then - if (select (1, ...) == "raid") then - EncounterDetails:ShowIcon() + if (encounterDetails.db.show_icon == 1) then + if (select(1, ...) == "raid") then + encounterDetails:ShowIcon() else - EncounterDetails:HideIcon() + encounterDetails:HideIcon() end end - + elseif (event == "PLUGIN_DISABLED") then - EncounterDetails:HideIcon() - EncounterDetails:CloseWindow() - + encounterDetails:HideIcon() + encounterDetails:CloseWindow() + elseif (event == "PLUGIN_ENABLED") then - if (EncounterDetails.db.show_icon == 5) then - EncounterDetails:AutoShowIcon() - elseif (EncounterDetails.db.show_icon == 4) then - EncounterDetails:ShowIcon() + if (encounterDetails.db.show_icon == 5) then + encounterDetails:AutoShowIcon() + + elseif (encounterDetails.db.show_icon == 4) then + encounterDetails:ShowIcon() end end end - - - --desativado, agora ele � gerenciado dentro do proprio details! - function EncounterDetails:CreateCallbackListeners() - - EncounterDetails.DBM_timers = {} - - local current_encounter = false - - local current_table_dbm = {} - local current_table_bigwigs = {} - - local event_frame = CreateFrame ("frame", nil, UIParent, "BackdropTemplate") - event_frame:SetScript ("OnEvent", function (self, event, ...) - if (event == "ENCOUNTER_START") then - local encounterID, encounterName, difficultyID, raidSize = select (1, ...) - current_encounter = encounterID - - elseif (event == "ENCOUNTER_END" or event == "PLAYER_REGEN_ENABLED") then - if (current_encounter) then - - if (_G.DBM) then - local db = _detalhes.global_plugin_database ["DETAILS_PLUGIN_ENCOUNTER_DETAILS"] - for spell, timer_table in pairs (current_table_dbm) do - if (not db.encounter_timers_dbm [timer_table[1]]) then - timer_table.id = current_encounter - db.encounter_timers_dbm [timer_table[1]] = timer_table - end - end - end - if (BigWigs) then - local db = _detalhes.global_plugin_database ["DETAILS_PLUGIN_ENCOUNTER_DETAILS"] - for timer_id, timer_table in pairs (current_table_bigwigs) do - if (not db.encounter_timers_bw [timer_id]) then - timer_table.id = current_encounter - db.encounter_timers_bw [timer_id] = timer_table - end - end - end - - end - - current_encounter = false - wipe (current_table_dbm) - wipe (current_table_bigwigs) - end - end) - event_frame:RegisterEvent ("ENCOUNTER_START") - event_frame:RegisterEvent ("ENCOUNTER_END") - event_frame:RegisterEvent ("PLAYER_REGEN_ENABLED") - ---DBM_TimerStart Timer183828cdcount 2 Death Brand CD (2) 42.5 Interface\Icons\warlock_summon_doomguard cdcount 183828 1 1438 ---DBM_TimerStart Timer183828cdcount 3 Death Brand CD (3) 42.5 Interface\Icons\warlock_summon_doomguard cdcount 183828 1 1438 - - --EncounterDetails.DBM_timers - if (_G.DBM) then - local dbm_timer_callback = function (bar_type, id, msg, timer, icon, bartype, spellId, colorId, modid) - --print (bar_type, id, msg, timer, icon, bartype, spellId, colorId, modid) - local spell = tostring (spellId) - if (spell and not current_table_dbm [spell]) then - current_table_dbm [spell] = {spell, id, msg, timer, icon, bartype, spellId, colorId, modid} - end - end - DBM:RegisterCallback ("DBM_TimerStart", dbm_timer_callback) - end - function EncounterDetails:RegisterBigWigsCallBack() - if (BigWigsLoader) then - function EncounterDetails:BigWigs_StartBar (event, module, spellid, bar_text, time, icon, ...) - --print (event, module, spellid, bar_text, time, icon, ...) - spellid = tostring (spellid) - if (not current_table_bigwigs [spellid]) then - current_table_bigwigs [spellid] = {(type (module) == "string" and module) or (module and module.moduleName) or "", spellid or "", bar_text or "", time or 0, icon or ""} - end - end - if (BigWigsLoader.RegisterMessage) then - BigWigsLoader.RegisterMessage (EncounterDetails, "BigWigs_StartBar") - end - end - end - EncounterDetails:ScheduleTimer ("RegisterBigWigsCallBack", 5) - ---BigWigs_StartBar BigWigs_Bosses_Brackenspore mind_fungus Mind Fungus 51 Interface\Icons\inv_mushroom_10 true ---bigwigs startbar mind_fungus ---BigWigs_StartBar BigWigs_Bosses_Brackenspore 159996 Infesting Spores (2) 58 Interface\Icons\Ability_Creature_Disease_01 ---bigwigs startbar 160013 - - end - - function EncounterDetails:WasEncounter() - - --> check if last combat was a boss encounter fight - if (not EncounterDetails.debugmode) then - + function encounterDetails:WasEncounter() + --check if last combat was a boss encounter + if (not encounterDetails.debugmode) then if (not _combat_object.is_boss) then return - elseif (_combat_object.is_boss.encounter == "pvp") then + + elseif (_combat_object.is_boss.encounter == "pvp") then return end - + if (_combat_object.instance_type ~= "raid") then return end - end - --> boss found, we need to show the icon - EncounterDetails:ShowIcon() + --boss found, show the icon + encounterDetails:ShowIcon() end - - --> show icon on toolbar - - local re_ShowIconBallonTutorial = function() - EncounterDetails:ShowIconBallonTutorial() - end - - function EncounterDetails:ShowIconBallonTutorial() - if (InCombatLockdown()) then - C_Timer.After (5, function() - --print ("in combat") - re_ShowIconBallonTutorial() - end) - return - end - - local hook_AlertButtonCloseButton = function() - --print ("done tutorial") - EncounterDetails:SetTutorialCVar ("ENCOUNTER_DETAILS_BALLON_TUTORIAL1", true) - end - - if (EncounterDetailsTutorialAlertButton1 or not EncounterDetails.ToolbarButton or not EncounterDetails.ToolbarButton:IsShown()) then - --print (EncounterDetailsTutorialAlertButton1, not EncounterDetails.ToolbarButton, not EncounterDetails.ToolbarButton:IsShown()) - return - end - - --[=[ - local alert = CreateFrame ("frame", "EncounterDetailsTutorialAlertButton1", EncounterDetails.ToolbarButton, "MicroButtonAlertTemplate") - alert:SetFrameLevel (302) - alert.label = "Click here (on the skull icon) to bring the Encounter Breakdown panel" - alert.Text:SetSpacing (4) - alert:SetClampedToScreen (true) - MicroButtonAlert_SetText (alert, alert.label) - alert:SetPoint ("bottom", EncounterDetails.ToolbarButton, "top", 0, 22) - alert.CloseButton:HookScript ("OnClick", hook_AlertButtonCloseButton) - alert:Show() - --]=] - --print ("showing ballon") - end - - function EncounterDetails:ShowIcon() - EncounterDetails.showing = true - --> [1] button to show [2] button animation: "star", "blink" or true (blink) - EncounterDetails:ShowToolbarIcon (EncounterDetails.ToolbarButton, "star") - --EncounterDetails:SetTutorialCVar ("ENCOUNTER_DETAILS_BALLON_TUTORIAL1", false) --debug - if (not EncounterDetails:GetTutorialCVar ("ENCOUNTER_DETAILS_BALLON_TUTORIAL1")) then - --print ("nao viu o tutorial ainda") - C_Timer.After (2, EncounterDetails.ShowIconBallonTutorial) - end - + function encounterDetails:ShowIcon() + encounterDetails.showing = true + --[1] button to show [2] button animation: "star", "blink" or true(blink) + encounterDetails:ShowToolbarIcon(encounterDetails.ToolbarButton, "star") end - - --> hide icon on toolbar - function EncounterDetails:HideIcon() - EncounterDetails.showing = false - EncounterDetails:HideToolbarIcon (EncounterDetails.ToolbarButton) - end - - local re_ShowTutorialAlert = function() - EncounterDetails:ShowTutorial() - end - local hook_AlertCloseButton = function() - re_ShowTutorialAlert() - end - - function EncounterDetails:ShowTutorial() - --deprecated - end - - --[=[ - EncounterDetailsFrame:HookScript ("OnShow", function() - C_Timer.After (0.1, function() - if (not EncounterDetails.LastOpenedTime or EncounterDetails.LastOpenedTime + 2 < GetTime()) then - if (_detalhes.AddOnStartTime and _detalhes.AddOnStartTime + 30 < GetTime()) then - EncounterDetails:OpenAndRefresh() - end - end - end) - end) - --]=] - --> user clicked on button, need open or close window - function EncounterDetails:OpenWindow() - - if (EncounterDetails.Frame:IsShown()) then - return EncounterDetails:CloseWindow() + --hide icon on toolbar + function encounterDetails:HideIcon() + encounterDetails.showing = false + encounterDetails:HideToolbarIcon(encounterDetails.ToolbarButton) + end + + --user clicked on button, need open or close window + function encounterDetails:OpenWindow() + if (encounterDetails.Frame:IsShown()) then + return encounterDetails:CloseWindow() end - - --> build all window data - EncounterDetails.db.opened = EncounterDetails.db.opened + 1 - EncounterDetails:OpenAndRefresh() - --> show - EncounterDetailsFrame:Show() - EncounterDetails.open = true - - if (EncounterDetailsFrame.ShowType == "graph") then - EncounterDetails:BuildDpsGraphic() + + --build all window data + encounterDetails.db.opened = encounterDetails.db.opened + 1 + encounterDetails:OpenAndRefresh() + --show + edFrame:Show() + encounterDetails.open = true + + if (edFrame.ShowType == "graph") then + encounterDetails:ShowChartFrame() end - + --select latest emote segment - Details_EncounterDetailsEmotesSegmentDropdown.MyObject:Select (1) - Details_EncounterDetailsEmotesSegmentDropdown.MyObject:Refresh() - FauxScrollFrame_SetOffset (EncounterDetails_EmoteScroll, 0) - EncounterDetails:SetEmoteSegment (1) - EncounterDetails_EmoteScroll:Update() - - if (EncounterDetailsFrame.ShowType ~= "emotes") then + encounterDetails.emoteSegmentsDropdown:Select(1) + encounterDetails.emoteSegmentsDropdown:Refresh() + encounterDetails:SetEmoteSegment(1) + + if (edFrame.ShowType ~= "emotes") then --hide emote frames - for _, widget in pairs (EncounterDetails.Frame.EmoteWidgets) do + for _, widget in pairs(encounterDetails.Frame.EmoteWidgets) do widget:Hide() end end - C_Timer.After (3, function() EncounterDetails:ShowTutorial() end) + DetailsPluginContainerWindow.OpenPlugin(encounterDetails) - DetailsPluginContainerWindow.OpenPlugin (EncounterDetails) - return true end - - function EncounterDetails:CloseWindow() - EncounterDetails.open = false - EncounterDetailsFrame:Hide() + + function encounterDetails:CloseWindow() + encounterDetails.open = false + edFrame:Hide() return true end - + local cooltip_menu = function() - - local CoolTip = GameCooltip2 - - CoolTip:Reset() - CoolTip:SetType ("menu") - - CoolTip:SetOption ("TextSize", Details.font_sizes.menus) - CoolTip:SetOption ("TextFont", Details.font_faces.menus) - - CoolTip:SetOption ("ButtonHeightModSub", -2) - CoolTip:SetOption ("ButtonHeightMod", -5) - - CoolTip:SetOption ("ButtonsYModSub", -3) - CoolTip:SetOption ("ButtonsYMod", -6) - - CoolTip:SetOption ("YSpacingModSub", -3) - CoolTip:SetOption ("YSpacingMod", 1) - - CoolTip:SetOption ("HeighMod", 3) - CoolTip:SetOption ("SubFollowButton", true) - - Details:SetTooltipMinWidth() - - --build the header - --- CoolTip:AddLine (Loc ["STRING_PLUGIN_NAME"]) --- CoolTip:AddIcon (ENCOUNTERDETAILS_BUTTON.__icon, 1, 1, 20, 20) --- CoolTip:AddMenu (1, EncounterDetails.Frame.switch, "main") - --- GameCooltip:AddLine ("$div") - - --build the menu options - - --summary - CoolTip:AddLine ("Encounter Summary") - CoolTip:AddMenu (1, EncounterDetails.Frame.switch, "main") - CoolTip:AddIcon ("Interface\\AddOns\\Details_EncounterDetails\\images\\boss_frame_buttons", 1, 1, 20, 22, 0, 0.1015625, 0, 0.505625) - - --chart - CoolTip:AddLine ("Damage Graphic") - CoolTip:AddMenu (1, EncounterDetails.Frame.switch, "graph") - CoolTip:AddIcon ("Interface\\AddOns\\Details_EncounterDetails\\images\\boss_frame_buttons", 1, 1, 20, 22, 0.1271875, 0.21875, 0, 0.505625) - - --emotes - CoolTip:AddLine ("Boss Emotes") - CoolTip:AddMenu (1, EncounterDetails.Frame.switch, "emotes") - CoolTip:AddIcon ("Interface\\AddOns\\Details_EncounterDetails\\images\\boss_frame_buttons", 1, 1, 20, 22, 91/256, 116/256, 0, 0.505625) - - --weakauras - CoolTip:AddLine ("Create Encounter Weakauras") - CoolTip:AddMenu (1, EncounterDetails.Frame.switch, "spellsauras") - - if (_G.WeakAuras) then - CoolTip:AddIcon ([[Interface\AddOns\WeakAuras\Media\Textures\icon]], 1, 1, 20, 20) - else - CoolTip:AddIcon ("Interface\\AddOns\\Details_EncounterDetails\\images\\boss_frame_buttons", 1, 1, 20, 22, 121/256, 146/256, 0, 0.505625) - end + local gameCooltip = GameCooltip + + gameCooltip:Reset() + gameCooltip:SetType("menu") + + gameCooltip:SetOption("TextSize", Details.font_sizes.menus) + gameCooltip:SetOption("TextFont", Details.font_faces.menus) + + gameCooltip:SetOption("ButtonHeightModSub", -2) + gameCooltip:SetOption("ButtonHeightMod", -5) + + gameCooltip:SetOption("ButtonsYModSub", -3) + gameCooltip:SetOption("ButtonsYMod", -6) + + gameCooltip:SetOption("YSpacingModSub", -3) + gameCooltip:SetOption("YSpacingMod", 1) + + gameCooltip:SetOption("HeighMod", 3) + gameCooltip:SetOption("SubFollowButton", true) + + Details:SetTooltipMinWidth() + + --summary + gameCooltip:AddLine("Encounter Summary") + gameCooltip:AddMenu(1, encounterDetails.Frame.switch, "main") + gameCooltip:AddIcon("Interface\\AddOns\\Details_EncounterDetails\\images\\boss_frame_buttons", 1, 1, 20, 20, 0, 0.125, 0, 0.5) + + --chart + gameCooltip:AddLine("Damage Graphic") + gameCooltip:AddMenu(1, encounterDetails.Frame.switch, "graph") + gameCooltip:AddIcon("Interface\\AddOns\\Details_EncounterDetails\\images\\boss_frame_buttons", 1, 1, 20, 20, 0.125*3, 0.125*4, 0, 0.5) + + --emotes + gameCooltip:AddLine("Boss Emotes") + gameCooltip:AddMenu(1, encounterDetails.Frame.switch, "emotes") + gameCooltip:AddIcon("Interface\\AddOns\\Details_EncounterDetails\\images\\boss_frame_buttons", 1, 1, 20, 20, 0.125*4, 0.125*5, 0, 0.5) + + --phases + gameCooltip:AddLine("Damage by Boss Phase") + gameCooltip:AddMenu(1, encounterDetails.Frame.switch, "phases") + gameCooltip:AddIcon("Interface\\AddOns\\Details_EncounterDetails\\images\\boss_frame_buttons", 1, 1, 20, 20, 0.125, 0.125*2, 0, 0.505625) - --phases - CoolTip:AddLine ("Damage by Boss Phase") - CoolTip:AddMenu (1, EncounterDetails.Frame.switch, "phases") - CoolTip:AddIcon ("Interface\\AddOns\\Details_EncounterDetails\\images\\boss_frame_buttons", 1, 1, 20, 22, 151/256, 176/256, 0, 0.505625) - - -- - - local textPoint = {"left", "left", 4, 0} - - local SharedMedia = LibStub:GetLibrary("LibSharedMedia-3.0") - --apply the backdrop settings to the menu Details:FormatCooltipBackdrop() - CoolTip:SetOwner (ENCOUNTERDETAILS_BUTTON, "bottom", "top", 0, 0) - CoolTip:ShowCooltip() - + gameCooltip:SetOwner(ENCOUNTERDETAILS_BUTTON, "bottom", "top", 0, 0) + gameCooltip:ShowCooltip() end - - EncounterDetails.ToolbarButton = _detalhes.ToolBar:NewPluginToolbarButton (EncounterDetails.OpenWindow, "Interface\\AddOns\\Details_EncounterDetails\\images\\icon", Loc ["STRING_PLUGIN_NAME"], Loc ["STRING_TOOLTIP"], 16, 16, "ENCOUNTERDETAILS_BUTTON", cooltip_menu) --"Interface\\COMMON\\help-i" - EncounterDetails.ToolbarButton.shadow = true --> loads icon_shadow.tga when the instance is showing icons with shadows - - --> setpoint anchors mod if needed - EncounterDetails.ToolbarButton.y = 0.5 - EncounterDetails.ToolbarButton.x = 0 - - --> build all frames ans widgets - _detalhes.EncounterDetailsTempWindow (EncounterDetails) - _detalhes.EncounterDetailsTempWindow = nil - - --> ~remover ~autoabrir �brir ~abrir ~auto - --C_Timer.After (.5, EncounterDetails.OpenWindow) - - + + encounterDetails.ToolbarButton = Details.ToolBar:NewPluginToolbarButton(encounterDetails.OpenWindow, "Interface\\AddOns\\Details_EncounterDetails\\images\\icon", Loc ["STRING_PLUGIN_NAME"], Loc ["STRING_TOOLTIP"], 16, 16, "ENCOUNTERDETAILS_BUTTON", cooltip_menu) --"Interface\\COMMON\\help-i" + encounterDetails.ToolbarButton.shadow = true --loads icon_shadow.tga when the instance is showing icons with shadows + + --setpoint anchors mod if needed + encounterDetails.ToolbarButton.y = 0.5 + encounterDetails.ToolbarButton.x = 0 + + --build all frames ans widgets + Details.EncounterDetailsTempWindow(encounterDetails) + Details.EncounterDetailsTempWindow = nil end -local sort_damage_from = function (a, b) - if (a[3] ~= "PET" and b[3] ~= "PET") then - return a[2] > b[2] - elseif (a[3] == "PET" and b[3] ~= "PET") then - return false - elseif (a[3] ~= "PET" and b[3] == "PET") then - return true - else - return a[2] > b[2] - end -end +--custom tooltip for dead details --------------------------------------------------------------------------------------------------------- ---> custom tooltip for dead details --------------------------------------------------------------------------------------------------------- - --tooltip backdrop, color and border local bgColor, borderColor = {0.17, 0.17, 0.17, .9}, {.30, .30, .30, .3} - - local function KillInfo (deathTable, row) - + + local function KillInfo(deathTable, row) local iconSize = 19 - + local eventos = deathTable [1] local hora_da_morte = deathTable [2] local hp_max = deathTable [5] - + local battleress = false local lastcooldown = false - + GameCooltip:Reset() - GameCooltip:SetType ("tooltipbar") - GameCooltip:SetOwner (row) - - GameCooltip:AddLine ("Click to Report", nil, 1, "orange") - GameCooltip:AddIcon ([[Interface\TUTORIALFRAME\UI-TUTORIAL-FRAME]], 1, 1, 12, 16, 0.015625, 0.13671875, 0.4375, 0.59765625) - GameCooltip:AddStatusBar (0, 1, 1, 1, 1, 1, false, {value = 100, color = {.3, .3, .3, .5}, specialSpark = false, texture = [[Interface\AddOns\Details\images\bar_serenity]]}) - + GameCooltip:SetType("tooltipbar") + GameCooltip:SetOwner(row) + + GameCooltip:AddLine("Click to Report", nil, 1, "orange") + GameCooltip:AddIcon([[Interface\TUTORIALFRAME\UI-TUTORIAL-FRAME]], 1, 1, 12, 16, 0.015625, 0.13671875, 0.4375, 0.59765625) + GameCooltip:AddStatusBar(0, 1, 1, 1, 1, 1, false, {value = 100, color = {.3, .3, .3, .5}, specialSpark = false, texture = [[Interface\AddOns\Details\images\bar_serenity]]}) + local statusBarBackground = {value = 100, color = {.21, .21, .21, 0.8}, texture = [[Interface\AddOns\Details\images\bar_serenity]]} - + --death parser - for index, event in _ipairs (eventos) do - - local hp = _math_floor (event[5]/hp_max*100) - if (hp > 100) then + for index, event in ipairs(eventos) do + + local hp = math.floor(event[5]/hp_max*100) + if (hp > 100) then hp = 100 end - + local evtype = event [1] - local spellname, _, spellicon = _GetSpellInfo (event [2]) + local spellname, _, spellicon = _GetSpellInfo(event [2]) local amount = event [3] local time = event [4] local source = event [6] - if (type (evtype) == "boolean") then - --> is damage or heal + if (type(evtype) == "boolean") then + --is damage or heal if (evtype) then - --> damage - + --damage + local overkill = event [10] or 0 if (overkill > 0) then amount = amount - overkill - overkill = " (" .. Details:ToK (overkill) .. " |cFFFF8800overkill|r)" + overkill = "(" .. Details:ToK(overkill) .. " |cFFFF8800overkill|r)" else overkill = "" end - - if (source:find ("%[")) then - source = source:gsub ("%[%*%] ", "") + + if (source:find("%[")) then + source = source:gsub("%[%*%] ", "") end - - GameCooltip:AddLine ("" .. _cstr ("%.1f", time - hora_da_morte) .. "s " .. spellname .. " (" .. source .. ")", "-" .. Details:ToK (amount) .. overkill .. " (" .. hp .. "%)", 1, "white", "white") - GameCooltip:AddIcon (spellicon, 1, 1, 16, 16, .1, .9, .1, .9) - + + GameCooltip:AddLine("" .. string.format("%.1f", time - hora_da_morte) .. "s " .. spellname .. "(" .. source .. ")", "-" .. Details:ToK(amount) .. overkill .. "(" .. hp .. "%)", 1, "white", "white") + GameCooltip:AddIcon(spellicon, 1, 1, 16, 16, .1, .9, .1, .9) + if (event [9]) then - --> friendly fire - GameCooltip:AddStatusBar (hp, 1, "darkorange", true, statusBarBackground) + --friendly fire + GameCooltip:AddStatusBar(hp, 1, "darkorange", true, statusBarBackground) else - --> from a enemy - GameCooltip:AddStatusBar (hp, 1, "red", true, statusBarBackground) + --from a enemy + GameCooltip:AddStatusBar(hp, 1, "red", true, statusBarBackground) end else - --> heal - local class = Details:GetClass (source) - local spec = Details:GetSpec (source) + --heal + local class = Details:GetClass(source) + local spec = Details:GetSpec(source) - GameCooltip:AddLine ("" .. _cstr ("%.1f", time - hora_da_morte) .. "s " .. spellname .. " (" .. Details:GetOnlyName (Details:AddClassOrSpecIcon (source, class, spec, 16, true)) .. ")", "+" .. Details:ToK (amount) .. " (" .. hp .. "%)", 1, "white", "white") - GameCooltip:AddIcon (spellicon, 1, 1, 16, 16, .1, .9, .1, .9) - GameCooltip:AddStatusBar (hp, 1, "green", true, statusBarBackground) + GameCooltip:AddLine("" .. string.format("%.1f", time - hora_da_morte) .. "s " .. spellname .. "(" .. Details:GetOnlyName(Details:AddClassOrSpecIcon(source, class, spec, 16, true)) .. ")", "+" .. Details:ToK(amount) .. "(" .. hp .. "%)", 1, "white", "white") + GameCooltip:AddIcon(spellicon, 1, 1, 16, 16, .1, .9, .1, .9) + GameCooltip:AddStatusBar(hp, 1, "green", true, statusBarBackground) end - - elseif (type (evtype) == "number") then + + elseif (type(evtype) == "number") then if (evtype == 1) then - --> cooldown - GameCooltip:AddLine ("" .. _cstr ("%.1f", time - hora_da_morte) .. "s " .. spellname .. " (" .. source .. ")", "cooldown (" .. hp .. "%)", 1, "white", "white") - GameCooltip:AddIcon (spellicon, 1, 1, 16, 16, .1, .9, .1, .9) - GameCooltip:AddStatusBar (100, 1, "yellow", true, statusBarBackground) - + --cooldown + GameCooltip:AddLine("" .. string.format("%.1f", time - hora_da_morte) .. "s " .. spellname .. "(" .. source .. ")", "cooldown(" .. hp .. "%)", 1, "white", "white") + GameCooltip:AddIcon(spellicon, 1, 1, 16, 16, .1, .9, .1, .9) + GameCooltip:AddStatusBar(100, 1, "yellow", true, statusBarBackground) + elseif (evtype == 2 and not battleress) then - --> battle ress + --battle ress battleress = event - + elseif (evtype == 3) then - --> last cooldown used + --last cooldown used lastcooldown = event - + elseif (evtype == 4) then - --> debuff - if (source:find ("%[")) then - source = source:gsub ("%[%*%] ", "") + --debuff + if (source:find("%[")) then + source = source:gsub("%[%*%] ", "") end - - GameCooltip:AddLine ("" .. _cstr ("%.1f", time - hora_da_morte) .. "s [x" .. amount .. "] " .. spellname .. " (" .. source .. ")", "debuff (" .. hp .. "%)", 1, "white", "white") - GameCooltip:AddIcon (spellicon, 1, 1, 16, 16, .1, .9, .1, .9) - GameCooltip:AddStatusBar (100, 1, "purple", true, statusBarBackground) - + + GameCooltip:AddLine("" .. string.format("%.1f", time - hora_da_morte) .. "s [x" .. amount .. "] " .. spellname .. "(" .. source .. ")", "debuff(" .. hp .. "%)", 1, "white", "white") + GameCooltip:AddIcon(spellicon, 1, 1, 16, 16, .1, .9, .1, .9) + GameCooltip:AddStatusBar(100, 1, "purple", true, statusBarBackground) + end end end - GameCooltip:AddLine (deathTable [6] .. " " .. "died" , "-- -- -- ", 1, "white") - GameCooltip:AddIcon ("Interface\\AddOns\\Details\\images\\small_icons", 1, 1, iconSize, iconSize, .75, 1, 0, 1) - GameCooltip:AddStatusBar (0, 1, .5, .5, .5, .5, false, {value = 100, color = {.5, .5, .5, 1}, specialSpark = false, texture = [[Interface\AddOns\Details\images\bar4_vidro]]}) - + GameCooltip:AddLine(deathTable [6] .. " " .. "died" , "-- -- -- ", 1, "white") + GameCooltip:AddIcon("Interface\\AddOns\\Details\\images\\small_icons", 1, 1, iconSize, iconSize, .75, 1, 0, 1) + GameCooltip:AddStatusBar(0, 1, .5, .5, .5, .5, false, {value = 100, color = {.5, .5, .5, 1}, specialSpark = false, texture = [[Interface\AddOns\Details\images\bar4_vidro]]}) + if (battleress) then - local nome_magia, _, icone_magia = _GetSpellInfo (battleress [2]) - GameCooltip:AddLine ("+" .. _cstr ("%.1f", battleress[4] - hora_da_morte) .. "s " .. nome_magia .. " (" .. battleress[6] .. ")", "", 1, "white") - GameCooltip:AddIcon ("Interface\\Glues\\CharacterSelect\\Glues-AddOn-Icons", 1, 1, nil, nil, .75, 1, 0, 1) - GameCooltip:AddStatusBar (0, 1, .5, .5, .5, .5, false, {value = 100, color = {.5, .5, .5, 1}, specialSpark = false, texture = [[Interface\AddOns\Details\images\bar4_vidro]]}) + local nome_magia, _, icone_magia = _GetSpellInfo(battleress [2]) + GameCooltip:AddLine("+" .. string.format("%.1f", battleress[4] - hora_da_morte) .. "s " .. nome_magia .. "(" .. battleress[6] .. ")", "", 1, "white") + GameCooltip:AddIcon("Interface\\Glues\\CharacterSelect\\Glues-AddOn-Icons", 1, 1, nil, nil, .75, 1, 0, 1) + GameCooltip:AddStatusBar(0, 1, .5, .5, .5, .5, false, {value = 100, color = {.5, .5, .5, 1}, specialSpark = false, texture = [[Interface\AddOns\Details\images\bar4_vidro]]}) end - + if (lastcooldown) then - if (lastcooldown[3] == 1) then - local nome_magia, _, icone_magia = _GetSpellInfo (lastcooldown [2]) - GameCooltip:AddLine (_cstr ("%.1f", lastcooldown[4] - hora_da_morte) .. "s " .. nome_magia .. " (" .. Loc ["STRING_LAST_COOLDOWN"] .. ")") - GameCooltip:AddIcon (icone_magia) + if (lastcooldown[3] == 1) then + local nome_magia, _, icone_magia = _GetSpellInfo(lastcooldown [2]) + GameCooltip:AddLine(string.format("%.1f", lastcooldown[4] - hora_da_morte) .. "s " .. nome_magia .. "(" .. Loc ["STRING_LAST_COOLDOWN"] .. ")") + GameCooltip:AddIcon(icone_magia) else - GameCooltip:AddLine (Loc ["STRING_NOLAST_COOLDOWN"]) - GameCooltip:AddIcon ([[Interface\CHARACTERFRAME\UI-Player-PlayTimeUnhealthy]], 1, 1, 18, 18) + GameCooltip:AddLine(Loc ["STRING_NOLAST_COOLDOWN"]) + GameCooltip:AddIcon([[Interface\CHARACTERFRAME\UI-Player-PlayTimeUnhealthy]], 1, 1, 18, 18) end - GameCooltip:AddStatusBar (0, 1, 1, 1, 1, 1, false, {value = 100, color = {.3, .3, .3, 1}, specialSpark = false, texture = [[Interface\AddOns\Details\images\bar_serenity]]}) + GameCooltip:AddStatusBar(0, 1, 1, 1, 1, 1, false, {value = 100, color = {.3, .3, .3, 1}, specialSpark = false, texture = [[Interface\AddOns\Details\images\bar_serenity]]}) end --death log cooltip settings - GameCooltip:SetOption ("StatusBarHeightMod", -6) - GameCooltip:SetOption ("FixedWidth", 400) - GameCooltip:SetOption ("TextSize", 10) - GameCooltip:SetOption ("LeftBorderSize", -4) - GameCooltip:SetOption ("RightBorderSize", 5) - GameCooltip:SetOption ("StatusBarTexture", [[Interface\AddOns\Details\images\bar_serenity]]) - GameCooltip:SetBackdrop (1, Details.cooltip_preset2_backdrop, bgColor, borderColor) - - GameCooltip:SetOwner (row, "bottomright", "bottomleft", -2, -50) + GameCooltip:SetOption("StatusBarHeightMod", -6) + GameCooltip:SetOption("FixedWidth", 400) + GameCooltip:SetOption("TextSize", 10) + GameCooltip:SetOption("LeftBorderSize", -4) + GameCooltip:SetOption("RightBorderSize", 5) + GameCooltip:SetOption("StatusBarTexture", [[Interface\AddOns\Details\images\bar_serenity]]) + GameCooltip:SetBackdrop(1, Details.cooltip_preset2_backdrop, bgColor, borderColor) + + GameCooltip:SetOwner(row, "bottomright", "bottomleft", -2, -50) row.OverlayTexture:Show() GameCooltip:ShowCooltip() end ---> custom tooltip for dispells details --------------------------------------------------------------------------------------------------------- -local function DispellInfo (dispell, barra) - - local jogadores = dispell [1] --> [nome od jogador] = total - local tabela_jogadores = {} - - for nome, tabela in _pairs (jogadores) do --> tabela = [1] total tomado [2] classe - tabela_jogadores [#tabela_jogadores + 1] = {nome, tabela [1], tabela [2]} - end - - _table_sort (tabela_jogadores, Details.Sort2) - - for index, tabela in _ipairs (tabela_jogadores) do - local coords = EncounterDetails.class_coords [tabela[3]] - if (not coords) then - GameCooltip:AddLine (EncounterDetails:GetOnlyName (tabela[1]), tabela[2], 1, "white", "orange") - GameCooltip:AddIcon ("Interface\\GossipFrame\\DailyActiveQuestIcon") - else - GameCooltip:AddLine (EncounterDetails:GetOnlyName (tabela[1]), tabela[2], 1, "white", "orange") - - local specID = Details:GetSpec (tabela[1]) - if (specID) then - local texture, l, r, t, b = Details:GetSpecIcon (specID, false) - GameCooltip:AddIcon (texture, 1, 1, EncounterDetails.CooltipLineHeight, EncounterDetails.CooltipLineHeight, l, r, t, b) - else - GameCooltip:AddIcon ("Interface\\AddOns\\Details\\images\\classes_small", nil, 1, EncounterDetails.CooltipLineHeight, EncounterDetails.CooltipLineHeight, (coords[1]), (coords[2]), (coords[3]), (coords[4])) - end - end - end - - local spellname = GetSpellInfo (barra.spellid) - if (spellname) then - GameTooltip:SetOwner (GameCooltipFrame1, "ANCHOR_NONE") - GameTooltip:SetSpellByID (barra.spellid) - GameTooltip:SetPoint ("topright", GameCooltipFrame1, "topleft", -2, 0) - GameTooltip:Show() - end -end +--custom tooltip for dispells details --------------------------------------------------------------------------------------------------------- ---> custom tooltip for kick details --------------------------------------------------------------------------------------------------------- -local function KickBy (magia, barra) +--custom tooltip for kick details --------------------------------------------------------------------------------------------------------- - local jogadores = magia [1] --> [nome od jogador] = total - local tabela_jogadores = {} - - for nome, tabela in _pairs (jogadores) do --> tabela = [1] total tomado [2] classe - tabela_jogadores [#tabela_jogadores + 1] = {nome, tabela [1], tabela [2]} - end - - _table_sort (tabela_jogadores, Details.Sort2) - - local spellName, _, spellIcon = GetSpellInfo (barra.lineText1:GetText()) - GameCooltip:AddLine (barra.lineText1:GetText()) - if (spellIcon) then - GameCooltip:AddIcon (spellIcon, nil, 1, EncounterDetails.CooltipLineHeight, EncounterDetails.CooltipLineHeight, 5/64, 59/64, 5/64, 59/64) - end - - for index, tabela in _ipairs (tabela_jogadores) do - local coords = EncounterDetails.class_coords [tabela[3]] - GameCooltip:AddLine (EncounterDetails:GetOnlyName (tabela[1]), tabela[2], 1, "white") - - local specID = Details:GetSpec (tabela[1]) - if (specID) then - local texture, l, r, t, b = Details:GetSpecIcon (specID, false) - GameCooltip:AddIcon (texture, 1, 1, EncounterDetails.CooltipLineHeight, EncounterDetails.CooltipLineHeight, l, r, t, b) - else - GameCooltip:AddIcon ("Interface\\AddOns\\Details\\images\\classes_small", nil, 1, EncounterDetails.CooltipLineHeight, EncounterDetails.CooltipLineHeight, (coords[1]), (coords[2]), (coords[3]), (coords[4])) - end - - GameCooltip:AddStatusBar (100, 1, .3, .3, .3, .3, false, false, false) - end - - local spellname = GetSpellInfo (barra.spellid) - if (spellname) then - GameTooltip:SetOwner (GameCooltipFrame1, "ANCHOR_NONE") - GameTooltip:SetSpellByID (barra.spellid) - GameTooltip:SetPoint ("topright", GameCooltipFrame1, "topleft", -2, 0) - GameTooltip:Show() - end -end ---> custom tooltip for enemy abilities details --------------------------------------------------------------------------------------------------------- +--custom tooltip clicks on any bar --------------------------------------------------------------------------------------------------------- +function Details:BossInfoRowClick(barra, param1) -local function EnemySkills (habilidade, barra) - --> barra.jogador agora tem a tabela com --> [1] total dano causado [2] jogadores que foram alvos [3] jogadores que castaram essa magia [4] ID da magia - - local total = habilidade [1] - local jogadores = habilidade [2] --> [nome od jogador] = total - - local tabela_jogadores = {} - local total = 0 - - for nome, tabela in _pairs (jogadores) do --> tabela = [1] total tomado [2] classe - tabela_jogadores [#tabela_jogadores + 1] = {nome, tabela[1], tabela[2]} - total = total + tabela[1] - end - - _table_sort (tabela_jogadores, Details.Sort2) - - GameCooltip:AddLine (barra.lineText1:GetText() .. " Damage Done") - - local ToK = Details.ToKFunctions [Details.ps_abbreviation] - - local topValue = tabela_jogadores [1] and tabela_jogadores [1][2] - - for index, tabela in _ipairs (tabela_jogadores) do - local coords = EncounterDetails.class_coords [tabela[3]] - - GameCooltip:AddLine (EncounterDetails:GetOnlyName (tabela[1]), ToK (_, tabela[2]) .. " (" .. format ("%.1f", tabela[2] / total * 100) .. "%)", 1, "white") - local r, g, b, a = unpack (Details.tooltip.background) - - local actorClass = Details:GetClass (tabela[1]) - if (actorClass) then - local r, g, b = Details:GetClassColor (actorClass) - GameCooltip:AddStatusBar (tabela[2] / topValue * 100, 1, r, g, b, EncounterDetailsFrame.CooltipStatusbarAlpha, false, {value = 100, color = {.21, .21, .21, 0.5}, texture = [[Interface\AddOns\Details\images\bar_serenity]]}) - else - GameCooltip:AddStatusBar (tabela[2] / topValue * 100, 1, r, g, b, a, false, {value = 100, color = {.21, .21, .21, 0.8}, texture = [[Interface\AddOns\Details\images\bar_serenity]]}) - end - - local specID = Details:GetSpec (tabela[1]) - if (specID) then - local texture, l, r, t, b = Details:GetSpecIcon (specID, false) - GameCooltip:AddIcon (texture, 1, 1, EncounterDetails.CooltipLineHeight - 0, EncounterDetails.CooltipLineHeight - 0, l, r, t, b) - else - if (coords) then - GameCooltip:AddIcon ("Interface\\AddOns\\Details\\images\\classes_small", nil, 1, EncounterDetails.CooltipLineHeight-2, EncounterDetails.CooltipLineHeight-2, (coords[1]), (coords[2]), (coords[3]), (coords[4])) - end - end - end - - local spellname = GetSpellInfo (barra.spellid) - if (spellname) then - GameTooltip:SetOwner (GameCooltipFrame1, "ANCHOR_NONE") - GameTooltip:SetSpellByID (barra.spellid) - GameTooltip:SetPoint ("right", barra, "left", -2, 0) - GameTooltip:Show() - end - - GameCooltip:SetOwner (barra, "left", "right", 2, 0) -end - ---> custom tooltip for damage taken details --------------------------------------------------------------------------------------------------------- - -local function DamageTakenDetails (jogador, barra) - - local agressores = jogador.damage_from - local damage_taken = jogador.damage_taken - - local showing = _combat_object [class_type_damage] --> o que esta sendo mostrado -> [1] - dano [2] - cura --> pega o container com ._NameIndexTable ._ActorTable - - local meus_agressores = {} - - for nome, _ in _pairs (agressores) do --> agressores seria a lista de nomes - local este_agressor = showing._ActorTable[showing._NameIndexTable[nome]] - if (este_agressor) then --> checagem por causa do total e do garbage collector que n�o limpa os nomes que deram dano - local habilidades = este_agressor.spells._ActorTable - for id, habilidade in _pairs (habilidades) do - local alvos = habilidade.targets - for target_name, amount in _pairs (alvos) do - if (target_name == jogador.nome) then - meus_agressores [#meus_agressores+1] = {id, amount, este_agressor.nome} - end - end - end - end - end - - _table_sort (meus_agressores, Details.Sort2) - - GameCooltip:AddLine (barra.lineText1:GetText() .. " Damage Taken") - - local max = #meus_agressores - if (max > 20) then - max = 20 - end - - local teve_melee = false - - local ToK = Details.ToKFunctions [Details.ps_abbreviation] - local topDamage = meus_agressores[1] and meus_agressores[1][2] - - for i = 1, max do - local nome_magia, _, icone_magia = _GetSpellInfo (meus_agressores[i][1]) - - if (meus_agressores[i][1] == 1) then - nome_magia = "*"..meus_agressores[i][3] - teve_melee = true - end - - GameCooltip:AddLine (nome_magia, ToK (_, meus_agressores[i][2]) .. " (".._cstr("%.1f", (meus_agressores[i][2]/damage_taken) * 100).."%)", 1, "white") - GameCooltip:AddStatusBar (meus_agressores[i][2] / topDamage * 100, 1, .55, .55, .55, .834, false, {value = 100, color = {.21, .21, .21, 0.8}, texture = [[Interface\AddOns\Details\images\bar_serenity]]}) - - GameCooltip:AddIcon (icone_magia, nil, 1, EncounterDetails.CooltipLineHeight - 0, EncounterDetails.CooltipLineHeight - 0, .1, .9, .1, .9) - end - - if (teve_melee) then - GameTooltip:AddLine ("* "..Loc ["STRING_MELEE_DAMAGE"], 0, 1, 0) - end - - GameCooltip:SetOwner (barra, "left", "right", 2, 0) -end - ---> custom tooltip clicks on any bar --------------------------------------------------------------------------------------------------------- -function Details:BossInfoRowClick (barra, param1) - - if (type (self) == "table") then + if (type(self) == "table") then barra, param1 = self, barra end - - if (type (param1) == "table") then + + if (type(param1) == "table") then barra = param1 end - + if (barra._no_report) then return end local reportar - - if (barra.TTT == "morte" or true) then --> deaths -- todos os boxes est�o usando cooltip, por isso o 'true'. - - reportar = {barra.report_text .. " " .. (barra.lineText1 and barra.lineText1:GetText() or barra:GetParent() and barra:GetParent().lineText1 and barra:GetParent().lineText1:GetText() or "")} + + if (barra.TTT == "morte" or true) then --deaths -- todos os boxes est�o usando cooltip, por isso o 'true'. + + reportar = {barra.report_text .. " " ..(barra.lineText1 and barra.lineText1:GetText() or barra:GetParent() and barra:GetParent().lineText1 and barra:GetParent().lineText1:GetText() or "")} local beginAt = 1 if (barra.TTT == "damage_taken" or barra.TTT == "habilidades_inimigas" or barra.TTT == "total_interrupt" or barra.TTT == "add") then beginAt = 2 end --"habilidades_inimigas" - for i = beginAt, GameCooltip:GetNumLines(), 1 do - local texto_left, texto_right = GameCooltip:GetText (i) + for i = beginAt, GameCooltip:GetNumLines(), 1 do + local texto_left, texto_right = GameCooltip:GetText(i) - if (texto_left and texto_right) then - texto_left = texto_left:gsub (("|T(.*)|t "), "") + if (texto_left and texto_right) then + texto_left = texto_left:gsub(("|T(.*)|t "), "") reportar [#reportar+1] = ""..texto_left.." "..texto_right.."" end end else - + barra.report_text = barra.report_text or "" reportar = {barra.report_text .. " " .. _G.GameTooltipTextLeft1:GetText()} - local numLines = _GameTooltip:NumLines() - - for i = 1, numLines, 1 do + local numLines = GameTooltip:NumLines() + + for i = 1, numLines, 1 do local nome_left = "GameTooltipTextLeft"..i local texto_left = _G[nome_left] texto_left = texto_left:GetText() - + local nome_right = "GameTooltipTextRight"..i local texto_right = _G[nome_right] texto_right = texto_right:GetText() - - if (texto_left and texto_right) then - texto_left = texto_left:gsub (("|T(.*)|t "), "") + + if (texto_left and texto_right) then + texto_left = texto_left:gsub(("|T(.*)|t "), "") reportar [#reportar+1] = ""..texto_left.." "..texto_right.."" end - end + end end - return Details:Reportar (reportar, {_no_current = true, _no_inverse = true, _custom = true}) - + return Details:Reportar(reportar, {_no_current = true, _no_inverse = true, _custom = true}) end ---> custom tooltip that handle mouse enter and leave on customized rows --------------------------------------------------------------------------------------------------------- +--custom tooltip that handle mouse enter and leave on customized rows --------------------------------------------------------------------------------------------------------- local backdrop_bar_onenter = {bgFile = [[Interface\AddOns\Details\images\background]], tile = true, tileSize = 16, edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border", edgeSize = 8, insets = {left = 1, right = 1, top = 0, bottom = 1}} local backdrop_bar_onleave = {bgFile = [[Interface\AddOns\Details\images\background]], tile = true, tileSize = 16, insets = {left = 1, right = 1, top = 0, bottom = 1}} -function EncounterDetails:SetRowScripts (barra, index, container) +function encounterDetails:SetRowScripts(barra, index, container) - barra:SetScript ("OnMouseDown", function (self) + barra:SetScript("OnMouseDown", function(self) if (self.fading_in) then return end - - self.mouse_down = _GetTime() - local x, y = _GetCursorPosition() - self.x = _math_floor (x) - self.y = _math_floor (y) + + self.mouse_down = GetTime() + local x, y = GetCursorPosition() + self.x = math.floor(x) + self.y = math.floor(y) --EncounterDetailsFrame:StartMoving() - EncounterDetailsFrame.isMoving = true - + edFrame.isMoving = true + end) - - barra:SetScript ("OnMouseUp", function (self) + + barra:SetScript("OnMouseUp", function(self) if (self.fading_in) then return end - - if (EncounterDetailsFrame.isMoving) then + + if (edFrame.isMoving) then --EncounterDetailsFrame:GetParent():StopMovingOrSizing() - EncounterDetailsFrame.isMoving = false - --instancia:SaveMainWindowPosition() --> precisa fazer algo pra salvar o trem + edFrame.isMoving = false + --instancia:SaveMainWindowPosition() --precisa fazer algo pra salvar o trem end - - local x, y = _GetCursorPosition() - x = _math_floor (x) - y = _math_floor (y) - - if ((self.mouse_down+0.4 > _GetTime() and (x == self.x and y == self.y)) or (x == self.x and y == self.y)) then - Details:BossInfoRowClick (self) + + local x, y = GetCursorPosition() + x = math.floor(x) + y = math.floor(y) + + if ((self.mouse_down+0.4 > GetTime() and(x == self.x and y == self.y)) or(x == self.x and y == self.y)) then + Details:BossInfoRowClick(self) end end) - - barra:SetScript ("OnEnter", --> MOUSE OVER - function (self) - --> aqui 1 + + barra:SetScript("OnEnter", --MOUSE OVER + function(self) + --aqui 1 if (container.fading_in or container.faded) then return end - + self.mouse_over = true - self:SetHeight (EncounterDetails.Frame.DefaultBarHeight + 1) - self:SetAlpha (1) - EncounterDetails.SetBarBackdrop_OnEnter (self) - - --GameTooltip:SetOwner (self, "ANCHOR_TOPRIGHT") - GameCooltip:Preset (2) - GameCooltip:SetOwner (self) - EncounterDetails:FormatCooltipSettings() - - if (not self.TTT) then --> tool tip type + self:SetHeight(encounterDetails.Frame.DefaultBarHeight + 1) + self:SetAlpha(1) + encounterDetails.SetBarBackdrop_OnEnter(self) + + --GameTooltip:SetOwner(self, "ANCHOR_TOPRIGHT") + GameCooltip:Preset(2) + GameCooltip:SetOwner(self) + encounterDetails:FormatCooltipSettings() + + if (not self.TTT) then --tool tip type return end - - if (self.TTT == "damage_taken") then --> damage taken - DamageTakenDetails (self.jogador, barra) - - elseif (self.TTT == "habilidades_inimigas") then --> enemy abilytes + + if (self.TTT == "damage_taken") then --damage taken + DamageTakenDetails(self.jogador, barra) + + elseif (self.TTT == "habilidades_inimigas") then --enemy abilytes self.spellid = self.jogador [4] - EnemySkills (self.jogador, self) - + EnemySkills(self.jogador, self) + elseif (self.TTT == "total_interrupt") then self.spellid = self.jogador [3] - KickBy (self.jogador, self) - + KickBy(self.jogador, self) + elseif (self.TTT == "dispell") then self.spellid = self.jogador [3] - DispellInfo (self.jogador, self) - - elseif (self.TTT == "morte") then --> deaths - KillInfo (self.jogador, self) --> aqui 2 + DispellInfo(self.jogador, self) + + elseif (self.TTT == "morte") then --deaths + KillInfo(self.jogador, self) --aqui 2 end - + GameCooltip:Show() end) - - barra:SetScript ("OnLeave", --> MOUSE OUT - function (self) - - self:SetScript ("OnUpdate", nil) - + + barra:SetScript("OnLeave", --MOUSE OUT + function(self) + + self:SetScript("OnUpdate", nil) + if (self.fading_in or self.faded or not self:IsShown() or self.hidden) then return end - - self:SetHeight (EncounterDetails.Frame.DefaultBarHeight) - self:SetAlpha (0.9) - EncounterDetails.SetBarBackdrop_OnLeave (self) - + self:SetHeight(encounterDetails.Frame.DefaultBarHeight) + self:SetAlpha(0.9) + + encounterDetails.SetBarBackdrop_OnLeave(self) + GameTooltip:Hide() GameCooltip:Hide() - + if (self.OverlayTexture) then self.OverlayTexture:Hide() end end) end ---> Here start the data mine --------------------------------------------------------------------------------------------------------- -function EncounterDetails:OpenAndRefresh (_, segment) - - local frame = EncounterDetailsFrame --alias +--Here start the data mine --------------------------------------------------------------------------------------------------------- +function encounterDetails:OpenAndRefresh(_, segment) + local segmentsDropdown = _G[edFrame:GetName() .. "SegmentsDropdown"] + segmentsDropdown.MyObject:Refresh() + encounterDetails.LastOpenedTime = GetTime() + segmentsDropdown.MyObject:Refresh() - DebugMessage ("OpenAndRefresh() called") - _G [frame:GetName().."SegmentsDropdown"].MyObject:Refresh() - - EncounterDetails.LastOpenedTime = GetTime() - - _G [frame:GetName().."SegmentsDropdown"].MyObject:Refresh() - - EncounterDetailsFrame.ShowType = EncounterDetails.db.last_section_selected + edFrame.ShowType = encounterDetails.db.last_section_selected if (segment) then - _combat_object = EncounterDetails:GetCombat (segment) - EncounterDetails._segment = segment - - DebugMessage ("there's a segment to use:", segment, _combat_object, _combat_object and _combat_object.is_boss) - + _combat_object = encounterDetails:GetCombat(segment) + encounterDetails._segment = segment + DebugMessage("there's a segment to use:", segment, _combat_object, _combat_object and _combat_object.is_boss) + else - DebugMessage ("no segment has been passed, looping segments to find one.") - - local historico = Details.tabela_historico.tabelas + DebugMessage("no segment has been passed, looping segments to find one.") + local segmentsTable = Details:GetCombatSegments() local foundABoss = false - - for index, combate in ipairs (historico) do - if (combate.is_boss and combate.is_boss.index) then - EncounterDetails._segment = index - _combat_object = combate - - DebugMessage ("segment found: ", index, combate:GetCombatName(), combate.is_trash) + + for index, combatObject in ipairs(segmentsTable) do + if (combatObject.is_boss and combatObject.is_boss.index) then + encounterDetails._segment = index + _combat_object = combatObject + + DebugMessage("segment found: ", index, combatObject:GetCombatName(), combatObject.is_trash) --the first segment found here will be the first segment the dropdown found, so it can use the index 1 of the dropdown list - _G [frame:GetName().."SegmentsDropdown"].MyObject:Select (1, true) - - foundABoss = index + _G [edFrame:GetName().."SegmentsDropdown"].MyObject:Select(1, true) + + foundABoss = true break end end - + if (not foundABoss) then - DebugMessage ("boss not found during the segment loop") + DebugMessage("boss not found during the segment loop") end end - + if (not _combat_object) then - --EncounterDetails:Msg ("no combat found.") - DebugMessage ("_combat_object is nil, EXIT") + --EncounterDetails:Msg("no combat found.") + DebugMessage("_combat_object is nil, EXIT") return end - - local boss_id - local map_id - local boss_info - - local ToK = Details.ToKFunctions [Details.ps_abbreviation] - - if (EncounterDetails.debugmode and not _combat_object.is_boss) then - _combat_object.is_boss = { - index = 1, - name = "Immerseus", - zone = "Siege of Orggrimar", - mapid = 1136, - encounter = "Immerseus" - } - end - + if (not _combat_object.is_boss) then - - DebugMessage ("_combat_object is not a boss, trying another loop in the segments") - + DebugMessage("_combat_object is not a boss, trying another loop in the segments") + local foundSegment - for index, combat in _ipairs (EncounterDetails:GetCombatSegments()) do - - if (combat.is_boss and EncounterDetails:GetBossDetails (combat.is_boss.mapid, combat.is_boss.index)) then + for index, combat in ipairs(encounterDetails:GetCombatSegments()) do + if (combat.is_boss and encounterDetails:GetBossDetails(combat.is_boss.mapid, combat.is_boss.index)) then _combat_object = combat - + --the first segment found here will be the first segment the dropdown found, so it can use the index 1 of the dropdown list - _G [frame:GetName().."SegmentsDropdown"].MyObject:Select (1, true) - - DebugMessage ("found another segment during another loop", index, combat:GetCombatName(), combat.is_trash) + _G [edFrame:GetName() .. "SegmentsDropdown"].MyObject:Select(1, true) + + DebugMessage("found another segment during another loop", index, combat:GetCombatName(), combat.is_trash) foundSegment = true break end end - + if (not foundSegment) then - DebugMessage ("boss not found during the second loop segment") + DebugMessage("boss not found during the second loop segment") end - + if (not _combat_object.is_boss) then - DebugMessage ("_combat_object still isn't a boss segment, trying to get the last segment shown.") - if (EncounterDetails.LastSegmentShown) then - _combat_object = EncounterDetails.LastSegmentShown - DebugMessage ("found the last segment shown, using it.") + DebugMessage("_combat_object still isn't a boss segment, trying to get the last segment shown.") + if (encounterDetails.LastSegmentShown) then + _combat_object = encounterDetails.LastSegmentShown + DebugMessage("found the last segment shown, using it.") else - DebugMessage ("the segment isn't a boss, EXIT.") + DebugMessage("the segment isn't a boss, EXIT.") return end end end - - --> the segment is a boss - - boss_id = _combat_object.is_boss.index - map_id = _combat_object.is_boss.mapid - boss_info = Details:GetBossDetails (_combat_object.is_boss.mapid, _combat_object.is_boss.index) - - EncounterDetails.Frame.switch(EncounterDetailsFrame.ShowType) - if (EncounterDetailsFrame.ShowType == "phases") then - EncounterDetailsPhaseFrame.OnSelectPhase (1) - - elseif (EncounterDetailsFrame.ShowType == "graph") then - EncounterDetails:BuildDpsGraphic() - - elseif (EncounterDetailsFrame.ShowType == "spellsauras") then - --refresh spells and auras - --EncounterDetails.SpellScrollframe:Refresh() - EncounterDetails.update_enemy_spells() - EncounterDetails.update_bossmods() + encounterDetails.LastSegmentShown = _combat_object + + encounterDetails.Frame.switch(edFrame.ShowType) + + if (edFrame.ShowType == "phases") then + EncounterDetailsPhaseFrame.OnSelectPhase(1) + + elseif (edFrame.ShowType == "graph") then + encounterDetails:ShowChartFrame() end - EncounterDetails.LastSegmentShown = _combat_object - -------------- set boss name and zone name -------------- - EncounterDetailsFrame.boss_name:SetText (_combat_object.is_boss.encounter) - EncounterDetailsFrame.raid_name:SetText (_combat_object.is_boss.zone) + edFrame.bossNameLabel:SetText(_combat_object.is_boss.encounter) + edFrame.raidNameLabel:SetText(_combat_object.is_boss.zone) --------------- set portrait and background image -------------- +-------------- set portrait and background image -------------- local mapID = _combat_object.is_boss.mapid - local L, R, T, B, Texture = EncounterDetails:GetBossIcon (mapID, _combat_object.is_boss.index) - + local L, R, T, B, Texture = encounterDetails:GetBossIcon(mapID, _combat_object.is_boss.index) + if (L) then - EncounterDetailsFrame.boss_icone:SetTexture (Texture) - EncounterDetailsFrame.boss_icone:SetTexCoord (L, R, T, B) + edFrame.bossIcon:SetTexture(Texture) + edFrame.bossIcon:SetTexCoord(L, R, T, B) else - EncounterDetailsFrame.boss_icone:SetTexture ([[Interface\CHARACTERFRAME\TempPortrait]]) - EncounterDetailsFrame.boss_icone:SetTexCoord (0, 1, 0, 1) + edFrame.bossIcon:SetTexture([[Interface\CHARACTERFRAME\TempPortrait]]) + edFrame.bossIcon:SetTexCoord(0, 1, 0, 1) end - + --[=[ - local file, L, R, T, B = EncounterDetails:GetRaidBackground (_combat_object.is_boss.mapid) + local file, L, R, T, B = EncounterDetails:GetRaidBackground(_combat_object.is_boss.mapid) if (file) then - EncounterDetailsFrame.raidbackground:SetTexture (file) - EncounterDetailsFrame.raidbackground:SetTexCoord (L, R, T, B) + edFrame.raidBackgroundTexture:SetTexture(file) + edFrame.raidBackgroundTexture:SetTexCoord(L, R, T, B) else - EncounterDetailsFrame.raidbackground:SetTexture ([[Interface\Glues\LOADINGSCREENS\LoadScreenDungeon]]) - EncounterDetailsFrame.raidbackground:SetTexCoord (0, 1, 120/512, 408/512) + edFrame.raidBackgroundTexture:SetTexture([[Interface\Glues\LOADINGSCREENS\LoadScreenDungeon]]) + edFrame.raidBackgroundTexture:SetTexCoord(0, 1, 120/512, 408/512) end --]=] - - EncounterDetailsFrame.raidbackground:SetTexture (.3, .3, .3, .5) - --------------- set totals on down frame -------------- ---[[ data mine: - _combat_object ["totals_grupo"] hold the total [1] damage // [2] heal // [3] [energy_name] energies // [4] [misc_name] miscs --]] - --> Container Overall Damage Taken ~damagetaken ~damage taken - --[[ data mine: - combat tables have 4 containers [1] damage [2] heal [3] energy [4] misc each container have 2 tables: ._NameIndexTable and ._ActorTable --]] - local DamageContainer = _combat_object [class_type_damage] - - local damage_taken = Details.atributo_damage:RefreshWindow ({}, _combat_object, _, { key = "damage_taken", modo = Details.modos.group }) - - local container = frame.overall_damagetaken.gump - - local quantidade = 0 - local dano_do_primeiro = 0 - - for index, jogador in _ipairs (DamageContainer._ActorTable) do - --> ta em ordem de quem tomou mais dano. - - if (not jogador.grupo) then --> s� aparecer nego da raid - break - end - - if (jogador.classe and jogador.classe ~= "UNGROUPPLAYER" and jogador.classe ~= "UNKNOW") then - local barra = container.barras [index] - if (not barra) then - barra = EncounterDetails:CreateRow (index, container, 1, 0, -1) - Details:SetFontSize (barra.lineText1, CONST_FONT_SIZE) - Details:SetFontSize (barra.lineText4, CONST_FONT_SIZE) - barra.TTT = "damage_taken" -- tool tip type --> damage taken - barra.report_text = Loc ["STRING_PLUGIN_NAME"].."! "..Loc ["STRING_DAMAGE_TAKEN_REPORT"] - end - - if (jogador.nome:find ("-")) then - barra.lineText1:SetText (jogador.nome:gsub (("-.*"), "")) - else - barra.lineText1:SetText (jogador.nome) - end - - barra.lineText4:SetText (ToK (_, jogador.damage_taken)) - - Details:name_space (barra) - - barra.jogador = jogador - - barra.textura:SetStatusBarColor (_unpack (Details.class_colors [jogador.classe])) - - if (index == 1) then - barra.textura:SetValue (100) - dano_do_primeiro = jogador.damage_taken - else - barra.textura:SetValue (jogador.damage_taken/dano_do_primeiro *100) - end - - local specID = Details:GetSpec (jogador.nome) - if (specID) then - local texture, l, r, t, b = Details:GetSpecIcon (specID, false) - barra.icone:SetTexture (texture) - barra.icone:SetTexCoord (l, r, t, b) - else - barra.icone:SetTexture ("Interface\\AddOns\\Details\\images\\classes_small") - if (EncounterDetails.class_coords [jogador.classe]) then - barra.icone:SetTexCoord (_unpack (EncounterDetails.class_coords [jogador.classe])) - end - end - - barra:Show() - quantidade = quantidade + 1 - end - end - - EncounterDetails:JB_AtualizaContainer (container, quantidade) - - if (quantidade < #container.barras) then - for i = quantidade+1, #container.barras, 1 do - - if (barra) then - barra:Hide() - end - end - end - - --> Fim do container Overall Damage Taken - - --> Container Overall Habilidades Inimigas ~damage taken by spell - local habilidades_poll = {} - - --> pega as magias cont�nuas presentes em todas as fases - --deprecated - if (boss_info and boss_info.continuo) then - for index, spellid in _ipairs (boss_info.continuo) do - habilidades_poll [spellid] = true - end - end - - --> pega as habilidades que pertence especificamente a cada fase - --deprecated - if (boss_info and boss_info.phases) then - for fase_id, fase in _ipairs (boss_info.phases) do - if (fase.spells) then - for index, spellid in _ipairs (fase.spells) do - habilidades_poll [spellid] = true - end - end - end - end - - local habilidades_usadas = {} - local have_pool = false - for spellid, _ in _pairs (habilidades_poll) do - have_pool = true - break - end - - for index, jogador in _ipairs (DamageContainer._ActorTable) do - - --> get all spells from neutral and hostile npcs - if ( - _bit_band (jogador.flag_original, 0x00000060) ~= 0 and --is neutral or hostile - (not jogador.owner or (_bit_band (jogador.owner.flag_original, 0x00000060) ~= 0 and not jogador.owner.grupo and _bit_band (jogador.owner.flag_original, 0x00000400) == 0)) and --isn't a pet or the owner isn't a player - not jogador.grupo and - _bit_band (jogador.flag_original, 0x00000400) == 0 - ) then - - local habilidades = jogador.spells._ActorTable - - for id, habilidade in _pairs (habilidades) do - --if (habilidades_poll [id]) then - --> esse jogador usou uma habilidade do boss - local esta_habilidade = habilidades_usadas [id] --> tabela n�o numerica, pq diferentes monstros podem castar a mesma magia - if (not esta_habilidade) then - esta_habilidade = {0, {}, {}, id} --> [1] total dano causado [2] jogadores que foram alvos [3] jogadores que castaram essa magia [4] ID da magia - habilidades_usadas [id] = esta_habilidade - end - - --> adiciona ao [1] total de dano que esta habilidade causou - esta_habilidade[1] = esta_habilidade[1] + habilidade.total - - --> adiciona ao [3] total do jogador que castou - if (not esta_habilidade[3][jogador.nome]) then - esta_habilidade[3][jogador.nome] = 0 - end - - esta_habilidade[3][jogador.nome] = esta_habilidade[3][jogador.nome] + habilidade.total - - --> pega os alvos e adiciona ao [2] - local alvos = habilidade.targets - for target_name, amount in _pairs (alvos) do - - --> ele tem o nome do jogador, vamos ver se este alvo � realmente um jogador verificando na tabela do combate - local tabela_dano_do_jogador = DamageContainer._ActorTable [DamageContainer._NameIndexTable [target_name]] - if (tabela_dano_do_jogador and tabela_dano_do_jogador.grupo) then - if (not esta_habilidade[2] [target_name]) then - esta_habilidade[2] [target_name] = {0, tabela_dano_do_jogador.classe} - end - esta_habilidade[2] [target_name] [1] = esta_habilidade[2] [target_name] [1] + amount - end - end - --end - end - - elseif (have_pool) then - --> check if the spell id is in the spell poll. - local habilidades = jogador.spells._ActorTable - - for id, habilidade in _pairs (habilidades) do - if (habilidades_poll [id]) then - --> esse jogador usou uma habilidade do boss - local esta_habilidade = habilidades_usadas [id] --> tabela n�o numerica, pq diferentes monstros podem castar a mesma magia - if (not esta_habilidade) then - esta_habilidade = {0, {}, {}, id} --> [1] total dano causado [2] jogadores que foram alvos [3] jogadores que castaram essa magia [4] ID da magia - habilidades_usadas [id] = esta_habilidade - end - - --> adiciona ao [1] total de dano que esta habilidade causou - esta_habilidade[1] = esta_habilidade[1] + habilidade.total - - --> adiciona ao [3] total do jogador que castou - if (not esta_habilidade[3][jogador.nome]) then - esta_habilidade[3][jogador.nome] = 0 - end - - esta_habilidade[3][jogador.nome] = esta_habilidade[3][jogador.nome] + habilidade.total - - --> pega os alvos e adiciona ao [2] - local alvos = habilidade.targets - for target_name, amount in _pairs (alvos) do - - --> ele tem o nome do jogador, vamos ver se este alvo � realmente um jogador verificando na tabela do combate - local tabela_dano_do_jogador = DamageContainer._ActorTable [DamageContainer._NameIndexTable [target_name]] - if (tabela_dano_do_jogador and tabela_dano_do_jogador.grupo) then - if (not esta_habilidade[2] [target_name]) then - esta_habilidade[2] [target_name] = {0, tabela_dano_do_jogador.classe} - end - esta_habilidade[2] [target_name] [1] = esta_habilidade[2] [target_name] [1] + amount - end - end - end - end - end - end - - --> por em ordem - local tabela_em_ordem = {} - local jaFoi = {} - - for id, tabela in _pairs (habilidades_usadas) do - local spellname = Details.GetSpellInfo(tabela [4]) - - if (not jaFoi [spellname]) then - tabela [5] = spellname - tabela_em_ordem [#tabela_em_ordem+1] = tabela - jaFoi [spellname] = #tabela_em_ordem - else - local index = jaFoi [spellname] - tabela_em_ordem [index] [1] = tabela_em_ordem [index] [1] + tabela [1] - - local tt = tabela_em_ordem [index] [2] -- tabela com [PlayerName] = {amount, class} - - for playerName, t in pairs (tabela [2]) do - local amount, class = unpack (t) - if (tt [playerName]) then - tt [playerName][1] = tt [playerName][1] + amount - else - tt [playerName] = {amount, class} - end - end - end - end - - _table_sort (tabela_em_ordem, Details.Sort1) - - container = frame.overall_habilidades.gump - quantidade = 0 - dano_do_primeiro = 0 - - --> mostra o resultado nas barras - for index, habilidade in _ipairs (tabela_em_ordem) do - --> ta em ordem das habilidades que deram mais dano - - if (habilidade[1] > 0) then - - local barra = container.barras [index] - if (not barra) then - barra = EncounterDetails:CreateRow (index, container, 1, 0, -1) - barra.TTT = "habilidades_inimigas" -- tool tip type --enemy abilities - barra.report_text = Loc ["STRING_PLUGIN_NAME"].."! " .. Loc ["STRING_ABILITY_DAMAGE"] - Details:SetFontSize (barra.lineText1, CONST_FONT_SIZE) - Details:SetFontSize (barra.lineText4, CONST_FONT_SIZE) - barra.t:SetVertexColor (1, .8, .8, .8) - end - - local nome_magia, _, icone_magia = _GetSpellInfo (habilidade[4]) - - barra.lineText1:SetText (nome_magia) -- .. " (|cFFa0a0a0" .. habilidade[4] .. "|r) - barra.lineText4:SetText (ToK (_, habilidade[1])) - - Details:name_space (barra) - - barra.jogador = habilidade --> barra.jogador agora tem a tabela com --> [1] total dano causado [2] jogadores que foram alvos [3] jogadores que castaram essa magia [4] ID da magia - - local spellSchool = Details.spell_school_cache [nome_magia] or 1 - local r, g, b = Details:GetSpellSchoolColor (spellSchool) - - barra.t:SetVertexColor (r, g, b) - - if (index == 1) then - barra.textura:SetValue (100) - dano_do_primeiro = habilidade[1] - else - barra.textura:SetValue (habilidade[1]/dano_do_primeiro *100) - end - - barra.icone:SetTexture (icone_magia) - barra.icone:SetTexCoord (.1, .9, .1, .9) - - barra:Show() - quantidade = quantidade + 1 - - end - end - - EncounterDetails:JB_AtualizaContainer (container, quantidade) - - if (quantidade < #container.barras) then - for i = quantidade+1, #container.barras, 1 do - container.barras [i]:Hide() - end - end - - --> Fim do container Over Habilidades Inimigas - - --> Identificar os ADDs da luta: - - --> declara a pool onde ser�o armazenados os adds existentas na luta - local adds_pool = {} - - --> pega as habilidades que pertence especificamente a cada fase - - if (boss_info and boss_info.phases) then - for fase_id, fase in _ipairs (boss_info.phases) do - if (fase.adds) then - for index, addId in _ipairs (fase.adds) do - adds_pool [addId] = true - end - end - end - end - - --> agora ja tenho a lista de todos os adds da luta - -- vasculhar o container de dano e achar os adds: - -- ~add - - local adds = {} - - for index, jogador in _ipairs (DamageContainer._ActorTable) do - - --> s� estou interessado nos adds, conferir pelo nome - if (adds_pool [Details:GetNpcIdFromGuid (jogador.serial)] or ( - jogador.flag_original and - bit.band (jogador.flag_original, 0x00000060) ~= 0 and - (not jogador.owner or (_bit_band (jogador.owner.flag_original, 0x00000060) ~= 0 and not jogador.owner.grupo and _bit_band (jogador.owner.flag_original, 0x00000400) == 0)) and --isn't a pet or the owner isn't a player - not jogador.grupo and - _bit_band (jogador.flag_original, 0x00000400) == 0 - )) then --> � um inimigo ou neutro - - local nome = jogador.nome - - if (not nome:find ("%*")) then - local tabela = {nome = nome, total = 0, dano_em = {}, dano_em_total = 0, damage_from = {}, damage_from_total = 0} - - --> total de dano que ele causou - tabela.total = jogador.total - - --> em quem ele deu dano - for target_name, amount in _pairs (jogador.targets) do - local este_jogador = _combat_object (1, target_name) - if (este_jogador) then - if (este_jogador.classe ~= "PET" and este_jogador.classe ~= "UNGROUPPLAYER" and este_jogador.classe ~= "UNKNOW") then - tabela.dano_em [#tabela.dano_em +1] = {target_name, amount, este_jogador.classe} - tabela.dano_em_total = tabela.dano_em_total + amount - end - end - end - _table_sort (tabela.dano_em, Details.Sort2) - - --> quem deu dano nele - for agressor, _ in _pairs (jogador.damage_from) do - --local este_jogador = DamageContainer._ActorTable [DamageContainer._NameIndexTable [agressor]] - local este_jogador = _combat_object (1, agressor) - if (este_jogador and este_jogador:IsPlayer()) then - for target_name, amount in _pairs (este_jogador.targets) do - if (target_name == nome) then - tabela.damage_from [#tabela.damage_from+1] = {agressor, amount, este_jogador.classe} - tabela.damage_from_total = tabela.damage_from_total + amount - end - end - end - end - - _table_sort (tabela.damage_from, sort_damage_from) - - tabela [1] = tabela.damage_from_total - tinsert (adds, tabela) - end - end - - end - - --> montou a tabela, agora precisa mostrar no painel - - local function _DanoFeito (self) - self.textura:SetBlendMode ("ADD") - - local barra = self:GetParent() - local tabela = barra.jogador - local dano_em = tabela.dano_em - - GameCooltip:Preset (2) - GameCooltip:SetOwner (self) - - EncounterDetails:FormatCooltipSettings() - - GameCooltip:AddLine (barra.lineText1:GetText().." ".. "Damage Done") - - local topDamage = dano_em[1] and dano_em[1][2] - - local dano_em_total = tabela.dano_em_total - for _, esta_tabela in _pairs (dano_em) do - local coords = EncounterDetails.class_coords [esta_tabela[3]] - GameCooltip:AddLine (EncounterDetails:GetOnlyName (esta_tabela[1]), Details:ToK (esta_tabela[2]).." (".. _cstr ("%.1f", esta_tabela[2]/dano_em_total*100) .."%)", 1, "white", "orange") - - local specID = Details:GetSpec (esta_tabela[1]) - if (specID) then - local texture, l, r, t, b = Details:GetSpecIcon (specID, false) - GameCooltip:AddIcon (texture, 1, 1, EncounterDetails.CooltipLineHeight, EncounterDetails.CooltipLineHeight, l, r, t, b) - else - GameCooltip:AddIcon ([[Interface\AddOns\Details\images\classes_small]], 1, 1, EncounterDetails.CooltipLineHeight, EncounterDetails.CooltipLineHeight, (coords[1]), (coords[2]), (coords[3]), (coords[4])) - end - - local actorClass = Details:GetClass (esta_tabela[1]) - if (actorClass) then - local r, g, b = Details:GetClassColor (actorClass) - GameCooltip:AddStatusBar (esta_tabela[2] / topDamage * 100, 1, r, g, b, EncounterDetailsFrame.CooltipStatusbarAlpha, false, {value = 100, color = {.21, .21, .21, 0.5}, texture = [[Interface\AddOns\Details\images\bar_serenity]]}) - else - GameCooltip:AddStatusBar (esta_tabela[2] / topDamage * 100, 1, .3, .3, .3, .3, false, {value = 100, color = {.21, .21, .21, 0.8}, texture = [[Interface\AddOns\Details\images\bar_serenity]]}) - end - end - - self.textura:SetBlendMode ("ADD") - self.textura:SetSize (18, 18) - self.ArrowOnEnter = true - GameCooltip:SetOwner (self, "right", "left", -10, 0) - - GameCooltip:AddLine (" ") - GameCooltip:AddLine ("CLICK to Report") - GameCooltip:Show() - end - - local function _DanoRecebido (self) - - local barra = self - local tabela = barra.jogador - local damage_from = tabela.damage_from - - GameCooltip:Preset (2) - GameCooltip:SetOwner (self) - - EncounterDetails:FormatCooltipSettings() - - GameCooltip:AddLine (barra.lineText1:GetText().." "..Loc ["STRING_DAMAGE_TAKEN"]) - - local damage_from_total = tabela.damage_from_total - local topDamage = damage_from[1] and damage_from[1][2] - - for _, esta_tabela in _pairs (damage_from) do - - local coords = EncounterDetails.class_coords [esta_tabela[3]] - if (coords) then - GameCooltip:AddLine (EncounterDetails:GetOnlyName (esta_tabela[1]), Details:ToK (esta_tabela[2]).." (".. _cstr ("%.1f", esta_tabela[2]/damage_from_total*100) .."%)", 1, "white", "orange", nil, nil, "MONOCHRONE") - - local specID = Details:GetSpec (esta_tabela[1]) - if (specID) then - local texture, l, r, t, b = Details:GetSpecIcon (specID, false) - GameCooltip:AddIcon (texture, 1, 1, EncounterDetails.CooltipLineHeight, EncounterDetails.CooltipLineHeight, l, r, t, b) - else - GameCooltip:AddIcon ([[Interface\AddOns\Details\images\classes_small]], 1, 1, EncounterDetails.CooltipLineHeight, EncounterDetails.CooltipLineHeight, (coords[1]), (coords[2]), (coords[3]), (coords[4])) - end - - local actorClass = Details:GetClass (esta_tabela[1]) - if (actorClass) then - local r, g, b = Details:GetClassColor (actorClass) - GameCooltip:AddStatusBar (esta_tabela[2] / topDamage * 100, 1, r, g, b, EncounterDetailsFrame.CooltipStatusbarAlpha, false, {value = 100, color = {.21, .21, .21, 0.5}, texture = [[Interface\AddOns\Details\images\bar_serenity]]}) - else - GameCooltip:AddStatusBar (esta_tabela[2] / topDamage * 100, 1, .3, .3, .3, .3, false, {value = 100, color = {.21, .21, .21, 0.8}, texture = [[Interface\AddOns\Details\images\bar_serenity]]}) - end - else - GameCooltip:AddLine (esta_tabela[1], Details:ToK (esta_tabela[2]).." (".. _cstr ("%.1f", esta_tabela[2]/damage_from_total*100) .."%)") - GameCooltip:AddStatusBar (esta_tabela[2] / topDamage * 100, 1, .3, .3, .3, .3, false, {value = 100, color = {.21, .21, .21, 0.8}, texture = [[Interface\AddOns\Details\images\bar_serenity]]}) - end - end - - self.mouse_over = true - self:SetHeight (EncounterDetails.Frame.DefaultBarHeight + 1) - self:SetAlpha (1) - EncounterDetails.SetBarBackdrop_OnEnter (self) - - GameCooltip:AddLine (" ") - GameCooltip:AddLine ("CLICK to Report") - - GameCooltip:SetOwner (self, "left", "right", -60, 0) - GameCooltip:Show() - end - - local function _OnHide (self) - GameCooltip:Hide() - - if (self.ArrowOnEnter) then - self.textura:SetBlendMode ("BLEND") - self.textura:SetSize (16, 16) - else - self:SetAlpha (0.9) - self:SetHeight (EncounterDetails.Frame.DefaultBarHeight) - EncounterDetails.SetBarBackdrop_OnLeave (self) - end - end - - local y = 10 - local frame_adds = EncounterDetailsFrame.overall_adds - container = frame_adds.gump - local index = 1 - quantidade = 0 - - --table.sort (adds, sort_by_name) - table.sort (adds, Details.Sort1) - - for index, esta_tabela in _ipairs (adds) do - - local addName = esta_tabela.nome - local barra = container.barras [index] - - if (not barra) then - barra = EncounterDetails:CreateRow (index, container, -0) - - barra:SetWidth (155) - - barra:SetScript ("OnEnter", _DanoRecebido) - barra:SetScript ("OnLeave", _OnHide) - barra:HookScript ("OnMouseDown", EncounterDetails.BossInfoRowClick) - - local add_damage_done = _CreateFrame ("Button", nil, barra, "BackdropTemplate") - barra.report_text = "Details! Damage Taken of " - add_damage_done.report_text = "Details! Damage Done of " - add_damage_done.barra = barra - add_damage_done:SetWidth (EncounterDetails.CooltipLineHeight) - add_damage_done:SetHeight (EncounterDetails.CooltipLineHeight) - add_damage_done:EnableMouse (true) - add_damage_done:SetResizable (false) - add_damage_done:SetPoint ("left", barra, "left", 0, 0) - - add_damage_done:SetBackdrop ({bgFile = [[Interface\AddOns\Details\images\background]], tile = true, tileSize = 16}) - add_damage_done:SetBackdropColor (.5, .0, .0, 0.5) - - add_damage_done.textura = add_damage_done:CreateTexture (nil, "overlay") - add_damage_done.textura:SetTexture ("Interface\\Buttons\\UI-MicroStream-Red") - add_damage_done.textura:SetWidth (16) - add_damage_done.textura:SetHeight (16) - add_damage_done.textura:SetPoint ("topleft", add_damage_done, "topleft") - - add_damage_done:SetScript ("OnEnter", _DanoFeito) - add_damage_done:SetScript ("OnLeave", _OnHide) - add_damage_done:SetScript ("OnClick", EncounterDetails.BossInfoRowClick) - - barra.lineText1:SetPoint ("left", add_damage_done, "right", 2, 0) - barra.textura:SetStatusBarTexture("") - - Details:SetFontSize (barra.lineText1, CONST_FONT_SIZE) - Details:SetFontSize (barra.lineText4, CONST_FONT_SIZE) - - barra.TTT = "add" - add_damage_done.TTT = "add" - end - - barra.lineText1:SetText (addName) - barra.lineText4:SetText (Details:ToK (esta_tabela.damage_from_total)) - barra.lineText1:SetSize (barra:GetWidth() - barra.lineText4:GetStringWidth() - 34, 15) - - barra.jogador = esta_tabela --> barra.jogador agora tem a tabela com --> [1] total dano causado [2] jogadores que foram alvos [3] jogadores que castaram essa magia [4] ID da magia - - --barra.textura:SetStatusBarColor (_unpack (_detalhes.class_colors [jogador.classe])) - barra.textura:SetStatusBarColor (1, 1, 1, 1) --> a cor pode ser a spell school da magia - barra.textura:SetValue (100) - - barra:Show() - quantidade = quantidade + 1 - index = index +1 - end - - EncounterDetails:JB_AtualizaContainer (container, quantidade, 4) - - if (quantidade < #container.barras) then - for i = quantidade+1, #container.barras, 1 do - container.barras [i]:Hide() - end - end - - --> Fim do container Over ADDS - - --> Inicio do Container de Interrupts: - - local misc = _combat_object [class_type_misc] - - local total_interrompido = Details.atributo_misc:RefreshWindow ({}, _combat_object, _, { key = "interrupt", modo = Details.modos.group }) - - local frame_interrupts = EncounterDetailsFrame.overall_interrupt - container = frame_interrupts.gump - - quantidade = 0 - local interrupt_do_primeiro = 0 - - local habilidades_interrompidas = {} - - for index, jogador in _ipairs (misc._ActorTable) do - if (not jogador.grupo) then --> s� aparecer nego da raid - break - end - - if (jogador.classe and jogador.classe ~= "UNGROUPPLAYER") then - local interrupts = jogador.interrupt - if (interrupts and interrupts > 0) then - local oque_interrompi = jogador.interrompeu_oque - --> vai ter [spellid] = quantidade - - for spellid, amt in _pairs (oque_interrompi) do - if (not habilidades_interrompidas [spellid]) then --> se a spell n�o tiver na pool, cria a tabela dela - habilidades_interrompidas [spellid] = {{}, 0, spellid} --> tabela com quem interrompeu e o total de vezes que a habilidade foi interrompida - end - - if (not habilidades_interrompidas [spellid] [1] [jogador.nome]) then --> se o jogador n�o tiver na pool dessa habilidade interrompida, cria um indice pra ele. - habilidades_interrompidas [spellid] [1] [jogador.nome] = {0, jogador.classe} - end - - habilidades_interrompidas [spellid] [2] = habilidades_interrompidas [spellid] [2] + amt - habilidades_interrompidas [spellid] [1] [jogador.nome] [1] = habilidades_interrompidas [spellid] [1] [jogador.nome] [1] + amt - end - end - end - end - - --> por em ordem - tabela_em_ordem = {} - for spellid, tabela in _pairs (habilidades_interrompidas) do - tabela_em_ordem [#tabela_em_ordem+1] = tabela - end - _table_sort (tabela_em_ordem, Details.Sort2) - - index = 1 - - for _, tabela in _ipairs (tabela_em_ordem) do - - local barra = container.barras [index] - if (not barra) then - barra = EncounterDetails:CreateRow (index, container, 3, 0, -6) - Details:SetFontSize (barra.lineText1, CONST_FONT_SIZE) - Details:SetFontSize (barra.lineText4, CONST_FONT_SIZE) - barra.TTT = "total_interrupt" -- tool tip type - barra.report_text = "Details! ".. Loc ["STRING_INTERRUPTS_OF"] - barra:SetWidth (155) - end - - local spellid = tabela [3] - - local nome_magia, _, icone_magia = _GetSpellInfo (tabela [3]) - local successful = 0 - --> pegar quantas vezes a magia passou com sucesso. - for _, enemy_actor in _ipairs (DamageContainer._ActorTable) do - if (enemy_actor.spells._ActorTable [spellid]) then - local spell = enemy_actor.spells._ActorTable [spellid] - successful = spell.successful_casted - end - end - - barra.lineText1:SetText (nome_magia) - local total = successful + tabela [2] - barra.lineText4:SetText (tabela [2] .. " / ".. total) - - Details:name_space (barra) - - barra.jogador = tabela - - --barra.textura:SetStatusBarColor (_unpack (_detalhes.class_colors [jogador.classe])) - - if (index == 1) then - barra.textura:SetValue (100) - dano_do_primeiro = tabela [2] - else - barra.textura:SetValue (tabela [2]/dano_do_primeiro *100) - end - - barra.icone:SetTexture (icone_magia) - barra.icone:SetTexCoord (.1, .9, .1, .9) - - barra:Show() - - quantidade = quantidade + 1 - index = index + 1 - end - - EncounterDetails:JB_AtualizaContainer (container, quantidade, 4) - - if (quantidade < #container.barras) then - for i = quantidade+1, #container.barras, 1 do - container.barras[i]:Hide() - end - end - - --> Fim do container dos Interrupts - - --> Inicio do Container dos Dispells: - - --> force refresh window behavior - local total_dispelado = Details.atributo_misc:RefreshWindow ({}, _combat_object, _, { key = "dispell", modo = Details.modos.group }) - - local frame_dispell = EncounterDetailsFrame.overall_dispell - container = frame_dispell.gump - - quantidade = 0 - local dispell_do_primeiro = 0 - - local habilidades_dispeladas = {} - - for index, jogador in _ipairs (misc._ActorTable) do - if (not jogador.grupo) then --> s� aparecer nego da raid - break - end - - if (jogador.classe and jogador.classe ~= "UNGROUPPLAYER") then - - local dispells = jogador.dispell - if (dispells and dispells > 0) then - local oque_dispelei = jogador.dispell_oque - --> vai ter [spellid] = quantidade - - --print ("dispell: " .. jogador.classe .. " nome: " .. jogador.nome) - - for spellid, amt in _pairs (oque_dispelei) do - if (not habilidades_dispeladas [spellid]) then --> se a spell n�o tiver na pool, cria a tabela dela - habilidades_dispeladas [spellid] = {{}, 0, spellid} --> tabela com quem dispolou e o total de vezes que a habilidade foi dispelada - end - - if (not habilidades_dispeladas [spellid] [1] [jogador.nome]) then --> se o jogador n�o tiver na pool dessa habilidade interrompida, cria um indice pra ele. - habilidades_dispeladas [spellid] [1] [jogador.nome] = {0, jogador.classe} - --print (jogador.nome) - --print (jogador.classe) - end - - habilidades_dispeladas [spellid] [2] = habilidades_dispeladas [spellid] [2] + amt - habilidades_dispeladas [spellid] [1] [jogador.nome] [1] = habilidades_dispeladas [spellid] [1] [jogador.nome] [1] + amt - end - end - end - end - - --> por em ordem - tabela_em_ordem = {} - for spellid, tabela in _pairs (habilidades_dispeladas) do - tabela_em_ordem [#tabela_em_ordem+1] = tabela - end - _table_sort (tabela_em_ordem, Details.Sort2) - - index = 1 - - for _, tabela in _ipairs (tabela_em_ordem) do - - local barra = container.barras [index] - if (not barra) then - barra = EncounterDetails:CreateRow (index, container, 3, 3, -6) - Details:SetFontSize (barra.lineText1, CONST_FONT_SIZE) - Details:SetFontSize (barra.lineText4, CONST_FONT_SIZE) - barra.TTT = "dispell" -- tool tip type - barra.report_text = "Details! ".. Loc ["STRING_DISPELLS_OF"] - barra:SetWidth (160) - end - - local nome_magia, _, icone_magia = _GetSpellInfo (tabela [3]) - - barra.lineText1:SetText (nome_magia) - barra.lineText4:SetText (tabela [2]) - - Details:name_space (barra) - - barra.jogador = tabela - - --barra.textura:SetStatusBarColor (_unpack (_detalhes.class_colors [jogador.classe])) - - if (index == 1) then - barra.textura:SetValue (100) - dano_do_primeiro = tabela [2] - else - barra.textura:SetValue (tabela [2]/dano_do_primeiro *100) - end - - barra.icone:SetTexture (icone_magia) - barra.icone:SetTexCoord (.1, .9, .1, .9) - - barra:Show() - - quantidade = quantidade + 1 - index = index + 1 - end - - EncounterDetails:JB_AtualizaContainer (container, quantidade, 4) - - if (quantidade < #container.barras) then - for i = quantidade+1, #container.barras, 1 do - container.barras [i]:Hide() - end - end - - --> Fim do container dos Dispells - - --> Inicio do Container das Mortes: - local frame_mortes = EncounterDetailsFrame.overall_dead - container = frame_mortes.gump - - quantidade = 0 - - -- boss_info.spells_info o erro de lua do boss � a habilidade dele que n�o foi declarada ainda - - local mortes = _combat_object.last_events_tables - local habilidades_info = boss_info and boss_info.spell_mechanics or {} --barra.extra pega esse cara aqui --> ent�o esse erro � das habilidades que n�o tao - - for index, tabela in _ipairs (mortes) do - --> {esta_morte, time, este_jogador.nome, este_jogador.classe, _UnitHealthMax (alvo_name), minutos.."m "..segundos.."s", ["dead"] = true} - local barra = container.barras [index] - if (not barra) then - barra = EncounterDetails:CreateRow (index, container, 3, 0, 1) - barra.TTT = "morte" -- tool tip type - barra.report_text = "Details! " .. Loc ["STRING_DEAD_LOG"] - Details:SetFontSize (barra.lineText1, CONST_FONT_SIZE) - Details:SetFontSize (barra.lineText4, CONST_FONT_SIZE) - barra:SetWidth (169) - - local overlayTexture = barra:CreateTexture (nil, "overlay") - overlayTexture:SetAllPoints() - overlayTexture:SetColorTexture (1, 1, 1) - overlayTexture:SetAlpha (1) - overlayTexture:Hide() - barra.OverlayTexture = overlayTexture - end - - if (tabela [3]:find ("-")) then - barra.lineText1:SetText (index..". "..tabela [3]:gsub (("-.*"), "")) - else - barra.lineText1:SetText (index..". "..tabela [3]) - end - - barra.lineText4:SetText (tabela [6]) - - Details:name_space (barra) - - barra.jogador = tabela - barra.extra = habilidades_info - - barra.textura:SetStatusBarColor (_unpack (Details.class_colors [tabela [4]])) - barra.textura:SetValue (100) - - barra.icone:SetTexture ("Interface\\AddOns\\Details\\images\\classes_small") - barra.icone:SetTexCoord (_unpack (EncounterDetails.class_coords [tabela [4]])) - - barra:Show() - - quantidade = quantidade + 1 - - end - - EncounterDetails:JB_AtualizaContainer (container, quantidade, 10) - - if (quantidade < #container.barras) then - for i = quantidade+1, #container.barras, 1 do - container.barras [i]:Hide() - end - end + edFrame.raidBackgroundTexture:SetTexture(.3, .3, .3, .5) end local events_to_track = { @@ -2128,11 +800,10 @@ local events_to_track = { } local enemy_spell_pool -local CLEvents = function (self, event) - +local CLEvents = function(self, event) local time, token, hidding, who_serial, who_name, who_flags, who_flags2, alvo_serial, alvo_name, alvo_flags, alvo_flags2, spellid, spellname, school, aura_type = CombatLogGetCurrentEventInfo() - if (events_to_track [token] and _bit_band (who_flags or 0x0, 0x00000060) ~= 0) then + if (events_to_track [token] and bitBand(who_flags or 0x0, 0x00000060) ~= 0) then local t = enemy_spell_pool [spellid] if (not t) then t = {["token"] = {[token] = true}, ["source"] = who_name, ["school"] = school} @@ -2141,11 +812,11 @@ local CLEvents = function (self, event) end enemy_spell_pool [spellid] = t return - + elseif (t.token [token]) then return end - + t.token [token] = true if (token == "SPELL_AURA_APPLIED") then t.type = aura_type @@ -2165,7 +836,6 @@ local installPluginFunc = function() local PLUGIN_MINIMAL_DETAILS_VERSION_REQUIRED = 1 local PLUGIN_TYPE = "TOOLBAR" local PLUGIN_LOCALIZED_NAME = Loc ["STRING_PLUGIN_NAME"] - local PLUGIN_REAL_NAME = "DETAILS_PLUGIN_ENCOUNTER_DETAILS" local PLUGIN_ICON = [[Interface\Scenarios\ScenarioIcon-Boss]] local PLUGIN_AUTHOR = "Terciob" local PLUGIN_VERSION = "v1.06" @@ -2186,7 +856,7 @@ local installPluginFunc = function() PLUGIN_TYPE, PLUGIN_LOCALIZED_NAME, PLUGIN_ICON, - EncounterDetails, + encounterDetails, PLUGIN_REAL_NAME, PLUGIN_MINIMAL_DETAILS_VERSION_REQUIRED, PLUGIN_AUTHOR, @@ -2198,11 +868,33 @@ local installPluginFunc = function() print(install.error) end - --table.wipe(EncounterDetailsDB.encounter_spells) - EncounterDetails.charsaved = EncounterDetailsDB or {emotes = {}} - EncounterDetailsDB = EncounterDetails.charsaved - EncounterDetails.charsaved.encounter_spells = EncounterDetails.charsaved.encounter_spells or {} - EncounterDetails.boss_emotes_table = EncounterDetails.charsaved.emotes + encounterDetails.charsaved = EncounterDetailsDB or {emotes = {}, chartData = {}} + EncounterDetailsDB = encounterDetails.charsaved + + EncounterDetailsDB.chartData = EncounterDetailsDB.chartData or {} + EncounterDetailsDB.emotes = EncounterDetailsDB.emotes or {} + + --make a cleanup on saved charts + local now = time() + for combatUniqueId, charts in pairs(EncounterDetailsDB.chartData) do + --check if details! still have a combat with the same id + local bCombatExists = Details:DoesCombatWithUIDExists(combatUniqueId) + if (not bCombatExists) then + EncounterDetailsDB.chartData[combatUniqueId] = nil + else + --check if the data is already 48hrs old + for chartName, chartData in pairs(charts) do + if (chartData.__time) then + if (now - chartData.__time > 60*60*24*2) then + charts[chartName] = nil + end + end + end + end + end + + encounterDetails.charsaved.encounter_spells = encounterDetails.charsaved.encounter_spells or {} + encounterDetails.boss_emotes_table = encounterDetails.charsaved.emotes --build a table on global saved variables if (not Details.global_plugin_database["DETAILS_PLUGIN_ENCOUNTER_DETAILS"]) then @@ -2210,23 +902,23 @@ local installPluginFunc = function() end --Register needed events - Details:RegisterEvent(EncounterDetails, "COMBAT_PLAYER_ENTER") - Details:RegisterEvent(EncounterDetails, "COMBAT_PLAYER_LEAVE") - Details:RegisterEvent(EncounterDetails, "COMBAT_BOSS_FOUND") - Details:RegisterEvent(EncounterDetails, "DETAILS_DATA_RESET") - Details:RegisterEvent(EncounterDetails, "GROUP_ONENTER") - Details:RegisterEvent(EncounterDetails, "GROUP_ONLEAVE") - Details:RegisterEvent(EncounterDetails, "ZONE_TYPE_CHANGED") + Details:RegisterEvent(encounterDetails, "COMBAT_PLAYER_ENTER") + Details:RegisterEvent(encounterDetails, "COMBAT_PLAYER_LEAVE") + Details:RegisterEvent(encounterDetails, "COMBAT_BOSS_FOUND") + Details:RegisterEvent(encounterDetails, "DETAILS_DATA_RESET") + Details:RegisterEvent(encounterDetails, "GROUP_ONENTER") + Details:RegisterEvent(encounterDetails, "GROUP_ONLEAVE") + Details:RegisterEvent(encounterDetails, "ZONE_TYPE_CHANGED") - EncounterDetailsFrame:RegisterEvent("ENCOUNTER_START") - EncounterDetailsFrame:RegisterEvent("ENCOUNTER_END") - EncounterDetails.EnemySpellPool = EncounterDetails.charsaved.encounter_spells - enemy_spell_pool = EncounterDetails.EnemySpellPool - EncounterDetails.CLEvents = CreateFrame("frame", nil, UIParent, "BackdropTemplate") - EncounterDetails.CLEvents:SetScript("OnEvent", CLEvents) - EncounterDetails.CLEvents:Hide() + edFrame:RegisterEvent("ENCOUNTER_START") + edFrame:RegisterEvent("ENCOUNTER_END") + encounterDetails.EnemySpellPool = encounterDetails.charsaved.encounter_spells + enemy_spell_pool = encounterDetails.EnemySpellPool + encounterDetails.CLEvents = CreateFrame("frame", nil, UIParent, "BackdropTemplate") + encounterDetails.CLEvents:SetScript("OnEvent", CLEvents) + encounterDetails.CLEvents:Hide() - EncounterDetails.BossWhispColors = { + encounterDetails.BossWhispColors = { [1] = "RAID_BOSS_EMOTE", [2] = "RAID_BOSS_WHISPER", [3] = "MONSTER_EMOTE", @@ -2235,21 +927,16 @@ local installPluginFunc = function() [6] = "MONSTER_PARTY", [7] = "MONSTER_YELL", } - - --embed the plugin into the plugin window - if (DetailsPluginContainerWindow) then - DetailsPluginContainerWindow.EmbedPlugin(EncounterDetails, EncounterDetails.Frame, false, EncounterDetails.OpenAndRefresh) - end end end -function EncounterDetails:OnEvent(self, event, ...) +function encounterDetails:OnEvent(self, event, ...) if (event == "ENCOUNTER_START") then --tracks if a enemy spell is instant cast - EncounterDetails.CLEvents:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED") + encounterDetails.CLEvents:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED") elseif (event == "ENCOUNTER_END") then - EncounterDetails.CLEvents:UnregisterEvent("COMBAT_LOG_EVENT_UNFILTERED") + encounterDetails.CLEvents:UnregisterEvent("COMBAT_LOG_EVENT_UNFILTERED") elseif (event == "ADDON_LOADED") then local addonName = select(1, ...) diff --git a/plugins/Details_EncounterDetails/Details_EncounterDetails.toc b/plugins/Details_EncounterDetails/Details_EncounterDetails.toc index 1889b7e8..79dadab9 100644 --- a/plugins/Details_EncounterDetails/Details_EncounterDetails.toc +++ b/plugins/Details_EncounterDetails/Details_EncounterDetails.toc @@ -1,4 +1,4 @@ -## Interface: 100100 +## Interface: 100105 ## Title: Details!: Encounter Breakdown (plugin) ## Notes: Show detailed information about a boss encounter. Also provide damage per phase, graphic charts, easy weakauras creation. ## RequiredDeps: Details @@ -10,6 +10,12 @@ enUS.lua ptBR.lua -frames.lua Details_EncounterDetails.lua +frames_chart.lua +frames_emote.lua +frames_phases.lua +frames_summary.lua +frames.lua + + diff --git a/plugins/Details_EncounterDetails/Details_EncounterDetails_Wrath.toc b/plugins/Details_EncounterDetails/Details_EncounterDetails_Wrath.toc index 7f5397b4..b6f4cd7a 100644 --- a/plugins/Details_EncounterDetails/Details_EncounterDetails_Wrath.toc +++ b/plugins/Details_EncounterDetails/Details_EncounterDetails_Wrath.toc @@ -8,6 +8,10 @@ enUS.lua ptBR.lua -frames.lua -Details_EncounterDetails.lua \ No newline at end of file +Details_EncounterDetails.lua +frames_chart.lua +frames_emote.lua +frames_phases.lua +frames_summary.lua +frames.lua \ No newline at end of file diff --git a/plugins/Details_EncounterDetails/ED_Definitions.lua b/plugins/Details_EncounterDetails/ED_Definitions.lua new file mode 100644 index 00000000..282430f2 --- /dev/null +++ b/plugins/Details_EncounterDetails/ED_Definitions.lua @@ -0,0 +1,8 @@ + +---@class ed_barline : button +---@field statusBar statusbar +---@field lineText1 fontstring +---@field lineText4 fontstring +---@field statusBarTexture texture +---@field Icon texture + diff --git a/plugins/Details_EncounterDetails/Libs/DF/.gitignore b/plugins/Details_EncounterDetails/Libs/DF/.gitignore new file mode 100644 index 00000000..df44e95e --- /dev/null +++ b/plugins/Details_EncounterDetails/Libs/DF/.gitignore @@ -0,0 +1,11 @@ + +background.blp +border_1.blp +border_2.blp +border_3.blp +cooltip_background.blp +feedback_sites.blp +icons.blp +mail.blp +*.json +CHANGES.txt diff --git a/plugins/Details_EncounterDetails/Libs/DF/DFPixelUtil.lua b/plugins/Details_EncounterDetails/Libs/DF/DFPixelUtil.lua new file mode 100644 index 00000000..e59fe6a2 --- /dev/null +++ b/plugins/Details_EncounterDetails/Libs/DF/DFPixelUtil.lua @@ -0,0 +1,66 @@ +DFPixelUtil = {}; + +function DFPixelUtil.GetPixelToUIUnitFactor() + local physicalWidth, physicalHeight = GetPhysicalScreenSize(); + return 768.0 / physicalHeight; +end + +function DFPixelUtil.GetNearestPixelSize(uiUnitSize, layoutScale, minPixels) + if uiUnitSize == 0 and (not minPixels or minPixels == 0) then + return 0; + end + + local uiUnitFactor = DFPixelUtil.GetPixelToUIUnitFactor(); + local numPixels = Round((uiUnitSize * layoutScale) / uiUnitFactor); + local rawNumPixels = numPixels; + if minPixels then + if uiUnitSize < 0.0 then + if numPixels > -minPixels then + numPixels = -minPixels; + end + else + if numPixels < minPixels then + numPixels = minPixels; + end + end + end + + return numPixels * uiUnitFactor / layoutScale; +end + +function DFPixelUtil.SetWidth(region, width, minPixels) + region:SetWidth(DFPixelUtil.GetNearestPixelSize(width, region:GetEffectiveScale(), minPixels)); +end + +function DFPixelUtil.SetHeight(region, height, minPixels) + region:SetHeight(DFPixelUtil.GetNearestPixelSize(height, region:GetEffectiveScale(), minPixels)); +end + +function DFPixelUtil.SetSize(region, width, height, minWidthPixels, minHeightPixels) + DFPixelUtil.SetWidth(region, width, minWidthPixels); + DFPixelUtil.SetHeight(region, height, minHeightPixels); +end + +function DFPixelUtil.SetPoint(region, point, relativeTo, relativePoint, offsetX, offsetY, minOffsetXPixels, minOffsetYPixels) + region:SetPoint(point, relativeTo, relativePoint, + DFPixelUtil.GetNearestPixelSize(offsetX, region:GetEffectiveScale(), minOffsetXPixels), + DFPixelUtil.GetNearestPixelSize(offsetY, region:GetEffectiveScale(), minOffsetYPixels) + ); +end + +function DFPixelUtil.SetStatusBarValue(statusBar, value) + local width = statusBar:GetWidth(); + if width and width > 0.0 then + local min, max = statusBar:GetMinMaxValues(); + local percent = ClampedPercentageBetween(value, min, max); + if percent == 0.0 or percent == 1.0 then + statusBar:SetValue(value); + else + local numPixels = DFPixelUtil.GetNearestPixelSize(statusBar:GetWidth() * percent, statusBar:GetEffectiveScale()); + local roundedValue = Lerp(min, max, numPixels / width); + statusBar:SetValue(roundedValue); + end + else + statusBar:SetValue(value); + end +end diff --git a/plugins/Details_EncounterDetails/Libs/DF/LibDFramework-1.0.toc b/plugins/Details_EncounterDetails/Libs/DF/LibDFramework-1.0.toc new file mode 100644 index 00000000..4c8166cc --- /dev/null +++ b/plugins/Details_EncounterDetails/Libs/DF/LibDFramework-1.0.toc @@ -0,0 +1,5 @@ +## Interface: 100100 +## Title: Lib: LibDFramework-1.0 +## Notes: Base Framework for many Addons + +load.xml diff --git a/plugins/Details_EncounterDetails/Libs/DF/addon.lua b/plugins/Details_EncounterDetails/Libs/DF/addon.lua new file mode 100644 index 00000000..d1af8ee0 --- /dev/null +++ b/plugins/Details_EncounterDetails/Libs/DF/addon.lua @@ -0,0 +1,132 @@ + +local DF = _G ["DetailsFramework"] +local _ + +if (not DF or not DetailsFrameworkCanLoad) then + return +end + +--runs when the addon received addon_loaded +local addonPreLoad = function(addonFrame, event, ...) + --check if the saved variables table is created, if not create one + _G[addonFrame.__savedVarsName] = _G[addonFrame.__savedVarsName] or {} + + if (addonFrame.__savedVarsDefaultTemplate) then + --load saved vars for this character + DF.SavedVars.LoadSavedVarsForPlayer(addonFrame) + end + + if (addonFrame.OnLoad) then + DF:Dispatch(addonFrame.OnLoad, addonFrame, ...) + end +end + +--runs when the addon received player_login +local addonInit = function(addonFrame, event, ...) + if (addonFrame.OnInit) then + DF:Dispatch(addonFrame.OnInit, addonFrame, ...) + end +end + +--when the player logout or reloadUI +local addonUnload = function(addonFrame, event, ...) + --close saved tables + DF.SavedVars.CloseSavedTable(addonFrame.db) +end + +local addonEvents = { + ["ADDON_LOADED"] = addonPreLoad, + ["PLAYER_LOGIN"] = addonInit, + ["PLAYER_LOGOUT"] = addonUnload, +} + +local addonOnEvent = function(addonFrame, event, ...) + local func = addonEvents[event] + if (func) then + func(addonFrame, event, ...) + else + --might be a registered event from the user + if (addonFrame[event]) then + DF:CoreDispatch(addonFrame.__name, addonFrame[event], addonFrame, event, ...) + end + end +end + +local getAddonName = function(addonFrame) + return addonFrame:GetName() +end + +function DF:CreateNewAddOn(addonName, globalSavedVariablesName, savedVarsTemplate) + local newAddon = CreateFrame("frame", addonName, UIParent) + newAddon.__name = addonName + newAddon.__savedVarsName = globalSavedVariablesName + newAddon.__savedVarsDefaultTemplate = savedVarsTemplate + + newAddon.GetAddonName = getAddonName + + newAddon:RegisterEvent("ADDON_LOADED") + newAddon:RegisterEvent("PLAYER_LOGIN") + newAddon:RegisterEvent("PLAYER_LOGOUT") + newAddon:SetScript("OnEvent", addonOnEvent) + + return newAddon +end + + + + +--old create addon +function DF:CreateAddOn (name, global_saved, global_table, options_table, broker) + + local addon = LibStub("AceAddon-3.0"):NewAddon (name, "AceConsole-3.0", "AceEvent-3.0", "AceTimer-3.0", "DetailsFramework-1.0", "AceComm-3.0") + _G [name] = addon + addon.__name = name + + function addon:OnInitialize() + + if (global_saved) then + if (broker and broker.Minimap and not global_table.Minimap) then + DF:Msg(name, "broker.Minimap is true but no global.Minimap declared.") + end + self.db = LibStub("AceDB-3.0"):New (global_saved, global_table or {}, true) + end + + if (options_table) then + LibStub("AceConfig-3.0"):RegisterOptionsTable (name, options_table) + addon.OptionsFrame1 = LibStub("AceConfigDialog-3.0"):AddToBlizOptions (name, name) + + LibStub("AceConfig-3.0"):RegisterOptionsTable (name .. "-Profiles", LibStub("AceDBOptions-3.0"):GetOptionsTable (self.db)) + addon.OptionsFrame2 = LibStub("AceConfigDialog-3.0"):AddToBlizOptions (name .. "-Profiles", "Profiles", name) + end + + if (broker) then + local broker_click_function = broker.OnClick + if (not broker_click_function and options_table) then + broker_click_function = function() + InterfaceOptionsFrame_OpenToCategory (name) + InterfaceOptionsFrame_OpenToCategory (name) + end + end + + local databroker = LibStub("LibDataBroker-1.1"):NewDataObject (name, { + type = broker.type or "launcher", + icon = broker.icon or [[Interface\PvPRankBadges\PvPRank15]], + text = broker.text or "", + OnTooltipShow = broker.OnTooltipShow, + OnClick = broker_click_function + }) + + if (databroker and broker.Minimap and global_table.Minimap) then + LibStub("LibDBIcon-1.0"):Register (name, databroker, addon.db.profile.Minimap) + end + end + + if (addon.OnInit) then + xpcall(addon.OnInit, geterrorhandler(), addon) + end + + end + + return addon + +end diff --git a/plugins/Details_EncounterDetails/Libs/DF/auras.lua b/plugins/Details_EncounterDetails/Libs/DF/auras.lua new file mode 100644 index 00000000..941141b4 --- /dev/null +++ b/plugins/Details_EncounterDetails/Libs/DF/auras.lua @@ -0,0 +1,1282 @@ + +local DF = _G ["DetailsFramework"] +if (not DF or not DetailsFrameworkCanLoad) then + return +end + +local _ +local tinsert = tinsert +local GetSpellInfo = GetSpellInfo +local lower = string.lower +local GetSpellBookItemInfo = GetSpellBookItemInfo + +local CONST_MAX_SPELLS = 450000 + +function DF:GetAuraByName (unit, spellName, isDebuff) + isDebuff = isDebuff and "HARMFUL|PLAYER" + + for i = 1, 40 do + local name, texture, count, debuffType, duration, expirationTime, caster, canStealOrPurge, nameplateShowPersonal, spellId, canApplyAura, isBossDebuff, isCastByPlayer, nameplateShowAll = UnitAura (unit, i, isDebuff) + if (not name) then + return + end + + if (name == spellName) then + return name, texture, count, debuffType, duration, expirationTime, caster, canStealOrPurge, nameplateShowPersonal, spellId, canApplyAura, isBossDebuff, isCastByPlayer, nameplateShowAll + end + end +end + +local default_text_for_aura_frame = { + AUTOMATIC = "Automatic", + MANUAL = "Manual", + METHOD = "Aura Tracking Method:", + BUFFS_IGNORED = "Buffs Ignored", + DEBUFFS_IGNORED = "Debuffs Ignored", + BUFFS_TRACKED = "Buffs Tracked", + DEBUFFS_TRACKED = "Debuffs Tracked", + + AUTOMATIC_DESC = "Auras are being tracked automatically, the addon controls what to show.\nYou may add auras to the blacklist or add extra auras to track.", + MANUAL_DESC = "Auras are being tracked manually, the addon only check for auras you entered below.", + + MANUAL_ADD_BLACKLIST_BUFF = "Add Buff to Blacklist", + MANUAL_ADD_BLACKLIST_DEBUFF = "Add Debuff to Blacklist", + MANUAL_ADD_TRACKLIST_BUFF = "Add Buff to Tracklist", + MANUAL_ADD_TRACKLIST_DEBUFF = "Add Debuff to Tracklist", +} + +function DF:LoadAllSpells (hashMap, indexTable, allSpellsSameName) + + --pre checking which tables to fill to avoid checking if the table exists during the gigantic loop for performance + + if (not DF.LoadingAuraAlertFrame) then + DF.LoadingAuraAlertFrame = CreateFrame("frame", "DetailsFrameworkLoadingAurasAlert", UIParent, "BackdropTemplate") + DF.LoadingAuraAlertFrame:SetSize(340, 75) + DF.LoadingAuraAlertFrame:SetPoint("center") + DF.LoadingAuraAlertFrame:SetFrameStrata("TOOLTIP") + DF:ApplyStandardBackdrop(DF.LoadingAuraAlertFrame) + DF.LoadingAuraAlertFrame:SetBackdropBorderColor(1, 0.8, 0.1) + + DF.LoadingAuraAlertFrame.IsLoadingLabel1 = DF:CreateLabel(DF.LoadingAuraAlertFrame, "We are currently loading spell names and spell IDs") + DF.LoadingAuraAlertFrame.IsLoadingLabel2 = DF:CreateLabel(DF.LoadingAuraAlertFrame, "This may take only a few seconds") + DF.LoadingAuraAlertFrame.IsLoadingImage1 = DF:CreateImage(DF.LoadingAuraAlertFrame, [[Interface\DialogFrame\UI-Dialog-Icon-AlertOther]], 32, 32) + DF.LoadingAuraAlertFrame.IsLoadingLabel1.align = "center" + DF.LoadingAuraAlertFrame.IsLoadingLabel2.align = "center" + + DF.LoadingAuraAlertFrame.IsLoadingLabel1:SetPoint("center", 16, 10) + DF.LoadingAuraAlertFrame.IsLoadingLabel2:SetPoint("center", 16, -5) + DF.LoadingAuraAlertFrame.IsLoadingImage1:SetPoint("left", 10, 0) + end + + DF.LoadingAuraAlertFrame:Show() + + C_Timer.After(0, function() + if (hashMap and not indexTable) then + for i = 1, CONST_MAX_SPELLS do + local spellName = GetSpellInfo(i) + if (spellName) then + hashMap [lower (spellName)] = i + end + end + + elseif (not hashMap and indexTable) then + for i = 1, CONST_MAX_SPELLS do + local spellName = GetSpellInfo(i) + if (spellName) then + indexTable [#indexTable+1] = lower (spellName) + end + end + + elseif (hashMap and indexTable) then + if (allSpellsSameName) then + for i = 1, CONST_MAX_SPELLS do + local spellName = GetSpellInfo(i) + if (spellName) then + spellName = lower (spellName) + indexTable [#indexTable + 1] = spellName + hashMap [spellName] = i + + --same name table + local sameNameTable = allSpellsSameName [spellName] + if (not sameNameTable) then + sameNameTable = {} + allSpellsSameName [spellName] = sameNameTable + end + sameNameTable [#sameNameTable + 1] = i + end + end + else + for i = 1, CONST_MAX_SPELLS do + local spellName = GetSpellInfo(i) + if (spellName) then + spellName = lower (spellName) + indexTable [#indexTable + 1] = spellName + hashMap [spellName] = i + end + end + end + end + + DF.LoadingAuraAlertFrame:Hide() + end) + +end + +local cleanfunction = function() end + +do + local metaPrototype = { + WidgetType = "aura_tracker", + dversion = DF.dversion, + } + + --check if there's a metaPrototype already existing + if (_G[DF.GlobalWidgetControlNames["aura_tracker"]]) then + --get the already existing metaPrototype + local oldMetaPrototype = _G[DF.GlobalWidgetControlNames["aura_tracker"]] + --check if is older + if ( (not oldMetaPrototype.dversion) or (oldMetaPrototype.dversion < DF.dversion) ) then + --the version is older them the currently loading one + --copy the new values into the old metatable + for funcName, _ in pairs(metaPrototype) do + oldMetaPrototype[funcName] = metaPrototype[funcName] + end + end + else + --first time loading the framework + _G[DF.GlobalWidgetControlNames["aura_tracker"]] = metaPrototype + end +end + +local AuraTrackerMetaFunctions = _G[DF.GlobalWidgetControlNames["aura_tracker"]] +DF:Mixin(AuraTrackerMetaFunctions, DF.ScriptHookMixin) + +--create panels +local on_profile_changed = function(self, newdb) + + self.db = newdb + + --automatic + self.buff_ignored:DoSetData (newdb.aura_tracker.buff_banned) + self.debuff_ignored:DoSetData (newdb.aura_tracker.debuff_banned) + self.buff_tracked:DoSetData (newdb.aura_tracker.buff_tracked) + self.debuff_tracked:DoSetData (newdb.aura_tracker.debuff_tracked) + + self.buff_ignored:DoRefresh() + self.debuff_ignored:DoRefresh() + self.buff_tracked:DoRefresh() + self.debuff_tracked:DoRefresh() + + --manual + self.buffs_added:SetData (newdb.aura_tracker.buff) + self.debuffs_added:SetData (newdb.aura_tracker.debuff) + self.buffs_added:Refresh() + self.debuffs_added:Refresh() + + --method + if (newdb.aura_tracker.track_method == 0x1) then + self.f_auto:Show() + self.f_manual:Hide() + + self.AutomaticTrackingCheckbox:SetValue(true) + self.ManualTrackingCheckbox:SetValue(false) + self.desc_label.text = self.LocTexts.AUTOMATIC_DESC + + elseif (newdb.aura_tracker.track_method == 0x2) then + self.f_auto:Hide() + self.f_manual:Show() + + self.AutomaticTrackingCheckbox:SetValue(false) + self.ManualTrackingCheckbox:SetValue(true) + self.desc_label.text = self.LocTexts.MANUAL_DESC + end +end + +local aura_panel_defaultoptions = { + height = 400, + row_height = 18, + width = 230, + button_text_template = "OPTIONS_FONT_TEMPLATE" +} + +function DF:CreateAuraConfigPanel (parent, name, db, change_callback, options, texts) + + local options_text_template = DF:GetTemplate("font", "OPTIONS_FONT_TEMPLATE") + local options_dropdown_template = DF:GetTemplate("dropdown", "OPTIONS_DROPDOWN_TEMPLATE") + local options_switch_template = DF:GetTemplate("switch", "OPTIONS_CHECKBOX_TEMPLATE") + local options_slider_template = DF:GetTemplate("slider", "OPTIONS_SLIDER_TEMPLATE") + local options_button_template = DF:GetTemplate("button", "OPTIONS_BUTTON_TEMPLATE") + + local f = CreateFrame("frame", name, parent, "BackdropTemplate") + f.db = db + f.OnProfileChanged = on_profile_changed + f.LocTexts = texts + options = options or {} + self.table.deploy(options, aura_panel_defaultoptions) + + local f_auto = CreateFrame("frame", "$parent_Automatic", f, "BackdropTemplate") + local f_manual = CreateFrame("frame", "$parent_Manual", f, "BackdropTemplate") + f_auto:SetPoint("topleft", f, "topleft", 0, -24) + f_manual:SetPoint("topleft", f, "topleft", 0, -24) + f_auto:SetSize(600, 600) + f_manual:SetSize(600, 600) + f.f_auto = f_auto + f.f_manual = f_manual + + --check if the texts table is valid and also deploy default values into the table in case some value is nil + texts = (type(texts == "table") and texts) or default_text_for_aura_frame + DF.table.deploy(texts, default_text_for_aura_frame) + + ------------- + + local on_switch_tracking_method = function(self) + local method = self.Method + + f.db.aura_tracker.track_method = method + if (change_callback) then + DF:QuickDispatch(change_callback) + end + + if (method == 0x1) then + f_auto:Show() + f_manual:Hide() + f.AutomaticTrackingCheckbox:SetValue(true) + f.ManualTrackingCheckbox:SetValue(false) + f.desc_label.text = texts.AUTOMATIC_DESC + + elseif (method == 0x2) then + f_auto:Hide() + f_manual:Show() + f.AutomaticTrackingCheckbox:SetValue(false) + f.ManualTrackingCheckbox:SetValue(true) + f.desc_label.text = texts.MANUAL_DESC + end + end + + local background_method_selection = CreateFrame("frame", nil, f, "BackdropTemplate") + background_method_selection:SetHeight(82) + background_method_selection:SetPoint("topleft", f, "topleft", 0, 0) + background_method_selection:SetPoint("topright", f, "topright", 0, 0) + DF:ApplyStandardBackdrop(background_method_selection) + + local tracking_method_label = self:CreateLabel(background_method_selection, texts.METHOD, 12, "orange") + tracking_method_label:SetPoint("topleft", background_method_selection, "topleft", 6, -4) + + f.desc_label = self:CreateLabel(background_method_selection, "", 10, "silver") + f.desc_label:SetPoint("left", background_method_selection, "left", 130, 0) + f.desc_label:SetJustifyV ("top") + + local automatic_tracking_checkbox = DF:CreateSwitch(background_method_selection, on_switch_tracking_method, f.db.aura_tracker.track_method == 0x1, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, DF:GetTemplate("switch", "OPTIONS_CHECKBOX_BRIGHT_TEMPLATE")) + automatic_tracking_checkbox.Method = 0x1 + automatic_tracking_checkbox:SetAsCheckBox() + automatic_tracking_checkbox:SetSize(24, 24) + f.AutomaticTrackingCheckbox = automatic_tracking_checkbox + + local automatic_tracking_label = DF:CreateLabel(background_method_selection, "Automatic") + automatic_tracking_label:SetPoint("left", automatic_tracking_checkbox, "right", 2, 0) + + local manual_tracking_checkbox = DF:CreateSwitch(background_method_selection, on_switch_tracking_method, f.db.aura_tracker.track_method == 0x2, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, DF:GetTemplate("switch", "OPTIONS_CHECKBOX_BRIGHT_TEMPLATE")) + manual_tracking_checkbox.Method = 0x2 + manual_tracking_checkbox:SetAsCheckBox() + manual_tracking_checkbox:SetSize(24, 24) + f.ManualTrackingCheckbox = manual_tracking_checkbox + + local manual_tracking_label = DF:CreateLabel(background_method_selection, "Manual") + manual_tracking_label:SetPoint("left", manual_tracking_checkbox, "right", 2, 0) + + automatic_tracking_checkbox:SetPoint("topleft", tracking_method_label, "bottomleft", 0, -6) + manual_tracking_checkbox:SetPoint("topleft", automatic_tracking_checkbox, "bottomleft", 0, -6) + + +-------- anchors points + + local y = -110 + +-------- automatic + + --manual add the buff and ebuff names + local AllSpellsMap = {} + local AllSpellNames = {} + + --store a table with spell name as key and in the value an index table with spell IDs + local AllSpellsSameName = {} + + local load_all_spells = function(self, capsule) + if (not next (AllSpellsMap)) then + DF:LoadAllSpells (AllSpellsMap, AllSpellNames, AllSpellsSameName) + + f_auto.AddBuffBlacklistTextBox.SpellAutoCompleteList = AllSpellNames + f_auto.AddDebuffBlacklistTextBox.SpellAutoCompleteList = AllSpellNames + f_auto.AddBuffTracklistTextBox.SpellAutoCompleteList = AllSpellNames + f_auto.AddDebuffTracklistTextBox.SpellAutoCompleteList = AllSpellNames + + f_manual.NewBuffTextBox.SpellAutoCompleteList = AllSpellNames + f_manual.NewDebuffTextBox.SpellAutoCompleteList = AllSpellNames + + -- + + f_auto.AddBuffBlacklistTextBox:SetAsAutoComplete ("SpellAutoCompleteList") + f_auto.AddDebuffBlacklistTextBox:SetAsAutoComplete ("SpellAutoCompleteList") + f_auto.AddBuffTracklistTextBox:SetAsAutoComplete ("SpellAutoCompleteList") + f_auto.AddDebuffTracklistTextBox:SetAsAutoComplete ("SpellAutoCompleteList") + + f_manual.NewBuffTextBox:SetAsAutoComplete ("SpellAutoCompleteList") + f_manual.NewDebuffTextBox:SetAsAutoComplete ("SpellAutoCompleteList") + + -- + + f_auto.AddBuffBlacklistTextBox.ShouldOptimizeAutoComplete = true + f_auto.AddDebuffBlacklistTextBox.ShouldOptimizeAutoComplete = true + f_auto.AddBuffTracklistTextBox.ShouldOptimizeAutoComplete = true + f_auto.AddDebuffTracklistTextBox.ShouldOptimizeAutoComplete = true + + f_manual.NewBuffTextBox.ShouldOptimizeAutoComplete = true + f_manual.NewDebuffTextBox.ShouldOptimizeAutoComplete = true + end + end + + --this set the width of the background box, text entry and button + local textEntryWidth = 120 + + --create the background + local background_add_blacklist = CreateFrame("frame", nil, f_auto, "BackdropTemplate") + background_add_blacklist:SetSize(textEntryWidth + 10, 135) + DF:ApplyStandardBackdrop(background_add_blacklist) + background_add_blacklist.__background:SetVertexColor(0.47, 0.27, 0.27) + + local background_add_tracklist = CreateFrame("frame", nil, f_auto, "BackdropTemplate") + background_add_tracklist:SetSize(textEntryWidth + 10, 135) + DF:ApplyStandardBackdrop(background_add_tracklist) + background_add_tracklist.__background:SetVertexColor(0.27, 0.27, 0.47) + + --black list + --create labels + local buff_blacklist_label = self:CreateLabel(background_add_blacklist, texts.MANUAL_ADD_BLACKLIST_BUFF, DF:GetTemplate("font", "OPTIONS_FONT_TEMPLATE")) + local debuff_blacklist_label = self:CreateLabel(background_add_blacklist, texts.MANUAL_ADD_BLACKLIST_DEBUFF, DF:GetTemplate("font", "OPTIONS_FONT_TEMPLATE")) + + local buff_name_blacklist_entry = self:CreateTextEntry(background_add_blacklist, function()end, textEntryWidth, 20, "AddBuffBlacklistTextBox", _, _, options_dropdown_template) + buff_name_blacklist_entry:SetHook("OnEditFocusGained", load_all_spells) + buff_name_blacklist_entry:SetJustifyH("left") + buff_name_blacklist_entry.tooltip = "Enter the buff name using lower case letters." + f_auto.AddBuffBlacklistTextBox = buff_name_blacklist_entry + + local debuff_name_blacklist_entry = self:CreateTextEntry(background_add_blacklist, function()end, textEntryWidth, 20, "AddDebuffBlacklistTextBox", _, _, options_dropdown_template) + debuff_name_blacklist_entry:SetHook("OnEditFocusGained", load_all_spells) + debuff_name_blacklist_entry:SetJustifyH("left") + debuff_name_blacklist_entry.tooltip = "Enter the debuff name using lower case letters." + f_auto.AddDebuffBlacklistTextBox = debuff_name_blacklist_entry + + local same_name_spells_add = function(spellID, t) + local spellName = GetSpellInfo(spellID) + if (spellName) then + if (not next (AllSpellsMap)) then + load_all_spells() + end + + spellName = lower (spellName) + local spellWithSameName = AllSpellsSameName [spellName] + if (spellWithSameName) then + if (t) then + t [spellName] = DF.table.copy({}, spellWithSameName) + else + db.aura_cache_by_name [spellName] = DF.table.copy({}, spellWithSameName) + end + end + end + end + DF.AddSpellWithSameName = same_name_spells_add + + local get_spellID_from_string = function(text) + --check if the user entered a spell ID + local isSpellID = tonumber(text) + if (isSpellID and isSpellID > 1 and isSpellID < 10000000) then + local isValidSpellID = GetSpellInfo(isSpellID) + if (isValidSpellID) then + return isSpellID + else + return + end + end + + --get the spell ID from the spell name + text = lower (text) + local spellID = AllSpellsMap [text] + if (not spellID) then + return + end + + return spellID + end + + local add_blacklist_buff_button = self:CreateButton(background_add_blacklist, function() + local text = buff_name_blacklist_entry.text + buff_name_blacklist_entry:SetText("") + buff_name_blacklist_entry:ClearFocus() + + if (text ~= "") then + --get the spellId + local spellId = get_spellID_from_string (text) + if (not spellId) then + DetailsFramework.Msg ({__name = "DetailsFramework"}, "Spell not found!") + return + end + + --add the spellName to the blacklist + f.db.aura_tracker.buff_banned [spellId] = true + + --refresh the buff blacklist frame + f.buff_ignored:DoRefresh() + + DF:QuickDispatch(change_callback) + + --add to spells with the same name cache + same_name_spells_add (spellId) + end + + end, textEntryWidth/2 -3, 20, "By Name", nil, nil, nil, nil, nil, nil, DF:GetTemplate("button", "OPTIONS_BUTTON_TEMPLATE"), DF:GetTemplate("font", options.button_text_template)) + + local add_blacklist_buff_button_id = self:CreateButton(background_add_blacklist, function() + local text = buff_name_blacklist_entry.text + buff_name_blacklist_entry:SetText("") + buff_name_blacklist_entry:ClearFocus() + + if (text ~= "") then + if (not tonumber(text)) then + DetailsFramework.Msg ({__name = "DetailsFramework"}, "Invalid Spell-ID.") + end + + --get the spellId + local spellId = get_spellID_from_string (text) + if (not spellId) then + DetailsFramework.Msg ({__name = "DetailsFramework"}, "Spell not found!") + return + end + + --add the spellId to the blacklist + f.db.aura_tracker.buff_banned [spellId] = false + + --refresh the buff blacklist frame + f.buff_ignored:DoRefresh() + + DF:QuickDispatch(change_callback) + + --add to spells with the same name cache + same_name_spells_add (spellId) + end + + end, textEntryWidth/2 -3, 20, "By ID", nil, nil, nil, nil, nil, nil, DF:GetTemplate("button", "OPTIONS_BUTTON_TEMPLATE"), DF:GetTemplate("font", options.button_text_template)) + + local add_blacklist_debuff_button = self:CreateButton(background_add_blacklist, function() + local text = debuff_name_blacklist_entry.text + debuff_name_blacklist_entry:SetText("") + debuff_name_blacklist_entry:ClearFocus() + + if (text ~= "") then + --get the spellId + local spellId = get_spellID_from_string (text) + if (not spellId) then + DetailsFramework.Msg ({__name = "DetailsFramework"}, "Spell not found!") + return + end + + --add the spellName to the blacklist + f.db.aura_tracker.debuff_banned [spellId] = true + + --refresh the buff blacklist frame + f.debuff_ignored:DoRefresh() + + DF:QuickDispatch(change_callback) + + --add to spells with the same name cache + same_name_spells_add (spellId) + end + end, textEntryWidth/2 -3, 20, "By Name", nil, nil, nil, nil, nil, nil, DF:GetTemplate("button", "OPTIONS_BUTTON_TEMPLATE"), DF:GetTemplate("font", options.button_text_template)) + + local add_blacklist_debuff_button_id = self:CreateButton(background_add_blacklist, function() + local text = debuff_name_blacklist_entry.text + debuff_name_blacklist_entry:SetText("") + debuff_name_blacklist_entry:ClearFocus() + + if (text ~= "") then + if (not tonumber(text)) then + DetailsFramework.Msg ({__name = "DetailsFramework"}, "Invalid Spell-ID.") + end + + --get the spellId + local spellId = get_spellID_from_string (text) + if (not spellId) then + DetailsFramework.Msg ({__name = "DetailsFramework"}, "Spell not found!") + return + end + + --add the spellId to the blacklist + f.db.aura_tracker.debuff_banned [spellId] = false + + --refresh the buff blacklist frame + f.debuff_ignored:DoRefresh() + + DF:QuickDispatch(change_callback) + + --add to spells with the same name cache + same_name_spells_add (spellId) + end + end, textEntryWidth/2 -3, 20, "By ID", nil, nil, nil, nil, nil, nil, DF:GetTemplate("button", "OPTIONS_BUTTON_TEMPLATE"), DF:GetTemplate("font", options.button_text_template)) + + + --track list + local buff_tracklist_label = self:CreateLabel(background_add_tracklist, texts.MANUAL_ADD_TRACKLIST_BUFF, DF:GetTemplate("font", "OPTIONS_FONT_TEMPLATE")) + local debuff_tracklist_label = self:CreateLabel(background_add_tracklist, texts.MANUAL_ADD_TRACKLIST_DEBUFF, DF:GetTemplate("font", "OPTIONS_FONT_TEMPLATE")) + + local buff_name_tracklist_entry = self:CreateTextEntry(background_add_tracklist, function()end, textEntryWidth, 20, "AddBuffTracklistTextBox", _, _, options_dropdown_template) + buff_name_tracklist_entry:SetHook("OnEditFocusGained", load_all_spells) + buff_name_tracklist_entry:SetJustifyH("left") + buff_name_tracklist_entry.tooltip = "Enter the buff name using lower case letters." + f_auto.AddBuffTracklistTextBox = buff_name_tracklist_entry + + local debuff_name_tracklist_entry = self:CreateTextEntry(background_add_tracklist, function()end, textEntryWidth, 20, "AddDebuffTracklistTextBox", _, _, options_dropdown_template) + debuff_name_tracklist_entry:SetHook("OnEditFocusGained", load_all_spells) + debuff_name_tracklist_entry:SetJustifyH("left") + debuff_name_tracklist_entry.tooltip = "Enter the debuff name using lower case letters." + f_auto.AddDebuffTracklistTextBox = debuff_name_tracklist_entry + + local add_tracklist_debuff_button = self:CreateButton(background_add_tracklist, function() + local text = debuff_name_tracklist_entry.text + debuff_name_tracklist_entry:SetText("") + debuff_name_tracklist_entry:ClearFocus() + + if (text ~= "") then + --get the spellId + local spellId = get_spellID_from_string (text) + if (not spellId) then + DetailsFramework.Msg ({__name = "DetailsFramework"}, "Spell not found!") + return + end + + --add the spellName to the tracklist + f.db.aura_tracker.debuff_tracked [spellId] = true + + --refresh the buff blacklist frame + f.debuff_tracked:DoRefresh() + + DF:QuickDispatch(change_callback) + + --add to spells with the same name cache + same_name_spells_add (spellId) + end + end, textEntryWidth/2 -3, 20, "By Name", nil, nil, nil, nil, nil, nil, DF:GetTemplate("button", "OPTIONS_BUTTON_TEMPLATE"), DF:GetTemplate("font", options.button_text_template)) + + local add_tracklist_debuff_button_id = self:CreateButton(background_add_tracklist, function() + local text = debuff_name_tracklist_entry.text + debuff_name_tracklist_entry:SetText("") + debuff_name_tracklist_entry:ClearFocus() + + if (text ~= "") then + if (not tonumber(text)) then + DetailsFramework.Msg ({__name = "DetailsFramework"}, "Invalid Spell-ID.") + end + + --get the spellId + local spellId = get_spellID_from_string (text) + if (not spellId) then + DetailsFramework.Msg ({__name = "DetailsFramework"}, "Spell not found!") + return + end + + f.db.aura_tracker.debuff_tracked [spellId] = false + + --refresh the buff blacklist frame + f.debuff_tracked:DoRefresh() + + DF:QuickDispatch(change_callback) + + --add to spells with the same name cache + same_name_spells_add (spellId) + end + end, textEntryWidth/2 -3, 20, "By ID", nil, nil, nil, nil, nil, nil, DF:GetTemplate("button", "OPTIONS_BUTTON_TEMPLATE"), DF:GetTemplate("font", options.button_text_template)) + + local add_tracklist_buff_button = self:CreateButton(background_add_tracklist, function() + local text = buff_name_tracklist_entry.text + buff_name_tracklist_entry:SetText("") + buff_name_tracklist_entry:ClearFocus() + + if (text ~= "") then + --get the spellId + local spellId = get_spellID_from_string (text) + if (not spellId) then + DetailsFramework.Msg ({__name = "DetailsFramework"}, "Spell not found!") + return + end + + --add the spellName to the tracklist + f.db.aura_tracker.buff_tracked [spellId] = true + + --refresh the buff tracklist frame + f.buff_tracked:DoRefresh() + + --callback the addon + DF:QuickDispatch(change_callback) + + --add to spells with the same name cache + same_name_spells_add (spellId) + end + + end, textEntryWidth/2 -3, 20, "By Name", nil, nil, nil, nil, nil, nil, DF:GetTemplate("button", "OPTIONS_BUTTON_TEMPLATE"), DF:GetTemplate("font", options.button_text_template)) + + local add_tracklist_buff_button_id = self:CreateButton(background_add_tracklist, function() + local text = buff_name_tracklist_entry.text + buff_name_tracklist_entry:SetText("") + buff_name_tracklist_entry:ClearFocus() + + if (text ~= "") then + if (not tonumber(text)) then + DetailsFramework.Msg ({__name = "DetailsFramework"}, "Invalid Spell-ID.") + end + + --get the spellId + local spellId = get_spellID_from_string (text) + if (not spellId) then + DetailsFramework.Msg ({__name = "DetailsFramework"}, "Spell not found!") + return + end + + --add the spellId to the tracklist + f.db.aura_tracker.buff_tracked [spellId] = false + + --refresh the buff tracklist frame + f.buff_tracked:DoRefresh() + + --callback the addon + DF:QuickDispatch(change_callback) + + --add to spells with the same name cache + same_name_spells_add (spellId) + end + end, textEntryWidth/2 -3, 20, "By ID", nil, nil, nil, nil, nil, nil, DF:GetTemplate("button", "OPTIONS_BUTTON_TEMPLATE"), DF:GetTemplate("font", options.button_text_template)) + + --anchors: + background_add_blacklist:SetPoint("topleft", f_auto, "topleft", 0, y) + background_add_tracklist:SetPoint("topleft", background_add_blacklist, "bottomleft", 0, -10) + + --debuff blacklist + debuff_name_blacklist_entry:SetPoint("topleft", background_add_blacklist, "topleft", 5, -20) + debuff_blacklist_label:SetPoint("bottomleft", debuff_name_blacklist_entry, "topleft", 0, 2) + add_blacklist_debuff_button:SetPoint("topleft", debuff_name_blacklist_entry, "bottomleft", 0, -2) + add_blacklist_debuff_button_id:SetPoint("left", add_blacklist_debuff_button, "right", 1, 0) + + --buff blacklist + buff_blacklist_label:SetPoint("topleft", add_blacklist_debuff_button.widget, "bottomleft", 0, -10) + buff_name_blacklist_entry:SetPoint("topleft", buff_blacklist_label, "bottomleft", 0, -2) + add_blacklist_buff_button:SetPoint("topleft", buff_name_blacklist_entry, "bottomleft", 0, -2) + add_blacklist_buff_button_id:SetPoint("left", add_blacklist_buff_button, "right", 1, 0) + + + --debuff tracklist + debuff_name_tracklist_entry:SetPoint("topleft", background_add_tracklist, "topleft", 5, -20) + debuff_tracklist_label:SetPoint("bottomleft", debuff_name_tracklist_entry, "topleft", 0, 2) + add_tracklist_debuff_button:SetPoint("topleft", debuff_name_tracklist_entry, "bottomleft", 0, -2) + add_tracklist_debuff_button_id:SetPoint("left", add_tracklist_debuff_button, "right", 1, 0) + + --buff tracklist + buff_tracklist_label:SetPoint("topleft", add_tracklist_debuff_button.widget, "bottomleft", 0, -10) + buff_name_tracklist_entry:SetPoint("topleft", buff_tracklist_label, "bottomleft", 0, -2) + add_tracklist_buff_button:SetPoint("topleft", buff_name_tracklist_entry, "bottomleft", 0, -2) + add_tracklist_buff_button_id:SetPoint("left", add_tracklist_buff_button, "right", 1, 0) + + local ALL_BUFFS = {} + local ALL_DEBUFFS = {} + + --options passed to the create aura panel + local width, height, row_height = options.width, options.height, options.row_height + + local autoTrackList_LineOnEnter = function(self, capsule, value) + + local flag = self.Flag + value = value or self.SpellID + + if not flag then + GameCooltip2:Preset(2) + GameCooltip2:SetOwner(self, "left", "right", 2, 0) + GameCooltip2:SetOption("TextSize", 10) + + local spellName, _, spellIcon = GetSpellInfo(value) + if (spellName) then + GameCooltip2:AddLine(spellName .. " (" .. value .. ")") + GameCooltip2:AddIcon (spellIcon, 1, 1, 14, 14, .1, .9, .1, .9) + end + GameCooltip2:Show() + else + + local spellName = GetSpellInfo(value) + if (spellName) then + + local spellsWithSameName = db.aura_cache_by_name [lower (spellName)] + if (not spellsWithSameName) then + same_name_spells_add (value) + spellsWithSameName = db.aura_cache_by_name [lower (spellName)] + end + + if (spellsWithSameName) then + GameCooltip2:Preset(2) + GameCooltip2:SetOwner(self, "left", "right", 2, 0) + GameCooltip2:SetOption("TextSize", 10) + + for i, spellID in ipairs(spellsWithSameName) do + local spellName, _, spellIcon = GetSpellInfo(spellID) + if (spellName) then + GameCooltip2:AddLine(spellName .. " (" .. spellID .. ")") + GameCooltip2:AddIcon (spellIcon, 1, 1, 14, 14, .1, .9, .1, .9) + end + end + + GameCooltip2:Show() + end + end + + end + end + + local autoTrackList_LineOnLeave = function() + GameCooltip2:Hide() + end + + local scrollWidth = 208 + local scrollHeight = 343 + local lineAmount = 18 + local lineHeight = 18 + local backdropColor = {.8, .8, .8, 0.2} + local backdropColor_OnEnter = {.8, .8, .8, 0.4} + + local createAuraScrollBox = function(parent, name, member, title, db, removeFunc) + + local updateFunc = function(self, data, offset, totalLines) + for i = 1, totalLines do + local index = i + offset + local auraTable = data [index] + if (auraTable) then + local line = self:GetLine (i) + local spellID, spellName, spellIcon, lowerSpellName, flag = unpack(auraTable) + + line.SpellID = spellID + line.SpellName = spellName + line.SpellNameLower = lowerSpellName + line.SpellIcon = spellIcon + line.Flag = flag + + if flag then + line.name:SetText(spellName) + else + line.name:SetText(spellName .. " (" .. spellID .. ")") + end + line.icon:SetTexture(spellIcon) + line.icon:SetTexCoord(.1, .9, .1, .9) + end + end + end + + local lineOnEnter = function(self) + self:SetBackdropColor(unpack(backdropColor_OnEnter)) + + --GameTooltip:SetOwner(self, "ANCHOR_CURSOR") + --GameTooltip:SetSpellByID(self.SpellID) + --GameTooltip:AddLine(" ") + --GameTooltip:Show() + end + + local lineOnLeave = function(self) + self:SetBackdropColor(unpack(backdropColor)) + --GameTooltip:Hide() + end + + local onRemoveClick = function(self) + local spellID = self:GetParent().SpellID + db [spellID] = nil + db ["".. (spellID or "")] = nil -- cleanup... + parent [member]:DoRefresh() + if (removeFunc) then + DF:QuickDispatch(removeFunc) + end + end + + local createLineFunc = function(self, index) + local line = CreateFrame("button", "$parentLine" .. index, self, "BackdropTemplate") + line:SetPoint("topleft", self, "topleft", 1, - ((index - 1) * (lineHeight + 1)) - 1) + line:SetSize(scrollWidth - 2, lineHeight) + line:SetScript("OnEnter", autoTrackList_LineOnEnter) + line:HookScript ("OnEnter", lineOnEnter) + line:SetScript("OnLeave", autoTrackList_LineOnLeave) + line:HookScript ("OnLeave", lineOnLeave) + + line:SetBackdrop({bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tileSize = 64, tile = true}) + line:SetBackdropColor(unpack(backdropColor)) + + local icon = line:CreateTexture("$parentIcon", "overlay") + icon:SetSize(lineHeight - 2, lineHeight - 2) + + local name = line:CreateFontString("$parentName", "overlay", "GameFontNormal") + DF:SetFontSize(name, 10) + + local remove_button = CreateFrame("button", "$parentRemoveButton", line, "UIPanelCloseButton") + remove_button:SetSize(16, 16) + remove_button:SetScript("OnClick", onRemoveClick) + remove_button:SetPoint("topright", line, "topright") + remove_button:GetNormalTexture():SetDesaturated(true) + + icon:SetPoint("left", line, "left", 2, 0) + name:SetPoint("left", icon, "right", 3, 0) + + line.icon = icon + line.name = name + line.removebutton = remove_button + + return line + end + + local scroll = DF:CreateScrollBox (parent, name, updateFunc, db, scrollWidth, scrollHeight, lineAmount, lineHeight) + DF:ReskinSlider(scroll) + parent [member] = scroll + scroll.OriginalData = db + + function scroll:DoRefresh() + local t = {} + local added = {} + for spellID, flag in pairs(scroll.OriginalData) do + local spellName, _, spellIcon = GetSpellInfo(spellID) + if (spellName and not added[tonumber(spellID) or 0]) then + local lowerSpellName = spellName:lower() + tinsert(t, {spellID, spellName, spellIcon, lowerSpellName, flag}) + added[tonumber(spellID) or 0] = true + end + end + + table.sort (t, function(t1, t2) return t1[4] < t2[4] end) + + self:SetData (t) + self:Refresh() + end + + function scroll:DoSetData (newDB) + self:SetData (newDB) + scroll.OriginalData = newDB + self:DoRefresh() + end + + local title = DF:CreateLabel(parent, title) + title.textcolor = "silver" + title.textsize = 10 + title:SetPoint("bottomleft", scroll, "topleft", 0, 2) + + for i = 1, lineAmount do + scroll:CreateLine (createLineFunc) + end + + scroll:DoRefresh() + return scroll + end + + local buff_tracked = createAuraScrollBox (f_auto, "$parentBuffTracked", "BuffTrackerScroll", f.LocTexts.BUFFS_TRACKED, f.db.aura_tracker.buff_tracked, function() + if (change_callback) then + DF:QuickDispatch(change_callback) + end + end) + local debuff_tracked = createAuraScrollBox (f_auto, "$parentDebuffTracked", "DebuffTrackerScroll", f.LocTexts.DEBUFFS_TRACKED, f.db.aura_tracker.debuff_tracked, function() + if (change_callback) then + DF:QuickDispatch(change_callback) + end + end) + + local buff_ignored = createAuraScrollBox (f_auto, "$parentBuffIgnored", "BuffIgnoredScroll", f.LocTexts.BUFFS_IGNORED, f.db.aura_tracker.buff_banned, function() + if (change_callback) then + DF:QuickDispatch(change_callback) + end + end) + local debuff_ignored = createAuraScrollBox (f_auto, "$parentDebuffIgnored", "DebuffIgnoredScroll", f.LocTexts.DEBUFFS_IGNORED, f.db.aura_tracker.debuff_banned, function() + if (change_callback) then + DF:QuickDispatch(change_callback) + end + end) + + local xLocation = 140 + scrollWidth = scrollWidth + 20 + + debuff_ignored:SetPoint("topleft", f_auto, "topleft", 0 + xLocation, y) + buff_ignored:SetPoint("topleft", f_auto, "topleft", 8 + scrollWidth + xLocation, y) + debuff_tracked:SetPoint("topleft", f_auto, "topleft", 16 + (scrollWidth * 2) + xLocation, y) + buff_tracked:SetPoint("topleft", f_auto, "topleft", 24 + (scrollWidth * 3) + xLocation, y) + + f.buff_ignored = buff_ignored + f.debuff_ignored = debuff_ignored + f.buff_tracked = buff_tracked + f.debuff_tracked = debuff_tracked + + f_auto:SetScript("OnShow", function() + for i = 1, BUFF_MAX_DISPLAY do + local name, texture, count, debuffType, duration, expirationTime, caster, _, nameplateShowPersonal, spellId, _, _, _, nameplateShowAll = UnitAura ("player", i, "HELPFUL") + if (name) then + ALL_BUFFS [spellId] = true + end + local name, texture, count, debuffType, duration, expirationTime, caster, _, nameplateShowPersonal, spellId, _, _, _, nameplateShowAll = UnitAura ("player", i, "HARMFUL") + if (name) then + ALL_DEBUFFS [spellId] = true + end + end + + buff_tracked:DoRefresh() + debuff_tracked:DoRefresh() + buff_ignored:DoRefresh() + debuff_ignored:DoRefresh() + + end) + f_auto:SetScript("OnHide", function() + -- + end) + + --show the frame selecton on the f.db + + if (f.db.aura_tracker.track_method == 0x1) then + on_switch_tracking_method (automatic_tracking_checkbox) + elseif (f.db.aura_tracker.track_method == 0x2) then + on_switch_tracking_method (manual_tracking_checkbox) + end + +-------manual + + --build the two aura scrolls for buff and debuff + + local scroll_width = width + local scroll_height = height + local scroll_lines = 15 + local scroll_line_height = 20 + + local backdrop_color = {.8, .8, .8, 0.2} + local backdrop_color_on_enter = {.8, .8, .8, 0.4} + + local line_onenter = function(self) + self:SetBackdropColor(unpack(backdrop_color_on_enter)) + local spellid = select(7, GetSpellInfo(self.value)) + if (spellid) then + GameTooltip:SetOwner(self, "ANCHOR_CURSOR") + GameTooltip:SetSpellByID(spellid) + GameTooltip:AddLine(" ") + GameTooltip:Show() + end + end + + local line_onleave = function(self) + self:SetBackdropColor(unpack(backdrop_color)) + GameTooltip:Hide() + end + + local onclick_remove_button = function(self) + local spell = self:GetParent().value + local data = self:GetParent():GetParent():GetData() + + for i = 1, #data do + if (data[i] == spell) then + tremove(data, i) + break + end + end + + self:GetParent():GetParent():Refresh() + end + + local scroll_createline = function(self, index) + local line = CreateFrame("button", "$parentLine" .. index, self, "BackdropTemplate") + line:SetPoint("topleft", self, "topleft", 1, -((index-1)*(scroll_line_height+1)) - 1) + line:SetSize(scroll_width - 2, scroll_line_height) + line:SetScript("OnEnter", line_onenter) + line:SetScript("OnLeave", line_onleave) + + line:SetBackdrop({bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tileSize = 64, tile = true}) + line:SetBackdropColor(unpack(backdrop_color)) + + local icon = line:CreateTexture("$parentIcon", "overlay") + icon:SetSize(scroll_line_height - 2, scroll_line_height - 2) + + local name = line:CreateFontString("$parentName", "overlay", "GameFontNormal") + + local remove_button = CreateFrame("button", "$parentRemoveButton", line, "UIPanelCloseButton") + remove_button:SetSize(16, 16) + remove_button:SetScript("OnClick", onclick_remove_button) + remove_button:SetPoint("topright", line, "topright") + remove_button:GetNormalTexture():SetDesaturated(true) + + icon:SetPoint("left", line, "left", 2, 0) + name:SetPoint("left", icon, "right", 2, 0) + + line.icon = icon + line.name = name + line.removebutton = remove_button + + return line + end + + local scroll_refresh = function(self, data, offset, total_lines) + for i = 1, total_lines do + local index = i + offset + local aura = data [index] + if (aura) then + local line = self:GetLine (i) + local name, _, icon = GetSpellInfo(aura) + line.value = aura + if (name) then + line.name:SetText(name) + line.icon:SetTexture(icon) + line.icon:SetTexCoord(.1, .9, .1, .9) + else + line.name:SetText(aura) + line.icon:SetTexture([[Interface\InventoryItems\WoWUnknownItem01]]) + end + end + end + end + + local buffs_added = self:CreateScrollBox (f_manual, "$parentBuffsAdded", scroll_refresh, f.db.aura_tracker.buff, scroll_width, scroll_height, scroll_lines, scroll_line_height) + buffs_added:SetPoint("topleft", f_manual, "topleft", 0, y) + DF:ReskinSlider(buffs_added) + + for i = 1, scroll_lines do + buffs_added:CreateLine (scroll_createline) + end + + local debuffs_added = self:CreateScrollBox (f_manual, "$parentDebuffsAdded", scroll_refresh, f.db.aura_tracker.debuff, scroll_width, scroll_height, scroll_lines, scroll_line_height) + debuffs_added:SetPoint("topleft", f_manual, "topleft", width+30, y) + DF:ReskinSlider(debuffs_added) + + for i = 1, scroll_lines do + debuffs_added:CreateLine (scroll_createline) + end + + f.buffs_added = buffs_added + f.debuffs_added = debuffs_added + + local buffs_added_name = DF:CreateLabel(buffs_added, "Buffs", 12, "silver") + buffs_added_name:SetTemplate(DF:GetTemplate("font", "OPTIONS_FONT_TEMPLATE")) + buffs_added_name:SetPoint("bottomleft", buffs_added, "topleft", 0, 2) + buffs_added.Title = buffs_added_name + + local debuffs_added_name = DF:CreateLabel(debuffs_added, "Debuffs", 12, "silver") + debuffs_added_name:SetTemplate(DF:GetTemplate("font", "OPTIONS_FONT_TEMPLATE")) + debuffs_added_name:SetPoint("bottomleft", debuffs_added, "topleft", 0, 2) + debuffs_added.Title = debuffs_added_name + + -- build the text entry to type the spellname + local new_buff_string = self:CreateLabel(f_manual, "Add Buff") + local new_debuff_string = self:CreateLabel(f_manual, "Add Debuff") + local new_buff_entry = self:CreateTextEntry(f_manual, function()end, 200, 20, "NewBuffTextBox", _, _, options_dropdown_template) + local new_debuff_entry = self:CreateTextEntry(f_manual, function()end, 200, 20, "NewDebuffTextBox", _, _, options_dropdown_template) + + new_buff_entry:SetHook("OnEditFocusGained", load_all_spells) + new_debuff_entry:SetHook("OnEditFocusGained", load_all_spells) + new_buff_entry.tooltip = "Enter the buff name using lower case letters.\n\nYou can add several spells at once using |cFFFFFF00;|r to separate each spell name." + new_debuff_entry.tooltip = "Enter the debuff name using lower case letters.\n\nYou can add several spells at once using |cFFFFFF00;|r to separate each spell name." + + new_buff_entry:SetJustifyH("left") + new_debuff_entry:SetJustifyH("left") + + local add_buff_button = self:CreateButton(f_manual, function() + + local text = new_buff_entry.text + new_buff_entry:SetText("") + new_buff_entry:ClearFocus() + + if (text ~= "") then + --check for more than one spellname + if (text:find(";")) then + for _, spellName in ipairs({strsplit(";", text)}) do + spellName = self:trim (spellName) + local spellID = get_spellID_from_string (spellName) + + if (spellID) then + tinsert(f.db.aura_tracker.buff, spellID) + --[[ + if not tonumber(spellName) then + tinsert(f.db.aura_tracker.buff, spellName) + else + tinsert(f.db.aura_tracker.buff, spellID) + end + ]]-- + else + print("spellId not found for spell:", spellName) + end + end + else + --get the spellId + local spellID = get_spellID_from_string (text) + if (not spellID) then + print("spellIs for spell ", text, "not found") + return + end + + tinsert(f.db.aura_tracker.buff, spellID) + --[[ + if not tonumber(text) then + tinsert(f.db.aura_tracker.buff, text) + else + tinsert(f.db.aura_tracker.buff, spellID) + end + ]]-- + end + + buffs_added:Refresh() + end + + end, 100, 20, "Add Buff", nil, nil, nil, nil, nil, nil, DF:GetTemplate("button", "OPTIONS_BUTTON_TEMPLATE")) + + local add_debuff_button = self:CreateButton(f_manual, function() + local text = new_debuff_entry.text + new_debuff_entry:SetText("") + new_debuff_entry:ClearFocus() + if (text ~= "") then + --check for more than one spellname + if (text:find(";")) then + for _, spellName in ipairs({strsplit(";", text)}) do + spellName = self:trim (spellName) + local spellID = get_spellID_from_string (spellName) + + if (spellID) then + tinsert(f.db.aura_tracker.debuff, spellID) + --[[ + if not tonumber(spellName) then + tinsert(f.db.aura_tracker.debuff, spellName) + else + tinsert(f.db.aura_tracker.debuff, spellID) + end + ]]-- + else + print("spellId not found for spell:", spellName) + end + end + else + --get the spellId + local spellID = get_spellID_from_string (text) + if (not spellID) then + print("spellIs for spell ", text, "not found") + return + end + + tinsert(f.db.aura_tracker.debuff, spellID) + --[[ + if not tonumber(text) then + print(text) + tinsert(f.db.aura_tracker.debuff, text) + else + print(spellID) + tinsert(f.db.aura_tracker.debuff, spellID) + end + ]]-- + end + + debuffs_added:Refresh() + end + end, 100, 20, "Add Debuff", nil, nil, nil, nil, nil, nil, DF:GetTemplate("button", "OPTIONS_BUTTON_TEMPLATE")) + + local multiple_spells_label = DF:CreateLabel(buffs_added, "You can add multiple auras at once by separating them with ';'.\nExample: Fireball; Frostbolt; Flamestrike", 10, "gray") + multiple_spells_label:SetSize(350, 24) + multiple_spells_label:SetJustifyV ("top") + + local export_box = self:CreateTextEntry(f_manual, function()end, 242, 20, "ExportAuraTextBox", _, _, options_dropdown_template) + + local export_buff_button = self:CreateButton(f_manual, function() + local str = "" + for _, spellId in ipairs(f.db.aura_tracker.buff) do + local spellName = GetSpellInfo(spellId) + if (spellName) then + str = str .. spellName .. "; " + end + end + export_box.text = str + export_box:SetFocus(true) + export_box:HighlightText() + + end, 120, 20, "Export Buffs", nil, nil, nil, nil, nil, nil, DF:GetTemplate("button", "OPTIONS_BUTTON_TEMPLATE")) + + local export_debuff_button = self:CreateButton(f_manual, function() + local str = "" + for _, spellId in ipairs(f.db.aura_tracker.debuff) do + local spellName = GetSpellInfo(spellId) + if (spellName) then + str = str .. spellName .. "; " + end + end + + export_box.text = str + export_box:SetFocus(true) + export_box:HighlightText() + + end, 120, 20, "Export Debuffs", nil, nil, nil, nil, nil, nil, DF:GetTemplate("button", "OPTIONS_BUTTON_TEMPLATE")) + + new_buff_entry:SetPoint("topleft", f_manual, "topleft", 480, y) + new_buff_string:SetPoint("bottomleft", new_buff_entry, "topleft", 0, 2) + add_buff_button:SetPoint("left", new_buff_entry, "right", 2, 0) + add_buff_button.tooltip = "Add the aura to be tracked.\n\nClick an aura on the list to remove it." + + new_debuff_string:SetPoint("topleft", new_buff_entry, "bottomleft", 0, -6) + new_debuff_entry:SetPoint("topleft", new_debuff_string, "bottomleft", 0, -2) + add_debuff_button:SetPoint("left", new_debuff_entry, "right", 2, 0) + add_debuff_button.tooltip = "Add the aura to be tracked.\n\nClick an aura on the list to remove it." + + multiple_spells_label:SetPoint("topleft", new_debuff_entry, "bottomleft", 0, -6) + + export_buff_button:SetPoint("topleft", multiple_spells_label, "bottomleft", 0, -12) + export_debuff_button:SetPoint("left",export_buff_button, "right", 2, 0) + export_box:SetPoint("topleft", export_buff_button, "bottomleft", 0, -6) + + buffs_added:Refresh() + debuffs_added:Refresh() + + +----------------------- ---------------------------------------------- ---------------------------------------------- ----------------------- + + f:SetScript("OnShow", function() + buffs_added:Refresh() + debuffs_added:Refresh() + end) + + return f +end + + +function DF:GetAllPlayerSpells (include_lower_case) + local playerSpells = {} + local tab, tabTex, offset, numSpells = GetSpellTabInfo (2) + for i = 1, numSpells do + local index = offset + i + local spellType, spellId = GetSpellBookItemInfo (index, "player") + if (spellType == "SPELL") then + local spellName = GetSpellInfo(spellId) + tinsert(playerSpells, spellName) + if (include_lower_case) then + tinsert(playerSpells, lower (spellName)) + end + end + end + return playerSpells +end + +function DF:SetAutoCompleteWithSpells (textentry) + textentry:SetHook("OnEditFocusGained", function() + local playerSpells = DF:GetAllPlayerSpells (true) + textentry.WordList = playerSpells + end) + textentry:SetAsAutoComplete ("WordList") +end + +--check for aura + + +-- add aura + + +--handle savedvariables + + +--remove a aura + + + + + +--handle UNIT_AURA event + + diff --git a/plugins/Details_EncounterDetails/Libs/DF/button.lua b/plugins/Details_EncounterDetails/Libs/DF/button.lua new file mode 100644 index 00000000..1aafe10e --- /dev/null +++ b/plugins/Details_EncounterDetails/Libs/DF/button.lua @@ -0,0 +1,1358 @@ + +local detailsFramework = _G["DetailsFramework"] + +if (not detailsFramework or not DetailsFrameworkCanLoad) then + return +end + +local _ +local unpack = unpack +local emptyFunction = function() end +local APIButtonFunctions = false + +do + local metaPrototype = { + WidgetType = "button", + dversion = detailsFramework.dversion + } + + --check if there's a metaPrototype already existing + if (_G[detailsFramework.GlobalWidgetControlNames["button"]]) then + --get the already existing metaPrototype + local oldMetaPrototype = _G[detailsFramework.GlobalWidgetControlNames["button"]] + --check if is older + if ( (not oldMetaPrototype.dversion) or (oldMetaPrototype.dversion < detailsFramework.dversion) ) then + --the version is older them the currently loading one + --copy the new values into the old metatable + for funcName, _ in pairs(metaPrototype) do + oldMetaPrototype[funcName] = metaPrototype[funcName] + end + end + else + --first time loading the framework + _G[detailsFramework.GlobalWidgetControlNames["button"]] = metaPrototype + end +end + +local ButtonMetaFunctions = _G[detailsFramework.GlobalWidgetControlNames["button"]] + +detailsFramework:Mixin(ButtonMetaFunctions, detailsFramework.SetPointMixin) +detailsFramework:Mixin(ButtonMetaFunctions, detailsFramework.FrameMixin) +detailsFramework:Mixin(ButtonMetaFunctions, detailsFramework.TooltipHandlerMixin) +detailsFramework:Mixin(ButtonMetaFunctions, detailsFramework.ScriptHookMixin) + +------------------------------------------------------------------------------------------------------------ +--metatables + + ButtonMetaFunctions.__call = function(self) + local frameWidget = self.widget + detailsFramework:CoreDispatch((frameWidget:GetName() or "Button") .. ":__call()", self.func, frameWidget, "LeftButton", self.param1, self.param2) + end + +------------------------------------------------------------------------------------------------------------ +--members + + --tooltip + local gmember_tooltip = function(object) + return object:GetTooltip() + end + + --shown + local gmember_shown = function(object) + return object:IsShown() + end + --frame width + local gmember_width = function(object) + return object.button:GetWidth() + end + + --frame height + local gmember_height = function(object) + return object.button:GetHeight() + end + + --text + local gmember_text = function(object) + return object.button.text:GetText() + end + + --function + local gmember_function = function(object) + return rawget(object, "func") + end + + --text color + local gmember_textcolor = function(object) + return object.button.text:GetTextColor() + end + + --text font + local gmember_textfont = function(object) + local fontface = object.button.text:GetFont() + return fontface + end + + --text size + local gmember_textsize = function(object) + local _, fontsize = object.button.text:GetFont() + return fontsize + end + + --texture + local gmember_texture = function(object) + return {object.button:GetNormalTexture(), object.button:GetHighlightTexture(), object.button:GetPushedTexture(), object.button:GetDisabledTexture()} + end + + --locked + local gmember_locked = function(object) + return rawget(object, "is_locked") + end + + ButtonMetaFunctions.GetMembers = ButtonMetaFunctions.GetMembers or {} + ButtonMetaFunctions.GetMembers["tooltip"] = gmember_tooltip + ButtonMetaFunctions.GetMembers["shown"] = gmember_shown + ButtonMetaFunctions.GetMembers["width"] = gmember_width + ButtonMetaFunctions.GetMembers["height"] = gmember_height + ButtonMetaFunctions.GetMembers["text"] = gmember_text + ButtonMetaFunctions.GetMembers["clickfunction"] = gmember_function + ButtonMetaFunctions.GetMembers["texture"] = gmember_texture + ButtonMetaFunctions.GetMembers["locked"] = gmember_locked + ButtonMetaFunctions.GetMembers["fontcolor"] = gmember_textcolor + ButtonMetaFunctions.GetMembers["fontface"] = gmember_textfont + ButtonMetaFunctions.GetMembers["fontsize"] = gmember_textsize + ButtonMetaFunctions.GetMembers["textcolor"] = gmember_textcolor --alias + ButtonMetaFunctions.GetMembers["textfont"] = gmember_textfont --alias + ButtonMetaFunctions.GetMembers["textsize"] = gmember_textsize --alias + + ButtonMetaFunctions.__index = function(object, key) + local func = ButtonMetaFunctions.GetMembers[key] + if (func) then + return func(object, key) + end + + local alreadyHaveKey = rawget(object, key) + if (alreadyHaveKey) then + return alreadyHaveKey + end + + return ButtonMetaFunctions[key] + end + +------------------------------------------------------------------------------------------------------------------------------------------------------------------- + + --tooltip + local smember_tooltip = function(object, value) + return object:SetTooltip (value) + end + + --show + local smember_show = function(object, value) + if (value) then + return object:Show() + else + return object:Hide() + end + end + + --hide + local smember_hide = function(object, value) + if (not value) then + return object:Show() + else + return object:Hide() + end + end + + --frame width + local smember_width = function(object, value) + return object.button:SetWidth(value) + end + + --frame height + local smember_height = function(object, value) + return object.button:SetHeight(value) + end + + --text + local smember_text = function(object, value) + return object.button.text:SetText(value) + end + + --function + local smember_function = function(object, value) + return rawset(object, "func", value) + end + + --param1 + local smember_param1 = function(object, value) + return rawset(object, "param1", value) + end + + --param2 + local smember_param2 = function(object, value) + return rawset(object, "param2", value) + end + + --text color + local smember_textcolor = function(object, value) + local value1, value2, value3, value4 = detailsFramework:ParseColors(value) + return object.button.text:SetTextColor(value1, value2, value3, value4) + end + + --text font + local smember_textfont = function(object, value) + return detailsFramework:SetFontFace (object.button.text, value) + end + + --text size + local smember_textsize = function(object, value) + return detailsFramework:SetFontSize(object.button.text, value) + end + + --texture + local smember_texture = function(object, value) + if (type(value) == "table") then + local value1, value2, value3, value4 = unpack(value) + if (value1) then + object.button:SetNormalTexture(value1) + end + if (value2) then + object.button:SetHighlightTexture(value2, "ADD") + end + if (value3) then + object.button:SetPushedTexture(value3) + end + if (value4) then + object.button:SetDisabledTexture(value4) + end + else + object.button:SetNormalTexture(value) + object.button:SetHighlightTexture(value, "ADD") + object.button:SetPushedTexture(value) + object.button:SetDisabledTexture(value) + end + return + end + + --locked + local smember_locked = function(object, value) + if (value) then + object.button:SetMovable(false) + return rawset(object, "is_locked", true) + else + object.button:SetMovable(true) + rawset(object, "is_locked", false) + return + end + end + + --text align + local smember_textalign = function(object, value) + if (value == "left" or value == "<") then + object.button.text:SetPoint("left", object.button, "left", 2, 0) + object.capsule_textalign = "left" + + elseif (value == "center" or value == "|") then + object.button.text:SetPoint("center", object.button, "center", 0, 0) + object.capsule_textalign = "center" + + elseif (value == "right" or value == ">") then + object.button.text:SetPoint("right", object.button, "right", -2, 0) + object.capsule_textalign = "right" + end + end + + ButtonMetaFunctions.SetMembers= ButtonMetaFunctions.SetMembers or {} + ButtonMetaFunctions.SetMembers["tooltip"] = smember_tooltip + ButtonMetaFunctions.SetMembers["show"] = smember_show + ButtonMetaFunctions.SetMembers["hide"] = smember_hide + ButtonMetaFunctions.SetMembers["width"] = smember_width + ButtonMetaFunctions.SetMembers["height"] = smember_height + ButtonMetaFunctions.SetMembers["text"] = smember_text + ButtonMetaFunctions.SetMembers["clickfunction"] = smember_function + ButtonMetaFunctions.SetMembers["param1"] = smember_param1 + ButtonMetaFunctions.SetMembers["param2"] = smember_param2 + ButtonMetaFunctions.SetMembers["textcolor"] = smember_textcolor + ButtonMetaFunctions.SetMembers["textfont"] = smember_textfont + ButtonMetaFunctions.SetMembers["textsize"] = smember_textsize + ButtonMetaFunctions.SetMembers["fontcolor"] = smember_textcolor--alias + ButtonMetaFunctions.SetMembers["fontface"] = smember_textfont--alias + ButtonMetaFunctions.SetMembers["fontsize"] = smember_textsize--alias + ButtonMetaFunctions.SetMembers["texture"] = smember_texture + ButtonMetaFunctions.SetMembers["locked"] = smember_locked + ButtonMetaFunctions.SetMembers["textalign"] = smember_textalign + + ButtonMetaFunctions.__newindex = function(object, key, value) + local func = ButtonMetaFunctions.SetMembers[key] + if (func) then + return func(object, value) + else + return rawset(object, key, value) + end + end + +------------------------------------------------------------------------------------------------------------ +--methods + + ---change the function which will be called when the button is pressed + ---@param func function + ---@param param1 any + ---@param param2 any + ---@param clickType string|nil + function ButtonMetaFunctions:SetClickFunction(func, param1, param2, clickType) + if (not clickType or string.find(string.lower(clickType), "left")) then + if (func) then + rawset(self, "func", func) + else + rawset(self, "func", emptyFunction) + end + + if (param1 ~= nil) then + rawset(self, "param1", param1) + end + if (param2 ~= nil) then + rawset(self, "param2", param2) + end + + elseif (clickType or string.find(string.lower(clickType), "right")) then + if (func) then + rawset(self, "funcright", func) + else + rawset(self, "funcright", emptyFunction) + end + end + end + + ---set the text shown on the button + ---@param text string + function ButtonMetaFunctions:SetText(text) + self.button.text:SetText(text) + end + + ---set the color of the button text + ---@param ... any + function ButtonMetaFunctions:SetTextColor(...) + local red, green, blue, alpha = detailsFramework:ParseColors(...) + self.button.text:SetTextColor(red, green, blue, alpha) + end + ButtonMetaFunctions.SetFontColor = ButtonMetaFunctions.SetTextColor --alias + + ---set the size of the button text + ---@param ... number + function ButtonMetaFunctions:SetFontSize(...) + detailsFramework:SetFontSize(self.button.text, ...) + end + + ---set the font into the button text + ---@param font string + function ButtonMetaFunctions:SetFontFace(font) + detailsFramework:SetFontFace(self.button.text, font) + end + + ---comment + ---@param normalTexture any + ---@param highlightTexture any + ---@param pressedTexture any + ---@param disabledTexture any + function ButtonMetaFunctions:SetTexture(normalTexture, highlightTexture, pressedTexture, disabledTexture) + if (normalTexture) then + self.button:SetNormalTexture(normalTexture) + elseif (type(normalTexture) ~= "boolean") then + self.button:SetNormalTexture("") + end + + if (type(highlightTexture) == "boolean") then + if (highlightTexture and normalTexture and type(normalTexture) ~= "boolean") then + self.button:SetHighlightTexture(normalTexture, "ADD") + end + elseif (highlightTexture == nil) then + self.button:SetHighlightTexture("") + else + self.button:SetHighlightTexture(highlightTexture, "ADD") + end + + if (type(pressedTexture) == "boolean") then + if (pressedTexture and normalTexture and type(normalTexture) ~= "boolean") then + self.button:SetPushedTexture(normalTexture) + end + elseif (pressedTexture == nil) then + self.button:SetPushedTexture("") + else + self.button:SetPushedTexture(pressedTexture, "ADD") + end + + if (type(disabledTexture) == "boolean") then + if (disabledTexture and normalTexture and type(normalTexture) ~= "boolean") then + self.button:SetDisabledTexture(normalTexture) + end + elseif (disabledTexture == nil) then + self.button:SetDisabledTexture("") + else + self.button:SetDisabledTexture(disabledTexture, "ADD") + end + end + + ---return the texture set into the icon with SetIcon() + ---@return number|nil texture + function ButtonMetaFunctions:GetIconTexture() + if (self.icon) then + return self.icon:GetTexture() + end + end + + ---add an icon to the left of the button text + ---@param texture any + ---@param width number|nil + ---@param height number|nil + ---@param layout "background|border|overlay|artwork"|nil + ---@param texcoord table|nil + ---@param overlay any + ---@param textDistance number|nil + ---@param leftPadding number|nil + ---@param textHeight number|nil + ---@param shortMethod any + function ButtonMetaFunctions:SetIcon(texture, width, height, layout, texcoord, overlay, textDistance, leftPadding, textHeight, shortMethod) + if (not self.icon) then + self.icon = self:CreateTexture(nil, "artwork") + self.icon:SetSize(self.height * 0.8, self.height * 0.8) + self.icon:SetPoint("left", self.widget, "left", 4 + (leftPadding or 0), 0) + self.icon.leftPadding = leftPadding or 0 + self.widget.text:ClearAllPoints() + self.widget.text:SetPoint("left", self.icon, "right", textDistance or 2, 0 + (textHeight or 0)) + end + + if (type(texture) == "string") then + local isAtlas = C_Texture.GetAtlasInfo(texture) + if (isAtlas) then + self.icon:SetAtlas(texture) + + elseif (detailsFramework:IsHtmlColor(texture)) then + local r, g, b, a = detailsFramework:ParseColors(texture) + self.icon:SetColorTexture(r, g, b, a) + else + self.icon:SetTexture(texture) + end + elseif (type(texture) == "table") then + local r, g, b, a = detailsFramework:ParseColors(texture) + self.icon:SetColorTexture(r, g, b, a) + else + self.icon:SetTexture(texture) + end + + self.icon:SetSize(width or self.height * 0.8, height or self.height * 0.8) + self.icon:SetDrawLayer(layout or "artwork") + + if (texcoord) then + self.icon:SetTexCoord(unpack(texcoord)) + else + self.icon:SetTexCoord(0, 1, 0, 1) + end + + if (overlay) then + if (type(overlay) == "string") then + local r, g, b, a = detailsFramework:ParseColors(overlay) + self.icon:SetVertexColor(r, g, b, a) + else + self.icon:SetVertexColor(unpack(overlay)) + end + else + self.icon:SetVertexColor(1, 1, 1, 1) + end + + local buttonWidth = self.button:GetWidth() + local iconWidth = self.icon:GetWidth() + local textWidth = self.button.text:GetStringWidth() + if (textWidth > buttonWidth - 15 - iconWidth) then + if (shortMethod == false) then + + elseif (not shortMethod) then + local new_width = textWidth + 15 + iconWidth + self.button:SetWidth(new_width) + + elseif (shortMethod == 1) then + local loop = true + local textSize = 11 + while (loop) do + if (textWidth + 15 + iconWidth < buttonWidth or textSize < 8) then + loop = false + break + else + detailsFramework:SetFontSize(self.button.text, textSize) + textWidth = self.button.text:GetStringWidth() + textSize = textSize - 1 + end + end + end + end + end + + ---query if the button is enabled or not + ---@return boolean + function ButtonMetaFunctions:IsEnabled() + return self.button:IsEnabled() + end + + ---enable the button making it clickable and not grayed out + ---@return unknown + function ButtonMetaFunctions:Enable() + return self.button:Enable() + end + + ---disable the button making it unclickable and grayed out + ---@return unknown + function ButtonMetaFunctions:Disable() + return self.button:Disable() + end + + ---simulate a click on the button + function ButtonMetaFunctions:Exec() + local frameWidget = self.widget + detailsFramework:CoreDispatch((frameWidget:GetName() or "Button") .. ":Exec()", self.func, frameWidget, "LeftButton", self.param1, self.param2) + end + + ---simulate a click on the button, but this function is called with a different name + function ButtonMetaFunctions:Click() + local frameWidget = self.widget + detailsFramework:CoreDispatch((frameWidget:GetName() or "Button") .. ":Click()", self.func, frameWidget, "LeftButton", self.param1, self.param2) + end + + ---simulate a right click on the button + function ButtonMetaFunctions:RightClick() + local frameWidget = self.widget + detailsFramework:CoreDispatch((frameWidget:GetName() or "Button") .. ":RightClick()", self.funcright, frameWidget, "RightButton", self.param1, self.param2) + end + +--custom textures + function ButtonMetaFunctions:InstallCustomTexture() + --function deprecated, now just set a the standard template + self:SetTemplate(detailsFramework:GetTemplate("button", "OPTIONS_BUTTON_TEMPLATE")) + end + +------------------------------------------------------------------------------------------------------------ +--scripts + + local OnEnter = function(button) + local object = button.MyObject + + local kill = object:RunHooksForWidget("OnEnter", button, object) + if (kill) then + return + end + + object.is_mouse_over = true + + if (button.texture) then + if (button.texture.coords) then + button.texture:SetTexCoord(unpack(button.texture.coords.Highlight)) + else + button.texture:SetTexCoord(0, 1, 0.24609375, 0.49609375) + end + end + + if (object.onenter_backdrop_border_color) then + button:SetBackdropBorderColor(unpack(object.onenter_backdrop_border_color)) + end + + if (object.onenter_backdrop) then + button:SetBackdropColor(unpack(object.onenter_backdrop)) + end + + object:ShowTooltip() + end + + local OnLeave = function(button) + local object = button.MyObject + + local kill = object:RunHooksForWidget("OnLeave", button, object) + if (kill) then + return + end + + object.is_mouse_over = false + + if (button.texture and not object.is_mouse_down) then + if (button.texture.coords) then + button.texture:SetTexCoord(unpack(button.texture.coords.Normal)) + else + button.texture:SetTexCoord(0, 1, 0, 0.24609375) + end + end + + if (object.onleave_backdrop_border_color) then + button:SetBackdropBorderColor(unpack(object.onleave_backdrop_border_color)) + end + + if (object.onleave_backdrop) then + button:SetBackdropColor(unpack(object.onleave_backdrop)) + end + + object:HideTooltip() + end + + local OnHide = function(button) + local object = button.MyObject + local kill = object:RunHooksForWidget("OnHide", button, object) + if (kill) then + return + end + end + + local OnShow = function(button) + local object = button.MyObject + local kill = object:RunHooksForWidget("OnShow", button, object) + if (kill) then + return + end + end + + local OnMouseDown = function(button, buttontype) + if (not button:IsEnabled()) then + return + end + + local object = button.MyObject + + local kill = object:RunHooksForWidget("OnMouseDown", button, object) + if (kill) then + return + end + + object.is_mouse_down = true + + if (button.texture) then + if (button.texture.coords) then + button.texture:SetTexCoord(unpack(button.texture.coords.Pushed)) + else + button.texture:SetTexCoord(0, 1, 0.5078125, 0.75) + end + end + + if (object.capsule_textalign) then + if (object.icon) then + object.icon:SetPoint("left", button, "left", 5 + (object.icon.leftpadding or 0), -1) + + elseif (object.capsule_textalign == "left") then + button.text:SetPoint("left", button, "left", 3, -1) + + elseif (object.capsule_textalign == "center") then + button.text:SetPoint("center", button, "center", 1, -1) + + elseif (object.capsule_textalign == "right") then + button.text:SetPoint("right", button, "right", -1, -1) + end + else + if (object.icon) then + object.icon:SetPoint("left", button, "left", 5 + (object.icon.leftpadding or 0), -1) + else + button.text:SetPoint("center", button,"center", 1, -1) + end + end + + button.mouse_down = GetTime() + local x, y = GetCursorPosition() + button.x = math.floor(x) + button.y = math.floor(y) + + if (not object.container.isLocked and object.container:IsMovable()) then + if (not button.isLocked and button:IsMovable()) then + object.container.isMoving = true + object.container:StartMoving() + end + end + + if (object.options.OnGrab) then + if (type(object.options.OnGrab) == "string" and object.options.OnGrab == "PassClick") then + if (buttontype == "LeftButton") then + detailsFramework:CoreDispatch((button:GetName() or "Button") .. ":OnMouseDown()", object.func, button, buttontype, object.param1, object.param2) + else + detailsFramework:CoreDispatch((button:GetName() or "Button") .. ":OnMouseDown()", object.funcright, button, buttontype, object.param1, object.param2) + end + end + end + end + + local OnMouseUp = function(button, buttonType) + if (not button:IsEnabled()) then + return + end + + local object = button.MyObject + + local kill = object:RunHooksForWidget("OnMouseUp", button, object) + if (kill) then + return + end + + object.is_mouse_down = false + + if (button.texture) then + if (button.texture.coords) then + if (object.is_mouse_over) then + button.texture:SetTexCoord(unpack(button.texture.coords.Highlight)) + else + button.texture:SetTexCoord(unpack(coords.Normal)) + end + else + if (object.is_mouse_over) then + button.texture:SetTexCoord(0, 1, 0.24609375, 0.49609375) + else + button.texture:SetTexCoord(0, 1, 0, 0.24609375) + end + end + end + + if (object.capsule_textalign) then + if (object.icon) then + object.icon:SetPoint("left", button, "left", 4 + (object.icon.leftpadding or 0), 0) + + elseif (object.capsule_textalign == "left") then + button.text:SetPoint("left", button, "left", 2, 0) + + elseif (object.capsule_textalign == "center") then + button.text:SetPoint("center", button, "center", 0, 0) + + elseif (object.capsule_textalign == "right") then + button.text:SetPoint("right", button, "right", -2, 0) + end + else + if (object.icon) then + object.icon:SetPoint("left", button, "left", 4 + (object.icon.leftpadding or 0), 0) + else + button.text:SetPoint("center", button,"center", 0, 0) + end + end + + if (object.container.isMoving) then + object.container:StopMovingOrSizing() + object.container.isMoving = false + end + + local x, y = GetCursorPosition() + x = math.floor(x) + y = math.floor(y) + + button.mouse_down = button.mouse_down or 0 --avoid issues when the button was pressed while disabled and release when enabled + + if ((x == button.x and y == button.y) or (button.mouse_down + 0.5 > GetTime() and button:IsMouseOver())) then + if (buttonType == "LeftButton") then + detailsFramework:CoreDispatch((button:GetName() or "Button") .. ":OnMouseUp()", object.func, button, buttonType, object.param1, object.param2) + else + detailsFramework:CoreDispatch((button:GetName() or "Button") .. ":OnMouseUp()", object.funcright, button, buttonType, object.param1, object.param2) + end + end + end + +------------------------------------------------------------------------------------------------------------ + +---receives a table where the keys are settings and the values are the values to set +---this is the list of keys the table support: +---width, height, icon|table, textcolor, textsize, textfont, textalign, backdrop, backdropcolor, backdropbordercolor, onentercolor, onleavecolor, onenterbordercolor, onleavebordercolor +---@param template table +function ButtonMetaFunctions:SetTemplate(template) + if (type(template) == "string") then + template = detailsFramework:GetTemplate("button", template) + end + + if (not template) then + detailsFramework:Error("template not found") + return + end + + if (template.width) then + self:SetWidth(template.width) + end + + if (template.height) then + self:SetHeight(template.height) + end + + if (template.backdrop) then + self:SetBackdrop(template.backdrop) + end + + if (template.backdropcolor) then + local r, g, b, a = detailsFramework:ParseColors(template.backdropcolor) + self:SetBackdropColor(r, g, b, a) + self.onleave_backdrop = {r, g, b, a} + end + + if (template.backdropbordercolor) then + local r, g, b, a = detailsFramework:ParseColors(template.backdropbordercolor) + self:SetBackdropBorderColor(r, g, b, a) + self.onleave_backdrop_border_color = {r, g, b, a} + end + + if (template.onentercolor) then + local r, g, b, a = detailsFramework:ParseColors(template.onentercolor) + self.onenter_backdrop = {r, g, b, a} + end + + if (template.onleavecolor) then + local r, g, b, a = detailsFramework:ParseColors(template.onleavecolor) + self.onleave_backdrop = {r, g, b, a} + end + + if (template.onenterbordercolor) then + local r, g, b, a = detailsFramework:ParseColors(template.onenterbordercolor) + self.onenter_backdrop_border_color = {r, g, b, a} + end + + if (template.onleavebordercolor) then + local r, g, b, a = detailsFramework:ParseColors(template.onleavebordercolor) + self.onleave_backdrop_border_color = {r, g, b, a} + end + + if (template.icon) then + local iconInfo = template.icon + self:SetIcon(iconInfo.texture, iconInfo.width, iconInfo.height, iconInfo.layout, iconInfo.texcoord, iconInfo.color, iconInfo.textdistance, iconInfo.leftpadding) + end + + if (template.textsize) then + self.textsize = template.textsize + end + + if (template.textfont) then + self.textfont = template.textfont + end + + if (template.textcolor) then + self.textcolor = template.textcolor + end + + if (template.textalign) then + self.textalign = template.textalign + end +end + +------------------------------------------------------------------------------------------------------------ +--object constructor + local onDisableFunc = function(self) + self.texture_disabled:Show() + self.texture_disabled:SetVertexColor(0, 0, 0) + self.texture_disabled:SetAlpha(.5) + end + + local onEnableFunc = function(self) + self.texture_disabled:Hide() + end + + local createButtonWidgets = function(self) + self:SetSize(100, 20) + + self.text = self:CreateFontString("$parent_Text", "ARTWORK", "GameFontNormal") + self.text:SetJustifyH("CENTER") + self.text:SetPoint("CENTER", self, "CENTER", 0, 0) + self:SetFontString(self.text) + detailsFramework:SetFontSize(self.text, 10) + + self.texture_disabled = self:CreateTexture("$parent_TextureDisabled", "OVERLAY") + self.texture_disabled:SetAllPoints() + self.texture_disabled:Hide() + self.texture_disabled:SetTexture("Interface\\Tooltips\\UI-Tooltip-Background") + + self:SetScript("OnDisable", onDisableFunc) + self:SetScript("OnEnable", onEnableFunc) + end + + ---@class df_button : button + ---@field tooltip string + ---@field shown boolean + ---@field width number + ---@field height number + ---@field text string + ---@field clickfunction function + ---@field texture string + ---@field locked boolean + ---@field fontcolor any + ---@field fontface string + ---@field fontsize number + ---@field textcolor any + ---@field textfont string + ---@field textsize number + ---@field SetTemplate fun(self: df_button, template: table) set the button visual by a template + ---@field RightClick fun(self: df_button) right click the button executing its right click function + ---@field Exec fun(self: df_button) execute the button function for the left button + ---@field Disable fun(self: df_button) disable the button + ---@field Enable fun(self: df_button) enable the button + ---@field IsEnabled fun(self: df_button) : boolean returns true if the button is enabled + ---@field SetIcon fun(self: df_button,texture: string, width: number|nil, height: number|nil, layout: string|nil, texcoord: table|nil, overlay: table|nil, textDistance: number|nil, leftPadding: number|nil, textHeight: number|nil, shortMethod: any|nil) + ---@field GetIconTexture fun(self: df_button) : string returns the texture path of the button icon + ---@field SetTexture fun(self: df_button, normalTexture: string, highlightTexture: string, pressedTexture: string, disabledTexture: string) set the regular button textures + ---@field SetFontFace fun(self: df_button, font: string) set the button font + ---@field SetFontSize fun(self: df_button, size: number) set the button font size + ---@field SetTextColor fun(self: df_button, color: any) set the button text color + ---@field SetText fun(self: df_button, text: string) set the button text + ---@field SetClickFunction fun(self: df_button, func: function, param1: any, param2: any, clickType: "left"|"right"|nil) + + ---create a Details Framework button + ---@param parent table + ---@param func function + ---@param width number + ---@param height number + ---@param text string + ---@param param1 any|nil + ---@param param2 any|nil + ---@param texture any|nil + ---@param member string|nil + ---@param name string|nil + ---@param shortMethod boolean|nil + ---@param buttonTemplate table|nil + ---@param textTemplate table|nil + ---@return df_button + function detailsFramework:CreateButton(parent, func, width, height, text, param1, param2, texture, member, name, shortMethod, buttonTemplate, textTemplate) + return detailsFramework:NewButton(parent, parent, name, member, width, height, func, param1, param2, texture, text, shortMethod, buttonTemplate, textTemplate) + end + + ---@return df_button + function detailsFramework:NewButton(parent, container, name, member, width, height, func, param1, param2, texture, text, shortMethod, buttonTemplate, textTemplate) + if (not name) then + name = "DetailsFrameworkButtonNumber" .. detailsFramework.ButtonCounter + detailsFramework.ButtonCounter = detailsFramework.ButtonCounter + 1 + + elseif (not parent) then + error("Details! FrameWork: parent not found.", 2) + end + + if (name:find("$parent")) then + local parentName = detailsFramework.GetParentName(parent) + name = name:gsub("$parent", parentName) + end + + local buttonObject = {type = "button", dframework = true} + + if (member) then + parent[member] = buttonObject + end + + if (parent.dframework) then + parent = parent.widget + end + + --container is used to move the 'container' frame when attempt to move the button + buttonObject.container = container or parent + + --default members + buttonObject.is_locked = true + buttonObject.options = {OnGrab = false} + + buttonObject.button = CreateFrame("button", name, parent, "BackdropTemplate") + detailsFramework:Mixin(buttonObject.button, detailsFramework.WidgetFunctions) + + createButtonWidgets(buttonObject.button) + buttonObject.button:SetSize(width or 100, height or 20) + buttonObject.widget = buttonObject.button + buttonObject.button.MyObject = buttonObject + + if (not APIButtonFunctions) then + APIButtonFunctions = true + local idx = getmetatable(buttonObject.button).__index + for funcName, funcAddress in pairs(idx) do + if (not ButtonMetaFunctions[funcName]) then + ButtonMetaFunctions[funcName] = function(object, ...) + local x = loadstring("return _G['"..object.button:GetName().."']:"..funcName.."(...)") + return x(...) + end + end + end + end + + buttonObject.text_overlay = _G[name .. "_Text"] + buttonObject.disabled_overlay = _G[name .. "_TextureDisabled"] + + texture = texture or "" + buttonObject.button:SetNormalTexture(texture) + buttonObject.button:SetPushedTexture(texture) + buttonObject.button:SetDisabledTexture(texture) + buttonObject.button:SetHighlightTexture(texture, "ADD") + + local locTable = text + detailsFramework.Language.SetTextWithLocTableWithDefault(buttonObject.button.text, locTable, text) + + buttonObject.button.text:SetPoint("center", buttonObject.button, "center") + + local textWidth = buttonObject.button.text:GetStringWidth() + if (textWidth > width - 15 and buttonObject.button.text:GetText() ~= "") then + if (shortMethod == false) then --if is false, do not use auto resize + --do nothing + elseif (not shortMethod) then --if the value is omitted, use the default resize + local new_width = textWidth + 15 + buttonObject.button:SetWidth(new_width) + + elseif (shortMethod == 1) then + local loop = true + local textsize = 11 + while (loop) do + if (textWidth + 15 < width or textsize < 8) then + loop = false + break + else + detailsFramework:SetFontSize(buttonObject.button.text, textsize) + textWidth = buttonObject.button.text:GetStringWidth() + textsize = textsize - 1 + end + end + elseif (shortMethod == 2) then + + end + end + + buttonObject.func = func or emptyFunction + buttonObject.funcright = emptyFunction + buttonObject.param1 = param1 + buttonObject.param2 = param2 + buttonObject.short_method = shortMethod + + if (textTemplate) then + if (textTemplate.size) then + detailsFramework:SetFontSize(buttonObject.button.text, textTemplate.size) + end + + if (textTemplate.color) then + local r, g, b, a = detailsFramework:ParseColors(textTemplate.color) + buttonObject.button.text:SetTextColor(r, g, b, a) + end + + if (textTemplate.font) then + local SharedMedia = LibStub:GetLibrary("LibSharedMedia-3.0") + local font = SharedMedia:Fetch("font", textTemplate.font) + detailsFramework:SetFontFace(buttonObject.button.text, font) + end + end + + --hooks + buttonObject.HookList = { + OnEnter = {}, + OnLeave = {}, + OnHide = {}, + OnShow = {}, + OnMouseDown = {}, + OnMouseUp = {}, + } + + buttonObject.button:SetScript("OnEnter", OnEnter) + buttonObject.button:SetScript("OnLeave", OnLeave) + buttonObject.button:SetScript("OnHide", OnHide) + buttonObject.button:SetScript("OnShow", OnShow) + buttonObject.button:SetScript("OnMouseDown", OnMouseDown) + buttonObject.button:SetScript("OnMouseUp", OnMouseUp) + + setmetatable(buttonObject, ButtonMetaFunctions) + + if (buttonTemplate) then + buttonObject:SetTemplate(buttonTemplate) + end + + return buttonObject + end + +------------------------------------------------------------------------------------------------------------ +--color picker button + local pickcolorCallback = function(self, red, green, blue, alpha, button) + alpha = math.abs(alpha - 1) + button.MyObject.color_texture:SetVertexColor(red, green, blue, alpha) + + --safecall + detailsFramework:CoreDispatch((self:GetName() or "ColorPicker") .. ".pickcolor_callback()", button.MyObject.color_callback, button.MyObject, red, green, blue, alpha) + button.MyObject:RunHooksForWidget("OnColorChanged", button.MyObject, red, green, blue, alpha) + end + + local pickcolor = function(self) + local red, green, blue, alpha = self.MyObject.color_texture:GetVertexColor() + alpha = math.abs(alpha - 1) + detailsFramework:ColorPick(self, red, green, blue, alpha, pickcolorCallback) + end + + local setColorPickColor = function(button, ...) + local red, green, blue, alpha = detailsFramework:ParseColors(...) + button.color_texture:SetVertexColor(red, green, blue, alpha) + end + + local colorpickCancel = function(self) + ColorPickerFrame:Hide() + end + + local getColorPickColor = function(self) + return self.color_texture:GetVertexColor() + end + + ---create a button which opens a color picker when clicked + ---@param parent table + ---@param name string|nil + ---@param member string|nil + ---@param callback function + ---@param alpha number|nil + ---@param buttonTemplate table|nil + ---@return table|nil + function detailsFramework:CreateColorPickButton(parent, name, member, callback, alpha, buttonTemplate) + return detailsFramework:NewColorPickButton(parent, name, member, callback, alpha, buttonTemplate) + end + + function detailsFramework:NewColorPickButton(parent, name, member, callback, alpha, buttonTemplate) + --button + local colorPickButton = detailsFramework:NewButton(parent, _, name, member, 16, 16, pickcolor, alpha, "param2", nil, nil, nil, buttonTemplate) + colorPickButton.color_callback = callback + colorPickButton.Cancel = colorpickCancel + colorPickButton.SetColor = setColorPickColor + colorPickButton.GetColor = getColorPickColor + + colorPickButton.HookList.OnColorChanged = {} + + if (not buttonTemplate) then + colorPickButton:SetTemplate(detailsFramework:GetTemplate("button", "OPTIONS_BUTTON_TEMPLATE")) + end + + --background showing a grid to indicate the transparency + local background = colorPickButton:CreateTexture(nil, "background", nil, 2) + background:SetPoint("topleft", colorPickButton.widget, "topleft", 0, 0) + background:SetPoint("bottomright", colorPickButton.widget, "bottomright", 0, 0) + background:SetTexture([[Interface\ITEMSOCKETINGFRAME\UI-EMPTYSOCKET]]) + background:SetTexCoord(3/16, 13/16, 3/16, 13/16) + background:SetAlpha(0.3) + + --texture which shows the texture color + local colorTexture = detailsFramework:NewImage(colorPickButton, nil, 16, 16, nil, nil, "color_texture", "$parentTex") + colorTexture:SetColorTexture(1, 1, 1) + colorTexture:SetPoint("topleft", colorPickButton.widget, "topleft", 0, 0) + colorTexture:SetPoint("bottomright", colorPickButton.widget, "bottomright", 0, 0) + colorTexture:SetDrawLayer("background", 3) + + return colorPickButton + end + + function detailsFramework:SetRegularButtonTexture(button, texture, left, right, top, bottom) + if (type(left) == "table") then + left, right, top, bottom = unpack(left) + end + + if (not left) then + left, right, top, bottom = 0, 1, 0, 1 + end + + local atlas + if (type(texture) == "string") then + atlas = C_Texture.GetAtlasInfo(texture) + end + + local normalTexture = button:GetNormalTexture() + local pushedTexture = button:GetPushedTexture() + local highlightTexture = button:GetHightlightTexture() + local disabledTexture = button:GetDisabledTexture() + + if (atlas) then + normalTexture:SetAtlas(texture) + pushedTexture:SetAtlas(texture) + highlightTexture:SetAtlas(texture) + disabledTexture:SetAtlas(texture) + else + normalTexture:SetTexture(texture) + pushedTexture:SetTexture(texture) + highlightTexture:SetTexture(texture) + disabledTexture:SetTexture(texture) + normalTexture:SetTexCoord(left, right, top, bottom) + pushedTexture:SetTexCoord(left, right, top, bottom) + highlightTexture:SetTexCoord(left, right, top, bottom) + disabledTexture:SetTexCoord(left, right, top, bottom) + end + end + + function detailsFramework:SetRegularButtonVertexColor(button, ...) + local r, g, b, a = detailsFramework:ParseColor(...) + local normalTexture = button:GetNormalTexture() + local pushedTexture = button:GetPushedTexture() + local highlightTexture = button:GetHightlightTexture() + local disabledTexture = button:GetDisabledTexture() + + normalTexture:SetVertexColor(r, g, b, a) + pushedTexture:SetVertexColor(r, g, b, a) + highlightTexture:SetVertexColor(r, g, b, a) + disabledTexture:SetVertexColor(r, g, b, a) + end + + +------------------------------------------------------------------------------------------------------------ +--tab button + +---@class df_tabbutton : button +---@field LeftTexture texture +---@field RightTexture texture +---@field MiddleTexture texture +---@field SelectedTexture texture +---@field Text fontstring +---@field CloseButton df_closebutton +---@field leftTextureName string +---@field rightTextureName string +---@field middleTextureName string +---@field leftTextureSelectedName string +---@field rightTextureSelectedName string +---@field middleTextureSelectedName string +---@field bIsSelected boolean +---@field SetText fun(self: df_tabbutton, text: string) +---@field SetSelected fun(self: df_tabbutton, selected: boolean) +---@field IsSelected fun(self: df_tabbutton): boolean +---@field Reset fun(self: df_tabbutton) + +detailsFramework.TabButtonMixin = { + ---set the text of the tab button + ---@param self df_tabbutton + ---@param text string + SetText = function(self, text) + self.Text:SetText(text) + --adjust the width of the tab button to fit the text + local fontStringLength = self.Text:GetStringWidth() + self:SetWidth(fontStringLength + 20) + end, + + ---highlight the tab textures to indicate the tab is selected + ---@param self df_tabbutton + ---@param selected boolean + SetSelected = function(self, selected) + self.LeftTexture:SetAtlas(selected and self.leftTextureSelectedName or self.leftTextureName) + self.RightTexture:SetAtlas(selected and self.rightTextureSelectedName or self.rightTextureName) + self.MiddleTexture:SetAtlas(selected and self.middleTextureSelectedName or self.middleTextureName) + self.SelectedTexture:SetShown(selected) + self.bIsSelected = selected + end, + + ---get a boolean representing if the tab is selected + ---@param self df_tabbutton + ---@return boolean + IsSelected = function(self) + return self.bIsSelected + end, + + ---set all textures to their default values, set the text to an empty string, set the selected state to false + ---@param self df_tabbutton + Reset = function(self) + self.LeftTexture:SetAtlas(self.leftTextureName) + self.RightTexture:SetAtlas(self.rightTextureName) + self.MiddleTexture:SetAtlas(self.middleTextureName) + self.Text:SetText("") + self.bIsSelected = false + self.SelectedTexture:Hide() + end, + +} + +---create a button which can be used as a tab button, has textures for left, right, middle and a text +---@param parent frame +---@param frameName string|nil +---@return df_tabbutton +function detailsFramework:CreateTabButton(parent, frameName) + ---@type df_tabbutton + local tabButton = CreateFrame("button", frameName, parent) + tabButton:SetSize(50, 20) + tabButton.bIsSelected = false + + detailsFramework:Mixin(tabButton, detailsFramework.TabButtonMixin) + + tabButton.LeftTexture = tabButton:CreateTexture(nil, "artwork") + tabButton.RightTexture = tabButton:CreateTexture(nil, "artwork") + tabButton.MiddleTexture = tabButton:CreateTexture(nil, "artwork") + tabButton.SelectedTexture = tabButton:CreateTexture(nil, "overlay") + tabButton.SelectedTexture:SetBlendMode("ADD") + tabButton.SelectedTexture:SetAlpha(0.5) + tabButton.SelectedTexture:Hide() + tabButton.Text = tabButton:CreateFontString(nil, "overlay", "GameFontNormal") + tabButton.CloseButton = detailsFramework:CreateCloseButton(tabButton, "$parentCloseButton") + + tabButton.Text:SetPoint("center", tabButton, "center", 0, 0) + tabButton.CloseButton:SetPoint("topright", tabButton, "topright", 0, 0) + + tabButton.LeftTexture:SetPoint("bottomleft", tabButton, "bottomleft", 0, 0) + tabButton.LeftTexture:SetPoint("topleft", tabButton, "topleft", 0, 0) + + tabButton.RightTexture:SetPoint("bottomright", tabButton, "bottomright", 0, 0) + tabButton.RightTexture:SetPoint("topright", tabButton, "topright", 0, 0) + + tabButton.MiddleTexture:SetPoint("topleft", tabButton.LeftTexture, "topright", 0, 0) + tabButton.MiddleTexture:SetPoint("topright", tabButton.RightTexture, "topleft", 0, 0) + + tabButton.SelectedTexture:SetAllPoints(tabButton.MiddleTexture) + + tabButton.leftTextureName = "Options_Tab_Left" + tabButton.rightTextureName = "Options_Tab_Right" + tabButton.middleTextureName = "Options_Tab_Middle" + + tabButton.leftTextureSelectedName = "Options_Tab_Active_Left" + tabButton.rightTextureSelectedName = "Options_Tab_Active_Right" + tabButton.middleTextureSelectedName = "Options_Tab_Active_Middle" + + tabButton.LeftTexture:SetAtlas(tabButton.leftTextureName) + tabButton.LeftTexture:SetWidth(2) + + tabButton.RightTexture:SetAtlas(tabButton.rightTextureName) + tabButton.RightTexture:SetWidth(2) + + tabButton.MiddleTexture:SetAtlas(tabButton.middleTextureName) + tabButton.MiddleTexture:SetHeight(20) + + tabButton.SelectedTexture:SetTexture([[Interface\PaperDollInfoFrame\UI-Character-Tab-Highlight-yellow]]) + + tabButton.Text:SetText("") + + return tabButton +end + +------------------------------------------------------------------------------------------------------------ +--close button + +detailsFramework.CloseButtonMixin = { + OnClick = function(self) + self:GetParent():Hide() + end, + OnEnter = function(self) + self:GetNormalTexture():SetVertexColor(1, 0, 0) + end, + OnLeave = function(self) + self:GetNormalTexture():SetVertexColor(1, 1, 1) + end, +} + +---@class df_closebutton : button +---@field OnClick fun(self: df_closebutton) +---@field OnEnter fun(self: df_closebutton) +---@field OnLeave fun(self: df_closebutton) + +---create a close button which when clicked will hide the parent frame +---@param parent frame +---@param frameName string|nil +---@return df_closebutton +function detailsFramework:CreateCloseButton(parent, frameName) --make documentation + ---@type df_closebutton + local closeButton = CreateFrame("button", frameName, parent, "UIPanelCloseButton") + closeButton:SetFrameLevel(parent:GetFrameLevel() + 1) + closeButton:SetSize(16, 16) + + detailsFramework:Mixin(closeButton, detailsFramework.CloseButtonMixin) + + local normalTexture = closeButton:GetNormalTexture() + local pushedTexture = closeButton:GetPushedTexture() + local highlightTexture = closeButton:GetHighlightTexture() + local disabledTexture = closeButton:GetDisabledTexture() + + normalTexture:SetAtlas("RedButton-Exit") + highlightTexture:SetAtlas("RedButton-Highlight") + pushedTexture:SetAtlas("RedButton-exit-pressed") + disabledTexture:SetAtlas("RedButton-Exit-Disabled") + + normalTexture:SetDesaturated(true) + highlightTexture:SetDesaturated(true) + pushedTexture:SetDesaturated(true) + + closeButton:SetAlpha(0.7) + closeButton:SetScript("OnClick", closeButton.OnClick) + closeButton:SetScript("OnEnter", closeButton.OnEnter) + closeButton:SetScript("OnLeave", closeButton.OnLeave) + + return closeButton +end + +--[=[ + --example: + local frame = CreateFrame("frame", "MyTestFrameForCloseButton", UIParent) + frame:SetSize(200, 200) + frame:SetPoint("center", UIParent, "center", 0, 0) + + local closeButton = detailsFramework:CreateCloseButton(frame, "$parentCloseButton") + closeButton:SetPoint("topright", frame, "topright", 0, 0) +--]=] \ No newline at end of file diff --git a/plugins/Details_EncounterDetails/Libs/DF/button.xml b/plugins/Details_EncounterDetails/Libs/DF/button.xml new file mode 100644 index 00000000..aa885f31 --- /dev/null +++ b/plugins/Details_EncounterDetails/Libs/DF/button.xml @@ -0,0 +1,3 @@ + +