diff --git a/Browser/Properties/Resources.zh-CN.resx b/Browser/Properties/Resources.zh-CN.resx index cabd6d878..5f3d1b3eb 100644 --- a/Browser/Properties/Resources.zh-CN.resx +++ b/Browser/Properties/Resources.zh-CN.resx @@ -1,394 +1,394 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 下(&B) - - - 隐藏(&I) - - - 左(&L) - - - 右(&R) - - - 上(&T) - - - 更新忽略缓存(&C) - - - 前往登录页面 - - - 缩放: - - - 应用样式表失败。 - - - -try {{ -var node = document.getElementById('{0}'); -if (node) document.getElementsByTagName('head')[0].removeChild(node); -node = document.createElement('div'); -node.innerHTML = 'F<style id=\'{0}\'>body {{ visibility: hidden; }} \ -#flashWrap {{ position: fixed; left: 0; top: 0; width: 100% !important; height: 100% !important; }} \ -#htmlWrap {{ visibility: visible; width: 100% !important; height: 100% !important; }}</style>'; -document.getElementsByTagName('head')[0].appendChild(node.lastChild); -}} -catch(e) {{ - alert("フレームCSS適用に失敗しました: "+e); -}} - - - 移至登录页面。 -你确定吗? - - - 更多选择 - - - 缩放:适合 - - - -try {{ -var node = document.getElementById('{0}'); -if (node) document.getElementsByTagName('head')[0].removeChild(node); -node = document.createElement('div'); -node.innerHTML = 'P<style id=\'{0}\'>body {{ visibility: hidden; overflow: hidden; }} \ -div #block_background {{ visibility: visible; }} \ -div #alert {{ visibility: visible; overflow: scroll; overflow-x: hidden; top: 3% !important; left: 3% !important; width: 94% !important; height: 94%; padding: 2%; box-sizing: border-box;}} \ -div.dmm-ntgnavi {{ display: none; }} \ -#area-game {{ position: fixed; left: 0; top: 0; width: 100%; height: 100%; }} \ -#game_frame {{ visibility: visible; width: 100% !important; height: 100% !important; }}</style>'; -document.getElementsByTagName('head')[0].appendChild(node.lastChild); -}} -catch(e) {{ - alert("无法应用页面CSS: "+e); -}} - - - 重新加载。 -你确定吗? - - - 截图失败。 - - - 复制到剪贴板(&C) - - - 沉默 - - - 刷新 - - - 截屏 - - - 缩放 - - - 七四式电子观测仪浏览器 - - - -try { - if ( DMM.netgame.reloadDialog ) DMM.netgame.reloadDialog = function (){}; -} -catch(e) { - alert("DMM 无法隐藏页面更新对话框: "+e); -} - - - var node = document.getElementById('{0}'); -if (node) document.getElementsByTagName('head')[0].removeChild(node); - - - var timeToAdd = 1000 * 60 * 60 * 24 * 7 * 4 * 6; -var date = new Date(); -var expiryTime = parseInt(date.getTime()) + timeToAdd; -date.setTime(expiryTime); -var utcTime = date.toUTCString(); -document.cookie = "ckcy=1;expires="+utcTime+";domain=www.dmm.com;path=/netgame/"; - - - var element = document.getElementById('welcome'); element.parentNode.removeChild(element); - - - var element = document.getElementById('welcome'); element.parentNode.removeChild(element); - - - 确认 - - - 忽略缓存并重新加载。 -你确定吗? - - - 显示工具菜单 - - - 打开开发者工具 - - - 窗口合适 - - - 删除缓存 - - - 浏览器渲染过程 - - - 没有正常结束。 - - - 被另一个进程终止。 - - - 已经崩溃。 - - - 被意外终止。 - - - 重新加载后,该进程将启动。 - - - 您确定要清除缓存吗? - - - 确认重启浏览器 - - - 截屏(&S) - - - 上一张截图(&P) - - - 打开屏幕截图文件夹(&O) - - - 音量(&V) - - - 沉默(&M) - - - 刷新(&R) - - - 转到登录页面(&L) - - - 移动(&N)... - - - 应用样式表 - - - 配置(&A) - - - 尚无截图。 - - - 无法加载浏览器组件。 -需要 Microsoft Visual C++ 2019 Redistributable。 -打开下载页面? -(请安装 vc_redist.x64.exe) - - - CefSharp 加载错误 - - - 无法隐藏 DMM 刷新对话框。 - - - 砍口垒未加载,无法截屏。 - - - 屏幕截图已保存至 {0}。 - - - 无法保存屏幕截图。 - - - 屏幕截图已复制到剪贴板。 - - - 无法将屏幕截图复制到剪贴板。 - - - 屏幕截图 {0} 已复制到剪贴板。 - - - 缩放(&Z) - - - 文件(_F) - - - 后退 - - - 向前 - - - DMM点 - - - 明石列表 - - - 未找到 WebView2。开始下载。 - - - WebView2 下载完成。开始安装。 - - - WebView2 安装完成。 - - - 由于缺少权限,无法应用 Vulkan 解决方法。以管理员身份运行 Electronic Observer 以使解决方法生效。 - - - 检测到 WebView2 的版本较旧。正在下载最新版本。 - - - 尝试安装 WebView2 时发生错误。请手动安装WebView2。 - - - 缓存删除处理完成。 - - - 您即将前进到自动刷新工具中的规则禁止的单元格。 -你想刷新一下吗? - - - 应用浏览器字体失败。 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 下(&B) + + + 隐藏(&I) + + + 左(&L) + + + 右(&R) + + + 上(&T) + + + 更新忽略缓存(&C) + + + 前往登录页面 + + + 缩放: + + + 应用样式表失败。 + + + +try {{ +var node = document.getElementById('{0}'); +if (node) document.getElementsByTagName('head')[0].removeChild(node); +node = document.createElement('div'); +node.innerHTML = 'F<style id=\'{0}\'>body {{ visibility: hidden; }} \ +#flashWrap {{ position: fixed; left: 0; top: 0; width: 100% !important; height: 100% !important; }} \ +#htmlWrap {{ visibility: visible; width: 100% !important; height: 100% !important; }}</style>'; +document.getElementsByTagName('head')[0].appendChild(node.lastChild); +}} +catch(e) {{ + alert("フレームCSS適用に失敗しました: "+e); +}} + + + 移至登录页面。 +你确定吗? + + + 更多选择 + + + 缩放:适合 + + + +try {{ +var node = document.getElementById('{0}'); +if (node) document.getElementsByTagName('head')[0].removeChild(node); +node = document.createElement('div'); +node.innerHTML = 'P<style id=\'{0}\'>body {{ visibility: hidden; overflow: hidden; }} \ +div #block_background {{ visibility: visible; }} \ +div #alert {{ visibility: visible; overflow: scroll; overflow-x: hidden; top: 3% !important; left: 3% !important; width: 94% !important; height: 94%; padding: 2%; box-sizing: border-box;}} \ +div.dmm-ntgnavi {{ display: none; }} \ +#area-game {{ position: fixed; left: 0; top: 0; width: 100%; height: 100%; }} \ +#game_frame {{ visibility: visible; width: 100% !important; height: 100% !important; }}</style>'; +document.getElementsByTagName('head')[0].appendChild(node.lastChild); +}} +catch(e) {{ + alert("无法应用页面CSS: "+e); +}} + + + 重新加载。 +你确定吗? + + + 截图失败。 + + + 复制到剪贴板(&C) + + + 沉默 + + + 刷新 + + + 截屏 + + + 缩放 + + + 七四式电子观测仪浏览器 + + + +try { + if ( DMM.netgame.reloadDialog ) DMM.netgame.reloadDialog = function (){}; +} +catch(e) { + alert("DMM 无法隐藏页面更新对话框: "+e); +} + + + var node = document.getElementById('{0}'); +if (node) document.getElementsByTagName('head')[0].removeChild(node); + + + var timeToAdd = 1000 * 60 * 60 * 24 * 7 * 4 * 6; +var date = new Date(); +var expiryTime = parseInt(date.getTime()) + timeToAdd; +date.setTime(expiryTime); +var utcTime = date.toUTCString(); +document.cookie = "ckcy=1;expires="+utcTime+";domain=www.dmm.com;path=/netgame/"; + + + var element = document.getElementById('welcome'); element.parentNode.removeChild(element); + + + var element = document.getElementById('welcome'); element.parentNode.removeChild(element); + + + 确认 + + + 忽略缓存并重新加载。 +你确定吗? + + + 显示工具菜单 + + + 打开开发者工具 + + + 窗口合适 + + + 删除缓存 + + + 浏览器渲染过程 + + + 没有正常结束。 + + + 被另一个进程终止。 + + + 已经崩溃。 + + + 被意外终止。 + + + 重新加载后,该进程将启动。 + + + 您确定要清除缓存吗? + + + 确认重启浏览器 + + + 截屏(&S) + + + 上一张截图(&P) + + + 打开屏幕截图文件夹(&O) + + + 音量(&V) + + + 沉默(&M) + + + 刷新(&R) + + + 转到登录页面(&L) + + + 移动(&N)... + + + 应用样式表 + + + 配置(&A) + + + 尚无截图。 + + + 无法加载浏览器组件。 +需要 Microsoft Visual C++ 2019 Redistributable。 +打开下载页面? +(请安装 vc_redist.x64.exe) + + + CefSharp 加载错误 + + + 无法隐藏 DMM 刷新对话框。 + + + 砍口垒未加载,无法截屏。 + + + 屏幕截图已保存至 {0}。 + + + 无法保存屏幕截图。 + + + 屏幕截图已复制到剪贴板。 + + + 无法将屏幕截图复制到剪贴板。 + + + 屏幕截图 {0} 已复制到剪贴板。 + + + 缩放(&Z) + + + 文件(_F) + + + 后退 + + + 向前 + + + DMM点 + + + 明石列表 + + + 未找到 WebView2。开始下载。 + + + WebView2 下载完成。开始安装。 + + + WebView2 安装完成。 + + + 由于缺少权限,无法应用 Vulkan 解决方法。以管理员身份运行 Electronic Observer 以使解决方法生效。 + + + 检测到 WebView2 的版本较旧。正在下载最新版本。 + + + 尝试安装 WebView2 时发生错误。请手动安装WebView2。 + + + 缓存删除处理完成。 + + + 您即将前进到自动刷新工具中的规则禁止的单元格。 +你想刷新一下吗? + + + 应用浏览器字体失败。 + \ No newline at end of file diff --git a/Browser/WebView2Browser/AirControlSimulator/AirControlSimulatorResources.zh-CN.resx b/Browser/WebView2Browser/AirControlSimulator/AirControlSimulatorResources.zh-CN.resx index c55410ce5..266b35efe 100644 --- a/Browser/WebView2Browser/AirControlSimulator/AirControlSimulatorResources.zh-CN.resx +++ b/Browser/WebView2Browser/AirControlSimulator/AirControlSimulatorResources.zh-CN.resx @@ -1,144 +1,144 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 装备 - - - 舰队 - - - 锁定的舰娘 - - - 制空权模拟器 - - - 数据刷新 - - - 锁定的装备 - - - 所有装备 - - - 所有舰娘 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 装备 + + + 舰队 + + + 锁定的舰娘 + + + 制空权模拟器 + + + 数据刷新 + + + 锁定的装备 + + + 所有装备 + + + 所有舰娘 + \ No newline at end of file diff --git a/Browser/WebView2Browser/CompassPrediction/CompassPredictionResources.zh-CN.resx b/Browser/WebView2Browser/CompassPrediction/CompassPredictionResources.zh-CN.resx index a7517f10a..5f703d8b6 100644 --- a/Browser/WebView2Browser/CompassPrediction/CompassPredictionResources.zh-CN.resx +++ b/Browser/WebView2Browser/CompassPrediction/CompassPredictionResources.zh-CN.resx @@ -1,129 +1,129 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 数据刷新 - - - 同步出击海域 - - - 罗盘模拟器 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 数据刷新 + + + 同步出击海域 + + + 罗盘模拟器 + \ No newline at end of file diff --git a/ElectronicObserver.Core/Types/Data/IDDictionary.cs b/ElectronicObserver.Core/Types/Data/IDDictionary.cs index 6b0e58c59..00011a6c2 100644 --- a/ElectronicObserver.Core/Types/Data/IDDictionary.cs +++ b/ElectronicObserver.Core/Types/Data/IDDictionary.cs @@ -8,7 +8,7 @@ namespace ElectronicObserver.Core.Types.Data; /// IDを持つデータのリストを保持します。 /// /// -public class IDDictionary : IReadOnlyDictionary where TData : class?, IIdentifiable? +public class IDDictionary : IReadOnlyDictionary where TData : class, IIdentifiable { private readonly IDictionary dict; @@ -71,7 +71,9 @@ public bool TryGetValue(int key, out TData value) public IEnumerable Values => dict.Values; - public TData this[int key] => dict.ContainsKey(key) ? dict[key] : null; +#pragma warning disable CS8766 // Nullability of reference types in return type doesn't match implicitly implemented member (possibly because of nullability attributes). + public TData? this[int key] => dict.ContainsKey(key) ? dict[key] : null; +#pragma warning restore CS8766 // Nullability of reference types in return type doesn't match implicitly implemented member (possibly because of nullability attributes). public int Count => dict.Count; diff --git a/ElectronicObserver.Core/Types/Mocks/EquipmentDataMock.cs b/ElectronicObserver.Core/Types/Mocks/EquipmentDataMock.cs index b1defa936..9e4d24706 100644 --- a/ElectronicObserver.Core/Types/Mocks/EquipmentDataMock.cs +++ b/ElectronicObserver.Core/Types/Mocks/EquipmentDataMock.cs @@ -56,4 +56,6 @@ public void LoadFromResponse(string apiname, dynamic data) { throw new System.NotImplementedException(); } + + public override string ToString() => $"[{EquipmentID}] {Name}"; } diff --git a/ElectronicObserver.KancolleApi.Types/ApiReqMap/AirRaid/ApiReqMapAirRaidResponse.cs b/ElectronicObserver.KancolleApi.Types/ApiReqMap/AirRaid/ApiReqMapAirRaidResponse.cs new file mode 100644 index 000000000..61a778670 --- /dev/null +++ b/ElectronicObserver.KancolleApi.Types/ApiReqMap/AirRaid/ApiReqMapAirRaidResponse.cs @@ -0,0 +1,8 @@ +namespace ElectronicObserver.KancolleApi.Types.ApiReqMap.AirRaid; + +// todo: no idea if there's supposed to be more data here +public class ApiReqMapAirRaidResponse +{ + [JsonPropertyName("api_destruction_battle")] + public List ApiDestructionBattle { get; set; } = []; +} diff --git a/ElectronicObserver.KancolleApi.Types/ApiReqMap/AirRaid/HeavyBaseAirRaidWave.cs b/ElectronicObserver.KancolleApi.Types/ApiReqMap/AirRaid/HeavyBaseAirRaidWave.cs new file mode 100644 index 000000000..d4b3cfdbb --- /dev/null +++ b/ElectronicObserver.KancolleApi.Types/ApiReqMap/AirRaid/HeavyBaseAirRaidWave.cs @@ -0,0 +1,36 @@ +using ElectronicObserver.KancolleApi.Types.ApiReqMap.Models; + +namespace ElectronicObserver.KancolleApi.Types.ApiReqMap.AirRaid; + +public class HeavyBaseAirRaidWave +{ + [JsonPropertyName("api_formation")] + public List ApiFormation { get; set; } = []; + + [JsonPropertyName("api_ship_ke")] + public List ApiShipKe { get; set; } = []; + + [JsonPropertyName("api_ship_lv")] + public List ApiShipLv { get; set; } = []; + + [JsonPropertyName("api_e_nowhps")] + public List ApiENowhps { get; set; } = []; + + [JsonPropertyName("api_e_maxhps")] + public List ApiEMaxhps { get; set; } = []; + + [JsonPropertyName("api_eSlot")] + public List> ApiESlot { get; set; } = []; + + [JsonPropertyName("api_f_nowhps")] + public List ApiFNowhps { get; set; } = []; + + [JsonPropertyName("api_f_maxhps")] + public List ApiFMaxhps { get; set; } = []; + + [JsonPropertyName("api_air_base_attack")] + public ApiAirBaseRaid ApiAirBaseAttack { get; set; } = null!; + + [JsonPropertyName("api_lost_kind")] + public int ApiLostKind { get; set; } +} diff --git a/ElectronicObserver.KancolleApi.Types/Models/APIHougeki.cs b/ElectronicObserver.KancolleApi.Types/Models/APIHougeki.cs index 7a43e78d9..ae3b54343 100644 --- a/ElectronicObserver.KancolleApi.Types/Models/APIHougeki.cs +++ b/ElectronicObserver.KancolleApi.Types/Models/APIHougeki.cs @@ -5,7 +5,7 @@ namespace ElectronicObserver.KancolleApi.Types.Models; /// /// All values will be null when there's a no attack night battle. -/// eg. sub vs sub +/// e.g. sub vs sub /// public class ApiHougeki { diff --git a/ElectronicObserver/Common/ContentDialogs/ExportFilter/ExportFilterResources.zh-CN.resx b/ElectronicObserver/Common/ContentDialogs/ExportFilter/ExportFilterResources.zh-CN.resx index cca568a2c..88b1869b6 100644 --- a/ElectronicObserver/Common/ContentDialogs/ExportFilter/ExportFilterResources.zh-CN.resx +++ b/ElectronicObserver/Common/ContentDialogs/ExportFilter/ExportFilterResources.zh-CN.resx @@ -1,132 +1,132 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 导出过滤器 - - - 全部 - - - 忽略细胞过滤器 - - - 忽略失误 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 导出过滤器 + + + 全部 + + + 忽略细胞过滤器 + + + 忽略失误 + \ No newline at end of file diff --git a/ElectronicObserver/Common/ContentDialogs/ExportProgress/ExportProgressResources.zh-CN.resx b/ElectronicObserver/Common/ContentDialogs/ExportProgress/ExportProgressResources.zh-CN.resx index d866cdeda..d0b6f6014 100644 --- a/ElectronicObserver/Common/ContentDialogs/ExportProgress/ExportProgressResources.zh-CN.resx +++ b/ElectronicObserver/Common/ContentDialogs/ExportProgress/ExportProgressResources.zh-CN.resx @@ -1,126 +1,126 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 数据处理... - - - 取消 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 数据处理... + + + 取消 + \ No newline at end of file diff --git a/ElectronicObserver/Common/Datagrid/ColumnSelector.zh-CN.resx b/ElectronicObserver/Common/Datagrid/ColumnSelector.zh-CN.resx index e686e1462..522256df1 100644 --- a/ElectronicObserver/Common/Datagrid/ColumnSelector.zh-CN.resx +++ b/ElectronicObserver/Common/Datagrid/ColumnSelector.zh-CN.resx @@ -1,129 +1,129 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 列名称 - - - 选择列 - - - 显示 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 列名称 + + + 选择列 + + + 显示 + \ No newline at end of file diff --git a/ElectronicObserver/Common/Datagrid/DataGridResources.zh-CN.resx b/ElectronicObserver/Common/Datagrid/DataGridResources.zh-CN.resx index fc9c287cd..dc2749142 100644 --- a/ElectronicObserver/Common/Datagrid/DataGridResources.zh-CN.resx +++ b/ElectronicObserver/Common/Datagrid/DataGridResources.zh-CN.resx @@ -1,129 +1,129 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 重置排序 - - - 隐藏 - - - 打开列选择器 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 重置排序 + + + 隐藏 + + + 打开列选择器 + \ No newline at end of file diff --git a/ElectronicObserver/Data/Battle/BattleAirBattle.cs b/ElectronicObserver/Data/Battle/BattleAirBattle.cs deleted file mode 100644 index 889f90200..000000000 --- a/ElectronicObserver/Data/Battle/BattleAirBattle.cs +++ /dev/null @@ -1,53 +0,0 @@ -using System.Collections.Generic; -using ElectronicObserver.Data.Battle.Phase; - -namespace ElectronicObserver.Data.Battle; - -/// -/// 通常艦隊 vs 通常艦隊 航空戦 -/// -public class BattleAirBattle : BattleDay -{ - - public PhaseAirBattle AirBattle2 { get; protected set; } - - public override void LoadFromResponse(string apiname, dynamic data) - { - base.LoadFromResponse(apiname, (object)data); - - JetBaseAirAttack = new PhaseJetBaseAirAttack(this, "噴式基地航空隊攻撃"); - JetAirBattle = new PhaseJetAirBattle(this, "噴式航空戦"); - BaseAirAttack = new PhaseBaseAirAttack(this, "基地航空隊攻撃"); - FriendlySupportInfo = new PhaseFriendlySupportInfo(this, "友軍艦隊"); - FriendlyAirBattle = new PhaseFriendlyAirBattle(this, "友軍支援航空攻撃"); - AirBattle = new PhaseAirBattle(this, "第一次航空戦"); - Support = new PhaseSupport(this, "支援攻撃"); - AirBattle2 = new PhaseAirBattle(this, "第二次航空戦", "2"); - - foreach (var phase in GetPhases()) - phase.EmulateBattle(_resultHPs, _attackDamages); - - } - - public override string APIName => "api_req_sortie/airbattle"; - - public override string BattleName => ConstantsRes.Title_NormalFleetAirBattle; - - - - - public override IEnumerable GetPhases() - { - yield return Initial; - yield return Searching; - yield return JetBaseAirAttack; - yield return JetAirBattle; - yield return BaseAirAttack; - yield return FriendlySupportInfo; - yield return FriendlyAirBattle; - yield return AirBattle; - yield return Support; - yield return AirBattle2; - } - -} diff --git a/ElectronicObserver/Data/Battle/BattleAirRaid.cs b/ElectronicObserver/Data/Battle/BattleAirRaid.cs deleted file mode 100644 index b79927d1a..000000000 --- a/ElectronicObserver/Data/Battle/BattleAirRaid.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System.Collections.Generic; -using ElectronicObserver.Data.Battle.Phase; - -namespace ElectronicObserver.Data.Battle; - -/// -/// 通常艦隊 vs 通常艦隊 長距離空襲戦 -/// -public class BattleAirRaid : BattleDay -{ - - public override void LoadFromResponse(string apiname, dynamic data) - { - base.LoadFromResponse(apiname, (object)data); - - JetBaseAirAttack = new PhaseJetBaseAirAttack(this, "噴式基地航空隊攻撃"); - JetAirBattle = new PhaseJetAirBattle(this, "噴式航空戦"); - BaseAirAttack = new PhaseBaseAirAttack(this, "基地航空隊攻撃"); - AirBattle = new PhaseAirBattle(this, "空襲戦"); - // 支援は出ないものとする - - foreach (var phase in GetPhases()) - phase.EmulateBattle(_resultHPs, _attackDamages); - - } - - public override string APIName => "api_req_sortie/ld_airbattle"; - - public override string BattleName => ConstantsRes.Title_NormalFleetAirRaid; - - - public override IEnumerable GetPhases() - { - yield return Initial; - yield return Searching; - yield return JetBaseAirAttack; - yield return JetAirBattle; - yield return BaseAirAttack; - yield return AirBattle; - } -} diff --git a/ElectronicObserver/Data/Battle/BattleBaseAirRaid.cs b/ElectronicObserver/Data/Battle/BattleBaseAirRaid.cs deleted file mode 100644 index 16fdd816f..000000000 --- a/ElectronicObserver/Data/Battle/BattleBaseAirRaid.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System.Collections.Generic; -using ElectronicObserver.Data.Battle.Phase; - -namespace ElectronicObserver.Data.Battle; - -/// -/// 基地防空戦 -/// -public class BattleBaseAirRaid : BattleDay -{ - - public PhaseBaseAirRaid BaseAirRaid { get; protected set; } - - public override void LoadFromResponse(string apiname, dynamic data) - { - base.LoadFromResponse(apiname, (object)data); - - BaseAirRaid = new PhaseBaseAirRaid(this, "防空戦"); - - foreach (var phase in GetPhases()) - phase.EmulateBattle(_resultHPs, _attackDamages); - - } - - - public override string APIName => "api_req_map/next"; - - public override string BattleName => ConstantsRes.Title_BaseAirRaid; - - public override bool IsBaseAirRaid => true; - - public override IEnumerable GetPhases() - { - yield return Initial; - yield return Searching; - yield return BaseAirRaid; - } -} diff --git a/ElectronicObserver/Data/Battle/BattleCombinedAirBattle.cs b/ElectronicObserver/Data/Battle/BattleCombinedAirBattle.cs deleted file mode 100644 index ca2e7969b..000000000 --- a/ElectronicObserver/Data/Battle/BattleCombinedAirBattle.cs +++ /dev/null @@ -1,52 +0,0 @@ -using System.Collections.Generic; -using ElectronicObserver.Data.Battle.Phase; - -namespace ElectronicObserver.Data.Battle; - -/// -/// 連合艦隊 vs 通常艦隊 航空戦 -/// -public class BattleCombinedAirBattle : BattleDay -{ - - public PhaseAirBattle AirBattle2 { get; protected set; } - - public override void LoadFromResponse(string apiname, dynamic data) - { - base.LoadFromResponse(apiname, (object)data); - - JetBaseAirAttack = new PhaseJetBaseAirAttack(this, "噴式基地航空隊攻撃"); - JetAirBattle = new PhaseJetAirBattle(this, "噴式航空戦"); - BaseAirAttack = new PhaseBaseAirAttack(this, "基地航空隊攻撃"); - FriendlySupportInfo = new PhaseFriendlySupportInfo(this, "友軍艦隊"); - FriendlyAirBattle = new PhaseFriendlyAirBattle(this, "友軍支援航空攻撃"); - AirBattle = new PhaseAirBattle(this, "第一次航空戦"); - Support = new PhaseSupport(this, "支援攻撃"); - AirBattle2 = new PhaseAirBattle(this, "第二次航空戦", "2"); - - foreach (var phase in GetPhases()) - phase.EmulateBattle(_resultHPs, _attackDamages); - - } - - - public override string APIName => "api_req_combined_battle/airbattle"; - - public override string BattleName => ConstantsRes.Title_CombinedFleetAirBattle; - - - public override IEnumerable GetPhases() - { - yield return Initial; - yield return Searching; - yield return JetBaseAirAttack; - yield return JetAirBattle; - yield return BaseAirAttack; - yield return FriendlySupportInfo; - yield return FriendlyAirBattle; - yield return AirBattle; - yield return Support; - yield return AirBattle2; - } - -} diff --git a/ElectronicObserver/Data/Battle/BattleCombinedAirRaid.cs b/ElectronicObserver/Data/Battle/BattleCombinedAirRaid.cs deleted file mode 100644 index d99780ae1..000000000 --- a/ElectronicObserver/Data/Battle/BattleCombinedAirRaid.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System.Collections.Generic; -using ElectronicObserver.Data.Battle.Phase; - -namespace ElectronicObserver.Data.Battle; - -/// -/// 連合艦隊 vs 通常艦隊 長距離空襲戦 -/// -public class BattleCombinedAirRaid : BattleDay -{ - - public override void LoadFromResponse(string apiname, dynamic data) - { - base.LoadFromResponse(apiname, (object)data); - - JetBaseAirAttack = new PhaseJetBaseAirAttack(this, "噴式基地航空隊攻撃"); - JetAirBattle = new PhaseJetAirBattle(this, "噴式航空戦"); - BaseAirAttack = new PhaseBaseAirAttack(this, "基地航空隊攻撃"); - AirBattle = new PhaseAirBattle(this, "空襲戦"); - // 支援はないものとする - - foreach (var phase in GetPhases()) - phase.EmulateBattle(_resultHPs, _attackDamages); - - } - - - public override string APIName => "api_req_combined_battle/ld_airbattle"; - - public override string BattleName => ConstantsRes.Title_CombinedFleetAirRaid; - - - public override IEnumerable GetPhases() - { - yield return Initial; - yield return Searching; - yield return JetBaseAirAttack; - yield return JetAirBattle; - yield return BaseAirAttack; - yield return AirBattle; - } - -} diff --git a/ElectronicObserver/Data/Battle/BattleCombinedEachDay.cs b/ElectronicObserver/Data/Battle/BattleCombinedEachDay.cs deleted file mode 100644 index 328b89731..000000000 --- a/ElectronicObserver/Data/Battle/BattleCombinedEachDay.cs +++ /dev/null @@ -1,61 +0,0 @@ -using System.Collections.Generic; -using ElectronicObserver.Data.Battle.Phase; - -namespace ElectronicObserver.Data.Battle; - -/// -/// 機動部隊 vs 連合艦隊 昼戦 -/// -public class BattleCombinedEachDay : BattleDay -{ - - public override void LoadFromResponse(string apiname, dynamic data) - { - base.LoadFromResponse(apiname, (object)data); - - JetBaseAirAttack = new PhaseJetBaseAirAttack(this, "噴式基地航空隊攻撃"); - JetAirBattle = new PhaseJetAirBattle(this, "噴式航空戦"); - BaseAirAttack = new PhaseBaseAirAttack(this, "基地航空隊攻撃"); - FriendlySupportInfo = new PhaseFriendlySupportInfo(this, "友軍艦隊"); - FriendlyAirBattle = new PhaseFriendlyAirBattle(this, "友軍支援航空攻撃"); - AirBattle = new PhaseAirBattle(this, "航空戦"); - Support = new PhaseSupport(this, "支援攻撃"); - OpeningASW = new PhaseOpeningASW(this, "先制対潜"); - OpeningTorpedo = new PhaseTorpedo(this, "先制雷撃", 0); - Shelling1 = new PhaseShelling(this, "第一次砲撃戦", 1, "1"); - Shelling2 = new PhaseShelling(this, "第二次砲撃戦", 2, "2"); - Torpedo = new PhaseTorpedo(this, "雷撃戦", 3); - Shelling3 = new PhaseShelling(this, "第三次砲撃戦", 4, "3"); - - - foreach (var phase in GetPhases()) - phase.EmulateBattle(_resultHPs, _attackDamages); - - } - - - public override string APIName => "api_req_combined_battle/each_battle"; - - public override string BattleName => ConstantsRes.Title_CombinedEachDay; - - - public override IEnumerable GetPhases() - { - yield return Initial; - yield return Searching; - yield return JetBaseAirAttack; - yield return JetAirBattle; - yield return BaseAirAttack; - yield return FriendlySupportInfo; - yield return FriendlyAirBattle; - yield return AirBattle; - yield return Support; - yield return OpeningASW; - yield return OpeningTorpedo; - yield return Shelling1; - yield return Shelling2; - yield return Torpedo; - yield return Shelling3; - } - -} diff --git a/ElectronicObserver/Data/Battle/BattleCombinedEachWater.cs b/ElectronicObserver/Data/Battle/BattleCombinedEachWater.cs deleted file mode 100644 index c73a0768d..000000000 --- a/ElectronicObserver/Data/Battle/BattleCombinedEachWater.cs +++ /dev/null @@ -1,61 +0,0 @@ -using System.Collections.Generic; -using ElectronicObserver.Data.Battle.Phase; - -namespace ElectronicObserver.Data.Battle; - -/// -/// 水上部隊 vs 連合艦隊 昼戦 -/// -public class BattleCombinedEachWater : BattleDay -{ - - public override void LoadFromResponse(string apiname, dynamic data) - { - base.LoadFromResponse(apiname, (object)data); - - JetBaseAirAttack = new PhaseJetBaseAirAttack(this, "噴式基地航空隊攻撃"); - JetAirBattle = new PhaseJetAirBattle(this, "噴式航空戦"); - BaseAirAttack = new PhaseBaseAirAttack(this, "基地航空隊攻撃"); - FriendlySupportInfo = new PhaseFriendlySupportInfo(this, "友軍艦隊"); - FriendlyAirBattle = new PhaseFriendlyAirBattle(this, "友軍支援航空攻撃"); - AirBattle = new PhaseAirBattle(this, "航空戦"); - Support = new PhaseSupport(this, "支援攻撃"); - OpeningASW = new PhaseOpeningASW(this, "先制対潜"); - OpeningTorpedo = new PhaseTorpedo(this, "先制雷撃", 0); - Shelling1 = new PhaseShelling(this, "第一次砲撃戦", 1, "1"); - Shelling2 = new PhaseShelling(this, "第二次砲撃戦", 2, "2"); - Shelling3 = new PhaseShelling(this, "第三次砲撃戦", 3, "3"); - Torpedo = new PhaseTorpedo(this, "雷撃戦", 4); - - foreach (var phase in GetPhases()) - phase.EmulateBattle(_resultHPs, _attackDamages); - - } - - - public override string APIName => "api_req_combined_battle/each_battle_water"; - - public override string BattleName => ConstantsRes.Title_CombinedEachWater; - - - - public override IEnumerable GetPhases() - { - yield return Initial; - yield return Searching; - yield return JetBaseAirAttack; - yield return JetAirBattle; - yield return BaseAirAttack; - yield return FriendlySupportInfo; - yield return FriendlyAirBattle; - yield return AirBattle; - yield return Support; - yield return OpeningASW; - yield return OpeningTorpedo; - yield return Shelling1; - yield return Shelling2; - yield return Shelling3; - yield return Torpedo; - } - -} diff --git a/ElectronicObserver/Data/Battle/BattleCombinedNightOnly.cs b/ElectronicObserver/Data/Battle/BattleCombinedNightOnly.cs deleted file mode 100644 index 1c41aa73c..000000000 --- a/ElectronicObserver/Data/Battle/BattleCombinedNightOnly.cs +++ /dev/null @@ -1,44 +0,0 @@ -using System.Collections.Generic; -using ElectronicObserver.Data.Battle.Phase; - -namespace ElectronicObserver.Data.Battle; - -/// -/// 連合艦隊 vs 通常艦隊 開幕夜戦 -/// -public class BattleCombinedNightOnly : BattleNight -{ - - public override void LoadFromResponse(string apiname, dynamic data) - { - base.LoadFromResponse(apiname, (object)data); - - NightInitial = new PhaseNightInitial(this, "夜戦開始", true); - FriendlySupportInfo = new PhaseFriendlySupportInfo(this, "友軍艦隊"); - FriendlyShelling = new PhaseFriendlyShelling(this, "友軍艦隊援護"); - Support = new PhaseSupport(this, "夜間支援攻撃", true); - NightBattle = new PhaseNightBattle(this, "夜戦", 0); - - - foreach (var phase in GetPhases()) - phase.EmulateBattle(_resultHPs, _attackDamages); - } - - - - public override string APIName => "api_req_combined_battle/sp_midnight"; - - public override string BattleName => ConstantsRes.Title_CombinedNightOnly; - - - public override IEnumerable GetPhases() - { - yield return Initial; - yield return Searching; - yield return NightInitial; - yield return FriendlySupportInfo; - yield return FriendlyShelling; - yield return Support; - yield return NightBattle; - } -} diff --git a/ElectronicObserver/Data/Battle/BattleCombinedNormalDay.cs b/ElectronicObserver/Data/Battle/BattleCombinedNormalDay.cs deleted file mode 100644 index 18e43da3d..000000000 --- a/ElectronicObserver/Data/Battle/BattleCombinedNormalDay.cs +++ /dev/null @@ -1,61 +0,0 @@ -using System.Collections.Generic; -using ElectronicObserver.Data.Battle.Phase; - -namespace ElectronicObserver.Data.Battle; - -/// -/// 機動部隊 vs 通常艦隊 昼戦 -/// -public class BattleCombinedNormalDay : BattleDay -{ - - public override void LoadFromResponse(string apiname, dynamic data) - { - base.LoadFromResponse(apiname, (object)data); - - JetBaseAirAttack = new PhaseJetBaseAirAttack(this, "噴式基地航空隊攻撃"); - JetAirBattle = new PhaseJetAirBattle(this, "噴式航空戦"); - BaseAirAttack = new PhaseBaseAirAttack(this, "基地航空隊攻撃"); - FriendlySupportInfo = new PhaseFriendlySupportInfo(this, "友軍艦隊"); - FriendlyAirBattle = new PhaseFriendlyAirBattle(this, "友軍支援航空攻撃"); - AirBattle = new PhaseAirBattle(this, "航空戦"); - Support = new PhaseSupport(this, "支援攻撃"); - OpeningASW = new PhaseOpeningASW(this, "先制対潜"); - OpeningTorpedo = new PhaseTorpedo(this, "先制雷撃", 0); - Shelling1 = new PhaseShelling(this, "第一次砲撃戦", 1, "1"); - Torpedo = new PhaseTorpedo(this, "雷撃戦", 2); - Shelling2 = new PhaseShelling(this, "第二次砲撃戦", 3, "2"); - Shelling3 = new PhaseShelling(this, "第三次砲撃戦", 4, "3"); - - foreach (var phase in GetPhases()) - phase.EmulateBattle(_resultHPs, _attackDamages); - - } - - - public override string APIName => "api_req_combined_battle/battle"; - - public override string BattleName => ConstantsRes.Title_CombinedNormalDay; - - - - public override IEnumerable GetPhases() - { - yield return Initial; - yield return Searching; - yield return JetBaseAirAttack; - yield return JetAirBattle; - yield return BaseAirAttack; - yield return FriendlySupportInfo; - yield return FriendlyAirBattle; - yield return AirBattle; - yield return Support; - yield return OpeningASW; - yield return OpeningTorpedo; - yield return Shelling1; - yield return Torpedo; - yield return Shelling2; - yield return Shelling3; - } - -} diff --git a/ElectronicObserver/Data/Battle/BattleCombinedNormalNight.cs b/ElectronicObserver/Data/Battle/BattleCombinedNormalNight.cs deleted file mode 100644 index 012745588..000000000 --- a/ElectronicObserver/Data/Battle/BattleCombinedNormalNight.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System.Collections.Generic; -using ElectronicObserver.Data.Battle.Phase; - -namespace ElectronicObserver.Data.Battle; - -/// -/// 連合艦隊 vs 通常艦隊 夜戦 -/// -public class BattleCombinedNormalNight : BattleNight -{ - - public override void LoadFromResponse(string apiname, dynamic data) - { - base.LoadFromResponse(apiname, (object)data); - - NightInitial = new PhaseNightInitial(this, "夜戦開始", true); - FriendlySupportInfo = new PhaseFriendlySupportInfo(this, "友軍艦隊"); - FriendlyShelling = new PhaseFriendlyShelling(this, "友軍艦隊援護"); - // 支援なし? - NightBattle = new PhaseNightBattle(this, "夜戦", 0); - - - foreach (var phase in GetPhases()) - phase.EmulateBattle(_resultHPs, _attackDamages); - } - - - public override string APIName => "api_req_combined_battle/midnight_battle"; - - public override string BattleName => BattleRes.CombinedFleetNightBattle; - - - public override IEnumerable GetPhases() - { - yield return Initial; - yield return NightInitial; - yield return FriendlySupportInfo; - yield return FriendlyShelling; - yield return NightBattle; - } -} diff --git a/ElectronicObserver/Data/Battle/BattleCombinedRadar.cs b/ElectronicObserver/Data/Battle/BattleCombinedRadar.cs deleted file mode 100644 index a2c12bc00..000000000 --- a/ElectronicObserver/Data/Battle/BattleCombinedRadar.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.Collections.Generic; -using ElectronicObserver.Data.Battle.Phase; - -namespace ElectronicObserver.Data.Battle; - -/// -/// 連合艦隊 vs 通常艦隊 レーダー射撃 -/// -public class BattleCombinedRadar : BattleDay -{ - public override void LoadFromResponse(string apiname, dynamic data) - { - base.LoadFromResponse(apiname, (object)data); - - JetBaseAirAttack = new PhaseJetBaseAirAttack(this, "噴式基地航空隊攻撃"); - BaseAirAttack = new PhaseBaseAirAttack(this, "基地航空隊攻撃"); - Shelling1 = new PhaseRadar(this, "レーダー射撃"); - - foreach (var phase in GetPhases()) - phase.EmulateBattle(_resultHPs, _attackDamages); - } - - public override string APIName => "api_req_combined_battle/ld_shooting"; - - public override string BattleName => BattleRes.CombinedFleetRadarAmbush; - - public override IEnumerable GetPhases() - { - yield return Initial; - yield return Searching; // ? - yield return JetBaseAirAttack; - yield return BaseAirAttack; - yield return Shelling1; - } -} diff --git a/ElectronicObserver/Data/Battle/BattleCombinedWater.cs b/ElectronicObserver/Data/Battle/BattleCombinedWater.cs deleted file mode 100644 index 3be5efcfd..000000000 --- a/ElectronicObserver/Data/Battle/BattleCombinedWater.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System.Collections.Generic; -using ElectronicObserver.Data.Battle.Phase; - -namespace ElectronicObserver.Data.Battle; - -/// -/// 水上部隊 vs 通常艦隊 昼戦 -/// -public class BattleCombinedWater : BattleDay -{ - - public override void LoadFromResponse(string apiname, dynamic data) - { - base.LoadFromResponse(apiname, (object)data); - - JetBaseAirAttack = new PhaseJetBaseAirAttack(this, "噴式基地航空隊攻撃"); - JetAirBattle = new PhaseJetAirBattle(this, "噴式航空戦"); - BaseAirAttack = new PhaseBaseAirAttack(this, "基地航空隊攻撃"); - FriendlySupportInfo = new PhaseFriendlySupportInfo(this, "友軍艦隊"); - FriendlyAirBattle = new PhaseFriendlyAirBattle(this, "友軍支援航空攻撃"); - AirBattle = new PhaseAirBattle(this, "航空戦"); - Support = new PhaseSupport(this, "支援攻撃"); - OpeningASW = new PhaseOpeningASW(this, "先制対潜"); - OpeningTorpedo = new PhaseTorpedo(this, "先制雷撃", 0); - Shelling1 = new PhaseShelling(this, "第一次砲撃戦", 1, "1"); - Shelling2 = new PhaseShelling(this, "第二次砲撃戦", 2, "2"); - Shelling3 = new PhaseShelling(this, "第三次砲撃戦", 3, "3"); - Torpedo = new PhaseTorpedo(this, "雷撃戦", 4); - - foreach (var phase in GetPhases()) - phase.EmulateBattle(_resultHPs, _attackDamages); - - } - - - public override string APIName => "api_req_combined_battle/battle_water"; - - public override string BattleName => BattleRes.SuijouButaiDayBattle; - - - public override IEnumerable GetPhases() - { - yield return Initial; - yield return Searching; - yield return JetBaseAirAttack; - yield return JetAirBattle; - yield return BaseAirAttack; - yield return FriendlySupportInfo; - yield return FriendlyAirBattle; - yield return AirBattle; - yield return Support; - yield return OpeningASW; - yield return OpeningTorpedo; - yield return Shelling1; - yield return Shelling2; - yield return Shelling3; - yield return Torpedo; - } -} diff --git a/ElectronicObserver/Data/Battle/BattleData.cs b/ElectronicObserver/Data/Battle/BattleData.cs deleted file mode 100644 index 8e5254653..000000000 --- a/ElectronicObserver/Data/Battle/BattleData.cs +++ /dev/null @@ -1,167 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; -using System.Text; -using ElectronicObserver.Data.Battle.Phase; - -namespace ElectronicObserver.Data.Battle; - -/// -/// 戦闘情報を保持するデータの基底です。 -/// -public abstract class BattleData : ResponseWrapper -{ - - protected int[] _resultHPs; - /// - /// 戦闘終了時の各艦のHP - /// - public ReadOnlyCollection ResultHPs => Array.AsReadOnly(_resultHPs); - - protected int[] _attackDamages; - /// - /// 各艦の与ダメージ - /// - public ReadOnlyCollection AttackDamages => Array.AsReadOnly(_attackDamages); - - - public PhaseInitial Initial { get; protected set; } - public PhaseSearching Searching { get; protected set; } - public PhaseFriendlySupportInfo FriendlySupportInfo { get; protected set; } - public PhaseSupport Support { get; protected set; } - - - public override void LoadFromResponse(string apiname, dynamic data) - { - base.LoadFromResponse(apiname, (object)data); - - Initial = new PhaseInitial(this, BattleRes.Participant); - Searching = new PhaseSearching(this, BattleRes.PhaseSearching); - - _resultHPs = new int[24]; - Array.Copy(Initial.FriendInitialHPs, 0, _resultHPs, 0, Initial.FriendInitialHPs.Length); - Array.Copy(Initial.EnemyInitialHPs, 0, _resultHPs, 12, Initial.EnemyInitialHPs.Length); - if (Initial.FriendInitialHPsEscort != null) - Array.Copy(Initial.FriendInitialHPsEscort, 0, _resultHPs, 6, 6); - if (Initial.EnemyInitialHPsEscort != null) - Array.Copy(Initial.EnemyInitialHPsEscort, 0, _resultHPs, 18, 6); - - - - if (_attackDamages == null) - _attackDamages = new int[_resultHPs.Length]; - } - - - /// - /// MVP 取得候補艦のインデックス [0-6] - /// - public IEnumerable MVPShipIndexes - { - get - { - int memberCount = Initial.FriendFleet.Members.Count; - int max = _attackDamages.Take(memberCount).Max(); - if (max == 0) - { // 全員ノーダメージなら旗艦MVP - yield return 0; - - } - else - { - for (int i = 0; i < memberCount; i++) - { - if (_attackDamages[i] == max) - yield return i; - } - } - } - } - - - /// - /// 連合艦隊随伴艦隊の MVP 取得候補艦のインデックス [0-5] - /// - public IEnumerable MVPShipCombinedIndexes - { - get - { - int max = _attackDamages.Skip(6).Take(6).Max(); - if (max == 0) - { // 全員ノーダメージなら旗艦MVP - yield return 0; - - } - else - { - for (int i = 0; i < 6; i++) - { - if (_attackDamages[i + 6] == max) - yield return i; - } - } - } - } - - - /// - /// 前回の戦闘データからパラメータを引き継ぎます。 - /// - internal void TakeOverParameters(BattleData prev) - { - _attackDamages = (int[])prev._attackDamages.Clone(); - } - - - - /// - /// 対応しているAPIの名前を取得します。 - /// - public abstract string APIName { get; } - - /// - /// 戦闘形態の名称 - /// - public abstract string BattleName { get; } - - - public virtual bool IsPractice => false; - public virtual bool IsFriendCombined => Initial.IsFriendCombined; - public virtual bool IsEnemyCombined => Initial.IsEnemyCombined; - public virtual bool IsBaseAirRaid => false; - - - - /// - /// すべての戦闘詳細データを取得します。 - /// - public string GetBattleDetail() - { - return GetBattleDetail(-1); - } - - /// - /// 指定したインデックスの艦の戦闘詳細データを取得します。 - /// - /// インデックス。[0-23] - public string GetBattleDetail(int index) - { - var sb = new StringBuilder(); - - foreach (var phase in GetPhases()) - { - string bd = phase.GetBattleDetail(index); - - if (!string.IsNullOrEmpty(bd)) - { - sb.AppendLine("== " + phase.Title + " ==").Append(bd); - } - } - return sb.ToString(); - } - - - public abstract IEnumerable GetPhases(); - -} diff --git a/ElectronicObserver/Data/Battle/BattleDay.cs b/ElectronicObserver/Data/Battle/BattleDay.cs deleted file mode 100644 index c0704ea80..000000000 --- a/ElectronicObserver/Data/Battle/BattleDay.cs +++ /dev/null @@ -1,23 +0,0 @@ -using ElectronicObserver.Data.Battle.Phase; - -namespace ElectronicObserver.Data.Battle; - -/// -/// 昼戦の基底クラス -/// -public abstract class BattleDay : BattleData -{ - - public PhaseJetBaseAirAttack JetBaseAirAttack { get; protected set; } - public PhaseJetAirBattle JetAirBattle { get; protected set; } - public PhaseBaseAirAttack BaseAirAttack { get; protected set; } - public PhaseFriendlyAirBattle FriendlyAirBattle { get; protected set; } - public PhaseAirBattle AirBattle { get; protected set; } - public PhaseOpeningASW OpeningASW { get; protected set; } - public PhaseTorpedo OpeningTorpedo { get; protected set; } - public PhaseShelling Shelling1 { get; protected set; } - public PhaseShelling Shelling2 { get; protected set; } - public PhaseShelling Shelling3 { get; protected set; } - public PhaseTorpedo Torpedo { get; protected set; } - -} diff --git a/ElectronicObserver/Data/Battle/BattleDayFromNight.cs b/ElectronicObserver/Data/Battle/BattleDayFromNight.cs deleted file mode 100644 index 0092a751d..000000000 --- a/ElectronicObserver/Data/Battle/BattleDayFromNight.cs +++ /dev/null @@ -1,26 +0,0 @@ -using ElectronicObserver.Data.Battle.Phase; - -namespace ElectronicObserver.Data.Battle; - -/// -/// 夜昼戦 -/// -public abstract class BattleDayFromNight : BattleNight -{ - - public PhaseSupport NightSupport { get; protected set; } - public PhaseNightBattle NightBattle2 { get; protected set; } - - public bool NextToDay => (int)RawData.api_day_flag != 0; - - public PhaseJetBaseAirAttack JetBaseAirAttack { get; protected set; } - public PhaseJetAirBattle JetAirBattle { get; protected set; } - public PhaseBaseAirAttack BaseAirAttack { get; protected set; } - public PhaseAirBattle AirBattle { get; protected set; } - public PhaseOpeningASW OpeningASW { get; protected set; } - public PhaseTorpedo OpeningTorpedo { get; protected set; } - public PhaseShelling Shelling1 { get; protected set; } - public PhaseShelling Shelling2 { get; protected set; } - public PhaseTorpedo Torpedo { get; protected set; } - -} diff --git a/ElectronicObserver/Data/Battle/BattleEnemyCombinedDay.cs b/ElectronicObserver/Data/Battle/BattleEnemyCombinedDay.cs deleted file mode 100644 index d4fb52d85..000000000 --- a/ElectronicObserver/Data/Battle/BattleEnemyCombinedDay.cs +++ /dev/null @@ -1,60 +0,0 @@ -using System.Collections.Generic; -using ElectronicObserver.Data.Battle.Phase; - -namespace ElectronicObserver.Data.Battle; - -/// -/// 通常艦隊 vs 連合艦隊 昼戦 -/// -public class BattleEnemyCombinedDay : BattleDay -{ - - public override void LoadFromResponse(string apiname, dynamic data) - { - base.LoadFromResponse(apiname, (object)data); - - JetBaseAirAttack = new PhaseJetBaseAirAttack(this, "噴式基地航空隊攻撃"); - JetAirBattle = new PhaseJetAirBattle(this, "噴式航空戦"); - BaseAirAttack = new PhaseBaseAirAttack(this, "基地航空隊攻撃"); - FriendlySupportInfo = new PhaseFriendlySupportInfo(this, "友軍艦隊"); - FriendlyAirBattle = new PhaseFriendlyAirBattle(this, "友軍支援航空攻撃"); - AirBattle = new PhaseAirBattle(this, "航空戦"); - Support = new PhaseSupport(this, "支援攻撃"); - OpeningASW = new PhaseOpeningASW(this, "先制対潜"); - OpeningTorpedo = new PhaseTorpedo(this, "先制雷撃", 0); - Shelling1 = new PhaseShelling(this, "第一次砲撃戦", 1, "1"); - Torpedo = new PhaseTorpedo(this, "雷撃戦", 2); - Shelling2 = new PhaseShelling(this, "第二次砲撃戦", 3, "2"); - Shelling3 = new PhaseShelling(this, "第三次砲撃戦", 4, "3"); - - foreach (var phase in GetPhases()) - phase.EmulateBattle(_resultHPs, _attackDamages); - - } - - - public override string APIName => "api_req_combined_battle/ec_battle"; - - public override string BattleName => ConstantsRes.Title_EnemyCombinedDay; - - - - public override IEnumerable GetPhases() - { - yield return Initial; - yield return Searching; - yield return JetBaseAirAttack; - yield return JetAirBattle; - yield return BaseAirAttack; - yield return FriendlySupportInfo; - yield return FriendlyAirBattle; - yield return AirBattle; - yield return Support; - yield return OpeningASW; - yield return OpeningTorpedo; - yield return Shelling1; - yield return Torpedo; - yield return Shelling2; - yield return Shelling3; - } -} diff --git a/ElectronicObserver/Data/Battle/BattleEnemyCombinedDayFromNight.cs b/ElectronicObserver/Data/Battle/BattleEnemyCombinedDayFromNight.cs deleted file mode 100644 index f01fa02b7..000000000 --- a/ElectronicObserver/Data/Battle/BattleEnemyCombinedDayFromNight.cs +++ /dev/null @@ -1,74 +0,0 @@ -using System.Collections.Generic; -using ElectronicObserver.Data.Battle.Phase; - -namespace ElectronicObserver.Data.Battle; - -/// -/// 通常/連合艦隊 vs 連合艦隊 夜昼戦 -/// -public class BattleEnemyCombinedDayFromNight : BattleDayFromNight -{ - - public override void LoadFromResponse(string apiname, dynamic data) - { - base.LoadFromResponse(apiname, (object)data); - - NightInitial = new PhaseNightInitial(this, "夜戦開始", false); - FriendlySupportInfo = new PhaseFriendlySupportInfo(this, "友軍艦隊"); - FriendlyShelling = new PhaseFriendlyShelling(this, "友軍艦隊援護"); - NightSupport = new PhaseSupport(this, "夜間支援攻撃", true); - NightBattle = new PhaseNightBattle(this, "第一次夜戦", 1); - NightBattle2 = new PhaseNightBattle(this, "第二次夜戦", 2); - - - if (NextToDay) - { - JetBaseAirAttack = new PhaseJetBaseAirAttack(this, "噴式基地航空隊攻撃"); - JetAirBattle = new PhaseJetAirBattle(this, "噴式航空戦"); - BaseAirAttack = new PhaseBaseAirAttack(this, "基地航空隊攻撃"); - Support = new PhaseSupport(this, "支援攻撃"); - // ここに友軍艦隊航空攻撃が入るかわからない - AirBattle = new PhaseAirBattle(this, "航空戦"); - OpeningASW = new PhaseOpeningASW(this, "先制対潜"); - OpeningTorpedo = new PhaseTorpedo(this, "先制雷撃", 0); - Shelling1 = new PhaseShelling(this, "第一次砲撃戦", 1, "1"); - Shelling2 = new PhaseShelling(this, "第二次砲撃戦", 2, "2"); - Torpedo = new PhaseTorpedo(this, "雷撃戦", 3); - } - - foreach (var phase in GetPhases()) - phase.EmulateBattle(_resultHPs, _attackDamages); - } - - public override string APIName => "api_req_combined_battle/ec_night_to_day"; - - public override string BattleName => BattleRes.EnemyCombinedFleetNightDayBattle; - - - - public override IEnumerable GetPhases() - { - yield return Initial; - yield return Searching; - yield return NightInitial; - yield return FriendlySupportInfo; - yield return FriendlyShelling; - yield return NightSupport; - yield return NightBattle; - yield return NightBattle2; - - if (NextToDay) - { - yield return JetBaseAirAttack; - yield return JetAirBattle; - yield return BaseAirAttack; - yield return Support; - yield return AirBattle; - yield return OpeningASW; - yield return OpeningTorpedo; - yield return Shelling1; - yield return Shelling2; - yield return Torpedo; - } - } -} diff --git a/ElectronicObserver/Data/Battle/BattleEnemyCombinedNight.cs b/ElectronicObserver/Data/Battle/BattleEnemyCombinedNight.cs deleted file mode 100644 index 743b2a80e..000000000 --- a/ElectronicObserver/Data/Battle/BattleEnemyCombinedNight.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System.Collections.Generic; -using ElectronicObserver.Data.Battle.Phase; - -namespace ElectronicObserver.Data.Battle; - -/// -/// 通常/連合艦隊 vs 連合艦隊 夜戦 -/// -public class BattleEnemyCombinedNight : BattleNight -{ - - public override void LoadFromResponse(string apiname, dynamic data) - { - base.LoadFromResponse(apiname, (object)data); - - NightInitial = new PhaseNightInitial(this, "夜戦開始", false); - FriendlySupportInfo = new PhaseFriendlySupportInfo(this, "友軍艦隊"); - FriendlyShelling = new PhaseFriendlyShelling(this, "友軍艦隊援護"); - // 支援なし? - NightBattle = new PhaseNightBattle(this, "夜戦", 0); - - - foreach (var phase in GetPhases()) - phase.EmulateBattle(_resultHPs, _attackDamages); - } - - - public override string APIName => "api_req_combined_battle/ec_midnight_battle"; - - public override string BattleName => ConstantsRes.Title_EnemyCombinedNight; - - - - public override IEnumerable GetPhases() - { - yield return Initial; - yield return NightInitial; - yield return FriendlySupportInfo; - yield return FriendlyShelling; - yield return NightBattle; - } -} diff --git a/ElectronicObserver/Data/Battle/BattleManager.cs b/ElectronicObserver/Data/Battle/BattleManager.cs index 4f4f6a864..7e12bbda1 100644 --- a/ElectronicObserver/Data/Battle/BattleManager.cs +++ b/ElectronicObserver/Data/Battle/BattleManager.cs @@ -1,14 +1,47 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Linq; +using System.Text.Json; +using CommunityToolkit.Mvvm.DependencyInjection; using ElectronicObserver.Core.Types; +using ElectronicObserver.Core.Types.Attacks; using ElectronicObserver.Core.Types.Extensions; -using ElectronicObserver.Data.Battle.Detail; -using ElectronicObserver.Data.Battle.Phase; +using ElectronicObserver.KancolleApi.Types.ApiReqBattleMidnight.Battle; +using ElectronicObserver.KancolleApi.Types.ApiReqBattleMidnight.SpMidnight; +using ElectronicObserver.KancolleApi.Types.ApiReqCombinedBattle.Airbattle; +using ElectronicObserver.KancolleApi.Types.ApiReqCombinedBattle.Battle; +using ElectronicObserver.KancolleApi.Types.ApiReqCombinedBattle.Battleresult; +using ElectronicObserver.KancolleApi.Types.ApiReqCombinedBattle.BattleWater; +using ElectronicObserver.KancolleApi.Types.ApiReqCombinedBattle.EachBattle; +using ElectronicObserver.KancolleApi.Types.ApiReqCombinedBattle.EachBattleWater; +using ElectronicObserver.KancolleApi.Types.ApiReqCombinedBattle.EcBattle; +using ElectronicObserver.KancolleApi.Types.ApiReqCombinedBattle.EcMidnightBattle; +using ElectronicObserver.KancolleApi.Types.ApiReqCombinedBattle.EcNightToDay; +using ElectronicObserver.KancolleApi.Types.ApiReqCombinedBattle.LdAirbattle; +using ElectronicObserver.KancolleApi.Types.ApiReqCombinedBattle.LdShooting; +using ElectronicObserver.KancolleApi.Types.ApiReqCombinedBattle.MidnightBattle; +using ElectronicObserver.KancolleApi.Types.ApiReqCombinedBattle.SpMidnight; +using ElectronicObserver.KancolleApi.Types.ApiReqMap.Next; +using ElectronicObserver.KancolleApi.Types.ApiReqMap.Start; +using ElectronicObserver.KancolleApi.Types.ApiReqPractice.Battle; +using ElectronicObserver.KancolleApi.Types.ApiReqPractice.BattleResult; +using ElectronicObserver.KancolleApi.Types.ApiReqPractice.MidnightBattle; +using ElectronicObserver.KancolleApi.Types.ApiReqSortie.Airbattle; +using ElectronicObserver.KancolleApi.Types.ApiReqSortie.Battle; +using ElectronicObserver.KancolleApi.Types.ApiReqSortie.Battleresult; +using ElectronicObserver.KancolleApi.Types.ApiReqSortie.LdAirbattle; +using ElectronicObserver.KancolleApi.Types.ApiReqSortie.LdShooting; +using ElectronicObserver.KancolleApi.Types.ApiReqSortie.NightToDay; +using ElectronicObserver.KancolleApi.Types.Interfaces; using ElectronicObserver.Resource.Record; using ElectronicObserver.Utility.Mathematics; +using ElectronicObserver.Window.Dialog.BattleDetail; using ElectronicObserver.Window.Dialog.QuestTrackerManager.Enums; +using ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle; +using ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle.Phase; +using ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Node; namespace ElectronicObserver.Data.Battle; @@ -17,153 +50,94 @@ namespace ElectronicObserver.Data.Battle; /// public class BattleManager : APIWrapper { - - public static readonly string BattleLogPath = "BattleLog"; - - public delegate void ShipLevelUpHandler(IShipData ship, int nextLevel); + public static string BattleLogPath => "BattleLog"; /// /// Ship will have the level before level up /// /// /// - public event ShipLevelUpHandler ShipLevelUp; + public delegate void ShipLevelUpHandler(IShipData ship, int nextLevel); + + public event ShipLevelUpHandler? ShipLevelUp; /// /// 羅針盤データ /// - public CompassData Compass { get; private set; } + public CompassData? Compass { get; private set; } /// /// 昼戦データ /// - public BattleDay BattleDay { get; private set; } + public FirstBattleData? FirstBattle { get; private set; } /// /// 夜戦データ /// - public BattleNight BattleNight { get; private set; } + public BattleData? SecondBattle { get; private set; } /// /// 戦闘結果データ /// - public BattleResultData Result { get; private set; } + public BattleResult? Result { get; private set; } /// /// The battle result api doesn't report SS, so we need to evaluate it manually. /// - public string PredictedBattleRank { get; set; } + public string? PredictedBattleRank { get; set; } // In the api, heavy base air raid is implemented as 3 different air raid battles // If we decide to collapse it down into 1 battle, this should be deleted // and heavy base air raid moved to BattleDay like regular BattleBaseAirRaid - public List HeavyBaseAirRaids { get; } = new(); - - [Flags] - public enum BattleModes - { - Undefined, // 未定義 - Normal, // 昼夜戦(通常戦闘) - NightOnly, // 夜戦 - NightDay, // 夜昼戦 - AirBattle, // 航空戦 - AirRaid, // 長距離空襲戦 - Radar, // レーダー射撃 - Practice, // 演習 - BaseAirRaid, // 基地空襲戦 - BattlePhaseMask = 0xFF, // 戦闘形態マスク - CombinedTaskForce = 0x100, // 機動部隊 - CombinedSurface = 0x200, // 水上部隊 - CombinedMask = 0xFF00, // 連合艦隊仕様 - EnemyCombinedFleet = 0x10000, // 敵連合艦隊 - } - - /// - /// 戦闘種別 - /// - public BattleModes BattleMode { get; private set; } - - - /// - /// 昼戦から開始する戦闘かどうか - /// - public bool StartsFromDayBattle => !StartsFromNightBattle; - - /// - /// 夜戦から開始する戦闘かどうか - /// - public bool StartsFromNightBattle - { - get - { - var phase = BattleMode & BattleModes.BattlePhaseMask; - return phase == BattleModes.NightOnly || phase == BattleModes.NightDay; - } - } + public List HeavyBaseAirRaids { get; } = []; /// /// 連合艦隊戦かどうか /// - public bool IsCombinedBattle => (BattleMode & BattleModes.CombinedMask) != 0; + public bool IsCombinedBattle => FirstBattle is { IsCombined: true }; /// /// 演習かどうか /// - public bool IsPractice => (BattleMode & BattleModes.BattlePhaseMask) == BattleModes.Practice; + public bool IsPractice => FirstBattle is { IsPractice: true }; /// /// 敵が連合艦隊かどうか /// - public bool IsEnemyCombined => (BattleMode & BattleModes.EnemyCombinedFleet) != 0; + public bool IsEnemyCombined => FirstBattle is { IsEnemyCombined: true }; /// /// 基地空襲戦かどうか /// - public bool IsBaseAirRaid => (BattleMode & BattleModes.BattlePhaseMask) == BattleModes.BaseAirRaid; - - - /// - /// 1回目の戦闘 - /// - public BattleData FirstBattle => HeavyBaseAirRaids switch - { - // first battle gets used for things like engagement - // remove this part if heavy air raids get moved to BattleDay - { Count: > 0 } => HeavyBaseAirRaids.Last(), - _ => StartsFromDayBattle ? BattleDay : BattleNight - }; - - /// - /// 2回目の戦闘 - /// - public BattleData SecondBattle => StartsFromDayBattle ? (BattleData)BattleNight : BattleDay; + public bool IsBaseAirRaid => FirstBattle is { IsBaseAirRaid: true }; + public bool IsAirRaid => FirstBattle is { IsAirRaid: true }; /// /// 出撃中に入手した艦船数 /// - public int DroppedShipCount { get; internal set; } + public int DroppedShipCount { get; private set; } /// /// 出撃中に入手した装備数 /// - public int DroppedEquipmentCount { get; internal set; } + public int DroppedEquipmentCount { get; private set; } /// /// 出撃中に入手したアイテム - ID と 個数 のペア /// - public Dictionary DroppedItemCount { get; internal set; } + private Dictionary DroppedItemCount { get; } = []; /// /// 演習の敵提督名 /// - public string EnemyAdmiralName { get; internal set; } + private string? EnemyAdmiralName { get; set; } /// /// 演習の敵提督階級 /// - public string EnemyAdmiralRank { get; internal set; } + private string? EnemyAdmiralRank { get; set; } /// /// True if Resupply was used before the battle @@ -179,25 +153,48 @@ public bool StartsFromNightBattle /// /// 特殊攻撃発動回数 /// - public Dictionary SpecialAttackCount { get; private set; } + public Dictionary SpecialAttackCount { get; } = []; /// /// 記録する特殊攻撃 /// - private int[] TracedSpecialAttack { get; } = [100, 101, 102, 103, 104, 105, 300, 301, 302, 400, 401]; + private List TracedSpecialAttack { get; } = [100, 101, 102, 103, 104, 105, 300, 301, 302, 400, 401]; + public override void LoadFromRequest(string apiname, Dictionary data) + { + switch (apiname) + { + case "api_req_sortie/battle": + ResupplyUsed = data.ContainsKey("api_supply_flag") && data["api_supply_flag"] == "1"; + RationUsed = data.ContainsKey("api_ration_flag") && data["api_ration_flag"] == "1"; + break; + } + + } + private BattleFactory BattleFactory => Ioc.Default.GetRequiredService(); - public BattleManager() + private BattleFleets Fleets { - DroppedItemCount = new Dictionary(); - SpecialAttackCount = new Dictionary(); - } + get + { + IFleetData fleet = KCDatabase.Instance.Fleet.Fleets.Values + .First(f => f.IsInSortie); + return new(fleet) + { + FleetId = fleet.FleetID, + CombinedFlag = KCDatabase.Instance.Fleet.CombinedFlag, + NodeSupportFleetId = KCDatabase.Instance.Fleet.NodeSupportFleet ?? 0, + BossSupportFleetId = KCDatabase.Instance.Fleet.BossSupportFleet ?? 0, + }; + } + } + [System.Diagnostics.CodeAnalysis.SuppressMessage("Critical Code Smell", "S3776:Cognitive Complexity of methods should not be too high", Justification = "todo")] public override void LoadFromResponse(string apiname, dynamic data) { - //base.LoadFromResponse( apiname, data ); //不要 + object? apiData = DeserializeResponse(apiname, data.ToString()); HeavyBaseAirRaids.Clear(); @@ -205,24 +202,24 @@ public override void LoadFromResponse(string apiname, dynamic data) { case "api_req_map/start": case "api_req_map/next": - BattleDay = null; - BattleNight = null; + { + FirstBattle = null; + SecondBattle = null; Result = null; - BattleMode = BattleModes.Undefined; Compass = new CompassData(); Compass.LoadFromResponse(apiname, data); - if (Compass.HasAirRaid) + if (apiData is ApiReqMapNextResponse { ApiDestructionBattle: { } battle }) { - BattleMode = BattleModes.BaseAirRaid; - BattleDay = new BattleBaseAirRaid(); - BattleDay.LoadFromResponse(apiname, Compass.AirRaidData); + FirstBattle = BattleFactory.CreateBattle(battle, Fleets); BattleFinished(); } - break; + } + break; case "api_req_map/air_raid": - BattleMode = BattleModes.BaseAirRaid; + { + /* todo // BattleDay = new BattleHeavyBaseAirRaid(); // BattleDay.LoadFromResponse(apiname, data.api_destruction_battle[0]); foreach (dynamic airraid in data.api_destruction_battle) @@ -232,123 +229,167 @@ public override void LoadFromResponse(string apiname, dynamic data) HeavyBaseAirRaids.Add(raid); } BattleFinished(); - break; + */ + } + break; case "api_req_sortie/battle": - BattleMode = BattleModes.Normal; - BattleDay = new BattleNormalDay(); - BattleDay.LoadFromResponse(apiname, data); - break; + { + if (apiData is not ApiReqSortieBattleResponse battle) break; + + FirstBattle = BattleFactory.CreateBattle(battle, Fleets); + } + break; case "api_req_battle_midnight/battle": - BattleNight = new BattleNormalNight(); - BattleNight.TakeOverParameters(BattleDay); - BattleNight.LoadFromResponse(apiname, data); - break; + { + if (apiData is not ApiReqBattleMidnightBattleResponse battle) break; + + Debug.Assert(FirstBattle is not null); + + SecondBattle = BattleFactory.CreateBattle(battle, FirstBattle.FleetsAfterBattle); + } + break; case "api_req_battle_midnight/sp_midnight": - BattleMode = BattleModes.NightOnly; - BattleDay = null; - BattleNight = new BattleNightOnly(); - BattleNight.LoadFromResponse(apiname, data); - break; + { + if (apiData is not ApiReqBattleMidnightSpMidnightResponse battle) break; + + FirstBattle = BattleFactory.CreateBattle(battle, Fleets); + } + break; case "api_req_sortie/airbattle": - BattleMode = BattleModes.AirBattle; - BattleDay = new BattleAirBattle(); - BattleDay.LoadFromResponse(apiname, data); - break; + { + if (apiData is not ApiReqSortieAirbattleResponse battle) break; + + FirstBattle = BattleFactory.CreateBattle(battle, Fleets); + } + break; case "api_req_sortie/ld_airbattle": - BattleMode = BattleModes.AirRaid; - BattleDay = new BattleAirRaid(); - BattleDay.LoadFromResponse(apiname, data); - break; + { + if (apiData is not ApiReqSortieLdAirbattleResponse battle) break; + + FirstBattle = BattleFactory.CreateBattle(battle, Fleets); + } + break; case "api_req_sortie/night_to_day": - BattleMode = BattleModes.NightDay; - BattleNight = new BattleNormalDayFromNight(); - BattleNight.LoadFromResponse(apiname, data); - break; + { + if (apiData is not ApiReqSortieNightToDayResponse battle) break; + + FirstBattle = BattleFactory.CreateBattle(battle, Fleets); + } + break; case "api_req_sortie/ld_shooting": - BattleMode = BattleModes.Radar; - BattleDay = new BattleNormalRadar(); - BattleDay.LoadFromResponse(apiname, data); - break; + { + if (apiData is not ApiReqSortieLdShootingResponse battle) break; + + FirstBattle = BattleFactory.CreateBattle(battle, Fleets); + } + break; case "api_req_combined_battle/battle": - BattleMode = BattleModes.Normal | BattleModes.CombinedTaskForce; - BattleDay = new BattleCombinedNormalDay(); - BattleDay.LoadFromResponse(apiname, data); - break; + { + if (apiData is not ApiReqCombinedBattleBattleResponse battle) break; + + FirstBattle = BattleFactory.CreateBattle(battle, Fleets); + } + break; case "api_req_combined_battle/midnight_battle": - BattleNight = new BattleCombinedNormalNight(); - //BattleNight.TakeOverParameters( BattleDay ); //checkme: 連合艦隊夜戦では昼戦での与ダメージがMVPに反映されない仕様? - BattleNight.LoadFromResponse(apiname, data); - break; + { + if (apiData is not ApiReqCombinedBattleMidnightBattleResponse battle) break; + + Debug.Assert(FirstBattle is not null); + + SecondBattle = BattleFactory.CreateBattle(battle, FirstBattle.FleetsAfterBattle); + } + break; case "api_req_combined_battle/sp_midnight": - BattleMode = BattleModes.NightOnly | BattleModes.CombinedMask; - BattleDay = null; - BattleNight = new BattleCombinedNightOnly(); - BattleNight.LoadFromResponse(apiname, data); - break; + { + if (apiData is not ApiReqCombinedBattleSpMidnightResponse battle) break; + + FirstBattle = BattleFactory.CreateBattle(battle, Fleets); + } + break; case "api_req_combined_battle/airbattle": - BattleMode = BattleModes.AirBattle | BattleModes.CombinedTaskForce; - BattleDay = new BattleCombinedAirBattle(); - BattleDay.LoadFromResponse(apiname, data); - break; + { + if (apiData is not ApiReqCombinedBattleAirbattleResponse battle) break; + + FirstBattle = BattleFactory.CreateBattle(battle, Fleets); + } + break; case "api_req_combined_battle/battle_water": - BattleMode = BattleModes.Normal | BattleModes.CombinedSurface; - BattleDay = new BattleCombinedWater(); - BattleDay.LoadFromResponse(apiname, data); - break; + { + if (apiData is not ApiReqCombinedBattleBattleWaterResponse battle) break; + + FirstBattle = BattleFactory.CreateBattle(battle, Fleets); + } + break; case "api_req_combined_battle/ld_airbattle": - BattleMode = BattleModes.AirRaid | BattleModes.CombinedTaskForce; - BattleDay = new BattleCombinedAirRaid(); - BattleDay.LoadFromResponse(apiname, data); - break; + { + if (apiData is not ApiReqCombinedBattleLdAirbattleResponse battle) break; + + FirstBattle = BattleFactory.CreateBattle(battle, Fleets); + } + break; case "api_req_combined_battle/ec_battle": - BattleMode = BattleModes.Normal | BattleModes.EnemyCombinedFleet; - BattleDay = new BattleEnemyCombinedDay(); - BattleDay.LoadFromResponse(apiname, data); - break; + { + if (apiData is not ApiReqCombinedBattleEcBattleResponse battle) break; + + FirstBattle = BattleFactory.CreateBattle(battle, Fleets); + } + break; case "api_req_combined_battle/ec_midnight_battle": - BattleNight = new BattleEnemyCombinedNight(); - BattleNight.TakeOverParameters(BattleDay); - BattleNight.LoadFromResponse(apiname, data); - break; + { + if (apiData is not ApiReqCombinedBattleEcMidnightBattleResponse battle) break; + + Debug.Assert(FirstBattle is not null); + + SecondBattle = BattleFactory.CreateBattle(battle, FirstBattle.FleetsAfterBattle); + } + break; case "api_req_combined_battle/ec_night_to_day": - BattleMode = BattleModes.NightDay | BattleModes.EnemyCombinedFleet; - BattleNight = new BattleEnemyCombinedDayFromNight(); - BattleNight.LoadFromResponse(apiname, data); - break; + { + if (apiData is not ApiReqCombinedBattleEcNightToDayResponse battle) break; + + FirstBattle = BattleFactory.CreateBattle(battle, Fleets); + } + break; case "api_req_combined_battle/each_battle": - BattleMode = BattleModes.Normal | BattleModes.CombinedTaskForce | BattleModes.EnemyCombinedFleet; - BattleDay = new BattleCombinedEachDay(); - BattleDay.LoadFromResponse(apiname, data); - break; + { + if (apiData is not ApiReqCombinedBattleEachBattleResponse battle) break; + + FirstBattle = BattleFactory.CreateBattle(battle, Fleets); + } + break; case "api_req_combined_battle/each_battle_water": - BattleMode = BattleModes.Normal | BattleModes.CombinedSurface | BattleModes.EnemyCombinedFleet; - BattleDay = new BattleCombinedEachWater(); - BattleDay.LoadFromResponse(apiname, data); - break; + { + if (apiData is not ApiReqCombinedBattleEachBattleWaterResponse battle) break; + + FirstBattle = BattleFactory.CreateBattle(battle, Fleets); + } + break; case "api_req_combined_battle/ld_shooting": - BattleMode = BattleModes.Radar | BattleModes.CombinedTaskForce; - BattleDay = new BattleCombinedRadar(); - BattleDay.LoadFromResponse(apiname, data); - break; + { + if (apiData is not ApiReqCombinedBattleLdShootingResponse battle) break; + + FirstBattle = BattleFactory.CreateBattle(battle, Fleets); + } + break; case "api_req_member/get_practice_enemyinfo": EnemyAdmiralName = data.api_nickname; @@ -356,31 +397,43 @@ public override void LoadFromResponse(string apiname, dynamic data) break; case "api_req_practice/battle": - BattleMode = BattleModes.Practice; - BattleDay = new BattlePracticeDay(); - BattleDay.LoadFromResponse(apiname, data); - break; + { + if (apiData is not ApiReqPracticeBattleResponse battle) break; + + FirstBattle = BattleFactory.CreateBattle(battle, Fleets); + } + break; case "api_req_practice/midnight_battle": - BattleNight = new BattlePracticeNight(); - BattleNight.TakeOverParameters(BattleDay); - BattleNight.LoadFromResponse(apiname, data); - break; + { + if (apiData is not ApiReqPracticeMidnightBattleResponse battle) break; + + Debug.Assert(FirstBattle is not null); + + SecondBattle = BattleFactory.CreateBattle(battle, FirstBattle.FleetsAfterBattle); + } + break; case "api_req_sortie/battleresult": case "api_req_combined_battle/battleresult": case "api_req_practice/battle_result": - Result = new BattleResultData(); - Result.LoadFromResponse(apiname, data); + { + Result = apiData switch + { + ApiReqCombinedBattleBattleresultResponse c => new(c), + ISortieBattleResultApi s => new(s), + ApiReqPracticeBattleResultResponse p => new(p), + _ => null, + }; BattleFinished(); break; + } case "api_port/port": Compass = null; - BattleDay = null; - BattleNight = null; + FirstBattle = null; + SecondBattle = null; Result = null; - BattleMode = BattleModes.Undefined; PredictedBattleRank = ""; DroppedShipCount = DroppedEquipmentCount = 0; DroppedItemCount.Clear(); @@ -392,70 +445,99 @@ public override void LoadFromResponse(string apiname, dynamic data) break; } - } - public override void LoadFromRequest(string apiname, Dictionary data) + private static object? DeserializeResponse(string apiName, string json) => apiName switch { - switch (apiname) - { - case "api_req_sortie/battle": - ResupplyUsed = data.ContainsKey("api_supply_flag") && data["api_supply_flag"] == "1"; - RationUsed = data.ContainsKey("api_ration_flag") && data["api_ration_flag"] == "1"; - break; - } - - } + "api_req_map/start" => JsonSerializer.Deserialize(json), + + "api_req_sortie/battle" => JsonSerializer.Deserialize(json), + "api_req_battle_midnight/sp_midnight" => JsonSerializer.Deserialize(json), + "api_req_sortie/airbattle" => JsonSerializer.Deserialize(json), + "api_req_sortie/ld_airbattle" => JsonSerializer.Deserialize(json), + "api_req_sortie/night_to_day" => JsonSerializer.Deserialize(json), + "api_req_sortie/ld_shooting" => JsonSerializer.Deserialize(json), + "api_req_combined_battle/battle" => JsonSerializer.Deserialize(json), + "api_req_combined_battle/sp_midnight" => JsonSerializer.Deserialize(json), + "api_req_combined_battle/airbattle" => JsonSerializer.Deserialize(json), + "api_req_combined_battle/battle_water" => JsonSerializer.Deserialize(json), + "api_req_combined_battle/ld_airbattle" => JsonSerializer.Deserialize(json), + "api_req_combined_battle/ec_battle" => JsonSerializer.Deserialize(json), + "api_req_combined_battle/ec_night_to_day" => JsonSerializer.Deserialize(json), + "api_req_combined_battle/each_battle" => JsonSerializer.Deserialize(json), + "api_req_combined_battle/each_battle_water" => JsonSerializer.Deserialize(json), + "api_req_combined_battle/ld_shooting" => JsonSerializer.Deserialize(json), + + "api_req_battle_midnight/battle" => JsonSerializer.Deserialize(json), + "api_req_combined_battle/midnight_battle" => JsonSerializer.Deserialize(json), + "api_req_combined_battle/ec_midnight_battle" => JsonSerializer.Deserialize(json), + + "api_req_sortie/battleresult" => JsonSerializer.Deserialize(json), + "api_req_combined_battle/battleresult" => JsonSerializer.Deserialize(json), + + "api_req_practice/battle" => JsonSerializer.Deserialize(json), + "api_req_practice/battle_result" => JsonSerializer.Deserialize(json), + + _ => null, + }; /// /// 戦闘終了時に各種データの収集を行います。 /// private void BattleFinished() { - //敵編成記録 - EnemyFleetRecord.EnemyFleetElement enemyFleetData = EnemyFleetRecord.EnemyFleetElement.CreateFromCurrentState(); + EnemyFleetRecord.EnemyFleetElement? enemyFleetData = EnemyFleetRecord.EnemyFleetElement.CreateFromCurrentState(); if (enemyFleetData != null) + { RecordManager.Instance.EnemyFleet.Update(enemyFleetData); - + } // ロギング if (IsPractice) { + Debug.Assert(Result is not null); + Utility.Logger.Add(2, string.Format(BattleRes.BattleFinishedPractice, EnemyAdmiralName, EnemyAdmiralRank, Result.EnemyFleetName, Result.Rank, Result.AdmiralExp, Result.BaseExp)); } else if (IsBaseAirRaid) { - if (BattleDay is BattleBaseAirRaid { BaseAirRaid: { } airraid }) + Debug.Assert(Compass is not null); + + if (FirstBattle is BattleBaseAirRaid raid) { - var initialHPs = BattleDay.Initial.FriendInitialHPs.TakeWhile(hp => hp >= 0); - var damage = initialHPs.Zip(BattleDay.ResultHPs.Take(initialHPs.Count()), (initial, result) => initial - result).Sum(); + PhaseBaseAirRaid? airraid = raid.BaseAirRaid; + List initialHPs = FirstBattle.Initial.FriendInitialHPs.TakeWhile(hp => hp >= 0).ToList(); + int damage = initialHPs.Zip(FirstBattle.ResultHPs.Take(initialHPs.Count), (initial, result) => initial - result).Sum(); Utility.Logger.Add(2, string.Format(BattleRes.BattleFinishedBaseAirRaid, Compass.MapAreaID, Compass.MapInfoID, Compass.CellDisplay, - Constants.GetAirSuperiority(airraid.IsAvailable ? airraid.AirSuperiority : -1), damage, Constants.GetAirRaidDamage(Compass.AirRaidDamageKind))); + Constants.GetAirSuperiority(airraid?.AirState ?? AirState.Unknown), damage, Constants.GetAirRaidDamage(Compass.AirRaidDamageKind))); } foreach (BattleBaseAirRaid battleBaseAirRaid in HeavyBaseAirRaids) { List initialHPs = battleBaseAirRaid.Initial.FriendInitialHPs.TakeWhile(hp => hp >= 0).ToList(); - int damage = initialHPs.Zip(battleBaseAirRaid.ResultHPs.Take(initialHPs.Count()), (initial, result) => initial - result).Sum(); - PhaseBaseAirRaid baseAirRaid = battleBaseAirRaid.BaseAirRaid; + int damage = initialHPs.Zip(battleBaseAirRaid.ResultHPs.Take(initialHPs.Count), (initial, result) => initial - result).Sum(); + PhaseBaseAirRaid? baseAirRaid = battleBaseAirRaid.BaseAirRaid; - int airRaidDamageKind = (int)battleBaseAirRaid.RawData.api_lost_kind; + int airRaidDamageKind = baseAirRaid?.ApiLostKind ?? 0; Utility.Logger.Add(2, string.Format(BattleRes.BattleFinishedBaseAirRaid, Compass.MapAreaID, Compass.MapInfoID, Compass.CellDisplay, - Constants.GetAirSuperiority(baseAirRaid.IsAvailable ? baseAirRaid.AirSuperiority : -1), damage, Constants.GetAirRaidDamage(airRaidDamageKind))); + Constants.GetAirSuperiority(baseAirRaid?.AirState ?? AirState.Unknown), damage, Constants.GetAirRaidDamage(airRaidDamageKind))); } } else { + Debug.Assert(Compass is not null); + Debug.Assert(Result is not null); + Utility.Logger.Add(2, string.Format(BattleRes.BattleFinishedSortie, Compass.MapAreaID, Compass.MapInfoID, Compass.CellDisplay, KCDatabase.Instance.Translation.Operation.FleetName(Result.EnemyFleetName), Result.Rank, Result.AdmiralExp, Result.BaseExp)); @@ -465,14 +547,17 @@ private void BattleFinished() // Level up if (!IsBaseAirRaid) { - var exps = Result.ExpList; - var lvup = Result.LevelUpList; - for (int i = 0; i < lvup.Length; i++) + Debug.Assert(FirstBattle is not null); + Debug.Assert(Result is not null); + + List exps = Result.ExpList; + List> lvup = Result.LevelUpList; + for (int i = 0; i < lvup.Count; i++) { - if (lvup[i].Length >= 2 && i < exps.Length && lvup[i][0] + exps[i] >= lvup[i][1]) + if (lvup[i].Count >= 2 && i < exps.Count && lvup[i][0] + exps[i] >= lvup[i][1]) { - var ship = FirstBattle.Initial.FriendFleet.MembersInstance[i]; - int increment = Math.Max(lvup[i].Length - 2, 1); + IShipData ship = FirstBattle.FleetsBeforeBattle.Fleet.MembersInstance[i]!; + int increment = Math.Max(lvup[i].Count - 2, 1); ShipLevelUp?.Invoke(ship, ship.Level + increment); Utility.Logger.Add(2, string.Format(BattleRes.HasLeveledUp, ship.Name, ship.Level + increment)); @@ -481,14 +566,15 @@ private void BattleFinished() if (IsCombinedBattle) { - exps = Result.ExpListCombined; - lvup = Result.LevelUpListCombined; - for (int i = 0; i < lvup.Length; i++) + exps = Result.ExpListCombined!; + lvup = Result.LevelUpListCombined!; + + for (int i = 0; i < lvup.Count; i++) { - if (lvup[i].Length >= 2 && i < exps.Length && lvup[i][0] + exps[i] >= lvup[i][1]) + if (lvup[i].Count >= 2 && i < exps.Count && lvup[i][0] + exps[i] >= lvup[i][1]) { - var ship = FirstBattle.Initial.FriendFleetEscort.MembersInstance[i]; - int increment = Math.Max(lvup[i].Length - 2, 1); + IShipData ship = FirstBattle.FleetsBeforeBattle.EscortFleet!.MembersInstance[i]!; + int increment = Math.Max(lvup[i].Count - 2, 1); ShipLevelUp?.Invoke(ship, ship.Level + increment); Utility.Logger.Add(2, string.Format(BattleRes.HasLeveledUp, ship.Name, ship.Level + increment)); @@ -502,24 +588,24 @@ private void BattleFinished() //ドロップ艦記録 if (!IsPractice && !IsBaseAirRaid) { + Debug.Assert(Compass is not null); + Debug.Assert(Result is not null); //checkme: とてもアレな感じ - int shipID = Result.DroppedShipID; - int itemID = Result.DroppedItemID; - int eqID = Result.DroppedEquipmentID; + int shipId = (int?)Result.DroppedShipId ?? -1; + int itemId = Result.DroppedItemId ?? -1; + int eqId = Result.DroppedEquipmentId ?? -1; bool showLog = Utility.Configuration.Config.Log.ShowSpoiler; - if (shipID != -1) + if (KCDatabase.Instance.MasterShips[shipId] is IShipDataMaster ship) { - - IShipDataMaster ship = KCDatabase.Instance.MasterShips[shipID]; DroppedShipCount++; IEnumerable? defaultSlot = ship.DefaultSlot?.Select(i => i switch { < 1 => null, - _ => KCDatabase.Instance.MasterEquipments[i] + _ => KCDatabase.Instance.MasterEquipments[i], }); if (defaultSlot != null) @@ -533,25 +619,21 @@ private void BattleFinished() Utility.Logger.Add(2, string.Format(LoggerRes.ShipAdded, ship.ShipTypeName, ship.NameWithClass)); } - if (itemID != -1) + if (itemId != -1) { - - if (!DroppedItemCount.ContainsKey(itemID)) - DroppedItemCount.Add(itemID, 0); - DroppedItemCount[itemID]++; + DroppedItemCount.TryAdd(itemId, 0); + DroppedItemCount[itemId]++; if (showLog) { - var item = KCDatabase.Instance.UseItems[itemID]; - var itemmaster = KCDatabase.Instance.MasterUseItems[itemID]; - Utility.Logger.Add(2, string.Format(LoggerRes.ItemObtained, itemmaster?.NameTranslated ?? (BattleRes.UnknownItem + itemID), (item?.Count ?? 0) + DroppedItemCount[itemID])); + IUseItem? item = KCDatabase.Instance.UseItems[itemId]; + IUseItemMaster? itemMaster = KCDatabase.Instance.MasterUseItems[itemId]; + Utility.Logger.Add(2, string.Format(LoggerRes.ItemObtained, itemMaster?.NameTranslated ?? (BattleRes.UnknownItem + itemId), (item?.Count ?? 0) + DroppedItemCount[itemId])); } } - if (eqID != -1) + if (KCDatabase.Instance.MasterEquipments[eqId] is IEquipmentDataMaster eq) { - - IEquipmentDataMaster eq = KCDatabase.Instance.MasterEquipments[eqID]; if (eq.UsesSlotSpace()) { DroppedEquipmentCount++; @@ -565,38 +647,62 @@ private void BattleFinished() // 満員判定 - if (shipID == -1 && ( + if (shipId == -1 && ( KCDatabase.Instance.Admiral.MaxShipCount - (KCDatabase.Instance.Ships.Count + DroppedShipCount) <= 0 || KCDatabase.Instance.Admiral.MaxEquipmentCount - (KCDatabase.Instance.Equipments.Values.Count(e => e.MasterEquipment.UsesSlotSpace()) + DroppedEquipmentCount) <= 0)) { - shipID = -2; + shipId = -2; } - RecordManager.Instance.ShipDrop.Add(shipID, itemID, eqID, Compass.MapAreaID, Compass.MapInfoID, Compass.CellId, Compass.MapInfo.EventDifficulty, Compass.EventID == 5, enemyFleetData.FleetID, Result.Rank, KCDatabase.Instance.Admiral.Level); + Debug.Assert(enemyFleetData is not null); + + RecordManager.Instance.ShipDrop.Add(shipId, itemId, eqId, Compass.MapAreaID, Compass.MapInfoID, Compass.CellId, Compass.MapInfo.EventDifficulty, Compass.EventID == 5, enemyFleetData.FleetID, Result.Rank, KCDatabase.Instance.Admiral.Level); } - void IncrementSpecialAttack(BattleData bd) + void IncrementSpecialAttack(BattleData? bd) { - if (bd == null) - return; + if (bd == null) return; - foreach (var phase in bd.GetPhases()) + foreach (PhaseBase phase in bd.Phases) { - foreach (var detail in phase.BattleDetails) + switch (phase) { - int kind = detail.AttackType; + case PhaseShelling shelling: + { + foreach (DayAttackKind attackType in shelling.AttackDisplays + .Where(a => a.AttackerIndex.FleetFlag is FleetFlag.Player) + .Select(a => a.AttackType) + .Where(a => TracedSpecialAttack.Contains((int)a))) + { + if (!SpecialAttackCount.TryAdd((int)attackType, 1)) + { + SpecialAttackCount[(int)attackType]++; + } + } + + break; + } - if (detail.AttackerIndex.IsFriend && TracedSpecialAttack.Contains(kind)) + case PhaseNightBattle night: { - if (SpecialAttackCount.ContainsKey(kind)) - SpecialAttackCount[kind]++; - else - SpecialAttackCount.Add(kind, 1); + foreach (NightAttackKind attackType in night.AttackDisplays + .Where(a => a.AttackerIndex.FleetFlag is FleetFlag.Player) + .Select(a => a.AttackType) + .Where(a => TracedSpecialAttack.Contains((int)a))) + { + if (!SpecialAttackCount.TryAdd((int)attackType, 1)) + { + SpecialAttackCount[(int)attackType]++; + } + } + + break; } } } } + IncrementSpecialAttack(FirstBattle); IncrementSpecialAttack(SecondBattle); @@ -606,61 +712,73 @@ void IncrementSpecialAttack(BattleData bd) /// /// 勝利ランクを予測します。 /// - /// 味方の損害率を出力します。 - /// 敵の損害率を出力します。 - public int PredictWinRank(out double friendrate, out double enemyrate) + /// 味方の損害率を出力します。 + /// 敵の損害率を出力します。 + public int PredictWinRank(out double friendRate, out double enemyRate) { - BattleData activeBattle = SecondBattle ?? FirstBattle; - PhaseInitial firstInitial = FirstBattle.Initial; + BattleData? activeBattle = SecondBattle ?? FirstBattle; + + // should never happen + if (activeBattle is null) + { + friendRate = 0; + enemyRate = 0; + return -1; + } + BattleFleets fleetsBefore = activeBattle.FleetsBeforeBattle; + + List hpsBefore = activeBattle.InitialHPs.ToList(); List hpsAfter = activeBattle.ResultHPs.ToList(); - BattleRankPrediction prediction = (BattleMode & BattleModes.BattlePhaseMask) switch + Debug.Assert(fleetsBefore.EnemyFleet is not null); + + BattleRankPrediction prediction = activeBattle switch { - BattleModes.AirRaid or BattleModes.Radar => new AirRaidBattleRankPrediction() + { IsAirRaid: true } or { IsRadar: true } => new AirRaidBattleRankPrediction() { - FriendlyMainFleetBefore = firstInitial.FriendFleet, - FriendlyMainFleetAfter = BattleRankPrediction.SimulateFleetAfterBattle(firstInitial.FriendFleet, hpsAfter, BattleSides.FriendMain)!, + FriendlyMainFleetBefore = fleetsBefore.Fleet, + FriendlyMainFleetAfter = BattleRankPrediction.SimulateFleetAfterBattle(fleetsBefore.Fleet, hpsAfter, BattleSides.FriendMain)!, - FriendlyEscortFleetBefore = firstInitial.FriendFleetEscort, - FriendlyEscortFleetAfter = BattleRankPrediction.SimulateFleetAfterBattle(firstInitial.FriendFleetEscort, hpsAfter, BattleSides.FriendEscort), + FriendlyEscortFleetBefore = fleetsBefore.EscortFleet, + FriendlyEscortFleetAfter = BattleRankPrediction.SimulateFleetAfterBattle(fleetsBefore.EscortFleet, hpsAfter, BattleSides.FriendEscort), - EnemyMainFleetBefore = firstInitial.EnemyFleet, - EnemyMainFleetAfter = BattleRankPrediction.SimulateFleetAfterBattle(firstInitial.EnemyFleet, hpsAfter, BattleSides.EnemyMain)!, + EnemyMainFleetBefore = fleetsBefore.EnemyFleet, + EnemyMainFleetAfter = BattleRankPrediction.SimulateFleetAfterBattle(fleetsBefore.EnemyFleet, hpsAfter, BattleSides.EnemyMain)!, - EnemyEscortFleetBefore = firstInitial.EnemyFleetEscort, - EnemyEscortFleetAfter = BattleRankPrediction.SimulateFleetAfterBattle(firstInitial.EnemyFleetEscort, hpsAfter, BattleSides.EnemyEscort), + EnemyEscortFleetBefore = fleetsBefore.EnemyEscortFleet, + EnemyEscortFleetAfter = BattleRankPrediction.SimulateFleetAfterBattle(fleetsBefore.EnemyEscortFleet, hpsAfter, BattleSides.EnemyEscort), }, - BattleModes.BaseAirRaid => new BaseAirRaidBattleRankPrediction() + { IsBaseAirRaid: true } => new BaseAirRaidBattleRankPrediction() { - AirBaseBeforeAfter = BaseAirRaidBattleRankPrediction.SimulateBaseAfterBattle(firstInitial.FriendInitialHPs.ToList(), hpsAfter), + AirBaseBeforeAfter = BaseAirRaidBattleRankPrediction.SimulateBaseAfterBattle(hpsBefore, hpsAfter), - EnemyMainFleetBefore = firstInitial.EnemyFleet, - EnemyMainFleetAfter = BattleRankPrediction.SimulateFleetAfterBattle(firstInitial.EnemyFleet, hpsAfter, BattleSides.EnemyMain)!, + EnemyMainFleetBefore = fleetsBefore.EnemyFleet, + EnemyMainFleetAfter = BattleRankPrediction.SimulateFleetAfterBattle(fleetsBefore.EnemyFleet, hpsAfter, BattleSides.EnemyMain)!, - EnemyEscortFleetBefore = firstInitial.EnemyFleetEscort, - EnemyEscortFleetAfter = BattleRankPrediction.SimulateFleetAfterBattle(firstInitial.EnemyFleetEscort, hpsAfter, BattleSides.EnemyEscort), + EnemyEscortFleetBefore = fleetsBefore.EnemyEscortFleet, + EnemyEscortFleetAfter = BattleRankPrediction.SimulateFleetAfterBattle(fleetsBefore.EnemyEscortFleet, hpsAfter, BattleSides.EnemyEscort), }, _ => new NormalBattleRankPrediction() { - FriendlyMainFleetBefore = firstInitial.FriendFleet, - FriendlyMainFleetAfter = BattleRankPrediction.SimulateFleetAfterBattle(firstInitial.FriendFleet, hpsAfter, BattleSides.FriendMain)!, + FriendlyMainFleetBefore = fleetsBefore.Fleet, + FriendlyMainFleetAfter = BattleRankPrediction.SimulateFleetAfterBattle(fleetsBefore.Fleet, hpsAfter, BattleSides.FriendMain)!, - FriendlyEscortFleetBefore = firstInitial.FriendFleetEscort, - FriendlyEscortFleetAfter = BattleRankPrediction.SimulateFleetAfterBattle(firstInitial.FriendFleetEscort, hpsAfter, BattleSides.FriendEscort), + FriendlyEscortFleetBefore = fleetsBefore.EscortFleet, + FriendlyEscortFleetAfter = BattleRankPrediction.SimulateFleetAfterBattle(fleetsBefore.EscortFleet, hpsAfter, BattleSides.FriendEscort), - EnemyMainFleetBefore = firstInitial.EnemyFleet, - EnemyMainFleetAfter = BattleRankPrediction.SimulateFleetAfterBattle(firstInitial.EnemyFleet, hpsAfter, BattleSides.EnemyMain)!, + EnemyMainFleetBefore = fleetsBefore.EnemyFleet, + EnemyMainFleetAfter = BattleRankPrediction.SimulateFleetAfterBattle(fleetsBefore.EnemyFleet, hpsAfter, BattleSides.EnemyMain)!, - EnemyEscortFleetBefore = firstInitial.EnemyFleetEscort, - EnemyEscortFleetAfter = BattleRankPrediction.SimulateFleetAfterBattle(firstInitial.EnemyFleetEscort, hpsAfter, BattleSides.EnemyEscort), + EnemyEscortFleetBefore = fleetsBefore.EnemyEscortFleet, + EnemyEscortFleetAfter = BattleRankPrediction.SimulateFleetAfterBattle(fleetsBefore.EnemyEscortFleet, hpsAfter, BattleSides.EnemyEscort), }, }; BattleRank rank = prediction.PredictRank(); - friendrate = prediction.FriendHpRate; - enemyrate = prediction.EnemyHpRate; + friendRate = prediction.FriendHpRate; + enemyRate = prediction.EnemyHpRate; return (int)rank; } @@ -670,69 +788,66 @@ public int PredictWinRank(out double friendrate, out double enemyrate) /// public bool WillNightBattleWithMainFleet() { - if (StartsFromDayBattle && IsEnemyCombined) + if (!IsEnemyCombined) return false; // ? true? + if (FirstBattle?.Initial is not { IsEnemyCombined: true } initial) return false; // ? true? + + int score = 0; + List resultHps = FirstBattle.ResultHPs.ToList(); + + for (int i = 0; i < initial.EnemyInitialHPsEscort.Count; i++) { - var initial = BattleDay.Initial; - int score = 0; - for (int i = 0; i < initial.EnemyInitialHPsEscort.Length; i++) + if (initial.EnemyMembersEscort[i] > 0) { - if (initial.EnemyMembersEscort[i] > 0) - { - double rate = (double)BattleDay.ResultHPs[BattleIndex.Get(BattleSides.EnemyEscort, i)] / initial.EnemyMaxHPsEscort[i]; + double rate = (double)resultHps[BattleIndex.Get(BattleSides.EnemyEscort, i)] / + initial.EnemyMaxHPsEscort[i]; - if (rate > 0.5) - { - score += 10; - } - else if (rate > 0.25) - { - score += 7; - } + if (rate > 0.5) + { + score += 10; + } + else if (rate > 0.25) + { + score += 7; + } - if (i == 0 && rate > 0) - { - score += 10; - } + if (i == 0 && rate > 0) + { + score += 10; } } - return score < 30; } - else return false; // ? true? + + return score < 30; } private void WriteBattleLog() { - - if (!Utility.Configuration.Config.Log.SaveBattleLog) - return; + if (!Utility.Configuration.Config.Log.SaveBattleLog) return; try { string parent = BattleLogPath; - if (!Directory.Exists(parent)) - Directory.CreateDirectory(parent); + Directory.CreateDirectory(parent); + + string info = (IsPractice, Compass) switch + { + (true, _) => "practice", + (_, not null) => $"{Compass.MapAreaID}-{Compass.MapInfoID}-{Compass.CellId}", - string info; - if (IsPractice) - info = "practice"; - else - info = $"{Compass.MapAreaID}-{Compass.MapInfoID}-{Compass.CellId}"; + // should never happen + _ => "???", + }; string path = $"{parent}\\{DateTimeHelper.GetTimeStamp()}@{info}.txt"; - using (var sw = new StreamWriter(path, false, Utility.Configuration.Config.Log.FileEncoding)) - { - sw.Write(BattleDetailDescriptor.GetBattleDetail(this)); - } - + using StreamWriter sw = new(path, false, Utility.Configuration.Config.Log.FileEncoding); + sw.Write(BattleDetailDescriptor.GetBattleDetail(this)); } catch (Exception ex) { - Utility.ErrorReporter.SendErrorReport(ex, "戦闘ログの出力に失敗しました。"); } } - } diff --git a/ElectronicObserver/Data/Battle/BattleNight.cs b/ElectronicObserver/Data/Battle/BattleNight.cs deleted file mode 100644 index 9fdb9d4dd..000000000 --- a/ElectronicObserver/Data/Battle/BattleNight.cs +++ /dev/null @@ -1,14 +0,0 @@ -using ElectronicObserver.Data.Battle.Phase; - -namespace ElectronicObserver.Data.Battle; - -/// -/// 夜戦の基底クラス -/// -public abstract class BattleNight : BattleData -{ - public PhaseNightInitial NightInitial { get; protected set; } - public PhaseFriendlyShelling FriendlyShelling { get; protected set; } - public PhaseNightBattle NightBattle { get; protected set; } - -} diff --git a/ElectronicObserver/Data/Battle/BattleNightOnly.cs b/ElectronicObserver/Data/Battle/BattleNightOnly.cs deleted file mode 100644 index 2d1bf2afb..000000000 --- a/ElectronicObserver/Data/Battle/BattleNightOnly.cs +++ /dev/null @@ -1,44 +0,0 @@ -using System.Collections.Generic; -using ElectronicObserver.Data.Battle.Phase; - -namespace ElectronicObserver.Data.Battle; - -/// -/// 通常/連合艦隊 vs 通常艦隊 開幕夜戦 -/// -public class BattleNightOnly : BattleNight -{ - - public override void LoadFromResponse(string apiname, dynamic data) - { - base.LoadFromResponse(apiname, (object)data); - - NightInitial = new PhaseNightInitial(this, "夜戦開始", false); - FriendlySupportInfo = new PhaseFriendlySupportInfo(this, "友軍艦隊"); - FriendlyShelling = new PhaseFriendlyShelling(this, "友軍艦隊援護"); - Support = new PhaseSupport(this, "夜間支援攻撃", true); - NightBattle = new PhaseNightBattle(this, "夜戦", 0); - - - foreach (var phase in GetPhases()) - phase.EmulateBattle(_resultHPs, _attackDamages); - } - - - public override string APIName => "api_req_battle_midnight/sp_midnight"; - - public override string BattleName => ConstantsRes.Title_NightOnly; - - - - public override IEnumerable GetPhases() - { - yield return Initial; - yield return Searching; - yield return NightInitial; - yield return FriendlySupportInfo; - yield return FriendlyShelling; - yield return Support; - yield return NightBattle; - } -} diff --git a/ElectronicObserver/Data/Battle/BattleNormalDay.cs b/ElectronicObserver/Data/Battle/BattleNormalDay.cs deleted file mode 100644 index c241accfa..000000000 --- a/ElectronicObserver/Data/Battle/BattleNormalDay.cs +++ /dev/null @@ -1,61 +0,0 @@ -using System.Collections.Generic; -using ElectronicObserver.Data.Battle.Phase; - -namespace ElectronicObserver.Data.Battle; - -/// -/// 通常艦隊 vs 通常艦隊 昼戦 -/// -public class BattleNormalDay : BattleDay -{ - - - public override void LoadFromResponse(string apiname, dynamic data) - { - base.LoadFromResponse(apiname, (object)data); - - JetBaseAirAttack = new PhaseJetBaseAirAttack(this, "噴式基地航空隊攻撃"); - JetAirBattle = new PhaseJetAirBattle(this, "噴式航空戦"); - BaseAirAttack = new PhaseBaseAirAttack(this, "基地航空隊攻撃"); - FriendlySupportInfo = new PhaseFriendlySupportInfo(this, "友軍艦隊"); - FriendlyAirBattle = new PhaseFriendlyAirBattle(this, "友軍支援航空攻撃"); - AirBattle = new PhaseAirBattle(this, "航空戦"); - Support = new PhaseSupport(this, "支援攻撃"); - OpeningASW = new PhaseOpeningASW(this, "先制対潜"); - OpeningTorpedo = new PhaseTorpedo(this, "先制雷撃", 0); - Shelling1 = new PhaseShelling(this, "第一次砲撃戦", 1, "1"); - Shelling2 = new PhaseShelling(this, "第二次砲撃戦", 2, "2"); - Shelling3 = new PhaseShelling(this, "第三次砲撃戦", 3, "3"); - Torpedo = new PhaseTorpedo(this, "雷撃戦", 4); - - foreach (var phase in GetPhases()) - phase.EmulateBattle(_resultHPs, _attackDamages); - - } - - - public override string APIName => "api_req_sortie/battle"; - - public override string BattleName => ConstantsRes.Title_NormalDay; - - - - public override IEnumerable GetPhases() - { - yield return Initial; - yield return Searching; - yield return JetBaseAirAttack; - yield return JetAirBattle; - yield return BaseAirAttack; - yield return FriendlySupportInfo; - yield return FriendlyAirBattle; - yield return AirBattle; - yield return Support; - yield return OpeningASW; - yield return OpeningTorpedo; - yield return Shelling1; - yield return Shelling2; - yield return Shelling3; - yield return Torpedo; - } -} diff --git a/ElectronicObserver/Data/Battle/BattleNormalDayFromNight.cs b/ElectronicObserver/Data/Battle/BattleNormalDayFromNight.cs deleted file mode 100644 index 8fef93a07..000000000 --- a/ElectronicObserver/Data/Battle/BattleNormalDayFromNight.cs +++ /dev/null @@ -1,74 +0,0 @@ -using System.Collections.Generic; -using ElectronicObserver.Data.Battle.Phase; - -namespace ElectronicObserver.Data.Battle; - -/// -/// 通常/連合艦隊 vs 通常艦隊 夜昼戦 -/// -public class BattleNormalDayFromNight : BattleDayFromNight -{ - - public override void LoadFromResponse(string apiname, dynamic data) - { - base.LoadFromResponse(apiname, (object)data); - - NightInitial = new PhaseNightInitial(this, "夜戦開始", false); - FriendlySupportInfo = new PhaseFriendlySupportInfo(this, "友軍艦隊"); - FriendlyShelling = new PhaseFriendlyShelling(this, "友軍艦隊援護"); - NightSupport = new PhaseSupport(this, "夜間支援攻撃", true); - NightBattle = new PhaseNightBattle(this, "第一次夜戦", 1); - NightBattle2 = new PhaseNightBattle(this, "第二次夜戦", 2); - - - if (NextToDay) - { - JetBaseAirAttack = new PhaseJetBaseAirAttack(this, "噴式基地航空隊攻撃"); - JetAirBattle = new PhaseJetAirBattle(this, "噴式航空戦"); - BaseAirAttack = new PhaseBaseAirAttack(this, "基地航空隊攻撃"); - Support = new PhaseSupport(this, "支援攻撃"); - // ここに友軍艦隊航空攻撃が来るかわからない - AirBattle = new PhaseAirBattle(this, "航空戦"); - OpeningASW = new PhaseOpeningASW(this, "先制対潜"); - OpeningTorpedo = new PhaseTorpedo(this, "先制雷撃", 0); - Shelling1 = new PhaseShelling(this, "第一次砲撃戦", 1, "1"); - Shelling2 = new PhaseShelling(this, "第二次砲撃戦", 2, "2"); - Torpedo = new PhaseTorpedo(this, "雷撃戦", 3); - } - - foreach (var phase in GetPhases()) - phase.EmulateBattle(_resultHPs, _attackDamages); - } - - public override string APIName => "api_req_sortie/night_to_day"; - - public override string BattleName => "対通常艦隊 夜昼戦"; - - - - public override IEnumerable GetPhases() - { - yield return Initial; - yield return Searching; - yield return NightInitial; - yield return FriendlySupportInfo; - yield return FriendlyShelling; - yield return NightSupport; - yield return NightBattle; - yield return NightBattle2; - - if (NextToDay) - { - yield return JetBaseAirAttack; - yield return JetAirBattle; - yield return BaseAirAttack; - yield return Support; - yield return AirBattle; - yield return OpeningASW; - yield return OpeningTorpedo; - yield return Shelling1; - yield return Shelling2; - yield return Torpedo; - } - } -} diff --git a/ElectronicObserver/Data/Battle/BattleNormalNight.cs b/ElectronicObserver/Data/Battle/BattleNormalNight.cs deleted file mode 100644 index 4e6d1c080..000000000 --- a/ElectronicObserver/Data/Battle/BattleNormalNight.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System.Collections.Generic; -using ElectronicObserver.Data.Battle.Phase; - -namespace ElectronicObserver.Data.Battle; - -/// -/// 通常艦隊 vs 通常艦隊 夜戦 -/// -public class BattleNormalNight : BattleNight -{ - - public override void LoadFromResponse(string apiname, dynamic data) - { - base.LoadFromResponse(apiname, (object)data); - - NightInitial = new PhaseNightInitial(this, "夜戦開始", false); - FriendlySupportInfo = new PhaseFriendlySupportInfo(this, "友軍艦隊"); - FriendlyShelling = new PhaseFriendlyShelling(this, "友軍艦隊援護"); - // 支援なし? - NightBattle = new PhaseNightBattle(this, "夜戦", 0); - - foreach (var phase in GetPhases()) - phase.EmulateBattle(_resultHPs, _attackDamages); - } - - - public override string APIName => "api_req_battle_midnight/battle"; - - public override string BattleName => ConstantsRes.Title_NormalNight; - - - - public override IEnumerable GetPhases() - { - yield return Initial; - yield return NightInitial; - yield return FriendlySupportInfo; - yield return FriendlyShelling; - yield return NightBattle; - } -} diff --git a/ElectronicObserver/Data/Battle/BattleNormalRadar.cs b/ElectronicObserver/Data/Battle/BattleNormalRadar.cs deleted file mode 100644 index c72ff7edf..000000000 --- a/ElectronicObserver/Data/Battle/BattleNormalRadar.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.Collections.Generic; -using ElectronicObserver.Data.Battle.Phase; - -namespace ElectronicObserver.Data.Battle; - -/// -/// 通常艦隊 vs 通常艦隊 レーダー射撃 -/// -public class BattleNormalRadar : BattleDay -{ - public override void LoadFromResponse(string apiname, dynamic data) - { - base.LoadFromResponse(apiname, (object)data); - - JetBaseAirAttack = new PhaseJetBaseAirAttack(this, "噴式基地航空隊攻撃"); - BaseAirAttack = new PhaseBaseAirAttack(this, "基地航空隊攻撃"); - Shelling1 = new PhaseRadar(this, "レーダー射撃"); - - foreach (var phase in GetPhases()) - phase.EmulateBattle(_resultHPs, _attackDamages); - } - - public override string APIName => "api_req_sortie/ld_shooting"; - - public override string BattleName => "通常艦隊 レーダー射撃"; - - public override IEnumerable GetPhases() - { - yield return Initial; - yield return Searching; // ? - yield return JetBaseAirAttack; - yield return BaseAirAttack; - yield return Shelling1; - } -} diff --git a/ElectronicObserver/Data/Battle/BattlePracticeDay.cs b/ElectronicObserver/Data/Battle/BattlePracticeDay.cs deleted file mode 100644 index a9121ee91..000000000 --- a/ElectronicObserver/Data/Battle/BattlePracticeDay.cs +++ /dev/null @@ -1,52 +0,0 @@ -using System.Collections.Generic; -using ElectronicObserver.Data.Battle.Phase; - -namespace ElectronicObserver.Data.Battle; - -/// -/// 演習 昼戦 -/// -public class BattlePracticeDay : BattleDay -{ - - public override void LoadFromResponse(string apiname, dynamic data) - { - base.LoadFromResponse(apiname, (object)data); - - JetAirBattle = new PhaseJetAirBattle(this, "噴式航空戦"); - AirBattle = new PhaseAirBattle(this, "航空戦"); - OpeningASW = new PhaseOpeningASW(this, "先制対潜"); - OpeningTorpedo = new PhaseTorpedo(this, "先制雷撃", 0); - Shelling1 = new PhaseShelling(this, "第一次砲撃戦", 1, "1"); - Shelling2 = new PhaseShelling(this, "第二次砲撃戦", 2, "2"); - Shelling3 = new PhaseShelling(this, "第三次砲撃戦", 3, "3"); - Torpedo = new PhaseTorpedo(this, "雷撃戦", 4); - - - foreach (var phase in GetPhases()) - phase.EmulateBattle(_resultHPs, _attackDamages); - - } - - - public override string APIName => "api_req_practice/battle"; - - public override string BattleName => ConstantsRes.Title_PracticeDay; - - public override bool IsPractice => true; - - - public override IEnumerable GetPhases() - { - yield return Initial; - yield return Searching; - yield return JetAirBattle; - yield return AirBattle; - yield return OpeningASW; - yield return OpeningTorpedo; - yield return Shelling1; - yield return Shelling2; - yield return Shelling3; - yield return Torpedo; - } -} diff --git a/ElectronicObserver/Data/Battle/BattlePracticeNight.cs b/ElectronicObserver/Data/Battle/BattlePracticeNight.cs deleted file mode 100644 index c009f2797..000000000 --- a/ElectronicObserver/Data/Battle/BattlePracticeNight.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System.Collections.Generic; -using ElectronicObserver.Data.Battle.Phase; - -namespace ElectronicObserver.Data.Battle; - -/// -/// 演習 夜戦 -/// -public class BattlePracticeNight : BattleNight -{ - - public override void LoadFromResponse(string apiname, dynamic data) - { - base.LoadFromResponse(apiname, (object)data); - - NightInitial = new PhaseNightInitial(this, "夜戦開始", false); - NightBattle = new PhaseNightBattle(this, "夜戦", 0); - - NightBattle.EmulateBattle(_resultHPs, _attackDamages); - - } - - - public override string APIName => "api_req_practice/midnight_battle"; - - public override string BattleName => ConstantsRes.Title_PracticeNight; - - public override bool IsPractice => true; - - - public override IEnumerable GetPhases() - { - yield return Initial; - yield return NightInitial; - yield return NightBattle; - } -} diff --git a/ElectronicObserver/Data/Battle/BattleResultData.cs b/ElectronicObserver/Data/Battle/BattleResultData.cs deleted file mode 100644 index 4707a7e3d..000000000 --- a/ElectronicObserver/Data/Battle/BattleResultData.cs +++ /dev/null @@ -1,250 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace ElectronicObserver.Data.Battle; - -/// -/// 戦闘結果のデータを扱います。 -/// -public class BattleResultData : ResponseWrapper -{ - - /// - /// 現在保存されているAPIの名前 - /// - private string _APIName { get; set; } - - - - // :( - /// - /// 演習の結果かどうか - /// - private bool IsPractice => _APIName == "api_req_practice/battle_result"; - - - - - /// - /// 勝利ランク - /// - public string Rank => RawData.api_win_rank; - - /// - /// 獲得提督経験値 - /// - public int AdmiralExp => (int)RawData.api_get_exp; - - /// - /// MVP艦のインデックス (1-6, -1=なし) - /// - public int MVPIndex => (int)RawData.api_mvp; - - /// - /// 随伴艦隊 MVP 艦のインデックス (1-6, -1=なし) - /// - public int MVPIndexCombined => RawData.api_mvp_combined() && RawData.api_mvp_combined != null ? (int)RawData.api_mvp_combined : -1; - - - /// - /// 獲得基本経験値 - /// - public int BaseExp => (int)RawData.api_get_base_exp; - - - /// - /// 主力艦隊の入手経験値リスト [0-5] - /// 欠番は -1 - /// - public int[] ExpList - { - get - { - if (!RawData.api_get_ship_exp()) - return new int[6]; - - var src = (int[])RawData.api_get_ship_exp; - var ret = new int[Math.Max(src.Length - 1, 6)]; - Array.Copy(src, 1, ret, 0, src.Length - 1); - return ret; - } - } - - /// - /// 随伴艦隊の入手経験値リスト [0-5] - /// 欠番は -1 - /// - public int[] ExpListCombined - { - get - { - if (!RawData.api_get_ship_exp_combined()) - return new int[6]; - - var src = (int[])RawData.api_get_ship_exp_combined; - var ret = new int[Math.Max(src.Length - 1, 6)]; - Array.Copy(src, 1, ret, 0, src.Length - 1); - return ret; - } - } - - /// - /// 主力艦隊のレベルアップリスト [所属艦船数] - /// [0]=現在のexp, [1]=(あれば)次のレベルの経験値, [2]=(あれば)その次のレベルの経験値, ... - /// - public int[][] LevelUpList - { - get - { - if (!RawData.api_get_exp_lvup()) - return new int[0][]; - - var ret = new List(); - foreach (var data in RawData.api_get_exp_lvup) - { - ret.Add((int[])data); - } - return ret.ToArray(); - } - } - - /// - /// 随伴艦隊のレベルアップリスト [所属艦船数] - /// [0]=現在のexp, [1]=(あれば)次のレベルの経験値, [2]=(あれば)その次のレベルの経験値, ... - /// - public int[][] LevelUpListCombined - { - get - { - if (!RawData.api_get_exp_lvup_combined()) - return new int[0][]; - - var ret = new List(); - foreach (var data in RawData.api_get_exp_lvup_combined) - { - ret.Add((int[])data); - } - return ret.ToArray(); - } - } - - - //lostflag - - - /// - /// 敵艦隊名 - /// - public string EnemyFleetName => RawData.api_enemy_info.api_deck_name; - - //undone: 複数の battleresult に対応させる - - - /// - /// ドロップした艦船のID - /// - public int DroppedShipID - { - get - { - if (IsPractice) - return -1; - if ((int)RawData.api_get_flag[1] == 0) - return -1; - - return (int)RawData.api_get_ship.api_ship_id; - } - } - - - /// - /// ドロップしたアイテムのID - /// - public int DroppedItemID - { - get - { - if (IsPractice) - return -1; - if ((int)RawData.api_get_flag[0] == 0) - return -1; - - return (int)RawData.api_get_useitem.api_useitem_id; - } - } - - - /// - /// ドロップした装備のID(現在未使用) - /// - public int DroppedEquipmentID - { - get - { - if (IsPractice) - return -1; - if ((int)RawData.api_get_flag[2] == 0) - return -1; - - return (int)RawData.api_get_slotitem.api_slotitem_id; - } - } - - - - - /// - /// 護衛退避可能か - /// - public bool CanEscape - { - get - { - if (!RawData.api_escape()) - { - return false; - } - else - { - return (int)RawData.api_escape != 0; - } - } - } - - /// - /// 退避艦のインデックス - /// - public IEnumerable EscapingShipIndex - { - get - { - if (!RawData.api_escape()) - { - return null; - } - else if (!RawData.api_escape.api_tow_idx()) - { - return new int[1] { (int)RawData.api_escape.api_escape_idx[0] }; - } - else - { - return new int[2] { (int)RawData.api_escape.api_escape_idx[0], (int)RawData.api_escape.api_tow_idx[0] }; - } - - } - } - - /// - /// api_first_clear is 1 when clearing a map for the first time - /// for maps with gauges it's 1 every time the last gauge is cleared - /// - public bool IsFirstClear => RawData.api_first_clear > 0; - - public override void LoadFromResponse(string apiname, dynamic data) - { - base.LoadFromResponse(apiname, (object)data); - - _APIName = apiname; - - } -} diff --git a/ElectronicObserver/Data/Battle/Detail/BattleDetail.cs b/ElectronicObserver/Data/Battle/Detail/BattleDetail.cs deleted file mode 100644 index d51988cb7..000000000 --- a/ElectronicObserver/Data/Battle/Detail/BattleDetail.cs +++ /dev/null @@ -1,488 +0,0 @@ -using System; -using System.Linq; -using System.Text; -using ElectronicObserver.Core.Types; -using ElectronicObserver.Core.Types.Attacks; -using ElectronicObserver.Utility.Data; - -namespace ElectronicObserver.Data.Battle.Detail; - -/// -/// 戦闘詳細のデータを保持します。 -/// -public abstract class BattleDetail -{ - - public double[] RawDamages { get; protected set; } - public int[] Damages { get; protected set; } - public bool[] GuardsFlagship { get; protected set; } - public CriticalType[] CriticalTypes { get; protected set; } - public int AttackType { get; protected set; } - public int[] EquipmentIDs { get; protected set; } - public int DefenderHP { get; protected set; } - - public IShipDataMaster Attacker { get; protected set; } - public IShipDataMaster Defender { get; protected set; } - - - /// 攻撃側インデックス - public BattleIndex AttackerIndex { get; protected set; } - - /// 防御側インデックス - public BattleIndex DefenderIndex { get; protected set; } - - - protected readonly BattleData Battle; - - - public enum CriticalType - { - Miss = 0, - Hit = 1, - Critical = 2, - Invalid = -1 - } - - - /// 戦闘情報。 - /// 攻撃側のインデックス。 - /// 防御側のインデックス。 - /// ダメージの配列。 - /// 命中判定の配列。 - /// 攻撃種別。 - /// 防御側の攻撃を受ける直前のHP。 - public BattleDetail(BattleData bd, BattleIndex attackerIndex, BattleIndex defenderIndex, double[] damages, int[] criticalTypes, int attackType, int[] equipmentIDs, int defenderHP) - { - Battle = bd; - - AttackerIndex = attackerIndex; - DefenderIndex = defenderIndex; - RawDamages = damages; - Damages = damages.Select(dmg => (int)dmg).ToArray(); - GuardsFlagship = damages.Select(dmg => dmg != Math.Floor(dmg)).ToArray(); - CriticalTypes = criticalTypes.Select(i => (CriticalType)i).ToArray(); - AttackType = attackType; - EquipmentIDs = equipmentIDs; - DefenderHP = defenderHP; - - } - - - protected int[] SetAttacker() - { - if (AttackerIndex < 0) - { - Attacker = null; - return null; - } - else - { - switch (AttackerIndex.Side) - { - case BattleSides.FriendMain: - { - var atk = Battle.Initial.FriendFleet.MembersInstance[AttackerIndex.Index]; - Attacker = atk.MasterShip; - return atk.AllSlotMaster.ToArray(); - } - - case BattleSides.FriendEscort: - { - var atk = Battle.Initial.FriendFleetEscort.MembersInstance[AttackerIndex.Index]; - Attacker = atk.MasterShip; - return atk.AllSlotMaster.ToArray(); - } - - case BattleSides.EnemyMain: - Attacker = Battle.Initial.EnemyMembersInstance[AttackerIndex.Index]; - return Battle.Initial.EnemySlots[AttackerIndex.Index]; - - case BattleSides.EnemyEscort: - Attacker = Battle.Initial.EnemyMembersEscortInstance[AttackerIndex.Index]; - return Battle.Initial.EnemySlotsEscort[AttackerIndex.Index]; - - default: - throw new NotSupportedException(); - } - } - } - - protected void SetDefender() - { - if (Battle.IsBaseAirRaid) - { - Defender = null; - } - else - { - switch (DefenderIndex.Side) - { - case BattleSides.FriendMain: - Defender = Battle.Initial.FriendFleet.MembersInstance[DefenderIndex.Index].MasterShip; - break; - - case BattleSides.FriendEscort: - Defender = Battle.Initial.FriendFleetEscort.MembersInstance[DefenderIndex.Index].MasterShip; - break; - - case BattleSides.EnemyMain: - Defender = Battle.Initial.EnemyMembersInstance[DefenderIndex.Index]; - break; - - case BattleSides.EnemyEscort: - Defender = Battle.Initial.EnemyMembersEscortInstance[DefenderIndex.Index]; - break; - } - } - - } - - - - /// - /// 戦闘詳細の情報を出力します。 - /// - public override string ToString() - { - - StringBuilder builder = new StringBuilder(); - - - if (Battle.IsPractice) - builder.AppendFormat("{0}{1} → {2}{3}", - Attacker == null ? "" : AttackerIndex.IsFriend ? $"{BattleRes.Friendly} " : $"{BattleRes.Enemy} ", GetAttackerName(), - DefenderIndex.IsFriend ? $"{BattleRes.Friendly} " : $"{BattleRes.Enemy} ", GetDefenderName() - ).AppendLine(); - else - builder.AppendFormat("{0} → {1}", GetAttackerName(), GetDefenderName()).AppendLine(); - - - if (AttackType >= 0) - builder.Append("[").Append(GetAttackKind()).Append("] "); - - /*// - if ( EquipmentIDs != null ) { - var eqs = EquipmentIDs.Select( id => KCDatabase.Instance.MasterEquipments[id] ).Where( eq => eq != null ).Select( eq => eq.Name ); - if ( eqs.Any() ) - builder.Append( "(" ).Append( string.Join( ", ", eqs ) ).Append( ") " ); - } - //*/ - - for (int i = 0; i < Damages.Length; i++) - { - if (CriticalTypes[i] == CriticalType.Invalid) // カットイン(主砲/主砲)、カットイン(主砲/副砲)時に発生する - continue; - - if (i > 0) - builder.Append(" , "); - - if (GuardsFlagship[i]) - builder.Append($"<{BattleRes.Protected}> "); - - switch (CriticalTypes[i]) - { - case CriticalType.Miss: - builder.Append("Miss"); - break; - case CriticalType.Hit: - builder.Append(Damages[i]).Append(" Dmg"); - break; - case CriticalType.Critical: - builder.Append(Damages[i]).Append(" Critical!"); - break; - } - - } - - - int beforeHP = Math.Max(DefenderHP, 0); - int afterHP = Math.Max(DefenderHP - Damages.Sum(), 0); - if (beforeHP != afterHP) - builder.AppendFormat(" ( {0} → {1} )", beforeHP, afterHP); - - - - builder.AppendLine(); - - - // damage control - if (beforeHP > 0 && afterHP <= 0 && DefenderIndex.IsFriend && !Battle.IsPractice && !Battle.IsBaseAirRaid) - { - var defender = (DefenderIndex.Side == BattleSides.FriendEscort ? Battle.Initial.FriendFleetEscort : Battle.Initial.FriendFleet) - ?.MembersInstance?.ElementAtOrDefault(DefenderIndex.Index); - if (defender != null) - { - int id = defender.DamageControlID; - - if (id == 42) - builder.AppendFormat($" {BattleRes.DameconActivated} HP{0}", (int)(defender.HPMax * 0.2)).AppendLine(); - - else if (id == 43) - builder.AppendFormat($" {BattleRes.GoddessActivated} HP{0}", defender.HPMax).AppendLine(); - - } - } - return builder.ToString(); - } - - - protected virtual string GetAttackerName() - { - int index = AttackerIndex.Index + 1 + (AttackerIndex.IsEscort ? 6 : 0); - - if (Attacker == null) - return "#" + index; - - return Attacker.NameWithClass + " #" + index; - } - - protected virtual string GetDefenderName() - { - int index = DefenderIndex.Index + 1 + (DefenderIndex.IsEscort ? 6 : 0); - - if (Defender == null) - return "#" + index; - return Defender.NameWithClass + " #" + index; - } - - protected abstract int CaclulateAttackKind(int[] slots, int attackerShipID, int defenderShipID); - protected abstract string GetAttackKind(); - -} - - -/// -/// 昼戦の戦闘詳細データを保持します。 -/// -public class BattleDayDetail : BattleDetail -{ - - public BattleDayDetail(BattleData bd, BattleIndex attackerId, BattleIndex defenderId, double[] damages, int[] criticalTypes, int attackType, int[] equipmentIDs, int defenderHP) - : base(bd, attackerId, defenderId, damages, criticalTypes, attackType, equipmentIDs, defenderHP) - { - var attackerSlots = SetAttacker(); - SetDefender(); - - if (AttackType == 0 && Attacker != null) - AttackType = CaclulateAttackKind(attackerSlots, Attacker.ShipID, Defender.ShipID); - - } - - protected override int CaclulateAttackKind(int[] slots, int attackerShipID, int defenderShipID) - { - return (int)Calculator.GetDayAttackKind(slots, attackerShipID, defenderShipID, false); - } - - protected override string GetAttackKind() - { - return DayAttack.AttackDisplay((DayAttackKind)AttackType); - } -} - -/// -/// 支援攻撃の戦闘詳細データを保持します。 -/// -public class BattleSupportDetail : BattleDetail -{ - - public BattleSupportDetail(BattleData bd, BattleIndex defenderId, double damage, int criticalType, int attackType, int defenderHP) - : base(bd, BattleIndex.Invalid, defenderId, new double[] { damage }, new int[] { criticalType }, attackType, null, defenderHP) - { - var attackerSlots = SetAttacker(); - SetDefender(); - - if (AttackType == 0 && Attacker != null) - AttackType = CaclulateAttackKind(attackerSlots, Attacker.ShipID, Defender.ShipID); - } - - protected override string GetAttackerName() - { - return BattleRes.SupportFleet; - } - - protected override int CaclulateAttackKind(int[] slots, int attackerShipID, int defenderShipID) - { - return -1; - } - - protected override string GetAttackKind() - { - switch (AttackType) - { - case 1: - return ConstantsRes.AirAttack; - case 2: - return ConstantsRes.Shelling; - case 3: - return ConstantsRes.TorpedoAttack; - case 4: - return ConstantsRes.BombingAttack; - default: - return ConstantsRes.Unknown; - } - } - -} - -/// -/// 夜戦における戦闘詳細データを保持します。 -/// -public class BattleNightDetail : BattleDetail -{ - - public bool NightAirAttackFlag { get; protected set; } - - public BattleNightDetail(BattleData bd, BattleIndex attackerId, BattleIndex defenderId, double[] damages, int[] criticalTypes, int attackType, int[] equipmentIDs, bool nightAirAttackFlag, int defenderHP) - : base(bd, attackerId, defenderId, damages, criticalTypes, attackType, equipmentIDs, defenderHP) - { - NightAirAttackFlag = nightAirAttackFlag; - - var attackerSlots = SetAttacker(); - SetDefender(); - - if (AttackType == 0 && Attacker != null) - AttackType = CaclulateAttackKind(attackerSlots, Attacker.ShipID, Defender.ShipID); - } - - protected override int CaclulateAttackKind(int[] slots, int attackerShipID, int defenderShipID) - { - return (int)Calculator.GetNightAttackKind(slots, attackerShipID, defenderShipID, false, NightAirAttackFlag); - } - - protected override string GetAttackKind() - { - return NightAttack.AttackDisplay((NightAttackKind)AttackType); - } -} - -/// -/// 航空戦における戦闘詳細データを保持します。 -/// -public class BattleAirDetail : BattleDayDetail -{ - public int WaveIndex { get; protected set; } - - public BattleAirDetail(BattleData bd, int waveIndex, BattleIndex defenderId, double damage, int criticalType, int attackType, int defenderHP) - : base(bd, BattleIndex.Invalid, defenderId, new double[] { damage }, new int[] { criticalType }, attackType, null, defenderHP) - { - WaveIndex = waveIndex; - } - - protected override string GetAttackerName() - { - if (WaveIndex <= 0) - { - if (DefenderIndex.Side == BattleSides.FriendMain || DefenderIndex.Side == BattleSides.FriendEscort) - return BattleRes.EnemyAirSquadron; - else - return BattleRes.FriendlyAirSquadron; - - } - else - { - return string.Format(BattleRes.AirSquadronWave, WaveIndex); - - } - } - - protected override string GetDefenderName() - { - if (WaveIndex < 0 && DefenderIndex.Side == BattleSides.FriendMain) - return string.Format(BattleRes.Base, DefenderIndex.Index + 1); - - return base.GetDefenderName(); - } - - protected override int CaclulateAttackKind(int[] slots, int attackerShipID, int defenderShipID) - { - return -1; - } - - protected override string GetAttackKind() - { - switch (AttackType) - { - case 1: - return ConstantsRes.TorpedoAttack; - case 2: - return ConstantsRes.BombingAttack; - case 3: - return ConstantsRes.TorpBombingAttack; - default: - return ConstantsRes.Unknown; - } - } - -} - - -/// -/// 友軍艦隊砲撃における戦闘詳細データを保持します。 -/// -public class BattleFriendlyShellingDetail : BattleDetail -{ - - public bool NightAirAttackFlag { get; protected set; } - - public BattleFriendlyShellingDetail(BattleNight bd, BattleIndex attackerId, BattleIndex defenderId, double[] damages, int[] criticalTypes, int attackType, int[] equipmentIDs, bool nightAirAttackFlag, int defenderHP) - : base(bd, attackerId, defenderId, damages, criticalTypes, attackType, equipmentIDs, defenderHP) - { - NightAirAttackFlag = nightAirAttackFlag; - - int[] attackerSlots; - - if (attackerId.IsFriend) - { - Attacker = bd.FriendlySupportInfo.FriendlyMembersInstance[attackerId.Index]; - attackerSlots = bd.FriendlySupportInfo.FriendlySlots[attackerId.Index]; - } - else - { - attackerSlots = SetAttacker(); - } - - if (defenderId.IsFriend) - Defender = bd.FriendlySupportInfo.FriendlyMembersInstance[defenderId.Index]; - else - SetDefender(); - - - if (AttackType == 0 && Attacker != null) - AttackType = CaclulateAttackKind(attackerSlots, Attacker.ShipID, Defender.ShipID); - } - - protected override int CaclulateAttackKind(int[] slots, int attackerShipID, int defenderShipID) - { - return (int)Calculator.GetNightAttackKind(slots, attackerShipID, defenderShipID, false, NightAirAttackFlag); - } - - protected override string GetAttackKind() - { - return NightAttack.AttackDisplay((NightAttackKind)AttackType); - } -} - -/// -/// 友軍艦隊航空攻撃における戦闘詳細データを保持します。 -/// -public class BattleFriendlyAirDetail : BattleAirDetail -{ - public BattleFriendlyAirDetail(BattleData bd, BattleIndex defenderId, double damage, int criticalType, int attackType, int defenderHP) - : base(bd, 0, defenderId, damage, criticalType, attackType, defenderHP) - { - if (defenderId.IsFriend) - Defender = bd.FriendlySupportInfo.FriendlyMembersInstance[defenderId.Index]; - else - SetDefender(); - } - - protected override string GetDefenderName() - { - if (DefenderIndex.IsFriend) - { - return Battle.FriendlySupportInfo.FriendlyMembersInstance[DefenderIndex.Index].NameWithClass + " #" + (DefenderIndex.Index + 1); - } - - return base.GetDefenderName(); - } -} diff --git a/ElectronicObserver/Data/Battle/Phase/PhaseAirBattle.cs b/ElectronicObserver/Data/Battle/Phase/PhaseAirBattle.cs deleted file mode 100644 index 348d5ea0a..000000000 --- a/ElectronicObserver/Data/Battle/Phase/PhaseAirBattle.cs +++ /dev/null @@ -1,109 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using ElectronicObserver.Core.Types; -using ElectronicObserver.Data.Battle.Detail; - -namespace ElectronicObserver.Data.Battle.Phase; - -/// -/// 航空戦フェーズの処理を行います。 -/// -public class PhaseAirBattle : PhaseAirBattleBase -{ - - public PhaseAirBattle(BattleData data, string title, string suffix = "") - : base(data, title) - { - - AirBattleData = RawData.IsDefined("api_kouku" + suffix) ? RawData["api_kouku" + suffix] : null; - StageFlag = RawData.IsDefined("api_stage_flag" + suffix) ? (int[])RawData["api_stage_flag" + suffix] : null; - - LaunchedShipIndexFriend = GetLaunchedShipIndex(0); - LaunchedShipIndexEnemy = GetLaunchedShipIndex(1); - - TorpedoFlags = ConcatStage3Array("api_frai_flag", "api_erai_flag"); - BomberFlags = ConcatStage3Array("api_fbak_flag", "api_ebak_flag"); - Criticals = ConcatStage3Array("api_fcl_flag", "api_ecl_flag"); - Damages = ConcatStage3Array("api_fdam", "api_edam"); - } - - - public override void EmulateBattle(int[] hps, int[] damages) - { - if (!IsAvailable) return; - - CalculateAttack(0, hps); - CalculateAttackDamage(damages); - } - - - - /// - /// 航空戦での与ダメージを推測します。 - /// - /// 与ダメージリスト。 - private void CalculateAttackDamage(int[] damages) - { - // 敵はめんどくさすぎるので省略 - // 仮想火力を求め、それに従って合計ダメージを分配 - - var firepower = new int[12]; - var launchedIndex = LaunchedShipIndexFriend; - - foreach (int i in launchedIndex) - { - var ship = Battle.Initial.GetFriendShip(i); - - if (ship == null) - continue; - - var slots = ship.SlotInstanceMaster; - var aircrafts = ship.Aircraft; - for (int s = 0; s < slots.Count; s++) - { - - if (slots[s] == null) - continue; - - switch (slots[s].CategoryType) - { - // 通常の爆撃機系 - case EquipmentTypes.CarrierBasedBomber: - case EquipmentTypes.SeaplaneBomber: - firepower[i] += (int)(1.0 * (slots[s].Bomber * Math.Sqrt(aircrafts[s]) + 25)); - break; - - // 噴式爆撃機 - case EquipmentTypes.JetBomber: - firepower[i] += (int)(1.0 / Math.Sqrt(2) * (slots[s].Bomber * Math.Sqrt(aircrafts[s]) + 25)); - break; - - // 通常の攻撃機系 (80%と150%はランダムのため係数は平均値) - case EquipmentTypes.CarrierBasedTorpedo: - firepower[i] += (int)(1.15 * (slots[s].Torpedo * Math.Sqrt(aircrafts[s]) + 25)); - break; - - // 噴式攻撃機(いる?) - case EquipmentTypes.JetTorpedo: - firepower[i] += (int)(1.15 / Math.Sqrt(2) * (slots[s].Torpedo * Math.Sqrt(aircrafts[s]) + 25)); - break; - } - } - } - - int totalFirepower = firepower.Sum(); - int totalDamage = Damages.Select(dmg => (int)dmg).Skip(12).Take(12).Sum(); - - for (int i = 0; i < firepower.Length; i++) - { - damages[i] += (int)Math.Round((double)totalDamage * firepower[i] / Math.Max(totalFirepower, 1)); - } - } - - protected override IEnumerable SearchBattleDetails(int index) - { - return BattleDetails.Where(d => d.DefenderIndex == index); - } - -} diff --git a/ElectronicObserver/Data/Battle/Phase/PhaseAirBattleBase.cs b/ElectronicObserver/Data/Battle/Phase/PhaseAirBattleBase.cs deleted file mode 100644 index ce916e4e4..000000000 --- a/ElectronicObserver/Data/Battle/Phase/PhaseAirBattleBase.cs +++ /dev/null @@ -1,272 +0,0 @@ -using System; -using System.Linq; -using ElectronicObserver.Core.Types; -using ElectronicObserver.Data.Battle.Detail; - -namespace ElectronicObserver.Data.Battle.Phase; - -/// -/// 航空戦フェーズ処理の基底となるクラスです。 -/// -public abstract class PhaseAirBattleBase : PhaseBase -{ - - public PhaseAirBattleBase(BattleData data, string title) - : base(data, title) - { - - } - - public override bool IsAvailable => StageFlag != null && StageFlag.Any(i => i != 0); - - - - /// - /// 被ダメージ処理を行います。 - /// - /// (基地航空隊の場合)現在の攻撃ウェーブのインデックス。それ以外の場合は 0 - /// 現在のHPリスト。 - protected void CalculateAttack(int waveIndex, int[] hps) - { - for (int i = 0; i < hps.Length; i++) - { - - int attackType = (TorpedoFlags[i] > 0 ? 1 : 0) | (BomberFlags[i] > 0 ? 2 : 0); - if (attackType > 0) - { - - // 航空戦は miss/hit=0, critical=1 のため +1 する(通常は miss=0, hit=1, critical=2) - BattleDetails.Add(new BattleAirDetail(Battle, waveIndex, new BattleIndex(i, Battle.IsFriendCombined, Battle.IsEnemyCombined), Damages[i], Criticals[i] + 1, attackType, hps[i])); - AddDamage(hps, i, (int)Damages[i]); - } - } - } - - - - /// - /// 各 Stage が存在するか - /// - public int[] StageFlag { get; protected set; } - - /// - /// 航空戦の生データ - /// - public dynamic AirBattleData { get; protected set; } - - - /// - /// 航空機を発艦させた自軍艦船のインデックス 値は[0-11] - /// - public int[] LaunchedShipIndexFriend { get; protected set; } - - /// - /// 航空機を発艦させた敵軍艦船のインデックス 値は[0-11] - /// - public int[] LaunchedShipIndexEnemy { get; protected set; } - - - /// - /// 航空機を発艦させた艦船のインデックスを取得します。 - /// - /// 取得する配列のインデックス。基本的に 0=自軍, 1=敵軍 - protected int[] GetLaunchedShipIndex(int index) - { - if (AirBattleData == null) - return null; - - if (!AirBattleData.api_plane_from()) - return new int[0]; - - dynamic data = AirBattleData.api_plane_from; - - if (data == null || !data.IsArray) - return new int[0]; - - var planes = (dynamic[]?)data; - if (index < planes?.Length) - { - var plane = (int[])planes[index]; - - if (plane == null) - return new int[0]; - - return plane.Where(i => i > 0).Select(i => i - 1).ToArray(); - } - - return new int[0]; - } - - - // stage 1 - - /// - /// Stage1(空対空戦闘)が存在するか - /// - public bool IsStage1Available => StageFlag != null && StageFlag[0] != 0 && AirBattleData.api_stage1() && AirBattleData.api_stage1 != null; - - /// - /// 自軍Stage1参加機数 - /// - public int AircraftTotalStage1Friend => (int)AirBattleData.api_stage1.api_f_count; - - /// - /// 敵軍Stage1参加機数 - /// - public int AircraftTotalStage1Enemy => (int)AirBattleData.api_stage1.api_e_count; - - /// - /// 自軍Stage1撃墜機数 - /// - public int AircraftLostStage1Friend => (int)AirBattleData.api_stage1.api_f_lostcount; - - /// - /// 敵軍Stage1撃墜機数 - /// - public int AircraftLostStage1Enemy => (int)AirBattleData.api_stage1.api_e_lostcount; - - /// - /// 制空権 - /// - public int AirSuperiority => !AirBattleData.api_stage1.api_disp_seiku() ? -1 : (int)AirBattleData.api_stage1.api_disp_seiku; - - /// - /// 自軍触接機ID - /// - public int TouchAircraftFriend => !AirBattleData.api_stage1.api_touch_plane() ? -1 : (int)AirBattleData.api_stage1.api_touch_plane[0]; - - /// - /// 敵軍触接機ID - /// - public int TouchAircraftEnemy => !AirBattleData.api_stage1.api_touch_plane() ? -1 : (int)AirBattleData.api_stage1.api_touch_plane[1]; - - - // stage 2 - - /// - /// Stage2(艦対空戦闘)が存在するか - /// - public bool IsStage2Available => StageFlag != null && StageFlag[1] != 0 && AirBattleData.api_stage2() && AirBattleData.api_stage2 != null; - - /// - /// 自軍Stage2参加機数 - /// - public int AircraftTotalStage2Friend => (int)AirBattleData.api_stage2.api_f_count; - - /// - /// 敵軍Stage2参加機数 - /// - public int AircraftTotalStage2Enemy => (int)AirBattleData.api_stage2.api_e_count; - - /// - /// 自軍Stage2撃墜機数 - /// - public int AircraftLostStage2Friend => (int)AirBattleData.api_stage2.api_f_lostcount; - - /// - /// 敵軍Stage2撃墜機数 - /// - public int AircraftLostStage2Enemy => (int)AirBattleData.api_stage2.api_e_lostcount; - - - /// - /// 対空カットインが発動したか - /// - public bool IsAACutinAvailable => AirBattleData.api_stage2.api_air_fire(); - - /// - /// 対空カットイン発動艦番号 - /// - public int AACutInIndex => (int)AirBattleData.api_stage2.api_air_fire.api_idx; - - /// - /// 対空カットイン発動艦 - /// - public IShipData AACutInShip => Battle.Initial.GetFriendShip(AACutInIndex); - - /// - /// 対空カットイン発動艦の名前 - /// - public virtual string AACutInShipName => AACutInShip.NameWithLevel; - - /// - /// 対空カットイン種別 - /// - public int AACutInKind => (int)AirBattleData.api_stage2.api_air_fire.api_kind; - - - // stage 3 - - /// - /// Stage3(航空攻撃)が存在するか - /// - public bool IsStage3Available => StageFlag != null && StageFlag[2] != 0 && AirBattleData.api_stage3() && AirBattleData.api_stage3 != null; - - /// - /// Stage3(航空攻撃)(対随伴艦隊)が存在するか - /// - public bool IsStage3CombinedAvailable => StageFlag != null && StageFlag[2] != 0 && AirBattleData.api_stage3_combined() && AirBattleData.api_stage3_combined != null; - - - protected T[] ConcatStage3Array(string friendName, string enemyName) where T : struct, IComparable - { - - T[] ret = new T[24]; - - void SetArray(string stage3Name, string sideName, int retIndex) - { - if (!AirBattleData[stage3Name].IsDefined(sideName)) - return; - - var ar = (dynamic[])AirBattleData[stage3Name][sideName]; - if (ar == null) - return; - - for (int i = 0; i < ar.Length; i++) - { - var value = (T?)ar[i] ?? default(T); - - // Max(value, 0) - if (value.CompareTo(default(T)) < 0) - value = default(T); - - ret[retIndex + i] = value; - } - } - - - if (IsStage3Available) - { - SetArray("api_stage3", friendName, 0); - SetArray("api_stage3", enemyName, 12); - } - if (IsStage3CombinedAvailable) - { - SetArray("api_stage3_combined", friendName, 6); - SetArray("api_stage3_combined", enemyName, 18); - } - - return ret; - } - - - /// - /// 被雷撃フラグ - /// - public int[] TorpedoFlags { get; protected set; } - - /// - /// 被爆撃フラグ - /// - public int[] BomberFlags { get; protected set; } - - /// - /// 各艦のクリティカルフラグ - /// - public int[] Criticals { get; protected set; } - - /// - /// 各艦の被ダメージ - /// - public double[] Damages { get; protected set; } -} diff --git a/ElectronicObserver/Data/Battle/Phase/PhaseBase.cs b/ElectronicObserver/Data/Battle/Phase/PhaseBase.cs deleted file mode 100644 index b42b8b425..000000000 --- a/ElectronicObserver/Data/Battle/Phase/PhaseBase.cs +++ /dev/null @@ -1,126 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using ElectronicObserver.Data.Battle.Detail; - -namespace ElectronicObserver.Data.Battle.Phase; - -/// -/// 戦闘フェーズの基底クラスです。 -/// -public abstract class PhaseBase -{ - protected BattleData Battle; - public List BattleDetails { get; protected set; } - public readonly string Title; - - - private string TranslatedPhaseTitle(string title) => title switch - { - "噴式基地航空隊攻撃" => BattleRes.BattlePhaseLandBasedJet, - "噴式航空戦" => BattleRes.BattlePhaseJet, - "基地航空隊攻撃" => BattleRes.BattlePhaseLandBasedAir, - "防空戦" => BattleRes.BattlePhaseAirBaseRaid, - "航空戦" => BattleRes.BattlePhaseAirBattle, - "空襲戦" => BattleRes.BattlePhaseAirRaid, - "第一次航空戦" => BattleRes.BattlePhaseAirAttackFirst, - "第二次航空戦" => BattleRes.BattlePhaseAirAttackSecond, - "支援攻撃" => BattleRes.BattlePhaseSupportExpedition, - "先制対潜" => BattleRes.BattlePhaseOpeningAsw, - "先制雷撃" => BattleRes.BattlePhaseOpeningTorpedo, - "第一次砲撃戦" => BattleRes.BattlePhaseShellingFirst, - "第二次砲撃戦" => BattleRes.BattlePhaseShellingSecond, - "第三次砲撃戦" => BattleRes.BattlePhaseShellingThird, - "雷撃戦" => BattleRes.BattlePhaseClosingTorpedo, - "夜戦" => BattleRes.BattlePhaseNightBattle, - "第一次夜戦" => BattleRes.BattlePhaseNightBattleFirst, - "第二次夜戦" => BattleRes.BattlePhaseNightBattleSecond, - "夜間支援攻撃" => BattleRes.BattlePhaseNightSupportExpedition, - - _ => title, - }; - - protected PhaseBase(BattleData battle, string title) - { - Battle = battle; - BattleDetails = new List(); - Title = TranslatedPhaseTitle(title); - } - - - protected dynamic RawData => Battle.RawData; - - - protected static bool IsIndexFriend(int index) => 0 <= index && index < 12; - protected static bool IsIndexEnemy(int index) => 12 <= index && index < 24; - - - /// - /// 被ダメージ処理を行います。 - /// - /// 各艦のHPリスト。 - /// ダメージを受ける艦のインデックス。 - /// ダメージ。 - protected void AddDamage(int[] hps, int index, int damage) - { - - hps[index] -= Math.Max(damage, 0); - - // 自軍艦の撃沈が発生した場合(ダメコン処理) - if (hps[index] <= 0 && IsIndexFriend(index) && !Battle.IsPractice) - { - var ship = Battle.Initial.GetFriendShip(index); - if (ship == null) - return; - - int id = ship.DamageControlID; - - if (id == 42) - hps[index] = (int)(ship.HPMax * 0.2); - - else if (id == 43) - hps[index] = ship.HPMax; - - } - } - - - protected virtual IEnumerable SearchBattleDetails(int index) - { - return BattleDetails.Where(d => d.AttackerIndex == index || d.DefenderIndex == index); - } - public virtual string GetBattleDetail(int index) - { - IEnumerable list; - if (index == -1) - list = BattleDetails; - else - list = SearchBattleDetails(index); - - if (list.Any()) - { - return string.Join("\r\n", list) + "\r\n"; - } - else return null; - } - public virtual string GetBattleDetail() { return GetBattleDetail(-1); } - - - public override string ToString() => string.Join(" / \r\n", BattleDetails); - - - - /// - /// データが有効かどうかを示します。 - /// - public abstract bool IsAvailable { get; } - - /// - /// 戦闘をエミュレートします。 - /// - /// 各艦のHPリスト。 - /// 各艦の与ダメージリスト。 - public abstract void EmulateBattle(int[] hps, int[] damages); - - -} diff --git a/ElectronicObserver/Data/Battle/Phase/PhaseBaseAirAttack.cs b/ElectronicObserver/Data/Battle/Phase/PhaseBaseAirAttack.cs deleted file mode 100644 index e12019eb9..000000000 --- a/ElectronicObserver/Data/Battle/Phase/PhaseBaseAirAttack.cs +++ /dev/null @@ -1,149 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; -using ElectronicObserver.Core.Types; -using ElectronicObserver.Data.Battle.Detail; - -namespace ElectronicObserver.Data.Battle.Phase; - -/// -/// 基地航空隊攻撃フェーズの処理を行います。 -/// -public class PhaseBaseAirAttack : PhaseBase -{ - - - /// - /// 基地航空隊攻撃フェーズの、個々の攻撃フェーズの処理を行います。 - /// - public class PhaseBaseAirAttackUnit : PhaseAirBattleBase - { - - - public PhaseBaseAirAttackUnit(BattleData data, string title, int index) - : base(data, title) - { - - AirAttackIndex = index; - AirBattleData = data.RawData.api_air_base_attack[index]; - StageFlag = AirBattleData.api_stage_flag() ? (int[])AirBattleData.api_stage_flag : null; - - LaunchedShipIndexEnemy = GetLaunchedShipIndex(0); - - _squadrons = GetSquadrons().ToArray(); - - TorpedoFlags = ConcatStage3Array("api_frai_flag", "api_erai_flag"); - BomberFlags = ConcatStage3Array("api_fbak_flag", "api_ebak_flag"); - Criticals = ConcatStage3Array("api_fcl_flag", "api_ecl_flag"); - Damages = ConcatStage3Array("api_fdam", "api_edam"); - } - - - public override void EmulateBattle(int[] hps, int[] damages) - { - - if (!IsAvailable) return; - - CalculateAttack(AirAttackIndex + 1, hps); - } - - - /// - /// 攻撃ID (第n波, 0から始まる) - /// - public int AirAttackIndex { get; private set; } - - /// - /// 航空隊ID - /// - public int AirUnitID => (int)AirBattleData.api_base_id; - - - - private BattleBaseAirCorpsSquadron[] _squadrons; - /// - /// 参加した航空中隊データ - /// - public ReadOnlyCollection Squadrons => Array.AsReadOnly(_squadrons); - - private IEnumerable GetSquadrons() - { - foreach (dynamic d in AirBattleData.api_squadron_plane) - yield return new BattleBaseAirCorpsSquadron(d); - } - - } - - - - public PhaseBaseAirAttack(BattleData data, string title) - : base(data, title) - { - - AirAttackUnits = new List(); - - if (!IsAvailable) - return; - - - int i = 0; - foreach (var unit in RawData.api_air_base_attack) - { - AirAttackUnits.Add(new PhaseBaseAirAttackUnit(data, title, i)); - i++; - } - - } - - - /// - /// 個々の攻撃フェーズのデータ - /// - public List AirAttackUnits { get; private set; } - - - - public override bool IsAvailable => RawData.api_air_base_attack(); - - - public override void EmulateBattle(int[] hps, int[] damages) - { - - if (!IsAvailable) - return; - - foreach (var a in AirAttackUnits) - { - - a.EmulateBattle(hps, damages); - } - } - - - protected override IEnumerable SearchBattleDetails(int index) - { - return AirAttackUnits.SelectMany(p => p.BattleDetails).Where(d => d.DefenderIndex == index); - } - -} - - -/// -/// 戦闘に参加した基地航空隊中隊のデータ -/// -public class BattleBaseAirCorpsSquadron -{ - public int EquipmentID { get; private set; } - public int AircraftCount { get; private set; } - public IEquipmentDataMaster EquipmentInstance => KCDatabase.Instance.MasterEquipments[EquipmentID]; - - public BattleBaseAirCorpsSquadron(dynamic data) - { - EquipmentID = (int)data.api_mst_id; - AircraftCount = (int)data.api_count; - } - - public override string ToString() => $"{EquipmentInstance?.NameEN ?? "Unknown Plane"} x {AircraftCount}"; - -} diff --git a/ElectronicObserver/Data/Battle/Phase/PhaseBaseAirRaid.cs b/ElectronicObserver/Data/Battle/Phase/PhaseBaseAirRaid.cs deleted file mode 100644 index b4c22c31a..000000000 --- a/ElectronicObserver/Data/Battle/Phase/PhaseBaseAirRaid.cs +++ /dev/null @@ -1,64 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; -using DynaJson; - -namespace ElectronicObserver.Data.Battle.Phase; - -/// -/// 基地空襲戦フェーズ -/// -public class PhaseBaseAirRaid : PhaseAirBattleBase -{ - - private BattleBaseAirCorpsSquadron[] _squadrons; - /// - /// 参加した航空中隊データ - /// - public ReadOnlyCollection Squadrons => Array.AsReadOnly(_squadrons); - - private IEnumerable GetSquadrons() - { - if (AirBattleData.api_map_squadron_plane == null) - yield break; - - foreach (KeyValuePair p in AirBattleData.api_map_squadron_plane) - { - if (!(p.Value is JsonObject)) - continue; - if (!p.Value.IsArray) - continue; - - foreach (dynamic e in p.Value) - yield return new BattleBaseAirCorpsSquadron(e); - } - } - - - public PhaseBaseAirRaid(BattleData data, string title) - : base(data, title) - { - - AirBattleData = data.RawData.api_air_base_attack; - StageFlag = AirBattleData.api_stage_flag() ? (int[])AirBattleData.api_stage_flag : null; - - LaunchedShipIndexFriend = GetLaunchedShipIndex(0); - LaunchedShipIndexEnemy = GetLaunchedShipIndex(1); - - _squadrons = GetSquadrons().ToArray(); - - TorpedoFlags = ConcatStage3Array("api_frai_flag", "api_erai_flag"); - BomberFlags = ConcatStage3Array("api_fbak_flag", "api_ebak_flag"); - Criticals = ConcatStage3Array("api_fcl_flag", "api_ecl_flag"); - Damages = ConcatStage3Array("api_fdam", "api_edam"); - } - - public override void EmulateBattle(int[] hps, int[] damages) - { - if (!IsAvailable) return; - - CalculateAttack(-1, hps); - } - -} diff --git a/ElectronicObserver/Data/Battle/Phase/PhaseFriendlyAirBattle.cs b/ElectronicObserver/Data/Battle/Phase/PhaseFriendlyAirBattle.cs deleted file mode 100644 index d267d685c..000000000 --- a/ElectronicObserver/Data/Battle/Phase/PhaseFriendlyAirBattle.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using ElectronicObserver.Data.Battle.Detail; - -namespace ElectronicObserver.Data.Battle.Phase; - -/// -/// 昼戦における友軍艦隊航空攻撃フェーズの処理を行います。 -/// -public class PhaseFriendlyAirBattle : PhaseAirBattleBase -{ - public PhaseFriendlyAirBattle(BattleData battle, string title) - : base(battle, title) - { - if (!IsAvailable) - return; - - AirBattleData = RawData.api_friendly_kouku; - StageFlag = AirBattleData.api_stage_flag; - - LaunchedShipIndexFriend = GetLaunchedShipIndex(0); - LaunchedShipIndexEnemy = GetLaunchedShipIndex(1); - - TorpedoFlags = ConcatStage3Array("api_frai_flag", "api_erai_flag"); - BomberFlags = ConcatStage3Array("api_fbak_flag", "api_ebak_flag"); - Criticals = ConcatStage3Array("api_fcl_flag", "api_ecl_flag"); - Damages = ConcatStage3Array("api_fdam", "api_edam"); - } - - public override bool IsAvailable => RawData.api_friendly_kouku(); - - public override void EmulateBattle(int[] hps, int[] damages) - { - if (!IsAvailable) - return; - - var friendHps = Battle.FriendlySupportInfo.FriendlyInitialHPs.ToArray(); - - for (int i = 0; i < TorpedoFlags.Length; i++) - { - int attackType = (TorpedoFlags[i] > 0 ? 1 : 0) | (BomberFlags[i] > 0 ? 2 : 0); - if (attackType > 0) - { - bool isEnemy = new BattleIndex(i, false, Battle.IsEnemyCombined).IsEnemy; - - - // 航空戦は miss/hit=0, critical=1 のため +1 する(通常は miss=0, hit=1, critical=2) - BattleDetails.Add(new BattleFriendlyAirDetail( - Battle, - new BattleIndex(i, Battle.IsFriendCombined, Battle.IsEnemyCombined), - Damages[i], - Criticals[i] + 1, - attackType, - isEnemy ? hps[i] : friendHps[i])); - - if (isEnemy) - AddDamage(hps, i, (int)Damages[i]); - } - } - } - - protected override IEnumerable SearchBattleDetails(int index) - { - return BattleDetails.Where(d => d.DefenderIndex.IsEnemy && d.DefenderIndex == index); - } - - public override string AACutInShipName => Battle.FriendlySupportInfo.FriendlyMembersInstance[AACutInIndex].Name + " Lv. " + Battle.FriendlySupportInfo.FriendlyLevels[AACutInIndex]; -} diff --git a/ElectronicObserver/Data/Battle/Phase/PhaseFriendlyShelling.cs b/ElectronicObserver/Data/Battle/Phase/PhaseFriendlyShelling.cs deleted file mode 100644 index 3f8df72c1..000000000 --- a/ElectronicObserver/Data/Battle/Phase/PhaseFriendlyShelling.cs +++ /dev/null @@ -1,242 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using ElectronicObserver.Core.Types; -using ElectronicObserver.Data.Battle.Detail; - -namespace ElectronicObserver.Data.Battle.Phase; - -/// -/// 夜戦における友軍艦隊砲撃フェーズの処理を行います。 -/// -public class PhaseFriendlyShelling : PhaseBase -{ - public PhaseFriendlyShelling(BattleData battle, string title) - : base(battle, title) - { - if (!IsAvailable) - return; - - // battle translation - - int[] fleetflag = (int[])ShellingData.api_at_eflag; - int[] attackers = (int[])ShellingData.api_at_list; - int[] nightAirAttackFlags = (int[])ShellingData.api_n_mother_list; - int[] attackTypes = (int[])ShellingData.api_sp_list; - int[][] defenders = ((dynamic[])ShellingData.api_df_list).Select(elem => ((int[])elem).Where(e => e != -1).ToArray()).ToArray(); - int[][] attackEquipments = ((dynamic[])ShellingData.api_si_list).Select(elem => ((dynamic[])elem).Select(ch => ch is string ? int.Parse(ch) : (int)ch).ToArray()).ToArray(); - int[][] criticals = ((dynamic[])ShellingData.api_cl_list).Select(elem => ((int[])elem).Where(e => e != -1).ToArray()).ToArray(); - double[][] rawDamages = ((dynamic[])ShellingData.api_damage).Select(elem => ((double[])elem).Where(e => e != -1).ToArray()).ToArray(); - - Attacks = new List(); - - - - for (int i = 0; i < attackers.Length; i++) - { - var attack = new PhaseFriendlySupportAttack - { - Attacker = new BattleIndex(attackers[i] + (fleetflag[i] == 0 ? 0 : 12), false, Battle.IsEnemyCombined), - NightAirAttackFlag = nightAirAttackFlags[i] == -1, - AttackType = attackTypes[i], - EquipmentIDs = attackEquipments[i], - }; - for (int k = 0; k < defenders[i].Length; k++) - { - var defender = new PhaseFriendlySupportDefender - { - Defender = new BattleIndex(defenders[i][k] + (fleetflag[i] == 0 ? 12 : 0), false, Battle.IsEnemyCombined), - CriticalFlag = criticals[i][k], - RawDamage = rawDamages[i][k] - }; - attack.Defenders.Add(defender); - } - - Attacks.Add(attack); - } - } - - public override bool IsAvailable => RawData.api_friendly_battle(); - - - public override void EmulateBattle(int[] hps, int[] damages) - { - if (!IsAvailable) - return; - - int[] friendhps = Battle.FriendlySupportInfo.FriendlyInitialHPs; - - foreach (var attack in Attacks) - { - foreach (var defs in attack.Defenders.GroupBy(d => d.Defender)) - { - BattleDetails.Add(new BattleFriendlyShellingDetail( - (BattleNight)Battle, - attack.Attacker, - defs.Key, - defs.Select(d => d.RawDamage).ToArray(), - defs.Select(d => d.CriticalFlag).ToArray(), - attack.AttackType, - attack.EquipmentIDs, - attack.NightAirAttackFlag, - defs.Key.IsFriend ? friendhps[defs.Key] : hps[defs.Key])); - - if (defs.Key.IsFriend) - friendhps[defs.Key] -= Math.Max(defs.Sum(d => d.Damage), 0); - else - AddDamage(hps, defs.Key, defs.Sum(d => d.Damage)); - } - } - - } - - - - /// - /// 戦闘データ - /// - public dynamic BattleData => RawData.api_friendly_battle; - - /// - /// 砲撃戦データ - /// - public dynamic ShellingData => RawData.api_friendly_battle.api_hougeki; - - - - /// - /// 自軍照明弾投射艦インデックス - /// - public int FlareIndexFriend => (int)BattleData.api_flare_pos[0]; - - /// - /// 敵軍照明弾投射艦インデックス - /// - public int FlareIndexEnemy => (int)BattleData.api_flare_pos[1]; - - - /// - /// 自軍照明弾投射艦 - /// - public IShipDataMaster FlareFriendInstance - { - get - { - int index = FlareIndexFriend; - if (0 <= index && index < Battle.FriendlySupportInfo.FriendlyMembersInstance.Length) - return Battle.FriendlySupportInfo.FriendlyMembersInstance[index]; - return null; - } - } - - /// - /// 敵軍照明弾投射艦 - /// - public IShipDataMaster FlareEnemyInstance - { - get - { - int index = FlareIndexEnemy; - var nightinitial = (Battle as BattleNight)?.NightInitial; - - if (nightinitial != null && - 0 <= index && index < nightinitial.EnemyMembersInstance.Length) - return nightinitial.EnemyMembersInstance[index]; - return null; - } - } - - - /// - /// 自軍探照灯照射艦番号 - /// - public int SearchlightIndexFriend - { - get - { - int index = -1; - var eqmaster = KCDatabase.Instance.MasterEquipments; - - for (int i = 0; i < Battle.FriendlySupportInfo.FriendlyMembersInstance.Length; i++) - { - if (Battle.FriendlySupportInfo.FriendlyMembers[i] != -1 && Battle.FriendlySupportInfo.FriendlyInitialHPs[i] > 1) - { - if (Battle.FriendlySupportInfo.FriendlySlots[i].Any(id => eqmaster[id]?.CategoryType == EquipmentTypes.SearchlightLarge)) - return i; - else if (Battle.FriendlySupportInfo.FriendlySlots[i].Any(id => eqmaster[id]?.CategoryType == EquipmentTypes.Searchlight) && index == -1) - index = i; - } - } - - return index; - } - } - - - /// - /// 敵軍探照灯照射艦番号 - /// 厳密には異なるが(友軍の攻撃で探照灯所持艦の HP が 1 になった場合 -1 になる)、めったに起こるものでもないので気にしないことにする - /// - public int SearchlightIndexEnemy => (Battle as BattleNight)?.NightInitial?.SearchlightIndexEnemy ?? -1; - - - /// - /// 自軍探照灯照射艦 - /// - public IShipDataMaster SearchlightFriendInstance - { - get - { - int index = SearchlightIndexFriend; - if (0 <= index && index < Battle.FriendlySupportInfo.FriendlyMembersInstance.Length) - return Battle.FriendlySupportInfo.FriendlyMembersInstance[index]; - return null; - } - } - - /// - /// 敵軍探照灯投射艦 - /// - public IShipDataMaster SearchlightEnemyInstance - { - get - { - int index = SearchlightIndexEnemy; - var nightinitial = (Battle as BattleNight)?.NightInitial; - - if (nightinitial != null && - 0 <= index && index < nightinitial.EnemyMembersInstance.Length) - return nightinitial.EnemyMembersInstance[index]; - return null; - } - } - - - - public List Attacks { get; private set; } - - - public class PhaseFriendlySupportAttack - { - public BattleIndex Attacker; - public int AttackType; - public bool NightAirAttackFlag; - public List Defenders; - public int[] EquipmentIDs; - - public PhaseFriendlySupportAttack() - { - Defenders = new List(); - } - } - - public class PhaseFriendlySupportDefender - { - public BattleIndex Defender; - public int CriticalFlag; - public double RawDamage; - public bool GuardsFlagship => RawDamage != Math.Floor(RawDamage); - public int Damage => (int)RawDamage; - } - -} diff --git a/ElectronicObserver/Data/Battle/Phase/PhaseFriendlySupportInfo.cs b/ElectronicObserver/Data/Battle/Phase/PhaseFriendlySupportInfo.cs deleted file mode 100644 index cd776544c..000000000 --- a/ElectronicObserver/Data/Battle/Phase/PhaseFriendlySupportInfo.cs +++ /dev/null @@ -1,128 +0,0 @@ -using System; -using System.Linq; -using ElectronicObserver.Core.Types; - -namespace ElectronicObserver.Data.Battle.Phase; - -/// -/// 友軍艦隊の情報を処理します。 -/// -public class PhaseFriendlySupportInfo : PhaseBase -{ - public PhaseFriendlySupportInfo(BattleData battle, string title) - : base(battle, title) - { - if (!IsAvailable) - return; - - // info translation - - int[] GetArrayOrDefault(string objectName, int length) => !InfoData.IsDefined(objectName) ? null : FixedArray((int[])InfoData[objectName], length); - int[][] GetArraysOrDefault(string objectName, int topLength, int bottomLength) - { - if (!InfoData.IsDefined(objectName)) - return null; - - int[][] ret = new int[topLength][]; - dynamic[] raw = (dynamic[])InfoData[objectName]; - for (int i = 0; i < ret.Length; i++) - { - if (i < raw.Length) - ret[i] = FixedArray((int[])raw[i], bottomLength); - else - ret[i] = Enumerable.Repeat(-1, bottomLength).ToArray(); - } - return ret; - } - - FriendlyMembers = GetArrayOrDefault("api_ship_id", 7); - FriendlyMembersInstance = FriendlyMembers.Select(id => KCDatabase.Instance.MasterShips[id]).ToArray(); - FriendlyLevels = GetArrayOrDefault("api_ship_lv", 7); - FriendlyInitialHPs = GetArrayOrDefault("api_nowhps", 7); - FriendlyMaxHPs = GetArrayOrDefault("api_maxhps", 7); - - FriendlySlots = GetArraysOrDefault("api_Slot", 7, 5); - FriendlyExpansionSlots = GetArrayOrDefault("api_slot_ex", 7); - FriendlyParameters = GetArraysOrDefault("api_Param", 7, 4); - } - - public override bool IsAvailable => RawData.api_friendly_info(); - - public override void EmulateBattle(int[] hps, int[] damages) - { - // nop - } - - - /// - /// 友軍情報 - /// - public dynamic InfoData => RawData.api_friendly_info; - - /// - /// 種別? - /// - public int Type => (int)InfoData.api_production_type; - - - /// - /// 友軍艦隊ID - /// - public int[] FriendlyMembers { get; private set; } - - /// - /// 友軍艦隊 - /// - public IShipDataMaster[] FriendlyMembersInstance { get; private set; } - - - /// - /// 友軍艦隊レベル - /// - public int[] FriendlyLevels { get; private set; } - - /// - /// 友軍艦隊初期HP - /// - public int[] FriendlyInitialHPs { get; private set; } - - /// - /// 友軍艦隊最大HP - /// - public int[] FriendlyMaxHPs { get; private set; } - - - /// - /// 友軍艦隊装備 - /// - public int[][] FriendlySlots { get; private set; } - - /// - /// 友軍艦隊装備 (拡張スロット) - /// - public int[] FriendlyExpansionSlots { get; private set; } - - /// - /// 友軍艦隊パラメータ - /// - public int[][] FriendlyParameters { get; private set; } - - // api_voice_id - // api_voice_p_no - - - - protected static int[] FixedArray(int[] array, int length, int defaultValue = -1) - { - var ret = new int[length]; - int l = Math.Min(length, array.Length); - Array.Copy(array, ret, l); - if (l < length) - { - for (int i = l; i < length; i++) - ret[i] = defaultValue; - } - - return ret; - } -} diff --git a/ElectronicObserver/Data/Battle/Phase/PhaseInitial.cs b/ElectronicObserver/Data/Battle/Phase/PhaseInitial.cs deleted file mode 100644 index 403e99a0f..000000000 --- a/ElectronicObserver/Data/Battle/Phase/PhaseInitial.cs +++ /dev/null @@ -1,329 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using ElectronicObserver.Core.Types; -using ElectronicObserver.Core.Types.Mocks; - -namespace ElectronicObserver.Data.Battle.Phase; - -/// -/// 戦闘開始フェーズの処理を行います。 -/// -public class PhaseInitial : PhaseBase -{ - - /// - /// 自軍艦隊ID - /// - public int FriendFleetID { get; private set; } - - /// - /// 自軍艦隊 - /// - public FleetData FriendFleet => KCDatabase.Instance.Fleet[FriendFleetID]; - - /// - /// 自軍随伴艦隊 - /// - public FleetData FriendFleetEscort => IsFriendCombined ? KCDatabase.Instance.Fleet[2] : null; - - - /// - /// 敵艦隊メンバ - /// - public int[] EnemyMembers { get; private set; } - - /// - /// 敵艦隊メンバ - /// - public IShipDataMaster?[] EnemyMembersInstance { get; private set; } - - - /// - /// 敵艦隊メンバ(随伴艦隊) - /// - public int[]? EnemyMembersEscort { get; private set; } - - /// - /// 敵艦隊メンバ(随伴艦隊) - /// - public IShipDataMaster?[]? EnemyMembersEscortInstance { get; private set; } - - public IFleetData EnemyFleet { get; private set; } - - public IFleetData? EnemyFleetEscort { get; private set; } - - /// - /// 敵艦のレベル - /// - public int[] EnemyLevels { get; private set; } - - /// - /// 敵艦のレベル(随伴艦隊) - /// - public int[]? EnemyLevelsEscort { get; private set; } - - - public int[] FriendInitialHPs { get; private set; } - public int[]? FriendInitialHPsEscort { get; private set; } - public int[] EnemyInitialHPs { get; private set; } - public int[]? EnemyInitialHPsEscort { get; private set; } - - public int[] FriendMaxHPs { get; private set; } - public int[]? FriendMaxHPsEscort { get; private set; } - public int[] EnemyMaxHPs { get; private set; } - public int[]? EnemyMaxHPsEscort { get; private set; } - - public bool[] IsEnemyTargetable { get; } - public bool[] IsEnemyTargetableEscort { get; } - - - /// - /// 敵艦のスロット - /// - public int[][] EnemySlots { get; private set; } - - /// - /// 敵艦のスロット - /// - public IEquipmentDataMaster[][] EnemySlotsInstance { get; private set; } - - - /// - /// 敵艦のスロット(随伴艦隊) - /// - public int[][] EnemySlotsEscort { get; private set; } - - /// - /// 敵艦のスロット(随伴艦隊) - /// - public IEquipmentDataMaster[][]? EnemySlotsEscortInstance { get; private set; } - - - /// - /// 敵艦のパラメータ - /// - public int[][] EnemyParameters { get; private set; } - - /// - /// 敵艦のパラメータ(随伴艦隊) - /// - public int[][] EnemyParametersEscort { get; private set; } - - - /// - /// 装甲破壊されているか - /// - public bool IsBossDamaged => RawData.api_xal01() && (int)RawData.api_xal01 > 0; - - - /// - /// 戦闘糧食を食べた艦娘のインデックス [0-11] - /// - public int[] RationIndexes { get; private set; } - - - public bool IsFriendCombined => FriendInitialHPsEscort != null; - public bool IsEnemyCombined => EnemyInitialHPsEscort != null; - - - - public PhaseInitial(BattleData data, string title) - : base(data, title) - { - { - dynamic id = RawData.api_dock_id() ? RawData.api_dock_id : - RawData.api_deck_id() ? RawData.api_deck_id : 1; - FriendFleetID = id is string ? int.Parse((string)id) : (int)id; - } - if (FriendFleetID <= 0) - FriendFleetID = 1; - - - int[]? GetArrayOrDefault(string objectName, int length) - { - object[]? values = RawData.IsDefined(objectName) switch - { - true => RawData[objectName].Deserialize(), - _ => null, - }; - - if (values is null) return null; - - int[] cleanedValues = values - .Select(v => v switch - { - double d => (int?)d, - int i => i, - // enemy HP and max HP can have "N/A" as a value for untargetable enemies - // this value then gets updated to the real HP value in HandleTargetability - string => -2, - _ => null, - }) - .Where(v => v is not null) - .Select(v => v!.Value) - .ToArray(); - - return FixedArray(cleanedValues, length); - } - - int[][] GetArraysOrDefault(string objectName, int topLength, int bottomLength) - { - if (!RawData.IsDefined(objectName)) - return null; - - int[][] ret = new int[topLength][]; - dynamic[] raw = (dynamic[])RawData[objectName]; - for (int i = 0; i < ret.Length; i++) - { - if (i < raw.Length) - ret[i] = FixedArray((int[])raw[i], bottomLength); - else - ret[i] = Enumerable.Repeat(-1, bottomLength).ToArray(); - } - return ret; - } - - int[]? HandleTargetability(int[]? hps, IShipDataMaster?[]? ships, bool[] isTargetable) - { - if (hps is null) return null; - if (ships is null) return null; - - for (int i = 0; i < hps.Length; i++) - { - if (hps[i] is not -2) continue; - if (ships[i] is not {} ship) continue; - - isTargetable[i] = false; - hps[i] = ship.HPMax; - } - - return hps; - } - - int mainMemberCount = 7; - int escortMemberCount = 6; - - IsEnemyTargetable = new[] { true, true, true, true, true, true, true }; - IsEnemyTargetableEscort = new[] { true, true, true, true, true, true }; - - EnemyMembers = GetArrayOrDefault("api_ship_ke", mainMemberCount)!; - EnemyMembersInstance = EnemyMembers.Select(id => KCDatabase.Instance.MasterShips[id]).ToArray(); - - EnemyMembersEscort = GetArrayOrDefault("api_ship_ke_combined", escortMemberCount); - EnemyMembersEscortInstance = EnemyMembersEscort?.Select(id => KCDatabase.Instance.MasterShips[id]).ToArray(); - - EnemyLevels = GetArrayOrDefault("api_ship_lv", mainMemberCount)!; - EnemyLevelsEscort = GetArrayOrDefault("api_ship_lv_combined", escortMemberCount); - - FriendInitialHPs = GetArrayOrDefault("api_f_nowhps", mainMemberCount)!; - FriendInitialHPsEscort = GetArrayOrDefault("api_f_nowhps_combined", escortMemberCount); - EnemyInitialHPs = HandleTargetability(GetArrayOrDefault("api_e_nowhps", mainMemberCount), EnemyMembersInstance, IsEnemyTargetable)!; - EnemyInitialHPsEscort = HandleTargetability(GetArrayOrDefault("api_e_nowhps_combined", escortMemberCount), EnemyMembersEscortInstance, IsEnemyTargetableEscort); - - FriendMaxHPs = GetArrayOrDefault("api_f_maxhps", mainMemberCount)!; - FriendMaxHPsEscort = GetArrayOrDefault("api_f_maxhps_combined", escortMemberCount); - EnemyMaxHPs = HandleTargetability(GetArrayOrDefault("api_e_maxhps", mainMemberCount), EnemyMembersInstance, IsEnemyTargetable)!; - EnemyMaxHPsEscort = HandleTargetability(GetArrayOrDefault("api_e_maxhps_combined", escortMemberCount), EnemyMembersEscortInstance, IsEnemyTargetableEscort); - - - EnemySlots = GetArraysOrDefault("api_eSlot", mainMemberCount, 5); - EnemySlotsInstance = EnemySlots.Select(part => part.Select(id => KCDatabase.Instance.MasterEquipments[id]).ToArray()).ToArray(); - - EnemySlotsEscort = GetArraysOrDefault("api_eSlot_combined", escortMemberCount, 5); - EnemySlotsEscortInstance = EnemySlotsEscort?.Select(part => part.Select(id => KCDatabase.Instance.MasterEquipments[id]).ToArray()).ToArray(); - - EnemyParameters = GetArraysOrDefault("api_eParam", mainMemberCount, 4); - EnemyParametersEscort = GetArraysOrDefault("api_eParam_combined", escortMemberCount, 4); - - InitializeEnemyFleets(); - - var rations = new List(); - if (RawData.api_combat_ration()) - { - rations.AddRange(((int[])RawData.api_combat_ration).Select(i => FriendFleet.Members.IndexOf(i))); - } - if (RawData.api_combat_ration_combined()) - { - rations.AddRange(((int[])RawData.api_combat_ration_combined).Select(i => FriendFleetEscort.Members.IndexOf(i) + 6)); - } - RationIndexes = rations.ToArray(); - } - - private void InitializeEnemyFleets() - { - EnemyFleet = new FleetDataMock - { - MembersInstance = new(EnemyMembersInstance - .OfType() - .Select(shipMaster => new ShipDataMock(shipMaster)) - .Cast() - .ToList()), - }; - - for (int index = 0; index < EnemyFleet.MembersInstance.Count; index++) - { - if (EnemyFleet.MembersInstance[index] is ShipDataMock ship) - { - ship.HPCurrent = EnemyInitialHPs[index]; - ship.CanBeTargeted = IsEnemyTargetable[index]; - } - } - - EnemyFleetEscort = null; - - if (EnemyMembersEscortInstance is not null) - { - EnemyFleetEscort = new FleetDataMock() - { - MembersInstance = new(EnemyMembersEscortInstance - .OfType() - .Select(shipMaster => new ShipDataMock(shipMaster)) - .Cast() - .ToList()), - }; - - for (int index = 0; index < EnemyFleetEscort.MembersInstance.Count; index++) - { - if (EnemyFleetEscort.MembersInstance[index] is ShipDataMock ship) - { - ship.HPCurrent = EnemyInitialHPsEscort?[index] ?? 0; - ship.CanBeTargeted = IsEnemyTargetableEscort[index]; - } - } - } - } - - public IShipData GetFriendShip(int index) - { - if (index < 0 || index >= 12) - return null; - - if (index < FriendFleet.Members.Count) - return FriendFleet.MembersInstance[index]; - else if (index >= 6 && FriendFleetEscort != null) - return FriendFleetEscort.MembersInstance[index - 6]; - else - return null; - } - - protected static int[] FixedArray(int[] array, int length, int defaultValue = -1) - { - var ret = new int[length]; - int l = Math.Min(length, array.Length); - Array.Copy(array, ret, l); - if (l < length) - { - for (int i = l; i < length; i++) - ret[i] = defaultValue; - } - - return ret; - } - - public override bool IsAvailable => RawData != null; - - public override void EmulateBattle(int[] hps, int[] damages) - { - } -} diff --git a/ElectronicObserver/Data/Battle/Phase/PhaseJetAirBattle.cs b/ElectronicObserver/Data/Battle/Phase/PhaseJetAirBattle.cs deleted file mode 100644 index 9251f3e92..000000000 --- a/ElectronicObserver/Data/Battle/Phase/PhaseJetAirBattle.cs +++ /dev/null @@ -1,105 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using ElectronicObserver.Core.Types; -using ElectronicObserver.Data.Battle.Detail; - -namespace ElectronicObserver.Data.Battle.Phase; - -/// -/// 噴式強襲航空攻撃フェーズの処理を行います。 -/// -public class PhaseJetAirBattle : PhaseAirBattleBase -{ - - public PhaseJetAirBattle(BattleData data, string title) - : base(data, title) - { - - AirBattleData = RawData.api_injection_kouku() ? RawData.api_injection_kouku : null; - if (AirBattleData != null) - { - StageFlag = new int[] { - AirBattleData.api_stage1() ? 1 : 0, - AirBattleData.api_stage2() ? 1 : 0, - AirBattleData.api_stage3() ? 1 : 0, - }; - } - - LaunchedShipIndexFriend = GetLaunchedShipIndex(0); - LaunchedShipIndexEnemy = GetLaunchedShipIndex(1); - - TorpedoFlags = ConcatStage3Array("api_frai_flag", "api_erai_flag"); - BomberFlags = ConcatStage3Array("api_fbak_flag", "api_ebak_flag"); - Criticals = ConcatStage3Array("api_fcl_flag", "api_ecl_flag"); - Damages = ConcatStage3Array("api_fdam", "api_edam"); - } - - public override void EmulateBattle(int[] hps, int[] damages) - { - - if (!IsAvailable) return; - - CalculateAttack(0, hps); - CalculateAttackDamage(damages); - } - - - /// - /// 航空戦での与ダメージを推測します。 - /// - /// 与ダメージリスト。 - private void CalculateAttackDamage(int[] damages) - { - // 敵はめんどくさすぎるので省略 - // 仮想火力を求め、それに従って合計ダメージを分配 - - var firepower = new int[12]; - var launchedIndex = LaunchedShipIndexFriend; - var members = Battle.Initial.FriendFleet.MembersWithoutEscaped; - - foreach (int i in launchedIndex) - { - - IShipData ship = Battle.Initial.GetFriendShip(i); - if (ship == null) - continue; - - var slots = ship.SlotInstanceMaster; - var aircrafts = ship.Aircraft; - for (int s = 0; s < slots.Count; s++) - { - - if (slots[s] == null) - continue; - - switch (slots[s].CategoryType) - { - case EquipmentTypes.JetBomber: - firepower[i] += (int)(1.0 * (slots[s].Bomber * Math.Sqrt(aircrafts[s]) + 25)); - break; - - // 噴式攻撃機 (80%と150%はランダムのため係数は平均値) - case EquipmentTypes.JetTorpedo: - firepower[i] += (int)(1.15 * (slots[s].Torpedo * Math.Sqrt(aircrafts[s]) + 25)); - break; - } - } - } - - int totalFirepower = firepower.Sum(); - int totalDamage = Damages.Select(dmg => (int)dmg).Skip(12).Take(12).Sum(); - - for (int i = 0; i < firepower.Length; i++) - { - damages[i] += (int)Math.Round((double)totalDamage * firepower[i] / Math.Max(totalFirepower, 1)); - } - } - - - protected override IEnumerable SearchBattleDetails(int index) - { - return BattleDetails.Where(d => d.DefenderIndex == index); - } - -} diff --git a/ElectronicObserver/Data/Battle/Phase/PhaseJetBaseAirAttack.cs b/ElectronicObserver/Data/Battle/Phase/PhaseJetBaseAirAttack.cs deleted file mode 100644 index bad20ac98..000000000 --- a/ElectronicObserver/Data/Battle/Phase/PhaseJetBaseAirAttack.cs +++ /dev/null @@ -1,141 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; -using ElectronicObserver.Data.Battle.Detail; - -namespace ElectronicObserver.Data.Battle.Phase; - -/// -/// 噴式航空機による基地航空隊攻撃フェーズの処理を行います。 -/// -public class PhaseJetBaseAirAttack : PhaseBase -{ - - /// - /// 噴式航空機による基地航空隊攻撃フェーズの、個々の攻撃フェーズの処理を行います。 - /// - public class PhaseJetBaseAirAttackUnit : PhaseAirBattleBase - { - - public PhaseJetBaseAirAttackUnit(BattleData data, string title, int index) - : base(data, title) - { - - if (index == -1) - { - AirAttackIndex = 0; - AirBattleData = data.RawData.api_air_base_injection; - } - else - { - AirAttackIndex = index; - AirBattleData = data.RawData.api_air_base_injection[index]; - } - - if (AirBattleData != null) - { - StageFlag = new int[] { - AirBattleData.api_stage1() ? 1 : 0, - AirBattleData.api_stage2() ? 1 : 0, - AirBattleData.api_stage3() ? 1 : 0, - }; - } - - _squadrons = GetSquadrons().ToArray(); - - TorpedoFlags = ConcatStage3Array("api_frai_flag", "api_erai_flag"); - BomberFlags = ConcatStage3Array("api_fbak_flag", "api_ebak_flag"); - Criticals = ConcatStage3Array("api_fcl_flag", "api_ecl_flag"); - Damages = ConcatStage3Array("api_fdam", "api_edam"); - } - - - public override void EmulateBattle(int[] hps, int[] damages) - { - - if (!IsAvailable) return; - - CalculateAttack(AirAttackIndex + 1, hps); - } - - - /// - /// 攻撃ID (第n波, 0から始まる) - /// - public int AirAttackIndex { get; private set; } - - - private BattleBaseAirCorpsSquadron[] _squadrons; - /// - /// 参加した航空中隊データ - /// - public ReadOnlyCollection Squadrons => Array.AsReadOnly(_squadrons); - - private IEnumerable GetSquadrons() - { - foreach (dynamic d in AirBattleData.api_air_base_data) - yield return new BattleBaseAirCorpsSquadron(d); - } - - } - - - - public PhaseJetBaseAirAttack(BattleData data, string title) - : base(data, title) - { - - AirAttackUnits = new List(); - - if (!IsAvailable) - return; - - - dynamic attackData = RawData.api_air_base_injection; - if (attackData.IsArray) - { - int i = 0; - foreach (var unit in RawData.api_air_base_injection) - { - AirAttackUnits.Add(new PhaseJetBaseAirAttackUnit(data, title, i)); - i++; - } - - } - else if (attackData.IsObject) - { - AirAttackUnits.Add(new PhaseJetBaseAirAttackUnit(data, title, -1)); - } - } - - - /// - /// 個々の攻撃フェーズのデータ - /// - public List AirAttackUnits { get; private set; } - - - - public override bool IsAvailable => RawData.api_air_base_injection(); - - - public override void EmulateBattle(int[] hps, int[] damages) - { - - if (!IsAvailable) - return; - - foreach (var a in AirAttackUnits) - { - - a.EmulateBattle(hps, damages); - } - } - - - protected override IEnumerable SearchBattleDetails(int index) - { - return AirAttackUnits.SelectMany(p => p.BattleDetails).Where(d => d.DefenderIndex == index); - } -} diff --git a/ElectronicObserver/Data/Battle/Phase/PhaseNightBattle.cs b/ElectronicObserver/Data/Battle/Phase/PhaseNightBattle.cs deleted file mode 100644 index 4640463e5..000000000 --- a/ElectronicObserver/Data/Battle/Phase/PhaseNightBattle.cs +++ /dev/null @@ -1,162 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using ElectronicObserver.Core.Types.Attacks; -using ElectronicObserver.Data.Battle.Detail; - -namespace ElectronicObserver.Data.Battle.Phase; - -/// -/// 夜戦フェーズの処理を行います。 -/// -public class PhaseNightBattle : PhaseBase -{ - - private readonly int PhaseID; - - - public PhaseNightBattle(BattleData data, string title, int phaseID) - : base(data, title) - { - - PhaseID = phaseID; - - - if (!IsAvailable) - return; - - - int[] fleetflag = (int[])ShellingData.api_at_eflag; - int[] attackers = (int[])ShellingData.api_at_list; - int[] nightAirAttackFlags = (int[])ShellingData.api_n_mother_list; - int[] attackTypes = (int[])ShellingData.api_sp_list; - int[][] defenders = ((dynamic[])ShellingData.api_df_list).Select(elem => ((int[])elem).Where(e => e != -1).ToArray()).ToArray(); - int[][] attackEquipments = ((dynamic[])ShellingData.api_si_list).Select(elem => ((dynamic[])elem).Select(ch => ch is string ? int.Parse(ch) : (int)ch).ToArray()).ToArray(); - int[][] criticals = ((dynamic[])ShellingData.api_cl_list).Select(elem => ((int[])elem).Where(e => e != -1).ToArray()).ToArray(); - double[][] rawDamages = ((dynamic[])ShellingData.api_damage).Select(elem => ((double[])elem).Where(e => e != -1).ToArray()).ToArray(); - - Attacks = new List(); - - - - for (int i = 0; i < attackers.Length; i++) - { - var attack = new PhaseNightBattleAttack - { - Attacker = new BattleIndex(attackers[i] + (fleetflag[i] == 0 ? 0 : 12), Battle.IsFriendCombined, Battle.IsEnemyCombined), - NightAirAttackFlag = nightAirAttackFlags[i] == -1, - AttackType = attackTypes[i], - EquipmentIDs = attackEquipments[i], - }; - for (int k = 0; k < defenders[i].Length; k++) - { - var defender = new PhaseNightBattleDefender - { - Defender = new BattleIndex(defenders[i][k] + (fleetflag[i] == 0 ? 12 : 0), Battle.IsFriendCombined, Battle.IsEnemyCombined), - CriticalFlag = criticals[i][k], - RawDamage = rawDamages[i][k] - }; - attack.Defenders.Add(defender); - } - - Attacks.Add(attack); - } - - } - - public override bool IsAvailable => - RawData.IsDefined(ShellingDataName) && - RawData[ShellingDataName].api_at_list() && - RawData[ShellingDataName].api_at_list != null; - - - public dynamic ShellingData => RawData[ShellingDataName]; - - private string ShellingDataName => PhaseID == 0 ? "api_hougeki" : ("api_n_hougeki" + PhaseID); - - public override void EmulateBattle(int[] hps, int[] damages) - { - if (!IsAvailable) return; - - foreach (var atk in Attacks) - { - if (atk.AttackTypeTyped.IsSpecialAttack()) - { - List attackers = atk.AttackTypeTyped switch - { - NightAttackKind.CutinZuiun => Enumerable.Repeat(atk.Attacker.Index, 2).ToList(), - _ => atk.AttackTypeTyped.SpecialAttackIndexes(), - }; - - int fleetCount = KCDatabase.Instance.Fleet.Fleets.Values - .Count(f => f.IsInSortie); - - for (int i = 0; i < atk.Defenders.Count; i++) - { - int attackerIndex = attackers[i]; - - BattleIndex comboatk = fleetCount switch - { - 2 => new(attackerIndex + 6, true, true), - _ => new BattleIndex(atk.Attacker.Side, attackerIndex) - }; - - BattleDetails.Add(new BattleNightDetail(Battle, comboatk, atk.Defenders[i].Defender, new[] { atk.Defenders[i].RawDamage }, new[] { atk.Defenders[i].CriticalFlag }, atk.AttackType, atk.EquipmentIDs, atk.NightAirAttackFlag, hps[atk.Defenders[i].Defender])); - AddDamage(hps, atk.Defenders[i].Defender, atk.Defenders[i].Damage); - damages[comboatk] += atk.Defenders[i].Damage; - } - } - else - { - foreach (var defs in atk.Defenders.GroupBy(d => d.Defender)) - { - BattleDetails.Add(new BattleNightDetail(Battle, atk.Attacker, defs.Key, defs.Select(d => d.RawDamage).ToArray(), defs.Select(d => d.CriticalFlag).ToArray(), atk.AttackType, atk.EquipmentIDs, atk.NightAirAttackFlag, hps[defs.Key])); - AddDamage(hps, defs.Key, defs.Sum(d => d.Damage)); - } - damages[atk.Attacker] += atk.Defenders.Sum(d => d.Damage); - } - } - - } - - - public List Attacks { get; private set; } - public class PhaseNightBattleAttack - { - public BattleIndex Attacker; - - public int AttackType; - - public NightAttackKind AttackTypeTyped => (NightAttackKind)AttackType; - - public bool NightAirAttackFlag; - - public List Defenders; - - public int[] EquipmentIDs; - - public PhaseNightBattleAttack() - { - Defenders = new List(); - } - - public override string ToString() => $"{Attacker}[{AttackType}] -> [{string.Join(", ", Defenders)}]"; - - } - public class PhaseNightBattleDefender - { - public BattleIndex Defender; - public int CriticalFlag; - public double RawDamage; - public bool GuardsFlagship => RawDamage != Math.Floor(RawDamage); - public int Damage => (int)RawDamage; - - public override string ToString() - { - return string.Format("{0};{1}-{2}{3}", Defender, Damage, - CriticalFlag == 0 ? "miss" : CriticalFlag == 1 ? "dmg" : CriticalFlag == 2 ? "crit" : "INVALID", - GuardsFlagship ? " (guard)" : ""); - } - } - -} diff --git a/ElectronicObserver/Data/Battle/Phase/PhaseNightInitial.cs b/ElectronicObserver/Data/Battle/Phase/PhaseNightInitial.cs deleted file mode 100644 index f12073e77..000000000 --- a/ElectronicObserver/Data/Battle/Phase/PhaseNightInitial.cs +++ /dev/null @@ -1,214 +0,0 @@ -using System.Linq; -using ElectronicObserver.Core.Types; - -namespace ElectronicObserver.Data.Battle.Phase; - -/// -/// 夜戦開始フェーズの処理を行います。 -/// -public class PhaseNightInitial : PhaseBase -{ - - private readonly bool IsEscort; - - public PhaseNightInitial(BattleData battle, string title, bool isEscort) - : base(battle, title) - { - IsEscort = isEscort; - } - - public override bool IsAvailable => RawData != null; - - public override void EmulateBattle(int[] hps, int[] damages) - { - // nop - } - - - - /// - /// 戦闘する自軍艦隊 - /// 1=主力艦隊, 2=随伴艦隊 - /// - public int ActiveFriendFleet => !RawData.api_active_deck() ? 1 : (int)RawData.api_active_deck[0]; - - /// - /// 自軍艦隊ID - /// - public int FriendFleetID - { - get - { - if (IsFriendEscort) - return 2; - else - return Battle.Initial.FriendFleetID; - } - } - - /// - /// 自軍艦隊 - /// - public FleetData FriendFleet => KCDatabase.Instance.Fleet[FriendFleetID]; - - /// - /// 自軍が随伴艦隊かどうか - /// - public bool IsFriendEscort => IsEscort || ActiveFriendFleet != 1; - - - /// - /// 敵軍艦隊ID - /// - public int EnemyFleetID => !RawData.api_active_deck() ? 1 : (int)RawData.api_active_deck[1]; - - /// - /// 敵軍艦隊 - /// - public int[] EnemyMembers => !IsEnemyEscort ? Battle.Initial.EnemyMembers : Battle.Initial.EnemyMembersEscort; - - /// - /// 敵軍艦隊 - /// - public IShipDataMaster[] EnemyMembersInstance => !IsEnemyEscort ? Battle.Initial.EnemyMembersInstance : Battle.Initial.EnemyMembersEscortInstance; - - /// - /// 敵軍が随伴艦隊かどうか - /// - public bool IsEnemyEscort => EnemyFleetID != 1; - - - /// - /// 自軍触接機ID - /// - public int TouchAircraftFriend => (RawData.api_touch_plane[0] is string) ? int.Parse(RawData.api_touch_plane[0]) : (int)RawData.api_touch_plane[0]; - - - /// - /// 敵軍触接機ID - /// - public int TouchAircraftEnemy => (RawData.api_touch_plane[1] is string) ? int.Parse(RawData.api_touch_plane[1]) : (int)RawData.api_touch_plane[1]; - - - /// - /// 自軍照明弾投射艦インデックス(0-11, -1=発動せず) - /// - public int FlareIndexFriend => (int)RawData.api_flare_pos[0]; - - /// - /// 敵軍照明弾投射艦インデックス(0-11, -1=発動せず) - /// - public int FlareIndexEnemy => (int)RawData.api_flare_pos[1]; - - - /// - /// 自軍照明弾投射艦 - /// - public IShipData FlareFriendInstance - { - get - { - int index = FlareIndexFriend; - - if (index < 0) - return null; - - if (IsFriendEscort) - return FriendFleet.MembersInstance[index - 6]; - else - return FriendFleet.MembersInstance[index]; - - } - } - - /// - /// 敵軍照明弾投射艦 - /// - public IShipDataMaster FlareEnemyInstance - { - get - { - int index = FlareIndexEnemy; - - if (index < 0) - return null; - - if (IsEnemyEscort) - return EnemyMembersInstance[index - 6]; - else - return EnemyMembersInstance[index]; - } - } - - - /// - /// 自軍探照灯照射艦番号 - /// - public int SearchlightIndexFriend - { - get - { - var ships = FriendFleet.MembersWithoutEscaped; - var hps = IsFriendEscort ? Battle.Initial.FriendInitialHPsEscort : Battle.Initial.FriendInitialHPs; - int index = -1; - - for (int i = 0; i < ships.Count; i++) - { - var ship = ships[i]; - if (ship != null && hps[i] > 1) - { - - if (ship.SlotInstanceMaster.Any(e => e?.CategoryType == EquipmentTypes.SearchlightLarge)) - return i; - else if (ship.SlotInstanceMaster.Any(e => e?.CategoryType == EquipmentTypes.Searchlight) && index == -1) - index = i; - } - } - - return index; - } - } - - /// - /// 敵軍探照灯照射艦番号(0-5) - /// - public int SearchlightIndexEnemy - { - get - { - var ships = EnemyMembersInstance; - var eqs = Battle.Initial.EnemySlotsInstance; - var hps = IsEnemyEscort ? Battle.Initial.EnemyInitialHPsEscort : Battle.Initial.EnemyInitialHPs; - int index = -1; - - for (int i = 0; i < ships.Length; i++) - { - if (ships[i] != null && hps[i] > 1) - { - - if (eqs[i].Any(e => e?.CategoryType == EquipmentTypes.SearchlightLarge)) - return i; - else if (eqs[i].Any(e => e?.CategoryType == EquipmentTypes.Searchlight) && index == -1) - index = i; - - } - } - - return index; - } - } - - /// - /// 敵軍探照灯照射艦 - /// - public IShipDataMaster SearchlightEnemyInstance - { - get - { - int index = SearchlightIndexEnemy; - return index == -1 ? null : EnemyMembersInstance[index]; - } - } - - -} diff --git a/ElectronicObserver/Data/Battle/Phase/PhaseOpeningASW.cs b/ElectronicObserver/Data/Battle/Phase/PhaseOpeningASW.cs deleted file mode 100644 index 5eba66859..000000000 --- a/ElectronicObserver/Data/Battle/Phase/PhaseOpeningASW.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace ElectronicObserver.Data.Battle.Phase; - -/// -/// 開幕対潜攻撃フェーズの処理を行います。 -/// -public class PhaseOpeningASW : PhaseShelling -{ - - // 砲撃戦とフォーマットが同じなので流用 - - public PhaseOpeningASW(BattleData data, string title) - : base(data, title, 0, "") - { - - } - - public override bool IsAvailable => (int)RawData.api_opening_taisen_flag != 0; - - public override dynamic ShellingData => RawData.api_opening_taisen; -} diff --git a/ElectronicObserver/Data/Battle/Phase/PhaseRadar.cs b/ElectronicObserver/Data/Battle/Phase/PhaseRadar.cs deleted file mode 100644 index 8c2a99db4..000000000 --- a/ElectronicObserver/Data/Battle/Phase/PhaseRadar.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace ElectronicObserver.Data.Battle.Phase; - -/// -/// レーダー射撃フェーズの処理を行います。 -/// -public class PhaseRadar : PhaseShelling -{ - - // 砲撃戦とフォーマットが同じなので流用 - - public PhaseRadar(BattleData data, string title) - : base(data, title, 1, "1") - { - } - - public override bool IsAvailable => RawData.api_hougeki1() && RawData.api_hougeki1 != null; - -} diff --git a/ElectronicObserver/Data/Battle/Phase/PhaseSearching.cs b/ElectronicObserver/Data/Battle/Phase/PhaseSearching.cs deleted file mode 100644 index 8be53ef57..000000000 --- a/ElectronicObserver/Data/Battle/Phase/PhaseSearching.cs +++ /dev/null @@ -1,64 +0,0 @@ -namespace ElectronicObserver.Data.Battle.Phase; - -/// -/// 索敵フェーズの処理を行います。 -/// -public class PhaseSearching : PhaseBase -{ - - - public PhaseSearching(BattleData data, string title) - : base(data, title) { } - - - public override bool IsAvailable => RawData.api_search() && RawData.api_formation(); - - public override void EmulateBattle(int[] hps, int[] damages) - { - } - - - /// - /// 自軍索敵結果 - /// - public int SearchingFriend => !RawData.api_search() ? -1 : (int)RawData.api_search[0]; - - - /// - /// 敵軍索敵結果 - /// - public int SearchingEnemy => !RawData.api_search() ? -1 : (int)RawData.api_search[1]; - - - /// - /// 自軍陣形 - /// - public int FormationFriend - { - get - { - dynamic form = RawData.api_formation[0]; - return form is string ? int.Parse((string)form) : (int)form; - } - } - - /// - /// 敵軍陣形 - /// - public int FormationEnemy => (int)RawData.api_formation[1]; - - /// - /// 交戦形態 - /// - public int EngagementForm => (int)RawData.api_formation[2]; - - /// - /// 0, 1, 2, 3 - number of active smokers
- /// null - no idea when this can be null - ///
- public int? SmokeCount => RawData.api_smoke_type() switch - { - true => (int)RawData.api_smoke_type, - _ => null, - }; -} diff --git a/ElectronicObserver/Data/Battle/Phase/PhaseShelling.cs b/ElectronicObserver/Data/Battle/Phase/PhaseShelling.cs deleted file mode 100644 index 60c861081..000000000 --- a/ElectronicObserver/Data/Battle/Phase/PhaseShelling.cs +++ /dev/null @@ -1,136 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using ElectronicObserver.Core.Types.Attacks; -using ElectronicObserver.Data.Battle.Detail; - -namespace ElectronicObserver.Data.Battle.Phase; - -/// -/// 砲撃戦フェーズの処理を行います。 -/// -public class PhaseShelling : PhaseBase -{ - protected readonly int PhaseID; - protected readonly string Suffix; - - public List Attacks { get; private set; } - - public class PhaseShellingAttack - { - public BattleIndex Attacker; - - public int AttackType; - - public DayAttackKind AttackTypeTyped => (DayAttackKind)AttackType; - - public List Defenders; - - public int[] EquipmentIDs; - - public PhaseShellingAttack() - { - Defenders = new List(); - } - - public override string ToString() => $"{Attacker}[{AttackType}] -> [{string.Join(", ", Defenders)}]"; - - } - public class PhaseShellingDefender - { - public BattleIndex Defender; - public int CriticalFlag; - public double RawDamage; - public bool GuardsFlagship => RawDamage != Math.Floor(RawDamage); - public int Damage => (int)RawDamage; - - public override string ToString() - { - return string.Format("{0};{1}-{2}{3}", Defender, Damage, - CriticalFlag == 0 ? "miss" : CriticalFlag == 1 ? "dmg" : CriticalFlag == 2 ? "crit" : "INVALID", - GuardsFlagship ? " (guard)" : ""); - } - } - - public PhaseShelling(BattleData data, string title, int phaseID, string suffix) - : base(data, title) - { - - PhaseID = phaseID; - Suffix = suffix; - - if (!IsAvailable) - return; - - // "translate" - - int[] fleetflag = (int[])ShellingData.api_at_eflag; - int[] attackers = (int[])ShellingData.api_at_list; - int[] attackTypes = (int[])ShellingData.api_at_type; - int[][] defenders = ((dynamic[])ShellingData.api_df_list).Select(elem => (int[])elem).ToArray(); - int[][] attackEquipments = ((dynamic[])ShellingData.api_si_list).Select(elem => ((dynamic[])elem).Select(ch => ch is string ? int.Parse(ch) : (int)ch).ToArray()).ToArray(); - int[][] criticalFlags = ((dynamic[])ShellingData.api_cl_list).Select(elem => (int[])elem).ToArray(); - double[][] rawDamages = ((dynamic[])ShellingData.api_damage).Select(elem => ((double[])elem).Select(p => Math.Max(p, 0)).ToArray()).ToArray(); - - Attacks = new List(); - - for (int i = 0; i < attackers.Length; i++) - { - var attack = new PhaseShellingAttack() - { - Attacker = new BattleIndex(attackers[i] + (fleetflag[i] == 0 ? 0 : 12), Battle.IsFriendCombined, Battle.IsEnemyCombined), - }; - - - for (int k = 0; k < defenders[i].Length; k++) - { - var defender = new PhaseShellingDefender - { - Defender = new BattleIndex(defenders[i][k] + (fleetflag[i] == 0 ? 12 : 0), Battle.IsFriendCombined, Battle.IsEnemyCombined), - CriticalFlag = criticalFlags[i][k], - RawDamage = rawDamages[i][k], - }; - - attack.Defenders.Add(defender); - } - - attack.AttackType = attackTypes[i]; - attack.EquipmentIDs = attackEquipments[i]; - - Attacks.Add(attack); - } - } - - public override bool IsAvailable => (int)RawData.api_hourai_flag[PhaseID - 1] != 0; - - public virtual dynamic ShellingData => RawData["api_hougeki" + Suffix]; - - public override void EmulateBattle(int[] hps, int[] damages) - { - if (!IsAvailable) return; - - foreach (PhaseShellingAttack atk in Attacks) - { - if (atk.AttackTypeTyped.IsSpecialAttack()) - { - List attackers = atk.AttackTypeTyped.SpecialAttackIndexes(); - - for (int i = 0; i < atk.Defenders.Count; i++) - { - var comboatk = new BattleIndex(atk.Attacker.Side, attackers[i]); - BattleDetails.Add(new BattleDayDetail(Battle, comboatk, atk.Defenders[i].Defender, new[] { atk.Defenders[i].RawDamage }, new[] { atk.Defenders[i].CriticalFlag }, atk.AttackType, atk.EquipmentIDs, hps[atk.Defenders[i].Defender])); - AddDamage(hps, atk.Defenders[i].Defender, atk.Defenders[i].Damage); - damages[comboatk] += atk.Defenders[i].Damage; - } - } - else { - foreach (var defs in atk.Defenders.GroupBy(d => d.Defender)) - { - BattleDetails.Add(new BattleDayDetail(Battle, atk.Attacker, defs.Key, defs.Select(d => d.RawDamage).ToArray(), defs.Select(d => d.CriticalFlag).ToArray(), atk.AttackType, atk.EquipmentIDs, hps[defs.Key])); - AddDamage(hps, defs.Key, defs.Sum(d => d.Damage)); - } - damages[atk.Attacker] += atk.Defenders.Sum(d => d.Damage); - } - } - } -} diff --git a/ElectronicObserver/Data/Battle/Phase/PhaseSupport.cs b/ElectronicObserver/Data/Battle/Phase/PhaseSupport.cs deleted file mode 100644 index 4d3f3a3ef..000000000 --- a/ElectronicObserver/Data/Battle/Phase/PhaseSupport.cs +++ /dev/null @@ -1,168 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using ElectronicObserver.Data.Battle.Detail; - -namespace ElectronicObserver.Data.Battle.Phase; - -/// -/// 支援攻撃フェーズの処理を行います。 -/// -public class PhaseSupport : PhaseBase -{ - - public readonly bool IsNight; - - public PhaseSupport(BattleData data, string title, bool isNight = false) - : base(data, title) - { - IsNight = isNight; - - switch (SupportFlag) - { - case 1: // 空撃 - case 4: // 対潜 - { - if ((int)SupportData.api_support_airatack.api_stage_flag[2] != 0) - { - // 敵連合でも api_stage3_combined は存在しない? - - Damages = ((double[])SupportData.api_support_airatack.api_stage3.api_edam).ToArray(); - Criticals = ((int[])SupportData.api_support_airatack.api_stage3.api_ecl_flag).ToArray(); - - // 航空戦なので crit フラグが違う - for (int i = 0; i < Criticals.Length; i++) - Criticals[i]++; - } - else - { - Damages = new double[12]; - Criticals = new int[12]; - } - } - break; - case 2: // 砲撃 - case 3: // 雷撃 - { - var dmg = (double[])SupportData.api_support_hourai.api_damage; - var cl = (int[])SupportData.api_support_hourai.api_cl_list; - - Damages = new double[12]; - Array.Copy(dmg, Damages, dmg.Length); - - Criticals = new int[12]; - Array.Copy(cl, Criticals, cl.Length); - } - break; - default: - Damages = new double[12]; - Criticals = new int[12]; - break; - } - } - - - public override bool IsAvailable => SupportFlag != 0; - - public override void EmulateBattle(int[] hps, int[] damages) - { - - if (!IsAvailable) return; - - for (int i = 0; i < Battle.Initial.EnemyMembers.Length; i++) - { - if (Battle.Initial.EnemyMembers[i] > 0) - { - var index = new BattleIndex(BattleSides.EnemyMain, i); - BattleDetails.Add(new BattleSupportDetail(Battle, index, Damages[i], Criticals[i], SupportFlag, hps[index])); - AddDamage(hps, index, (int)Damages[i]); - } - } - if (Battle.IsEnemyCombined) - { - for (int i = 0; i < Battle.Initial.EnemyMembersEscort.Length; i++) - { - if (Battle.Initial.EnemyMembersEscort[i] > 0) - { - var index = new BattleIndex(BattleSides.EnemyEscort, i); - BattleDetails.Add(new BattleSupportDetail(Battle, index, Damages[i + 6], Criticals[i + 6], SupportFlag, hps[index])); - AddDamage(hps, index, (int)Damages[i + 6]); - } - } - } - } - - protected override IEnumerable SearchBattleDetails(int index) - { - return BattleDetails.Where(d => d.DefenderIndex == index); - } - - - /// - /// 支援艦隊フラグ - /// - public int SupportFlag - { - get - { - if (IsNight) - return RawData.api_n_support_flag() ? (int)RawData.api_n_support_flag : 0; - else - return RawData.api_support_flag() ? (int)RawData.api_support_flag : 0; - } - } - - public dynamic SupportData => IsNight ? RawData.api_n_support_info : RawData.api_support_info; - - /// - /// 支援艦隊ID - /// - public int SupportFleetID - { - get - { - switch (SupportFlag) - { - case 1: - case 4: - return (int)SupportData.api_support_airatack.api_deck_id; - - case 2: - case 3: - return (int)SupportData.api_support_hourai.api_deck_id; - - default: - return -1; - - } - } - } - - /// - /// 支援艦隊 - /// - public FleetData SupportFleet - { - get - { - int id = SupportFleetID; - if (id != -1) - return KCDatabase.Instance.Fleet[id]; - else - return null; - } - } - - - /// - /// 与ダメージ [12] - /// - public double[] Damages { get; private set; } - - /// - /// クリティカルフラグ [12] - /// - public int[] Criticals { get; private set; } - - -} diff --git a/ElectronicObserver/Data/Battle/Phase/PhaseTorpedo.cs b/ElectronicObserver/Data/Battle/Phase/PhaseTorpedo.cs deleted file mode 100644 index 6583f2186..000000000 --- a/ElectronicObserver/Data/Battle/Phase/PhaseTorpedo.cs +++ /dev/null @@ -1,147 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using ElectronicObserver.Data.Battle.Detail; - -namespace ElectronicObserver.Data.Battle.Phase; - -/// -/// 雷撃戦フェーズの処理を行います。 -/// -public class PhaseTorpedo : PhaseBase -{ - - /// - /// フェーズID 0=開幕雷撃, 1-4=雷撃戦 - /// - private readonly int phaseID; - - public PhaseTorpedo(BattleData data, string title, int phaseID) - : base(data, title) - { - - this.phaseID = phaseID; - - if (!IsAvailable) - return; - - Damages = GetConcatArray("api_fdam", "api_edam", 0.0); - - if (IsOpeningTorpedoPhase) - { - AttackDamages = GetConcatArray("api_fydam_list_items", "api_eydam_list_items", null); - Targets = GetConcatArray("api_frai_list_items", "api_erai_list_items", null); - CriticalFlags = GetConcatArray("api_fcl_list_items", "api_ecl_list_items", null); - } - else if (IsClosingTorpedoPhase) - { - AttackDamages = GetConcatArray("api_fydam", "api_eydam", 0).Select(i => new[] { i }).ToArray(); - Targets = GetConcatArray("api_frai", "api_erai", -1).Select(i => new[] { i }).ToArray(); - CriticalFlags = GetConcatArray("api_fcl", "api_ecl", 0).Select(i => new[] { i }).ToArray(); - } - - } - - - public override bool IsAvailable => IsOpeningTorpedoPhase || IsClosingTorpedoPhase; - - private bool IsOpeningTorpedoPhase => phaseID == 0 && (RawData.api_opening_flag() ? (int)RawData.api_opening_flag != 0 : false); - private bool IsClosingTorpedoPhase => phaseID != 0 && ((int)RawData.api_hourai_flag[phaseID - 1] != 0); - - - public override void EmulateBattle(int[] hps, int[] damages) - { - - if (!IsAvailable) - return; - - // 表示上は逐次ダメージ反映のほうが都合がいいが、AddDamage を逐次的にやるとダメコン判定を誤るため - int[] currentHP = new int[hps.Length]; - Array.Copy(hps, currentHP, currentHP.Length); - - for (int i = 0; i < Targets.Length; i++) - { - if (Targets[i] is null) continue; - - for (int j = 0; j < Targets[i].Length; j++) - { - if (Targets[i][j] < 0) continue; - - BattleIndex attacker = new BattleIndex(i, Battle.IsFriendCombined, Battle.IsEnemyCombined); - BattleIndex defender = new BattleIndex(Targets[i][j] + (i < 12 ? 12 : 0), Battle.IsFriendCombined, Battle.IsEnemyCombined); - - BattleDetails.Add(new BattleDayDetail(Battle, attacker, defender, new double[] { AttackDamages[i][j] + Damages[defender] - Math.Floor(Damages[defender]) }, //propagates "guards flagship" flag - new int[] { CriticalFlags[i][j] }, -1, null, currentHP[defender])); - currentHP[defender] -= Math.Max(AttackDamages[i][j], 0); - } - } - - for (int i = 0; i < hps.Length; i++) - { - AddDamage(hps, i, (int)Damages[i]); - damages[i] += AttackDamages[i]?.Sum() ?? 0; - } - - } - - - public dynamic TorpedoData => phaseID == 0 ? RawData.api_opening_atack : RawData.api_raigeki; - - - /// - /// 各艦の被ダメージ - /// - public double[] Damages { get; private set; } - - /// - /// 各艦の与ダメージ - /// - public int[]?[] AttackDamages { get; private set; } - - /// - /// 各艦のターゲットインデックス - /// - public int[]?[] Targets { get; private set; } - - /// - /// クリティカルフラグ(攻撃側) - /// - public int[]?[] CriticalFlags { get; private set; } - - - - - private T[] GetConcatArray(string friendName, string enemyName, T defaultValue) - { - var friend = ConvertToArray(TorpedoData[friendName], 12, defaultValue); - var enemy = ConvertToArray(TorpedoData[enemyName], 12, defaultValue); - - var ret = new T[24]; - - for (int i = 0; i < 12; i++) - { - ret[i] = friend[i]; - ret[i + 12] = enemy[i]; - } - - return ret; - } - - /// - /// 基本的には `(T[])json` と等価ですが、特定の状況下におけるデータエラーを回避するための実装が含まれています - /// https://github.com/andanteyk/ElectronicObserver/issues/294 - /// - private static T[] ConvertToArray(dynamic json, int maxLength, T defaultValue) - { - var ret = Enumerable.Repeat(defaultValue, maxLength).ToArray(); - int i = 0; - foreach (var member in json) - { - ret[i++ % maxLength] = - member is KeyValuePair pair ? (T)pair.Value : - member != null ? (T)member : - default(T); - } - return ret; - } -} diff --git a/ElectronicObserver/Data/Bonodere/BonodereSubmissionResources.zh-CN.resx b/ElectronicObserver/Data/Bonodere/BonodereSubmissionResources.zh-CN.resx index 851ab2307..88b19d2fb 100644 --- a/ElectronicObserver/Data/Bonodere/BonodereSubmissionResources.zh-CN.resx +++ b/ElectronicObserver/Data/Bonodere/BonodereSubmissionResources.zh-CN.resx @@ -1,129 +1,129 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - Bonodere 错误 - - - Bonodere提交:成功 - - - 检测到不一致的数据 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Bonodere 错误 + + + Bonodere提交:成功 + + + 检测到不一致的数据 + \ No newline at end of file diff --git a/ElectronicObserver/Data/Constants.cs b/ElectronicObserver/Data/Constants.cs index 4dc0baeb1..8c2c21a7e 100644 --- a/ElectronicObserver/Data/Constants.cs +++ b/ElectronicObserver/Data/Constants.cs @@ -635,34 +635,20 @@ public static int GetFormation(string value) /// /// 陣形を表す文字列(短縮版)を取得します。 /// - public static string GetFormationShort(int id) - { - switch (id) - { - case 1: - return ConstantsRes.LineAheadShort; - case 2: - return ConstantsRes.DoubleLineShort; - case 3: - return ConstantsRes.DiamondShort; - case 4: - return ConstantsRes.EchelonShort; - case 5: - return ConstantsRes.LineAbreastShort; - case 6: - return ConstantsRes.VanguardShort; - case 11: - return ConstantsRes.FirstPatrolFormationShort; - case 12: - return ConstantsRes.SecondPatrolFormationShort; - case 13: - return ConstantsRes.ThirdPatrolFormationShort; - case 14: - return ConstantsRes.FourthPatrolFormationShort; - default: - return ConstantsRes.Unknown; - } - } + public static string GetFormationShort(FormationType formationType) => formationType switch + { + FormationType.LineAhead => ConstantsRes.LineAheadShort, + FormationType.DoubleLine => ConstantsRes.DoubleLineShort, + FormationType.Diamond => ConstantsRes.DiamondShort, + FormationType.Echelon => ConstantsRes.EchelonShort, + FormationType.LineAbreast => ConstantsRes.LineAbreastShort, + FormationType.Vanguard => ConstantsRes.VanguardShort, + FormationType.FirstPatrolFormation => ConstantsRes.FirstPatrolFormationShort, + FormationType.SecondPatrolFormation=> ConstantsRes.SecondPatrolFormationShort, + FormationType.ThirdPatrolFormation => ConstantsRes.ThirdPatrolFormationShort, + FormationType.FourthPatrolFormation => ConstantsRes.FourthPatrolFormationShort, + _ => ConstantsRes.Unknown, + }; /// /// 交戦形態を表す文字列を取得します。 @@ -723,31 +709,16 @@ public static string GetEngagementFormShort(int id) /// /// 索敵結果を表す文字列(短縮版)を取得します。 /// - public static string GetSearchingResultShort(int id) + public static string GetSearchingResultShort(DetectionType id) => id switch { - switch (id) - { - case 1: - return ConstantsRes.Success; - case 2: - return ConstantsRes.Success + "△"; - case 3: - return ConstantsRes.NoReturn; - case 4: - return ConstantsRes.Failure; - case 5: - return ConstantsRes.Success; - case 6: - return ConstantsRes.Failure; - default: - return ConstantsRes.Unknown; - } - } - - /// - /// 制空戦の結果を表す文字列を取得します。 - /// - public static string GetAirSuperiority(int id) => GetAirSuperiority((AirState)id); + DetectionType.Success => ConstantsRes.Success, + DetectionType.SuccessNoReturn => ConstantsRes.Success + "△", + DetectionType.NoReturn => ConstantsRes.NoReturn, + DetectionType.Failure => ConstantsRes.Failure, + DetectionType.SuccessNoPlane => ConstantsRes.Success, + DetectionType.FailureNoPlane => ConstantsRes.Failure, + _ => ConstantsRes.Unknown, + }; /// /// 制空戦の結果を表す文字列を取得します。 diff --git a/ElectronicObserver/Data/ConstantsRes.zh-CN.resx b/ElectronicObserver/Data/ConstantsRes.zh-CN.resx index f9bf7180c..ab2750804 100644 --- a/ElectronicObserver/Data/ConstantsRes.zh-CN.resx +++ b/ElectronicObserver/Data/ConstantsRes.zh-CN.resx @@ -1,1099 +1,1099 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 防空装置 - - - 高速+ - - - 长门,准备好了么?冲了哦,第一战队,齐射,开火! - - - 僚舰夜战突袭(傻摸) - - - 最速 - - - 演习 昼战 - - - 演习 夜战 - - - BOSS战斗 - - - 一般战斗 - - - 泊地 - - - - - - 驱逐舰CI(鱼雷/运输桶/水雷战队 熟练见张员) - - - 驱逐舰CI(鱼雷/鱼雷/水雷战队 熟练见张员) - - - 对空CI ( {0}, {1}({2}) ) - - - SS++ - - - 资源 - - - 单纵阵 - - - 警戒阵 - - - 无损失 - - - 损失陆航 - - - 资源・陆航 - - - 资源损失 - - - 联合舰队-机动部队 对联合舰队 昼战 - - - 联合部队-机动部队 昼战 - - - 通常舰队 对联合舰队 昼战 - - - 《{0}》 - - - 通常舰队 开幕夜战 - - - 通常舰队 昼战 - - - 通常舰队 夜战 - - - 联合舰队 开幕夜战 - - - 对联合舰队 夜战 - - - 联合舰队-水上部队 对联合舰队 昼战 - - - 没有发生 - - - 无事件 - - - 无损失 - - - 损失的资源·陆航 - - - 损失的资源 - - - 雷达伏击 - - - 陆航的损失 - - - 联合舰队 航空战 - - - 提督 - - - 空袭 - - - 航空战 - - - - - - 大口径主炮 - - - 高速修复材 - - - - - - 复纵阵 - - - 轮型阵 - - - 梯形阵 - - - 节点: - - - - - - 高角炮+高射装置 - - - 我军阵容: - - - 我军照明弹投射: {0} #{1} - - - 我军夜间接触: - - - 我军索敌: - - - 我军接触 - - - 我军探照灯照射: {0} #{1} - - - 昼战 - - - 昼夜战 - - - - - - 中佐 - - - 中破 - - - 中将 - - - 中坚少佐 - - - - - - 制空权丧失 - - - 制空权确保 - - - - - - 远征结果 - - - 远征 - - - 元帅 - - - 樱虹 - - - - - - - - - 长门级改二特殊攻击(胸热)! - - - 夜转昼战 - - - 夜战 - - - 夜战 - - - 夜间瑞云CI - - - 对陆攻击(大发动艇) - - - 对陆攻击(大发动艇) - - - 对陆攻击(大发+战车) - - - 对陆攻击(内火艇) - - - 对陆攻击(特大发动艇) - - - 对陆攻击(特大发+战车) - - - 对陆地点 - - - 演习 - - - 休息 - - - 新米中佐 - - - 新米少佐 - - - 小破 - - - 无伤 - - - - - - 旋涡 - - - 友军基地航空队 参加中队: - - - 未选择 - - - 未返回 - - - 退避 - - - 退避 - - - 同航战 - - - 通常舰队 航空战 - - - 通常舰队 长距离空袭 - - - 通常舰队 雷达射击 - - - 通常舰队 - - - 通常攻击 - - - 提督经验值: +{0} - - - 梯形阵 - - - 特殊放置 - - - 弹药 - - - 其他 - - - 其他 - - - 索敌 - - - 损害 - - - 损害 - - - 水上部队 - - - 运输部队 - - - 时报 - - - 失败(非索敌机) - - - 失败 - - - 少佐 - - - 少将 - - - 三式弹 - - - 瑞云立体攻击 - - - 燃料 - - - 驱逐舰CI(主炮/鱼雷/电探) - - - 驱逐舰CI(鱼雷/见长/电探) - - - 潜水舰队攻击(3・4) - - - 潜水舰队攻击2・4) - - - 潜水舰队攻击(2・3) - - - 这只是我的想象 - - - 破坏 - - - 喷进炮改二 - - - 炮击支援 - - - 炮击 - - - - - - 母港 - - - 轮型阵 - - - 陆上 - - - 连续射击 - - - 连续射击 - - - 联合舰队 长距离空袭 - - - 脱离 - - - 雷击支援 - - - 雷击+暴击 - - - 雷击 - - - - - - 空袭战 - - - 空母CI - - - 开发资材 - - - 警戒阵 - - - - - - 交战形态: - - - 舰娘基本经验值: +{0} - - - 舰娘 - - - 健在 - - - - - - 家具币 - - - 集中机枪 - - - 机动部队 - - - 击沉 - - - 陆航基地空袭战 - - - 没有获得资源 - - - 混乱 - - - 辉虹 - - - - - - 航空支援 - - - 航空战 - - - 航空优势 - - - 航空劣势 - - - 航空均势 - - - 海空立体攻击 - - - 工厂 - - - 高速建造材 - - - 高速 - - - 高角炮x2 - - - 高角炮 - - - 钢材 - - - 改装 - - - 改修资材 - - - 复纵阵 - - - 非战斗 - - - 放置 - - - 防空 - - - 反航战 - - - 对通常舰队 夜转昼战 - - - 对潜支援 - - - - - - 电探 - - - 第一战队、突击!主炮、全力齐射! - - - 第一警戒航行序列 - - - 第一警戒 - - - 第一警戒 - - - 第四警戒航行序列 - - - 第四警戒 - - - 第四警戒 - - - 第三警戒航行序列 - - - 第三警戒 - - - 第三警戒 - - - 第二警戒 - - - 第二警戒 - - - 第二警戒 - - - 第{0}基地 - - - 敌方联合舰队 - - - 敌军照明弾投射: {0} #{1} - - - 敌军夜间接触: - - - 敌军探照灯照射: {0} #{1} - - - 敌军接触 - - - 低速 - - - 单纵阵 - - - 单横阵 - - - 单横阵 - - - - - - 铝土 - - - 大佐 - - - 常见的 - - - 大破 - - - Cut-in - - - 暴雷攻击 - - - EX全息 - - - 编成 - - - 大将 - - - 大成功 - - - 全息 - - - - - - 船团护卫成功 - - - 激光攻击 - - - - - - (主炮x3) - - - (主炮/彻甲弹) - - - (主炮/主炮) - - - (主炮x2/副炮) - - - (主炮/电探) - - - (主炮/副炮) - - - (主炮/鱼雷) - - - - - - - - - 稀有 - - - - - - 火箭弹轰炸 - - - S全息 - - - 出击 - - - SS全息 - - - 初期位置 - - - 成功 - - - 成功(非侦查机) - - - 成功(部分未归还) - - - 补给 - - - T有利 - - - T不利 - - - (鱼雷x2) - - - 不明 - - - 超长 - - - - - - BOSS战 - - - 出击中 - - - SS全息+ - - - 待机 - - - 出击 - - - 暴击 - - - (BOSS) - - - 〈第{0}波〉 - - - 〈友军主力舰队〉 - - - 〈友军舰队〉 - - - 〈友军伴随舰队〉 - - - 〈敌方主力舰队〉 - - - 〈敌方伴随舰队〉 - - - 〈敌方舰队〉 - - - 〈基地航空队〉 - - - / 敌军阵容: - - - / 敌军索敌: - - - 《战斗结束》 - - - #{0}: {1} {2} HP: {3} / {4} - 火力{5}, 雷装{6}, 对空{7}, 装甲{8} - - - - 火力{0}, 雷装{1}, 对空{2}, 装甲{3} - - - ◆ 战斗结果 - ◆ - - - 排名:{0} - - - MVP(主力舰队): {0} - - - MVP(伴随舰队): {0} - - - 降低: - - - T有利 - - - T不利 - - - 激光攻击 - - - CI(主炮/副炮) - - - CI(主炮/电探) - - - CI(主炮/彻甲弹) - - - CI(主炮/主炮) - - - 纳尔逊摸 (Nelson Touch) - - - 科罗拉多摸 (Colorado Touch) - - - CI(主炮/鱼雷) - - - CI(鱼雷x2) - - - CI(主炮x2/副炮) - - - CI(主炮x3) - - - <秋月> - - - <摩耶> - - - <五十铃> - - - <霞> - - - <皋月> - - - (非高射装置) - - - <鬼怒> - - - <由良> - - - <文月> - - - (非集中) - - - <UIT-25> - - - <龙田> - - - <伊势> - - - <武藏> - - - <滨风> - - - <天龙> - - - 火箭发射器 x2 或 FCR/砰砰炮 或 火箭发射器/砰砰炮 <英国> - - - Fletcher炮改 - - - Atlanta炮 - - - 一月 - - - 二月 - - - 三月 - - - 四月 - - - 五月 - - - 六月 - - - 七月 - - - 八月 - - - 九月 - - - 十月 - - - 十一月 - - - 十二月 - - - 重置 - - - 大和开始突击!二号舰也请跟上来!全主炮、齐射! - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 防空装置 + + + 高速+ + + + 长门,准备好了么?冲了哦,第一战队,齐射,开火! + + + 僚舰夜战突袭(傻摸) + + + 最速 + + + 演习 昼战 + + + 演习 夜战 + + + BOSS战斗 + + + 一般战斗 + + + 泊地 + + + + + + 驱逐舰CI(鱼雷/运输桶/水雷战队 熟练见张员) + + + 驱逐舰CI(鱼雷/鱼雷/水雷战队 熟练见张员) + + + 对空CI ( {0}, {1}({2}) ) + + + SS++ + + + 资源 + + + 单纵阵 + + + 警戒阵 + + + 无损失 + + + 损失陆航 + + + 资源・陆航 + + + 资源损失 + + + 联合舰队-机动部队 对联合舰队 昼战 + + + 联合部队-机动部队 昼战 + + + 通常舰队 对联合舰队 昼战 + + + 《{0}》 + + + 通常舰队 开幕夜战 + + + 通常舰队 昼战 + + + 通常舰队 夜战 + + + 联合舰队 开幕夜战 + + + 对联合舰队 夜战 + + + 联合舰队-水上部队 对联合舰队 昼战 + + + 没有发生 + + + 无事件 + + + 无损失 + + + 损失的资源·陆航 + + + 损失的资源 + + + 雷达伏击 + + + 陆航的损失 + + + 联合舰队 航空战 + + + 提督 + + + 空袭 + + + 航空战 + + + + + + 大口径主炮 + + + 高速修复材 + + + + + + 复纵阵 + + + 轮型阵 + + + 梯形阵 + + + 节点: + + + + + + 高角炮+高射装置 + + + 我军阵容: + + + 我军照明弹投射: {0} #{1} + + + 我军夜间接触: + + + 我军索敌: + + + 我军接触 + + + 我军探照灯照射: {0} #{1} + + + 昼战 + + + 昼夜战 + + + + + + 中佐 + + + 中破 + + + 中将 + + + 中坚少佐 + + + + + + 制空权丧失 + + + 制空权确保 + + + + + + 远征结果 + + + 远征 + + + 元帅 + + + 樱虹 + + + + + + + + + 长门级改二特殊攻击(胸热)! + + + 夜转昼战 + + + 夜战 + + + 夜战 + + + 夜间瑞云CI + + + 对陆攻击(大发动艇) + + + 对陆攻击(大发动艇) + + + 对陆攻击(大发+战车) + + + 对陆攻击(内火艇) + + + 对陆攻击(特大发动艇) + + + 对陆攻击(特大发+战车) + + + 对陆地点 + + + 演习 + + + 休息 + + + 新米中佐 + + + 新米少佐 + + + 小破 + + + 无伤 + + + + + + 旋涡 + + + 友军基地航空队 参加中队: + + + 未选择 + + + 未返回 + + + 退避 + + + 退避 + + + 同航战 + + + 通常舰队 航空战 + + + 通常舰队 长距离空袭 + + + 通常舰队 雷达射击 + + + 通常舰队 + + + 通常攻击 + + + 提督经验值: +{0} + + + 梯形阵 + + + 特殊放置 + + + 弹药 + + + 其他 + + + 其他 + + + 索敌 + + + 损害 + + + 损害 + + + 水上部队 + + + 运输部队 + + + 时报 + + + 失败(非索敌机) + + + 失败 + + + 少佐 + + + 少将 + + + 三式弹 + + + 瑞云立体攻击 + + + 燃料 + + + 驱逐舰CI(主炮/鱼雷/电探) + + + 驱逐舰CI(鱼雷/见长/电探) + + + 潜水舰队攻击(3・4) + + + 潜水舰队攻击2・4) + + + 潜水舰队攻击(2・3) + + + 这只是我的想象 + + + 破坏 + + + 喷进炮改二 + + + 炮击支援 + + + 炮击 + + + + + + 母港 + + + 轮型阵 + + + 陆上 + + + 连续射击 + + + 连续射击 + + + 联合舰队 长距离空袭 + + + 脱离 + + + 雷击支援 + + + 雷击+暴击 + + + 雷击 + + + + + + 空袭战 + + + 空母CI + + + 开发资材 + + + 警戒阵 + + + + + + 交战形态: + + + 舰娘基本经验值: +{0} + + + 舰娘 + + + 健在 + + + + + + 家具币 + + + 集中机枪 + + + 机动部队 + + + 击沉 + + + 陆航基地空袭战 + + + 没有获得资源 + + + 混乱 + + + 辉虹 + + + + + + 航空支援 + + + 航空战 + + + 航空优势 + + + 航空劣势 + + + 航空均势 + + + 海空立体攻击 + + + 工厂 + + + 高速建造材 + + + 高速 + + + 高角炮x2 + + + 高角炮 + + + 钢材 + + + 改装 + + + 改修资材 + + + 复纵阵 + + + 非战斗 + + + 放置 + + + 防空 + + + 反航战 + + + 对通常舰队 夜转昼战 + + + 对潜支援 + + + + + + 电探 + + + 第一战队、突击!主炮、全力齐射! + + + 第一警戒航行序列 + + + 第一警戒 + + + 第一警戒 + + + 第四警戒航行序列 + + + 第四警戒 + + + 第四警戒 + + + 第三警戒航行序列 + + + 第三警戒 + + + 第三警戒 + + + 第二警戒 + + + 第二警戒 + + + 第二警戒 + + + 第{0}基地 + + + 敌方联合舰队 + + + 敌军照明弾投射: {0} #{1} + + + 敌军夜间接触: + + + 敌军探照灯照射: {0} #{1} + + + 敌军接触 + + + 低速 + + + 单纵阵 + + + 单横阵 + + + 单横阵 + + + + + + 铝土 + + + 大佐 + + + 常见的 + + + 大破 + + + Cut-in + + + 暴雷攻击 + + + EX全息 + + + 编成 + + + 大将 + + + 大成功 + + + 全息 + + + + + + 船团护卫成功 + + + 激光攻击 + + + + + + (主炮x3) + + + (主炮/彻甲弹) + + + (主炮/主炮) + + + (主炮x2/副炮) + + + (主炮/电探) + + + (主炮/副炮) + + + (主炮/鱼雷) + + + + + + + + + 稀有 + + + + + + 火箭弹轰炸 + + + S全息 + + + 出击 + + + SS全息 + + + 初期位置 + + + 成功 + + + 成功(非侦查机) + + + 成功(部分未归还) + + + 补给 + + + T有利 + + + T不利 + + + (鱼雷x2) + + + 不明 + + + 超长 + + + + + + BOSS战 + + + 出击中 + + + SS全息+ + + + 待机 + + + 出击 + + + 暴击 + + + (BOSS) + + + 〈第{0}波〉 + + + 〈友军主力舰队〉 + + + 〈友军舰队〉 + + + 〈友军伴随舰队〉 + + + 〈敌方主力舰队〉 + + + 〈敌方伴随舰队〉 + + + 〈敌方舰队〉 + + + 〈基地航空队〉 + + + / 敌军阵容: + + + / 敌军索敌: + + + 《战斗结束》 + + + #{0}: {1} {2} HP: {3} / {4} - 火力{5}, 雷装{6}, 对空{7}, 装甲{8} + + + - 火力{0}, 雷装{1}, 对空{2}, 装甲{3} + + + ◆ 战斗结果 + ◆ + + + 排名:{0} + + + MVP(主力舰队): {0} + + + MVP(伴随舰队): {0} + + + 降低: + + + T有利 + + + T不利 + + + 激光攻击 + + + CI(主炮/副炮) + + + CI(主炮/电探) + + + CI(主炮/彻甲弹) + + + CI(主炮/主炮) + + + 纳尔逊摸 (Nelson Touch) + + + 科罗拉多摸 (Colorado Touch) + + + CI(主炮/鱼雷) + + + CI(鱼雷x2) + + + CI(主炮x2/副炮) + + + CI(主炮x3) + + + <秋月> + + + <摩耶> + + + <五十铃> + + + <霞> + + + <皋月> + + + (非高射装置) + + + <鬼怒> + + + <由良> + + + <文月> + + + (非集中) + + + <UIT-25> + + + <龙田> + + + <伊势> + + + <武藏> + + + <滨风> + + + <天龙> + + + 火箭发射器 x2 或 FCR/砰砰炮 或 火箭发射器/砰砰炮 <英国> + + + Fletcher炮改 + + + Atlanta炮 + + + 一月 + + + 二月 + + + 三月 + + + 四月 + + + 五月 + + + 六月 + + + 七月 + + + 八月 + + + 九月 + + + 十月 + + + 十一月 + + + 十二月 + + + 重置 + + + 大和开始突击!二号舰也请跟上来!全主炮、齐射! + \ No newline at end of file diff --git a/ElectronicObserver/Data/DataRes.zh-CN.resx b/ElectronicObserver/Data/DataRes.zh-CN.resx index 81dd9a706..4b12397b6 100644 --- a/ElectronicObserver/Data/DataRes.zh-CN.resx +++ b/ElectronicObserver/Data/DataRes.zh-CN.resx @@ -1,196 +1,196 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 舰娘数量{0}{1} - - - Lv总计 - - - 旗舰Lv - - - (驱逐+海防) - - - 空母系 - - - 潜艇系 - - - (轻巡+练巡+护卫空母) - - - 旗舰: - - - 旗舰:护卫空母 - - - 火力 - - - 对空 - - - 对潜 - - - 索敌 - - - {0}: 装备的舰娘数量 {1}{2} - - - {0}: 装备数量 {1}{2} - - - 失败 - - - 成功 - - - 护卫队(轻巡1驱逐2其他) - - - 护卫队(轻巡1驱逐3其他) - - - 不支持 - - - (未证实) - - - {0} {1}{2} - - - {0} {1}{2} - - - (不含水母) - - - 有搭载数为0的飞机 -可能不满足远征成功的条件 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 舰娘数量{0}{1} + + + Lv总计 + + + 旗舰Lv + + + (驱逐+海防) + + + 空母系 + + + 潜艇系 + + + (轻巡+练巡+护卫空母) + + + 旗舰: + + + 旗舰:护卫空母 + + + 火力 + + + 对空 + + + 对潜 + + + 索敌 + + + {0}: 装备的舰娘数量 {1}{2} + + + {0}: 装备数量 {1}{2} + + + 失败 + + + 成功 + + + 护卫队(轻巡1驱逐2其他) + + + 护卫队(轻巡1驱逐3其他) + + + 不支持 + + + (未证实) + + + {0} {1}{2} + + + {0} {1}{2} + + + (不含水母) + + + 有搭载数为0的飞机 +可能不满足远征成功的条件 + \ No newline at end of file diff --git a/ElectronicObserver/Data/FleetManager.cs b/ElectronicObserver/Data/FleetManager.cs index 80091a93f..ddfeeed4a 100644 --- a/ElectronicObserver/Data/FleetManager.cs +++ b/ElectronicObserver/Data/FleetManager.cs @@ -98,10 +98,10 @@ public override void LoadFromResponse(string apiname, dynamic data) { int index = ii - 1; - if (index < battle.FirstBattle.Initial.FriendFleet.Members.Count) - battle.FirstBattle.Initial.FriendFleet.Escape(index); + if (index < battle.FirstBattle.FleetsBeforeBattle.Fleet.Members.Count) + battle.FirstBattle.FleetsBeforeBattle.Fleet.Escape(index); else - battle.FirstBattle.Initial.FriendFleetEscort.Escape(index - 6); + battle.FirstBattle.FleetsBeforeBattle.EscortFleet!.Escape(index - 6); } } break; diff --git a/ElectronicObserver/Data/FleetRes.zh-CN.resx b/ElectronicObserver/Data/FleetRes.zh-CN.resx index e438021c2..0daad4cb1 100644 --- a/ElectronicObserver/Data/FleetRes.zh-CN.resx +++ b/ElectronicObserver/Data/FleetRes.zh-CN.resx @@ -1,201 +1,201 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 泊地修理中 - - - 完成时间 - - - !!正在大破进击 !! - - - 大破舰娘沉没! - - - 入渠中 - - - 预计恢复日期 - - - 疲劳 - - - 战意高扬! - - - #{0}「{1}」已返回母港。 - - - 无所属舰娘 - - - 远征中 - - - 出击中 - - - 准备出击! - - - 油 : {0} -弹 : {1} -铝 : {2} ({3}机) - - - 最低士气: {0} -剩余 {1} 次可以远征 - - - 未补给 - - - {0} : {1} -完成日期 : {2} - - - 泊地修理中 - - - 开始时间 : {0} -修复时间 : - - - - #{0} : {1} @ {2} x -{3} HP - - - - 入渠中 - - - 完成日期 : - - - 预计恢复时间: {0} -(预测误差: {1}) - - - 油 : {0}/{1} ({2}%) -弹 : {3}/{4} ({5}%) - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 泊地修理中 + + + 完成时间 + + + !!正在大破进击 !! + + + 大破舰娘沉没! + + + 入渠中 + + + 预计恢复日期 + + + 疲劳 + + + 战意高扬! + + + #{0}「{1}」已返回母港。 + + + 无所属舰娘 + + + 远征中 + + + 出击中 + + + 准备出击! + + + 油 : {0} +弹 : {1} +铝 : {2} ({3}机) + + + 最低士气: {0} +剩余 {1} 次可以远征 + + + 未补给 + + + {0} : {1} +完成日期 : {2} + + + 泊地修理中 + + + 开始时间 : {0} +修复时间 : + + + + #{0} : {1} @ {2} x -{3} HP + + + + 入渠中 + + + 完成日期 : + + + 预计恢复时间: {0} +(预测误差: {1}) + + + 油 : {0}/{1} ({2}%) +弹 : {3}/{4} ({5}%) + \ No newline at end of file diff --git a/ElectronicObserver/Data/KCDatabase.cs b/ElectronicObserver/Data/KCDatabase.cs index 36524ebf7..0177fcb7d 100644 --- a/ElectronicObserver/Data/KCDatabase.cs +++ b/ElectronicObserver/Data/KCDatabase.cs @@ -60,7 +60,7 @@ public sealed class KCDatabase : IKCDatabase /// /// 保有装備のデータ /// - public IDDictionary Equipments { get; private set; } + public IDDictionary Equipments { get; private set; } /// diff --git a/ElectronicObserver/Data/PoiDbSubmission/PoiDbSubmissionResources.zh-CN.resx b/ElectronicObserver/Data/PoiDbSubmission/PoiDbSubmissionResources.zh-CN.resx index c95cc9ce7..fdb06fef0 100644 --- a/ElectronicObserver/Data/PoiDbSubmission/PoiDbSubmissionResources.zh-CN.resx +++ b/ElectronicObserver/Data/PoiDbSubmission/PoiDbSubmissionResources.zh-CN.resx @@ -1,126 +1,126 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - PoiDB 错误 - - - 详细信息 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + PoiDB 错误 + + + 详细信息 + \ No newline at end of file diff --git a/ElectronicObserver/Data/Quest/QuestProgressManager.cs b/ElectronicObserver/Data/Quest/QuestProgressManager.cs index 945678483..8549c182a 100644 --- a/ElectronicObserver/Data/Quest/QuestProgressManager.cs +++ b/ElectronicObserver/Data/Quest/QuestProgressManager.cs @@ -1275,7 +1275,7 @@ void BattleFinished(string apiname, dynamic data) var bm = KCDatabase.Instance.Battle; var battle = bm.SecondBattle ?? bm.FirstBattle; - var hps = battle.ResultHPs; + var hps = battle.ResultHPs.ToList(); if (hps == null) return; @@ -1293,17 +1293,17 @@ void BattleFinished(string apiname, dynamic data) continue; foreach (var p in slaughterList) - p.Increment(ship.ShipType); + p.Increment(ship.MasterShip.ShipType); } if (bm.IsEnemyCombined && hps[Battle.BattleIndex.Get(Battle.BattleSides.EnemyEscort, i)] <= 0) { - var ship = battle.Initial.EnemyMembersEscortInstance[i]; + var ship = battle.Initial.EnemyMembersEscortInstance?[i]; if (ship == null) continue; foreach (var p in slaughterList) - p.Increment(ship.ShipType); + p.Increment(ship.MasterShip.ShipType); } } diff --git a/ElectronicObserver/Data/Quest/QuestTracking.zh-CN.resx b/ElectronicObserver/Data/Quest/QuestTracking.zh-CN.resx index 0b77c1599..9aed0a726 100644 --- a/ElectronicObserver/Data/Quest/QuestTracking.zh-CN.resx +++ b/ElectronicObserver/Data/Quest/QuestTracking.zh-CN.resx @@ -1,225 +1,225 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - Boss - - - Boss胜利 - - - 达成 - - - 出击 - - - S胜 - - - 补给 - - - 击沉 - - - 建造 - - - 开发 - - - 解体 - - - 装备改修 - - - 现代化改修 - - - 入渠 - - - 废弃 - - - - - - - - - (第{0}阶段) - - - 出击 {0}/{1} - - - S胜 {0}/{1} - - - Boss {0}/{1} - - - Boss胜利 {0}/{1} - - - 出击 {0}, S胜 {1}, Boss {2}, Boss胜利 {3} - - - Boss - - - 到达 - - - 战斗 - - - 以上 - - - 胜利 - - - 胜利 - - - 图鉴 - - - 图标 - - - 远征 - - - 演习 - - - 任务进度已自动保存。 - - - 到达 - - - 首次清除 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Boss + + + Boss胜利 + + + 达成 + + + 出击 + + + S胜 + + + 补给 + + + 击沉 + + + 建造 + + + 开发 + + + 解体 + + + 装备改修 + + + 现代化改修 + + + 入渠 + + + 废弃 + + + + + + + + + (第{0}阶段) + + + 出击 {0}/{1} + + + S胜 {0}/{1} + + + Boss {0}/{1} + + + Boss胜利 {0}/{1} + + + 出击 {0}, S胜 {1}, Boss {2}, Boss胜利 {3} + + + Boss + + + 到达 + + + 战斗 + + + 以上 + + + 胜利 + + + 胜利 + + + 图鉴 + + + 图标 + + + 远征 + + + 演习 + + + 任务进度已自动保存。 + + + 到达 + + + 首次清除 + \ No newline at end of file diff --git a/ElectronicObserver/Data/TsunDbSubmission/Battle/TsunDbBattleData.cs b/ElectronicObserver/Data/TsunDbSubmission/Battle/TsunDbBattleData.cs index c35d85fd4..e316f94ab 100644 --- a/ElectronicObserver/Data/TsunDbSubmission/Battle/TsunDbBattleData.cs +++ b/ElectronicObserver/Data/TsunDbSubmission/Battle/TsunDbBattleData.cs @@ -93,7 +93,7 @@ public TsunDbBattleData(string apiName, dynamic rawApi) Fleet = new TsunDbFleetsAndAirBaseData(); ResupplyUsed = Database.Battle.ResupplyUsed; - Formation = Database.Battle.FirstBattle.Searching.FormationFriend; + Formation = (int)Database.Battle.FirstBattle.Searching.PlayerFormationType; AmountOfNodes = TsunDbSubmissionManager.CurrentMapAmountOfNodes; RawApi = JsonSerializer.Deserialize(rawApi.ToString()); diff --git a/ElectronicObserver/Data/TsunDbSubmission/EnemyComp.cs b/ElectronicObserver/Data/TsunDbSubmission/EnemyComp.cs index 045e3e70e..f73783d11 100644 --- a/ElectronicObserver/Data/TsunDbSubmission/EnemyComp.cs +++ b/ElectronicObserver/Data/TsunDbSubmission/EnemyComp.cs @@ -3,7 +3,7 @@ using System.Linq; using System.Text.Json.Serialization; using ElectronicObserver.Core.Types; -using ElectronicObserver.Data.Battle.Phase; +using ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle.Phase; namespace ElectronicObserver.Data.TsunDbSubmission; @@ -21,7 +21,7 @@ public class EnemyComp : TsunDbEntity public List HP { get; private set; } = new(); [JsonPropertyName("stats")] - public List Stats { get; private set; } = new(); + public List> Stats { get; private set; } = new(); [JsonPropertyName("equip")] public List Equips { get; private set; } = new(); @@ -53,7 +53,7 @@ public class EnemyComp : TsunDbEntity public List? HPEscort { get; private set; } [JsonPropertyName("statsEscort")] - public List? StatsEscort { get; private set; } + public List>? StatsEscort { get; private set; } [JsonPropertyName("equipEscort")] public List? EquipsEscort { get; private set; } @@ -70,7 +70,7 @@ public void PrepareEnemyCompFromCurrentState() HP = initial.EnemyMaxHPs.Take(shipCount).ToList(); Stats = initial.EnemyParameters.Take(shipCount).ToList(); Equips = initial.EnemySlots.Take(shipCount).ToList(); - Formation = db.Battle.FirstBattle.Searching.FormationEnemy; + Formation = (int)db.Battle.FirstBattle.Searching.EnemyFormationType; // If this is an event map if (db.Battle.Compass.MapAreaID > 30) @@ -94,6 +94,6 @@ public void PrepareEnemyCompFromCurrentState() EquipsEscort = initial.EnemySlotsEscort.Take(shipCount).ToList(); } - IsAirRaid = db.Battle.BattleMode == Data.Battle.BattleManager.BattleModes.AirRaid; + IsAirRaid = db.Battle.IsAirRaid; } } diff --git a/ElectronicObserver/Data/TsunDbSubmission/ShipDrop.cs b/ElectronicObserver/Data/TsunDbSubmission/ShipDrop.cs index 95b188d31..3d85c8bd7 100644 --- a/ElectronicObserver/Data/TsunDbSubmission/ShipDrop.cs +++ b/ElectronicObserver/Data/TsunDbSubmission/ShipDrop.cs @@ -68,7 +68,7 @@ private void PrepareDropData(dynamic apidata) HqLvl = db.Admiral.Level; Difficulty = mapInfoData.EventDifficulty > 0 ? mapInfoData.EventDifficulty : 0; - Ship = db.Battle.Result.DroppedShipID > 0 ? db.Battle.Result.DroppedShipID : -1; + Ship = db.Battle.Result.DroppedShipId > 0 ? (int)db.Battle.Result.DroppedShipId : -1; PrepareEnemyCompData(apidata); } diff --git a/ElectronicObserver/Data/TsunDbSubmission/ShipDropLoc.cs b/ElectronicObserver/Data/TsunDbSubmission/ShipDropLoc.cs index 9a290b87e..1fb9be302 100644 --- a/ElectronicObserver/Data/TsunDbSubmission/ShipDropLoc.cs +++ b/ElectronicObserver/Data/TsunDbSubmission/ShipDropLoc.cs @@ -51,6 +51,6 @@ private void PrepareDropData(dynamic apidata) } Difficulty = mapInfoData.EventDifficulty > 0 ? mapInfoData.EventDifficulty : 0; - Ship = db.Battle.Result.DroppedShipID > 0 ? db.Battle.Result.DroppedShipID : -1; + Ship = db.Battle.Result.DroppedShipId > 0 ? (int)db.Battle.Result.DroppedShipId : -1; } } diff --git a/ElectronicObserver/LoggerRes.zh-CN.resx b/ElectronicObserver/LoggerRes.zh-CN.resx index e01e0970d..8510e13cb 100644 --- a/ElectronicObserver/LoggerRes.zh-CN.resx +++ b/ElectronicObserver/LoggerRes.zh-CN.resx @@ -1,308 +1,308 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 附加信息 : {0} - - - 通讯内容 : {0} - - - APIObserver:开始在端口 {0} 上接收。 - - - APIObserver:接收已停止。 - - - 更新了参数。 - - - {0}「{1}」开发成功。(消耗{2}/{3}/{4}/{5} 秘书舰: {6}) - - - 不存在。 - - - 获得了{0}「{1}」。 - - - 发送到 艦これ 统计数据库时发生错误。 - - - 错误 : {0} - - - 错误报告 : {0} - - - 设置 Flash 质量。 - - - 失败了。 - - - 无法将 {0} 发送到 砍口垒 统计数据库。 - - - API加载失败。 - - -  加载失败。 - - - 加载记录失败。 - - - 加载资源文件失败。 - - - 无法加载数据存储。 - - - 无法恢复窗口布局。 - - - 无法恢复子窗口布局。 - - - 无法恢复窗口状态。 - - - 无法重命名舰娘资源。 - - - 无法保存子窗口布局。 - - - 保存通讯内容失败。 - - - 无法保存窗口状态。 - - - 无法存储。 - - - 无法写入错误报告。 -{0} -{1} - - - 数据存储写入失败。 - - - API文件 {0} 的加载失败了。{1} - - - 提督已抵达镇守府。正在将舰队指挥权转交给您。 - - - 图像资源 {0} 加载失败。 - - - 图像资源 {0} 不存在。 - - - {0} 的改修失败了。 - - - 的改修成功了。( - - - 的初始装备已记录。 - - - 开发失败。(消耗 {0}/{1}/{2}/{3} 秘书舰: {4}) - - - 获得物品「{0}」。(总计:{1} 个) - - - 您现已与 {0} 结婚了。(运+{1}→{2}/{3}) - - - 记录已加载。 - - - 收到请求: - - - 记录 - - - 的参数已记录。 - - - 接收请求时发生错误。 - - - 从服务器收到错误代码。 - - - 已保存 API 文件 {0}。 - - - 已将 {0} 发送至 砍口垒 统计数据库。 - - - {0}「{1}」加入了您的舰队。 - - - {0}「{1}」的建造已完成。 - - - 已解体。 - - - 数据存储 {0} 不存在。 - - - 数据存储文件不存在。 - - - {0} 已被复制。 - - - 已退役。 - - - 复制 {0} 失败。 {1} - - - MVP 候选人有多位。请检查日志。 - - - 自动保存记录失败。 - - - 执行了记录的自动保存。 - - - 对{0}的修改成功。 - - - 任务『{0}』已完成。 - - - #{0}「{1}」 正在出击 「{2}-{3} {4}」。 - - - #{0}「{1}」正在远征「{2}: {3}」。 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 附加信息 : {0} + + + 通讯内容 : {0} + + + APIObserver:开始在端口 {0} 上接收。 + + + APIObserver:接收已停止。 + + + 更新了参数。 + + + {0}「{1}」开发成功。(消耗{2}/{3}/{4}/{5} 秘书舰: {6}) + + + 不存在。 + + + 获得了{0}「{1}」。 + + + 发送到 艦これ 统计数据库时发生错误。 + + + 错误 : {0} + + + 错误报告 : {0} + + + 设置 Flash 质量。 + + + 失败了。 + + + 无法将 {0} 发送到 砍口垒 统计数据库。 + + + API加载失败。 + + +  加载失败。 + + + 加载记录失败。 + + + 加载资源文件失败。 + + + 无法加载数据存储。 + + + 无法恢复窗口布局。 + + + 无法恢复子窗口布局。 + + + 无法恢复窗口状态。 + + + 无法重命名舰娘资源。 + + + 无法保存子窗口布局。 + + + 保存通讯内容失败。 + + + 无法保存窗口状态。 + + + 无法存储。 + + + 无法写入错误报告。 +{0} +{1} + + + 数据存储写入失败。 + + + API文件 {0} 的加载失败了。{1} + + + 提督已抵达镇守府。正在将舰队指挥权转交给您。 + + + 图像资源 {0} 加载失败。 + + + 图像资源 {0} 不存在。 + + + {0} 的改修失败了。 + + + 的改修成功了。( + + + 的初始装备已记录。 + + + 开发失败。(消耗 {0}/{1}/{2}/{3} 秘书舰: {4}) + + + 获得物品「{0}」。(总计:{1} 个) + + + 您现已与 {0} 结婚了。(运+{1}→{2}/{3}) + + + 记录已加载。 + + + 收到请求: + + + 记录 + + + 的参数已记录。 + + + 接收请求时发生错误。 + + + 从服务器收到错误代码。 + + + 已保存 API 文件 {0}。 + + + 已将 {0} 发送至 砍口垒 统计数据库。 + + + {0}「{1}」加入了您的舰队。 + + + {0}「{1}」的建造已完成。 + + + 已解体。 + + + 数据存储 {0} 不存在。 + + + 数据存储文件不存在。 + + + {0} 已被复制。 + + + 已退役。 + + + 复制 {0} 失败。 {1} + + + MVP 候选人有多位。请检查日志。 + + + 自动保存记录失败。 + + + 执行了记录的自动保存。 + + + 对{0}的修改成功。 + + + 任务『{0}』已完成。 + + + #{0}「{1}」 正在出击 「{2}-{3} {4}」。 + + + #{0}「{1}」正在远征「{2}: {3}」。 + \ No newline at end of file diff --git a/ElectronicObserver/Notifier/NotifierDamage.cs b/ElectronicObserver/Notifier/NotifierDamage.cs index df89ae9bc..2083046fd 100644 --- a/ElectronicObserver/Notifier/NotifierDamage.cs +++ b/ElectronicObserver/Notifier/NotifierDamage.cs @@ -182,10 +182,10 @@ private void CheckBattle() var list = new List(); var battle = bm.SecondBattle ?? bm.FirstBattle; - list.AddRange(GetDamagedShips(battle.Initial.FriendFleet, battle.ResultHPs.ToArray())); + list.AddRange(GetDamagedShips(battle.FleetsBeforeBattle.Fleet, battle.ResultHPs.ToArray())); if (bm.IsCombinedBattle) - list.AddRange(GetDamagedShips(battle.Initial.FriendFleetEscort, battle.ResultHPs.Skip(6).ToArray())); + list.AddRange(GetDamagedShips(battle.FleetsBeforeBattle.EscortFleet!, battle.ResultHPs.Skip(6).ToArray())); if (list.Count > 0) @@ -211,7 +211,7 @@ private string[] GetDamagedShips(IEnumerable ships) return ships.Where(s => IsShipDamaged(s, s?.HPCurrent ?? 0)).Select(s => $"{s.NameWithLevel} ({s.HPCurrent}/{s.HPMax})").ToArray(); } - private string[] GetDamagedShips(FleetData fleet, int[] hps) + private string[] GetDamagedShips(IFleetData fleet, int[] hps) { LinkedList list = new LinkedList(); diff --git a/ElectronicObserver/Properties/BattleRes.zh-CN.resx b/ElectronicObserver/Properties/BattleRes.zh-CN.resx index 0b779425c..ea39884ae 100644 --- a/ElectronicObserver/Properties/BattleRes.zh-CN.resx +++ b/ElectronicObserver/Properties/BattleRes.zh-CN.resx @@ -1,307 +1,307 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 友军 - - - 战斗粮食补给 - - - (无) - - - 敌军 - - - 普通损管已启动 - - - 女神损管已启动 - - - 夜战 - - - 敌军航空队 - - - 开幕雷击 - - - 开幕对潜 - - - 基地航空队喷式强袭 - - - 喷式强袭 - - - 航空战 - - - 索敌 - - - 支援舰队 - - - 我军航空队 - - - 第{0}基地 - - - 演习 - - - (未确定) - - - 敌军索敌 - - - 我军索敌 - - - 退避中 - - - 夜战开始 - - - 在 {0}-{1}-{2}与「{3}」交战。 (评级: {4}, 提督经验+{5}, 舰娘经验+{6}). - - - - 空袭 - - - 基地航空队航空战 - - - 基地航空队 第{0}波 - - - 击破: {0} / {1} 回 - - - 保护 - - - / 索敌能力 [1] {0}, [2] {1}, [3] {2}, [4] {3} - - - 烟雾 - - - 友军航空攻击支援 - - - 夜间支援攻击 - - - 友军舰队援护 - - - 第一次夜战 - - - 第二次夜战 - - - 雷击战 - - - 第一次炮击战 - - - 第二次炮击战 - - - 第三次炮击战 - - - 支援攻击 - - - 第一次航空战 - - - 第二次航空战 - - - 陆航基地空袭 - - - 未知物品 - ID: - - - {0} 等级提升至 lv{1}. - - - 在 {0}-{1}-{2} ({3}遭受空袭, 受到伤害: {4}, {5}). - - - 敌方联合舰队 夜转昼 - - - 战力 - - - 联合舰队 水面部队 昼战 - - - 联合舰队雷达射击 - - - 联合舰队 夜战 - - - #{0}: 基地航空队 #{1} 血量: {2} / {3} - - - 友军舰队 - - - 对空CI 类型 #{2} ( {0}, {1} ) - - - 我军阵型 - - - 敌军阵型 - - - 交战类型 - - - : 装甲破坏(削甲) - - - 制空战力 - - - 制空战力 {0} (対基地 {1}) - - - 与「{0}」{1}的「{2}」进行了演习。(评级: {3}, 提督经验+{4}, 舰娘经验+{5} ) - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 友军 + + + 战斗粮食补给 + + + (无) + + + 敌军 + + + 普通损管已启动 + + + 女神损管已启动 + + + 夜战 + + + 敌军航空队 + + + 开幕雷击 + + + 开幕对潜 + + + 基地航空队喷式强袭 + + + 喷式强袭 + + + 航空战 + + + 索敌 + + + 支援舰队 + + + 我军航空队 + + + 第{0}基地 + + + 演习 + + + (未确定) + + + 敌军索敌 + + + 我军索敌 + + + 退避中 + + + 夜战开始 + + + 在 {0}-{1}-{2}与「{3}」交战。 (评级: {4}, 提督经验+{5}, 舰娘经验+{6}). + + + + 空袭 + + + 基地航空队航空战 + + + 基地航空队 第{0}波 + + + 击破: {0} / {1} 回 + + + 保护 + + + / 索敌能力 [1] {0}, [2] {1}, [3] {2}, [4] {3} + + + 烟雾 + + + 友军航空攻击支援 + + + 夜间支援攻击 + + + 友军舰队援护 + + + 第一次夜战 + + + 第二次夜战 + + + 雷击战 + + + 第一次炮击战 + + + 第二次炮击战 + + + 第三次炮击战 + + + 支援攻击 + + + 第一次航空战 + + + 第二次航空战 + + + 陆航基地空袭 + + + 未知物品 - ID: + + + {0} 等级提升至 lv{1}. + + + 在 {0}-{1}-{2} ({3}遭受空袭, 受到伤害: {4}, {5}). + + + 敌方联合舰队 夜转昼 + + + 战力 + + + 联合舰队 水面部队 昼战 + + + 联合舰队雷达射击 + + + 联合舰队 夜战 + + + #{0}: 基地航空队 #{1} 血量: {2} / {3} + + + 友军舰队 + + + 对空CI 类型 #{2} ( {0}, {1} ) + + + 我军阵型 + + + 敌军阵型 + + + 交战类型 + + + : 装甲破坏(削甲) + + + 制空战力 + + + 制空战力 {0} (対基地 {1}) + + + 与「{0}」{1}的「{2}」进行了演习。(评级: {3}, 提督经验+{4}, 舰娘经验+{5} ) + \ No newline at end of file diff --git a/ElectronicObserver/Properties/Data/BattleRes.zh-CN.resx b/ElectronicObserver/Properties/Data/BattleRes.zh-CN.resx index d118c8d3b..bc39ad2d2 100644 --- a/ElectronicObserver/Properties/Data/BattleRes.zh-CN.resx +++ b/ElectronicObserver/Properties/Data/BattleRes.zh-CN.resx @@ -1,306 +1,306 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 友军 - - - 战斗粮食补给 - - - (无) - - - 敌军 - - - 普通损管已启动 - - - 女神损管已启动 - - - 夜战 - - - 敌军航空队 - - - 开幕雷击 - - - 开幕对潜 - - - 基地航空队喷式强袭 - - - 喷式强袭 - - - 航空战 - - - 索敌 - - - 支援舰队 - - - 我军航空队 - - - 第{0}基地 - - - 演习 - - - (未确定) - - - 敌军索敌 - - - 我军索敌 - - - 退避中 - - - 夜战开始 - - - 空袭 - - - 基地航空队航空战 - - - 基地航空队 第{0}波 - - - 击破: {0} / {1} 回 - - - 保护 - - - / 索敌能力 [1] {0}, [2] {1}, [3] {2}, [4] {3} - - - 烟雾 - - - 友军航空攻击支援 - - - 夜间支援攻击 - - - 友军舰队援护 - - - 第一次夜战 - - - 第二次夜战 - - - 雷击战 - - - 第一次炮击战 - - - 第二次炮击战 - - - 第三次炮击战 - - - 支援攻击 - - - 第一次航空战 - - - 第二次航空战 - - - 陆航基地空袭 - - - 未知物品 - ID: - - - {0} 等级提升至 lv{1}. - - - 敌方联合舰队 夜转昼 - - - 战力 - - - 联合舰队 水面部队 昼战 - - - 联合舰队雷达射击 - - - 联合舰队 夜战 - - - #{0}: 基地航空队 #{1} 血量: {2} / {3} - - - 友军舰队 - - - 对空CI 类型 #{2} ( {0}, {1} ) - - - 我军阵型 - - - 敌军阵型 - - - 交战类型 - - - : 装甲破坏(削甲) - - - 制空战力 - - - 制空战力 {0} (対基地 {1}) - - - 「{0}」在演习中与{1}的「{2}」交战了。(等级:{3}、提督Exp+{4}、舰娘Exp+{5} ​​) - - - 该基地于 {0}-{1}-{2} 遭到空袭。 ({3},受到的总伤害:{4},{5}) - - - 在{0}-{1}-{2}与“{3}”展开战斗。 (等级:{4}、提督Exp+{5}、舰娘Exp+{6}) - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 友军 + + + 战斗粮食补给 + + + (无) + + + 敌军 + + + 普通损管已启动 + + + 女神损管已启动 + + + 夜战 + + + 敌军航空队 + + + 开幕雷击 + + + 开幕对潜 + + + 基地航空队喷式强袭 + + + 喷式强袭 + + + 航空战 + + + 索敌 + + + 支援舰队 + + + 我军航空队 + + + 第{0}基地 + + + 演习 + + + (未确定) + + + 敌军索敌 + + + 我军索敌 + + + 退避中 + + + 夜战开始 + + + 空袭 + + + 基地航空队航空战 + + + 基地航空队 第{0}波 + + + 击破: {0} / {1} 回 + + + 保护 + + + / 索敌能力 [1] {0}, [2] {1}, [3] {2}, [4] {3} + + + 烟雾 + + + 友军航空攻击支援 + + + 夜间支援攻击 + + + 友军舰队援护 + + + 第一次夜战 + + + 第二次夜战 + + + 雷击战 + + + 第一次炮击战 + + + 第二次炮击战 + + + 第三次炮击战 + + + 支援攻击 + + + 第一次航空战 + + + 第二次航空战 + + + 陆航基地空袭 + + + 未知物品 - ID: + + + {0} 等级提升至 lv{1}. + + + 敌方联合舰队 夜转昼 + + + 战力 + + + 联合舰队 水面部队 昼战 + + + 联合舰队雷达射击 + + + 联合舰队 夜战 + + + #{0}: 基地航空队 #{1} 血量: {2} / {3} + + + 友军舰队 + + + 对空CI 类型 #{2} ( {0}, {1} ) + + + 我军阵型 + + + 敌军阵型 + + + 交战类型 + + + : 装甲破坏(削甲) + + + 制空战力 + + + 制空战力 {0} (対基地 {1}) + + + 「{0}」在演习中与{1}的「{2}」交战了。(等级:{3}、提督Exp+{4}、舰娘Exp+{5} ​​) + + + 该基地于 {0}-{1}-{2} 遭到空袭。 ({3},受到的总伤害:{4},{5}) + + + 在{0}-{1}-{2}与“{3}”展开战斗。 (等级:{4}、提督Exp+{5}、舰娘Exp+{6}) + \ No newline at end of file diff --git a/ElectronicObserver/Properties/NotifierBaseAirCorpsResources.zh-CN.resx b/ElectronicObserver/Properties/NotifierBaseAirCorpsResources.zh-CN.resx index 105d9aa6f..f8dd6f04d 100644 --- a/ElectronicObserver/Properties/NotifierBaseAirCorpsResources.zh-CN.resx +++ b/ElectronicObserver/Properties/NotifierBaseAirCorpsResources.zh-CN.resx @@ -1,138 +1,138 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 休息中 - - - 未编成 - - - 待机中 - - - 基地航空队报告 - - - 尚未准备好出击: - - - 配置转换完成,重新进入母港以更新。 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 休息中 + + + 未编成 + + + 待机中 + + + 基地航空队报告 + + + 尚未准备好出击: + + + 配置转换完成,重新进入母港以更新。 + \ No newline at end of file diff --git a/ElectronicObserver/Properties/ResourceRecordResources.zh-CN.resx b/ElectronicObserver/Properties/ResourceRecordResources.zh-CN.resx index bc30b920a..7aa51ed70 100644 --- a/ElectronicObserver/Properties/ResourceRecordResources.zh-CN.resx +++ b/ElectronicObserver/Properties/ResourceRecordResources.zh-CN.resx @@ -1,150 +1,150 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 敌方基地空袭 - - - {0}的初始装备已更新。 - - - ShipParameter: {0} 的索敌值超出范围( [{1} ~ {2}] ~ {3} )。 - - - ShipParameter: {0} 的回避值超出范围( [{1} ~ {2}] ~ {3} )。 - - - ShipParameter: {0}的对潜值超出范围( [{1} ~ {2}] ~ {3} )。 - - - 记录已保存。 - - - 文件{0}不存在。 - - - 无法写入文件 {0}。 - - - 保存记录失败。 - - - 无法加载文件 {0}。 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 敌方基地空袭 + + + {0}的初始装备已更新。 + + + ShipParameter: {0} 的索敌值超出范围( [{1} ~ {2}] ~ {3} )。 + + + ShipParameter: {0} 的回避值超出范围( [{1} ~ {2}] ~ {3} )。 + + + ShipParameter: {0}的对潜值超出范围( [{1} ~ {2}] ~ {3} )。 + + + 记录已保存。 + + + 文件{0}不存在。 + + + 无法写入文件 {0}。 + + + 保存记录失败。 + + + 无法加载文件 {0}。 + \ No newline at end of file diff --git a/ElectronicObserver/Properties/Resources.zh-CN.resx b/ElectronicObserver/Properties/Resources.zh-CN.resx index eaef55239..f3259e586 100644 --- a/ElectronicObserver/Properties/Resources.zh-CN.resx +++ b/ElectronicObserver/Properties/Resources.zh-CN.resx @@ -1,273 +1,273 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 开发 - - - 翻译版本 - - - 确定关闭吗? - - - 启动完成。 - - - 正在关闭… - - - 翻译来源 - - - 布局已初始化。 -从“显示”菜单添加您最喜欢的窗口。 - - - 移至登录页面。 -你确定吗? - - - 因版本升级而确认(~1.5.0) - - - 因版本升级而确认(~1.4.6) - - - 更新信息 - - - 浏览器进程之间发生通信错误。 - - - 浏览器进程意外关闭。 - - - 浏览器关闭时发生错误。 - - - 感谢您使用{0}。 -有关设置和使用信息,请参阅菜单中的“帮助”→“在线帮助”选项。 -建议在使用前阅读。 - - - 已成功保存来自 {0} 的窗口布局。 - - - 窗口布局已从 {0} 恢复。 - - - 舰娘数据尚未加载。 - - - 开发者(点击此处报告错误并联系我们) - - - 打开布局文件 - - - 窗口布局文件不存在。 - - - 检测到您正在从先前版本升级。 -我们现在会将您当前的记录文件转换为新格式。 -(您的原始文件将移至 Record_Backup 文件夹。) -继续? -(如果您不转换记录,它们可能会变得不可读。) - - - 检测到您正在从先前版本升级。 -以前的船组数据已变得不兼容,因此必须对其进行初始化(当前现有文件将移至Settings_Backup)。 -继续? -如果不初始化就继续,可能会出现错误。 - - - 帮助 - - - 移动至… - - - 第一条启动消息 - - - 无法启动浏览器进程。 - - - 无法处理更新信息。 - - - 删除失败。 - - - 由于版本升级,删除群组数据失败。 - - - 设备数据尚未加载。 - - - 请输入目标网址。 - - - 74EO已经启动,无法存在多个74EO。 -如果出现误报,请使用 -m 选项从命令行启动它。 - - - 新版本74EO{0}已发布。 -更新内容: -{1} - -打开下载页面? -(单击“取消”可禁用更新通知) - - - 七四式电子观测仪 - - - 现在 - - - 由于版本升级,记录转换失败。 - - - 转换失败并出现错误: -{0} -继续启动74EO吗? -(继续可能会损坏您当前的记录) - - - 关闭完成。 - - - 浏览器 - - - 关闭 - - - 所有未保存的记录都将丢失。 -加载记录? - - - 版本、关于74EO - - - 新版本已发布! : - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 开发 + + + 翻译版本 + + + 确定关闭吗? + + + 启动完成。 + + + 正在关闭… + + + 翻译来源 + + + 布局已初始化。 +从“显示”菜单添加您最喜欢的窗口。 + + + 移至登录页面。 +你确定吗? + + + 因版本升级而确认(~1.5.0) + + + 因版本升级而确认(~1.4.6) + + + 更新信息 + + + 浏览器进程之间发生通信错误。 + + + 浏览器进程意外关闭。 + + + 浏览器关闭时发生错误。 + + + 感谢您使用{0}。 +有关设置和使用信息,请参阅菜单中的“帮助”→“在线帮助”选项。 +建议在使用前阅读。 + + + 已成功保存来自 {0} 的窗口布局。 + + + 窗口布局已从 {0} 恢复。 + + + 舰娘数据尚未加载。 + + + 开发者(点击此处报告错误并联系我们) + + + 打开布局文件 + + + 窗口布局文件不存在。 + + + 检测到您正在从先前版本升级。 +我们现在会将您当前的记录文件转换为新格式。 +(您的原始文件将移至 Record_Backup 文件夹。) +继续? +(如果您不转换记录,它们可能会变得不可读。) + + + 检测到您正在从先前版本升级。 +以前的船组数据已变得不兼容,因此必须对其进行初始化(当前现有文件将移至Settings_Backup)。 +继续? +如果不初始化就继续,可能会出现错误。 + + + 帮助 + + + 移动至… + + + 第一条启动消息 + + + 无法启动浏览器进程。 + + + 无法处理更新信息。 + + + 删除失败。 + + + 由于版本升级,删除群组数据失败。 + + + 设备数据尚未加载。 + + + 请输入目标网址。 + + + 74EO已经启动,无法存在多个74EO。 +如果出现误报,请使用 -m 选项从命令行启动它。 + + + 新版本74EO{0}已发布。 +更新内容: +{1} + +打开下载页面? +(单击“取消”可禁用更新通知) + + + 七四式电子观测仪 + + + 现在 + + + 由于版本升级,记录转换失败。 + + + 转换失败并出现错误: +{0} +继续启动74EO吗? +(继续可能会损坏您当前的记录) + + + 关闭完成。 + + + 浏览器 + + + 关闭 + + + 所有未保存的记录都将丢失。 +加载记录? + + + 版本、关于74EO + + + 新版本已发布! : + \ No newline at end of file diff --git a/ElectronicObserver/Properties/Utility/SoftwareInformationResources.zh-CN.resx b/ElectronicObserver/Properties/Utility/SoftwareInformationResources.zh-CN.resx index 31a0c8e82..d641bc647 100644 --- a/ElectronicObserver/Properties/Utility/SoftwareInformationResources.zh-CN.resx +++ b/ElectronicObserver/Properties/Utility/SoftwareInformationResources.zh-CN.resx @@ -1,162 +1,162 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 无法下载74EO。 - - - 您当前使用的是最新版本({0} 版本)。 - - - 更新程序下载完成。 - - - 翻译文件已更新。 - - - 开始下载更新。{0} - - - 更新 URL 无效。 - - - 文件 {0} 已更新。 - - - {0}无法更新数据{1} - - - 无法解析更新数据: - - - 获取更新数据失败。 - - - 无法下载更新程序。 - - - 正在下载更新... - - - 下载完成。 - - - 关闭 七四式电子观测仪 以完成更新过程。它将自动重启。 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 无法下载74EO。 + + + 您当前使用的是最新版本({0} 版本)。 + + + 更新程序下载完成。 + + + 翻译文件已更新。 + + + 开始下载更新。{0} + + + 更新 URL 无效。 + + + 文件 {0} 已更新。 + + + {0}无法更新数据{1} + + + 无法解析更新数据: + + + 获取更新数据失败。 + + + 无法下载更新程序。 + + + 正在下载更新... + + + 下载完成。 + + + 关闭 七四式电子观测仪 以完成更新过程。它将自动重启。 + \ No newline at end of file diff --git a/ElectronicObserver/Properties/Window/BaseAirCorpsResources.zh-CN.resx b/ElectronicObserver/Properties/Window/BaseAirCorpsResources.zh-CN.resx index 2ebc42b78..f7a956de7 100644 --- a/ElectronicObserver/Properties/Window/BaseAirCorpsResources.zh-CN.resx +++ b/ElectronicObserver/Properties/Window/BaseAirCorpsResources.zh-CN.resx @@ -1,153 +1,153 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 未补给 - - - 所属海域: - - - 检查正在转换中的设备(&R) - - - 基地航空队 - - - 全队航程:{0} - - - {0} (航程: {1}) - - - 未知海域 - - - 全部制空: 防空 {0} / 对高空 {1} - - - {0} [{1}] 制空{2}/战斗行动半径{3} - - - (无) - - - 复制到剪贴板(&C) - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 未补给 + + + 所属海域: + + + 检查正在转换中的设备(&R) + + + 基地航空队 + + + 全队航程:{0} + + + {0} (航程: {1}) + + + 未知海域 + + + 全部制空: 防空 {0} / 对高空 {1} + + + {0} [{1}] 制空{2}/战斗行动半径{3} + + + (无) + + + 复制到剪贴板(&C) + \ No newline at end of file diff --git a/ElectronicObserver/Properties/Window/BattleResources.zh-CN.resx b/ElectronicObserver/Properties/Window/BattleResources.zh-CN.resx index 3e09a574b..ffcfae64f 100644 --- a/ElectronicObserver/Properties/Window/BattleResources.zh-CN.resx +++ b/ElectronicObserver/Properties/Window/BattleResources.zh-CN.resx @@ -1,183 +1,183 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 基地航空队 - - - 损失率 - - - 支援攻击 - - - 第{0}基地 - - - 防空火力 - - - 第1次: - - - (未激活) - - - (无) - - - 我军 - - - 喷式强袭: - - - 我军舰队 - - - 敌军舰队 - - - 接触中 - - - 对空CI种类: - - - 对空CI - - - 第2次: - - - 紧凑模式(_C) - - - 损失率 - - - 战斗结果判定 - - - 我军僚队 - - - 敌军僚队 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 基地航空队 + + + 损失率 + + + 支援攻击 + + + 第{0}基地 + + + 防空火力 + + + 第1次: + + + (未激活) + + + (无) + + + 我军 + + + 喷式强袭: + + + 我军舰队 + + + 敌军舰队 + + + 接触中 + + + 对空CI种类: + + + 对空CI + + + 第2次: + + + 紧凑模式(_C) + + + 损失率 + + + 战斗结果判定 + + + 我军僚队 + + + 敌军僚队 + \ No newline at end of file diff --git a/ElectronicObserver/Properties/Window/BrowserHostResources.zh-CN.resx b/ElectronicObserver/Properties/Window/BrowserHostResources.zh-CN.resx index 3e7a3e22c..965bbbf3e 100644 --- a/ElectronicObserver/Properties/Window/BrowserHostResources.zh-CN.resx +++ b/ElectronicObserver/Properties/Window/BrowserHostResources.zh-CN.resx @@ -1,142 +1,142 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 错误 - - - 浏览器 - - - 删除缓存失败。 - - - 无法重新启动浏览器进程。 -对于给您带来的不便,我们深表歉意,但请关闭此工具一次。 - - - 无法重新启动浏览器。 - - - 缓存删除处理完成。正在重新启动浏览器… - - - 关闭浏览器以开始清除缓存… - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 错误 + + + 浏览器 + + + 删除缓存失败。 + + + 无法重新启动浏览器进程。 +对于给您带来的不便,我们深表歉意,但请关闭此工具一次。 + + + 无法重新启动浏览器。 + + + 缓存删除处理完成。正在重新启动浏览器… + + + 关闭浏览器以开始清除缓存… + \ No newline at end of file diff --git a/ElectronicObserver/Properties/Window/CompassResources.zh-CN.resx b/ElectronicObserver/Properties/Window/CompassResources.zh-CN.resx index 0d0e8b30d..36b9b799b 100644 --- a/ElectronicObserver/Properties/Window/CompassResources.zh-CN.resx +++ b/ElectronicObserver/Properties/Window/CompassResources.zh-CN.resx @@ -1,209 +1,209 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 罗盘 - - - (阵形) - - - 路线选择 - - - 确保: {0} -优势: {1} -均衡: {2} -劣势: {3} - - - - (制空战斗力) - - - 空袭 - - - - 神秘物品 - - - 发现攻击目标! - - - 未发现敌方 - - - 平静的海峡 - - - 平静的海面 - - - 平静的海面 - - - 需要警戒 - - - 候选:{0} / {1} -(点击左右翻页) - - - 候选: {0} - - - 发现敌方舰队! - - - 索敌飞机发射! - - - (敌方舰队名) - - - {0}击破: {1} / {2} 回 - - - (无) - - - / - - - (事件) - - - 已激活 - - - 可修复 - - - (事件详情) - - - (目的地) - - - (海域) - - - 前进路线警戒! - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 罗盘 + + + (阵形) + + + 路线选择 + + + 确保: {0} +优势: {1} +均衡: {2} +劣势: {3} + + + + (制空战斗力) + + + 空袭 - + + + 神秘物品 + + + 发现攻击目标! + + + 未发现敌方 + + + 平静的海峡 + + + 平静的海面 + + + 平静的海面 + + + 需要警戒 + + + 候选:{0} / {1} +(点击左右翻页) + + + 候选: {0} + + + 发现敌方舰队! + + + 索敌飞机发射! + + + (敌方舰队名) + + + {0}击破: {1} / {2} 回 + + + (无) + + + / + + + (事件) + + + 已激活 + + + 可修复 + + + (事件详情) + + + (目的地) + + + (海域) + + + 前进路线警戒! + \ No newline at end of file diff --git a/ElectronicObserver/Properties/Window/Dialog/AlbumMasterEquipmentResources.zh-CN.resx b/ElectronicObserver/Properties/Window/Dialog/AlbumMasterEquipmentResources.zh-CN.resx index 592818d4e..d29941adc 100644 --- a/ElectronicObserver/Properties/Window/Dialog/AlbumMasterEquipmentResources.zh-CN.resx +++ b/ElectronicObserver/Properties/Window/Dialog/AlbumMasterEquipmentResources.zh-CN.resx @@ -1,273 +1,273 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 射程 - - - 速度 - - - 爆装 - - - 索敌 - - - 火力 - - - 雷装 - - - 对空 - - - 装甲 - - - 对潜 - - - 回避 - - - 命中 - - - 输出到CSV - - - 装备图鉴 - - - (右键复制) - - - 对爆 - - - 迎击 - - - 可装备 - - - 排除 - - - 扩展槽 - - - 错误 - - - 无法将装备图鉴导出到CSV - - - 开发 - - - {0} 的初始装备舰和开发公式未知。 - - - 获取方式搜索 - - - +砍口垒 - - - 初始有装备的舰娘: - - - 图鉴编号: - - - 无法在 DuckDuckGo 上搜索。 - - - 改修所需的资源 - - - 改修所需的资源 - - - 拥有 - - - 二号舰 - - - - - - 消耗的装备 - - - 旋翼机 - - - 试制FaT规格九五式酸素鱼雷改 - - - [5英寸连装炮] -这是该国使用最广泛的驱逐舰主炮的双炮管版本。 -它也被作为高射炮安装在大型舰船上。 -目前,它作为深海驱逐舰的主要武器而受到青睐。 - - - 作战行动航程 - - - 部署成本 - - - 装备种类 - - - 装备名字 - - - 搜索初始装备船与开发公式(&S) - - - 展示(&V) - - - 按装备名称在DuckDuckGo上搜索(&G) - - - 复制装备和数据(&D) - - - 复制装备名称(&N) - - - 编辑(&E) - - - 输出到CSV(用于数据)(&D)... - - - 输出到CSV(用于浏览)(&U)... - - - 文件(&F) - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 射程 + + + 速度 + + + 爆装 + + + 索敌 + + + 火力 + + + 雷装 + + + 对空 + + + 装甲 + + + 对潜 + + + 回避 + + + 命中 + + + 输出到CSV + + + 装备图鉴 + + + (右键复制) + + + 对爆 + + + 迎击 + + + 可装备 + + + 排除 + + + 扩展槽 + + + 错误 + + + 无法将装备图鉴导出到CSV + + + 开发 + + + {0} 的初始装备舰和开发公式未知。 + + + 获取方式搜索 + + + +砍口垒 + + + 初始有装备的舰娘: + + + 图鉴编号: + + + 无法在 DuckDuckGo 上搜索。 + + + 改修所需的资源 + + + 改修所需的资源 + + + 拥有 + + + 二号舰 + + + + + + 消耗的装备 + + + 旋翼机 + + + 试制FaT规格九五式酸素鱼雷改 + + + [5英寸连装炮] +这是该国使用最广泛的驱逐舰主炮的双炮管版本。 +它也被作为高射炮安装在大型舰船上。 +目前,它作为深海驱逐舰的主要武器而受到青睐。 + + + 作战行动航程 + + + 部署成本 + + + 装备种类 + + + 装备名字 + + + 搜索初始装备船与开发公式(&S) + + + 展示(&V) + + + 按装备名称在DuckDuckGo上搜索(&G) + + + 复制装备和数据(&D) + + + 复制装备名称(&N) + + + 编辑(&E) + + + 输出到CSV(用于数据)(&D)... + + + 输出到CSV(用于浏览)(&U)... + + + 文件(&F) + \ No newline at end of file diff --git a/ElectronicObserver/Properties/Window/Dialog/AlbumMasterShipResources.zh-CN.resx b/ElectronicObserver/Properties/Window/Dialog/AlbumMasterShipResources.zh-CN.resx index 9edd240c2..882b769ba 100644 --- a/ElectronicObserver/Properties/Window/Dialog/AlbumMasterShipResources.zh-CN.resx +++ b/ElectronicObserver/Properties/Window/Dialog/AlbumMasterShipResources.zh-CN.resx @@ -1,263 +1,263 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 命中 - - - 索敌 - - - 编辑参数(&E)... - - - 爆装 - - - (右键查看图鉴) - - - (左键打开,右键打开新窗口) - - - 战斗详报 - - - 新型航空兵装资材 - - - 舰船图鉴输出到CSV失败。 - - - 请选择一艘船。 - - - 敌军舰队名称不明 - - - 建造 - - - {0}出现的海域未知。 - - - 地图海域搜索 - - - 请指定舰船。 - - - 未选择舰娘 - - - 陆上设施 - - - 补强增设 - - - - - - 舰船ID: - - - 对爆 - - - 回避 - - - 迎击 - - - 对潜 - - - 复制船名(&N) - - - 复制船舶数据(&C) - - - 在DuckDuckGo搜索舰船名称(&G) - - - 图像查看器(&V) - - - 显示指定级别的预测统计数据。 - - - 耐久 - - - (右键单击打开图像查看器) - - - 复制特殊设备表(&S) - - - 从默认记录更新(&M) - - - |目标艆ID|目标艆|可装备|不可装备| - - - 资源名称:{0} -图形版本{1} -语音版本{2} -主港语音版本{3} -({4}) - - - 舰种不明 - - - 改修后: {0} (+{1}) - - - 改修后: {0} (+{1}) -(内部最大耐久度: {2}) - - - 原始射程 - - - (无) - - - 火力 - - - 雷装 - - - 对空 - - - 装甲 - - - 舰种ID - - - |目标艆ID|目标艆|可装备ID|可装备| - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 命中 + + + 索敌 + + + 编辑参数(&E)... + + + 爆装 + + + (右键查看图鉴) + + + (左键打开,右键打开新窗口) + + + 战斗详报 + + + 新型航空兵装资材 + + + 舰船图鉴输出到CSV失败。 + + + 请选择一艘船。 + + + 敌军舰队名称不明 + + + 建造 + + + {0}出现的海域未知。 + + + 地图海域搜索 + + + 请指定舰船。 + + + 未选择舰娘 + + + 陆上设施 + + + 补强增设 + + + + + + 舰船ID: + + + 对爆 + + + 回避 + + + 迎击 + + + 对潜 + + + 复制船名(&N) + + + 复制船舶数据(&C) + + + 在DuckDuckGo搜索舰船名称(&G) + + + 图像查看器(&V) + + + 显示指定级别的预测统计数据。 + + + 耐久 + + + (右键单击打开图像查看器) + + + 复制特殊设备表(&S) + + + 从默认记录更新(&M) + + + |目标艆ID|目标艆|可装备|不可装备| + + + 资源名称:{0} +图形版本{1} +语音版本{2} +主港语音版本{3} +({4}) + + + 舰种不明 + + + 改修后: {0} (+{1}) + + + 改修后: {0} (+{1}) +(内部最大耐久度: {2}) + + + 原始射程 + + + (无) + + + 火力 + + + 雷装 + + + 对空 + + + 装甲 + + + 舰种ID + + + |目标艆ID|目标艆|可装备ID|可装备| + \ No newline at end of file diff --git a/ElectronicObserver/Properties/Window/Dialog/AlbumShipParameterResources.zh-CN.resx b/ElectronicObserver/Properties/Window/Dialog/AlbumShipParameterResources.zh-CN.resx index 866553014..ad888de1f 100644 --- a/ElectronicObserver/Properties/Window/Dialog/AlbumShipParameterResources.zh-CN.resx +++ b/ElectronicObserver/Properties/Window/Dialog/AlbumShipParameterResources.zh-CN.resx @@ -1,126 +1,126 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 错误 - - - 参数设置失败。 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 错误 + + + 参数设置失败。 + \ No newline at end of file diff --git a/ElectronicObserver/Properties/Window/Dialog/AntiAirDefenseResources.zh-CN.resx b/ElectronicObserver/Properties/Window/Dialog/AntiAirDefenseResources.zh-CN.resx index a00f3b052..92486c6b6 100644 --- a/ElectronicObserver/Properties/Window/Dialog/AntiAirDefenseResources.zh-CN.resx +++ b/ElectronicObserver/Properties/Window/Dialog/AntiAirDefenseResources.zh-CN.resx @@ -1,223 +1,223 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 对空 - - - 轮型阵 - - - 勾选后会显示所有对空cut in选项。 -不勾选仅显示现时配装可能触发的对空cut in。 - - - 对空CI: - - - 舰队: - - - 第二舰队 - - - 第四舰队 - - - 固定击坠 - - - 加权对空 - - - 单纵阵之外 - - - 百分比击落与固定击落如果都成功的击落数 - - - 错误 - - - 百分比击落成功时的击落数 - - - 固定击落成功时的击落数 - - - 喷进弹幕 - - - 百分比击落与固定击落如果都失败的击落数 - - - 对空喷进弹幕的激活概率 - - - 读取舰队数据失败,请在启动砍口垒后开启。 - - - AA细节 - - - 复纵阵 - - - 阵型: - - - 舰队防空: - - - 全灭概率: - - - 第一舰队 - - - 第三舰队 - - - 联合舰队 - - - 都成功 - - - 舰名 - - - 都失败 - - - 仅固定 - - - 仅比例 - - - 百分比击坠 - - - 全部都可以选择 - - - 敌方格子机数: - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 对空 + + + 轮型阵 + + + 勾选后会显示所有对空cut in选项。 +不勾选仅显示现时配装可能触发的对空cut in。 + + + 对空CI: + + + 舰队: + + + 第二舰队 + + + 第四舰队 + + + 固定击坠 + + + 加权对空 + + + 单纵阵之外 + + + 百分比击落与固定击落如果都成功的击落数 + + + 错误 + + + 百分比击落成功时的击落数 + + + 固定击落成功时的击落数 + + + 喷进弹幕 + + + 百分比击落与固定击落如果都失败的击落数 + + + 对空喷进弹幕的激活概率 + + + 读取舰队数据失败,请在启动砍口垒后开启。 + + + AA细节 + + + 复纵阵 + + + 阵型: + + + 舰队防空: + + + 全灭概率: + + + 第一舰队 + + + 第三舰队 + + + 联合舰队 + + + 都成功 + + + 舰名 + + + 都失败 + + + 仅固定 + + + 仅比例 + + + 百分比击坠 + + + 全部都可以选择 + + + 敌方格子机数: + \ No newline at end of file diff --git a/ElectronicObserver/Properties/Window/Dialog/BaseAirCorpsSimulationResources.zh-CN.resx b/ElectronicObserver/Properties/Window/Dialog/BaseAirCorpsSimulationResources.zh-CN.resx index e47058fab..164e75ce3 100644 --- a/ElectronicObserver/Properties/Window/Dialog/BaseAirCorpsSimulationResources.zh-CN.resx +++ b/ElectronicObserver/Properties/Window/Dialog/BaseAirCorpsSimulationResources.zh-CN.resx @@ -1,255 +1,255 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 航程 - - - 第二基地航空队 - - - (无) - - - (不明) - - - 活动海域 - - - 类型 - - - 成本 - - - 选择 - - - 爆装 - - - 清除陆航名称 - - - 清除陆航名称(&C) - - - 这将清除所有陆航配置。 -你确定吗? - - - 编辑(&E) - - - 出击编队 - - - 出击制空 - - - 第三基地航空队 - - - 第一基地航空队 - - - 对爆 - - - 目标航程 - - - 目标制空 - - - 高空轰炸(&H) - - - 对空 - - - 对潜 - - - 防空编辑 - - - 防空制空 - - - 总量 - - - 回避 - - - 火力 - - - 未收到基地航空队数据 - - - 导入当前配置(&I) - - - 设置(&S) - - - 基地航空队编成模拟 - - - 雷装 - - - 装甲 - - - 迎击 - - - 索敌 - - - 命中 - - - 部署消耗 - - - 额定搭载 - - - 搭载 - - - 自动组织失败。 -要么条件不满足,要么没有足够的飞机。 - - - 自动编成失败 - - - 没有基地航空队的数据。 -请移动到出击画面一次。 - - - 有重复 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 航程 + + + 第二基地航空队 + + + (无) + + + (不明) + + + 活动海域 + + + 类型 + + + 成本 + + + 选择 + + + 爆装 + + + 清除陆航名称 + + + 清除陆航名称(&C) + + + 这将清除所有陆航配置。 +你确定吗? + + + 编辑(&E) + + + 出击编队 + + + 出击制空 + + + 第三基地航空队 + + + 第一基地航空队 + + + 对爆 + + + 目标航程 + + + 目标制空 + + + 高空轰炸(&H) + + + 对空 + + + 对潜 + + + 防空编辑 + + + 防空制空 + + + 总量 + + + 回避 + + + 火力 + + + 未收到基地航空队数据 + + + 导入当前配置(&I) + + + 设置(&S) + + + 基地航空队编成模拟 + + + 雷装 + + + 装甲 + + + 迎击 + + + 索敌 + + + 命中 + + + 部署消耗 + + + 额定搭载 + + + 搭载 + + + 自动组织失败。 +要么条件不满足,要么没有足够的飞机。 + + + 自动编成失败 + + + 没有基地航空队的数据。 +请移动到出击画面一次。 + + + 有重复 + \ No newline at end of file diff --git a/ElectronicObserver/Properties/Window/Dialog/BattleDetailResources.zh-CN.resx b/ElectronicObserver/Properties/Window/Dialog/BattleDetailResources.zh-CN.resx index aa28c012b..03b6c28e4 100644 --- a/ElectronicObserver/Properties/Window/Dialog/BattleDetailResources.zh-CN.resx +++ b/ElectronicObserver/Properties/Window/Dialog/BattleDetailResources.zh-CN.resx @@ -1,123 +1,123 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 战斗详情 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 战斗详情 + \ No newline at end of file diff --git a/ElectronicObserver/Properties/Window/Dialog/ConfigurationNotifierResources.zh-CN.resx b/ElectronicObserver/Properties/Window/Dialog/ConfigurationNotifierResources.zh-CN.resx index c17cbd05a..d50ff77d1 100644 --- a/ElectronicObserver/Properties/Window/Dialog/ConfigurationNotifierResources.zh-CN.resx +++ b/ElectronicObserver/Properties/Window/Dialog/ConfigurationNotifierResources.zh-CN.resx @@ -1,245 +1,245 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 错误 - - - 未编成·配置转换中 - - - [休息] - - - 指定通知音量。 -0 为静音,100 为最大音量。 - - - *这些设置将在测试时应用 - - - 泊地修理设置 - - - 发动条件: - - - 基地航空队设置 - - - 未补给时 - - - [退避] - - - [待机] - - - 通常海域 - - - 疲劳时 - - - 出击前,如果有陆航未补给将会收到通知。 - - - 出击前,如果有陆航在[休息]将会收到通知。 - - - 出击前,如果有陆航橙脸将会收到通知。 - - - 出击前,如果有陆航在[退避]将会收到通知。 - - - 出击前,如果有陆航在[待机]将会收到通知。 - - - 出击前,通常海域的陆航没准备好时将会收到通知。 - - - 活动海域 - - - 出击前,活动海域的陆航没准备好时将会收到通知。 - - - 装备的配置转换完成 - - - 装备的配置转换完成时将会收到通知。 - - - 陆航的配置转换完成 - - - 陆航飞机槽位配置转换完成后将会收到通知。 -与“装备的配置转换完成”不同的是,已经返回装备栏的飞机不会得到通知。 - - - 战斗结束设置 - - - 启用空闲时间 - - - 空闲时间 - - - 战斗开始后一定时间后会发送通知。 - - - 指定空闲时间(以秒为单位)。 - - - 总是 - - - 当明石作为旗舰时 - - - 当有艆需要修理时 - - - 预设 - - - 总是:每过20分钟提醒您。 -明石旗舰时:除上述情况外,我们仅在明石旗舰时通知您。 -有艆需要修理时:除上述情况外,仅在具备实际可以修理舰娘的条件时才进行通知。 -创建预设时:除上述内容外,当包含符合修复条件的预设时,还会通知您。 - - - 这是一个测试通知。 -当您移动并关闭它时,显示位置将会更新。 - - - 这是一个测试通知。 - - - 出击前,如果有陆航中队没有编成或在配置转换,您将会收到通知。 - - - 显示时激活对话框。 -禁用它可以更轻松地隐藏对话框,而不会干扰操作。 -(猜测是游戏退出时的提示) - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 错误 + + + 未编成·配置转换中 + + + [休息] + + + 指定通知音量。 +0 为静音,100 为最大音量。 + + + *这些设置将在测试时应用 + + + 泊地修理设置 + + + 发动条件: + + + 基地航空队设置 + + + 未补给时 + + + [退避] + + + [待机] + + + 通常海域 + + + 疲劳时 + + + 出击前,如果有陆航未补给将会收到通知。 + + + 出击前,如果有陆航在[休息]将会收到通知。 + + + 出击前,如果有陆航橙脸将会收到通知。 + + + 出击前,如果有陆航在[退避]将会收到通知。 + + + 出击前,如果有陆航在[待机]将会收到通知。 + + + 出击前,通常海域的陆航没准备好时将会收到通知。 + + + 活动海域 + + + 出击前,活动海域的陆航没准备好时将会收到通知。 + + + 装备的配置转换完成 + + + 装备的配置转换完成时将会收到通知。 + + + 陆航的配置转换完成 + + + 陆航飞机槽位配置转换完成后将会收到通知。 +与“装备的配置转换完成”不同的是,已经返回装备栏的飞机不会得到通知。 + + + 战斗结束设置 + + + 启用空闲时间 + + + 空闲时间 + + + 战斗开始后一定时间后会发送通知。 + + + 指定空闲时间(以秒为单位)。 + + + 总是 + + + 当明石作为旗舰时 + + + 当有艆需要修理时 + + + 预设 + + + 总是:每过20分钟提醒您。 +明石旗舰时:除上述情况外,我们仅在明石旗舰时通知您。 +有艆需要修理时:除上述情况外,仅在具备实际可以修理舰娘的条件时才进行通知。 +创建预设时:除上述内容外,当包含符合修复条件的预设时,还会通知您。 + + + 这是一个测试通知。 +当您移动并关闭它时,显示位置将会更新。 + + + 这是一个测试通知。 + + + 出击前,如果有陆航中队没有编成或在配置转换,您将会收到通知。 + + + 显示时激活对话框。 +禁用它可以更轻松地隐藏对话框,而不会干扰操作。 +(猜测是游戏退出时的提示) + \ No newline at end of file diff --git a/ElectronicObserver/Properties/Window/Dialog/ConfigurationResources.zh-CN.resx b/ElectronicObserver/Properties/Window/Dialog/ConfigurationResources.zh-CN.resx index 6edf0b612..bd58c6345 100644 --- a/ElectronicObserver/Properties/Window/Dialog/ConfigurationResources.zh-CN.resx +++ b/ElectronicObserver/Properties/Window/Dialog/ConfigurationResources.zh-CN.resx @@ -1,818 +1,818 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - *网络设置重启后生效 - - - 指定上行代理的地址。 -默认值为 127.0.0.1。 - - - 下游代理(适用于高级用户): - - - 指定下游代理设置。 -此设置将覆盖上游代理设置。 -仅适用于高级用户。 - - - 使用系统代理 - - - 指定本地代理服务器的端口号。 - - - 使用本地代理服务器。 -如果您想通过第三方应用程序(例如:MyFleetGirls)路由连接,请启用。 - - - 注册为系统代理 - - - 浏览…… - - - 保存API数据 - - - 禁用装备种类翻译 - - - 禁用装备名称翻译 - - - 禁用舰种翻译 - - - 禁用艆名翻译 - - - 禁用其他翻译 - - - 远征,出击,任务 - - - 主题: - - - 使用指定的颜色主题。 -更改将在重启后生效。 -自定义选项将使用 Settings\ColorScheme.json 中的颜色值 - - - 这是预览。 -使用下面的滑块调整数值。 - - - 使用固定字体高度 - - - 启用后,无论字体如何,每个 UI 列都将具有大致相同的高度(与之前的版本 2.6.2 一样)。 -禁用时,列高根据字体而变化(可能比启用时更大)。 -如果禁用,操作可能会稍微变慢。 - - - 像砍口垒UI一样在颜色条上使用渐变,如HP条,资源条。 - - - 立即写入日志 - - - 指定添加日志的同时是否写入日志文件。 -如果禁用,所有数据将在程序末尾写入。 -如果启用,即使发生强制终止等问题,您也可以留下日志,但可能会在一定程度上减慢进程速度。 -请注意,如果禁用“将日志保存到文件”,则此规范将无效。 - - - 保存战斗日志 - - - 指定是否保存战斗日志。 -战斗日志保存在BattleLog文件夹中。 - - - 显示剧透 - - - 在日志中显示已开发的物品和掉落的船只。 -禁用此设置可隐藏信息。 - - - 指定程序的日志记录级别。较小的数字意味着更详细的日志记录。 -1:调试级别 -2:正常(推荐) -3:仅错误 - - - 行为 - - - 应用程序 ID - - - 与 Discord Rich Presence 配合使用的应用程序 ID - - - 强制更新 - - - 翻译URL - - - 指定用于翻译更新的存储库 - - - 显示甲章数量 - - - 查看在 Discord Rich Presence 上显示您拥有的甲章数量。 - - - 启用 Discord RPC - - - 启用 Discord Rich Presence - - - Discord RPC 消息 - - - 允许您选择在 discord 上显示什么消息。使用 {{secretary}} 在消息中输入您秘书舰的名字。 - - - 派出未满足条件的远征队时警告 - - - 当未满足条件的远征队出发时是否发出警告。 - - - 当没有贴条的舰娘出击时警告 - - - 当没有贴条的舰娘出击时是否显示警告框 -由于获取的信息不完整,可能会出现误判。注意。 - - - 设置计算力量(战斗中的攻击力)时的标准交战模式。 - - - 攻击力表示交战形态: - - - 使用系统设置通知/BGM 音量 - - - 指定通知、BGM 等的主机音量设置是否使用系统音量设置。 -如果禁用,您可以单独设置音量,但无法使用音量混合器等进行调节。 -如果启用,可以使用音量混合器等进行调整,但单个音量设置将被忽略。 - - - 即刻 - - - 自动保存日志: - - - 启动时加载 API 列表 - - - 启动时加载以下 API 列表。 -API列表的格式和使用方法请参见在线帮助。 - - - 显示debug菜单 - - - 启用主窗口中的“调试”菜单。 -这是一个调试功能,不建议普通用户使用。 -无法保证使用过程中的操作,因此请使用*自行承担风险*。 - - - 即使启用了上述“锁定布局”, -指定是否可以关闭浮动窗口(与主体分离的窗口)。 -如果您经常临时打开窗口,启用此功能会很方便。 - - - 锁定当前布局 - - - 防止更改选项卡布局和窗口大小。 - - - 时间表示形式: - - - 服务器时间: - - - 更新演习为止 - - - 更新任务为止 - - - 显示状态栏 - - - 检查更新 - - - 始终处于最前端 - - - 退出时确认 - - - 子窗口 - - - 舰队 - - - 按出击海域对舰娘名称进行颜色编码 - - - 根据出击海域设置舰娘名称的背景颜色。 - - - 舰队状态显示: - - - 只显示一个 - - - 全部缩短显示 - - - 显示多个文件时缩短 - - - 全部正常显示 - - - 远征舰队未出击时强调显示 - - - 当第2至第4舰队到达母港时,会以彩色显示。 - - - 大破时闪烁 - - - 设置在母港有大破舰娘时是否闪烁。 -出击时也会闪烁。 - - - 表示泊地修理时的血量回复 - - - 如果启用,恢复的血量将在泊地修理20分钟后显示在HP栏上。 - - - 显示制空范围 - - - 指定是否将制空权范围显示为“最小到最大内部熟练度”。 -通常,空中优势被计算为具有最低的内部熟练程度。 - - - 以数字方式显示舰载机熟练程度 - - - 以数字(1,2,3)而不是符号(|,||,>>)显示飞机熟练程度。 - - - 指定舰娘名字横幅的宽度。 - - - 显示疲劳度图标 - - - 指定是否显示疲劳度图标。 -如果不显示,则会通过背景颜色来区分。 - - - 叠加熟练度 - - - 指定装备改装等级和舰载机熟练度的显示。 -如果设置为“隐藏”则不会显示。 -在“优先”的情况下,当双方均为Lv.1以上时,将优先显示。 -如果选择“显示两者”,则始终显示两者。 - - - 装备信息显示: - - - 设置远征、入渠结束后是否闪烁标签。 - - - 显示泊地修理计时器 - - - 指定是否在“舰队一览”中显示泊地修理计时器。 - - - 忽略熟练度 - - - 包括熟练度 - - - 指定是否显示“达到下一等级所需的经验值”。 -省略它可以节省空间。 - - - 缩短 HP 条 - - - 固定艆名宽度 - - - 指定艆名的固定宽度。 -它会减少水平空间需求,但可能会切断长艆名。 - - - 显示滚动条 - - - 指定显示区域扩展时是否显示滚动条。 -如果适合,则不会显示。 - - - 显示舰载机的数量 - - - 艆名最大宽度: - - - 指定舰娘名称的最大显示宽度。 - - - 显示艆名 - - - 司令部 - - - 其他项目: - - - 显示/隐藏设置: - - - 母港排序 - - - 显示状态栏 - - - 战斗 - - - 在同一行显示第 7 艘船 - - - 与游击队(7艘)出击时,指定显示第7艘舰信息的位置。 -启用时,将显示在第 6 艘舰船下方,禁用时,将显示在与第 1 艘随行舰队舰艇相同的位置。 -禁用它会节省一些空间。 - - - 在HP栏上显示船舶类型缩写 - - - 显示舰种(例如:DD)而不是 HP 标题文本。 - - - 显示 HP 条 - - - 如果隐藏它,可以节省一些垂直空间。 - - - 隐藏直到战斗结束 - - - 战斗中隐藏战斗预测画面,避免剧透。 -即使隐藏,也可以通过战斗窗口的右键菜单暂时显示。 - - - 浏览器 - - - 保存浏览器错误日志 * - - - 如果启用,会将浏览器错误日志保存在 BrowserLog.log 中。 -它可能有助于解决问题,但写入可能会减慢运行速度。 - - - 将颜色配置文件修复为 sRGB * - - - 如果您的浏览器的颜色很奇怪,启用它可能会解决问题。 -重启后就会有反映。 - - - 保留绘图缓冲区 * - - - 禁用该设置可能会提高性能。 -注意:如果未启用保留绘图缓冲区,则截图 -大小可能会受到浏览器窗口大小的限制。 -* 更改将在应用程序重新启动后生效。 - - - * 标有 标记的设置需重启后生效 - - - 启用硬件加速* - - - 指定是否使用GPU进行绘图。 -启用它可能会提高性能。 -注意:如果需要使用窗口捕获,请禁用此设置。 -* 更改将在应用程序重新启动后生效。 - - - 隐藏弹出的重新加载窗口 - - - 隐藏浏览器窗口中出现的 DMM 页面重新加载弹出对话框。 - - - 重新加载时检查 - - - 刷新页面之前显示确认对话框。 - - - 截屏 - - - 如何保存: - - - 保存到文件 - - - 复制到剪贴板 - - - 保存两者 - - - 避免 Twitter 图像压缩 - - - 如果您将 PNG 格式的图像上传到 Twitter,它将自动转换为 JPEG 格式,并且图像质量会下降。 -对图像应用修改,以便阻止 Twitter 自动将它们转换为 JPEG。 - - - 缩放倍率: - - - 基地航空队 - - - 仅显示活动海域内的陆航 - - - 活动期间隐藏普通图的陆航。 - - - 自动刷新(更新)? - - - 指定发送和接收 API 时是否自动更新显示。 -可能会增加处理负载。 - - - - ※启用自动更新,可能会增加处理负载 - - - 也更新树状图 - - - 发送/接收 API 数据时自动更新树内容。 -仅当启用自动刷新时才有效。可能会增加处理负载。 - - - 这是一个过滤器,用于选择自动更新期间要加载的 API。 -正则表达式也可用。 - - - 自动更新过滤器: - - - 全屏时静音 - - - 将所有通知静音 - - - 隐藏/停止所有通知和通知声音 - - - 改造等级 - - - 同步静音 - - - 指定是否与浏览器静音联动。 - - - 打开API列表文件 - - - 游玩时间 - - - 启用 TsunDb 发送 - - - 陆航通知设定… - - - 战斗结束通知 - - - - - - 黑暗 - - - 自定义 - - - 同航战 - - - 反航战 - - - T有利 - - - T不利 - - - 使用上游(本地?)代理: - - - 指定的文件夹不存在。 - - - 错误 - - - 请先启动砍口垒。 - - - 保存自动代理配置脚本(PAC) - - - 代理自动配置脚本已保存。 -文件路径已复制到剪贴板,将其粘贴到 Internet Explorer 中的代理设置中。 - - - PAC脚本已保存 - - - 无法保存自动代理配置脚本。 - - - BGM 播放器音量将设置为 {0}。 -您确定吗? - - - 总音量设置 - - - 使用字母进行节点分配 - - - 英语 - - - 日本语 - - - 使用小工具重定向 * - - - 更改主题或语言后,请重新启动七四EO。 - - - 语言: - - - 重定向小工具 api 调用以绕过阻止外国人的墙。 -如果您居住在日本或使用日本 VPN,则可以禁用此选项。 - - - Vulkan 解决方法* - - - 删除了 vulkan 软件渲染实现所需的 WebView2 文件,这可能会导致旧硬件的 CPU 负载过高。 - - - 显示上下文菜单 - - - 右键单击浏览器可显示上下文菜单。 - - - 端口和上游代理端口值必须不同。 - - - 允许为同一个舰娘添加训练计划 - - - 如果不勾选,当添加新的舰艇训练计划时,舰艇列表将被过滤,仅显示没有训练计划的舰艇。 -如果选中,则不会应用任何过滤器。 - - - 显示所有敌方组成 - - - 禁用后,将仅显示与地图屏幕预览匹配的合成。 -启用后,预览将被忽略并显示所有合成。 - - - 韩语 - - - 自定义小工具缓存 URL - - - https://electronicobserveren.github.io/cache - - - https://kcwiki.github.io/cache - - - 仅输入缓存服务器 URL 的开头部分,即“/gadget_html5/”子目录之前的所有内容。 -例如,如果尝试使用“http://luckyjervis.com/gadget_html5/js/kcs_const.js”,则需要在字段中输入“http://luckyjervis.com/”。 - - - 网址格式无效。 - - - 74EO-EN版 API URL - - - 用于报告数据问题的 74 Electronic Observer API 的 URL。 - - - 舰娘训练结束 - - - Bonodere整合 - - - 登录名 - - - 登录 - - - 退出 - - - 密码 - - - 用户名 - - - 隐私政策 - - - 数据提交常见问题解答 - - - 简体中文语 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + *网络设置重启后生效 + + + 指定上行代理的地址。 +默认值为 127.0.0.1。 + + + 下游代理(适用于高级用户): + + + 指定下游代理设置。 +此设置将覆盖上游代理设置。 +仅适用于高级用户。 + + + 使用系统代理 + + + 指定本地代理服务器的端口号。 + + + 使用本地代理服务器。 +如果您想通过第三方应用程序(例如:MyFleetGirls)路由连接,请启用。 + + + 注册为系统代理 + + + 浏览…… + + + 保存API数据 + + + 禁用装备种类翻译 + + + 禁用装备名称翻译 + + + 禁用舰种翻译 + + + 禁用艆名翻译 + + + 禁用其他翻译 + + + 远征,出击,任务 + + + 主题: + + + 使用指定的颜色主题。 +更改将在重启后生效。 +自定义选项将使用 Settings\ColorScheme.json 中的颜色值 + + + 这是预览。 +使用下面的滑块调整数值。 + + + 使用固定字体高度 + + + 启用后,无论字体如何,每个 UI 列都将具有大致相同的高度(与之前的版本 2.6.2 一样)。 +禁用时,列高根据字体而变化(可能比启用时更大)。 +如果禁用,操作可能会稍微变慢。 + + + 像砍口垒UI一样在颜色条上使用渐变,如HP条,资源条。 + + + 立即写入日志 + + + 指定添加日志的同时是否写入日志文件。 +如果禁用,所有数据将在程序末尾写入。 +如果启用,即使发生强制终止等问题,您也可以留下日志,但可能会在一定程度上减慢进程速度。 +请注意,如果禁用“将日志保存到文件”,则此规范将无效。 + + + 保存战斗日志 + + + 指定是否保存战斗日志。 +战斗日志保存在BattleLog文件夹中。 + + + 显示剧透 + + + 在日志中显示已开发的物品和掉落的船只。 +禁用此设置可隐藏信息。 + + + 指定程序的日志记录级别。较小的数字意味着更详细的日志记录。 +1:调试级别 +2:正常(推荐) +3:仅错误 + + + 行为 + + + 应用程序 ID + + + 与 Discord Rich Presence 配合使用的应用程序 ID + + + 强制更新 + + + 翻译URL + + + 指定用于翻译更新的存储库 + + + 显示甲章数量 + + + 查看在 Discord Rich Presence 上显示您拥有的甲章数量。 + + + 启用 Discord RPC + + + 启用 Discord Rich Presence + + + Discord RPC 消息 + + + 允许您选择在 discord 上显示什么消息。使用 {{secretary}} 在消息中输入您秘书舰的名字。 + + + 派出未满足条件的远征队时警告 + + + 当未满足条件的远征队出发时是否发出警告。 + + + 当没有贴条的舰娘出击时警告 + + + 当没有贴条的舰娘出击时是否显示警告框 +由于获取的信息不完整,可能会出现误判。注意。 + + + 设置计算力量(战斗中的攻击力)时的标准交战模式。 + + + 攻击力表示交战形态: + + + 使用系统设置通知/BGM 音量 + + + 指定通知、BGM 等的主机音量设置是否使用系统音量设置。 +如果禁用,您可以单独设置音量,但无法使用音量混合器等进行调节。 +如果启用,可以使用音量混合器等进行调整,但单个音量设置将被忽略。 + + + 即刻 + + + 自动保存日志: + + + 启动时加载 API 列表 + + + 启动时加载以下 API 列表。 +API列表的格式和使用方法请参见在线帮助。 + + + 显示debug菜单 + + + 启用主窗口中的“调试”菜单。 +这是一个调试功能,不建议普通用户使用。 +无法保证使用过程中的操作,因此请使用*自行承担风险*。 + + + 即使启用了上述“锁定布局”, +指定是否可以关闭浮动窗口(与主体分离的窗口)。 +如果您经常临时打开窗口,启用此功能会很方便。 + + + 锁定当前布局 + + + 防止更改选项卡布局和窗口大小。 + + + 时间表示形式: + + + 服务器时间: + + + 更新演习为止 + + + 更新任务为止 + + + 显示状态栏 + + + 检查更新 + + + 始终处于最前端 + + + 退出时确认 + + + 子窗口 + + + 舰队 + + + 按出击海域对舰娘名称进行颜色编码 + + + 根据出击海域设置舰娘名称的背景颜色。 + + + 舰队状态显示: + + + 只显示一个 + + + 全部缩短显示 + + + 显示多个文件时缩短 + + + 全部正常显示 + + + 远征舰队未出击时强调显示 + + + 当第2至第4舰队到达母港时,会以彩色显示。 + + + 大破时闪烁 + + + 设置在母港有大破舰娘时是否闪烁。 +出击时也会闪烁。 + + + 表示泊地修理时的血量回复 + + + 如果启用,恢复的血量将在泊地修理20分钟后显示在HP栏上。 + + + 显示制空范围 + + + 指定是否将制空权范围显示为“最小到最大内部熟练度”。 +通常,空中优势被计算为具有最低的内部熟练程度。 + + + 以数字方式显示舰载机熟练程度 + + + 以数字(1,2,3)而不是符号(|,||,>>)显示飞机熟练程度。 + + + 指定舰娘名字横幅的宽度。 + + + 显示疲劳度图标 + + + 指定是否显示疲劳度图标。 +如果不显示,则会通过背景颜色来区分。 + + + 叠加熟练度 + + + 指定装备改装等级和舰载机熟练度的显示。 +如果设置为“隐藏”则不会显示。 +在“优先”的情况下,当双方均为Lv.1以上时,将优先显示。 +如果选择“显示两者”,则始终显示两者。 + + + 装备信息显示: + + + 设置远征、入渠结束后是否闪烁标签。 + + + 显示泊地修理计时器 + + + 指定是否在“舰队一览”中显示泊地修理计时器。 + + + 忽略熟练度 + + + 包括熟练度 + + + 指定是否显示“达到下一等级所需的经验值”。 +省略它可以节省空间。 + + + 缩短 HP 条 + + + 固定艆名宽度 + + + 指定艆名的固定宽度。 +它会减少水平空间需求,但可能会切断长艆名。 + + + 显示滚动条 + + + 指定显示区域扩展时是否显示滚动条。 +如果适合,则不会显示。 + + + 显示舰载机的数量 + + + 艆名最大宽度: + + + 指定舰娘名称的最大显示宽度。 + + + 显示艆名 + + + 司令部 + + + 其他项目: + + + 显示/隐藏设置: + + + 母港排序 + + + 显示状态栏 + + + 战斗 + + + 在同一行显示第 7 艘船 + + + 与游击队(7艘)出击时,指定显示第7艘舰信息的位置。 +启用时,将显示在第 6 艘舰船下方,禁用时,将显示在与第 1 艘随行舰队舰艇相同的位置。 +禁用它会节省一些空间。 + + + 在HP栏上显示船舶类型缩写 + + + 显示舰种(例如:DD)而不是 HP 标题文本。 + + + 显示 HP 条 + + + 如果隐藏它,可以节省一些垂直空间。 + + + 隐藏直到战斗结束 + + + 战斗中隐藏战斗预测画面,避免剧透。 +即使隐藏,也可以通过战斗窗口的右键菜单暂时显示。 + + + 浏览器 + + + 保存浏览器错误日志 * + + + 如果启用,会将浏览器错误日志保存在 BrowserLog.log 中。 +它可能有助于解决问题,但写入可能会减慢运行速度。 + + + 将颜色配置文件修复为 sRGB * + + + 如果您的浏览器的颜色很奇怪,启用它可能会解决问题。 +重启后就会有反映。 + + + 保留绘图缓冲区 * + + + 禁用该设置可能会提高性能。 +注意:如果未启用保留绘图缓冲区,则截图 +大小可能会受到浏览器窗口大小的限制。 +* 更改将在应用程序重新启动后生效。 + + + * 标有 标记的设置需重启后生效 + + + 启用硬件加速* + + + 指定是否使用GPU进行绘图。 +启用它可能会提高性能。 +注意:如果需要使用窗口捕获,请禁用此设置。 +* 更改将在应用程序重新启动后生效。 + + + 隐藏弹出的重新加载窗口 + + + 隐藏浏览器窗口中出现的 DMM 页面重新加载弹出对话框。 + + + 重新加载时检查 + + + 刷新页面之前显示确认对话框。 + + + 截屏 + + + 如何保存: + + + 保存到文件 + + + 复制到剪贴板 + + + 保存两者 + + + 避免 Twitter 图像压缩 + + + 如果您将 PNG 格式的图像上传到 Twitter,它将自动转换为 JPEG 格式,并且图像质量会下降。 +对图像应用修改,以便阻止 Twitter 自动将它们转换为 JPEG。 + + + 缩放倍率: + + + 基地航空队 + + + 仅显示活动海域内的陆航 + + + 活动期间隐藏普通图的陆航。 + + + 自动刷新(更新)? + + + 指定发送和接收 API 时是否自动更新显示。 +可能会增加处理负载。 + + + + ※启用自动更新,可能会增加处理负载 + + + 也更新树状图 + + + 发送/接收 API 数据时自动更新树内容。 +仅当启用自动刷新时才有效。可能会增加处理负载。 + + + 这是一个过滤器,用于选择自动更新期间要加载的 API。 +正则表达式也可用。 + + + 自动更新过滤器: + + + 全屏时静音 + + + 将所有通知静音 + + + 隐藏/停止所有通知和通知声音 + + + 改造等级 + + + 同步静音 + + + 指定是否与浏览器静音联动。 + + + 打开API列表文件 + + + 游玩时间 + + + 启用 TsunDb 发送 + + + 陆航通知设定… + + + 战斗结束通知 + + + + + + 黑暗 + + + 自定义 + + + 同航战 + + + 反航战 + + + T有利 + + + T不利 + + + 使用上游(本地?)代理: + + + 指定的文件夹不存在。 + + + 错误 + + + 请先启动砍口垒。 + + + 保存自动代理配置脚本(PAC) + + + 代理自动配置脚本已保存。 +文件路径已复制到剪贴板,将其粘贴到 Internet Explorer 中的代理设置中。 + + + PAC脚本已保存 + + + 无法保存自动代理配置脚本。 + + + BGM 播放器音量将设置为 {0}。 +您确定吗? + + + 总音量设置 + + + 使用字母进行节点分配 + + + 英语 + + + 日本语 + + + 使用小工具重定向 * + + + 更改主题或语言后,请重新启动七四EO。 + + + 语言: + + + 重定向小工具 api 调用以绕过阻止外国人的墙。 +如果您居住在日本或使用日本 VPN,则可以禁用此选项。 + + + Vulkan 解决方法* + + + 删除了 vulkan 软件渲染实现所需的 WebView2 文件,这可能会导致旧硬件的 CPU 负载过高。 + + + 显示上下文菜单 + + + 右键单击浏览器可显示上下文菜单。 + + + 端口和上游代理端口值必须不同。 + + + 允许为同一个舰娘添加训练计划 + + + 如果不勾选,当添加新的舰艇训练计划时,舰艇列表将被过滤,仅显示没有训练计划的舰艇。 +如果选中,则不会应用任何过滤器。 + + + 显示所有敌方组成 + + + 禁用后,将仅显示与地图屏幕预览匹配的合成。 +启用后,预览将被忽略并显示所有合成。 + + + 韩语 + + + 自定义小工具缓存 URL + + + https://electronicobserveren.github.io/cache + + + https://kcwiki.github.io/cache + + + 仅输入缓存服务器 URL 的开头部分,即“/gadget_html5/”子目录之前的所有内容。 +例如,如果尝试使用“http://luckyjervis.com/gadget_html5/js/kcs_const.js”,则需要在字段中输入“http://luckyjervis.com/”。 + + + 网址格式无效。 + + + 74EO-EN版 API URL + + + 用于报告数据问题的 74 Electronic Observer API 的 URL。 + + + 舰娘训练结束 + + + Bonodere整合 + + + 登录名 + + + 登录 + + + 退出 + + + 密码 + + + 用户名 + + + 隐私政策 + + + 数据提交常见问题解答 + + + 简体中文语 + \ No newline at end of file diff --git a/ElectronicObserver/Properties/Window/Dialog/ConstructionRecordViewerResources.zh-CN.resx b/ElectronicObserver/Properties/Window/Dialog/ConstructionRecordViewerResources.zh-CN.resx index 452cd3f84..1dc461a27 100644 --- a/ElectronicObserver/Properties/Window/Dialog/ConstructionRecordViewerResources.zh-CN.resx +++ b/ElectronicObserver/Properties/Window/Dialog/ConstructionRecordViewerResources.zh-CN.resx @@ -1,177 +1,177 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 大型舰建造 - - - 开发资材 - - - 秘书舰 - - - 搜索 - - - 日期 - - - 名字 - - - 开始 - - - 总计 - - - 开发资材 - - - (全部) - - - 次数 - - - 建造记录 - - - 秘书舰 - - - 开发公式 - - - 艆名 - - - 类别 - - - 结束 - - - 开发公式 - - - 空位 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 大型舰建造 + + + 开发资材 + + + 秘书舰 + + + 搜索 + + + 日期 + + + 名字 + + + 开始 + + + 总计 + + + 开发资材 + + + (全部) + + + 次数 + + + 建造记录 + + + 秘书舰 + + + 开发公式 + + + 艆名 + + + 类别 + + + 结束 + + + 开发公式 + + + 空位 + \ No newline at end of file diff --git a/ElectronicObserver/Properties/Window/Dialog/DevelopmentRecordViewerResources.zh-CN.resx b/ElectronicObserver/Properties/Window/Dialog/DevelopmentRecordViewerResources.zh-CN.resx index f56db2475..646227366 100644 --- a/ElectronicObserver/Properties/Window/Dialog/DevelopmentRecordViewerResources.zh-CN.resx +++ b/ElectronicObserver/Properties/Window/Dialog/DevelopmentRecordViewerResources.zh-CN.resx @@ -1,189 +1,189 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 开始 - - - 舰种 - - - 名字 - - - (成功) - - - 搜索 - - - 合计 - - - 开发公式 - - - 结束 - - - 类型 - - - 装备名称 - - - 日期 - - - 开发公式 - - - 秘书舰 - - - 详细 - - - 开发记录 - - - (全部) - - - (失败) - - - 装备 - - - 每个公式的次数 - - - 按舰种划分的次数 - - - (不明) - - - 所选项目总数 - - - 秘书舰 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 开始 + + + 舰种 + + + 名字 + + + (成功) + + + 搜索 + + + 合计 + + + 开发公式 + + + 结束 + + + 类型 + + + 装备名称 + + + 日期 + + + 开发公式 + + + 秘书舰 + + + 详细 + + + 开发记录 + + + (全部) + + + (失败) + + + 装备 + + + 每个公式的次数 + + + 按舰种划分的次数 + + + (不明) + + + 所选项目总数 + + + 秘书舰 + \ No newline at end of file diff --git a/ElectronicObserver/Properties/Window/Dialog/DropRecordViewerResources.zh-CN.resx b/ElectronicObserver/Properties/Window/Dialog/DropRecordViewerResources.zh-CN.resx index bd319e796..f4b1cc10e 100644 --- a/ElectronicObserver/Properties/Window/Dialog/DropRecordViewerResources.zh-CN.resx +++ b/ElectronicObserver/Properties/Window/Dialog/DropRecordViewerResources.zh-CN.resx @@ -1,251 +1,251 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 指定要搜索的项目名称。 -(Drop) 仅当项目被丢弃时才提取。 - - - 指定要搜索的舰娘名称。 - - - 指定要搜索的装备名称。 - - - 指定搜索的开始日期。 - - - 开始 - - - 结束 - - - 指定搜索的结束日期。 - - - S胜 - - - A胜 - - - B胜 - - - 败北 - - - 指定海图的难度。 - - - 搜索 - - - 名字 - - - 日期 - - - 海域 - - - RANK - - - S胜 - - - A胜 - - - B胜 - - - Boss - - - 指定海域ID。 -*ID大于20为活动海域。 - - - 指定海域ID。 - - - 指定海域ID。 - - - 合并相同掉落物。 - - - 舰船 - - - 物品 - - - 装备 - - - - - - - 状态条1 - - - 删除日志 - - - (全部) - - - (无) - - - (满) - - - (降低) - - - [Boss] - - - 没有找到战斗日志。 - - - 正在搜索战斗日志... - - - 打开战斗日志{0}。 - - - 无法打开战斗日志。 - - - 所选项目:{0} / {1} ({2:p1}) - - - 今天 - - - 忽略常见掉落 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 指定要搜索的项目名称。 +(Drop) 仅当项目被丢弃时才提取。 + + + 指定要搜索的舰娘名称。 + + + 指定要搜索的装备名称。 + + + 指定搜索的开始日期。 + + + 开始 + + + 结束 + + + 指定搜索的结束日期。 + + + S胜 + + + A胜 + + + B胜 + + + 败北 + + + 指定海图的难度。 + + + 搜索 + + + 名字 + + + 日期 + + + 海域 + + + RANK + + + S胜 + + + A胜 + + + B胜 + + + Boss + + + 指定海域ID。 +*ID大于20为活动海域。 + + + 指定海域ID。 + + + 指定海域ID。 + + + 合并相同掉落物。 + + + 舰船 + + + 物品 + + + 装备 + + + - + + + 状态条1 + + + 删除日志 + + + (全部) + + + (无) + + + (满) + + + (降低) + + + [Boss] + + + 没有找到战斗日志。 + + + 正在搜索战斗日志... + + + 打开战斗日志{0}。 + + + 无法打开战斗日志。 + + + 所选项目:{0} / {1} ({2:p1}) + + + 今天 + + + 忽略常见掉落 + \ No newline at end of file diff --git a/ElectronicObserver/Properties/Window/Dialog/EquipmentListResources.zh-CN.resx b/ElectronicObserver/Properties/Window/Dialog/EquipmentListResources.zh-CN.resx index 956449706..6f39a3e2e 100644 --- a/ElectronicObserver/Properties/Window/Dialog/EquipmentListResources.zh-CN.resx +++ b/ElectronicObserver/Properties/Window/Dialog/EquipmentListResources.zh-CN.resx @@ -1,144 +1,144 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 文件(&F) - - - 保存CSV为(&C)... - - - 更新(&U) - - - 输出到 CSV - - - 复制装备清单至舰队分析界面(&A) - - - 错误 - - - 仅显示锁定的装备(_L) - - - 显示(_V) - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 文件(&F) + + + 保存CSV为(&C)... + + + 更新(&U) + + + 输出到 CSV + + + 复制装备清单至舰队分析界面(&A) + + + 错误 + + + 仅显示锁定的装备(_L) + + + 显示(_V) + \ No newline at end of file diff --git a/ElectronicObserver/Properties/Window/Dialog/EquipmentPickerResources.zh-CN.resx b/ElectronicObserver/Properties/Window/Dialog/EquipmentPickerResources.zh-CN.resx index 6154ff821..c735d8b33 100644 --- a/ElectronicObserver/Properties/Window/Dialog/EquipmentPickerResources.zh-CN.resx +++ b/ElectronicObserver/Properties/Window/Dialog/EquipmentPickerResources.zh-CN.resx @@ -1,123 +1,123 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 装备选择器 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 装备选择器 + \ No newline at end of file diff --git a/ElectronicObserver/Properties/Window/Dialog/ExpCheckerResources.zh-CN.resx b/ElectronicObserver/Properties/Window/Dialog/ExpCheckerResources.zh-CN.resx index 3d1a55b39..4807e7aef 100644 --- a/ElectronicObserver/Properties/Window/Dialog/ExpCheckerResources.zh-CN.resx +++ b/ElectronicObserver/Properties/Window/Dialog/ExpCheckerResources.zh-CN.resx @@ -1,197 +1,197 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 出击次数 - - - 出击获得的经验 - - - 无目标舰娘 - - - 目标舰娘 - - - 所需经验 - - - 没有可用舰娘。 -请返回母港。 - - - 现代化改修 - - - 运改修 - - - 您可以通过输入每次出击获得的经验来计算出动次数。 - - - 按舰队搜索 - - - 所需经验计算 - - - 只能选择当前舰队的舰娘。 - - - 显示条件 - - - 启用后,将从 1 级开始显示。 -禁用时,将显示下一个级别。 - - - 显示所有声纳/深水炸弹(水听/暴雷)组合。 - - - 对潜改修 - - - 先反装备(先手反潜装备) - - - 对潜 - - - 显示全部Lv - - - 显示全部对潜装备 - - - 命中 - - - *由于对潜值未知,因此无法进行计算。 - - - *由于对潜值仍为近似值,因此计算可能不准确。 - - - 将反潜修改值从当前值更改。 - - - 将运改修值从当前值更改。 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 出击次数 + + + 出击获得的经验 + + + 无目标舰娘 + + + 目标舰娘 + + + 所需经验 + + + 没有可用舰娘。 +请返回母港。 + + + 现代化改修 + + + 运改修 + + + 您可以通过输入每次出击获得的经验来计算出动次数。 + + + 按舰队搜索 + + + 所需经验计算 + + + 只能选择当前舰队的舰娘。 + + + 显示条件 + + + 启用后,将从 1 级开始显示。 +禁用时,将显示下一个级别。 + + + 显示所有声纳/深水炸弹(水听/暴雷)组合。 + + + 对潜改修 + + + 先反装备(先手反潜装备) + + + 对潜 + + + 显示全部Lv + + + 显示全部对潜装备 + + + 命中 + + + *由于对潜值未知,因此无法进行计算。 + + + *由于对潜值仍为近似值,因此计算可能不准确。 + + + 将反潜修改值从当前值更改。 + + + 将运改修值从当前值更改。 + \ No newline at end of file diff --git a/ElectronicObserver/Properties/Window/Dialog/ExpeditionCheckResources.zh-CN.resx b/ElectronicObserver/Properties/Window/Dialog/ExpeditionCheckResources.zh-CN.resx index d381cd84a..9c5d6bd8c 100644 --- a/ElectronicObserver/Properties/Window/Dialog/ExpeditionCheckResources.zh-CN.resx +++ b/ElectronicObserver/Properties/Window/Dialog/ExpeditionCheckResources.zh-CN.resx @@ -1,141 +1,141 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 成功条件 - - - 远征名称 - - - 检测能否远征 - - - 第四舰队 - - - 第三舰队 - - - 第二舰队 - - - 第一舰队 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 成功条件 + + + 远征名称 + + + 检测能否远征 + + + 第四舰队 + + + 第三舰队 + + + 第二舰队 + + + 第一舰队 + \ No newline at end of file diff --git a/ElectronicObserver/Properties/Window/Dialog/LocalAPILoader2Resources.zh-CN.resx b/ElectronicObserver/Properties/Window/Dialog/LocalAPILoader2Resources.zh-CN.resx index 33e8d0101..7dadc7954 100644 --- a/ElectronicObserver/Properties/Window/Dialog/LocalAPILoader2Resources.zh-CN.resx +++ b/ElectronicObserver/Properties/Window/Dialog/LocalAPILoader2Resources.zh-CN.resx @@ -1,175 +1,175 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 操作已在进行中。 -是否要中断操作? - - - 文件夹未指定或不存在。 - - - 搜索 - - - 接下来运行 - - - 运行 - - - 之前搜索 - - - 请选择单行。 - - - 从文件加载 API - - - 信息 - - - 文件名 - - - 无法启动 API 文件。 {0}:{1} - - - 错误 - - - 确认 - - - 重新加载(&R) - - - 打开文件夹(&O)... - - - 文件(&F) - - - 执行(&E) - - - 删除(&D) - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 操作已在进行中。 +是否要中断操作? + + + 文件夹未指定或不存在。 + + + 搜索 + + + 接下来运行 + + + 运行 + + + 之前搜索 + + + 请选择单行。 + + + 从文件加载 API + + + 信息 + + + 文件名 + + + 无法启动 API 文件。 {0}:{1} + + + 错误 + + + 确认 + + + 重新加载(&R) + + + 打开文件夹(&O)... + + + 文件(&F) + + + 执行(&E) + + + 删除(&D) + \ No newline at end of file diff --git a/ElectronicObserver/Properties/Window/Dialog/QuestTrackerManagerResources.zh-CN.resx b/ElectronicObserver/Properties/Window/Dialog/QuestTrackerManagerResources.zh-CN.resx index e480adc0d..4e5cdc56e 100644 --- a/ElectronicObserver/Properties/Window/Dialog/QuestTrackerManagerResources.zh-CN.resx +++ b/ElectronicObserver/Properties/Window/Dialog/QuestTrackerManagerResources.zh-CN.resx @@ -1,250 +1,250 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 7-2-1 - - - 7-3-2 - - - 7-3-1 - - - 7-2-2 - - - 未知任务 - - - 警告 - - - 舰娘位置 - - - X - - - 未知任务,请确保你使用的是最新的74EO。 - - - 1-6N - - - 舰娘 - - - 7-5-3 - - - 7-5-2 - - - 7-5-1 - - - 舰娘国籍 - - - 舰种 - - - 查看详情 - - - 未知要求,请确保你使用的是最新的74EO。 - - - 艆(部分) - - - - - - 任务追踪管理器 - - - 演习 - - - 位置 - - - - - - 节点范围 - - - 必须旗舰 - - - 最小改造 - - - 从剪贴板加载 - - - 旗舰 - - - 文件 - - - 远征 - - - 检测到现有的任务跟踪器。重复的任务跟踪器将覆盖您当前的任务跟踪器,并且您的该任务跟踪器的进度将丢失。受影响的任务跟踪器是: - -{0} - -您想覆盖这些任务追踪器吗? - - - 精确改造 - - - 装备废弃 - - - 将跟踪器复制到剪贴板 - - - 复制 - - - 击杀Boss - - - 战斗节点ID - - - 任何修改 - - - - - - 允许的舰种 - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 7-2-1 + + + 7-3-2 + + + 7-3-1 + + + 7-2-2 + + + 未知任务 + + + 警告 + + + 舰娘位置 + + + X + + + 未知任务,请确保你使用的是最新的74EO。 + + + 1-6N + + + 舰娘 + + + 7-5-3 + + + 7-5-2 + + + 7-5-1 + + + 舰娘国籍 + + + 舰种 + + + 查看详情 + + + 未知要求,请确保你使用的是最新的74EO。 + + + 艆(部分) + + + + + + 任务追踪管理器 + + + 演习 + + + 位置 + + + + + + 节点范围 + + + 必须旗舰 + + + 最小改造 + + + 从剪贴板加载 + + + 旗舰 + + + 文件 + + + 远征 + + + 检测到现有的任务跟踪器。重复的任务跟踪器将覆盖您当前的任务跟踪器,并且您的该任务跟踪器的进度将丢失。受影响的任务跟踪器是: + +{0} + +您想覆盖这些任务追踪器吗? + + + 精确改造 + + + 装备废弃 + + + 将跟踪器复制到剪贴板 + + + 复制 + + + 击杀Boss + + + 战斗节点ID + + + 任何修改 + + + + + + 允许的舰种 + + + + \ No newline at end of file diff --git a/ElectronicObserver/Properties/Window/Dialog/ResourceChartResources.zh-CN.resx b/ElectronicObserver/Properties/Window/Dialog/ResourceChartResources.zh-CN.resx index 9a55d554e..eb5afe370 100644 --- a/ElectronicObserver/Properties/Window/Dialog/ResourceChartResources.zh-CN.resx +++ b/ElectronicObserver/Properties/Window/Dialog/ResourceChartResources.zh-CN.resx @@ -1,181 +1,181 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 文件(&F) - - - 保存图表图像(&S)... - - - 选择图表(&G) - - - 资源(&R) - - - 资源(差值)(&E) - - - 资材(&M) - - - 资材(差值)(&A) - - - 经验值(&E) - - - 经验值(差值)(&X) - - - 范围(&S) - - - 显示所有数据 - - - 显示每日平均值 - - - 保存图表 - - - 记录数据不存在。 -请移至您的母港一次。 - - - 错误 - - - 保存资源图表图像失败。 - - - 从星期一开始 (_E) - - - 从月初开始(_O) - - - 从3个月(季度初)开始(_N) - - - 从年初开始(_R) - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 文件(&F) + + + 保存图表图像(&S)... + + + 选择图表(&G) + + + 资源(&R) + + + 资源(差值)(&E) + + + 资材(&M) + + + 资材(差值)(&A) + + + 经验值(&E) + + + 经验值(差值)(&X) + + + 范围(&S) + + + 显示所有数据 + + + 显示每日平均值 + + + 保存图表 + + + 记录数据不存在。 +请移至您的母港一次。 + + + 错误 + + + 保存资源图表图像失败。 + + + 从星期一开始 (_E) + + + 从月初开始(_O) + + + 从3个月(季度初)开始(_N) + + + 从年初开始(_R) + \ No newline at end of file diff --git a/ElectronicObserver/Properties/Window/Dialog/ShipGraphicViewerResources.zh-CN.resx b/ElectronicObserver/Properties/Window/Dialog/ShipGraphicViewerResources.zh-CN.resx index 640a2969c..e872b4371 100644 --- a/ElectronicObserver/Properties/Window/Dialog/ShipGraphicViewerResources.zh-CN.resx +++ b/ElectronicObserver/Properties/Window/Dialog/ShipGraphicViewerResources.zh-CN.resx @@ -1,182 +1,182 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 文件(&F) - - - 打开(&O) - - - 复制到剪贴板(&C) - - - 展示(&V) - - - 插值模式(&I) - - - 清除(&N) - - - 平滑(&B) - - - 放大(&E) - - - 缩小(&S) - - - 100%(&1) - - - 缩放至​​(&F) - - - 打开图像文件 - - - 保存图像 - - - 舰娘图像查看器 - - - 图像查看器:加载图像时发生错误。 - - - 没有找到图像。 - - - {0}无法打开。 -{1} -{2} - - - {0} / {1} -{2} ({3}) -缩放{4:p1} -(使用←/→键翻页) - - - 缩放(&Z) - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 文件(&F) + + + 打开(&O) + + + 复制到剪贴板(&C) + + + 展示(&V) + + + 插值模式(&I) + + + 清除(&N) + + + 平滑(&B) + + + 放大(&E) + + + 缩小(&S) + + + 100%(&1) + + + 缩放至​​(&F) + + + 打开图像文件 + + + 保存图像 + + + 舰娘图像查看器 + + + 图像查看器:加载图像时发生错误。 + + + 没有找到图像。 + + + {0}无法打开。 +{1} +{2} + + + {0} / {1} +{2} ({3}) +缩放{4:p1} +(使用←/→键翻页) + + + 缩放(&Z) + \ No newline at end of file diff --git a/ElectronicObserver/Properties/Window/Dialog/ShipGroupCSVOutputResources.zh-CN.resx b/ElectronicObserver/Properties/Window/Dialog/ShipGroupCSVOutputResources.zh-CN.resx index 6ee4c6f09..d90238337 100644 --- a/ElectronicObserver/Properties/Window/Dialog/ShipGroupCSVOutputResources.zh-CN.resx +++ b/ElectronicObserver/Properties/Window/Dialog/ShipGroupCSVOutputResources.zh-CN.resx @@ -1,141 +1,141 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 用于数据 - - - 用于阅览 - - - 仅输出可见列 - - - 输出全部 - - - 输出目的地 - - - 保存 CSV - - - 将组导出到 CSV - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 用于数据 + + + 用于阅览 + + + 仅输出可见列 + + + 输出全部 + + + 输出目的地 + + + 保存 CSV + + + 将组导出到 CSV + \ No newline at end of file diff --git a/ElectronicObserver/Properties/Window/Dialog/ShipGroupColumnFilterResources.zh-CN.resx b/ElectronicObserver/Properties/Window/Dialog/ShipGroupColumnFilterResources.zh-CN.resx index 20357b702..da4e6800b 100644 --- a/ElectronicObserver/Properties/Window/Dialog/ShipGroupColumnFilterResources.zh-CN.resx +++ b/ElectronicObserver/Properties/Window/Dialog/ShipGroupColumnFilterResources.zh-CN.resx @@ -1,144 +1,144 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 栏目名称 - - - 展示 - - - 选择启用指定的列。 - - - 自动调整大小 - - - 选择自动调整指定列的大小。 - - - 宽度 - - - 冻结列数 - - - 选择列 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 栏目名称 + + + 展示 + + + 选择启用指定的列。 + + + 自动调整大小 + + + 选择自动调整指定列的大小。 + + + 宽度 + + + 冻结列数 + + + 选择列 + \ No newline at end of file diff --git a/ElectronicObserver/Properties/Window/Dialog/ShipGroupFilterResources.zh-CN.resx b/ElectronicObserver/Properties/Window/Dialog/ShipGroupFilterResources.zh-CN.resx index cbecbe0b8..ea737c534 100644 --- a/ElectronicObserver/Properties/Window/Dialog/ShipGroupFilterResources.zh-CN.resx +++ b/ElectronicObserver/Properties/Window/Dialog/ShipGroupFilterResources.zh-CN.resx @@ -1,305 +1,305 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 初始化 - - - 转换为公式 - - - (说明) - - - 左侧 - - - 右侧 - - - 状况 - - - 添加 - - - 删除 - - - 编辑 - - - 公式 - - - 外部条件 - - - 内部条件 - - - - - - 添加 - - - 删除 - - - 优化 - - - 筛选 - - - 包含/排除列表 - - - 启用/禁用 - - - 逆转条件 - - - - - - 向上 - - - - - - 向下 - - - - - - 启用/禁用 - - - 将包含/排除列表转换为表达式。 -请注意,反向转换是不可能的。 - - - 从列表中删除不存在的舰娘。 - - - 删除列表中的所有内容。 - - - 选择要删除的行。 - - - 选择包含目标表达式的行(左侧)。 -如果该行不存在,则添加该行。 - - - 选择目标表达式列(左侧)。 - - - 请选择目标行。 - - - 确认初始化 - - - 初始化{0}。 -你确定吗? - - - 将当前包含/排除列表转换为表达式。 -无法进行反向转换。 -你确定吗? - - - 从剪贴板导入过滤器。 -当前过滤器将被丢弃(包含/排除过滤器将被保留) -你确定吗? - - - 检查过滤器的导入 - - - 剪贴板是空的。 -复制过滤器数据并再次选择。 - - - 无法导入 - - - 该数据格式无法导入 - - - 无论筛选内容如何,你都可以从组内的右键菜单添加/移除舰娘。 - - - - 导入过滤器失败。 - - - 已将过滤器导出到剪贴板。 -您可以使用“导入过滤器”导入它或 -将其粘贴到记事本等中并保存。 - - - 导出过滤器 - - - 导出过滤器失败。 - - - 无法导出 - - - 取消 - - - 筛选 - - - 包含/排除列表 - - - 艆名 - - - 包含列表 - - - 排除列表 - - - 菜单 ▼ - - - 导入过滤器(&I) - - - 导出过滤器(&E) - - - 筛选器设置 - - - 错误 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 初始化 + + + 转换为公式 + + + (说明) + + + 左侧 + + + 右侧 + + + 状况 + + + 添加 + + + 删除 + + + 编辑 + + + 公式 + + + 外部条件 + + + 内部条件 + + + + + + 添加 + + + 删除 + + + 优化 + + + 筛选 + + + 包含/排除列表 + + + 启用/禁用 + + + 逆转条件 + + + + + + 向上 + + + + + + 向下 + + + + + + 启用/禁用 + + + 将包含/排除列表转换为表达式。 +请注意,反向转换是不可能的。 + + + 从列表中删除不存在的舰娘。 + + + 删除列表中的所有内容。 + + + 选择要删除的行。 + + + 选择包含目标表达式的行(左侧)。 +如果该行不存在,则添加该行。 + + + 选择目标表达式列(左侧)。 + + + 请选择目标行。 + + + 确认初始化 + + + 初始化{0}。 +你确定吗? + + + 将当前包含/排除列表转换为表达式。 +无法进行反向转换。 +你确定吗? + + + 从剪贴板导入过滤器。 +当前过滤器将被丢弃(包含/排除过滤器将被保留) +你确定吗? + + + 检查过滤器的导入 + + + 剪贴板是空的。 +复制过滤器数据并再次选择。 + + + 无法导入 + + + 该数据格式无法导入 + + + 无论筛选内容如何,你都可以从组内的右键菜单添加/移除舰娘。 + + + + 导入过滤器失败。 + + + 已将过滤器导出到剪贴板。 +您可以使用“导入过滤器”导入它或 +将其粘贴到记事本等中并保存。 + + + 导出过滤器 + + + 导出过滤器失败。 + + + 无法导出 + + + 取消 + + + 筛选 + + + 包含/排除列表 + + + 艆名 + + + 包含列表 + + + 排除列表 + + + 菜单 ▼ + + + 导入过滤器(&I) + + + 导出过滤器(&E) + + + 筛选器设置 + + + 错误 + \ No newline at end of file diff --git a/ElectronicObserver/Properties/Window/Dialog/ShipGroupSortOrderResources.zh-CN.resx b/ElectronicObserver/Properties/Window/Dialog/ShipGroupSortOrderResources.zh-CN.resx index 94c10e248..7aa7524b4 100644 --- a/ElectronicObserver/Properties/Window/Dialog/ShipGroupSortOrderResources.zh-CN.resx +++ b/ElectronicObserver/Properties/Window/Dialog/ShipGroupSortOrderResources.zh-CN.resx @@ -1,144 +1,144 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 自动排序 - - - 栏目名称 - - - 命令 - - - 按升序或降序对列进行排序。 - - - 全部 >> - - - << 全部 - - - 栏目名称 - - - 自动排序 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 自动排序 + + + 栏目名称 + + + 命令 + + + 按升序或降序对列进行排序。 + + + 全部 >> + + + << 全部 + + + 栏目名称 + + + 自动排序 + \ No newline at end of file diff --git a/ElectronicObserver/Properties/Window/Dialog/ShipPickerResources.zh-CN.resx b/ElectronicObserver/Properties/Window/Dialog/ShipPickerResources.zh-CN.resx index c40004915..7fc373480 100644 --- a/ElectronicObserver/Properties/Window/Dialog/ShipPickerResources.zh-CN.resx +++ b/ElectronicObserver/Properties/Window/Dialog/ShipPickerResources.zh-CN.resx @@ -1,123 +1,123 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 选择舰娘 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 选择舰娘 + \ No newline at end of file diff --git a/ElectronicObserver/Properties/Window/Dialog/VersionResources.zh-CN.resx b/ElectronicObserver/Properties/Window/Dialog/VersionResources.zh-CN.resx index 7c102ee19..c7f489b57 100644 --- a/ElectronicObserver/Properties/Window/Dialog/VersionResources.zh-CN.resx +++ b/ElectronicObserver/Properties/Window/Dialog/VersionResources.zh-CN.resx @@ -1,144 +1,144 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 项目站点(错误报告、建议): - - - 开发: - - - 关闭 - - - 版本、关于74EO - - - {0} (ver. {1} - {2}版本) - - - 试制七四式电子观测仪零型(ver. 0.0) - - - 修改者: - - - Andante - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 项目站点(错误报告、建议): + + + 开发: + + + 关闭 + + + 版本、关于74EO + + + {0} (ver. {1} - {2}版本) + + + 试制七四式电子观测仪零型(ver. 0.0) + + + 修改者: + + + Andante + \ No newline at end of file diff --git a/ElectronicObserver/Properties/Window/DockResources.zh-CN.resx b/ElectronicObserver/Properties/Window/DockResources.zh-CN.resx index ad14a4eb1..dc233c075 100644 --- a/ElectronicObserver/Properties/Window/DockResources.zh-CN.resx +++ b/ElectronicObserver/Properties/Window/DockResources.zh-CN.resx @@ -1,123 +1,123 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 入渠 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 入渠 + \ No newline at end of file diff --git a/ElectronicObserver/Properties/Window/FleetOverviewResources.zh-CN.resx b/ElectronicObserver/Properties/Window/FleetOverviewResources.zh-CN.resx index b3bdea279..f1f7298de 100644 --- a/ElectronicObserver/Properties/Window/FleetOverviewResources.zh-CN.resx +++ b/ElectronicObserver/Properties/Window/FleetOverviewResources.zh-CN.resx @@ -1,144 +1,144 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 舰队 - - - 搭载运输缶:{0} 件({12} 艆) -搭载大发动艇:{1} 件({13} 艆) -水上电探:{10} 件({11} 艆) -运输量(TP):S {2} / A {3} - -总制空:{4} -总索敌:{5:f2} -新公式-33式(33): -分歧点系数1:{6:f2} -分歧点系数2:{7:f2} -分歧点系数3:{8:f2} -分歧点系数4:{9:f2} - - - 泊地修理计时器 -开始: - - - 恢复 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 舰队 + + + 搭载运输缶:{0} 件({12} 艆) +搭载大发动艇:{1} 件({13} 艆) +水上电探:{10} 件({11} 艆) +运输量(TP):S {2} / A {3} + +总制空:{4} +总索敌:{5:f2} +新公式-33式(33): +分歧点系数1:{6:f2} +分歧点系数2:{7:f2} +分歧点系数3:{8:f2} +分歧点系数4:{9:f2} + + + 泊地修理计时器 +开始: + + + 恢复 + \ No newline at end of file diff --git a/ElectronicObserver/Properties/Window/FleetPresetResources.zh-CN.resx b/ElectronicObserver/Properties/Window/FleetPresetResources.zh-CN.resx index 8dfac603e..83a084326 100644 --- a/ElectronicObserver/Properties/Window/FleetPresetResources.zh-CN.resx +++ b/ElectronicObserver/Properties/Window/FleetPresetResources.zh-CN.resx @@ -1,126 +1,126 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 编成预设 - - - 最低条件 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 编成预设 + + + 最低条件 + \ No newline at end of file diff --git a/ElectronicObserver/Properties/Window/FleetResources.zh-CN.resx b/ElectronicObserver/Properties/Window/FleetResources.zh-CN.resx index 56877b191..38a4007e3 100644 --- a/ElectronicObserver/Properties/Window/FleetResources.zh-CN.resx +++ b/ElectronicObserver/Properties/Window/FleetResources.zh-CN.resx @@ -1,284 +1,284 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - *未加载* - - - 编成另存为图像(&I) - - - 复制舰娘列表到舰队分析 - - - 复制装备列表到舰队分析 - - - 防空火力(AA)详细表示(&A) - - - 无法发动 - - - 航空支援 - - - 支援射击 - - - 长距离支援雷击 - - - 总等级: {0} / 平均: {1:0.00} -{2}舰队 -支援攻击: {3} -总计火力 {4} ({20}) / 雷装 {5} / 对空 {6} ({21}) / 对潜 {7} ({22}) / 索敌 {8} ({23}){26} -搭载运输缶: {9}个 ({10}艆) -搭载大发动艇: {11}个 ({12}艆, +{13:p1}) -运送量(TP): S {14} / A {15} -水上电探: {24}个 ({25}艆) -总消耗: 油 {16} / 弹 {17} -(每场战斗 油 {18} / 弹 {19}) - - - 无熟练度 - - - 有熟练度 - - - 新公式(33) 分歧点系数: {0} - (点击切换) - -接触开始率: - 确保 {1:p1} / 优势 {2:p1} - - - - 接触选择率: - - -  命中{0} : {1:p1} - - - {0}{1} {2} -火力: {3}/{4} -雷装: {5}/{6} -对空: {7}/{8} -装甲: {9}/{10} -对潜: {11}/{12} -回避: {13}/{14} -索敌: {15}/{16} -运: {17} -命中: {18:+#;-#;+0} -爆装: {19:+#;-#;+0} -射程: {20} / 速力: {21} -(右键查看图鉴) - - - (右键计算所需Exp) - - - 威力 - - - 航母CI(战爆攻-FBA) - - - 航母CI(爆爆攻-BBA) - - - 航母CI(爆攻-BA) - - - 命中 - - - 对潜 - - - (可先手) - - - 对空喷进弹幕 - - - 空袭威力 - - - {0} 制空战力{1} / 索敌能力 {2} / 运输能力 {3} - - - 全部 - - - 对潜支援 - - - 烟幕 - - - 将舰娘列表复制到舰队分析 - - - 将装备列表复制到舰队分析 - - - (右键打开图鉴) - - - 舰娘训练计划 - - - 计算所需经验 - - - 编辑舰娘训练 - - - 消除舰娘训练 - - - 特殊炮击(昼战): - - - 特殊炮击(夜战): - - - 夜侦 - - - 照明弹 - - - 锁定 - - - 复制为图像(&S) - - - 复制编成文本(&C) - - - 复制编成(BD-builder)(&D) - - - 复制并曝光到舰队分析(&R) - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + *未加载* + + + 编成另存为图像(&I) + + + 复制舰娘列表到舰队分析 + + + 复制装备列表到舰队分析 + + + 防空火力(AA)详细表示(&A) + + + 无法发动 + + + 航空支援 + + + 支援射击 + + + 长距离支援雷击 + + + 总等级: {0} / 平均: {1:0.00} +{2}舰队 +支援攻击: {3} +总计火力 {4} ({20}) / 雷装 {5} / 对空 {6} ({21}) / 对潜 {7} ({22}) / 索敌 {8} ({23}){26} +搭载运输缶: {9}个 ({10}艆) +搭载大发动艇: {11}个 ({12}艆, +{13:p1}) +运送量(TP): S {14} / A {15} +水上电探: {24}个 ({25}艆) +总消耗: 油 {16} / 弹 {17} +(每场战斗 油 {18} / 弹 {19}) + + + 无熟练度 + + + 有熟练度 + + + 新公式(33) 分歧点系数: {0} + (点击切换) + +接触开始率: + 确保 {1:p1} / 优势 {2:p1} + + + + 接触选择率: + + +  命中{0} : {1:p1} + + + {0}{1} {2} +火力: {3}/{4} +雷装: {5}/{6} +对空: {7}/{8} +装甲: {9}/{10} +对潜: {11}/{12} +回避: {13}/{14} +索敌: {15}/{16} +运: {17} +命中: {18:+#;-#;+0} +爆装: {19:+#;-#;+0} +射程: {20} / 速力: {21} +(右键查看图鉴) + + + (右键计算所需Exp) + + + 威力 + + + 航母CI(战爆攻-FBA) + + + 航母CI(爆爆攻-BBA) + + + 航母CI(爆攻-BA) + + + 命中 + + + 对潜 + + + (可先手) + + + 对空喷进弹幕 + + + 空袭威力 + + + {0} 制空战力{1} / 索敌能力 {2} / 运输能力 {3} + + + 全部 + + + 对潜支援 + + + 烟幕 + + + 将舰娘列表复制到舰队分析 + + + 将装备列表复制到舰队分析 + + + (右键打开图鉴) + + + 舰娘训练计划 + + + 计算所需经验 + + + 编辑舰娘训练 + + + 消除舰娘训练 + + + 特殊炮击(昼战): + + + 特殊炮击(夜战): + + + 夜侦 + + + 照明弹 + + + 锁定 + + + 复制为图像(&S) + + + 复制编成文本(&C) + + + 复制编成(BD-builder)(&D) + + + 复制并曝光到舰队分析(&R) + \ No newline at end of file diff --git a/ElectronicObserver/Properties/Window/HeadquartersResources.zh-CN.resx b/ElectronicObserver/Properties/Window/HeadquartersResources.zh-CN.resx index 3b54d30f6..68ed9fed9 100644 --- a/ElectronicObserver/Properties/Window/HeadquartersResources.zh-CN.resx +++ b/ElectronicObserver/Properties/Window/HeadquartersResources.zh-CN.resx @@ -1,446 +1,446 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 该月战果 - - - 该日战果 - - - 此次战果 - - - 海外舰最新技术 - - - 南瓜 - - - 白襻(白带) - - - 海色缎带(蓝带) - - - 晴天娃娃 - - - 圣诞精品礼物箱 - - - 从舰娘那里获得的巧克力 - - - 沙丁鱼 - - - 秋刀鱼 - - - 沙丁鱼 - - - 秋刀鱼 - - - 茶叶 - - - 海苔 - - - 梅干 - - - 大米 - - - (提督名) - - - (提督签名) - - - HQ Lv. - - - (舰娘数) - - - (装备数) - - - (修复) - - - (建造) - - - (开发) - - - (改修) - - - (家具) - - - (任意) - - - (燃料) - - - (弹药) - - - (钢材) - - - 司令部 - - - 提督名 - - - 提督签名 - - - 司令部Lv - - - 舰娘数量 - - - 装备数量 - - - 高速修复材 - - - 高速建造材 - - - 开发资材 - - - 改修资材 - - - 家具币 - - - 燃料 - - - 弹药 - - - 钢材 - - - 铝土 - - - 任何物品 - - - 出击次数: {0} / 出击胜利: {1} ({2:p2}) / 出击失败: {3} - - - 每次出击获得的平均经验值: {0:n2} / 胜利时 {1:n2} - - - 远征次数: {0} / 远征成功: {1} ({2:p2}) / 远征失败: {3} - - - 演习次数: {0} / 演习成功: {1} ({2:p2}) / 演习失败: {3} - - - 甲章持有数量: {0} - - - 此次: +{0} exp. / 战果 {1:n2} - - - 该日: +{0} exp. / 战果 {1:n2} - - - 该月: +{0} exp. / 战果 {1:n2} - - - 此次: {0:+##;-##;±0} -该周: {1:+##;-##;±0} -该月: {2:+##;-##;±0} - - - (小) x {0} ( +{1} ) -(中) x {2} ( +{3} ) -(大) x {4} ( +{5} ) - - - 修复 - - - 开发 - - - 建造 - - - 改修 - - - 无法将资源复制到剪贴板。 - - - (可以在设置中更改显示物品) -(右键显示全部物品) - - - 未知物品 (ID: {0}) - - - 拥有物品清单 - - - 环绕偏移 - - - 战斗详报 - - - 秋刀鱼罐头 - - - 战斗粮食 - - - 战斗粮食(特制饭团) - - - 设营队 - - - 家具箱(大) - - - 家具箱(中) - - - 家具箱(小) - - - (疑似铝土) - - - 补强增设 - - - 洋上补给 - - - 潜水舰补给物资 - - - Ne式引擎 - - - 新型兵装资材 - - - 新型航空器设计图 - - - 海峡章 - - - 改装设计图 - - - 凤翔小姐的晚餐券 - - - 母港扩张 - - - 菱饼 - - - 船坞开放匙 - - - 装饰材料 - - - 甲种勋章 - - - 试制甲板用弹射器 - - - 司令部要员 - - - 特制家具职人 - - - 紧急修理资材 - - - 契约一份&戒指 - - - 礼物箱 - - - 勋章 - - - 给粮舰[伊良湖] - - - 给粮舰[间宫] - - - 熟练搭乘员 - - - 新型火炮兵装资材 - - - 捷号章 - - - 新型航空兵装资材 - - - 节分豆 - - - 新型喷进装备开发资材 - - - 应急修理要员 - - - 应急修理女神 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 该月战果 + + + 该日战果 + + + 此次战果 + + + 海外舰最新技术 + + + 南瓜 + + + 白襻(白带) + + + 海色缎带(蓝带) + + + 晴天娃娃 + + + 圣诞精品礼物箱 + + + 从舰娘那里获得的巧克力 + + + 沙丁鱼 + + + 秋刀鱼 + + + 沙丁鱼 + + + 秋刀鱼 + + + 茶叶 + + + 海苔 + + + 梅干 + + + 大米 + + + (提督名) + + + (提督签名) + + + HQ Lv. + + + (舰娘数) + + + (装备数) + + + (修复) + + + (建造) + + + (开发) + + + (改修) + + + (家具) + + + (任意) + + + (燃料) + + + (弹药) + + + (钢材) + + + 司令部 + + + 提督名 + + + 提督签名 + + + 司令部Lv + + + 舰娘数量 + + + 装备数量 + + + 高速修复材 + + + 高速建造材 + + + 开发资材 + + + 改修资材 + + + 家具币 + + + 燃料 + + + 弹药 + + + 钢材 + + + 铝土 + + + 任何物品 + + + 出击次数: {0} / 出击胜利: {1} ({2:p2}) / 出击失败: {3} + + + 每次出击获得的平均经验值: {0:n2} / 胜利时 {1:n2} + + + 远征次数: {0} / 远征成功: {1} ({2:p2}) / 远征失败: {3} + + + 演习次数: {0} / 演习成功: {1} ({2:p2}) / 演习失败: {3} + + + 甲章持有数量: {0} + + + 此次: +{0} exp. / 战果 {1:n2} + + + 该日: +{0} exp. / 战果 {1:n2} + + + 该月: +{0} exp. / 战果 {1:n2} + + + 此次: {0:+##;-##;±0} +该周: {1:+##;-##;±0} +该月: {2:+##;-##;±0} + + + (小) x {0} ( +{1} ) +(中) x {2} ( +{3} ) +(大) x {4} ( +{5} ) + + + 修复 + + + 开发 + + + 建造 + + + 改修 + + + 无法将资源复制到剪贴板。 + + + (可以在设置中更改显示物品) +(右键显示全部物品) + + + 未知物品 (ID: {0}) + + + 拥有物品清单 + + + 环绕偏移 + + + 战斗详报 + + + 秋刀鱼罐头 + + + 战斗粮食 + + + 战斗粮食(特制饭团) + + + 设营队 + + + 家具箱(大) + + + 家具箱(中) + + + 家具箱(小) + + + (疑似铝土) + + + 补强增设 + + + 洋上补给 + + + 潜水舰补给物资 + + + Ne式引擎 + + + 新型兵装资材 + + + 新型航空器设计图 + + + 海峡章 + + + 改装设计图 + + + 凤翔小姐的晚餐券 + + + 母港扩张 + + + 菱饼 + + + 船坞开放匙 + + + 装饰材料 + + + 甲种勋章 + + + 试制甲板用弹射器 + + + 司令部要员 + + + 特制家具职人 + + + 紧急修理资材 + + + 契约一份&戒指 + + + 礼物箱 + + + 勋章 + + + 给粮舰[伊良湖] + + + 给粮舰[间宫] + + + 熟练搭乘员 + + + 新型火炮兵装资材 + + + 捷号章 + + + 新型航空兵装资材 + + + 节分豆 + + + 新型喷进装备开发资材 + + + 应急修理要员 + + + 应急修理女神 + \ No newline at end of file diff --git a/ElectronicObserver/Properties/Window/InformationResources.zh-CN.resx b/ElectronicObserver/Properties/Window/InformationResources.zh-CN.resx index fbb164212..8fa4f8ce2 100644 --- a/ElectronicObserver/Properties/Window/InformationResources.zh-CN.resx +++ b/ElectronicObserver/Properties/Window/InformationResources.zh-CN.resx @@ -1,177 +1,177 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 包含练巡加成的水面舰: {0} / S胜利: {1} - - - 包含练巡加成的潜水艇: {0} / S胜利: {1} - - - 信息 - - - 已确认敌方削弱(削甲成功)! - - - S胜利 - - - 练巡加成: {0} / S胜利: {1} - - - 破坏 - - - - - - 未完成的月常远征 - - - 输赢判断: {0} - - - 我们已确认海域变化(解密成功)! - - - [误出击警告] -未贴条舰娘: - - - - 没有贴条的舰娘在出击队伍中。 -请谨慎行事。 - -(可以从“设置”→“行为”禁用此警告。) - - - 误出击警告 - - - #{0} {1} 的远征 {2}:{3} 可能会失败。 - -未补给 - -(可以从“设置”→“行为”禁用此警告。) - - - *海域削弱* - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 包含练巡加成的水面舰: {0} / S胜利: {1} + + + 包含练巡加成的潜水艇: {0} / S胜利: {1} + + + 信息 + + + 已确认敌方削弱(削甲成功)! + + + S胜利 + + + 练巡加成: {0} / S胜利: {1} + + + 破坏 + + + + + + 未完成的月常远征 + + + 输赢判断: {0} + + + 我们已确认海域变化(解密成功)! + + + [误出击警告] +未贴条舰娘: + + + + 没有贴条的舰娘在出击队伍中。 +请谨慎行事。 + +(可以从“设置”→“行为”禁用此警告。) + + + 误出击警告 + + + #{0} {1} 的远征 {2}:{3} 可能会失败。 + +未补给 + +(可以从“设置”→“行为”禁用此警告。) + + + *海域削弱* + \ No newline at end of file diff --git a/ElectronicObserver/Properties/Window/JsonResources.zh-CN.resx b/ElectronicObserver/Properties/Window/JsonResources.zh-CN.resx index caecc9d7e..6a2822afe 100644 --- a/ElectronicObserver/Properties/Window/JsonResources.zh-CN.resx +++ b/ElectronicObserver/Properties/Window/JsonResources.zh-CN.resx @@ -1,159 +1,159 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 全部展开 - - - 全部收起 - - - 收起到父节点 - - - 将此节点输出到 CSV... - - - 将此节点复制到剪贴板 - - - ◆ 可以读取D&D保存的json文件 - - - 启用自动更新可能会严重影响性能 - - - 筛选: - - - 同时更新 JSON 树视图 - - - 自动更新 - - - 将节点导出到 CSV - - - 记录并复制该节点 - - - <自动更新已禁用。请从配置中启用它> - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 全部展开 + + + 全部收起 + + + 收起到父节点 + + + 将此节点输出到 CSV... + + + 将此节点复制到剪贴板 + + + ◆ 可以读取D&D保存的json文件 + + + 启用自动更新可能会严重影响性能 + + + 筛选: + + + 同时更新 JSON 树视图 + + + 自动更新 + + + 将节点导出到 CSV + + + 记录并复制该节点 + + + <自动更新已禁用。请从配置中启用它> + \ No newline at end of file diff --git a/ElectronicObserver/Properties/Window/MainResources.zh-CN.resx b/ElectronicObserver/Properties/Window/MainResources.zh-CN.resx index 53a4274fe..6c6a074b4 100644 --- a/ElectronicObserver/Properties/Window/MainResources.zh-CN.resx +++ b/ElectronicObserver/Properties/Window/MainResources.zh-CN.resx @@ -1,459 +1,459 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - - - - - - - 文件(_F) - - - 关闭(&X) - - - 设置(&C)... - - - 布局(&L) - - - 保存到另一个文件(&C)... - - - 恢复(&L) - - - 锁定布局(&T) - - - 从另一个文件恢复(&O)... - - - 保存(&S) - - - 窗口最前端(&M) - - - 通知(&N) - - - 将所有通知静音(&M) - - - 记录(&R) - - - 加载(&L) - - - 保存(&S) - - - 显示(_V) - - - 舰队(&F) - - - #&1 - - - #&2 - - - #&3 - - - #&4 - - - 舰队一览(&O) - - - 舰娘列表(&G) - - - 入渠(&D) - - - 工厂(&A) - - - 基地航空队(&S) - - - 司令部(&H) - - - 任务(&Q) - - - 信息(&I) - - - 罗盘(&C) - - - 战斗(&B) - - - 浏览器 (&M) - - - 日志(&L) - - - 窗口捕捉(&W) - - - 子窗口 (&C) - - - 再次搜索并导入所有内容 (&S) - - - 打开所有窗口(&R) - - - JSON(&J) - - - 工具(&T) - - - 装备一览(&Q) - - - 掉落记录(&D) - - - 开发记录(&V) - - - 建造记录(&R) - - - 資源图表(&C) - - - 舰娘图鉴(&S) - - - 装备图鉴(&E) - - - 防空火力详情(&A) - - - 输出编成图像(&F) - - - 基地航空队编成(&B) - - - 计算所需经验值(&X) - - - 远征检查(&M) - - - 额外的浏览器 - - - Debug(&D) - - - 从文件加载 API(&L)... - - - 加载 API 列表(&A)... - - - 从旧的 api_start2 构建记录(&O)... - - - 错误 - - - 作战室 - - - 删除旧的 API 数据(&D) - - - 重命名舰娘资源(&R)... - - - 从旧的api_start2恢复深海栖舰(&A)... - - - 帮助(&H) - - - 在线帮助(&H)... - - - 版本信息(&V) - - - 准备中... - - - - - - 舰队和预设(&P) - - - 试制七四式电子观测仪 - - - 报告问题 - - - 加入我们的 Discord - - - 检查更新 - - - 开始… - - - {0}你想退出吗? - - - 确认 - - - 已成功从 {0} 加载窗口布局。 - - - 舰娘数据尚未加载。 - - - 装备数据尚未加载。 - - - 这将使用您的浏览器打开 EO wiki。 -你确定吗? - - - 帮助 - - - 在外部浏览器中打开联机帮助。 -你确定吗? - - - 报告问题 - - - 无法打开浏览器 - - - 打开布局文件 - - - 保存布局文件 - - - 活动将于 {0} 开始 - - - 活动已经开始。 - - - 活动将于 {0} 结束 - - - 活动期间已结束。 - - - 维护将于 {0} 开始 - - - 维护已结束 - - - 下次演习重置: - - - 下次任务重置: - - - 您的 Windows 用户无权在当前位置创建文件。将 74EO 文件夹移动到您有写入权限的位置,例如桌面上。 - - - 任务数据未加载。 - - - 检查您是否有有效的布局文件。 -布局在 5.0.0 版本中被破坏,因此之前创建的布局不再起作用。 -有关更多信息或获取现有布局,请参阅此 github 问题:https://github.com/ElectronicObserverEN/ElectronicObserver/issues/71 - -您想打开这个 github 问题吗? - - - 无法加载布局 - - - 复制到剪贴板失败。 - - - 调整 - - - 网格分割器尺寸 - - - 下载更新 (_D) - - - リリースノートを開く (_O) - - - 有可用更新 (_U) - - - 正在下载更新... ({0:##0.00}%) - - - 正在下载更新程序... ({0:##0.00}%) - - - 加载保存的API - - - 无法加载窗口捕获数据 - - - https://github.com/RyuuKitsune/ElectronicObserver/wiki - - - 维护结束于 {0} - - - 维护已开始 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + + + + + 文件(_F) + + + 关闭(&X) + + + 设置(&C)... + + + 布局(&L) + + + 保存到另一个文件(&C)... + + + 恢复(&L) + + + 锁定布局(&T) + + + 从另一个文件恢复(&O)... + + + 保存(&S) + + + 窗口最前端(&M) + + + 通知(&N) + + + 将所有通知静音(&M) + + + 记录(&R) + + + 加载(&L) + + + 保存(&S) + + + 显示(_V) + + + 舰队(&F) + + + #&1 + + + #&2 + + + #&3 + + + #&4 + + + 舰队一览(&O) + + + 舰娘列表(&G) + + + 入渠(&D) + + + 工厂(&A) + + + 基地航空队(&S) + + + 司令部(&H) + + + 任务(&Q) + + + 信息(&I) + + + 罗盘(&C) + + + 战斗(&B) + + + 浏览器 (&M) + + + 日志(&L) + + + 窗口捕捉(&W) + + + 子窗口 (&C) + + + 再次搜索并导入所有内容 (&S) + + + 打开所有窗口(&R) + + + JSON(&J) + + + 工具(&T) + + + 装备一览(&Q) + + + 掉落记录(&D) + + + 开发记录(&V) + + + 建造记录(&R) + + + 資源图表(&C) + + + 舰娘图鉴(&S) + + + 装备图鉴(&E) + + + 防空火力详情(&A) + + + 输出编成图像(&F) + + + 基地航空队编成(&B) + + + 计算所需经验值(&X) + + + 远征检查(&M) + + + 额外的浏览器 + + + Debug(&D) + + + 从文件加载 API(&L)... + + + 加载 API 列表(&A)... + + + 从旧的 api_start2 构建记录(&O)... + + + 错误 + + + 作战室 + + + 删除旧的 API 数据(&D) + + + 重命名舰娘资源(&R)... + + + 从旧的api_start2恢复深海栖舰(&A)... + + + 帮助(&H) + + + 在线帮助(&H)... + + + 版本信息(&V) + + + 准备中... + + + + + + 舰队和预设(&P) + + + 试制七四式电子观测仪 + + + 报告问题 + + + 加入我们的 Discord + + + 检查更新 + + + 开始… + + + {0}你想退出吗? + + + 确认 + + + 已成功从 {0} 加载窗口布局。 + + + 舰娘数据尚未加载。 + + + 装备数据尚未加载。 + + + 这将使用您的浏览器打开 EO wiki。 +你确定吗? + + + 帮助 + + + 在外部浏览器中打开联机帮助。 +你确定吗? + + + 报告问题 + + + 无法打开浏览器 + + + 打开布局文件 + + + 保存布局文件 + + + 活动将于 {0} 开始 + + + 活动已经开始。 + + + 活动将于 {0} 结束 + + + 活动期间已结束。 + + + 维护将于 {0} 开始 + + + 维护已结束 + + + 下次演习重置: + + + 下次任务重置: + + + 您的 Windows 用户无权在当前位置创建文件。将 74EO 文件夹移动到您有写入权限的位置,例如桌面上。 + + + 任务数据未加载。 + + + 检查您是否有有效的布局文件。 +布局在 5.0.0 版本中被破坏,因此之前创建的布局不再起作用。 +有关更多信息或获取现有布局,请参阅此 github 问题:https://github.com/ElectronicObserverEN/ElectronicObserver/issues/71 + +您想打开这个 github 问题吗? + + + 无法加载布局 + + + 复制到剪贴板失败。 + + + 调整 + + + 网格分割器尺寸 + + + 下载更新 (_D) + + + リリースノートを開く (_O) + + + 有可用更新 (_U) + + + 正在下载更新... ({0:##0.00}%) + + + 正在下载更新程序... ({0:##0.00}%) + + + 加载保存的API + + + 无法加载窗口捕获数据 + + + https://github.com/RyuuKitsune/ElectronicObserver/wiki + + + 维护结束于 {0} + + + 维护已开始 + \ No newline at end of file diff --git a/ElectronicObserver/Properties/Window/QuestResources.zh-CN.resx b/ElectronicObserver/Properties/Window/QuestResources.zh-CN.resx index 801a8ad72..429d57b89 100644 --- a/ElectronicObserver/Properties/Window/QuestResources.zh-CN.resx +++ b/ElectronicObserver/Properties/Window/QuestResources.zh-CN.resx @@ -1,215 +1,215 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - (未获得) - - - (未获得的任务 x {0}) - - - +砍口垒 - - - 在 _Startpage 中搜索“{0}” - - - 在 DuckDuckGo(&G) 中搜索“{0}”(&G) - - - https://zh.kcwiki.cn/wiki/任务#{0} - - - site:https://zh.kcwiki.cn - - - 尺寸调整 - - - - - - 标头 - - - 显示过滤器(&Q) - - - 达成! - - - 复制未翻译的任务数据(&N) - - - 重置进度(&R) - - - 修改进度(_M) - - - - - - 信息 - - - 从列表中删除任务 {0} 并重置进度。 -你确定吗? -(当您打开砍口垒本身的任务屏幕时,它会正确更新。) - - - 任务“{0}”的进度无法更改。 - - - 显示任务代码 - - - 复制任务标题(&T) - - - 任务搜索失败 - - - 复制任务描述(&D) - - - 所有任务均已翻译 - - - 在 _Startpage 上搜索 - - - 在DuckDuckGo上搜索(&G) - - - 在舰娘百科上搜索任务名(&K) - - - 在舰娘百科上搜索任务名(&K) - - - 在DuckDuckGo上搜索任务名称失败。 - - - 在Startpage上搜索任务名失败。 - - - 重置任务进度 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + (未获得) + + + (未获得的任务 x {0}) + + + +砍口垒 + + + 在 _Startpage 中搜索“{0}” + + + 在 DuckDuckGo(&G) 中搜索“{0}”(&G) + + + https://zh.kcwiki.cn/wiki/任务#{0} + + + site:https://zh.kcwiki.cn + + + 尺寸调整 + + + + + + 标头 + + + 显示过滤器(&Q) + + + 达成! + + + 复制未翻译的任务数据(&N) + + + 重置进度(&R) + + + 修改进度(_M) + + + + + + 信息 + + + 从列表中删除任务 {0} 并重置进度。 +你确定吗? +(当您打开砍口垒本身的任务屏幕时,它会正确更新。) + + + 任务“{0}”的进度无法更改。 + + + 显示任务代码 + + + 复制任务标题(&T) + + + 任务搜索失败 + + + 复制任务描述(&D) + + + 所有任务均已翻译 + + + 在 _Startpage 上搜索 + + + 在DuckDuckGo上搜索(&G) + + + 在舰娘百科上搜索任务名(&K) + + + 在舰娘百科上搜索任务名(&K) + + + 在DuckDuckGo上搜索任务名称失败。 + + + 在Startpage上搜索任务名失败。 + + + 重置任务进度 + \ No newline at end of file diff --git a/ElectronicObserver/Properties/Window/ShipGroupResources.zh-CN.resx b/ElectronicObserver/Properties/Window/ShipGroupResources.zh-CN.resx index 444e50a85..1655590b2 100644 --- a/ElectronicObserver/Properties/Window/ShipGroupResources.zh-CN.resx +++ b/ElectronicObserver/Properties/Window/ShipGroupResources.zh-CN.resx @@ -1,289 +1,289 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 入渠 - - - 装备1 - - - 装备2 - - - 装备3 - - - 装备4 - - - 装备5 - - - 舰种 - - - 舰名 - - - 改装 - - - 舰队 - - - 入渠时间 - - - 入渠钢材 - - - 入渠燃料 - - - 夜战威力 - - - 添加到组(&A)... - - - 添加到新组(&N)... - - - 消除(&E) - - - 过滤器设置(&F)... - - - 列显示设置(&C)... - - - 自动排序设置(&S)... - - - CSV 输出(&O)... - - - 添加组(&A) - - - 复制组(&C) - - - 更改群组名称(&R)... - - - 删除组(&D) - - - 自动更新 - - - 显示状态栏 - - - - - - 舰娘组:未找到组。要恢复默认设置,请在完成后删除 {0}。 - - - 所属: {0}只 - - - Lv: 总计 {0:N0} / 平均 {1:N2} - - - Exp: 总计 {0:N0} / 平均 {1:N2} - - - 错误:试图引用不存在的组。请联系开发者 - - - (无) - - - 选择:{0}/{1} 只 - - - 添加组 - - - 请输入群组名称: - - - 复制组 - - - 请输入群组名称: - - - 确认 - - - 您想删除组 [{0}] 吗? -此操作无法撤消。 - - - 错误 - - - 该组无法删除。 - - - 更改群组名称 - - - 请输入群组名称: - - - 该组无法重命名。 - - - 该组无法修改。 - - - ShipGroup:列设置对话框中发生错误。 - - - ShipGroup:过滤器对话框中发生错误。 - - - ShipGroup:自动排序顺序设置对话框中发生错误。 - - - 选择组 - - - 选择要添加的组: - - - 将群组 CSV 保存到 {0}。 - - - 无法输出船组 CSV。 - - - 排序ID - - - 1 HP 修复时间 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 入渠 + + + 装备1 + + + 装备2 + + + 装备3 + + + 装备4 + + + 装备5 + + + 舰种 + + + 舰名 + + + 改装 + + + 舰队 + + + 入渠时间 + + + 入渠钢材 + + + 入渠燃料 + + + 夜战威力 + + + 添加到组(&A)... + + + 添加到新组(&N)... + + + 消除(&E) + + + 过滤器设置(&F)... + + + 列显示设置(&C)... + + + 自动排序设置(&S)... + + + CSV 输出(&O)... + + + 添加组(&A) + + + 复制组(&C) + + + 更改群组名称(&R)... + + + 删除组(&D) + + + 自动更新 + + + 显示状态栏 + + + + + + 舰娘组:未找到组。要恢复默认设置,请在完成后删除 {0}。 + + + 所属: {0}只 + + + Lv: 总计 {0:N0} / 平均 {1:N2} + + + Exp: 总计 {0:N0} / 平均 {1:N2} + + + 错误:试图引用不存在的组。请联系开发者 + + + (无) + + + 选择:{0}/{1} 只 + + + 添加组 + + + 请输入群组名称: + + + 复制组 + + + 请输入群组名称: + + + 确认 + + + 您想删除组 [{0}] 吗? +此操作无法撤消。 + + + 错误 + + + 该组无法删除。 + + + 更改群组名称 + + + 请输入群组名称: + + + 该组无法重命名。 + + + 该组无法修改。 + + + ShipGroup:列设置对话框中发生错误。 + + + ShipGroup:过滤器对话框中发生错误。 + + + ShipGroup:自动排序顺序设置对话框中发生错误。 + + + 选择组 + + + 选择要添加的组: + + + 将群组 CSV 保存到 {0}。 + + + 无法输出船组 CSV。 + + + 排序ID + + + 1 HP 修复时间 + \ No newline at end of file diff --git a/ElectronicObserver/Properties/Window/WindowCaptureResources.zh-CN.resx b/ElectronicObserver/Properties/Window/WindowCaptureResources.zh-CN.resx index 0ede8618b..68e3cd78e 100644 --- a/ElectronicObserver/Properties/Window/WindowCaptureResources.zh-CN.resx +++ b/ElectronicObserver/Properties/Window/WindowCaptureResources.zh-CN.resx @@ -1,129 +1,129 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 检查窗口捕获 - - - 您确定捕捉该窗口吗? - -警告:捕捉的窗口可能会变得不稳定并导致数据丢失。 -请先保存数据并返回母港以确保安全,然后再继续。 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 检查窗口捕获 + + + 您确定捕捉该窗口吗? + +警告:捕捉的窗口可能会变得不稳定并导致数据丢失。 +请先保存数据并返回母港以确保安全,然后再继续。 + \ No newline at end of file diff --git a/ElectronicObserver/Resource/Record/EnemyFleetRecord.cs b/ElectronicObserver/Resource/Record/EnemyFleetRecord.cs index 595f7fabe..11c022e76 100644 --- a/ElectronicObserver/Resource/Record/EnemyFleetRecord.cs +++ b/ElectronicObserver/Resource/Record/EnemyFleetRecord.cs @@ -169,7 +169,7 @@ private ulong ComputeHash() /// /// 現在の状態からインスタンスを生成します。 /// - public static EnemyFleetElement CreateFromCurrentState() + public static EnemyFleetElement? CreateFromCurrentState() { var battle = KCDatabase.Instance.Battle; @@ -187,9 +187,9 @@ public static EnemyFleetElement CreateFromCurrentState() battle.Compass.MapInfoID, battle.IsBaseAirRaid ? -1 : battle.Compass.CellId, battle.Compass.MapInfo.EventDifficulty, - battle.FirstBattle.Searching.FormationEnemy, - battle.IsEnemyCombined ? initial.EnemyMembers.Take(6).Concat(initial.EnemyMembersEscort).ToArray() : initial.EnemyMembers, - battle.IsEnemyCombined ? initial.EnemyLevels.Take(6).Concat(initial.EnemyLevelsEscort).ToArray() : initial.EnemyLevels, + (int)battle.FirstBattle.Searching.EnemyFormationType, + battle.IsEnemyCombined ? initial.EnemyMembers.Take(6).Concat(initial.EnemyMembersEscort).ToArray() : initial.EnemyMembers.ToArray(), + battle.IsEnemyCombined ? initial.EnemyLevels.Take(6).Concat(initial.EnemyLevelsEscort).ToArray() : initial.EnemyLevels.ToArray(), baseExp); } @@ -216,7 +216,7 @@ public override void RegisterEvents() } - public EnemyFleetElement this[ulong i] + public EnemyFleetElement? this[ulong i] { get { diff --git a/ElectronicObserver/Resource/Record/ShipParameterRecord.cs b/ElectronicObserver/Resource/Record/ShipParameterRecord.cs index 975a19963..575684c3c 100644 --- a/ElectronicObserver/Resource/Record/ShipParameterRecord.cs +++ b/ElectronicObserver/Resource/Record/ShipParameterRecord.cs @@ -7,6 +7,8 @@ using ElectronicObserver.Data; using ElectronicObserver.Data.Battle; using ElectronicObserver.Observer; +using ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle; +using ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle.Interfaces; namespace ElectronicObserver.Resource.Record; @@ -273,12 +275,12 @@ public sealed class ShipParameterElement : RecordElementBase /// /// 初期装備 /// - public int[] DefaultSlot { get; internal set; } + public int[]? DefaultSlot { get; internal set; } /// /// 搭載機数 /// - public int[] Aircraft { get; internal set; } + public int[]? Aircraft { get; internal set; } /// @@ -1086,25 +1088,26 @@ void UpdateParams(int id, int maxhp, int[] status, int[] slot) Update(param); } - - for (int i = 0; i < binit.EnemyMembers.Length; i++) + int[] enemyMembers = binit.EnemyMembers.ToArray(); + for (int i = 0; i < enemyMembers.Length; i++) { - int id = binit.EnemyMembers[i]; + int id = enemyMembers[i]; if (id <= 0) continue; - UpdateParams(id, binit.EnemyMaxHPs[i], binit.EnemyParameters?[i], binit.EnemySlots[i]); + UpdateParams(id, binit.EnemyMaxHPs[i], binit.EnemyParameters?[i].ToArray(), binit.EnemySlots[i]); } if (battle.IsEnemyCombined) { - for (int i = 0; i < binit.EnemyMembersEscort.Length; i++) + int[] enemyMembersEscort = binit.EnemyMembersEscort!.ToArray(); + for (int i = 0; i < enemyMembersEscort.Length; i++) { - int id = binit.EnemyMembersEscort[i]; + int id = enemyMembersEscort[i]; if (id <= 0) continue; - UpdateParams(id, binit.EnemyMaxHPsEscort[i], binit.EnemyParametersEscort?[i], binit.EnemySlotsEscort[i]); + UpdateParams(id, binit.EnemyMaxHPsEscort[i], binit.EnemyParametersEscort?[i].ToArray(), binit.EnemySlotsEscort[i]); } } @@ -1115,7 +1118,7 @@ void EstimateUnknownAircraftSlot() var db = KCDatabase.Instance; // 航空戦が存在するときだけ処理する - if (!(battle is BattleDay battleDay)) + if (!(battle is FirstBattleData battleDay)) return; @@ -1125,7 +1128,7 @@ void EstimateUnknownAircraftSlot() members = members.Concat(binit.EnemyMembersEscort); - void checkNoAircraft(int id, int[] eqs) + void CheckNoAircraft(int id, int[] eqs) { if (id <= 0 || this[id].Aircraft != null) @@ -1139,12 +1142,12 @@ void checkNoAircraft(int id, int[] eqs) } for (int i = 0; i < binit.EnemyMembers.Length; i++) - checkNoAircraft(binit.EnemyMembers[i], binit.EnemySlots[i]); + CheckNoAircraft(binit.EnemyMembers[i], binit.EnemySlots[i]); if (battleDay.IsEnemyCombined) { for (int i = 0; i < binit.EnemyMembersEscort.Length; i++) - checkNoAircraft(binit.EnemyMembersEscort[i], binit.EnemySlotsEscort[i]); + CheckNoAircraft(binit.EnemyMembersEscort[i], binit.EnemySlotsEscort[i]); } @@ -1173,7 +1176,7 @@ void checkNoAircraft(int id, int[] eqs) } - void estimate(int actualAircraftCount, Func isAircraft) + void Estimate(int actualAircraftCount, Func isAircraft) { if (unknownShipEquipment.Select(id => db.MasterEquipments[id]).Count(isAircraft) != 1) return; @@ -1215,22 +1218,21 @@ int getAircraftCount(int shipID, int[] equipmentIDs, int[] aircraft) } } - - if (battleDay.BaseAirAttack?.IsAvailable ?? false) + if (battleDay is IBaseAirAttack { BaseAirAttack: { } baseAirAttack }) { - var firstUnit = battleDay.BaseAirAttack.AirAttackUnits.FirstOrDefault(); + var firstUnit = baseAirAttack.Units.FirstOrDefault(); if (!firstUnit?.IsStage1Available ?? false) return; - estimate(firstUnit.AircraftTotalStage1Enemy, eq => eq?.IsAircraft ?? false); + Estimate(firstUnit.AircraftTotalStage1Enemy, eq => eq?.IsAircraft ?? false); } - else if (battleDay.AirBattle?.IsStage1Available ?? false) + else if (battleDay is IAirBattle { AirBattle: { } airBattle }) { - estimate(battleDay.AirBattle.AircraftTotalStage1Enemy, eq => eq?.IsCombatAircraft ?? false); + Estimate(airBattle.AircraftTotalStage1Enemy, eq => eq?.IsCombatAircraft ?? false); } - else if (battleDay is BattleBaseAirRaid battleAirRaid && (battleAirRaid.BaseAirRaid?.IsStage1Available ?? false)) + else if (battleDay is BattleBaseAirRaid battleAirRaid && (battleAirRaid.BaseAirRaid is not null)) { - estimate(battleAirRaid.BaseAirRaid.AircraftTotalStage1Enemy, eq => eq?.IsCombatAircraft ?? false); + Estimate(battleAirRaid.BaseAirRaid.AircraftTotalStage1Enemy, eq => eq?.IsCombatAircraft ?? false); } } diff --git a/ElectronicObserver/Services/ToolService.cs b/ElectronicObserver/Services/ToolService.cs index b77efb99f..63dc09dbd 100644 --- a/ElectronicObserver/Services/ToolService.cs +++ b/ElectronicObserver/Services/ToolService.cs @@ -441,7 +441,7 @@ private static string GetSmokerCsvLine(SortieDetailViewModel sortieDetail, Phase phaseTitle, attackDisplay.AttackKind, attackDisplay.WaveIndex.ToString(), - attackDisplay.AttackerName, + attackDisplay.AttackerDisplay, (attackDisplay.DefenderIndex.Index + 1).ToString(), attackDisplay.Defender.Name, attackDisplay.Defender.Level.ToString(), diff --git a/ElectronicObserver/Data/Battle/Detail/BattleDetailDescriptor.cs b/ElectronicObserver/Window/Dialog/BattleDetail/BattleDetailDescriptor.cs similarity index 52% rename from ElectronicObserver/Data/Battle/Detail/BattleDetailDescriptor.cs rename to ElectronicObserver/Window/Dialog/BattleDetail/BattleDetailDescriptor.cs index e2493ccae..5a9f93b53 100644 --- a/ElectronicObserver/Data/Battle/Detail/BattleDetailDescriptor.cs +++ b/ElectronicObserver/Window/Dialog/BattleDetail/BattleDetailDescriptor.cs @@ -1,21 +1,27 @@ using System; +using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Text; using ElectronicObserver.Core.Types; using ElectronicObserver.Core.Types.AntiAir; -using ElectronicObserver.Data.Battle.Phase; +using ElectronicObserver.Data; +using ElectronicObserver.Data.Battle; using ElectronicObserver.Resource.Record; using ElectronicObserver.Utility.Data; +using ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle; +using ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle.Phase; +using ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Node; using ElectronicObserver.Window.Wpf; -namespace ElectronicObserver.Data.Battle.Detail; +namespace ElectronicObserver.Window.Dialog.BattleDetail; public static class BattleDetailDescriptor { - + [System.Diagnostics.CodeAnalysis.SuppressMessage("Critical Code Smell", "S3776:Cognitive Complexity of methods should not be too high", Justification = "todo")] public static string GetBattleDetail(BattleManager bm) { - var sb = new StringBuilder(); + StringBuilder sb = new(); if (bm.IsPractice) { @@ -24,15 +30,17 @@ public static string GetBattleDetail(BattleManager bm) } else { + Debug.Assert(bm.Compass is not null); + sb.AppendFormat("{0} ({1}-{2})", bm.Compass.MapInfo.NameEN, bm.Compass.MapAreaID, bm.Compass.MapInfoID); if (bm.Compass.MapInfo.EventDifficulty > 0) sb.AppendFormat(" [{0}]", Constants.GetDifficulty(bm.Compass.MapInfo.EventDifficulty)); - sb.Append(ConstantsRes.BattleDetail_Node).Append(bm.Compass.CellId.ToString()); + sb.Append(ConstantsRes.BattleDetail_Node).Append(bm.Compass.CellId); if (bm.Compass.EventID == 5) sb.Append(ConstantsRes.BattleDetail_Boss); sb.AppendLine(); - var mapinfo = bm.Compass.MapInfo; + IMapInfoData mapinfo = bm.Compass.MapInfo; if (!mapinfo.IsCleared) { if (mapinfo.RequiredDefeatedCount != -1) @@ -59,15 +67,17 @@ public static string GetBattleDetail(BattleManager bm) { foreach (BattleBaseAirRaid baseAirRaid in bm.HeavyBaseAirRaids) { - sb.AppendFormat("◆ {0} ◆\r\n", baseAirRaid.BattleName) + sb.AppendFormat("◆ {0} ◆\r\n", baseAirRaid.Title) .AppendLine(GetBattleDetail(baseAirRaid)); } } else { - sb.AppendFormat("◆ {0} ◆\r\n", bm.FirstBattle.BattleName).AppendLine(GetBattleDetail(bm.FirstBattle)); + Debug.Assert(bm.FirstBattle is not null); + + sb.AppendFormat("◆ {0} ◆\r\n", bm.FirstBattle.Title).AppendLine(GetBattleDetail(bm.FirstBattle)); if (bm.SecondBattle != null) - sb.AppendFormat("◆ {0} ◆\r\n", bm.SecondBattle.BattleName).AppendLine(GetBattleDetail(bm.SecondBattle)); + sb.AppendFormat("◆ {0} ◆\r\n", bm.SecondBattle.Title).AppendLine(GetBattleDetail(bm.SecondBattle)); } @@ -79,25 +89,24 @@ public static string GetBattleDetail(BattleManager bm) return sb.ToString(); } - + [System.Diagnostics.CodeAnalysis.SuppressMessage("Critical Code Smell", "S3776:Cognitive Complexity of methods should not be too high", Justification = "todo")] public static string GetBattleDetail(BattleData battle) { - - var sbmaster = new StringBuilder(); + StringBuilder sbmaster = new(); bool isBaseAirRaid = battle.IsBaseAirRaid; - - foreach (var phase in battle.GetPhases()) + foreach (PhaseBase phase in battle.Phases) { - - var sb = new StringBuilder(); + StringBuilder sb = new(); switch (phase) { case PhaseBaseAirRaid p: sb.AppendLine(ConstantsRes.BattleDetail_AirAttackUnits); - sb.Append(" ").AppendLine(string.Join(", ", p.Squadrons.Where(sq => sq.EquipmentInstance != null).Select(sq => sq.ToString()).DefaultIfEmpty(BattleRes.Empty))); + sb.Append(' ').AppendLine(string.Join(", ", + p.Squadrons.Where(sq => sq.Equipment != null).Select(sq => sq.ToString()) + .DefaultIfEmpty(BattleRes.Empty))); GetBattleDetailPhaseAirBattle(sb, p); @@ -111,12 +120,13 @@ public static string GetBattleDetail(BattleData battle) case PhaseBaseAirAttack p: - foreach (var a in p.AirAttackUnits) + foreach (PhaseBaseAirAttackUnit a in p.Units) { - sb.AppendFormat(ConstantsRes.BattleDetail_AirAttackWave + "\r\n", a.AirAttackIndex + 1); + sb.AppendFormat(ConstantsRes.BattleDetail_AirAttackWave + "\r\n", a.WaveIndex + 1); sb.AppendLine(ConstantsRes.BattleDetail_AirAttackUnits); - sb.Append(" ").AppendLine(string.Join(", ", a.Squadrons.Where(sq => sq.EquipmentInstance != null).Select(sq => sq.ToString()))); + sb.Append(' ').AppendLine(string.Join(", ", + a.Squadrons.Where(sq => sq.Equipment != null).Select(sq => sq.ToString()))); GetBattleDetailPhaseAirBattle(sb, a); sb.Append(a.GetBattleDetail()); @@ -131,12 +141,13 @@ public static string GetBattleDetail(BattleData battle) case PhaseJetBaseAirAttack p: - foreach (var a in p.AirAttackUnits) + foreach (PhaseBaseAirAttackUnit a in p.Units) { - sb.AppendFormat(ConstantsRes.BattleDetail_AirAttackWave + "\r\n", a.AirAttackIndex + 1); + sb.AppendFormat(ConstantsRes.BattleDetail_AirAttackWave + "\r\n", a.WaveIndex + 1); sb.AppendLine(ConstantsRes.BattleDetail_AirAttackUnits); - sb.Append(" ").AppendLine(string.Join(", ", a.Squadrons.Where(sq => sq.EquipmentInstance != null).Select(sq => sq.ToString()))); + sb.Append(' ').AppendLine(string.Join(", ", + a.Squadrons.Where(sq => sq.Equipment != null).Select(sq => sq.ToString()))); GetBattleDetailPhaseAirBattle(sb, a); sb.Append(a.GetBattleDetail()); @@ -145,25 +156,26 @@ public static string GetBattleDetail(BattleData battle) break; case PhaseInitial p: + Debug.Assert(p.FleetsBeforePhase is not null); - - if (p.FriendFleetEscort != null) + if (p.FleetsBeforePhase.EscortFleet != null) sb.Append(ConstantsRes.BattleDetail_FriendMainFleet); else sb.Append(ConstantsRes.BattleDetail_FriendFleet); - void appendFleetInfo(FleetData fleet) + void AppendFleetInfo(IFleetData fleet) { sb.Append($" {BattleRes.AirSuperiority} "); - sb.Append(GetRangeString(Calculator.GetAirSuperiority(fleet, false), Calculator.GetAirSuperiority(fleet, true))); + sb.Append(GetRangeString(Calculator.GetAirSuperiority(fleet), + Calculator.GetAirSuperiority(fleet, true))); - double truncate2(double value) => Math.Floor(value * 100) / 100; + static double Truncate2(double value) => Math.Floor(value * 100) / 100; sb.AppendFormat(BattleRes.Los, - truncate2(Calculator.GetSearchingAbility_New33(fleet, 1)), - truncate2(Calculator.GetSearchingAbility_New33(fleet, 2)), - truncate2(Calculator.GetSearchingAbility_New33(fleet, 3)), - truncate2(Calculator.GetSearchingAbility_New33(fleet, 4))); + Truncate2(Calculator.GetSearchingAbility_New33(fleet, 1)), + Truncate2(Calculator.GetSearchingAbility_New33(fleet, 2)), + Truncate2(Calculator.GetSearchingAbility_New33(fleet, 3)), + Truncate2(Calculator.GetSearchingAbility_New33(fleet, 4))); } if (isBaseAirRaid) @@ -173,33 +185,38 @@ void appendFleetInfo(FleetData fleet) } else { - appendFleetInfo(p.FriendFleet); + AppendFleetInfo(p.FleetsBeforePhase.Fleet); sb.AppendLine(); - OutputFriendData(sb, p.FriendFleet, p.FriendInitialHPs, p.FriendMaxHPs); + OutputFriendData(sb, p.FleetsBeforePhase.Fleet, p.FriendInitialHPs, p.FriendMaxHPs); } - if (p.FriendFleetEscort != null) + if (p.FleetsBeforePhase.EscortFleet != null) { + Debug.Assert(p.FriendInitialHPsEscort is not null); + Debug.Assert(p.FriendMaxHPsEscort is not null); + sb.AppendLine(); sb.Append(ConstantsRes.BattleDetail_FriendEscortFleet); - appendFleetInfo(p.FriendFleetEscort); + AppendFleetInfo(p.FleetsBeforePhase.EscortFleet); sb.AppendLine(); - OutputFriendData(sb, p.FriendFleetEscort, p.FriendInitialHPsEscort, p.FriendMaxHPsEscort); + OutputFriendData(sb, p.FleetsBeforePhase.EscortFleet, p.FriendInitialHPsEscort, + p.FriendMaxHPsEscort); } sb.AppendLine(); - void appendEnemyFleetInfo(int[] members) + void AppendEnemyFleetInfo(int[] members) { int air = 0; int airbase = 0; bool indeterminate = false; for (int i = 0; i < members.Length; i++) { - var param = RecordManager.Instance.ShipParameter[members[i]]; + ShipParameterRecord.ShipParameterElement? param = + RecordManager.Instance.ShipParameter[members[i]]; if (param == null) continue; if (param.DefaultSlot == null || param.Aircraft == null) @@ -212,9 +229,11 @@ void appendEnemyFleetInfo(int[] members) { air += Calculator.GetAirSuperiority(param.DefaultSlot[s], param.Aircraft[s]); if (KCDatabase.Instance.MasterEquipments[param.DefaultSlot[s]]?.IsAircraft ?? false) - airbase += Calculator.GetAirSuperiority(param.DefaultSlot[s], param.Aircraft[s], 0, 0, AirBaseActionKind.Mission); + airbase += Calculator.GetAirSuperiority(param.DefaultSlot[s], param.Aircraft[s], 0, + 0, AirBaseActionKind.Mission); } } + sb.AppendFormat(BattleRes.AirBaseAirPower, air, airbase); if (indeterminate) sb.Append(BattleRes.ToBeDetermined); @@ -225,47 +244,52 @@ void appendEnemyFleetInfo(int[] members) else sb.Append(ConstantsRes.BattleDetail_EnemyFleet); - appendEnemyFleetInfo(p.EnemyMembers); + AppendEnemyFleetInfo(p.EnemyMembers); if (p.IsBossDamaged) sb.Append(BattleRes.BossDebuffed); sb.AppendLine(); - OutputEnemyData(sb, p.EnemyMembersInstance, p.EnemyLevels, p.EnemyInitialHPs, p.EnemyMaxHPs, p.EnemySlotsInstance, p.EnemyParameters); + OutputEnemyData(sb, p.EnemyMembersInstance, p.EnemyLevels, p.EnemyInitialHPs, p.EnemyMaxHPs, + p.EnemySlotsInstance, p.EnemyParameters); - if (p.EnemyMembersEscort != null) + if (p.IsEnemyCombined) { sb.AppendLine(); sb.AppendLine(ConstantsRes.BattleDetail_EnemyEscortFleet); - appendEnemyFleetInfo(p.EnemyMembersEscort); + AppendEnemyFleetInfo(p.EnemyMembersEscort); sb.AppendLine(); - OutputEnemyData(sb, p.EnemyMembersEscortInstance, p.EnemyLevelsEscort, p.EnemyInitialHPsEscort, p.EnemyMaxHPsEscort, p.EnemySlotsEscortInstance, p.EnemyParametersEscort); + OutputEnemyData(sb, p.EnemyMembersEscortInstance, p.EnemyLevelsEscort, p.EnemyInitialHPsEscort, + p.EnemyMaxHPsEscort, p.EnemySlotsEscortInstance, p.EnemyParametersEscort); } sb.AppendLine(); - if (battle.GetPhases().Where(ph => ph is PhaseBaseAirAttack || ph is PhaseBaseAirRaid).Any(ph => ph != null && ph.IsAvailable)) + if (battle.Phases.Any(ph => ph is PhaseBaseAirAttack or PhaseBaseAirRaid)) { + Debug.Assert(KCDatabase.Instance.Battle.Compass is not null); + sb.AppendLine(ConstantsRes.BattleDetail_AirBase); - GetBattleDetailBaseAirCorps(sb, KCDatabase.Instance.Battle.Compass.MapAreaID); // :( + GetBattleDetailBaseAirCorps(sb, KCDatabase.Instance.Battle.Compass.MapAreaID); // :( sb.AppendLine(); } - if (p.RationIndexes.Length > 0) + if (p.ApiCombatRation?.Count > 0) { sb.AppendLine($"〈{BattleRes.CombatRation}〉"); - foreach (var index in p.RationIndexes) + foreach (int index in p.ApiCombatRation) { - var ship = p.GetFriendShip(index); + IShipData? ship = p.FleetsBeforePhase.GetShip(new(index, FleetFlag.Player)); if (ship != null) { sb.AppendFormat(" {0} #{1}\r\n", ship.NameWithLevel, index + 1); } } + sb.AppendLine(); } @@ -274,12 +298,13 @@ void appendEnemyFleetInfo(int[] members) case PhaseNightInitial p: { - var eq = KCDatabase.Instance.MasterEquipments[p.TouchAircraftFriend]; + IEquipmentDataMaster? eq = p.TouchAircraftFriend; if (eq != null) { sb.Append(ConstantsRes.BattleDetail_FriendlyNightContact).AppendLine(eq.NameEN); } - eq = KCDatabase.Instance.MasterEquipments[p.TouchAircraftEnemy]; + + eq = p.TouchAircraftEnemy; if (eq != null) { sb.Append(ConstantsRes.BattleDetail_EnemyNightContact).AppendLine(eq.NameEN); @@ -287,25 +312,29 @@ void appendEnemyFleetInfo(int[] members) } { - int searchlightIndex = p.SearchlightIndexFriend; - if (searchlightIndex != -1) + if (p.SearchlightFriend is not null) { - sb.AppendFormat(ConstantsRes.BattleDetail_FriendlySearchlight + "\r\n", p.FriendFleet.MembersInstance[searchlightIndex].Name, searchlightIndex + 1); + sb.AppendFormat(ConstantsRes.BattleDetail_FriendlySearchlight + "\r\n", + p.SearchlightFriend.Name, p.SearchlightIndexFriend + 1); } - searchlightIndex = p.SearchlightIndexEnemy; - if (searchlightIndex != -1) + + if (p.SearchlightEnemy is not null) { - sb.AppendFormat(ConstantsRes.BattleDetail_EnemySearchlight + "\r\n", p.EnemyMembersInstance[searchlightIndex].NameWithClass, searchlightIndex + 1); + sb.AppendFormat(ConstantsRes.BattleDetail_EnemySearchlight + "\r\n", + p.SearchlightEnemy.MasterShip.NameWithClass, p.SearchlightIndexEnemy + 1); } } - if (p.FlareIndexFriend != -1) + if (p.FlareFriend is not null) { - sb.AppendFormat(ConstantsRes.BattleDetail_FriendlyStarshell + "\r\n", p.FlareFriendInstance.NameWithLevel, p.FlareIndexFriend + 1); + sb.AppendFormat(ConstantsRes.BattleDetail_FriendlyStarshell + "\r\n", + p.FlareFriend.NameWithLevel, p.FlareIndexFriend + 1); } - if (p.FlareIndexEnemy != -1) + + if (p.FlareEnemy is not null) { - sb.AppendFormat(ConstantsRes.BattleDetail_EnemyStarshell + "\r\n", p.FlareEnemyInstance.NameWithClass, p.FlareIndexEnemy + 1); + sb.AppendFormat(ConstantsRes.BattleDetail_EnemyStarshell + "\r\n", + p.FlareEnemy.MasterShip.NameWithClass, p.FlareIndexEnemy + 1); } sb.AppendLine(); @@ -313,11 +342,13 @@ void appendEnemyFleetInfo(int[] members) case PhaseSearching p: - sb.Append($"{BattleRes.Formation}: ").Append(Constants.GetFormation(p.FormationFriend)); - sb.Append($" / {BattleRes.EnemyFormation}: ").AppendLine(Constants.GetFormation(p.FormationEnemy)); - sb.Append($"{BattleRes.Engagement}: ").AppendLine(Constants.GetEngagementForm(p.EngagementForm)); - sb.Append($"{BattleRes.Contact}: ").Append(Constants.GetSearchingResult(p.SearchingFriend)); - sb.Append($" / {BattleRes.EnemyContact}: ").AppendLine(Constants.GetSearchingResult(p.SearchingEnemy)); + sb.Append($"{BattleRes.Formation}: ").Append(Constants.GetFormation(p.PlayerFormationType)); + sb.Append($" / {BattleRes.EnemyFormation}: ") + .AppendLine(Constants.GetFormation(p.EnemyFormationType)); + sb.Append($"{BattleRes.Engagement}: ").AppendLine(Constants.GetEngagementForm(p.EngagementType)); + sb.Append($"{BattleRes.Contact}: ").Append(Constants.GetSearchingResult(p.PlayerDetectionType)); + sb.Append($" / {BattleRes.EnemyContact}: ") + .AppendLine(Constants.GetSearchingResult(p.EnemyDetectionType)); if (p.SmokeCount > 0) { @@ -329,53 +360,46 @@ void appendEnemyFleetInfo(int[] members) break; case PhaseSupport p: - if (p.IsAvailable) + if (p.SupportFleet is not null) { sb.AppendLine($"〈{BattleRes.SupportFleet}〉"); OutputSupportData(sb, p.SupportFleet); sb.AppendLine(); } + break; case PhaseFriendlySupportInfo p: - if (p.IsAvailable) - { - OutputFriendlySupportData(sb, p); - sb.AppendLine(); - } + OutputFriendlySupportData(sb, p); + sb.AppendLine(); break; case PhaseFriendlyShelling p: - if (p.IsAvailable) + if (p.SearchlightFriend is not null) { - { - int searchlightIndex = p.SearchlightIndexFriend; - if (searchlightIndex != -1) - { - sb.AppendFormat(ConstantsRes.BattleDetail_FriendlySearchlight + "\r\n", p.SearchlightFriendInstance.NameWithClass, searchlightIndex + 1); - } - searchlightIndex = p.SearchlightIndexEnemy; - if (searchlightIndex != -1) - { - sb.AppendFormat(ConstantsRes.BattleDetail_EnemySearchlight + "\r\n", p.SearchlightEnemyInstance.NameWithClass, searchlightIndex + 1); - } - } + sb.AppendFormat(ConstantsRes.BattleDetail_FriendlySearchlight + "\r\n", + p.SearchlightFriend.MasterShip.NameWithClass, p.SearchlightIndexFriend + 1); + } - { - int flareIndex = p.FlareIndexFriend; - if (flareIndex != -1) - { - sb.AppendFormat(ConstantsRes.BattleDetail_FriendlyStarshell + "\r\n", p.FlareFriendInstance.NameWithClass, flareIndex + 1); - } - flareIndex = p.FlareIndexEnemy; - if (flareIndex != -1) - { - sb.AppendFormat(ConstantsRes.BattleDetail_EnemyStarshell + "\r\n", p.FlareEnemyInstance.NameWithClass, flareIndex + 1); - } - } + if (p.SearchlightEnemy is not null) + { + sb.AppendFormat(ConstantsRes.BattleDetail_EnemySearchlight + "\r\n", + p.SearchlightEnemy.MasterShip.NameWithClass, p.SearchlightIndexEnemy + 1); + } - sb.AppendLine(); + if (p.FlareFriend is not null) + { + sb.AppendFormat(ConstantsRes.BattleDetail_FriendlyStarshell + "\r\n", + p.FlareFriend.MasterShip.NameWithClass, p.FlareIndexFriend + 1); + } + + if (p.FlareEnemy is not null) + { + sb.AppendFormat(ConstantsRes.BattleDetail_EnemyStarshell + "\r\n", + p.FlareEnemy.MasterShip.NameWithClass, p.FlareIndexEnemy + 1); } + + sb.AppendLine(); break; case PhaseFriendlyAirBattle p: @@ -383,11 +407,13 @@ void appendEnemyFleetInfo(int[] members) GetBattleDetailPhaseAirBattle(sb, p); break; - } + case AttackPhaseBase attackPhase: + + sb.AppendLine(attackPhase.GetBattleDetail()); - if (!(phase is PhaseBaseAirAttack || phase is PhaseJetBaseAirAttack)) // 通常出力と重複するため - sb.Append(phase.GetBattleDetail()); + break; + } if (sb.Length > 0) { @@ -399,10 +425,11 @@ void appendEnemyFleetInfo(int[] members) { sbmaster.AppendLine(ConstantsRes.BattleDetail_BattleEnd); - var friend = battle.Initial.FriendFleet; - var friendescort = battle.Initial.FriendFleetEscort; - var enemy = battle.Initial.EnemyMembersInstance; - var enemyescort = battle.Initial.EnemyMembersEscortInstance; + IFleetData friend = battle.FleetsAfterBattle.Fleet; + IFleetData? friendescort = battle.FleetsAfterBattle.EscortFleet; + List enemy = battle.Initial.EnemyMembersInstance; + List? enemyescort = battle.Initial.EnemyMembersEscortInstance; + List resultHps = battle.ResultHPs.ToList(); if (friendescort != null) sbmaster.AppendLine(ConstantsRes.BattleDetail_FriendMainFleet); @@ -418,35 +445,39 @@ void appendEnemyFleetInfo(int[] members) continue; OutputResultData(sbmaster, i, string.Format(BattleRes.Base, i + 1), - battle.Initial.FriendInitialHPs[i], battle.ResultHPs[i], battle.Initial.FriendMaxHPs[i]); + battle.Initial.FriendInitialHPs[i], resultHps[i], battle.Initial.FriendMaxHPs[i]); } } else { - for (int i = 0; i < friend.Members.Count(); i++) + Debug.Assert(friend.Members is not null); + + for (int i = 0; i < friend.Members.Count; i++) { - var ship = friend.MembersInstance[i]; - if (ship == null) - continue; + if (friend.MembersInstance[i] is not IShipData ship) continue; OutputResultData(sbmaster, i, ship.Name, - battle.Initial.FriendInitialHPs[i], battle.ResultHPs[i], battle.Initial.FriendMaxHPs[i]); + battle.Initial.FriendInitialHPs[i], resultHps[i], battle.Initial.FriendMaxHPs[i]); } } if (friendescort != null) { + Debug.Assert(friendescort.Members is not null); + Debug.Assert(battle.Initial.FriendInitialHPsEscort is not null); + Debug.Assert(battle.Initial.FriendMaxHPsEscort is not null); + sbmaster.AppendLine().AppendLine(ConstantsRes.BattleDetail_FriendEscortFleet); - for (int i = 0; i < friendescort.Members.Count(); i++) + for (int i = 0; i < friendescort.Members.Count; i++) { var ship = friendescort.MembersInstance[i]; if (ship == null) continue; OutputResultData(sbmaster, i + 6, ship.Name, - battle.Initial.FriendInitialHPsEscort[i], battle.ResultHPs[i + 6], battle.Initial.FriendMaxHPsEscort[i]); + battle.Initial.FriendInitialHPsEscort[i], resultHps[i + 6], battle.Initial.FriendMaxHPsEscort[i]); } } @@ -458,29 +489,30 @@ void appendEnemyFleetInfo(int[] members) else sbmaster.AppendLine(ConstantsRes.BattleDetail_EnemyFleet); - for (int i = 0; i < enemy.Length; i++) + for (int i = 0; i < enemy.Count; i++) { - var ship = enemy[i]; + IShipData? ship = enemy[i]; if (ship == null) continue; OutputResultData(sbmaster, i, - ship.NameWithClass, - battle.Initial.EnemyInitialHPs[i], battle.ResultHPs[i + 12], battle.Initial.EnemyMaxHPs[i]); + ship.MasterShip.NameWithClass, + battle.Initial.EnemyInitialHPs[i], resultHps[i + 12], battle.Initial.EnemyMaxHPs[i]); } if (enemyescort != null) { + Debug.Assert(battle.Initial.EnemyInitialHPsEscort is not null); + Debug.Assert(battle.Initial.EnemyMaxHPsEscort is not null); + sbmaster.AppendLine().AppendLine(ConstantsRes.BattleDetail_EnemyEscortFleet); - for (int i = 0; i < enemyescort.Length; i++) + for (int i = 0; i < enemyescort.Count; i++) { - var ship = enemyescort[i]; - if (ship == null) - continue; + if (enemyescort[i] is not IShipData ship) continue; - OutputResultData(sbmaster, i + 6, ship.NameWithClass, - battle.Initial.EnemyInitialHPsEscort[i], battle.ResultHPs[i + 18], battle.Initial.EnemyMaxHPsEscort[i]); + OutputResultData(sbmaster, i + 6, ship.MasterShip.NameWithClass, + battle.Initial.EnemyInitialHPsEscort[i], resultHps[i + 18], battle.Initial.EnemyMaxHPsEscort[i]); } } @@ -494,14 +526,16 @@ void appendEnemyFleetInfo(int[] members) private static void GetBattleDetailBaseAirCorps(StringBuilder sb, int mapAreaID) { - foreach (var corps in KCDatabase.Instance.BaseAirCorps.Values.Where(corps => corps.MapAreaID == mapAreaID)) + foreach (BaseAirCorpsData corps in KCDatabase.Instance.BaseAirCorps.Values.Where(corps => corps.MapAreaID == mapAreaID)) { sb.AppendFormat("{0} [{1}] " + BattleRes.AirSuperiority + " {2}\r\n {3}\r\n", corps.Name, Constants.GetBaseAirCorpsActionKind(corps.ActionKind), - GetRangeString(Calculator.GetAirSuperiority(corps, false), Calculator.GetAirSuperiority(corps, true)), + GetRangeString(Calculator.GetAirSuperiority(corps), Calculator.GetAirSuperiority(corps, true)), string.Join(", ", corps.Squadrons.Values - .Where(sq => sq.State == 1 && sq.EquipmentInstance != null) - .Select(sq => sq.EquipmentInstance.NameWithLevel))); + .Where(sq => sq.State == 1) + .Select(sq => sq.EquipmentInstance) + .OfType() + .Select(eq => eq.NameWithLevel))); } } @@ -510,14 +544,14 @@ private static void GetBattleDetailPhaseAirBattle(StringBuilder sb, PhaseAirBatt if (p.IsStage1Available) { - sb.Append("Stage 1: ").AppendLine(Constants.GetAirSuperiority(p.AirSuperiority)); + sb.Append("Stage 1: ").AppendLine(Constants.GetAirSuperiority(p.AirState)); sb.AppendFormat($" {BattleRes.Friendly}: -{{0}}/{{1}}\r\n {BattleRes.Enemy}: -{{2}}/{{3}}\r\n", p.AircraftLostStage1Friend, p.AircraftTotalStage1Friend, p.AircraftLostStage1Enemy, p.AircraftTotalStage1Enemy); - if (p.TouchAircraftFriend > 0) - sb.AppendFormat($" {BattleRes.Contact}: {{0}}\r\n", KCDatabase.Instance.MasterEquipments[p.TouchAircraftFriend].NameEN); - if (p.TouchAircraftEnemy > 0) - sb.AppendFormat($" {BattleRes.EnemyContact}: {{0}}\r\n", KCDatabase.Instance.MasterEquipments[p.TouchAircraftEnemy].NameEN); + if (p.TouchAircraftFriend is not null) + sb.AppendFormat($" {BattleRes.Contact}: {{0}}\r\n", p.TouchAircraftFriend); + if (p.TouchAircraftEnemy is not null) + sb.AppendFormat($" {BattleRes.EnemyContact}: {{0}}\r\n", p.TouchAircraftEnemy); } if (p.IsStage2Available) { @@ -539,13 +573,46 @@ private static void GetBattleDetailPhaseAirBattle(StringBuilder sb, PhaseAirBatt sb.AppendLine(); } + private static void GetBattleDetailPhaseAirBattle(StringBuilder sb, PhaseBaseAirRaid p) + { - private static void OutputFriendData(StringBuilder sb, FleetData fleet, int[] initialHPs, int[] maxHPs) + if (p.IsStage1Available) + { + sb.Append("Stage 1: ").AppendLine(Constants.GetAirSuperiority(p.AirState)); + sb.AppendFormat($" {BattleRes.Friendly}: -{{0}}/{{1}}\r\n {BattleRes.Enemy}: -{{2}}/{{3}}\r\n", + p.AircraftLostStage1Friend, p.AircraftTotalStage1Friend, + p.AircraftLostStage1Enemy, p.AircraftTotalStage1Enemy); + if (p.TouchAircraftFriend is not null) + sb.AppendFormat($" {BattleRes.Contact}: {{0}}\r\n", p.TouchAircraftFriend); + if (p.TouchAircraftEnemy is not null) + sb.AppendFormat($" {BattleRes.EnemyContact}: {{0}}\r\n", p.TouchAircraftEnemy); + } + if (p.IsStage2Available) + { + sb.Append("Stage 2: "); + if (p.IsAACutinAvailable) + { + sb.AppendFormat(BattleRes.AaciType, + p.AACutInShipName, + AntiAirCutIn.FromId(p.AACutInKind).EquipmentConditionsSingleLineDisplay(), + p.AACutInKind); + } + sb.AppendLine(); + sb.AppendFormat($" {BattleRes.Friendly}: -{{0}}/{{1}}\r\n {BattleRes.Enemy}: -{{2}}/{{3}}\r\n", + p.AircraftLostStage2Friend, p.AircraftTotalStage2Friend, + p.AircraftLostStage2Enemy, p.AircraftTotalStage2Enemy); + } + + if (p.IsStage1Available || p.IsStage2Available) + sb.AppendLine(); + } + + private static void OutputFriendData(StringBuilder sb, IFleetData fleet, List initialHPs, List maxHPs) { for (int i = 0; i < fleet.MembersInstance.Count; i++) { - var ship = fleet.MembersInstance[i]; + IShipData? ship = fleet.MembersInstance[i]; if (ship == null) continue; @@ -562,18 +629,18 @@ private static void OutputFriendData(StringBuilder sb, FleetData fleet, int[] in ship.FirepowerBase, ship.TorpedoBase, ship.AABase, ship.ArmorBase, fleet.EscapedShipList.Contains(ship.MasterID) ? $" ({BattleRes.Escaped})" : ""); - sb.Append(" "); + sb.Append(' '); sb.AppendLine(string.Join(", ", ship.AllSlotInstance.Zip( - ship.ExpansionSlot > 0 ? ship.Aircraft.Concat(new[] { 0 }) : ship.Aircraft, + ship.ExpansionSlot > 0 ? ship.Aircraft.Concat([0]) : ship.Aircraft, (eq, aircraft) => eq == null ? null : ((eq.MasterEquipment.IsAircraft ? $"[{aircraft}] " : "") + eq.NameWithLevel) ).Where(str => str != null))); } } - private static void OutputFriendBase(StringBuilder sb, int[] initialHPs, int[] maxHPs) + private static void OutputFriendBase(StringBuilder sb, List initialHPs, List maxHPs) { - for (int i = 0; i < initialHPs.Length; i++) + for (int i = 0; i < initialHPs.Count; i++) { if (maxHPs[i] <= 0) continue; @@ -586,12 +653,11 @@ private static void OutputFriendBase(StringBuilder sb, int[] initialHPs, int[] m } - public static void OutputSupportData(StringBuilder sb, FleetData fleet) + private static void OutputSupportData(StringBuilder sb, IFleetData fleet) { - for (int i = 0; i < fleet.MembersInstance.Count; i++) { - var ship = fleet.MembersInstance[i]; + IShipData? ship = fleet.MembersInstance[i]; if (ship == null) continue; @@ -606,7 +672,7 @@ public static void OutputSupportData(StringBuilder sb, FleetData fleet) ship.MasterShip.ShipTypeName, ship.NameWithLevel, ship.FirepowerBase, ship.TorpedoBase, ship.AABase, ship.ArmorBase); - sb.Append(" "); + sb.Append(' '); sb.AppendLine(string.Join(", ", ship.AllSlotInstance.Where(eq => eq != null))); } @@ -614,10 +680,11 @@ public static void OutputSupportData(StringBuilder sb, FleetData fleet) private static void OutputFriendlySupportData(StringBuilder sb, PhaseFriendlySupportInfo p) { + Debug.Assert(p.FleetsBeforePhase?.FriendFleet is not null); - for (int i = 0; i < p.FriendlyMembersInstance.Length; i++) + for (int i = 0; i < p.FleetsBeforePhase.FriendFleet.MembersInstance.Count; i++) { - var ship = p.FriendlyMembersInstance[i]; + IShipData? ship = p.FleetsBeforePhase.FriendFleet.MembersInstance[i]; if (ship == null) continue; @@ -631,31 +698,28 @@ private static void OutputFriendlySupportData(StringBuilder sb, PhaseFriendlySup $"{GeneralRes.Armor} {{9}}" + $"\r\n", i + 1, - ship.ShipTypeName, p.FriendlyMembersInstance[i].NameWithClass, p.FriendlyLevels[i], - p.FriendlyInitialHPs[i], p.FriendlyMaxHPs[i], - p.FriendlyParameters[i][0], p.FriendlyParameters[i][1], p.FriendlyParameters[i][2], p.FriendlyParameters[i][3]); - - sb.Append(" "); - sb.AppendLine(string.Join(", ", p.FriendlySlots[i] - .Concat(new[] { p.FriendlyExpansionSlots?[i] ?? -1 }) - .Select(id => KCDatabase.Instance.MasterEquipments[id]) - .Where(eq => eq != null) - .Select(eq => eq.NameEN))); + ship.MasterShip.ShipTypeName, ship.MasterShip.NameWithClass, ship.Level, + ship.HPCurrent, ship.HPMax, + ship.FirepowerBase, ship.TorpedoBase, ship.AABase, ship.ArmorBase); + + sb.Append(' '); + sb.AppendLine(string.Join(", ", ship.AllSlotInstance + .OfType() + .Select(eq => eq.MasterEquipment.NameEN))); } } - private static void OutputEnemyData(StringBuilder sb, IShipDataMaster[] members, int[] levels, int[] initialHPs, int[] maxHPs, IEquipmentDataMaster[][] slots, int[][] parameters) + private static void OutputEnemyData(StringBuilder sb, List members, int[] levels, List initialHPs, int[] maxHPs, IEquipmentData?[][] slots, List> parameters) { - for (int i = 0; i < members.Length; i++) + for (int i = 0; i < members.Count; i++) { - if (members[i] == null) - continue; + if (members[i] is not IShipData ship) continue; sb.AppendFormat("#{0}: ID:{1} {2} {3} Lv. {4} HP: {5} / {6}", i + 1, - members[i].ShipID, - members[i].ShipTypeName, members[i].NameWithClass, + ship.ShipID, + ship.MasterShip.ShipTypeName, ship.MasterShip.NameWithClass, levels[i], initialHPs[i], maxHPs[i]); @@ -669,12 +733,11 @@ private static void OutputEnemyData(StringBuilder sb, IShipDataMaster[] members, parameters[i][0], parameters[i][1], parameters[i][2], parameters[i][3]); } - sb.AppendLine().Append(" "); + sb.AppendLine().Append(' '); sb.AppendLine(string.Join(", ", slots[i].Where(eq => eq != null))); } } - private static void OutputResultData(StringBuilder sb, int index, string name, int initialHP, int resultHP, int maxHP) { sb.AppendFormat("#{0}: {1} HP: ({2} → {3})/{4} ({5})\r\n", @@ -685,12 +748,15 @@ private static void OutputResultData(StringBuilder sb, int index, string name, i resultHP - initialHP); } - + [System.Diagnostics.CodeAnalysis.SuppressMessage("Critical Code Smell", "S3776:Cognitive Complexity of methods should not be too high", Justification = "todo")] private static string GetBattleResult(BattleManager bm) { - var result = bm.Result; + Debug.Assert(bm.Result is not null); + Debug.Assert(bm.FirstBattle is not null); - var sb = new StringBuilder(); + BattleResult result = bm.Result; + + StringBuilder sb = new(); sb.AppendLine(ConstantsRes.BattleDetail_Result); @@ -698,16 +764,25 @@ private static string GetBattleResult(BattleManager bm) if (bm.IsCombinedBattle) { - sb.AppendFormat(ConstantsRes.BattleDetail_ResultMVPMain + "\r\n", - result.MVPIndex == -1 ? "(なし)" : bm.FirstBattle.Initial.FriendFleet.MembersInstance[result.MVPIndex - 1].NameWithLevel); - sb.AppendFormat(ConstantsRes.BattleDetail_ResultMVPEscort + "\r\n", - result.MVPIndexCombined == -1 ? "(なし)" : bm.FirstBattle.Initial.FriendFleetEscort.MembersInstance[result.MVPIndexCombined - 1].NameWithLevel); + sb.AppendFormat(ConstantsRes.BattleDetail_ResultMVPMain + "\r\n", result.MvpIndex switch + { + -1 => "(なし)", + _ => bm.FirstBattle.FleetsBeforeBattle.Fleet.MembersInstance[result.MvpIndex]?.NameWithLevel, + }); + sb.AppendFormat(ConstantsRes.BattleDetail_ResultMVPEscort + "\r\n", result.MvpIndexCombined switch + { + -1 or null => "(なし)", + int index => bm.FirstBattle.FleetsBeforeBattle.EscortFleet!.MembersInstance[index]?.NameWithLevel, + }); } else { - sb.AppendFormat("MVP: {0}\r\n", - result.MVPIndex == -1 ? "(なし)" : bm.FirstBattle.Initial.FriendFleet.MembersInstance[result.MVPIndex - 1].NameWithLevel); + sb.AppendFormat("MVP: {0}\r\n", result.MvpIndex switch + { + -1 => "(なし)", + _ => bm.FirstBattle.FleetsBeforeBattle.Fleet.MembersInstance[result.MvpIndex]?.NameWithLevel, + }); } sb.AppendFormat(ConstantsRes.BattleDetail_AdmiralExp + "\r\n", result.AdmiralExp); @@ -720,22 +795,22 @@ private static string GetBattleResult(BattleManager bm) int length = sb.Length; - var ship = KCDatabase.Instance.MasterShips[result.DroppedShipID]; + IShipDataMaster? ship = KCDatabase.Instance.MasterShips[(int?)result.DroppedShipId ?? -1]; if (ship != null) { sb.AppendFormat(" {0} {1}\r\n", ship.ShipTypeName, ship.NameWithClass); } - var eq = KCDatabase.Instance.MasterEquipments[result.DroppedEquipmentID]; + IEquipmentDataMaster? eq = KCDatabase.Instance.MasterEquipments[result.DroppedEquipmentId ?? -1]; if (eq != null) { sb.AppendFormat(" {0} {1}\r\n", eq.CategoryTypeInstance.NameEN, eq.NameEN); } - var item = KCDatabase.Instance.MasterUseItems[result.DroppedItemID]; + IUseItemMaster? item = KCDatabase.Instance.MasterUseItems[result.DroppedItemId ?? -1]; if (item != null) { - sb.Append(" ").AppendLine(item.NameTranslated); + sb.Append(' ').AppendLine(item.NameTranslated); } if (length == sb.Length) @@ -747,5 +822,4 @@ private static string GetBattleResult(BattleManager bm) return sb.ToString(); } - } diff --git a/ElectronicObserver/Window/Tools/SortieRecordViewer/DataExport/DataExportHelper.cs b/ElectronicObserver/Window/Tools/SortieRecordViewer/DataExport/DataExportHelper.cs index 9dc11b6f6..a24ed2525 100644 --- a/ElectronicObserver/Window/Tools/SortieRecordViewer/DataExport/DataExportHelper.cs +++ b/ElectronicObserver/Window/Tools/SortieRecordViewer/DataExport/DataExportHelper.cs @@ -607,17 +607,17 @@ void ProcessData(IFleetData fleet, IFleetData attackerFleet, FleetFlag fleetFlag AirBaseSquadron4Aircraft = airAttackUnit.Squadrons.Skip(3).FirstOrDefault()?.AircraftCount, Stage1 = new() { - PlayerAircraftTotal = airAttackUnit.Stage1FCount, - PlayerAircraftLost = airAttackUnit.Stage1FLostcount, - EnemyAircraftTotal = airAttackUnit.Stage1ECount, - EnemyAircraftLost = airAttackUnit.Stage1ELostcount, + PlayerAircraftTotal = airAttackUnit.AircraftTotalStage1Friend, + PlayerAircraftLost = airAttackUnit.AircraftLostStage1Friend, + EnemyAircraftTotal = airAttackUnit.AircraftTotalStage1Enemy, + EnemyAircraftLost = airAttackUnit.AircraftLostStage1Enemy, }, Stage2 = new() { - PlayerAircraftTotal = airAttackUnit.Stage2FCount, - PlayerAircraftLost = airAttackUnit.Stage2FLostcount, - EnemyAircraftTotal = airAttackUnit.Stage2ECount, - EnemyAircraftLost = airAttackUnit.Stage2ELostcount, + PlayerAircraftTotal = airAttackUnit.AircraftTotalStage2Friend, + PlayerAircraftLost = airAttackUnit.AircraftLostStage2Friend, + EnemyAircraftTotal = airAttackUnit.AircraftTotalStage2Enemy, + EnemyAircraftLost = airAttackUnit.AircraftLostStage2Enemy, }, Attacker1 = MakeShip(attackerFleet.MembersWithoutEscaped?.Skip(0).FirstOrDefault()), Attacker2 = MakeShip(attackerFleet.MembersWithoutEscaped?.Skip(1).FirstOrDefault()), @@ -651,7 +651,7 @@ void ProcessData(IFleetData fleet, IFleetData attackerFleet, FleetFlag fleetFlag HitType.Critical => 1, _ => 0, }, - Damage = attackDisplay?.Damage ?? 0, + Damage = (int?)attackDisplay?.Damage ?? 0, Protected = attackDisplay?.GuardsFlagship switch { true => 1, @@ -721,10 +721,10 @@ private static List AirBaseAirDefense( EnemyFormation = Constants.GetFormation(searching.EnemyFormationType), Engagement = Constants.GetEngagementForm(searching.EngagementType), AirBaseDamage = GetAirBaseDamage(airBaseRaid.ApiLostKind), - PlayerAircraft = airBaseRaid.Stage1FCount, - PlayerAircraftLost = airBaseRaid.Stage1FLostcount, - EnemyAircraft = airBaseRaid.Stage1ECount, - EnemyAircraftLost = airBaseRaid.Stage1ELostcount, + PlayerAircraft = airBaseRaid.AircraftTotalStage1Friend, + PlayerAircraftLost = airBaseRaid.AircraftLostStage1Friend, + EnemyAircraft = airBaseRaid.AircraftTotalStage1Enemy, + EnemyAircraftLost = airBaseRaid.AircraftLostStage1Enemy, AirState = GetAirState(airBaseRaid), PlayerContact = airBaseRaid.TouchAircraftFriend ?? "なし", EnemyContact = airBaseRaid.TouchAircraftEnemy ?? "なし", @@ -798,17 +798,17 @@ private static AirBattleExportModel MakeAirBattleExport(BattleNode node, CommonData = MakeCommonData(node, IsFirstNode(sortieDetail.Nodes, node), sortieDetail, admiralLevel, airBattle, searching), Stage1 = new() { - PlayerAircraftTotal = airBattle.Stage1FCount, - PlayerAircraftLost = airBattle.Stage1FLostcount, - EnemyAircraftTotal = airBattle.Stage1ECount, - EnemyAircraftLost = airBattle.Stage1ELostcount, + PlayerAircraftTotal = airBattle.AircraftTotalStage1Friend, + PlayerAircraftLost = airBattle.AircraftLostStage1Friend, + EnemyAircraftTotal = airBattle.AircraftTotalStage1Enemy, + EnemyAircraftLost = airBattle.AircraftLostStage1Enemy, }, Stage2 = new() { - PlayerAircraftTotal = airBattle.Stage2FCount, - PlayerAircraftLost = airBattle.Stage2FLostcount, - EnemyAircraftTotal = airBattle.Stage2ECount, - EnemyAircraftLost = airBattle.Stage2ELostcount, + PlayerAircraftTotal = airBattle.AircraftTotalStage2Friend, + PlayerAircraftLost = airBattle.AircraftLostStage2Friend, + EnemyAircraftTotal = airBattle.AircraftTotalStage2Enemy, + EnemyAircraftLost = airBattle.AircraftLostStage2Enemy, }, AntiAirCutIn = new() { @@ -840,7 +840,7 @@ private static AirBattleExportModel MakeAirBattleExport(BattleNode node, HitType.Critical => 1, _ => 0, }, - Damage = attackDisplay?.Damage ?? 0, + Damage = (int?)attackDisplay?.Damage ?? 0, Protected = attackDisplay?.GuardsFlagship switch { true => 1, @@ -956,7 +956,7 @@ private static CommonDataExportModel MakeCommonData(BattleNode node, bool isFirs (true, _) => CsvExportResources.BossNode, _ => "", }, - Rank = WinRank(node.BattleResult?.WinRank), + Rank = WinRank(node.BattleResult?.Rank), EnemyFleet = node.BattleResult?.EnemyFleetName, AdmiralLevel = admiralLevel, PlayerFormation = Constants.GetFormation(searching.PlayerFormationType), diff --git a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/AirBattleData.cs b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/AirBattleData.cs index ff8045d19..4c3faeff1 100644 --- a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/AirBattleData.cs +++ b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/AirBattleData.cs @@ -1,16 +1,17 @@ using ElectronicObserver.KancolleApi.Types.Interfaces; +using ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle.Interfaces; using ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle.Phase; namespace ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle; -public abstract class AirBattleData : FirstBattleData +public abstract class AirBattleData : FirstBattleData, IBaseAirAttack, IAirBattle { protected PhaseJetBaseAirAttack? JetBaseAirAttack { get; } - protected PhaseJetAirBattle? JetAirBattle { get; } - protected PhaseBaseAirAttack? BaseAirAttack { get; } + public PhaseJetAirBattle? JetAirBattle { get; } + public PhaseBaseAirAttack? BaseAirAttack { get; } protected PhaseFriendlySupportInfo? FriendlySupportInfo { get; } protected PhaseFriendlyAirBattle? FriendlyAirBattle { get; } - protected PhaseAirBattle? AirBattle { get; } + public PhaseAirBattle? AirBattle { get; } protected AirBattleData(PhaseFactory phaseFactory, BattleFleets fleets, IAirBattleApiResponse battle, bool isMultiAirBattle = false) : base(phaseFactory, fleets, battle) diff --git a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/BattleAirBattle.cs b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/BattleAirBattle.cs index 6059a14f2..ee25a5d76 100644 --- a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/BattleAirBattle.cs +++ b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/BattleAirBattle.cs @@ -14,7 +14,7 @@ public sealed class BattleAirBattle : AirBattleData public override string Title => ConstantsRes.Title_NormalFleetAirBattle; private PhaseSupport? Support { get; } - private PhaseAirBattle? AirBattle2 { get; } + public PhaseAirBattle? AirBattle2 { get; } public BattleAirBattle(PhaseFactory phaseFactory, BattleFleets fleets, ApiReqSortieAirbattleResponse battle) : base(phaseFactory, fleets, battle, true) diff --git a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/BattleBaseAirRaid.cs b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/BattleBaseAirRaid.cs index b20c9ecbd..2622be07f 100644 --- a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/BattleBaseAirRaid.cs +++ b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/BattleBaseAirRaid.cs @@ -12,7 +12,7 @@ public sealed class BattleBaseAirRaid : FirstBattleData { public override string Title => ConstantsRes.Title_BaseAirRaid; - private PhaseBaseAirRaid? BaseAirRaid { get; } + public PhaseBaseAirRaid? BaseAirRaid { get; } public BattleBaseAirRaid(PhaseFactory phaseFactory, BattleFleets fleets, ApiDestructionBattle battle) : base(phaseFactory, fleets, battle) diff --git a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/BattleCombinedAirBattle.cs b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/BattleCombinedAirBattle.cs index bef3594db..cf008aff3 100644 --- a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/BattleCombinedAirBattle.cs +++ b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/BattleCombinedAirBattle.cs @@ -13,7 +13,7 @@ public sealed class BattleCombinedAirBattle : AirBattleData public override string Title => ConstantsRes.Title_NormalFleetAirBattle; private PhaseSupport? Support { get; } - private PhaseAirBattle? AirBattle2 { get; } + public PhaseAirBattle? AirBattle2 { get; } public BattleCombinedAirBattle(PhaseFactory phaseFactory, BattleFleets fleets, ApiReqCombinedBattleAirbattleResponse battle) : base(phaseFactory, fleets, battle) diff --git a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/BattleData.cs b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/BattleData.cs index 459ff736a..c440400e6 100644 --- a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/BattleData.cs +++ b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/BattleData.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using ElectronicObserver.Core.Types; using ElectronicObserver.KancolleApi.Types.Interfaces; using ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle.Phase; @@ -14,7 +15,80 @@ public abstract class BattleData protected PhaseFactory PhaseFactory { get; } public BattleFleets FleetsBeforeBattle => Initial.FleetsAfterPhase!; - public BattleFleets FleetsAfterBattle { get; protected set; } + public BattleFleets FleetsAfterBattle { get; private set; } + + public bool IsPractice => this is BattlePracticeDay or BattlePracticeNight; + public bool IsFriendCombined => FleetsBeforeBattle.EscortFleet is not null; + public bool IsEnemyCombined => FleetsBeforeBattle.EnemyEscortFleet is not null; + public bool IsCombined => IsFriendCombined || IsEnemyCombined; + public bool IsBaseAirRaid => this is BattleBaseAirRaid; + public bool IsRadar => this is BattleNormalRadar or BattleCombinedRadar; + public bool IsAirRaid => this is BattleAirRaid or BattleCombinedAirRaid; + + public IEnumerable InitialHPs => GetHpList(FleetsBeforeBattle.Fleet) + .Concat(GetHpList(FleetsBeforeBattle.EscortFleet)) + .Take(12) + .Concat(GetHpList(FleetsBeforeBattle.EnemyFleet)) + .Concat(GetHpList(FleetsBeforeBattle.EnemyEscortFleet)); + + public IEnumerable ResultHPs => GetHpList(FleetsAfterBattle.Fleet) + .Concat(GetHpList(FleetsAfterBattle.EscortFleet)) + .Take(12) + .Concat(GetHpList(FleetsAfterBattle.EnemyFleet)) + .Concat(GetHpList(FleetsAfterBattle.EnemyEscortFleet)); + + private static IEnumerable GetHpList(IFleetData? fleet) => + fleet?.MembersInstance + .Select(s => s?.HPCurrent ?? 0) + .Concat(Enumerable.Repeat(0, 6)) + .Take(Math.Max(fleet.MembersInstance.Count, 6)) + ?? Enumerable.Repeat(0, 6); + + public IEnumerable MvpShipIndexes() + { + if (FleetsBeforeBattle.Fleet.Members is null) return [0]; + + List<(int? Index, int Damage)> damages = Phases + .OfType() + .SelectMany(p => p.AttackDisplays) + .Where(a => a.AttackerIndex?.FleetFlag is FleetFlag.Player) + .Where(a => a.AttackerIndex?.Index < FleetsBeforeBattle.Fleet.Members.Count) + .GroupBy(a => a.AttackerIndex?.Index) + .Select(g => (g.Key, (int)g.Sum(a => a.Damage))) + .ToList(); + + int max = damages.Select(d => d.Damage).Max(); + + if (max is 0) return [0]; + + return damages + .Where(d => d.Damage == max) + .Select(d => d.Index) + .OfType(); + } + + public IEnumerable MvpShipCombinedIndexes() + { + if (FleetsBeforeBattle.EscortFleet?.Members is null) return [0]; + + List<(int? Index, int Damage)> damages = Phases + .OfType() + .SelectMany(p => p.AttackDisplays) + .Where(a => a.AttackerIndex?.FleetFlag is FleetFlag.Player) + .Where(a => a.AttackerIndex?.Index > 5) + .GroupBy(a => a.AttackerIndex?.Index) + .Select(g => (g.Key, (int)g.Sum(a => a.Damage))) + .ToList(); + + int max = damages.Select(d => d.Damage).Max(); + + if (max is 0) return [0]; + + return damages + .Where(d => d.Damage == max) + .Select(d => d.Index - 6) + .OfType(); + } public IEnumerable AirBaseBeforeAfter => FleetsBeforeBattle.AirBases .Zip(FleetsAfterBattle.AirBases, (before, after) => (Before: before, After: after)) @@ -39,6 +113,7 @@ public abstract class BattleData public PhaseInitial Initial { get; } public IEnumerable Phases => AllPhases().OfType(); + public List AttackDamages { get; } = [.. Enumerable.Repeat(0, 24)]; protected BattleData(PhaseFactory phaseFactory, BattleFleets fleets, IBattleApiResponse battle) { @@ -53,7 +128,20 @@ protected void EmulateBattle() { foreach (PhaseBase phase in Phases) { - FleetsAfterBattle = phase.EmulateBattle(FleetsAfterBattle); + FleetsAfterBattle = phase.EmulateBattle(FleetsAfterBattle, AttackDamages); } } + + public string GetBattleDetail(int index) => string.Join("\r\n", Phases + .OfType() + .Select(p => p.GetBattleDetail(index) switch + { + string detail => $""" + == {p.Title} == + {detail} + """, + + _ => null, + }) + .Where(d => !string.IsNullOrEmpty(d))); } diff --git a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/BattleFactory.cs b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/BattleFactory.cs index 5e0053ae3..e607d552b 100644 --- a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/BattleFactory.cs +++ b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/BattleFactory.cs @@ -1,20 +1,25 @@ using ElectronicObserver.KancolleApi.Types.ApiReqBattleMidnight.Battle; using ElectronicObserver.KancolleApi.Types.ApiReqBattleMidnight.SpMidnight; +using ElectronicObserver.KancolleApi.Types.ApiReqCombinedBattle.Airbattle; using ElectronicObserver.KancolleApi.Types.ApiReqCombinedBattle.Battle; using ElectronicObserver.KancolleApi.Types.ApiReqCombinedBattle.BattleWater; using ElectronicObserver.KancolleApi.Types.ApiReqCombinedBattle.EachBattle; using ElectronicObserver.KancolleApi.Types.ApiReqCombinedBattle.EachBattleWater; using ElectronicObserver.KancolleApi.Types.ApiReqCombinedBattle.EcBattle; using ElectronicObserver.KancolleApi.Types.ApiReqCombinedBattle.EcMidnightBattle; +using ElectronicObserver.KancolleApi.Types.ApiReqCombinedBattle.EcNightToDay; using ElectronicObserver.KancolleApi.Types.ApiReqCombinedBattle.LdAirbattle; using ElectronicObserver.KancolleApi.Types.ApiReqCombinedBattle.LdShooting; using ElectronicObserver.KancolleApi.Types.ApiReqCombinedBattle.MidnightBattle; using ElectronicObserver.KancolleApi.Types.ApiReqCombinedBattle.SpMidnight; using ElectronicObserver.KancolleApi.Types.ApiReqMap.Models; +using ElectronicObserver.KancolleApi.Types.ApiReqPractice.Battle; +using ElectronicObserver.KancolleApi.Types.ApiReqPractice.MidnightBattle; using ElectronicObserver.KancolleApi.Types.ApiReqSortie.Airbattle; using ElectronicObserver.KancolleApi.Types.ApiReqSortie.Battle; using ElectronicObserver.KancolleApi.Types.ApiReqSortie.LdAirbattle; using ElectronicObserver.KancolleApi.Types.ApiReqSortie.LdShooting; +using ElectronicObserver.KancolleApi.Types.ApiReqSortie.NightToDay; using ElectronicObserver.KancolleApi.Types.Legacy.OpeningTorpedoRework; using ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle.Phase; @@ -92,4 +97,19 @@ public BattleCombinedEachDay CreateBattle(OpeningTorpedoRework_ApiReqCombinedBat public BattleCombinedEachWater CreateBattle(OpeningTorpedoRework_ApiReqCombinedBattleEachBattleWaterResponse battle, BattleFleets fleets) => new(PhaseFactory, fleets, battle); + + public BattleNormalDayFromNight CreateBattle(ApiReqSortieNightToDayResponse battle, BattleFleets fleets) + => new(PhaseFactory, fleets, battle); + + public BattleEnemyCombinedDayFromNight CreateBattle(ApiReqCombinedBattleEcNightToDayResponse battle, BattleFleets fleets) + => new(PhaseFactory, fleets, battle); + + public BattleCombinedAirBattle CreateBattle(ApiReqCombinedBattleAirbattleResponse battle, BattleFleets fleets) + => new(PhaseFactory, fleets, battle); + + public BattlePracticeDay CreateBattle(ApiReqPracticeBattleResponse battle, BattleFleets fleets) + => new(PhaseFactory, fleets, battle); + + public BattlePracticeNight CreateBattle(ApiReqPracticeMidnightBattleResponse battle, BattleFleets fleets) + => new(PhaseFactory, fleets, battle); } diff --git a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/BattleIndex.cs b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/BattleIndex.cs index ee8a53f56..09cf1879c 100644 --- a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/BattleIndex.cs +++ b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/BattleIndex.cs @@ -5,4 +5,11 @@ namespace ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle; public record BattleIndex(int Index, FleetFlag FleetFlag) { public string Display => $"#{Index + 1}"; + public bool IsFriend => FleetFlag is FleetFlag.Player; + + public int ToFlatIndex() => FleetFlag switch + { + FleetFlag.Player => Index, + _ => Index + 12, + }; } diff --git a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/BattlePracticeDay.cs b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/BattlePracticeDay.cs index d868f82c7..6fd2ee6d1 100644 --- a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/BattlePracticeDay.cs +++ b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/BattlePracticeDay.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using ElectronicObserver.KancolleApi.Types.ApiReqPractice.Battle; using ElectronicObserver.KancolleApi.Types.Legacy.OpeningTorpedoRework; +using ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle.Interfaces; using ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle.Phase; namespace ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle; @@ -9,12 +10,12 @@ namespace ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle; /// 演習 昼戦
/// api_req_practice/battle ///
-public sealed class BattlePracticeDay : FirstBattleData +public sealed class BattlePracticeDay : FirstBattleData, IAirBattle { public override string Title => ConstantsRes.Title_PracticeDay; - private PhaseJetAirBattle? JetAirBattle { get; } - private PhaseAirBattle? AirBattle { get; } + public PhaseJetAirBattle? JetAirBattle { get; } + public PhaseAirBattle? AirBattle { get; } private PhaseOpeningAsw? OpeningAsw { get; } private PhaseOpeningTorpedo? OpeningTorpedo { get; } private PhaseShelling? Shelling1 { get; } diff --git a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/DayBattleData.cs b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/DayBattleData.cs index 420ee4413..ad3a9fdfc 100644 --- a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/DayBattleData.cs +++ b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/DayBattleData.cs @@ -6,7 +6,7 @@ namespace ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle; public abstract class DayBattleData : AirBattleData { - protected PhaseSupport? Support { get; } + public PhaseSupport? Support { get; } protected PhaseOpeningAsw? OpeningAsw { get; } protected PhaseOpeningTorpedo? OpeningTorpedo { get; } protected PhaseShelling? Shelling1 { get; } diff --git a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/DayFromNightBattleData.cs b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/DayFromNightBattleData.cs index 1ff84a204..fd0a4db40 100644 --- a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/DayFromNightBattleData.cs +++ b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/DayFromNightBattleData.cs @@ -1,18 +1,21 @@ using ElectronicObserver.KancolleApi.Types.Interfaces; using ElectronicObserver.KancolleApi.Types.Legacy.OpeningTorpedoRework; +using ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle.Interfaces; using ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle.Phase; namespace ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle; -public abstract class DayFromNightBattleData : NightOnlyBattleData +public abstract class DayFromNightBattleData : NightOnlyBattleData, IBaseAirAttack, IAirBattle { + public bool NextToDay { get; } + protected PhaseNightBattle? NightBattle { get; } protected PhaseNightBattle? NightBattle2 { get; } protected PhaseJetBaseAirAttack? JetBaseAirAttack { get; } - protected PhaseJetAirBattle? JetAirBattle { get; } - protected PhaseBaseAirAttack? BaseAirAttack { get; } - protected PhaseAirBattle? AirBattle { get; } - protected PhaseSupport? Support { get; } + public PhaseJetAirBattle? JetAirBattle { get; } + public PhaseBaseAirAttack? BaseAirAttack { get; } + public PhaseAirBattle? AirBattle { get; } + public PhaseSupport? Support { get; } protected PhaseOpeningAsw? OpeningAsw { get; } protected PhaseOpeningTorpedo? OpeningTorpedo { get; } protected PhaseShelling? Shelling1 { get; } @@ -22,6 +25,8 @@ public abstract class DayFromNightBattleData : NightOnlyBattleData protected DayFromNightBattleData(PhaseFactory phaseFactory, BattleFleets fleets, IDayFromNightBattleApiResponse battle) : base(phaseFactory, fleets, battle) { + NextToDay = battle.ApiDayFlag != 0; + NightBattle = PhaseFactory.NightBattle(battle.ApiNHougeki1); NightBattle2 = PhaseFactory.NightBattle(battle.ApiNHougeki2); JetBaseAirAttack = PhaseFactory.JetBaseAirAttack(battle.ApiAirBaseInjection); @@ -39,6 +44,8 @@ protected DayFromNightBattleData(PhaseFactory phaseFactory, BattleFleets fleets, protected DayFromNightBattleData(PhaseFactory phaseFactory, BattleFleets fleets, IOpeningTorpedoRework_DayFromNightBattleApiResponse battle) : base(phaseFactory, fleets, battle) { + NextToDay = battle.ApiDayFlag != 0; + NightBattle = PhaseFactory.NightBattle(battle.ApiNHougeki1); NightBattle2 = PhaseFactory.NightBattle(battle.ApiNHougeki2); JetBaseAirAttack = PhaseFactory.JetBaseAirAttack(battle.ApiAirBaseInjection); diff --git a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/FirstBattleData.cs b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/FirstBattleData.cs index 6df5e4d4b..8f4294644 100644 --- a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/FirstBattleData.cs +++ b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/FirstBattleData.cs @@ -5,7 +5,7 @@ namespace ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle; public abstract class FirstBattleData : BattleData { - protected PhaseSearching Searching { get; } + public PhaseSearching Searching { get; } protected FirstBattleData(PhaseFactory phaseFactory, BattleFleets fleets, IFirstBattleApiResponse battle) : base(phaseFactory, fleets, battle) diff --git a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Interfaces/IAirBattle.cs b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Interfaces/IAirBattle.cs new file mode 100644 index 000000000..81310a4b0 --- /dev/null +++ b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Interfaces/IAirBattle.cs @@ -0,0 +1,9 @@ +using ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle.Phase; + +namespace ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle.Interfaces; + +public interface IAirBattle +{ + PhaseJetAirBattle? JetAirBattle { get; } + PhaseAirBattle? AirBattle { get; } +} diff --git a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Interfaces/IBaseAirAttack.cs b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Interfaces/IBaseAirAttack.cs new file mode 100644 index 000000000..900f64b98 --- /dev/null +++ b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Interfaces/IBaseAirAttack.cs @@ -0,0 +1,8 @@ +using ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle.Phase; + +namespace ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle.Interfaces; + +public interface IBaseAirAttack +{ + PhaseBaseAirAttack? BaseAirAttack { get; } +} diff --git a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Interfaces/INightInitial.cs b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Interfaces/INightInitial.cs new file mode 100644 index 000000000..accb56567 --- /dev/null +++ b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Interfaces/INightInitial.cs @@ -0,0 +1,8 @@ +using ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle.Phase; + +namespace ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle.Interfaces; + +public interface INightInitial +{ + PhaseNightInitial? NightInitial { get; } +} diff --git a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Interfaces/IPhaseAirBattle.cs b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Interfaces/IPhaseAirBattle.cs new file mode 100644 index 000000000..d6ecc3b7b --- /dev/null +++ b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Interfaces/IPhaseAirBattle.cs @@ -0,0 +1,29 @@ +using ElectronicObserver.Core.Types; + +namespace ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle.Interfaces; + +public interface IPhaseAirBattle +{ + bool IsStage1Available { get; } + bool IsStage2Available { get; } + + int AircraftLostStage1Friend { get; } + int AircraftTotalStage1Friend { get; } + int AircraftLostStage1Enemy { get; } + int AircraftTotalStage1Enemy { get; } + + int AircraftLostStage2Friend { get; } + int AircraftTotalStage2Friend { get; } + int AircraftLostStage2Enemy { get; } + int AircraftTotalStage2Enemy { get; } + + string? TouchAircraftFriend { get; } + string? TouchAircraftEnemy { get; } + + AirState AirState { get; } + + bool IsAACutinAvailable { get; } + int AACutInIndex { get; } + string? AACutInShipName { get; } + int AACutInKind { get; } +} diff --git a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/NightBattleData.cs b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/NightBattleData.cs index 6ecf74871..ef98883aa 100644 --- a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/NightBattleData.cs +++ b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/NightBattleData.cs @@ -1,11 +1,12 @@ using ElectronicObserver.KancolleApi.Types.Interfaces; +using ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle.Interfaces; using ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle.Phase; namespace ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle; -public abstract class NightBattleData : FirstBattleData +public abstract class NightBattleData : FirstBattleData, INightInitial { - protected PhaseNightInitial? NightInitial { get; } + public PhaseNightInitial? NightInitial { get; } protected PhaseFriendlySupportInfo? FriendlySupportInfo { get; } protected PhaseFriendlyShelling? FriendlyShelling { get; } diff --git a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/NightOnlyBattleData.cs b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/NightOnlyBattleData.cs index d83c23659..325c88a64 100644 --- a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/NightOnlyBattleData.cs +++ b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/NightOnlyBattleData.cs @@ -5,7 +5,7 @@ namespace ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle; public abstract class NightOnlyBattleData : NightBattleData { - protected PhaseSupport? NightSupport { get; } + public PhaseSupport? NightSupport { get; } protected NightOnlyBattleData(PhaseFactory phaseFactory, BattleFleets fleets, INightBattleApiResponse battle) : base(phaseFactory, fleets, battle) diff --git a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/AirBaseRaidAttackViewModel.cs b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/AirBaseRaidAttackViewModel.cs index 0c83bea66..bab3298f4 100644 --- a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/AirBaseRaidAttackViewModel.cs +++ b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/AirBaseRaidAttackViewModel.cs @@ -9,23 +9,25 @@ public sealed class AirBaseRaidAttackViewModel : AttackViewModelBase { private int WaveIndex { get; } - public BattleIndex DefenderIndex { get; } - public IBaseAirCorpsData Defender { get; } - public int DefenderHpBeforeAttack { get; } - - private double Damage { get; } - private HitType HitType { get; } - private AirAttack AttackType { get; } - public string DamageDisplay { get; } - - public string AttackerName => (WaveIndex, DefenderIndex.FleetFlag) switch + public override BattleIndex? AttackerIndex => null; + public override string AttackerDisplay => (WaveIndex, DefenderIndex.FleetFlag) switch { - (> 0, _) => string.Format(BattleRes.AirSquadronWave, WaveIndex), + ( > 0, _) => string.Format(BattleRes.AirSquadronWave, WaveIndex), (_, FleetFlag.Player) => BattleRes.EnemyAirSquadron, (_, FleetFlag.Enemy) => BattleRes.FriendlyAirSquadron, _ => "???", }; + public override BattleIndex DefenderIndex { get; } + public IBaseAirCorpsData Defender { get; } + private int DefenderHpBeforeAttack { get; } + public override string DefenderDisplay { get; } + + public override double Damage { get; } + private HitType HitType { get; } + private AirAttack AttackType { get; } + public override string DamageDisplay { get; } + public AirBaseRaidAttackViewModel(BattleFleets fleets, int waveIndex, AirBattleAttack attack) { WaveIndex = waveIndex; @@ -34,6 +36,8 @@ public AirBaseRaidAttackViewModel(BattleFleets fleets, int waveIndex, AirBattleA DefenderIndex = attack.Defenders.First().Defender; Defender = fleets.GetAirBase(DefenderIndex)!; + DefenderDisplay = $"{Defender.Name} {DefenderIndex.Display}"; + AttackType = attack.AttackType; DamageDisplay = diff --git a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/AirBattleAttackViewModel.cs b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/AirBattleAttackViewModel.cs index b41cabba9..073c9997e 100644 --- a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/AirBattleAttackViewModel.cs +++ b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/AirBattleAttackViewModel.cs @@ -9,25 +9,27 @@ public sealed class AirBattleAttackViewModel : AttackViewModelBase { public int WaveIndex { get; } - public BattleIndex DefenderIndex { get; } + public override BattleIndex? AttackerIndex => null; + public override string AttackerDisplay => (WaveIndex, DefenderIndex.FleetFlag) switch + { + ( > 0, _) => string.Format(BattleRes.AirSquadronWave, WaveIndex), + (_, FleetFlag.Player) => BattleRes.EnemyAirSquadron, + (_, FleetFlag.Enemy) => BattleRes.FriendlyAirSquadron, + _ => "???", + }; + + public override BattleIndex DefenderIndex { get; } public IShipData Defender { get; } public int DefenderHpBeforeAttack { get; } + public override string DefenderDisplay { get; } - public int Damage { get; } + public override double Damage { get; } public HitType HitType { get; } public AirAttack AttackType { get; } private IEquipmentData? UsedDamecon { get; } - public string DamageDisplay { get; } + public override string DamageDisplay { get; } public bool GuardsFlagship { get; } - public string AttackerName => (WaveIndex, DefenderIndex.FleetFlag) switch - { - ( > 0, _) => string.Format(BattleRes.AirSquadronWave, WaveIndex), - (_, FleetFlag.Player) => BattleRes.EnemyAirSquadron, - (_, FleetFlag.Enemy) => BattleRes.FriendlyAirSquadron, - _ => "???", - }; - public string AttackKind => GetAttackKind(AttackType); public AirBattleAttackViewModel(BattleFleets fleets, int waveIndex, AirBattleAttack attack) @@ -38,12 +40,14 @@ public AirBattleAttackViewModel(BattleFleets fleets, int waveIndex, AirBattleAtt DefenderIndex = attack.Defenders.First().Defender; Defender = fleets.GetShip(DefenderIndex)!; + DefenderDisplay = $"{Defender.Name} {DefenderIndex.Display}"; + AttackType = attack.AttackType; GuardsFlagship = attack.Defenders.First().GuardsFlagship; DefenderHpBeforeAttack = Defender.HPCurrent; - int hpAfterAttacks = Math.Max(0, DefenderHpBeforeAttack - Damage); + int hpAfterAttacks = Math.Max(0, DefenderHpBeforeAttack - (int)Damage); if (hpAfterAttacks <= 0 && GetDamecon(Defender) is { } damecon) { diff --git a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/AttackPhaseBase.cs b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/AttackPhaseBase.cs new file mode 100644 index 000000000..bf3ee41b9 --- /dev/null +++ b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/AttackPhaseBase.cs @@ -0,0 +1,29 @@ +using System.Collections.Generic; +using System.Linq; + +namespace ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle.Phase; + +public abstract class AttackPhaseBase : PhaseBase +{ + public abstract IEnumerable AttackDisplays { get; } + + private IEnumerable SearchBattleDetails(int index) => AttackDisplays + .Where(a => a.AttackerIndex?.ToFlatIndex() == index || a.DefenderIndex.ToFlatIndex() == index) + .Select(a => a.ToString()); + + public string? GetBattleDetail(int index = -1) + { + IEnumerable list = index switch + { + -1 => AttackDisplays.Select(d => d.ToString()), + _ => SearchBattleDetails(index), + }; + + if (list.Any()) + { + return string.Join("\r\n\r\n", list) + "\r\n"; + } + + return null; + } +} diff --git a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/AttackViewModelBase.cs b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/AttackViewModelBase.cs index 0a44c3850..b7465a0f2 100644 --- a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/AttackViewModelBase.cs +++ b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/AttackViewModelBase.cs @@ -6,6 +6,21 @@ namespace ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle.Phase public abstract class AttackViewModelBase { + /// + /// null for unknown attacker index such as AB, support, air attack etc... + /// + public abstract BattleIndex? AttackerIndex { get; } + public abstract string AttackerDisplay { get; } + + public abstract BattleIndex DefenderIndex { get; } + public abstract string DefenderDisplay { get; } + + public abstract double Damage { get; } + + // \u2192 = → + public string AttackerDefenderDisplay => $"{AttackerDisplay} \u2192 {DefenderDisplay}"; + public abstract string DamageDisplay { get; } + protected static IEquipmentData? GetDamecon(IShipData ship) => ship.AllSlotInstance .FirstOrDefault(e => e?.MasterEquipment.CategoryType is EquipmentTypes.DamageControl); @@ -26,4 +41,9 @@ private static string HitDisplay(bool guardsFlagship, double damage) true => $"<{BattleRes.Protected}> ", _ => "", }; + + public override string ToString() => $""" + {AttackerDefenderDisplay} + {DamageDisplay} + """; } diff --git a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseAirBattleBase.cs b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseAirBattleBase.cs index 3b2220bf9..4e52fe645 100644 --- a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseAirBattleBase.cs +++ b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseAirBattleBase.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Text; using ElectronicObserver.Core.Types; @@ -7,11 +8,12 @@ using ElectronicObserver.KancolleApi.Types.ApiReqSortie.Models; using ElectronicObserver.KancolleApi.Types.Interfaces; using ElectronicObserver.KancolleApi.Types.Models; +using ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle.Interfaces; using ElectronicObserver.Window.Wpf; namespace ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle.Phase; -public class PhaseAirBattleBase : PhaseBase +public class PhaseAirBattleBase : AttackPhaseBase, IPhaseAirBattle { public override string Title => BattleRes.BattlePhaseAirBattle; @@ -24,27 +26,44 @@ public class PhaseAirBattleBase : PhaseBase public AirState AirState { get; } - public int Stage1FLostcount { get; } - public int Stage1FCount { get; } - public int Stage1ELostcount { get; } - public int Stage1ECount { get; } + public int AircraftLostStage1Friend { get; } + public int AircraftTotalStage1Friend { get; } + public int AircraftLostStage1Enemy { get; } + public int AircraftTotalStage1Enemy { get; } - public int Stage2FLostcount { get; private set; } - public int Stage2FCount { get; private set; } - public int Stage2ELostcount { get; private set; } - public int Stage2ECount { get; private set; } + public int AircraftLostStage2Friend { get; private set; } + public int AircraftTotalStage2Friend { get; private set; } + public int AircraftLostStage2Enemy { get; private set; } + public int AircraftTotalStage2Enemy { get; private set; } + + [MemberNotNullWhen(true, nameof(ApiAirFire))] + public bool IsAACutinAvailable => ApiAirFire is not null; + + public int AACutInIndex => ApiAirFire?.ApiIdx ?? -1; + public string? AACutInShipName => IsAACutinAvailable switch + { + true => FleetsAfterPhase?.GetShip(new(ApiAirFire.ApiIdx, FleetFlag.Player))?.NameWithLevel, + _ => null, + }; + public int AACutInKind => ApiAirFire?.ApiKind ?? -1; /// /// AACI /// public ApiAirFire? ApiAirFire { get; private set; } + [MemberNotNullWhen(true, nameof(Stage1))] + public bool IsStage1Available => Stage1 is not null; + private ApiStage1? Stage1 => AirBattleData switch { IApiAirBattle aab => aab.ApiStage1, _ => null, }; + [MemberNotNullWhen(true, nameof(Stage2))] + public bool IsStage2Available => Stage2 is not null; + private ApiStage2? Stage2 => AirBattleData switch { IApiAirBattle aab => aab.ApiStage2, @@ -86,14 +105,14 @@ public class PhaseAirBattleBase : PhaseBase public List LaunchedShipIndexFriend { get; } public List LaunchedShipIndexEnemy { get; } - private List Attacks { get; } = new(); - public List AttackDisplays { get; } = new(); + private List Attacks { get; } = []; + public override List AttackDisplays { get; } = []; public string? Stage1Display { get; } public string? TouchAircraftFriend => Stage1?.ApiTouchPlane switch { - [EquipmentId id and > 0, ..] => KcDatabase.MasterEquipments[(int)id].NameEN, + [EquipmentId id and > 0, ..] => KcDatabase.MasterEquipments[(int)id]?.NameEN, _ => null, }; public string? TouchAircraftFriendDisplay => TouchAircraftFriend switch @@ -104,7 +123,7 @@ public class PhaseAirBattleBase : PhaseBase public string? TouchAircraftEnemy => Stage1?.ApiTouchPlane switch { - [_, EquipmentId id and > 0, ..] => KcDatabase.MasterEquipments[(int)id].NameEN, + [_, EquipmentId id and > 0, ..] => KcDatabase.MasterEquipments[(int)id]?.NameEN, _ => null, }; public string? TouchAircraftEnemyDisplay => TouchAircraftEnemy switch @@ -124,18 +143,18 @@ protected PhaseAirBattleBase(IKCDatabase kcDatabase, IApiAirBattle airBattleData if (airBattleData.ApiStage1 is not null) { AirState = airBattleData.ApiStage1.ApiDispSeiku; - Stage1FLostcount = airBattleData.ApiStage1.ApiFLostcount; - Stage1FCount = airBattleData.ApiStage1.ApiFCount; - Stage1ELostcount = airBattleData.ApiStage1.ApiELostcount; - Stage1ECount = airBattleData.ApiStage1.ApiECount; + AircraftLostStage1Friend = airBattleData.ApiStage1.ApiFLostcount; + AircraftTotalStage1Friend = airBattleData.ApiStage1.ApiFCount; + AircraftLostStage1Enemy = airBattleData.ApiStage1.ApiELostcount; + AircraftTotalStage1Enemy = airBattleData.ApiStage1.ApiECount; Stage1Display = GetStage1Display ( AirState, - Stage1FLostcount, - Stage1FCount, - Stage1ELostcount, - Stage1ECount + AircraftLostStage1Friend, + AircraftTotalStage1Friend, + AircraftLostStage1Enemy, + AircraftTotalStage1Enemy ); } @@ -143,26 +162,27 @@ protected PhaseAirBattleBase(IKCDatabase kcDatabase, IApiAirBattle airBattleData LaunchedShipIndexEnemy = GetLaunchedShipIndex(airBattleData.ApiPlaneFrom, 1); } - protected PhaseAirBattleBase(IApiJetAirBattle airBattleData, int waveIndex = 0) + protected PhaseAirBattleBase(IKCDatabase kcDatabase, IApiJetAirBattle airBattleData, int waveIndex = 0) { + KcDatabase = kcDatabase; AirBattleData = airBattleData; WaveIndex = waveIndex; if (airBattleData.ApiStage1 is not null) { AirState = AirState.Unknown; - Stage1FLostcount = airBattleData.ApiStage1.ApiFLostcount; - Stage1FCount = airBattleData.ApiStage1.ApiFCount; - Stage1ELostcount = airBattleData.ApiStage1.ApiELostcount; - Stage1ECount = airBattleData.ApiStage1.ApiECount; + AircraftLostStage1Friend = airBattleData.ApiStage1.ApiFLostcount; + AircraftTotalStage1Friend = airBattleData.ApiStage1.ApiFCount; + AircraftLostStage1Enemy = airBattleData.ApiStage1.ApiELostcount; + AircraftTotalStage1Enemy = airBattleData.ApiStage1.ApiECount; Stage1Display = GetStage1Display ( AirState, - Stage1FLostcount, - Stage1FCount, - Stage1ELostcount, - Stage1ECount + AircraftLostStage1Friend, + AircraftTotalStage1Friend, + AircraftLostStage1Enemy, + AircraftTotalStage1Enemy ); } @@ -170,25 +190,25 @@ protected PhaseAirBattleBase(IApiJetAirBattle airBattleData, int waveIndex = 0) LaunchedShipIndexEnemy = GetLaunchedShipIndex(airBattleData.ApiPlaneFrom, 1); } - public override BattleFleets EmulateBattle(BattleFleets battleFleets) + public override BattleFleets EmulateBattle(BattleFleets battleFleets, List damages) { FleetsBeforePhase = battleFleets.Clone(); FleetsAfterPhase = battleFleets; if (Stage2 is { } stage2) { - Stage2FLostcount = stage2.ApiFLostcount; - Stage2FCount = stage2.ApiFCount; - Stage2ELostcount = stage2.ApiELostcount; - Stage2ECount = stage2.ApiECount; + AircraftLostStage2Friend = stage2.ApiFLostcount; + AircraftTotalStage2Friend = stage2.ApiFCount; + AircraftLostStage2Enemy = stage2.ApiELostcount; + AircraftTotalStage2Enemy = stage2.ApiECount; ApiAirFire = stage2.ApiAirFire; } else if (Stage2Jet is { } stage2Jet) { - Stage2FLostcount = stage2Jet.ApiFLostcount; - Stage2FCount = stage2Jet.ApiFCount; - Stage2ELostcount = stage2Jet.ApiELostcount; - Stage2ECount = stage2Jet.ApiECount; + AircraftLostStage2Friend = stage2Jet.ApiFLostcount; + AircraftTotalStage2Friend = stage2Jet.ApiFCount; + AircraftLostStage2Enemy = stage2Jet.ApiELostcount; + AircraftTotalStage2Enemy = stage2Jet.ApiECount; } StringBuilder sb = new(); @@ -203,8 +223,8 @@ public override BattleFleets EmulateBattle(BattleFleets battleFleets) } sb.AppendLine(); - sb.AppendLine($" {BattleRes.Friendly}: -{Stage2FLostcount}/{Stage2FCount}"); - sb.Append($" {BattleRes.Enemy}: -{Stage2ELostcount}/{Stage2ECount}"); + sb.AppendLine($" {BattleRes.Friendly}: -{AircraftLostStage2Friend}/{AircraftTotalStage2Friend}"); + sb.Append($" {BattleRes.Enemy}: -{AircraftLostStage2Enemy}/{AircraftTotalStage2Enemy}"); Stage2Display = sb.ToString(); diff --git a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseBase.cs b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseBase.cs index 81ac655fe..b0d3a033d 100644 --- a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseBase.cs +++ b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseBase.cs @@ -14,7 +14,7 @@ public abstract class PhaseBase public BattleFleets? FleetsBeforePhase { get; protected set; } public BattleFleets? FleetsAfterPhase { get; protected set; } - public virtual BattleFleets EmulateBattle(BattleFleets battleFleets) + public virtual BattleFleets EmulateBattle(BattleFleets battleFleets, List damages) { FleetsBeforePhase = battleFleets.Clone(); FleetsAfterPhase = battleFleets; @@ -101,8 +101,8 @@ protected static List GetAttacks(FleetFlag fleetFlag, int index _ => AirAttack.None, }, - Defenders = new List - { + Defenders = + [ new() { Defender = new BattleIndex(t.Index, fleetFlag), @@ -117,9 +117,9 @@ protected static List GetAttacks(FleetFlag fleetFlag, int index }, RawDamage = t.Damage, }, - }, + ], }).ToList() - ?? new(); + ?? []; protected static List GetLaunchedShipIndex(List?> apiPlaneFrom, int index) => apiPlaneFrom @@ -128,5 +128,5 @@ protected static List GetLaunchedShipIndex(List?> apiPlaneFrom, i ?.Where(i => i > 0) .Select(i => i - 1) .ToList() - ?? new(); + ?? []; } diff --git a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseBaseAirAttack.cs b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseBaseAirAttack.cs index b756a874c..9c24e7f40 100644 --- a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseBaseAirAttack.cs +++ b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseBaseAirAttack.cs @@ -20,14 +20,14 @@ public PhaseBaseAirAttack(IKCDatabase kcDatabase, List apiAirB } } - public override BattleFleets EmulateBattle(BattleFleets battleFleets) + public override BattleFleets EmulateBattle(BattleFleets battleFleets, List damages) { FleetsBeforePhase = battleFleets.Clone(); FleetsAfterPhase = battleFleets; foreach (PhaseBaseAirAttackUnit attackUnit in Units) { - FleetsAfterPhase = attackUnit.EmulateBattle(FleetsAfterPhase); + FleetsAfterPhase = attackUnit.EmulateBattle(FleetsAfterPhase, damages); } return FleetsAfterPhase.Clone(); diff --git a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseBaseAirAttackUnit.cs b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseBaseAirAttackUnit.cs index 6674e73b7..e358585d2 100644 --- a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseBaseAirAttackUnit.cs +++ b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseBaseAirAttackUnit.cs @@ -36,8 +36,8 @@ public PhaseBaseAirAttackUnit(IKCDatabase kcDatabase, ApiAirBaseAttack airBattle Display = sb.ToString(); } - public PhaseBaseAirAttackUnit(ApiAirBaseInjection airBattleData, int waveIndex) - : base(airBattleData, waveIndex) + public PhaseBaseAirAttackUnit(IKCDatabase kcDatabase, ApiAirBaseInjection airBattleData, int waveIndex) + : base(kcDatabase, airBattleData, waveIndex) { Squadrons = airBattleData.ApiAirBaseData.Select(b => new BattleBaseAirCorpsSquadron { diff --git a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseBaseAirRaid.cs b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseBaseAirRaid.cs index 0a23d105f..915f364b8 100644 --- a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseBaseAirRaid.cs +++ b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseBaseAirRaid.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Text; using ElectronicObserver.Core.Types; @@ -7,11 +8,12 @@ using ElectronicObserver.KancolleApi.Types.ApiReqMap.Models; using ElectronicObserver.KancolleApi.Types.ApiReqSortie.Models; using ElectronicObserver.KancolleApi.Types.Models; +using ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle.Interfaces; using ElectronicObserver.Window.Wpf; namespace ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle.Phase; -public class PhaseBaseAirRaid : PhaseBase +public class PhaseBaseAirRaid : AttackPhaseBase, IPhaseAirBattle { public override string Title => BattleRes.BattlePhaseAirBaseRaid; @@ -21,23 +23,45 @@ public class PhaseBaseAirRaid : PhaseBase public AirState AirState { get; } - public int Stage1FLostcount { get; } - public int Stage1FCount { get; } - public int Stage1ELostcount { get; } - public int Stage1ECount { get; } + public int AircraftLostStage1Friend { get; } + public int AircraftTotalStage1Friend { get; } + public int AircraftLostStage1Enemy { get; } + public int AircraftTotalStage1Enemy { get; } - public int Stage2FLostcount { get; private set; } - public int Stage2FCount { get; private set; } - public int Stage2ELostcount { get; private set; } - public int Stage2ECount { get; private set; } + public int AircraftLostStage2Friend { get; private set; } + public int AircraftTotalStage2Friend { get; private set; } + public int AircraftLostStage2Enemy { get; private set; } + public int AircraftTotalStage2Enemy { get; private set; } + + [MemberNotNullWhen(true, nameof(ApiAirFire))] + public bool IsAACutinAvailable => ApiAirFire is not null; + + public int AACutInIndex => ApiAirFire?.ApiIdx ?? -1; + public string? AACutInShipName => IsAACutinAvailable switch + { + true => FleetsAfterPhase?.GetShip(new(ApiAirFire.ApiIdx, FleetFlag.Player))?.NameWithLevel, + _ => null, + }; + public int AACutInKind => ApiAirFire?.ApiKind ?? -1; /// /// AACI /// public ApiAirFire? ApiAirFire { get; private set; } + [MemberNotNullWhen(true, nameof(Stage1))] + public bool IsStage1Available => Stage1 is not null; + private ApiStage1? Stage1 => AirBattleData.ApiStage1; + + [MemberNotNullWhen(true, nameof(Stage2))] + public bool IsStage2Available => Stage2 is not null; + private ApiStage2? Stage2 => AirBattleData.ApiStage2; + + [MemberNotNullWhen(true, nameof(Stage3))] + public bool IsStage3Available => Stage3 is not null; + private ApiStage3? Stage3 => AirBattleData.ApiStage3; private int WaveIndex { get; } @@ -45,14 +69,14 @@ public class PhaseBaseAirRaid : PhaseBase public List LaunchedShipIndexFriend { get; } public List LaunchedShipIndexEnemy { get; } - private List Attacks { get; } = new(); - public List AttackDisplays { get; } = new(); + private List Attacks { get; } = []; + public override List AttackDisplays { get; } = []; public string? Stage1Display { get; } public string? TouchAircraftFriend => Stage1?.ApiTouchPlane switch { - [EquipmentId id and > 0, ..] => KCDatabase.Instance.MasterEquipments[(int)id].NameEN, + [EquipmentId id and > 0, ..] => KCDatabase.Instance.MasterEquipments[(int)id]?.NameEN, _ => null, }; public string? TouchAircraftFriendDisplay => TouchAircraftFriend switch @@ -63,7 +87,7 @@ public class PhaseBaseAirRaid : PhaseBase public string? TouchAircraftEnemy => Stage1?.ApiTouchPlane switch { - [_, EquipmentId id and > 0, ..] => KCDatabase.Instance.MasterEquipments[(int)id].NameEN, + [_, EquipmentId id and > 0, ..] => KCDatabase.Instance.MasterEquipments[(int)id]?.NameEN, _ => null, }; public string? TouchAircraftEnemyDisplay => TouchAircraftEnemy switch @@ -74,17 +98,17 @@ public class PhaseBaseAirRaid : PhaseBase public string? Stage2Display { get; protected set; } - public List PlayerTorpedoFlags { get; set; } = new(); - public List PlayerBomberFlags { get; set; } = new(); - public List PlayerHitFlags { get; set; } = new(); - public List PlayerDamage { get; set; } = new(); + public List PlayerTorpedoFlags { get; set; } = []; + public List PlayerBomberFlags { get; set; } = []; + public List PlayerHitFlags { get; set; } = []; + public List PlayerDamage { get; set; } = []; - public List EnemyTorpedoFlags { get; set; } = new(); - public List EnemyBomberFlags { get; set; } = new(); - public List EnemyHitFlags { get; set; } = new(); - public List EnemyDamage { get; set; } = new(); + public List EnemyTorpedoFlags { get; set; } = []; + public List EnemyBomberFlags { get; set; } = []; + public List EnemyHitFlags { get; set; } = []; + public List EnemyDamage { get; set; } = []; - private List Squadrons { get; } + public List Squadrons { get; } public string Display { get; } @@ -97,18 +121,18 @@ public PhaseBaseAirRaid(ApiDestructionBattle battle, int waveIndex = 0) if (AirBattleData.ApiStage1 is not null) { AirState = AirBattleData.ApiStage1.ApiDispSeiku; - Stage1FLostcount = AirBattleData.ApiStage1.ApiFLostcount; - Stage1FCount = AirBattleData.ApiStage1.ApiFCount; - Stage1ELostcount = AirBattleData.ApiStage1.ApiELostcount; - Stage1ECount = AirBattleData.ApiStage1.ApiECount; + AircraftLostStage1Friend = AirBattleData.ApiStage1.ApiFLostcount; + AircraftTotalStage1Friend = AirBattleData.ApiStage1.ApiFCount; + AircraftLostStage1Enemy = AirBattleData.ApiStage1.ApiELostcount; + AircraftTotalStage1Enemy = AirBattleData.ApiStage1.ApiECount; Stage1Display = GetStage1Display ( AirState, - Stage1FLostcount, - Stage1FCount, - Stage1ELostcount, - Stage1ECount + AircraftLostStage1Friend, + AircraftTotalStage1Friend, + AircraftLostStage1Enemy, + AircraftTotalStage1Enemy ); } @@ -122,7 +146,7 @@ public PhaseBaseAirRaid(ApiDestructionBattle battle, int waveIndex = 0) Equipment = KCDatabase.Instance.MasterEquipments[(int)b.ApiMstId], AircraftCount = b.ApiCount, }).ToList() - ?? new(); + ?? []; StringBuilder sb = new(); @@ -135,17 +159,17 @@ public PhaseBaseAirRaid(ApiDestructionBattle battle, int waveIndex = 0) Display = sb.ToString(); } - public override BattleFleets EmulateBattle(BattleFleets battleFleets) + public override BattleFleets EmulateBattle(BattleFleets battleFleets, List damages) { FleetsBeforePhase = battleFleets.Clone(); FleetsAfterPhase = battleFleets; if (Stage2 is { } stage2) { - Stage2FLostcount = stage2.ApiFLostcount; - Stage2FCount = stage2.ApiFCount; - Stage2ELostcount = stage2.ApiELostcount; - Stage2ECount = stage2.ApiECount; + AircraftLostStage2Friend = stage2.ApiFLostcount; + AircraftTotalStage2Friend = stage2.ApiFCount; + AircraftLostStage2Enemy = stage2.ApiELostcount; + AircraftTotalStage2Enemy = stage2.ApiECount; ApiAirFire = stage2.ApiAirFire; StringBuilder sb = new(); @@ -160,8 +184,8 @@ public override BattleFleets EmulateBattle(BattleFleets battleFleets) } sb.AppendLine(); - sb.AppendLine($" {BattleRes.Friendly}: -{Stage2FLostcount}/{Stage2FCount}"); - sb.Append($" {BattleRes.Enemy}: -{Stage2ELostcount}/{Stage2ECount}"); + sb.AppendLine($" {BattleRes.Friendly}: -{AircraftLostStage2Friend}/{AircraftTotalStage2Friend}"); + sb.Append($" {BattleRes.Enemy}: -{AircraftLostStage2Enemy}/{AircraftTotalStage2Enemy}"); Stage2Display = sb.ToString(); } diff --git a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseClosingTorpedo.cs b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseClosingTorpedo.cs index fbe9d9378..90ca68842 100644 --- a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseClosingTorpedo.cs +++ b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseClosingTorpedo.cs @@ -12,7 +12,7 @@ public sealed class PhaseClosingTorpedo(ApiRaigekiClass apiRaigekiClass) : Phase private List Attacks { get; } = []; - public override BattleFleets EmulateBattle(BattleFleets battleFleets) + public override BattleFleets EmulateBattle(BattleFleets battleFleets, List damages) { FleetsBeforePhase = battleFleets.Clone(); FleetsAfterPhase = battleFleets; @@ -24,6 +24,7 @@ public override BattleFleets EmulateBattle(BattleFleets battleFleets) { AttackDisplays.Add(new(FleetsAfterPhase, attack)); AddDamage(FleetsAfterPhase, attack.Defenders.First().Defender, attack.Defenders.First().Damage); + damages[attack.Attacker.ToFlatIndex()] += attack.Defenders.Sum(d => d.Damage); } return FleetsAfterPhase.Clone(); diff --git a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseFactory.cs b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseFactory.cs index c747f93fa..f2b9c7ff7 100644 --- a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseFactory.cs +++ b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseFactory.cs @@ -33,14 +33,14 @@ public sealed class PhaseFactory(IKCDatabase kcDatabase) public PhaseJetBaseAirAttack? JetBaseAirAttack(ApiAirBaseInjection? a) => a switch { null => null, - _ => new(a), + _ => new(KcDatabase, a), }; [return: NotNullIfNotNull(nameof(a))] public PhaseJetAirBattle? JetAirBattle(ApiInjectionKouku? a) => a switch { null => null, - _ => new(a), + _ => new(KcDatabase, a), }; [return: NotNullIfNotNull(nameof(a))] diff --git a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseFriendNightBattleAttackViewModel.cs b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseFriendNightBattleAttackViewModel.cs index 170e1d2c4..f8fde7a7d 100644 --- a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseFriendNightBattleAttackViewModel.cs +++ b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseFriendNightBattleAttackViewModel.cs @@ -8,25 +8,32 @@ namespace ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle.Phase public sealed class PhaseFriendNightBattleAttackViewModel : AttackViewModelBase { - public BattleIndex AttackerIndex { get; } + public override BattleIndex AttackerIndex { get; } public IShipData Attacker { get; } public int AttackerHpBeforeAttack { get; } + public override string AttackerDisplay { get; } - public BattleIndex DefenderIndex { get; } + public override BattleIndex DefenderIndex { get; } public IShipData Defender { get; } - public List DefenderHpBeforeAttacks { get; } = new(); + private List DefenderHpBeforeAttacks { get; } = []; + public override string DefenderDisplay { get; } + public override double Damage { get; } private List Attacks { get; } private IEquipmentData? UsedDamecon { get; } - public string DamageDisplay { get; } + public override string DamageDisplay { get; } public PhaseFriendNightBattleAttackViewModel(BattleFleets fleets, BattleIndex attacker, BattleIndex defender, NightAttackKind attackType, List defenders) { AttackerIndex = attacker; Attacker = fleets.GetFriendShip(AttackerIndex)!; + AttackerDisplay = $"{Attacker.Name} {AttackerIndex.Display}"; + DefenderIndex = defender; Defender = fleets.GetFriendShip(DefenderIndex)!; + DefenderDisplay = $"{Defender.Name} {DefenderIndex.Display}"; + Attacks = defenders .Select(d => new NightAttack { @@ -38,6 +45,7 @@ public PhaseFriendNightBattleAttackViewModel(BattleFleets fleets, BattleIndex at CriticalFlag = d.CriticalFlag, }) .ToList(); + Damage = Attacks.Sum(a => a.Damage); AttackerHpBeforeAttack = Attacker.HPCurrent; DefenderHpBeforeAttacks.Add(Defender.HPCurrent); @@ -47,7 +55,8 @@ public PhaseFriendNightBattleAttackViewModel(BattleFleets fleets, BattleIndex at DefenderHpBeforeAttacks.Add(Math.Max(0, DefenderHpBeforeAttacks[^1] - nightAttack.Damage)); } - int hpAfterAttacks = Math.Max(0, Defender.HPCurrent - Attacks.Sum(a => a.Damage)); + + int hpAfterAttacks = Math.Max(0, Defender.HPCurrent - (int)Damage); if (hpAfterAttacks <= 0 && GetDamecon(Defender) is { } damecon) { diff --git a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseFriendlyShelling.cs b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseFriendlyShelling.cs index dd166eb12..5645de401 100644 --- a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseFriendlyShelling.cs +++ b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseFriendlyShelling.cs @@ -10,7 +10,7 @@ namespace ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle.Phase; -public class PhaseFriendlyShelling : PhaseBase +public class PhaseFriendlyShelling : AttackPhaseBase { public override string Title => BattleRes.BattlePhaseFriendlyShelling; @@ -18,20 +18,20 @@ public class PhaseFriendlyShelling : PhaseBase private ApiFriendlyBattle ApiFriendlyBattle { get; } private ApiHougeki ShellingData => ApiFriendlyBattle.ApiHougeki; - private int FlareIndexFriend { get; set; } - private int FlareIndexEnemy { get; set; } - private IShipData? FlareFriend { get; set; } - private IShipData? FlareEnemy { get; set; } + public int FlareIndexFriend { get; private set; } + public int FlareIndexEnemy { get; private set; } + public IShipData? FlareFriend { get; private set; } + public IShipData? FlareEnemy { get; private set; } - private int SearchlightIndexFriend { get; set; } - private int SearchlightIndexEnemy { get; set; } - private IShipData? SearchlightFriend { get; set; } - private IShipData? SearchlightEnemy { get; set; } + public int SearchlightIndexFriend { get; private set; } + public int SearchlightIndexEnemy { get; private set; } + public IShipData? SearchlightFriend { get; private set; } + public IShipData? SearchlightEnemy { get; private set; } public string InitialDisplay => GetDisplay(); - private List Attacks { get; } = new(); - public List AttackDisplays { get; } = new(); + private List Attacks { get; } = []; + public override List AttackDisplays { get; } = []; public PhaseFriendlyShelling(IKCDatabase kcDatabase, ApiFriendlyBattle apiFriendlyBattle) { @@ -53,7 +53,7 @@ public PhaseFriendlyShelling(IKCDatabase kcDatabase, ApiFriendlyBattle apiFriend List> defenders = ShellingData.ApiDfList!.Select(elem => elem.Where(e => e != -1).ToList()).ToList(); List> attackEquipments = ShellingData.ApiSiList!.Select(elem => elem.Select(ParseInt).ToList()).ToList(); List> criticals = ShellingData.ApiClList!.Select(elem => elem.Where(e => e != HitType.Invalid).ToList()).ToList(); - List> rawDamages = ShellingData.ApiDamage!.Select(elem => elem.Where(e => e != -1).ToList()).ToList(); + List> rawDamages = ShellingData.ApiDamage!.Select(elem => elem.Where(e => e >= 0).ToList()).ToList(); for (int i = 0; i < attackers.Count; i++) { @@ -63,7 +63,8 @@ public PhaseFriendlyShelling(IKCDatabase kcDatabase, ApiFriendlyBattle apiFriend NightAirAttackFlag = nightAirAttackFlags[i] == -1, AttackType = attackTypes[i], DisplayEquipments = attackEquipments[i] - .Select(i => KcDatabase.MasterEquipments[i]) + .Select(id => KcDatabase.MasterEquipments[id]) + .OfType() .ToList(), }; @@ -89,7 +90,7 @@ public PhaseFriendlyShelling(IKCDatabase kcDatabase, ApiFriendlyBattle apiFriend } } - public override BattleFleets EmulateBattle(BattleFleets battleFleets) + public override BattleFleets EmulateBattle(BattleFleets battleFleets, List damages) { FleetsBeforePhase = battleFleets.Clone(); FleetsAfterPhase = battleFleets; @@ -141,7 +142,7 @@ public override BattleFleets EmulateBattle(BattleFleets battleFleets) private string GetDisplay() { - List values = new(); + List values = []; if (SearchlightFriend is not null) { diff --git a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseFriendlySupportInfo.cs b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseFriendlySupportInfo.cs index bbe4ef68d..53038e801 100644 --- a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseFriendlySupportInfo.cs +++ b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseFriendlySupportInfo.cs @@ -13,7 +13,7 @@ public class PhaseFriendlySupportInfo : PhaseBase { public override string Title => BattleRes.FriendlyFleet; - private List Ships { get; } = new(); + private List Ships { get; } = []; public string Display => CreateDisplay(); @@ -30,13 +30,14 @@ public PhaseFriendlySupportInfo(ApiFriendlyInfo apiFriendlyInfo) for (int i = 0; i < count; i++) { // this should be impossible - if (apiFriendlyInfo.ApiShipId[i] <= 0) + if (apiFriendlyInfo.ApiShipId[i] <= 0 || + KCDatabase.Instance.MasterShips[(int)apiFriendlyInfo.ApiShipId[i]] is not IShipDataMaster shipData) { Ships.Add(null); continue; } - ShipDataMock ship = new(KCDatabase.Instance.MasterShips[(int)apiFriendlyInfo.ApiShipId[i]]) + ShipDataMock ship = new(shipData) { Level = apiFriendlyInfo.ApiShipLv[i], HPCurrent = apiFriendlyInfo.ApiNowhps[i], @@ -44,7 +45,11 @@ public PhaseFriendlySupportInfo(ApiFriendlyInfo apiFriendlyInfo) .Append(apiFriendlyInfo.ApiSlotEx[i]) .Select(id => id switch { - > 0 => new EquipmentDataMock(KCDatabase.Instance.MasterEquipments[(int)id]), + > 0 => KCDatabase.Instance.MasterEquipments[(int)id] switch + { + IEquipmentDataMaster eq => new EquipmentDataMock(eq), + _ => null, + }, _ => null, }) .Cast() @@ -54,12 +59,12 @@ public PhaseFriendlySupportInfo(ApiFriendlyInfo apiFriendlyInfo) AABase = apiFriendlyInfo.ApiParam[i][2], ArmorBase = apiFriendlyInfo.ApiParam[i][3], }; - + Ships.Add(ship); } } - public override BattleFleets EmulateBattle(BattleFleets battleFleets) + public override BattleFleets EmulateBattle(BattleFleets battleFleets, List damages) { FleetsBeforePhase = battleFleets.Clone(); FleetsAfterPhase = battleFleets; diff --git a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseInitial.cs b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseInitial.cs index ed5a44f33..946382dbd 100644 --- a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseInitial.cs +++ b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseInitial.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Text; using System.Text.Json; @@ -21,16 +22,50 @@ public class PhaseInitial : PhaseBase private IKCDatabase KcDatabase { get; } + /// + /// 自軍艦隊ID + /// + public int FriendFleetID { get; private set; } + public bool IsEnemyCombinedFleet { get; } public int? ApiXal01 { get; } - private bool IsBossDamaged => ApiXal01 > 0; + public bool IsBossDamaged => ApiXal01 > 0; public List? ApiCombatRation { get; } public List? ApiCombatRationCombined { get; } - private List FriendInitialHPs { get; } - private List FriendMaxHPs { get; } + public List FriendInitialHPs { get; } + public List FriendMaxHPs { get; } + public List? FriendInitialHPsEscort { get; } + public List? FriendMaxHPsEscort { get; } + + public List EnemyMembersInstance { get; } + public List? EnemyMembersEscortInstance { get; } + + public int[] EnemyMembers => EnemyMembersInstance.Select(s => s?.MasterShip.ShipID ?? -1).ToArray(); + public int[] EnemyLevels => EnemyMembersInstance.Select(s => s?.Level ?? -1).ToArray(); + public List EnemyInitialHPs => EnemyMembersInstance.Select(s => s?.HPCurrent ?? -1).ToList(); + public int[] EnemyMaxHPs => EnemyMembersInstance.Select(s => s?.HPMax ?? -1).ToArray(); + public List> EnemyParameters { get; } + public int[][] EnemySlots => EnemyMembersInstance.Select(s => s?.SlotInstance.Select(e => e?.EquipmentID ?? -1).ToArray() ?? []).ToArray(); + public IEquipmentData?[][] EnemySlotsInstance => EnemyMembersInstance.Select(s => s?.SlotInstance.ToArray() ?? []).ToArray(); + + [MemberNotNullWhen(true, nameof(EnemyMembersEscort))] + [MemberNotNullWhen(true, nameof(EnemyMembersEscortInstance))] + [MemberNotNullWhen(true, nameof(EnemyLevelsEscort))] + [MemberNotNullWhen(true, nameof(EnemyInitialHPsEscort))] + [MemberNotNullWhen(true, nameof(EnemyMaxHPsEscort))] + [MemberNotNullWhen(true, nameof(EnemyParametersEscort))] + [MemberNotNullWhen(true, nameof(EnemySlotsEscort))] + [MemberNotNullWhen(true, nameof(EnemySlotsEscortInstance))] + public bool IsEnemyCombined => EnemyMembersEscortInstance is not null; + + public int[]? EnemyMembersEscort => EnemyMembersEscortInstance?.Select(s => s?.MasterShip.ShipID ?? -1).ToArray(); + public int[]? EnemyLevelsEscort => EnemyMembersEscortInstance?.Select(s => s?.Level ?? -1).ToArray(); + public List? EnemyInitialHPsEscort => EnemyMembersEscortInstance?.Select(s => s?.HPCurrent ?? -1).ToList(); + public int[]? EnemyMaxHPsEscort => EnemyMembersEscortInstance?.Select(s => s?.HPMax ?? -1).ToArray(); + public List>? EnemyParametersEscort { get; } + public int[][]? EnemySlotsEscort => EnemyMembersEscortInstance?.Select(s => s?.SlotInstance.Select(e => e?.EquipmentID ?? -1).ToArray() ?? []).ToArray(); + public IEquipmentData?[][]? EnemySlotsEscortInstance => EnemyMembersEscortInstance?.Select(s => s?.SlotInstance.ToArray() ?? []).ToArray(); - private List EnemyMembersInstance { get; } - private List? EnemyMembersEscortInstance { get; } private string PlayerMainFleetTitle => FleetsAfterPhase?.EscortFleet switch { @@ -170,6 +205,7 @@ public PhaseInitial(IKCDatabase kcDatabase, BattleFleets fleets, IBattleApiRespo { KcDatabase = kcDatabase; FleetsBeforePhase = fleets; + FriendFleetID = battle.ApiDeckId; if (battle is IAirBaseBattle { ApiAirBaseAttack: not null } abb) { @@ -203,40 +239,18 @@ public PhaseInitial(IKCDatabase kcDatabase, BattleFleets fleets, IBattleApiRespo Escape(fleets.Fleet, battle.ApiEscapeIdx); + EnemyParameters = battle.ApiEParam + .Concat(Enumerable.Repeat(0, 6).Select(_ => new List { 0, 0, 0, 0 })) + .Take(6) + .ToList(); + EnemyMembersInstance = battle.ApiShipKe .Zip(battle.ApiShipLv, (id, level) => (Id: id, Level: level)) .Zip(battle.ApiESlot, (t, equipment) => (t.Id, t.Level, Equipment: equipment)) .Zip(battle.ApiENowhps, (t, hp) => (t.Id, t.Level, t.Equipment, Hp: hp)) - .Select(t => t.Id switch - { - > 0 => new ShipDataMock(KcDatabase.MasterShips[t.Id]) - { - HPCurrent = t.Hp switch - { - JsonElement { ValueKind: JsonValueKind.Number } n => n.GetInt32(), - JsonElement { ValueKind: JsonValueKind.String } => KcDatabase.MasterShips[t.Id].HPMin, - _ => throw new NotImplementedException(), - }, - Level = t.Level, - Condition = 49, - SlotInstance = t.Equipment - .Select(id => id switch - { - > 0 => new EquipmentDataMock(KcDatabase.MasterEquipments[id]), - _ => null, - }) - .Cast() - .ToList(), - CanBeTargeted = t.Hp switch - { - JsonElement { ValueKind: JsonValueKind.Number } => true, - JsonElement { ValueKind: JsonValueKind.String } => false, - _ => throw new NotImplementedException(), - }, - }, - _ => null, - }) - .Cast() + .Select(t => MakeShip(KcDatabase, t.Id, t.Level, t.Equipment, t.Hp)) + .Concat(Enumerable.Repeat((IShipData?)null, 6)) + .Take(6) .ToList(); SetEnemyRange(EnemyMembersInstance); @@ -245,6 +259,9 @@ public PhaseInitial(IKCDatabase kcDatabase, BattleFleets fleets, IBattleApiRespo public PhaseInitial(IKCDatabase kcDatabase, BattleFleets fleets, IPlayerCombinedFleetBattle battle) : this(kcDatabase, fleets, (IBattleApiResponse)battle) { + FriendInitialHPsEscort = battle.ApiFNowhpsCombined; + FriendMaxHPsEscort = battle.ApiFMaxhpsCombined; + ApiCombatRationCombined = battle.ApiCombatRationCombined; SetEscortFleetParameters(fleets, battle); Escape(fleets.EscortFleet, battle.ApiEscapeIdxCombined); @@ -256,11 +273,19 @@ public PhaseInitial(IKCDatabase kcDatabase, BattleFleets fleets, IEnemyCombinedF IsEnemyCombinedFleet = true; EnemyMembersEscortInstance = MakeEnemyEscortFleet(battle); SetEnemyRange(EnemyMembersEscortInstance); + + EnemyParametersEscort = battle.ApiEParamCombined + .Concat(Enumerable.Repeat(0, 6).Select(_ => new List { 0, 0, 0, 0 })) + .Take(6) + .ToList(); } public PhaseInitial(IKCDatabase kcDatabase, BattleFleets fleets, ICombinedBattleApiResponse battle) : this(kcDatabase, fleets, (IBattleApiResponse)battle) { + FriendInitialHPsEscort = battle.ApiFNowhpsCombined; + FriendMaxHPsEscort = battle.ApiFMaxhpsCombined; + ApiCombatRationCombined = battle.ApiCombatRationCombined; SetEscortFleetParameters(fleets, battle); Escape(fleets.EscortFleet, battle.ApiEscapeIdxCombined); @@ -268,6 +293,11 @@ public PhaseInitial(IKCDatabase kcDatabase, BattleFleets fleets, ICombinedBattle IsEnemyCombinedFleet = true; EnemyMembersEscortInstance = MakeEnemyEscortFleet(battle); SetEnemyRange(EnemyMembersEscortInstance); + + EnemyParametersEscort = battle.ApiEParamCombined + .Concat(Enumerable.Repeat(0, 6).Select(_ => new List { 0, 0, 0, 0 })) + .Take(6) + .ToList(); } public PhaseInitial(IKCDatabase kcDatabase, BattleFleets fleets, ICombinedNightBattleApiResponse battle) @@ -288,34 +318,18 @@ public PhaseInitial(IKCDatabase kcDatabase, BattleFleets fleets, ApiDestructionB FriendInitialHPs = battle.ApiFNowhps; FriendMaxHPs = battle.ApiFMaxhps; + EnemyParameters = battle.ApiEParam + .Concat(Enumerable.Repeat(0, 6).Select(_ => new List { 0, 0, 0, 0 })) + .Take(6) + .ToList(); + EnemyMembersInstance = battle.ApiShipKe .Zip(battle.ApiShipLv, (id, level) => (Id: id, Level: level)) .Zip(battle.ApiESlot, (t, equipment) => (t.Id, t.Level, Equipment: equipment)) .Zip(battle.ApiENowhps, (t, hp) => (t.Id, t.Level, t.Equipment, Hp: hp)) - .Select(t => t.Id switch - { - > 0 => new ShipDataMock(KcDatabase.MasterShips[t.Id]) - { - HPCurrent = t.Hp switch - { - JsonElement { ValueKind: JsonValueKind.Number } n => n.GetInt32(), - JsonElement { ValueKind: JsonValueKind.String } => KcDatabase.MasterShips[t.Id].HPMin, - _ => throw new NotImplementedException(), - }, - Level = t.Level, - Condition = 49, - SlotInstance = t.Equipment - .Select(id => id switch - { - > 0 => new EquipmentDataMock(KcDatabase.MasterEquipments[id]), - _ => null, - }) - .Cast() - .ToList(), - }, - _ => null, - }) - .Cast() + .Select(t => MakeShip(KcDatabase, t.Id, t.Level, t.Equipment, t.Hp)) + .Concat(Enumerable.Repeat((IShipData?)null, 6)) + .Take(6) .ToList(); } @@ -364,28 +378,47 @@ private static void Escape(IFleetData? fleet, List? escapeIndexes) .Zip(battle.ApiShipLvCombined, (id, level) => (Id: id, Level: level)) .Zip(battle.ApiESlotCombined, (t, equipment) => (t.Id, t.Level, Equipment: equipment)) .Zip(battle.ApiENowhpsCombined, (t, hp) => (t.Id, t.Level, t.Equipment, Hp: hp)) - .Select(t => t.Id switch + .Select(t => MakeShip(KcDatabase, t.Id, t.Level, t.Equipment, t.Hp)) + .Concat(Enumerable.Repeat((IShipData?)null, 6)) + .Take(6) + .ToList(); + + private static ShipDataMock? MakeShip(IKCDatabase db, int shipId, int level, List equipmentIds, object hp) + { + if (shipId <= 0) return null; + + IShipDataMaster? ship = db.MasterShips[shipId]; + + if (ship is null) return null; + + return new(ship) { - > 0 => new ShipDataMock(KcDatabase.MasterShips[t.Id]) + HPCurrent = hp switch { - HPCurrent = t.Hp, - Level = t.Level, - Condition = 49, - SlotInstance = t.Equipment - .Select(id => id switch + int i => i, + JsonElement { ValueKind: JsonValueKind.Number } n => n.GetInt32(), + JsonElement { ValueKind: JsonValueKind.String } => ship.HPMin, + _ => throw new NotImplementedException(), + }, + Level = level, + Condition = 49, + SlotInstance = equipmentIds + .Select(id => id switch + { + > 0 => db.MasterEquipments[id] switch { - > 0 => new EquipmentDataMock(KcDatabase.MasterEquipments[id]), + IEquipmentDataMaster eq => new EquipmentDataMock(eq), _ => null, - }) - .Cast() - .ToList(), - }, - _ => null, - }) - .Cast() - .ToList(); + }, + _ => null, + }) + .Cast() + .ToList(), + CanBeTargeted = hp is not JsonElement { ValueKind: JsonValueKind.String }, + }; + } - private void SetEnemyRange(List ships) + private static void SetEnemyRange(List ships) { foreach (IShipData? ship in ships) { @@ -393,13 +426,13 @@ private void SetEnemyRange(List ships) s.Range = Math.Max(s.MasterShip.Range, s.AllSlotInstance switch { - [] => 0, - _ => s.AllSlotInstance.Max(s => s?.MasterEquipment.Range ?? 0), + [] => 0, + _ => s.AllSlotInstance.Max(e => e?.MasterEquipment.Range ?? 0), }); } } - public override BattleFleets EmulateBattle(BattleFleets battleFleets) + public override BattleFleets EmulateBattle(BattleFleets battleFleets, List damages) { battleFleets = FleetsBeforePhase!.Clone(); FleetsAfterPhase = battleFleets; diff --git a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseJetAirBattle.cs b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseJetAirBattle.cs index 35de85d7c..da846db46 100644 --- a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseJetAirBattle.cs +++ b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseJetAirBattle.cs @@ -1,13 +1,10 @@ -using ElectronicObserver.KancolleApi.Types.Models; +using ElectronicObserver.Core.Types.Data; +using ElectronicObserver.KancolleApi.Types.Models; namespace ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle.Phase; -public class PhaseJetAirBattle : PhaseAirBattleBase +public class PhaseJetAirBattle(IKCDatabase kcDatabase, ApiInjectionKouku apiInjectionKouku) + : PhaseAirBattleBase(kcDatabase, apiInjectionKouku) { public override string Title => BattleRes.BattlePhaseJet; - - public PhaseJetAirBattle(ApiInjectionKouku apiInjectionKouku) : base(apiInjectionKouku) - { - - } } diff --git a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseJetBaseAirAttack.cs b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseJetBaseAirAttack.cs index 04155b446..4e79cbb18 100644 --- a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseJetBaseAirAttack.cs +++ b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseJetBaseAirAttack.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using ElectronicObserver.Core.Types.Data; using ElectronicObserver.KancolleApi.Types.Models; namespace ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle.Phase; @@ -9,19 +10,19 @@ public class PhaseJetBaseAirAttack : PhaseBase public List Units { get; } = new(); - public PhaseJetBaseAirAttack(ApiAirBaseInjection apiAirBaseInjection) + public PhaseJetBaseAirAttack(IKCDatabase kcDatabase, ApiAirBaseInjection apiAirBaseInjection) { - Units.Add(new(apiAirBaseInjection, 0)); + Units.Add(new(kcDatabase, apiAirBaseInjection, 0)); } - public override BattleFleets EmulateBattle(BattleFleets battleFleets) + public override BattleFleets EmulateBattle(BattleFleets battleFleets, List damages) { FleetsBeforePhase = battleFleets.Clone(); FleetsAfterPhase = battleFleets; foreach (PhaseBaseAirAttackUnit attackUnit in Units) { - FleetsAfterPhase = attackUnit.EmulateBattle(FleetsAfterPhase); + FleetsAfterPhase = attackUnit.EmulateBattle(FleetsAfterPhase, damages); } return FleetsAfterPhase.Clone(); diff --git a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseNightBattle.cs b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseNightBattle.cs index edbeddccd..f4c94fdbd 100644 --- a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseNightBattle.cs +++ b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseNightBattle.cs @@ -9,13 +9,13 @@ namespace ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle.Phase; -public class PhaseNightBattle : PhaseBase +public class PhaseNightBattle : AttackPhaseBase { public override string Title => BattleRes.BattlePhaseNightBattle; private IKCDatabase KcDatabase { get; } - private List Attacks { get; } = new(); - public List AttackDisplays { get; } = new(); + private List Attacks { get; } = []; + public override List AttackDisplays { get; } = []; public PhaseNightBattle(IKCDatabase kcDatabase, List apiAtEflag, List apiAtList, List> apiClList, List> apiDamage, List> apiDfList, @@ -37,7 +37,7 @@ public PhaseNightBattle(IKCDatabase kcDatabase, List apiAtEflag, List List> defenders = apiDfList.Select(elem => elem.Where(e => e != -1).ToList()).ToList(); List> attackEquipments = apiSiList.Select(elem => elem.Select(ParseInt).ToList()).ToList(); List> criticals = apiClList.Select(elem => elem.Where(e => e != HitType.Invalid).ToList()).ToList(); - List> rawDamages = apiDamage.Select(elem => elem.Where(e => e != -1).ToList()).ToList(); + List> rawDamages = apiDamage.Select(elem => elem.Where(e => e >= 0).ToList()).ToList(); for (int i = 0; i < attackers.Count; i++) { @@ -47,7 +47,8 @@ public PhaseNightBattle(IKCDatabase kcDatabase, List apiAtEflag, List NightAirAttackFlag = nightAirAttackFlags[i] == -1, AttackType = attackTypes[i], DisplayEquipments = attackEquipments[i] - .Select(i => KcDatabase.MasterEquipments[i]) + .Select(id => KcDatabase.MasterEquipments[id]) + .OfType() .ToList(), }; @@ -73,7 +74,7 @@ public PhaseNightBattle(IKCDatabase kcDatabase, List apiAtEflag, List } } - public override BattleFleets EmulateBattle(BattleFleets battleFleets) + public override BattleFleets EmulateBattle(BattleFleets battleFleets, List damages) { FleetsBeforePhase = battleFleets.Clone(); FleetsAfterPhase = battleFleets; @@ -82,32 +83,7 @@ public override BattleFleets EmulateBattle(BattleFleets battleFleets) { if (atk.AttackType.IsSpecialAttack()) { - List attackers = atk.AttackType switch - { - NightAttackKind.CutinZuiun => Enumerable.Repeat(atk.Attacker.Index, 2).ToList(), - _ => atk.AttackType.SpecialAttackIndexes(), - }; - - int fleetCount = KCDatabase.Instance.Fleet.Fleets.Values - .Count(f => f.IsInSortie); - - for (int i = 0; i < atk.Defenders.Count; i++) - { - int attackerIndex = attackers[i]; - - PhaseNightBattleAttack comboAttack = atk with - { - Attacker = fleetCount switch - { - 2 => new(attackerIndex + 6, FleetFlag.Player), - _ => new(attackerIndex, FleetFlag.Player), - }, - Defenders = new() { atk.Defenders[i] }, - }; - - AttackDisplays.Add(new PhaseNightBattleAttackViewModel(FleetsAfterPhase, comboAttack, comboAttack.Defenders.First().Defender)); - AddDamage(FleetsAfterPhase, atk.Defenders[i].Defender, atk.Defenders[i].Damage); - } + ProcessSpecialAttack(atk, damages, FleetsAfterPhase); } else { @@ -115,10 +91,42 @@ public override BattleFleets EmulateBattle(BattleFleets battleFleets) { AttackDisplays.Add(new PhaseNightBattleAttackViewModel(FleetsAfterPhase, atk, atk.Defenders.First().Defender)); AddDamage(FleetsAfterPhase, defs.Key, defs.Sum(d => d.Damage)); + damages[atk.Attacker.ToFlatIndex()] += defs.Sum(d => d.Damage); } } } return FleetsAfterPhase.Clone(); } + + private void ProcessSpecialAttack(PhaseNightBattleAttack atk, List damages, BattleFleets fleetsAfterPhase) + { + List attackers = atk.AttackType switch + { + NightAttackKind.CutinZuiun => Enumerable.Repeat(atk.Attacker.Index, 2).ToList(), + _ => atk.AttackType.SpecialAttackIndexes(), + }; + + int fleetCount = KCDatabase.Instance.Fleet.Fleets.Values + .Count(f => f.IsInSortie); + + for (int i = 0; i < atk.Defenders.Count; i++) + { + int attackerIndex = attackers[i]; + + PhaseNightBattleAttack comboAttack = atk with + { + Attacker = fleetCount switch + { + 2 => new(attackerIndex + 6, FleetFlag.Player), + _ => new(attackerIndex, FleetFlag.Player), + }, + Defenders = [atk.Defenders[i]], + }; + + AttackDisplays.Add(new PhaseNightBattleAttackViewModel(fleetsAfterPhase, comboAttack, comboAttack.Defenders.First().Defender)); + AddDamage(fleetsAfterPhase, atk.Defenders[i].Defender, atk.Defenders[i].Damage); + damages[comboAttack.Attacker.ToFlatIndex()] += comboAttack.Defenders.Sum(d => d.Damage); + } + } } diff --git a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseNightBattleAttackViewModel.cs b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseNightBattleAttackViewModel.cs index 5af2d6170..e8ecba8e6 100644 --- a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseNightBattleAttackViewModel.cs +++ b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseNightBattleAttackViewModel.cs @@ -2,31 +2,42 @@ using System.Collections.Generic; using System.Linq; using ElectronicObserver.Core.Types; +using ElectronicObserver.Core.Types.Attacks; namespace ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle.Phase; public sealed class PhaseNightBattleAttackViewModel : AttackViewModelBase { - public BattleIndex AttackerIndex { get; } + public override BattleIndex AttackerIndex { get; } public IShipData Attacker { get; } public int AttackerHpBeforeAttack { get; } + public override string AttackerDisplay { get; } - public BattleIndex DefenderIndex { get; } + public override BattleIndex DefenderIndex { get; } public IShipData Defender { get; } - public List DefenderHpBeforeAttacks { get; } = new(); + public List DefenderHpBeforeAttacks { get; } = []; + public override string DefenderDisplay { get; } + public override double Damage { get; } + public NightAttackKind AttackType { get; } public List DisplayEquipment { get; } public List Attacks { get; } private IEquipmentData? UsedDamecon { get; } - public string DamageDisplay { get; } + + public override string DamageDisplay { get; } public PhaseNightBattleAttackViewModel(BattleFleets fleets, PhaseNightBattleAttack attack, BattleIndex defenderIndex) { AttackerIndex = attack.Attacker; Attacker = fleets.GetShip(AttackerIndex)!; + AttackerDisplay = $"{Attacker.Name} {AttackerIndex.Display}"; + DefenderIndex = defenderIndex; Defender = fleets.GetShip(DefenderIndex)!; + DefenderDisplay = $"{Defender.Name} {DefenderIndex.Display}"; + + AttackType = attack.AttackType; Attacks = attack.Defenders .Where(d => d.Defender == DefenderIndex) .Select(d => new NightAttack @@ -40,6 +51,7 @@ public PhaseNightBattleAttackViewModel(BattleFleets fleets, PhaseNightBattleAtta }) .ToList(); DisplayEquipment = attack.DisplayEquipments; + Damage = Attacks.Sum(a => a.Damage); AttackerHpBeforeAttack = Attacker.HPCurrent; DefenderHpBeforeAttacks.Add(Defender.HPCurrent); @@ -49,7 +61,7 @@ public PhaseNightBattleAttackViewModel(BattleFleets fleets, PhaseNightBattleAtta DefenderHpBeforeAttacks.Add(Math.Max(0, DefenderHpBeforeAttacks[^1] - nightAttack.Damage)); } - int hpAfterAttacks = Math.Max(0, Defender.HPCurrent - Attacks.Sum(a => a.Damage)); + int hpAfterAttacks = Math.Max(0, Defender.HPCurrent - (int)Damage); if (hpAfterAttacks <= 0 && GetDamecon(Defender) is { } damecon) { diff --git a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseNightInitial.cs b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseNightInitial.cs index 70b17fa6b..23e18e5ba 100644 --- a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseNightInitial.cs +++ b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseNightInitial.cs @@ -23,13 +23,13 @@ public class PhaseNightInitial : PhaseBase public int FlareIndexFriend { get; } public int FlareIndexEnemy { get; } - private IShipData? FlareFriend { get; } - private IShipData? FlareEnemy { get; } + public IShipData? FlareFriend { get; } + public IShipData? FlareEnemy { get; } public int SearchlightIndexFriend { get; } public int SearchlightIndexEnemy { get; } - private IShipData? SearchlightFriend { get; } - private IShipData? SearchlightEnemy { get; } + public IShipData? SearchlightFriend { get; } + public IShipData? SearchlightEnemy { get; } public IEquipmentData? SearchlightEquipmentFriend => GetSearchlight(SearchlightFriend); public IEquipmentData? SearchlightEquipmentEnemy => GetSearchlight(SearchlightEnemy); diff --git a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseOpeningTorpedo.cs b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseOpeningTorpedo.cs index 04826269b..da477026a 100644 --- a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseOpeningTorpedo.cs +++ b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseOpeningTorpedo.cs @@ -25,7 +25,7 @@ public PhaseOpeningTorpedo(ApiRaigekiClass apiRaigekiClass) ApiRaigekiClass = apiRaigekiClass; } - public override BattleFleets EmulateBattle(BattleFleets battleFleets) + public override BattleFleets EmulateBattle(BattleFleets battleFleets, List damages) { FleetsBeforePhase = battleFleets.Clone(); FleetsAfterPhase = battleFleets; @@ -45,6 +45,7 @@ public override BattleFleets EmulateBattle(BattleFleets battleFleets) { AttackDisplays.Add(new(FleetsAfterPhase, attack)); AddDamage(FleetsAfterPhase, attack.Defenders.First().Defender, attack.Defenders.First().Damage); + damages[attack.Attacker.ToFlatIndex()] += attack.Defenders.Sum(d => d.Damage); } return FleetsAfterPhase.Clone(); diff --git a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseSearching.cs b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseSearching.cs index cbb8d4feb..6351c9f48 100644 --- a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseSearching.cs +++ b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseSearching.cs @@ -4,19 +4,19 @@ namespace ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle.Phase; -public class PhaseSearching : PhaseBase +public class PhaseSearching(IFirstBattleApiResponse battle) : PhaseBase { public override string Title => BattleRes.PhaseSearching; - public FormationType PlayerFormationType { get; } - public FormationType EnemyFormationType { get; } - public EngagementType EngagementType { get; } + public FormationType PlayerFormationType { get; } = (FormationType)battle.ApiFormation[0]; + public FormationType EnemyFormationType { get; } = (FormationType)battle.ApiFormation[1]; + public EngagementType EngagementType { get; } = (EngagementType)battle.ApiFormation[2]; public DetectionType PlayerDetectionType { get; } public DetectionType EnemyDetectionType { get; } - public int? SmokeCount { get; } - public int? BalloonCell { get; } + public int? SmokeCount { get; } = battle.ApiSmokeType; + public int? BalloonCell { get; } = battle.ApiBalloonCell; public string Display => $""" {BattleRes.Formation}: {Constants.GetFormation(PlayerFormationType)} / {BattleRes.EnemyFormation}: {Constants.GetFormation(EnemyFormationType)} @@ -30,16 +30,6 @@ public class PhaseSearching : PhaseBase _ => "", }; - public PhaseSearching(IFirstBattleApiResponse battle) - { - PlayerFormationType = (FormationType)battle.ApiFormation[0]; - EnemyFormationType = (FormationType)battle.ApiFormation[1]; - EngagementType = (EngagementType)battle.ApiFormation[2]; - - SmokeCount = battle.ApiSmokeType; - BalloonCell = battle.ApiBalloonCell; - } - public PhaseSearching(IDaySearch battle) : this((IFirstBattleApiResponse)battle) { PlayerDetectionType = battle.ApiSearch[0]; diff --git a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseShelling.cs b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseShelling.cs index 4f86c84e3..d133f95a0 100644 --- a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseShelling.cs +++ b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseShelling.cs @@ -9,7 +9,7 @@ namespace ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle.Phase; -public class PhaseShelling : PhaseBase +public class PhaseShelling : AttackPhaseBase { public override string Title => DayShellingPhase switch { @@ -24,8 +24,8 @@ public class PhaseShelling : PhaseBase private ApiHougeki1 ShellingData { get; } public DayShellingPhase DayShellingPhase { get; } - private List Attacks { get; } = new(); - public List AttackDisplays { get; } = new(); + private List Attacks { get; } = []; + public override List AttackDisplays { get; } = []; public PhaseShelling(IKCDatabase kcDatabase, ApiHougeki1 shellingData, DayShellingPhase dayShellingPhase) { @@ -46,7 +46,7 @@ public PhaseShelling(IKCDatabase kcDatabase, ApiHougeki1 shellingData, DayShelli List> defenders = ShellingData.ApiDfList.Select(elem => elem.Where(e => e != -1).ToList()).ToList(); List> attackEquipments = ShellingData.ApiSiList.Select(elem => elem.Select(ParseInt).ToList()).ToList(); List> criticalFlags = ShellingData.ApiClList.Select(elem => elem.Where(e => e != HitType.Invalid).ToList()).ToList(); - List> rawDamages = ShellingData.ApiDamage.Select(elem => elem.Where(e => e != -1).ToList()).ToList(); + List> rawDamages = ShellingData.ApiDamage.Select(elem => elem.Where(e => e >= 0).ToList()).ToList(); for (int i = 0; i < attackers.Count; i++) { @@ -56,6 +56,7 @@ public PhaseShelling(IKCDatabase kcDatabase, ApiHougeki1 shellingData, DayShelli AttackType = attackTypes[i], DisplayEquipments = attackEquipments[i] .Select(id => KcDatabase.MasterEquipments[id]) + .OfType() .ToList(), }; @@ -81,7 +82,7 @@ public PhaseShelling(IKCDatabase kcDatabase, ApiHougeki1 shellingData, DayShelli } } - public override BattleFleets EmulateBattle(BattleFleets battleFleets) + public override BattleFleets EmulateBattle(BattleFleets battleFleets, List damages) { FleetsBeforePhase = battleFleets.Clone(); FleetsAfterPhase = battleFleets; @@ -97,11 +98,12 @@ public override BattleFleets EmulateBattle(BattleFleets battleFleets) PhaseShellingAttack comboAttack = atk with { Attacker = new(attackers[i], FleetFlag.Player), - Defenders = new() { atk.Defenders[i] }, + Defenders = [atk.Defenders[i]], }; AttackDisplays.Add(new PhaseShellingAttackViewModel(FleetsAfterPhase, comboAttack)); AddDamage(FleetsAfterPhase, atk.Defenders[i].Defender, atk.Defenders[i].Damage); + damages[comboAttack.Attacker.ToFlatIndex()] += comboAttack.Defenders.Sum(d => d.Damage); } } else @@ -110,6 +112,7 @@ public override BattleFleets EmulateBattle(BattleFleets battleFleets) { AttackDisplays.Add(new PhaseShellingAttackViewModel(FleetsAfterPhase, atk)); AddDamage(FleetsAfterPhase, defs.Key, defs.Sum(d => d.Damage)); + damages[atk.Attacker.ToFlatIndex()] += defs.Sum(d => d.Damage); } } } diff --git a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseShellingAttackViewModel.cs b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseShellingAttackViewModel.cs index 9a7d7ff5a..38155008a 100644 --- a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseShellingAttackViewModel.cs +++ b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseShellingAttackViewModel.cs @@ -9,26 +9,33 @@ namespace ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle.Phase public sealed class PhaseShellingAttackViewModel : AttackViewModelBase { - public BattleIndex AttackerIndex { get; } + public override BattleIndex AttackerIndex { get; } public IShipData Attacker { get; } public int AttackerHpBeforeAttack { get; } + public override string AttackerDisplay { get; } - public BattleIndex DefenderIndex { get; } + public override BattleIndex DefenderIndex { get; } public IShipData Defender { get; } - public List DefenderHpBeforeAttacks { get; } = new(); + public List DefenderHpBeforeAttacks { get; } = []; + public override string DefenderDisplay { get; } - private DayAttackKind AttackType { get; } + public override double Damage { get; } + public DayAttackKind AttackType { get; } public List DisplayEquipment { get; } public List Attacks { get; } private IEquipmentData? UsedDamecon { get; } - public string DamageDisplay { get; } + public override string DamageDisplay { get; } public PhaseShellingAttackViewModel(BattleFleets fleets, PhaseShellingAttack attack) { AttackerIndex = attack.Attacker; Attacker = fleets.GetShip(AttackerIndex)!; + AttackerDisplay = $"{Attacker.Name} {AttackerIndex.Display}"; + DefenderIndex = attack.Defenders.First().Defender; Defender = fleets.GetShip(DefenderIndex)!; + DefenderDisplay = $"{Defender.Name} {DefenderIndex.Display}"; + AttackType = ProcessAttack(Attacker, Defender, attack.AttackType); Attacks = attack.Defenders .Select(d => new DayAttack @@ -42,6 +49,7 @@ public PhaseShellingAttackViewModel(BattleFleets fleets, PhaseShellingAttack att }) .ToList(); DisplayEquipment = attack.DisplayEquipments; + Damage = Attacks.Sum(a => a.Damage); AttackerHpBeforeAttack = Attacker.HPCurrent; DefenderHpBeforeAttacks.Add(Defender.HPCurrent); @@ -51,7 +59,7 @@ public PhaseShellingAttackViewModel(BattleFleets fleets, PhaseShellingAttack att DefenderHpBeforeAttacks.Add(Math.Max(0, DefenderHpBeforeAttacks[^1] - dayAttack.Damage)); } - int hpAfterAttacks = Math.Max(0, Defender.HPCurrent - Attacks.Sum(a => a.Damage)); + int hpAfterAttacks = Math.Max(0, Defender.HPCurrent - (int)Damage); if (hpAfterAttacks <= 0 && GetDamecon(Defender) is { } damecon) { diff --git a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseSupport.cs b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseSupport.cs index 0bebe48a1..fff77aab7 100644 --- a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseSupport.cs +++ b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseSupport.cs @@ -8,7 +8,7 @@ namespace ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle.Phase; -public class PhaseSupport : PhaseBase +public class PhaseSupport : AttackPhaseBase { public override string Title => IsNightSupport switch { @@ -22,22 +22,22 @@ public class PhaseSupport : PhaseBase public int? Stage2FLostcount { get; } public int? Stage2FCount { get; } - private SupportType ApiSupportFlag { get; } + public SupportType SupportFlag { get; } private bool IsNightSupport { get; } private List Damages { get; } private List Criticals { get; } private int SupportFleetId { get; } - private IFleetData? SupportFleet { get; set; } + public IFleetData? SupportFleet { get; private set; } public string? SupportFleetDisplay => CreateDisplay(); - private List Attacks { get; } = new(); - public List AttackDisplays { get; } = new(); + private List Attacks { get; } = []; + public override List AttackDisplays { get; } = []; - public PhaseSupport(SupportType apiSupportFlag, ApiSupportInfo apiSupportInfo, bool isNightSupport) + public PhaseSupport(SupportType supportFlag, ApiSupportInfo apiSupportInfo, bool isNightSupport) { - ApiSupportFlag = apiSupportFlag; + SupportFlag = supportFlag; IsNightSupport = isNightSupport; static object? SupportAttack(SupportType apiSupportFlag, ApiSupportInfo apiSupportInfo) => apiSupportFlag switch @@ -47,17 +47,17 @@ public PhaseSupport(SupportType apiSupportFlag, ApiSupportInfo apiSupportInfo, b _ => null, }; - Damages = SupportAttack(apiSupportFlag, apiSupportInfo) switch + Damages = SupportAttack(supportFlag, apiSupportInfo) switch { ApiSupportAiratack attack when attack.ApiStageFlag[2] is not 0 => attack.ApiStage3.ApiEdam, ApiSupportHourai attack => attack.ApiDamage, - _ => new(), + _ => [], }; - Criticals = SupportAttack(apiSupportFlag, apiSupportInfo) switch + Criticals = SupportAttack(supportFlag, apiSupportInfo) switch { ApiSupportAiratack attack when attack.ApiStageFlag[2] is not 0 => attack.ApiStage3.ApiEclFlag.Select(h => h switch @@ -68,10 +68,10 @@ ApiSupportAiratack attack when attack.ApiStageFlag[2] is not 0 ApiSupportHourai attack => attack.ApiClList, - _ => new(), + _ => [], }; - SupportFleetId = SupportAttack(apiSupportFlag, apiSupportInfo) switch + SupportFleetId = SupportAttack(supportFlag, apiSupportInfo) switch { ApiSupportAiratack attack => attack.ApiDeckId, ApiSupportHourai attack => attack.ApiDeckId, @@ -89,7 +89,7 @@ ApiSupportAiratack attack when attack.ApiStageFlag[2] is not 0 } } - public override BattleFleets EmulateBattle(BattleFleets battleFleets) + public override BattleFleets EmulateBattle(BattleFleets battleFleets, List damages) { FleetsBeforePhase = battleFleets.Clone(); FleetsAfterPhase = battleFleets; @@ -107,16 +107,16 @@ public override BattleFleets EmulateBattle(BattleFleets battleFleets) { Attacks.Add(new() { - AttackType = ApiSupportFlag, - Defenders = new() - { + AttackType = SupportFlag, + Defenders = + [ new() { Defender = new(i, FleetFlag.Enemy), RawDamage = Damages[i], CriticalFlag = Criticals[i], }, - }, + ], }); } @@ -130,16 +130,16 @@ public override BattleFleets EmulateBattle(BattleFleets battleFleets) { Attacks.Add(new() { - AttackType = ApiSupportFlag, - Defenders = new() - { + AttackType = SupportFlag, + Defenders = + [ new() { Defender = new(i + 6, FleetFlag.Enemy), RawDamage = Damages[i + 6], CriticalFlag = Criticals[i + 6], }, - }, + ], }); } } diff --git a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseSupportAttackViewModel.cs b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseSupportAttackViewModel.cs index 7b879dcb4..050718f2a 100644 --- a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseSupportAttackViewModel.cs +++ b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseSupportAttackViewModel.cs @@ -7,21 +7,26 @@ namespace ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle.Phase public sealed class PhaseSupportAttackViewModel : AttackViewModelBase { - public string Attacker => BattleRes.SupportFleet; + public override BattleIndex? AttackerIndex => null; + public override string AttackerDisplay => BattleRes.SupportFleet; - public BattleIndex DefenderIndex { get; } + public override BattleIndex DefenderIndex { get; } public IShipData Defender { get; } - public List DefenderHpBeforeAttacks { get; } = new(); + private List DefenderHpBeforeAttacks { get; } = []; + public override string DefenderDisplay { get; } + public override double Damage { get; } private SupportType AttackType { get; } private List Attacks { get; } private IEquipmentData? UsedDamecon { get; } - public string DamageDisplay { get; } + public override string DamageDisplay { get; } public PhaseSupportAttackViewModel(BattleFleets fleets, PhaseSupportAttack attack) { DefenderIndex = attack.Defenders.First().Defender; Defender = fleets.GetShip(DefenderIndex)!; + DefenderDisplay = $"{Defender.Name} {DefenderIndex.Display}"; + AttackType = attack.AttackType; Attacks = attack.Defenders .Select(d => new SupportAttack @@ -33,6 +38,7 @@ public PhaseSupportAttackViewModel(BattleFleets fleets, PhaseSupportAttack attac CriticalFlag = d.CriticalFlag, }) .ToList(); + Damage = Attacks.Sum(a => a.Damage); DefenderHpBeforeAttacks.Add(Defender.HPCurrent); @@ -41,7 +47,7 @@ public PhaseSupportAttackViewModel(BattleFleets fleets, PhaseSupportAttack attac DefenderHpBeforeAttacks.Add(Math.Max(0, DefenderHpBeforeAttacks[^1] - supportAttack.Damage)); } - int hpAfterAttacks = Math.Max(0, Defender.HPCurrent - Attacks.Sum(a => a.Damage)); + int hpAfterAttacks = Math.Max(0, Defender.HPCurrent - (int)Damage); if (hpAfterAttacks <= 0 && GetDamecon(Defender) is { } damecon) { diff --git a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseTorpedo.cs b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseTorpedo.cs index 5f3386c98..5c1f30ca3 100644 --- a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseTorpedo.cs +++ b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseTorpedo.cs @@ -6,9 +6,9 @@ namespace ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle.Phase; -public abstract class PhaseTorpedo : PhaseBase +public abstract class PhaseTorpedo : AttackPhaseBase { - public List AttackDisplays { get; } = []; + public override List AttackDisplays { get; } = []; protected static PhaseTorpedoAttack MakeAttack(int attackerIndex, int targetIndex, FleetFlag fleetFlag, List targets, List damages, List attackDamages, List criticalFlags) diff --git a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseTorpedoAttack.cs b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseTorpedoAttack.cs index adb7a79b3..a59144b39 100644 --- a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseTorpedoAttack.cs +++ b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseTorpedoAttack.cs @@ -5,7 +5,7 @@ namespace ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle.Phase public record PhaseTorpedoAttack { - public BattleIndex Attacker { get; init; } + public required BattleIndex Attacker { get; init; } public DayAttackKind AttackType { get; init; } - public List Defenders { get; init; } = new(); + public List Defenders { get; init; } = []; } diff --git a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseTorpedoAttackViewModel.cs b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseTorpedoAttackViewModel.cs index 2cb280d0a..81839adee 100644 --- a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseTorpedoAttackViewModel.cs +++ b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/Phase/PhaseTorpedoAttackViewModel.cs @@ -9,25 +9,32 @@ namespace ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle.Phase public sealed class PhaseTorpedoAttackViewModel : AttackViewModelBase { - public BattleIndex AttackerIndex { get; } + public override BattleIndex AttackerIndex { get; } public IShipData Attacker { get; } public int AttackerHpBeforeAttack { get; } + public override string AttackerDisplay { get; } - public BattleIndex DefenderIndex { get; } + public override BattleIndex DefenderIndex { get; } public IShipData Defender { get; } - public List DefenderHpBeforeAttacks { get; } = new(); + private List DefenderHpBeforeAttacks { get; } = []; + public override string DefenderDisplay { get; } + public override double Damage { get; } private DayAttackKind AttackType { get; } public List Attacks { get; } private IEquipmentData? UsedDamecon { get; } - public string DamageDisplay { get; } + public override string DamageDisplay { get; } public PhaseTorpedoAttackViewModel(BattleFleets fleets, PhaseTorpedoAttack attack) { AttackerIndex = attack.Attacker; Attacker = fleets.GetShip(AttackerIndex)!; + AttackerDisplay = $"{Attacker.Name} {AttackerIndex.Display}"; + DefenderIndex = attack.Defenders.First().Defender; Defender = fleets.GetShip(DefenderIndex)!; + DefenderDisplay = $"{Defender.Name} {DefenderIndex.Display}"; + AttackType = ProcessAttack(Attacker, Defender, attack.AttackType); Attacks = attack.Defenders .Select(d => new DayAttack @@ -40,6 +47,7 @@ public PhaseTorpedoAttackViewModel(BattleFleets fleets, PhaseTorpedoAttack attac CriticalFlag = d.CriticalFlag, }) .ToList(); + Damage = Attacks.Sum(a => a.Damage); AttackerHpBeforeAttack = Attacker.HPCurrent; DefenderHpBeforeAttacks.Add(Defender.HPCurrent); @@ -49,7 +57,7 @@ public PhaseTorpedoAttackViewModel(BattleFleets fleets, PhaseTorpedoAttack attac DefenderHpBeforeAttacks.Add(Math.Max(0, DefenderHpBeforeAttacks[^1] - dayAttack.Damage)); } - int hpAfterAttacks = Math.Max(0, Defender.HPCurrent - Attacks.Sum(a => a.Damage)); + int hpAfterAttacks = Math.Max(0, Defender.HPCurrent - (int)Damage); if (hpAfterAttacks <= 0 && GetDamecon(Defender) is { } damecon) { diff --git a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/RadarBattleData.cs b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/RadarBattleData.cs index a1de64ac0..089265ce6 100644 --- a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/RadarBattleData.cs +++ b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/RadarBattleData.cs @@ -1,12 +1,13 @@ using ElectronicObserver.KancolleApi.Types.Interfaces; +using ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle.Interfaces; using ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle.Phase; namespace ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle; -public abstract class RadarBattleData : FirstBattleData +public abstract class RadarBattleData : FirstBattleData, IBaseAirAttack { protected PhaseJetBaseAirAttack? JetBaseAirAttack { get; } - protected PhaseBaseAirAttack? BaseAirAttack { get; } + public PhaseBaseAirAttack? BaseAirAttack { get; } protected PhaseRadar? Shelling1 { get; } protected RadarBattleData(PhaseFactory phaseFactory, BattleFleets fleets, IRadarBattleApiResponse battle) diff --git a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/SecondNightBattleData.cs b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/SecondNightBattleData.cs index 7593b9624..1c7164af3 100644 --- a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/SecondNightBattleData.cs +++ b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Battle/SecondNightBattleData.cs @@ -1,11 +1,12 @@ using ElectronicObserver.KancolleApi.Types.Interfaces; +using ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle.Interfaces; using ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle.Phase; namespace ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle; -public abstract class SecondNightBattleData : BattleData +public abstract class SecondNightBattleData : BattleData, INightInitial { - protected PhaseNightInitial? NightInitial { get; } + public PhaseNightInitial? NightInitial { get; } protected PhaseFriendlySupportInfo? FriendlySupportInfo { get; } protected PhaseFriendlyShelling? FriendlyShelling { get; } protected PhaseNightBattle? NightBattle { get; } diff --git a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Node/BattleNode.cs b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Node/BattleNode.cs index 649629e7d..4f228fd07 100644 --- a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Node/BattleNode.cs +++ b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Node/BattleNode.cs @@ -49,7 +49,7 @@ public void AddResult(ISortieBattleResultApi result) _ => new(result), }; - ResultRank = string.Format(ConstantsRes.BattleDetail_ResultRank, BattleResult.WinRank); + ResultRank = string.Format(ConstantsRes.BattleDetail_ResultRank, BattleResult.Rank); ResultMvpMain = BattleResult.MvpIndex switch { @@ -107,10 +107,10 @@ public void AddResult(ISortieBattleResultApi result) bool damageTaken = hpBeforeBattle > hpAfterBattle; - return (BattleResult?.WinRank, damageTaken) switch + return (BattleResult?.Rank, damageTaken) switch { ("S", false) => "SS", - _ => BattleResult?.WinRank, + _ => BattleResult?.Rank, }; } diff --git a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Node/BattleResult.cs b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Node/BattleResult.cs index 31eac2934..2fd881e0c 100644 --- a/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Node/BattleResult.cs +++ b/ElectronicObserver/Window/Tools/SortieRecordViewer/Sortie/Node/BattleResult.cs @@ -2,6 +2,7 @@ using System.Linq; using ElectronicObserver.Core.Types; using ElectronicObserver.KancolleApi.Types.ApiReqCombinedBattle.Battleresult; +using ElectronicObserver.KancolleApi.Types.ApiReqPractice.BattleResult; using ElectronicObserver.KancolleApi.Types.Interfaces; using ElectronicObserver.KancolleApi.Types.Models; @@ -9,7 +10,7 @@ namespace ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Node; public class BattleResult { - public string WinRank { get; } + public string Rank { get; } public int AdmiralExp { get; } public int MvpIndex { get; } public int? MvpIndexCombined { get; } @@ -37,7 +38,7 @@ public class BattleResult public BattleResult(ISortieBattleResultApi result) { - WinRank = result.ApiWinRank; + Rank = result.ApiWinRank; AdmiralExp = result.ApiGetExp; MvpIndex = result.ApiMvp - 1; BaseExp = result.ApiGetBaseExp; @@ -62,4 +63,15 @@ public BattleResult(ApiReqCombinedBattleBattleresultResponse result) ExpListCombined = result.ApiGetShipExpCombined; LevelUpListCombined = result.ApiGetExpLvupCombined; } + + public BattleResult(ApiReqPracticeBattleResultResponse result) + { + Rank = result.ApiWinRank; + AdmiralExp = result.ApiGetExp; + MvpIndex = result.ApiMvp - 1; + BaseExp = result.ApiGetBaseExp; + ExpList = result.ApiGetShipExp; + LevelUpList = result.ApiGetExpLvup; + EnemyFleetName = result.ApiEnemyInfo.ApiDeckName; + } } diff --git a/ElectronicObserver/Window/Tools/SortieRecordViewer/SortieCostViewer/AirBaseCostCalculator.cs b/ElectronicObserver/Window/Tools/SortieRecordViewer/SortieCostViewer/AirBaseCostCalculator.cs index abcc9a3b9..cf80cb1e1 100644 --- a/ElectronicObserver/Window/Tools/SortieRecordViewer/SortieCostViewer/AirBaseCostCalculator.cs +++ b/ElectronicObserver/Window/Tools/SortieRecordViewer/SortieCostViewer/AirBaseCostCalculator.cs @@ -140,7 +140,7 @@ private static int GetAircraftLossFromRaid(SortieDetailViewModel sortieDetails) .FirstOrDefault() ?.Units .DistinctBy(u => u.AirBaseId) - .Select(u => u.Stage1FCount); + .Select(u => u.AircraftTotalStage1Friend); if (aircraftInBattle is null) return 0; @@ -168,11 +168,11 @@ private static int GetAircraftLossFromAirBattles(IEnumerable nodes) .SelectMany(n => n.AllPhases) .Sum(p => p switch { - PhaseBaseAirRaid r => r.Stage1FLostcount + r.Stage2FLostcount, + PhaseBaseAirRaid r => r.AircraftLostStage1Friend + r.AircraftLostStage2Friend, PhaseBaseAirAttack r => r.Units .Select((u, i) => (i % 2) switch { - 1 => u.Stage1FLostcount + u.Stage2FLostcount, + 1 => u.AircraftLostStage1Friend + u.AircraftLostStage2Friend, _ => 0, }) .Sum(), diff --git a/ElectronicObserver/Window/Tools/SortieRecordViewer/SortieCostViewer/SupplyCostCalculator.cs b/ElectronicObserver/Window/Tools/SortieRecordViewer/SortieCostViewer/SupplyCostCalculator.cs index 54a1aa045..5e5305a9e 100644 --- a/ElectronicObserver/Window/Tools/SortieRecordViewer/SortieCostViewer/SupplyCostCalculator.cs +++ b/ElectronicObserver/Window/Tools/SortieRecordViewer/SortieCostViewer/SupplyCostCalculator.cs @@ -263,7 +263,7 @@ private static SortieCostModel CalculateSupplyCost(SortieDetailViewModel details { bauxite += battleNode.FirstBattle.Phases .OfType() - .Sum(b => b.Stage1FLostcount + b.Stage2FLostcount) * 5; + .Sum(b => b.AircraftLostStage1Friend + b.AircraftLostStage2Friend) * 5; if (battleNode.BattleResult is null) continue; diff --git a/ElectronicObserver/Window/Tools/SortieRecordViewer/SortieDetail/PhaseControl.xaml b/ElectronicObserver/Window/Tools/SortieRecordViewer/SortieDetail/PhaseControl.xaml index 48422bae8..8929a3b5e 100644 --- a/ElectronicObserver/Window/Tools/SortieRecordViewer/SortieDetail/PhaseControl.xaml +++ b/ElectronicObserver/Window/Tools/SortieRecordViewer/SortieDetail/PhaseControl.xaml @@ -80,7 +80,7 @@ - + @@ -92,7 +92,7 @@ - + @@ -104,7 +104,7 @@ - + diff --git a/ElectronicObserver/Window/Wpf/Battle/BattleView.xaml.cs b/ElectronicObserver/Window/Wpf/Battle/BattleView.xaml.cs index eacee4bc2..e74dc5360 100644 --- a/ElectronicObserver/Window/Wpf/Battle/BattleView.xaml.cs +++ b/ElectronicObserver/Window/Wpf/Battle/BattleView.xaml.cs @@ -27,9 +27,6 @@ public BattleView() // not really sure how to do this mvvm style private void FrameworkElement_OnContextMenuOpening(object sender, ContextMenuEventArgs e) { - var bm = KCDatabase.Instance.Battle; - - if (bm == null || bm.BattleMode == BattleManager.BattleModes.Undefined) - e.Handled = true; + e.Handled = KCDatabase.Instance.Battle.FirstBattle is null; } } diff --git a/ElectronicObserver/Window/Wpf/Battle/BattleViewModel.cs b/ElectronicObserver/Window/Wpf/Battle/BattleViewModel.cs index 6989bf21f..2a57017d2 100644 --- a/ElectronicObserver/Window/Wpf/Battle/BattleViewModel.cs +++ b/ElectronicObserver/Window/Wpf/Battle/BattleViewModel.cs @@ -11,15 +11,18 @@ using ElectronicObserver.Core.Types.AntiAir; using ElectronicObserver.Data; using ElectronicObserver.Data.Battle; -using ElectronicObserver.Data.Battle.Detail; -using ElectronicObserver.Data.Battle.Phase; using ElectronicObserver.Observer; using ElectronicObserver.Resource; using ElectronicObserver.Utility; using ElectronicObserver.ViewModels; using ElectronicObserver.ViewModels.Translations; using ElectronicObserver.Window.Dialog.BattleDetail; +using ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle; +using ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle.Interfaces; +using ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle.Phase; +using ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Node; using ElectronicObserver.Window.Wpf.Battle.ViewModels; +using BattleIndex = ElectronicObserver.Data.Battle.BattleIndex; using Color = System.Drawing.Color; namespace ElectronicObserver.Window.Wpf.Battle; @@ -201,7 +204,7 @@ public BattleViewModel() : base("Battle", "Battle", IconContent.FormBattle) o.ApiReqPractice_MidnightBattle.ResponseReceived += Updated; o.ApiReqPractice_BattleResult.ResponseReceived += Updated; - PropertyChanged += (sender, args) => + PropertyChanged += (_, args) => { if (args.PropertyName is not nameof(CompactMode)) return; @@ -220,9 +223,9 @@ public BattleViewModel() : base("Battle", "Battle", IconContent.FormBattle) [RelayCommand] private void ShowBattleDetail() { - BattleManager? bm = KCDatabase.Instance.Battle; + BattleManager bm = KCDatabase.Instance.Battle; - if (bm == null || bm.BattleMode == BattleManager.BattleModes.Undefined) return; + if (bm.FirstBattle is null) return; BattleDetailView dialog = new(new BattleDetailViewModel { @@ -239,6 +242,7 @@ private void ShowBattleResult() PlayerFleetVisible = true; } + [SuppressMessage("Critical Code Smell", "S3776:Cognitive Complexity of methods should not be too high", Justification = "todo")] private void Updated(string apiname, dynamic data) { KCDatabase db = KCDatabase.Instance; @@ -255,7 +259,7 @@ private void Updated(string apiname, dynamic data) case "api_req_map/start": case "api_req_map/next": - if (!bm.Compass.HasAirRaid) + if (bm.FirstBattle is null) { ViewVisible = false; break; @@ -264,8 +268,8 @@ private void Updated(string apiname, dynamic data) SetFormation(bm); ClearSearchingResult(); ClearBaseAirAttack(); - SetAerialWarfare(null, ((BattleBaseAirRaid)bm.BattleDay).BaseAirRaid); - SetHPBar(bm.BattleDay); + SetAerialWarfare(null, ((BattleBaseAirRaid)bm.FirstBattle).BaseAirRaid); + SetHPBar(bm.FirstBattle); SetDamageRate(bm); ViewVisible = !hideDuringBattle; @@ -297,10 +301,19 @@ private void Updated(string apiname, dynamic data) { SetFormation(bm); - SetSearchingResult(bm.BattleDay); - SetBaseAirAttack(bm.BattleDay.BaseAirAttack); - SetAerialWarfare(bm.BattleDay.JetAirBattle, bm.BattleDay.AirBattle); - SetHPBar(bm.BattleDay); + SetSearchingResult(bm.FirstBattle); + + if (bm.FirstBattle is IBaseAirAttack baa) + { + SetBaseAirAttack(baa.BaseAirAttack); + } + + if (bm.FirstBattle is IAirBattle ab) + { + SetAerialWarfare(ab.JetAirBattle, ab.AirBattle); + } + + SetHPBar(bm.FirstBattle); SetDamageRate(bm); // BaseLayoutPanel.Visible = !hideDuringBattle; @@ -312,9 +325,10 @@ private void Updated(string apiname, dynamic data) case "api_req_battle_midnight/battle": case "api_req_practice/midnight_battle": { + if (bm.SecondBattle is not INightInitial b) return; - SetNightBattleEvent(bm.BattleNight.NightInitial); - SetHPBar(bm.BattleNight); + SetNightBattleEvent(b.NightInitial); + SetHPBar(bm.SecondBattle); SetDamageRate(bm); // BaseLayoutPanel.Visible = !hideDuringBattle; @@ -325,13 +339,14 @@ private void Updated(string apiname, dynamic data) case "api_req_battle_midnight/sp_midnight": { + if (bm.FirstBattle is not INightInitial b) return; SetFormation(bm); ClearBaseAirAttack(); ClearAerialWarfare(); ClearSearchingResult(); - SetNightBattleEvent(bm.BattleNight.NightInitial); - SetHPBar(bm.BattleNight); + SetNightBattleEvent(b.NightInitial); + SetHPBar(bm.FirstBattle); SetDamageRate(bm); // BaseLayoutPanel.Visible = !hideDuringBattle; @@ -342,12 +357,13 @@ private void Updated(string apiname, dynamic data) case "api_req_sortie/airbattle": { + if (bm.FirstBattle is not BattleAirBattle bab) return; SetFormation(bm); - SetSearchingResult(bm.BattleDay); - SetBaseAirAttack(bm.BattleDay.BaseAirAttack); - SetAerialWarfare(bm.BattleDay.JetAirBattle, bm.BattleDay.AirBattle, ((BattleAirBattle)bm.BattleDay).AirBattle2); - SetHPBar(bm.BattleDay); + SetSearchingResult(bab); + SetBaseAirAttack(bab.BaseAirAttack); + SetAerialWarfare(bab.JetAirBattle, bab.AirBattle, bab.AirBattle2); + SetHPBar(bab); SetDamageRate(bm); // BaseLayoutPanel.Visible = !hideDuringBattle; @@ -358,8 +374,7 @@ private void Updated(string apiname, dynamic data) case "api_req_sortie/night_to_day": { - // 暫定 - var battle = bm.BattleNight as BattleDayFromNight; + if (bm.FirstBattle is not BattleNormalDayFromNight battle) return; SetFormation(bm); ClearAerialWarfare(); @@ -374,7 +389,7 @@ private void Updated(string apiname, dynamic data) SetAerialWarfare(battle.JetAirBattle, battle.AirBattle); } - SetHPBar(bm.BattleDay); + SetHPBar(bm.FirstBattle); SetDamageRate(bm); // BaseLayoutPanel.Visible = !hideDuringBattle; @@ -393,10 +408,19 @@ private void Updated(string apiname, dynamic data) { SetFormation(bm); - SetSearchingResult(bm.BattleDay); - SetBaseAirAttack(bm.BattleDay.BaseAirAttack); - SetAerialWarfare(bm.BattleDay.JetAirBattle, bm.BattleDay.AirBattle); - SetHPBar(bm.BattleDay); + SetSearchingResult(bm.FirstBattle); + + if (bm.FirstBattle is IBaseAirAttack baa) + { + SetBaseAirAttack(baa.BaseAirAttack); + } + + if (bm.FirstBattle is IAirBattle ab) + { + SetAerialWarfare(ab.JetAirBattle, ab.AirBattle); + } + + SetHPBar(bm.FirstBattle); SetDamageRate(bm); // BaseLayoutPanel.Visible = !hideDuringBattle; @@ -407,12 +431,13 @@ private void Updated(string apiname, dynamic data) case "api_req_combined_battle/airbattle": { + if (bm.FirstBattle is not BattleCombinedAirBattle bcab) return; SetFormation(bm); - SetSearchingResult(bm.BattleDay); - SetBaseAirAttack(bm.BattleDay.BaseAirAttack); - SetAerialWarfare(bm.BattleDay.JetAirBattle, bm.BattleDay.AirBattle, ((BattleCombinedAirBattle)bm.BattleDay).AirBattle2); - SetHPBar(bm.BattleDay); + SetSearchingResult(bcab); + SetBaseAirAttack(bcab.BaseAirAttack); + SetAerialWarfare(bcab.JetAirBattle, bcab.AirBattle, bcab.AirBattle2); + SetHPBar(bcab); SetDamageRate(bm); // BaseLayoutPanel.Visible = !hideDuringBattle; @@ -424,9 +449,10 @@ private void Updated(string apiname, dynamic data) case "api_req_combined_battle/midnight_battle": case "api_req_combined_battle/ec_midnight_battle": { + if (bm.SecondBattle is not INightInitial b) break; - SetNightBattleEvent(bm.BattleNight.NightInitial); - SetHPBar(bm.BattleNight); + SetNightBattleEvent(b.NightInitial); + SetHPBar(bm.SecondBattle); SetDamageRate(bm); // BaseLayoutPanel.Visible = !hideDuringBattle; @@ -437,13 +463,14 @@ private void Updated(string apiname, dynamic data) case "api_req_combined_battle/sp_midnight": { + if (bm.FirstBattle is not INightInitial b) break; SetFormation(bm); ClearAerialWarfare(); ClearSearchingResult(); ClearBaseAirAttack(); - SetNightBattleEvent(bm.BattleNight.NightInitial); - SetHPBar(bm.BattleNight); + SetNightBattleEvent(b.NightInitial); + SetHPBar(bm.SecondBattle); SetDamageRate(bm); // BaseLayoutPanel.Visible = !hideDuringBattle; @@ -454,7 +481,7 @@ private void Updated(string apiname, dynamic data) case "api_req_combined_battle/ec_night_to_day": { - var battle = bm.BattleNight as BattleDayFromNight; + if (bm.FirstBattle is not DayFromNightBattleData battle) break; SetFormation(bm); ClearAerialWarfare(); @@ -512,13 +539,15 @@ private void Updated(string apiname, dynamic data) ///
private void SetFormation(BattleManager bm) { - FormationFriendText = Constants.GetFormationShort(bm.FirstBattle.Searching.FormationFriend); - FormationEnemyText = Constants.GetFormationShort(bm.FirstBattle.Searching.FormationEnemy); - FormationText = Constants.GetEngagementForm(bm.FirstBattle.Searching.EngagementForm); + if (bm.FirstBattle is not { Searching: { } searching }) return; + + FormationFriendText = Constants.GetFormationShort(searching.PlayerFormationType); + FormationEnemyText = Constants.GetFormationShort(searching.EnemyFormationType); + FormationText = Constants.GetEngagementForm(searching.EngagementType); - if (bm.IsEnemyCombined && bm.StartsFromDayBattle) + if (bm.IsEnemyCombined) { // highlights for the fleet you'll fight in night battle // todo: this should probably go to config @@ -563,10 +592,10 @@ private void SetFormation(BattleManager bm) FleetEnemyBackColor = FleetEnemyEscortBackColor = Color.Transparent.ToBrush(); } - FormationForeColor = (bm.FirstBattle.Searching.EngagementForm switch + FormationForeColor = (searching.EngagementType switch { - 3 => Configuration.Config.UI.Color_Green, - 4 => Configuration.Config.UI.Color_Red, + EngagementType.TAdvantage => Configuration.Config.UI.Color_Green, + EngagementType.TDisadvantage => Configuration.Config.UI.Color_Red, _ => Configuration.Config.UI.ForeColor, }).ToBrush(); } @@ -574,29 +603,31 @@ private void SetFormation(BattleManager bm) /// /// 索敵結果を設定します。 /// - private void SetSearchingResult(BattleData bd) + private void SetSearchingResult(FirstBattleData? bd) { - int search = bd.Searching.SearchingFriend; + if (bd is not { Searching: { } searching }) return; + + DetectionType search = searching.PlayerDetectionType; SearchingFriendText = Constants.GetSearchingResultShort(search); SearchingFriendIcon = search switch { <= 0 => null, - < 4 => EquipmentIconType.Seaplane, + < DetectionType.Failure => EquipmentIconType.Seaplane, _ => EquipmentIconType.Radar, }; SearchingFriendToolTip = null; - Smoker1Active = bd.Searching.SmokeCount >= 1; - Smoker2Active = bd.Searching.SmokeCount >= 2; - Smoker3Active = bd.Searching.SmokeCount >= 3; + Smoker1Active = searching.SmokeCount >= 1; + Smoker2Active = searching.SmokeCount >= 2; + Smoker3Active = searching.SmokeCount >= 3; - search = bd.Searching.SearchingEnemy; + search = searching.EnemyDetectionType; SearchingEnemyText = Constants.GetSearchingResultShort(search); SearchingEnemyIcon = search switch { <= 0 => null, - < 4 => EquipmentIconType.Seaplane, + < DetectionType.Failure => EquipmentIconType.Seaplane, _ => EquipmentIconType.Radar, }; SearchingEnemyToolTip = null; @@ -623,9 +654,9 @@ private void ClearSearchingResult() /// /// 基地航空隊フェーズの結果を設定します。 /// - private void SetBaseAirAttack(PhaseBaseAirAttack pd) + private void SetBaseAirAttack(PhaseBaseAirAttack? pd) { - if (pd?.IsAvailable != true) + if (pd is null) { ClearBaseAirAttack(); return; @@ -637,10 +668,10 @@ private void SetBaseAirAttack(PhaseBaseAirAttack pd) StringBuilder sb = new(); int index = 1; - foreach (PhaseBaseAirAttack.PhaseBaseAirAttackUnit phase in pd.AirAttackUnits) + foreach (PhaseBaseAirAttackUnit phase in pd.Units) { sb.AppendFormat(GeneralRes.BaseWave + " - " + GeneralRes.BaseAirCorps + " :\r\n", - index, phase.AirUnitID); + index, phase.AirBaseId); if (phase.IsStage1Available) { @@ -649,7 +680,7 @@ private void SetBaseAirAttack(PhaseBaseAirAttack pd) " -{2}/{3} | {4}\r\n", phase.AircraftLostStage1Friend, phase.AircraftTotalStage1Friend, phase.AircraftLostStage1Enemy, phase.AircraftTotalStage1Enemy, - Constants.GetAirSuperiority(phase.AirSuperiority)); + Constants.GetAirSuperiority(phase.AirState)); } if (phase.IsStage2Available) @@ -679,19 +710,13 @@ private void ClearBaseAirAttack() /// /// 航空戦表示用ヘルパー /// - private sealed class AerialWarfareFormatter + private sealed class AerialWarfareFormatter(IPhaseAirBattle? air, string phaseName) { - public PhaseAirBattleBase? Air { get; } - public string PhaseName { get; set; } - - public AerialWarfareFormatter(PhaseAirBattleBase? air, string phaseName) - { - Air = air; - PhaseName = phaseName; - } + public IPhaseAirBattle? Air { get; } = air; + public string PhaseName { get; set; } = phaseName; [MemberNotNullWhen(true, nameof(Air))] - public bool Enabled => Air is { IsAvailable: true }; + public bool Enabled => Air is not null; [MemberNotNullWhen(true, nameof(Air))] public bool Stage1Enabled => Enabled && Air.IsStage1Available; @@ -732,7 +757,7 @@ private static ArgumentOutOfRangeException InvalidStage(int phase) => _ => throw InvalidStage(stage), }; - public int GetTouchAircraft(bool isFriend) => isFriend switch + public string? GetTouchAircraft(bool isFriend) => isFriend switch { true when Enabled => Air.TouchAircraftFriend, _ when Enabled => Air.TouchAircraftEnemy, @@ -740,7 +765,7 @@ private static ArgumentOutOfRangeException InvalidStage(int phase) => }; } - private void SetAerialWarfare(PhaseAirBattleBase? phaseJet, PhaseAirBattleBase phase1) + private void SetAerialWarfare(IPhaseAirBattle? phaseJet, IPhaseAirBattle? phase1) => SetAerialWarfare(phaseJet, phase1, null); /// @@ -749,7 +774,8 @@ private void SetAerialWarfare(PhaseAirBattleBase? phaseJet, PhaseAirBattleBase p /// 噴式航空戦のデータ。発生していなければ null /// 第一次航空戦(通常航空戦)のデータ。 /// 第二次航空戦のデータ。発生していなければ null - private void SetAerialWarfare(PhaseAirBattleBase? phaseJet, PhaseAirBattleBase phase1, PhaseAirBattleBase? phase2) + [SuppressMessage("Critical Code Smell", "S3776:Cognitive Complexity of methods should not be too high", Justification = "todo")] + private void SetAerialWarfare(IPhaseAirBattle? phaseJet, IPhaseAirBattle? phase1, IPhaseAirBattle? phase2) { List phases = new() { @@ -811,13 +837,11 @@ void ClearAACutinLabel() .Where(p => p.Stage1Enabled) .ToList(); - AirSuperiorityText = Constants.GetAirSuperiority(((AirState?)phases[1].Air?.AirSuperiority) ?? AirState.Unknown); - AirSuperiorityForeColor = (phases[1].Air?.AirSuperiority switch + AirSuperiorityText = Constants.GetAirSuperiority((phases[1].Air?.AirState) ?? AirState.Unknown); + AirSuperiorityForeColor = (phases[1].Air?.AirState switch { - // AS+ or AS - 1 or 2 => Configuration.Config.UI.Color_Green, - // AI or AI- - 3 or 4 => Configuration.Config.UI.Color_Red, + AirState.Supremacy or AirState.Superiority => Configuration.Config.UI.Color_Green, + AirState.Denial or AirState.Incapability => Configuration.Config.UI.Color_Red, _ => Configuration.Config.UI.ForeColor, }).ToBrush(); @@ -825,7 +849,7 @@ void ClearAACutinLabel() AirSuperiorityToolTip = needAppendInfo switch { true => string.Join("", phases1.Select(p => - $"{p.PhaseName}{Constants.GetAirSuperiority(((AirState?)p.Air?.AirSuperiority) ?? AirState.Unknown)}\r\n")), + $"{p.PhaseName}{Constants.GetAirSuperiority(p.Air?.AirState ?? AirState.Unknown)}\r\n")), _ => null, }; @@ -840,10 +864,10 @@ void ClearAACutinLabel() string? toolTip = currentToolTip; EquipmentIconType? icon; - if (phases1.Any(p => p.GetTouchAircraft(isFriend) > 0)) + if (phases1.Any(p => p.GetTouchAircraft(isFriend) is not null)) { icon = EquipmentIconType.Seaplane; - toolTip += FormBattle.Contact + "\r\n" + string.Join("\r\n", phases1.Select(p => $"{p.PhaseName}{(KCDatabase.Instance.MasterEquipments[p.GetTouchAircraft(isFriend)]?.NameEN ?? FormBattle.None)}")); + toolTip += FormBattle.Contact + "\r\n" + string.Join("\r\n", phases1.Select(p => $"{p.PhaseName}{(p.GetTouchAircraft(isFriend) ?? FormBattle.None)}")); } else { @@ -858,7 +882,7 @@ void ClearAACutinLabel() } else { - AirSuperiorityText = Constants.GetAirSuperiority(-1); + AirSuperiorityText = Constants.GetAirSuperiority(AirState.Unknown); AirSuperiorityToolTip = null; AirStage1FriendText = "-"; @@ -967,9 +991,11 @@ private void ClearAerialWarfare() /// /// 両軍のHPゲージを設定します。 /// - private void SetHPBar(BattleData bd) + [SuppressMessage("Critical Code Smell", "S3776:Cognitive Complexity of methods should not be too high", Justification = "todo")] + private void SetHPBar(BattleData? bd) { - KCDatabase db = KCDatabase.Instance; + if (bd is null) return; + bool isPractice = bd.IsPractice; bool isFriendCombined = bd.IsFriendCombined; bool isEnemyCombined = bd.IsEnemyCombined; @@ -980,13 +1006,8 @@ private void SetHPBar(BattleData bd) IsEnemyCombinedFleet = isEnemyCombined; var initial = bd.Initial; - var resultHPs = bd.ResultHPs; - var attackDamages = bd.AttackDamages; - - /* - foreach (var bar in HPBars) - bar.SuspendUpdate(); - */ + var resultHPs = bd.ResultHPs.ToList(); + List attackDamages = bd.AttackDamages; void EnableHPBar(int index, int initialHP, int resultHP, int maxHP, bool isTargetable) { @@ -1013,7 +1034,7 @@ void SetEnemyBackground(int index) } // friend main - for (int i = 0; i < initial.FriendInitialHPs.Length; i++) + for (int i = 0; i < initial.FriendInitialHPs.Count; i++) { int refindex = BattleIndex.Get(BattleSides.FriendMain, i); @@ -1038,9 +1059,9 @@ void SetEnemyBackground(int index) } else { - IShipData ship = bd.Initial.FriendFleet.MembersInstance[i]; + IShipData ship = bd.FleetsBeforeBattle.Fleet.MembersInstance[i]!; name = ship.NameWithLevel; - isEscaped = bd.Initial.FriendFleet.EscapedShipList.Contains(ship.MasterID); + isEscaped = bd.FleetsBeforeBattle.Fleet.EscapedShipList.Contains(ship.MasterID); isLandBase = ship.MasterShip.IsLandBase; bar.Text = KCDatabase.Instance.Translation.Ship.TypeNameShort(ship.MasterShip.ShipType); } @@ -1072,28 +1093,28 @@ void SetEnemyBackground(int index) // enemy main - for (int i = 0; i < initial.EnemyInitialHPs.Length; i++) + for (int i = 0; i < initial.EnemyInitialHPs.Count; i++) { int refindex = BattleIndex.Get(BattleSides.EnemyMain, i); if (initial.EnemyInitialHPs[i] != -1) { - EnableHPBar(refindex, initial.EnemyInitialHPs[i], resultHPs[refindex], initial.EnemyMaxHPs[i], initial.IsEnemyTargetable[i]); - IShipDataMaster ship = bd.Initial.EnemyMembersInstance[i]; + IShipData ship = bd.Initial.EnemyMembersInstance[i]!; + EnableHPBar(refindex, ship.HPCurrent, resultHPs[refindex], ship.HPMax, ship.CanBeTargeted); var bar = HPBars[refindex]; - bar.Text = KCDatabase.Instance.Translation.Ship.TypeNameShort(ship.ShipType); + bar.Text = KCDatabase.Instance.Translation.Ship.TypeNameShort(ship.MasterShip.ShipType); SetEnemyBackground(refindex); bar.ToolTip = string.Format("{0} Lv. {1}\r\nHP: ({2} → {3})/{4} ({5}) [{6}]\r\n\r\n{7}", - ship.NameWithClass, - initial.EnemyLevels[i], + ship.MasterShip.NameWithClass, + ship.Level, Math.Max(bar.PrevValue, 0), Math.Max(bar.Value, 0), bar.MaximumValue, bar.Value - bar.PrevValue, - Constants.GetDamageState((double)bar.Value / bar.MaximumValue, isPractice, ship.IsLandBase), + Constants.GetDamageState((double)bar.Value / bar.MaximumValue, isPractice, ship.MasterShip.IsLandBase), bd.GetBattleDetail(refindex) ); } @@ -1107,7 +1128,7 @@ void SetEnemyBackground(int index) // friend escort if (isFriendCombined) { - for (int i = 0; i < initial.FriendInitialHPsEscort!.Length; i++) + for (int i = 0; i < initial.FriendInitialHPsEscort!.Count; i++) { int refindex = BattleIndex.Get(BattleSides.FriendEscort, i); @@ -1115,8 +1136,8 @@ void SetEnemyBackground(int index) { EnableHPBar(refindex, initial.FriendInitialHPsEscort[i], resultHPs[refindex], initial.FriendMaxHPsEscort![i], true); - IShipData? ship = bd.Initial.FriendFleetEscort.MembersInstance![i]; - bool isEscaped = bd.Initial.FriendFleetEscort.EscapedShipList.Contains(ship.MasterID); + IShipData ship = bd.FleetsBeforeBattle.EscortFleet!.MembersInstance[i]!; + bool isEscaped = bd.FleetsBeforeBattle.EscortFleet.EscapedShipList.Contains(ship.MasterID); var bar = HPBars[refindex]; bar.Text = KCDatabase.Instance.Translation.Ship.TypeNameShort(ship.MasterShip.ShipType); @@ -1172,23 +1193,22 @@ void SetEnemyBackground(int index) if (initial.EnemyInitialHPsEscort![i] != -1) { - EnableHPBar(refindex, initial.EnemyInitialHPsEscort[i], resultHPs[refindex], initial.EnemyMaxHPsEscort![i], initial.IsEnemyTargetableEscort[i]); - - IShipDataMaster ship = bd.Initial.EnemyMembersEscortInstance![i]; + IShipData ship = bd.Initial.EnemyMembersEscortInstance![i]!; + EnableHPBar(refindex, initial.EnemyInitialHPsEscort[i], resultHPs[refindex], ship.HPMax, ship.CanBeTargeted); var bar = HPBars[refindex]; - bar.Text = KCDatabase.Instance.Translation.Ship.TypeNameShort(ship.ShipType); + bar.Text = KCDatabase.Instance.Translation.Ship.TypeNameShort(ship.MasterShip.ShipType); SetEnemyBackground(refindex); bar.ToolTip = string.Format("{0} Lv. {1}\r\nHP: ({2} → {3})/{4} ({5}) [{6}]\r\n\r\n{7}", - ship.NameWithClass, - bd.Initial.EnemyLevelsEscort![i], + ship.MasterShip.NameWithClass, + ship.Level, Math.Max(bar.PrevValue, 0), Math.Max(bar.Value, 0), bar.MaximumValue, bar.Value - bar.PrevValue, - Constants.GetDamageState((double)bar.Value / bar.MaximumValue, isPractice, ship.IsLandBase), + Constants.GetDamageState((double)bar.Value / bar.MaximumValue, isPractice, ship.MasterShip.IsLandBase), bd.GetBattleDetail(refindex) ); } @@ -1211,21 +1231,24 @@ void SetEnemyBackground(int index) { // support PhaseSupport? support = null; - if (bd is BattleDayFromNight bddn && (bddn.NightSupport?.IsAvailable ?? false)) + if (bd is BattleNormalDayFromNight { NightSupport: { } nightSupport }) { - support = bddn.NightSupport; + support = nightSupport; } - support ??= bd.Support; + if (bd is DayBattleData { Support: { } s }) + { + support ??= s; + } - if (support?.IsAvailable ?? false) + if (support is not null) { FleetFriendIcon = support.SupportFlag switch { - 1 => EquipmentIconType.CarrierBasedTorpedo, - 2 => EquipmentIconType.MainGunLarge, - 3 => EquipmentIconType.Torpedo, - 4 => EquipmentIconType.DepthCharge, + SupportType.Aerial => EquipmentIconType.CarrierBasedTorpedo, + SupportType.Shelling => EquipmentIconType.MainGunLarge, + SupportType.Torpedo => EquipmentIconType.Torpedo, + SupportType.AntiSubmarine => EquipmentIconType.DepthCharge, _ => EquipmentIconType.Unknown, }; @@ -1257,14 +1280,14 @@ void SetEnemyBackground(int index) if (!isBaseAirRaid) { - foreach (int i in bd.MVPShipIndexes) + foreach (int i in bd.MvpShipIndexes()) { HPBars[BattleIndex.Get(BattleSides.FriendMain, i)].BackColor = Configuration.Config.UI.Battle_ColorHPBarsMVP; } if (isFriendCombined) { - foreach (int i in bd.MVPShipCombinedIndexes) + foreach (int i in bd.MvpShipCombinedIndexes()) { HPBars[BattleIndex.Get(BattleSides.FriendEscort, i)].BackColor = Configuration.Config.UI.Battle_ColorHPBarsMVP; } @@ -1272,7 +1295,7 @@ void SetEnemyBackground(int index) } } - private bool _hpBarMoved = false; + private bool _hpBarMoved; /// /// 味方遊撃部隊7人目のHPゲージ(通常時は連合艦隊第二艦隊旗艦のHPゲージ)を移動します。 /// @@ -1316,9 +1339,13 @@ private void SetDamageRate(BattleManager bm) if (bm.IsBaseAirRaid) { - int kind = bm.Compass.AirRaidDamageKind; + int kind = bm.Compass!.AirRaidDamageKind; WinRankText = Constants.GetAirRaidDamageShort(kind); - WinRankForeColor = (1 <= kind && kind <= 3) ? WinRankColor_Lose : WinRankColor_Win; + WinRankForeColor = kind switch + { + >= 1 and <= 3 => WinRankColor_Lose, + _ => WinRankColor_Win, + }; } else { @@ -1330,9 +1357,11 @@ private void SetDamageRate(BattleManager bm) /// /// 夜戦における各種表示を設定します。 /// - private void SetNightBattleEvent(PhaseNightInitial pd) + private void SetNightBattleEvent(PhaseNightInitial? pd) { - FleetData fleet = pd.FriendFleet; + if (pd?.FleetsBeforePhase is null) return; + + IFleetData fleet = pd.FleetsBeforePhase.Fleet; //味方探照灯判定 { @@ -1340,9 +1369,9 @@ private void SetNightBattleEvent(PhaseNightInitial pd) if (index != -1) { - IShipData ship = fleet.MembersInstance[index]; + IShipData ship = fleet.MembersInstance[index]!; - AirStage1FriendText = "#" + (index + (pd.IsFriendEscort ? 6 : 0) + 1); + AirStage1FriendText = "#" + (index + 1); AirStage1FriendForeColor = Configuration.Config.UI.ForeColor.ToBrush(); AirStage1FriendIcon = EquipmentIconType.Searchlight; AirStage1FriendToolTip = GeneralRes.SearchlightUsed + ": " + ship.NameWithLevel; @@ -1358,10 +1387,10 @@ private void SetNightBattleEvent(PhaseNightInitial pd) int index = pd.SearchlightIndexEnemy; if (index != -1) { - AirStage1EnemyText = "#" + (index + (pd.IsEnemyEscort ? 6 : 0) + 1); + AirStage1EnemyText = "#" + (index + 1); AirStage1EnemyForeColor = Configuration.Config.UI.ForeColor.ToBrush(); AirStage1EnemyIcon = EquipmentIconType.Searchlight; - AirStage1EnemyToolTip = GeneralRes.SearchlightUsed + ": " + pd.SearchlightEnemyInstance.NameWithClass; + AirStage1EnemyToolTip = GeneralRes.SearchlightUsed + ": " + pd.SearchlightEnemy!.MasterShip.NameWithClass; } else { @@ -1370,22 +1399,22 @@ private void SetNightBattleEvent(PhaseNightInitial pd) } //夜間触接判定 - if (pd.TouchAircraftFriend != -1) + if (pd.TouchAircraftFriend is not null) { SearchingFriendText = GeneralRes.NightContact; SearchingFriendIcon = EquipmentIconType.Seaplane; - SearchingFriendToolTip = GeneralRes.NightContacting + ": " + KCDatabase.Instance.MasterEquipments[pd.TouchAircraftFriend].NameEN; + SearchingFriendToolTip = GeneralRes.NightContacting + ": " + pd.TouchAircraftFriend.NameEN; } else { SearchingFriendToolTip = null; } - if (pd.TouchAircraftEnemy != -1) + if (pd.TouchAircraftEnemy is not null) { SearchingEnemyText = GeneralRes.NightContact; SearchingEnemyIcon = EquipmentIconType.Seaplane; - SearchingEnemyToolTip = GeneralRes.NightContacting + ": " + KCDatabase.Instance.MasterEquipments[pd.TouchAircraftEnemy].NameEN; + SearchingEnemyToolTip = GeneralRes.NightContacting + ": " + pd.TouchAircraftEnemy.NameEN; } else { @@ -1394,14 +1423,12 @@ private void SetNightBattleEvent(PhaseNightInitial pd) //照明弾投射判定 { - int index = pd.FlareIndexFriend; - - if (index != -1) + if (pd.FlareFriend is not null) { - AirStage2FriendText = "#" + (index + 1); + AirStage2FriendText = "#" + (pd.FlareIndexFriend + 1); AirStage2FriendForeColor = Configuration.Config.UI.ForeColor.ToBrush(); AirStage2FriendIcon = EquipmentIconType.StarShell; - AirStage2FriendToolTip = GeneralRes.StarShellUsed + ": " + pd.FlareFriendInstance.NameWithLevel; + AirStage2FriendToolTip = GeneralRes.StarShellUsed + ": " + pd.FlareFriend.NameWithLevel; } else @@ -1411,14 +1438,12 @@ private void SetNightBattleEvent(PhaseNightInitial pd) } { - int index = pd.FlareIndexEnemy; - - if (index != -1) + if (pd.FlareEnemy is not null) { - AirStage2EnemyText = "#" + (index + 1); + AirStage2EnemyText = "#" + (pd.FlareIndexEnemy + 1); AirStage2EnemyForeColor = Configuration.Config.UI.ForeColor.ToBrush(); AirStage2EnemyIcon = EquipmentIconType.StarShell; - AirStage2EnemyToolTip = GeneralRes.StarShellUsed + ": " + pd.FlareEnemyInstance.NameWithClass; + AirStage2EnemyToolTip = GeneralRes.StarShellUsed + ": " + pd.FlareEnemy.MasterShip.NameWithClass; } else { @@ -1432,32 +1457,31 @@ private void SetNightBattleEvent(PhaseNightInitial pd) /// 戦闘終了後に、MVP艦の表示を更新します。 /// /// 戦闘データ。 + [SuppressMessage("Critical Code Smell", "S3776:Cognitive Complexity of methods should not be too high", Justification = "todo")] private void SetMVPShip(BattleManager bm) { bool isCombined = bm.IsCombinedBattle; - BattleData bd = bm.StartsFromDayBattle switch - { - true => bm.BattleDay, - _ => bm.BattleNight, - }; + BattleData? bd = bm.SecondBattle ?? bm.FirstBattle; + BattleResult? br = bm.Result; - BattleResultData br = bm.Result; + if (bd is null) return; + if (br is null) return; - FleetData friend = bd.Initial.FriendFleet; - FleetData? escort = isCombined switch + IFleetData friend = bd.FleetsBeforeBattle.Fleet; + IFleetData? escort = isCombined switch { false => null, - _ => bd.Initial.FriendFleetEscort, + _ => bd.FleetsBeforeBattle.EscortFleet, }; - for (int i = 0; i < friend.Members.Count; i++) + for (int i = 0; i < friend.Members!.Count; i++) { if (friend.EscapedShipList.Contains(friend.Members[i])) { HPBars[i].BackColor = Configuration.Config.UI.Battle_ColorHPBarsEscaped; } - else if (br.MVPIndex == i + 1) + else if (br.MvpIndex == i + 1) { HPBars[i].BackColor = Configuration.Config.UI.Battle_ColorHPBarsMVP; } @@ -1469,13 +1493,13 @@ private void SetMVPShip(BattleManager bm) if (escort != null) { - for (int i = 0; i < escort.Members.Count; i++) + for (int i = 0; i < escort.Members!.Count; i++) { if (escort.EscapedShipList.Contains(escort.Members[i])) { HPBars[i + 6].BackColor = Configuration.Config.UI.Battle_ColorHPBarsEscaped; } - else if (br.MVPIndexCombined == i + 1) + else if (br.MvpIndexCombined == i + 1) { HPBars[i + 6].BackColor = Configuration.Config.UI.Battle_ColorHPBarsMVP; } diff --git a/ElectronicObserver/Window/Wpf/Compass/CompassViewModel.cs b/ElectronicObserver/Window/Wpf/Compass/CompassViewModel.cs index e8eef8007..99a79c2d7 100644 --- a/ElectronicObserver/Window/Wpf/Compass/CompassViewModel.cs +++ b/ElectronicObserver/Window/Wpf/Compass/CompassViewModel.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Text; using System.Windows.Media; @@ -15,6 +16,7 @@ using ElectronicObserver.Utility.Data; using ElectronicObserver.ViewModels; using ElectronicObserver.ViewModels.Translations; +using ElectronicObserver.Window.Tools.SortieRecordViewer.Sortie.Battle; using ElectronicObserver.Window.Wpf.Compass.ViewModels; namespace ElectronicObserver.Window.Wpf.Compass; @@ -97,28 +99,26 @@ public CompassViewModel() : base("Compass", "Compass", IconContent.FormCompass) private void Updated(string apiname, dynamic data) { - System.Drawing.Color GetColorFromEventKind(int kind) + static System.Drawing.Color GetColorFromEventKind(int kind) => kind switch { - switch (kind) - { - case 0: - case 1: - default: //昼夜戦・その他 - return Utility.Configuration.Config.UI.ForeColor; - case 2: - case 3: //夜戦・夜昼戦 - return Utility.Configuration.Config.UI.Compass_ColorTextEventKind3; - case 4: //航空戦 - case 6: //長距離空襲戦 - return Utility.Configuration.Config.UI.Compass_ColorTextEventKind6; - case 5: // 敵連合 - return Utility.Configuration.Config.UI.Compass_ColorTextEventKind5; - case 7: // 夜昼戦(対連合艦隊) - return Utility.Configuration.Config.UI.Compass_ColorTextEventKind3; - case 8: // レーダー射撃 - return Utility.Configuration.Config.UI.Compass_ColorTextEventKind3; - } - } + //夜戦・夜昼戦 + 2 or 3 => Utility.Configuration.Config.UI.Compass_ColorTextEventKind3, + + // 航空戦・長距離空襲戦 + 4 or 6 => Utility.Configuration.Config.UI.Compass_ColorTextEventKind6, + + // 敵連合 + 5 => Utility.Configuration.Config.UI.Compass_ColorTextEventKind5, + + // 夜昼戦(対連合艦隊) + 7 => Utility.Configuration.Config.UI.Compass_ColorTextEventKind3, + + // レーダー射撃 + 8 => Utility.Configuration.Config.UI.Compass_ColorTextEventKind3, + + //昼夜戦・その他 + _ => Utility.Configuration.Config.UI.ForeColor + }; if (apiname == "api_port/port") { @@ -141,6 +141,8 @@ System.Drawing.Color GetColorFromEventKind(int kind) } else { + Debug.Assert(Db.Battle.Compass is not null); + CompassData compass = Db.Battle.Compass; // ex: world 5-5 @@ -236,8 +238,8 @@ System.Drawing.Color GetColorFromEventKind(int kind) case 3: //渦潮 { int materialmax = KCDatabase.Instance.Fleet.Fleets.Values - .Where(f => f != null && f.IsInSortie) - .SelectMany(f => f.MembersWithoutEscaped) + .Where(f => f is { IsInSortie: true }) + .SelectMany(f => f.MembersWithoutEscaped!) .Max(s => { if (s == null) return 0; @@ -281,31 +283,16 @@ System.Drawing.Color GetColorFromEventKind(int kind) case 1: //イベントなし case 6: //気のせいだった - switch (compass.EventKind) + eventkind = compass.EventKind switch { - - case 0: //気のせいだった - default: - break; - case 1: - eventkind = FormCompass.NoEnemySighted; - break; - case 2: - eventkind = FormCompass.BranchChoice; - break; - case 3: - eventkind = FormCompass.CalmSea; - break; - case 4: - eventkind = FormCompass.CalmStrait; - break; - case 5: - eventkind = FormCompass.NeedToBeCareful; - break; - case 6: - eventkind = FormCompass.CalmSea2; - break; - } + 1 => FormCompass.NoEnemySighted, + 2 => FormCompass.BranchChoice, + 3 => FormCompass.CalmSea, + 4 => FormCompass.CalmStrait, + 5 => FormCompass.NeedToBeCareful, + 6 => FormCompass.CalmSea2, + _ => eventkind + }; if (compass.RouteChoices != null) { @@ -354,7 +341,6 @@ System.Drawing.Color GetColorFromEventKind(int kind) break; - case 4: //航空戦 default: UpdateEnemyFleet(); break; @@ -384,7 +370,7 @@ System.Drawing.Color GetColorFromEventKind(int kind) } else if (Db.Battle.HeavyBaseAirRaids.Any()) { - int apiLostKind = (int)Db.Battle.HeavyBaseAirRaids.Last().RawData.api_lost_kind; + int apiLostKind = Db.Battle.HeavyBaseAirRaids.Last().BaseAirRaid?.ApiLostKind ?? 0; TextEventKindIcon = EquipmentIconType.CarrierBasedBomber; TextEventKindToolTip = FormCompass.AirRaid + Constants.GetAirRaidDamage(apiLostKind); @@ -399,6 +385,8 @@ System.Drawing.Color GetColorFromEventKind(int kind) private void UpdateEnemyFleet() { + Debug.Assert(Db.Battle.Compass is not null); + CompassData compass = Db.Battle.Compass; CurrentViewModel = EnemyListViewModel; @@ -432,11 +420,11 @@ private void UpdateEnemyFleet() return a.Formation - b.Formation; }); - NextEnemyFleetCandidate(0); + NextEnemyFleetCandidate(); } } - private void NextEnemyFleetCandidate(int offset) + private void NextEnemyFleetCandidate() { if (_enemyFleetCandidate == null || _enemyFleetCandidate.Count == 0) return; @@ -450,7 +438,7 @@ private void NextEnemyFleetCandidate(int offset) .Select(f => new EnemyFleetElementViewModel { EnemyFleetCandidate = f.First(), - Formations = f.Select(fleet => fleet.Formation).ToList() + Formations = f.Select(fleet => (FormationType)fleet.Formation).ToList(), }) .ToList(); @@ -561,20 +549,24 @@ private void UpdateEnemyFleetInstant(bool isPractice = false) CurrentViewModel = BattleViewModel; BattleManager bm = KCDatabase.Instance.Battle; - BattleData bd = bm.FirstBattle; - int[] enemies = bd.Initial.EnemyMembers; - int[][] slots = bd.Initial.EnemySlots; - int[] levels = bd.Initial.EnemyLevels; - int[][] parameters = bd.Initial.EnemyParameters; - int[] hps = bd.Initial.EnemyMaxHPs; + if (bm.FirstBattle is not FirstBattleData bd) return; + + int[] enemies = bd.Initial.EnemyMembers.ToArray(); + int[][] slots = bd.Initial.EnemySlots.ToArray(); + int[] levels = bd.Initial.EnemyLevels.ToArray(); + List> parameters = bd.Initial.EnemyParameters; + int[] hps = bd.Initial.EnemyMaxHPs.ToArray(); _enemyFleetCandidate = null; if (!bm.IsPractice) { - EnemyFleetRecord.EnemyFleetElement efcurrent = EnemyFleetRecord.EnemyFleetElement.CreateFromCurrentState(); - EnemyFleetRecord.EnemyFleetElement efrecord = RecordManager.Instance.EnemyFleet[efcurrent.FleetID]; + EnemyFleetRecord.EnemyFleetElement? efcurrent = EnemyFleetRecord.EnemyFleetElement.CreateFromCurrentState(); + + Debug.Assert(efcurrent is not null); + + EnemyFleetRecord.EnemyFleetElement? efrecord = RecordManager.Instance.EnemyFleet[efcurrent.FleetID]; if (efrecord != null) { TextEnemyFleetNameText = KCDatabase.Instance.Translation.Operation.FleetName(efrecord.FleetName); @@ -583,17 +575,22 @@ private void UpdateEnemyFleetInstant(bool isPractice = false) TextEventDetailToolTip = GeneralRes.EnemyFleetID + ": " + efcurrent.FleetID.ToString("x16"); } - TextFormationText = Constants.GetFormationShort(bd.Searching.FormationEnemy); + TextFormationText = Constants.GetFormationShort(bd.Searching.EnemyFormationType); { int air = Calculator.GetAirSuperiority(enemies, slots); - TextAirSuperiorityText = isPractice ? - air.ToString() + " ~ " + Calculator.GetAirSuperiorityAtMaxLevel(enemies, slots).ToString() : - air.ToString(); + TextAirSuperiorityText = isPractice switch + { + true => air + " ~ " + Calculator.GetAirSuperiorityAtMaxLevel(enemies, slots), + _ => air.ToString(), + }; if (enemies.Select(id => KCDatabase.Instance.MasterShips[id]) - .Any(ship => ship != null && RecordManager.Instance.ShipParameter[ship.ShipID]?.Aircraft == null)) + .OfType() + .Any(ship => RecordManager.Instance.ShipParameter[ship.ShipID]?.Aircraft == null)) + { TextAirSuperiorityText += "?"; + } TextAirSuperiorityToolTip = GetAirSuperiorityString(isPractice ? 0 : air); } diff --git a/ElectronicObserver/Window/Wpf/Compass/ViewModels/EnemyFleetElementViewModel.cs b/ElectronicObserver/Window/Wpf/Compass/ViewModels/EnemyFleetElementViewModel.cs index 01c7237bd..49e3bea2e 100644 --- a/ElectronicObserver/Window/Wpf/Compass/ViewModels/EnemyFleetElementViewModel.cs +++ b/ElectronicObserver/Window/Wpf/Compass/ViewModels/EnemyFleetElementViewModel.cs @@ -30,7 +30,7 @@ public class EnemyFleetElementViewModel : ObservableObject public bool HasEscortFleet => EscortFleetMember.Any(ship => ship.ShipId > 0); - public List Formations { get; init; } = new(); + public List Formations { get; init; } = new(); public string FormationString => string.Join('/', Formations.Select(Constants.GetFormationShort)); diff --git a/ElectronicObserver/Window/Wpf/InformationView/InformationViewModel.cs b/ElectronicObserver/Window/Wpf/InformationView/InformationViewModel.cs index 80a31615b..353796a9d 100644 --- a/ElectronicObserver/Window/Wpf/InformationView/InformationViewModel.cs +++ b/ElectronicObserver/Window/Wpf/InformationView/InformationViewModel.cs @@ -1,4 +1,7 @@ using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Text; using System.Windows; @@ -69,7 +72,7 @@ private void Updated(string apiname, dynamic data) if (_inSortie != null) { - Text = GetConsumptionResource(data); + Text = GetConsumptionResource(); } _inSortie = null; @@ -93,7 +96,7 @@ private void Updated(string apiname, dynamic data) break; case "api_get_member/mapinfo": - Text = GetMapGauge(data); + Text = GetMapGauge(); break; case "api_get_member/mission": @@ -153,7 +156,7 @@ private void Updated(string apiname, dynamic data) break; case "api_req_practice/battle": - _inSortie = new List() { KCDatabase.Instance.Battle.BattleDay.Initial.FriendFleetID }; + _inSortie = [KCDatabase.Instance.Battle.FirstBattle!.Initial.FriendFleetID]; break; } @@ -174,27 +177,79 @@ private string GetPracticeEnemyInfo(dynamic data) sb.Append($"{GeneralRes.BaseExp}: {(int)exp.BaseA} / {InformationResources.SRank}: {(int)exp.BaseS}"); - if (exp.TrainingCruiserSurfaceA is not null && exp.TrainingCruiserSurfaceS is not null) + Debug.Assert(fleet.MembersInstance is not null); + + if (fleet.MembersInstance.Any(s => s is { MasterShip.ShipType: ShipTypes.TrainingCruiser })) { - int trainingCruiserSurfaceA = (int)exp.TrainingCruiserSurfaceA; - int trainingCruiserSurfaceS = (int)exp.TrainingCruiserSurfaceS; + ReadOnlyCollection? members = fleet.MembersInstance; + List subCT = members + .Skip(1) + .OfType() + .Where(s => s is { MasterShip.ShipType: ShipTypes.TrainingCruiser }) + .ToList(); + + double bonus; + + // 旗艦が練巡 + if (members[0] is { MasterShip.ShipType: ShipTypes.TrainingCruiser } ship) + { + + int level = ship.Level; + + if (subCT.Any()) + { + bonus = level switch + { + // 旗艦+随伴 + < 10 => 1.10, + < 30 => 1.13, + < 60 => 1.16, + < 100 => 1.20, + _ => 1.25, + }; + } + else + { + bonus = level switch + { + // 旗艦のみ + < 10 => 1.05, + < 30 => 1.08, + < 60 => 1.12, + < 100 => 1.15, + _ => 1.20, + }; + } - if (exp.TrainingCruiserSubmarineA is not null && exp.TrainingCruiserSubmarineS is not null) + } + else { - int trainingCruiserSubmarineA = (int)exp.TrainingCruiserSubmarineA; - int trainingCruiserSubmarineS = (int)exp.TrainingCruiserSubmarineS; - sb.AppendLine(); + int level = subCT.Max(s => s.Level); - if (trainingCruiserSurfaceA == trainingCruiserSubmarineA) + if (subCT.Count > 1) { - sb.AppendFormat(InformationResources.CTBonus, trainingCruiserSurfaceA, trainingCruiserSurfaceS); + bonus = level switch + { + // 随伴複数 + < 10 => 1.04, + < 30 => 1.06, + < 60 => 1.08, + < 100 => 1.12, + _ => 1.175, + }; } else { - sb.AppendFormat(InformationResources.CtBonusSurface, trainingCruiserSurfaceA, trainingCruiserSurfaceS); - sb.AppendLine(); - sb.AppendFormat(InformationResources.CtBonusSubmarine, trainingCruiserSubmarineA, trainingCruiserSubmarineS); + bonus = level switch + { + // 随伴単艦 + < 10 => 1.03, + < 30 => 1.05, + < 60 => 1.07, + < 100 => 1.10, + _ => 1.15, + }; } } } @@ -203,18 +258,17 @@ private string GetPracticeEnemyInfo(dynamic data) } private string GetAlbumInfo(dynamic data) { + StringBuilder sb = new(); - StringBuilder sb = new StringBuilder(); - - if (data != null && data.api_list() && data.api_list != null) + if (data != null && data!.api_list() && data!.api_list != null) { - if (data.api_list[0].api_yomi()) + if (data!.api_list[0].api_yomi()) { //艦娘図鑑 const int bound = 70; // 図鑑1ページあたりの艦船数 int startIndex = (((int)data.api_list[0].api_index_no - 1) / bound) * bound + 1; - bool[] flags = Enumerable.Repeat(false, bound).ToArray(); + bool[] flags = Enumerable.Repeat(false, bound).ToArray(); sb.AppendLine(GeneralRes.DamagedArtUnseen); @@ -256,7 +310,7 @@ private string GetAlbumInfo(dynamic data) //装備図鑑 const int bound = 70; // 図鑑1ページあたりの装備数 int startIndex = (((int)data.api_list[0].api_index_no - 1) / bound) * bound + 1; - bool[] flags = Enumerable.Repeat(false, bound).ToArray(); + bool[] flags = Enumerable.Repeat(false, bound).ToArray(); foreach (dynamic elem in data.api_list) { @@ -269,7 +323,7 @@ private string GetAlbumInfo(dynamic data) { if (!flags[i]) { - IEquipmentDataMaster eq = KCDatabase.Instance.MasterEquipments.Values.FirstOrDefault(s => s.AlbumNo == startIndex + i); + IEquipmentDataMaster? eq = KCDatabase.Instance.MasterEquipments.Values.FirstOrDefault(s => s.AlbumNo == startIndex + i); if (eq != null) { sb.AppendLine(eq.NameEN); @@ -282,34 +336,9 @@ private string GetAlbumInfo(dynamic data) return sb.ToString(); } - - private string GetCreateItemInfo(dynamic data) + private string GetMapGauge() { - - if ((int)data.api_create_flag == 0) - { - - StringBuilder sb = new StringBuilder(); - sb.AppendLine(GeneralRes.DevelopmentFailed); - sb.AppendLine(data.api_fdata); - - IEquipmentDataMaster eqm = KCDatabase.Instance.MasterEquipments[int.Parse(((string)data.api_fdata).Split(",".ToCharArray())[1])]; - if (eqm != null) - sb.AppendLine(eqm.NameEN); - - - return sb.ToString(); - - } - else - return ""; - } - - - private string GetMapGauge(dynamic data) - { - - StringBuilder sb = new StringBuilder(); + StringBuilder sb = new(); sb.AppendLine(GeneralRes.MapGauges); string rpcMapInfo = ""; @@ -364,7 +393,9 @@ private string GetMapGauge(dynamic data) private enum MissionState { + // ReSharper disable once UnusedMember.Local New, + // ReSharper disable once UnusedMember.Local NotCompleted, Completed } @@ -440,11 +471,10 @@ private string GetSupplyInformation(dynamic data) } - private string GetConsumptionResource(dynamic data) + private string GetConsumptionResource() { - StringBuilder sb = new StringBuilder(); - var material = KCDatabase.Instance.Material; + MaterialData material = KCDatabase.Instance.Material; int fuel_diff = material.Fuel - _prevResource[0], @@ -452,11 +482,13 @@ private string GetConsumptionResource(dynamic data) steel_diff = material.Steel - _prevResource[2], bauxite_diff = material.Bauxite - _prevResource[3]; + Debug.Assert(_inSortie is not null); - var ships = KCDatabase.Instance.Fleet.Fleets.Values + List ships = KCDatabase.Instance.Fleet.Fleets.Values .Where(f => _inSortie.Contains(f.FleetID)) - .SelectMany(f => f.MembersInstance) - .Where(s => s != null); + .SelectMany(f => f.MembersInstance!) + .OfType() + .ToList(); int fuel_supply = ships.Sum(s => s.SupplyFuel); int ammo = ships.Sum(s => s.SupplyAmmo); @@ -476,21 +508,26 @@ private string GetConsumptionResource(dynamic data) } + [SuppressMessage("ReSharper", "PossibleMultipleEnumeration")] private void CheckSallyArea() { // only check if there's any event maps // this function shouldn't get called outside of events so the check should be pointless // if (KCDatabase.Instance.MapArea.Values.Any(m => m.ID > 20)) return; - IEnumerable> group; - - if (KCDatabase.Instance.Fleet.CombinedFlag != 0) - group = new[] { KCDatabase.Instance.Fleet[1].MembersInstance.Concat(KCDatabase.Instance.Fleet[2].MembersInstance).Where(s => s != null) }; - else - group = KCDatabase.Instance.Fleet.Fleets.Values - .Where(f => f?.ExpeditionState == 0) - .Select(f => f.MembersInstance.Where(s => s != null)); - + IEnumerable> group = KCDatabase.Instance.Fleet.CombinedFlag switch + { + 0 => KCDatabase.Instance.Fleet.Fleets.Values + .Where(f => f.ExpeditionState == 0) + .Select(f => f.MembersInstance!.OfType()), + + _ => + [ + KCDatabase.Instance.Fleet[1].MembersInstance! + .Concat(KCDatabase.Instance.Fleet[2].MembersInstance!) + .OfType() + ], + }; group = group.Where(ss => ss.All(s => s.RepairingDockID == -1) && @@ -499,21 +536,28 @@ private void CheckSallyArea() if (group.Any()) { - var freeShips = group.SelectMany(f => f).Where(s => s.SallyArea == 0); + IEnumerable freeShips = group + .SelectMany(f => f) + .Where(s => s.SallyArea == 0); Text = InformationResources.FleetTagWarning + string.Join("\r\n", freeShips.Select(s => s.NameWithLevel)); if (Utility.Configuration.Config.Control.ShowSallyAreaAlertDialog) + { MessageBox.Show(InformationResources.FleetTagAlertDialogText, InformationResources.FleetTagAlertDialogCaption, MessageBoxButton.OK, MessageBoxImage.Warning); + } } } private void CheckExpedition(int missionID, int fleetID) { - var fleet = KCDatabase.Instance.Fleet[fleetID]; - var result = MissionClearCondition.Check(missionID, fleet); - var mission = KCDatabase.Instance.Mission[missionID]; + FleetData fleet = KCDatabase.Instance.Fleet[fleetID]; + MissionClearCondition.MissionClearConditionResult result = MissionClearCondition.Check(missionID, fleet); + MissionData? mission = KCDatabase.Instance.Mission[missionID]; + + Debug.Assert(fleet.MembersInstance is not null); + Debug.Assert(mission is not null); if (!result.IsSuceeded) { @@ -538,9 +582,4 @@ private void RecordMaterials() _prevResource[2] = material.Steel; _prevResource[3] = material.Bauxite; } - - protected string GetPersistString() - { - return "Information"; - } }