Thread Tools Display Modes
07/05/15, 02:36 PM   #1
merlight
AddOn Author - Click to view addons
Join Date: Jul 2014
Posts: 671
[fixed] Custom guild rank names not well-defined -> game freezes

There's a long-standing bug -- related to custom guild rank names -- that causes the game to freeze whenever you select an "affected" guild in the Guild interface.

As of writing I'm aware of two affected guilds:
  • Twilight Market (EU)
  • Dark Brotherhood Merchant (??)
The bug only exhibits itself in English localization. Switching to German or French using /script SetCVar("language.2", "de" or "fr") allows you to view the guild interface without freezing. But it has nothing to do with non-ASCII characters, as one might guess at first.

Some time ago, I published an add-on/hack that prevents the freeze by replacing function ZO_GuildRanks_Shared:NeedsSave() with one that always returns false. This is okay for players who can't edit ranks, since we never need to save. I've been told the add-on "works" for officers as well, but obviously prevents them from changing ranks/permissions. So I was wondering why NeedsSave returns true during the very first refresh (before I had a chance to edit ranks), and despite the fact that I don't even have the required permission to edit ranks.

Twilight Market currently has four ranks (note there are only English letters):
  1. Guildmaster -- default (en)
  2. Officer -- default (en)
  3. Steward -- custom
  4. Trader -- custom

Strangely, rank.hasCustomName for the first two ranks is not always the same inside ZO_GuildRank_Shared:NeedsSave(). While clicking on different ranks in the guildRanks tab, their hasCustomName is sometimes true and sometimes false. I didn't try hard to find out why that happens, since I think the whole default/custom name logic needs more thought -- guilds are multi-lingual, yet GetDefaultGuildRankName() returns a localized string, not some canonical rank name.

What happens after ZO_GuildRanks_Shared:NeedsSave() returns true?
Lua Code:
  1. function ZO_GuildRanks_Keyboard:RefreshEditPermissions()
  2.     ...
  3.     else -- player doesn't have permission to edit permissions (ranks)
  4.         if(self:NeedsSave()) then
  5.             self:Cancel()
  6.         end
  7.     ...
  8. end
  9.  
  10. function ZO_GuildRanks_Keyboard:Cancel()
  11.     self:ClearSavePending()
  12.     self:RefreshRanksFromGuildData() -- !!!
  13. end

And here's the catch: RefreshRanksFromGuildData -> SelectRank -> RefreshRankInfo -> RefreshEditPermissions -> Cancel -> RefreshRanksFromGuildData -> BOOM

I'm going to rewrite my add-on so that instead of replacing NeedsSave(), it will prevent calling RefreshRanksFromGuildData() recursively. Of course, that doesn't fix the core issue with NeedsSave() returning true when it shouldn't.

For testing purposes I replaced global function DoesPlayerHaveGuildPermission() with one pretending that I do have GUILD_PERMISSION_PERMISSION_EDIT. Whenever I switch to Twilight Market's ranks tab, the Save and Cancel buttons immediately show up. In other guilds they only show up after I make changes. This means the core issue really lies in NeedsSave().
 
07/05/15, 04:43 PM   #2
merlight
AddOn Author - Click to view addons
Join Date: Jul 2014
Posts: 671
Another observation

Lua Code:
  1. function ZO_GuildRanks_Keyboard:RefreshRankInfo()
  2.     ...
  3.     self.rankNameEdit:SetText(rank.name)
  4.     ...
  5. end

SetText() triggers "OnTextChanged" event and leads to ZO_GuildRanks_Keyboard:GuildRankNameEdit_OnTextChanged() calling ZO_GuildRank_Shared:SetName(), which is superfluous. You're filling rankNameEdit from rank.name, and it ends up setting rank.name from rankNameEdit (and consequently setting rank.hasCustomName differently from how it was set in ZO_GuildRank_Shared:New()).

If I disable the "OnTextChanged" handler during the SetText() call, I get no freeze and Save/Cancel buttons don't show up. All four ranks have hasCustomName == true. Seems like this little thing fixes it... almost. There's still an issue with the first two ranks. When I select 'Trader' (rank #4 with custom name) and change it to 'Trader123', Save/Cancel buttons show up; and when I change it back to 'Trader', the buttons disappear. Great. But if I do the same with 'Officer' (rank #2 with default name), the buttons don't disappear after I change the name back to original 'Officer'. And now the funny part: I switch language to "de", rename rank 'Officer' to 'Officer123', Save/Cancel buttons show up, rename back to 'Officer', and the buttons disappear!

Now let me guess. The first two ranks -- 'Guildmaster' and 'Officer' -- are the default English names. But they're not default in German/French. So when the actual guildmaster saved these ranks running a German client, they were deemed custom and saved as such. Now GetGuildRankCustomName() returns these names verbatim, instead of empty strings you'd expect on English client.

In short, if (GetGuildRankCustomName(gid, rid) == GetDefaultGuildRankName(gid, rid)), then hasCustomName logic fails, and coupled with the undesirable OnTextChanged behaviour and recursive RefreshRanksFromGuildData, the game freezes.
 
07/05/15, 11:41 PM   #3
QuadroTony
Banned
AddOn Author - Click to view addons
Join Date: Apr 2014
Posts: 828
btw did you report this to the off forum too?

Last edited by QuadroTony : 07/06/15 at 05:47 AM.
 
07/06/15, 05:14 AM   #4
merlight
AddOn Author - Click to view addons
Join Date: Jul 2014
Posts: 671
No. The bug has been reported many times on official forums, and you don't get to talk to devs there. Here we have @ZOS_ChipHilseberg who can hopefully check this out, or tell someone who can.
 
07/06/15, 05:48 AM   #5
QuadroTony
Banned
AddOn Author - Click to view addons
Join Date: Apr 2014
Posts: 828
btw this is my ranks, no problem so far

 
07/07/15, 08:01 AM   #6
ZOS_ChipHilseberg
ZOS Staff!
Premium Member
Yes this person is from ZeniMax!
Join Date: Oct 2014
Posts: 551
I'll see what I can do to reproduce this internally.
 
07/07/15, 10:41 AM   #7
merlight
AddOn Author - Click to view addons
Join Date: Jul 2014
Posts: 671
Originally Posted by ZOS_ChipHilseberg View Post
I'll see what I can do to reproduce this internally.
Great. Here are the steps I just did in-game to reproduce (with English client):

1. (en) Create a new guild
2. /script SetCVar("language.2", "de")
3. (de) Rename rank #2 from "Offizier" to "Officer"
4. /script SetCVar("language.2", "en")
5. /script ZO_PreHook("DoesPlayerHaveGuildPermission", function(gid, perm) return perm == GUILD_PERMISSION_PERMISSION_EDIT end)
6. (en) open guild info, switch to the guild's ranks tab
7. (en) select rank "Officer" -> FREEZE

Note: Step 5. disables the EDIT permission, so that in step 7. function ZO_GuildRanks_Keyboard:RefreshEditPermissions() follows the regular-member code path (if NeedsSave then Cancel end).

Kill eso.exe, then log back in (English):

8. go straight to the new guild's ranks tab (the game doesn't freeze when you have EDIT permission)
9. select the "Officer" rank and immediately Save button appears
10. press Save
11. repeat steps 5-7 from above -> no freeze
 
07/07/15, 11:07 AM   #8
Halja
 
Halja's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2014
Posts: 111
Merlight,

Does launching the client in German mode to begin with show the same behavior as the English?

Using SetCVar("language.2", ... does change out the "SI_" strings for localizations but there are other components which don't get reloaded for the language change. I'm not sure of the full list but I have seen differences between using that cVAr change and re-launching the client under a different language.

--Halja
 
07/07/15, 01:16 PM   #9
merlight
AddOn Author - Click to view addons
Join Date: Jul 2014
Posts: 671
Originally Posted by Halja View Post
Does launching the client in German mode to begin with show the same behavior as the English?
I did the previous test in reverse, same results.
Start the game in English, renamed rank "Officer" to "Offizier"
Quit game
SET Language.2 "de" in UserSettings.txt
Start the game in German
/script -- that trick in step 5. above to disable edit permissions
Go to guild ranks, select "Offizier" -> FREEZE
 
07/07/15, 03:04 PM   #10
ZOS_ChipHilseberg
ZOS Staff!
Premium Member
Yes this person is from ZeniMax!
Join Date: Oct 2014
Posts: 551
I was able to reproduce this and found that changing SetName(name) to check if name ~= self.name before doing the rest of the function worked. The problem is as you described and we need to consider a name that matches the default name as custom if we didn't type it.
 

ESOUI » Developer Discussions » Bug Reports » [fixed] Custom guild rank names not well-defined -> game freezes

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