Поход «Разведка» (решения 31.10, п. 2): до цели и обратно без боя, сбора и потерь, обычный слот

IWorld.TryStartScout, MarchData.scout, WorldEventType.ScoutArrived; кнопка «Разведка» в окне атаки;
разведка не разбивает лагерь и не занимает точку.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Alexander
2026-11-01 13:11:55 +01:00
co-authored by Claude Opus 5.5
parent 24268f3cfb
commit 33db41002e
14 changed files with 208 additions and 17 deletions
@@ -106,6 +106,7 @@ public class WorldMapController : MonoBehaviour
if (circleNavButton != null) circleNavButton.onClick.AddListener(CircleWindow.Open); // модуль Круга
HookUpComingSoon(settlementNavButton, "Поселение");
sendButton.onClick.AddListener(OnSendPressed);
CreateScoutButton();
cancelButton.onClick.AddListener(CloseAttackPanel);
popupOkButton.onClick.AddListener(ShowNextPopup);
soldiersSlider.onValueChanged.AddListener(_ => { UpdateSoldiersToSendText(); if (attackPanel.activeSelf) RefreshAttackConditions(); });
@@ -124,6 +125,7 @@ public class WorldMapController : MonoBehaviour
if (MarchManager.Instance == null) return;
MarchManager.Instance.OnBattleResolved += HandleBattleResolved;
MarchManager.Instance.OnGatherStarted += HandleGatherStarted;
MarchManager.Instance.OnScoutArrived += HandleScoutArrived;
MarchManager.Instance.OnMarchReturned += HandleMarchReturned;
}
@@ -132,6 +134,7 @@ public class WorldMapController : MonoBehaviour
if (MarchManager.Instance == null) return;
MarchManager.Instance.OnBattleResolved -= HandleBattleResolved;
MarchManager.Instance.OnGatherStarted -= HandleGatherStarted;
MarchManager.Instance.OnScoutArrived -= HandleScoutArrived;
MarchManager.Instance.OnMarchReturned -= HandleMarchReturned;
}
@@ -165,6 +168,41 @@ public class WorldMapController : MonoBehaviour
button.onClick.AddListener(ArmiesWindow.Open);
}
// Кнопка «Разведка» в окне атаки (решения 31.10, п. 2) -- копия «Отправить». Три кнопки в ряд: Отмена, Разведка, Отправить
private Button scoutButton;
void CreateScoutButton()
{
var copy = Instantiate(sendButton.gameObject, sendButton.transform.parent);
copy.name = "ScoutButton";
scoutButton = copy.GetComponent<Button>();
scoutButton.onClick.RemoveAllListeners();
scoutButton.onClick.AddListener(OnScoutPressed);
var label = copy.GetComponentInChildren<TMP_Text>();
if (label != null) label.text = "Разведка";
Place(cancelButton, -290f);
Place(scoutButton, 0f);
Place(sendButton, 290f);
}
static void Place(Button button, float x)
{
var rt = (RectTransform)button.transform;
rt.anchoredPosition = new Vector2(x, rt.anchoredPosition.y);
rt.sizeDelta = new Vector2(Mathf.Min(rt.sizeDelta.x, 260f), rt.sizeDelta.y);
}
void OnScoutPressed()
{
if (selectedTarget == null) return;
int soldiers = (int)soldiersSlider.value;
hintText.text = MarchManager.Instance.TryStartScout(selectedTarget.id, soldiers, out string error)
? $"Разведка выступила: {soldiers} воинов идут к цели «{selectedTarget.displayName}» и вернутся без боя"
: "Разведка не начата: " + error;
CloseAttackPanel();
}
void HookUpComingSoon(Button button, string sectionName)
{
if (button == null) return;
@@ -415,6 +453,7 @@ public class WorldMapController : MonoBehaviour
soldiersSlider.interactable = available > 0;
bool slotFree = !GameServices.TryGet(out IArmy slotsArmy) || slotsArmy.ActiveMarches < slotsArmy.MarchSlots;
sendButton.interactable = available > 0 && slotFree;
if (scoutButton != null) scoutButton.interactable = available > 0 && slotFree;
UpdateSoldiersToSendText();
RefreshAttackConditions(); // путь -- по составу при выбранном числе воинов
@@ -669,6 +708,14 @@ public class WorldMapController : MonoBehaviour
EnqueuePopup(title, body);
}
void HandleScoutArrived(MarchData march)
{
string target = World.TargetName(march);
hintText.text = march.targetEmpty
? $"Разведка: «{target}» уже нет, войско возвращается"
: $"Разведка дошла до цели «{target}» и возвращается домой";
}
void HandleGatherStarted(MarchData march)
{
string target = World.TargetName(march);