
About this mod
Deadlock Font ChangerDeadlock Font Changer — это графическая утилита, позволяющая легко заменять стандартный шрифт в игре Deadlock на любой пользовательский. Приложение имеет стильный неоновый интерфейс, автоматически находит игру и делает процесс смены шрифта максимально простым. ФункцииСтильный интерфейс: Современный дизайн в неоновом стиле со скругленными углами и эффектами свечения. Автоматический поиск: Утилита сама находит директорию установки Deadlock на вашем компьютере. Выбор шрифта: Позволяет выбирать любой файл шрифта в формате .ttf или .otf. Безопасная установка: Автоматически создает резервную копию (.backup) оригинального файла конфигурации. Встроенная справка: Вся необходимая информация доступна по клику на иконку "i" прямо в приложении. Установка и использованиеШаг 1: Важная подготовкаПеред первым запуском необходимо подготовить игру. Этот шаг выполняется только один раз! Скачайте архив с программой и распакуйте его. Найдите в папке с программой файл fonts.conf. Скопируйте этот файл и замените им оригинальный файл в папке с игрой по пути: .../steamapps/common/Deadlock/game/citadel/panorama/fonts/ Шаг 2: Использование программыЗапустите Deadlock Font Changer.exe. Если путь к игре не был найден автоматически, программа попросит указать его вручную. Нажмите "Выбрать .ttf/.otf файл" и выберите шрифт, который хотите установить. Нажмите "Применить шрифт". Готово! Запускайте игру и наслаждайтесь новым шрифтом. Устранение неполадокШрифт не применяется: Убедитесь, что вы выполнили "Шаг 1: Важная подготовка" и заменили fonts.conf в папке с игрой. Проблемы с правами доступа: Если появляется ошибка доступа, запустите Deadlock Font Changer.exe от имени администратора. Как вернуть стандартный шрифт: Перейдите в папку .../Deadlock/game/citadel/panorama/fonts/. Удалите измененный файл fonts.conf. Найдите файл fonts.conf.backup и переименуйте его обратно в fonts.conf. СообществоПрисоединяйтесь к нам, чтобы следить за обновлениями и другими модами! The source code: import sys import os import shutil import webbrowser import locale from pathlib import Path from PyQt6.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QLabel, QPushButton, QFileDialog, QProgressBar, QGraphicsDropShadowEffect, QSizePolicy, QSpacerItem, QDialog, QTextBrowser) from PyQt6.QtCore import Qt, QThread, pyqtSignal, QSize, QPoint, QRectF from PyQt6.QtGui import (QPainter, QColor, QBrush, QFont, QPainterPath, QIcon) # --- ФУНКЦИЯ ДЛЯ ПРАВИЛЬНЫХ ПУТЕЙ В EXE --- def resource_path(relative_path): """ Получает абсолютный путь к ресурсам, работает и для dev, и для PyInstaller """ try: # PyInstaller создает временную папку и хранит путь в _MEIPASS base_path = sys._MEIPASS except Exception: base_path = os.path.abspath(".") return os.path.join(base_path, relative_path) # --- СЛОВАРЬ ЛОКАЛИЗАЦИИ --- I18N = { 'ru': { 'app_title': "Deadlock Font Changer", 'info_title': "О программе", 'loading_title': "Deadlock Font Changer", 'loading_text': "Поиск Deadlock...", 'main_title': "DEADLOCK", 'main_subtitle': "Font Changer", 'status_found': "Deadlock найден: {path}", 'status_not_found': "Deadlock не найден. Укажите путь вручную.", 'status_path_set': "Путь к Deadlock задан: {path}", 'btn_select_path': "Указать путь к Deadlock", 'btn_select_font': "Выбрать .ttf/.otf файл", 'btn_apply': "Применить шрифт", 'font_not_selected': "Шрифт не выбран", 'font_selected': "Выбран: {font_name}", 'btn_ok': "ПОНЯТНО", 'dialog_select_folder': "Выберите папку с Deadlock", 'dialog_select_font': "Выберите шрифт", 'msg_error_title': "Ошибка", 'msg_success_title': "Успех", 'msg_wrong_folder': "Это не похоже на папку с Deadlock.\nПроверьте путь 'game/citadel/panorama/fonts'", 'msg_success_applied': "Шрифт успешно изменен!", 'msg_permission_error': "Ошибка доступа. \nЗапустите программу от имени администратора.", 'msg_unexpected_error': "Ошибка:\n{error}", 'readme_text': """ Обзор Deadlock Font Changer — это графическая утилита для изменения конфигурации шрифтов в игре Deadlock. ВАЖНЫЙ ШАГ: Перед использованием скопируйте файл fonts.conf из папки с программой и замените им оригинальный файл в игре: .../Deadlock/game/citadel/panorama/fonts/ Укажите путь к Deadlock. Выберите файл шрифта. Нажмите "Применить шрифт". Устранение неполадок Убедитесь, что вы выполнили "ВАЖНЫЙ ШАГ". Восстановление: Удалите fonts.conf и переименуйте fonts.conf.backup обратно. """ }, 'en': { 'app_title': "Deadlock Font Changer", 'info_title': "About", 'loading_title': "Deadlock Font Changer", 'loading_text': "Searching for Deadlock...", 'main_title': "DEADLOCK", 'main_subtitle': "Font Changer", 'status_found': "Deadlock found: {path}", 'status_not_found': "Deadlock not found. Specify path manually.", 'status_path_set': "Deadlock path set: {path}", 'btn_select_path': "Select Deadlock Path", 'btn_select_font': "Select .ttf/.otf file", 'btn_apply': "Apply Font", 'font_not_selected': "No font selected", 'font_selected': "Selected: {font_name}", 'btn_ok': "OK", 'dialog_select_folder': "Select Deadlock Folder", 'dialog_select_font': "Select Font", 'msg_error_title': "Error", 'msg_success_title': "Success", 'msg_wrong_folder': "Incorrect Deadlock folder.\nCheck 'game/citadel/panorama/fonts'", 'msg_success_applied': "Font changed successfully!", 'msg_permission_error': "Permission error. \nRun as administrator.", 'msg_unexpected_error': "Error:\n{error}", 'readme_text': """ Overview Deadlock Font Changer is a utility to change font configuration in Deadlock. IMPORTANT STEP: Before use, copy fonts.conf from the program folder and replace the original file in: .../Deadlock/game/citadel/panorama/fonts/ Specify Deadlock path. Select .ttf or .otf file. Click "Apply Font". Troubleshooting Make sure you replaced fonts.conf manually. Restore: Delete fonts.conf and rename fonts.conf.backup back. """ } } CURRENT_LANGUAGE = 'en' def tr(key, **kwargs): return I18N[CURRENT_LANGUAGE].get(key, key).format(**kwargs) # --- ШАБЛОН КОНФИГА --- FONTS_CONF_TEMPLATE = ''' ../../citadel/panorama/fonts WINDOWSFONTDIR ~/.fonts /usr/share/fonts /usr/local/share/fonts fonts .uifont FONTFILENAME .ttf .otf WINDOWSTEMPDIR_FONTCONFIG_CACHE ~/.fontconfig Stratum2 FONTNAME Arial FONTNAME Times New Roman FONTNAME Courier New FONTNAME Noto Sans FONTNAME false true 96 ''' # --- UI ЭЛЕМЕНТЫ --- class GlowEffect(QGraphicsDropShadowEffect): def __init__(self, color=QColor("#E040FB"), blur=35): super().__init__() self.setBlurRadius(blur); self.setColor(color); self.setXOffset(0); self.setYOffset(0) class MainBackgroundWidget(QWidget): def paintEvent(self, event): painter = QPainter(self); painter.setRenderHint(QPainter.RenderHint.Antialiasing) path = QPainterPath(); path.addRoundedRect(QRectF(self.rect()), 20, 20) painter.setClipPath(path); painter.fillRect(self.rect(), QColor("#1a1a1a")) class StyledButton(QPushButton): def __init__(self, text_key, parent=None): super().__init__(tr(text_key), parent); self.text_key = text_key self.setMinimumHeight(40); self.setFont(QFont("Segoe UI", 11, QFont.Weight.Bold)) self.setGraphicsEffect(GlowEffect(blur=25)); self.update_style() def update_style(self): self.setStyleSheet("QPushButton{background-color:rgba(224,64,251,0.7);color:white;border:1px solid rgba(255,255,255,0.2);border-radius:8px;padding:8px 16px;} QPushButton:hover{background-color:rgba(224,64,251,0.9);} QPushButton:pressed{background-color:rgba(200,50,220,1);} QPushButton:disabled{background-color:rgba(85,85,85,0.5);color:#888;}") def retranslate(self): self.setText(tr(self.text_key)) class InfoWin(QDialog): def __init__(self, parent=None): super().__init__(parent); self.setFixedSize(500, 550); self.setWindowFlags(Qt.WindowType.FramelessWindowHint | Qt.WindowType.Dialog) self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground); self.setWindowModality(Qt.WindowModality.ApplicationModal) bg = MainBackgroundWidget(); l = QVBoxLayout(self); l.setContentsMargins(0,0,0,0); l.addWidget(bg) c = QVBoxLayout(bg); c.setContentsMargins(20, 20, 20, 20); c.setSpacing(15) self.t = QLabel(); self.t.setFont(QFont("Segoe UI", 16, QFont.Weight.Bold)); self.t.setStyleSheet("color:white;"); self.t.setGraphicsEffect(GlowEffect(blur=20)) self.b = QTextBrowser(); self.b.setOpenExternalLinks(True); self.b.setStyleSheet("background:transparent;color:#DDDDDD;border:none;font-size:11pt;") self.ok = StyledButton('btn_ok'); self.ok.clicked.connect(self.accept) c.addWidget(self.t, alignment=Qt.AlignmentFlag.AlignCenter); c.addWidget(self.b); c.addWidget(self.ok, alignment=Qt.AlignmentFlag.AlignCenter) self.re(); self._p = None def re(self): self.t.setText(tr('info_title')); self.b.setHtml(tr('readme_text')); self.ok.retranslate() def mousePressEvent(self, e): if e.button() == Qt.MouseButton.LeftButton: self._p = e.globalPosition().toPoint() def mouseMoveEvent(self, e): if self._p: d = e.globalPosition().toPoint() - self._p; self.move(self.x() + d.x(), self.y() + d.y()); self._p = e.globalPosition().toPoint() class MsgBox(QDialog): def __init__(self, title_key, message, parent=None): super().__init__(parent); self.setFixedSize(450, 220); self.setWindowFlags(Qt.WindowType.FramelessWindowHint | Qt.WindowType.Dialog) self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground); self.setWindowModality(Qt.WindowModality.ApplicationModal) bg = MainBackgroundWidget(); l = QVBoxLayout(self); l.setContentsMargins(0,0,0,0); l.addWidget(bg) c = QVBoxLayout(bg); c.setSpacing(15); c.setAlignment(Qt.AlignmentFlag.AlignCenter) t = QLabel(tr(title_key)); t.setFont(QFont("Segoe UI", 14, QFont.Weight.Bold)) t.setStyleSheet("color:white;"); t.setGraphicsEffect(GlowEffect(blur=20)) t.setAlignment(Qt.AlignmentFlag.AlignCenter) ml = QLabel(message); ml.setFont(QFont("Segoe UI", 11)); ml.setWordWrap(True) ml.setAlignment(Qt.AlignmentFlag.AlignCenter); ml.setStyleSheet("color:#DDDDDD;") b = StyledButton('btn_ok'); b.setMinimumWidth(140); b.clicked.connect(self.accept) c.addWidget(t); c.addWidget(ml); c.addWidget(b); self._p = None def mousePressEvent(self, e): if e.button() == Qt.MouseButton.LeftButton: self._p = e.globalPosition().toPoint() def mouseMoveEvent(self, e): if self._p: d = e.globalPosition().toPoint() - self._p; self.move(self.x() + d.x(), self.y() + d.y()); self._p = e.globalPosition().toPoint() # --- ПОИСК И ЛОГИКА --- class SearchThread(QThread): fin = pyqtSignal(str) def run(self): paths = [os.path.join(os.environ.get("ProgramFiles(x86)", "C:/Program Files (x86)"), "Steam/steamapps/common"), os.path.join(os.environ.get("ProgramFiles", "C:/Program Files"), "Steam/steamapps/common")] for d in "CDEFGHIJKLMONPQRSTUVWXYZ": p = f"{d}:\\SteamLibrary\\steamapps\\common" if os.path.isdir(p): paths.append(p) found = "" for p in paths: target = os.path.join(p, "Deadlock") if os.path.isdir(target): found = target; break self.fin.emit(found) class MainWin(QMainWindow): def __init__(self): super().__init__(); self.gp = None; self.fp = None; self.setFixedSize(800, 600) self.setWindowFlags(Qt.WindowType.FramelessWindowHint); self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground) self.ui(); self.start_s(); self._p = None def lang_toggle(self): global CURRENT_LANGUAGE; CURRENT_LANGUAGE = 'ru' if CURRENT_LANGUAGE == 'en' else 'en' self.re(); self.info_d.re() def ui(self): self.central = MainBackgroundWidget(); self.setCentralWidget(self.central) root = QVBoxLayout(self.central); root.setContentsMargins(10, 10, 10, 20) # Top Bar top = QHBoxLayout(); self.info_d = InfoWin(self) self.bl
The people behind it
- dyson behind Author