Fix extracting +X to Class Skills with param value

This commit is contained in:
2023-10-25 18:08:48 +02:00
parent b5b7149c79
commit 91a62f03ac
4 changed files with 109 additions and 44 deletions

View File

@@ -8,27 +8,30 @@ import sys
path = sys.argv[1] if len(sys.argv) >= 2 else "."
# NOTE: These map "linked stats" to code in properties.txt.
# If None is given, the stat is excluded from the output.
# NOTE: Special handling of stats. None = Skip stat.
# Note that All Resistance is actually 4 stats in the save files, that the game combines
# into one. Same applies for all stats.
special_stats = {
"firemindam": "dmg-fire",
"firemindam": {"template": "dmg-fire"},
"firemaxdam": None,
"lightmindam": "dmg-ltng",
"lightmindam": {"template": "dmg-ltng"},
"lightmaxdam": None,
"magicmindam": "dmg-mag",
"magicmindam": {"template": "dmg-mag"},
"magicmaxdam": None,
"coldmindam": "dmg-cold",
"coldmindam": {"template": "dmg-cold"},
"coldmaxdam": None,
"coldlength": None,
"poisonmindam": "dmg-pois",
"poisonmindam": {"template": "dmg-pois"},
"poisonmaxdam": None,
"poisonlength": None,
"mindamage": "dmg-norm",
"mindamage": {"template": "dmg-norm"},
"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_addclassskills": {
"template": "ama",
"param_tooltips": ["ama", "pal", "nec", "sor", "bar", "dru", "ass"],
},
}
# Patching of missing data in properties.txt
@@ -53,6 +56,7 @@ with open(os.path.join(path, "properties.txt")) as f:
prop = {
"stats": [row[f"stat{i}"] for i in range(1, 8) if len(row[f"stat{i}"]) > 0],
"tooltip": row["*Tooltip"],
"val1": None if len(row["val1"]) == 0 else int(row["val1"]),
}
properties[row["code"]] = prop
if len(prop["stats"]) == 1 and prop["stats"][0] not in stat_to_prop:
@@ -72,12 +76,24 @@ with open(os.path.join(path, "itemstatcost.txt")) as f:
}
stats = {}
for stat, statdat in itemstatcost.items():
if stat in special_stats:
if special_stats[stat] is None:
for stat in itemstatcost:
try:
special = (
special_stats[stat]
if stat in special_stats
else {"template": stat_to_prop[stat]}
)
except KeyError:
print(
f"Failed getting property for stat {stat}. Skipping! (See `special_stats` for fixing)"
)
continue
else:
prop = properties[special_stats[stat]]
# special = None -> Skip
if special is None:
continue
# special.template: properties.txt row
prop = properties[special["template"]]
obj = {
"text": prop["tooltip"],
"save_bits": [],
@@ -90,21 +106,21 @@ for stat, statdat in itemstatcost.items():
f"Unexpected divergence in save_add for stats in prop {special_stats[stat]}"
)
obj["save_bits"].append(itemstatcost[prop_stat]["save_bits"])
else:
try:
prop = properties[stat_to_prop[stat]]
except KeyError:
print(
f"Failed getting property for stat {stat}. Skipping! (See `special_stats` for fixing)"
)
continue
obj = {
# special.param_tooltips: extra tooltips depending on param value
if "param_tooltips" in special:
tooltips = []
for id in special["param_tooltips"]:
prop = properties[id]
tooltips.append(
{
"param": prop["val1"],
"text": prop["tooltip"],
"save_bits": [statdat["save_bits"]],
"save_add": statdat["save_add"],
"save_param_bits": statdat["save_param_bits"],
}
stats[statdat["id"]] = obj
)
obj["text"] = tooltips
stats[itemstatcost[stat]["id"]] = obj
with open("stats.json", "w", newline="\n") as f:
json.dump(stats, f, indent=4)

View File

@@ -393,7 +393,36 @@
"save_param_bits": null
},
"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": [
3
],

View File

@@ -65,11 +65,16 @@ class Stat:
print(" " * indent, str(self))
def __str__(self):
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:
subst_text = subst_text.replace("#", str(val), 1)
if self.parameter:
subst_text = re.sub(r"\[[^\]]*\]", str(self.parameter), subst_text, 1)
if param:
subst_text = re.sub(r"\[[^\]]*\]", str(param), subst_text, 1)
return subst_text

View File

@@ -123,4 +123,19 @@ class ParseItemTest(unittest.TestCase):
# this is one of the items that had stackable "0" instead of ""
data = bytes.fromhex("100080000524d4fc5f308dc1e10908fe03")
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(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")