diff --git a/contrib/stats.py b/contrib/stats.py index 22c4f4c..5e5a41d 100644 --- a/contrib/stats.py +++ b/contrib/stats.py @@ -24,8 +24,12 @@ special_stats = { "poisonmindam": {"template": "dmg-pois"}, "poisonmaxdam": None, "poisonlength": None, - "mindamage": {"template": "dmg-norm"}, - "maxdamage": None, + "mindamage": {"template": "dmg-min"}, + "maxdamage": {"template": "dmg-max"}, + "secondary_mindamage": {"template": "dmg-min"}, + "secondary_maxdamage": {"template": "dmg-max"}, + "item_throw_mindamage": {"template": "dmg-min"}, + "item_throw_maxdamage": {"template": "dmg-max"}, "item_maxdamage_percent": {"template": "dmg%"}, # max before min for this stat "item_mindamage_percent": None, "item_addclassskills": { @@ -39,8 +43,8 @@ special_stats = { # instead of relying on the debug tooltips of properties.txt, since the game does not # actually use those, but rather they are present for the excel developers. properties_patches = { - "dmg-min": {"stat1": "secondary_mindamage"}, - "dmg-max": {"stat1": "secondary_maxdamage"}, + "dmg-min": {"stat1": "VARIABLE"}, + "dmg-max": {"stat1": "VARIABLE"}, "dmg%": {"stat1": "item_maxdamage_percent", "stat2": "item_mindamage_percent"}, } @@ -97,10 +101,12 @@ for stat in itemstatcost: obj = { "text": prop["tooltip"], "save_bits": [], - "save_add": itemstatcost[prop["stats"][0]]["save_add"], - "save_param_bits": itemstatcost[prop["stats"][0]]["save_param_bits"], + "save_add": itemstatcost[stat]["save_add"], + "save_param_bits": itemstatcost[stat]["save_param_bits"], } for prop_stat in prop["stats"]: + if prop_stat == "VARIABLE": + prop_stat = stat if itemstatcost[prop_stat]["save_add"] != obj["save_add"]: print( f"Unexpected divergence in save_add for stats in prop {special_stats[stat]}" diff --git a/d2warehouse/data/stats.json b/d2warehouse/data/stats.json index 8a9d947..f877ec1 100644 --- a/d2warehouse/data/stats.json +++ b/d2warehouse/data/stats.json @@ -89,9 +89,16 @@ "save_param_bits": null }, "21": { - "text": "Adds #-# Damage", + "text": "+# to Minimum Damage", + "save_bits": [ + 6 + ], + "save_add": 0, + "save_param_bits": null + }, + "22": { + "text": "+# to Maximum Damage", "save_bits": [ - 6, 7 ], "save_add": 0, @@ -869,6 +876,22 @@ "save_add": 0, "save_param_bits": null }, + "159": { + "text": "+# to Minimum Damage", + "save_bits": [ + 6 + ], + "save_add": 0, + "save_param_bits": null + }, + "160": { + "text": "+# to Maximum Damage", + "save_bits": [ + 7 + ], + "save_add": 0, + "save_param_bits": null + }, "179": { "text": "#% to Attack Rating versus [Monster Type]", "save_bits": [ diff --git a/d2warehouse/tests/test_parse_item.py b/d2warehouse/tests/test_parse_item.py index 8ea5737..f72c27a 100644 --- a/d2warehouse/tests/test_parse_item.py +++ b/d2warehouse/tests/test_parse_item.py @@ -139,3 +139,52 @@ class ParseItemTest(unittest.TestCase): data, item = parse_item(data) self.assertEqual(data, b"") self.assertEqual(str(item.stats[7]), "+2 to Druid Skill Levels") + + def test_stat_min_max_damage(self): + # Magic javelin with 3 to minimum damage and 21 attack rating + # Mod is id 21 (mindmg) + # Note: Since this is a javelin, it also has the stat 159 (min throwing dmg) + data = bytes.fromhex( + "10008000050014dddb05074ae2c006f10e701010a065420515864fc37f" + ) + data, item = parse_item(data) + self.assertEqual(data, b"") + self.assertEqual(str(item.stats[1]), "+3 to Minimum Damage") + self.assertEqual(str(item.stats[2]), "+3 to Minimum Damage") + + # Rare spear with 2 max dmg + some other stats + # Mod is id 24 (secondary_maxdmg) + data = bytes.fromhex( + "10008000050094e6095cd89f590b23557340c2629612233cf09010a14183094260109c6866232080cc7f" + ) + data, item = parse_item(data) + self.assertEqual(data, b"") + self.assertEqual(str(item.stats[2]), "+2 to Maximum Damage") + + # Unique: Husoldal Evo + # Adds 20-32 damage mod + its other stats + # Mod is 2 stats: id 23 (secondary_mindmg) and id 24 (secondary_maxdmg) + data = bytes.fromhex( + "10008000051cd4611704229c67b1472db89111a158b109e95ca0308094c85d507502ff01" + ) + data, item = parse_item(data) + self.assertEqual(data, b"") + self.assertEqual(str(item.stats[2]), "+20 to Minimum Damage") + self.assertEqual(str(item.stats[3]), "+32 to Maximum Damage") + + # Jewel with minimum & maximum damage (+ others) + # This jewel has all of the stats: + # Primary (21, 22) + # Secondary (23, 24) + # Throwing (159, 160) + data = bytes.fromhex( + "10008000050014dd004269ea621ed446f0e05be494e9d02b0e9ca8a058085c50300464045e7c524005fe03" + ) + data, item = parse_item(data) + self.assertEqual(data, b"") + self.assertEqual(str(item.stats[1]), "+10 to Minimum Damage") + self.assertEqual(str(item.stats[2]), "+1 to Maximum Damage") + self.assertEqual(str(item.stats[3]), "+10 to Minimum Damage") + self.assertEqual(str(item.stats[4]), "+1 to Maximum Damage") + self.assertEqual(str(item.stats[6]), "+10 to Minimum Damage") + self.assertEqual(str(item.stats[7]), "+1 to Maximum Damage")