collinsmith / riiablo

Diablo II remade using Java and LibGDX
http://riiablo.com
Apache License 2.0
884 stars 101 forks source link

aggregating stats versus additional stats #24

Closed collinsmith closed 5 years ago

collinsmith commented 5 years ago

Aggregations seem to be performed on a list-by-list basis, i.e., runeword properties will add to existing magic properties, but set properties will not aggregate with magic and (I assume, but untested) rune properties.

It seems that multiple copies of the same aggregateable skill in a single list will choose the last one. Some skills maintain their independence, e.g., charged skills will not overwrite if it's the same skill with a different level (i.e., different param value), but if the level and skill are the same (i.e., same param value) the skill is overwritten. In this case, the charges will add to each other.

I need to enumerate this relationship and investigate more, but my best guess is:

To reiterate on the property lists:

So, item inherent properties list will be all the active list values added together, and then the algorithm will run to modify the item values all at once, so all the properties ED will add together and then when the lists are all added, ED will actually be calculated and applied to defense stat, etc.

TODO: how do things like aggregated charges work, since I'm guessing it subtracts a charge from one of the properties internally and then maybe re-generates the aggregate stat. TODO: I need to figure out and more clearly define the differentiation between the visual list aggregation and the actual item property aggregation, since all the item stats need to continue to be discrete internally for saving purposes, but I don't think it's realistic to calculate them on the fly every time a stat is retrieved at least visually

collinsmith commented 5 years ago

I'm going to try and rewrite my stat and property list class as PropertyList which wraps an IntMap and uses statId | (param << 16) as the key (stats are represented as their int indexes and no longer as an enum). The max bits for param=16 and the max bits for statId=9 so this is well within the required bounds. I'm choosing to give statId extra width to support additional stats, but I don't plan on adding many, if any. So far this is working out well, however I cannot sort the results (expected) and I'll need to generate a sorted list for the visual representation of the stats separately -- this will actually help when I aggregate multiple stats.

I'm not going to build it in yet, but I'm also considering how item updates will be made. Some stats have callbacks, e.g., charged item skills that add the skill to the user when equipped. With charged item skills, this is also a 2-way street because using the skill should modify the item stat, etc. I'm assuming too that something similar should be used if say an item is equipped and the players strength drops below the required strength, then item should appear red (equipped but unusable).

collinsmith commented 5 years ago

I mentioned this in https://github.com/collinsmith/diablo/issues/19#issuecomment-475806740

How I'm going to support

strModAllResistances        All Resistances +%d
strModFireDamage        +%d fire damage
strModFireDamageRange       Adds %d-%d fire damage
strModColdDamage        +%d cold damage
strModColdDamageRange       Adds %d-%d cold damage
strModLightningDamage       +%d lightning damage
strModLightningDamageRange  Adds %d-%d lightning damage
strModMagicDamage       +%d magic damage
strModMagicDamageRange      Adds %d-%d magic damage
strModPoisonDamage      +%d poison damage over %d seconds
strModPoisonDamageRange     Adds %d-%d poison damage over %d seconds
strModMinDamage         +%d damage
strModMinDamageRange        Adds %d-%d damage
strModEnhancedDamage        Enhanced damage

Since these are all visual only and will only be present in the item details, I think I will address this by formatting "fake" stats. I.e., when generating the item details I will omit the discrete stats and add the above aggregate stat instead (I may also ignore dgrp because it's inconsistent and handle it with all the others). These may use a custom descfunc and possibly even encoding, or I can just generate the string manually. The concern with trying to hack it into a custom descfunc or encoding is that all of the multi-value props may not fit within 32-bits (they very well might). Another approach I might take is making a new aggregate stat class AggregateStat which has 2+ children Stat instances and a pre-determined string for multi-value or single value (Range or no range variant), but in this case, all resistances and all attributes behaves differently when all the stats are different (they output as their super).

collinsmith commented 5 years ago

I just wanted to note that I realized with this approach _bytime properties include all of their params within the value field, therefore something that is really a param such as time of day is in the value field (i.e., two _bytime properties with different times should remain discrete). My solution to this problem will be to hard-code the _bytime properties as param=2 bits, value=20 bits. I may not implement this immediately, but when I decide I want to support _bytime properties, the workaround is here.

collinsmith commented 5 years ago

As for list aggregations for the display details:

A better way of thinking of this too is:

So because both magic and runeword property lists are same group, they are added, while the other remain discrete.

collinsmith commented 5 years ago

Support for socketed item attributes is on the docket to be added. For jewels this should be fairly straightforward as they have discrete magical properties, however gems and runes may provide a challenge. My current assumption for gems and runes is to assume they have no inherent magical properties and sort of add them on the fly depending on the item they are socketed into (these have different properties for weapons, armors/helms, shields). I will need to investigate a bit on how difficult this might be, because these items have their properties within gems.txt which is not yet supported and looks like it relies on properties.txt which is also not yet supported. Adding support for properties.txt is a necessary prerequisite to properly supporting set bonuses (the gold bonus applied to the set as a whole).

collinsmith commented 5 years ago

I added descriptions for gems/runes. As far as displaying the selected property list in the parent item description, I think it might be possible to use the existing property lists (i.e., indexes 0-3 for weapon, armor, helm, shield or whatever order is best) for the properties, but this is a bit more complicated since gems are "simple" items with no magical properties, and then these lists shouldn't display as if they were magical properties in the original item (they display as white in the game).

collinsmith commented 5 years ago

20b84c8 added support for socketed items properties aggregating with their parents

collinsmith commented 5 years ago

I rewrote part of property list to more appropriately handle adding properties. The properties will generate randomly. This is largely untested because item generation is not yet implemented, but it should be a good start. This was necessary because gems and runes contain no inherent properties, so their properties must be generated on the fly and aggregated with their parent item (they are not random though, e.g., they give random(10,10) to stats, which eval to just 10).

collinsmith commented 5 years ago

Most properties work as expected, however there are at least 2 which do not. maxdamage and secondary_maxdamage both display the same value +%d to Maximum Damage and since both are present on some items, the attribute appears twice. item_throw_maxdamage should also appear, but that is a non-visible stat. I think for stats like these I will try aggregating all min damage and all max damage stats together --- after the min/max pairs have aggregated. I haven't seen any other oddballs.

collinsmith commented 5 years ago

I'm going to close this issue. I think everything has been covered on the visual end of item stats. I'll reopen if necessary.