From 698263ce630043a27e51e5b51a17b2b5e35dea1a Mon Sep 17 00:00:00 2001 From: hyperion51 Date: Tue, 26 May 2020 01:12:06 +0100 Subject: [PATCH] Entity Properties & Thermal Regulation Entities such as colonies and ships can now be clicked on to reveal their properties or context menus Orbital Colony loadout now has a new item (thermostatic heater) which itself has a new behavior type (Thermotoggle) allowing it to regulate its temperature for more agreeable living conditions Fixed stat modifiers for hull stats (e.g. Hull Expansion) Widened property label in DB inspector --- .../.idea/contentModel.xml | 1 + Assets/Prefabs/Child.prefab | 2 +- Assets/Scripts/Editor/DatabaseInspector.cs | 4 +- .../ServerShared/Behaviors/Behaviors.cs | 2 + .../ServerShared/Behaviors/Radiator.cs | 5 +- .../Scripts/ServerShared/Behaviors/Reactor.cs | 9 +-- .../ServerShared/Behaviors/StatModifier.cs | 4 +- .../ServerShared/Behaviors/Thermotoggle.cs | 43 ++++++++++++++ .../Behaviors/Thermotoggle.cs.meta | 11 ++++ Assets/Scripts/ServerShared/Entity.cs | 14 ++++- Assets/Scripts/ServerShared/GameContext.cs | 17 +++++- Assets/Scripts/StrategyGameManager.cs | 57 ++++++++++++------- Assets/Scripts/UI/ClickRaycaster.cs | 5 +- Assets/Scripts/UI/ReadOnlyPropertiesPanel.cs | 1 + Economy.Shared.Unity.csproj | 1 + 15 files changed, 143 insertions(+), 33 deletions(-) create mode 100644 Assets/Scripts/ServerShared/Behaviors/Thermotoggle.cs create mode 100644 Assets/Scripts/ServerShared/Behaviors/Thermotoggle.cs.meta diff --git a/.idea/.idea.Aetheria-Economy/.idea/contentModel.xml b/.idea/.idea.Aetheria-Economy/.idea/contentModel.xml index c98b5121b..a802605a7 100644 --- a/.idea/.idea.Aetheria-Economy/.idea/contentModel.xml +++ b/.idea/.idea.Aetheria-Economy/.idea/contentModel.xml @@ -1273,6 +1273,7 @@ + diff --git a/Assets/Prefabs/Child.prefab b/Assets/Prefabs/Child.prefab index 0369f7863..24bb20748 100644 --- a/Assets/Prefabs/Child.prefab +++ b/Assets/Prefabs/Child.prefab @@ -29,7 +29,7 @@ Transform: m_GameObject: {fileID: 7411673047664575939} m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: -0.6599999, z: 0} - m_LocalScale: {x: 0.25000015, y: 0.25000015, z: 0} + m_LocalScale: {x: 0.25000015, y: 0.25000015, z: 0.25} m_Children: [] m_Father: {fileID: 0} m_RootOrder: 0 diff --git a/Assets/Scripts/Editor/DatabaseInspector.cs b/Assets/Scripts/Editor/DatabaseInspector.cs index cad57e00f..eb6c3b813 100644 --- a/Assets/Scripts/Editor/DatabaseInspector.cs +++ b/Assets/Scripts/Editor/DatabaseInspector.cs @@ -28,7 +28,7 @@ public class DatabaseInspector : EditorWindow private static float2 _dragOffset; private bool _ctrlDown; private string[] _hardpointTypes; - private const int width = 100; + private const int width = 150; private const int labelWidth = 20; private Material _galaxyMat; private Texture2D _white; @@ -985,7 +985,7 @@ public class DatabaseInspector : EditorWindow } // Only display heat, durability and quality effects if the stat actually varies - if (Math.Abs(value.Min - value.Max) > .01f) + if (Math.Abs(value.Min - value.Max) > .0001f) { using (new HorizontalScope()) { diff --git a/Assets/Scripts/ServerShared/Behaviors/Behaviors.cs b/Assets/Scripts/ServerShared/Behaviors/Behaviors.cs index 193f86992..3bbe25702 100644 --- a/Assets/Scripts/ServerShared/Behaviors/Behaviors.cs +++ b/Assets/Scripts/ServerShared/Behaviors/Behaviors.cs @@ -87,6 +87,8 @@ public abstract class PersistentBehaviorData Union(20, typeof(SwitchData)), Union(21, typeof(TriggerData)), Union(22, typeof(VisibilityData)), + Union(23, typeof(ThermotoggleData)), + Union(24, typeof(EnergyDrawData)), JsonConverter(typeof(JsonKnownTypesConverter)), JsonObject(MemberSerialization.OptIn)] public abstract class BehaviorData { diff --git a/Assets/Scripts/ServerShared/Behaviors/Radiator.cs b/Assets/Scripts/ServerShared/Behaviors/Radiator.cs index 78e0be173..ddbc0f069 100644 --- a/Assets/Scripts/ServerShared/Behaviors/Radiator.cs +++ b/Assets/Scripts/ServerShared/Behaviors/Radiator.cs @@ -22,6 +22,8 @@ public class Radiator : IBehavior public GameContext Context { get; } public BehaviorData Data => _data; + + public float Emissivity; private RadiatorData _data; @@ -35,7 +37,8 @@ public class Radiator : IBehavior public bool Update(float delta) { - var rad = pow(Entity.Temperature, Context.GlobalData.HeatRadiationPower) * Context.GlobalData.HeatRadiationMultiplier; + Emissivity = Context.Evaluate(_data.Emissivity, Item, Entity); + var rad = pow(Entity.Temperature, Context.GlobalData.HeatRadiationPower) * Context.GlobalData.HeatRadiationMultiplier * Emissivity; Entity.Temperature -= rad * delta; Entity.VisibilitySources[this] = rad; return true; diff --git a/Assets/Scripts/ServerShared/Behaviors/Reactor.cs b/Assets/Scripts/ServerShared/Behaviors/Reactor.cs index 66bf23bd4..ea298f953 100644 --- a/Assets/Scripts/ServerShared/Behaviors/Reactor.cs +++ b/Assets/Scripts/ServerShared/Behaviors/Reactor.cs @@ -34,6 +34,7 @@ public class Reactor : IBehavior public GameContext Context { get; } public BehaviorData Data => _data; + public float Capacitance; public Reactor(GameContext context, ReactorData data, Entity entity, Gear item) { @@ -45,17 +46,17 @@ public class Reactor : IBehavior public bool Update(float delta) { - var cap = Context.Evaluate(_data.Capacitance, Item, Entity); + Capacitance = Context.Evaluate(_data.Capacitance, Item, Entity); var charge = Context.Evaluate(_data.Charge, Item, Entity) * delta; var efficiency = Context.Evaluate(_data.Efficiency, Item, Entity); Entity.AddHeat(charge / efficiency); Entity.Energy += charge; - if (Entity.Energy > cap) + if (Entity.Energy > Capacitance) { - Entity.AddHeat(-(Entity.Energy - cap) / efficiency * (1 - 1 / Context.Evaluate(_data.UnderloadRecovery, Item, Entity))); - Entity.Energy = cap; + Entity.AddHeat(-(Entity.Energy - Capacitance) / efficiency * (1 - 1 / Context.Evaluate(_data.UnderloadRecovery, Item, Entity))); + Entity.Energy = Capacitance; } if (Entity.Energy < 0) diff --git a/Assets/Scripts/ServerShared/Behaviors/StatModifier.cs b/Assets/Scripts/ServerShared/Behaviors/StatModifier.cs index a9fda97bc..351f0bb3f 100644 --- a/Assets/Scripts/ServerShared/Behaviors/StatModifier.cs +++ b/Assets/Scripts/ServerShared/Behaviors/StatModifier.cs @@ -54,14 +54,14 @@ public class StatModifier : IBehavior, IInitializableBehavior, IDisposableBehavi if (statField != null) { if (typeof(EquippableItemData).IsAssignableFrom(targetType)) - _stats = Entity.EquippedItems + _stats = Entity.EquippedItems.Append(Entity.Hull) .Select(id => Context.Cache.Get(id)) .Where(gear => _data.RequireBehavior == null || gear.ItemData.Behaviors.Any(behavior => behavior.GetType() == _data.RequireBehavior)) .Where(gear => gear.ItemData.GetType() == targetType) .Select(gear => statField.GetValue(gear.ItemData) as PerformanceStat) .ToArray(); else - _stats = Entity.EquippedItems + _stats = Entity.EquippedItems.Append(Entity.Hull) .Select(id => Context.Cache.Get(id)) .Where(gear => _data.RequireBehavior == null || gear.ItemData.Behaviors.Any(behavior => behavior.GetType() == _data.RequireBehavior)) .SelectMany(gear => gear.ItemData.Behaviors) diff --git a/Assets/Scripts/ServerShared/Behaviors/Thermotoggle.cs b/Assets/Scripts/ServerShared/Behaviors/Thermotoggle.cs new file mode 100644 index 000000000..5192c07f7 --- /dev/null +++ b/Assets/Scripts/ServerShared/Behaviors/Thermotoggle.cs @@ -0,0 +1,43 @@ +using System; +using System.Linq; +using MessagePack; +using Newtonsoft.Json; + +[InspectableField, MessagePackObject, JsonObject(MemberSerialization.OptIn), Order(-22)] +public class ThermotoggleData : BehaviorData +{ + [TemperatureInspectable, JsonProperty("targetTemp"), Key(1)] + public float TargetTemperature; + + [InspectableField, JsonProperty("perSecond"), Key(2)] + public bool HighPass; + + public override IBehavior CreateInstance(GameContext context, Entity entity, Gear item) + { + return new Thermotoggle(context, this, entity, item); + } +} + +public class Thermotoggle : IBehavior +{ + private ThermotoggleData _data; + + private Entity Entity { get; } + private Gear Item { get; } + private GameContext Context { get; } + + public BehaviorData Data => _data; + + public Thermotoggle(GameContext context, ThermotoggleData data, Entity entity, Gear item) + { + _data = data; + Entity = entity; + Item = item; + Context = context; + } + + public bool Update(float delta) + { + return Entity.Temperature < _data.TargetTemperature ^ _data.HighPass; + } +} \ No newline at end of file diff --git a/Assets/Scripts/ServerShared/Behaviors/Thermotoggle.cs.meta b/Assets/Scripts/ServerShared/Behaviors/Thermotoggle.cs.meta new file mode 100644 index 000000000..82c88062b --- /dev/null +++ b/Assets/Scripts/ServerShared/Behaviors/Thermotoggle.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8e461bdbde38ffb4486490d7998d62af +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/ServerShared/Entity.cs b/Assets/Scripts/ServerShared/Entity.cs index fded7b6d2..ac210bc88 100644 --- a/Assets/Scripts/ServerShared/Entity.cs +++ b/Assets/Scripts/ServerShared/Entity.cs @@ -42,6 +42,7 @@ public abstract class Entity : DatabaseEntry, IMessagePackSerializationCallbackR private Dictionary> ItemBehaviors; [IgnoreMember] public float Mass { get; private set; } + [IgnoreMember] public float OccupiedCapacity { get; private set; } [IgnoreMember] public float SpecificHeat { get; private set; } [IgnoreMember] public float Visibility => VisibilitySources.Values.Sum(); @@ -128,6 +129,9 @@ public abstract class Entity : DatabaseEntry, IMessagePackSerializationCallbackR EquippedItems.Select(i => Context.Cache.Get(i)).Sum(i => i.HeatCapacity) + Cargo.Select(i => Context.Cache.Get(i)).Sum(ii => ii.HeatCapacity) + Children.Select(i => Context.Cache.Get(i)).Sum(c=>c.SpecificHeat); + + OccupiedCapacity = EquippedItems.Select(i => Context.Cache.Get(i)).Sum(i => i.ItemData.Size) + + Cargo.Select(i => Context.Cache.Get(i)).Sum(ii => Context.GetSize(ii)); } public IEnumerable GetBehaviors() where T : class, IBehavior @@ -165,7 +169,14 @@ public abstract class Entity : DatabaseEntry, IMessagePackSerializationCallbackR public void AddHeat(float heat) { - Temperature += heat / SpecificHeat; + if (Parent != Guid.Empty) + { + var parent = Context.Cache.Get(Parent); + parent.AddHeat(heat); + } + else + Temperature += heat / SpecificHeat; + } public virtual void Update(float delta) @@ -189,6 +200,7 @@ public abstract class Entity : DatabaseEntry, IMessagePackSerializationCallbackR var parent = Context.Cache.Get(Parent); Position = parent.Position; Velocity = parent.Velocity; + Temperature = parent.Temperature; } // Processing stale item data properly was a pain in my ass, so the shortcut is just persisting and restoring everything diff --git a/Assets/Scripts/ServerShared/GameContext.cs b/Assets/Scripts/ServerShared/GameContext.cs index 416e5102b..7627b1ab9 100644 --- a/Assets/Scripts/ServerShared/GameContext.cs +++ b/Assets/Scripts/ServerShared/GameContext.cs @@ -405,6 +405,20 @@ public class GameContext return 0; } + public float GetSize(ItemInstance item) + { + var data = GetData(item); + switch (item) + { + case CraftedItemInstance _: + return data.Size; + case SimpleCommodity commodity: + return data.Size * commodity.Quantity; + } + + return 0; + } + public float GetHeatCapacity(ItemInstance item) { var data = GetData(item); @@ -659,7 +673,8 @@ public class GameContext var entity = new OrbitalEntity(this, hull.ID, gear.Select(g => g.ID), cargo.Select(c => c.ID).Concat(simpleCargo.Select(c => c.ID)), orbit.ID, zone) { - Name = $"{loadoutData.Name} {Random.NextInt(1,255):X}" + Name = $"{loadoutData.Name} {Random.NextInt(1,255):X}", + Temperature = 293 }; Cache.Add(entity); diff --git a/Assets/Scripts/StrategyGameManager.cs b/Assets/Scripts/StrategyGameManager.cs index 4ef82bed1..933069425 100644 --- a/Assets/Scripts/StrategyGameManager.cs +++ b/Assets/Scripts/StrategyGameManager.cs @@ -232,7 +232,7 @@ public class StrategyGameManager : MonoBehaviour foreach (var entry in zone.Contents) _cache.Add(entry); if(_currentTab==GalaxyTabButton && _selectedZone == zone.Zone.ID) - PopulateZoneProperties(_selectedZone); + PopulatePropertiesPanel(_selectedZone); if (_currentTab == ZoneTabButton && _populatedZone != zone.Zone.ID) PopulateZone(); }); @@ -256,7 +256,7 @@ public class StrategyGameManager : MonoBehaviour var zone = _cache.Get(_selectedZone); if (_populatedZone != _selectedZone && zone != null) PopulateZone(); - PopulateZoneProperties(_populatedZone); + PopulatePropertiesPanel(_populatedZone); Camera.transform.position = -Vector3.forward; if (zone != null) Camera.orthographicSize = zone.Radius * ZoneSizeScale; @@ -280,10 +280,16 @@ public class StrategyGameManager : MonoBehaviour _boundaryMaterial = ZoneBoundary.material; _backgroundMaterial = ZoneBackground.material; - ClickRaycaster.OnClickMiss += () => + ClickRaycaster.OnClickMiss += data => { if (_currentTab == GalaxyTabButton) PopulateGalaxyProperties(); - else if (_currentTab == ZoneTabButton) PopulateZoneProperties(_populatedZone); + else if (_currentTab == ZoneTabButton) + { + if (data.button == PointerEventData.InputButton.Left) + PopulatePropertiesPanel(_populatedZone); + else if (data.button == PointerEventData.InputButton.Right) + ShowContextMenu(_populatedZone); + } else if (_currentTab == TechTabButton) PopulateTechProperties(); }; } @@ -296,15 +302,6 @@ public class StrategyGameManager : MonoBehaviour PropertiesPanel.AddProperty("Sectors", () => $"{_context.GalaxyZones.Count}"); } - private void PopulateZoneProperties(Guid zone) - { - PropertiesPanel.Clear(); - var zoneData = _cache.Get(zone); - PropertiesPanel.Title.text = zoneData.Name; - PropertiesPanel.AddSection("Sector"); - PropertiesPanel.AddProperty("Planets", () => $"{zoneData.Planets.Length}"); - } - private void PopulateTechProperties() { PropertiesPanel.Clear(); @@ -522,7 +519,8 @@ public class StrategyGameManager : MonoBehaviour if(planet.Belt) PropertiesPanel.AddSection("Asteroid Belt"); else - PropertiesPanel.AddSection(planet.Mass > _context.GlobalData.SunMass ? "Star" : + PropertiesPanel.AddSection( + planet.Mass > _context.GlobalData.SunMass ? "Star" : planet.Mass > _context.GlobalData.GasGiantMass ? "Gas Giant" : planet.Mass > _context.GlobalData.PlanetMass ? "Planet" : "Planetoid"); @@ -533,6 +531,31 @@ public class StrategyGameManager : MonoBehaviour return new Tuple(itemData.Name, $"{resource.Value:0}"); })); } + + if (targetObject is Entity entity) + { + PropertiesPanel.Clear(); + PropertiesPanel.Title.text = entity.Name; + var hull = _context.Cache.Get(entity.Hull); + var hullData = _context.Cache.Get(hull.Data); + PropertiesPanel.AddSection( + hullData.HullType == HullType.Ship ? "Drone Ship" : + hullData.HullType == HullType.Station ? "Colony" : + "Weapons Platform"); + PropertiesPanel.AddProperty("Hull", () => $"{hullData.Name}"); + PropertiesPanel.AddProperty("Capacity", () => $"{entity.OccupiedCapacity}/{_context.Evaluate(hullData.Capacity, hull, entity)}"); + PropertiesPanel.AddProperty("Mass", () => $"{entity.Mass}"); + PropertiesPanel.AddProperty("Temperature", () => $"{entity.Temperature:0}°K"); + PropertiesPanel.AddProperty("Energy", () => $"{entity.Energy:0}/{entity.GetBehaviors().First().Capacitance:0}"); + } + + if (targetObject is ZoneData zone) + { + PropertiesPanel.Clear(); + PropertiesPanel.Title.text = zone.Name; + PropertiesPanel.AddSection("Sector"); + PropertiesPanel.AddProperty("Planets", () => $"{zone.Planets.Length}"); + } } void PopulateGalaxy() @@ -576,11 +599,7 @@ public class StrategyGameManager : MonoBehaviour CultClient.Send(new ZoneRequestMessage{ZoneID = zone.ZoneID}); if (TestMode) { - // if(!_context.Cache.Get(zone.ZoneID).Visited) - // { - // GenerateZone(zone.ZoneID); - // } - PopulateZoneProperties(zone.ZoneID); + PopulatePropertiesPanel(zone.ZoneID); } _selectedZone = zone.ZoneID; _selectedGalaxyZone = instanceZone; diff --git a/Assets/Scripts/UI/ClickRaycaster.cs b/Assets/Scripts/UI/ClickRaycaster.cs index fb62e89ec..cfc73483a 100644 --- a/Assets/Scripts/UI/ClickRaycaster.cs +++ b/Assets/Scripts/UI/ClickRaycaster.cs @@ -2,10 +2,11 @@ using System.Collections; using System.Collections.Generic; using UnityEngine; +using UnityEngine.EventSystems; public class ClickRaycaster : MonoBehaviour { - public event Action OnClickMiss; + public event Action OnClickMiss; public Camera RayCamera; private ClickCatcher _clickCatcher; @@ -22,7 +23,7 @@ public class ClickRaycaster : MonoBehaviour if (clickable != null) clickable.Click(pointer); } - else OnClickMiss?.Invoke(); + else OnClickMiss?.Invoke(pointer); }; } } diff --git a/Assets/Scripts/UI/ReadOnlyPropertiesPanel.cs b/Assets/Scripts/UI/ReadOnlyPropertiesPanel.cs index 88b6cf131..64458168e 100644 --- a/Assets/Scripts/UI/ReadOnlyPropertiesPanel.cs +++ b/Assets/Scripts/UI/ReadOnlyPropertiesPanel.cs @@ -25,6 +25,7 @@ public class ReadOnlyPropertiesPanel : MonoBehaviour { var property = Instantiate(PropertyPrefab, transform); property.Name.text = name; + property.Value.text = value(); property.ValueFunction = value; _properties.Add(property.gameObject); } diff --git a/Economy.Shared.Unity.csproj b/Economy.Shared.Unity.csproj index 8eb5d47fc..e802f2137 100644 --- a/Economy.Shared.Unity.csproj +++ b/Economy.Shared.Unity.csproj @@ -90,6 +90,7 @@ +