The cards have been restocked at least once since I created this thread for those who were wondering. I created this thread mid-march and the cards were restocked early April. So it shouldn't take too long.
Cool thanks. That worked as much as I needed it to - they're now restored to English and are marked as needing review at least.
I still wish there was a way to remark them as untranslated, but I think this problem isn't common enough to warrant a ticket. And this solution should work just as well. Thanks again.
I had a few phrases in one of my addons which were previously not translated into some languages. Thus they were marked as needing translation.
However, someone recently went in and translated them all using Google Translate. I don't like automated translators since they can sometimes be incorrect or confusing to the end-user - who would possibly better understand the original English.
How do I go about reverting his/her translations properly? There is no 'Previous Translation' radio button, since it is the first translation. Also if I mark the 'New Translation' radio button and delete all the text, it makes no change when I hit save.
First of all, if possible, instead of making variables frame1, frame2, frame3 and frame4; you'd be better off making a table of frames.
local frames = {};
frames[1] = CreateFrame("Frame"); -- or access a global premade frame
frames[2] = CreateFrame("Frame"); -- You get the idea.
A table lookup in your for loop would be much more efficient than concatenating strings and looking up globals on every update.
If you already have an 'active' variable for each of the four frames that you maintain somewhere, that's great. Otherwise "frames[1]:IsShown()" may do the trick depending on your definition of 'active' is.
I'm trying to follow your logic. On the second code block you posted on post #3, the code makes next to no sense. The first loop to me is an unneeded redundancy. You have a loop checking if any frame is active. Then if any frame is active you have a loop checking which of the frames are active.
Here is some code of what I think you're trying to accomplish. It may not be exactly what you want, but hopefully it'll help you figure out what you need to do.
local lastUpdate = 1
local function OnUpdateFunc(self, elapsed)
lastUpdate = lastUpdate + elapsed
isRunning = false; -- first assume no frames are running
if lastUpdate > 1 then
for i = 1, 4 do
local frame = frames[i]; -- This is the frames table I suggested earlier
if frame.active then
isRunning = true; -- At least one frame is active, but don't break
print("frame", i, "is active")
--frame:Show() -- Also do any other code you need to do.
else
print("frame", i, "is not active") -- Note it's better to pass multiple variables to print than to preconcatenate the string yourself.
--frame:Hide()
end
end
lastUpdate = 0
end
if (not isRunning) then -- This would happen if we finished the loop but no frames were active
print("no active frames")
f:SetScript("OnUpdate", nil) -- Do any other code you need here for this condition
end
end
I don't think SetMapToCurrentZone is too bad. I know the "Zone Map" (Shift+M) likes to call it a lot.
If you do in fact need to call it to fix your issue, you should try to limit the amount of times you call it. Instead of calling it for every snapshot, why not only call it if GetPlayerMapPosition() returns 0, 0?
The best you can do is if you're in a zone or instance that supports coordinates, track the combat log for events which involve the hostile target.
If the hostile target melee attacks someone in your party, you can assume the target is 'at the same position' (or pretty close to it).
Another way you can do it is with 'line of sight' calculations. For each player who casts a harmful attack to the target, you can assume they're facing the target (since if they're facing away they wouldn't have been able to attack). This is really easy if there's melee players.
If there's only ranged players, then you'll have to calculate their position and direction, then triangulate the position of the mob. The downside is the only directionality available is of the player itself, so you would need everyone in the party running the addon and have the addon communicate. Still this wouldn't be very accurate since there's room for error on the players facing - it doesn't need to be directly square to the target. Also the data would not produce a result if all the range are stacked, as there can be 'infinite' possibilites for the target-player distance.
All in all, to "fake" it this way involves a lot of math and overhead that is probably not even worth the effort, especially because the end result would probably not be as accurate as you need it to be.
Including what pigmonkey and Xinhuan said, in the situation you described the event will be fired twice. But arg1 should be "focus" for one firing and "target" for the other firing. I would check to make sure this is true if you have doubts.
As long as you can confirm it only fires once per focus target change with arg1 being "focus," then you will have no problem doing what pigmonkey said.
Note that once you're actually in an instance or raid UNIT_TARGET will be firing MANY times. As long as you do the check that pigmonkey reiterated, you won't really have to worry about how often the event is firing.
I'm not 100% sure, but I imagine the 'visual range' is the range in which characters are drawn - which is much further than you can tab target. Think about when you have "Target of Target" turned on, and after you get so far away you can no longer see who your target is targeting. That is probably the range, since the default UI would no longer be able to tell when your target's target changes. And this is well within the range of any raid/instance encounter.
Another thing you can do, similar to locks, is make your own Register/Unregister/IsRegistered event functions for your frame. Make the first call to Register actually register the event. Any call to Unregister just raise a flag for your OnEvent handler to not dispatch the message. A subsequent call to Register would clear the flag. Then IsRegistered would return the status of this flag.
This solution is probably only sensible for existing large addons where you don't want to go through each event to manually add locks, and already rely on the UnregisterEvent working.
@OrionShock
I understand what you're saying. So it seems that any event triggered from an API call is handled by every addon before that API call returns. o.O I definitely see potential for stack overflow if this effect was chained by multiple addons.
Nice, that definitely seems to make the most sense.
@lilsparky
I wonder if the issue is that the "ADDON_LOADED" event IS being registered, but because of the queue it isn't being registered until after the ADDON_LOADED event has already fired.
Edit:
Also related to weird event 'queuing' behavior.
I'm not exactly sure how the order of events processing is determined. I used to assume it was a simple queue. However, take the following example.
--Addon1.lua - loaded before Addon2
frame1:RegisterEvent("LOOT_OPENED")
frame1:LOOT_OPENED() -- just assume the event handler dispatched the event to this function
CloseLoot(); -- assume we decided all the loot was garbage, didn't want any of it
end
--Addon2.lua - loaded after Addon1
frame2:RegisterEvent("LOOT_OPENED")
frame2:RegisterEvent("LOOT_CLOSED")
frame2:LOOT_OPENED()
print("The loot opened!");
end
frame2:LOOT_CLOSED()
print("The loot closed!");
end
--Expected output when looting if the events were processed in a queue
The loot opened!
The loot closed!
--Actual output
The loot closed!
The loot opened!
For some reason the addons which registered the events after the first process them out of order if they're both fired in the same frame. I'm guessing for some reason the events are processed like a stack rather than a queue, or they're processed in alphabetical order?
I often see it suggested that if you call global functions repeatedly, you should make a local reference to that global function to prevent the repeated lookup.
My question is, would that present a problem in the following example?
-- Faux Blizzard Code -- i.e. pretend this is real
function SomeGlobal()
return 3;
end
-- Addon1.lua -- loaded before Addon2
local SomeGlobal = SomeGlobal
function TriggeredEverySoOften() -- This is triggered every so often, after every addon has loaded.
print(SomeGlobal());
end
-- Addon2.lua -- loaded after Addon1
local OldSomeGlobal = SomeGlobal;
function SomeGlobal(...)
OldSomeGlobal(...);
return 5;
end
Basically, after Addon2 loads, would we expect TriggeredEverySoOften of Addon1 to print 3 or 5?
If you're going to promote "safe" hooking (good for you), you need to do it completely... that means handling returns as well as args.
I don't want to go off-topic, but I want to ask since you brought it up.
In OrionShock's hooking example, what's the best way to handle the return of OldCollapseSkillHeader if you were to assume that at some point in the future Blizzard might decide to make the function return multiple values.
Is there an efficient way to temporarily store the list of return values, then return them later? Or would you have to know the number of return values, and make a sufficient amount of locals? Also this is assuming that you don't want your new function to return immediately after calling the old function.
If you have programming experience: http://wowprogramming.com/ -- they also have an online reference http://wowwiki.com/api -- Also look to the right of this page for "Main Menu" to click for Events, Widget API, etc...
If you have no programming experience:
I don't actually have that wowprogramming book, so I don't know if it's a good starting point, hopefully someone else can comment.
Also a great place to start is by looking at the code for existing addons. It would be more beneficial to look at 'smaller' addons so you can better see what's happening. In other words, don't open Cartographer first and expect to understand what's going on.
As long as you don't add files, you can modify the addons while WoW is running, and do '/reload' to make the changes take effect. Play around with an existing addon to see what happens.
If you have Auctioneer or Gatherer, they come with !Swatter which is really nice for finding errors. Type /swatter if you have it. If not, look into the BugGrabber or ImprovedErrorFrame addons.
The Ace3 Library basically simplifies some of the intricate work, so you won't have to invent the wheel to start making your addon. The Ace3 library is also well documented.
0
0
I still wish there was a way to remark them as untranslated, but I think this problem isn't common enough to warrant a ticket. And this solution should work just as well. Thanks again.
0
However, someone recently went in and translated them all using Google Translate. I don't like automated translators since they can sometimes be incorrect or confusing to the end-user - who would possibly better understand the original English.
How do I go about reverting his/her translations properly? There is no 'Previous Translation' radio button, since it is the first translation. Also if I mark the 'New Translation' radio button and delete all the text, it makes no change when I hit save.
0
A table lookup in your for loop would be much more efficient than concatenating strings and looking up globals on every update.
If you already have an 'active' variable for each of the four frames that you maintain somewhere, that's great. Otherwise "frames[1]:IsShown()" may do the trick depending on your definition of 'active' is.
I'm trying to follow your logic. On the second code block you posted on post #3, the code makes next to no sense. The first loop to me is an unneeded redundancy. You have a loop checking if any frame is active. Then if any frame is active you have a loop checking which of the frames are active.
Here is some code of what I think you're trying to accomplish. It may not be exactly what you want, but hopefully it'll help you figure out what you need to do.
0
If you do in fact need to call it to fix your issue, you should try to limit the amount of times you call it. Instead of calling it for every snapshot, why not only call it if GetPlayerMapPosition() returns 0, 0?
0
If the hostile target melee attacks someone in your party, you can assume the target is 'at the same position' (or pretty close to it).
Another way you can do it is with 'line of sight' calculations. For each player who casts a harmful attack to the target, you can assume they're facing the target (since if they're facing away they wouldn't have been able to attack). This is really easy if there's melee players.
If there's only ranged players, then you'll have to calculate their position and direction, then triangulate the position of the mob. The downside is the only directionality available is of the player itself, so you would need everyone in the party running the addon and have the addon communicate. Still this wouldn't be very accurate since there's room for error on the players facing - it doesn't need to be directly square to the target. Also the data would not produce a result if all the range are stacked, as there can be 'infinite' possibilites for the target-player distance.
All in all, to "fake" it this way involves a lot of math and overhead that is probably not even worth the effort, especially because the end result would probably not be as accurate as you need it to be.
0
So I would assume UnitHasVehicleUI would also return true.
0
Including what pigmonkey and Xinhuan said, in the situation you described the event will be fired twice. But arg1 should be "focus" for one firing and "target" for the other firing. I would check to make sure this is true if you have doubts.
As long as you can confirm it only fires once per focus target change with arg1 being "focus," then you will have no problem doing what pigmonkey said.
Note that once you're actually in an instance or raid UNIT_TARGET will be firing MANY times. As long as you do the check that pigmonkey reiterated, you won't really have to worry about how often the event is firing.
0
0
This solution is probably only sensible for existing large addons where you don't want to go through each event to manually add locks, and already rely on the UnregisterEvent working.
0
I understand what you're saying. So it seems that any event triggered from an API call is handled by every addon before that API call returns. o.O I definitely see potential for stack overflow if this effect was chained by multiple addons.
0
Nice, that definitely seems to make the most sense.
@lilsparky
I wonder if the issue is that the "ADDON_LOADED" event IS being registered, but because of the queue it isn't being registered until after the ADDON_LOADED event has already fired.
Edit:
Also related to weird event 'queuing' behavior.
I'm not exactly sure how the order of events processing is determined. I used to assume it was a simple queue. However, take the following example.
For some reason the addons which registered the events after the first process them out of order if they're both fired in the same frame. I'm guessing for some reason the events are processed like a stack rather than a queue, or they're processed in alphabetical order?
0
My question is, would that present a problem in the following example?
Basically, after Addon2 loads, would we expect TriggeredEverySoOften of Addon1 to print 3 or 5?
0
I don't want to go off-topic, but I want to ask since you brought it up.
In OrionShock's hooking example, what's the best way to handle the return of OldCollapseSkillHeader if you were to assume that at some point in the future Blizzard might decide to make the function return multiple values.
Is there an efficient way to temporarily store the list of return values, then return them later? Or would you have to know the number of return values, and make a sufficient amount of locals? Also this is assuming that you don't want your new function to return immediately after calling the old function.
0
http://wowprogramming.com/ -- they also have an online reference
http://wowwiki.com/api -- Also look to the right of this page for "Main Menu" to click for Events, Widget API, etc...
If you have no programming experience:
I don't actually have that wowprogramming book, so I don't know if it's a good starting point, hopefully someone else can comment.
If you're not familiar with Lua:
http://www.lua.org/manual/5.1/
Also a great place to start is by looking at the code for existing addons. It would be more beneficial to look at 'smaller' addons so you can better see what's happening. In other words, don't open Cartographer first and expect to understand what's going on.
As long as you don't add files, you can modify the addons while WoW is running, and do '/reload' to make the changes take effect. Play around with an existing addon to see what happens.
If you have Auctioneer or Gatherer, they come with !Swatter which is really nice for finding errors. Type /swatter if you have it. If not, look into the BugGrabber or ImprovedErrorFrame addons.
Edit:
I forgot to include you may also want to go to http://www.wowace.com/addons/ace3/
The Ace3 Library basically simplifies some of the intricate work, so you won't have to invent the wheel to start making your addon. The Ace3 library is also well documented.