Aetheria/Assets/Scripts/ActionGameManager.cs
Reinier Vens ef816cc7e0 Murder Satellites
Created TurretController, which performs basic combat for fixed orbital installations
Projectiles self-destruct at maximum range
Created turret prefab
Outfitted turret in game manager
Entity position is now 3D
Entities responsible for updating their own position and orientation
Barrel positions and orientations available from entity code
Inventory code will display modal dialog for invalid item moves instead of breaking
Yaw articulation working (full 360 rotation still borked)
2021-01-06 14:56:39 +00:00

558 lines
No EOL
22 KiB
C#

/* 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<Ship> PlayerShips { get; } = new List<Ship>();
public DatabaseCache ItemData { get; private set; }
public ItemManager ItemManager { get; private set; }
public Zone Zone { get; private set; }
void Start()
{
// _transposer = DockCamera.GetCinemachineComponent<CinemachineFramingTransposer>();
// _composer = DockCamera.GetCinemachineComponent<CinemachineComposer>();
//_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<ZonePack>(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<HullData>().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<DockingBayData>().First();
var dockingBay = ItemManager.CreateInstance(dockingBayData, 1, 1) as EquippableItem;
station.TryEquip(dockingBay);
station.Active = true;
var reactorData = ItemData.GetAll<GearData>().First(x => x.HardpointType == HardpointType.Reactor && x.Shape.Height == 2);
var autocannonData = ItemData.GetAll<GearData>().First(x => x.Name == "Autocannon");
var ammoData = ItemData.GetAll<SimpleCommodityData>().First(x => x.Name == "AC2 Ammo");
var turretType = ItemData.GetAll<HullData>().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<GearData>().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<CargoBayData>().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<HullData>().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<GearData>().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<GearData>().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<CargoBayData>().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<TextMeshProUGUI>().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<Cockpit>() == null)
{
ConfirmationDialog.Title.text = "Can't undock. Missing cockpit component!";
ConfirmationDialog.Show();
}
else if (_currentShip.GetBehavior<Thruster>() == null)
{
ConfirmationDialog.Title.text = "Can't undock. Missing thruster component!";
ConfirmationDialog.Show();
}
else if (_currentShip.GetBehavior<Reactor>() == 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<EquippedCargoBay> AvailableCargoBays()
{
if (_currentShip.Parent != null)
{
foreach (var bay in _currentShip.Parent.DockingBays)
{
if (PlayerShips.Contains(bay.DockedShip)) yield return bay;
}
}
}
public IEnumerable<Ship> 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<Vector2>();
_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<Vector2>();
}
}
Zone.Update(_time, Time.deltaTime);
SectorRenderer.Time = _time;
}
}