/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ using System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; using Cinemachine; using MessagePack; using TMPro; using UniRx; using UnityEngine; using Unity.Mathematics; using UnityEngine.InputSystem; using UnityEngine.UI; using static Unity.Mathematics.math; using float2 = Unity.Mathematics.float2; public class ActionGameManager : MonoBehaviour { public GameSettings Settings; public SectorRenderer SectorRenderer; // public MapView MapView; public CinemachineVirtualCamera DockCamera; public CinemachineVirtualCamera FollowCamera; public GameObject GameplayUI; public MenuPanel Menu; public MapRenderer MenuMap; public SchematicDisplay SchematicDisplay; public InventoryMenu Inventory; public InventoryPanel ShipPanel; public ConfirmationDialog ConfirmationDialog; public float2 Sensitivity; //public PlayerInput Input; // private CinemachineFramingTransposer _transposer; // private CinemachineComposer _composer; private DirectoryInfo _filePath; private bool _editMode; private float _time; private AetheriaInput _input; private int _zoomLevelIndex; private Ship _currentShip; // private ShipInput _shipInput; private float2 _shipYawPitch; private float3 _viewDirection; public List PlayerShips { get; } = new List(); public DatabaseCache ItemData { get; private set; } public ItemManager ItemManager { get; private set; } public Zone Zone { get; private set; } void Start() { // _transposer = DockCamera.GetCinemachineComponent(); // _composer = DockCamera.GetCinemachineComponent(); //_lookAt = new GameObject().transform; ConsoleController.MessageReceiver = this; _filePath = new DirectoryInfo(Application.dataPath).Parent.CreateSubdirectory("GameData"); ItemData = new DatabaseCache(); ItemData.Load(_filePath.FullName); ItemManager = new ItemManager(ItemData, Settings.GameplaySettings, Debug.Log); var zoneFile = Path.Combine(_filePath.FullName, "Home.zone"); // If the game has already been run, there will be a Home file containing a ZonePack; if not, generate one var zonePack = File.Exists(zoneFile) ? MessagePackSerializer.Deserialize(File.ReadAllBytes(zoneFile)): ZoneGenerator.GenerateZone( settings: Settings.ZoneSettings, // mapLayers: Context.MapLayers, // resources: Context.Resources, mass: Settings.DefaultZoneMass, radius: Settings.DefaultZoneRadius ); Zone = new Zone(Settings.PlanetSettings, zonePack); SectorRenderer.ItemManager = ItemManager; SectorRenderer.LoadZone(Zone); _input = new AetheriaInput(); _input.Player.Enable(); _input.Global.Enable(); _input.UI.Enable(); _zoomLevelIndex = Settings.DefaultMinimapZoom; _input.Player.MinimapZoom.performed += context => { _zoomLevelIndex = (_zoomLevelIndex + 1) % Settings.MinimapZoomLevels.Length; SectorRenderer.MinimapDistance = Settings.MinimapZoomLevels[_zoomLevelIndex]; }; _input.Global.MapToggle.performed += context => { if (Menu.gameObject.activeSelf && Menu.CurrentTab == MenuTab.Map) { Cursor.lockState = CursorLockMode.Locked; _input.Player.Enable(); Menu.gameObject.SetActive(false); GameplayUI.SetActive(true); return; } Cursor.lockState = CursorLockMode.None; _input.Player.Disable(); GameplayUI.SetActive(false); Menu.ShowTab(MenuTab.Map); MenuMap.Position = _currentShip.Position.xz; }; _input.Global.Inventory.performed += context => { if (Menu.gameObject.activeSelf && Menu.CurrentTab == MenuTab.Inventory) { Cursor.lockState = CursorLockMode.Locked; _input.Player.Enable(); Menu.gameObject.SetActive(false); GameplayUI.SetActive(true); return; } Cursor.lockState = CursorLockMode.None; _input.Player.Disable(); Menu.ShowTab(MenuTab.Inventory); GameplayUI.SetActive(false); var cargo = _currentShip.CargoBays.FirstOrDefault(); if (cargo != null) { Inventory.GetPanel.Display(cargo); } else Inventory.GetPanel.Clear(); Inventory.GetPanel.Display(_currentShip); }; _input.Global.Dock.performed += context => { if (_currentShip.Parent == null) Dock(); else Undock(); }; #region Trigger Groups _input.Player.PreviousWeaponGroup.performed += context => { if (_currentShip.Parent != null) return; SchematicDisplay.SelectedGroupIndex--; }; _input.Player.NextWeaponGroup.performed += context => { if (_currentShip.Parent != null) return; SchematicDisplay.SelectedGroupIndex++; }; _input.Player.PreviousWeapon.performed += context => { if (_currentShip.Parent != null) return; SchematicDisplay.SelectedItemIndex--; }; _input.Player.NextWeapon.performed += context => { if (_currentShip.Parent != null) return; SchematicDisplay.SelectedItemIndex++; }; _input.Player.ToggleWeaponGroup.performed += context => { if (_currentShip.Parent != null) return; var item = SchematicDisplay.SchematicItems[SchematicDisplay.SelectedItemIndex]; if (_currentShip.TriggerGroups[SchematicDisplay.SelectedGroupIndex].Contains(item.Item)) _currentShip.TriggerGroups[SchematicDisplay.SelectedGroupIndex].Remove(item.Item); else _currentShip.TriggerGroups[SchematicDisplay.SelectedGroupIndex].Add(item.Item); SchematicDisplay.UpdateTriggerGroups(); }; _input.Player.FireGroup1.started += context => { if (_currentShip.Parent != null) return; foreach (var item in _currentShip.TriggerGroups[0]) { foreach (var behaviors in item.BehaviorGroups) { if (behaviors.Switch != null) behaviors.Switch.Activated = true; behaviors.Trigger?.Pull(); } } }; _input.Player.FireGroup1.canceled += context => { if (_currentShip.Parent != null) return; foreach (var item in _currentShip.TriggerGroups[0]) { foreach (var behaviors in item.BehaviorGroups) { if (behaviors.Switch != null) behaviors.Switch.Activated = false; } } }; _input.Player.FireGroup2.started += context => { if (_currentShip.Parent != null) return; foreach (var item in _currentShip.TriggerGroups[1]) { foreach (var behaviors in item.BehaviorGroups) { if (behaviors.Switch != null) behaviors.Switch.Activated = true; behaviors.Trigger?.Pull(); } } }; _input.Player.FireGroup2.canceled += context => { if (_currentShip.Parent != null) return; foreach (var item in _currentShip.TriggerGroups[1]) { foreach (var behaviors in item.BehaviorGroups) { if (behaviors.Switch != null) behaviors.Switch.Activated = false; } } }; _input.Player.FireGroup3.started += context => { if (_currentShip.Parent != null) return; foreach (var item in _currentShip.TriggerGroups[2]) { foreach (var behaviors in item.BehaviorGroups) { if (behaviors.Switch != null) behaviors.Switch.Activated = true; behaviors.Trigger?.Pull(); } } }; _input.Player.FireGroup3.canceled += context => { if (_currentShip.Parent != null) return; foreach (var item in _currentShip.TriggerGroups[2]) { foreach (var behaviors in item.BehaviorGroups) { if (behaviors.Switch != null) behaviors.Switch.Activated = false; } } }; _input.Player.FireGroup4.started += context => { if (_currentShip.Parent != null) return; foreach (var item in _currentShip.TriggerGroups[3]) { foreach (var behaviors in item.BehaviorGroups) { if (behaviors.Switch != null) behaviors.Switch.Activated = true; behaviors.Trigger?.Pull(); } } }; _input.Player.FireGroup4.canceled += context => { if (_currentShip.Parent != null) return; foreach (var item in _currentShip.TriggerGroups[3]) { foreach (var behaviors in item.BehaviorGroups) { if (behaviors.Switch != null) behaviors.Switch.Activated = false; } } }; _input.Player.FireGroup5.started += context => { if (_currentShip.Parent != null) return; foreach (var item in _currentShip.TriggerGroups[4]) { foreach (var behaviors in item.BehaviorGroups) { if (behaviors.Switch != null) behaviors.Switch.Activated = true; behaviors.Trigger?.Pull(); } } }; _input.Player.FireGroup5.canceled += context => { if (_currentShip.Parent != null) return; foreach (var item in _currentShip.TriggerGroups[4]) { foreach (var behaviors in item.BehaviorGroups) { if (behaviors.Switch != null) behaviors.Switch.Activated = false; } } }; _input.Player.FireGroup6.started += context => { if (_currentShip.Parent != null) return; foreach (var item in _currentShip.TriggerGroups[5]) { foreach (var behaviors in item.BehaviorGroups) { if (behaviors.Switch != null) behaviors.Switch.Activated = true; behaviors.Trigger?.Pull(); } } }; _input.Player.FireGroup6.canceled += context => { if (_currentShip.Parent != null) return; foreach (var item in _currentShip.TriggerGroups[5]) { foreach (var behaviors in item.BehaviorGroups) { if (behaviors.Switch != null) behaviors.Switch.Activated = false; } } }; #endregion // ConsoleController.AddCommand("editmode", _ => ToggleEditMode()); ConsoleController.AddCommand("savezone", args => { if (args.Length > 0) Zone.Data.Name = args[0]; SaveZone(); }); var stationType = ItemData.GetAll().First(x=>x.HullType==HullType.Station); var stationHull = ItemManager.CreateInstance(stationType, 0, 1) as EquippableItem; var stationParent = Zone.PlanetInstances.Values.OrderByDescending(p => p.BodyData.Mass.Value).ElementAt(3); var stationParentOrbit = stationParent.Orbit.Data.ID; var stationParentPos = Zone.GetOrbitPosition(stationParentOrbit); var stationPos = stationParentPos + ItemManager.Random.NextFloat2Direction() * stationParent.GravityWellRadius.Value * .1f; var stationOrbit = Zone.CreateOrbit(stationParentOrbit, stationPos); var station = new OrbitalEntity(ItemManager, Zone, stationHull, stationOrbit.ID); Zone.Entities.Add(station); var dockingBayData = ItemData.GetAll().First(); var dockingBay = ItemManager.CreateInstance(dockingBayData, 1, 1) as EquippableItem; station.TryEquip(dockingBay); station.Active = true; var reactorData = ItemData.GetAll().First(x => x.HardpointType == HardpointType.Reactor && x.Shape.Height == 2); var autocannonData = ItemData.GetAll().First(x => x.Name == "Autocannon"); var ammoData = ItemData.GetAll().First(x => x.Name == "AC2 Ammo"); var turretType = ItemData.GetAll().First(x=>x.HullType==HullType.Turret); var turretHull = ItemManager.CreateInstance(turretType, 0, 1) as EquippableItem; var turretParent = Zone.PlanetInstances.Values.OrderByDescending(p => p.BodyData.Mass.Value).ElementAt(5); var turretParentOrbit = turretParent.Orbit.Data.ID; var turretParentPos = Zone.GetOrbitPosition(turretParentOrbit); var turretPos = turretParentPos + ItemManager.Random.NextFloat2Direction() * turretParent.GravityWellRadius.Value * .05f; var turretOrbit = Zone.CreateOrbit(turretParentOrbit, turretPos); var turret = new OrbitalEntity(ItemManager, Zone, turretHull, turretOrbit.ID); turret.TryEquip(ItemManager.CreateInstance(reactorData, .5f, 1) as EquippableItem); var controlModuleData = ItemData.GetAll().First(x => x.Name == "Murder Module"); turret.TryEquip(ItemManager.CreateInstance(controlModuleData, .5f, 1) as EquippableItem); turret.TryEquip(ItemManager.CreateInstance(autocannonData, .5f, 1) as EquippableItem); turret.TryEquip(ItemManager.CreateInstance(autocannonData, .5f, 1) as EquippableItem); var cargo1Data = ItemData.GetAll().First(x => x.Name == "Cargo Bay 1x1"); var cargo1 = ItemManager.CreateInstance(cargo1Data, .5f, 1); turret.TryEquip(cargo1 as EquippableItem); turret.CargoBays.First().TryStore(ItemManager.CreateInstance(ammoData, 400)); turret.Active = true; Zone.Entities.Add(turret); var hullType = ItemData.GetAll().First(x=>x.HullType==HullType.Ship); var shipHull = ItemManager.CreateInstance(hullType, 0, 1) as EquippableItem; var ship = new Ship(ItemManager, Zone, shipHull); PlayerShips.Add(ship); _currentShip = ship; var thrusterData = ItemData.GetAll().First(x => x.HardpointType == HardpointType.Thruster && x.Shape.Height == 1); for (int i = 0; i < 8; i++) { ship.TryEquip(ItemManager.CreateInstance(thrusterData, .5f, 1) as EquippableItem); //dockingCargo.TryStore(ItemManager.CreateInstance(thrusterData, .5f, 1)); } ship.TryEquip(ItemManager.CreateInstance(reactorData, .5f, 1) as EquippableItem); var cockpitData = ItemData.GetAll().First(x => x.Behaviors.Any(b=>b is CockpitData)); ship.TryEquip(ItemManager.CreateInstance(cockpitData, .5f, 1) as EquippableItem); ship.TryEquip(ItemManager.CreateInstance(autocannonData, .5f, 1) as EquippableItem); ship.TryEquip(ItemManager.CreateInstance(autocannonData, .5f, 1) as EquippableItem); var cargoData = ItemData.GetAll().First(x => x.Name == "Cargo Bay 4x4"); ship.TryEquip(ItemManager.CreateInstance(cargoData, .5f, 1) as EquippableItem); ship.CargoBays.First().TryStore(ItemManager.CreateInstance(ammoData, 200)); //dockingCargo.TryStore(ItemManager.CreateInstance(reactorData, .5f, 1)); Dock(); // MapButton.onClick.AddListener(() => // { // if (_currentMenuTabButton == MapPanel) return; // // _currentMenuTabButton.GetComponent().color = Color.white; // _currentMenuTabButton = MapButton; // }); // //InventoryPanel.Display(ItemManager, entity); } public void Dock() { if (_currentShip.Parent != null) return; foreach (var entity in Zone.Entities.ToArray()) { if (lengthsq(entity.Position.xz - _currentShip.Position.xz) < Settings.GameplaySettings.DockingDistance * Settings.GameplaySettings.DockingDistance) { var bay = entity.TryDock(_currentShip); if (bay != null) { DockCamera.enabled = true; FollowCamera.enabled = false; _currentShip.Active = false; var orbital = (OrbitalEntity) entity; DockCamera.Follow = SectorRenderer.EntityInstances[orbital].Transform; var parentOrbit = Zone.Orbits[orbital.OrbitData].Data.Parent; var parentPlanet = SectorRenderer.Planets[Zone.Planets.FirstOrDefault(p => p.Value.Orbit == parentOrbit).Key]; DockCamera.LookAt = parentPlanet.Body.transform; Menu.ShowTab(MenuTab.Inventory); Inventory.GetPanel.Display(bay); Inventory.GetPanel.Display(_currentShip); Cursor.lockState = CursorLockMode.None; _input.Player.Disable(); GameplayUI.SetActive(false); } } } } public void Undock() { if (_currentShip.Parent == null) return; if (_currentShip.GetBehavior() == null) { ConfirmationDialog.Title.text = "Can't undock. Missing cockpit component!"; ConfirmationDialog.Show(); } else if (_currentShip.GetBehavior() == null) { ConfirmationDialog.Title.text = "Can't undock. Missing thruster component!"; ConfirmationDialog.Show(); } else if (_currentShip.GetBehavior() == null) { ConfirmationDialog.Title.text = "Can't undock. Missing reactor component!"; ConfirmationDialog.Show(); } else if (_currentShip.Parent.TryUndock(_currentShip)) { Menu.gameObject.SetActive(false); _currentShip.Active = true; //_shipInput = new ShipInput(_input.Player, _currentShip); DockCamera.enabled = false; FollowCamera.enabled = true; FollowCamera.LookAt = SectorRenderer.EntityInstances[_currentShip].LookAtPoint; FollowCamera.Follow = SectorRenderer.EntityInstances[_currentShip].Transform; Cursor.lockState = CursorLockMode.Locked; GameplayUI.SetActive(true); _input.Player.Enable(); ShipPanel.Display(_currentShip); SchematicDisplay.ShowShip(_currentShip); } else { ConfirmationDialog.Title.text = "Can't undock. Must empty docking bay!"; ConfirmationDialog.Show(); } } public void SaveZone() => File.WriteAllBytes( Path.Combine(_filePath.FullName, $"{Zone.Data.Name}.zone"), MessagePackSerializer.Serialize(Zone.Pack())); // public void ToggleEditMode() // { // _editMode = !_editMode; // FollowCamera.gameObject.SetActive(!_editMode); // TopDownCamera.gameObject.SetActive(_editMode); // } public IEnumerable AvailableCargoBays() { if (_currentShip.Parent != null) { foreach (var bay in _currentShip.Parent.DockingBays) { if (PlayerShips.Contains(bay.DockedShip)) yield return bay; } } } public IEnumerable AvailableShips() { if (_currentShip.Parent != null) { foreach (var ship in PlayerShips) { if (_currentShip.Parent.Children.Contains(ship)) yield return ship; } } else yield return _currentShip; } void Update() { if(!_editMode) { _time += Time.deltaTime; ItemManager.Time = Time.time; if(_currentShip.Parent==null) { var look = _input.Player.Look.ReadValue(); _shipYawPitch = float2(_shipYawPitch.x + look.x * Sensitivity.x, clamp(_shipYawPitch.y + look.y * Sensitivity.y, -.45f * PI, .45f * PI)); _viewDirection = mul(float3(0, 0, 1), Unity.Mathematics.float3x3.Euler(float3(_shipYawPitch.yx, 0), RotationOrder.YXZ)); _currentShip.LookDirection = _viewDirection; _currentShip.MovementDirection = _input.Player.Move.ReadValue(); } } Zone.Update(_time, Time.deltaTime); SectorRenderer.Time = _time; } }