Разведка М3 (ядро): тайные операции -- группа до 10 пехоты/лучников, до 2 операций, проверки обнаружения, прерывание и возврат

- Разведка: CheckCovertGroup, StartCovert, CheckCovertUntil (15/25/35%, при входе и каждые 5 реальных минут, максимум при пересечении, 5-75%, детерминированно по одной сетке), EndCovert; сохранение covert=
- Армия: AvailableUnits, TakeUnitsForMarch -- поход точного состава
- Мир: AbortMission -- домой от места обнаружения, без отчёта; охраняемые области и позиция армии через IWorldMap
- Карта: «Тайно» в окне атаки и окне чужой армии, окно «РАЗВЕДЧИКОВ ЗАМЕТИЛИ»
- «Шпион» -- переключатель IntelligenceConfig (ТЕСТ); 5 тестов

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Alexander
2026-11-06 17:15:22 +01:00
co-authored by Claude Opus 5.5
parent 56a5a82a8c
commit 2835c514d8
18 changed files with 622 additions and 14 deletions
+38 -1
View File
@@ -131,6 +131,7 @@ public class WorldMapController : MonoBehaviour
MarchManager.Instance.OnGatherStarted += HandleGatherStarted;
MarchManager.Instance.OnScoutArrived += HandleScoutArrived;
MarchManager.Instance.OnReconCompleted += HandleReconCompleted;
MarchManager.Instance.OnCovertDetected += HandleCovertDetected;
MarchManager.Instance.OnMarchReturned += HandleMarchReturned;
}
@@ -141,6 +142,7 @@ public class WorldMapController : MonoBehaviour
MarchManager.Instance.OnGatherStarted -= HandleGatherStarted;
MarchManager.Instance.OnScoutArrived -= HandleScoutArrived;
MarchManager.Instance.OnReconCompleted -= HandleReconCompleted;
MarchManager.Instance.OnCovertDetected -= HandleCovertDetected;
MarchManager.Instance.OnMarchReturned -= HandleMarchReturned;
}
@@ -200,6 +202,30 @@ public class WorldMapController : MonoBehaviour
Place(scoutButton, -110f);
Place(scout3Button, 110f);
Place(sendButton, 330f);
// «Тайно» (Разведка М3) -- над кнопками разведки: группа до 10 пехоты / лучников, может быть обнаружена
covertButton = CopyOfSend("CovertButton", CovertLabel, () =>
{
ReconReportText.CovertMode = !ReconReportText.CovertMode;
RefreshCovertButton();
});
var crt = (RectTransform)covertButton.transform;
var srt = (RectTransform)scoutButton.transform;
crt.anchoredPosition = srt.anchoredPosition + new Vector2(110f, srt.rect.height + 12f);
crt.sizeDelta = new Vector2(420f, srt.sizeDelta.y);
RefreshCovertButton();
}
private Button covertButton;
static string CovertLabel => ReconReportText.CovertMode ? "Тайно: ВКЛ (до 10 пехоты и лучников)" : "Тайно: выкл";
void RefreshCovertButton()
{
if (covertButton == null) return;
bool can = GameServices.TryGet(out IIntelligence intel) && intel.CovertEnabled;
covertButton.gameObject.SetActive(can && selectedTarget != null && selectedTarget.type != MapNodeType.ResourcePoint);
var label = covertButton.GetComponentInChildren<TMP_Text>();
if (label != null) label.text = CovertLabel;
}
Button CopyOfSend(string name, string text, UnityEngine.Events.UnityAction onClick)
@@ -226,10 +252,13 @@ public class WorldMapController : MonoBehaviour
if (selectedTarget == null) return;
int soldiers = (int)soldiersSlider.value;
bool point = selectedTarget.type == MapNodeType.ResourcePoint;
// Тайно (М3) -- не больше 10: лишних с ползунка не берём
if (!point && ReconReportText.CovertMode && GameServices.TryGet(out IIntelligence spyIntel) && spyIntel.CovertEnabled)
soldiers = Mathf.Min(soldiers, spyIntel.CovertMaxSoldiers);
string error;
bool ok = point
? MarchManager.Instance.TryStartScout(selectedTarget.id, soldiers, out error)
: MarchManager.Instance.TryStartRecon(selectedTarget.id, soldiers, level, out error);
: MarchManager.Instance.TryStartRecon(selectedTarget.id, soldiers, level, ReconReportText.CovertMode, out error);
long hold = !point && GameServices.TryGet(out IIntelligence intel) ? intel.ReconDurationMs(selectedTarget.id, level) : 0;
hintText.text = ok
? point ? $"Разведка выступила: {soldiers} воинов идут к цели «{selectedTarget.displayName}» и вернутся без боя"
@@ -596,6 +625,7 @@ public class WorldMapController : MonoBehaviour
scout3Button.gameObject.SetActive(!pointTarget); // у точки отчёта нет -- только дойти и вернуться
scout3Button.interactable = available > 0 && slotFree;
}
RefreshCovertButton();
UpdateSoldiersToSendText();
RefreshAttackConditions(); // путь -- по составу при выбранном числе воинов
@@ -858,6 +888,13 @@ public class WorldMapController : MonoBehaviour
EnqueuePopup(title, body);
}
// Разведка М3: тайный отряд заметили -- миссия прервана, отряд идёт домой (без отчёта, без боя)
void HandleCovertDetected(MarchData march)
{
EnqueuePopup("РАЗВЕДЧИКОВ ЗАМЕТИЛИ",
$"Тайный отряд ({march.soldiers} воинов) заметили у цели «{World.TargetName(march)}». Миссия прервана: разведчики возвращаются домой, отчёта не будет.");
}
void HandleReconCompleted(MarchData march)
{
if (GameServices.TryGet(out IIntelligence intel) && intel.TryGetLatestReport(MarchManager.ReconTargetId(march), out var report))