2021-03-13 03:23:58 +00:00
|
|
|
using System;
|
2026-08-10 14:57:50 +01:00
|
|
|
using System.Collections;
|
2026-06-30 19:14:49 +01:00
|
|
|
using System.Collections.Generic;
|
2026-08-10 14:57:50 +01:00
|
|
|
using System.IO;
|
Land RunSave and the one-cache run and player lifecycle (Cut 10)
Owner: ActionGameManager composes the process's one cache. Its CultCache
getter attaches the catalog, GameData/run.cc and GameData/player.cc on
first access, in either scene, and nothing reopens it.
- RunSave (SavedGame.cs) replaces the SavedGame constructor:
- Capture builds the live run as plain documents and writes nothing. Zone
contents are `zone.Contents?.PackZone() ?? zone.PackedContents`, so a
zone generated earlier but not loaded this session keeps its contents
and its orbit and body records instead of being erased by the next save.
- Commit is the only writer of SavedGame and SavedZone: one Commit with
zone i at `savedzone-{i}`, SavedGame.Zones set to those refs, and every
stored SavedZone outside that set removed. Orbits and bodies staged by
zone generation land in the same single-file write.
- Clear removes every run record in one Commit.
- Run begins: New Game's first statement is RunSave.Clear. Run saves:
ActionGameManager.SaveRun at wormhole arrival and quit. Run ends: Die
clears the run, then saves settings.
- Run exists only as the run store's SavedGame global: MainMenu enables
Continue from it (and logs when the run store holds records but no
SavedGame), and StartGame reads it once to pick the new-run or resume
branch.
- PlayerSettings: the getter returns the player store's global and, on
first launch, commits GetDefaultPlayerSettings; it is the only creator.
SavePlayerSettings commits the instance.
- InputDisplayLayout reads its InputLayout from the catalog by the layout
asset's name and throws when the catalog has none.
Tests: new RunSaveTests (5): RepeatedSavesKeepRecordCountConstant,
SaveRemovesZonesNoLongerInTheRun, SaveWritesOnlyTheRunStore,
ResumeThenSaveKeepsUnloadedZoneContents, ClearRemovesEveryRunRecord. Each
fails with its rule mutated out.
Builds: headless, 11 tests pass, Unity batchmode compile reports no error CS.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 22:00:27 +02:00
|
|
|
using System.Linq;
|
2026-08-10 14:57:50 +01:00
|
|
|
using System.Threading;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using TMPro;
|
2021-03-15 11:40:46 +00:00
|
|
|
using UniRx;
|
2021-03-13 03:23:58 +00:00
|
|
|
using UnityEngine;
|
2021-03-14 03:56:49 +00:00
|
|
|
using UnityEngine.SceneManagement;
|
2021-03-13 03:23:58 +00:00
|
|
|
using UnityEngine.UI;
|
2026-09-14 17:39:12 +02:00
|
|
|
using static CultMath.math;
|
2021-03-13 03:23:58 +00:00
|
|
|
|
|
|
|
|
public class MainMenu : MonoBehaviour
|
|
|
|
|
{
|
2022-07-18 08:44:54 +01:00
|
|
|
public VolumeCloudRenderer CloudRenderer;
|
2021-03-20 04:20:17 +00:00
|
|
|
public GameSettings Settings;
|
2021-03-15 11:40:46 +00:00
|
|
|
public ConfirmationDialog Dialog;
|
2021-03-14 03:56:49 +00:00
|
|
|
public bool InGame;
|
2026-08-10 14:57:50 +01:00
|
|
|
public Prototype PanelPrototype;
|
|
|
|
|
public float FadeTime = .5f;
|
|
|
|
|
public float FadeDistance = 512;
|
|
|
|
|
public float FadeAlphaExponent = 2;
|
|
|
|
|
public float FadePositionExponent = 2;
|
|
|
|
|
|
|
|
|
|
private (PropertiesPanel panel, CanvasGroup group) _currentMenu, _nextMenu;
|
|
|
|
|
private bool _fadeFromRight;
|
|
|
|
|
private float _fadeLerp;
|
|
|
|
|
private bool _fading;
|
|
|
|
|
private Vector3 _panelPosition;
|
|
|
|
|
//private Task<DatabaseCache> _databaseLoad;
|
2021-03-13 03:23:58 +00:00
|
|
|
|
|
|
|
|
void Start()
|
|
|
|
|
{
|
2026-08-10 14:57:50 +01:00
|
|
|
// Start loading the database in the background 'cause it takes a few seconds
|
|
|
|
|
//_databaseLoad = Task.Run(() => ActionGameManager.Database);
|
|
|
|
|
|
|
|
|
|
_panelPosition = PanelPrototype.transform.position;
|
|
|
|
|
|
|
|
|
|
var panel1 = PanelPrototype.Instantiate<PropertiesPanel>();
|
|
|
|
|
_currentMenu = (panel1, panel1.GetComponent<CanvasGroup>());
|
|
|
|
|
|
|
|
|
|
var panel2 = PanelPrototype.Instantiate<PropertiesPanel>();
|
|
|
|
|
_nextMenu = (panel2, panel2.GetComponent<CanvasGroup>());
|
|
|
|
|
|
|
|
|
|
_currentMenu.panel.gameObject.SetActive(false);
|
|
|
|
|
//_saveDirectory = ActionGameManager.GameDataDirectory.CreateSubdirectory("Saves");
|
|
|
|
|
|
|
|
|
|
ShowMain();
|
|
|
|
|
Fade(true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void Update()
|
|
|
|
|
{
|
|
|
|
|
if (_fading)
|
|
|
|
|
{
|
|
|
|
|
_fadeLerp += Time.deltaTime / FadeTime;
|
|
|
|
|
|
|
|
|
|
_currentMenu.panel.transform.position =
|
|
|
|
|
_panelPosition + (_fadeFromRight ? Vector3.left : Vector3.right) * (FadeDistance * pow(_fadeLerp, FadePositionExponent));
|
|
|
|
|
_nextMenu.panel.transform.position =
|
|
|
|
|
_panelPosition + (_fadeFromRight ? Vector3.right : Vector3.left) * (FadeDistance * pow(1-_fadeLerp, FadePositionExponent));
|
|
|
|
|
_currentMenu.group.alpha = pow(1 - _fadeLerp, FadeAlphaExponent);
|
|
|
|
|
_nextMenu.group.alpha = pow(_fadeLerp, FadeAlphaExponent);
|
|
|
|
|
|
|
|
|
|
if (_fadeLerp > 1)
|
2026-06-30 19:14:49 +01:00
|
|
|
{
|
2026-08-10 14:57:50 +01:00
|
|
|
_fading = false;
|
|
|
|
|
_currentMenu.panel.gameObject.SetActive(false);
|
|
|
|
|
var temp = _currentMenu;
|
|
|
|
|
_currentMenu = _nextMenu;
|
|
|
|
|
_nextMenu = temp;
|
2026-06-30 19:14:49 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-10 14:57:50 +01:00
|
|
|
private string TitleSubtitle(string title, string subtitle) => $"{title}\n<smallcaps><size=50%>{subtitle}";
|
2026-06-30 19:14:49 +01:00
|
|
|
|
2026-08-10 14:57:50 +01:00
|
|
|
private void Fade(bool fromRight)
|
2026-06-30 19:14:49 +01:00
|
|
|
{
|
2026-08-10 14:57:50 +01:00
|
|
|
_nextMenu.panel.gameObject.SetActive(true);
|
|
|
|
|
_nextMenu.group.alpha = 0;
|
|
|
|
|
_fading = true;
|
|
|
|
|
_fadeLerp = 0;
|
|
|
|
|
_fadeFromRight = fromRight;
|
2026-06-30 19:14:49 +01:00
|
|
|
}
|
|
|
|
|
|
Ship S2 fixes: structural anchors are not mounts, mod presets refused, one bad mod never bricks the boot
- Validate: a hardpoint's anchor role is fixed by its type (thruster-emitter, radiator-mesh, else articulation); ShipModPlan's
duplicate role check is deleted.
- Loadouts.Commit refuses a preset naming a mod design (mod-hull:/mod-ship:), so the shipped catalog never references a mod.
- Compose quarantines each package: a bad package is excluded and named, a collision excludes every package involved; the
game boots on the rest (or the shipped catalog) and the main menu lists the exclusions.
- RequireDesigns refuses a save with a null item or lot instead of throwing NullReferenceException.
- Tests: per structural role, muzzle id ties, every slot/zone/lot in RequireDesigns, listing order, exclusion cases.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 08:30:52 +02:00
|
|
|
private static bool _exclusionsShown;
|
|
|
|
|
|
2026-08-10 14:57:50 +01:00
|
|
|
private void ShowMain()
|
2026-06-30 19:14:49 +01:00
|
|
|
{
|
2026-08-10 14:57:50 +01:00
|
|
|
_nextMenu.panel.Clear();
|
|
|
|
|
_nextMenu.panel.Title.text = TitleSubtitle("aetheria", "terminus");
|
Land RunSave and the one-cache run and player lifecycle (Cut 10)
Owner: ActionGameManager composes the process's one cache. Its CultCache
getter attaches the catalog, GameData/run.cc and GameData/player.cc on
first access, in either scene, and nothing reopens it.
- RunSave (SavedGame.cs) replaces the SavedGame constructor:
- Capture builds the live run as plain documents and writes nothing. Zone
contents are `zone.Contents?.PackZone() ?? zone.PackedContents`, so a
zone generated earlier but not loaded this session keeps its contents
and its orbit and body records instead of being erased by the next save.
- Commit is the only writer of SavedGame and SavedZone: one Commit with
zone i at `savedzone-{i}`, SavedGame.Zones set to those refs, and every
stored SavedZone outside that set removed. Orbits and bodies staged by
zone generation land in the same single-file write.
- Clear removes every run record in one Commit.
- Run begins: New Game's first statement is RunSave.Clear. Run saves:
ActionGameManager.SaveRun at wormhole arrival and quit. Run ends: Die
clears the run, then saves settings.
- Run exists only as the run store's SavedGame global: MainMenu enables
Continue from it (and logs when the run store holds records but no
SavedGame), and StartGame reads it once to pick the new-run or resume
branch.
- PlayerSettings: the getter returns the player store's global and, on
first launch, commits GetDefaultPlayerSettings; it is the only creator.
SavePlayerSettings commits the instance.
- InputDisplayLayout reads its InputLayout from the catalog by the layout
asset's name and throws when the catalog has none.
Tests: new RunSaveTests (5): RepeatedSavesKeepRecordCountConstant,
SaveRemovesZonesNoLongerInTheRun, SaveWritesOnlyTheRunStore,
ResumeThenSaveKeepsUnloadedZoneContents, ClearRemovesEveryRunRecord. Each
fails with its rule mutated out.
Builds: headless, 11 tests pass, Unity batchmode compile reports no error CS.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 22:00:27 +02:00
|
|
|
if (!InGame)
|
|
|
|
|
{
|
|
|
|
|
// A run exists only as the run store's SavedGame global.
|
|
|
|
|
var cache = ActionGameManager.CultCache;
|
Ship S2 fixes: structural anchors are not mounts, mod presets refused, one bad mod never bricks the boot
- Validate: a hardpoint's anchor role is fixed by its type (thruster-emitter, radiator-mesh, else articulation); ShipModPlan's
duplicate role check is deleted.
- Loadouts.Commit refuses a preset naming a mod design (mod-hull:/mod-ship:), so the shipped catalog never references a mod.
- Compose quarantines each package: a bad package is excluded and named, a collision excludes every package involved; the
game boots on the rest (or the shipped catalog) and the main menu lists the exclusions.
- RequireDesigns refuses a save with a null item or lot instead of throwing NullReferenceException.
- Tests: per structural role, muzzle id ties, every slot/zone/lot in RequireDesigns, listing order, exclusion cases.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 08:30:52 +02:00
|
|
|
if (ActionGameManager.ModExclusions.Length > 0 && !_exclusionsShown)
|
|
|
|
|
{
|
|
|
|
|
_exclusionsShown = true;
|
|
|
|
|
Refuse("Some mods were not loaded", string.Join("\n", ActionGameManager.ModExclusions.Select(exclusion => exclusion.ToString())));
|
|
|
|
|
}
|
Land RunSave and the one-cache run and player lifecycle (Cut 10)
Owner: ActionGameManager composes the process's one cache. Its CultCache
getter attaches the catalog, GameData/run.cc and GameData/player.cc on
first access, in either scene, and nothing reopens it.
- RunSave (SavedGame.cs) replaces the SavedGame constructor:
- Capture builds the live run as plain documents and writes nothing. Zone
contents are `zone.Contents?.PackZone() ?? zone.PackedContents`, so a
zone generated earlier but not loaded this session keeps its contents
and its orbit and body records instead of being erased by the next save.
- Commit is the only writer of SavedGame and SavedZone: one Commit with
zone i at `savedzone-{i}`, SavedGame.Zones set to those refs, and every
stored SavedZone outside that set removed. Orbits and bodies staged by
zone generation land in the same single-file write.
- Clear removes every run record in one Commit.
- Run begins: New Game's first statement is RunSave.Clear. Run saves:
ActionGameManager.SaveRun at wormhole arrival and quit. Run ends: Die
clears the run, then saves settings.
- Run exists only as the run store's SavedGame global: MainMenu enables
Continue from it (and logs when the run store holds records but no
SavedGame), and StartGame reads it once to pick the new-run or resume
branch.
- PlayerSettings: the getter returns the player store's global and, on
first launch, commits GetDefaultPlayerSettings; it is the only creator.
SavePlayerSettings commits the instance.
- InputDisplayLayout reads its InputLayout from the catalog by the layout
asset's name and throws when the catalog has none.
Tests: new RunSaveTests (5): RepeatedSavesKeepRecordCountConstant,
SaveRemovesZonesNoLongerInTheRun, SaveWritesOnlyTheRunStore,
ResumeThenSaveKeepsUnloadedZoneContents, ClearRemovesEveryRunRecord. Each
fails with its rule mutated out.
Builds: headless, 11 tests pass, Unity batchmode compile reports no error CS.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 22:00:27 +02:00
|
|
|
var saved = cache.GetGlobal<SavedGame>();
|
|
|
|
|
if (saved == null && cache.AllStoredDocuments.Any(stored => RunSave.IsRunRecord(stored.Descriptor.DocumentType)))
|
|
|
|
|
Debug.Log("run store has no SavedGame; Continue disabled");
|
|
|
|
|
_nextMenu.panel.AddButton("Continue", saved == null ? (Action) null : () =>
|
|
|
|
|
{
|
2026-09-30 06:43:52 +02:00
|
|
|
try { RunSave.RequireDesigns(cache, saved); }
|
|
|
|
|
catch (InvalidOperationException error) { Refuse("Cannot continue this run", error.Message); return; }
|
Land RunSave and the one-cache run and player lifecycle (Cut 10)
Owner: ActionGameManager composes the process's one cache. Its CultCache
getter attaches the catalog, GameData/run.cc and GameData/player.cc on
first access, in either scene, and nothing reopens it.
- RunSave (SavedGame.cs) replaces the SavedGame constructor:
- Capture builds the live run as plain documents and writes nothing. Zone
contents are `zone.Contents?.PackZone() ?? zone.PackedContents`, so a
zone generated earlier but not loaded this session keeps its contents
and its orbit and body records instead of being erased by the next save.
- Commit is the only writer of SavedGame and SavedZone: one Commit with
zone i at `savedzone-{i}`, SavedGame.Zones set to those refs, and every
stored SavedZone outside that set removed. Orbits and bodies staged by
zone generation land in the same single-file write.
- Clear removes every run record in one Commit.
- Run begins: New Game's first statement is RunSave.Clear. Run saves:
ActionGameManager.SaveRun at wormhole arrival and quit. Run ends: Die
clears the run, then saves settings.
- Run exists only as the run store's SavedGame global: MainMenu enables
Continue from it (and logs when the run store holds records but no
SavedGame), and StartGame reads it once to pick the new-run or resume
branch.
- PlayerSettings: the getter returns the player store's global and, on
first launch, commits GetDefaultPlayerSettings; it is the only creator.
SavePlayerSettings commits the instance.
- InputDisplayLayout reads its InputLayout from the catalog by the layout
asset's name and throws when the catalog has none.
Tests: new RunSaveTests (5): RepeatedSavesKeepRecordCountConstant,
SaveRemovesZonesNoLongerInTheRun, SaveWritesOnlyTheRunStore,
ResumeThenSaveKeepsUnloadedZoneContents, ClearRemovesEveryRunRecord. Each
fails with its rule mutated out.
Builds: headless, 11 tests pass, Unity batchmode compile reports no error CS.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 22:00:27 +02:00
|
|
|
ActionGameManager.CurrentGalaxy = new Galaxy(cache, saved, Debug.Log);
|
2026-09-30 06:43:52 +02:00
|
|
|
EnterGame();
|
Land RunSave and the one-cache run and player lifecycle (Cut 10)
Owner: ActionGameManager composes the process's one cache. Its CultCache
getter attaches the catalog, GameData/run.cc and GameData/player.cc on
first access, in either scene, and nothing reopens it.
- RunSave (SavedGame.cs) replaces the SavedGame constructor:
- Capture builds the live run as plain documents and writes nothing. Zone
contents are `zone.Contents?.PackZone() ?? zone.PackedContents`, so a
zone generated earlier but not loaded this session keeps its contents
and its orbit and body records instead of being erased by the next save.
- Commit is the only writer of SavedGame and SavedZone: one Commit with
zone i at `savedzone-{i}`, SavedGame.Zones set to those refs, and every
stored SavedZone outside that set removed. Orbits and bodies staged by
zone generation land in the same single-file write.
- Clear removes every run record in one Commit.
- Run begins: New Game's first statement is RunSave.Clear. Run saves:
ActionGameManager.SaveRun at wormhole arrival and quit. Run ends: Die
clears the run, then saves settings.
- Run exists only as the run store's SavedGame global: MainMenu enables
Continue from it (and logs when the run store holds records but no
SavedGame), and StartGame reads it once to pick the new-run or resume
branch.
- PlayerSettings: the getter returns the player store's global and, on
first launch, commits GetDefaultPlayerSettings; it is the only creator.
SavePlayerSettings commits the instance.
- InputDisplayLayout reads its InputLayout from the catalog by the layout
asset's name and throws when the catalog has none.
Tests: new RunSaveTests (5): RepeatedSavesKeepRecordCountConstant,
SaveRemovesZonesNoLongerInTheRun, SaveWritesOnlyTheRunStore,
ResumeThenSaveKeepsUnloadedZoneContents, ClearRemovesEveryRunRecord. Each
fails with its rule mutated out.
Builds: headless, 11 tests pass, Unity batchmode compile reports no error CS.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 22:00:27 +02:00
|
|
|
});
|
|
|
|
|
}
|
2026-08-10 14:57:50 +01:00
|
|
|
_nextMenu.panel.AddButton("New Game",
|
|
|
|
|
() =>
|
|
|
|
|
{
|
Every new run is a scenario: the script harness, the tutorial and main galaxies as scenarios, the New Game submenu and six test arenas
A Scenario is an abstract C# class compiled with the game: Generate picks the galaxy through GalaxyStage (Main or
Prelude, at the scenario's seed, the background noise drawn from the same seed), Stage places the run's first
entities through ScenarioStage (Fit, Bare, Generated, Preset, Player, Place, Cargo), which collects named failures
and admits nothing. RunStart generates the galaxy, the arena under Ambient and admits everything through Zone.Admit,
all or nothing. The aetheria.scenario record, ScenarioShip, ScenarioEntity, RunStart.Check and the null-scenario
branch are cut.
New Game opens a submenu: Tutorial Galaxy and Main Galaxy, then (editor and development builds) Djinni Shakedown,
Starved Reactor, Arcs, Duel, Launcher Angles and Long Haul, each with its brief. MainMenu.Launch is the one way into a
new run; ActionGameManager.PendingScenario carries the scenario to StartGame once.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 20:33:55 +02:00
|
|
|
ShowScenarios();
|
2026-08-10 14:57:50 +01:00
|
|
|
Fade(true);
|
|
|
|
|
});
|
|
|
|
|
_nextMenu.panel.AddButton("Settings",
|
|
|
|
|
() =>
|
|
|
|
|
{
|
|
|
|
|
ShowSettings();
|
|
|
|
|
Fade(true);
|
|
|
|
|
});
|
|
|
|
|
_nextMenu.panel.AddButton("Quit", Application.Quit);
|
2026-06-17 06:10:41 +01:00
|
|
|
}
|
|
|
|
|
|
Every new run is a scenario: the script harness, the tutorial and main galaxies as scenarios, the New Game submenu and six test arenas
A Scenario is an abstract C# class compiled with the game: Generate picks the galaxy through GalaxyStage (Main or
Prelude, at the scenario's seed, the background noise drawn from the same seed), Stage places the run's first
entities through ScenarioStage (Fit, Bare, Generated, Preset, Player, Place, Cargo), which collects named failures
and admits nothing. RunStart generates the galaxy, the arena under Ambient and admits everything through Zone.Admit,
all or nothing. The aetheria.scenario record, ScenarioShip, ScenarioEntity, RunStart.Check and the null-scenario
branch are cut.
New Game opens a submenu: Tutorial Galaxy and Main Galaxy, then (editor and development builds) Djinni Shakedown,
Starved Reactor, Arcs, Duel, Launcher Angles and Long Haul, each with its brief. MainMenu.Launch is the one way into a
new run; ActionGameManager.PendingScenario carries the scenario to StartGame once.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 20:33:55 +02:00
|
|
|
// New Game: every way to set up a run, each with its brief. The test arenas are listed only in editor and
|
|
|
|
|
// development builds.
|
|
|
|
|
private void ShowScenarios()
|
|
|
|
|
{
|
|
|
|
|
_nextMenu.panel.Clear();
|
|
|
|
|
_nextMenu.panel.Title.text = TitleSubtitle("new game", "scenarios");
|
|
|
|
|
AddScenarios(Scenarios.Modes);
|
|
|
|
|
if (Debug.isDebugBuild)
|
|
|
|
|
{
|
|
|
|
|
_nextMenu.panel.AddSection("test arenas");
|
|
|
|
|
AddScenarios(Scenarios.Tests);
|
|
|
|
|
}
|
|
|
|
|
_nextMenu.panel.AddButton("Back",
|
|
|
|
|
() =>
|
|
|
|
|
{
|
|
|
|
|
ShowMain();
|
|
|
|
|
Fade(false);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void AddScenarios(IEnumerable<Scenario> scenarios)
|
|
|
|
|
{
|
|
|
|
|
foreach (var scenario in scenarios)
|
|
|
|
|
{
|
|
|
|
|
_nextMenu.panel.AddButton(scenario.Name, () => Launch(scenario));
|
|
|
|
|
_nextMenu.panel.AddProperty(() => scenario.Brief);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// The only way into a new run: clears the saved run, generates the scenario's galaxy off the main thread, and
|
|
|
|
|
// enters the game, where StartGame has RunStart stage it.
|
|
|
|
|
private void Launch(Scenario scenario)
|
|
|
|
|
{
|
|
|
|
|
RunSave.Clear(ActionGameManager.CultCache);
|
|
|
|
|
var generatorState = "Loading Database Contents";
|
|
|
|
|
|
|
|
|
|
Fade(true);
|
|
|
|
|
_nextMenu.panel.gameObject.SetActive(false);
|
|
|
|
|
Dialog.Clear();
|
|
|
|
|
Dialog.Title.text = "Generating Galaxy";
|
|
|
|
|
Dialog.AddProperty(() => generatorState);
|
|
|
|
|
Dialog.Show();
|
|
|
|
|
|
|
|
|
|
var stage = new GalaxyStage(
|
|
|
|
|
Settings.SectorGenerationSettings,
|
|
|
|
|
Settings.SectorBackgroundSettings,
|
|
|
|
|
Settings.TutorialGenerationSettings,
|
|
|
|
|
Settings.TutorialBackgroundSettings,
|
|
|
|
|
Settings.NameGeneratorSettings,
|
|
|
|
|
ActionGameManager.CultCache,
|
|
|
|
|
ActionGameManager.PlayerSettings,
|
|
|
|
|
ActionGameManager.GameDataDirectory.CreateSubdirectory("Narrative"),
|
|
|
|
|
Debug.Log,
|
|
|
|
|
state => generatorState = state);
|
|
|
|
|
Task.Run(() =>
|
|
|
|
|
{
|
|
|
|
|
var galaxy = RunStart.Generate(scenario, stage);
|
|
|
|
|
Observable.NextFrame().Subscribe(_ =>
|
|
|
|
|
{
|
|
|
|
|
ActionGameManager.CurrentGalaxy = galaxy;
|
|
|
|
|
ActionGameManager.PendingScenario = scenario;
|
|
|
|
|
EnterGame();
|
|
|
|
|
});
|
|
|
|
|
}).ContinueWith(t => Debug.LogException(t.Exception), TaskContinuationOptions.OnlyOnFaulted);
|
|
|
|
|
}
|
|
|
|
|
|
2026-09-30 06:43:52 +02:00
|
|
|
// The one way into the game scene. Mod ship prototypes import asynchronously at boot, so the scene waits for them,
|
2026-10-03 15:38:35 +02:00
|
|
|
// and a preload that could not run at all stops here with its reason rather than in the first zone.
|
2026-09-30 06:43:52 +02:00
|
|
|
private void EnterGame() => StartCoroutine(EnterGameWhenModShipsAreReady());
|
|
|
|
|
|
|
|
|
|
private IEnumerator EnterGameWhenModShipsAreReady()
|
|
|
|
|
{
|
|
|
|
|
var loading = ShipModShips.Loading;
|
|
|
|
|
while (!loading.IsCompleted) yield return null;
|
|
|
|
|
if (loading.IsFaulted)
|
|
|
|
|
{
|
|
|
|
|
Refuse("Mod ships failed to load", loading.Exception.GetBaseException().Message);
|
|
|
|
|
yield break;
|
|
|
|
|
}
|
|
|
|
|
SceneManager.LoadScene("ARPG");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void Refuse(string title, string reason)
|
|
|
|
|
{
|
|
|
|
|
Debug.LogError($"{title}: {reason}");
|
|
|
|
|
Dialog.Clear();
|
|
|
|
|
Dialog.Title.text = title;
|
|
|
|
|
Dialog.AddProperty(() => reason);
|
|
|
|
|
Dialog.Show(onCancel: () => { }, cancelText: "OK");
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-10 14:57:50 +01:00
|
|
|
private void ShowSettings()
|
2026-06-17 11:24:36 +01:00
|
|
|
{
|
2026-08-10 14:57:50 +01:00
|
|
|
_nextMenu.panel.Clear();
|
|
|
|
|
_nextMenu.panel.Title.text = "settings";
|
|
|
|
|
_nextMenu.panel.AddButton("Gameplay",
|
|
|
|
|
() =>
|
2026-06-17 12:14:16 +01:00
|
|
|
{
|
2026-08-10 14:57:50 +01:00
|
|
|
ShowGameplaySettings();
|
|
|
|
|
Fade(true);
|
|
|
|
|
});
|
|
|
|
|
_nextMenu.panel.AddButton("Graphics",
|
|
|
|
|
() =>
|
|
|
|
|
{
|
|
|
|
|
ShowGraphicsSettings();
|
|
|
|
|
Fade(true);
|
|
|
|
|
});
|
|
|
|
|
_nextMenu.panel.AddButton("Input",
|
|
|
|
|
() =>
|
|
|
|
|
{
|
|
|
|
|
ShowInputSettings();
|
|
|
|
|
Fade(true);
|
|
|
|
|
});
|
|
|
|
|
_nextMenu.panel.AddButton("Audio",
|
|
|
|
|
() =>
|
|
|
|
|
{
|
|
|
|
|
ShowAudioSettings();
|
|
|
|
|
Fade(true);
|
|
|
|
|
});
|
|
|
|
|
_nextMenu.panel.AddButton("Back",
|
|
|
|
|
() =>
|
|
|
|
|
{
|
|
|
|
|
ShowMain();
|
|
|
|
|
Fade(false);
|
|
|
|
|
});
|
2026-06-17 11:24:36 +01:00
|
|
|
}
|
2026-08-10 14:57:50 +01:00
|
|
|
|
|
|
|
|
private void ShowGameplaySettings()
|
|
|
|
|
{
|
|
|
|
|
_nextMenu.panel.Clear();
|
|
|
|
|
_nextMenu.panel.Title.text = TitleSubtitle("gameplay", "settings");
|
|
|
|
|
_nextMenu.panel.AddField("Name",
|
|
|
|
|
() => ActionGameManager.PlayerSettings.Name,
|
|
|
|
|
s => ActionGameManager.PlayerSettings.Name = s);
|
|
|
|
|
_nextMenu.panel.AddField("Temperature Unit",
|
|
|
|
|
() => (int) ActionGameManager.PlayerSettings.GameplaySettings.TemperatureUnit,
|
|
|
|
|
i => ActionGameManager.PlayerSettings.GameplaySettings.TemperatureUnit = (TemperatureUnit) i,
|
|
|
|
|
Enum.GetNames(typeof(TemperatureUnit)));
|
|
|
|
|
_nextMenu.panel.AddField("Significant Digits",
|
|
|
|
|
() => ActionGameManager.PlayerSettings.GameplaySettings.SignificantDigits,
|
|
|
|
|
i => ActionGameManager.PlayerSettings.GameplaySettings.SignificantDigits = i);
|
|
|
|
|
_nextMenu.panel.AddButton("Back",
|
|
|
|
|
() =>
|
|
|
|
|
{
|
|
|
|
|
ActionGameManager.SavePlayerSettings();
|
|
|
|
|
ShowSettings();
|
|
|
|
|
Fade(false);
|
|
|
|
|
});
|
2026-06-16 21:08:20 +01:00
|
|
|
}
|
|
|
|
|
|
2026-08-10 14:57:50 +01:00
|
|
|
private void ShowGraphicsSettings()
|
2026-06-16 19:05:00 +01:00
|
|
|
{
|
2026-08-10 14:57:50 +01:00
|
|
|
_nextMenu.panel.Clear();
|
|
|
|
|
_nextMenu.panel.Title.text = TitleSubtitle("graphics", "settings");
|
|
|
|
|
_nextMenu.panel.AddField("Nebula Quality",
|
|
|
|
|
() => (int)ActionGameManager.PlayerSettings.GraphicsSettings.NebulaQuality,
|
|
|
|
|
i =>
|
|
|
|
|
{
|
|
|
|
|
ActionGameManager.PlayerSettings.GraphicsSettings.NebulaQuality = (Quality)i;
|
|
|
|
|
CloudRenderer.quality = ActionGameManager.PlayerSettings.GraphicsSettings.NebulaQuality;
|
|
|
|
|
},
|
|
|
|
|
Enum.GetNames(typeof(Quality)));
|
|
|
|
|
_nextMenu.panel.AddField("Show Asteroids in Minimap",
|
|
|
|
|
() => ActionGameManager.PlayerSettings.GraphicsSettings.ShowAsteroidsInMinimap,
|
|
|
|
|
b => ActionGameManager.PlayerSettings.GraphicsSettings.ShowAsteroidsInMinimap = b);
|
|
|
|
|
_nextMenu.panel.AddButton("Back",
|
|
|
|
|
() =>
|
|
|
|
|
{
|
|
|
|
|
ShowSettings();
|
|
|
|
|
Fade(false);
|
|
|
|
|
});
|
2026-06-16 19:05:00 +01:00
|
|
|
}
|
|
|
|
|
|
2026-08-10 14:57:50 +01:00
|
|
|
private void ShowInputSettings()
|
2026-06-16 19:05:00 +01:00
|
|
|
{
|
2026-08-10 14:57:50 +01:00
|
|
|
_nextMenu.panel.Clear();
|
|
|
|
|
_nextMenu.panel.Title.text = TitleSubtitle("input", "settings");
|
|
|
|
|
_nextMenu.panel.AddButton("Back",
|
|
|
|
|
() =>
|
|
|
|
|
{
|
|
|
|
|
ShowSettings();
|
|
|
|
|
Fade(false);
|
|
|
|
|
});
|
2026-06-30 19:14:49 +01:00
|
|
|
}
|
|
|
|
|
|
2026-08-10 14:57:50 +01:00
|
|
|
private void ShowAudioSettings()
|
2026-06-30 19:14:49 +01:00
|
|
|
{
|
2026-08-10 14:57:50 +01:00
|
|
|
_nextMenu.panel.Clear();
|
|
|
|
|
_nextMenu.panel.Title.text = TitleSubtitle("audio", "settings");
|
|
|
|
|
_nextMenu.panel.AddButton("Back",
|
|
|
|
|
() =>
|
|
|
|
|
{
|
|
|
|
|
ShowSettings();
|
|
|
|
|
Fade(false);
|
|
|
|
|
});
|
2026-06-15 22:47:15 +01:00
|
|
|
}
|
2021-03-13 03:23:58 +00:00
|
|
|
}
|