Heat Pipes

Thermal Layer Removed
Items can be destroyed from inventory menu via drag & drop
Trade menu contains only priced items
Trade menu has filters for commodities
Conductivity can be adjusted along schematic edges
Thermals rebalanced
This commit is contained in:
Reinier Vens 2021-01-17 02:45:52 +00:00
commit ebec68e7f0
28 changed files with 1706 additions and 322 deletions

View file

@ -50,7 +50,6 @@ public class ActionGameManager : MonoBehaviour
private float _time;
private AetheriaInput _input;
private int _zoomLevelIndex;
private Ship _currentShip;
// private ShipInput _shipInput;
private float2 _shipYawPitch;
@ -60,10 +59,7 @@ public class ActionGameManager : MonoBehaviour
public List<Ship> PlayerShips { get; } = new List<Ship>();
public EquippedDockingBay DockingBay { get; private set; }
public Ship CurrentShip
{
get => _currentShip;
}
public Ship CurrentShip { get; set; }
public DatabaseCache ItemData { get; private set; }
public ItemManager ItemManager { get; private set; }
public Zone Zone { get; private set; }
@ -123,12 +119,12 @@ public class ActionGameManager : MonoBehaviour
Cursor.lockState = CursorLockMode.Locked;
_input.Player.Enable();
Menu.gameObject.SetActive(false);
if (_currentShip != null && _currentShip.Parent == null)
if (CurrentShip != null && CurrentShip.Parent == null)
{
GameplayUI.SetActive(true);
SchematicDisplay.ShowShip(_currentShip);
ShipPanel.Display(_currentShip, true);
SchematicDisplay.ShowShip(CurrentShip);
ShipPanel.Display(CurrentShip, true);
}
return;
@ -138,7 +134,7 @@ public class ActionGameManager : MonoBehaviour
_input.Player.Disable();
GameplayUI.SetActive(false);
Menu.ShowTab(MenuTab.Map);
MenuMap.Position = _currentShip.Position.xz;
MenuMap.Position = CurrentShip.Position.xz;
};
_input.Global.Inventory.performed += context =>
@ -148,12 +144,12 @@ public class ActionGameManager : MonoBehaviour
Cursor.lockState = CursorLockMode.Locked;
_input.Player.Enable();
Menu.gameObject.SetActive(false);
if (_currentShip != null && _currentShip.Parent == null)
if (CurrentShip != null && CurrentShip.Parent == null)
{
GameplayUI.SetActive(true);
SchematicDisplay.ShowShip(_currentShip);
ShipPanel.Display(_currentShip, true);
SchematicDisplay.ShowShip(CurrentShip);
ShipPanel.Display(CurrentShip, true);
}
return;
}
@ -162,86 +158,79 @@ public class ActionGameManager : MonoBehaviour
_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();
if (CurrentShip.Parent == null) Dock();
else Undock();
};
_input.Player.TargetReticle.performed += context =>
{
var underReticle = Zone.Entities.Where(x => x != _currentShip).MaxBy(x => dot(normalize(x.Position - _currentShip.Position), _currentShip.LookDirection));
_currentShip.Target.Value = _currentShip.Target.Value == underReticle ? null : underReticle;
var underReticle = Zone.Entities.Where(x => x != CurrentShip).MaxBy(x => dot(normalize(x.Position - CurrentShip.Position), CurrentShip.LookDirection));
CurrentShip.Target.Value = CurrentShip.Target.Value == underReticle ? null : underReticle;
};
_input.Player.TargetNearest.performed += context =>
{
_currentShip.Target.Value = Zone.Entities.Where(x=>x!=_currentShip).MaxBy(x => length(x.Position - _currentShip.Position));
CurrentShip.Target.Value = Zone.Entities.Where(x=>x!=CurrentShip).MaxBy(x => length(x.Position - CurrentShip.Position));
};
_input.Player.TargetNext.performed += context =>
{
var targets = Zone.Entities.Where(x => x != _currentShip).OrderBy(x => length(x.Position - _currentShip.Position)).ToArray();
var currentTargetIndex = Array.IndexOf(targets, _currentShip.Target.Value);
_currentShip.Target.Value = targets[(currentTargetIndex + 1) % targets.Length];
var targets = Zone.Entities.Where(x => x != CurrentShip).OrderBy(x => length(x.Position - CurrentShip.Position)).ToArray();
var currentTargetIndex = Array.IndexOf(targets, CurrentShip.Target.Value);
CurrentShip.Target.Value = targets[(currentTargetIndex + 1) % targets.Length];
};
_input.Player.TargetPrevious.performed += context =>
{
var targets = Zone.Entities.Where(x => x != _currentShip).OrderBy(x => length(x.Position - _currentShip.Position)).ToArray();
var currentTargetIndex = Array.IndexOf(targets, _currentShip.Target.Value);
_currentShip.Target.Value = targets[(currentTargetIndex + targets.Length - 1) % targets.Length];
var targets = Zone.Entities.Where(x => x != CurrentShip).OrderBy(x => length(x.Position - CurrentShip.Position)).ToArray();
var currentTargetIndex = Array.IndexOf(targets, CurrentShip.Target.Value);
CurrentShip.Target.Value = targets[(currentTargetIndex + targets.Length - 1) % targets.Length];
};
#region Trigger Groups
_input.Player.PreviousWeaponGroup.performed += context =>
{
if (_currentShip.Parent != null) return;
if (CurrentShip.Parent != null) return;
SchematicDisplay.SelectedGroupIndex--;
};
_input.Player.NextWeaponGroup.performed += context =>
{
if (_currentShip.Parent != null) return;
if (CurrentShip.Parent != null) return;
SchematicDisplay.SelectedGroupIndex++;
};
_input.Player.PreviousWeapon.performed += context =>
{
if (_currentShip.Parent != null) return;
if (CurrentShip.Parent != null) return;
SchematicDisplay.SelectedItemIndex--;
};
_input.Player.NextWeapon.performed += context =>
{
if (_currentShip.Parent != null) return;
if (CurrentShip.Parent != null) return;
SchematicDisplay.SelectedItemIndex++;
};
_input.Player.ToggleWeaponGroup.performed += context =>
{
if (_currentShip.Parent != null) return;
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);
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])
if (CurrentShip.Parent != null) return;
foreach (var item in CurrentShip.TriggerGroups[0])
{
foreach (var behaviors in item.BehaviorGroups)
{
@ -254,8 +243,8 @@ public class ActionGameManager : MonoBehaviour
_input.Player.FireGroup1.canceled += context =>
{
if (_currentShip.Parent != null) return;
foreach (var item in _currentShip.TriggerGroups[0])
if (CurrentShip.Parent != null) return;
foreach (var item in CurrentShip.TriggerGroups[0])
{
foreach (var behaviors in item.BehaviorGroups)
{
@ -267,8 +256,8 @@ public class ActionGameManager : MonoBehaviour
_input.Player.FireGroup2.started += context =>
{
if (_currentShip.Parent != null) return;
foreach (var item in _currentShip.TriggerGroups[1])
if (CurrentShip.Parent != null) return;
foreach (var item in CurrentShip.TriggerGroups[1])
{
foreach (var behaviors in item.BehaviorGroups)
{
@ -281,8 +270,8 @@ public class ActionGameManager : MonoBehaviour
_input.Player.FireGroup2.canceled += context =>
{
if (_currentShip.Parent != null) return;
foreach (var item in _currentShip.TriggerGroups[1])
if (CurrentShip.Parent != null) return;
foreach (var item in CurrentShip.TriggerGroups[1])
{
foreach (var behaviors in item.BehaviorGroups)
{
@ -294,8 +283,8 @@ public class ActionGameManager : MonoBehaviour
_input.Player.FireGroup3.started += context =>
{
if (_currentShip.Parent != null) return;
foreach (var item in _currentShip.TriggerGroups[2])
if (CurrentShip.Parent != null) return;
foreach (var item in CurrentShip.TriggerGroups[2])
{
foreach (var behaviors in item.BehaviorGroups)
{
@ -308,8 +297,8 @@ public class ActionGameManager : MonoBehaviour
_input.Player.FireGroup3.canceled += context =>
{
if (_currentShip.Parent != null) return;
foreach (var item in _currentShip.TriggerGroups[2])
if (CurrentShip.Parent != null) return;
foreach (var item in CurrentShip.TriggerGroups[2])
{
foreach (var behaviors in item.BehaviorGroups)
{
@ -321,8 +310,8 @@ public class ActionGameManager : MonoBehaviour
_input.Player.FireGroup4.started += context =>
{
if (_currentShip.Parent != null) return;
foreach (var item in _currentShip.TriggerGroups[3])
if (CurrentShip.Parent != null) return;
foreach (var item in CurrentShip.TriggerGroups[3])
{
foreach (var behaviors in item.BehaviorGroups)
{
@ -335,8 +324,8 @@ public class ActionGameManager : MonoBehaviour
_input.Player.FireGroup4.canceled += context =>
{
if (_currentShip.Parent != null) return;
foreach (var item in _currentShip.TriggerGroups[3])
if (CurrentShip.Parent != null) return;
foreach (var item in CurrentShip.TriggerGroups[3])
{
foreach (var behaviors in item.BehaviorGroups)
{
@ -348,8 +337,8 @@ public class ActionGameManager : MonoBehaviour
_input.Player.FireGroup5.started += context =>
{
if (_currentShip.Parent != null) return;
foreach (var item in _currentShip.TriggerGroups[4])
if (CurrentShip.Parent != null) return;
foreach (var item in CurrentShip.TriggerGroups[4])
{
foreach (var behaviors in item.BehaviorGroups)
{
@ -362,8 +351,8 @@ public class ActionGameManager : MonoBehaviour
_input.Player.FireGroup5.canceled += context =>
{
if (_currentShip.Parent != null) return;
foreach (var item in _currentShip.TriggerGroups[4])
if (CurrentShip.Parent != null) return;
foreach (var item in CurrentShip.TriggerGroups[4])
{
foreach (var behaviors in item.BehaviorGroups)
{
@ -375,8 +364,8 @@ public class ActionGameManager : MonoBehaviour
_input.Player.FireGroup6.started += context =>
{
if (_currentShip.Parent != null) return;
foreach (var item in _currentShip.TriggerGroups[5])
if (CurrentShip.Parent != null) return;
foreach (var item in CurrentShip.TriggerGroups[5])
{
foreach (var behaviors in item.BehaviorGroups)
{
@ -389,8 +378,8 @@ public class ActionGameManager : MonoBehaviour
_input.Player.FireGroup6.canceled += context =>
{
if (_currentShip.Parent != null) return;
foreach (var item in _currentShip.TriggerGroups[5])
if (CurrentShip.Parent != null) return;
foreach (var item in CurrentShip.TriggerGroups[5])
{
foreach (var behaviors in item.BehaviorGroups)
{
@ -454,15 +443,15 @@ public class ActionGameManager : MonoBehaviour
var shipHull = ItemManager.CreateInstance(hullType, 0, 1) as EquippableItem;
var ship = new Ship(ItemManager, Zone, shipHull);
PlayerShips.Add(ship);
_currentShip = ship;
_currentShip.Target.Subscribe(target =>
CurrentShip = ship;
CurrentShip.Target.Subscribe(target =>
{
TargetIndicator.gameObject.SetActive(_currentShip.Target.Value != null);
TargetIndicator.gameObject.SetActive(CurrentShip.Target.Value != null);
TargetShipPanel.gameObject.SetActive(target != null);
if (target != null)
{
TargetShipPanel.Display(target, true);
TargetSchematicDisplay.ShowShip(target, _currentShip);
TargetSchematicDisplay.ShowShip(target, CurrentShip);
}
});
ship.ArmorDamage.Subscribe(hit =>
@ -478,7 +467,7 @@ public class ActionGameManager : MonoBehaviour
var data = ItemManager.GetData(hit.item.EquippableItem);
EventLog.LogMessage(
$"{hit.item.EquippableItem.Name} hit for {hit.damage} damage, currently {((int) (hit.item.EquippableItem.Durability / data.Durability * 100)).ToString()}%",
data.HardpointType == HardpointType.Thermal ? Settings.ThermalHitColor : Settings.GearHitColor);
Settings.GearHitColor);
});
ship.HardpointDamage.Subscribe(hit => EventLog.LogMessage(
$"{Enum.GetName(typeof(HardpointType), hit.hardpoint.Type)} hardpoint hit for {hit.damage} damage, currently {((int) (ship.HardpointArmor[hit.hardpoint] / hit.hardpoint.Armor * 100)).ToString()}%",
@ -524,27 +513,25 @@ public class ActionGameManager : MonoBehaviour
public void Dock()
{
if (_currentShip.Parent != null) return;
if (CurrentShip.Parent != null) return;
foreach (var entity in Zone.Entities.ToArray())
{
if (lengthsq(entity.Position.xz - _currentShip.Position.xz) <
if (lengthsq(entity.Position.xz - CurrentShip.Position.xz) <
Settings.GameplaySettings.DockingDistance * Settings.GameplaySettings.DockingDistance)
{
var bay = entity.TryDock(_currentShip);
var bay = entity.TryDock(CurrentShip);
if (bay != null)
{
DockingBay = bay;
DockCamera.enabled = true;
FollowCamera.enabled = false;
_currentShip.Active = 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);
@ -557,44 +544,44 @@ public class ActionGameManager : MonoBehaviour
public void Undock()
{
if (_currentShip.Parent == null) return;
if (_currentShip.GetBehavior<Cockpit>() == null)
if (CurrentShip.Parent == null) return;
if (CurrentShip.GetBehavior<Cockpit>() == null)
{
ConfirmationDialog.Clear();
ConfirmationDialog.Title.text = "Can't undock. Missing cockpit component!";
ConfirmationDialog.Show();
}
else if (_currentShip.GetBehavior<Thruster>() == null)
else if (CurrentShip.GetBehavior<Thruster>() == null)
{
ConfirmationDialog.Clear();
ConfirmationDialog.Title.text = "Can't undock. Missing thruster component!";
ConfirmationDialog.Show();
}
else if (_currentShip.GetBehavior<Reactor>() == null)
else if (CurrentShip.GetBehavior<Reactor>() == null)
{
ConfirmationDialog.Clear();
ConfirmationDialog.Title.text = "Can't undock. Missing reactor component!";
ConfirmationDialog.Show();
}
else if (_currentShip.Parent.TryUndock(_currentShip))
else if (CurrentShip.Parent.TryUndock(CurrentShip))
{
Menu.gameObject.SetActive(false);
DockingBay = null;
_currentShip.Active = true;
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;
ArticulationGroups = _currentShip.Equipment
FollowCamera.LookAt = SectorRenderer.EntityInstances[CurrentShip].LookAtPoint;
FollowCamera.Follow = SectorRenderer.EntityInstances[CurrentShip].Transform;
ArticulationGroups = CurrentShip.Equipment
.Where(item => item.Behaviors.Any(x => x.Data is WeaponData && !(x.Data is LauncherData)))
.GroupBy(item => SectorRenderer.EntityInstances[_currentShip]
.GetBarrel(_currentShip.Hardpoints[item.Position.x, item.Position.y])
.GroupBy(item => SectorRenderer.EntityInstances[CurrentShip]
.GetBarrel(CurrentShip.Hardpoints[item.Position.x, item.Position.y])
.GetComponentInParent<ArticulationPoint>()?.Group ?? -1)
.Select((group, index) => {
return (
group.Select(item => _currentShip.Hardpoints[item.Position.x, item.Position.y]).ToArray(),
group.Select(item => SectorRenderer.EntityInstances[_currentShip].GetBarrel(_currentShip.Hardpoints[item.Position.x, item.Position.y])).ToArray(),
group.Select(item => CurrentShip.Hardpoints[item.Position.x, item.Position.y]).ToArray(),
group.Select(item => SectorRenderer.EntityInstances[CurrentShip].GetBarrel(CurrentShip.Hardpoints[item.Position.x, item.Position.y])).ToArray(),
Crosshairs[index]
);
}).ToArray();
@ -604,7 +591,7 @@ public class ActionGameManager : MonoBehaviour
foreach (var group in ArticulationGroups)
group.crosshair.gameObject.SetActive(true);
LockingIndicators = _currentShip.GetBehaviors<TargetLock>().Select(x =>
LockingIndicators = CurrentShip.GetBehaviors<TargetLock>().Select(x =>
{
var i = LockIndicator.Instantiate<PlaceUIElementWorldspace>();
return (x, i, i.GetComponent<Rotate>());
@ -614,8 +601,8 @@ public class ActionGameManager : MonoBehaviour
Cursor.lockState = CursorLockMode.Locked;
GameplayUI.SetActive(true);
_input.Player.Enable();
ShipPanel.Display(_currentShip, true);
SchematicDisplay.ShowShip(_currentShip);
ShipPanel.Display(CurrentShip, true);
SchematicDisplay.ShowShip(CurrentShip);
}
else
{
@ -636,9 +623,9 @@ public class ActionGameManager : MonoBehaviour
public IEnumerable<EquippedCargoBay> AvailableCargoBays()
{
if (_currentShip.Parent != null)
if (CurrentShip.Parent != null)
{
foreach (var bay in _currentShip.Parent.DockingBays)
foreach (var bay in CurrentShip.Parent.DockingBays)
{
if (PlayerShips.Contains(bay.DockedShip)) yield return bay;
}
@ -647,15 +634,15 @@ public class ActionGameManager : MonoBehaviour
public IEnumerable<Ship> AvailableShips()
{
if (_currentShip.Parent != null)
if (CurrentShip.Parent != null)
{
foreach (var ship in PlayerShips)
{
if (_currentShip.Parent.Children.Contains(ship)) yield return ship;
if (CurrentShip.Parent.Children.Contains(ship)) yield return ship;
}
}
else
yield return _currentShip;
yield return CurrentShip;
}
void Update()
@ -664,13 +651,13 @@ public class ActionGameManager : MonoBehaviour
{
_time += Time.deltaTime;
ItemManager.Time = Time.time;
if(_currentShip.Parent==null)
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>();
CurrentShip.LookDirection = _viewDirection;
CurrentShip.MovementDirection = _input.Player.Move.ReadValue<Vector2>();
}
}
Zone.Update(_time, Time.deltaTime);
@ -684,12 +671,12 @@ public class ActionGameManager : MonoBehaviour
private void UpdateTargetIndicators()
{
if (_currentShip == null || _currentShip.Parent != null) return;
if (CurrentShip == null || CurrentShip.Parent != null) return;
ViewDot.Target = SectorRenderer.EntityInstances[_currentShip].LookAtPoint.position;
if (_currentShip.Target.Value != null)
TargetIndicator.Target = _currentShip.Target.Value.Position;
var distance = length((float3)ViewDot.Target - _currentShip.Position);
ViewDot.Target = SectorRenderer.EntityInstances[CurrentShip].LookAtPoint.position;
if (CurrentShip.Target.Value != null)
TargetIndicator.Target = CurrentShip.Target.Value.Position;
var distance = length((float3)ViewDot.Target - CurrentShip.Position);
foreach (var (_, barrels, crosshair) in ArticulationGroups)
{
var averagePosition = Vector3.zero;
@ -700,10 +687,10 @@ public class ActionGameManager : MonoBehaviour
}
foreach (var (targetLock, indicator, spin) in LockingIndicators)
{
var showLockingIndicator = targetLock.Lock > .01f && _currentShip.Target.Value != null;
var showLockingIndicator = targetLock.Lock > .01f && CurrentShip.Target.Value != null;
indicator.gameObject.SetActive(showLockingIndicator);
if(showLockingIndicator)
indicator.Target = _currentShip.Target.Value.Position;
indicator.Target = CurrentShip.Target.Value.Position;
indicator.NoiseAmplitude = Settings.GameplaySettings.LockIndicatorNoiseAmplitude * (1 - targetLock.Lock);
indicator.NoiseFrequency = Settings.GameplaySettings.LockIndicatorFrequency.Evaluate(targetLock.Lock);
spin.Speed = Settings.GameplaySettings.LockSpinSpeed.Evaluate(targetLock.Lock);

View file

@ -4,7 +4,7 @@ MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
executionOrder: -10
icon: {instanceID: 0}
userData:
assetBundleName:

View file

@ -28,7 +28,6 @@ public class GameSettings : ScriptableObject
public Color ArmorHitColor;
public Color HardpointHitColor;
public Color GearHitColor;
public Color ThermalHitColor;
public Gradient ArmorGradient;
public Gradient DurabilityGradient;
[HideInInspector] public Sprite[] ItemIcons;

View file

@ -19,6 +19,8 @@ public class InventoryMenu : MonoBehaviour
public ActionGameManager GameManager;
public RectTransform DragParent;
public ConfirmationDialog Dialog;
public ObservablePointerEnterTrigger BackgroundEntered;
public ObservablePointerExitTrigger BackgroundExited;
private int _currentPanel = -1;
@ -41,9 +43,31 @@ public class InventoryMenu : MonoBehaviour
private int2 _dragTargetPosition;
private int2 _lastDragPosition;
private bool _dragTargetValid;
private bool _destroyItem;
private void OnEnable()
{
BackgroundEntered.gameObject.SetActive(true);
BackgroundEntered.OnPointerEnterAsObservable().Subscribe(enter =>
{
_destroyItem = true;
});
BackgroundExited.OnPointerExitAsObservable().Subscribe(enter =>
{
_destroyItem = false;
});
var cargo = GameManager.DockingBay ?? GameManager.CurrentShip.CargoBays.FirstOrDefault();
if (cargo!=null)
InventoryPanels[0].Display(cargo);
InventoryPanels[1].Display(GameManager.CurrentShip);
}
private void OnDisable()
{
BackgroundEntered.gameObject.SetActive(false);
}
public InventoryPanel GetPanel => InventoryPanels[_currentPanel = (_currentPanel + 1) % InventoryPanels.Length];
void Start()
{
PropertiesPanel.Context = GameManager.ItemManager;
@ -150,6 +174,25 @@ public class InventoryMenu : MonoBehaviour
{
_dragItem.Rotation = _originalRotation;
}
if (_destroyItem)
{
if (data is InventoryCargoEventData cargoEvent)
{
cargoEvent.CargoBay.Remove(_dragItem);
}
else if (data is InventoryEntityEventData entityEvent)
{
if (entityEvent.Entity.Unequip(_originalEquippedItem) == null)
{
Dialog.Clear();
Dialog.Title.text = "Unable to destroy item!";
Dialog.AddProperty("Verify that cargo bays are empty before un-equipping them.");
Dialog.Show();
}
}
}
panel.IgnoreOccupancy = null;
panel.RefreshCells();
if(_dragTargetPanel!=panel)

View file

@ -5,6 +5,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UniRx.Triggers;
using UnityEngine;
public class MenuPanel : MonoBehaviour
@ -50,7 +51,7 @@ public class MenuPanel : MonoBehaviour
}
}
void Awake()
private void Awake()
{
foreach (var tabButton in TabButtons.GetComponentsInChildren<MenuTabButton>())
{
@ -59,8 +60,12 @@ public class MenuPanel : MonoBehaviour
_tabs.Add(tabButton.Tab, tabButton);
tabButton.Button.onClick.AddListener(() => ShowTab(tabButton.Tab));
}
ShowTab(MenuTab.Inventory);
}
// void Start()
// {
// ShowTab(MenuTab.Inventory);
// }
}
public enum MenuTab

View file

@ -269,30 +269,14 @@ public class SectorRenderer : MonoBehaviour
}
}
// Search all cells occupied by target cells for any thermal equipment
var equippedThermals = new List<EquippedItem>();
foreach (var hullCoord in hitShape.Coordinates)
{
if (entity.ThermalOccupancy[hullCoord.x, hullCoord.y] != null)
{
equippedThermals.Add(entity.ThermalOccupancy[hullCoord.x, hullCoord.y]);
}
}
float remainder = 0;
// Direct damage is divided between gear and thermal equipment (if present)
if (equippedGear != null && equippedThermals.Count > 0)
if (equippedGear != null)
{
remainder = max(directDamage / 2 - equippedGear.EquippableItem.Durability, 0);
equippedGear.EquippableItem.Durability = max(equippedGear.EquippableItem.Durability - directDamage / 2, 0);
entity.ItemDamage.OnNext((equippedGear, directDamage / 2));
foreach (var t in equippedThermals)
{
remainder += max(directDamage / (2 * equippedThermals.Count) - t.EquippableItem.Durability, 0);
t.EquippableItem.Durability = max(equippedGear.EquippableItem.Durability - directDamage / (2 * equippedThermals.Count), 0);
entity.ItemDamage.OnNext((t, directDamage / (2 * equippedThermals.Count)));
}
}
else if (equippedGear != null)
{
@ -300,15 +284,6 @@ public class SectorRenderer : MonoBehaviour
equippedGear.EquippableItem.Durability = max(equippedGear.EquippableItem.Durability - directDamage, 0);
entity.ItemDamage.OnNext((equippedGear, directDamage));
}
else if (equippedThermals.Count > 0)
{
foreach (var t in equippedThermals)
{
remainder += max(directDamage / (equippedThermals.Count) - t.EquippableItem.Durability, 0);
t.EquippableItem.Durability = max(equippedGear.EquippableItem.Durability - directDamage / equippedThermals.Count, 0);
entity.ItemDamage.OnNext((t, directDamage / equippedThermals.Count));
}
}
else remainder = directDamage;
// Direct damage remaining after all items are destroyed damages the hull
@ -331,8 +306,6 @@ public class SectorRenderer : MonoBehaviour
{
if (entity.GearOccupancy[hullCoord.x, hullCoord.y] != null)
surroundingEquipment.Add(entity.GearOccupancy[hullCoord.x, hullCoord.y]);
if (entity.ThermalOccupancy[hullCoord.x, hullCoord.y] != null)
surroundingEquipment.Add(entity.ThermalOccupancy[hullCoord.x, hullCoord.y]);
}
// Divide spread damage among all surrounding cells
@ -402,8 +375,7 @@ public class SectorRenderer : MonoBehaviour
var penetrationPoint = float2(hitCell);
var penetrationCell = hitCell;
while (hullData.Shape[penetrationCell] &&
entity.GearOccupancy[penetrationCell.x, penetrationCell.y] == null &&
entity.ThermalOccupancy[penetrationCell.x, penetrationCell.y] == null)
entity.GearOccupancy[penetrationCell.x, penetrationCell.y] == null)
{
penetrationPoint += penetrationVector * .5f;
penetrationCell = int2(penetrationPoint);

View file

@ -28,7 +28,7 @@ public abstract class Entity
public float2 Velocity;
public float[,] Temperature;
public float4[,] Conductivity;
public bool2[,] HullConductivity;
public float[,] ThermalMass;
public float Energy;
@ -58,7 +58,6 @@ public abstract class Entity
public List<IPopulationAssignment> PopulationAssignments = new List<IPopulationAssignment>();
public EquippedItem[,] GearOccupancy;
public EquippedItem[,] ThermalOccupancy;
public HardpointData[,] Hardpoints;
public float[,] Armor;
@ -123,7 +122,7 @@ public abstract class Entity
Equipment.Add(new EquippedItem(ItemManager, Hull, int2.zero, this));
Mass = hullData.Mass;
Temperature = new float[hullData.Shape.Width, hullData.Shape.Height];
Conductivity = new float4[hullData.Shape.Width, hullData.Shape.Height];
HullConductivity = new bool2[hullData.Shape.Width,hullData.Shape.Height];
ThermalMass = new float[hullData.Shape.Width, hullData.Shape.Height];
Armor = new float[hullData.Shape.Width, hullData.Shape.Height];
var cellCount = hullData.Shape.Coordinates.Length;
@ -132,11 +131,9 @@ public abstract class Entity
if (!hullData.InteriorCells[v])
Armor[v.x, v.y] = hullData.Armor;
Temperature[v.x, v.y] = 280;
Conductivity[v.x, v.y] = hullData.Conductivity;
ThermalMass[v.x, v.y] = hullData.Mass * hullData.SpecificHeat / cellCount;
}
GearOccupancy = new EquippedItem[hullData.Shape.Width, hullData.Shape.Height];
ThermalOccupancy = new EquippedItem[hullData.Shape.Width, hullData.Shape.Height];
Hardpoints = new HardpointData[hullData.Shape.Width, hullData.Shape.Height];
foreach (var hardpoint in hullData.Hardpoints)
{
@ -232,13 +229,11 @@ public abstract class Entity
var hullData = ItemManager.GetData(Hull) as HullData;
var itemData = ItemManager.GetData(item.EquippableItem);
var itemLayer = (itemData.HardpointType == HardpointType.Thermal ? ThermalOccupancy : GearOccupancy);
foreach (var i in hullData.Shape.Coordinates)
if (itemLayer[i.x, i.y] == item)
if (GearOccupancy[i.x, i.y] == item)
{
ThermalMass[i.x, i.y] -= ItemManager.GetThermalMass(item.EquippableItem) / itemData.Shape.Coordinates.Length;
Conductivity[i.x, i.y] /= itemData.Conductivity;
itemLayer[i.x, i.y] = null;
GearOccupancy[i.x, i.y] = null;
}
Mass -= itemData.Mass;
@ -252,7 +247,7 @@ public abstract class Entity
if (!hullData.Shape[hullCoord]) return false;
// Items without specific hardpoints on the ship can be freely rotated and placed anywhere
if (itemData.HardpointType == HardpointType.Tool || itemData.HardpointType == HardpointType.Thermal)
if (itemData.HardpointType == HardpointType.Tool)
{
// Check every cell of the item's shape
foreach (var i in itemData.Shape.Coordinates)
@ -261,7 +256,10 @@ public abstract class Entity
// If there's a hardpoint there, it won't fit
// Thermal items have their own layer and do not collide with gear
var itemCoord = hullCoord + itemData.Shape.Rotate(i, item.Rotation);
if (!hullData.InteriorCells[itemCoord] || (itemData.HardpointType == HardpointType.Tool && Hardpoints[itemCoord.x, itemCoord.y] != null) || (itemData.HardpointType == HardpointType.Thermal ? ThermalOccupancy : GearOccupancy)[itemCoord.x, itemCoord.y] != null) return false;
if (!hullData.InteriorCells[itemCoord] ||
itemData.HardpointType == HardpointType.Tool && Hardpoints[itemCoord.x, itemCoord.y] != null ||
GearOccupancy[itemCoord.x, itemCoord.y] != null)
return false;
}
}
else
@ -315,7 +313,7 @@ public abstract class Entity
// Tools and thermal equipment can be installed anywhere on the ship
// Search the whole ship for somewhere the item will fit
if (itemData.HardpointType == HardpointType.Tool || itemData.HardpointType == HardpointType.Thermal)
if (itemData.HardpointType == HardpointType.Tool)
{
foreach (var hullCoord2 in hullData.InteriorCells.Coordinates)
{
@ -364,7 +362,7 @@ public abstract class Entity
if (!ItemFits(itemData, hullData, item, hullCoord)) return false;
EquippedItem equippedItem;
if (itemData.HardpointType == HardpointType.Tool || itemData.HardpointType == HardpointType.Thermal)
if (itemData.HardpointType == HardpointType.Tool)
{
if(itemData is CargoBayData)
{
@ -396,8 +394,7 @@ public abstract class Entity
var occupiedCoord = hullCoord + itemData.Shape.Rotate(i, item.Rotation);
// TODO: Track thermal mass of cargo bay contents as reactive property
ThermalMass[occupiedCoord.x, occupiedCoord.y] += ItemManager.GetThermalMass(item) / itemData.Shape.Coordinates.Length;
Conductivity[occupiedCoord.x, occupiedCoord.y] *= itemData.Conductivity;
(itemData.HardpointType == HardpointType.Thermal ? ThermalOccupancy : GearOccupancy)[occupiedCoord.x, occupiedCoord.y] = equippedItem;
GearOccupancy[occupiedCoord.x, occupiedCoord.y] = equippedItem;
}
Mass += itemData.Mass;
@ -437,13 +434,13 @@ public abstract class Entity
return true;
}
public void AddChild(Entity entity)
private void AddChild(Entity entity)
{
Mass += entity.Mass;
Children.Add(entity);
}
public void RemoveChild(Entity entity)
private void RemoveChild(Entity entity)
{
Mass -= entity.Mass;
Children.Remove(entity);
@ -521,28 +518,43 @@ public abstract class Entity
var temp = Temperature[v.x, v.y];
var heatTransfer = 0f;
if (v.x > 0)
heatTransfer += (Temperature[v.x - 1, v.y] - temp) * Conductivity[v.x, v.y].y * Conductivity[v.x - 1, v.y].w;
if (hullData.Shape[int2(v.x - 1, v.y)])
heatTransfer += (Temperature[v.x - 1, v.y] - temp) *
(GearOccupancy[v.x, v.y]?.Conductivity ?? 1) *
(GearOccupancy[v.x - 1, v.y]?.Conductivity ?? 1) *
(HullConductivity[v.x - 1, v.y].x ? hullData.Conductivity : 1 / hullData.Conductivity);
if (hullData.Shape[int2(v.x + 1, v.y)])
heatTransfer += (Temperature[v.x + 1, v.y] - temp) *
(GearOccupancy[v.x, v.y]?.Conductivity ?? 1) *
(GearOccupancy[v.x + 1, v.y]?.Conductivity ?? 1) *
(HullConductivity[v.x, v.y].x ? hullData.Conductivity : 1 / hullData.Conductivity);
if (v.x < hullData.Shape.Width - 1)
heatTransfer += (Temperature[v.x + 1, v.y] - temp) * Conductivity[v.x, v.y].w * Conductivity[v.x + 1, v.y].y;
if (hullData.Shape[int2(v.x, v.y - 1)])
heatTransfer += (Temperature[v.x, v.y - 1] - temp) *
(GearOccupancy[v.x, v.y]?.Conductivity ?? 1) *
(GearOccupancy[v.x, v.y - 1]?.Conductivity ?? 1) *
(HullConductivity[v.x, v.y - 1].y ? hullData.Conductivity : 1 / hullData.Conductivity);
if (v.y > 0)
heatTransfer += (Temperature[v.x, v.y - 1] - temp) * Conductivity[v.x, v.y].z * Conductivity[v.x, v.y - 1].x;
if (v.y < hullData.Shape.Height - 1)
heatTransfer += (Temperature[v.x, v.y + 1] - temp) * Conductivity[v.x, v.y].x * Conductivity[v.x, v.y + 1].z;
if (hullData.Shape[int2(v.x, v.y + 1)])
heatTransfer += (Temperature[v.x, v.y + 1] - temp) *
(GearOccupancy[v.x, v.y]?.Conductivity ?? 1) *
(GearOccupancy[v.x, v.y + 1]?.Conductivity ?? 1) *
(HullConductivity[v.x, v.y].y ? hullData.Conductivity : 1 / hullData.Conductivity);
newTemp[v.x, v.y] = Temperature[v.x, v.y] + heatTransfer * min(ItemManager.GameplaySettings.HeatConductionMultiplier * delta,1) / ThermalMass[v.x,v.y];
// For all cells on the border of the entity, radiate some heat into space, increasing the visibility of the ship
if (!hullData.InteriorCells[v])
if (Parent==null && !hullData.InteriorCells[v])
{
var rad = pow(newTemp[v.x, v.y], ItemManager.GameplaySettings.HeatRadiationExponent) *
ItemManager.GameplaySettings.HeatRadiationMultiplier;
newTemp[v.x, v.y] -= rad * delta;
radiation += rad;
}
if(float.IsNaN(newTemp[v.x, v.y]) || newTemp[v.x, v.y] < 0)
ItemManager.Log("HOUSTON, WE HAVE A PROBLEM!");
}
VisibilitySources[this] = radiation;
@ -608,19 +620,18 @@ public abstract class Entity
// }
}
[MessagePackObject, JsonObject(MemberSerialization.OptIn)]
public class EquippedItem
{
[JsonProperty("item"), Key(0)] public EquippableItem EquippableItem;
public EquippableItem EquippableItem;
[JsonProperty("position"), Key(1)] public int2 Position;
public int2 Position;
[IgnoreMember]
public IBehavior[] Behaviors;
[IgnoreMember]
public BehaviorGroup[] BehaviorGroups;
public float Conductivity { get; }
public Shape InsetShape { get; }
public int SortPosition;
@ -648,6 +659,7 @@ public class EquippedItem
_entity = entity;
EquippableItem = item;
Position = position;
Conductivity = _data.Conductivity;
var hullData = itemManager.GetData(entity.Hull);
InsetShape = hullData.Shape.Inset(_data.Shape, position, item.Rotation);
@ -689,8 +701,8 @@ public class EquippedItem
EquippableItem.Durability -= delta;
}
foreach (var behavior in Behaviors.Where(b => b is IAlwaysUpdatedBehavior).Cast<IAlwaysUpdatedBehavior>())
behavior.Update(delta);
foreach (var behavior in Behaviors)//.Where(b => b is IAlwaysUpdatedBehavior).Cast<IAlwaysUpdatedBehavior>())
if(behavior is IAlwaysUpdatedBehavior alwaysUpdatedBehavior) alwaysUpdatedBehavior.Update(delta);
if (Online)
{

View file

@ -83,21 +83,21 @@ public enum MegaPlacementType
public enum SimpleCommodityCategory
{
Minerals,
Metals,
Alloys,
Compounds,
Organics,
Ammo,
Consumer
Minerals = 0,
Metals = 1,
Alloys = 2,
Compounds = 3,
Organics = 4,
Ammo = 5,
Consumer = 6
}
public enum CompoundCommodityCategory
{
Wearables,
Consumables,
Luxuries,
Tools,
Manufacturing,
Assemblies
Wearables = 0,
Consumables = 1,
Luxuries = 2,
Tools = 3,
Manufacturing = 4,
Assemblies = 5
}

View file

@ -192,20 +192,26 @@ public abstract class ItemData : DatabaseEntry, INamedEntry
[InspectableText, JsonProperty("description"), Key(2)]
public string Description;
[InspectableText, JsonProperty("manufacturer"), Key(3)]
public string Manufacturer;
[InspectableField, JsonProperty("mass"), Key(3)]
[InspectableField, JsonProperty("mass"), Key(4)]
public float Mass;
[InspectableField, JsonProperty("shape"), Key(4)]
[InspectableField, JsonProperty("shape"), Key(5)]
public Shape Shape;
// Heat needed to change temperature of 1 gram by 1 degree
[InspectableField, JsonProperty("specificHeat"), Key(5)]
[InspectableField, JsonProperty("specificHeat"), Key(6)]
public float SpecificHeat = 1;
[InspectableField, JsonProperty("conductivity"), Key(6)]
[InspectableField, JsonProperty("conductivity"), Key(7)]
public float Conductivity = 1;
[InspectableField, JsonProperty("price"), Key(8)]
public int Price = 0;
[IgnoreMember] public string EntryName
{
get => Name;
@ -233,10 +239,10 @@ public class SimpleCommodityData : ItemData
// [InspectableField, JsonProperty("floor"), Key(11)]
// public float Floor = 5f;
[InspectableField, JsonProperty("maxStackSize"), Key(7)]
[InspectableField, JsonProperty("maxStackSize"), Key(9)]
public int MaxStack = 10;
[InspectableField, JsonProperty("category"), Key(8)]
[InspectableField, JsonProperty("category"), Key(10)]
public SimpleCommodityCategory Category;
}
@ -248,17 +254,17 @@ public class SimpleCommodityData : ItemData
JsonConverter(typeof(JsonKnownTypesConverter<CraftedItemData>))]
public abstract class CraftedItemData : ItemData
{
[InspectableField, JsonProperty("ingredientQualityWeight"), Key(7)]
[InspectableField, JsonProperty("ingredientQualityWeight"), Key(9)]
public float IngredientQualityWeight = .5f;
}
[RethinkTable("Items"), Inspectable, MessagePackObject]
public class CompoundCommodityData : CraftedItemData
{
[InspectableDatabaseLink(typeof(PersonalityAttribute)), JsonProperty("demandProfile"), Key(8)]
[InspectableDatabaseLink(typeof(PersonalityAttribute)), JsonProperty("demandProfile"), Key(10)]
public Dictionary<Guid, float> DemandProfile = new Dictionary<Guid, float>();
[InspectableField, JsonProperty("category"), Key(9)]
[InspectableField, JsonProperty("category"), Key(11)]
public CompoundCommodityCategory Category;
}
@ -267,22 +273,22 @@ public class CompoundCommodityData : CraftedItemData
JsonObject(MemberSerialization.OptIn), JsonConverter(typeof(JsonKnownTypesConverter<EquippableItemData>))]
public abstract class EquippableItemData : CraftedItemData
{
[InspectableTexture, JsonProperty("schematic"), Key(8)]
[InspectableTexture, JsonProperty("schematic"), Key(10)]
public string Schematic;
[InspectableField, JsonProperty("behaviors"), Key(9)]
[InspectableField, JsonProperty("behaviors"), Key(11)]
public List<BehaviorData> Behaviors = new List<BehaviorData>();
[InspectableField, JsonProperty("durability"), Key(10)]
[InspectableField, JsonProperty("durability"), Key(12)]
public float Durability;
[TemperatureInspectable, JsonProperty("minTemp"), Key(11)]
[TemperatureInspectable, JsonProperty("minTemp"), Key(13)]
public float MinimumTemperature;
[TemperatureInspectable, JsonProperty("maxTemp"), Key(12)]
[TemperatureInspectable, JsonProperty("maxTemp"), Key(14)]
public float MaximumTemperature;
[InspectableField, JsonProperty("durabilityExponent"), Key(13), SimplePerformanceStat]
[InspectableField, JsonProperty("durabilityExponent"), Key(15), SimplePerformanceStat]
public PerformanceStat DurabilityExponent = new PerformanceStat();
[IgnoreMember]
@ -296,7 +302,7 @@ public abstract class EquippableItemData : CraftedItemData
[RethinkTable("Items"), Inspectable, MessagePackObject, JsonObject(MemberSerialization.OptIn)]
public class GearData : EquippableItemData
{
[InspectableField, JsonProperty("hardpointType"), Key(14)]
[InspectableField, JsonProperty("hardpointType"), Key(16)]
public HardpointType Hardpoint;
[IgnoreMember] public override HardpointType HardpointType => Hardpoint;
@ -305,7 +311,7 @@ public class GearData : EquippableItemData
[RethinkTable("Items"), Inspectable, MessagePackObject, JsonObject(MemberSerialization.OptIn)]
public class CargoBayData : EquippableItemData
{
[InspectableField, JsonProperty("interiorShape"), Key(14)]
[InspectableField, JsonProperty("interiorShape"), Key(16)]
public Shape InteriorShape;
[IgnoreMember] public override HardpointType HardpointType => HardpointType.Tool;
}
@ -313,7 +319,7 @@ public class CargoBayData : EquippableItemData
[RethinkTable("Items"), Inspectable, MessagePackObject, JsonObject(MemberSerialization.OptIn)]
public class DockingBayData : CargoBayData
{
[InspectableField, JsonProperty("maxSize"), Key(15)]
[InspectableField, JsonProperty("maxSize"), Key(17)]
public int2 MaxSize;
[IgnoreMember] public override HardpointType HardpointType => HardpointType.Tool;
}
@ -321,19 +327,19 @@ public class DockingBayData : CargoBayData
[RethinkTable("Items"), Inspectable, MessagePackObject, JsonObject(MemberSerialization.OptIn)]
public class HullData : EquippableItemData
{
[InspectableField, JsonProperty("hardpoints"), Key(14)]
[InspectableField, JsonProperty("hardpoints"), Key(16)]
public List<HardpointData> Hardpoints = new List<HardpointData>();
[InspectablePrefab, JsonProperty("prefab"), Key(15)]
[InspectablePrefab, JsonProperty("prefab"), Key(17)]
public string Prefab;
[InspectableField, JsonProperty("hullType"), Key(16)]
[InspectableField, JsonProperty("hullType"), Key(18)]
public HullType HullType;
[InspectableField, JsonProperty("gridOffset"), Key(17)]
[InspectableField, JsonProperty("gridOffset"), Key(19)]
public float GridOffset;
[InspectableField, JsonProperty("armor"), Key(18)]
[InspectableField, JsonProperty("armor"), Key(20)]
public float Armor;
[IgnoreMember]

View file

@ -213,10 +213,15 @@ public class ItemManager
return ItemQuality[item];
}
private readonly Dictionary<(PerformanceStat stat, EquippableItem item), float> StatQuality = new Dictionary<(PerformanceStat stat, EquippableItem item), float>();
// Determine quality of either the item itself or the specific ingredient this stat depends on
public float Quality(PerformanceStat stat, EquippableItem item)
{
if (StatQuality.ContainsKey((stat, item)))
return StatQuality[(stat, item)];
var itemData = GetData(item);
var blueprint = ItemData.Get<BlueprintData>(item.Blueprint);
var activeEffects = blueprint.StatEffects.Where(x => GetAffectedStat(blueprint, x) == stat).ToArray();
@ -244,6 +249,7 @@ public class ItemManager
quality = sum / ingredients.Length;
}
StatQuality[(stat, item)] = quality;
return quality;
}
@ -268,11 +274,13 @@ public class ItemManager
//var heat = !stat.HeatDependent ? 1 : pow(itemData.Performance(entity.Temperature), Evaluate(itemData.HeatExponent,item));
var durability = !stat.DurabilityDependent ? 1 : pow(item.Durability / itemData.Durability, Evaluate(itemData.DurabilityExponent,item));
var quality = pow(Quality(stat, item), stat.QualityExponent);
var scaleModifier = stat.GetScaleModifiers(entity).Values.Aggregate(1.0f, (current, mod) => current * mod);
var constantModifier = stat.GetConstantModifiers(entity).Values.Sum();
var scaleModifier = 1.0f;
foreach (var value in stat.GetScaleModifiers(entity).Values) scaleModifier = scaleModifier * value;
float constantModifier = 0;
foreach (var value in stat.GetConstantModifiers(entity).Values) constantModifier += value;
var result = lerp(stat.Min, stat.Max, durability * quality) * scaleModifier + constantModifier;
if (float.IsNaN(result))
return stat.Min;

View file

@ -23,6 +23,8 @@ public class TradeMenu : MonoBehaviour
private EquippedCargoBay _targetCargo;
private (ItemFilter filter, HardpointType type) _hardpointFilter;
private (ItemFilter filter, SimpleCommodityCategory type) _commodityFilter;
private (ItemFilter filter, CompoundCommodityCategory type) _compoundCommodityFilter;
private List<(ItemFilter filter, Type type)> _behaviorFilters = new List<(ItemFilter filter, Type type)>();
private void OnEnable()
@ -40,7 +42,16 @@ public class TradeMenu : MonoBehaviour
IEnumerable<HardpointType> hardpointTypes = (HardpointType[]) Enum.GetValues(typeof(HardpointType));
if (_hardpointFilter.filter != null)
hardpointTypes = hardpointTypes.Where(x => x != _hardpointFilter.type);
ContextMenu.AddDropdown("Item Type", hardpointTypes
IEnumerable<SimpleCommodityCategory> commodityTypes = (SimpleCommodityCategory[]) Enum.GetValues(typeof(SimpleCommodityCategory));
if (_commodityFilter.filter != null)
commodityTypes = commodityTypes.Where(x => x != _commodityFilter.type);
IEnumerable<CompoundCommodityCategory> compoundCommodityTypes = (CompoundCommodityCategory[]) Enum.GetValues(typeof(CompoundCommodityCategory));
if (_compoundCommodityFilter.filter != null)
compoundCommodityTypes = compoundCommodityTypes.Where(x => x != _compoundCommodityFilter.type);
ContextMenu.AddDropdown("Gear Type", hardpointTypes
.Select<HardpointType, (string, Action, bool)>(x => (Enum.GetName(typeof(HardpointType), x), () =>
{
if (_hardpointFilter.filter == null)
@ -52,11 +63,75 @@ public class TradeMenu : MonoBehaviour
Populate();
};
}
if(_commodityFilter.filter != null)
{
_commodityFilter.filter.GetComponent<Prototype>().ReturnToPool();
_commodityFilter.filter = null;
}
if(_compoundCommodityFilter.filter != null)
{
_compoundCommodityFilter.filter.GetComponent<Prototype>().ReturnToPool();
_compoundCommodityFilter.filter = null;
}
_hardpointFilter.filter.Label.text = $"Hardpoint: {Enum.GetName(typeof(HardpointType), x)}";
_hardpointFilter.type = x;
Populate();
}, true)));
ContextMenu.AddDropdown("Simple Commodity", commodityTypes
.Select<SimpleCommodityCategory, (string, Action, bool)>(x => (Enum.GetName(typeof(SimpleCommodityCategory), x), () =>
{
if (_commodityFilter.filter == null)
{
_commodityFilter.filter = FilterPrototype.Instantiate<ItemFilter>();
_commodityFilter.filter.OnDisable += () =>
{
_commodityFilter.filter = null;
Populate();
};
}
if(_hardpointFilter.filter != null)
{
_hardpointFilter.filter.GetComponent<Prototype>().ReturnToPool();
_hardpointFilter.filter = null;
}
if(_compoundCommodityFilter.filter != null)
{
_compoundCommodityFilter.filter.GetComponent<Prototype>().ReturnToPool();
_compoundCommodityFilter.filter = null;
}
_commodityFilter.filter.Label.text = $"Hardpoint: {Enum.GetName(typeof(SimpleCommodityCategory), x)}";
_commodityFilter.type = x;
Populate();
}, true)));
ContextMenu.AddDropdown("Compound Commodity", compoundCommodityTypes
.Select<CompoundCommodityCategory, (string, Action, bool)>(x => (Enum.GetName(typeof(CompoundCommodityCategory), x), () =>
{
if (_compoundCommodityFilter.filter == null)
{
_compoundCommodityFilter.filter = FilterPrototype.Instantiate<ItemFilter>();
_compoundCommodityFilter.filter.OnDisable += () =>
{
_compoundCommodityFilter.filter = null;
Populate();
};
}
if(_hardpointFilter.filter != null)
{
_hardpointFilter.filter.GetComponent<Prototype>().ReturnToPool();
_hardpointFilter.filter = null;
}
if(_commodityFilter.filter != null)
{
_commodityFilter.filter.GetComponent<Prototype>().ReturnToPool();
_commodityFilter.filter = null;
}
_compoundCommodityFilter.filter.Label.text = $"Hardpoint: {Enum.GetName(typeof(CompoundCommodityCategory), x)}";
_compoundCommodityFilter.type = x;
Populate();
}, true)));
ContextMenu.AddDropdown("Item Behavior", typeof(BehaviorData).GetAllChildClasses()
.Where(x=> x.GetCustomAttribute<RuntimeInspectable>() != null && _behaviorFilters.All(f => f.type != x))
.Select<Type, (string, Action, bool)>(x=> (x.Name.FormatTypeName(), () =>
@ -94,23 +169,46 @@ public class TradeMenu : MonoBehaviour
void Populate()
{
var columns = new List<(string name, int size, Func<EquippableItemData, Func<string>> output, Func<EquippableItemData, IComparable> sortKey)>();
var columns = new List<(string name, int size, Func<ItemData, Func<string>> output, Func<ItemData, IComparable> sortKey)>();
columns.Add(("Name", 3,
data => () => data.Name,
data => data.Name));
if(_hardpointFilter.filter==null)
columns.Add(("Type", 2,
data => () => Enum.GetName(typeof(HardpointType), data.HardpointType),
data => data.HardpointType));
data => () =>
{
if (data is SimpleCommodityData s)
return Enum.GetName(typeof(SimpleCommodityCategory), s.Category);
if(data is CompoundCommodityData c)
return Enum.GetName(typeof(CompoundCommodityCategory), c.Category);
if(data is EquippableItemData e)
return Enum.GetName(typeof(HardpointType), e.HardpointType);
return "None";
},
data =>
{
if (data is SimpleCommodityData s)
return (int) s.Category;
var offset = Enum.GetValues(typeof(SimpleCommodityCategory)).Length;
if(data is CompoundCommodityData c)
return (int) c.Category + offset;
offset += Enum.GetValues(typeof(CompoundCommodityCategory)).Length;
if(data is EquippableItemData e)
return (int) e.HardpointType + offset;
return 0;
}));
columns.Add(("Mass", 1,
data => () => data.Mass.SignificantDigits(3),
data => data.Mass));
columns.Add(("Price", 1,
data => () => data.Price.ToString(),
data => data.Price));
columns.Add(("Size", 1,
data => () => $"{data.Shape.Width}x{data.Shape.Height}",
data => data.Shape.Width*data.Shape.Height));
var items = GameManager.ItemManager.ItemData.GetAll<EquippableItemData>();
var items = GameManager.ItemManager.ItemData.GetAll<ItemData>().Where(i=>i.Price!=0);
if (MinimumSizeFilter.gameObject.activeSelf)
items = items.Where(i =>
@ -122,12 +220,18 @@ public class TradeMenu : MonoBehaviour
!(MaximumSizeFilter.Width.text.Length > 0 && i.Shape.Width > int.Parse(MaximumSizeFilter.Width.text) ||
MaximumSizeFilter.Height.text.Length > 0 && i.Shape.Height > int.Parse(MaximumSizeFilter.Height.text)));
if(_commodityFilter.filter != null)
items = items.Where(i => i is SimpleCommodityData s && s.Category == _commodityFilter.type);
if(_compoundCommodityFilter.filter != null)
items = items.Where(i => i is CompoundCommodityData c && c.Category == _compoundCommodityFilter.type);
if (_hardpointFilter.filter != null)
items = items.Where(i => i.HardpointType == _hardpointFilter.type);
items = items.Where(i => i is EquippableItemData e && e.HardpointType == _hardpointFilter.type);
foreach (var (_, type) in _behaviorFilters)
{
items = items.Where(i => i.Behaviors.Any(b => type.IsInstanceOfType(b)));
items = items.Where(i => i is EquippableItemData e && e.Behaviors.Any(b => type.IsInstanceOfType(b)));
foreach (var field in type.GetFields().Where(f => f.GetCustomAttribute<RuntimeInspectable>() != null))
{
@ -135,32 +239,32 @@ public class TradeMenu : MonoBehaviour
if (fieldType == typeof(float))
columns.Add((field.Name, 1, data =>
{
var behavior = data.Behaviors.FirstOrDefault(b => type.IsInstanceOfType(b));
var behavior = ((EquippableItemData) data).Behaviors.FirstOrDefault(b => type.IsInstanceOfType(b));
return () => ((float) field.GetValue(behavior)).SignificantDigits(3);
}, data =>
{
var behavior = data.Behaviors.FirstOrDefault(b => type.IsInstanceOfType(b));
var behavior = ((EquippableItemData) data).Behaviors.FirstOrDefault(b => type.IsInstanceOfType(b));
return (float) field.GetValue(behavior);
}));
else if (fieldType == typeof(int))
columns.Add((field.Name, 1, data =>
{
var behavior = data.Behaviors.FirstOrDefault(b => type.IsInstanceOfType(b));
var behavior = ((EquippableItemData) data).Behaviors.FirstOrDefault(b => type.IsInstanceOfType(b));
return () => ((int) field.GetValue(behavior)).ToString();
}, data =>
{
var behavior = data.Behaviors.FirstOrDefault(b => type.IsInstanceOfType(b));
var behavior = ((EquippableItemData) data).Behaviors.FirstOrDefault(b => type.IsInstanceOfType(b));
return (int) field.GetValue(behavior);
}));
else if (fieldType == typeof(PerformanceStat))
{
columns.Add((field.Name, 1, data =>
{
var behavior = data.Behaviors.FirstOrDefault(b => type.IsInstanceOfType(b));
var behavior = ((EquippableItemData) data).Behaviors.FirstOrDefault(b => type.IsInstanceOfType(b));
return () => ((PerformanceStat) field.GetValue(behavior)).Max.SignificantDigits(3);
}, data =>
{
var behavior = data.Behaviors.FirstOrDefault(b => type.IsInstanceOfType(b));
var behavior = ((EquippableItemData) data).Behaviors.FirstOrDefault(b => type.IsInstanceOfType(b));
return ((PerformanceStat) field.GetValue(behavior)).Max;
}));
}
@ -168,8 +272,22 @@ public class TradeMenu : MonoBehaviour
}
columns.Add(("Owned", 1,
data => () => (_targetCargo.ItemsOfType.ContainsKey(data.ID) ? _targetCargo.ItemsOfType[data.ID].Count : 0).ToString(),
data => _targetCargo.ItemsOfType.ContainsKey(data.ID) ? _targetCargo.ItemsOfType[data.ID].Count : 0));
data => () =>
{
if (data is HullData)
return GameManager.PlayerShips.Count(s => s.Hull.Data == data.ID && s.Parent == GameManager.CurrentShip.Parent).ToString();
if(data is SimpleCommodityData)
return (_targetCargo.ItemsOfType.ContainsKey(data.ID) ? _targetCargo.ItemsOfType[data.ID].Cast<SimpleCommodity>().Sum(s=>s.Quantity) : 0).ToString();
return (_targetCargo.ItemsOfType.ContainsKey(data.ID) ? _targetCargo.ItemsOfType[data.ID].Count : 0).ToString();
},
data =>
{
if (data is HullData)
return GameManager.PlayerShips.Count(s => s.Hull.Data == data.ID && s.Parent == GameManager.CurrentShip.Parent);
if(data is SimpleCommodityData)
return _targetCargo.ItemsOfType.ContainsKey(data.ID) ? _targetCargo.ItemsOfType[data.ID].Cast<SimpleCommodity>().Sum(s=>s.Quantity) : 0;
return _targetCargo.ItemsOfType.ContainsKey(data.ID) ? _targetCargo.ItemsOfType[data.ID].Count : 0;
}));
Spreadsheet.ShowData(
columns.Select(x => x.name).ToArray(),
@ -188,7 +306,16 @@ public class TradeMenu : MonoBehaviour
},
OnDoubleClick = () =>
{
_targetCargo.TryStore(GameManager.ItemManager.CreateInstance(i, .1f, 1));
if (i is HullData h)
{
var ship = new Ship(GameManager.ItemManager, GameManager.Zone, GameManager.ItemManager.CreateInstance(h, .1f, 1) as EquippableItem);
ship.SetParent(GameManager.CurrentShip.Parent);
GameManager.PlayerShips.Add(ship);
}
else if(i is CraftedItemData c)
_targetCargo.TryStore(GameManager.ItemManager.CreateInstance(c, .1f, 1));
else if(i is SimpleCommodityData s)
_targetCargo.TryStore(GameManager.ItemManager.CreateInstance(s, 1));
Populate();
}
}));

View file

@ -25,9 +25,13 @@ public class InventoryPanel : MonoBehaviour
public ContextMenu ContextMenu;
public TextMeshProUGUI Title;
public Button Dropdown;
public Button Current;
public Button Thermal;
public GridLayoutGroup Grid;
public Sprite[] NodeBackgroundTextures;
public Sprite[] NodeTextures;
public Sprite[] ThermalTextures;
public float ThermalToggleRegionSize = .2f;
public Prototype NodePrototype;
public RawImage TemperatureDisplay;
public Texture2D TemperatureColor;
@ -36,6 +40,8 @@ public class InventoryPanel : MonoBehaviour
public float MaxTemperature;
public bool FitToContent;
public float CellHitPulseTime;
public Color ToggleEnabledColor;
public Color ToggleDisabledColor;
public Color CellBackgroundColor = new Color(0, 0, 0, .75f);
Subject<InventoryEventData> _onBeginDrag;
@ -60,6 +66,7 @@ public class InventoryPanel : MonoBehaviour
private List<IDisposable> _subscriptions = new List<IDisposable>();
private Dictionary<int2, int> _cellAnimationSequence = new Dictionary<int2, int>();
private int _hitSequence = 0;
private bool _thermal = false;
private bool _hud;
@ -76,6 +83,26 @@ public class InventoryPanel : MonoBehaviour
private void Start()
{
if (Thermal)
{
Thermal.onClick.AddListener(() =>
{
Display(_displayedEntity, false, !_thermal);
});
}
if (Current)
{
Current.onClick.AddListener(() =>
{
if (_displayedEntity != GameManager.CurrentShip)
{
GameManager.CurrentShip = (Ship) _displayedEntity;
GameManager.DockingBay.DockedShip = (Ship) _displayedEntity;
Current.targetGraphic.color = ToggleEnabledColor;
}
});
}
if(Dropdown)
{
Dropdown.onClick.AddListener(() =>
@ -85,16 +112,17 @@ public class InventoryPanel : MonoBehaviour
{
if (ship.CargoBays.Any())
{
ContextMenu.AddDropdown(ship.Name,
ship.CargoBays
.Select<EquippedCargoBay, (string text, Action action, bool enabled)>((bay, index) =>
($"Bay {index}", () => Display(bay), true))
.Prepend(("Equipment", () => Display(ship), true)));
var options = ship.CargoBays
.Where(bay => bay != _displayedCargo)
.Select<EquippedCargoBay, (string text, Action action, bool enabled)>((bay, index) =>
($"Bay {index}", () => Display(bay), true));
if(ship != _displayedEntity) options = options.Prepend(("Equipment", () => Display(ship), true));
ContextMenu.AddDropdown(ship.Name, options);
}
else ContextMenu.AddOption(ship.Name, () => Display(ship));
else if(ship != _displayedEntity) ContextMenu.AddOption(ship.Name, () => Display(ship));
}
if(GameManager.DockingBay!=null)
if(GameManager.DockingBay!=null && _displayedCargo!=GameManager.DockingBay)
ContextMenu.AddOption(GameManager.DockingBay.Name, () => Display(GameManager.DockingBay));
ContextMenu.Show();
@ -131,6 +159,7 @@ public class InventoryPanel : MonoBehaviour
{
Clear();
}
public void Clear()
{
@ -150,28 +179,34 @@ public class InventoryPanel : MonoBehaviour
_subscriptions.Clear();
TemperatureDisplay.gameObject.SetActive(false);
if(Title)
Title.text = "None";
}
public void Display(Entity entity, bool hud = false)
public void Display(Entity entity, bool hud = false, bool thermal = false)
{
Clear();
_thermal = thermal;
_hud = hud;
_displayedEntity = entity;
_displayedCargo = null;
_firstRect = null;
if(Title)
Title.text = entity.Name;
var hullData = GameManager.ItemManager.GetData(entity.Hull) as HullData;
if (FitToContent)
{
var gridRect = Grid.GetComponent<RectTransform>();
var rect = gridRect.rect;
Grid.cellSize = Vector2.one * (int) min(rect.width / (hullData.Shape.Width + 1), rect.height / (hullData.Shape.Height + 1));
}
_temperatureTexture = new Texture2D(
hullData.Shape.Width+2,
hullData.Shape.Height+2,
@ -181,9 +216,18 @@ public class InventoryPanel : MonoBehaviour
TemperatureDisplay.texture = _temperatureTexture;
var tempRect = TemperatureDisplay.rectTransform;
tempRect.sizeDelta = Grid.cellSize * new Vector2(hullData.Shape.Width + 2, hullData.Shape.Height + 2);
//tempRect.anchoredPosition =
//FakeOccupancy = new Shape(hullData.Shape.Width, hullData.Shape.Height);
//IgnoreOccupancy = new Shape(hullData.Shape.Width, hullData.Shape.Height);
if (Current)
{
Current.gameObject.SetActive(true);
Current.targetGraphic.color = entity == GameManager.CurrentShip ? ToggleEnabledColor : ToggleDisabledColor;
}
if (Thermal)
{
Thermal.gameObject.SetActive(true);
Thermal.targetGraphic.color = thermal ? ToggleEnabledColor : ToggleDisabledColor;
}
Grid.constraintCount = hullData.Shape.Width;
foreach (var v in hullData.Shape.AllCoordinates)
{
@ -201,18 +245,50 @@ public class InventoryPanel : MonoBehaviour
cell.Background.color = CellBackgroundColor;
if (!_firstRect)
_firstRect = cell.GetComponent<RectTransform>();
cell.PointerClickTrigger.OnPointerClickAsObservable()
.Subscribe(data => _onClick?.OnNext(new InventoryEntityEventData(data, v, entity)));
cell.BeginDragTrigger.OnBeginDragAsObservable()
.Subscribe(data => _onBeginDrag?.OnNext(new InventoryEntityEventData(data, v, entity)));
cell.DragTrigger.OnDragAsObservable()
.Subscribe(data => _onDrag?.OnNext(new InventoryEntityEventData(data, v, entity)));
cell.EndDragTrigger.OnEndDragAsObservable()
.Subscribe(data => _onEndDrag?.OnNext(new InventoryEntityEventData(data, v, entity)));
cell.PointerEnterTrigger.OnPointerEnterAsObservable()
.Subscribe(data => _onPointerEnter?.OnNext(new InventoryEntityEventData(data, v, entity)));
cell.PointerExitTrigger.OnPointerExitAsObservable()
.Subscribe(data => _onPointerExit?.OnNext(new InventoryEntityEventData(data, v, entity)));
if (!thermal)
{
cell.PointerClickTrigger.OnPointerClickAsObservable()
.Subscribe(data => _onClick?.OnNext(new InventoryEntityEventData(data, v, entity)));
cell.BeginDragTrigger.OnBeginDragAsObservable()
.Subscribe(data => _onBeginDrag?.OnNext(new InventoryEntityEventData(data, v, entity)));
cell.DragTrigger.OnDragAsObservable()
.Subscribe(data => _onDrag?.OnNext(new InventoryEntityEventData(data, v, entity)));
cell.EndDragTrigger.OnEndDragAsObservable()
.Subscribe(data => _onEndDrag?.OnNext(new InventoryEntityEventData(data, v, entity)));
cell.PointerEnterTrigger.OnPointerEnterAsObservable()
.Subscribe(data => _onPointerEnter?.OnNext(new InventoryEntityEventData(data, v, entity)));
cell.PointerExitTrigger.OnPointerExitAsObservable()
.Subscribe(data => _onPointerExit?.OnNext(new InventoryEntityEventData(data, v, entity)));
}
else
{
cell.PointerClickTrigger.OnPointerClickAsObservable().Subscribe(data =>
{
var rect = cell.GetComponent<RectTransform>();
var point = Rect.PointToNormalized(rect.rect, rect.InverseTransformPoint(data.position));
Debug.Log($"Clicked at pos {data.position}, normalized {point}");
if (hullData.Shape[int2(v.x - 1, v.y)] && point.x < ThermalToggleRegionSize)
{
entity.HullConductivity[v.x - 1, v.y].x = !entity.HullConductivity[v.x - 1, v.y].x;
RefreshCells(new []{v,int2(v.x - 1, v.y)});
}
if (hullData.Shape[int2(v.x + 1, v.y)] && point.x > 1 - ThermalToggleRegionSize)
{
entity.HullConductivity[v.x, v.y].x = !entity.HullConductivity[v.x, v.y].x;
RefreshCells(new []{v,int2(v.x + 1, v.y)});
}
if (hullData.Shape[int2(v.x, v.y - 1)] && point.y < ThermalToggleRegionSize)
{
entity.HullConductivity[v.x, v.y - 1].y = !entity.HullConductivity[v.x, v.y - 1].y;
RefreshCells(new []{v,int2(v.x, v.y - 1)});
}
if (hullData.Shape[int2(v.x, v.y + 1)] && point.y > 1 - ThermalToggleRegionSize)
{
entity.HullConductivity[v.x, v.y].y = !entity.HullConductivity[v.x, v.y].y;
RefreshCells(new []{v,int2(v.x, v.y + 1)});
}
});
}
CellInstances.Add(v, cell);
}
}
@ -255,7 +331,6 @@ public class InventoryPanel : MonoBehaviour
HitType.Armor => Settings.ArmorHitColor,
HitType.Hardpoint => Settings.HardpointHitColor,
HitType.Gear => Settings.GearHitColor,
HitType.Thermal => Settings.ThermalHitColor,
_ => Color.white
};
float startTime = Time.time;
@ -276,7 +351,13 @@ public class InventoryPanel : MonoBehaviour
Clear();
_displayedCargo = cargo;
_displayedEntity = null;
TemperatureDisplay.gameObject.SetActive(false);
if (Current)
Current.gameObject.SetActive(false);
if (Thermal)
Thermal.gameObject.SetActive(false);
if(Title)
Title.text = cargo.Name;
@ -372,9 +453,30 @@ public class InventoryPanel : MonoBehaviour
if (item != null)
spriteIndex += 1 << 8;
if (_thermal)
{
bool ThermalMatch(int2 offset)
{
if (!hullData.Shape[v + offset]) return false;
var i = (offset.x, offset.y);
return i switch
{
(1, 0) => _displayedEntity.HullConductivity[v.x, v.y].x,
(-1, 0) => _displayedEntity.HullConductivity[v.x-1, v.y].x,
(0, 1) => _displayedEntity.HullConductivity[v.x, v.y].y,
(0, -1) => _displayedEntity.HullConductivity[v.x, v.y-1].y,
_ => false
};
}
spriteIndex = 0;
for(int i = 0; i < 4; i++)
if (ThermalMatch(_offsets[i]))
spriteIndex += 1 << i;
}
CellInstances[v].Background.sprite = NodeBackgroundTextures[bgSpriteIndex];
CellInstances[v].Icon.sprite = NodeTextures[spriteIndex];
CellInstances[v].Icon.sprite = _thermal ? ThermalTextures[spriteIndex] : NodeTextures[spriteIndex];
CellInstances[v].Icon.color = GetColor(v);
}
}