2020-12-22 03:13:43 +00:00
/ * 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 ;
2020-12-14 02:56:35 +00:00
using System.Collections.Generic ;
2026-06-17 01:50:15 +01:00
using System.Globalization ;
2020-12-20 03:04:52 +00:00
using System.Linq ;
2026-06-14 00:48:20 +01:00
using GameCult.Aetheria.State.Unity ;
2026-06-16 21:35:58 +01:00
using GameCult.Eve.Surface ;
using GameCult.Eve.UnityUIToolkit ;
2020-12-14 02:56:35 +00:00
using UnityEngine ;
2020-12-20 03:04:52 +00:00
using UniRx ;
using UniRx.Triggers ;
using Unity.Mathematics ;
2026-06-16 21:35:58 +01:00
using UnityEngine.UIElements ;
2020-12-14 02:56:35 +00:00
public class InventoryMenu : MonoBehaviour
{
2026-06-16 21:35:58 +01:00
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" ;
2026-06-16 23:44:14 +01:00
private const string CargoItemDetailsSurfaceId = "aetheria.inventory.cargo_item_details" ;
private const string CloseCargoItemDetailsCommand = "aetheria.inventory.cargo_item_details.close" ;
2026-06-17 01:50:15 +01:00
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" ;
2026-06-16 21:35:58 +01:00
private const float ShutdownThresholdStep = 0.05f ;
2020-12-20 03:04:52 +00:00
public InventoryPanel [ ] InventoryPanels ;
public ActionGameManager GameManager ;
2021-01-06 14:56:39 +00:00
public ConfirmationDialog Dialog ;
2021-05-12 00:15:11 +01:00
// public ClickCatcher Background;
2020-12-20 03:04:52 +00:00
2020-12-22 03:13:43 +00:00
private int _currentPanel = - 1 ;
2020-12-20 03:04:52 +00:00
private int2 _selectedPosition ;
private InventoryPanel _selectedPanel ;
2020-12-22 21:32:37 +00:00
private ItemInstance _selectedItem ;
2026-06-17 01:50:15 +01:00
private EquippedItem _selectedEquippedItem ;
2026-06-14 00:48:20 +01:00
private int2 [ ] _selectedCells ;
2026-06-16 21:35:58 +01:00
private UIDocument _shipSettingsSurfaceDocument ;
2026-06-16 23:44:14 +01:00
private UIDocument _cargoItemDetailsSurfaceDocument ;
2026-06-17 01:50:15 +01:00
private UIDocument _equippedItemDetailsSurfaceDocument ;
2021-05-12 00:15:11 +01:00
// private List<IDisposable> _backgroundSubscriptions;
2020-12-20 03:04:52 +00:00
2021-05-12 00:15:11 +01:00
// 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;
2021-01-17 02:45:52 +00:00
private void OnEnable ( )
{
2021-05-12 00:15:11 +01:00
// Background.gameObject.SetActive(true);
2021-01-17 02:45:52 +00:00
2021-05-12 00:15:11 +01:00
// Background.OnEnter.Subscribe(enter =>
// {
// _destroyItem = true;
// });
// BackgroundExited.OnPointerExitAsObservable().Subscribe(enter =>
// {
// _destroyItem = false;
// });
2021-03-10 09:18:07 +00:00
var cargo = GameManager . DockingBay ? ? GameManager . CurrentEntity . CargoBays . FirstOrDefault ( ) ;
2021-01-17 02:45:52 +00:00
if ( cargo ! = null )
InventoryPanels [ 0 ] . Display ( cargo ) ;
2021-04-10 01:47:16 +01:00
else InventoryPanels [ 0 ] . Clear ( ) ;
2021-03-10 09:18:07 +00:00
if ( GameManager . CurrentEntity ! = null )
InventoryPanels [ 1 ] . Display ( GameManager . CurrentEntity ) ;
2021-02-01 08:13:14 +00:00
else InventoryPanels [ 1 ] . Clear ( ) ;
2021-01-17 02:45:52 +00:00
}
private void OnDisable ( )
{
2026-06-16 21:35:58 +01:00
HideCurrentShipSettingsSurface ( ) ;
2026-06-16 23:44:14 +01:00
HideCargoItemDetailsSurface ( ) ;
2026-06-17 01:50:15 +01:00
HideEquippedItemDetailsSurface ( ) ;
2021-05-12 00:15:11 +01:00
// Background.gameObject.SetActive(false);
2021-01-17 02:45:52 +00:00
}
2020-12-20 03:04:52 +00:00
2020-12-14 02:56:35 +00:00
void Start ( )
{
2020-12-20 03:04:52 +00:00
foreach ( var panel in InventoryPanels )
{
2021-04-10 01:47:16 +01:00
panel . OnClickAsObservable ( ) . Subscribe ( e = >
2020-12-20 03:04:52 +00:00
{
2021-04-10 01:47:16 +01:00
if ( e . data is InventoryCargoEventData cargoEvent )
2020-12-20 03:04:52 +00:00
{
var item = cargoEvent . CargoBay . Occupancy [ cargoEvent . Position . x , cargoEvent . Position . y ] ;
if ( item ! = null )
{
2021-04-10 01:47:16 +01:00
if ( e . clickCount = = 2 )
2020-12-20 03:04:52 +00:00
{
2026-06-16 23:44:14 +01:00
HideCargoItemDetailsSurface ( ) ;
2026-06-17 01:50:15 +01:00
HideEquippedItemDetailsSurface ( ) ;
2026-06-16 23:44:14 +01:00
ClearSelectedItemSelection ( ) ;
2021-01-27 16:14:41 +00:00
var otherPanel = panel = = InventoryPanels [ 0 ] ? InventoryPanels [ 1 ] : InventoryPanels [ 0 ] ;
2026-06-16 01:59:18 +01:00
if ( CommitCargoItemTransfer ( cargoEvent . CargoBay , otherPanel , item ) )
2020-12-20 03:04:52 +00:00
{
2022-07-10 02:53:09 +01:00
// TODO: SFX: Equip
2021-01-27 16:14:41 +00:00
panel . RefreshCells ( ) ;
otherPanel . RefreshCells ( ) ;
2020-12-20 03:04:52 +00:00
}
2022-07-10 02:53:09 +01:00
// else
// TODO: SFX: Fail
2020-12-20 03:04:52 +00:00
}
2021-01-27 16:14:41 +00:00
else
2020-12-20 03:04:52 +00:00
{
2026-06-16 21:35:58 +01:00
HideCurrentShipSettingsSurface ( ) ;
2026-06-16 23:44:14 +01:00
HideCargoItemDetailsSurface ( ) ;
2026-06-17 01:50:15 +01:00
HideEquippedItemDetailsSurface ( ) ;
2026-06-16 23:44:14 +01:00
ClearSelectedItemSelection ( ) ;
2021-01-27 16:14:41 +00:00
_selectedPanel = panel ;
_selectedPosition = cargoEvent . CargoBay . Cargo [ item ] ;
_selectedItem = item ;
2026-06-14 00:48:20 +01:00
_selectedCells = GetSelectedCells ( item , _selectedPosition ) ;
ApplySelectedCellHighlight ( ) ;
2026-06-16 23:44:14 +01:00
RenderCargoItemDetailsSurface ( item ) ;
2022-07-10 02:53:09 +01:00
// TODO: SFX: Success
2020-12-20 03:04:52 +00:00
}
}
}
2021-04-10 01:47:16 +01:00
else if ( e . data is InventoryEntityEventData entityEvent )
2020-12-20 03:04:52 +00:00
{
var item = entityEvent . Entity . GearOccupancy [ entityEvent . Position . x , entityEvent . Position . y ] ;
if ( item ! = null )
{
2021-04-10 01:47:16 +01:00
if ( e . clickCount = = 2 )
2020-12-20 03:04:52 +00:00
{
2026-06-16 23:44:14 +01:00
HideCargoItemDetailsSurface ( ) ;
2026-06-17 01:50:15 +01:00
HideEquippedItemDetailsSurface ( ) ;
2026-06-16 23:44:14 +01:00
ClearSelectedItemSelection ( ) ;
2021-01-27 16:14:41 +00:00
var otherPanel = panel = = InventoryPanels [ 0 ] ? InventoryPanels [ 1 ] : InventoryPanels [ 0 ] ;
2026-06-16 01:59:18 +01:00
if ( CommitEquippedItemTransfer ( entityEvent . Entity , item , otherPanel ) )
2020-12-20 03:04:52 +00:00
{
2026-06-16 01:59:18 +01:00
// TODO: SFX: Unequip
panel . RefreshCells ( ) ;
otherPanel . RefreshCells ( ) ;
2022-07-10 02:53:09 +01:00
// else
// TODO: SFX: Fail
2020-12-20 03:04:52 +00:00
}
}
2021-01-27 16:14:41 +00:00
else
2020-12-20 03:04:52 +00:00
{
2026-06-16 21:35:58 +01:00
HideCurrentShipSettingsSurface ( ) ;
2026-06-16 23:44:14 +01:00
HideCargoItemDetailsSurface ( ) ;
ClearSelectedItemSelection ( ) ;
2021-01-27 16:14:41 +00:00
_selectedPanel = panel ;
_selectedPosition = item . Position ;
_selectedItem = item . EquippableItem ;
2026-06-17 01:50:15 +01:00
_selectedEquippedItem = item ;
2026-06-14 00:48:20 +01:00
_selectedCells = GetSelectedCells ( item . EquippableItem , _selectedPosition ) ;
ApplySelectedCellHighlight ( ) ;
2026-06-17 01:50:15 +01:00
RenderEquippedItemDetailsSurface ( item ) ;
2022-07-10 02:53:09 +01:00
// TODO: SFX: Success
2020-12-20 03:04:52 +00:00
}
}
}
} ) ;
2021-03-07 01:10:31 +00:00
panel . OnBackgroundClick . Subscribe ( data = >
{
2021-03-15 11:40:46 +00:00
if ( GameManager . CurrentEntity = = null ) return ; // Only show ship settings if there's a ship, duh!
2026-06-16 21:35:58 +01:00
RenderCurrentShipSettingsSurface ( GameManager . CurrentEntity ) ;
2021-03-07 01:10:31 +00:00
} ) ;
2020-12-20 03:04:52 +00:00
}
2020-12-14 02:56:35 +00:00
}
2026-06-16 21:35:58 +01:00
private void RenderCurrentShipSettingsSurface ( Entity entity )
{
if ( entity = = null )
return ;
2026-06-16 23:44:14 +01:00
HideCargoItemDetailsSurface ( ) ;
2026-06-17 01:50:15 +01:00
HideEquippedItemDetailsSurface ( ) ;
2026-06-16 23:44:14 +01:00
ClearSelectedItemSelection ( ) ;
2026-06-16 21:35:58 +01:00
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 ) ;
}
2026-06-16 23:44:14 +01:00
private void RenderCargoItemDetailsSurface ( ItemInstance item )
{
var typedItem = FindTypedInventoryItem ( item ) ;
if ( item = = null | | typedItem = = null )
return ;
2026-06-17 01:50:15 +01:00
HideEquippedItemDetailsSurface ( ) ;
2026-06-16 23:44:14 +01:00
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 ) ;
}
2026-06-17 01:50:15 +01:00
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 ) ) ;
}
}
2026-06-16 23:44:14 +01:00
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 )
2026-06-17 01:50:15 +01:00
{
return BuildItemBehaviorCards ( CargoItemDetailsSurfaceId , typedItem , equippableItem ) ;
}
private IEnumerable < EveSurfaceComponent > BuildItemBehaviorCards (
string surfaceId ,
AetheriaRuntimeCatalogItem typedItem ,
EquippableItem equippableItem )
2026-06-16 23:44:14 +01:00
{
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 (
2026-06-17 01:50:15 +01:00
$"{surfaceId}.behavior.{behavior.Kind}.stat_modifier" ,
2026-06-16 23:44:14 +01:00
"Stat Modifier" ,
Metric (
2026-06-17 01:50:15 +01:00
$"{surfaceId}.behavior.{behavior.Kind}.target" ,
2026-06-16 23:44:14 +01:00
$"{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
2026-06-17 01:50:15 +01:00
. Select ( field = > BuildItemBehaviorMetric ( surfaceId , behavior , field , equippableItem ) )
2026-06-16 23:44:14 +01:00
. Where ( metric = > metric ! = null )
. ToArray ( ) ;
if ( fields . Length = = 0 )
continue ;
yield return Card (
2026-06-17 01:50:15 +01:00
$"{surfaceId}.behavior.{behavior.Kind}" ,
2026-06-16 23:44:14 +01:00
behavior . Kind . FormatTypeName ( ) ,
fields ) ;
}
}
private EveSurfaceComponent BuildCargoItemBehaviorMetric (
AetheriaRuntimeBehaviorPayload behavior ,
AetheriaRuntimeBehaviorFieldMetadata field ,
EquippableItem equippableItem )
2026-06-17 01:50:15 +01:00
{
return BuildItemBehaviorMetric ( CargoItemDetailsSurfaceId , behavior , field , equippableItem ) ;
}
private EveSurfaceComponent BuildItemBehaviorMetric (
string surfaceId ,
AetheriaRuntimeBehaviorPayload behavior ,
AetheriaRuntimeBehaviorFieldMetadata field ,
EquippableItem equippableItem )
2026-06-16 23:44:14 +01:00
{
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 (
2026-06-17 01:50:15 +01:00
$"{surfaceId}.behavior.{behavior.Kind}.{field.Key}" ,
2026-06-16 23:44:14 +01:00
field . Name . SplitCamelCase ( ) ,
value ) ;
}
2026-06-16 21:35:58 +01:00
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 ) } ) ;
}
2026-06-17 01:50:15 +01:00
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 ) ;
}
2026-06-16 21:35:58 +01:00
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 > ( ) ) ;
}
2026-06-17 01:50:15 +01:00
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 ) ;
}
2026-06-16 01:59:18 +01:00
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 ;
}
2026-06-16 23:44:14 +01:00
private void ClearSelectedItemSelection ( )
{
ClearSelectedCellHighlight ( ) ;
_selectedPanel = null ;
_selectedItem = null ;
2026-06-17 01:50:15 +01:00
_selectedEquippedItem = null ;
2026-06-16 23:44:14 +01:00
_selectedCells = null ;
_selectedPosition = default ;
}
2026-06-16 01:59:18 +01:00
private bool CommitEquippedItemTransfer ( Entity origin , EquippedItem item , InventoryPanel destination )
{
if ( destination . DisplayedCargo ! = null )
return GameManager . CommitEquippedItemStore ( origin , item , destination . DisplayedCargo ) ;
return false ;
}
2020-12-14 02:56:35 +00:00
void Update ( )
{
2021-05-12 00:15:11 +01:00
// 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);
// }
2020-12-14 02:56:35 +00:00
}
2026-06-14 00:48:20 +01:00
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 ( ) ;
}
2026-06-14 01:54:28 +01:00
return Array . Empty < int2 > ( ) ;
2026-06-14 00:48:20 +01:00
}
private static AetheriaRuntimeCatalogItem FindTypedInventoryItem ( ItemInstance item )
{
2026-06-15 00:49:54 +01:00
return ActionGameManager . RuntimeCatalog ? . FindItem ( item ? . ItemKey ? ? "" ) ;
2026-06-14 00:48:20 +01:00
}
2026-06-16 23:44:14 +01:00
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 ;
}
2026-06-14 00:48:20 +01:00
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 )
} ;
}
2026-06-16 21:35:58 +01:00
private void OnDestroy ( )
{
if ( _shipSettingsSurfaceDocument ! = null )
{
Destroy ( _shipSettingsSurfaceDocument . gameObject ) ;
_shipSettingsSurfaceDocument = null ;
}
2026-06-16 23:44:14 +01:00
if ( _cargoItemDetailsSurfaceDocument ! = null )
{
Destroy ( _cargoItemDetailsSurfaceDocument . gameObject ) ;
_cargoItemDetailsSurfaceDocument = null ;
}
2026-06-17 01:50:15 +01:00
if ( _equippedItemDetailsSurfaceDocument ! = null )
{
Destroy ( _equippedItemDetailsSurfaceDocument . gameObject ) ;
_equippedItemDetailsSurfaceDocument = null ;
}
2026-06-16 21:35:58 +01:00
}
2020-12-14 02:56:35 +00:00
}