Thread Tools Display Modes
05/22/17, 10:32 AM   #1
sirinsidiator
 
sirinsidiator's Avatar
AddOn Author - Click to view addons
Join Date: Apr 2014
Posts: 1,566
[implemented] Guild Kiosks

A while ago I added a new feature to AwesomeGuildStore which automatically generates a list of every guild kiosk in the game and when a player visits the NPC it remembers the guild owner.
This is currently language dependent and basically only works in English, because the kiosks are tracked by the NPC name and map name and guild names are parsed from strings.

With Morrowind out of the door I figured I'd summarize what I currently do to achieve this and what API additions I would like to see in order to simplify the feature and make it work more robustly.

There are 3 different data sets I collect.
  • store data - is basically a location where one or more kiosks are. This uses a combination of the map name and location index as an identifier and contains infos on how to find the specific location (e.g. when I want to show it on the map) and also which kiosks are there.
  • kiosk data - uses the NPC name as an id and simply contains the last visit time, exact coordinates and a reference to the store location.
  • owner data - maps a guild name to a kiosk id for every week

1) Getting all stores and kiosks
This currently works by iterating over all zone and city maps and looking through all location pins for the desired type.
When switching to a zone map, it iterates over all location pins and checks for guild kiosks by comparing the icon.
Then it steps into each city map by iterating over all POIs and using ProcessMapClick on them and repeating the same function used to get kiosks on a zone map.
It collects the kiosk from the location tooltips, but there are several problems:
  • For kiosks in outlaw refuges it cannot get the NPC name from the tooltip as it is not shown. The thieves guild in Hew's Bane however does show the name of the trader inside.
  • The kiosks in Kvatch (Gold Coast) and in some outlaw refuges do not have a dedicated kiosk icon, but instead are shown as part of another tooltip.
  • Some NPC names on the kiosk tooltips are incorrect (e.g. one of the traders shown on the tooltip in wayrest is actually in elden root irc).
  • For some outlaw refuges the name on the location tooltip on the city map is not the same as the map name inside the refuge (e.g. "Orsinium Outlaw Refuge" vs "Orsinium Outlaws Refuge", "Vivec City Outlaws Refuge" vs "Vivec Outlaws Refuge")
  • The actual location of the individual traders can only be approximated as they all use the same location pin

2) Getting the location and guild owner
The addon scans the unit caption whenever the player looks at a different NPC and tries to parse it for the guild name.
When the guild store is opened, it will also store the exact location of the kiosk as it is not available from the outside (using the "reticleover" unittag).
For guilds that the player is a member of, the kiosk name is received via GetGuildOwnedKioskInfo to automatically update the list.

Main problems here:
  • NPCs won't give away their map location when not talked to
  • Information about the guild kiosk owners is only available from the unit caption and has to be matched when the guild store is not open
    (On a side note, the kiosk caption language is not updated when the client language is changed on the fly and only refreshes on relog)
  • Kiosk captions seem to trigger a server request when the NPC is looked at for the first time and only updates to show the guild owner when the player looks away and back to the NPC (it also sometimes takes several seconds before it finally shows up)
  • GetGuildOwnedKioskInfo returns a localized string which contains kiosk name and location, which has to be parsed in order to get the NPCs name, but different locations use different wording (e.g. a in b, a in the b, a on b, a near b). A second and third parameter to return just the kiosk and location would be really nice

3) Trading weeks
The owner data is then stored per ISO week in order to keep record of which guilds have shown up where.
The game itself does not supply the trader change time anywhere outside of the kiosk bidding dialog, so I had to hardcode the UTC time which has been announced in some forum post. I also had to write a whole library to handle timestamps and get ISO weeks from them.
The game also does not reliably update the guild information when the trader change happens and there is a delay of one or more minute before anyone knows if their bid actually made it unless they stand in front of the kiosk and open the guild store after the change.

Problems:
  • No way to get the trader change time
  • No way to work with timestamps and get ISO weeks
  • No way to reliably update info about the kiosk of joined guilds when the trader change happened

For 1 and 2 it would be ideal if there was a whole new API to get kiosk data:
Lua Code:
  1. count = GetNumGuildKiosks() -- returns the number of kiosk NPCs
  2. traderName, storeName, guildOwnerName, locationIndex, mapX, mapY = GetGuildKioskInfo(kioskIndex)
  3. -- traderName is the NPC
  4. -- storeName the name of the shop which is currently only available from GetGameCameraNonInteractableName()
  5. -- guildOwnerName is the guild name of the current owner
  6. -- locationIndex is the map location index which can be used to get the tooltip
  7. -- mapX/Y is the exact position of the NPC on the target map
  8. SetMapToGuildKiosk(kioskIndex) -- allows to directly open the target map
  9. kioskId = GetGuildKioskId(index) -- converts to a kiosk ID which identifies them independently of version and language
  10. kioskIndex = GetGuildKioskIndex(kioskId) -- allows to get the index from the id for use with SetMapToGuildKiosk and GetGuildKioskInfo
But I am also open for other ideas that make this more robust and easier to handle different languages.

For 3 it would be nice to have some more functions to work with timestamps in order to move the calculations from lua to c code. A function GetTraderChangeTime() which returns the timestamp for the next trader change on the current server and an event which gets fired at the trader change time and signals that the new owner info is now available would also be very desirable.
 
05/22/17, 03:46 PM   #2
ZOS_ChipHilseberg
ZOS Staff!
Premium Member
Yes this person is from ZeniMax!
Join Date: Oct 2014
Posts: 551
1) Getting all stores and kiosks
We don't really have any better data representation than the one you are accessing (POIs in Zones). The kiosk NPCs are all separate NPCs with no relation to each other. The NPCs also don't have information about where they spawn, since the spawning of an NPC is controlled by another system. The best info is really the map info.

2) Main problems here:
NPCs won't give away their map location when not talked to
Are these locations not static? Which is to say that you could capture them once? For the reasons above knowing the location of an NPC in the abstact can be challenging.
Information about the guild kiosk owners is only available from the unit caption and has to be matched when the guild store is not open
(On a side note, the kiosk caption language is not updated when the client language is changed on the fly and only refreshes on relog)
I'm not sure what you mean by matched here. But in general the owner of a guild store is messaged down with the NPC info. Messaging the state of all guild stores on login would naturally be a larger request and a system change. The caption bug has to do with caching we do for performance. It could be invalidated on a language change if it is hindering you.
Kiosk captions seem to trigger a server request when the NPC is looked at for the first time and only updates to show the guild owner when the player looks away and back to the NPC (it also sometimes takes several seconds before it finally shows up)
Guild names have to be resolved on the server so it takes some time to get the name for the guild id that is sent down with the NPC.
GetGuildOwnedKioskInfo returns a localized string which contains kiosk name and location, which has to be parsed in order to get the NPCs name, but different locations use different wording (e.g. a in b, a in the b, a on b, a near b). A second and third parameter to return just the kiosk and location would be really nice
The text passed down through the API is entirely designer controlled so unfortunately we don't have it split into pieces.
3) Problems:
No way to get the trader change time
This is a server setting that we could message down on player login.
No way to reliably update info about the kiosk of joined guilds when the trader change happened
It might be possible to broadcast a message to all clients when this happens, but it might also be too much traffic.

A lot of the requested changes would require adding more to the data setup and using a good bit of designer time to populate which I don't have control of. However, I can ask about the server time things. If you can think of changes that would not require accessing traders globally those would have a better chance of getting done too.
 
05/22/17, 05:32 PM   #3
cyxui
AddOn Author - Click to view addons
Join Date: Nov 2015
Posts: 61
Originally Posted by ZOS_ChipHilseberg View Post
We don't really have any better data representation than the one you are accessing (POIs in Zones). The kiosk NPCs are all separate NPCs with no relation to each other. The NPCs also don't have information about where they spawn, since the spawning of an NPC is controlled by another system. The best info is really the map info.


Are these locations not static? Which is to say that you could capture them once? For the reasons above knowing the location of an NPC in the abstact can be challenging.

I'm not sure what you mean by matched here. But in general the owner of a guild store is messaged down with the NPC info. Messaging the state of all guild stores on login would naturally be a larger request and a system change. The caption bug has to do with caching we do for performance. It could be invalidated on a language change if it is hindering you.

Guild names have to be resolved on the server so it takes some time to get the name for the guild id that is sent down with the NPC.

The text passed down through the API is entirely designer controlled so unfortunately we don't have it split into pieces.

This is a server setting that we could message down on player login.

It might be possible to broadcast a message to all clients when this happens, but it might also be too much traffic.

A lot of the requested changes would require adding more to the data setup and using a good bit of designer time to populate which I don't have control of. However, I can ask about the server time things. If you can think of changes that would not require accessing traders globally those would have a better chance of getting done too.
Can we get a kiosk ID for each area? Or an ID for each NPC works too. The get ID should work on both in the guild store interface as well as the Guild own kiosk information (like the API should be able to figure out the ID for guild1 of the player without having to walk to the kiosk)

It is making it so much harder to localize due to the string parsing nature. Having said that can we have an API to get masterwrit's required item's item link instead of having to parse it!! plz..plz...plz..
 
05/23/17, 04:40 AM   #4
sirinsidiator
 
sirinsidiator's Avatar
AddOn Author - Click to view addons
Join Date: Apr 2014
Posts: 1,566
Originally Posted by ZOS_ChipHilseberg View Post
We don't really have any better data representation than the one you are accessing (POIs in Zones). The kiosk NPCs are all separate NPCs with no relation to each other. The NPCs also don't have information about where they spawn, since the spawning of an NPC is controlled by another system. The best info is really the map info.
Okay. In that case it would be desireable that the map info is corrected where it is wrong or incomplete. I can make a list of all the problems if you want.

Originally Posted by ZOS_ChipHilseberg View Post
Are these locations not static? Which is to say that you could capture them once? For the reasons above knowing the location of an NPC in the abstact can be challenging.
One of my design goals was to make it work without having to store the data in the addon. This is so I do not have to update the list manually on every update which may add new traders.

Originally Posted by ZOS_ChipHilseberg View Post
I'm not sure what you mean by matched here. But in general the owner of a guild store is messaged down with the NPC info. Messaging the state of all guild stores on login would naturally be a larger request and a system change. The caption bug has to do with caching we do for performance. It could be invalidated on a language change if it is hindering you.
Matched means this:
Lua Code:
  1. local guildKioskWithNamePattern = GetString(SI_GUILD_KIOSK_DISPLAY_CAPTION_WITH_OWNER):gsub("%(<<1>>%)", "%%((.+)%%)")
  2.  
  3. local function GetUnitGuildKioskOwner(unitTag)
  4.     local caption = GetUnitCaption(unitTag)
  5.     if(caption) then
  6.         return GetUnitCaption(unitTag):match(guildKioskWithNamePattern)
  7.     end
  8. end
It extracts the guild name from the caption, but an api method GetUnitGuildKioskOwner which directly returns it would be nice.
The caching between language changes is not really a problem for "normal" users, but it requires me to relog when I want to test it in different languages. If it's easy to fix I would welcome it, but it's not really a priority.

Originally Posted by ZOS_ChipHilseberg View Post
Guild names have to be resolved on the server so it takes some time to get the name for the guild id that is sent down with the NPC.
Resolving it directly when the NPC info is sent is not possible? You could even cache it on the server for a week. IMO it would not just help addons, but also feel a lot better for all players who regularily have to do with traders. Right now it looks like there is a bug in the game tbh.

Originally Posted by ZOS_ChipHilseberg View Post
The text passed down through the API is entirely designer controlled so unfortunately we don't have it split into pieces.
That's too bad. It's one of the biggest problems I face right now, because I do not know all the different possibilities for the different languages and can only rely on user reports.
Getting all the possible strings myself is not really feasable, because there are now 184 traders and I would need to hire each of them and then switch to all languages in order to compile this list.

Originally Posted by ZOS_ChipHilseberg View Post
This is a server setting that we could message down on player login.
This would be great!

Originally Posted by ZOS_ChipHilseberg View Post
It might be possible to broadcast a message to all clients when this happens, but it might also be too much traffic.
Maybe limit it just to ranks with the hire trader permission then? Normal players are not interested in it anyways.


Originally Posted by ZOS_ChipHilseberg View Post
A lot of the requested changes would require adding more to the data setup and using a good bit of designer time to populate which I don't have control of. However, I can ask about the server time things. If you can think of changes that would not require accessing traders globally those would have a better chance of getting done too.
Thanks! The things above would help with making it a bit easier for me, but NPC ids and map ids for the city maps would still be the only way to help me with the language compatibility. Right now I cannot reuse the data from a german client for an english client without collecting a list of all NPC and map names in all languages, which is something I want to avoid.
 
06/06/17, 08:56 AM   #5
ZOS_ChipHilseberg
ZOS Staff!
Premium Member
Yes this person is from ZeniMax!
Join Date: Oct 2014
Posts: 551
I added GetGuildKioskCycleTimes() - despawnTimestampS, bidEndTimestampS, respawnTimestampS. These values are available on guild data loaded.

I also exposed the os time functions if that is any help.
 
06/06/17, 09:00 AM   #6
Ayantir
 
Ayantir's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2014
Posts: 1,019
Originally Posted by ZOS_ChipHilseberg View Post
I added GetGuildKioskCycleTimes() - despawnTimestampS, bidEndTimestampS, respawnTimestampS. These values are available on guild data loaded.

I also exposed the os time functions if that is any help.



 
06/06/17, 09:59 AM   #7
sirinsidiator
 
sirinsidiator's Avatar
AddOn Author - Click to view addons
Join Date: Apr 2014
Posts: 1,566
Originally Posted by ZOS_ChipHilseberg View Post
I added GetGuildKioskCycleTimes() - despawnTimestampS, bidEndTimestampS, respawnTimestampS. These values are available on guild data loaded.

I also exposed the os time functions if that is any help.
This is awesome.

Exposing the os time functions will help me a lot and possibly make LibDateTime unnecessary. Just wondering, for "normal" Lua 5.1 on windows os.date causes a crashes for certain patterns that are not supported by the Microsoft implementation of strftime used underneath. Will ESO Lua and possibly the game also crash in that case? (e.g. when calling os.date("%V") to get the current ISO week number)

Last edited by sirinsidiator : 06/06/17 at 10:07 AM.
 

ESOUI » Developer Discussions » Wish List » [implemented] Guild Kiosks

Thread Tools
Display Modes

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