Compare commits
1 Commits
v0.1.3
...
1c1110a6e7
Author | SHA1 | Date | |
---|---|---|---|
1c1110a6e7 |
@ -8,7 +8,7 @@ on:
|
||||
|
||||
env:
|
||||
# Common version, will be used for tagging the release
|
||||
VERSION: 0.1.3
|
||||
VERSION: 0.1.2
|
||||
PKGDEST: "/tmp/portprotonqt"
|
||||
PACKAGE: "portprotonqt"
|
||||
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||
|
11
CHANGELOG.md
@ -3,16 +3,13 @@
|
||||
Все заметные изменения в этом проекте фиксируются в этом файле.
|
||||
Формат основан на [Keep a Changelog](https://keepachangelog.com/) и придерживается принципов [Semantic Versioning](https://semver.org/).
|
||||
|
||||
## [0.1.3] - 2025-07-05
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
- Аргумент `--session` для запуска приложения в gamescope (Исключительно в целях тестирования)
|
||||
- Аргумент `--session` для запуска приложения в gamescope с GAMESCOPE_CMD
|
||||
- Начальная поддержка EGS (Без EOS, скачивания игр и запуска игр из сторонних магазинов)
|
||||
- Автодополнение bash для комманды portprotonqt
|
||||
- Поддержка геймпадов в диалоге выбора игры
|
||||
- Быстрый запуск и остановка игры через контекстное меню
|
||||
- Иконки в контекстом меню
|
||||
- Обложки для части автоинсталлов
|
||||
|
||||
### Changed
|
||||
- Удалены сборки для Fedora 40
|
||||
@ -20,8 +17,6 @@
|
||||
- Статус выделения и наведения на карточки теперь взаимоисключают друг друга
|
||||
- Все desktop файлы создаются с коментарием "Запустить игру {название} через PortProton"
|
||||
- Заполнители в переводах теперь стали более осмысленными
|
||||
- Изменена компоновка диалога добавления игры для лучшего отображения в Gamescope
|
||||
- Текст бейджей теперь обрезается через ... если не помещается
|
||||
|
||||
### Fixed
|
||||
- Дублирование обводки выделения карточек при быстром перемешении мыши
|
||||
@ -30,8 +25,6 @@
|
||||
- Ошибки темы в нативном пакете
|
||||
- Ошибки темы в Gamescope
|
||||
- Размер иконок для desktop файлов теперь 128x128
|
||||
- Пустая область при обновлении сетки игр
|
||||
- Запуск игры при открытом оверлее
|
||||
|
||||
### Contributors
|
||||
- @Dervart
|
||||
|
@ -34,8 +34,6 @@
|
||||
- [ ] Достигнуть паритета функциональности с PortProton
|
||||
- [X] Добавить возможность изменения названия, описания и обложки через файлы `.local/share/PortProtonQT/custom_data/exe_name/{desc,name,cover}`
|
||||
- [X] Добавить встроенное переопределение названия, описания и обложки, например, по пути `portprotonqt/custom_data` [Документация](documentation/metadata_override/)
|
||||
- [ ] Добавить переводы в переопределения
|
||||
- [ ] Придумать как переопределять launcher.exe
|
||||
- [X] Добавить в карточку игры сведения о поддержке геймпада
|
||||
- [X] Добавить в карточки данные с ProtonDB
|
||||
- [X] Добавить в карточки данные с AreWeAntiCheatYet
|
||||
|
@ -25,7 +25,7 @@ AppDir:
|
||||
id: ru.linux_gaming.PortProtonQt
|
||||
name: PortProtonQt
|
||||
icon: ru.linux_gaming.PortProtonQt
|
||||
version: 0.1.3
|
||||
version: 0.1.2
|
||||
exec: usr/bin/python3
|
||||
exec_args: "-m portprotonqt.app $@"
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
pkgname=portprotonqt
|
||||
pkgver=0.1.3
|
||||
pkgver=0.1.2
|
||||
pkgrel=1
|
||||
pkgdesc="Modern GUI for managing and launching games from PortProton, Steam, and Epic Games Store"
|
||||
arch=('any')
|
||||
|
@ -2,7 +2,6 @@
|
||||
%global pypi_version 0.1.1
|
||||
%global oname PortProtonQt
|
||||
%global build_timestamp %(date +"%Y%m%d")
|
||||
%global _python_no_extras_requires 1
|
||||
|
||||
%global rel_build 1.git.%{build_timestamp}%{?dist}
|
||||
|
||||
@ -48,8 +47,6 @@ Requires: xdg-utils
|
||||
%description -n python3-%{pypi_name}-git
|
||||
This application provides a sleek, intuitive graphical interface for managing and launching games from PortProton, Steam, and Epic Games Store. It consolidates your game libraries into a single, user-friendly hub for seamless navigation and organization. Its lightweight structure and cross-platform support deliver a cohesive gaming experience, eliminating the need for multiple launchers. Unique PortProton integration enhances Linux gaming, enabling effortless play of Windows-based titles with minimal setup.
|
||||
|
||||
%{?python_disable_dependency_generator}
|
||||
|
||||
%prep
|
||||
git clone https://git.linux-gaming.ru/Boria138/PortProtonQt.git
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
%global pypi_name portprotonqt
|
||||
%global pypi_version 0.1.3
|
||||
%global pypi_version 0.1.2
|
||||
%global oname PortProtonQt
|
||||
%global _python_no_extras_requires 1
|
||||
|
||||
Name: python-%{pypi_name}
|
||||
Version: %{pypi_version}
|
||||
@ -45,8 +44,6 @@ Requires: xdg-utils
|
||||
%description -n python3-%{pypi_name}
|
||||
This application provides a sleek, intuitive graphical interface for managing and launching games from PortProton, Steam, and Epic Games Store. It consolidates your game libraries into a single, user-friendly hub for seamless navigation and organization. Its lightweight structure and cross-platform support deliver a cohesive gaming experience, eliminating the need for multiple launchers. Unique PortProton integration enhances Linux gaming, enabling effortless play of Windows-based titles with minimal setup.
|
||||
|
||||
%{?python_disable_dependency_generator}
|
||||
|
||||
%prep
|
||||
git clone https://git.linux-gaming.ru/Boria138/PortProtonQt
|
||||
cd %{oname}
|
||||
|
@ -197,7 +197,7 @@
|
||||
},
|
||||
{
|
||||
"normalized_name": "rec room",
|
||||
"status": "Running"
|
||||
"status": "Broken"
|
||||
},
|
||||
{
|
||||
"normalized_name": "world war 3",
|
||||
@ -221,7 +221,7 @@
|
||||
},
|
||||
{
|
||||
"normalized_name": "zero hour",
|
||||
"status": "Running"
|
||||
"status": "Broken"
|
||||
},
|
||||
{
|
||||
"normalized_name": "ironsight",
|
||||
@ -309,7 +309,7 @@
|
||||
},
|
||||
{
|
||||
"normalized_name": "dirty bomb",
|
||||
"status": "Running"
|
||||
"status": "Broken"
|
||||
},
|
||||
{
|
||||
"normalized_name": "empyrion galactic survival",
|
||||
@ -989,7 +989,7 @@
|
||||
},
|
||||
{
|
||||
"normalized_name": "marauders",
|
||||
"status": "Running"
|
||||
"status": "Broken"
|
||||
},
|
||||
{
|
||||
"normalized_name": "predecessor",
|
||||
@ -1101,7 +1101,7 @@
|
||||
},
|
||||
{
|
||||
"normalized_name": "deceit 2",
|
||||
"status": "Running"
|
||||
"status": "Broken"
|
||||
},
|
||||
{
|
||||
"normalized_name": "block n load 2",
|
||||
@ -1781,7 +1781,7 @@
|
||||
},
|
||||
{
|
||||
"normalized_name": "splitgate 2",
|
||||
"status": "Running"
|
||||
"status": "Planned"
|
||||
},
|
||||
{
|
||||
"normalized_name": "xera survival",
|
||||
@ -1897,7 +1897,7 @@
|
||||
},
|
||||
{
|
||||
"normalized_name": "test drive unlimited solar crown",
|
||||
"status": "Running"
|
||||
"status": "Planned"
|
||||
},
|
||||
{
|
||||
"normalized_name": "resident evil resistance",
|
||||
@ -3461,7 +3461,7 @@
|
||||
},
|
||||
{
|
||||
"normalized_name": "crsed cuisine royale",
|
||||
"status": "Denied"
|
||||
"status": "Supported"
|
||||
},
|
||||
{
|
||||
"normalized_name": "project nebula",
|
||||
@ -4329,7 +4329,7 @@
|
||||
},
|
||||
{
|
||||
"normalized_name": "blindfire",
|
||||
"status": "Supported"
|
||||
"status": "Broken"
|
||||
},
|
||||
{
|
||||
"normalized_name": "h hour world's elite",
|
||||
@ -4414,17 +4414,5 @@
|
||||
{
|
||||
"normalized_name": "ragnarok origin roo",
|
||||
"status": "Running"
|
||||
},
|
||||
{
|
||||
"normalized_name": "fantasy life i the girl who steals time",
|
||||
"status": "Running"
|
||||
},
|
||||
{
|
||||
"normalized_name": "la tale evolved",
|
||||
"status": "Running"
|
||||
},
|
||||
{
|
||||
"normalized_name": "carx street",
|
||||
"status": "Broken"
|
||||
}
|
||||
]
|
@ -1,20 +1,4 @@
|
||||
[
|
||||
{
|
||||
"normalized_title": "settlement survival",
|
||||
"slug": "settlement-survival"
|
||||
},
|
||||
{
|
||||
"normalized_title": "the elder scrolls iv oblivion",
|
||||
"slug": "the-elder-scrolls-iv-oblivion-remastered"
|
||||
},
|
||||
{
|
||||
"normalized_title": "dead space 3",
|
||||
"slug": "dead-space-3"
|
||||
},
|
||||
{
|
||||
"normalized_title": "dead space 2",
|
||||
"slug": "dead-space-2"
|
||||
},
|
||||
{
|
||||
"normalized_title": "hades",
|
||||
"slug": "hades"
|
||||
@ -115,6 +99,10 @@
|
||||
"normalized_title": "hotshot racing",
|
||||
"slug": "hotshot-racing"
|
||||
},
|
||||
{
|
||||
"normalized_title": "s.t.a.l.k.e.r. anomaly g.a.m.m.a",
|
||||
"slug": "s-t-a-l-k-e-r-anomaly-g-a-m-m-a"
|
||||
},
|
||||
{
|
||||
"normalized_title": "golazo! 2",
|
||||
"slug": "golazo-2"
|
||||
@ -1810,45 +1798,5 @@
|
||||
{
|
||||
"normalized_title": "atomic heart",
|
||||
"slug": "atomic-heart"
|
||||
},
|
||||
{
|
||||
"normalized_title": "genshin impact",
|
||||
"slug": "genshin-impact"
|
||||
},
|
||||
{
|
||||
"normalized_title": "battle.net",
|
||||
"slug": "battle-net"
|
||||
},
|
||||
{
|
||||
"normalized_title": "valorant",
|
||||
"slug": "valorant"
|
||||
},
|
||||
{
|
||||
"normalized_title": "русы против ящеров",
|
||||
"slug": "rusy-protiv-yashherov"
|
||||
},
|
||||
{
|
||||
"normalized_title": "last floor",
|
||||
"slug": "last-floor"
|
||||
},
|
||||
{
|
||||
"normalized_title": "fpv kamikaze drone",
|
||||
"slug": "fpv-kamikaze-drone"
|
||||
},
|
||||
{
|
||||
"normalized_title": "wild terra 2 new lands",
|
||||
"slug": "wild-terra-2-new-lands"
|
||||
},
|
||||
{
|
||||
"normalized_title": "armored warfare",
|
||||
"slug": "armored-warfare"
|
||||
},
|
||||
{
|
||||
"normalized_title": "warhammer 40 000 dawn of war",
|
||||
"slug": "warhammer-40-000-dawn-of-war"
|
||||
},
|
||||
{
|
||||
"normalized_title": "warhammer 40 000 space marine",
|
||||
"slug": "warhammer-40-000-space-marine"
|
||||
}
|
||||
]
|
@ -16,5 +16,3 @@ Content-Transfer-Encoding:
|
||||
Generated-By:
|
||||
start.sh
|
||||
EGS
|
||||
Stop Game
|
||||
\t
|
||||
|
@ -20,9 +20,9 @@ Current translation status:
|
||||
|
||||
| Locale | Progress | Translated |
|
||||
| :----- | -------: | ---------: |
|
||||
| [de_DE](./de_DE/LC_MESSAGES/messages.po) | 0% | 0 of 192 |
|
||||
| [es_ES](./es_ES/LC_MESSAGES/messages.po) | 0% | 0 of 192 |
|
||||
| [ru_RU](./ru_RU/LC_MESSAGES/messages.po) | 100% | 192 of 192 |
|
||||
| [de_DE](./de_DE/LC_MESSAGES/messages.po) | 0% | 0 of 182 |
|
||||
| [es_ES](./es_ES/LC_MESSAGES/messages.po) | 0% | 0 of 182 |
|
||||
| [ru_RU](./ru_RU/LC_MESSAGES/messages.po) | 100% | 182 of 182 |
|
||||
|
||||
---
|
||||
|
||||
|
@ -20,9 +20,9 @@
|
||||
|
||||
| Локаль | Прогресс | Переведено |
|
||||
| :----- | -------: | ---------: |
|
||||
| [de_DE](./de_DE/LC_MESSAGES/messages.po) | 0% | 0 из 192 |
|
||||
| [es_ES](./es_ES/LC_MESSAGES/messages.po) | 0% | 0 из 192 |
|
||||
| [ru_RU](./ru_RU/LC_MESSAGES/messages.po) | 100% | 192 из 192 |
|
||||
| [de_DE](./de_DE/LC_MESSAGES/messages.po) | 0% | 0 из 182 |
|
||||
| [es_ES](./es_ES/LC_MESSAGES/messages.po) | 0% | 0 из 182 |
|
||||
| [ru_RU](./ru_RU/LC_MESSAGES/messages.po) | 100% | 182 из 182 |
|
||||
|
||||
---
|
||||
|
||||
|
@ -14,7 +14,7 @@ logger = get_logger(__name__)
|
||||
|
||||
__app_id__ = "ru.linux_gaming.PortProtonQt"
|
||||
__app_name__ = "PortProtonQt"
|
||||
__app_version__ = "0.1.3"
|
||||
__app_version__ = "0.1.2"
|
||||
|
||||
def main():
|
||||
app = QApplication(sys.argv)
|
||||
|
@ -6,17 +6,14 @@ import subprocess
|
||||
import threading
|
||||
import logging
|
||||
import orjson
|
||||
import psutil
|
||||
import signal
|
||||
from PySide6.QtWidgets import QMessageBox, QDialog, QMenu, QLineEdit, QApplication
|
||||
from PySide6.QtWidgets import QMessageBox, QDialog, QMenu, QFileDialog
|
||||
from PySide6.QtCore import QUrl, QPoint, QObject, Signal, Qt
|
||||
from PySide6.QtGui import QDesktopServices, QIcon, QKeySequence
|
||||
from PySide6.QtGui import QDesktopServices
|
||||
from portprotonqt.localization import _
|
||||
from portprotonqt.config_utils import parse_desktop_entry, read_favorites, save_favorites
|
||||
from portprotonqt.steam_api import is_game_in_steam, add_to_steam, remove_from_steam
|
||||
from portprotonqt.egs_api import add_egs_to_steam, get_egs_executable, remove_egs_from_steam
|
||||
from portprotonqt.dialogs import AddGameDialog, FileExplorer, generate_thumbnail
|
||||
from portprotonqt.theme_manager import ThemeManager
|
||||
from portprotonqt.dialogs import AddGameDialog, generate_thumbnail
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -43,7 +40,6 @@ class ContextMenuManager:
|
||||
self.parent = parent
|
||||
self.portproton_location = portproton_location
|
||||
self.theme = theme
|
||||
self.theme_manager = ThemeManager()
|
||||
self.load_games = load_games_callback
|
||||
self.update_game_grid = update_game_grid_callback
|
||||
self.legendary_path = os.path.join(
|
||||
@ -122,37 +118,6 @@ class ContextMenuManager:
|
||||
logger.error("Failed to read installed.json: %s", e)
|
||||
return False
|
||||
|
||||
def _is_game_running(self, game_card) -> bool:
|
||||
"""
|
||||
Check if the game associated with the game_card is currently running.
|
||||
|
||||
Args:
|
||||
game_card: The GameCard instance containing game data.
|
||||
|
||||
Returns:
|
||||
bool: True if the game is running, False otherwise.
|
||||
"""
|
||||
if game_card.game_source == "epic":
|
||||
exe_path = get_egs_executable(game_card.appid, self.legendary_config_path)
|
||||
if not exe_path or not os.path.exists(exe_path):
|
||||
return False
|
||||
current_exe = os.path.basename(exe_path)
|
||||
elif game_card.game_source == "steam":
|
||||
return False
|
||||
else:
|
||||
exec_line = self._get_exec_line(game_card.name, game_card.exec_line)
|
||||
if not exec_line:
|
||||
return False
|
||||
exe_path = self._parse_exe_path(exec_line, game_card.name)
|
||||
if not exe_path:
|
||||
return False
|
||||
current_exe = os.path.basename(exe_path)
|
||||
|
||||
# Check if the current_exe matches the target_exe in MainWindow
|
||||
if hasattr(self.parent, 'target_exe') and self.parent.target_exe == current_exe:
|
||||
return True
|
||||
return False
|
||||
|
||||
def show_context_menu(self, game_card, pos: QPoint):
|
||||
"""
|
||||
Show the context menu for a game card at the specified position.
|
||||
@ -161,58 +126,40 @@ class ContextMenuManager:
|
||||
game_card: The GameCard instance requesting the context menu.
|
||||
pos: The position (in widget coordinates) where the menu should appear.
|
||||
"""
|
||||
|
||||
def get_safe_icon(icon_name: str) -> QIcon:
|
||||
icon = self.theme_manager.get_icon(icon_name)
|
||||
if isinstance(icon, QIcon):
|
||||
return icon
|
||||
elif isinstance(icon, str) and os.path.exists(icon):
|
||||
return QIcon(icon)
|
||||
return QIcon()
|
||||
|
||||
menu = QMenu(self.parent)
|
||||
menu.setStyleSheet(self.theme.CONTEXT_MENU_STYLE)
|
||||
|
||||
# Check if the game is running
|
||||
is_running = self._is_game_running(game_card)
|
||||
action_text = _("Stop Game") if is_running else _("Launch Game")
|
||||
action_icon = "stop" if is_running else "play"
|
||||
launch_action = menu.addAction(get_safe_icon(action_icon), action_text)
|
||||
launch_action.triggered.connect(
|
||||
lambda: self._launch_game(game_card)
|
||||
)
|
||||
|
||||
favorites = read_favorites()
|
||||
is_favorite = game_card.name in favorites
|
||||
icon_name = "star_full" if is_favorite else "star"
|
||||
text = _("Remove from Favorites") if is_favorite else _("Add to Favorites")
|
||||
favorite_action = menu.addAction(get_safe_icon(icon_name), text)
|
||||
favorite_action = menu.addAction(
|
||||
_("Remove from Favorites") if is_favorite else _("Add to Favorites")
|
||||
)
|
||||
favorite_action.triggered.connect(lambda: self.toggle_favorite(game_card, not is_favorite))
|
||||
|
||||
if game_card.game_source == "epic":
|
||||
import_action = menu.addAction(get_safe_icon("epic_games"), _("Import to Legendary"))
|
||||
import_action = menu.addAction(_("Import to Legendary"))
|
||||
import_action.triggered.connect(
|
||||
lambda: self.import_to_legendary(game_card.name, game_card.appid)
|
||||
)
|
||||
if self._is_egs_game_installed(game_card.appid):
|
||||
is_in_steam = is_game_in_steam(game_card.name)
|
||||
icon_name = "delete" if is_in_steam else "steam"
|
||||
text = _("Remove from Steam") if is_in_steam else _("Add to Steam")
|
||||
steam_action = menu.addAction(get_safe_icon(icon_name), text)
|
||||
steam_action = menu.addAction(
|
||||
_("Remove from Steam") if is_in_steam else _("Add to Steam")
|
||||
)
|
||||
steam_action.triggered.connect(
|
||||
lambda: self.remove_from_steam(game_card.name, game_card.exec_line, game_card.game_source)
|
||||
if is_in_steam
|
||||
else self.add_egs_to_steam(game_card.name, game_card.appid)
|
||||
)
|
||||
open_folder_action = menu.addAction(get_safe_icon("search"), _("Open Game Folder"))
|
||||
open_folder_action = menu.addAction(_("Open Game Folder"))
|
||||
open_folder_action.triggered.connect(
|
||||
lambda: self.open_egs_game_folder(game_card.appid)
|
||||
)
|
||||
desktop_dir = subprocess.check_output(['xdg-user-dir', 'DESKTOP']).decode('utf-8').strip()
|
||||
desktop_path = os.path.join(desktop_dir, f"{game_card.name}.desktop")
|
||||
icon_name = "delete" if os.path.exists(desktop_path) else "desktop"
|
||||
text = _("Remove from Desktop") if os.path.exists(desktop_path) else _("Add to Desktop")
|
||||
desktop_action = menu.addAction(get_safe_icon(icon_name), text)
|
||||
desktop_action = menu.addAction(
|
||||
_("Remove from Desktop") if os.path.exists(desktop_path) else _("Add to Desktop")
|
||||
)
|
||||
desktop_action.triggered.connect(
|
||||
lambda: self.remove_egs_from_desktop(game_card.name)
|
||||
if os.path.exists(desktop_path)
|
||||
@ -221,7 +168,6 @@ class ContextMenuManager:
|
||||
applications_dir = os.path.join(os.path.expanduser("~"), ".local", "share", "applications")
|
||||
menu_path = os.path.join(applications_dir, f"{game_card.name}.desktop")
|
||||
menu_action = menu.addAction(
|
||||
get_safe_icon("delete" if os.path.exists(menu_path) else "menu"),
|
||||
_("Remove from Menu") if os.path.exists(menu_path) else _("Add to Menu")
|
||||
)
|
||||
menu_action.triggered.connect(
|
||||
@ -233,113 +179,46 @@ class ContextMenuManager:
|
||||
if game_card.game_source not in ("steam", "epic"):
|
||||
desktop_dir = subprocess.check_output(['xdg-user-dir', 'DESKTOP']).decode('utf-8').strip()
|
||||
desktop_path = os.path.join(desktop_dir, f"{game_card.name}.desktop")
|
||||
icon_name = "delete" if os.path.exists(desktop_path) else "desktop"
|
||||
text = _("Remove from Desktop") if os.path.exists(desktop_path) else _("Add to Desktop")
|
||||
desktop_action = menu.addAction(get_safe_icon(icon_name), text)
|
||||
desktop_action = menu.addAction(
|
||||
_("Remove from Desktop") if os.path.exists(desktop_path) else _("Add to Desktop")
|
||||
)
|
||||
desktop_action.triggered.connect(
|
||||
lambda: self.remove_from_desktop(game_card.name)
|
||||
if os.path.exists(desktop_path)
|
||||
else self.add_to_desktop(game_card.name, game_card.exec_line)
|
||||
)
|
||||
edit_action = menu.addAction(get_safe_icon("edit"), _("Edit Shortcut"))
|
||||
edit_action = menu.addAction(_("Edit Shortcut"))
|
||||
edit_action.triggered.connect(
|
||||
lambda: self.edit_game_shortcut(game_card.name, game_card.exec_line, game_card.cover_path)
|
||||
)
|
||||
delete_action = menu.addAction(get_safe_icon("delete"), _("Delete from PortProton"))
|
||||
delete_action = menu.addAction(_("Delete from PortProton"))
|
||||
delete_action.triggered.connect(lambda: self.delete_game(game_card.name, game_card.exec_line))
|
||||
open_folder_action = menu.addAction(get_safe_icon("search"), _("Open Game Folder"))
|
||||
open_folder_action = menu.addAction(_("Open Game Folder"))
|
||||
open_folder_action.triggered.connect(
|
||||
lambda: self.open_game_folder(game_card.name, game_card.exec_line)
|
||||
)
|
||||
applications_dir = os.path.join(os.path.expanduser("~"), ".local", "share", "applications")
|
||||
menu_path = os.path.join(applications_dir, f"{game_card.name}.desktop")
|
||||
icon_name = "delete" if os.path.exists(menu_path) else "menu"
|
||||
text = _("Remove from Menu") if os.path.exists(menu_path) else _("Add to Menu")
|
||||
menu_action = menu.addAction(get_safe_icon(icon_name), text)
|
||||
menu_action = menu.addAction(
|
||||
_("Remove from Menu") if os.path.exists(menu_path) else _("Add to Menu")
|
||||
)
|
||||
menu_action.triggered.connect(
|
||||
lambda: self.remove_from_menu(game_card.name)
|
||||
if os.path.exists(menu_path)
|
||||
else self.add_to_menu(game_card.name, game_card.exec_line)
|
||||
)
|
||||
is_in_steam = is_game_in_steam(game_card.name)
|
||||
icon_name = "delete" if is_in_steam else "steam"
|
||||
text = _("Remove from Steam") if is_in_steam else _("Add to Steam")
|
||||
steam_action = menu.addAction(get_safe_icon(icon_name), text)
|
||||
steam_action = menu.addAction(
|
||||
_("Remove from Steam") if is_in_steam else _("Add to Steam")
|
||||
)
|
||||
steam_action.triggered.connect(
|
||||
lambda: (
|
||||
self.remove_from_steam(game_card.name, game_card.exec_line, game_card.game_source)
|
||||
if is_in_steam
|
||||
else self.add_to_steam(game_card.name, game_card.exec_line, game_card.cover_path)
|
||||
)
|
||||
lambda: self.remove_from_steam(game_card.name, game_card.exec_line, game_card.game_source)
|
||||
if is_in_steam
|
||||
else self.add_to_steam(game_card.name, game_card.exec_line, game_card.cover_path)
|
||||
)
|
||||
|
||||
menu.exec(game_card.mapToGlobal(pos))
|
||||
|
||||
def _launch_game(self, game_card):
|
||||
"""
|
||||
Launch or stop a game based on its current state.
|
||||
|
||||
Args:
|
||||
game_card: The GameCard instance containing game data.
|
||||
"""
|
||||
if not self._check_portproton():
|
||||
return
|
||||
|
||||
# Check if the game is running
|
||||
if self._is_game_running(game_card):
|
||||
# Stop the game
|
||||
if hasattr(self.parent, 'game_processes') and self.parent.game_processes:
|
||||
for proc in self.parent.game_processes:
|
||||
try:
|
||||
parent = psutil.Process(proc.pid)
|
||||
children = parent.children(recursive=True)
|
||||
for child in children:
|
||||
try:
|
||||
child.terminate()
|
||||
except psutil.NoSuchProcess:
|
||||
pass
|
||||
psutil.wait_procs(children, timeout=5)
|
||||
for child in children:
|
||||
if child.is_running():
|
||||
child.kill()
|
||||
os.killpg(os.getpgid(proc.pid), signal.SIGTERM)
|
||||
except psutil.NoSuchProcess:
|
||||
pass
|
||||
self.parent.game_processes = []
|
||||
self.parent.resetPlayButton()
|
||||
if hasattr(self.parent, 'checkProcessTimer') and self.parent.checkProcessTimer is not None:
|
||||
self.parent.checkProcessTimer.stop()
|
||||
self.parent.checkProcessTimer.deleteLater()
|
||||
self.parent.checkProcessTimer = None
|
||||
self._show_status_message(_("Stopped '{game_name}'").format(game_name=game_card.name))
|
||||
return
|
||||
|
||||
# Launch the game
|
||||
if game_card.game_source == "epic":
|
||||
if not os.path.exists(self.legendary_path):
|
||||
self.signals.show_warning_dialog.emit(
|
||||
_("Error"),
|
||||
_("Legendary executable not found at {path}").format(path=self.legendary_path)
|
||||
)
|
||||
return
|
||||
# Construct EGS launch command
|
||||
wrapper = "flatpak run ru.linux_gaming.PortProton"
|
||||
start_sh_path = os.path.join(self.portproton_location, "data", "scripts", "start.sh")
|
||||
if self.portproton_location and ".var" not in self.portproton_location:
|
||||
wrapper = start_sh_path
|
||||
if not os.path.exists(start_sh_path):
|
||||
self.signals.show_warning_dialog.emit(
|
||||
_("Error"),
|
||||
_("start.sh not found at {path}").format(path=start_sh_path)
|
||||
)
|
||||
return
|
||||
exec_line = f'"{self.legendary_path}" launch {game_card.appid} --no-wine --wrapper "env START_FROM_STEAM=1 {wrapper}"'
|
||||
else:
|
||||
exec_line = self._get_exec_line(game_card.name, game_card.exec_line)
|
||||
if not exec_line:
|
||||
return
|
||||
self.parent.toggleGame(exec_line)
|
||||
|
||||
def add_egs_to_steam(self, game_name: str, app_name: str):
|
||||
"""
|
||||
Adds an EGS game to Steam using the egs_api.
|
||||
@ -403,56 +282,35 @@ class ContextMenuManager:
|
||||
"""
|
||||
if not self._check_portproton():
|
||||
return
|
||||
folder_path = QFileDialog.getExistingDirectory(
|
||||
self.parent, _("Select Game Installation Folder"), os.path.expanduser("~")
|
||||
)
|
||||
if not folder_path:
|
||||
self._show_status_message(_("No folder selected"))
|
||||
return
|
||||
if not os.path.exists(self.legendary_path):
|
||||
self.signals.show_warning_dialog.emit(
|
||||
_("Error"),
|
||||
_("Legendary executable not found at {path}").format(path=self.legendary_path)
|
||||
)
|
||||
return
|
||||
|
||||
# Используем FileExplorer с directory_only=True
|
||||
file_explorer = FileExplorer(
|
||||
parent=self.parent,
|
||||
theme=self.theme,
|
||||
initial_path=os.path.expanduser("~"),
|
||||
directory_only=True
|
||||
)
|
||||
|
||||
def on_folder_selected(folder_path):
|
||||
if not folder_path:
|
||||
self._show_status_message(_("No folder selected"))
|
||||
return
|
||||
def run_import():
|
||||
cmd = [self.legendary_path, "import", app_name, folder_path]
|
||||
try:
|
||||
subprocess.run(cmd, capture_output=True, text=True, check=True)
|
||||
self.signals.show_info_dialog.emit(
|
||||
_("Success"),
|
||||
_("Imported '{game_name}' to Legendary").format(game_name=game_name)
|
||||
def run_import():
|
||||
cmd = [self.legendary_path, "import", app_name, folder_path]
|
||||
try:
|
||||
subprocess.run(cmd, capture_output=True, text=True, check=True)
|
||||
self.signals.show_info_dialog.emit(
|
||||
_("Success"),
|
||||
_("Imported '{game_name}' to Legendary").format(game_name=game_name)
|
||||
)
|
||||
except subprocess.CalledProcessError as e:
|
||||
self.signals.show_warning_dialog.emit(
|
||||
_("Error"),
|
||||
_("Failed to import '{game_name}' to Legendary: {error}").format(
|
||||
game_name=game_name, error=e.stderr
|
||||
)
|
||||
except subprocess.CalledProcessError as e:
|
||||
self.signals.show_warning_dialog.emit(
|
||||
_("Error"),
|
||||
_("Failed to import '{game_name}' to Legendary: {error}").format(
|
||||
game_name=game_name, error=e.stderr
|
||||
)
|
||||
)
|
||||
self._show_status_message(_("Importing '{game_name}' to Legendary...").format(game_name=game_name))
|
||||
threading.Thread(target=run_import, daemon=True).start()
|
||||
|
||||
# Подключаем сигнал выбора файла/папки
|
||||
file_explorer.file_signal.file_selected.connect(on_folder_selected)
|
||||
|
||||
# Центрируем FileExplorer относительно родительского виджета
|
||||
parent_widget = self.parent
|
||||
if parent_widget:
|
||||
parent_geometry = parent_widget.geometry()
|
||||
center_point = parent_geometry.center()
|
||||
file_explorer_geometry = file_explorer.geometry()
|
||||
file_explorer_geometry.moveCenter(center_point)
|
||||
file_explorer.setGeometry(file_explorer_geometry)
|
||||
|
||||
file_explorer.show()
|
||||
)
|
||||
self._show_status_message(_("Importing '{game_name}' to Legendary...").format(game_name=game_name))
|
||||
threading.Thread(target=run_import, daemon=True).start()
|
||||
|
||||
def toggle_favorite(self, game_card, add: bool):
|
||||
"""
|
||||
@ -1082,55 +940,3 @@ Icon={icon_path}
|
||||
_("Error"),
|
||||
_("Failed to open folder: {error}").format(error=str(e))
|
||||
)
|
||||
|
||||
class CustomLineEdit(QLineEdit):
|
||||
|
||||
def __init__(self, *args, theme=None, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.theme = theme
|
||||
self.theme_manager = ThemeManager()
|
||||
|
||||
def contextMenuEvent(self, event):
|
||||
def get_safe_icon(icon_name: str) -> QIcon:
|
||||
icon = self.theme_manager.get_icon(icon_name)
|
||||
if isinstance(icon, QIcon):
|
||||
return icon
|
||||
elif isinstance(icon, str) and os.path.exists(icon):
|
||||
return QIcon(icon)
|
||||
return QIcon()
|
||||
|
||||
def add_action(text: str, shortcut: QKeySequence.StandardKey, icon_name: str, slot, enabled=True):
|
||||
icon = get_safe_icon(icon_name)
|
||||
shortcut_str = QKeySequence(shortcut).toString(QKeySequence.SequenceFormat.NativeText)
|
||||
action_text = f"{text}\t{shortcut_str}"
|
||||
action = menu.addAction(icon, action_text)
|
||||
action.triggered.connect(slot)
|
||||
action.setEnabled(enabled)
|
||||
|
||||
menu = QMenu(self)
|
||||
|
||||
if self.theme and hasattr(self.theme, "CONTEXT_MENU_STYLE"):
|
||||
menu.setStyleSheet(self.theme.CONTEXT_MENU_STYLE)
|
||||
|
||||
add_action(_("Undo"), QKeySequence.StandardKey.Undo, "undo", self.undo, self.isUndoAvailable())
|
||||
add_action(_("Redo"), QKeySequence.StandardKey.Redo, "redo", self.redo, self.isRedoAvailable())
|
||||
|
||||
menu.addSeparator()
|
||||
|
||||
add_action(_("Cut"), QKeySequence.StandardKey.Cut, "cut", self.cut, self.hasSelectedText())
|
||||
add_action(_("Copy"), QKeySequence.StandardKey.Copy, "copy", self.copy, self.hasSelectedText())
|
||||
add_action(_("Paste"), QKeySequence.StandardKey.Paste, "paste", self.paste,
|
||||
QApplication.clipboard().mimeData().hasText())
|
||||
add_action(_("Delete"), QKeySequence.StandardKey.Delete, "delete", self._delete_selected_text,
|
||||
self.hasSelectedText())
|
||||
|
||||
menu.addSeparator()
|
||||
|
||||
add_action(_("Select All"), QKeySequence.StandardKey.SelectAll, "select_all", self.selectAll, bool(self.text()))
|
||||
|
||||
menu.exec(event.globalPos())
|
||||
|
||||
def _delete_selected_text(self):
|
||||
cursor_pos = self.cursorPosition()
|
||||
self.backspace()
|
||||
self.setCursorPosition(cursor_pos)
|
||||
|
Before Width: | Height: | Size: 643 KiB |
@ -1,3 +0,0 @@
|
||||
name=Albion Online
|
||||
description_ru=Многопользовательская песочница в жанре MMORPG, где игроки могут исследовать открытый мир, заниматься ремеслом, добычей ресурсов и сражаться с другими игроками. Игра предлагает уникальную систему классов, позволяющую игрокам изменять свои роли в зависимости от выбранного снаряжения.
|
||||
description_en=A multiplayer sandbox MMORPG where players can explore an open world, engage in crafting, gather resources, and battle against other players. The game features a unique class system that allows players to change their roles based on the gear they equip.
|
Before Width: | Height: | Size: 178 KiB |
@ -1,3 +0,0 @@
|
||||
name=Ankama Launcher
|
||||
description_ru=Лаунчер для игр Ankama.
|
||||
description_en=Launcher for Ankama studio games.
|
Before Width: | Height: | Size: 508 KiB |
@ -1,3 +0,0 @@
|
||||
name=Arizona Games Launcher
|
||||
description_ru=Лаунчер для игры Arizona Role Play.
|
||||
description_en=Launcher for the Arizona Role Play game.
|
Before Width: | Height: | Size: 217 KiB |
@ -1,3 +0,0 @@
|
||||
name=Battle.net Launcher
|
||||
description_ru=Лаунчер для игр Activision и Blizzard.
|
||||
description_en=Launcher for Activision and Blizzard studio games.
|
Before Width: | Height: | Size: 702 KiB |
@ -1,3 +0,0 @@
|
||||
name=Black Desert Online (RU)
|
||||
description_ru=Многопользовательская ролевая игра с открытым миром, известная своей потрясающей графикой и глубокой системой кастомизации персонажей. Игроки могут исследовать обширные земли, выполнять задания, участвовать в PvP-сражениях и заниматься различными ремеслами.
|
||||
description_en=A massively multiplayer online role-playing game set in an open world, renowned for its stunning graphics and deep character customization system. Players can explore vast lands, complete quests, engage in PvP battles, and participate in various crafting activities.
|
Before Width: | Height: | Size: 827 KiB |
@ -1,3 +0,0 @@
|
||||
name=Chicken Invaders Universe
|
||||
description_ru=Захватывающая аркадная игра, в которой игроки сражаются с агрессивными курицами из космоса, защищая свою планету. Игра предлагает множество уровней, кооперативный режим и возможность улучшения космического корабля.
|
||||
description_en=An exciting arcade game where players battle aggressive space chickens to defend their planet. The game features multiple levels, a cooperative mode, and the ability to upgrade their spaceship.
|
Before Width: | Height: | Size: 429 KiB |
@ -1,3 +0,0 @@
|
||||
name=CONTRACT WARS
|
||||
description_ru=Многопользовательский шутер от первого лица, где игроки участвуют в противостоянии между двумя командами на разнообразных картах. Игра предлагает широкий выбор оружия и возможностей для настройки персонажей, что делает каждый матч уникальным.
|
||||
description_en=A multiplayer first-person shooter where players engage in battles between two teams on various maps. The game offers a wide selection of weapons and character customization options, making each match unique.
|
Before Width: | Height: | Size: 1.1 MiB |
@ -1,3 +0,0 @@
|
||||
name=Age of Empires Online
|
||||
description_ru=Многопользовательская стратегия в реальном времени, где игроки строят свои цивилизации, собирают ресурсы и сражаются с противниками. Игра предлагает уникальную экономическую систему и возможность развивать свои города с помощью различных миссий и задач.
|
||||
description_en=A multiplayer real-time strategy game where players build their civilizations, gather resources, and battle against opponents. The game features a unique economic system and the ability to develop cities through various missions and quests.
|
Before Width: | Height: | Size: 254 KiB |
@ -1,3 +0,0 @@
|
||||
name=Cemu
|
||||
description_ru=Эмулятор Wii U, который позволяет пользователям запускать и играть в игры, выпущенные на этой консоли, с высокой производительностью и улучшенной графикой.
|
||||
description_en=A Wii U emulator that allows users to launch and play games released on this console with high performance and enhanced graphics.
|
Before Width: | Height: | Size: 946 KiB |
@ -1,3 +0,0 @@
|
||||
name=Secret World Legends (ENG)
|
||||
description_ru=MMORPG с уникальной историей и сеттингом, основанная на мифах, легендах и тайных обществах, позволяющая игрокам исследовать современный мир, полный сверхъестественных существ и загадок. Игра предлагает свободу в выборе навыков и построении персонажей, а также захватывающие квесты и глубокий сюжет.
|
||||
description_en=An MMORPG with a unique story and setting based on myths, legends, and secret societies, allowing players to explore a modern world filled with supernatural beings and mysteries. The game offers freedom in skill selection and character building, along with engaging quests and a rich narrative.
|
Before Width: | Height: | Size: 511 KiB |
@ -1,3 +0,0 @@
|
||||
name=Broken Ranks (ENG)
|
||||
description_ru=MMORPG игра, предлагающая глубокий сон и уникальную боевую систему, которая ориентирует внимание на стратегию и деятельность персоны. Игроки исследуют мрачный мир, полный интриг и опасностей, развивая своих героев и принимая ключевые решения, влияющие на ход истории.
|
||||
description_en=An MMORPG game offering deep sleep and a unique combat system that focuses on the strategy and activities of the person. Players explore a dark world full of intrigue and danger, developing their characters and making key decisions that affect the course of history.
|
Before Width: | Height: | Size: 44 KiB |
@ -1,3 +0,0 @@
|
||||
name=Dolphin 5.0
|
||||
description_ru=Мощный эмулятор для игровых консолей Nintendo GameCube и Wii, который позволяет запускать игры на ПК с улучшенной графикой и производительностью. Он поддерживает широкий спектр функций, включая HD-разрешение, множество настройек управления и возможность использования модификаций.
|
||||
description_en=A powerful emulator for Nintendo GameCube and Wii consoles that allows users to play games on their PCs with enhanced graphics and performance. It supports a wide range of features, including HD resolution, numerous control configurations, and the ability to use modifications.
|
Before Width: | Height: | Size: 936 KiB |
@ -1,3 +0,0 @@
|
||||
name=Doomsday
|
||||
description_ru=Стратегическая игра в реальном времени, где игроки управляют отрядом выживших в постапокалиптическом мире, стремясь восстановить цивилизацию и защититься от различных угроз. Игра предлагает элементы строительства базы, тактические сражения и глубокую проработку сюжета.
|
||||
description_en=A real-time strategy game where players manage a group of survivors in a post-apocalyptic world, aiming to rebuild civilization and defend against various threats. The game features base-building elements, tactical combat, and a deep narrative experience.
|
Before Width: | Height: | Size: 674 KiB |
@ -1,3 +0,0 @@
|
||||
name=Eldevin (ENG)
|
||||
description_ru=MMORPG с красочной графикой, где игроки исследуют обширный фэнтезийный мир, выполняют квесты и сражаются с врагами, чтобы развивать свои персонажи. Игра предлагает разнообразные классы и навыки, а также системы крафта и группового взаимодействия.
|
||||
description_en=An MMORPG with vibrant graphics where players explore a vast fantasy world, complete quests, and battle enemies to develop their characters. The game features diverse classes and skills, as well as crafting and group interaction systems.
|
Before Width: | Height: | Size: 351 KiB |
@ -1,3 +0,0 @@
|
||||
name=Epic Games Launcher
|
||||
description_ru=Лаунчер для библиотеки игр Epic Games.
|
||||
description_en=Launcher for the Epic Games game library.
|
Before Width: | Height: | Size: 963 KiB |
@ -1,3 +0,0 @@
|
||||
name=STALCRAFT
|
||||
description_ru=Многопользовательская игра с открытым миром, вдохновленная вселенной S.T.A.L.K.E.R., где игроки исследуют заброшенные зоны, сражаются с мутантами и другими сталкерами, а также выполняют различные квесты. Игра сочетает элементы выживания, RPG и шутера от первого лица, предлагая уникальный опыт в постапокалиптическом мире.
|
||||
description_en=A multiplayer open-world game inspired by the S.T.A.L.K.E.R. universe, where players explore abandoned zones, battle mutants and other stalkers, and complete various quests. The game combines elements of survival, RPG, and first-person shooter, offering a unique experience in a post-apocalyptic world.
|
Before Width: | Height: | Size: 757 KiB |
@ -1,3 +0,0 @@
|
||||
name=ExoTanks
|
||||
description_ru=Многопользовательская боевая игра, в которой игроки управляют экзоскелетами и сражаются в различных аренах, используя мощное вооружение и стратегический подход. Игра предлагает как командные, так и одиночные режимы, а также возможность кастомизации своего экзоскелета для уникального стиля игры.
|
||||
description_en=A multiplayer battle game where players control exoskeletons and fight in various arenas using powerful weapons and strategic gameplay. The game offers both team and solo modes, along with the ability to customize their exoskeleton for a unique playing style.
|
Before Width: | Height: | Size: 954 KiB |
@ -1,3 +0,0 @@
|
||||
name=Farlight 84
|
||||
description_ru=Многопользовательская игра в жанре королевская битва, которая проходит в красочном и футуристическом мире, где игроки сражаются друг с другом с использованием уникальных навыков и оружия. Игра предлагает захватывающий геймплей с элементами строительства, а также возможность использовать различные транспортные средства для перемещения по карте.
|
||||
description_en=A multiplayer battle royale game set in a colorful and futuristic world where players fight against each other using unique skills and weapons. The game features exciting gameplay with building elements, as well as the ability to utilize various vehicles to navigate the map.
|
Before Width: | Height: | Size: 1.0 MiB |
@ -1,3 +0,0 @@
|
||||
name=Fractured Online (ENG)
|
||||
description_ru=Fractured Online — это первая массовая многопользовательская ролевая онлайн-игра с открытым миром, сочетающая динамичные сражения с полностью интерактивным окружением. Она одинаково понравится любителям соревновательного и кооперативного игрового процесса. С самого первого дня погрузитесь в бой. Побеждайте врагов благодаря собственным навыкам и смекалке, а не снаряжению или уровню. Собирайте ресурсы, создавайте предметы, торгуйте и отправляйтесь в легендарные путешествия в одиночку или создайте поселение со своей гильдией и превратите его в следующую империю.
|
||||
description_en=Fractured Online is the first open-world sandbox MMORPG mixing action combat with fully interactable environments, appealing equally to lovers of competitive and cooperative gameplay. Jump right into the fray from day one. Defeat your enemies through your own skill and cleverness, not equipment or level. Gather resources, craft, trade and venture into legendary travels as a solitary hero, or start a settlement with your guild and grow it into the next empire.
|
Before Width: | Height: | Size: 552 KiB |
@ -1,3 +0,0 @@
|
||||
name=Goose Goose Duck
|
||||
description_ru=Многопользовательская игра в жанре социальной дедукции, где игроки выступают в роли уток или гусей, пытаясь выполнить задания и выявить среди них "уток" — предателей. Игра сочетает в себе элементы стратегии и общения, требуя от игроков координации и способности распознавать обман.
|
||||
description_en=A multiplayer social deduction game where players take on the roles of ducks or geese, trying to complete tasks and identify the "ducks" — the impostors among them. The game combines elements of strategy and communication, requiring players to coordinate and recognize deception.
|
Before Width: | Height: | Size: 680 KiB |
@ -1,3 +0,0 @@
|
||||
name=GOG Galaxy Launcher
|
||||
description_ru=Лаунчер для библиотеки игр GOG.
|
||||
description_en=Launcher for the GOG game library.
|
Before Width: | Height: | Size: 360 KiB |
@ -1,3 +0,0 @@
|
||||
name=Guild Wars 2
|
||||
description_ru=MMORPG с ярким миром и уникальной системой динамических событий, где игроки могут свободно исследовать просторы Тираи и участвовать в масштабных сражениях. Игра предлагает разнообразие рас и классов, а также акцент на совместной игре и взаимодействии между игроками.
|
||||
description_en=An MMORPG with a vibrant world and a unique system of dynamic events, where players can freely explore the realms of Tyria and engage in large-scale battles. The game offers a variety of races and classes, with an emphasis on cooperative play and player interaction.
|
Before Width: | Height: | Size: 247 KiB |
@ -1,3 +0,0 @@
|
||||
name=Indiegala Client
|
||||
description_ru=Лаунчер для библиотеки игр Indiegala.
|
||||
description_en=Launcher for the Indiegala game library.
|
Before Width: | Height: | Size: 1.0 MiB |
@ -1,3 +0,0 @@
|
||||
name=Last Chaos
|
||||
description_ru=Last Chaos – классическая MMORPG с шестью классами, осадами замков, корейским гриндом и километрами подземелий. Противостояние Апполона и Эреса набирает обороты, так что спешите принять одну из сторон.
|
||||
description_en=Last Chaos is a classic MMORPG with six classes, castle sieges, a Korean grind and kilometers of dungeons. The confrontation between Apollo and Eres is gaining momentum, so hurry up to take one of the sides.
|
Before Width: | Height: | Size: 901 KiB |
@ -1,3 +0,0 @@
|
||||
name=DC Universe Online (ENG)
|
||||
description_ru=MMORPG, в которой игроки создают собственных супергероев или суперзлодеев во вселенной DC Comics и участвуют в эпических битвах с известными персонажами, такими как Супермен и Бэтмен. Игра предлагает обширные квесты, захватывающие PvP-режимы и возможность совместной игры с другими игроками.
|
||||
description_en=An MMORPG where players create their own superheroes or supervillains in the DC Comics universe and engage in epic battles alongside iconic characters like Superman and Batman. The game features extensive quests, exciting PvP modes, and the ability to team up with other players.
|
Before Width: | Height: | Size: 864 KiB |
@ -1,3 +0,0 @@
|
||||
name=Anomaly Zone
|
||||
description_ru=Экшен-игра про сталкеров, где игроки исследуют таинственные миры и сражаются с разнообразными противниками. Игра предлагает захватывающий сюжет и возможность улучшать персонажа, открывая новые способности и снаряжение.
|
||||
description_en=An action game about stalkers, where players explore mysterious worlds and fight against a variety of opponents. The game offers an exciting storyline and the opportunity to improve the character by unlocking new abilities and equipment.
|
Before Width: | Height: | Size: 346 KiB |
@ -1,3 +0,0 @@
|
||||
name=CALIBER
|
||||
description_ru=Тактический шутер от третьего лица, где игроки могут выбирать из различных персонажей с уникальными способностями и сражаться в командных режимах. Игра предлагает реалистичную графику и динамичные бои, обеспечивая увлекательный игровой процесс.
|
||||
description_en=A tactical third-person shooter where players can choose from various characters with unique abilities and engage in team-based modes. The game features realistic graphics and dynamic combat, providing an engaging gameplay experience.
|
Before Width: | Height: | Size: 56 KiB |
@ -1,3 +0,0 @@
|
||||
name=Rockstar Games Launcher
|
||||
description_ru=Лаунчер для игр Rockstar.
|
||||
description_en=Launcher for Rockstar studio games.
|
Before Width: | Height: | Size: 1.0 MiB |
@ -1,3 +0,0 @@
|
||||
name=Toontown Rewritten (ENG)
|
||||
description_ru=Многопользовательская онлайн-игра, где игроки берут на себя роли мультяшных персонажей, сражаясь с противниками в локациях, наполненных юмором и приключениями. Игра предлагает кооперативный геймплей, квесты, мини-игры и возможность взаимодействия с другими игроками в красочном мире.
|
||||
description_en=A multiplayer online game, where players take on the roles of cartoon characters battling foes in humorous and adventurous locations. The game offers cooperative gameplay, quests, mini-games, and opportunities for interaction with other players in a colorful world.
|
Before Width: | Height: | Size: 769 KiB |
@ -1,3 +0,0 @@
|
||||
name=Warframe
|
||||
description_ru=Бесплатная многопользовательская онлайн-игра в жанре экшен-RPG, в которой игроки управляют древними воинами, известными как Тенно, и сражаются против различных фракций в разнообразных миссиях по всей галактике. Игра предлагает множество возможностей для кастомизации персонажей, кооперативный геймплей и постоянно обновляющийся контент.
|
||||
description_en=A free-to-play multiplayer online action RPG where players control ancient warriors known as Tenno and battle against various factions in diverse missions across the galaxy. The game offers extensive character customization options, cooperative gameplay, and continuously updated content.
|
Before Width: | Height: | Size: 806 KiB |
@ -1,3 +0,0 @@
|
||||
name=The Lord of the Rings Online (ENG)
|
||||
description_ru=MMORPG, основанная на произведениях Дж. Р. Р. Толкиена, позволяющая игрокам исследовать Средиземье, принимать участие в эпических квестах и сражениях с известными персонажами и созданиями из вселенной Властелина колец. Игра предлагает глубокую кастомизацию персонажей, богатый сюжет и множество возможностей для игры в одиночку или в группе.
|
||||
description_en=An MMORPG based on the works of J. R. R. Tolkien, allowing players to explore Middle-earth, take part in epic quests and battles with famous characters and creatures from the Lord of the Rings universe. The game offers deep customization of characters, a rich plot and many opportunities to play alone or in a group.
|
Before Width: | Height: | Size: 762 KiB |
@ -1,3 +0,0 @@
|
||||
name=Metal War Online
|
||||
description_ru=Многопользовательская онлайн-игра в жанре экшен с элементами стратегии, где игроки управляют боевыми роботами и сражаются на различных аренах. Игра предлагает богатую кастомизацию техники и разнообразные игровые режимы, позволяя каждому игроку создавать уникальный стиль боя.
|
||||
description_en=A multiplayer online action game with strategic elements, where players control combat robots and battle on various arenas. The game offers extensive customization options for the machines and a variety of game modes, allowing each player to create a unique fighting style.
|
Before Width: | Height: | Size: 684 KiB |
@ -1,3 +0,0 @@
|
||||
name=Mini World
|
||||
description_ru=Песочница, в которой игроки могут исследовать, строить и создавать свои уникальные миры в 3D-окружении. Игра предлагает разнообразные режимы, включая выживание и творчество, а также возможность взаимодействовать с другими игроками в многопользовательском формате.
|
||||
description_en=A sandbox game where players can explore, build, and create their unique worlds in a 3D environment. The game offers various modes, including survival and creative, as well as the ability to interact with other players in a multiplayer format.
|
Before Width: | Height: | Size: 240 KiB |
@ -1,3 +0,0 @@
|
||||
name=PPSSPP
|
||||
description_ru=Эмулятор портативной игровой консоли PlayStation Portable (PSP), позволяющий запускать игры PSP на компьютерах и мобильных устройствах. Он поддерживает улучшенную графику и различные настройки, что позволяет наслаждаться классическими играми с высоким качеством.
|
||||
description_en=An emulator for the PlayStation Portable (PSP) handheld gaming console, enabling users to play PSP games on computers and mobile devices. It supports enhanced graphics and various settings, allowing players to enjoy classic games at high quality.
|
Before Width: | Height: | Size: 963 KiB |
@ -1,3 +0,0 @@
|
||||
name=Panzar
|
||||
description_ru=Многопользовательская онлайн-игра в жанре экшен, где игроки сражаются в командах, используя различные классы персонажей и уникальные способности. Игра предлагает тактические сражения на больших картах с разрушительным взаимодействием окружения.
|
||||
description_en=A multiplayer online action game where players battle in teams using various character classes and unique abilities. The game features tactical battles on large maps with destructible environments.
|
Before Width: | Height: | Size: 961 KiB |
@ -1,3 +0,0 @@
|
||||
name=Path of Exile
|
||||
description_ru=Бесплатная онлайн-игра в жанре action RPG, в которой игроки исследуют мрачный мир, сражаются с монстрами и развивают свои персонажи через глубокую систему навыков и предметов. Игра известна своим сложным геймплеем и постоянно обновляемым контентом, включая сезонные лиги и уникальные механики.
|
||||
description_en=A free online action RPG where players explore a dark world, fight monsters, and develop their characters through a deep skill and item system. The game is known for its challenging gameplay and constantly updated content, including seasonal leagues and unique mechanics.
|
Before Width: | Height: | Size: 701 KiB |
@ -1,3 +0,0 @@
|
||||
name=Plarium Play
|
||||
description_ru=Лаунчер для игр Plarium.
|
||||
description_en=Launcher for Plarium studio games.
|
Before Width: | Height: | Size: 637 KiB |
@ -1,3 +0,0 @@
|
||||
name=Project64
|
||||
description_ru=Эмулятор Nintendo 64, который позволяет играть в игры этой консоли на современных устройствах. Поддерживает различные настройки графики и управления, обеспечивая высококачественный игровой опыт.
|
||||
description_en=The Nintendo 64 emulator, which allows you to play games of this console on modern devices. Supports various graphics and control settings, providing a high-quality gaming experience.
|
Before Width: | Height: | Size: 592 KiB |
@ -1,3 +0,0 @@
|
||||
name=Pulse Online
|
||||
description_ru=Многопользовательская онлайн-игра в жанре MMORPG, действие которой происходит в научно-фантастическом мире с уникальной боевой системой и глубоким крафтом. Игроки могут исследовать обширные локации, выполнять квесты, сражаться с противниками и взаимодействовать с другими участниками игры.
|
||||
description_en=A multiplayer online game in the MMORPG genre set in a sci-fi world with a unique combat system and deep crafting mechanics. Players can explore vast locations, complete quests, battle enemies, and interact with other participants in the game.
|
Before Width: | Height: | Size: 724 KiB |
@ -1,3 +0,0 @@
|
||||
name=Russian Fishing 4
|
||||
description_ru=Реалистичный симулятор рыбалки, который предлагает игрокам погрузиться в увлекательный процесс ловли рыбы в различных красивых водоемах России. Игра включает в себя широкий выбор снастей, видов рыб и возможностей для соревнований с другими рыбаками.
|
||||
description_en=A realistic fishing simulator that immerses players in the enjoyable process of catching fish in various beautiful bodies of water across Russia. The game features a wide selection of tackle, fish species, and opportunities for competition with other anglers.
|
Before Width: | Height: | Size: 623 KiB |
@ -1,4 +0,0 @@
|
||||
name=Saturn
|
||||
description_ru=Сатурн — это тактическая RPG, действие которой происходит на Земле и на спутниках Сатурна.
|
||||
Таинственный сигнал из космоса заставляет искусственный интеллект машин восстать против своих создателей по всей Солнечной системе. Защищайтесь от угрозы на Земле и подключайтесь к роботам на спутниках Сатурна, чтобы остановить конец света. На спасение мира дается всего 3 дня.
|
||||
description_en=Saturn is a tactical RPG set on the moons of Saturn and on Earth. The protagonist controls robots on the moons of Saturn and explores an underground city where one can find keys to the secrets of deep space.
|