forked from omicron/d2warehouse
Fix extracting +X to Class Skills with param value
This commit is contained in:
@@ -8,27 +8,30 @@ import sys
|
|||||||
|
|
||||||
path = sys.argv[1] if len(sys.argv) >= 2 else "."
|
path = sys.argv[1] if len(sys.argv) >= 2 else "."
|
||||||
|
|
||||||
# NOTE: These map "linked stats" to code in properties.txt.
|
# NOTE: Special handling of stats. None = Skip stat.
|
||||||
# If None is given, the stat is excluded from the output.
|
|
||||||
# Note that All Resistance is actually 4 stats in the save files, that the game combines
|
# Note that All Resistance is actually 4 stats in the save files, that the game combines
|
||||||
# into one. Same applies for all stats.
|
# into one. Same applies for all stats.
|
||||||
special_stats = {
|
special_stats = {
|
||||||
"firemindam": "dmg-fire",
|
"firemindam": {"template": "dmg-fire"},
|
||||||
"firemaxdam": None,
|
"firemaxdam": None,
|
||||||
"lightmindam": "dmg-ltng",
|
"lightmindam": {"template": "dmg-ltng"},
|
||||||
"lightmaxdam": None,
|
"lightmaxdam": None,
|
||||||
"magicmindam": "dmg-mag",
|
"magicmindam": {"template": "dmg-mag"},
|
||||||
"magicmaxdam": None,
|
"magicmaxdam": None,
|
||||||
"coldmindam": "dmg-cold",
|
"coldmindam": {"template": "dmg-cold"},
|
||||||
"coldmaxdam": None,
|
"coldmaxdam": None,
|
||||||
"coldlength": None,
|
"coldlength": None,
|
||||||
"poisonmindam": "dmg-pois",
|
"poisonmindam": {"template": "dmg-pois"},
|
||||||
"poisonmaxdam": None,
|
"poisonmaxdam": None,
|
||||||
"poisonlength": None,
|
"poisonlength": None,
|
||||||
"mindamage": "dmg-norm",
|
"mindamage": {"template": "dmg-norm"},
|
||||||
"maxdamage": None,
|
"maxdamage": None,
|
||||||
"item_maxdamage_percent": "dmg%", # max before min for this stat
|
"item_maxdamage_percent": {"template": "dmg%"}, # max before min for this stat
|
||||||
"item_mindamage_percent": None,
|
"item_mindamage_percent": None,
|
||||||
|
"item_addclassskills": {
|
||||||
|
"template": "ama",
|
||||||
|
"param_tooltips": ["ama", "pal", "nec", "sor", "bar", "dru", "ass"],
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
# Patching of missing data in properties.txt
|
# Patching of missing data in properties.txt
|
||||||
@@ -53,6 +56,7 @@ with open(os.path.join(path, "properties.txt")) as f:
|
|||||||
prop = {
|
prop = {
|
||||||
"stats": [row[f"stat{i}"] for i in range(1, 8) if len(row[f"stat{i}"]) > 0],
|
"stats": [row[f"stat{i}"] for i in range(1, 8) if len(row[f"stat{i}"]) > 0],
|
||||||
"tooltip": row["*Tooltip"],
|
"tooltip": row["*Tooltip"],
|
||||||
|
"val1": None if len(row["val1"]) == 0 else int(row["val1"]),
|
||||||
}
|
}
|
||||||
properties[row["code"]] = prop
|
properties[row["code"]] = prop
|
||||||
if len(prop["stats"]) == 1 and prop["stats"][0] not in stat_to_prop:
|
if len(prop["stats"]) == 1 and prop["stats"][0] not in stat_to_prop:
|
||||||
@@ -72,39 +76,51 @@ with open(os.path.join(path, "itemstatcost.txt")) as f:
|
|||||||
}
|
}
|
||||||
|
|
||||||
stats = {}
|
stats = {}
|
||||||
for stat, statdat in itemstatcost.items():
|
for stat in itemstatcost:
|
||||||
if stat in special_stats:
|
try:
|
||||||
if special_stats[stat] is None:
|
special = (
|
||||||
continue
|
special_stats[stat]
|
||||||
else:
|
if stat in special_stats
|
||||||
prop = properties[special_stats[stat]]
|
else {"template": stat_to_prop[stat]}
|
||||||
obj = {
|
)
|
||||||
"text": prop["tooltip"],
|
except KeyError:
|
||||||
"save_bits": [],
|
print(
|
||||||
"save_add": itemstatcost[prop["stats"][0]]["save_add"],
|
f"Failed getting property for stat {stat}. Skipping! (See `special_stats` for fixing)"
|
||||||
"save_param_bits": itemstatcost[prop["stats"][0]]["save_param_bits"],
|
)
|
||||||
}
|
continue
|
||||||
for prop_stat in prop["stats"]:
|
# special = None -> Skip
|
||||||
if itemstatcost[prop_stat]["save_add"] != obj["save_add"]:
|
if special is None:
|
||||||
print(
|
continue
|
||||||
f"Unexpected divergence in save_add for stats in prop {special_stats[stat]}"
|
|
||||||
)
|
# special.template: properties.txt row
|
||||||
obj["save_bits"].append(itemstatcost[prop_stat]["save_bits"])
|
prop = properties[special["template"]]
|
||||||
else:
|
obj = {
|
||||||
try:
|
"text": prop["tooltip"],
|
||||||
prop = properties[stat_to_prop[stat]]
|
"save_bits": [],
|
||||||
except KeyError:
|
"save_add": itemstatcost[prop["stats"][0]]["save_add"],
|
||||||
|
"save_param_bits": itemstatcost[prop["stats"][0]]["save_param_bits"],
|
||||||
|
}
|
||||||
|
for prop_stat in prop["stats"]:
|
||||||
|
if itemstatcost[prop_stat]["save_add"] != obj["save_add"]:
|
||||||
print(
|
print(
|
||||||
f"Failed getting property for stat {stat}. Skipping! (See `special_stats` for fixing)"
|
f"Unexpected divergence in save_add for stats in prop {special_stats[stat]}"
|
||||||
)
|
)
|
||||||
continue
|
obj["save_bits"].append(itemstatcost[prop_stat]["save_bits"])
|
||||||
obj = {
|
|
||||||
"text": prop["tooltip"],
|
# special.param_tooltips: extra tooltips depending on param value
|
||||||
"save_bits": [statdat["save_bits"]],
|
if "param_tooltips" in special:
|
||||||
"save_add": statdat["save_add"],
|
tooltips = []
|
||||||
"save_param_bits": statdat["save_param_bits"],
|
for id in special["param_tooltips"]:
|
||||||
}
|
prop = properties[id]
|
||||||
stats[statdat["id"]] = obj
|
tooltips.append(
|
||||||
|
{
|
||||||
|
"param": prop["val1"],
|
||||||
|
"text": prop["tooltip"],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
obj["text"] = tooltips
|
||||||
|
|
||||||
|
stats[itemstatcost[stat]["id"]] = obj
|
||||||
|
|
||||||
with open("stats.json", "w", newline="\n") as f:
|
with open("stats.json", "w", newline="\n") as f:
|
||||||
json.dump(stats, f, indent=4)
|
json.dump(stats, f, indent=4)
|
||||||
|
|||||||
@@ -393,7 +393,36 @@
|
|||||||
"save_param_bits": null
|
"save_param_bits": null
|
||||||
},
|
},
|
||||||
"83": {
|
"83": {
|
||||||
"text": "+# to Amazon Skill Levels",
|
"text": [
|
||||||
|
{
|
||||||
|
"param": 0,
|
||||||
|
"text": "+# to Amazon Skill Levels"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"param": 3,
|
||||||
|
"text": "+# to Paladin Skill Levels"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"param": 2,
|
||||||
|
"text": "+# to Necromancer Skill Levels"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"param": 1,
|
||||||
|
"text": "+# to Sorceress Skill Levels"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"param": 4,
|
||||||
|
"text": "+# to Barbarian Skill Levels"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"param": 5,
|
||||||
|
"text": "+# to Druid Skill Levels"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"param": 6,
|
||||||
|
"text": "+# to Assassin Skill Levels"
|
||||||
|
}
|
||||||
|
],
|
||||||
"save_bits": [
|
"save_bits": [
|
||||||
3
|
3
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -65,11 +65,16 @@ class Stat:
|
|||||||
print(" " * indent, str(self))
|
print(" " * indent, str(self))
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
subst_text = self.text
|
param = self.parameter
|
||||||
|
if isinstance(self.text, list):
|
||||||
|
subst_text = next(filter(lambda v: v["param"] == param, self.text))["text"]
|
||||||
|
param = None
|
||||||
|
else:
|
||||||
|
subst_text = self.text
|
||||||
for val in self.values:
|
for val in self.values:
|
||||||
subst_text = subst_text.replace("#", str(val), 1)
|
subst_text = subst_text.replace("#", str(val), 1)
|
||||||
if self.parameter:
|
if param:
|
||||||
subst_text = re.sub(r"\[[^\]]*\]", str(self.parameter), subst_text, 1)
|
subst_text = re.sub(r"\[[^\]]*\]", str(param), subst_text, 1)
|
||||||
return subst_text
|
return subst_text
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -123,4 +123,19 @@ class ParseItemTest(unittest.TestCase):
|
|||||||
# this is one of the items that had stackable "0" instead of ""
|
# this is one of the items that had stackable "0" instead of ""
|
||||||
data = bytes.fromhex("100080000524d4fc5f308dc1e10908fe03")
|
data = bytes.fromhex("100080000524d4fc5f308dc1e10908fe03")
|
||||||
data, item = parse_item(data)
|
data, item = parse_item(data)
|
||||||
|
|
||||||
|
def test_stat_to_class_skills(self):
|
||||||
|
# Redeemer with +2 to Paladin skill levels
|
||||||
|
data = bytes.fromhex(
|
||||||
|
"1000800005c4d593081e37d107dfa330c868881031e29429cb6d415953466bf8eccd1c3aa13ce9fe03"
|
||||||
|
)
|
||||||
|
data, item = parse_item(data)
|
||||||
self.assertEqual(data, b"")
|
self.assertEqual(data, b"")
|
||||||
|
self.assertEqual(str(item.stats[1]), "+2 to Paladin Skill Levels")
|
||||||
|
# Jalal with +2 to Druid skills levels
|
||||||
|
data = bytes.fromhex(
|
||||||
|
"1000800005c4753c2f5c4c4e3d638f8fd0068a08006802d020ac3a612e85b915e65a989b528d91dd41a1a8c02b0540ff01"
|
||||||
|
)
|
||||||
|
data, item = parse_item(data)
|
||||||
|
self.assertEqual(data, b"")
|
||||||
|
self.assertEqual(str(item.stats[7]), "+2 to Druid Skill Levels")
|
||||||
|
|||||||
Reference in New Issue
Block a user