Shops & Weapon Icons

Added stations to loadout generator
Overhauled Trade menu to sell station inventory contents
Placing stations in ZoneGenerator
Moved weapons to new item type: WeaponItemData
Implemented icon sets for weapon functionality
Renamed MegaCorporation to Faction
Implemented quality-dependent item pricing
Added unoccupied space helper function for entity
Moved sector generation settings to settings file
This commit is contained in:
Reinier Vens 2021-03-20 04:20:17 +00:00
commit fd81bf267e
33 changed files with 1640 additions and 1077 deletions

View file

@ -86,7 +86,7 @@ Material:
- _Mode: 0
- _OcclusionStrength: 1
- _Parallax: 0.02
- _Scale: 2.4224877
- _Scale: 0.5
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1

BIN
Assets/Resources/Settings.asset (Stored with Git LFS)

Binary file not shown.

File diff suppressed because it is too large Load diff

View file

@ -249,7 +249,7 @@ PrefabInstance:
- target: {fileID: 878382121558056004, guid: 2758dfa2744d7ad4d8877545189d116e,
type: 3}
propertyPath: m_AnchoredPosition.x
value: 0
value: 60.98
objectReference: {fileID: 0}
- target: {fileID: 878382121558056004, guid: 2758dfa2744d7ad4d8877545189d116e,
type: 3}
@ -1302,8 +1302,8 @@ Transform:
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 741153267}
m_LocalRotation: {x: 0.015506903, y: 0.9502416, z: -0.30741313, w: 0.047933225}
m_LocalPosition: {x: -117.51999, y: -77.08743, z: 149.09026}
m_LocalRotation: {x: 0.015506899, y: 0.9502416, z: -0.3074132, w: 0.04793321}
m_LocalPosition: {x: -117.52, y: -77.08742, z: 149.09026}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children:
- {fileID: 412917866}
@ -1773,8 +1773,8 @@ Transform:
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 965376321}
m_LocalRotation: {x: 0.015506903, y: 0.9502416, z: -0.30741313, w: 0.047933225}
m_LocalPosition: {x: -117.51999, y: -77.08743, z: 149.09026}
m_LocalRotation: {x: 0.015506899, y: 0.9502416, z: -0.3074132, w: 0.04793321}
m_LocalPosition: {x: -117.52, y: -77.08742, z: 149.09026}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 0}
@ -2010,22 +2010,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 3d7c7b928d043a3449b93bce9de03d1c, type: 3}
m_Name:
m_EditorClassIdentifier:
Settings:
LinkDensity: 0.5
ZoneCount: 196
NameGeneratorMinLength: 5
NameGeneratorMaxLength: 10
NameGeneratorOrder: 3
MegaCount: 12
BossCount: 3
NoisePosition: 0
CloudExponent: 10
CloudAmplitude: 0.01
NoiseAmplitude: 1
NoiseOffset: 0.3
NoiseGain: 0.7
NoiseLacunarity: 2
NoiseFrequency: 1
Settings: {fileID: 11400000, guid: cd2344e2001a37544aab0960c164d4ff, type: 2}
Dialog: {fileID: 1000515314}
InGame: 0
PanelPrototype: {fileID: 6584140821722344273}
@ -2737,7 +2722,7 @@ PrefabInstance:
- target: {fileID: 878382121558056004, guid: 2758dfa2744d7ad4d8877545189d116e,
type: 3}
propertyPath: m_AnchoredPosition.x
value: 0
value: 55.675
objectReference: {fileID: 0}
- target: {fileID: 878382121558056004, guid: 2758dfa2744d7ad4d8877545189d116e,
type: 3}

View file

@ -304,6 +304,27 @@ public class DatabaseInspector : EditorWindow
else if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(List<>))
{
var listType = field.FieldType.GenericTypeArguments[0];
// if (listType.IsEnum)
// {
// Space();
// using (new VerticalScope(GUI.skin.box))
// {
// var list = (IList) field.GetValue(obj);
// if (list == null)
// {
// list = (IList) Activator.CreateInstance(type);
// field.SetValue(obj, list);
// GUI.changed = true;
// }
// var isflags = type.GetCustomAttributes<FlagsAttribute>().Any();
// var names = Enum.GetNames(field.FieldType);
//
// for (var i = 0; i < list.Count; i++)
// {
// list[i] = Inspect(field.Name.SplitCamelCase(), (int) list[i], isflags ? names.Skip(1).ToArray() : names, isflags);
// }
// }
// }
if (listType.GetCustomAttribute<InspectableFieldAttribute>() != null)
{
Space();
@ -365,23 +386,6 @@ public class DatabaseInspector : EditorWindow
_listItemFoldouts.Add(o.GetHashCode());
else
_listItemFoldouts.Remove(o.GetHashCode());
// using (var h = new HorizontalScope())
// {
// if (GUI.Button(h.rect, GUIContent.none, GUIStyle.none))
// {
// if(_listItemFoldouts.Contains(o.GetHashCode()))
// _listItemFoldouts.Remove(o.GetHashCode());
// else
// _listItemFoldouts.Add(o.GetHashCode());
// }
// var foldoutRect = GetControlRect(false, GUILayout.Width(EditorGUIUtility.singleLineHeight));
// if (Event.current.type == EventType.Repaint)
// {
// var controlId = GUIUtility.GetControlID(1337, FocusType.Keyboard, position);
// EditorStyles.foldout.Draw(foldoutRect, GUIContent.none, controlId, !_listItemFoldouts.Contains(o.GetHashCode()));
// }
// GUILayout.Label(o.ToString(), EditorStyles.boldLabel, GUILayout.Height(EditorGUIUtility.singleLineHeight), GUILayout.ExpandWidth(true));
// }
var rect = GetControlRect(false,
GUILayout.Width(EditorGUIUtility.singleLineHeight));

View file

@ -237,14 +237,8 @@ public class DatabaseListView : EditorWindow
itemGroups = typedItems.GroupBy(item => Enum.GetName(typeof(SimpleCommodityCategory), (item as SimpleCommodityData).Category));
else if(_itemTypes[i] == typeof(CompoundCommodityData))
itemGroups = typedItems.GroupBy(item => Enum.GetName(typeof(CompoundCommodityCategory), (item as CompoundCommodityData).Category));
else if(_itemTypes[i] == typeof(GearData))
itemGroups = typedItems.GroupBy(item =>
{
var hp = Enum.GetName(typeof(HardpointType), (item as GearData).Hardpoint);
if (hp == null)
hp = "Invalid Hardpoint";
return hp;
});
else if(_itemTypes[i] == typeof(GearData) || _itemTypes[i] == typeof(WeaponItemData))
itemGroups = typedItems.GroupBy(item => Enum.GetName(typeof(HardpointType), (item as GearData).Hardpoint) ?? "Invalid Hardpoint");
else if (_itemTypes[i] == typeof(HullData))
itemGroups = typedItems.GroupBy(item => Enum.GetName(typeof(HullType), (item as HullData).HullType));
else itemGroups = typedItems.GroupBy(item => "All");

View file

@ -12,6 +12,11 @@ using UnityEngine;
public class GameSettingsEditor : Editor
{
private bool _showIcons;
private bool _showWeaponTypeIcons;
private bool _showWeaponModifierIcons;
private bool _showWeaponFiringTypeIcons;
private bool _showWeaponCaliberIcons;
private bool _showWeaponRangeIcons;
private bool _showProperties;
private bool _showDatabase;
@ -36,6 +41,61 @@ public class GameSettingsEditor : Editor
for (var i = 0; i < data.ItemIcons.Length; i++)
data.ItemIcons[i] = (Sprite) EditorGUILayout.ObjectField(hardpointNames[i], data.ItemIcons[i], typeof(Sprite), false);
var modifierNames = Enum.GetNames(typeof(WeaponModifiers));
if(data.WeaponModifierIcons.Length!=modifierNames.Length)
Array.Resize(ref data.WeaponModifierIcons, modifierNames.Length);
if (GUILayout.Button("Weapon Modifier Icons", EditorStyles.toolbarButton))
_showWeaponModifierIcons = !_showWeaponModifierIcons;
if(_showWeaponModifierIcons)
for (var i = 0; i < data.WeaponModifierIcons.Length; i++)
data.WeaponModifierIcons[i] = (Sprite) EditorGUILayout.ObjectField(modifierNames[i], data.WeaponModifierIcons[i], typeof(Sprite), false);
var weaponTypeNames = Enum.GetNames(typeof(WeaponType));
if(data.WeaponTypeIcons.Length!=weaponTypeNames.Length)
Array.Resize(ref data.WeaponTypeIcons, weaponTypeNames.Length);
if (GUILayout.Button("Weapon Type Icons", EditorStyles.toolbarButton))
_showWeaponTypeIcons = !_showWeaponTypeIcons;
if(_showWeaponTypeIcons)
for (var i = 0; i < data.WeaponTypeIcons.Length; i++)
data.WeaponTypeIcons[i] = (Sprite) EditorGUILayout.ObjectField(weaponTypeNames[i], data.WeaponTypeIcons[i], typeof(Sprite), false);
var weaponCaliberNames = Enum.GetNames(typeof(WeaponCaliber));
if(data.WeaponCaliberIcons.Length!=weaponCaliberNames.Length)
Array.Resize(ref data.WeaponCaliberIcons, weaponCaliberNames.Length);
if (GUILayout.Button("Weapon Caliber Icons", EditorStyles.toolbarButton))
_showWeaponCaliberIcons = !_showWeaponCaliberIcons;
if(_showWeaponCaliberIcons)
for (var i = 0; i < data.WeaponCaliberIcons.Length; i++)
data.WeaponCaliberIcons[i] = (Sprite) EditorGUILayout.ObjectField(weaponCaliberNames[i], data.WeaponCaliberIcons[i], typeof(Sprite), false);
var weaponFireTypeNames = Enum.GetNames(typeof(WeaponFireType));
if(data.WeaponFireTypeIcons.Length!=weaponFireTypeNames.Length)
Array.Resize(ref data.WeaponFireTypeIcons, weaponFireTypeNames.Length);
if (GUILayout.Button("Weapon Type Icons", EditorStyles.toolbarButton))
_showWeaponFiringTypeIcons = !_showWeaponFiringTypeIcons;
if(_showWeaponFiringTypeIcons)
for (var i = 0; i < data.WeaponFireTypeIcons.Length; i++)
data.WeaponFireTypeIcons[i] = (Sprite) EditorGUILayout.ObjectField(weaponFireTypeNames[i], data.WeaponFireTypeIcons[i], typeof(Sprite), false);
var weaponRangeNames = Enum.GetNames(typeof(WeaponRange));
if(data.WeaponRangeIcons.Length!=weaponRangeNames.Length)
Array.Resize(ref data.WeaponRangeIcons, weaponRangeNames.Length);
if (GUILayout.Button("Weapon Range Icons", EditorStyles.toolbarButton))
_showWeaponRangeIcons = !_showWeaponRangeIcons;
if(_showWeaponRangeIcons)
for (var i = 0; i < data.WeaponRangeIcons.Length; i++)
data.WeaponRangeIcons[i] = (Sprite) EditorGUILayout.ObjectField(weaponRangeNames[i], data.WeaponRangeIcons[i], typeof(Sprite), false);
serializedObject.ApplyModifiedProperties();
}
}

View file

@ -79,8 +79,9 @@ public class ActionGameManager : MonoBehaviour
public PostProcessVolume DeathPP;
public PostProcessVolume HeatstrokePP;
public PostProcessVolume SevereHeatstrokePP;
[Header("Scene Links")]
public TradeMenu TradeMenu;
public Prototype HostileTargetIndicator;
public PlaceUIElementWorldspace ViewDot;
public PlaceUIElementWorldspace TargetIndicator;
@ -143,6 +144,10 @@ public class ActionGameManager : MonoBehaviour
(float2(0, -1), "Rear")
};
public EntitySettings NewEntitySettings
{
get => MessagePackSerializer.Deserialize<EntitySettings>(MessagePackSerializer.Serialize(Settings.GameplaySettings.DefaultEntitySettings));
}
public void SaveLoadout(EntityPack pack)
{
@ -513,26 +518,6 @@ public class ActionGameManager : MonoBehaviour
BindToEntity(targetEntity);
}
}
// var stationType = Database.GetAll<HullData>().First(x=>x.HullType==HullType.Station);
// var stationHull = ItemManager.CreateInstance(stationType) as EquippableItem;
// var stationParent = Zone.PlanetInstances.Values.OrderByDescending(p => p.BodyData.Mass.Value).ElementAt(3);
// var stationParentOrbit = stationParent.Orbit.Data.ID;
// var stationParentPos = Zone.GetOrbitPosition(stationParentOrbit);
// var stationPos = stationParentPos + ItemManager.Random.NextFloat2Direction() * stationParent.GravityWellRadius.Value * .1f;
// var stationOrbit = Zone.CreateOrbit(stationParentOrbit, stationPos);
// var station = new OrbitalEntity(ItemManager, Zone, stationHull, stationOrbit.ID, Settings.DefaultEntitySettings);
// Zone.Entities.Add(station);
// var dockingBayData = Database.GetAll<DockingBayData>().First();
// var dockingBay = ItemManager.CreateInstance(dockingBayData) as EquippableItem;
// station.TryEquip(dockingBay);
// station.Activate();
//
// DoDock(station, station.DockingBays.First());
// ship.ExitWormhole(
// SectorRenderer.WormholeInstances.Keys.First().Position,
// ItemManager.Random.NextFloat2Direction() * Settings.GameplaySettings.WormholeExitVelocity);
}
public void Dock()
@ -550,6 +535,7 @@ public class ActionGameManager : MonoBehaviour
{
UnbindEntity();
DoDock(entity, bay);
TradeMenu.Inventory = entity.CargoBays.First();
AkSoundEngine.PostEvent("Dock", gameObject);
return;
}

View file

@ -21,6 +21,7 @@ public class GameSettings : ScriptableObject
public int AsteroidMeshCount = 5;
public float MinimapAsteroidSize = 3;
public float PlanetRotationSpeed = 1;
public SectorGenerationSettings SectorGenerationSettings;
public BodySettingsCollection[] BodySettingsCollections;
public PlanetSettings PlanetSettings;
public ZoneGenerationSettings ZoneSettings;
@ -32,6 +33,37 @@ public class GameSettings : ScriptableObject
public Gradient ArmorGradient;
public Gradient DurabilityGradient;
[HideInInspector] public Sprite[] ItemIcons;
[HideInInspector] public Sprite[] WeaponTypeIcons;
[HideInInspector] public Sprite[] WeaponCaliberIcons;
[HideInInspector] public Sprite[] WeaponRangeIcons;
[HideInInspector] public Sprite[] WeaponFireTypeIcons;
[HideInInspector] public Sprite[] WeaponModifierIcons;
public Sprite GetIcon(WeaponType type) => WeaponTypeIcons[(int) type];
public Sprite GetIcon(WeaponRange range) => WeaponRangeIcons[(int) range];
public Sprite GetIcon(WeaponCaliber caliber) => WeaponCaliberIcons[(int) caliber];
public IEnumerable<Sprite> GetIcons(WeaponFireType type)
{
var count = Enum.GetValues(typeof(WeaponFireType)).Length;
var t = (int) type;
for (int i = 0; i < count - 1; i++)
{
if (1 << i == (1 << i & t))
yield return WeaponFireTypeIcons[i + 1];
}
}
public IEnumerable<Sprite> GetIcons(WeaponModifiers type)
{
var count = Enum.GetValues(typeof(WeaponModifiers)).Length;
var t = (int) type;
for (int i = 0; i < count - 1; i++)
{
if (1 << i == (1 << i & t))
yield return WeaponModifierIcons[i + 1];
}
}
}
[Serializable]

View file

@ -14,7 +14,7 @@ using Random = UnityEngine.Random;
public class MainMenu : MonoBehaviour
{
public SectorGenerationSettings Settings;
public GameSettings Settings;
public ConfirmationDialog Dialog;
public bool InGame;
public Prototype PanelPrototype;
@ -114,9 +114,9 @@ public class MainMenu : MonoBehaviour
Dialog.Title.text = "Generating Galaxy";
Dialog.AddProperty(() => generatorState);
Dialog.Show();
Settings.NoisePosition = Random.value * 100;
Settings.SectorGenerationSettings.NoisePosition = Random.value * 100;
var task = Task.Run(() => new Sector(Settings, ActionGameManager.Database, 0, setState));
var task = Task.Run(() => new Sector(Settings.SectorGenerationSettings, ActionGameManager.Database, 0, setState));
task.ContinueWith(task => Observable.NextFrame().Subscribe(_ =>
{
ActionGameManager.PlayerSettings.CurrentRun = null;

View file

@ -36,7 +36,7 @@ public class Corporation : DatabaseEntry, INamedEntry
}
[RethinkTable("Galaxy"), Inspectable, MessagePackObject, JsonObject(MemberSerialization.OptIn)]
public class MegaCorporation : DatabaseEntry, INamedEntry
public class Faction : DatabaseEntry, INamedEntry
{
[InspectableField, JsonProperty("name"), Key(1)]
public string Name;
@ -71,7 +71,7 @@ public class MegaCorporation : DatabaseEntry, INamedEntry
[InspectableField, JsonProperty("influence"), Key(11)]
public int InfluenceDistance = 4;
[InspectableDatabaseLink(typeof(MegaCorporation)), RangedFloat(0, 1), JsonProperty("allegiance"), Key(12)]
[InspectableDatabaseLink(typeof(Faction)), RangedFloat(0, 1), JsonProperty("allegiance"), Key(12)]
public Dictionary<Guid, float> Allegiance = new Dictionary<Guid, float>();
[IgnoreMember] public string EntryName

View file

@ -31,7 +31,7 @@ public interface INamedEntry
//Union(10, typeof(ZoneData)),
Union(11, typeof(PlayerData)),
Union(12, typeof(Corporation)),
Union(13, typeof(MegaCorporation)),
Union(13, typeof(Faction)),
Union(14, typeof(OrbitalEntity)),
Union(15, typeof(OrbitData)),
Union(16, typeof(BodyData)),
@ -49,6 +49,7 @@ public interface INamedEntry
Union(28, typeof(PlanetData)),
Union(29, typeof(CargoBayData)),
Union(30, typeof(DockingBayData)),
Union(31, typeof(WeaponItemData)),
JsonObject(MemberSerialization.OptIn), JsonConverter(typeof(JsonKnownTypesConverter<DatabaseEntry>))]
//[Union(21, typeof(ContractData))]
//[Union(22, typeof(Station))]

View file

@ -13,7 +13,7 @@ using int2 = Unity.Mathematics.int2;
public abstract class Entity
{
public Zone Zone;
public MegaCorporation Faction;
public Faction Faction;
public EquippableItem Hull;
public float3 Position;
@ -78,6 +78,8 @@ public abstract class Entity
}
}
public HullData HullData { get; }
public EntitySettings Settings { get; }
public bool OverrideShutdown { get; set; }
@ -162,6 +164,7 @@ public abstract class Entity
ItemManager = itemManager;
Zone = zone;
Hull = hull;
HullData = itemManager.GetData(hull) as HullData;
Name = hull.Name;
MapEntity();
TriggerGroups = new (List<Weapon> triggers, List<EquippedItem> items)[itemManager.GameplaySettings.TriggerGroupCount];
@ -277,6 +280,21 @@ public abstract class Entity
return CargoBays.FirstOrDefault(c => c.ItemsOfType.ContainsKey(itemDataID));
}
public Shape UnoccupiedSpace
{
get
{
var emptyShape = new Shape(HullData.Shape.Width, HullData.Shape.Height);
foreach (var v in HullData.Shape.Coordinates)
{
if (HullData.InteriorCells[v] && GearOccupancy[v.x, v.y] == null && Hardpoints[v.x,v.y] == null)
emptyShape[v] = true;
}
return emptyShape;
}
}
// Attempts to move a given number of items of the given type to the target Entity
// Returns the number of items successfully transferred
public int TryTransferItems(Entity target, Guid itemDataID, int quantity)
@ -1040,7 +1058,18 @@ public class EquippedCargoBay : EquippedItem
public float Mass { get; private set; }
public float ThermalMass { get; private set; }
public string Name { get; }
public Shape UnoccupiedSpace
{
get
{
var unoccupied = new Shape(Data.InteriorShape.Width, Data.InteriorShape.Height);
foreach (var v in unoccupied.AllCoordinates)
unoccupied[v] = Occupancy[v.x, v.y] == null;
return unoccupied;
}
}
public EquippedCargoBay(ItemManager itemManager, EquippableItem item, int2 position, Entity entity, string name) : base(itemManager, item, position, entity)
{
Data = ItemManager.GetData(EquippableItem) as CargoBayData;
@ -1101,6 +1130,7 @@ public class EquippedCargoBay : EquippedItem
if (remainingQuantity == 0) return true;
}
// TODO: Try alternate item rotations / use Shape.FitsWithin
// Search all the space in the cargo bay for an empty space where the item fits
foreach (var cargoCoord in Data.InteriorShape.Coordinates)
{

View file

@ -87,7 +87,7 @@ public static class EntitySerializer
private static void Restore(ItemManager itemManager, Zone zone, EntityPack pack, Entity entity, bool instantiate = false)
{
entity.Name = pack.Name;
entity.Faction = itemManager.ItemData.Get<MegaCorporation>(pack.Faction);
entity.Faction = itemManager.ItemData.Get<Faction>(pack.Faction);
entity.Children = pack.Children.Select(c =>
{
var child = Unpack(itemManager, zone, c, instantiate);

View file

@ -44,6 +44,60 @@ public enum HardpointType
ControlModule
}
public enum WeaponType
{
ElectromagneticallyPropelled,
ExplosivelyPropelled,
Laser,
Electrostatic,
ParticleProjection,
Missile,
MicroMissile,
SplitMissile,
Mine,
Jet
}
public enum WeaponRange
{
Melee,
Short,
Medium,
Long
}
public enum WeaponCaliber
{
Small,
Medium,
Large,
ExtraLarge
}
[Flags]
public enum WeaponFireType
{
None = 0,
Direct = 1 << 0,
Guided = 1 << 1,
Seeking = 1 << 2,
Continuous = 1 << 3,
Charged = 1 << 4
}
[Flags]
public enum WeaponModifiers
{
None = 0,
Airburst = 1 << 0,
Incendiary = 1 << 1,
ArmorPenetrating = 1 << 2,
NegativeEntropy = 1 << 3,
RapidFire = 1 << 4,
Burst = 1 << 5,
Cluster = 1 << 6
}
public enum DamageType
{
Kinetic,

View file

@ -219,14 +219,7 @@ public class Shape
}
}
[MessagePackObject,
Union(0, typeof(SimpleCommodityData)),
Union(1, typeof(CompoundCommodityData)),
Union(2, typeof(GearData)),
Union(3, typeof(HullData)),
Union(4, typeof(CargoBayData)),
Union(5, typeof(DockingBayData)),
JsonObject(MemberSerialization.OptIn), JsonConverter(typeof(JsonKnownTypesConverter<ItemData>))]
[MessagePackObject, JsonObject(MemberSerialization.OptIn), JsonConverter(typeof(JsonKnownTypesConverter<ItemData>))]
public abstract class ItemData : DatabaseEntry, INamedEntry
{
[InspectableField, JsonProperty("name"), Key(1)]
@ -235,7 +228,7 @@ public abstract class ItemData : DatabaseEntry, INamedEntry
[InspectableText, JsonProperty("description"), Key(2)]
public string Description;
[InspectableDatabaseLink(typeof(MegaCorporation)), JsonProperty("creator"), Key(3)]
[InspectableDatabaseLink(typeof(Faction)), JsonProperty("creator"), Key(3)]
public Guid Manufacturer;
[InspectableField, JsonProperty("mass"), Key(4)]
@ -288,12 +281,7 @@ public class SimpleCommodityData : ItemData
public SimpleCommodityCategory Category;
}
[MessagePackObject,
Union(0, typeof(CompoundCommodityData)),
Union(1, typeof(GearData)),
Union(2, typeof(HullData)),
JsonObject(MemberSerialization.OptIn),
JsonConverter(typeof(JsonKnownTypesConverter<CraftedItemData>))]
[MessagePackObject, JsonObject(MemberSerialization.OptIn), JsonConverter(typeof(JsonKnownTypesConverter<CraftedItemData>))]
public abstract class CraftedItemData : ItemData
{
[InspectableField, JsonProperty("ingredientQualityWeight"), Key(9)]
@ -310,9 +298,7 @@ public class CompoundCommodityData : CraftedItemData
public CompoundCommodityCategory Category;
}
[Union(0, typeof(GearData)),
Union(1, typeof(HullData)),
JsonObject(MemberSerialization.OptIn), JsonConverter(typeof(JsonKnownTypesConverter<EquippableItemData>))]
[JsonObject(MemberSerialization.OptIn), JsonConverter(typeof(JsonKnownTypesConverter<EquippableItemData>))]
public abstract class EquippableItemData : CraftedItemData
{
[InspectableTexture, JsonProperty("schematic"), Key(10)]
@ -405,7 +391,25 @@ public class DockingBayData : CargoBayData
{
[InspectableField, JsonProperty("maxSize"), Key(21)]
public int2 MaxSize;
[IgnoreMember] public override HardpointType HardpointType => HardpointType.Tool;
}
[RethinkTable("Items"), Inspectable, MessagePackObject, JsonObject(MemberSerialization.OptIn)]
public class WeaponItemData : GearData
{
[InspectableField, JsonProperty("range"), Key(21)]
public WeaponRange WeaponRange;
[InspectableField, JsonProperty("caliber"), Key(22)]
public WeaponCaliber WeaponCaliber;
[InspectableField, JsonProperty("weaponType"), Key(23)]
public WeaponType WeaponType;
[InspectableField, JsonProperty("fireTypes"), Key(24)]
public WeaponFireType WeaponFireTypes;
[InspectableField, JsonProperty("modifiers"), Key(25)]
public WeaponModifiers WeaponModifiers;
}
[RethinkTable("Items"), Inspectable, MessagePackObject, JsonObject(MemberSerialization.OptIn)]

View file

@ -272,144 +272,12 @@ public class ItemManager
return result;
}
// public Entity CreateEntity(Guid zoneID, Guid corporation, Guid loadout)
// {
// if (!(ItemData.Get(loadout) is LoadoutData loadoutData))
// {
// _logger("Attempted to spawn invalid loadout ID");
// return null;
// }
//
// if (!(ItemData.Get(loadoutData.Hull) is HullData hullData))
// {
// _logger("Attempted to spawn loadout with invalid hull ID");
// return null;
// }
//
// if (!(ItemData.Get(zoneID) is ZoneData zoneData))
// {
// _logger("Attempted to spawn entity with invalid zone ID");
// return null;
// }
//
// if (!(ItemData.Get(corporation) is Corporation corpData))
// {
// _logger("Attempted to spawn entity with invalid corporation ID");
// return null;
// }
//
// var gearData = loadoutData.Gear
// .Take(hullData.Hardpoints.Count)
// .Where(id => id != Guid.Empty)
// .Select(id => ItemData.Get<GearData>(id))
// .ToArray();
//
// if (gearData.Any(g=>g==null))
// {
// _logger("Attempted to spawn loadout with invalid gear ID");
// return null;
// }
//
// var gear = gearData
// .Select(gd => CreateInstance(gd.ID, GlobalData.StartingGearQualityMin, GlobalData.StartingGearQualityMax))
// .ToArray();
//
// if (gear.Any(g=>g==null))
// return null;
//
// foreach(var g in gear)
// ItemData.Add(g);
//
// var cargoData = loadoutData.CompoundCargo
// .SelectMany(x => Enumerable.Repeat(ItemData.Get<CraftedItemData>(x.Key), x.Value))
// .ToArray();
//
// if (cargoData.Any(g=>g==null))
// {
// _logger("Attempted to spawn loadout with invalid cargo ID");
// return null;
// }
//
// var cargo = cargoData
// .Select(gd => CreateInstance(gd.ID, GlobalData.StartingGearQualityMin, GlobalData.StartingGearQualityMax))
// .ToArray();
//
// if (cargo.Any(g=>g==null))
// return null;
//
// foreach(var c in cargo)
// ItemData.Add(c);
//
// var simpleCargo = loadoutData.SimpleCargo?
// .Select(x => CreateInstance(x.Key, x.Value))
// .ToArray() ?? new SimpleCommodity[0];
//
// if (simpleCargo.Any(g=>g==null))
// return null;
//
// var hull = CreateInstance(loadoutData.Hull, GlobalData.StartingGearQualityMin, GlobalData.StartingGearQualityMax);
//
// if(hull==null)
// return null;
//
// // Get target zone
// var zone = _zones[zoneID];
//
// if (hullData.HullType == HullType.Ship)
// {
// var entity = CreateShip(hull.ID, gear.Select(g => g.ID),
// cargo.Select(c => c.ID).Concat(simpleCargo.Select(c => c.ID)), zone, corporation, Guid.Empty, loadoutData.Name);
// entity.Active = true;
// return entity;
// }
//
// if (hullData.HullType == HullType.Station)
// {
// var distance = lerp(.2f, .8f, Random.NextFloat()) * zoneData.Radius;
// var orbit = new OrbitData
// {
// Context = this,
// Distance = new ReactiveProperty<float>(distance),
// Parent = zone.Orbits.Values.Select(o=>o.Data)
// .First(orbitData => orbitData.Parent == Guid.Empty).ID,
// Phase = Random.NextFloat()
// };
// zone.AddOrbit(orbit);
//
// 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, corporation)
// {
// Name = $"{loadoutData.Name} {Random.NextInt(1,255):X}",
// Temperature = 293,
// Population = 4
// };
// entity.Active = true;
// var parentCorp = ItemData.Get<MegaCorporation>(corpData.Parent);
// foreach (var attribute in parentCorp.Personality)
// entity.Personality[attribute.Key] = attribute.Value;
// ItemData.Add(entity);
//
// zone.Entities[entity.ID] = entity;
// return entity;
// }
//
// return null;
// }
//
// public Ship CreateShip(Guid hull, IEnumerable<Guid> gear, IEnumerable<Guid> cargo, Zone zone, Guid corporation, Guid homeEntity, string typeName)
// {
//
// var ship = new Ship(this, hull, gear, cargo, zone, corporation)
// {
// Name = $"{typeName} {Random.NextInt(1,255):X}",
// HomeEntity = homeEntity
// };
// ItemData.Add(ship);
//
// zone.Entities[ship.ID] = ship;
// return ship;
// }
public int GetPrice(CraftedItemInstance item)
{
var data = GetData(item);
return (int) (GameplaySettings.QualityPriceModifier.Evaluate(item.Quality) * data.Price);
}
public SimpleCommodity CreateInstance(SimpleCommodityData item, int count)
{
if (item != null)

View file

@ -11,7 +11,7 @@ public class LoadoutGenerator
public ItemManager ItemManager { get; }
public Sector Sector { get; }
public SectorZone Zone { get; }
public MegaCorporation Faction { get; }
public Faction Faction { get; }
public float PriceExponent { get; }
public LoadoutGenerator(
@ -19,7 +19,7 @@ public class LoadoutGenerator
ItemManager itemManager,
Sector sector,
SectorZone zone,
MegaCorporation faction,
Faction faction,
float priceExponent)
{
Random = random;
@ -48,6 +48,38 @@ public class LoadoutGenerator
return EntitySerializer.Pack(entity);
}
public EntityPack GenerateStationLoadout()
{
var hullData = RandomHull(HullType.Station);
var hull = ItemManager.CreateInstance(hullData) as EquippableItem;
var entity = new OrbitalEntity(ItemManager, null, hull, Guid.Empty, ItemManager.GameplaySettings.DefaultEntitySettings);
entity.Faction = Faction;
OutfitEntity(entity);
var emptyShape = entity.UnoccupiedSpace;
var dockingBayData = RandomItem<DockingBayData>(item => item.Shape.FitsWithin(emptyShape, out _, out _));
if (dockingBayData == null) throw new InvalidLoadoutException("No compatible docking bay found for station!");
dockingBayData.Shape.FitsWithin(emptyShape, out var cargoRotation, out var cargoPosition);
var dockingBay = ItemManager.CreateInstance(dockingBayData) as EquippableItem;
dockingBay.Rotation = cargoRotation;
if (!entity.TryEquip(dockingBay, cargoPosition))
{
throw new InvalidLoadoutException("Failed to equip selected docking bay!");
}
var cargo = entity.CargoBays.First();
var inventory = RandomItems<EquippableItemData>(16, data => !(data is CargoBayData));
foreach (var item in inventory)
{
var instance = ItemManager.CreateInstance(item);
cargo.TryStore(instance);
}
return EntitySerializer.Pack(entity);
}
public HullData RandomHull(HullType type)
{
return ItemManager.ItemData.GetAll<HullData>()
@ -55,13 +87,13 @@ public class LoadoutGenerator
.WeightedRandomElements(ref Random,
item =>
(Faction == null || item.Manufacturer == Faction.ID ? 1 : Faction.Allegiance[item.Manufacturer]) / // Prioritize items from allied manufacturers
Zone.Distance[Sector.HomeZones[ItemManager.ItemData.Get<MegaCorporation>(item.Manufacturer)]] / // Penalize distance to manufacturer headquarters
Zone.Distance[Sector.HomeZones[ItemManager.ItemData.Get<Faction>(item.Manufacturer)]] / // Penalize distance to manufacturer headquarters
pow(item.Price, PriceExponent), // Penalize item price to a controllable degree
1
).FirstOrDefault();
}
public T RandomItem<T>(Predicate<T> filter = null) where T : EquippableItemData
public T[] RandomItems<T>(int count, Predicate<T> filter = null) where T : EquippableItemData
{
return ItemManager.ItemData.GetAll<T>()
.Where(item => Sector.ContainsFaction(item.Manufacturer) &&
@ -69,11 +101,16 @@ public class LoadoutGenerator
(filter?.Invoke(item) ?? true))
.WeightedRandomElements(ref Random, item =>
(Faction == null || item.Manufacturer == Faction.ID ? 1 : Faction.Allegiance[item.Manufacturer]) * // Prioritize items from allied manufacturers
item.Shape.Coordinates.Length / // Prioritize items that fill more of the hardpoint's slots
Zone.Distance[Sector.HomeZones[ItemManager.ItemData.Get<MegaCorporation>(item.Manufacturer)]] / // Penalize distance to manufacturer headquarters
item.Shape.Coordinates.Length * item.Shape.Coordinates.Length / // Prioritize larger items
Zone.Distance[Sector.HomeZones[ItemManager.ItemData.Get<Faction>(item.Manufacturer)]] / // Penalize distance to manufacturer headquarters
pow(item.Price, PriceExponent), // Penalize item price to a controllable degree
1
).FirstOrDefault();
count
);
}
public T RandomItem<T>(Predicate<T> filter = null) where T : EquippableItemData
{
return RandomItems(1, filter).FirstOrDefault();
}
public T RandomItem<T>(HardpointData hardpoint, Predicate<T> filter = null) where T : EquippableItemData
@ -88,7 +125,7 @@ public class LoadoutGenerator
var hullData = ItemManager.GetData(entity.Hull) as HullData;
foreach (var v in hullData.Shape.Coordinates) entity.HullConductivity[v.x, v.y] = true;
var previousItems = new List<EquippableItemData>();
foreach (var hardpoint in hullData.Hardpoints)
foreach (var hardpoint in hullData.Hardpoints.OrderByDescending(h=>h.Shape.Coordinates.Length))
{
if (hardpoint.Type == HardpointType.ControlModule)
{
@ -103,7 +140,7 @@ public class LoadoutGenerator
}
else
{
// If a previously selected item fits, use that one
// If a previously selected item fits, use that one (this is why we must process larger hardpoints first)
var itemData = previousItems
.FirstOrDefault(i => i.HardpointType == hardpoint.Type && i.Shape.FitsWithin(hardpoint.Shape, hardpoint.Rotation, out _));
itemData ??= RandomItem<GearData>(hardpoint);
@ -121,26 +158,31 @@ public class LoadoutGenerator
}
}
var emptyShape = new Shape(hullData.Shape.Width, hullData.Shape.Height);
foreach (var v in hullData.Shape.Coordinates)
{
if (hullData.InteriorCells[v] && entity.Hardpoints[v.x, v.y] == null)
emptyShape[v] = true;
}
var emptyShape = entity.UnoccupiedSpace;
var cargoData = RandomItem<CargoBayData>(item =>
!(item is DockingBayData) &&
item.Shape.FitsWithin(emptyShape, out _, out _));
if (cargoData == null) throw new InvalidLoadoutException("No compatible cargo bay found for entity!");
cargoData.Shape.FitsWithin(emptyShape, out var cargoRotation, out var cargoPosition);
var cargo = ItemManager.CreateInstance(cargoData) as EquippableItem;
cargo.Rotation = cargoRotation;
if (!entity.TryEquip(cargo, cargoPosition))
throw new InvalidLoadoutException("Failed to equip selected cargo bay!");
emptyShape = entity.UnoccupiedSpace;
var capacitorData = RandomItem<GearData>(item =>
item.Behaviors.Any(b => b is CapacitorData) &&
item.Shape.FitsWithin(emptyShape, out _, out _));
if (capacitorData == null) throw new InvalidLoadoutException("No compatible capacitor found for entity!");
if(!capacitorData.Shape.FitsWithin(emptyShape, out var capacitorRotation, out var capacitorPosition))
throw new InvalidLoadoutException("Failed to equip selected capacitor!");
capacitorData.Shape.FitsWithin(emptyShape, out var capacitorRotation, out var capacitorPosition);
var capacitor = ItemManager.CreateInstance(capacitorData) as EquippableItem;
capacitor.Rotation = capacitorRotation;
if (!entity.TryEquip(capacitor, capacitorPosition))
{
throw new InvalidLoadoutException("Failed to equip selected capacitor!");
}
}
}

View file

@ -12,18 +12,18 @@ using Random = Unity.Mathematics.Random;
public class Sector
{
public Dictionary<MegaCorporation, SectorZone> HomeZones = new Dictionary<MegaCorporation, SectorZone>();
public Dictionary<MegaCorporation, SectorZone> BossZones = new Dictionary<MegaCorporation, SectorZone>();
public Dictionary<Faction, SectorZone> HomeZones = new Dictionary<Faction, SectorZone>();
public Dictionary<Faction, SectorZone> BossZones = new Dictionary<Faction, SectorZone>();
public SectorGenerationSettings Settings { get; }
public MegaCorporation[] Factions { get; }
public Faction[] Factions { get; }
public SectorZone[] Zones { get; }
public SectorZone Entrance { get; }
public SectorZone Exit { get; }
private HashSet<Guid> _containedFactions;
private SectorZone[] _exitPath;
private Dictionary<MegaCorporation, MarkovNameGenerator> _nameGenerators = new Dictionary<MegaCorporation, MarkovNameGenerator>();
private Dictionary<Faction, MarkovNameGenerator> _nameGenerators = new Dictionary<Faction, MarkovNameGenerator>();
public SectorZone[] ExitPath
{
@ -36,7 +36,7 @@ public class Sector
public Sector(DatabaseCache database, SavedGame savedGame)
{
Settings = savedGame.Settings;
Factions = savedGame.Factions.Select(database.Get<MegaCorporation>).ToArray();
Factions = savedGame.Factions.Select(database.Get<Faction>).ToArray();
Zones = savedGame.Zones.Select(zone =>
{
return new SectorZone
@ -70,7 +70,7 @@ public class Sector
public Sector(SectorGenerationSettings settings, DatabaseCache database, uint seed = 0, Action<string> progressCallback = null, float minLineSeparation = .01f)
{
Settings = settings;
var megas = database.GetAll<MegaCorporation>();
var megas = database.GetAll<Faction>();
var random = new Random(seed == 0 ? (uint) (DateTime.Now.Ticks % uint.MaxValue) : seed);
Factions = megas.OrderBy(x => random.NextFloat()).Take(settings.MegaCount).ToArray();
@ -382,8 +382,8 @@ public class SectorZone
public List<SectorZone> AdjacentZones = new List<SectorZone>();
public int Isolation;
public Dictionary<SectorZone, int> Distance;
public MegaCorporation[] Factions;
public MegaCorporation Owner;
public Faction[] Factions;
public Faction Owner;
public Zone Contents;
public ZonePack PackedContents;
}

View file

@ -134,6 +134,7 @@ public class GameplaySettings
{
public EntitySettings DefaultEntitySettings;
public RarityTier[] Tiers;
public ExponentialLerp QualityPriceModifier;
public float DefaultShutdownPerformance = .25f;
public float SevereHeatstrokeRiskThreshold = .25f;
public float WormholeDepth = 1000;

View file

@ -221,14 +221,22 @@ public static class ZoneGenerator
return planetData;
}).ToList();
if (sectorZone.Owner != null)
var nearestFaction = sector.Factions.MinBy(f => sector.HomeZones[f].Distance[sectorZone]);
var nearestFactionHomeZone = sector.HomeZones[nearestFaction];
var factionPresence = nearestFaction.InfluenceDistance - nearestFactionHomeZone.Distance[sectorZone];
var loadoutGenerator = new LoadoutGenerator(ref random, itemManager, sector, sectorZone, nearestFaction, 1);
for (int i = 0; i < factionPresence; i++)
{
var loadoutGenerator = new LoadoutGenerator(ref random, itemManager, sector, sectorZone, sectorZone.Owner, 1);
for (int i = 0; i < 3; i++)
{
pack.Entities.Add(loadoutGenerator.GenerateShipLoadout());
}
pack.Entities.Add(loadoutGenerator.GenerateShipLoadout());
}
var replacePlanet = pack.Planets.MinBy(p => p.Mass.Value);
pack.Planets.Remove(replacePlanet);
var stationOrbit = replacePlanet.Orbit;
var station = loadoutGenerator.GenerateStationLoadout();
((OrbitalEntityPack) station).Orbit = stationOrbit;
pack.Entities.Add(station);
return pack;
}

View file

@ -47,7 +47,7 @@ public class MenuPanel : MonoBehaviour
{
foreach (var tabButton in _tabs.Values)
{
tabButton.gameObject.SetActive(!tabButton.RequireParent || GameManager.CurrentEntity.Parent != null);
tabButton.gameObject.SetActive(!tabButton.RequireDock || GameManager.DockedEntity != null);
}
}

View file

@ -15,5 +15,5 @@ public class MenuTabButton : MonoBehaviour
public Button Button;
public MenuTab Tab;
public TextMeshProUGUI Text;
public bool RequireParent;
public bool RequireDock;
}

View file

@ -362,7 +362,7 @@ public class PropertiesPanel : MonoBehaviour
{
var data = Context.ItemData.Get<ItemData>(item.Data);
AddProperty(data.Description);//.Label.fontStyle = FontStyles.Normal;
var manufacturer = Context.ItemData.Get<MegaCorporation>(data.Manufacturer);
var manufacturer = Context.ItemData.Get<Faction>(data.Manufacturer);
if (manufacturer != null)
{
AddProperty("Manufacturer", () => manufacturer.Name);
@ -450,21 +450,6 @@ public class PropertiesPanel : MonoBehaviour
{
var data = Context.ItemData.Get<ItemData>(item.Data);
AddItemDataProperties(data);
// if (item is CraftedItemInstance craftedItemInstance)
// {
// var sourceEntity = Context.ItemData.Get<Entity>(craftedItemInstance.SourceEntity);
// if (sourceEntity != null)
// {
// var corporation = Context.ItemData.Get<Corporation>(sourceEntity.Corporation);
// AddProperty("Manufacturer", () => corporation.Name);
// }
// else
// {
// AddProperty("Manufacturer", () => "GameCult");
// }
// }
// if (item is SimpleCommodity simpleCommodity)
// AddProperty("Quantity", () => simpleCommodity.Quantity.ToString());
AddProperty("Mass", () => Context.GetMass(item).SignificantDigits(Context.GameplaySettings.SignificantDigits));
AddProperty("Thermal Mass", () => Context.GetThermalMass(item).SignificantDigits(Context.GameplaySettings.SignificantDigits));
if (item is EquippableItem gear)

View file

@ -142,8 +142,9 @@ public class SchematicDisplay : MonoBehaviour
.ToArray();
foreach (var x in _schematicItems)
{
x.ListElement.Icon.sprite = Settings.ItemIcons[(int) (entity.Hardpoints[x.Item.Position.x, x.Item.Position.y]?.Type ?? HardpointType.Tool)];
x.ListElement.Label.text = x.Item.EquippableItem.Name;
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 == Guid.Empty);

View file

@ -6,12 +6,46 @@ using UnityEngine.UI;
public class SchematicListElement : MonoBehaviour
{
public Image Icon;
public TextMeshProUGUI Label;
public GameSettings Settings;
public Prototype IconPrototype;
public TextMeshProUGUI DurabilityLabel;
public TextMeshProUGUI RangeLabel;
public TextMeshProUGUI AmmoLabel;
public Image InfiniteAmmoIcon;
public RectTransform CooldownFill;
public RectTransform HeatFill;
private List<Prototype> _iconInstances = new List<Prototype>();
public void ShowWeapon(WeaponItemData weapon)
{
foreach(var prototype in _iconInstances) prototype.ReturnToPool();
_iconInstances.Clear();
var caliberIcon = IconPrototype.Instantiate<Image>();
_iconInstances.Add(caliberIcon.GetComponent<Prototype>());
caliberIcon.sprite = Settings.GetIcon(weapon.WeaponCaliber);
var rangeIcon = IconPrototype.Instantiate<Image>();
_iconInstances.Add(rangeIcon.GetComponent<Prototype>());
rangeIcon.sprite = Settings.GetIcon(weapon.WeaponRange);
var typeIcon = IconPrototype.Instantiate<Image>();
_iconInstances.Add(typeIcon.GetComponent<Prototype>());
typeIcon.sprite = Settings.GetIcon(weapon.WeaponType);
foreach (var sprite in Settings.GetIcons(weapon.WeaponFireTypes))
{
var fireTypeIcon = IconPrototype.Instantiate<Image>();
_iconInstances.Add(fireTypeIcon.GetComponent<Prototype>());
fireTypeIcon.sprite = sprite;
}
foreach (var sprite in Settings.GetIcons(weapon.WeaponModifiers))
{
var modifierIcon = IconPrototype.Instantiate<Image>();
_iconInstances.Add(modifierIcon.GetComponent<Prototype>());
modifierIcon.sprite = sprite;
}
}
}

View file

@ -36,8 +36,8 @@ public class SectorMap : MonoBehaviour
public float IconBackgroundSize = 3;
public float LabelDistance = .4f;
private Dictionary<MegaCorporation, (RenderTexture influence, Material primaryMaterial, Material secondaryMaterial, Material linkMaterial)> _factionMaterials =
new Dictionary<MegaCorporation, (RenderTexture influence, Material primaryMaterial, Material secondaryMaterial, Material linkMaterial)>();
private Dictionary<Faction, (RenderTexture influence, Material primaryMaterial, Material secondaryMaterial, Material linkMaterial)> _factionMaterials =
new Dictionary<Faction, (RenderTexture influence, Material primaryMaterial, Material secondaryMaterial, Material linkMaterial)>();
public void Start()
{

View file

@ -30,15 +30,26 @@ public class TradeMenu : MonoBehaviour
private (ItemFilter filter, CompoundCommodityCategory type) _compoundCommodityFilter;
private List<(ItemFilter filter, Type type)> _behaviorFilters = new List<(ItemFilter filter, Type type)>();
public EquippedCargoBay Inventory { get; set; }
private void OnEnable()
{
_targetCargo = GameManager.DockingBay;
TargetCargoLabel.text = "Docking Bay";
Properties.Context = GameManager.ItemManager;
MinimumSizeFilter.Width.onEndEdit.RemoveAllListeners();
MinimumSizeFilter.Width.onEndEdit.AddListener(_ => Populate());
MinimumSizeFilter.Height.onEndEdit.RemoveAllListeners();
MinimumSizeFilter.Height.onEndEdit.AddListener(_ => Populate());
MaximumSizeFilter.Width.onEndEdit.RemoveAllListeners();
MaximumSizeFilter.Width.onEndEdit.AddListener(_ => Populate());
MaximumSizeFilter.Height.onEndEdit.RemoveAllListeners();
MaximumSizeFilter.Height.onEndEdit.AddListener(_ => Populate());
NewFilterButton.onClick.AddListener(() =>
{
ContextMenu.Clear();
@ -172,18 +183,20 @@ public class TradeMenu : MonoBehaviour
void Populate()
{
var columns = new List<(string name, int size, Func<ItemData, Func<string>> output, Func<ItemData, IComparable> sortKey)>();
var columns = new List<(string name, int size, Func<(ItemInstance item, ItemData data), Func<string>> output, Func<ItemData, IComparable> sortKey)>();
columns.Add(("Name", 3,
data => () => data.Name,
x => () => x.item is CraftedItemInstance craftedItemInstance ?
$"<color=#{ColorUtility.ToHtmlStringRGB(GameManager.ItemManager.GetTier(craftedItemInstance).tier.Color.ToColor())}>{x.data.Name}" :
x.data.Name,
data => data.Name));
if(_hardpointFilter.filter==null)
columns.Add(("Type", 2,
data => () =>
x => () =>
{
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);
if (x.data is SimpleCommodityData s) return Enum.GetName(typeof(SimpleCommodityCategory), s.Category);
if(x.data is CompoundCommodityData c) return Enum.GetName(typeof(CompoundCommodityCategory), c.Category);
if(x.data is EquippableItemData e) return Enum.GetName(typeof(HardpointType), e.HardpointType);
return "None";
},
data =>
@ -196,47 +209,48 @@ public class TradeMenu : MonoBehaviour
return 0;
}));
columns.Add(("Mass", 1,
data => () => data.Mass.SignificantDigits(3),
x => () => x.data.Mass.SignificantDigits(3),
data => data.Mass));
columns.Add(("Price", 1,
data => () => data.Price.ToString("N0"),
x => () => (x.item is CraftedItemInstance craftedItemInstance ? GameManager.ItemManager.GetPrice(craftedItemInstance) : x.data.Price).ToString("N0"),
data => data.Price));
columns.Add(("Size", 1,
data => () => $"{data.Shape.Width}x{data.Shape.Height}",
x => () => $"{x.data.Shape.Width}x{x.data.Shape.Height}",
data => data.Shape.Width*data.Shape.Height));
var items = GameManager.ItemManager.ItemData.GetAll<ItemData>().Where(i=>i.Price!=0);
var items = Inventory.Cargo.Keys
.Select<ItemInstance, (ItemInstance item, ItemData data)>(ii=>(ii, GameManager.ItemManager.GetData(ii)));
if (MinimumSizeFilter.gameObject.activeSelf)
items = items.Where(i =>
!(MinimumSizeFilter.Width.text.Length > 0 && i.Shape.Width < int.Parse(MinimumSizeFilter.Width.text) ||
MinimumSizeFilter.Height.text.Length > 0 && i.Shape.Height < int.Parse(MinimumSizeFilter.Height.text)));
!(MinimumSizeFilter.Width.text.Length > 0 && i.data.Shape.Width < int.Parse(MinimumSizeFilter.Width.text) ||
MinimumSizeFilter.Height.text.Length > 0 && i.data.Shape.Height < int.Parse(MinimumSizeFilter.Height.text)));
if (MaximumSizeFilter.gameObject.activeSelf)
items = items.Where(i =>
!(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)));
!(MaximumSizeFilter.Width.text.Length > 0 && i.data.Shape.Width > int.Parse(MaximumSizeFilter.Width.text) ||
MaximumSizeFilter.Height.text.Length > 0 && i.data.Shape.Height > int.Parse(MaximumSizeFilter.Height.text)));
if(_commodityFilter.filter != null)
items = items.Where(i => i is SimpleCommodityData s && s.Category == _commodityFilter.type);
items = items.Where(i => i.data is SimpleCommodityData s && s.Category == _commodityFilter.type);
if(_compoundCommodityFilter.filter != null)
items = items.Where(i => i is CompoundCommodityData c && c.Category == _compoundCommodityFilter.type);
items = items.Where(i => i.data is CompoundCommodityData c && c.Category == _compoundCommodityFilter.type);
if (_hardpointFilter.filter != null)
items = items.Where(i => i is EquippableItemData e && e.HardpointType == _hardpointFilter.type);
items = items.Where(i => i.data is EquippableItemData e && e.HardpointType == _hardpointFilter.type);
foreach (var (_, type) in _behaviorFilters)
{
items = items.Where(i => i is EquippableItemData e && e.Behaviors.Any(b => type.IsInstanceOfType(b)));
items = items.Where(i => i.data is EquippableItemData e && e.Behaviors.Any(b => type.IsInstanceOfType(b)));
foreach (var field in type.GetFields().Where(f => f.GetCustomAttribute<RuntimeInspectable>() != null))
{
var fieldType = field.FieldType;
if (fieldType == typeof(float))
columns.Add((field.Name, 1, data =>
columns.Add((field.Name, 1, x =>
{
var behavior = ((EquippableItemData) data).Behaviors.FirstOrDefault(b => type.IsInstanceOfType(b));
var behavior = ((EquippableItemData) x.data).Behaviors.FirstOrDefault(b => type.IsInstanceOfType(b));
return () => ((float) field.GetValue(behavior)).SignificantDigits(3);
}, data =>
{
@ -244,9 +258,9 @@ public class TradeMenu : MonoBehaviour
return (float) field.GetValue(behavior);
}));
else if (fieldType == typeof(int))
columns.Add((field.Name, 1, data =>
columns.Add((field.Name, 1, x =>
{
var behavior = ((EquippableItemData) data).Behaviors.FirstOrDefault(b => type.IsInstanceOfType(b));
var behavior = ((EquippableItemData) x.data).Behaviors.FirstOrDefault(b => type.IsInstanceOfType(b));
return () => ((int) field.GetValue(behavior)).ToString();
}, data =>
{
@ -255,9 +269,9 @@ public class TradeMenu : MonoBehaviour
}));
else if (fieldType == typeof(PerformanceStat))
{
columns.Add((field.Name, 1, data =>
columns.Add((field.Name, 1, x =>
{
var behavior = ((EquippableItemData) data).Behaviors.FirstOrDefault(b => type.IsInstanceOfType(b));
var behavior = ((EquippableItemData) x.data).Behaviors.FirstOrDefault(b => type.IsInstanceOfType(b));
return () => ((PerformanceStat) field.GetValue(behavior)).Max.SignificantDigits(3);
}, data =>
{
@ -269,13 +283,13 @@ public class TradeMenu : MonoBehaviour
}
columns.Add(("Owned", 1,
data => () =>
x => () =>
{
if (data is HullData)
return GameManager.DockedEntity.Children.Count(s => s.Hull.Data == data.ID && s is Ship {IsPlayerShip: true}).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();
if (x.data is HullData)
return GameManager.DockedEntity.Children.Count(s => s.Hull.Data == x.data.ID && s is Ship {IsPlayerShip: true}).ToString();
if(x.data is SimpleCommodityData)
return (_targetCargo.ItemsOfType.ContainsKey(x.data.ID) ? _targetCargo.ItemsOfType[x.data.ID].Cast<SimpleCommodity>().Sum(s=>s.Quantity) : 0).ToString();
return (_targetCargo.ItemsOfType.ContainsKey(x.data.ID) ? _targetCargo.ItemsOfType[x.data.ID].Count : 0).ToString();
},
data =>
{
@ -294,24 +308,21 @@ public class TradeMenu : MonoBehaviour
Columns = columns.Select(x => new SpreadsheetEntryColumn
{
Output = x.output(i),
SortKey = x.sortKey(i)
SortKey = x.sortKey(i.data)
}).ToArray(),
OnClick = () =>
{
Properties.Clear();
Properties.AddItemDataProperties(i);
Properties.AddItemProperties(i.item);
},
OnDoubleClick = () =>
{
switch (i)
switch (i.item)
{
case HullData h:
Buy(h);
case CraftedItemInstance c:
Buy(c);
break;
case CraftedItemData c:
Buy(c,1);
break;
case SimpleCommodityData s:
case SimpleCommodity s:
Buy(s, 1);
break;
}
@ -320,7 +331,7 @@ public class TradeMenu : MonoBehaviour
},
OnRightClick = () =>
{
if (!(i is HullData))
if (i.item is SimpleCommodity s)
{
ContextMenu.Clear();
ContextMenu.AddOption("Buy Quantity",
@ -328,19 +339,13 @@ public class TradeMenu : MonoBehaviour
{
int quantity = 1;
Dialog.Clear();
Dialog.Title.text = $"Buying {i.Name}";
Dialog.AddField("Quantity", () => quantity, q => quantity = min(q, GameManager.Credits/i.Price));
Dialog.Title.text = $"Buying {i.data.Name}";
Dialog.AddField("Quantity",
() => quantity,
q => quantity = min(min(q, GameManager.Credits / i.data.Price), s.Quantity));
Dialog.Show(() =>
{
switch (i)
{
case CraftedItemData c:
Buy(c,quantity);
break;
case SimpleCommodityData s:
Buy(s, quantity);
break;
}
Buy(s,quantity);
Populate();
});
@ -352,18 +357,33 @@ public class TradeMenu : MonoBehaviour
}));
}
private void Buy(HullData data)
private void Buy(CraftedItemInstance item)
{
if (data.Price < GameManager.Credits)
var data = GameManager.ItemManager.GetData(item);
var price = GameManager.ItemManager.GetPrice(item);
if (price < GameManager.Credits)
{
var hull = GameManager.ItemManager.CreateInstance(data) as EquippableItem;
Entity entity;
if(data.HullType==HullType.Ship)
entity = new Ship(GameManager.ItemManager, GameManager.Zone, hull, GameManager.Settings.GameplaySettings.DefaultEntitySettings) {IsPlayerShip = true};
else entity = new OrbitalEntity(GameManager.ItemManager, GameManager.Zone, hull, Guid.Empty, GameManager.Settings.GameplaySettings.DefaultEntitySettings);
entity.SetParent(GameManager.DockedEntity);
if (data is HullData hullData)
{
if (hullData.HullType != HullType.Ship) throw new ArgumentException("Attempted to buy non-ship hull from station, WTF are you doing?!");
var ship = new Ship(GameManager.ItemManager, GameManager.Zone, item as EquippableItem, GameManager.NewEntitySettings) {IsPlayerShip = true};
ship.SetParent(GameManager.DockedEntity);
GameManager.Credits -= data.Price;
GameManager.Credits -= data.Price;
}
else if (Inventory.TryTransferItem(_targetCargo, item))
{
GameManager.Credits -= price;
}
else
{
Dialog.Clear();
Dialog.Title.text = "Unable to buy: Insufficient Cargo Space!";
Dialog.Show();
Dialog.MoveToCursor();
return;
}
}
else
{
@ -371,41 +391,13 @@ public class TradeMenu : MonoBehaviour
Dialog.Title.text = "Unable to buy: Insufficient Credits!";
Dialog.Show();
Dialog.MoveToCursor();
return;
}
}
private void Buy(CraftedItemData data, int quantity)
{
for (int i = 0; i < quantity; i++)
{
if (data.Price < GameManager.Credits)
{
if (_targetCargo.TryStore(GameManager.ItemManager.CreateInstance(data)))
{
GameManager.Credits -= data.Price;
}
else
{
Dialog.Clear();
Dialog.Title.text = "Unable to buy: Insufficient Cargo Space!";
Dialog.Show();
Dialog.MoveToCursor();
return;
}
}
else
{
Dialog.Clear();
Dialog.Title.text = "Unable to buy: Insufficient Credits!";
Dialog.Show();
Dialog.MoveToCursor();
return;
}
}
}
private void Buy(SimpleCommodityData data, int quantity)
private void Buy(SimpleCommodity simpleCommodity, int quantity)
{
var data = GameManager.ItemManager.GetData(simpleCommodity);
// Up-rounded integer division from https://stackoverflow.com/a/503201
int lots = (quantity - 1) / data.MaxStack + 1;
int remaining = quantity;
@ -414,7 +406,7 @@ public class TradeMenu : MonoBehaviour
int q = min(remaining, data.MaxStack);
if (q * data.Price < GameManager.Credits)
{
if (_targetCargo.TryStore(GameManager.ItemManager.CreateInstance(data, q)))
if (Inventory.TryTransferItem(_targetCargo, simpleCommodity, quantity))
{
GameManager.Credits -= q * data.Price;
remaining -= q;

View file

@ -0,0 +1,473 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.Remoting.Contexts;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using Unity.Mathematics;
using static Unity.Mathematics.math;
public class TradeMenuDebug : MonoBehaviour
{
public ActionGameManager GameManager;
public ContextMenu ContextMenu;
public ConfirmationDialog Dialog;
public Button NewFilterButton;
public Prototype FilterPrototype;
public SizeFilter MinimumSizeFilter;
public SizeFilter MaximumSizeFilter;
public PropertiesPanel Properties;
public Spreadsheet Spreadsheet;
public TextMeshProUGUI TargetCargoLabel;
public Button FoldoutButton;
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()
{
_targetCargo = GameManager.DockingBay;
TargetCargoLabel.text = "Docking Bay";
Properties.Context = GameManager.ItemManager;
MinimumSizeFilter.Width.onEndEdit.AddListener(_ => Populate());
MinimumSizeFilter.Height.onEndEdit.AddListener(_ => Populate());
MaximumSizeFilter.Width.onEndEdit.AddListener(_ => Populate());
MaximumSizeFilter.Height.onEndEdit.AddListener(_ => Populate());
NewFilterButton.onClick.AddListener(() =>
{
ContextMenu.Clear();
IEnumerable<HardpointType> hardpointTypes = (HardpointType[]) Enum.GetValues(typeof(HardpointType));
if (_hardpointFilter.filter != null)
hardpointTypes = hardpointTypes.Where(x => x != _hardpointFilter.type);
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)
{
_hardpointFilter.filter = FilterPrototype.Instantiate<ItemFilter>();
_hardpointFilter.filter.OnDisable += () =>
{
_hardpointFilter.filter = null;
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(), () =>
{
var matchingType = _behaviorFilters.FirstOrDefault(y => y.type.IsAssignableFrom(x) || x.IsAssignableFrom(y.type));
if (matchingType.filter != null) matchingType.filter.DisableButton.onClick.Invoke();
var filter = FilterPrototype.Instantiate<ItemFilter>();
filter.Label.text = x.Name.FormatTypeName();
filter.OnDisable += () =>
{
_behaviorFilters.Remove((filter, x));
Populate();
};
_behaviorFilters.Add((filter, x));
Populate();
}, true)));
if(!MinimumSizeFilter.gameObject.activeSelf)
ContextMenu.AddOption("Minimum Size",
() =>
{
MinimumSizeFilter.gameObject.SetActive(true);
MinimumSizeFilter.OnDisable += () => Populate();
});
if(!MaximumSizeFilter.gameObject.activeSelf)
ContextMenu.AddOption("Maximum Size",
() =>
{
MaximumSizeFilter.gameObject.SetActive(true);
MaximumSizeFilter.OnDisable += () => Populate();
});
ContextMenu.Show();
});
Populate();
}
void Populate()
{
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 => () =>
{
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("N0"),
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<ItemData>().Where(i=>i.Price!=0);
if (MinimumSizeFilter.gameObject.activeSelf)
items = items.Where(i =>
!(MinimumSizeFilter.Width.text.Length > 0 && i.Shape.Width < int.Parse(MinimumSizeFilter.Width.text) ||
MinimumSizeFilter.Height.text.Length > 0 && i.Shape.Height < int.Parse(MinimumSizeFilter.Height.text)));
if (MaximumSizeFilter.gameObject.activeSelf)
items = items.Where(i =>
!(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 is EquippableItemData e && e.HardpointType == _hardpointFilter.type);
foreach (var (_, type) in _behaviorFilters)
{
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))
{
var fieldType = field.FieldType;
if (fieldType == typeof(float))
columns.Add((field.Name, 1, data =>
{
var behavior = ((EquippableItemData) data).Behaviors.FirstOrDefault(b => type.IsInstanceOfType(b));
return () => ((float) field.GetValue(behavior)).SignificantDigits(3);
}, data =>
{
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 = ((EquippableItemData) data).Behaviors.FirstOrDefault(b => type.IsInstanceOfType(b));
return () => ((int) field.GetValue(behavior)).ToString();
}, data =>
{
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 = ((EquippableItemData) data).Behaviors.FirstOrDefault(b => type.IsInstanceOfType(b));
return () => ((PerformanceStat) field.GetValue(behavior)).Max.SignificantDigits(3);
}, data =>
{
var behavior = ((EquippableItemData) data).Behaviors.FirstOrDefault(b => type.IsInstanceOfType(b));
return ((PerformanceStat) field.GetValue(behavior)).Max;
}));
}
}
}
columns.Add(("Owned", 1,
data => () =>
{
if (data is HullData)
return GameManager.DockedEntity.Children.Count(s => s.Hull.Data == data.ID && s is Ship {IsPlayerShip: true}).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.DockedEntity.Children.Count(s => s.Hull.Data == data.ID && s is Ship {IsPlayerShip: true});
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(),
columns.Select(x => x.size).ToArray(),
items.Select(i => new SpreadsheetEntryRow
{
Columns = columns.Select(x => new SpreadsheetEntryColumn
{
Output = x.output(i),
SortKey = x.sortKey(i)
}).ToArray(),
OnClick = () =>
{
Properties.Clear();
Properties.AddItemDataProperties(i);
},
OnDoubleClick = () =>
{
switch (i)
{
case HullData h:
Buy(h);
break;
case CraftedItemData c:
Buy(c,1);
break;
case SimpleCommodityData s:
Buy(s, 1);
break;
}
Populate();
},
OnRightClick = () =>
{
if (!(i is HullData))
{
ContextMenu.Clear();
ContextMenu.AddOption("Buy Quantity",
() =>
{
int quantity = 1;
Dialog.Clear();
Dialog.Title.text = $"Buying {i.Name}";
Dialog.AddField("Quantity", () => quantity, q => quantity = min(q, GameManager.Credits/i.Price));
Dialog.Show(() =>
{
switch (i)
{
case CraftedItemData c:
Buy(c,quantity);
break;
case SimpleCommodityData s:
Buy(s, quantity);
break;
}
Populate();
});
Dialog.MoveToCursor();
});
ContextMenu.Show();
}
}
}));
}
private void Buy(HullData data)
{
if (data.Price < GameManager.Credits)
{
var hull = GameManager.ItemManager.CreateInstance(data) as EquippableItem;
Entity entity;
if(data.HullType==HullType.Ship)
entity = new Ship(GameManager.ItemManager, GameManager.Zone, hull, GameManager.Settings.GameplaySettings.DefaultEntitySettings) {IsPlayerShip = true};
else entity = new OrbitalEntity(GameManager.ItemManager, GameManager.Zone, hull, Guid.Empty, GameManager.Settings.GameplaySettings.DefaultEntitySettings);
entity.SetParent(GameManager.DockedEntity);
GameManager.Credits -= data.Price;
}
else
{
Dialog.Clear();
Dialog.Title.text = "Unable to buy: Insufficient Credits!";
Dialog.Show();
Dialog.MoveToCursor();
}
}
private void Buy(CraftedItemData data, int quantity)
{
for (int i = 0; i < quantity; i++)
{
if (data.Price < GameManager.Credits)
{
if (_targetCargo.TryStore(GameManager.ItemManager.CreateInstance(data)))
{
GameManager.Credits -= data.Price;
}
else
{
Dialog.Clear();
Dialog.Title.text = "Unable to buy: Insufficient Cargo Space!";
Dialog.Show();
Dialog.MoveToCursor();
return;
}
}
else
{
Dialog.Clear();
Dialog.Title.text = "Unable to buy: Insufficient Credits!";
Dialog.Show();
Dialog.MoveToCursor();
return;
}
}
}
private void Buy(SimpleCommodityData data, int quantity)
{
// Up-rounded integer division from https://stackoverflow.com/a/503201
int lots = (quantity - 1) / data.MaxStack + 1;
int remaining = quantity;
for (int i = 0; i < lots; i++)
{
int q = min(remaining, data.MaxStack);
if (q * data.Price < GameManager.Credits)
{
if (_targetCargo.TryStore(GameManager.ItemManager.CreateInstance(data, q)))
{
GameManager.Credits -= q * data.Price;
remaining -= q;
}
else
{
Dialog.Clear();
Dialog.Title.text = "Unable to buy: Insufficient Cargo Space!";
Dialog.Show();
Dialog.MoveToCursor();
return;
}
}
else
{
Dialog.Clear();
Dialog.Title.text = "Unable to buy: Insufficient Credits!";
Dialog.Show();
Dialog.MoveToCursor();
return;
}
}
}
void Start()
{
FoldoutButton.onClick.AddListener(() =>
{
ContextMenu.Clear();
if(_targetCargo != GameManager.DockingBay)
ContextMenu.AddOption("Docking Bay",
() =>
{
_targetCargo = GameManager.DockingBay;
TargetCargoLabel.text = "Docking Bay";
});
foreach (var ship in GameManager.CurrentEntity.Parent.Children.Where(e => e is Ship {IsPlayerShip: true}))
{
foreach (var bay in ship.CargoBays.Select((bay, index) => (bay, index)))
ContextMenu.AddOption($"{ship.Name} Bay {bay.index}",
() =>
{
_targetCargo = bay.bay;
TargetCargoLabel.text = $"{ship.Name} Bay {bay.index}";
});
}
});
}
void Update()
{
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6eed32eb39c04a31b81e8a55685b222c
timeCreated: 1616191013

BIN
GameData/AetherDB.msgpack (Stored with Git LFS)

Binary file not shown.

BIN
GameData/PlayerSettings.msgpack (Stored with Git LFS)

Binary file not shown.

View file

@ -1,4 +1,4 @@
Empty Galaxy
Reset Galaxy
r.db('Aetheria').table('Galaxy').filter({$type:'ZoneData'}).update({visited: false})
r.db('Aetheria').table('Galaxy').filter({$type:'ZoneData'}).update({orbits: [ ]})
r.db('Aetheria').table('Galaxy').filter({$type:'ZoneData'}).update({planets: [ ]})
@ -20,4 +20,12 @@ r.db('Aetheria').table('Galaxy').filter({$type:'ZoneData'}).filter(function (zon
})
Find orphaned blueprints
r.db('Aetheria').table('Items').filter({$type:'BlueprintData'}).filter({item:'00000000-0000-0000-0000-000000000000'})
r.db('Aetheria').table('Items').filter({$type:'BlueprintData'}).filter({item:'00000000-0000-0000-0000-000000000000'})
Update type name for all items with launcher, ballistic or energy hardpoint types
r.db('Aetheria').table('Items').filter(
r.row("hardpointType").eq(9).or(r.row("hardpointType").eq(10)).or(r.row("hardpointType").eq(11))
).update({$type:'WeaponItemData'})
// Set required enum fields in weapons
r.db('Aetheria').table('Items').filter({$type:"WeaponItemData"}).update({range:0, caliber:0, weaponType:0, fireTypes:0, modifiers:0})