Files
trail-into-darkness/Assets/Code/GameState/PlayModes/AdventurePlayMode.cs
2026-05-06 11:29:50 +02:00

221 lines
9.4 KiB
C#

using Jovian.Calendar;
using Jovian.EncounterSystem;
using Jovian.PopupSystem;
using Jovian.PopupSystem.UI;
using Jovian.SaveSystem;
using Jovian.ZoneSystem;
using Nox.Core;
using Nox.Platform;
using Nox.Game.UI;
using Nox.UI;
using ZLinq;
using UnityEngine;
using UnityEngine.AddressableAssets;
using PlayMode = Nox.Core.PlayMode;
namespace Nox.Game {
public class AdventureData {
public bool isPartyMoving;
public int currentDay = 0;
public int suppliesAvailable = -1;
public float currentTime = -1f;
public DayPhase currentDayPhase = DayPhase.Morning;
}
public class AdventurePlayMode : IPlayMode {
private readonly PlatformSettings platformSettings;
private readonly PlayModeSettings bootstrapSettings;
private readonly GameDataState gameDataState;
private readonly ISaveSystem saveSystem;
private readonly PartyDefinition partyDefinition;
private readonly AdventureSettings adventureSettings;
private AdventureData adventureData;
private AdventureModePrefabs scenePrefabs;
private ICameraController cameraController;
private MapReference mapRef;
private PartyMovementHandler partyMovementHandler;
private PartyReference partyRef;
private MapLocationsReference mapLocationsReference;
private InputSystem_Actions inputActions;
private AdventureView adventureView;
private ZoneSystem zoneSystem;
private GuiReferences guiReferences;
private TimeHandler timeHandler;
private PartyInventoryHandler partyInventoryHandler;
private PartyGuiView partyGuiView;
private IPopupSystem popupSystem;
private EncounterRegistry encounterRegistry;
private EncounterHandler encounterHandler;
private EncounterPrefabs encounterPrefabs;
public AdventurePlayMode(
PlatformSettings platformSettings,
PartyDefinition partyDefinition,
PlayModeSettings bootstrapSettings,
GameDataState gameDataState,
ISaveSystem saveSystem,
AdventureSettings adventureSettings,
AdventureData adventureData) {
this.platformSettings = platformSettings;
this.partyDefinition = partyDefinition;
this.bootstrapSettings = bootstrapSettings;
this.gameDataState = gameDataState;
this.saveSystem = saveSystem;
this.adventureSettings = adventureSettings;
this.adventureData = adventureData;
}
public bool IsGameModeInitialized { get; private set; }
public void EnterPlayMode() {
inputActions = platformSettings.inputSettings.inputActions;
if(IsGameModeInitialized) {
inputActions.Player.Enable();
inputActions.UI.PauseMenu.Enable();
partyMovementHandler.ConsumeNextClick();
return;
}
Addressables.LoadSceneAsync(bootstrapSettings.gameModeData.AsValueEnumerable().FirstOrDefault(g => g.playMode == PlayMode.Adventure)?.scene)
.WaitForCompletion().ActivateAsync().completed += InitializeGameMode;
}
private void InitializeGameMode(AsyncOperation obj) {
inputActions.Player.Enable();
inputActions.UI.PauseMenu.Enable();
Debug.Log("Entering Adventure Play Mode");
if(partyDefinition == null) {
var sessions = saveSystem.GetAllSessions().AsValueEnumerable().OrderByDescending(s => s.lastSaveDateUtc).ToList();
if(sessions.Count == 0) {
return;
}
var latestSession = sessions[0];
var slots = saveSystem.GetSlots(latestSession.sessionId).AsValueEnumerable().OrderByDescending(s => s.timestampUtc).ToList();
if(slots.Count == 0) {
return;
}
var latestSlot = slots[0];
var saveData = saveSystem.Load<NoxSaveData>(latestSlot);
Debug.Log($"Loaded save {latestSlot.DisplayLabel}");
if(saveData == null) {
Debug.LogError("Failed to load save data");
return;
}
NoxSaveData.RestoreSavedData(saveSystem, gameDataState, ref adventureData);
Debug.LogWarning("AdventurePlayMode started from the Adventure Scene. Loading the last Autosave");
}
encounterRegistry ??= Addressables.LoadAssetAsync<EncounterRegistry>("EncounterRegistry").WaitForCompletion();
scenePrefabs ??= Addressables.LoadAssetAsync<AdventureModePrefabs>("AdventureMapPrefabs").WaitForCompletion();
encounterPrefabs = Addressables.LoadAssetAsync<EncounterPrefabs>("EncounterPrefabs").WaitForCompletion();
mapRef ??= Object.FindFirstObjectByType<MapReference>();
partyRef ??= Object.FindFirstObjectByType<PartyReference>();
if(partyRef && gameDataState.savedPartyPosition.HasValue) {
partyRef.transform.position = gameDataState.savedPartyPosition.Value;
}
mapLocationsReference ??= Object.FindFirstObjectByType<MapLocationsReference>();
if(!mapRef) {
mapRef ??= Object.Instantiate(scenePrefabs.mapReferencePrefab);
}
cameraController ??= new CameraController(platformSettings, mapRef);
cameraController.Initialize();
if(adventureData.suppliesAvailable == -1) {
adventureData.suppliesAvailable = adventureSettings.maxSupplies;
}
if(Mathf.Approximately(adventureData.currentTime, -1f)) {
adventureData.currentTime = 0.25f;
}
partyInventoryHandler ??= new PartyInventoryHandler(adventureData, adventureSettings);
partyInventoryHandler.Initialize();
var calendarSettings = Addressables.LoadAssetAsync<CalendarSettings>("CalendarSettings").WaitForCompletion();
var worldClock = new WorldClock(calendarSettings);
timeHandler ??= new TimeHandler(adventureSettings, adventureData, worldClock);
zoneSystem ??= new ZoneSystem(mapRef.zonesObjectHolder);
encounterHandler = new EncounterHandler(zoneSystem, encounterRegistry, encounterPrefabs);
partyMovementHandler ??= new PartyMovementHandler(
partyRef,
cameraController,
mapLocationsReference,
platformSettings.inputSettings,
encounterHandler,
adventureData,
adventureSettings);
partyMovementHandler.Initialize();
guiReferences ??= Object.FindFirstObjectByType<GuiReferences>();
adventureView ??= new AdventureView(gameDataState, guiReferences, inputActions, adventureData, adventureSettings, worldClock);
adventureView.Initialize();
if(partyGuiView == null && guiReferences.partyMemberSlotPrefab != null) {
var portraitsHolder = Addressables.LoadAssetAsync<PortraitsHolder>("PortraitsHolder").WaitForCompletion();
if(popupSystem == null) {
var popupSettings = Addressables.LoadAssetAsync<PopupSettings>("PopupSettings").WaitForCompletion();
var popupViewPrefab = Addressables.LoadAssetAsync<GameObject>("PopupReferencePrefab").WaitForCompletion().GetComponent<PopupReference>();
var guiCanvas = guiReferences.GetComponentInParent<Canvas>().transform;
popupSystem = new PopupSystem(popupSettings, popupViewPrefab, guiCanvas);
popupSystem.RegisterCategory(PopupCategory.Character, priority: 10);
}
partyGuiView = new PartyGuiView(guiReferences.portraitsContainer, guiReferences.partyMemberSlotPrefab, portraitsHolder, popupSystem);
partyGuiView.Initialize(partyDefinition);
}
IsGameModeInitialized = true;
}
public void Tick() {
if(!IsGameModeInitialized) {
return;
}
timeHandler.Tick();
partyInventoryHandler.Tick();
partyMovementHandler.Tick();
encounterHandler.Tick();
adventureView.Tick();
partyGuiView?.Tick();
popupSystem?.Tick(Time.deltaTime);
if(inputActions.UI.PauseMenu.WasPerformedThisFrame()) {
gameDataState.ChangePlayMode(PlayMode.PauseMenu);
}
}
public void LateTick() {
if(!IsGameModeInitialized) {
return;
}
cameraController.Tick();
}
public NoxSavedDataSet CaptureNoxSaveData() {
return new NoxSavedDataSet {
activePlayMode = PlayMode.Adventure,
activeParty = partyDefinition,
partyPosition = partyRef ? SerializableVector3.FromVector3(partyRef.transform.position) : SerializableVector3.Zero
};
}
public void ExitGameMode() {
inputActions.Player.Disable();
inputActions.UI.PauseMenu.Disable();
}
public void Dispose() {
partyGuiView?.Dispose();
popupSystem?.Dispose();
cameraController?.Dispose();
partyMovementHandler?.Dispose();
encounterHandler?.Dispose();
encounterRegistry = null;
Resources.UnloadUnusedAssets();
}
}
}