Formulator / qt /scripts /equipments.py
AngoHF's picture
04.29 commit
ff5593c
raw
history blame
11.4 kB
from collections import defaultdict
from typing import Dict, List, Union, Tuple
from general.gains.equipment import EQUIPMENT_GAINS
from qt.components.equipments import EquipmentsWidget
from qt.constant import POSITION_MAP, STONES_POSITIONS, EMBED_POSITIONS
from qt.constant import ATTR_TYPE_TRANSLATE, ATTR_TYPE_TRANSLATE_REVERSE
from qt.constant import STRENGTH_COF, EMBED_COF, MAX_STRENGTH_LEVEL, MAX_EMBED_LEVEL
class Enchant:
name: str
attr: Dict[str, int]
def __init__(self):
self.clear()
def clear(self):
self.name = ""
self.attr = {}
class Stone:
name: str
level: int
attr: Dict[str, int]
def __init__(self):
self.clear()
def clear(self):
self.name = ""
self.attr = {}
class Equipment:
name: str
base: Dict[str, int]
magic: Dict[str, int]
max_strength: int
embed: Dict[str, int]
gains: List[int]
special_enchant: Union[int | Tuple[int, int]]
special_enchant_gain: List[int | List[int]]
set_id: str
set_attr: Dict[int, Dict[str, int]]
set_gain: Dict[int, List[int]]
def __init__(self, label):
self.clear()
self.label = label
self.position = POSITION_MAP[label]
self.max_strength = MAX_STRENGTH_LEVEL
self.strength_level = MAX_STRENGTH_LEVEL
self.embed_levels = [MAX_EMBED_LEVEL for _ in range(EMBED_POSITIONS[self.position])]
self.enchant = Enchant()
if self.position in STONES_POSITIONS:
self.stone = Stone()
else:
self.stone = None
def clear(self):
self.name = ""
self.base = {}
self.magic = {}
self.embed = {}
self.gains = []
self.special_enchant_gain = []
self.set_id = ""
self.set_attr = {}
self.set_gain = {}
@property
def base_attr(self) -> Dict[str, int]:
return self.base
@property
def magic_attr(self) -> Dict[str, int]:
return self.magic
@property
def strength_attr(self) -> Dict[str, int]:
if self.strength_level:
return {k: int(STRENGTH_COF(self.strength_level) * v + 0.5) for k, v in self.magic.items()}
else:
return {}
@property
def embed_attr(self) -> Dict[str, int]:
return {
k: int(EMBED_COF(self.embed_levels[i]) * self.embed[k])
for i, k in enumerate(self.embed) if self.embed_levels[i]
}
@property
def base_attr_content(self):
return [[ATTR_TYPE_TRANSLATE[k], str(v)] for k, v in self.base_attr.items()]
@property
def magic_attr_content(self):
if strength_attr := self.strength_attr:
return [[ATTR_TYPE_TRANSLATE[k], f"{v}(+{strength_attr[k]})"] for k, v in self.magic_attr.items()]
else:
return [[ATTR_TYPE_TRANSLATE[k], f"{v}"] for k, v in self.magic_attr.items()]
@property
def embed_attr_content(self):
return [[ATTR_TYPE_TRANSLATE[k], str(v)] for k, v in self.embed_attr.items()]
class Equipments:
def __init__(self):
self.equipments = {label: Equipment(label) for label in POSITION_MAP}
def __getitem__(self, item) -> Equipment:
return self.equipments[item]
@property
def attrs(self):
final_attrs = defaultdict(int)
set_count = {}
set_effect = {}
for equipment in self.equipments.values():
if not equipment.name:
continue
for attr, value in equipment.base_attr.items():
final_attrs[attr] += value
for attr, value in equipment.magic_attr.items():
final_attrs[attr] += value
for attr, value in equipment.strength_attr.items():
final_attrs[attr] += value
for attr, value in equipment.embed_attr.items():
final_attrs[attr] += value
for attr, value in equipment.enchant.attr.items():
final_attrs[attr] += value
if equipment.stone:
for attr, value in equipment.stone.attr.items():
final_attrs[attr] += value
if equipment.set_id not in set_count:
set_count[equipment.set_id] = 0
set_effect[equipment.set_id] = equipment.set_attr
set_count[equipment.set_id] += 1
for set_id, set_attr in set_effect.items():
for count, attrs in set_attr.items():
if int(count) > set_count[set_id]:
break
for attr, value in attrs.items():
final_attrs[attr] += value
return final_attrs
@property
def gains(self):
final_gains = []
set_count = {}
set_effect = {}
for equipment in self.equipments.values():
if not equipment.name:
continue
final_gains += [gain for gain in equipment.gains + equipment.special_enchant_gain]
if equipment.set_id not in set_count:
set_count[equipment.set_id] = 0
set_effect[equipment.set_id] = equipment.set_gain
set_count[equipment.set_id] += 1
for set_id, set_gain in set_effect.items():
for count, gains in set_gain.items():
if int(count) > set_count[set_id]:
break
final_gains += gains
return [tuple(gain) if isinstance(gain, list) else gain for gain in final_gains]
def equipments_script(equipments_widget: EquipmentsWidget):
equipments = Equipments()
def equipment_update(label):
widget = equipments_widget[label]
equipment = equipments[label]
def inner(equipment_name):
if not equipment_name:
equipment.clear()
widget.detail_widget.hide()
return
if equipment.strength_level == equipment.max_strength:
max_strength = True
else:
max_strength = False
equipment.name = equipment_name
equipment_detail = widget.equipment_json[equipment_name]
for k, v in equipment_detail.items():
setattr(equipment, k, v)
if equipment.base:
widget.base_attr.set_content(equipment.base_attr_content)
widget.base_attr.show()
else:
widget.base_attr.hide()
if max_strength:
equipment.strength_level = equipment.max_strength
widget.strength_level.set_items([str(i) for i in range(equipment.max_strength + 1)])
widget.strength_level.combo_box.setCurrentIndex(equipment.strength_level)
if equipment.embed:
for i, (attr, value) in enumerate(equipment.embed.items()):
widget.embed_levels[i].set_label(f"镶嵌等级-{ATTR_TYPE_TRANSLATE[attr]}\t")
widget.embed_attr.set_content(equipment.embed_attr_content)
widget.embed_attr.show()
else:
widget.embed_attr.hide()
if isinstance(equipment.special_enchant, list):
equipment.special_enchant = tuple(equipment.special_enchant)
if equipment.special_enchant:
widget.special_enchant.set_text(EQUIPMENT_GAINS[equipment.special_enchant].gain_name)
widget.detail_widget.show()
return inner
def enchant_update(label):
widget = equipments_widget.equipments[label]
equipment = equipments[label]
def inner(enchant_name):
if enchant_name:
enchant_detail = widget.enchant_json[enchant_name]
equipment.enchant.name = enchant_name
for k, v in enchant_detail.items():
setattr(equipment.enchant, k, v)
else:
equipment.enchant.clear()
return inner
def special_enchant_update(label):
widget = equipments_widget.equipments[label]
equipment = equipments[label]
def inner(_):
if widget.special_enchant and widget.special_enchant.radio_button.isChecked():
equipment.special_enchant_gain = [equipment.special_enchant]
else:
equipment.special_enchant_gain = []
return inner
def strength_level_update(label):
widget = equipments_widget.equipments[label]
equipment = equipments[label]
def inner(index):
equipment.strength_level = index
if magic_attr_content := equipment.magic_attr_content:
widget.magic_attr.set_content(magic_attr_content)
widget.magic_attr.show()
else:
widget.magic_attr.hide()
return inner
def embed_level_update(i, label):
widget = equipments_widget.equipments[label]
equipment = equipments[label]
def inner(index):
equipment.embed_levels[i] = index
if embed_attr_content := equipment.embed_attr_content:
widget.embed_attr.set_content(embed_attr_content)
widget.embed_attr.show()
else:
widget.embed_attr.hide()
return inner
def stone_update(label):
widget = equipments_widget.equipments[label]
equipment = equipments[label]
def inner(_):
level = widget.stone_level.combo_box.currentText()
current = widget.stones_json
i = 0
while i < len(widget.stone_attrs):
attr = ATTR_TYPE_TRANSLATE_REVERSE.get(widget.stone_attrs[i].combo_box.currentText())
if attr in current:
current = current[attr]
i += 1
else:
break
if level in current:
for k, v in current[level].items():
setattr(equipment.stone, k, v)
else:
widget.stone_attrs[i].set_items([""] + [ATTR_TYPE_TRANSLATE[k] for k in current])
equipment.stone = Stone()
i += 1
while i < len(widget.stone_attrs):
widget.stone_attrs[i].set_items([""])
i += 1
return inner
for equipment_label, equipment_widget in equipments_widget.items():
equipment_widget.equipment.combo_box.currentTextChanged.connect(equipment_update(equipment_label))
if equipment_widget.special_enchant:
equipment_widget.special_enchant.radio_button.clicked.connect(special_enchant_update(equipment_label))
if equipment_widget.enchant:
equipment_widget.enchant.combo_box.currentTextChanged.connect(enchant_update(equipment_label))
equipment_widget.strength_level.combo_box.currentIndexChanged.connect(strength_level_update(equipment_label))
for n, embed_widget in enumerate(equipment_widget.embed_levels):
embed_widget.combo_box.currentIndexChanged.connect(embed_level_update(n, equipment_label))
if equipment_widget.stones_json:
equipment_widget.stone_level.combo_box.currentIndexChanged.connect(stone_update(equipment_label))
for stone_attr in equipment_widget.stone_attrs:
stone_attr.combo_box.currentIndexChanged.connect(stone_update(equipment_label))
return equipments