AetherDriveData and AetherDrive, Union(12) (now a retired-do-not-reuse comment, as 26 is), HardpointType.AetherDrive (last member, nothing shifts), Ship's drive sets, aggregates and Axis write, the five request-field rows, GameplaySettings Aether multipliers, ShipInstance's drive particles, SchematicDisplay's RPM display and AetherDriveUi, the undock refusal's drive clause, the drive prefab and material, and AetherDb's drive roles and brownout row. The design is kept at parked/aether-drive. Adds EveryShippedShipHullHasATopSpeed. ARPG.unity still holds stale serialized references to the removed SchematicDisplay fields and the RPM Display object; the next commit removes them. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
229 lines
9.9 KiB
C#
229 lines
9.9 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using TMPro;
|
|
using UnityEngine;
|
|
using UnityEngine.UI;
|
|
using CultMath;
|
|
using UnityEngine.Serialization;
|
|
using static CultMath.math;
|
|
|
|
public class SchematicDisplay : MonoBehaviour
|
|
{
|
|
public GameSettings Settings;
|
|
public Prototype ListElementPrototype;
|
|
|
|
public Color HeaderElementEnabledColor;
|
|
public Color HeaderElementDisabledColor;
|
|
|
|
public GameObject OverrideIcon;
|
|
public float OverrideIconBlinkSpeed;
|
|
public GameObject ShieldIcon;
|
|
public Image HeatsinkBackground;
|
|
|
|
public TextMeshProUGUI EnergyLabel;
|
|
public TextMeshProUGUI CockpitTemperatureLabel;
|
|
public TextMeshProUGUI RadiatorTemperatureLabel;
|
|
public TextMeshProUGUI HeatStorageTemperatureLabel;
|
|
public TextMeshProUGUI CargoTemperatureLabel;
|
|
public TextMeshProUGUI VisibilityLabel;
|
|
public TextMeshProUGUI HullDurabilityLabel;
|
|
public TextMeshProUGUI DistanceLabel;
|
|
|
|
public RectTransform SensorCooldownFill;
|
|
public RectTransform EnergyFill;
|
|
public RectTransform HullDurabilityFill;
|
|
public RectTransform HeatstrokeMeterFill;
|
|
public RectTransform HypothermiaMeterFill;
|
|
public RectTransform HeatstrokeLimitFill;
|
|
|
|
private Entity _entity;
|
|
private EquippableItem _hull;
|
|
private Radiator[] _radiators;
|
|
private Cockpit _cockpit;
|
|
private Reactor _reactor;
|
|
private Capacitor[] _capacitors;
|
|
private HeatStorage[] _heatStorages;
|
|
private EquippedCargoBay[] _cargoBays;
|
|
private SchematicDisplayItem[] _schematicItems;
|
|
|
|
private bool _enemy;
|
|
private Entity _player;
|
|
|
|
public SchematicDisplayItem[] SchematicItems
|
|
{
|
|
get { return _schematicItems; }
|
|
}
|
|
|
|
public class SchematicDisplayItem
|
|
{
|
|
public EquippedItem Item;
|
|
public SchematicListElement ListElement;
|
|
public IProgressBehavior Cooldown;
|
|
// public ItemUsage ItemUsage;
|
|
public Weapon Weapon;
|
|
}
|
|
|
|
public void ShowShip(Entity entity, Entity player = null)
|
|
{
|
|
_enemy = player != null;
|
|
_player = player;
|
|
if (_schematicItems != null)
|
|
foreach (var item in _schematicItems)
|
|
{
|
|
item.ListElement.GetComponent<Prototype>().ReturnToPool();
|
|
}
|
|
|
|
_entity = entity;
|
|
if (!_enemy)
|
|
{
|
|
_cockpit = entity.GetBehavior<Cockpit>();
|
|
_reactor = entity.GetBehavior<Reactor>();
|
|
_capacitors = entity.GetBehaviors<Capacitor>().ToArray();
|
|
|
|
_radiators = entity.GetBehaviors<Radiator>().ToArray();
|
|
if (_radiators.Length == 0)
|
|
RadiatorTemperatureLabel.text = "N/A";
|
|
|
|
_heatStorages = entity.GetBehaviors<HeatStorage>().ToArray();
|
|
if (_heatStorages.Length == 0)
|
|
HeatStorageTemperatureLabel.text = "N/A";
|
|
|
|
_cargoBays = entity.CargoBays.ToArray();
|
|
if (_cargoBays.Length == 0)
|
|
CargoTemperatureLabel.text = "N/A";
|
|
}
|
|
|
|
// Cut 2 (docs/fire-control-cut.md): an enemy schematic shows only what `player` has actually
|
|
// resolved (FireControl.IsRevealed) -- the same predicate the selection writer and the AI use. The
|
|
// player's own schematic is unfiltered; there is nothing to reveal about your own ship.
|
|
_schematicItems = entity.Equipment
|
|
.Where(x => x.Behaviors.Any(b => b.Data is WeaponData) && (!_enemy || FireControl.IsRevealed(player, x)))
|
|
.Select(x => new SchematicDisplayItem
|
|
{
|
|
Item = x,
|
|
ListElement = ListElementPrototype.Instantiate<SchematicListElement>(),
|
|
Cooldown = _enemy ? null : (IProgressBehavior) x.Behaviors.FirstOrDefault(b=> b is IProgressBehavior),
|
|
// ItemUsage = _enemy ? null : (ItemUsage) x.Behaviors.FirstOrDefault(b=> b is ItemUsage),
|
|
Weapon = (Weapon) x.Behaviors.FirstOrDefault(b=>b is Weapon)
|
|
})
|
|
.ToArray();
|
|
foreach (var x in _schematicItems)
|
|
{
|
|
if(x.Item.Data is WeaponItemData weaponItemData)
|
|
x.ListElement.ShowWeapon(weaponItemData);
|
|
//x.ListElement.Label.text = x.Item.EquippableItem.Name;
|
|
if (!_enemy)
|
|
{
|
|
x.ListElement.InfiniteAmmoIcon.gameObject.SetActive(!x.Weapon.WeaponData.AmmoType.IsSet());
|
|
x.ListElement.AmmoLabel.gameObject.SetActive(x.Weapon.WeaponData.AmmoType.IsSet());
|
|
}
|
|
}
|
|
}
|
|
|
|
void Update()
|
|
{
|
|
if (_entity != null)
|
|
{
|
|
if (!_enemy)
|
|
{
|
|
OverrideIcon.SetActive(_entity.OverrideShutdown && cos(Time.time * OverrideIconBlinkSpeed) > 0);
|
|
ShieldIcon.SetActive(_entity.Shield!=null && _entity.Shield.Item.Active.Value);
|
|
if (_radiators.Length == 1)
|
|
RadiatorTemperatureLabel.text = $"{((int)(_radiators[0].RadiatorTemperature - 273.15f)).ToString()}°C";
|
|
else if (_radiators.Length > 1)
|
|
RadiatorTemperatureLabel.text =
|
|
$"{((int)(_radiators.Min(r => r.RadiatorTemperature) - 273.15f)).ToString()}-" +
|
|
$"{((int)(_radiators.Max(r => r.RadiatorTemperature) - 273.15f)).ToString()}°C";
|
|
HeatsinkBackground.color = _entity.HeatsinksEnabled ? HeaderElementEnabledColor : HeaderElementDisabledColor;
|
|
|
|
if (_heatStorages.Length == 1)
|
|
HeatStorageTemperatureLabel.text = $"{((int)(_heatStorages[0].Item.Temperature - 273.15f)).ToString()}°C";
|
|
else if (_heatStorages.Length > 1)
|
|
HeatStorageTemperatureLabel.text =
|
|
$"{((int)(_heatStorages.Min(r => r.Item.Temperature) - 273.15f)).ToString()}-" +
|
|
$"{((int)(_heatStorages.Max(r => r.Item.Temperature) - 273.15f)).ToString()}°C";
|
|
|
|
if (_cargoBays.Length == 1)
|
|
CargoTemperatureLabel.text = $"{((int)(_cargoBays[0].Temperature - 273.15f)).ToString()}°C";
|
|
else if (_cargoBays.Length > 1)
|
|
CargoTemperatureLabel.text =
|
|
$"{((int)(_cargoBays.Min(r => r.Temperature) - 273.15f)).ToString()}-" +
|
|
$"{((int)(_cargoBays.Max(r => r.Temperature) - 273.15f)).ToString()}°C";
|
|
|
|
if(_cockpit != null)
|
|
{
|
|
CockpitTemperatureLabel.text = $"{((int) (_cockpit.Item.Temperature - 273.15f)).ToString()}°C";
|
|
|
|
HeatstrokeMeterFill.anchorMax = new Vector2(_entity.Heatstroke, 1);
|
|
HypothermiaMeterFill.anchorMax = new Vector2(_entity.Hypothermia, 1);
|
|
HeatstrokeLimitFill.anchorMax = new Vector2(unlerp(Settings.GameplaySettings.HypothermiaTemperature, Settings.GameplaySettings.HeatstrokeTemperature, _cockpit.Item.Temperature), 1);
|
|
}
|
|
|
|
SensorCooldownFill.anchorMax = new Vector2(_entity.Sensor?.Cooldown ?? 0, 1);
|
|
|
|
if (_capacitors.Length == 0)
|
|
{
|
|
EnergyFill.anchorMax = Vector2.up;
|
|
EnergyLabel.text = ActionGameManager.PlayerSettings.Format(_reactor.Draw);
|
|
}
|
|
else
|
|
{
|
|
var charge = _capacitors.Sum(x => x.Charge);
|
|
var maxCharge = _capacitors.Sum(x => x.Capacity);
|
|
EnergyFill.anchorMax = new Vector2(charge / maxCharge, 1);
|
|
EnergyLabel.text = $"{((int)charge).ToString()}/{((int)maxCharge).ToString()} + ({((int)_reactor.Draw).ToString()})";
|
|
}
|
|
}
|
|
// else
|
|
// {
|
|
// DistanceLabel.text = $"{(int)length(_entity.Position - _player.Position)}";
|
|
// }
|
|
|
|
// Cut 2 (docs/fire-control-cut.md): marks whichever row is the player's current aim point.
|
|
// Re-checked every frame (not just on ShowShip) because ResolvedTargetItem can drop on its own
|
|
// as info decays, with no event to hook.
|
|
if (_enemy && _schematicItems != null)
|
|
foreach (var x in _schematicItems)
|
|
x.ListElement.SetSelected(x.Item == _player.ResolvedTargetItem);
|
|
|
|
if(VisibilityLabel)
|
|
VisibilityLabel.text = ((int)_entity.Visibility).ToString();
|
|
|
|
if(HullDurabilityFill)
|
|
{
|
|
_hull = _entity.Hull;
|
|
var hullData = _entity.ItemManager.GetData(_hull);
|
|
var dur = _hull.Durability / hullData.Durability;
|
|
HullDurabilityFill.anchorMax = new Vector2(dur, 1);
|
|
HullDurabilityLabel.text = $"{ActionGameManager.PlayerSettings.Format(dur * 100)}%";
|
|
}
|
|
|
|
foreach (var x in _schematicItems)
|
|
{
|
|
if (!_enemy)
|
|
{
|
|
var itemData = _entity.ItemManager.GetData(x.Item.EquippableItem);
|
|
x.ListElement.HeatFill.anchorMax = new Vector2(unlerp(itemData.MinimumTemperature, itemData.MaximumTemperature, x.Item.Temperature), 0);
|
|
if (x.Cooldown != null)
|
|
x.ListElement.CooldownFill.anchorMax = new Vector2(x.Cooldown.Progress, 1);
|
|
x.ListElement.DurabilityLabel.text = $"{(int)(x.Item.EquippableItem.Durability / itemData.Durability * 100)}%";
|
|
if (x.Weapon.WeaponData.AmmoType.IsSet())
|
|
{
|
|
if(x.Weapon.WeaponData.MagazineSize > 1)
|
|
x.ListElement.AmmoLabel.text = x.Weapon.Ammo.ToString();
|
|
else
|
|
x.ListElement.AmmoLabel.text = _entity.CountItemsInCargo(x.Weapon.WeaponData.AmmoType.Key).ToString();
|
|
}
|
|
}
|
|
|
|
if (x.Weapon.WeaponData != null)
|
|
{
|
|
if(x.ListElement.RangeLabel)
|
|
x.ListElement.RangeLabel.text = ((int) x.Weapon.Range).ToString();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|