1246 lines
51 KiB
C#
1246 lines
51 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.Generic;
|
|
using System.Globalization;
|
|
using System.Linq;
|
|
using GameCult.Aetheria.State.Unity;
|
|
using GameCult.Eve.Surface;
|
|
using GameCult.Eve.UnityUIToolkit;
|
|
using UnityEngine;
|
|
using UniRx;
|
|
using UniRx.Triggers;
|
|
using Unity.Mathematics;
|
|
using UnityEngine.UIElements;
|
|
|
|
public class InventoryMenu : MonoBehaviour
|
|
{
|
|
private const string ShipSettingsSurfaceType = "surface-state";
|
|
private const string ShipSettingsSurfaceSchema = "gamecult.eve.surface.v1";
|
|
private const string ShipSettingsSurfaceProviderId = "aetheria";
|
|
private const string ShipSettingsSurfaceProviderKind = "inventory.menu";
|
|
private const string ShipSettingsSurfaceId = "aetheria.inventory.current_ship_settings";
|
|
private const string DecrementShutdownThresholdCommand = "aetheria.inventory.current_ship_settings.shutdown.decrement";
|
|
private const string IncrementShutdownThresholdCommand = "aetheria.inventory.current_ship_settings.shutdown.increment";
|
|
private const string ResetShutdownThresholdCommand = "aetheria.inventory.current_ship_settings.shutdown.reset";
|
|
private const string CloseShipSettingsCommand = "aetheria.inventory.current_ship_settings.close";
|
|
private const string CargoItemDetailsSurfaceId = "aetheria.inventory.cargo_item_details";
|
|
private const string CloseCargoItemDetailsCommand = "aetheria.inventory.cargo_item_details.close";
|
|
private const string EquippedItemDetailsSurfaceId = "aetheria.inventory.equipped_item_details";
|
|
private const string CloseEquippedItemDetailsCommand = "aetheria.inventory.equipped_item_details.close";
|
|
private const string ToggleEquippedItemOverrideShutdownCommand = "aetheria.inventory.equipped_item_details.override_shutdown.toggle";
|
|
private const string SetEquippedItemTargetTemperatureCommand = "aetheria.inventory.equipped_item_details.target_temperature.set";
|
|
private const string ToggleEquippedItemWeaponGroupCommand = "aetheria.inventory.equipped_item_details.weapon_group.toggle";
|
|
private const string BindEquippedItemWeaponGroupCommand = "aetheria.inventory.equipped_item_details.weapon_group.bind";
|
|
private const string ClearEquippedItemActionBarBindingCommand = "aetheria.inventory.equipped_item_details.action_bar.clear";
|
|
private const float ShutdownThresholdStep = 0.05f;
|
|
|
|
public InventoryPanel[] InventoryPanels;
|
|
public ActionGameManager GameManager;
|
|
public ConfirmationDialog Dialog;
|
|
// public ClickCatcher Background;
|
|
|
|
private int _currentPanel = -1;
|
|
|
|
private int2 _selectedPosition;
|
|
private InventoryPanel _selectedPanel;
|
|
private ItemInstance _selectedItem;
|
|
private EquippedItem _selectedEquippedItem;
|
|
private int2[] _selectedCells;
|
|
private UIDocument _shipSettingsSurfaceDocument;
|
|
private UIDocument _cargoItemDetailsSurfaceDocument;
|
|
private UIDocument _equippedItemDetailsSurfaceDocument;
|
|
// private List<IDisposable> _backgroundSubscriptions;
|
|
|
|
// private ItemInstance _dragItem;
|
|
// private Transform[] _dragCells;
|
|
// private Vector2[] _dragOffsets;
|
|
// private int2 _dragCellOffset;
|
|
// private ItemRotation _originalRotation;
|
|
// //private Shape _previousFakeOccupancy;
|
|
// private Shape _originalOccupancy;
|
|
// private EquippedItem _originalEquippedItem;
|
|
// private InventoryPanel _originalPanel;
|
|
//
|
|
// private InventoryPanel _dragTargetPanel;
|
|
// private int2 _dragTargetPosition;
|
|
// private int2 _lastDragPosition;
|
|
// private bool _dragTargetValid;
|
|
// private bool _destroyItem;
|
|
|
|
private void OnEnable()
|
|
{
|
|
// Background.gameObject.SetActive(true);
|
|
|
|
// Background.OnEnter.Subscribe(enter =>
|
|
// {
|
|
// _destroyItem = true;
|
|
// });
|
|
// BackgroundExited.OnPointerExitAsObservable().Subscribe(enter =>
|
|
// {
|
|
// _destroyItem = false;
|
|
// });
|
|
var cargo = GameManager.DockingBay ?? GameManager.CurrentEntity.CargoBays.FirstOrDefault();
|
|
if (cargo!=null)
|
|
InventoryPanels[0].Display(cargo);
|
|
else InventoryPanels[0].Clear();
|
|
if(GameManager.CurrentEntity != null)
|
|
InventoryPanels[1].Display(GameManager.CurrentEntity);
|
|
else InventoryPanels[1].Clear();
|
|
}
|
|
|
|
private void OnDisable()
|
|
{
|
|
HideCurrentShipSettingsSurface();
|
|
HideCargoItemDetailsSurface();
|
|
HideEquippedItemDetailsSurface();
|
|
// Background.gameObject.SetActive(false);
|
|
}
|
|
|
|
void Start()
|
|
{
|
|
foreach (var panel in InventoryPanels)
|
|
{
|
|
panel.OnClickAsObservable().Subscribe(e =>
|
|
{
|
|
if (e.data is InventoryCargoEventData cargoEvent)
|
|
{
|
|
var item = cargoEvent.CargoBay.Occupancy[cargoEvent.Position.x, cargoEvent.Position.y];
|
|
if(item!=null)
|
|
{
|
|
if (e.clickCount == 2)
|
|
{
|
|
HideCargoItemDetailsSurface();
|
|
HideEquippedItemDetailsSurface();
|
|
ClearSelectedItemSelection();
|
|
var otherPanel = panel == InventoryPanels[0] ? InventoryPanels[1] : InventoryPanels[0];
|
|
if (CommitCargoItemTransfer(cargoEvent.CargoBay, otherPanel, item))
|
|
{
|
|
// TODO: SFX: Equip
|
|
panel.RefreshCells();
|
|
otherPanel.RefreshCells();
|
|
}
|
|
// else
|
|
// TODO: SFX: Fail
|
|
}
|
|
else
|
|
{
|
|
HideCurrentShipSettingsSurface();
|
|
HideCargoItemDetailsSurface();
|
|
HideEquippedItemDetailsSurface();
|
|
ClearSelectedItemSelection();
|
|
_selectedPanel = panel;
|
|
_selectedPosition = cargoEvent.CargoBay.Cargo[item];
|
|
_selectedItem = item;
|
|
_selectedCells = GetSelectedCells(item, _selectedPosition);
|
|
ApplySelectedCellHighlight();
|
|
RenderCargoItemDetailsSurface(item);
|
|
// TODO: SFX: Success
|
|
}
|
|
}
|
|
}
|
|
else if (e.data is InventoryEntityEventData entityEvent)
|
|
{
|
|
var item = entityEvent.Entity.GearOccupancy[entityEvent.Position.x, entityEvent.Position.y];
|
|
if (item != null)
|
|
{
|
|
if (e.clickCount == 2)
|
|
{
|
|
HideCargoItemDetailsSurface();
|
|
HideEquippedItemDetailsSurface();
|
|
ClearSelectedItemSelection();
|
|
var otherPanel = panel == InventoryPanels[0] ? InventoryPanels[1] : InventoryPanels[0];
|
|
if (CommitEquippedItemTransfer(entityEvent.Entity, item, otherPanel))
|
|
{
|
|
// TODO: SFX: Unequip
|
|
panel.RefreshCells();
|
|
otherPanel.RefreshCells();
|
|
// else
|
|
// TODO: SFX: Fail
|
|
}
|
|
}
|
|
else
|
|
{
|
|
HideCurrentShipSettingsSurface();
|
|
HideCargoItemDetailsSurface();
|
|
ClearSelectedItemSelection();
|
|
_selectedPanel = panel;
|
|
_selectedPosition = item.Position;
|
|
_selectedItem = item.EquippableItem;
|
|
_selectedEquippedItem = item;
|
|
_selectedCells = GetSelectedCells(item.EquippableItem, _selectedPosition);
|
|
ApplySelectedCellHighlight();
|
|
RenderEquippedItemDetailsSurface(item);
|
|
// TODO: SFX: Success
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
panel.OnBackgroundClick.Subscribe(data =>
|
|
{
|
|
if (GameManager.CurrentEntity == null) return; // Only show ship settings if there's a ship, duh!
|
|
|
|
RenderCurrentShipSettingsSurface(GameManager.CurrentEntity);
|
|
});
|
|
}
|
|
}
|
|
|
|
private void RenderCurrentShipSettingsSurface(Entity entity)
|
|
{
|
|
if (entity == null)
|
|
return;
|
|
|
|
HideCargoItemDetailsSurface();
|
|
HideEquippedItemDetailsSurface();
|
|
ClearSelectedItemSelection();
|
|
|
|
var document = ResolveShipSettingsSurfaceDocument();
|
|
document.gameObject.SetActive(true);
|
|
|
|
var root = document.rootVisualElement;
|
|
root.Clear();
|
|
root.style.flexGrow = 1;
|
|
root.style.position = Position.Absolute;
|
|
root.style.left = 0;
|
|
root.style.top = 0;
|
|
root.style.right = 0;
|
|
root.style.bottom = 0;
|
|
root.style.alignItems = Align.FlexStart;
|
|
root.style.justifyContent = Justify.FlexStart;
|
|
root.pickingMode = PickingMode.Ignore;
|
|
|
|
var shell = new VisualElement();
|
|
shell.style.width = 360;
|
|
shell.style.maxWidth = 420;
|
|
shell.style.backgroundColor = new Color(0.08f, 0.1f, 0.14f, 0.94f);
|
|
shell.style.borderTopLeftRadius = 8;
|
|
shell.style.borderTopRightRadius = 8;
|
|
shell.style.borderBottomLeftRadius = 8;
|
|
shell.style.borderBottomRightRadius = 8;
|
|
shell.style.paddingLeft = 18;
|
|
shell.style.paddingRight = 18;
|
|
shell.style.paddingTop = 18;
|
|
shell.style.paddingBottom = 18;
|
|
shell.style.borderLeftWidth = 1;
|
|
shell.style.borderRightWidth = 1;
|
|
shell.style.borderTopWidth = 1;
|
|
shell.style.borderBottomWidth = 1;
|
|
shell.style.borderLeftColor = new Color(0.3f, 0.47f, 0.71f, 0.8f);
|
|
shell.style.borderRightColor = new Color(0.3f, 0.47f, 0.71f, 0.8f);
|
|
shell.style.borderTopColor = new Color(0.3f, 0.47f, 0.71f, 0.8f);
|
|
shell.style.borderBottomColor = new Color(0.3f, 0.47f, 0.71f, 0.8f);
|
|
shell.pickingMode = PickingMode.Position;
|
|
root.Add(shell);
|
|
|
|
var lowerer = new EveUiToolkitSurfaceLowerer();
|
|
shell.Add(lowerer.Lower(BuildCurrentShipSettingsSurfaceDefinition(entity), HandleCurrentShipSettingsSurfaceCommand));
|
|
}
|
|
|
|
private void HandleCurrentShipSettingsSurfaceCommand(EveSurfaceCommandRequest request)
|
|
{
|
|
var entity = GameManager.CurrentEntity;
|
|
if (entity?.Settings == null)
|
|
{
|
|
HideCurrentShipSettingsSurface();
|
|
return;
|
|
}
|
|
|
|
switch (request.Command)
|
|
{
|
|
case DecrementShutdownThresholdCommand:
|
|
GameManager.CommitEntityShutdownPerformance(
|
|
entity,
|
|
Mathf.Clamp01(entity.Settings.ShutdownPerformance - ShutdownThresholdStep));
|
|
RenderCurrentShipSettingsSurface(entity);
|
|
return;
|
|
case IncrementShutdownThresholdCommand:
|
|
GameManager.CommitEntityShutdownPerformance(
|
|
entity,
|
|
Mathf.Clamp01(entity.Settings.ShutdownPerformance + ShutdownThresholdStep));
|
|
RenderCurrentShipSettingsSurface(entity);
|
|
return;
|
|
case ResetShutdownThresholdCommand:
|
|
GameManager.CommitEntityShutdownPerformance(
|
|
entity,
|
|
Mathf.Clamp01(GameManager.Settings.GameplaySettings.DefaultShutdownPerformance));
|
|
RenderCurrentShipSettingsSurface(entity);
|
|
return;
|
|
case CloseShipSettingsCommand:
|
|
HideCurrentShipSettingsSurface();
|
|
return;
|
|
default:
|
|
Debug.LogWarning($"Unknown inventory ship settings command: {request.Command}");
|
|
return;
|
|
}
|
|
}
|
|
|
|
private void HideCurrentShipSettingsSurface()
|
|
{
|
|
if (_shipSettingsSurfaceDocument == null)
|
|
return;
|
|
|
|
_shipSettingsSurfaceDocument.rootVisualElement.Clear();
|
|
_shipSettingsSurfaceDocument.gameObject.SetActive(false);
|
|
}
|
|
|
|
private void RenderCargoItemDetailsSurface(ItemInstance item)
|
|
{
|
|
var typedItem = FindTypedInventoryItem(item);
|
|
if (item == null || typedItem == null)
|
|
return;
|
|
|
|
HideEquippedItemDetailsSurface();
|
|
|
|
var document = ResolveCargoItemDetailsSurfaceDocument();
|
|
document.gameObject.SetActive(true);
|
|
|
|
var root = document.rootVisualElement;
|
|
root.Clear();
|
|
root.style.flexGrow = 1;
|
|
root.style.position = Position.Absolute;
|
|
root.style.left = 0;
|
|
root.style.top = 0;
|
|
root.style.right = 0;
|
|
root.style.bottom = 0;
|
|
root.style.alignItems = Align.FlexStart;
|
|
root.style.justifyContent = Justify.FlexStart;
|
|
root.pickingMode = PickingMode.Ignore;
|
|
|
|
var shell = new VisualElement();
|
|
shell.style.width = 420;
|
|
shell.style.maxWidth = 520;
|
|
shell.style.backgroundColor = new Color(0.08f, 0.1f, 0.14f, 0.94f);
|
|
shell.style.borderTopLeftRadius = 8;
|
|
shell.style.borderTopRightRadius = 8;
|
|
shell.style.borderBottomLeftRadius = 8;
|
|
shell.style.borderBottomRightRadius = 8;
|
|
shell.style.paddingLeft = 18;
|
|
shell.style.paddingRight = 18;
|
|
shell.style.paddingTop = 18;
|
|
shell.style.paddingBottom = 18;
|
|
shell.style.borderLeftWidth = 1;
|
|
shell.style.borderRightWidth = 1;
|
|
shell.style.borderTopWidth = 1;
|
|
shell.style.borderBottomWidth = 1;
|
|
shell.style.borderLeftColor = new Color(0.3f, 0.47f, 0.71f, 0.8f);
|
|
shell.style.borderRightColor = new Color(0.3f, 0.47f, 0.71f, 0.8f);
|
|
shell.style.borderTopColor = new Color(0.3f, 0.47f, 0.71f, 0.8f);
|
|
shell.style.borderBottomColor = new Color(0.3f, 0.47f, 0.71f, 0.8f);
|
|
shell.pickingMode = PickingMode.Position;
|
|
root.Add(shell);
|
|
|
|
var lowerer = new EveUiToolkitSurfaceLowerer();
|
|
shell.Add(lowerer.Lower(BuildCargoItemDetailsSurfaceDefinition(item, typedItem), HandleCargoItemDetailsSurfaceCommand));
|
|
}
|
|
|
|
private void HandleCargoItemDetailsSurfaceCommand(EveSurfaceCommandRequest request)
|
|
{
|
|
if (string.Equals(request.Command, CloseCargoItemDetailsCommand, StringComparison.Ordinal))
|
|
{
|
|
HideCargoItemDetailsSurface();
|
|
ClearSelectedItemSelection();
|
|
return;
|
|
}
|
|
|
|
Debug.LogWarning($"Unknown inventory cargo item details command: {request.Command}");
|
|
}
|
|
|
|
private void HideCargoItemDetailsSurface()
|
|
{
|
|
if (_cargoItemDetailsSurfaceDocument == null)
|
|
return;
|
|
|
|
_cargoItemDetailsSurfaceDocument.rootVisualElement.Clear();
|
|
_cargoItemDetailsSurfaceDocument.gameObject.SetActive(false);
|
|
}
|
|
|
|
private void RenderEquippedItemDetailsSurface(EquippedItem item)
|
|
{
|
|
var typedItem = FindTypedInventoryItem(item?.EquippableItem);
|
|
if (item?.EquippableItem == null || typedItem == null)
|
|
return;
|
|
|
|
var document = ResolveEquippedItemDetailsSurfaceDocument();
|
|
document.gameObject.SetActive(true);
|
|
|
|
var root = document.rootVisualElement;
|
|
root.Clear();
|
|
root.style.flexGrow = 1;
|
|
root.style.position = Position.Absolute;
|
|
root.style.left = 0;
|
|
root.style.top = 0;
|
|
root.style.right = 0;
|
|
root.style.bottom = 0;
|
|
root.style.alignItems = Align.FlexStart;
|
|
root.style.justifyContent = Justify.FlexStart;
|
|
root.pickingMode = PickingMode.Ignore;
|
|
|
|
var shell = new VisualElement();
|
|
shell.style.width = 460;
|
|
shell.style.maxWidth = 560;
|
|
shell.style.backgroundColor = new Color(0.08f, 0.1f, 0.14f, 0.94f);
|
|
shell.style.borderTopLeftRadius = 8;
|
|
shell.style.borderTopRightRadius = 8;
|
|
shell.style.borderBottomLeftRadius = 8;
|
|
shell.style.borderBottomRightRadius = 8;
|
|
shell.style.paddingLeft = 18;
|
|
shell.style.paddingRight = 18;
|
|
shell.style.paddingTop = 18;
|
|
shell.style.paddingBottom = 18;
|
|
shell.style.borderLeftWidth = 1;
|
|
shell.style.borderRightWidth = 1;
|
|
shell.style.borderTopWidth = 1;
|
|
shell.style.borderBottomWidth = 1;
|
|
shell.style.borderLeftColor = new Color(0.3f, 0.47f, 0.71f, 0.8f);
|
|
shell.style.borderRightColor = new Color(0.3f, 0.47f, 0.71f, 0.8f);
|
|
shell.style.borderTopColor = new Color(0.3f, 0.47f, 0.71f, 0.8f);
|
|
shell.style.borderBottomColor = new Color(0.3f, 0.47f, 0.71f, 0.8f);
|
|
shell.pickingMode = PickingMode.Position;
|
|
root.Add(shell);
|
|
|
|
var lowerer = new EveUiToolkitSurfaceLowerer();
|
|
shell.Add(lowerer.Lower(BuildEquippedItemDetailsSurfaceDefinition(item, typedItem), HandleEquippedItemDetailsSurfaceCommand));
|
|
}
|
|
|
|
private void HandleEquippedItemDetailsSurfaceCommand(EveSurfaceCommandRequest request)
|
|
{
|
|
var item = _selectedEquippedItem;
|
|
if (item?.EquippableItem == null)
|
|
{
|
|
HideEquippedItemDetailsSurface();
|
|
ClearSelectedItemSelection();
|
|
return;
|
|
}
|
|
|
|
switch (request.Command)
|
|
{
|
|
case CloseEquippedItemDetailsCommand:
|
|
HideEquippedItemDetailsSurface();
|
|
ClearSelectedItemSelection();
|
|
return;
|
|
case ToggleEquippedItemOverrideShutdownCommand:
|
|
GameManager.CommitEquippedItemOverrideShutdown(item, !item.EquippableItem.OverrideShutdown);
|
|
RenderEquippedItemDetailsSurface(item);
|
|
return;
|
|
case SetEquippedItemTargetTemperatureCommand:
|
|
if (TryReadPayloadInt(request, "behaviorIndex", out var behaviorIndex) &&
|
|
behaviorIndex >= 0 &&
|
|
behaviorIndex < (item.Behaviors?.Length ?? 0) &&
|
|
item.Behaviors[behaviorIndex] is Thermotoggle thermotoggle &&
|
|
thermotoggle.Adjustable &&
|
|
TryReadPayloadFloat(request, "value", out var targetTemperature))
|
|
{
|
|
GameManager.CommitThermotoggleTargetTemperature(thermotoggle, targetTemperature);
|
|
RenderEquippedItemDetailsSurface(item);
|
|
return;
|
|
}
|
|
|
|
Debug.LogWarning("Unable to apply equipped-item target temperature command.");
|
|
RenderEquippedItemDetailsSurface(item);
|
|
return;
|
|
case ToggleEquippedItemWeaponGroupCommand:
|
|
if (TryReadPayloadInt(request, "group", out var groupIndex))
|
|
{
|
|
var assigned = !IsWeaponGroupAssigned(item, groupIndex);
|
|
if (GameManager.CommitWeaponGroupMembership(item, groupIndex, assigned))
|
|
{
|
|
RenderEquippedItemDetailsSurface(item);
|
|
return;
|
|
}
|
|
}
|
|
|
|
Debug.LogWarning("Unable to toggle equipped-item weapon group membership.");
|
|
return;
|
|
case BindEquippedItemWeaponGroupCommand:
|
|
if (TryReadPayloadInt(request, "group", out var bindGroupIndex) &&
|
|
TryReadPayloadInt(request, "slot", out var slotIndex) &&
|
|
GameManager.CommitWeaponGroupActionBarBinding(slotIndex, bindGroupIndex))
|
|
{
|
|
RenderEquippedItemDetailsSurface(item);
|
|
return;
|
|
}
|
|
|
|
Debug.LogWarning("Unable to bind equipped-item weapon group to action bar.");
|
|
return;
|
|
case ClearEquippedItemActionBarBindingCommand:
|
|
if (TryReadPayloadInt(request, "slot", out var clearSlotIndex) &&
|
|
GameManager.CommitClearActionBarBinding(clearSlotIndex))
|
|
{
|
|
RenderEquippedItemDetailsSurface(item);
|
|
return;
|
|
}
|
|
|
|
Debug.LogWarning("Unable to clear equipped-item action bar binding.");
|
|
return;
|
|
default:
|
|
Debug.LogWarning($"Unknown inventory equipped item details command: {request.Command}");
|
|
return;
|
|
}
|
|
}
|
|
|
|
private void HideEquippedItemDetailsSurface()
|
|
{
|
|
if (_equippedItemDetailsSurfaceDocument == null)
|
|
return;
|
|
|
|
_equippedItemDetailsSurfaceDocument.rootVisualElement.Clear();
|
|
_equippedItemDetailsSurfaceDocument.gameObject.SetActive(false);
|
|
}
|
|
|
|
private UIDocument ResolveEquippedItemDetailsSurfaceDocument()
|
|
{
|
|
if (_equippedItemDetailsSurfaceDocument != null)
|
|
return _equippedItemDetailsSurfaceDocument;
|
|
|
|
var host = new GameObject("Aetheria Inventory Equipped Item Details Surface");
|
|
host.transform.SetParent(transform, false);
|
|
var document = host.AddComponent<UIDocument>();
|
|
document.sortingOrder = 1002;
|
|
host.SetActive(false);
|
|
_equippedItemDetailsSurfaceDocument = document;
|
|
return document;
|
|
}
|
|
|
|
private EveSurfaceDocument BuildEquippedItemDetailsSurfaceDefinition(EquippedItem item, AetheriaRuntimeCatalogItem typedItem)
|
|
{
|
|
var children = new List<EveSurfaceComponent>
|
|
{
|
|
Card(
|
|
$"{EquippedItemDetailsSurfaceId}.summary",
|
|
BuildEquippedItemTitle(item, typedItem),
|
|
Text(
|
|
$"{EquippedItemDetailsSurfaceId}.description",
|
|
typedItem.Description ?? "No typed item description is available."),
|
|
Text(
|
|
$"{EquippedItemDetailsSurfaceId}.note",
|
|
"InventoryMenu still owns cell selection. This surface replaces the old equipped-item PropertiesPanel shell, including weapon-group and behavior controls."),
|
|
Metric(
|
|
$"{EquippedItemDetailsSurfaceId}.manufacturer",
|
|
"Manufacturer",
|
|
ActionGameManager.RuntimeCatalog?.GetManufacturer(typedItem)?.Name ?? "GameCult"),
|
|
Metric(
|
|
$"{EquippedItemDetailsSurfaceId}.mass",
|
|
"Mass",
|
|
ActionGameManager.RuntimePlayerSettings.Format((float)typedItem.Mass))),
|
|
Card(
|
|
$"{EquippedItemDetailsSurfaceId}.status.card",
|
|
"Status",
|
|
Metric(
|
|
$"{EquippedItemDetailsSurfaceId}.durability",
|
|
"Durability",
|
|
item.EquippableItem.Durability < .01f
|
|
? "Item Destroyed!"
|
|
: $"{(int)(item.EquippableItem.Durability / GetMaxDurability(typedItem, item.EquippableItem) * 100)}%"),
|
|
Metric(
|
|
$"{EquippedItemDetailsSurfaceId}.temperature",
|
|
"Temperature",
|
|
ActionGameManager.RuntimePlayerSettings.FormatTemperature(item.Temperature)),
|
|
Metric(
|
|
$"{EquippedItemDetailsSurfaceId}.thermal_range",
|
|
"Thermal Range",
|
|
FormatTemperatureRange(typedItem)))
|
|
};
|
|
|
|
foreach (var behaviorCard in BuildItemBehaviorCards(EquippedItemDetailsSurfaceId, typedItem, item.EquippableItem))
|
|
{
|
|
children.Add(behaviorCard);
|
|
}
|
|
|
|
children.Add(BuildEquippedItemControlCard(item));
|
|
|
|
if (item.GetBehavior<Weapon>() != null)
|
|
{
|
|
children.Add(BuildEquippedItemWeaponGroupCard(item));
|
|
children.AddRange(BuildEquippedItemActionBarCards(item));
|
|
}
|
|
|
|
children.Add(ButtonRow(
|
|
$"{EquippedItemDetailsSurfaceId}.actions",
|
|
Button($"{EquippedItemDetailsSurfaceId}.close", "Close", CloseEquippedItemDetailsCommand)));
|
|
|
|
return new EveSurfaceDocument(
|
|
ShipSettingsSurfaceType,
|
|
ShipSettingsSurfaceSchema,
|
|
ShipSettingsSurfaceProviderId,
|
|
ShipSettingsSurfaceProviderKind,
|
|
"Inventory Equipped Item Details",
|
|
version: 1,
|
|
DateTime.UtcNow.ToString("O"),
|
|
new EveSurfaceTree(
|
|
EquippedItemDetailsSurfaceId,
|
|
Node(
|
|
$"{EquippedItemDetailsSurfaceId}.root",
|
|
"surface",
|
|
Array.Empty<(string Key, string Value)>(),
|
|
children.ToArray()),
|
|
Array.Empty<EveStyleToken>()),
|
|
new[]
|
|
{
|
|
new EveCommandTemplate(CloseEquippedItemDetailsCommand, "Close", "unity-uitoolkit"),
|
|
new EveCommandTemplate(ToggleEquippedItemOverrideShutdownCommand, "Toggle Override Shutdown", "unity-uitoolkit"),
|
|
new EveCommandTemplate(SetEquippedItemTargetTemperatureCommand, "Set Target Temperature", "unity-uitoolkit"),
|
|
new EveCommandTemplate(ToggleEquippedItemWeaponGroupCommand, "Toggle Weapon Group", "unity-uitoolkit"),
|
|
new EveCommandTemplate(BindEquippedItemWeaponGroupCommand, "Bind Weapon Group", "unity-uitoolkit"),
|
|
new EveCommandTemplate(ClearEquippedItemActionBarBindingCommand, "Clear Action Bar Binding", "unity-uitoolkit")
|
|
});
|
|
}
|
|
|
|
private EveSurfaceComponent BuildEquippedItemControlCard(EquippedItem item)
|
|
{
|
|
var children = new List<EveSurfaceComponent>
|
|
{
|
|
Metric(
|
|
$"{EquippedItemDetailsSurfaceId}.controls.override_shutdown.metric",
|
|
"Override Shutdown",
|
|
item.EquippableItem.OverrideShutdown ? "Enabled" : "Disabled"),
|
|
ButtonRow(
|
|
$"{EquippedItemDetailsSurfaceId}.controls.override_shutdown.actions",
|
|
Button(
|
|
$"{EquippedItemDetailsSurfaceId}.controls.override_shutdown.toggle",
|
|
item.EquippableItem.OverrideShutdown ? "Disable Override" : "Enable Override",
|
|
ToggleEquippedItemOverrideShutdownCommand))
|
|
};
|
|
|
|
for (var i = 0; i < (item.Behaviors?.Length ?? 0); i++)
|
|
{
|
|
if (item.Behaviors[i] is not Thermotoggle thermotoggle || !thermotoggle.Adjustable)
|
|
continue;
|
|
|
|
children.Add(Metric(
|
|
$"{EquippedItemDetailsSurfaceId}.controls.thermotoggle.{i}.metric",
|
|
$"Target Temperature {i + 1}",
|
|
ActionGameManager.RuntimePlayerSettings.FormatTemperature(thermotoggle.TargetTemperature)));
|
|
children.Add(TextField(
|
|
$"{EquippedItemDetailsSurfaceId}.controls.thermotoggle.{i}.input",
|
|
$"Target Temperature {i + 1}",
|
|
SetEquippedItemTargetTemperatureCommand,
|
|
thermotoggle.TargetTemperature.ToString(CultureInfo.InvariantCulture),
|
|
("behaviorIndex", i.ToString(CultureInfo.InvariantCulture))));
|
|
}
|
|
|
|
return Card(
|
|
$"{EquippedItemDetailsSurfaceId}.controls.card",
|
|
"Controls",
|
|
children.ToArray());
|
|
}
|
|
|
|
private EveSurfaceComponent BuildEquippedItemWeaponGroupCard(EquippedItem item)
|
|
{
|
|
var groupButtons = Enumerable.Range(0, item.Entity?.WeaponGroups?.Length ?? 0)
|
|
.Select(groupIndex => CommandButton(
|
|
$"{EquippedItemDetailsSurfaceId}.weapon_groups.{groupIndex}",
|
|
IsWeaponGroupAssigned(item, groupIndex) ? $"G{groupIndex + 1} On" : $"G{groupIndex + 1} Off",
|
|
ToggleEquippedItemWeaponGroupCommand,
|
|
("group", groupIndex.ToString(CultureInfo.InvariantCulture))))
|
|
.ToArray();
|
|
|
|
return Card(
|
|
$"{EquippedItemDetailsSurfaceId}.weapon_groups.card",
|
|
"Weapon Groups",
|
|
Text(
|
|
$"{EquippedItemDetailsSurfaceId}.weapon_groups.note",
|
|
"Toggle membership directly; action-bar group binding is handled below."),
|
|
ButtonRow($"{EquippedItemDetailsSurfaceId}.weapon_groups.actions", groupButtons));
|
|
}
|
|
|
|
private IEnumerable<EveSurfaceComponent> BuildEquippedItemActionBarCards(EquippedItem item)
|
|
{
|
|
for (var slotIndex = 0; slotIndex < GameManager.GetActionBarSlotCount(); slotIndex++)
|
|
{
|
|
var bindButtons = Enumerable.Range(0, item.Entity?.WeaponGroups?.Length ?? 0)
|
|
.Select(groupIndex => CommandButton(
|
|
$"{EquippedItemDetailsSurfaceId}.action_bar.{slotIndex}.group.{groupIndex}",
|
|
$"G{groupIndex + 1}",
|
|
BindEquippedItemWeaponGroupCommand,
|
|
("slot", slotIndex.ToString(CultureInfo.InvariantCulture)),
|
|
("group", groupIndex.ToString(CultureInfo.InvariantCulture))))
|
|
.Concat(new[]
|
|
{
|
|
CommandButton(
|
|
$"{EquippedItemDetailsSurfaceId}.action_bar.{slotIndex}.clear",
|
|
"Clear",
|
|
ClearEquippedItemActionBarBindingCommand,
|
|
("slot", slotIndex.ToString(CultureInfo.InvariantCulture)))
|
|
})
|
|
.ToArray();
|
|
|
|
yield return Card(
|
|
$"{EquippedItemDetailsSurfaceId}.action_bar.{slotIndex}.card",
|
|
$"Action Bar {GameManager.GetActionBarSlotLabel(slotIndex)}",
|
|
Metric(
|
|
$"{EquippedItemDetailsSurfaceId}.action_bar.{slotIndex}.binding",
|
|
"Current",
|
|
GameManager.GetActionBarBindingLabel(slotIndex)),
|
|
ButtonRow($"{EquippedItemDetailsSurfaceId}.action_bar.{slotIndex}.actions", bindButtons));
|
|
}
|
|
}
|
|
|
|
private UIDocument ResolveCargoItemDetailsSurfaceDocument()
|
|
{
|
|
if (_cargoItemDetailsSurfaceDocument != null)
|
|
return _cargoItemDetailsSurfaceDocument;
|
|
|
|
var host = new GameObject("Aetheria Inventory Cargo Item Details Surface");
|
|
host.transform.SetParent(transform, false);
|
|
var document = host.AddComponent<UIDocument>();
|
|
document.sortingOrder = 1001;
|
|
host.SetActive(false);
|
|
_cargoItemDetailsSurfaceDocument = document;
|
|
return document;
|
|
}
|
|
|
|
private EveSurfaceDocument BuildCargoItemDetailsSurfaceDefinition(ItemInstance item, AetheriaRuntimeCatalogItem typedItem)
|
|
{
|
|
var children = new List<EveSurfaceComponent>
|
|
{
|
|
Card(
|
|
$"{CargoItemDetailsSurfaceId}.summary",
|
|
typedItem.Name,
|
|
Text(
|
|
$"{CargoItemDetailsSurfaceId}.description",
|
|
typedItem.Description ?? "No typed item description is available."),
|
|
Text(
|
|
$"{CargoItemDetailsSurfaceId}.note",
|
|
"InventoryMenu still owns cell selection. This surface replaces the old cargo-item PropertiesPanel shell."),
|
|
Metric(
|
|
$"{CargoItemDetailsSurfaceId}.manufacturer",
|
|
"Manufacturer",
|
|
ActionGameManager.RuntimeCatalog?.GetManufacturer(typedItem)?.Name ?? "GameCult"),
|
|
Metric(
|
|
$"{CargoItemDetailsSurfaceId}.mass",
|
|
"Mass",
|
|
ActionGameManager.RuntimePlayerSettings.Format(GetCargoItemMass(item, typedItem))))
|
|
};
|
|
|
|
if (typedItem.Price > 0)
|
|
{
|
|
children.Add(Card(
|
|
$"{CargoItemDetailsSurfaceId}.market.card",
|
|
"Market",
|
|
Metric(
|
|
$"{CargoItemDetailsSurfaceId}.price",
|
|
"Price",
|
|
typedItem.Price.ToString("N0"))));
|
|
}
|
|
|
|
if (item is SimpleCommodity simpleCommodity)
|
|
{
|
|
children.Add(Card(
|
|
$"{CargoItemDetailsSurfaceId}.quantity.card",
|
|
"Quantity",
|
|
Metric(
|
|
$"{CargoItemDetailsSurfaceId}.quantity",
|
|
"Units",
|
|
simpleCommodity.Quantity.ToString())));
|
|
}
|
|
|
|
if (item is EquippableItem equippableItem)
|
|
{
|
|
var (tier, upgrades) = GameManager.ItemManager.GetTier(equippableItem);
|
|
children.Add(Card(
|
|
$"{CargoItemDetailsSurfaceId}.status.card",
|
|
"Status",
|
|
Metric(
|
|
$"{CargoItemDetailsSurfaceId}.tier",
|
|
"Tier",
|
|
$"{tier.Name}{new string('+', upgrades)}"),
|
|
Metric(
|
|
$"{CargoItemDetailsSurfaceId}.durability",
|
|
"Durability",
|
|
$"{(int)(equippableItem.Durability / GetMaxDurability(typedItem, equippableItem) * 100)}%"),
|
|
Metric(
|
|
$"{CargoItemDetailsSurfaceId}.temperature_range",
|
|
"Thermal Range",
|
|
FormatTemperatureRange(typedItem))));
|
|
|
|
foreach (var behaviorCard in BuildCargoItemBehaviorCards(typedItem, equippableItem))
|
|
{
|
|
children.Add(behaviorCard);
|
|
}
|
|
}
|
|
|
|
children.Add(ButtonRow(
|
|
$"{CargoItemDetailsSurfaceId}.actions",
|
|
Button($"{CargoItemDetailsSurfaceId}.close", "Close", CloseCargoItemDetailsCommand)));
|
|
|
|
return new EveSurfaceDocument(
|
|
ShipSettingsSurfaceType,
|
|
ShipSettingsSurfaceSchema,
|
|
ShipSettingsSurfaceProviderId,
|
|
ShipSettingsSurfaceProviderKind,
|
|
"Inventory Cargo Item Details",
|
|
version: 1,
|
|
DateTime.UtcNow.ToString("O"),
|
|
new EveSurfaceTree(
|
|
CargoItemDetailsSurfaceId,
|
|
Node(
|
|
$"{CargoItemDetailsSurfaceId}.root",
|
|
"surface",
|
|
Array.Empty<(string Key, string Value)>(),
|
|
children.ToArray()),
|
|
Array.Empty<EveStyleToken>()),
|
|
new[]
|
|
{
|
|
new EveCommandTemplate(CloseCargoItemDetailsCommand, "Close", "unity-uitoolkit")
|
|
});
|
|
}
|
|
|
|
private IEnumerable<EveSurfaceComponent> BuildCargoItemBehaviorCards(
|
|
AetheriaRuntimeCatalogItem typedItem,
|
|
EquippableItem equippableItem)
|
|
{
|
|
return BuildItemBehaviorCards(CargoItemDetailsSurfaceId, typedItem, equippableItem);
|
|
}
|
|
|
|
private IEnumerable<EveSurfaceComponent> BuildItemBehaviorCards(
|
|
string surfaceId,
|
|
AetheriaRuntimeCatalogItem typedItem,
|
|
EquippableItem equippableItem)
|
|
{
|
|
foreach (var behavior in typedItem.BehaviorPayloads ?? Array.Empty<AetheriaRuntimeBehaviorPayload>())
|
|
{
|
|
if (string.Equals(behavior.Kind, AetheriaRuntimeBehaviorKinds.StatModifier, StringComparison.Ordinal))
|
|
{
|
|
var statReference = ReadTypedStatReference(FindTypedBehaviorField(behavior, 1)?.Value);
|
|
var modifier = ReadTypedPerformanceStat(FindTypedBehaviorField(behavior, 2)?.Value);
|
|
var modifierType = ReadTypedEnum(FindTypedBehaviorField(behavior, 3)?.Value, StatModifierType.Constant);
|
|
yield return Card(
|
|
$"{surfaceId}.behavior.{behavior.Kind}.stat_modifier",
|
|
"Stat Modifier",
|
|
Metric(
|
|
$"{surfaceId}.behavior.{behavior.Kind}.target",
|
|
$"{statReference.target.SplitCamelCase()}:{statReference.stat.SplitCamelCase()}",
|
|
$"{(modifierType == StatModifierType.Constant ? "+" : "x")}{ActionGameManager.RuntimePlayerSettings.Format(GameManager.ItemManager.Evaluate(modifier, equippableItem))}"));
|
|
continue;
|
|
}
|
|
|
|
var metadata = AetheriaRuntimeBehaviorMetadataCatalog.Get(behavior.Kind);
|
|
if (metadata == null)
|
|
continue;
|
|
|
|
var fields = metadata.DisplayFields
|
|
.Select(field => BuildItemBehaviorMetric(surfaceId, behavior, field, equippableItem))
|
|
.Where(metric => metric != null)
|
|
.ToArray();
|
|
|
|
if (fields.Length == 0)
|
|
continue;
|
|
|
|
yield return Card(
|
|
$"{surfaceId}.behavior.{behavior.Kind}",
|
|
behavior.Kind.FormatTypeName(),
|
|
fields);
|
|
}
|
|
}
|
|
|
|
private EveSurfaceComponent BuildCargoItemBehaviorMetric(
|
|
AetheriaRuntimeBehaviorPayload behavior,
|
|
AetheriaRuntimeBehaviorFieldMetadata field,
|
|
EquippableItem equippableItem)
|
|
{
|
|
return BuildItemBehaviorMetric(CargoItemDetailsSurfaceId, behavior, field, equippableItem);
|
|
}
|
|
|
|
private EveSurfaceComponent BuildItemBehaviorMetric(
|
|
string surfaceId,
|
|
AetheriaRuntimeBehaviorPayload behavior,
|
|
AetheriaRuntimeBehaviorFieldMetadata field,
|
|
EquippableItem equippableItem)
|
|
{
|
|
var payloadField = FindTypedBehaviorField(behavior, field.Key);
|
|
if (payloadField == null)
|
|
return null;
|
|
|
|
string value;
|
|
switch (field.ValueKind)
|
|
{
|
|
case AetheriaRuntimeBehaviorFieldValueKind.Number:
|
|
value = ActionGameManager.RuntimePlayerSettings.Format((float)payloadField.Value.NumberValue);
|
|
break;
|
|
case AetheriaRuntimeBehaviorFieldValueKind.Temperature:
|
|
value = ActionGameManager.RuntimePlayerSettings.FormatTemperature((float)payloadField.Value.NumberValue);
|
|
break;
|
|
case AetheriaRuntimeBehaviorFieldValueKind.Integer:
|
|
value = ((int)payloadField.Value.NumberValue).ToString();
|
|
break;
|
|
case AetheriaRuntimeBehaviorFieldValueKind.PerformanceStat:
|
|
value = ActionGameManager.RuntimePlayerSettings.Format(GameManager.ItemManager.Evaluate(ReadTypedPerformanceStat(payloadField.Value), equippableItem));
|
|
break;
|
|
default:
|
|
return null;
|
|
}
|
|
|
|
return Metric(
|
|
$"{surfaceId}.behavior.{behavior.Kind}.{field.Key}",
|
|
field.Name.SplitCamelCase(),
|
|
value);
|
|
}
|
|
|
|
private UIDocument ResolveShipSettingsSurfaceDocument()
|
|
{
|
|
if (_shipSettingsSurfaceDocument != null)
|
|
return _shipSettingsSurfaceDocument;
|
|
|
|
var host = new GameObject("Aetheria Inventory Ship Settings Surface");
|
|
host.transform.SetParent(transform, false);
|
|
var document = host.AddComponent<UIDocument>();
|
|
document.sortingOrder = 1000;
|
|
host.SetActive(false);
|
|
_shipSettingsSurfaceDocument = document;
|
|
return document;
|
|
}
|
|
|
|
private EveSurfaceDocument BuildCurrentShipSettingsSurfaceDefinition(Entity entity)
|
|
{
|
|
return new EveSurfaceDocument(
|
|
ShipSettingsSurfaceType,
|
|
ShipSettingsSurfaceSchema,
|
|
ShipSettingsSurfaceProviderId,
|
|
ShipSettingsSurfaceProviderKind,
|
|
"Current Ship Settings",
|
|
version: 1,
|
|
DateTime.UtcNow.ToString("O"),
|
|
new EveSurfaceTree(
|
|
ShipSettingsSurfaceId,
|
|
Node(
|
|
$"{ShipSettingsSurfaceId}.root",
|
|
"surface",
|
|
Array.Empty<(string Key, string Value)>(),
|
|
Card(
|
|
$"{ShipSettingsSurfaceId}.card",
|
|
entity.Name,
|
|
Metric(
|
|
$"{ShipSettingsSurfaceId}.shutdown.metric",
|
|
"Shutdown Threshold",
|
|
ActionGameManager.RuntimePlayerSettings.Format(entity.Settings.ShutdownPerformance)),
|
|
Text(
|
|
$"{ShipSettingsSurfaceId}.note",
|
|
"Gameplay still owns the mutation. This surface only lowers the current ship setting."),
|
|
ButtonRow(
|
|
$"{ShipSettingsSurfaceId}.shutdown.buttons",
|
|
Button($"{ShipSettingsSurfaceId}.shutdown.decrement", "Threshold -", DecrementShutdownThresholdCommand),
|
|
Button($"{ShipSettingsSurfaceId}.shutdown.increment", "Threshold +", IncrementShutdownThresholdCommand),
|
|
Button($"{ShipSettingsSurfaceId}.shutdown.reset", "Default", ResetShutdownThresholdCommand),
|
|
Button($"{ShipSettingsSurfaceId}.close", "Close", CloseShipSettingsCommand)))),
|
|
Array.Empty<EveStyleToken>()),
|
|
new[]
|
|
{
|
|
new EveCommandTemplate(DecrementShutdownThresholdCommand, "Threshold -", "unity-uitoolkit"),
|
|
new EveCommandTemplate(IncrementShutdownThresholdCommand, "Threshold +", "unity-uitoolkit"),
|
|
new EveCommandTemplate(ResetShutdownThresholdCommand, "Default", "unity-uitoolkit"),
|
|
new EveCommandTemplate(CloseShipSettingsCommand, "Close", "unity-uitoolkit")
|
|
});
|
|
}
|
|
|
|
private static EveSurfaceComponent Card(
|
|
string id,
|
|
string title,
|
|
params EveSurfaceComponent[] children)
|
|
{
|
|
return Node(id, "card", new[] { ("title", title) }, children);
|
|
}
|
|
|
|
private static EveSurfaceComponent Metric(string id, string label, string value)
|
|
{
|
|
return Node(id, "metric", new[] { ("label", label), ("value", value) });
|
|
}
|
|
|
|
private static EveSurfaceComponent Text(string id, string value)
|
|
{
|
|
return Node(id, "text", new[] { ("value", value) });
|
|
}
|
|
|
|
private static EveSurfaceComponent Button(string id, string label, string command)
|
|
{
|
|
return Node(id, "control.button", new[] { ("label", label), ("command", command) });
|
|
}
|
|
|
|
private static EveSurfaceComponent CommandButton(
|
|
string id,
|
|
string label,
|
|
string command,
|
|
params (string Key, string Value)[] props)
|
|
{
|
|
var buttonProps = new List<(string Key, string Value)>
|
|
{
|
|
("label", label),
|
|
("command", command)
|
|
};
|
|
|
|
if (props != null && props.Length > 0)
|
|
buttonProps.AddRange(props);
|
|
|
|
return Node(id, "control.button", buttonProps);
|
|
}
|
|
|
|
private static EveSurfaceComponent TextField(
|
|
string id,
|
|
string label,
|
|
string command,
|
|
string value,
|
|
params (string Key, string Value)[] props)
|
|
{
|
|
var fieldProps = new List<(string Key, string Value)>
|
|
{
|
|
("label", label),
|
|
("command", command),
|
|
("value", value ?? "")
|
|
};
|
|
|
|
if (props != null && props.Length > 0)
|
|
fieldProps.AddRange(props);
|
|
|
|
return Node(id, "control.text", fieldProps);
|
|
}
|
|
|
|
private static EveSurfaceComponent ButtonRow(
|
|
string id,
|
|
params EveSurfaceComponent[] children)
|
|
{
|
|
return Node(id, "row", Array.Empty<(string Key, string Value)>(), children);
|
|
}
|
|
|
|
private static EveSurfaceComponent Node(
|
|
string id,
|
|
string kind,
|
|
IEnumerable<(string Key, string Value)> props,
|
|
params EveSurfaceComponent[] children)
|
|
{
|
|
return new EveSurfaceComponent(
|
|
id,
|
|
kind,
|
|
props.ToDictionary(prop => prop.Key, prop => prop.Value, StringComparer.Ordinal),
|
|
children ?? Array.Empty<EveSurfaceComponent>());
|
|
}
|
|
|
|
private string BuildEquippedItemTitle(EquippedItem item, AetheriaRuntimeCatalogItem typedItem)
|
|
{
|
|
var (tier, upgrades) = GameManager.ItemManager.GetTier(item.EquippableItem);
|
|
return $"{typedItem?.Name ?? "Unknown Item"} ({tier.Name}{new string('+', upgrades)})";
|
|
}
|
|
|
|
private static bool IsWeaponGroupAssigned(EquippedItem item, int groupIndex)
|
|
{
|
|
return item?.Entity?.WeaponGroups != null &&
|
|
groupIndex >= 0 &&
|
|
groupIndex < item.Entity.WeaponGroups.Length &&
|
|
item.Entity.WeaponGroups[groupIndex].items.Contains(item);
|
|
}
|
|
|
|
private static bool TryReadPayloadInt(EveSurfaceCommandRequest request, string key, out int value)
|
|
{
|
|
value = 0;
|
|
return request?.Payload != null &&
|
|
request.Payload.TryGetValue(key, out var raw) &&
|
|
int.TryParse(raw, NumberStyles.Integer, CultureInfo.InvariantCulture, out value);
|
|
}
|
|
|
|
private static bool TryReadPayloadFloat(EveSurfaceCommandRequest request, string key, out float value)
|
|
{
|
|
value = 0f;
|
|
return request?.Payload != null &&
|
|
request.Payload.TryGetValue(key, out var raw) &&
|
|
float.TryParse(raw, NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out value);
|
|
}
|
|
|
|
private bool CommitCargoItemTransfer(EquippedCargoBay origin, InventoryPanel destination, ItemInstance item)
|
|
{
|
|
if (destination.DisplayedEntity != null && item is EquippableItem equippableItem)
|
|
return GameManager.CommitCargoItemEquip(origin, destination.DisplayedEntity, equippableItem);
|
|
|
|
if (destination.DisplayedCargo != null)
|
|
return GameManager.CommitCargoItemTransfer(origin, destination.DisplayedCargo, item);
|
|
|
|
return false;
|
|
}
|
|
|
|
private void ClearSelectedItemSelection()
|
|
{
|
|
ClearSelectedCellHighlight();
|
|
_selectedPanel = null;
|
|
_selectedItem = null;
|
|
_selectedEquippedItem = null;
|
|
_selectedCells = null;
|
|
_selectedPosition = default;
|
|
}
|
|
|
|
private bool CommitEquippedItemTransfer(Entity origin, EquippedItem item, InventoryPanel destination)
|
|
{
|
|
if (destination.DisplayedCargo != null)
|
|
return GameManager.CommitEquippedItemStore(origin, item, destination.DisplayedCargo);
|
|
|
|
return false;
|
|
}
|
|
|
|
void Update()
|
|
{
|
|
// if (Keyboard.current.qKey.wasPressedThisFrame && _dragItem != null)
|
|
// {
|
|
// _dragItem.Rotation = (ItemRotation) (((int) _dragItem.Rotation + 1) % 4);
|
|
// }
|
|
// if (Keyboard.current.eKey.wasPressedThisFrame && _dragItem != null)
|
|
// {
|
|
// _dragItem.Rotation = (ItemRotation) (((int) _dragItem.Rotation + 3) % 4);
|
|
// }
|
|
}
|
|
|
|
private void ClearSelectedCellHighlight()
|
|
{
|
|
if (_selectedPanel == null || _selectedCells == null) return;
|
|
|
|
foreach (var v in _selectedCells)
|
|
{
|
|
if (_selectedPanel.CellInstances.ContainsKey(v))
|
|
_selectedPanel.CellInstances[v].Icon.color = _selectedPanel.GetColor(v);
|
|
}
|
|
}
|
|
|
|
private void ApplySelectedCellHighlight()
|
|
{
|
|
if (_selectedPanel == null || _selectedCells == null) return;
|
|
|
|
foreach (var v in _selectedCells)
|
|
{
|
|
if (_selectedPanel.CellInstances.ContainsKey(v))
|
|
_selectedPanel.CellInstances[v].Icon.color = _selectedPanel.GetColor(v, true);
|
|
}
|
|
}
|
|
|
|
private int2[] GetSelectedCells(ItemInstance item, int2 position)
|
|
{
|
|
var typedItem = FindTypedInventoryItem(item);
|
|
if (typedItem != null && typedItem.ShapeCells.Count > 0)
|
|
{
|
|
return typedItem.ShapeCells
|
|
.Select(cell => RotateTypedShapeCell(cell, typedItem, item.Rotation) + position)
|
|
.ToArray();
|
|
}
|
|
|
|
return Array.Empty<int2>();
|
|
}
|
|
|
|
private static AetheriaRuntimeCatalogItem FindTypedInventoryItem(ItemInstance item)
|
|
{
|
|
return ActionGameManager.RuntimeCatalog?.FindItem(item?.ItemKey ?? "");
|
|
}
|
|
|
|
private static float GetCargoItemMass(ItemInstance item, AetheriaRuntimeCatalogItem typedItem)
|
|
{
|
|
if (typedItem == null)
|
|
return 0f;
|
|
|
|
return item is SimpleCommodity simpleCommodity
|
|
? (float)typedItem.Mass * simpleCommodity.Quantity
|
|
: (float)typedItem.Mass;
|
|
}
|
|
|
|
private static float GetMaxDurability(AetheriaRuntimeCatalogItem typedItem, EquippableItem item)
|
|
{
|
|
if (typedItem != null && typedItem.Durability > 0)
|
|
return (float)typedItem.Durability;
|
|
|
|
return Math.Max(item?.Durability ?? 1f, 1f);
|
|
}
|
|
|
|
private static string FormatTemperatureRange(AetheriaRuntimeCatalogItem item)
|
|
{
|
|
if (item.MaximumTemperature > item.MinimumTemperature)
|
|
{
|
|
return
|
|
$"{ActionGameManager.RuntimePlayerSettings.FormatTemperature((float)item.MinimumTemperature)} to " +
|
|
$"{ActionGameManager.RuntimePlayerSettings.FormatTemperature((float)item.MaximumTemperature)}";
|
|
}
|
|
|
|
return "No typed thermal range";
|
|
}
|
|
|
|
private static AetheriaRuntimeBehaviorField FindTypedBehaviorField(AetheriaRuntimeBehaviorPayload behavior, int? key)
|
|
{
|
|
return key == null
|
|
? null
|
|
: behavior.Fields.FirstOrDefault(field => field.Key == key.Value);
|
|
}
|
|
|
|
private static PerformanceStat ReadTypedPerformanceStat(AetheriaRuntimeBehaviorValue value)
|
|
{
|
|
return new PerformanceStat
|
|
{
|
|
Min = ReadTypedChildNumber(value, 0),
|
|
Max = ReadTypedChildNumber(value, 1),
|
|
HeatExponentMultiplier = ReadTypedChildNumber(value, 2),
|
|
DurabilityExponentMultiplier = ReadTypedChildNumber(value, 3),
|
|
QualityExponent = ReadTypedChildNumber(value, 4)
|
|
};
|
|
}
|
|
|
|
private static (string target, string stat) ReadTypedStatReference(AetheriaRuntimeBehaviorValue value)
|
|
{
|
|
return (
|
|
ReadTypedChildString(value, 1),
|
|
ReadTypedChildString(value, 2));
|
|
}
|
|
|
|
private static float ReadTypedChildNumber(AetheriaRuntimeBehaviorValue value, int index)
|
|
{
|
|
return value != null && value.Children.Count > index
|
|
? (float)value.Children[index].NumberValue
|
|
: 0f;
|
|
}
|
|
|
|
private static string ReadTypedChildString(AetheriaRuntimeBehaviorValue value, int index)
|
|
{
|
|
return value != null && value.Children.Count > index
|
|
? value.Children[index].StringValue ?? ""
|
|
: "";
|
|
}
|
|
|
|
private static T ReadTypedEnum<T>(AetheriaRuntimeBehaviorValue value, T fallback) where T : struct
|
|
{
|
|
if (!string.IsNullOrWhiteSpace(value?.StringValue) && Enum.TryParse(value.StringValue, true, out T parsed))
|
|
{
|
|
return parsed;
|
|
}
|
|
|
|
return value != null && Enum.IsDefined(typeof(T), (int)value.NumberValue)
|
|
? (T)Enum.ToObject(typeof(T), (int)value.NumberValue)
|
|
: fallback;
|
|
}
|
|
|
|
private static int2 RotateTypedShapeCell(
|
|
AetheriaRuntimeShapeCell cell,
|
|
AetheriaRuntimeCatalogItem item,
|
|
ItemRotation rotation)
|
|
{
|
|
return rotation switch
|
|
{
|
|
ItemRotation.Clockwise => new int2(cell.Y, item.ShapeWidth - 1 - cell.X),
|
|
ItemRotation.Reversed => new int2(item.ShapeWidth - 1 - cell.X, item.ShapeHeight - 1 - cell.Y),
|
|
ItemRotation.CounterClockwise => new int2(item.ShapeHeight - 1 - cell.Y, cell.X),
|
|
_ => new int2(cell.X, cell.Y)
|
|
};
|
|
}
|
|
|
|
private void OnDestroy()
|
|
{
|
|
if (_shipSettingsSurfaceDocument != null)
|
|
{
|
|
Destroy(_shipSettingsSurfaceDocument.gameObject);
|
|
_shipSettingsSurfaceDocument = null;
|
|
}
|
|
|
|
if (_cargoItemDetailsSurfaceDocument != null)
|
|
{
|
|
Destroy(_cargoItemDetailsSurfaceDocument.gameObject);
|
|
_cargoItemDetailsSurfaceDocument = null;
|
|
}
|
|
|
|
if (_equippedItemDetailsSurfaceDocument != null)
|
|
{
|
|
Destroy(_equippedItemDetailsSurfaceDocument.gameObject);
|
|
_equippedItemDetailsSurfaceDocument = null;
|
|
}
|
|
}
|
|
}
|