Thread Tools Display Modes
04/24/14, 04:47 AM   #1
Asto
 
Asto's Avatar
AddOn Author - Click to view addons
Join Date: Apr 2014
Posts: 18
Achievement Proplems -> Wrong Return Values

solutions: http://www.esoui.com/forums/showthre...=5637#post5637

1
I have a problem with the functionality of GetPreviousAchievementInLine

If i get an achievement update event, i have a achievement id. i pass it into the function and now the following happens:

if there is no previous achievement, for example
/zgoo GetPreviousAchievementInLine(38)
it return 0. Okay.

if there is a previous achievement that is completed, for example in my case
/zgoo GetPreviousAchievementInLine(67)
it returns the id 66. Perfect.

if there is a previous achievement in line that is not completed, for example in my case
/zgoo GetPreviousAchievementInLine(68)
it returns also 0. What the hell... :/

I would have assumed that if there is no prev achievement it returns false or nil or similiar but it is also 0. Or the function returns the correct id if there is a previous achievement but it's not completed yet.

How should i deal with it? Any ideas?

2
The second problem is the following... when getting category infos for an achievementId, in some cases i get the wrong data!? If i collect the data of achievementId 68 with GetCategoryInfoFromAchievementId(68) it returns 2, nil, 2. But 2, the toplevelindex, is the wrong category. It is in another in the journal. And if i pass those parameters into the reverse function GetAchievementId(2, nil, 2) i don't get 68 again. I get 838 as Id... but that is the correct one for the values 2 nil 2...

It works correct with the initial achievementId 41. I get 1, nil, 10 and in revers through GetAchievementId again Id 41.

Is this a bug in the API or a bug with some achievements? The problem occurs especially for the harvesting achievements (collecting wood, resolving quests etc)

Last edited by Asto : 04/24/14 at 10:08 AM.
  Reply With Quote
04/24/14, 06:55 AM   #2
Iyanga
AddOn Author - Click to view addons
Join Date: Apr 2014
Posts: 183
Originally Posted by Asto View Post
1
I have a problem with the functionality of GetPreviousAchievementInLine

If i get an achievement update event, i have a achievement id. i pass it into the function and now the following happens:

if there is no previous achievement, for example
/zgoo GetPreviousAchievementInLine(38)
it return 0. Okay.

if there is a previous achievement that is completed, for example in my case
/zgoo GetPreviousAchievementInLine(67)
it returns the id 66. Perfect.

if there is a previous achievement in line that is not completed, for example in my case
/zgoo GetPreviousAchievementInLine(68)
it returns also 0. What the hell... :/

I would have assumed that if there is no prev achievement it returns false or nil or similiar but it is also 0. Or the function returns the correct id if there is a previous achievement but it's not completed yet.

Well, if you read it as GetPreviousCompletedAchievementInLine it is consistent behavior.
How does GetNextAchievementInLine() react? If it also only returns completed achievements, the behavior is really consistent and intended.

How should i deal with it? Any ideas?
First you would need to tell what you actually want to achieve.

The second problem is the following... when getting category infos for an achievementId, in some cases i get the wrong data!? If i collect the data of achievementId 68 with GetCategoryInfoFromAchievementId(68) it returns 2, nil, 2. But 2, the toplevelindex, is the wrong category. It is in another in the journal. And if i pass those parameters into the reverse function GetAchievementId(2, nil, 2) i don't get 68 again. I get 838 as Id... but that is the correct one for the values 2 nil 2...

Hm, I've done a little cross check:

GetNumAchievementCategories, GetAchievementCategoryInfo, GetAchievementId and GetCategoryInfoFromAchievementId are in itself consistent.

You can do a successful roundtrip - what you get from these and feed into them again, is correct. You can traverse down to the achievement id of an achievement and from that achievement id back to the correct category.

This leads to the question: Where do you get the 68 from and why do you think it's a valid achievement id?

Traversing through the crafting achievements, I get as valid ids: 66, 69, 779 , ....

The 68 is an id for an information about a criterion progress it seems:
AchievementCategory->Subcategory->Achievement->Criterion->Progress

If you feed this progress id into GetCategoryInfoFromAchievementId(), you always get 2, nil, 2, no matter which progress id you use, so I assume it's some kind of error result.

That's what I can say at the moment...
  Reply With Quote
04/24/14, 07:42 AM   #3
Asto
 
Asto's Avatar
AddOn Author - Click to view addons
Join Date: Apr 2014
Posts: 18
1
Weird... They should name the method so but for me it doesn't make sense to return only completed achievements.

Well what i wanted to do: if the event EVENT_ACHIEVEMENT_UPDATED is thrown i get all events with the same progress criterion that got updated. In the most cases the achievements are on the same line, so i just wanted to show only the next achievable achievement.

I tried to check if there is a previous achievement and the previous achievement in the line is also incomplete, i wanted to ignore the event. So that my handler starts handling only when
1. there is no previous achievement and the one updated (this one) is incomplete
2. there is a previous achievement but that one is complete and this updated one is incomplete

At the moment i cannot differentiate between those cases. I could check if GetPreviousAchievementInLine returns 0. Works great for achievement lines. If it returns 0, i can ignore it because the previous one ins incomplete. The previous one may return a achievementId beceause the first achievement in the line is complete, so its perfect.

But i run into problems when i try to use this on the first achievement in the line or on achievements without a line. They also return 0 and i can't ignore them because they they just have no previous achievements

i hope you can understand my problem :/

2
I am listening to the event
Lua Code:
  1. -- Register Events
  2.     AchievementInfo.registerEvent(EVENT_ACHIEVEMENT_UPDATED, AchievementInfo.onAchievementUpdated)

And let's say my handler looks like
Lua Code:
  1. function AchievementInfo.onAchievementUpdated(eventCode, achId)
  2.     d(achId) -- for example 41, 67, ...
  3.  
  4.     d("- GetCatInfo")
  5.     d(GetCategoryInfoFromAchievementId(achId))
  6.     local a, b, c = GetCategoryInfoFromAchievementId(achId)
  7.  
  8.     d("- getAId")
  9.     d(GetAchievementId(a, b, c)) -- for example 41, but not 67, ... !?
  10. end

i get the following results when harvesting wood for example, where 67 and 68 are the last two harvester achievements ( http://esohead.com/achievements/67-node-harvester-iv and http://esohead.com/achievements/68-node-harvester-v ) that get updated when harvesting sth... Achievement ID 41 in the screens below is the achievement for slaying plants... that works correct

The main problem is: i want to get the category name of the achievements. Works fine with achId 38 or 41 when slaying humanoids or plants
Lua Code:
  1. local categoryTopLevelIndex = GetCategoryInfoFromAchievementId(achId)
  2. local catName = GetAchievementCategoryInfo(categoryTopLevelIndex)

but not for the node harvester achievements for example. because it returns the 2, nil, 2 thing. 2 is not the crafting category...

PS: I get the same 2, nil, 2 results for achId 65 and 66, hmm
Attached Thumbnails
Click image for larger version

Name:	68.jpg
Views:	488
Size:	8.0 KB
ID:	183  
Attached Images
  

Last edited by Asto : 04/24/14 at 08:00 AM.
  Reply With Quote
04/24/14, 08:25 AM   #4
Iyanga
AddOn Author - Click to view addons
Join Date: Apr 2014
Posts: 183
Playing around it seems to work like this:

All achievements have an achievementId.

Only the actually achieved achievement has a category though!

Using GetPreviousAchievementInLine() and GetNextAchievementInLine() return correctly the various ids of the progression line for me, you can traverse from 66 to 64 and from 64 to 68 and at the end of the line they both return correctly 0. If this doesn't work for you, you seem to be doing something wrong in your code.

So if you are currently Node Harvester III you can do:


0 returned for GetPreviousAchievementInLine(64) -> cannot get Category
id 64 returned for GetPreviousAchievementInLine(65) -> cannot get Category
id 65 returned for GetPreviousAchievementInLine(66) -> cannot get Category
id 66 Node Harvester III -> can get CategoryInfo()
id 67 returned for GetNextAchievementInLine(66) -> cannot get Category
id 68 returned for GetNextAchievementInLine(67) -> cannot get Category
0 returned for GetNextAchievementInLine(68) -> cannot get Category


If the achievement has no progression line, in example id 18 (the first general achievement), I get correctly 0 for GetNext and GetPrev.

So right now I assume you are doing something wrong in your code.

Except that you can't get the Category from an inactive achievement progression step, I don't see any strange behavior in the API.
  Reply With Quote
04/24/14, 08:49 AM   #5
Iyanga
AddOn Author - Click to view addons
Join Date: Apr 2014
Posts: 183
So, regarding your addon you need to change

Lua Code:
  1. local categoryTopLevelIndex = GetCategoryInfoFromAchievementId(achId)

into something more complex:
- Get the PreviousAchievementInLine()
- If it's not 0, get the AchievementInfo from it
- If the AchievementInfo completed == true, get the CategoryInfo to get the correct category
- If not, repeat and get previouspreviousAchievementInLine()
- If it IS 0, you can just get the CategoryInfo

Last edited by Iyanga : 04/24/14 at 08:56 AM.
  Reply With Quote
04/24/14, 08:58 AM   #6
Asto
 
Asto's Avatar
AddOn Author - Click to view addons
Join Date: Apr 2014
Posts: 18
Yes thank you for the testing and the explanation. Now i understand the system but it could be better

Lua Code:
  1. d(  "--- 64",
  2.     GetPreviousAchievementInLine(64),
  3.     GetAchievementCategoryInfo(GetCategoryInfoFromAchievementId(64)),
  4.     GetNextAchievementInLine(64),
  5.     "--- 65",
  6.     GetPreviousAchievementInLine(65),
  7.     GetAchievementCategoryInfo(GetCategoryInfoFromAchievementId(65)),
  8.     GetNextAchievementInLine(65),
  9.     "--- 66",
  10.     GetPreviousAchievementInLine(66),
  11.     GetAchievementCategoryInfo(GetCategoryInfoFromAchievementId(66)),
  12.     GetNextAchievementInLine(66),
  13.     "--- 67",
  14.     GetPreviousAchievementInLine(67),
  15.     GetAchievementCategoryInfo(GetCategoryInfoFromAchievementId(67)),
  16.     GetNextAchievementInLine(67),
  17.     "--- 68",
  18.     GetPreviousAchievementInLine(68),
  19.     GetAchievementCategoryInfo(GetCategoryInfoFromAchievementId(68)),
  20.     GetNextAchievementInLine(68),
  21.     "---"
  22. )



Why should only the achieved achievement return the correct category and the others not?
And why can i step through the achievements with previous and next only in one direction for unachieved achievements?

Now i understand the system but this is still weird. In my opinion they should "fix" the behaviour if possible
Attached Thumbnails
Click image for larger version

Name:	achievementLine.png
Views:	788
Size:	171.0 KB
ID:	185  

Last edited by Asto : 04/24/14 at 09:21 AM.
  Reply With Quote
04/24/14, 09:26 AM   #7
Asto
 
Asto's Avatar
AddOn Author - Click to view addons
Join Date: Apr 2014
Posts: 18
2
Oh i forgot about the thing that initially confused me...
see the following:



Solution
  • Now I could track down the following rules with your help and a few more tests:
    1. You get a category if the achievement is not a member of an achievement line
    2. If the achievement is member of a line
      1. but you did not complete any achievement of this line, the first achievement returns the correct category
      2. if you completed an achievement of the line, only the last completed achievement returns the correct category

Please tell me if that makes any sense...
They should change it in the future...

1
With the given "stepping behavior" (previous and next) i still can't decide between a first achievement and another later incomplete one in the line. I have to ignore the events for later achievements of a line.

Idea (dirty)
  • Maybe the only thing i could do to solve it: i could use achievementId, substract 1 (very dirty...) to get possibly the previous achievementId, test with a getNext if it is a previous achievement of the initial achievmentId i got (matching Ids).
    • If it matches the initial achievementId: Yaay! I found a previous one.
    • If it is not the previous achievement: Okay the event send me an achievement that is a first one of a line or a solo achievement.


Edit: Better Idea / Maybe the solution
  • I can decide between a solo achievement and a member of an achievement line with the following trick:
    1. The achievement with a valid category (not 2, nil, 2 i guess) is a solo achievement or the first unachieved of a line -> i want to handle it
    2. The achievement with a prev and next value (none of them is 0) is the achievement of a line i am currenty at -> i want to handle it
    3. ignore everything else

I definitely have to test that

Edit: Works

Last edited by Asto : 04/24/14 at 03:31 PM.
  Reply With Quote
04/24/14, 04:28 PM   #8
Iyanga
AddOn Author - Click to view addons
Join Date: Apr 2014
Posts: 183
Originally Posted by Asto View Post
  • I can decide between a solo achievement and a member of an achievement line with the following trick:
    1. The achievement with a valid category (not 2, nil, 2 i guess) is a solo achievement or the first unachieved of a line -> i want to handle it
    2. The achievement with a prev and next value (none of them is 0) is the achievement of a line i am currenty at -> i want to handle it
    3. ignore everything else
You can't check for "not( 2, nil, 2)" because 2, nil, 2 is a valid combination, too.

A solo achievement or the first achievement of the line returns a 0 to GetPrev(). As far as I can tell, you need to use this instead to have it reliable for all achievements.

The last achievement of the line will have a NextValue of 0, too, but you want to handle it - if you are actually working on the last achievement. You need to check the AchievementInfo and completed value where the character actually is, to determine what you can ignore.

In other words:
If your 66 is completed, you must ignore 68, but not 67, but if you are at 67, you must NOT ignore 68.
  Reply With Quote
04/25/14, 12:03 AM   #9
Asto
 
Asto's Avatar
AddOn Author - Click to view addons
Join Date: Apr 2014
Posts: 18
Yeah you are right. What i am actually doing is:

I do the reverse check to test if the achievement has a valid category. The ID at the end from the category data has to match the achievement ID so i know that it is correct. Because of the valid category, i can tell that i have a solo or a first achievement of a line (the event doesn't fire for completed achievements of progression lines).

Lua Code:
  1. -- Check if the category of an achievement is valid (reverse check)
  2. function AchievementInfo.checkForValidCategory(achId)
  3.     local categoryTopLevelIndex, categoryIndex, achievementIndex = GetCategoryInfoFromAchievementId(achId)
  4.     local reverseAchievementId = GetAchievementId(categoryTopLevelIndex, categoryIndex, achievementIndex)
  5.  
  6.     if achId == reverseAchievementId then
  7.         return true
  8.     end
  9.  
  10.     return false
  11. end

Is the category invalid, i know i am on a higher achievement in the line. Has this achievement a previousId value of 0 i can ignore it because it is to high. Has it a value of ~= 0 i can recursively check the previous achievement for the category

Last edited by Asto : 04/25/14 at 01:39 AM.
  Reply With Quote

ESOUI » Developer Discussions » General Authoring Discussion » Achievement Proplems > Return Values


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