Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

5-bit set IDs theory #5

Open
youbetterdont opened this issue Mar 17, 2019 · 13 comments
Open

5-bit set IDs theory #5

youbetterdont opened this issue Mar 17, 2019 · 13 comments

Comments

@youbetterdont
Copy link

d2s/item.go

Line 458 in db00d42

Is there a chance there could be more info lurking in this 5 bit value? The decoding appears to just be a count of the number of ones in the binary number. The position of the bits may indicate how many set pieces are needed to activate the bonus, for example. I was thinking about the best way to get the set bonuses working, and this would be some nice info to have if that's how it works. I might try to dig through the binary myself at some point, but thought I'd ask here first.

--M81 from slash discord

@squeek502
Copy link
Contributor

squeek502 commented Mar 18, 2019

Good catch. Did some testing and you're exactly right. The set bits correspond with how many items of that set need to be worn to get that bonus, and also with the values of the aprop fields in SetItems.txt.

If the bits are numbered 54321:

  • If bit 1 is set, then it requires >= 2 items worn
  • If bit 2 is set, then it requires >= 3 items worn
  • If bit 3 is set, then it requires >= 4 items worn
  • If bit 4 is set, then it requires >= 5 items worn
  • If bit 5 is set, then it requires >= 6 items worn

Examples:

  • M'avina's Belt
    • Set bonuses flag: 4 (00100)
    • SetItems.txt only has aprop3 field set
    • Only gets the bonus when >= 4 items are worn
  • IK Armor
    • Set bonuses flag: 31 (11111)
    • SetItems.txt has aprop1-aprop5 fields set
    • Get a new bonus each additional item that is worn
  • Trang's Armor
    • Set bonuses flag: 10 (01010)
    • SetItems.txt has aprop2 and aprop4 fields set
    • Only gets a new bonus when >= 3 items are worn and then another at >= 5 worn

@nokka
Copy link
Owner

nokka commented Mar 18, 2019

Yes you're right, the data should be there, I know I figured out the rules like two years ago when I did this, I can't remember exactly but there's a flag (the one you linked) that tells us how many lists of magical properties to read, and the lists are read here.

I think the thing left is to figure out how many set pieces you have to wear to get the bonus, so we can apply in the frontend on the Armory for example, to calculate the correct bonuses.

@youbetterdont
Copy link
Author

youbetterdont commented Mar 18, 2019

@nokka, are you saying you do read that information out somewhere? My comment was that not only does that 5-bit number tell you how many lists to read, it also tells you which bonuses to apply. It looks like @squeek502 confirmed this.

I did manage to figure out how to apply the green-text set bonuses without this extra piece of information, but it does require a bit more work. You can take a look here if you're curious. I still need to apply the partial and full set bonuses (gold text), but this should be pretty easy using the Sets.txt->Properties.txt->ItemStatCost.txt lookup. I assume these properties are not in the d2s file, and it doesn't look like the set ID itself is either ("Tal Rasha's Wrappings").

If I get this all working, I can let you know. Maybe there's an easy way to make it work with the armory.

@squeek502, one other thing to check is how this field works with the super special set item Civerb's Ward. That one has bonuses that depend on equipping specific other set items (not how many total pieces are worn). I believe this is the only item that works this way, so it's more of a curiosity. Maybe mod makers use this rare feature more.

My guess is it works the same way in that it corresponds to the aprop fields of SetItems.txt. Still, it seems there's no avoiding a lookup in the *.txt files.

squeek502 added a commit to squeek502/d2s that referenced this issue Mar 18, 2019
`set_attributes_req` is a companion array to `set_attributes` that stores the number of items that need to be worn for the corresponding property list to be active

Example json output:
```
"set_attributes":[[{"id":43,"name":"Cold Resist +{0}%","values":[40]}]],"set_attributes_req":[3]
```

which means that set_attributes[0] requires >= 3 items (set_attributes_req[0] is 3) of the set to be worn to recieve those bonuses

Addresses nokka#5
@squeek502
Copy link
Contributor

d2s currently doesn't put that info in the json. Made a PR for that: #6

@youbetterdont I haven't tested to see what the bits are set to for Civerb's Ward, but judging from SetItems.txt, it's probably a hardcoded special case in the code, since there's nothing that separates it in SetItems.txt (one possible bonus is in aprop1, one is in aprop2). My PR doesn't handle that special case.

@youbetterdont
Copy link
Author

That's a nice solution. So is my understanding correct that there is no reference to the set itself, nor is there any information about the gold-text set bonuses in the d2s file?

As far as the add_func=1 case, I bet the bit positions are tied to specific set pieces rather than the number of set items equipped, but this doesn't really impact anything on the file parsing side. We can always reconstruct the bitmask by placing a 1 in the bit positions specified by the new set_attributes_req list.

@squeek502
Copy link
Contributor

squeek502 commented Mar 18, 2019

there is no reference to the set itself, nor is there any information about the gold-text set bonuses in the d2s file

Correct

add_func=1

Ah, I see, yeah that does differentiate Civerb's Ward in SetItems.txt, didn't notice that before. Will do more testing on that.

EDIT: Here's a description of add_func=1: https://d2mods.info/forum/kb/viewarticle?a=348 (see the Appendix at the bottom)

@squeek502
Copy link
Contributor

squeek502 commented Mar 19, 2019

Confirmed that the bits are set the same with add_func 1 and 2. Civerb's Ward has the 5 bits set as: 00011. Not sure how it would be best for d2s to account for that.

@youbetterdont
Copy link
Author

I don’t think d2s can account for it. Seems like a lookup into the txt files is unavoidable anyway given that we don’t have a set ID or the gold text properties. I bet the bit positions are ordered consistently with the set items in SetItems.txt. That is, the LSB in this case is civerb’s Amulet, and the next bit is civerb’s scepter. The scheme you already implemented should still work fine. We should just think of the numbers representing set item offsets instead of total number of items worn.

If we want to integrate this with the armory, what is the best way to do that? The code I’m working on could produce a modified JSON file after the *.txt lookups. Not sure if combing through the game data files is in the scope of d2s.

@squeek502
Copy link
Contributor

squeek502 commented Mar 19, 2019

See the link I edited into a previous comment for a detailed description of add_func=1 (see appendix at the bottom). Some possible things that d2s could do (in addition to whats in #6):

  • Add a second companion array that gets filled with set IDs of the items required for those bonuses. So, for Civerb's Ward that'd look like [1, 2] (set IDs of the amulet and scepter respectively)
  • Use set_attributes_req for both, and have a second variable that provides the add_func for the item, so then users would switch how they use set_attributes_req depending on that second var.
  • Provide the 5 bits directly and let the user handle it

@squeek502
Copy link
Contributor

As for the overall set bonuses and set names, it might be consistent to hard-code them into d2s and provide them in their own key in the json when applicable. That would be pretty similar to e.g. socketables.go, as otherwise the rune bonuses would require a .txt lookup as well.

@youbetterdont
Copy link
Author

Thanks for the link. I've actually been referring to these item guides quite frequently. My thoughts:

Add a second companion array that gets filled with set IDs of the items required for those bonuses. So, for Civerb's Ward that'd look like [1, 2] (set IDs of the amulet and scepter respectively)

I think this information may already be here and encoded in the bit positions, but it's hard to confirm this given that this one item is the only exception.

Use set_attributes_req for both, and have a second variable that provides the add_func for the item, so then users would switch how they use set_attributes_req depending on that second var.

This would require a lookup to SetItems.txt, right? If you do this lookup, then you could just modify the set_attributes directly.

Provide the 5 bits directly and let the user handle it

This information is already in the scheme you've chosen if you think of the numbers in the list as bit positions instead of items required.

As for the overall set bonuses and set names, it might be consistent to hard-code them into d2s and provide them in their own key in the json when applicable. That would be pretty similar to e.g. socketables.go, as otherwise the rune bonuses would require a .txt lookup as well.

Is there a good reason to avoid the lookups? Hard-coding will make d2s less portable to other mods for example.

@squeek502
Copy link
Contributor

squeek502 commented Mar 19, 2019

I think this information may already be here and encoded in the bit positions, but it's hard to confirm this given that this one item is the only exception.

It is, but only by accident. If it was the amulet that used add_func=1 instead of the shield, then the required set IDs would be [0, 2] (shield and scepter respectively), but the bits would still look like 00011.

This information is already in the scheme you've chosen if you think of the numbers in the list as bit positions instead of items required.

True, but if the user is expected to need the bit position info, then it'd make more sense to provide it in a more usable format instead of having to do a very non-obvious transformation (bits |= 1 << (set_attributes_req[i] - 2) for i=0 to 4).

Is there a good reason to avoid the lookups? Hard-coding will make d2s less portable to other mods for example.

d2s is already extremely coupled to vanilla D2. It hard-codes language strings, ItemStatCost.txt values, rune bonuses, item stats like weapon damage, weapon/armor/stackable item codes, etc, etc. Decoupling it while providing the same json output would take a pretty extensive rewrite. For example, reading items in general needs info from Armor.txt, Weapons.txt, Misc.txt, and ItemStatCost.txt.

@youbetterdont
Copy link
Author

Gotcha. I just started working with the d2s JSON output, so I’m still new to this! I really like the output format. Super easy to work with.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants