Кристальная шахта: 3 синих кристалла за 7 реальных суток на шахту, до двух, пауза при полном хранилище (ответ 06.11, п. 3)

- CrystalMine (без Unity) + 5 тестов: ровно 3 за 7 суток, ×12 не действует, 49/50 -> 1, пауза, перезагрузка и часы назад без двойного начисления, офлайн-стройка
- Работает с конца стройки, офлайн досчитывается; вне недельного PvE-предела
- Вторая шахта -- Ратуша 9 (ТЕСТ); окно здания: следующий кристалл / пауза
- DEV «Ресурсы 100 000» -- обычные ресурсы мимо лимита склада

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Alexander
2026-11-06 16:31:47 +01:00
co-authored by Claude Opus 5.5
parent b51ad41925
commit 157d3ba510
12 changed files with 270 additions and 7 deletions
@@ -115,6 +115,7 @@ public class City3DController : MonoBehaviour, City3DSave.ILive
}
bool stateApplied; // сохранённый город уже поставлен (в первом кадре, после загрузки сохранения в Start)
public bool StateApplied => stateApplied;
void OnEnable()
{
+29
View File
@@ -116,6 +116,35 @@ public static class City3DGameplay
return string.Join(", ", parts.ToArray());
}
// Кристальные шахты: с какого момента каждая добывает (мс; long.MinValue -- давно достроена; конец стройки -- если
// ещё строится или достроилась офлайн). Город открыт -- по сцене, иначе -- по сохранению settlement3d.
// null -- город ещё не загружен: считать рано (иначе офлайн-время шахты пропало бы)
public static List<long> CrystalMinesActiveFrom()
{
var list = new List<long>();
var city = City3DController.Instance;
if (city != null)
{
if (!city.StateApplied) return null;
foreach (var id in Object.FindObjectsByType<PlacedBuildingId>(FindObjectsSortMode.None))
{
if (id.buildingName != "Кристалл") continue;
var t = BuildTimer.Of(id.gameObject);
list.Add(t != null && BuildTimer.IsConstructing(id.transform) ? t.endMs : long.MinValue);
}
return list;
}
if (!City3DSave.Loaded) return null;
if (City3DSave.Cached != null)
foreach (var e in City3DSave.Cached.buildings)
{
if (e == null || e.type != "Кристалл") continue;
bool building = e.timerKind == (int)BuildTimer.Kind.Build && e.level <= 1 && e.timerEndMs > 0;
list.Add(building ? e.timerEndMs : long.MinValue);
}
return list;
}
public static int CountBuilt(string gameName)
{
int n = 0;
+4
View File
@@ -39,6 +39,8 @@ public sealed class City3DSave : ISaveParticipant
public static readonly City3DSave Instance = new City3DSave();
public static Data Cached { get; private set; }
// Сохранение уже прочитано (или новая игра): по Cached можно считать здания вне 3D-сцены (Кристальная шахта на карте мира)
public static bool Loaded { get; private set; }
public static ILive Live;
public string SaveKey => "settlement3d";
@@ -51,6 +53,7 @@ public sealed class City3DSave : ISaveParticipant
public void Restore(string json)
{
Loaded = true;
Cached = string.IsNullOrEmpty(json) ? null : JsonUtility.FromJson<Data>(json);
if (Cached != null)
{
@@ -63,6 +66,7 @@ public sealed class City3DSave : ISaveParticipant
public void ResetState()
{
Loaded = true;
Cached = null;
Live?.OnSaveLoaded();
}