about summary refs log tree commit diff
path: root/dropcalc/mxl_types
diff options
context:
space:
mode:
Diffstat (limited to 'dropcalc/mxl_types')
-rw-r--r--dropcalc/mxl_types/__init__.py15
-rw-r--r--dropcalc/mxl_types/base.py34
-rw-r--r--dropcalc/mxl_types/dao.py13
-rw-r--r--dropcalc/mxl_types/item_ratio.py39
-rw-r--r--dropcalc/mxl_types/item_type.py32
-rw-r--r--dropcalc/mxl_types/set.py15
-rw-r--r--dropcalc/mxl_types/treasure_class.py46
-rw-r--r--dropcalc/mxl_types/unique.py18
8 files changed, 212 insertions, 0 deletions
diff --git a/dropcalc/mxl_types/__init__.py b/dropcalc/mxl_types/__init__.py
new file mode 100644
index 0000000..09b00bc
--- /dev/null
+++ b/dropcalc/mxl_types/__init__.py
@@ -0,0 +1,15 @@
+__all__ = ["ItemRatio", "ItemType", "BaseItem", "Weapon", "Armor", "Misc", "UniqueItem", "SetItem", "TreasureClass"]
+
+from .dao import BaseDAO
+
+from .item_ratio import ItemRatio
+from .item_type import ItemType
+from .base import BaseItem, Weapon, Armor, Misc
+from .unique import UniqueItem
+from .set import SetItem
+from .treasure_class import TreasureClass
+
+# TODO
+# MonStats grab Id, hcIdx, enabled, TreasureClass1(H), maybe remaining TC2/3/4(H)
+# SuperUniques Superunique, TC(H)
+# Levels MonLvl3 and nmon1-nmon20
diff --git a/dropcalc/mxl_types/base.py b/dropcalc/mxl_types/base.py
new file mode 100644
index 0000000..cd7e8be
--- /dev/null
+++ b/dropcalc/mxl_types/base.py
@@ -0,0 +1,34 @@
+from sqlalchemy import ForeignKey, String
+from sqlalchemy.orm import Mapped, mapped_column
+
+from .dao import BaseDAO
+
+
+class BaseItem(BaseDAO):
+	__tablename__ = "base"
+
+	code: Mapped[str] = mapped_column(String(4), primary_key=True)
+	name: Mapped[str]                                    # internal name only, game actually looks up `code` in strings
+	type = mapped_column(ForeignKey("item_type.Code"))   # can have two item_type... and all their parents
+	type2 = mapped_column(ForeignKey("item_type.Code"))  # should really figure out a better way to store them
+	rarity: Mapped[int]
+	level: Mapped[int]                                   # variously referred to as ilvl or qlvl
+	spawnable: Mapped[int]                               # items with spawnable=0 *can* be dropped directly from TCs, but shouldn't randomly drop
+	category: Mapped[str]
+
+	__mapper_args__ = {'polymorphic_on': 'category'}
+
+
+class Weapon(BaseItem):
+	filename = "Weapons.txt"
+	__mapper_args__ = {'polymorphic_identity': 'weap'}
+
+
+class Armor(BaseItem):
+	filename = "Armor.txt"
+	__mapper_args__ = {'polymorphic_identity': 'armo'}
+
+
+class Misc(BaseItem):
+	filename = "Misc.txt"
+	__mapper_args__ = {'polymorphic_identity': 'misc'}
diff --git a/dropcalc/mxl_types/dao.py b/dropcalc/mxl_types/dao.py
new file mode 100644
index 0000000..db459e7
--- /dev/null
+++ b/dropcalc/mxl_types/dao.py
@@ -0,0 +1,13 @@
+from sqlalchemy.orm import DeclarativeBase
+
+
+class BaseDAO(DeclarativeBase):
+	__csv_to_db__ = dict()
+
+	def is_valid(self):
+		return True
+
+	def __init__(self, iterable=(), **kwargs):
+		self.__dict__.update(iterable, **kwargs)
+		for this, that in self.__csv_to_db__.items():
+			self.__dict__[this] = self.__dict__[that]
diff --git a/dropcalc/mxl_types/item_ratio.py b/dropcalc/mxl_types/item_ratio.py
new file mode 100644
index 0000000..7a783c3
--- /dev/null
+++ b/dropcalc/mxl_types/item_ratio.py
@@ -0,0 +1,39 @@
+from sqlalchemy.orm import Mapped, mapped_column
+
+from .dao import BaseDAO
+
+
+class ItemRatio(BaseDAO):
+	filename = "ItemRatio_mp.txt"
+	__csv_to_db__ = {"Class_Specific": "Class Specific"}
+	__tablename__ = "item_ratio"
+
+	id: Mapped[int] = mapped_column(primary_key=True)
+
+	# D2Fileguide goes into more detail about how these are used
+	# the gist is 1 in (Quality - (mlvl-ilvl) / Divisor) * 128 of rolling each of these
+	# in the order unique, set, rare, magic, hiq, normal (and falling back on loq)
+	# further modified by MF after diminishing returns value (250 uni, 500 set, 600 rar) - which I believe is hardcoded
+	# and then the TC values
+	Unique: Mapped[int]
+	UniqueDivisor: Mapped[int]
+	UniqueMin: Mapped[int]
+	Rare: Mapped[int]
+	RareDivisor: Mapped[int]
+	RareMin: Mapped[int]
+	Set: Mapped[int]
+	SetDivisor: Mapped[int]
+	SetMin: Mapped[int]
+	Magic: Mapped[int]
+	MagicDivisor: Mapped[int]
+	MagicMin: Mapped[int]
+	HiQuality: Mapped[int]
+	HiQualityDivisor: Mapped[int]
+	Normal: Mapped[int]
+	NormalDivisor: Mapped[int]
+
+	Uber: Mapped[int]  # exceptional/elite as decided by normcode, ubercode, ultracode in Weapons.txt / Armor.txt
+	Class_Specific: Mapped[int]  # class specifics as decided by Class in Itemtypes.txt
+
+	def is_valid(self):
+		return self.Version == "1"
diff --git a/dropcalc/mxl_types/item_type.py b/dropcalc/mxl_types/item_type.py
new file mode 100644
index 0000000..8dd9b37
--- /dev/null
+++ b/dropcalc/mxl_types/item_type.py
@@ -0,0 +1,32 @@
+from typing import Optional
+
+from sqlalchemy import ForeignKey, String
+from sqlalchemy.orm import Mapped, mapped_column
+
+from .dao import BaseDAO
+
+
+class ItemType(BaseDAO):
+	filename = "ItemTypes.txt"
+	__tablename__ = "item_type"
+
+	Id: Mapped[int] = mapped_column(primary_key=True)
+	Code: Mapped[str] = mapped_column(String(4))  # referred to by other tables
+	ItemType: Mapped[Optional[str]]               # internal human readable name
+
+	Equiv1 = mapped_column(ForeignKey("item_type.Code"))
+	Equiv2 = mapped_column(ForeignKey("item_type.Code"))
+
+	# what does Rarity do here? fileguide description is unclear
+
+	def is_valid(self):
+		return is_int(self.Id) and self.Code not in (None, '')
+
+
+def is_int(obj):
+	try:
+		int(obj)
+	except ValueError:
+		return False
+	else:
+		return True
diff --git a/dropcalc/mxl_types/set.py b/dropcalc/mxl_types/set.py
new file mode 100644
index 0000000..498cdcf
--- /dev/null
+++ b/dropcalc/mxl_types/set.py
@@ -0,0 +1,15 @@
+from sqlalchemy import ForeignKey
+from sqlalchemy.orm import Mapped, mapped_column
+
+from . import BaseDAO
+
+
+class SetItem(BaseDAO):
+	filename = "SetItems.txt"
+	__tablename__ = "set_item"
+
+	id: Mapped[int] = mapped_column(primary_key=True)
+	index: Mapped[str]   # string reference, often also human-readable
+	item = mapped_column(ForeignKey("base.code"))  # note inconsistency with everything else...
+	rarity: Mapped[int]  # drop frequency, relative to other sets on this base
+	lvl: Mapped[int]     # minimum drop level
diff --git a/dropcalc/mxl_types/treasure_class.py b/dropcalc/mxl_types/treasure_class.py
new file mode 100644
index 0000000..d00da6f
--- /dev/null
+++ b/dropcalc/mxl_types/treasure_class.py
@@ -0,0 +1,46 @@
+from typing import Optional
+
+from sqlalchemy.orm import Mapped, mapped_column
+
+from . import BaseDAO
+
+
+class TreasureClass(BaseDAO):
+	filename = "TreasureClassEx.txt"
+	__csv_to_db__ = {"name": "Treasure Class"}
+	__tablename__ = "treasure_class"
+
+	name: Mapped[str] = mapped_column(primary_key=True)
+
+	group: Mapped[Optional[int]]
+	level: Mapped[Optional[int]]
+
+	Picks: Mapped[int]
+
+	Unique: Mapped[Optional[str]]
+	Set: Mapped[Optional[int]]
+	Rare: Mapped[Optional[int]]
+	Magic: Mapped[Optional[int]]
+
+	NoDrop: Mapped[Optional[int]]
+
+	Item1: Mapped[str]
+	Prob1: Mapped[int]
+	Item2: Mapped[Optional[str]]
+	Prob2: Mapped[Optional[int]]
+	Item3: Mapped[Optional[str]]
+	Prob3: Mapped[Optional[int]]
+	Item4: Mapped[Optional[str]]
+	Prob4: Mapped[Optional[int]]
+	Item5: Mapped[Optional[str]]
+	Prob5: Mapped[Optional[int]]
+	Item6: Mapped[Optional[str]]
+	Prob6: Mapped[Optional[int]]
+	Item7: Mapped[Optional[str]]
+	Prob7: Mapped[Optional[int]]
+	Item8: Mapped[Optional[str]]
+	Prob8: Mapped[Optional[int]]
+	Item9: Mapped[Optional[str]]
+	Prob9: Mapped[Optional[int]]
+	Item10: Mapped[Optional[str]]
+	Prob10: Mapped[Optional[int]]
diff --git a/dropcalc/mxl_types/unique.py b/dropcalc/mxl_types/unique.py
new file mode 100644
index 0000000..49c4e39
--- /dev/null
+++ b/dropcalc/mxl_types/unique.py
@@ -0,0 +1,18 @@
+from sqlalchemy import ForeignKey
+from sqlalchemy.orm import Mapped, mapped_column
+
+from . import BaseDAO
+
+
+class UniqueItem(BaseDAO):
+	filename = "UniqueItems.txt"
+	__tablename__ = "unique_item"
+
+	id: Mapped[int] = mapped_column(primary_key=True)
+	index: Mapped[str]   # string reference, often also human-readable
+	code = mapped_column(ForeignKey("base.code"))
+	rarity: Mapped[int]  # drop frequency, relative to other uniques on this base
+	lvl: Mapped[int]     # minimum drop level
+
+	def is_valid(self):
+		return self.enabled == "1"  # TODO: can we create fixed drop but not randomly available uniques by setting this to 0?