diff --git a/docs/feature-spec-roman-endless.md b/docs/feature-spec-roman-endless.md index 8eba838..2739f53 100644 --- a/docs/feature-spec-roman-endless.md +++ b/docs/feature-spec-roman-endless.md @@ -138,7 +138,7 @@ internal static Dictionary Build(BackupManager backup, bool maxP ### 3.3 `src/Core/Services/PatchEngine.cs` - 步驟 G(team.dat)改為傳入兩個布林: - `GetPatchedTeamDatBytes(backupManager, options.MaxPopulation, options.RomanEndless)`。 + `GetPatchedTeamDatBytes(gamePath, backupManager, options.MaxPopulation, options.RomanEndless)`。 - log:新增鍵 `SvcLogTeamDatRoman`(見 §3.6),在 romanEndless 為 true 時輸出 「已將 {n} 張無盡地圖的玩家陣營改為羅馬」。既有 `SvcLogTeamDatApplied/Restored` 邏輯保持。 diff --git a/src/Core/Features/FeatureDetector.cs b/src/Core/Features/FeatureDetector.cs index 37c6882..15452a5 100644 --- a/src/Core/Features/FeatureDetector.cs +++ b/src/Core/Features/FeatureDetector.cs @@ -288,11 +288,9 @@ internal PatchProfile Detect(string gamePath, BackupManager backupManager) // 使用塞爾特祭司 FigKelPri00_Priester 偵測法師施法距離 bool spellEntireMap = false; if (unitRows.TryGetValue("FigKelPri00_Priester", out var testSpellCols) && - origUnitRows.TryGetValue("FigKelPri00_Priester", out var testSpellOrigCols)) + origUnitRows.ContainsKey("FigKelPri00_Priester")) { double curRange = BackupManager.GetUnitMaxRange(testSpellCols, "priest"); - double origRange = BackupManager.GetUnitMaxRange(testSpellOrigCols, "priest"); - double expectedBaseRange = isFileBalanced ? 3840.0 : origRange; if (curRange > 0) { if (Math.Abs(curRange - 30000.0) < 100.0) diff --git a/src/Core/Services/PatchEngine.cs b/src/Core/Services/PatchEngine.cs index 2537032..183678d 100644 --- a/src/Core/Services/PatchEngine.cs +++ b/src/Core/Services/PatchEngine.cs @@ -134,7 +134,7 @@ public void ApplyPatches(string gamePath, PatchProfile profile, BackupManager ba patchedFiles[Path.Combine(gamePath, @"SYSTEM\DATA_MP\DEFAULTS\objdef.dau")] = objdefBytes; // G. team.dat - var teamDatPatches = GetPatchedTeamDatBytes(backupManager, options.MaxPopulation, options.RomanEndless); + var teamDatPatches = GetPatchedTeamDatBytes(gamePath, backupManager, options.MaxPopulation, options.RomanEndless); foreach (var kvp in teamDatPatches) { patchedFiles[Path.Combine(gamePath, kvp.Key.Replace('/', '\\'))] = kvp.Value; @@ -276,6 +276,8 @@ private void RestoreStatsFiles(string gamePath, BackupManager backupManager, Fil if (kvp.Key.StartsWith("MAPS/", StringComparison.OrdinalIgnoreCase) && kvp.Key.EndsWith("team.dat", StringComparison.OrdinalIgnoreCase)) { string destPath = Path.Combine(gamePath, kvp.Key.Replace('/', '\\')); + // 與套用路徑一致:地圖已被玩家移除時不重建其 team.dat。 + if (!File.Exists(destPath)) continue; byte[] patchedBytes = TeamDatPatcher.GetPatchedBytes(kvp.Value, new TeamDatOptions(false)); SafeWriteAllBytes(destPath, patchedBytes, rollback); _logger.Log(string.Format(Loc.Get("SvcLogRestoredPopulation"), destPath)); @@ -304,9 +306,14 @@ private byte[] GetPatchedObjdefBytes(BackupManager backupManager, PatchProfile o return ObjdefFeaturePatcher.Build(backupManager, options); } - private Dictionary GetPatchedTeamDatBytes(BackupManager backupManager, bool maxPopulation, bool romanEndless) + private Dictionary GetPatchedTeamDatBytes(string gamePath, BackupManager backupManager, bool maxPopulation, bool romanEndless) { var results = MaxPopulationFeature.Build(backupManager, maxPopulation, romanEndless); + // 備份中可能保有玩家已自行移除的地圖;只改寫磁碟上仍存在的 team.dat,不重建已刪除的地圖檔。 + foreach (string key in results.Keys.Where(k => !File.Exists(Path.Combine(gamePath, k.Replace('/', '\\')))).ToList()) + { + results.Remove(key); + } _logger.Log(maxPopulation ? string.Format(Loc.Get("SvcLogTeamDatApplied"), TeamDatPatcher.DefaultPopulationLimit, results.Count) : Loc.Get("SvcLogTeamDatRestored")); int endlessCount = results.Keys.Count(key => key.StartsWith("MAPS/ENDL_", StringComparison.OrdinalIgnoreCase)); _logger.Log(romanEndless