Delete legacy item data DTO hierarchy
This commit is contained in:
parent
71f2c14c33
commit
3e56eadeba
7 changed files with 353 additions and 620 deletions
|
|
@ -1,600 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Unity.Mathematics;
|
||||
using static Unity.Mathematics.math;
|
||||
using float2 = Unity.Mathematics.float2;
|
||||
using int2 = Unity.Mathematics.int2;
|
||||
|
||||
[Inspectable]
|
||||
public class Shape
|
||||
{
|
||||
public bool[,] Cells;
|
||||
|
||||
private bool _dirty = true;
|
||||
|
||||
public Shape()
|
||||
{
|
||||
Cells = new bool[1,1];
|
||||
Cells[0, 0] = true;
|
||||
}
|
||||
|
||||
public Shape(int width, int height)
|
||||
{
|
||||
Cells = new bool[width, height];
|
||||
}
|
||||
|
||||
public int Width
|
||||
{
|
||||
get { return Cells.GetLength(0); }
|
||||
set { Resize(value, Height); }
|
||||
}
|
||||
|
||||
public int Height
|
||||
{
|
||||
get { return Cells.GetLength(1); }
|
||||
set { Resize(Width, value); }
|
||||
}
|
||||
|
||||
public void Resize(int width, int height)
|
||||
{
|
||||
var newCells = new bool[width, height];
|
||||
|
||||
for (int x = 0; x < width; x++)
|
||||
{
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
newCells[x, y] = x >= Width || y >= Height || Cells[x, y];
|
||||
}
|
||||
}
|
||||
|
||||
Cells = newCells;
|
||||
}
|
||||
|
||||
private static int mod(int x, int m) {
|
||||
int r = x%m;
|
||||
return r<0 ? r+m : r;
|
||||
}
|
||||
|
||||
public int2 Rotate(int2 position, ItemRotation rotation)
|
||||
{
|
||||
return rotation switch
|
||||
{
|
||||
ItemRotation.Clockwise => int2(position.y, Width - 1 - position.x),
|
||||
ItemRotation.Reversed => int2(Width - 1 - position.x, Height - 1 - position.y),
|
||||
ItemRotation.CounterClockwise => int2(Height - 1 - position.y, position.x),
|
||||
_ => int2(position.x, position.y)
|
||||
};
|
||||
}
|
||||
|
||||
private int2[] _cachedShapeCoordinates;
|
||||
|
||||
public int2[] Coordinates
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_dirty)
|
||||
{
|
||||
_cachedShapeCoordinates = EnumerateShapeCoordinates().ToArray();
|
||||
_dirty = false;
|
||||
}
|
||||
return _cachedShapeCoordinates;
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerable<int2> EnumerateShapeCoordinates()
|
||||
{
|
||||
for (int y = 0; y < Height; y++)
|
||||
{
|
||||
for(int x = 0; x < Width; x++)
|
||||
{
|
||||
if(Cells[x,y]) yield return int2(x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int2[] _cachedAllShapeCoordinates;
|
||||
|
||||
public int2[] AllCoordinates => _cachedAllShapeCoordinates ?? (_cachedAllShapeCoordinates = EnumerateAllShapeCoordinates().ToArray());
|
||||
|
||||
private IEnumerable<int2> EnumerateAllShapeCoordinates()
|
||||
{
|
||||
for (int y = 0; y < Height; y++)
|
||||
{
|
||||
for(int x = 0; x < Width; x++)
|
||||
{
|
||||
yield return int2(x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private float2? _centerOfMass;
|
||||
|
||||
public float2 CenterOfMass => _centerOfMass ?? (_centerOfMass = Coordinates
|
||||
.Aggregate(float2.zero, (total, coord) => total + coord) / Coordinates.Length).Value;
|
||||
|
||||
public bool this[int2 pos] {
|
||||
get { return pos.x >= 0 && pos.y >= 0 && pos.x < Width && pos.y < Height && Cells[pos.x, pos.y]; }
|
||||
set
|
||||
{
|
||||
if (pos.x < 0 || pos.y < 0 || pos.x >= Width || pos.y >= Height) return;
|
||||
_dirty = true;
|
||||
Cells[pos.x, pos.y] = value;
|
||||
}
|
||||
}
|
||||
|
||||
public Shape Shrink()
|
||||
{
|
||||
var shape = new Shape(Width, Height);
|
||||
foreach(var shapeCoord in Coordinates)
|
||||
shape[shapeCoord] = (
|
||||
this[shapeCoord + int2(-1,-1)] && this[shapeCoord + int2(0,-1)] && this[shapeCoord + int2(1,-1)] &&
|
||||
this[shapeCoord + int2(-1,0)] && this[shapeCoord + int2(1,0)] &&
|
||||
this[shapeCoord + int2(-1,1)] && this[shapeCoord + int2(0,1)] && this[shapeCoord + int2(1,1)]
|
||||
);
|
||||
return shape;
|
||||
}
|
||||
|
||||
public Shape Inset(Shape inset, int2 insetPosition, ItemRotation rotation = ItemRotation.None)
|
||||
{
|
||||
var shape = new Shape(max(Width,insetPosition.x + inset.Width - 1), max(Height, insetPosition.y + inset.Height - 1));
|
||||
foreach (var v in inset.Coordinates)
|
||||
{
|
||||
var insetCoord = inset.Rotate(v, rotation) + insetPosition;
|
||||
shape[insetCoord] = true;
|
||||
}
|
||||
|
||||
return shape;
|
||||
}
|
||||
|
||||
public Shape Expand()
|
||||
{
|
||||
var shape = new Shape(Width, Height);
|
||||
foreach (var shapeCoord in AllCoordinates)
|
||||
shape[shapeCoord] = (
|
||||
this[shapeCoord + int2(-1,-1)] || this[shapeCoord + int2(0,-1)] || this[shapeCoord + int2(1,-1)] ||
|
||||
this[shapeCoord + int2(-1,0)] || this[shapeCoord] || this[shapeCoord + int2(1,0)] ||
|
||||
this[shapeCoord + int2(-1,1)] || this[shapeCoord + int2(0,1)] || this[shapeCoord + int2(1,1)]
|
||||
);
|
||||
return shape;
|
||||
}
|
||||
|
||||
// TODO: Use the power of math to optimize this function!
|
||||
// Try to find a rotation and position with which a shape can be placed to fit within another shape
|
||||
public bool FitsWithin(Shape other, out ItemRotation rotation, out int2 position)
|
||||
{
|
||||
// Try every item orientation
|
||||
foreach(var rot in (ItemRotation[])Enum.GetValues(typeof(ItemRotation)))
|
||||
{
|
||||
rotation = rot;
|
||||
if (FitsWithin(other, rot, out var pos))
|
||||
{
|
||||
position = pos;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
rotation = ItemRotation.None;
|
||||
position = int2.zero;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Try to find a position with which a shape can be placed to fit within another shape
|
||||
public bool FitsWithin(Shape other, ItemRotation rotation, out int2 position)
|
||||
{
|
||||
var width = rotation == ItemRotation.Clockwise || rotation == ItemRotation.CounterClockwise ? Height : Width;
|
||||
var height = rotation == ItemRotation.Clockwise || rotation == ItemRotation.CounterClockwise ? Width : Height;
|
||||
// Try every item position that could possibly fit
|
||||
for(int x = 0; x < other.Width - width + 1; x++)
|
||||
{
|
||||
for (int y = 0; y < other.Height - height + 1; y++)
|
||||
{
|
||||
position = int2(x, y);
|
||||
var fits = true;
|
||||
foreach (var v in Coordinates)
|
||||
{
|
||||
fits = fits && other[Rotate(v, rotation) + position];
|
||||
if (!fits) break;
|
||||
}
|
||||
|
||||
if (fits) return true;
|
||||
}
|
||||
}
|
||||
|
||||
position = int2.zero;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set every cell on the line from a to b to true according to Bresenham's Line Algorithm
|
||||
public void SetLine(float2 a, float2 b)
|
||||
{
|
||||
if (a.Equals(b))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// If line gradient is steep, swap x and y
|
||||
bool steep = Math.Abs(b.y - a.y) > Math.Abs(b.x - a.x);
|
||||
if (steep)
|
||||
{
|
||||
a = new float2(a.y, a.x);
|
||||
b = new float2(b.y, b.x);
|
||||
}
|
||||
|
||||
// If b is closer to the origin than a, swap a and b.
|
||||
if (a.x > b.x)
|
||||
{
|
||||
var temp = a;
|
||||
a = b;
|
||||
b = temp;
|
||||
}
|
||||
|
||||
float dx = b.x - a.x;
|
||||
float dy = b.y - a.y;
|
||||
float derr = Math.Abs(dy / dx); // dx != 0
|
||||
|
||||
int y = (int) Math.Round(a.y);
|
||||
int xStart = (int) Math.Round(a.x);
|
||||
float error = (a.y - y) + (xStart - a.x) * derr;
|
||||
|
||||
for (int x = xStart; x <= (int) Math.Round(b.x); x++)
|
||||
{
|
||||
if (x >= 0 && x < Width && y >= 0 && y < Height)
|
||||
{
|
||||
Cells[steep ? y : x, steep ? x : y] = true;
|
||||
}
|
||||
error += derr;
|
||||
if (error >= 0.5f)
|
||||
{
|
||||
y += Math.Sign(dy);
|
||||
error -= 1f;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public abstract class ItemData : INamedEntry
|
||||
{
|
||||
public Guid ID = Guid.NewGuid();
|
||||
|
||||
[Inspectable]
|
||||
public string Name;
|
||||
|
||||
[InspectableText]
|
||||
public string Description;
|
||||
public Guid Manufacturer;
|
||||
|
||||
[Inspectable]
|
||||
public float Mass;
|
||||
|
||||
[InspectableSchematicShape]
|
||||
public Shape Shape;
|
||||
|
||||
// Heat needed to change temperature of 1 gram by 1 degree
|
||||
[Inspectable]
|
||||
public float SpecificHeat = 1;
|
||||
|
||||
[Inspectable]
|
||||
public float Conductivity = 1;
|
||||
|
||||
[Inspectable]
|
||||
public int Price = 0;
|
||||
|
||||
public string EntryName
|
||||
{
|
||||
get => Name;
|
||||
set => Name = value;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return ID.GetHashCode();
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is ItemData item && item.ID == ID;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[Inspectable]
|
||||
public class SimpleCommodityData : ItemData
|
||||
{
|
||||
// // Types of body where this resource can be found
|
||||
// [InspectableField]
|
||||
// public BodyType ResourceBodyType;
|
||||
//
|
||||
// // Controls the lowest value in the resource distribution curve
|
||||
// [InspectableField]
|
||||
// public ExponentialLerp Distribution;
|
||||
//
|
||||
// // Minimum amount of resources needed for presence to register
|
||||
// [InspectableField]
|
||||
// public float Floor = 5f;
|
||||
|
||||
[Inspectable]
|
||||
public int MaxStack = 10;
|
||||
|
||||
[Inspectable]
|
||||
public SimpleCommodityCategory Category;
|
||||
}
|
||||
|
||||
public abstract class CraftedItemData : ItemData
|
||||
{
|
||||
// [Inspectable]
|
||||
// public float IngredientQualityWeight = .5f;
|
||||
}
|
||||
|
||||
[Inspectable]
|
||||
public class CompoundCommodityData : CraftedItemData
|
||||
{
|
||||
public Dictionary<Guid, float> DemandProfile = new Dictionary<Guid, float>();
|
||||
|
||||
[Inspectable]
|
||||
public CompoundCommodityCategory Category;
|
||||
}
|
||||
|
||||
[Inspectable]
|
||||
public class ConsumableItemData : CraftedItemData
|
||||
{
|
||||
[Inspectable]
|
||||
public bool Stackable;
|
||||
|
||||
[Inspectable]
|
||||
public float Duration;
|
||||
|
||||
[InspectableTexture]
|
||||
public string Icon;
|
||||
|
||||
[Inspectable]
|
||||
public BezierCurve Effectiveness;
|
||||
}
|
||||
|
||||
public abstract class EquippableItemData : CraftedItemData
|
||||
{
|
||||
[InspectableTexture]
|
||||
public string Schematic;
|
||||
|
||||
[Inspectable]
|
||||
public float Durability;
|
||||
|
||||
[InspectableTemperature]
|
||||
public float MinimumTemperature;
|
||||
|
||||
[InspectableTemperature]
|
||||
public float MaximumTemperature;
|
||||
|
||||
// [InspectableField, SimplePerformanceStat]
|
||||
// public PerformanceStat DurabilityExponent = new PerformanceStat();
|
||||
//
|
||||
// [InspectableField, SimplePerformanceStat]
|
||||
// public PerformanceStat HeatExponent = new PerformanceStat();
|
||||
|
||||
[InspectableAnimationCurve]
|
||||
public BezierCurve HeatPerformanceCurve;
|
||||
|
||||
[Inspectable]
|
||||
public float ThermalResilience = 1;
|
||||
|
||||
[InspectableTexture]
|
||||
public string ActionBarIcon;
|
||||
|
||||
[InspectableSoundBank]
|
||||
public uint SoundBank;
|
||||
|
||||
[Inspectable]
|
||||
public List<AudioStat> AudioStats = new List<AudioStat>();
|
||||
|
||||
public abstract HardpointType HardpointType { get; }
|
||||
|
||||
private const int STEPS = 64;
|
||||
|
||||
private float? _optimum;
|
||||
|
||||
public float OptimalTemperature
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_optimum==null)
|
||||
{
|
||||
var samples = Enumerable.Range(0, STEPS).Select(i => (float) i / STEPS).ToArray();
|
||||
float max = 0;
|
||||
_optimum = 0;
|
||||
foreach (var f in samples)
|
||||
{
|
||||
var p = HeatPerformanceCurve?.Evaluate(f)??0;
|
||||
if (p > max)
|
||||
{
|
||||
max = p;
|
||||
_optimum = f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (float) (MinimumTemperature + _optimum * (MaximumTemperature - MinimumTemperature));
|
||||
}
|
||||
}
|
||||
|
||||
public float Performance(float temperature)
|
||||
{
|
||||
return saturate(HeatPerformanceCurve?.Evaluate(unlerp(MinimumTemperature, MaximumTemperature, temperature))??1);
|
||||
}
|
||||
}
|
||||
|
||||
[Inspectable]
|
||||
public class AudioStat
|
||||
{
|
||||
[InspectableAudioParameter]
|
||||
public uint Parameter;
|
||||
|
||||
[Inspectable]
|
||||
public PerformanceStat Stat = new PerformanceStat();
|
||||
}
|
||||
|
||||
[Inspectable]
|
||||
public class GearData : EquippableItemData
|
||||
{
|
||||
[Inspectable]
|
||||
public HardpointType Hardpoint;
|
||||
|
||||
public override HardpointType HardpointType => Hardpoint;
|
||||
}
|
||||
|
||||
[Inspectable]
|
||||
public class CargoBayData : EquippableItemData
|
||||
{
|
||||
[Inspectable]
|
||||
public Shape InteriorShape;
|
||||
|
||||
public override HardpointType HardpointType => HardpointType.Tool;
|
||||
}
|
||||
|
||||
[Inspectable]
|
||||
public class DockingBayData : CargoBayData
|
||||
{
|
||||
[Inspectable]
|
||||
public int2 MaxSize;
|
||||
}
|
||||
|
||||
|
||||
public class WeaponItemData : GearData
|
||||
{
|
||||
[Inspectable]
|
||||
public WeaponRange WeaponRange;
|
||||
|
||||
[Inspectable]
|
||||
public WeaponCaliber WeaponCaliber;
|
||||
|
||||
[Inspectable]
|
||||
public WeaponType WeaponType;
|
||||
|
||||
[Inspectable]
|
||||
public WeaponFireType WeaponFireTypes;
|
||||
|
||||
[Inspectable]
|
||||
public WeaponModifiers WeaponModifiers;
|
||||
}
|
||||
|
||||
[Inspectable]
|
||||
public class HullData : EquippableItemData
|
||||
{
|
||||
[Inspectable]
|
||||
public List<HardpointData> Hardpoints = new List<HardpointData>();
|
||||
|
||||
[InspectablePrefab]
|
||||
public string Prefab;
|
||||
|
||||
[Inspectable]
|
||||
public HullType HullType;
|
||||
|
||||
[Inspectable]
|
||||
public float GridOffset;
|
||||
|
||||
[Inspectable]
|
||||
public float Armor;
|
||||
|
||||
[Inspectable]
|
||||
public float Drag;
|
||||
|
||||
[Inspectable]
|
||||
public bool CanTow;
|
||||
|
||||
public Shape InteriorCells
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_interiorCells == null)
|
||||
{
|
||||
_interiorCells = Shape.Shrink();
|
||||
}
|
||||
|
||||
return _interiorCells;
|
||||
}
|
||||
}
|
||||
|
||||
private Shape _interiorCells;
|
||||
|
||||
public override HardpointType HardpointType => HardpointType.Hull;
|
||||
}
|
||||
|
||||
[Inspectable]
|
||||
public class HardpointData : ITintInspector
|
||||
{
|
||||
[Inspectable] public HardpointType Type;
|
||||
[Inspectable] public int2 Position;
|
||||
[Inspectable] public Shape Shape = new Shape();
|
||||
[Inspectable] public string Transform;
|
||||
[Inspectable] public ItemRotation Rotation;
|
||||
[Inspectable] public float Armor;
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{Enum.GetName(typeof(HardpointType), Type)} Hardpoint {Rotation.Arrow()}";
|
||||
}
|
||||
|
||||
public float3 TintColor
|
||||
{
|
||||
get
|
||||
{
|
||||
return GetColor(Type);
|
||||
}
|
||||
}
|
||||
|
||||
public static float3 GetColor(HardpointType type)
|
||||
{
|
||||
if (_tintColors == null)
|
||||
{
|
||||
var hardpointTypes = (HardpointType[]) Enum.GetValues(typeof(HardpointType));
|
||||
_tintColors = hardpointTypes.ToDictionary(x => x,
|
||||
x => ColorMath.HsvToRgb(float3(frac((float)(int)x/hardpointTypes.Length + .25f), 1, 1)));
|
||||
}
|
||||
|
||||
return _tintColors.TryGetValue(type, out var color) ? color : _tintColors[HardpointType.Hull];
|
||||
}
|
||||
|
||||
private static Dictionary<HardpointType, float3> _tintColors;
|
||||
}
|
||||
|
||||
public class PerformanceStat
|
||||
{
|
||||
public float Min;
|
||||
|
||||
public float Max;
|
||||
public float HeatExponentMultiplier;
|
||||
public float DurabilityExponentMultiplier;
|
||||
public float QualityExponent;
|
||||
|
||||
private Dictionary<Entity,Dictionary<Behavior,float>> _scaleModifiers;
|
||||
private Dictionary<Entity,Dictionary<Behavior,float>> _constantModifiers;
|
||||
|
||||
private Dictionary<Entity, Dictionary<Behavior, float>> ScaleModifiers =>
|
||||
_scaleModifiers = _scaleModifiers ?? new Dictionary<Entity, Dictionary<Behavior, float>>();
|
||||
|
||||
private Dictionary<Entity, Dictionary<Behavior, float>> ConstantModifiers =>
|
||||
_constantModifiers = _constantModifiers ?? new Dictionary<Entity, Dictionary<Behavior, float>>();
|
||||
|
||||
public Dictionary<Behavior, float> GetScaleModifiers(Entity entity)
|
||||
{
|
||||
if(!ScaleModifiers.ContainsKey(entity))
|
||||
ScaleModifiers[entity] = new Dictionary<Behavior, float>();
|
||||
|
||||
return ScaleModifiers[entity];
|
||||
}
|
||||
|
||||
public Dictionary<Behavior, float> GetConstantModifiers(Entity entity)
|
||||
{
|
||||
if(!ConstantModifiers.ContainsKey(entity))
|
||||
ConstantModifiers[entity] = new Dictionary<Behavior, float>();
|
||||
|
||||
return ConstantModifiers[entity];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 25f318aff9c2426dbbfda22cb37e63b2
|
||||
timeCreated: 1584282670
|
||||
328
Assets/Scripts/ServerShared/RuntimeGeometry.cs
Normal file
328
Assets/Scripts/ServerShared/RuntimeGeometry.cs
Normal file
|
|
@ -0,0 +1,328 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Unity.Mathematics;
|
||||
using static Unity.Mathematics.math;
|
||||
using float2 = Unity.Mathematics.float2;
|
||||
using int2 = Unity.Mathematics.int2;
|
||||
|
||||
[Inspectable]
|
||||
public class Shape
|
||||
{
|
||||
public bool[,] Cells;
|
||||
|
||||
private bool _dirty = true;
|
||||
|
||||
public Shape()
|
||||
{
|
||||
Cells = new bool[1, 1];
|
||||
Cells[0, 0] = true;
|
||||
}
|
||||
|
||||
public Shape(int width, int height)
|
||||
{
|
||||
Cells = new bool[width, height];
|
||||
}
|
||||
|
||||
public int Width
|
||||
{
|
||||
get { return Cells.GetLength(0); }
|
||||
set { Resize(value, Height); }
|
||||
}
|
||||
|
||||
public int Height
|
||||
{
|
||||
get { return Cells.GetLength(1); }
|
||||
set { Resize(Width, value); }
|
||||
}
|
||||
|
||||
public void Resize(int width, int height)
|
||||
{
|
||||
var newCells = new bool[width, height];
|
||||
|
||||
for (var x = 0; x < width; x++)
|
||||
{
|
||||
for (var y = 0; y < height; y++)
|
||||
{
|
||||
newCells[x, y] = x >= Width || y >= Height || Cells[x, y];
|
||||
}
|
||||
}
|
||||
|
||||
Cells = newCells;
|
||||
}
|
||||
|
||||
public int2 Rotate(int2 position, ItemRotation rotation)
|
||||
{
|
||||
return rotation switch
|
||||
{
|
||||
ItemRotation.Clockwise => int2(position.y, Width - 1 - position.x),
|
||||
ItemRotation.Reversed => int2(Width - 1 - position.x, Height - 1 - position.y),
|
||||
ItemRotation.CounterClockwise => int2(Height - 1 - position.y, position.x),
|
||||
_ => int2(position.x, position.y)
|
||||
};
|
||||
}
|
||||
|
||||
private int2[] _cachedShapeCoordinates;
|
||||
|
||||
public int2[] Coordinates
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_dirty)
|
||||
{
|
||||
_cachedShapeCoordinates = EnumerateShapeCoordinates().ToArray();
|
||||
_dirty = false;
|
||||
}
|
||||
|
||||
return _cachedShapeCoordinates;
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerable<int2> EnumerateShapeCoordinates()
|
||||
{
|
||||
for (var y = 0; y < Height; y++)
|
||||
{
|
||||
for (var x = 0; x < Width; x++)
|
||||
{
|
||||
if (Cells[x, y])
|
||||
yield return int2(x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int2[] _cachedAllShapeCoordinates;
|
||||
|
||||
public int2[] AllCoordinates => _cachedAllShapeCoordinates ??= EnumerateAllShapeCoordinates().ToArray();
|
||||
|
||||
private IEnumerable<int2> EnumerateAllShapeCoordinates()
|
||||
{
|
||||
for (var y = 0; y < Height; y++)
|
||||
{
|
||||
for (var x = 0; x < Width; x++)
|
||||
{
|
||||
yield return int2(x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private float2? _centerOfMass;
|
||||
|
||||
public float2 CenterOfMass => _centerOfMass ??= Coordinates
|
||||
.Aggregate(float2.zero, (total, coord) => total + coord) / Coordinates.Length;
|
||||
|
||||
public bool this[int2 pos]
|
||||
{
|
||||
get { return pos.x >= 0 && pos.y >= 0 && pos.x < Width && pos.y < Height && Cells[pos.x, pos.y]; }
|
||||
set
|
||||
{
|
||||
if (pos.x < 0 || pos.y < 0 || pos.x >= Width || pos.y >= Height)
|
||||
return;
|
||||
|
||||
_dirty = true;
|
||||
Cells[pos.x, pos.y] = value;
|
||||
}
|
||||
}
|
||||
|
||||
public Shape Shrink()
|
||||
{
|
||||
var shape = new Shape(Width, Height);
|
||||
foreach (var shapeCoord in Coordinates)
|
||||
{
|
||||
shape[shapeCoord] = (
|
||||
this[shapeCoord + int2(-1, -1)] && this[shapeCoord + int2(0, -1)] && this[shapeCoord + int2(1, -1)] &&
|
||||
this[shapeCoord + int2(-1, 0)] && this[shapeCoord + int2(1, 0)] &&
|
||||
this[shapeCoord + int2(-1, 1)] && this[shapeCoord + int2(0, 1)] && this[shapeCoord + int2(1, 1)]
|
||||
);
|
||||
}
|
||||
|
||||
return shape;
|
||||
}
|
||||
|
||||
public Shape Inset(Shape inset, int2 insetPosition, ItemRotation rotation = ItemRotation.None)
|
||||
{
|
||||
var shape = new Shape(max(Width, insetPosition.x + inset.Width - 1), max(Height, insetPosition.y + inset.Height - 1));
|
||||
foreach (var v in inset.Coordinates)
|
||||
{
|
||||
var insetCoord = inset.Rotate(v, rotation) + insetPosition;
|
||||
shape[insetCoord] = true;
|
||||
}
|
||||
|
||||
return shape;
|
||||
}
|
||||
|
||||
public Shape Expand()
|
||||
{
|
||||
var shape = new Shape(Width, Height);
|
||||
foreach (var shapeCoord in AllCoordinates)
|
||||
{
|
||||
shape[shapeCoord] = (
|
||||
this[shapeCoord + int2(-1, -1)] || this[shapeCoord + int2(0, -1)] || this[shapeCoord + int2(1, -1)] ||
|
||||
this[shapeCoord + int2(-1, 0)] || this[shapeCoord] || this[shapeCoord + int2(1, 0)] ||
|
||||
this[shapeCoord + int2(-1, 1)] || this[shapeCoord + int2(0, 1)] || this[shapeCoord + int2(1, 1)]
|
||||
);
|
||||
}
|
||||
|
||||
return shape;
|
||||
}
|
||||
|
||||
public bool FitsWithin(Shape other, out ItemRotation rotation, out int2 position)
|
||||
{
|
||||
foreach (var rot in (ItemRotation[])Enum.GetValues(typeof(ItemRotation)))
|
||||
{
|
||||
rotation = rot;
|
||||
if (FitsWithin(other, rot, out var pos))
|
||||
{
|
||||
position = pos;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
rotation = ItemRotation.None;
|
||||
position = int2.zero;
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool FitsWithin(Shape other, ItemRotation rotation, out int2 position)
|
||||
{
|
||||
var width = rotation == ItemRotation.Clockwise || rotation == ItemRotation.CounterClockwise ? Height : Width;
|
||||
var height = rotation == ItemRotation.Clockwise || rotation == ItemRotation.CounterClockwise ? Width : Height;
|
||||
|
||||
for (var x = 0; x < other.Width - width + 1; x++)
|
||||
{
|
||||
for (var y = 0; y < other.Height - height + 1; y++)
|
||||
{
|
||||
position = int2(x, y);
|
||||
var fits = true;
|
||||
foreach (var v in Coordinates)
|
||||
{
|
||||
fits = fits && other[Rotate(v, rotation) + position];
|
||||
if (!fits)
|
||||
break;
|
||||
}
|
||||
|
||||
if (fits)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
position = int2.zero;
|
||||
return false;
|
||||
}
|
||||
|
||||
public void SetLine(float2 a, float2 b)
|
||||
{
|
||||
if (a.Equals(b))
|
||||
return;
|
||||
|
||||
var steep = Math.Abs(b.y - a.y) > Math.Abs(b.x - a.x);
|
||||
if (steep)
|
||||
{
|
||||
a = new float2(a.y, a.x);
|
||||
b = new float2(b.y, b.x);
|
||||
}
|
||||
|
||||
if (a.x > b.x)
|
||||
{
|
||||
var temp = a;
|
||||
a = b;
|
||||
b = temp;
|
||||
}
|
||||
|
||||
var dx = b.x - a.x;
|
||||
var dy = b.y - a.y;
|
||||
var derr = Math.Abs(dy / dx);
|
||||
|
||||
var y = (int)Math.Round(a.y);
|
||||
var xStart = (int)Math.Round(a.x);
|
||||
var error = (a.y - y) + (xStart - a.x) * derr;
|
||||
|
||||
for (var x = xStart; x <= (int)Math.Round(b.x); x++)
|
||||
{
|
||||
if (x >= 0 && x < Width && y >= 0 && y < Height)
|
||||
{
|
||||
Cells[steep ? y : x, steep ? x : y] = true;
|
||||
}
|
||||
|
||||
error += derr;
|
||||
if (error >= 0.5f)
|
||||
{
|
||||
y += Math.Sign(dy);
|
||||
error -= 1f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Inspectable]
|
||||
public class HardpointData : ITintInspector
|
||||
{
|
||||
[Inspectable] public HardpointType Type;
|
||||
[Inspectable] public int2 Position;
|
||||
[Inspectable] public Shape Shape = new Shape();
|
||||
[Inspectable] public string Transform;
|
||||
[Inspectable] public ItemRotation Rotation;
|
||||
[Inspectable] public float Armor;
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{Enum.GetName(typeof(HardpointType), Type)} Hardpoint {Rotation.Arrow()}";
|
||||
}
|
||||
|
||||
public float3 TintColor
|
||||
{
|
||||
get { return GetColor(Type); }
|
||||
}
|
||||
|
||||
public static float3 GetColor(HardpointType type)
|
||||
{
|
||||
if (_tintColors == null)
|
||||
{
|
||||
var hardpointTypes = (HardpointType[])Enum.GetValues(typeof(HardpointType));
|
||||
_tintColors = hardpointTypes.ToDictionary(
|
||||
x => x,
|
||||
x => ColorMath.HsvToRgb(float3(frac((float)(int)x / hardpointTypes.Length + .25f), 1, 1)));
|
||||
}
|
||||
|
||||
return _tintColors.TryGetValue(type, out var color) ? color : _tintColors[HardpointType.Hull];
|
||||
}
|
||||
|
||||
private static Dictionary<HardpointType, float3> _tintColors;
|
||||
}
|
||||
|
||||
public class PerformanceStat
|
||||
{
|
||||
public float Min;
|
||||
public float Max;
|
||||
public float HeatExponentMultiplier;
|
||||
public float DurabilityExponentMultiplier;
|
||||
public float QualityExponent;
|
||||
|
||||
private Dictionary<Entity, Dictionary<Behavior, float>> _scaleModifiers;
|
||||
private Dictionary<Entity, Dictionary<Behavior, float>> _constantModifiers;
|
||||
|
||||
private Dictionary<Entity, Dictionary<Behavior, float>> ScaleModifiers =>
|
||||
_scaleModifiers ??= new Dictionary<Entity, Dictionary<Behavior, float>>();
|
||||
|
||||
private Dictionary<Entity, Dictionary<Behavior, float>> ConstantModifiers =>
|
||||
_constantModifiers ??= new Dictionary<Entity, Dictionary<Behavior, float>>();
|
||||
|
||||
public Dictionary<Behavior, float> GetScaleModifiers(Entity entity)
|
||||
{
|
||||
if (!ScaleModifiers.ContainsKey(entity))
|
||||
ScaleModifiers[entity] = new Dictionary<Behavior, float>();
|
||||
|
||||
return ScaleModifiers[entity];
|
||||
}
|
||||
|
||||
public Dictionary<Behavior, float> GetConstantModifiers(Entity entity)
|
||||
{
|
||||
if (!ConstantModifiers.ContainsKey(entity))
|
||||
ConstantModifiers[entity] = new Dictionary<Behavior, float>();
|
||||
|
||||
return ConstantModifiers[entity];
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/ServerShared/RuntimeGeometry.cs.meta
Normal file
3
Assets/Scripts/ServerShared/RuntimeGeometry.cs.meta
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 49b6dbff1ee0467e98507f18bf7e9ea3
|
||||
timeCreated: 1781541660
|
||||
Loading…
Reference in a new issue