-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
1 parent
c77cdc5
commit 31c97e5
Showing
16 changed files
with
1,809 additions
and
86 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
# PWAAT-Save-Editor 逆转裁判 123 存档修改器 | ||
|
||
## 功能 | ||
* 导入、导出存档 | ||
* Steam 与 Xbox 存档互相转换 | ||
* 解锁章节 | ||
* 修改法庭内血量 | ||
|
||
## 使用教程 | ||
### 下载 | ||
1. 在 [Release 页](https://github.com/XcantloadX/PWAAT-Save-Editor/releases)下载最新版本的编辑器 | ||
2. 解压后运行 `PWAAT Save Editor.exe` | ||
|
||
### 导入/导出存档 | ||
Steam 转 Xbox:菜单栏 → 转换 → “Xbox ← Steam” | ||
|
||
Xbox 转 Steam:菜单栏 → 转换 → “Xbox → Steam” | ||
|
||
导入 Steam 存档:菜单栏 → 转换 → “Steam ← 文件...” | ||
|
||
导出 Steam 存档:菜单栏 → 转换 → “Steam → 文件...” | ||
|
||
### 解锁章节 | ||
1. 关闭游戏 | ||
2. 在“文件”菜单内打开任意存档 | ||
3. 按需求调整“解锁章节”框内的设置 | ||
4. “文件” → “保存” | ||
5. 启动游戏 | ||
|
||
### 修改血量 | ||
1. 在“文件”菜单内打开任意存档 | ||
2. 检查“选择存档”处自动选中的存档是否为想要修改的存档,若不是,改为想要修改的存档 | ||
3. 调整血量 | ||
4. “文件” → “保存” | ||
5. 在游戏内重新读取该存档 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import app.native_ui.implement | ||
# 让 PyInstaller 收集下面这些模块 | ||
import winrt.windows.foundation | ||
import winrt.windows.foundation.collections | ||
import winrt.windows.management | ||
import winrt.windows.management.deployment | ||
import winrt.windows.storage | ||
import winrt.windows.applicationmodel |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,250 @@ | ||
# -*- coding: utf-8 -*- | ||
|
||
########################################################################### | ||
## Python code generated with wxFormBuilder (version 4.0.0-0-g0efcecf) | ||
## http://www.wxformbuilder.org/ | ||
## | ||
## PLEASE DO *NOT* EDIT THIS FILE! | ||
########################################################################### | ||
|
||
import wx | ||
import wx.xrc | ||
|
||
########################################################################### | ||
## Class FrameMain | ||
########################################################################### | ||
|
||
class FrameMain ( wx.Frame ): | ||
|
||
def __init__( self, parent ): | ||
wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = u"逆转裁判 123 存档工具", pos = wx.DefaultPosition, size = wx.Size( 500,400 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL ) | ||
|
||
self.SetSizeHints( wx.DefaultSize, wx.DefaultSize ) | ||
self.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_WINDOW ) ) | ||
|
||
bSizer1 = wx.BoxSizer( wx.VERTICAL ) | ||
|
||
self.m_panel2 = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL ) | ||
bSizer4 = wx.BoxSizer( wx.VERTICAL ) | ||
|
||
self.m_notebook1 = wx.Notebook( self.m_panel2, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, 0 ) | ||
self.m_pnl_common = wx.Panel( self.m_notebook1, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL ) | ||
bSizer2 = wx.BoxSizer( wx.VERTICAL ) | ||
|
||
sbSizer_chapters = wx.StaticBoxSizer( wx.StaticBox( self.m_pnl_common, wx.ID_ANY, u"解锁章节" ), wx.VERTICAL ) | ||
|
||
fgSizer1 = wx.FlexGridSizer( 3, 2, 0, 20 ) | ||
fgSizer1.AddGrowableCol( 0 ) | ||
fgSizer1.AddGrowableCol( 1 ) | ||
fgSizer1.SetFlexibleDirection( wx.BOTH ) | ||
fgSizer1.SetNonFlexibleGrowMode( wx.FLEX_GROWMODE_SPECIFIED ) | ||
|
||
self.m_staticText1 = wx.StaticText( sbSizer_chapters.GetStaticBox(), wx.ID_ANY, u"逆转裁判 1", wx.DefaultPosition, wx.DefaultSize, 0 ) | ||
self.m_staticText1.Wrap( -1 ) | ||
|
||
fgSizer1.Add( self.m_staticText1, 0, wx.ALL, 5 ) | ||
|
||
m_chc_gs1Choices = [ u"第一章 最初的逆转", u"第二章 逆转姐妹", u"第三章 逆转的大将军", u"第四章 逆转,然后再见", u"第五章 复苏的逆转" ] | ||
self.m_chc_gs1 = wx.Choice( sbSizer_chapters.GetStaticBox(), wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, m_chc_gs1Choices, 0 ) | ||
self.m_chc_gs1.SetSelection( 0 ) | ||
fgSizer1.Add( self.m_chc_gs1, 0, wx.ALL, 5 ) | ||
|
||
self.m_staticText2 = wx.StaticText( sbSizer_chapters.GetStaticBox(), wx.ID_ANY, u"逆转裁判 2", wx.DefaultPosition, wx.DefaultSize, 0 ) | ||
self.m_staticText2.Wrap( -1 ) | ||
|
||
fgSizer1.Add( self.m_staticText2, 0, wx.ALL, 5 ) | ||
|
||
m_chc_gs2Choices = [ u"第一章 失落的逆转", u"第二章 再会,然后逆转", u"第三章 逆转马戏团", u"第四章 再见,逆转" ] | ||
self.m_chc_gs2 = wx.Choice( sbSizer_chapters.GetStaticBox(), wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, m_chc_gs2Choices, 0 ) | ||
self.m_chc_gs2.SetSelection( 0 ) | ||
fgSizer1.Add( self.m_chc_gs2, 0, wx.ALL, 5 ) | ||
|
||
self.m_staticText3 = wx.StaticText( sbSizer_chapters.GetStaticBox(), wx.ID_ANY, u"逆转裁判 3", wx.DefaultPosition, wx.DefaultSize, 0 ) | ||
self.m_staticText3.Wrap( -1 ) | ||
|
||
fgSizer1.Add( self.m_staticText3, 0, wx.ALL, 5 ) | ||
|
||
m_chc_gs3Choices = [ u"第一章 回忆的逆转", u"第二章 遭窃的逆转", u"第三章 逆转的秘方", u"第四章 初始的逆转", u"第五章 华丽的逆转" ] | ||
self.m_chc_gs3 = wx.Choice( sbSizer_chapters.GetStaticBox(), wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, m_chc_gs3Choices, 0 ) | ||
self.m_chc_gs3.SetSelection( 0 ) | ||
fgSizer1.Add( self.m_chc_gs3, 0, wx.ALL|wx.EXPAND, 5 ) | ||
|
||
|
||
sbSizer_chapters.Add( fgSizer1, 1, 0, 5 ) | ||
|
||
|
||
bSizer2.Add( sbSizer_chapters, 1, wx.EXPAND, 5 ) | ||
|
||
sbSizer_ingame = wx.StaticBoxSizer( wx.StaticBox( self.m_pnl_common, wx.ID_ANY, u"游戏内" ), wx.VERTICAL ) | ||
|
||
bSizer5 = wx.BoxSizer( wx.VERTICAL ) | ||
|
||
bSizer61 = wx.BoxSizer( wx.HORIZONTAL ) | ||
|
||
self.m_staticText5 = wx.StaticText( sbSizer_ingame.GetStaticBox(), wx.ID_ANY, u"存档选择", wx.DefaultPosition, wx.DefaultSize, 0 ) | ||
self.m_staticText5.Wrap( -1 ) | ||
|
||
bSizer61.Add( self.m_staticText5, 0, wx.ALL, 5 ) | ||
|
||
m_chc_savesChoices = [] | ||
self.m_chc_saves = wx.Choice( sbSizer_ingame.GetStaticBox(), wx.ID_ANY, wx.DefaultPosition, wx.Size( 350,-1 ), m_chc_savesChoices, 0 ) | ||
self.m_chc_saves.SetSelection( 0 ) | ||
bSizer61.Add( self.m_chc_saves, 0, wx.ALL, 5 ) | ||
|
||
|
||
bSizer5.Add( bSizer61, 0, wx.EXPAND, 5 ) | ||
|
||
bSizer6 = wx.BoxSizer( wx.HORIZONTAL ) | ||
|
||
self.m_staticText4 = wx.StaticText( sbSizer_ingame.GetStaticBox(), wx.ID_ANY, u"法庭内血量", wx.DefaultPosition, wx.DefaultSize, 0 ) | ||
self.m_staticText4.Wrap( -1 ) | ||
|
||
bSizer6.Add( self.m_staticText4, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 ) | ||
|
||
self.m_sld_hp = wx.Slider( sbSizer_ingame.GetStaticBox(), wx.ID_ANY, 0, 0, 80, wx.DefaultPosition, wx.Size( 150,-1 ), wx.SL_LABELS ) | ||
bSizer6.Add( self.m_sld_hp, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 ) | ||
|
||
|
||
bSizer5.Add( bSizer6, 0, wx.EXPAND, 5 ) | ||
|
||
|
||
sbSizer_ingame.Add( bSizer5, 1, wx.EXPAND, 5 ) | ||
|
||
|
||
bSizer2.Add( sbSizer_ingame, 1, wx.EXPAND, 5 ) | ||
|
||
|
||
self.m_pnl_common.SetSizer( bSizer2 ) | ||
self.m_pnl_common.Layout() | ||
bSizer2.Fit( self.m_pnl_common ) | ||
self.m_notebook1.AddPage( self.m_pnl_common, u"常用设置", True ) | ||
|
||
bSizer4.Add( self.m_notebook1, 1, wx.EXPAND, 5 ) | ||
|
||
|
||
self.m_panel2.SetSizer( bSizer4 ) | ||
self.m_panel2.Layout() | ||
bSizer4.Fit( self.m_panel2 ) | ||
bSizer1.Add( self.m_panel2, 1, wx.EXPAND |wx.ALL, 5 ) | ||
|
||
|
||
self.SetSizer( bSizer1 ) | ||
self.Layout() | ||
self.m_menubar = wx.MenuBar( 0 ) | ||
self.m_menu_file = wx.Menu() | ||
self.m_mi_open = wx.MenuItem( self.m_menu_file, wx.ID_ANY, u"打开..."+ u"\t" + u"Ctrl+O", wx.EmptyString, wx.ITEM_NORMAL ) | ||
self.m_mi_open.SetBitmap( wx.NullBitmap ) | ||
self.m_menu_file.Append( self.m_mi_open ) | ||
|
||
self.m_mi_open_steam = wx.MenuItem( self.m_menu_file, wx.ID_ANY, u"打开 Steam 存档", wx.EmptyString, wx.ITEM_NORMAL ) | ||
self.m_menu_file.Append( self.m_mi_open_steam ) | ||
|
||
self.m_mi_open_xbox = wx.MenuItem( self.m_menu_file, wx.ID_ANY, u"打开 Xbox 存档", wx.EmptyString, wx.ITEM_NORMAL ) | ||
self.m_menu_file.Append( self.m_mi_open_xbox ) | ||
|
||
self.m_menu_file.AppendSeparator() | ||
|
||
self.m_mi_save = wx.MenuItem( self.m_menu_file, wx.ID_ANY, u"保存"+ u"\t" + u"Ctrl+S", wx.EmptyString, wx.ITEM_NORMAL ) | ||
self.m_mi_save.SetBitmap( wx.NullBitmap ) | ||
self.m_menu_file.Append( self.m_mi_save ) | ||
|
||
self.m_mi_save_as = wx.MenuItem( self.m_menu_file, wx.ID_ANY, u"另存为...", wx.EmptyString, wx.ITEM_NORMAL ) | ||
self.m_menu_file.Append( self.m_mi_save_as ) | ||
|
||
self.m_menu_file.AppendSeparator() | ||
|
||
self.m_mi_show_debug = wx.MenuItem( self.m_menu_file, wx.ID_ANY, u"显示调试信息", wx.EmptyString, wx.ITEM_NORMAL ) | ||
self.m_menu_file.Append( self.m_mi_show_debug ) | ||
|
||
self.m_menubar.Append( self.m_menu_file, u"文件" ) | ||
|
||
self.m_menu_convert = wx.Menu() | ||
self.m_mi_xbox2steam = wx.MenuItem( self.m_menu_convert, wx.ID_ANY, u"Xbox → Steam", wx.EmptyString, wx.ITEM_NORMAL ) | ||
self.m_menu_convert.Append( self.m_mi_xbox2steam ) | ||
|
||
self.m_mi_steam2xbox = wx.MenuItem( self.m_menu_convert, wx.ID_ANY, u"Xbox ← Steam", wx.EmptyString, wx.ITEM_NORMAL ) | ||
self.m_menu_convert.Append( self.m_mi_steam2xbox ) | ||
|
||
self.m_menu_convert.AppendSeparator() | ||
|
||
self.m_mi_steam2file = wx.MenuItem( self.m_menu_convert, wx.ID_ANY, u"Steam → 文件...", wx.EmptyString, wx.ITEM_NORMAL ) | ||
self.m_menu_convert.Append( self.m_mi_steam2file ) | ||
|
||
self.m_mi_file2steam = wx.MenuItem( self.m_menu_convert, wx.ID_ANY, u"Steam ← 文件...", wx.EmptyString, wx.ITEM_NORMAL ) | ||
self.m_menu_convert.Append( self.m_mi_file2steam ) | ||
|
||
self.m_menubar.Append( self.m_menu_convert, u"转换" ) | ||
|
||
self.SetMenuBar( self.m_menubar ) | ||
|
||
|
||
self.Centre( wx.BOTH ) | ||
|
||
# Connect Events | ||
self.m_chc_gs1.Bind( wx.EVT_CHOICE, self.chc_gs1_on_choice ) | ||
self.m_chc_gs2.Bind( wx.EVT_CHOICE, self.chc_gs2_on_choice ) | ||
self.m_chc_gs3.Bind( wx.EVT_CHOICE, self.chc_gs3_on_choice ) | ||
self.m_chc_saves.Bind( wx.EVT_CHOICE, self.chc_savs_on_choice ) | ||
self.m_sld_hp.Bind( wx.EVT_SCROLL_CHANGED, self.sld_hp_on_scroll_changed ) | ||
self.Bind( wx.EVT_MENU, self.mi_open_on_select, id = self.m_mi_open.GetId() ) | ||
self.Bind( wx.EVT_MENU, self.mi_open_steam_on_select, id = self.m_mi_open_steam.GetId() ) | ||
self.Bind( wx.EVT_MENU, self.mi_open_xbox_on_select, id = self.m_mi_open_xbox.GetId() ) | ||
self.Bind( wx.EVT_MENU, self.mi_save_on_select, id = self.m_mi_save.GetId() ) | ||
self.Bind( wx.EVT_MENU, self.mi_save_as_on_select, id = self.m_mi_save_as.GetId() ) | ||
self.Bind( wx.EVT_MENU, self.mi_show_debug_on_select, id = self.m_mi_show_debug.GetId() ) | ||
self.Bind( wx.EVT_MENU, self.mi_xbox2steam_on_choice, id = self.m_mi_xbox2steam.GetId() ) | ||
self.Bind( wx.EVT_MENU, self.mi_steam2xbox_on_choice, id = self.m_mi_steam2xbox.GetId() ) | ||
self.Bind( wx.EVT_MENU, self.mi_steam2file_on_choice, id = self.m_mi_steam2file.GetId() ) | ||
self.Bind( wx.EVT_MENU, self.mi_file2steam_on_choice, id = self.m_mi_file2steam.GetId() ) | ||
|
||
def __del__( self ): | ||
pass | ||
|
||
|
||
# Virtual event handlers, override them in your derived class | ||
def chc_gs1_on_choice( self, event ): | ||
event.Skip() | ||
|
||
def chc_gs2_on_choice( self, event ): | ||
event.Skip() | ||
|
||
def chc_gs3_on_choice( self, event ): | ||
event.Skip() | ||
|
||
def chc_savs_on_choice( self, event ): | ||
event.Skip() | ||
|
||
def sld_hp_on_scroll_changed( self, event ): | ||
event.Skip() | ||
|
||
def mi_open_on_select( self, event ): | ||
event.Skip() | ||
|
||
def mi_open_steam_on_select( self, event ): | ||
event.Skip() | ||
|
||
def mi_open_xbox_on_select( self, event ): | ||
event.Skip() | ||
|
||
def mi_save_on_select( self, event ): | ||
event.Skip() | ||
|
||
def mi_save_as_on_select( self, event ): | ||
event.Skip() | ||
|
||
def mi_show_debug_on_select( self, event ): | ||
event.Skip() | ||
|
||
def mi_xbox2steam_on_choice( self, event ): | ||
event.Skip() | ||
|
||
def mi_steam2xbox_on_choice( self, event ): | ||
event.Skip() | ||
|
||
def mi_steam2file_on_choice( self, event ): | ||
event.Skip() | ||
|
||
def mi_file2steam_on_choice( self, event ): | ||
event.Skip() | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,194 @@ | ||
import sys | ||
import traceback | ||
import datetime | ||
|
||
import wx | ||
|
||
from .form import FrameMain | ||
from app.editor.save_editor import SaveEditor, NoOpenSaveFileError, SaveType | ||
import app.editor.locator as locator | ||
|
||
def _excepthook(type, value, tb): | ||
if type == NoOpenSaveFileError: | ||
# 不直接调用是因为弹出的消息框会导致原来的焦点控件多次聚焦, | ||
# 形成多次值改变事件,进而弹出多个消息框 | ||
wx.CallAfter(wx.MessageBox, '请先打开任意存档文件。', '错误', wx.OK | wx.ICON_ERROR) | ||
else: | ||
# 提示错误 | ||
wx.MessageBox(''.join(traceback.format_exception(type, value, tb)), '错误', wx.OK | wx.ICON_ERROR) | ||
traceback.print_exception(type, value, tb) | ||
sys.excepthook = _excepthook | ||
|
||
class Dialog(wx.Dialog): | ||
def __init__(self, parent, title, text): | ||
super().__init__(parent, title=title, style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER) | ||
|
||
sizer = wx.BoxSizer(wx.VERTICAL) | ||
|
||
text_ctrl = wx.TextCtrl(self, style=wx.TE_MULTILINE | wx.TE_READONLY) | ||
text_ctrl.SetValue(text) | ||
sizer.Add(text_ctrl, proportion=1, flag=wx.EXPAND | wx.ALL, border=10) | ||
|
||
button = wx.Button(self, label="确认") | ||
button.Bind(wx.EVT_BUTTON, self.on_confirm) | ||
sizer.Add(button, flag=wx.ALIGN_CENTER | wx.ALL, border=10) | ||
|
||
self.SetSizerAndFit(sizer) | ||
self.SetSize(600, 400) | ||
|
||
def on_confirm(self, event): | ||
self.EndModal(wx.ID_OK) | ||
|
||
class FrameMainImpl(FrameMain): | ||
def __init__(self, parent): | ||
super().__init__(parent) | ||
self.m_sld_hp.SetLineSize(8) | ||
|
||
self.editor = SaveEditor(language='hans') # TODO: i18n | ||
|
||
|
||
def sld_hp_on_scroll_changed(self, event): | ||
# 强制步进 8 | ||
value = self.m_sld_hp.Value | ||
remainder = value % 8 | ||
if remainder != 0: | ||
value -= remainder | ||
self.m_sld_hp.Value = value | ||
|
||
# 处理事件 | ||
self.editor.set_court_hp(self.m_chc_saves.GetSelection(), self.m_sld_hp.Value) | ||
|
||
def mi_open_on_select(self, event): | ||
with wx.FileDialog(self, "打开存档文件", wildcard="存档文件 (*.*)|*.*", style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) as fileDialog: | ||
if fileDialog.ShowModal() == wx.ID_CANCEL: | ||
return | ||
path = fileDialog.GetPath() | ||
self.editor.load(path) | ||
self.load_ui() | ||
|
||
def mi_open_steam_on_select(self, event): | ||
_, steam_path = locator.system_steam_save_path[0] | ||
self.editor.load(steam_path) | ||
self.load_ui() | ||
|
||
def mi_open_xbox_on_select(self, event): | ||
xbox_path = locator.system_xbox_save_path[0] | ||
self.editor.load(xbox_path) | ||
self.load_ui() | ||
|
||
def mi_save_on_select(self, event): | ||
self.editor.save() | ||
wx.MessageBox('保存成功', '提示', wx.OK | wx.ICON_INFORMATION) | ||
|
||
def mi_xbox2steam_on_choice(self, event): | ||
if not wx.MessageBox('此操作将会覆盖当前 Steam 存档文件,是否继续?', '警告', wx.YES_NO | wx.ICON_WARNING) == wx.YES: | ||
return | ||
xbox_path = locator.system_xbox_save_path[0] | ||
steam_id, steam_path = locator.system_steam_save_path[0] | ||
self.editor.load(xbox_path) | ||
self.editor.set_account_id(int(steam_id)) | ||
self.editor.convert(SaveType.STEAM) | ||
self.editor.save(steam_path) | ||
wx.MessageBox('转换成功', '提示', wx.OK | wx.ICON_INFORMATION) | ||
|
||
def mi_steam2xbox_on_choice(self, event): | ||
if not wx.MessageBox('此操作将会覆盖当前 Xbox 存档文件,是否继续?', '警告', wx.YES_NO | wx.ICON_WARNING) == wx.YES: | ||
return | ||
xbox_path = locator.system_xbox_save_path[0] | ||
_, steam_path = locator.system_steam_save_path[0] | ||
self.editor.load(steam_path) | ||
self.editor.convert(SaveType.XBOX) | ||
self.editor.save(xbox_path) | ||
wx.MessageBox('转换成功', '提示', wx.OK | wx.ICON_INFORMATION) | ||
|
||
def mi_save_as_on_select(self, event): | ||
with wx.FileDialog(self, "保存存档文件", wildcard="存档文件 (*.*)|*.*", style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT) as fileDialog: | ||
if fileDialog.ShowModal() == wx.ID_CANCEL: | ||
return | ||
path = fileDialog.GetPath() | ||
self.editor.save(path) | ||
wx.MessageBox('保存成功', '提示', wx.OK | wx.ICON_INFORMATION) | ||
|
||
def mi_show_debug_on_select(self, event): | ||
msg = 'Steam 路径: ' + repr(locator.steam_path) + '\n' | ||
msg += 'Steam 游戏路径: ' + repr(locator.steam_game_path) + '\n' | ||
msg += 'Steam 存档路径: ' + repr(locator.system_steam_save_path) + '\n' | ||
msg += 'Xbox 游戏路径: ' + repr(locator.xbox_game_path) + '\n' | ||
msg += 'Xbox 存档路径: ' + repr(locator.system_xbox_save_path) + '\n' | ||
if self.editor.opened: | ||
msg += '存档类型: ' + repr(self.editor.save_type) + '\n' | ||
msg += 'Steam ID: ' + repr(self.editor.get_account_id()) + '\n' | ||
# 显示信息 | ||
dialog = Dialog(self, '调试信息', msg) | ||
dialog.ShowModal() | ||
dialog.Destroy() | ||
|
||
def load_ui(self): | ||
# 解锁章节 | ||
gs1 = self.editor.get_unlocked_chapters(1) | ||
self.m_chc_gs1.SetSelection(gs1 - 1) | ||
gs2 = self.editor.get_unlocked_chapters(2) | ||
self.m_chc_gs2.SetSelection(gs2 - 1) | ||
gs3 = self.editor.get_unlocked_chapters(3) | ||
self.m_chc_gs3.SetSelection(gs3 - 1) | ||
|
||
# 存档选择 | ||
self.m_chc_saves.Clear() | ||
slots = self.editor.get_slots() | ||
for i, slot in enumerate(slots, 1): | ||
self.m_chc_saves.Append(f'{i:02d}: ' + slot.short_str) | ||
newest = max(slots, key=( | ||
lambda slot: | ||
datetime.datetime.strptime(slot.time, '%Y/%m/%d %H:%M:%S') if slot.time | ||
else datetime.datetime(1, 1, 1) | ||
)) | ||
self.m_chc_saves.SetSelection(slots.index(newest)) | ||
|
||
# 触发选择存档事件 | ||
self.chc_savs_on_choice(None) | ||
|
||
def chc_savs_on_choice(self, event): | ||
slot_number = self.m_chc_saves.GetSelection() | ||
if slot_number == wx.NOT_FOUND: | ||
return | ||
self.m_sld_hp.Value = self.editor.get_court_hp(slot_number) | ||
|
||
def mi_file2steam_on_choice(self, event): | ||
with wx.FileDialog(self, "打开文件", wildcard="存档文件 (*.*)|*.*", style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) as fileDialog: | ||
if fileDialog.ShowModal() == wx.ID_CANCEL: | ||
return | ||
if not wx.MessageBox('此操作将会覆盖当前 Steam 存档文件,是否继续?', '警告', wx.YES_NO | wx.ICON_WARNING) == wx.YES: | ||
return | ||
path = fileDialog.GetPath() | ||
self.editor.load(path) | ||
steam_id, steam_path = locator.system_steam_save_path[0] | ||
self.editor.set_account_id(int(steam_id)) | ||
self.editor.save(steam_path) | ||
wx.MessageBox('导入成功', '提示', wx.OK | wx.ICON_INFORMATION) | ||
|
||
def mi_steam2file_on_choice(self, event): | ||
# TODO 自动检测存档类型 | ||
with wx.FileDialog(self, "保存文件", wildcard="存档文件 (*.*)|*.*", style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT) as fileDialog: | ||
if fileDialog.ShowModal() == wx.ID_CANCEL: | ||
return | ||
path = fileDialog.GetPath() | ||
_, steam_path = locator.system_steam_save_path[0] | ||
self.editor.load(steam_path) | ||
if wx.MessageBox('是否擦除存档中 Steam ID 信息?', '提示', wx.YES_NO | wx.ICON_QUESTION) == wx.YES: | ||
self.editor.set_account_id(111111111) | ||
self.editor.save(path) | ||
wx.MessageBox('导出成功', '提示', wx.OK | wx.ICON_INFORMATION) | ||
|
||
def chc_gs1_on_choice(self, event): | ||
self.editor.set_unlocked_chapters(1, self.m_chc_gs1.GetSelection() + 1) | ||
|
||
def chc_gs2_on_choice(self, event): | ||
self.editor.set_unlocked_chapters(2, self.m_chc_gs2.GetSelection() + 1) | ||
|
||
def chc_gs3_on_choice(self, event): | ||
self.editor.set_unlocked_chapters(3, self.m_chc_gs3.GetSelection() + 1) | ||
|
||
app = wx.App() | ||
frame = FrameMainImpl(None) | ||
frame.Show() | ||
app.MainLoop() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,37 +1 @@ | ||
import os | ||
|
||
|
||
|
||
def find_game_path() -> str|None: | ||
""" | ||
自动搜索游戏安装路径 | ||
""" | ||
drives = ['C:', 'D:', 'E:', 'F:', 'G:', 'H:', 'I:', 'J:', 'K:', 'L:', 'M:', 'N:', 'O:', 'P:', 'Q:', 'R:', 'S:', 'T:', 'U:', 'V:', 'W:', 'X:', 'Y:', 'Z:'] | ||
for drive in drives: | ||
steam_library = os.path.join(drive, 'SteamLibrary') | ||
game_path = os.path.join(steam_library, 'steamapps', 'common', 'Phoenix Wright Ace Attorney Trilogy') | ||
if os.path.exists(game_path): | ||
return game_path | ||
return None | ||
|
||
def find_save_path() -> str|None: | ||
""" | ||
自动搜索存档路径 | ||
""" | ||
# 首先搜索 Steam 安装路径 | ||
guesses = [ | ||
'C:\\Program Files (x86)\\Steam', | ||
'D:\\Program Files (x86)\\Steam', | ||
'E:\\Program Files (x86)\\Steam', | ||
'F:\\Program Files (x86)\\Steam', | ||
'G:\\Program Files (x86)\\Steam', | ||
] | ||
guesses = [path for path in guesses if os.path.exists(path)] | ||
if not guesses: | ||
return None | ||
steam_path = guesses[0] | ||
# C:\Program Files (x86)\Steam\userdata\1082712526\787480\remote | ||
user_path = os.path.join(steam_path, 'userdata', '1082712526', '787480', 'remote', 'systemdata') | ||
if os.path.exists(user_path): | ||
return user_path | ||
return None |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.