import os
import xml.etree.ElementTree as ET
# Путь к папкам с файлами
OLD_FILES_DIR = r"C:\путь к файлу с которого адаптируем"
NEW_FILES_DIR = r"C:\путь к файлу под который адаптируем"
OUTPUT_DIR = r"C:\путь куда сохраняем результат"
# Создаём выходную папку, если её нет
os.makedirs(OUTPUT_DIR, exist_ok=True)
def parse_drops_and_spoils(old_drops):
"""Разделяет дропы и спойлы из старого формата."""
drops = []
spoils = []
for category in old_drops.findall("category"):
category_type = category.attrib.get("type", "").upper()
category_chance = float(category.attrib.get("chance", 0))
for drop in category.findall("drop"):
item_id = drop.attrib.get("itemid", "")
min_amount = drop.attrib.get("min", "0")
max_amount = drop.attrib.get("max", "0")
drop_chance = float(drop.attrib.get("chance", 0))
# Общий шанс дропа = шанс категории * шанс предмета
total_chance = category_chance * drop_chance / 100
# Разделяем дропы и спойлы по типу категории
if category_type == "SPOIL":
spoils.append({
"id": item_id,
"min": min_amount,
"max": max_amount,
"chance": round(total_chance, 4)
})
else:
drops.append({
"id": item_id,
"min": min_amount,
"max": max_amount,
"chance": round(total_chance, 4)
})
return drops, spoils
def indent_tree(elem, level=0):
"""Добавляет отступы для читаемого форматирования XML."""
i = "\n" + "\t" * level
if len(elem):
if not elem.text or not elem.text.strip():
elem.text = i + "\t"
if not elem.tail or not elem.tail.strip():
elem.tail = i
for child in elem:
indent_tree(child, level + 1)
if not elem.tail or not elem.tail.strip():
elem.tail = i
else:
if level and (not elem.tail or not elem.tail.strip()):
elem.tail = i
def update_npc(new_npc, old_npc):
"""Обновляет данные NPC в новом формате, используя старый."""
# Обновляем exp и sp
acquire = new_npc.find("acquire")
if acquire is not None:
exp = old_npc.find("set[@name='exp']")
sp = old_npc.find("set[@name='sp']")
if exp is not None:
acquire.set("exp", exp.attrib["val"])
if sp is not None:
acquire.set("sp", sp.attrib["val"])
# Обновляем дропы
old_drops = old_npc.find("drops")
if old_drops is None:
return
drop_lists = new_npc.find("dropLists")
if drop_lists is not None:
new_npc.remove(drop_lists)
new_drop_lists = ET.Element("dropLists")
# Разделяем дропы и спойлы
drops, spoils = parse_drops_and_spoils(old_drops)
# Добавляем дропы, если они есть
if drops:
drop_element = ET.SubElement(new_drop_lists, "drop")
for drop in drops:
ET.SubElement(drop_element, "item", {
"id": drop["id"],
"min": drop["min"],
"max": drop["max"],
"chance": str(drop["chance"])
})
# Добавляем спойлы, если они есть
if spoils:
spoil_element = ET.SubElement(new_drop_lists, "spoil")
for spoil in spoils:
ET.SubElement(spoil_element, "item", {
"id": spoil["id"],
"min": spoil["min"],
"max": spoil["max"],
"chance": str(spoil["chance"])
})
new_npc.append(new_drop_lists)
def create_old_npc_index(old_files):
"""Создаёт индекс NPC из старых файлов для быстрого доступа по ID."""
old_npc_index = {}
for old_file in old_files:
try:
old_tree = ET.parse(old_file)
old_root = old_tree.getroot()
for old_npc in old_root.findall("npc"):
old_id = old_npc.attrib.get("id")
if old_id:
old_npc_index[old_id] = old_npc
except Exception as e:
print(f"Ошибка при обработке файла {old_file}: {e}")
return old_npc_index
def process_files(new_file, old_npc_index, output_file):
"""Обрабатывает новый файл, обновляя его на основе старого индекса."""
try:
new_tree = ET.parse(new_file)
new_root = new_tree.getroot()
# Сопоставляем NPC по ID и обновляем
for new_npc in new_root.findall("npc"):
new_id = new_npc.attrib.get("id")
if new_id and new_id in old_npc_index:
update_npc(new_npc, old_npc_index[new_id])
# Добавляем отступы и сохраняем файл
indent_tree(new_root)
new_tree.write(output_file, encoding="utf-8", xml_declaration=True)
print(f"Обработан файл: {output_file}")
except Exception as e:
print(f"Ошибка обработки файла {new_file}: {e}")
def main():
"""Основная функция."""
old_files = [os.path.join(OLD_FILES_DIR, f) for f in os.listdir(OLD_FILES_DIR) if f.endswith(".xml")]
new_files = [os.path.join(NEW_FILES_DIR, f) for f in os.listdir(NEW_FILES_DIR) if f.endswith(".xml")]
if not old_files:
print("Старые файлы не найдены.")
return
if not new_files:
print("Новые файлы не найдены.")
return
# Создаём индекс для старых NPC
old_npc_index = create_old_npc_index(old_files)
# Обрабатываем каждый новый файл
for new_file in new_files:
output_file = os.path.join(OUTPUT_DIR, os.path.basename(new_file))
process_files(new_file, old_npc_index, output_file)
if __name__ == "__main__":
main()
print("Обработка завершена.")