Thread Tools Display Modes
02-17-17, 09:41 PM   #1
Mythricia
A Murloc Raider
 
Mythricia's Avatar
Join Date: Feb 2017
Posts: 6
Angry Programmatically determine instance expansion?

Heyo, new-ish addon dev here wading my way through the WoW API and Lua.

So far so good, although today I spent basically the entire day trying to do what the title suggests: Determine which expansion the instance you're currently inside, belongs to.

Somewhat of a mouthful of a sentence, but the idea seems simple enough. Or so I thought, but I've yet to find a way.

I got close using some of the Encounter Journal API: EJ_GetTierInfo() returns the full written name of the expansion, provided a "tier", such as 1 (Classic), 2 (Burning Crusade) and so on. And, you can use EJ_GetCurrentTier() to get the tier of the current instance... Except not really.

For some bizarre reason, despite GetCurrentInstance returning the current instance that the player is actually inside, GetCurrentTier doesn't. It returns the "tier" selected in the Encounter Journal! And that, in turn, is sadly not consistent. If you enter an instance, it does not change - meaning something like;
Lua Code:
  1. local instanceExp = EJ_GetTierInfo(EJ_GetCurrentTier())
^ Doesn't return the expected expansion, although it does return an expansion, just not related at all to the instance you're currently inside. And as far as I know, there's no way to force the EJ to set itself to the current instance tier, so there's no way to force an update the same way we do with the world map to get current player position for example... I looked at Blizzards own EJ code, and they do exactly the above query to initialize the EJ interface, but I suspect they have the same results and just don't worry about it.

TL;DR - I can't for the life of me figure out a way to do this. I really, really really really really don't want to have to maintain a hand-written table of Instance ID/Name -> Expansion relations... Prone to typos, mis-spellings, needs to be updated by hand every time something changes or new content comes out.. Just no. I auto-generate a table of continent names purely programmatically due to this exact reason :\

Anybody has any secret sauce that could help this?
  Reply With Quote
02-18-17, 03:20 AM   #2
briskman3000
A Flamescale Wyrmkin
 
briskman3000's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2009
Posts: 108
Your current way of doing what you want won't work the way you want it to, because those functions are designed around the encounter journal.

Something along these lines can get you started. This "should" print the name of the expansion assigned to the instance you zone into in the chat frame.

You will have to register it to PLAYER_ENTERING_WORLD

Lua Code:
  1. local function GetExpansion(self)
  2.     inInstance = IsInInstance()
  3.         if inInstance ~= nil then
  4.             instanceID = EJ_GetCurrentInstance()
  5.             EncounterJournal_OpenJournal(2, instanceID)
  6.             tierID = EJ_GetCurrentTier()
  7.             tierName = EJ_GetTierInfo(tierID)
  8.             print(tierName)
  9.         end
  10. end


Its a little wonky as it should open the Encounter Journal every time you zone in to an instance, but since I don't see another way to get what you are looking for, its a start at least.
__________________
My Addons: Convert Ratings Honor Track

Last edited by briskman3000 : 02-18-17 at 03:26 AM.
  Reply With Quote
02-18-17, 11:37 AM   #3
semlar
A Pyroguard Emberseer
 
semlar's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2007
Posts: 1,060
How do you intend to handle instances like Scholomance, which was a classic instance, but recreated in Mists of Pandaria?
  Reply With Quote
02-18-17, 03:23 PM   #4
briskman3000
A Flamescale Wyrmkin
 
briskman3000's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2009
Posts: 108
Originally Posted by semlar View Post
How do you intend to handle instances like Scholomance, which was a classic instance, but recreated in Mists of Pandaria?
Yea, even if my above code works, which I'm not 100% confident it will, instances that have been remade in a later xpac will report the wrong tier.

What exactly are you planning on doing with this info?
__________________
My Addons: Convert Ratings Honor Track
  Reply With Quote
02-18-17, 05:13 PM   #5
Ketho
A Pyroguard Emberseer
 
Ketho's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2010
Posts: 1,026
Originally Posted by Mythricia View Post
Determine which expansion the instance you're currently inside, belongs to.

You can build a list of instance ids with EJ_SelectTier and EJ_GetInstanceByIndex
I don't know when you need that information (loadondemand/events?) but here is an example
Lua Code:
  1. local instances = {}
  2.  
  3. local function GetInstances(showRaid)
  4.     for tier = 1, 7 do
  5.         EJ_SelectTier(tier)
  6.         local index = 1
  7.         local instanceID, name = EJ_GetInstanceByIndex(index, showRaid)
  8.        
  9.         while instanceID do
  10.             instances[instanceID] = tier
  11.             index = index + 1
  12.             instanceID, name = EJ_GetInstanceByIndex(index, showRaid)
  13.         end
  14.     end
  15. end
  16.  
  17. local function GetInstanceTier()
  18.     if not next(instances) then
  19.         GetInstances(false)
  20.         GetInstances(true)
  21.     end
  22.     return instances[EJ_GetCurrentInstance()]
  23. end
  24.  
  25. --print("Current instance tier is "..EJ_GetTierInfo(GetInstanceTier()))
Lua Code:
  1. local dungeon = {
  2.     [63] = 4, -- "Deadmines"
  3.     [64] = 4, -- "Shadowfang Keep"
  4.     [65] = 4, -- "Throne of the Tides"
  5.     [66] = 4, -- "Blackrock Caverns"
  6.     [67] = 4, -- "The Stonecore"
  7.     [68] = 4, -- "The Vortex Pinnacle"
  8.     [69] = 4, -- "Lost City of the Tol'vir"
  9.     [70] = 4, -- "Halls of Origination"
  10.     [71] = 4, -- "Grim Batol"
  11.     [76] = 4, -- "Zul'Gurub"
  12.     [77] = 4, -- "Zul'Aman"
  13.     [184] = 4, -- "End Time"
  14.     [185] = 4, -- "Well of Eternity"
  15.     [186] = 4, -- "Hour of Twilight"
  16.     [226] = 1, -- "Ragefire Chasm"
  17.     [227] = 1, -- "Blackfathom Deeps"
  18.     [228] = 1, -- "Blackrock Depths"
  19.     [229] = 1, -- "Lower Blackrock Spire"
  20.     [230] = 1, -- "Dire Maul"
  21.     [231] = 1, -- "Gnomeregan"
  22.     [232] = 1, -- "Maraudon"
  23.     [233] = 1, -- "Razorfen Downs"
  24.     [234] = 1, -- "Razorfen Kraul"
  25.     [236] = 1, -- "Stratholme"
  26.     [237] = 1, -- "The Temple of Atal'hakkar"
  27.     [238] = 1, -- "The Stockade"
  28.     [239] = 1, -- "Uldaman"
  29.     [240] = 1, -- "Wailing Caverns"
  30.     [241] = 1, -- "Zul'Farrak"
  31.     [246] = 5, -- "Scholomance"
  32.     [247] = 2, -- "Auchenai Crypts"
  33.     [248] = 2, -- "Hellfire Ramparts"
  34.     [249] = 2, -- "Magisters' Terrace"
  35.     [250] = 2, -- "Mana-Tombs"
  36.     [251] = 2, -- "Old Hillsbrad Foothills"
  37.     [252] = 2, -- "Sethekk Halls"
  38.     [253] = 2, -- "Shadow Labyrinth"
  39.     [254] = 2, -- "The Arcatraz"
  40.     [255] = 2, -- "The Black Morass"
  41.     [256] = 2, -- "The Blood Furnace"
  42.     [257] = 2, -- "The Botanica"
  43.     [258] = 2, -- "The Mechanar"
  44.     [259] = 2, -- "The Shattered Halls"
  45.     [260] = 2, -- "The Slave Pens"
  46.     [261] = 2, -- "The Steamvault"
  47.     [262] = 2, -- "The Underbog"
  48.     [271] = 3, -- "Ahn'kahet: The Old Kingdom"
  49.     [272] = 3, -- "Azjol-Nerub"
  50.     [273] = 3, -- "Drak'Tharon Keep"
  51.     [274] = 3, -- "Gundrak"
  52.     [275] = 3, -- "Halls of Lightning"
  53.     [276] = 3, -- "Halls of Reflection"
  54.     [277] = 3, -- "Halls of Stone"
  55.     [278] = 3, -- "Pit of Saron"
  56.     [279] = 3, -- "The Culling of Stratholme"
  57.     [280] = 3, -- "The Forge of Souls"
  58.     [281] = 3, -- "The Nexus"
  59.     [282] = 3, -- "The Oculus"
  60.     [283] = 3, -- "The Violet Hold"
  61.     [284] = 3, -- "Trial of the Champion"
  62.     [285] = 3, -- "Utgarde Keep"
  63.     [286] = 3, -- "Utgarde Pinnacle"
  64.     [302] = 5, -- "Stormstout Brewery"
  65.     [303] = 5, -- "Gate of the Setting Sun"
  66.     [311] = 5, -- "Scarlet Halls"
  67.     [312] = 5, -- "Shado-Pan Monastery"
  68.     [313] = 5, -- "Temple of the Jade Serpent"
  69.     [316] = 5, -- "Scarlet Monastery"
  70.     [321] = 5, -- "Mogu'shan Palace"
  71.     [324] = 5, -- "Siege of Niuzao Temple"
  72.     [385] = 6, -- "Bloodmaul Slag Mines"
  73.     [476] = 6, -- "Skyreach"
  74.     [536] = 6, -- "Grimrail Depot"
  75.     [537] = 6, -- "Shadowmoon Burial Grounds"
  76.     [547] = 6, -- "Auchindoun"
  77.     [556] = 6, -- "The Everbloom"
  78.     [558] = 6, -- "Iron Docks"
  79.     [559] = 6, -- "Upper Blackrock Spire"
  80.     [707] = 7, -- "Vault of the Wardens"
  81.     [716] = 7, -- "Eye of Azshara"
  82.     [721] = 7, -- "Halls of Valor"
  83.     [726] = 7, -- "The Arcway"
  84.     [727] = 7, -- "Maw of Souls"
  85.     [740] = 7, -- "Black Rook Hold"
  86.     [762] = 7, -- "Darkheart Thicket"
  87.     [767] = 7, -- "Neltharion's Lair"
  88.     [777] = 7, -- "Assault on Violet Hold"
  89.     [800] = 7, -- "Court of Stars"
  90.     [860] = 7, -- "Return to Karazhan"
  91. }
  92.  
  93. local raid = {
  94.     [72] = 4, -- "The Bastion of Twilight"
  95.     [73] = 4, -- "Blackwing Descent"
  96.     [74] = 4, -- "Throne of the Four Winds"
  97.     [75] = 4, -- "Baradin Hold"
  98.     [78] = 4, -- "Firelands"
  99.     [187] = 4, -- "Dragon Soul"
  100.     [317] = 5, -- "Mogu'shan Vaults"
  101.     [320] = 5, -- "Terrace of Endless Spring"
  102.     [322] = 5, -- "Pandaria"
  103.     [330] = 5, -- "Heart of Fear"
  104.     [362] = 5, -- "Throne of Thunder"
  105.     [369] = 5, -- "Siege of Orgrimmar"
  106.     [457] = 6, -- "Blackrock Foundry"
  107.     [477] = 6, -- "Highmaul"
  108.     [557] = 6, -- "Draenor"
  109.     [669] = 6, -- "Hellfire Citadel"
  110.     [741] = 1, -- "Molten Core"
  111.     [742] = 1, -- "Blackwing Lair"
  112.     [743] = 1, -- "Ruins of Ahn'Qiraj"
  113.     [744] = 1, -- "Temple of Ahn'Qiraj"
  114.     [745] = 2, -- "Karazhan"
  115.     [746] = 2, -- "Gruul's Lair"
  116.     [747] = 2, -- "Magtheridon's Lair"
  117.     [748] = 2, -- "Serpentshrine Cavern"
  118.     [749] = 2, -- "The Eye"
  119.     [750] = 2, -- "The Battle for Mount Hyjal"
  120.     [751] = 2, -- "Black Temple"
  121.     [752] = 2, -- "Sunwell Plateau"
  122.     [753] = 3, -- "Vault of Archavon"
  123.     [754] = 3, -- "Naxxramas"
  124.     [755] = 3, -- "The Obsidian Sanctum"
  125.     [756] = 3, -- "The Eye of Eternity"
  126.     [757] = 3, -- "Trial of the Crusader"
  127.     [758] = 3, -- "Icecrown Citadel"
  128.     [759] = 3, -- "Ulduar"
  129.     [760] = 3, -- "Onyxia's Lair"
  130.     [761] = 3, -- "The Ruby Sanctum"
  131.     [768] = 7, -- "The Emerald Nightmare"
  132.     [786] = 7, -- "The Nighthold"
  133.     [822] = 7, -- "Broken Isles"
  134.     [861] = 7, -- "Trial of Valor"
  135. }
Scholomance (1 & 5), Deadmines (1 & 4), etc get overwritten this way by the highest tier but you should indeed handle that too (e.g. DifficultyID)

Originally Posted by Mythricia View Post
And as far as I know, there's no way to force the EJ to set itself to the current instance tier, so there's no way to force an update the same way we do with the world map to get current player position

Not sure how it's usually done with the world map, but you can make the EJ set itself to the current dungeon (ref)
Unless you meant something else?
Lua Code:
  1. local function ResetDisplay()
  2.     local instanceID = EJ_GetCurrentInstance()
  3.     local _, instanceType, difficultyID = GetInstanceInfo()
  4.     EncounterJournal_ResetDisplay(instanceID, instanceType, difficultyID)
  5. end

Last edited by Ketho : 02-18-17 at 09:10 PM.
  Reply With Quote
02-18-17, 08:24 PM   #6
Mythricia
A Murloc Raider
 
Mythricia's Avatar
Join Date: Feb 2017
Posts: 6
Thanks a lot for the suggestions thus far, everyone!

I did arrive at the idea of generating a list of all instances indexing it by tier on demand, while I was away from the computer, that does seem to be a pretty good way of doing it, especially since it doesn't mess with the encounter journal, which I'd like to avoid since, well, the player may be using it, have something selected, etc, and I don't want to mess with that. I should be able to just generate the list once per session (something I already do with continent names for example), so it should be fairly benign.



Originally Posted by briskman3000 View Post
Your current way of doing what you want won't work the way you want it to, because those functions are designed around the encounter journal.

Something along these lines can get you started. This "should" print the name of the expansion assigned to the instance you zone into in the chat frame.

You will have to register it to PLAYER_ENTERING_WORLD

Lua Code:
  1. local function GetExpansion(self)
  2.     inInstance = IsInInstance()
  3.         if inInstance ~= nil then
  4.             instanceID = EJ_GetCurrentInstance()
  5.             EncounterJournal_OpenJournal(2, instanceID)
  6.             tierID = EJ_GetCurrentTier()
  7.             tierName = EJ_GetTierInfo(tierID)
  8.             print(tierName)
  9.         end
  10. end
This doesn't work, and is basically a roundabout way of doing what I already tried, which as you pointed out (and I also pointed out in the OP) doesn't actually work. This resets the journal to the correct instance, yes, but not the correct tier. This will happily print "You're inside Scholomance, from the Legion expansion"!


Originally Posted by Ketho View Post
Not sure how it's usually done with the world map, but you can make the EJ set itself to the current dungeon (ref)
Unless you meant something else?
Lua Code:
  1. local function ResetDisplay()
  2.     local instanceID = EJ_GetCurrentInstance()
  3.     local _, instanceType, difficultyID = GetInstanceInfo()
  4.     EncounterJournal_ResetDisplay(instanceID, instanceType, difficultyID)
  5. end

From my testing this is inconsistent at best, resetting the journal view after entering the instance doesn't have repeatable results, if the player has been browsing the journal beforehand. For instance, that ResetDisplay function Blizz themselves use, doesn't correctly reset the Tier, since there isn't actually a way to do that by function. As I said in the OP; GetCurrentTier gets the displayed tier, not the actual player tier. And as best I can find out, there's no way to actually *set* the tier, since .. well, you can't *get* the tier in the first place, so you don't know what to set it to.

It's basically the same problem as the other suggestion above, it all ends up with a catch 22. Need to know the tier so we can set the tier so we can know the tier.


How do you intend to handle instances like Scholomance, which was a classic instance, but recreated in Mists of Pandaria?
This is mostly a non-issue, I don't need historical accuracy, I just need a good way to categorize instances in some consistent and at least vaguely sensible fashion. If that means Scholomance gets listed twice, once for Classic and once for MoP, I don't mind (in fact that might be a good thing).



Originally Posted by briskman3000 View Post
Yea, even if my above code works, which I'm not 100% confident it will, instances that have been remade in a later xpac will report the wrong tier.

What exactly are you planning on doing with this info?

I'm basically creating a database of a characters activity over the course of their leveling experience (and after, potentially, but that's not the intent). Logging everything from zones visited, damage done, levelups, instances completed (what I'm working on right now), quests completed, and so on. Everything is logged in pretty high detail - for example I can extrapolate what my average active DPS was for level 67, and I know what zones I visted and how many times in that level, I know how many quests I completed in what zone, and what mob I killed the most of, etc...

I guess you could say I'm writing the NSA addon. But actually, there are good intentions behind it!

The database will be needed as a component of my actual addon, tentatively named "TellMyStory", which is an addon that will, through all this gathered data, once you hit max level (and assuming you've been running the addon since you created the character), generate a sort of short visual story of your leveling experience. Basically an animated infographic about what you did, when, how, and so on. It'll be able to dynamically figure out some fun facts, and present them in an interesting manner, while keeping it somewhat short (filtering what to show based on a rough "how interesting is this" metric)... Of course, for uber-nerds there will be a "Show me all the stats" button, that will be able to show .. well, all the stats, maybe graphs and pretty things, even those that weren't deemed "interesting" enough to show in the infographic.

Thus I need a lot of data, to be able to extrapolate a bunch of interesting stuff.

So that's what I'm doing right now, working on a data logging component. I might release that separately if there's any interest in it. All the raw collected data is stored in global table / SavedVariable anyhow, so it's not much of a stretch to build a bit of simplistic API on top.

Last edited by Mythricia : 02-18-17 at 08:39 PM.
  Reply With Quote
02-19-17, 02:58 PM   #7
JDoubleU00
A Firelord
 
JDoubleU00's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2008
Posts: 463
Your addon sound very interesting, one I would like to try. If you need beta testers, I would be happy to test it.
__________________
Author of JWExpBar and JWRepBar.
  Reply With Quote
02-19-17, 07:58 PM   #8
Mythricia
A Murloc Raider
 
Mythricia's Avatar
Join Date: Feb 2017
Posts: 6
It might take a good while before I have anything concrete to show, I'm learning Lua as I go, but I can definitively see needing some testing later on!
  Reply With Quote
02-20-17, 11:52 AM   #9
Yukyuk
A Chromatic Dragonspawn
 
Yukyuk's Avatar
AddOn Author - Click to view addons
Join Date: Apr 2015
Posts: 179
I also collect data for my own addon, Historia.

But nearly as much data as you are going to gather.
When you are ready to show your addon, I also will be happy to test.
__________________
Better to fail then never have tried at all.
  Reply With Quote
02-23-17, 03:43 AM   #10
Mythricia
A Murloc Raider
 
Mythricia's Avatar
Join Date: Feb 2017
Posts: 6
Alright, it took me 4 days, but I got it all working now. Figured I would share it. I've only been learning Lua and the WoW API for a couple weeks, and I'm a pretty novice programmer in the first place, so this probably took longer than it should have Any critique or hints from experienced peeps is welcome.

But the result is great. I can enter any raid or 5man instance from any expansion on any difficulty, and correctly determine what expansion it belongs to, without any hardcoded names, for neither instances nor expansions. This means, as long as the base API remains the same, this code should work for future expansions, dungeons, raids, without needing updating. In Theory™. Scenarios are not supported, but that's a separate problem all together.


This is the code, mind that this is basically a debug version written in isolation, I'm going to clean it up and refactor quite a bit later, but for now, it does what it needs to do. It's pretty littered with comments, for my own organizational sake. You should be able to copy paste this into WowLua and just run it.


In summary:

First, call GenerateInstanceTable() (no args), to generate the InstanceTable, which is a table of every instance name and instanceID, grouped by type (dungeon, raid) and expansion name.

Next, we call GetCurrentInstanceTier() (no args) and you'll get a string containing the in-game name of the expansion in return.

In this code, there are some debug things like returning "NotAnInstance" or "UnknownTier" and other weirdness if you're not actually inside an instance, but that was just for debugging.



Lua Code:
  1. -- Programmatically generate list of all dungeons and raids, to be used in determining what expansion
  2. -- the instance your are currently inside, actually belongs to.
  3.  
  4. -- Generate table of dungeon and raid instances by expansion
  5. function GenerateInstanceTable()
  6.    local instTable = {}
  7.  
  8.    instTable.trackedTypes = "party, raid"
  9.  
  10.    local numTiers = EJ_GetNumTiers()
  11.    local numToScan = 10000
  12.    local raid = false
  13.  
  14.    -- Run this twice, once for dungeons, once for raids
  15.    for b=1, 2 do
  16.       local instanceType = ""
  17.       if raid then instanceType = "Raids" else instanceType = "Dungeons" end
  18.       instTable[instanceType] = {}
  19.  
  20.       for t=1, numTiers do
  21.          EJ_SelectTier(t)
  22.          local tierName = EJ_GetTierInfo(t)
  23.          instTable[instanceType][tierName] = {}
  24.  
  25.          for i=1, numToScan do
  26.             local id, name = EJ_GetInstanceByIndex(i, raid)
  27.             if name then
  28.                instTable[instanceType][tierName][name] = id
  29.             end
  30.          end
  31.       end
  32.  
  33.       -- Flip state, do raids next round
  34.       raid = not raid
  35.    end
  36.  
  37.    return instTable
  38. end
  39.  
  40.  
  41. --[[Figure out which expansion our current instance belongs to.
  42.  
  43. Problem: Remade dungeons, such as Deadmines, belong to more than 1 expansion,
  44. but retain only one name and instanceID. Making a simple list of ID's insufficient.
  45.  
  46. At the time of writing (Legion), remade Vanilla dungeons are all Heroic variants.
  47. Meaning, if we enter a "vanilla" instance, on Heroic difficulty, it must be a remake.
  48. We can then simply skip scanning Vanilla, the next hit will accurately tell us our real tier.
  49.  
  50. This can break if something like a TBC instance is remade, for example, so this is a fragile approach.
  51. --]]
  52. function GetCurrentInstanceTier()
  53.    -- Check that the InstanceTable even exists, if not, create it
  54.    InstanceTable = InstanceTable or GenerateInstanceTable()
  55.  
  56.    -- Bail out if we're not even in an instance!
  57.    if not IsInInstance() then do return "NotAnInstance" end end
  58.  
  59.  
  60.    -- Generate a chronologically ordered list of expansion names
  61.    local tierList = (function()
  62.          local tt = {}
  63.          for i=1, EJ_GetNumTiers() do
  64.             tt[i] = EJ_GetTierInfo(i)
  65.          end
  66.          return tt
  67.    end)()
  68.  
  69.  
  70.    local name, instanceType, difficulty, difficultyName = GetInstanceInfo()
  71.    local instanceID = EJ_GetCurrentInstance()
  72.  
  73.    -- Determine the search key to be used. This should be refactored somehow.
  74.    local searchType = (
  75.       function()
  76.          if instanceType == "party" then
  77.             return "Dungeons"
  78.          elseif instanceType == "raid" then
  79.             return "Raids"
  80.          end
  81.       end
  82.    )()
  83.  
  84.    -- First, check if we even track this type of instance, if not, bail out
  85.    if not string.find(InstanceTable.trackedTypes, instanceType) then return "UnknownInstanceType" end
  86.  
  87.    -- Second, is it Heroic? If so, skip all of Vanilla. Else, search the entire instance table
  88.    local startIndex = (function()
  89.          if difficulty == 2 then
  90.             return 2
  91.          else return 1
  92.          end
  93.    end)()
  94.  
  95.  
  96.    -- Perform the actual search, scanning by instanceID, skipping Classic if we're in Heroic
  97.    for i = startIndex, #tierList do
  98.       subTable = InstanceTable[searchType][tierList[i]]
  99.  
  100.       for k, v in pairs(subTable) do
  101.          if (instanceID == v) then
  102.             return tierList[i]
  103.          end
  104.       end
  105.    end
  106.    return "UnknownTier"
  107. end
  108.  
  109.  
  110. -- Celebratory print()
  111. print("You are in \""..select(1,GetInstanceInfo()).."\ ("..select(4,GetInstanceInfo())..")\", from the \""..GetCurrentInstanceTier().."\" expansion.")

Last edited by Mythricia : 02-23-17 at 03:53 AM. Reason: Oops, bad variable naming, was potentially overriding lua globals. I'm bad.
  Reply With Quote
02-23-17, 05:16 AM   #11
Ketho
A Pyroguard Emberseer
 
Ketho's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2010
Posts: 1,026
never mind

Last edited by Ketho : 02-23-17 at 06:43 AM. Reason: i give up sorry
  Reply With Quote
02-23-17, 05:38 AM   #12
myrroddin
A Pyroguard Emberseer
 
myrroddin's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2008
Posts: 1,240
I don't understand what the extra () at the end of functions is doing. That is not a Lua thing.

And Ketho is correct, there are leaking global variables all over the place. I suggest using this tool to find them.
  Reply With Quote
02-23-17, 06:22 AM   #13
Layback_
An Onyxian Warder
Join Date: Feb 2016
Posts: 358
Just a quick question passing by..

What would be the actual purpose of EJ_SelectTier(index) function?

Neither WoWWiki nor Wowprogramming seem to document this function at the moment

I dumped this inside WoW, but looks like it does not return any output.



Also, should I install Lua on my PC first before using the tool suggested by myrroddin?

Last edited by Layback_ : 02-23-17 at 06:27 AM.
  Reply With Quote
02-23-17, 07:03 AM   #14
Mythricia
A Murloc Raider
 
Mythricia's Avatar
Join Date: Feb 2017
Posts: 6
Originally Posted by myrroddin View Post
I don't understand what the extra () at the end of functions is doing. That is not a Lua thing.

And Ketho is correct, there are leaking global variables all over the place. I suggest using this tool to find them.
Corrected this a few minutes after I posted the code since I noticed it while proofreading, they're all gone now. As for actually global variables of my own, they're not leaking anywhere, they're very much intended to be global tables and functions. Some were global just for testing. I did write in my post that this was just test code, not actual addon code.


As for the extra ()'s at the end of anonymous functions, try running the code without them. Doesn't run. That's why You need to encapsulate the function, to avoid creating a reference TO the function. I don't want that. I want a reference to the result of the function. And the function won't run if it's not called, so you need to call it, with (). This creates the awful syntax of (function() someCodeHere end)(), which is correct, you can find examples of this in other Lua docs.

Lua Code:
  1. > return function(x) return x*2 end
  2. function: 0x806b950
  3. > return (function(x) return x*2 end)(1)
  4. 2


I agree it's awful. Trust me, it was not the first thing I tried. Alas it is the only way to create an inline anonymous function inside a variable assignment. I'd be glad to be proven wrong, if you can show an alternative that actually runs (rather than guessing it should run). Sure, I could break out the function, but that's annoying, seeing as it's only going to be called from one place, and one place only.




Originally Posted by Layback_ View Post
Just a quick question passing by..

What would be the actual purpose of EJ_SelectTier(index) function?

Neither WoWWiki nor Wowprogramming seem to document this function at the moment

I dumped this inside WoW, but looks like it does not return any output.


Also, should I install Lua on my PC first before using the tool suggested by myrroddin?
EJ_SelectTier simply selects a tier in the Encounter Journal. EJ_SelectTier(1) selects the Classic expansion for example.

This is a hacky workaround, but needed to generate a list of all the instances and expansions. Only done once per login in my revised code (not posted here). Basically I crawl the encounter journal to get all the instances and expansions the game has to offer.

That's why it doesn't return anything in game - it's simply a UI function that selects a dropdown. This must be done, so that EJ_GetTierInfo() returns the expansion ("tier") name.





Should also mention that there were issues with using this code on ZONE_CHANGED_NEW_AREA, it turns out that the Encounter Journal is basically dead during the loading screen, so running my code on the Event trigger, would cause an error, due to my code relying on EJ_GetCurrentInstance() to get the instanceID.

Fortunately I had decided to store the instance names in the InstanceTable, so I simply swapped over to scanning for the instance name rather than the ID, since instance name is available during the loading screen, through GetInstanceInfo().

Simple enough fix, and it all works fine now. Instantly on zone-in, a log entry is created. For example "Dungeons -> Wrath of the Lich King -> An'kahet: The Old Kingdom" -> Meaning sub-table.

Last edited by Mythricia : 02-23-17 at 07:26 AM.
  Reply With Quote
02-23-17, 07:56 AM   #15
Lombra
A Molten Giant
 
Lombra's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2006
Posts: 554
Originally Posted by Mythricia View Post
I agree it's awful. Trust me, it was not the first thing I tried. Alas it is the only way to create an inline anonymous function inside a variable assignment. I'd be glad to be proven wrong, if you can show an alternative that actually runs (rather than guessing it should run). Sure, I could break out the function, but that's annoying, seeing as it's only going to be called from one place, and one place only.
You probably shouldn't be dealing with functions in the first place.

Lua Code:
  1. local tierList = (function()
  2.     local tt = {}
  3.     for i=1, EJ_GetNumTiers() do
  4.         tt[i] = EJ_GetTierInfo(i)
  5.     end
  6.     return tt
  7. end)()

Just do:
Lua Code:
  1. local tierlist = {}
  2. for i=1, EJ_GetNumTiers() do
  3.     tierlist[i] = EJ_GetTierInfo(i)
  4. end
__________________
Grab your sword and fight the Horde!
  Reply With Quote
02-24-17, 04:15 AM   #16
myrroddin
A Pyroguard Emberseer
 
myrroddin's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2008
Posts: 1,240
You do not need to install Lua to use that tool; it comes with everything required.
  Reply With Quote
02-24-17, 09:48 AM   #17
Mythricia
A Murloc Raider
 
Mythricia's Avatar
Join Date: Feb 2017
Posts: 6
Originally Posted by Ketho View Post
never mind
This plus the edit reason "i give up" is just the motivational ticket someone trying to learn something new needs.
  Reply With Quote
02-24-17, 10:00 AM   #18
Ketho
A Pyroguard Emberseer
 
Ketho's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2010
Posts: 1,026
Originally Posted by Mythricia View Post
This plus the edit reason "i give up" is just the motivational ticket someone trying to learn something new needs.

Okay here is my post again

I understand you still need to clean up and refactor but to be honest,
your code is giving me a lot of WTF's, it makes me wonder if my example was even looked at
  • Why use a for 10,000 loop instead of a while-do loop? Even still there are only around max 16-20 dungeon indexes per tier
  • Spaces instead of tabs?

Unless it's for testing purposes there still are some leaking globals
Code:
main (24 instructions, 96 bytes at 00000000007C8370)
	[5]	SETGLOBAL	0 -1	; GenerateInstanceTable
	[52]	SETGLOBAL	0 -2	; GetCurrentInstanceTier
function (57 instructions, 228 bytes at 00000000007C8880)
	[54]	SETGLOBAL	0 -1	; InstanceTable
	[98]	SETGLOBAL	12 -12	; subTable

Why create a function and then run it on the fly
Code:
-- Second, is it Heroic? If so, skip all of Vanilla. Else, search the entire instance table
local startIndex = (function()
	if difficulty == 2 then
		return 2
	else
		return 1
	end
end)()

local startIndex = (difficulty == 2) and 2 or 1
Code:
-- Generate a chronologically ordered list of expansion names
local tierList = (function()
	local tt = {}
	for i=1, EJ_GetNumTiers() do
		tt[i] = EJ_GetTierInfo(i)
	end
	return tt
end)()

local tierList = {}

for i = 1, EJ_GetNumTiers() do
	tierList[i] = EJ_GetTierInfo(i)
end

Why not use "party" and "raid" directly instead of changing it back and forth to "Dungeons" and "Raids"

Also why string.find instead of a table lookup? But I don't know what you're trying to do here
Code:
instTable.trackedTypes = "party, raid"

if not string.find(InstanceTable.trackedTypes, instanceType) then return "UnknownInstanceType" end

local trackedTypes = {
	party = true,
	raid = true,
}

if not trackedTypes[instanceType] then return "UnknownInstanceType" end

This do-end is superfluous
Code:
-- Bail out if we're not even in an instance!
if not IsInInstance() then do return "NotAnInstance" end end

This table structure is overly complicated, why not remap id to tier?
Code:
instTable[instanceType][tierName][name] = id

instTable[id] = tierId

Why not index a hash table instead of iterating through it
Code:
 -- Perform the actual search, scanning by instanceID, skipping Classic if we're in Heroic
for i = startIndex, #tierList do
	subTable = InstanceTable[searchType][tierList[i]]

	for k, v in pairs(subTable) do
		if (instanceID == v) then
			return tierList[i]
		end
	end
end

return instTable[instanceID] or "UnknownTier"

You can use format strings to keep it more readable
Code:
print("You are in \""..select(1,GetInstanceInfo()).."\ ("..select(4,GetInstanceInfo())..")\", from the \""..GetCurrentInstanceTier().."\" expansion.")

local name, difficultyName = GetInstanceInfo()
print( format('You are in "%s (%s)", from the "%s" expansion.', name, difficultyName, GetCurrentInstanceTier()) )

Last edited by Ketho : 02-24-17 at 10:05 AM.
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » Programmatically determine instance expansion?


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off