Files
d2warehouse/d2warehouse/tests/test_parse_item.py

251 lines
10 KiB
Python

import unittest
from d2warehouse.parser import parse_item
from d2warehouse.item import Quality, lookup_affix, lookup_runeword
class ParseItemTest(unittest.TestCase):
def test_gem(self):
# chipped diamond
data = bytes.fromhex("1000a0000524740910")
data, item = parse_item(data)
self.assertEqual(data, b"")
self.assertEqual(item.code, "gcw")
self.assertEqual(item.pos_x, 9)
self.assertEqual(item.pos_y, 0)
self.assertTrue(item.is_simple)
def test_buckler(self):
# white buckler
data = bytes.fromhex("10008000050054a1083f57a9190c01041818fc07")
data, item = parse_item(data)
self.assertEqual(data, b"")
self.assertEqual(item.code, "buc")
self.assertEqual(item.pos_x, 0)
self.assertEqual(item.pos_y, 0)
self.assertEqual(item.quality, Quality.NORMAL)
self.assertFalse(item.is_simple)
self.assertEqual(item.lvl, 12)
def test_rune(self):
# tal rune
data = bytes.fromhex("1000a0000564f67cfb00")
data, item = parse_item(data)
self.assertEqual(data, b"")
self.assertEqual(item.code, "r07")
self.assertEqual(item.pos_x, 9)
self.assertEqual(item.pos_y, 9)
self.assertTrue(item.is_simple)
def test_rare_a(self):
# random rare armor
data = bytes.fromhex(
"10008000050014df17c64083c30b866d534c958c39d15b42c0c1e1c08815cd9c04f80dff01"
)
data, item = parse_item(data)
self.assertEqual(data, b"")
self.assertEqual(item.code, "hla")
self.assertEqual(item.pos_x, 0)
self.assertEqual(item.pos_y, 0)
self.assertEqual(item.quality, Quality.RARE)
self.assertFalse(item.is_simple)
self.assertEqual(item.lvl, 5)
self.assertEqual(len(item.stats), 4)
self.assertEqual(item.defense, 23)
self.assertEqual(item.durability, 28)
self.assertEqual(item.max_durability, 28)
def test_tp_tome(self):
data = bytes.fromhex("100080000500d4a814daf7275a180240e03f")
data, item = parse_item(data)
self.assertEqual(data, b"")
self.assertEqual(item.code, "tbk")
self.assertEqual(item.quantity, 4)
def test_superior_sockets(self):
# superior armor with empty sockets
data = bytes.fromhex("10088000050014df175043b1b90cc38d80e3834070b004f41f")
data, item = parse_item(data)
self.assertEqual(data, b"")
self.assertEqual(item.quality, Quality.HIGH)
self.assertEqual(len(item.stats), 2)
self.assertEqual(item.sockets, 2)
self.assertEqual(len(item.socketed_items), 0)
def test_ed_max(self):
# test bugfix for https://gitlab.com/omicron-oss/d2warehouse/-/issues/1
data = bytes.fromhex(
"10008000050094e6095cd89f590b23557340c2629612233cf09010a14183094260109c6866232080cc7f"
)
data, item = parse_item(data)
self.assertEqual(data, b"")
self.assertEqual(item.code, "spr")
self.assertEqual(str(item.stats[0]), "+13% Enhanced Damage")
self.assertEqual(str(item.stats[2]), "+2 to Maximum Damage")
def test_runeword_lore(self):
# Lore: Ort Sol
data = bytes.fromhex(
"1008800405c055c637f1073af4558697412981070881506049e87f005516fb134582ff1000a0003500e07cbb001000a0003504e07c9800"
)
data, item = parse_item(data)
self.assertEqual(data, b"")
self.assertTrue(item.is_runeword)
self.assertEqual(item.sockets, 2)
self.assertEqual(item.socketed_items[0].code, "r09")
self.assertEqual(item.socketed_items[1].code, "r12")
rw = lookup_runeword(item.runeword_id)
self.assertEqual(rw["name"], "Lore")
self.assertEqual(str(item.stats[4]), "+1 to All Skills") # runeword stat
self.assertEqual(str(item.stats[2]), "+10 to Energy") # runeword stat
# TODO: sol rune stat -- should it be in representation?
# self.assertEqual(str(item.sockets[1].stats[0]), "Lightning Resist 30%")
def test_item_with_implicit(self):
# A 3 socket heraldic shield with 13 all res
data = bytes.fromhex(
"10088000054074be6dd0113247e788182002141273a25a8a6a2baab5a8f61f"
)
data, item = parse_item(data)
self.assertEqual(data, b"")
self.assertEqual(item.implicit, 24) # Rainbow, 8-15 all res
self.assertEqual(str(item.stats[0]), "Fire Resist +13%")
self.assertEqual(str(item.stats[1]), "Lightning Resist +13%")
self.assertEqual(str(item.stats[2]), "Cold Resist +13%")
self.assertEqual(str(item.stats[3]), "Poison Resist +13%")
def test_stackable_weapon(self):
data = bytes.fromhex("10208000054814dddb852a79b4708640408096ff")
data, item = parse_item(data)
self.assertEqual(data, b"")
def test_token_of_absolution(self):
# 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")
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")
def test_stat_indestructible(self):
# Shadow Killer, Unique claw with indestructible property
data = bytes.fromhex(
"1000c0000580d40b0aa72367d4d7c32920f588e0cc199d8c21a16881a9318485d07f"
)
data, item = parse_item(data)
self.assertEqual(data, b"")
self.assertEqual(str(item.stats[4]), "Indestructible")
def test_gorefoot(self):
data = bytes.fromhex(
"10008000050475a7260ca7d38d420f3610018706103c7cb0800f81130118d41a426244f80f"
)
data, item = parse_item(data)
self.assertEqual(data, b"")
self.assertEqual(item.stats[6].id, 140) # Extra Blood special stat
def test_byte_alignment(self):
# Fix for issue involving e.g. Natalya's Shadow
data = bytes.fromhex(
"100880000500148a1be03d81e1ae0510a00f0986001f4cd1229c9b2f5e3100c286fc07"
)
data, _ = parse_item(data)
self.assertEqual(data, b"")
def test_affixes(self):
data = bytes.fromhex(
"1000800005d0f4aa09173a36bf0723542d351ae4236acbd27000c30201a1052810208cf1241b4c50fc07"
)
data, item = parse_item(data)
self.assertEqual(data, b"")
req = item.requirements()
self.assertEqual(req["lvl"], 4)
# +8 stamina
self.assertAlmostEqual(lookup_affix(item.prefixes[0], True)["name"], "Rugged")
# 16% ed
self.assertAlmostEqual(lookup_affix(item.prefixes[1], True)["name"], "Sturdy")
# 10% fhr
self.assertAlmostEqual(
lookup_affix(item.suffixes[0], False)["name"], "of Balance"
)
# +1 dex
self.assertAlmostEqual(
lookup_affix(item.suffixes[1], False)["name"], "of Dexterity"
)
# Lightning bolt on hit
self.assertAlmostEqual(
lookup_affix(item.suffixes[2], False)["name"], "of Charged Shield"
)
def test_cathans_rule(self):
# Cathan's Rule: Only source of fire-max stat
data = bytes.fromhex(
"10008000050054c90448ad74276f910150448c180afc24ff1348fd3f212d85b415d25a48fb0f"
)
data, item = parse_item(data)
self.assertEqual(data, b"")
self.assertEqual(str(item.stats[0]), "+10 to Maximum Fire Damage")