forked from omicron/d2warehouse
Switch from affixes.json to stats.json
This commit is contained in:
@@ -1,215 +0,0 @@
|
|||||||
{
|
|
||||||
"0": {"bits": [8], "bias": 32, "text": "+{0} to Strength"},
|
|
||||||
"1": {"bits": [7], "bias": 32, "text": "+{0} to Energy"},
|
|
||||||
"2": {"bits": [7], "bias": 32, "text": "+{0} to Dexterity"},
|
|
||||||
"3": {"bits": [7], "bias": 32, "text": "+{0} to Vitality"},
|
|
||||||
"7": {"bits": [9], "bias": 32, "text": "+{0} to Life"},
|
|
||||||
"9": {"bits": [8], "bias": 32, "text": "+{0} to Mana"},
|
|
||||||
"11": {"bits": [8], "bias": 32, "text": "+{0} to Maximum Stamina"},
|
|
||||||
"16": {"bits": [9], "bias": 0, "text": "+{0}% Enhanced Defense"},
|
|
||||||
"17": {"bits": [9, 9], "bias": 0, "text": "+{0}% Enhanced Damage"},
|
|
||||||
"19": {"bits": [10], "bias": 0, "text": "+{0} to Attack rating"},
|
|
||||||
"20": {"bits": [6], "bias": 0, "text": "+{0}% Increased chance of blocking"},
|
|
||||||
"21": {"bits": [6], "bias": 0, "text": "+{0} to Minimum 1-handed damage"},
|
|
||||||
"22": {"bits": [7], "bias": 0, "text": "+{0} to Maximum 1-handed damage"},
|
|
||||||
"23": {"bits": [6], "bias": 0, "text": "+{0} to Minimum 2-handed damage"},
|
|
||||||
"24": {"bits": [7], "bias": 0, "text": "+{0} to Maximum 2-handed damage"},
|
|
||||||
"25": {"bits": [8], "bias": 0, "text": "Unknown (Invisible)"},
|
|
||||||
"26": {"bits": [8], "bias": 0, "text": "Unknown (Invisible)"},
|
|
||||||
"27": {"bits": [8], "bias": 0, "text": "Regenerate Mana {0}%"},
|
|
||||||
"28": {"bits": [8], "bias": 0, "text": "Heal Stamina {0}%"},
|
|
||||||
"31": {"bits": [11], "bias": 10, "text": "+{0} Defense"},
|
|
||||||
"32": {"bits": [9], "bias": 0, "text": "+{0} vs. Missile"},
|
|
||||||
"33": {"bits": [8], "bias": 10, "text": "+{0} vs. Melee"},
|
|
||||||
"34": {"bits": [6], "bias": 0, "text": "Damage Reduced by {0}"},
|
|
||||||
"35": {"bits": [6], "bias": 0, "text": "Magic Damage Reduced by {0}"},
|
|
||||||
"36": {"bits": [8], "bias": 0, "text": "Damage Reduced by {0}%"},
|
|
||||||
"37": {"bits": [8], "bias": 0, "text": "Magic Resist +{0}%"},
|
|
||||||
"38": {"bits": [8], "bias": 0, "text": "+{0}% to Maximum Magic Resist"},
|
|
||||||
"39": {"bits": [8], "bias": 50, "text": "Fire Resist +{0}%"},
|
|
||||||
"40": {"bits": [5], "bias": 0, "text": "+{0}% to Maximum Fire Resist"},
|
|
||||||
"41": {"bits": [8], "bias": 50, "text": "Lightning Resist +{0}%"},
|
|
||||||
"42": {"bits": [5], "bias": 0, "text": "+{0}% to Maximum Lightning Resist"},
|
|
||||||
"43": {"bits": [9], "bias": 200, "text": "Cold Resist +{0}%"},
|
|
||||||
"44": {"bits": [5], "bias": 0, "text": "+{0}% to Maximum Cold Resist"},
|
|
||||||
"45": {"bits": [8], "bias": 50, "text": "Poison Resist +{0}%"},
|
|
||||||
"46": {"bits": [5], "bias": 0, "text": "+{0}% to Maximum Poison Resist"},
|
|
||||||
"48": {"bits": [8, 9], "bias": 0, "text": "Adds {0}-{1} Fire Damage"},
|
|
||||||
"49": {"bits": [9], "bias": 0, "text": "+{0} to Maximum Fire Damage"},
|
|
||||||
"50": {"bits": [6, 10], "bias": 0, "text": "Adds {0}-{1} Lightning Damage"},
|
|
||||||
"52": {"bits": [8, 9], "bias": 0, "text": "Adds {0}-{1} Magic Damage"},
|
|
||||||
"54": {"bits": [8, 9, 8], "bias": 0, "text": "Adds {0}-{1} Cold Damage"},
|
|
||||||
"57": {"bits": [10, 10, 9], "bias": 0, "text": "Adds {0}-{1} Poison Damage over {2} Seconds"},
|
|
||||||
"60": {"bits": [7], "bias": 0, "text": "{0}% Life Stolen Per Hit"},
|
|
||||||
"62": {"bits": [7], "bias": 0, "text": "{0}% Mana Stolen Per Hit"},
|
|
||||||
"67": {"bits": [7], "bias": 30, "text": "Unknown (Invisible)"},
|
|
||||||
"68": {"bits": [7], "bias": 30, "text": "Unknown (Invisible)"},
|
|
||||||
"71": {"bits": [8], "bias": 100, "text": "Unknown (Invisible)"},
|
|
||||||
"72": {"bits": [9], "bias": 0, "text": "Unknown (Invisible)"},
|
|
||||||
"73": {"bits": [8], "bias": 0, "text": "+{0} Maximum Durability"},
|
|
||||||
"74": {"bits": [6], "bias": 30, "text": "Replenish Life +{0}"},
|
|
||||||
"75": {"bits": [7], "bias": 20, "text": "Increase Maximum Durability {0}%"},
|
|
||||||
"76": {"bits": [6], "bias": 10, "text": "Increase Maximum Life {0}%"},
|
|
||||||
"77": {"bits": [6], "bias": 10, "text": "Increase Maximum Mana {0}%"},
|
|
||||||
"78": {"bits": [7], "bias": 0, "text": "Attacker Takes Damage of {0}"},
|
|
||||||
"79": {"bits": [9], "bias": 100, "text": "{0}% Extra Gold from Monsters"},
|
|
||||||
"80": {"bits": [8], "bias": 100, "text": "{0}% Better Chance of Getting Magic Items"},
|
|
||||||
"81": {"bits": [7], "bias": 0, "text": "Knockback"},
|
|
||||||
"82": {"bits": [9], "bias": 20, "text": "Unknown (Invisible)"},
|
|
||||||
"83": {"bits": [3, 3], "bias": 0, "text": "+{1} to {0} Skill Levels"},
|
|
||||||
"84": {"bits": [3, 3], "bias": 0, "text": "+{1} to {0} Skill Levels"},
|
|
||||||
"85": {"bits": [9], "bias": 50, "text": "{0}% To Experience Gained"},
|
|
||||||
"86": {"bits": [7], "bias": 0, "text": "+{0} Life After Each Kill"},
|
|
||||||
"87": {"bits": [7], "bias": 0, "text": "Reduces Prices {0}%"},
|
|
||||||
"88": {"bits": [1], "bias": 0, "text": "Unknown (Invisible)"},
|
|
||||||
"89": {"bits": [4], "bias": 4, "text": "+{0} to Light Radius"},
|
|
||||||
"90": {"bits": [5], "bias": 0, "text": "Ambient light"},
|
|
||||||
"91": {"bits": [8], "bias": 100, "text": "Requirements {0}%"},
|
|
||||||
"92": {"bits": [7], "bias": 0, "text": "Level requirements +{0} (Invisible)"},
|
|
||||||
"93": {"bits": [7], "bias": 20, "text": "{0}% Increased Attack Speed"},
|
|
||||||
"94": {"bits": [7], "bias": 64, "text": "Unknown (Invisible)"},
|
|
||||||
"96": {"bits": [7], "bias": 20, "text": "{0}% Faster Run/Walk"},
|
|
||||||
"97": {"bits": [9, 6], "bias": 0, "text": "+{1} To {0}"},
|
|
||||||
"98": {"bits": [8, 1], "bias": 0, "text": "{1}+ to {0} (Visual effect only)"},
|
|
||||||
"99": {"bits": [7], "bias": 20, "text": "{0}% Faster Hit Recovery"},
|
|
||||||
"102": {"bits": [7], "bias": 20, "text": "{0}% Faster Block Rate"},
|
|
||||||
"105": {"bits": [7], "bias": 20, "text": "{0}% Faster Cast Rate"},
|
|
||||||
"107": {"bits": [9, 3], "bias": 0, "text": "+{1} To {0}"},
|
|
||||||
"108": {"bits": [1], "bias": 0, "text": "Rest In Peace"},
|
|
||||||
"109": {"bits": [9], "bias": 0, "text": "Unknown (Invisible)"},
|
|
||||||
"181": {"bits": [9, 5], "bias": 0, "text": "+{1} to spell {0} (char_class Only)"},
|
|
||||||
"182": {"bits": [9, 5], "bias": 0, "text": "+{1} to spell {0} (char_class Only)"},
|
|
||||||
"183": {"bits": [9, 5], "bias": 0, "text": "+{1} to spell {0} (char_class Only)"},
|
|
||||||
"184": {"bits": [9, 5], "bias": 0, "text": "+{1} to spell {0} (char_class Only)"},
|
|
||||||
"185": {"bits": [9, 5], "bias": 0, "text": "+{1} to spell {0} (char_class Only)"},
|
|
||||||
"186": {"bits": [9, 5], "bias": 0, "text": "+{1} to spell {0} (char_class Only)"},
|
|
||||||
"187": {"bits": [9, 5], "bias": 0, "text": "+{1} to spell {0} (char_class Only)"},
|
|
||||||
"110": {"bits": [8], "bias": 20, "text": "Poison Length Reduced by {0}%"},
|
|
||||||
"111": {"bits": [9], "bias": 20, "text": "Damage +{0}"},
|
|
||||||
"112": {"bits": [7], "bias": 0, "text": "Hit Causes Monsters to Flee {0}%"},
|
|
||||||
"113": {"bits": [7], "bias": 0, "text": "Hit Blinds Target +{0}"},
|
|
||||||
"114": {"bits": [6], "bias": 0, "text": "{0}% Damage Taken Goes to Mana"},
|
|
||||||
"115": {"bits": [1], "bias": 0, "text": "Ignore Target Defense"},
|
|
||||||
"116": {"bits": [7], "bias": 0, "text": "{0}% Target Defense"},
|
|
||||||
"117": {"bits": [7], "bias": 0, "text": "Prevent Monster Heal"},
|
|
||||||
"118": {"bits": [1], "bias": 0, "text": "Half Freeze Duration"},
|
|
||||||
"119": {"bits": [9], "bias": 20, "text": "{0}% Bonus to Attack Rating"},
|
|
||||||
"120": {"bits": [7], "bias": 128, "text": "{0} to Monster Defense Per Hit"},
|
|
||||||
"121": {"bits": [9], "bias": 20, "text": "+{0}% Damage to Demons"},
|
|
||||||
"122": {"bits": [9], "bias": 20, "text": "+{0}% Damage to Undead"},
|
|
||||||
"123": {"bits": [10], "bias": 128, "text": "+{0} to Attack Rating against Demons"},
|
|
||||||
"124": {"bits": [10], "bias": 128, "text": "+{0} to Attack Rating against Undead"},
|
|
||||||
"125": {"bits": [1], "bias": 0, "text": "Throwable"},
|
|
||||||
"126": {"bits": [3, 3], "bias": 0, "text": "+{0} to Fire Skills"},
|
|
||||||
"127": {"bits": [3], "bias": 0, "text": "+{0} to All Skill Levels"},
|
|
||||||
"128": {"bits": [5], "bias": 0, "text": "Attacker Takes Lightning Damage of {0}"},
|
|
||||||
"134": {"bits": [5], "bias": 0, "text": "Freezes Target +{0}"},
|
|
||||||
"135": {"bits": [7], "bias": 0, "text": "{0}% Chance of Open Wounds"},
|
|
||||||
"136": {"bits": [7], "bias": 0, "text": "{0}% Chance of Crushing Blow"},
|
|
||||||
"137": {"bits": [7], "bias": 0, "text": "+{0} Kick Damage"},
|
|
||||||
"138": {"bits": [7], "bias": 0, "text": "+{0} to Mana After Each Kill"},
|
|
||||||
"139": {"bits": [7], "bias": 0, "text": "+{0} Life after each Demon Kill"},
|
|
||||||
"140": {"bits": [7], "bias": 0, "text": "Extra Blood (Invisible)"},
|
|
||||||
"141": {"bits": [7], "bias": 0, "text": "{0}% Deadly Strike"},
|
|
||||||
"142": {"bits": [7], "bias": 0, "text": "Fire Absorb {0}%"},
|
|
||||||
"143": {"bits": [7], "bias": 0, "text": "+{0} Fire Absorb"},
|
|
||||||
"144": {"bits": [7], "bias": 0, "text": "Lightning Absorb {0}%"},
|
|
||||||
"145": {"bits": [7], "bias": 0, "text": "+{0} Lightning Absorb"},
|
|
||||||
"146": {"bits": [7], "bias": 0, "text": "Magic Absorb {0}%"},
|
|
||||||
"147": {"bits": [7], "bias": 0, "text": "+{0} Magic Absorb"},
|
|
||||||
"148": {"bits": [7], "bias": 0, "text": "Cold Absorb {0}%"},
|
|
||||||
"149": {"bits": [7], "bias": 0, "text": "+{0} Cold Absorb"},
|
|
||||||
"150": {"bits": [7], "bias": 0, "text": "Slows Target by {0}%"},
|
|
||||||
"151": {"bits": [9, 5], "bias": 0, "text": "Level +{1} {0} When Equipped"},
|
|
||||||
"152": {"bits": [1], "bias": 0, "text": "Indestructible"},
|
|
||||||
"153": {"bits": [1], "bias": 0, "text": "Cannot Be Frozen"},
|
|
||||||
"154": {"bits": [7], "bias": 20, "text": "{0}% Slower Stamina Drain"},
|
|
||||||
"155": {"bits": [10, 7], "bias": 0, "text": "{0}% Chance to Reanimate Target"},
|
|
||||||
"156": {"bits": [7], "bias": 0, "text": "Piercing Attack"},
|
|
||||||
"157": {"bits": [7], "bias": 0, "text": "Fires Magic Arrows"},
|
|
||||||
"158": {"bits": [7], "bias": 0, "text": "Fires Explosive Arrows or Bolts"},
|
|
||||||
"159": {"bits": [6], "bias": 0, "text": "+{0} to Minimum Throw Damage"},
|
|
||||||
"160": {"bits": [7], "bias": 0, "text": "+{0} to Maximum Throw Damage"},
|
|
||||||
"179": {"bits": [3], "bias": 0, "text": "+{0} to Druid Skill Levels"},
|
|
||||||
"180": {"bits": [3], "bias": 0, "text": "+{0} to Assassin Skill Levels"},
|
|
||||||
"188": {"bits": [3, 13, 3], "bias": 0, "text": "+{2} to {0} Skills ({1} only)"},
|
|
||||||
"189": {"bits": [10, 9], "bias": 0, "text": "+{0} to {1} Skills (char_class Only)"},
|
|
||||||
"190": {"bits": [10, 9], "bias": 0, "text": "+{0} to {1} Skills (char_class Only)"},
|
|
||||||
"191": {"bits": [10, 9], "bias": 0, "text": "+{0} to {1} Skills (char_class Only)"},
|
|
||||||
"192": {"bits": [10, 9], "bias": 0, "text": "+{0} to {1} Skills (char_class Only)"},
|
|
||||||
"193": {"bits": [10, 9], "bias": 0, "text": "+{0} to {1} Skills (char_class Only)"},
|
|
||||||
"194": {"bits": [4], "bias": 0, "text": "Adds {0} extra sockets to the item"},
|
|
||||||
"195": {"bits": [6, 10, 7], "bias": 0, "text": "{2}% Chance to Cast Level {0} {1} When you die"},
|
|
||||||
"196": {"bits": [6, 10, 7], "bias": 0, "text": "{2}% Chance to Cast Level {0} {1} When you die"},
|
|
||||||
"197": {"bits": [6, 10, 7], "bias": 0, "text": "{2}% Chance to Cast Level {0} {1} When you die"},
|
|
||||||
"198": {"bits": [6, 10, 7], "bias": 0, "text": "{2}% Chance to Cast Level {0} {1} On Striking"},
|
|
||||||
"199": {"bits": [6, 10, 7], "bias": 0, "text": "{2}% Chance to Cast Level {0} {1} On Striking"},
|
|
||||||
"200": {"bits": [6, 10, 7], "bias": 0, "text": "{2}% Chance to Cast Level {0} {1} On Striking"},
|
|
||||||
"201": {"bits": [6, 10, 7], "bias": 0, "text": "{2}% Chance to Cast Level {0} {1} When Struck"},
|
|
||||||
"202": {"bits": [6, 10, 7], "bias": 0, "text": "{2}% Chance to Cast Level {0} {1} When Struck"},
|
|
||||||
"203": {"bits": [6, 10, 7], "bias": 0, "text": "{2}% Chance to Cast Level {0} {1} When Struck"},
|
|
||||||
"204": {"bits": [6, 10, 8, 8], "bias": 0, "text": "Level {0} {1} ({2}/{3} Charges)"},
|
|
||||||
"205": {"bits": [6, 10, 8, 8], "bias": 0, "text": "Level {0} {1} ({2}/{3} Charges)"},
|
|
||||||
"206": {"bits": [6, 10, 8, 8], "bias": 0, "text": "Level {0} {1} ({2}/{3} Charges)"},
|
|
||||||
"207": {"bits": [6, 10, 8, 8], "bias": 0, "text": "Level {0} {1} ({2}/{3} Charges)"},
|
|
||||||
"208": {"bits": [6, 10, 8, 8], "bias": 0, "text": "Level {0} {1} ({2}/{3} Charges)"},
|
|
||||||
"209": {"bits": [6, 10, 8, 8], "bias": 0, "text": "Level {0} {1} ({2}/{3} Charges)"},
|
|
||||||
"210": {"bits": [6, 10, 8, 8], "bias": 0, "text": "Level {0} {1} ({2}/{3} Charges)"},
|
|
||||||
"211": {"bits": [6, 10, 8, 8], "bias": 0, "text": "Level {0} {1} ({2}/{3} Charges)"},
|
|
||||||
"212": {"bits": [6, 10, 8, 8], "bias": 0, "text": "Level {0} {1} ({2}/{3} Charges)"},
|
|
||||||
"213": {"bits": [6, 10, 8, 8], "bias": 0, "text": "Level {0} {1} ({2}/{3} Charges)"},
|
|
||||||
"214": {"bits": [6], "bias": 0, "text": "+{0} to Defense (Based on Character Level)"},
|
|
||||||
"215": {"bits": [6], "bias": 0, "text": "{0}% Enhanced Defense (Based on Character Level)"},
|
|
||||||
"216": {"bits": [6], "bias": 0, "text": "+{0} to Life (Based on Character Level)"},
|
|
||||||
"217": {"bits": [6], "bias": 0, "text": "+{0} to Mana (Based on Character Level)"},
|
|
||||||
"218": {"bits": [6], "bias": 0, "text": "+{0} to Maximum Damage (Based on Character Level)"},
|
|
||||||
"219": {"bits": [6], "bias": 0, "text": "{0}% Enhanced Maximum Damage (Based on Character Level)"},
|
|
||||||
"220": {"bits": [6], "bias": 0, "text": "+{0} to Strength (Based on Character Level)"},
|
|
||||||
"221": {"bits": [6], "bias": 0, "text": "+{0} to Dexterity (Based on Character Level)"},
|
|
||||||
"222": {"bits": [6], "bias": 0, "text": "+{0} to Energy (Based on Character Level)"},
|
|
||||||
"223": {"bits": [6], "bias": 0, "text": "+{0} to Vitality (Based on Character Level)"},
|
|
||||||
"224": {"bits": [6], "bias": 0, "text": "+{0} to Attack Rating (Based on Character Level)"},
|
|
||||||
"225": {"bits": [6], "bias": 0, "text": "{0}% Bonus to Attack Rating (Based on Character Level)"},
|
|
||||||
"226": {"bits": [6], "bias": 0, "text": "+{0} Cold Damage (Based on Character Level)"},
|
|
||||||
"227": {"bits": [6], "bias": 0, "text": "+{0} Fire Damage (Based on Character Level)"},
|
|
||||||
"228": {"bits": [6], "bias": 0, "text": "+{0} Lightning Damage (Based on Character Level)"},
|
|
||||||
"229": {"bits": [6], "bias": 0, "text": "+{0} Poison Damage (Based on Character Level)"},
|
|
||||||
"230": {"bits": [6], "bias": 0, "text": "Cold Resist +{0}% (Based on Character Level)"},
|
|
||||||
"231": {"bits": [6], "bias": 0, "text": "Fire Resist +{0}% (Based on Character Level)"},
|
|
||||||
"232": {"bits": [6], "bias": 0, "text": "Lightning Resist +{0}% (Based on Character Level)"},
|
|
||||||
"233": {"bits": [6], "bias": 0, "text": "Poison Resist +{0}% (Based on Character Level)"},
|
|
||||||
"234": {"bits": [6], "bias": 0, "text": "+{0} Cold Absorb (Based on Character Level)"},
|
|
||||||
"235": {"bits": [6], "bias": 0, "text": "+{0} Fire Absorb (Based on Character Level)"},
|
|
||||||
"236": {"bits": [6], "bias": 0, "text": "+{0} Lightning Absorb (Based on Character Level)"},
|
|
||||||
"237": {"bits": [6], "bias": 0, "text": "{0} Poison Absorb (Based on Character Level)"},
|
|
||||||
"238": {"bits": [5], "bias": 0, "text": "Attacker Takes Damage of {0} (Based on Character Level)"},
|
|
||||||
"239": {"bits": [6], "bias": 0, "text": "{0}% Extra Gold from Monsters (Based on Character Level)"},
|
|
||||||
"240": {"bits": [6], "bias": 0, "text": "{0}% Better Chance of Getting Magic Items (Based on Character Level)"},
|
|
||||||
"241": {"bits": [6], "bias": 0, "text": "Heal Stamina Plus {0}% (Based on Character Level)"},
|
|
||||||
"242": {"bits": [6], "bias": 0, "text": "+{0} Maxmium Stamina (Based on Character Level)"},
|
|
||||||
"243": {"bits": [6], "bias": 0, "text": "{0}% Damage to Demons (Based on Character Level)"},
|
|
||||||
"244": {"bits": [6], "bias": 0, "text": "{0}% Damage to Undead (Based on Character Level)"},
|
|
||||||
"245": {"bits": [6], "bias": 0, "text": "+{0} to Attack Rating against Demons (Based on Character Level)"},
|
|
||||||
"246": {"bits": [6], "bias": 0, "text": "+{0} to Attack Rating against Undead (Based on Character Level)"},
|
|
||||||
"247": {"bits": [6], "bias": 0, "text": "{0}% Chance of Crushing Blow (Based on Character Level)"},
|
|
||||||
"248": {"bits": [6], "bias": 0, "text": "{0}% Chance of Open Wounds (Based on Character Level)"},
|
|
||||||
"249": {"bits": [6], "bias": 0, "text": "+{0} Kick Damage (Based on Character Level)"},
|
|
||||||
"250": {"bits": [6], "bias": 0, "text": "{0}% to Deadly Strike (Based on Character Level)"},
|
|
||||||
"252": {"bits": [6], "bias": 0, "text": "Repairs 1 Durability in {0} Seconds"},
|
|
||||||
"253": {"bits": [6], "bias": 0, "text": "Replenishes Quantity"},
|
|
||||||
"254": {"bits": [8], "bias": 0, "text": "Increased Stack Size"},
|
|
||||||
"305": {"bits": [8], "bias": 50, "text": "{0} Pierce Cold"},
|
|
||||||
"306": {"bits": [8], "bias": 50, "text": "{0} Pierce Fire"},
|
|
||||||
"307": {"bits": [8], "bias": 50, "text": "{0} Pierce Lightning"},
|
|
||||||
"308": {"bits": [8], "bias": 50, "text": "{0} Pierce Poision"},
|
|
||||||
"324": {"bits": [6], "bias": 0, "text": "Unknown (Invisible)"},
|
|
||||||
"329": {"bits": [9], "bias": 50, "text": "{0}% To Fire Skill Damage"},
|
|
||||||
"330": {"bits": [9], "bias": 50, "text": "{0}% To Lightning Skill Damage"},
|
|
||||||
"331": {"bits": [9], "bias": 50, "text": "{0}% To Cold Skill Damage"},
|
|
||||||
"332": {"bits": [9], "bias": 50, "text": "{0}% To Poison Skill Damage"},
|
|
||||||
"333": {"bits": [8], "bias": 0, "text": "-{0}% To Enemy Fire Resistance"},
|
|
||||||
"334": {"bits": [8], "bias": 0, "text": "-{0}% To Enemy Lightning Resistance"},
|
|
||||||
"335": {"bits": [8], "bias": 0, "text": "-{0}% To Enemy Cold Resistance"},
|
|
||||||
"336": {"bits": [8], "bias": 0, "text": "-{0}% To Enemy Poison Resistance"},
|
|
||||||
"356": {"bits": [2], "bias": 0, "text": "Quest Item Difficulty +{0} (Invisible)"}
|
|
||||||
}
|
|
||||||
@@ -16,13 +16,14 @@
|
|||||||
# Mercator. If not, see <https://www.gnu.org/licenses/>.
|
# Mercator. If not, see <https://www.gnu.org/licenses/>.
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
from bitarray import bitarray
|
from bitarray import bitarray
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
|
|
||||||
_data_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "data")
|
_data_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "data")
|
||||||
_basetype_map = None
|
_basetype_map = None
|
||||||
_affix_map = None
|
_stats_map = None
|
||||||
|
|
||||||
|
|
||||||
class Quality(Enum):
|
class Quality(Enum):
|
||||||
@@ -50,22 +51,19 @@ class LowQualityType(Enum):
|
|||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Affix:
|
class Stat:
|
||||||
name_id: int
|
id: int | None = None # TODO: These 3 should probably not be optional
|
||||||
stat_id: int | None = None # TODO: These 3 should probably not be optional
|
values: list[int] | None = None
|
||||||
stat_values: list[int] | None = None
|
parameter: int | None = None
|
||||||
stat_text: str | None = None
|
text: str | None = None
|
||||||
|
|
||||||
def print(self, indent=5):
|
def print(self, indent=5):
|
||||||
# TODO: name lookup
|
subst_text = self.text
|
||||||
if self.stat_text:
|
for val in self.values:
|
||||||
subst_text = self.stat_text
|
subst_text = subst_text.replace("#", str(val), 1)
|
||||||
for i, val in enumerate(self.stat_values):
|
if self.parameter:
|
||||||
replace = "{" + str(i) + "}"
|
subst_text = re.sub("\[[^\]]*\]", str(self.parameter), subst_text, 1)
|
||||||
subst_text = subst_text.replace(replace, str(val))
|
print(" " * indent, subst_text)
|
||||||
else:
|
|
||||||
subst_text = "<No text>"
|
|
||||||
print(" " * indent, f"{hex(self.name_id)}: {subst_text}")
|
|
||||||
|
|
||||||
|
|
||||||
def txtbits(bits: bitarray) -> str:
|
def txtbits(bits: bitarray) -> str:
|
||||||
@@ -93,8 +91,8 @@ class Item:
|
|||||||
graphic: int | None = None
|
graphic: int | None = None
|
||||||
inherent: int | None = None
|
inherent: int | None = None
|
||||||
low_quality: LowQualityType | None = None
|
low_quality: LowQualityType | None = None
|
||||||
prefixes: list[Affix] | None = None
|
prefixes: list[int] | None = None
|
||||||
suffixes: list[Affix] | None = None
|
suffixes: list[int] | None = None
|
||||||
set_id: int | None = None
|
set_id: int | None = None
|
||||||
unique_id: int | None = None
|
unique_id: int | None = None
|
||||||
nameword1: int | None = None
|
nameword1: int | None = None
|
||||||
@@ -106,6 +104,7 @@ class Item:
|
|||||||
max_durability: int | None = None
|
max_durability: int | None = None
|
||||||
sockets: int | None = None
|
sockets: int | None = None
|
||||||
quantity: int | None = None
|
quantity: int | None = None
|
||||||
|
stats: list[Stat] | None = None
|
||||||
|
|
||||||
def print(self, indent=5, with_raw=False):
|
def print(self, indent=5, with_raw=False):
|
||||||
properties = []
|
properties = []
|
||||||
@@ -129,13 +128,9 @@ class Item:
|
|||||||
if self.quality:
|
if self.quality:
|
||||||
print(" " * indent, self.quality)
|
print(" " * indent, self.quality)
|
||||||
if self.prefixes:
|
if self.prefixes:
|
||||||
print(" " * indent, "Prefixes:")
|
print(" " * indent, "Prefixes:", self.prefixes)
|
||||||
for prefix in self.prefixes:
|
|
||||||
prefix.print(indent + 4)
|
|
||||||
if self.suffixes:
|
if self.suffixes:
|
||||||
print(" " * indent, "Suffixes:")
|
print(" " * indent, "Suffixes:", self.suffixes)
|
||||||
for suffix in self.suffixes:
|
|
||||||
suffix.print(indent + 4)
|
|
||||||
if self.set_id:
|
if self.set_id:
|
||||||
print(" " * indent, f"Set Id: {self.set_id}") # TODO: name lookup
|
print(" " * indent, f"Set Id: {self.set_id}") # TODO: name lookup
|
||||||
if self.unique_id:
|
if self.unique_id:
|
||||||
@@ -155,6 +150,10 @@ class Item:
|
|||||||
print(" " * indent, f"Num Sockets: {self.sockets}")
|
print(" " * indent, f"Num Sockets: {self.sockets}")
|
||||||
if self.quantity:
|
if self.quantity:
|
||||||
print(" " * indent, f"Quantity: {self.quantity}")
|
print(" " * indent, f"Quantity: {self.quantity}")
|
||||||
|
if self.stats:
|
||||||
|
print(" " * indent, "Stats:")
|
||||||
|
for stat in self.stats:
|
||||||
|
stat.print(indent + 4)
|
||||||
if with_raw:
|
if with_raw:
|
||||||
print(" " * indent, "Raw Item Data:")
|
print(" " * indent, "Raw Item Data:")
|
||||||
bits = bitarray(endian="little")
|
bits = bitarray(endian="little")
|
||||||
@@ -172,9 +171,9 @@ def lookup_basetype(code: str) -> dict:
|
|||||||
return _basetype_map[code]
|
return _basetype_map[code]
|
||||||
|
|
||||||
|
|
||||||
def lookup_affix(code: int) -> dict:
|
def lookup_stat(id: int) -> dict:
|
||||||
global _affix_map
|
global _stats_map
|
||||||
if _affix_map is None:
|
if _stats_map is None:
|
||||||
with open(os.path.join(_data_path, "affixes.json")) as f:
|
with open(os.path.join(_data_path, "stats.json")) as f:
|
||||||
_affix_map = json.load(f)
|
_stats_map = json.load(f)
|
||||||
return _affix_map[str(code)]
|
return _stats_map[str(id)]
|
||||||
|
|||||||
@@ -19,12 +19,12 @@ from bitarray import bitarray
|
|||||||
from bitarray.util import ba2int
|
from bitarray.util import ba2int
|
||||||
from d2warehouse.stash import Stash, StashTab
|
from d2warehouse.stash import Stash, StashTab
|
||||||
from d2warehouse.item import (
|
from d2warehouse.item import (
|
||||||
Affix,
|
|
||||||
Item,
|
Item,
|
||||||
LowQualityType,
|
LowQualityType,
|
||||||
Quality,
|
Quality,
|
||||||
lookup_affix,
|
Stat,
|
||||||
lookup_basetype,
|
lookup_basetype,
|
||||||
|
lookup_stat,
|
||||||
)
|
)
|
||||||
import d2warehouse.huffman as huffman
|
import d2warehouse.huffman as huffman
|
||||||
|
|
||||||
@@ -134,7 +134,6 @@ def parse_item(data: bytes) -> tuple[bytes, Item]:
|
|||||||
raise UnsupportedItemError("Ear items are not supported")
|
raise UnsupportedItemError("Ear items are not supported")
|
||||||
|
|
||||||
simple_byte_sz = int((sockets_end + 7) / 8)
|
simple_byte_sz = int((sockets_end + 7) / 8)
|
||||||
print("simple size", simple_byte_sz)
|
|
||||||
item = Item(
|
item = Item(
|
||||||
data[:simple_byte_sz],
|
data[:simple_byte_sz],
|
||||||
is_identified,
|
is_identified,
|
||||||
@@ -185,10 +184,9 @@ def parse_item(data: bytes) -> tuple[bytes, Item]:
|
|||||||
enchantments_end += itembase_end
|
enchantments_end += itembase_end
|
||||||
|
|
||||||
extended_byte_size = int((enchantments_end + 7) / 8)
|
extended_byte_size = int((enchantments_end + 7) / 8)
|
||||||
print("extended size", extended_byte_size)
|
|
||||||
|
|
||||||
item.raw_data = data[:]
|
item.raw_data = data[:extended_byte_size]
|
||||||
return b"", item # TODO: properly return remaining data
|
return data[extended_byte_size:], item
|
||||||
|
|
||||||
|
|
||||||
def parse_item_graphic(bits: bitarray) -> tuple[int | None, int]:
|
def parse_item_graphic(bits: bitarray) -> tuple[int | None, int]:
|
||||||
@@ -242,8 +240,8 @@ def parse_high_quality_data(bits: bitarray, item: Item) -> tuple[Item, int]:
|
|||||||
|
|
||||||
|
|
||||||
def parse_magic_data(bits: bitarray, item: Item) -> tuple[Item, int]:
|
def parse_magic_data(bits: bitarray, item: Item) -> tuple[Item, int]:
|
||||||
item.prefixes = [Affix(name_id=ba2int(bits[0:11]))]
|
item.prefixes = [ba2int(bits[0:11])]
|
||||||
item.suffixes = [Affix(name_id=ba2int(bits[11:22]))]
|
item.suffixes = [ba2int(bits[11:22])]
|
||||||
return item, 22
|
return item, 22
|
||||||
|
|
||||||
|
|
||||||
@@ -272,11 +270,11 @@ def parse_unique_data(bits: bitarray, item: Item) -> tuple[Item, int]:
|
|||||||
return item, 12
|
return item, 12
|
||||||
|
|
||||||
|
|
||||||
def parse_affix(bits: bitarray) -> tuple[Affix | None, int]:
|
def parse_affix(bits: bitarray) -> tuple[int | None, int]:
|
||||||
if not bits[0]:
|
if not bits[0]:
|
||||||
return None, 1
|
return None, 1
|
||||||
else:
|
else:
|
||||||
return Affix(name_id=ba2int(bits[1:12])), 12
|
return ba2int(bits[1:12]), 12
|
||||||
|
|
||||||
|
|
||||||
def parse_runeword(bits: bitarray) -> tuple[int, int]:
|
def parse_runeword(bits: bitarray) -> tuple[int, int]:
|
||||||
@@ -302,10 +300,7 @@ def parse_basetype_data(bits: bitarray, item: Item) -> tuple[Item, int]:
|
|||||||
if cls == "tome":
|
if cls == "tome":
|
||||||
ptr += 5 # unknown field
|
ptr += 5 # unknown field
|
||||||
|
|
||||||
# Unknown bit here, supposedly 96 bits of realm data?? follow if set
|
# Unknown bit here
|
||||||
if bits[ptr : ptr + 1]:
|
|
||||||
print("Unknown bit set, realm data follows?")
|
|
||||||
# ptr += 96 -- doesnt seem right
|
|
||||||
ptr += 1
|
ptr += 1
|
||||||
|
|
||||||
if cls == "armor":
|
if cls == "armor":
|
||||||
@@ -354,58 +349,61 @@ def parse_enchantments(bits: bitarray, item: Item) -> tuple[Item, int]:
|
|||||||
else:
|
else:
|
||||||
num_lists = 1
|
num_lists = 1
|
||||||
|
|
||||||
|
# TODO: One extra list for runewords?
|
||||||
|
|
||||||
|
if num_lists > 0:
|
||||||
|
item.stats = []
|
||||||
|
|
||||||
while num_lists > 0:
|
while num_lists > 0:
|
||||||
affixes, ptr = parse_enchantment_list(bits[ptr:])
|
stats, sz = parse_enchantment_list(bits[ptr:])
|
||||||
|
ptr += sz
|
||||||
num_lists -= 1
|
num_lists -= 1
|
||||||
|
item.stats.extend(stats)
|
||||||
for i, affix in enumerate(affixes):
|
|
||||||
# TODO: this works for magic, rare & crafted. But set & unique items do not have
|
|
||||||
# names specified in the save data, but do instead need to be read from data files
|
|
||||||
# to know if the mod is prefix or suffix. For now we add them all to prefixes.
|
|
||||||
# TODO: Also note, that sets have lists of mods they get from the set. Which should go
|
|
||||||
# seperately (assuming they are in the data files when not equipped...?)
|
|
||||||
if item.quality in [Quality.UNIQUE, Quality.SET]:
|
|
||||||
item.prefixes.append(Affix(name_id=0))
|
|
||||||
mod = item.prefixes[-1]
|
|
||||||
else:
|
|
||||||
# TODO: Here we assume that they are the same ordering as previously
|
|
||||||
mod = (
|
|
||||||
item.prefixes[i]
|
|
||||||
if i < len(item.prefixes)
|
|
||||||
else item.suffixes[i - len(item.prefixes)]
|
|
||||||
)
|
|
||||||
|
|
||||||
mod.stat_id = affix.stat_id
|
|
||||||
mod.stat_values = affix.stat_values
|
|
||||||
mod.stat_text = affix.stat_text
|
|
||||||
|
|
||||||
return item, ptr
|
return item, ptr
|
||||||
|
|
||||||
|
|
||||||
def parse_enchantment_list(bits: bitarray) -> tuple[list[Affix], int]:
|
def parse_enchantment_list(bits: bitarray) -> tuple[list[Stat], int]:
|
||||||
ptr = 0 # what is all this data?
|
ptr = 0
|
||||||
affixes = []
|
stats = []
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
id = ba2int(bits[ptr : ptr + 9])
|
id = ba2int(bits[ptr : ptr + 9])
|
||||||
ptr += 9
|
ptr += 9
|
||||||
if id == 0x1FF:
|
if id == 0x1FF:
|
||||||
break
|
break
|
||||||
print("id", id)
|
print("stat id", id)
|
||||||
|
|
||||||
affix = lookup_affix(id)
|
if id == 107:
|
||||||
|
print(id, 107, "remainind data:")
|
||||||
|
print(bits)
|
||||||
|
|
||||||
|
stat = lookup_stat(id)
|
||||||
|
|
||||||
values = []
|
values = []
|
||||||
for b in affix["bits"]:
|
param = None
|
||||||
print("bits", b)
|
if stat["save_param_bits"]:
|
||||||
|
param = ba2int(bits[ptr : ptr + stat["save_param_bits"]])
|
||||||
|
ptr += stat["save_param_bits"]
|
||||||
|
for b in stat["save_bits"]:
|
||||||
values.append(ba2int(bits[ptr : ptr + b]))
|
values.append(ba2int(bits[ptr : ptr + b]))
|
||||||
ptr += b
|
ptr += b
|
||||||
values = [v - affix["bias"] for v in values]
|
values = [v - stat["save_add"] for v in values]
|
||||||
text = affix["text"]
|
text = stat["text"]
|
||||||
|
|
||||||
affixes.append(Affix(name_id=0, stat_id=id, stat_values=values, stat_text=text))
|
stat = Stat(
|
||||||
|
id=id,
|
||||||
|
values=values,
|
||||||
|
parameter=param,
|
||||||
|
text=text,
|
||||||
|
)
|
||||||
|
|
||||||
return affixes, ptr
|
print("Stat:")
|
||||||
|
stat.print()
|
||||||
|
|
||||||
|
stats.append(stat)
|
||||||
|
|
||||||
|
return stats, ptr
|
||||||
|
|
||||||
|
|
||||||
def parse_items(data: bytes) -> list[Item]:
|
def parse_items(data: bytes) -> list[Item]:
|
||||||
|
|||||||
Reference in New Issue
Block a user