diff --git a/CREDITS.md b/CREDITS.md index 44c87160fb..0ecdb72b92 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -290,6 +290,7 @@ This page lists all the individual contributions to the project by their author. - Guard range customizations - Wall overlay unit sell exploit fix - Fix vehicles disguised as trees incorrectly displaying veterancy insignia when they shouldn't + - GapGen + SpySat desync fix - **Morton (MortonPL)**: - `XDrawOffset` for animations - Shield passthrough & absorption diff --git a/docs/Fixed-or-Improved-Logics.md b/docs/Fixed-or-Improved-Logics.md index 6c2070cb3b..b06faee175 100644 --- a/docs/Fixed-or-Improved-Logics.md +++ b/docs/Fixed-or-Improved-Logics.md @@ -315,6 +315,7 @@ This page describes all ingame logics that are fixed or improved in Phobos witho - Fixed an issue where a unit might cause the target to fall from above its own head when using a locomotor warhead with `Locomotor=Jumpjet` to pull a target with `BalloonHover=yes`. - Fixed the [EIP#007120F7](https://modenc.renegadeprojects.com/Internal_Error#eip_007120F7) that was triggered when repairing because the `Strength` value was lower than `RepairStep`. - Fixed the bug where non-Teleporter miners would not return to work after minerals are depleted and then regenerated. +- Fixed a desync due to an inconsistent shroud state caused by `GapGenerator` and `SpySat` interaction. ## Fixes / interactions with other extensions diff --git a/docs/Whats-New.md b/docs/Whats-New.md index 39685cd218..442f44181a 100644 --- a/docs/Whats-New.md +++ b/docs/Whats-New.md @@ -692,6 +692,7 @@ Fixes / interactions with other extensions: Vanilla fixes: - Vehicles overlapping `Wall=true` OverlayTypes no longer display sell cursor and cannot be sold (by CnCRAZER & Starkku) +- Fixed a desync due to an inconsistent shroud state caused by `GapGenerator` and `SpySat` interaction (by Starkku) Phobos fixes: - Fixed vehicles disguised as trees incorrectly displaying veterancy insignia when they shouldn't (by Starkku) diff --git a/src/Misc/Hooks.BugFixes.cpp b/src/Misc/Hooks.BugFixes.cpp index 63873b28c9..2cc9a3adb6 100644 --- a/src/Misc/Hooks.BugFixes.cpp +++ b/src/Misc/Hooks.BugFixes.cpp @@ -3275,3 +3275,92 @@ DEFINE_HOOK(0x7120DD, TechnoTypeClass_GetRepairStepCost, 0x6) return SkipGameCode; } + +#pragma region ShroudFix + +// These map cells are what SpySat skips revealing in MP normally. +static bool inline ShroudFix_IsCellInvalid(CellStruct* pMapCell) +{ + const int x = pMapCell->X; + const int y = pMapCell->Y; + auto const& rect = MapClass::Instance.MapRect; + + if (x == 7 && y == rect.Width + 5) + return true; + + if (x == 13 && y == rect.Width + 11) + return true; + + if (x == rect.Height + 13 && y == rect.Width + rect.Height - 15) + return true; + + return false; +} + +DEFINE_HOOK(0x6FB5E5, TechnoClass_DeleteGap_CellCheck, 0x5) +{ + enum { SkipCell = 0x6FB6F3 }; + + GET(CellStruct*, pMapCell, EDX); + + if (ShroudFix_IsCellInvalid(pMapCell)) + return SkipCell; + + return 0; +} + +DEFINE_HOOK(0x6FB2FB, TechnoClass_CreateGap_CellCheck, 0x5) +{ + enum { SkipCell = 0x6FB416 }; + + GET(CellStruct*, pMapCell, EDX); + + if (ShroudFix_IsCellInvalid(pMapCell)) + return SkipCell; + + return 0; +} + +// Replace the entire cell iterator loop for perf reasons. +DEFINE_HOOK(0x577AFF, MapClass_ResetShroud_CellCheck, 0x6) +{ + enum { SkipGameCode = 0x577B75 }; + + auto& map = MapClass::Instance; + map.CellIteratorReset(); + + for (auto pCell = map.CellIteratorNext(); pCell; pCell = map.CellIteratorNext()) + { + if (ShroudFix_IsCellInvalid(&pCell->MapCoords)) + continue; + + pCell->Flags &= ~(CellFlags::CenterRevealed | CellFlags::EdgeRevealed); + pCell->AltFlags &= ~(AltCellFlags::Mapped | AltCellFlags::NoFog); + pCell->ShroudCounter = 1; + pCell->GapsCoveringThisCell = 0; + } + + return SkipGameCode; +} + +// Replace the entire cell iterator loop for perf reasons. +DEFINE_HOOK(0x577BF1, MapClass_ResetShroudForTMission_CellCheck, 0x6) +{ + enum { SkipGameCode = 0x577C57 }; + + auto& map = MapClass::Instance; + map.CellIteratorReset(); + + for (auto pCell = map.CellIteratorNext(); pCell; pCell = map.CellIteratorNext()) + { + if (ShroudFix_IsCellInvalid(&pCell->MapCoords)) + continue; + + pCell->Flags &= ~(CellFlags::CenterRevealed | CellFlags::EdgeRevealed); + pCell->AltFlags &= ~(AltCellFlags::Mapped | AltCellFlags::NoFog); + } + + return SkipGameCode; +} + +#pragma endregion diff --git a/src/Phobos.cpp b/src/Phobos.cpp index c061b50170..60ce544c2f 100644 --- a/src/Phobos.cpp +++ b/src/Phobos.cpp @@ -271,6 +271,18 @@ void Phobos::ApplyOptimizations() if (!SessionClass::IsMultiplayer()) { + // Disable TechnoClass_DeleteGap_CellCheck + Patch::Apply_RAW(0x6FB5E5, { 0xB9, 0xE8, 0xF7, 0x87, 0x00 }); + + // Disable TechnoClass_CreateGap_CellCheck + Patch::Apply_RAW(0x6FB2FB, { 0xB9, 0xE8, 0xF7, 0x87, 0x00 }); + + // Disable MapClass_ResetShroud_CellCheck + Patch::Apply_RAW(0x577AFF, { 0x8B, 0x86, 0xF4, 0x00, 0x00, 0x00 }); + + // Disable MapClass_ResetShroudForTMission_CellCheck + Patch::Apply_RAW(0x577BF1, { 0x8B, 0x86, 0xF4, 0x00, 0x00, 0x00 }); + // Disable Random2Class_Random_SyncLog Patch::Apply_RAW(0x65C7D0, { 0xC3, 0x90, 0x90, 0x90, 0x90 });