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

@ -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;