diff --git a/.idea/.idea.Aetheria-Economy/.idea/contentModel.xml b/.idea/.idea.Aetheria-Economy/.idea/contentModel.xml
index a25e58a96..2c6726abe 100644
--- a/.idea/.idea.Aetheria-Economy/.idea/contentModel.xml
+++ b/.idea/.idea.Aetheria-Economy/.idea/contentModel.xml
@@ -9,18 +9,32 @@
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
@@ -672,6 +686,282 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -690,11 +980,17 @@
+
+
+
+
+
+
diff --git a/.idea/.idea.Aetheria-Economy/.idea/indexLayout.xml b/.idea/.idea.Aetheria-Economy/.idea/indexLayout.xml
index 8d9241bcb..75ee64a49 100644
--- a/.idea/.idea.Aetheria-Economy/.idea/indexLayout.xml
+++ b/.idea/.idea.Aetheria-Economy/.idea/indexLayout.xml
@@ -14,6 +14,7 @@
.idea
Economy.Server
Economy.Shared
+ GameData
Library
Logs
Server
diff --git a/.idea/.idea.Economy/.idea/indexLayout.xml b/.idea/.idea.Economy/.idea/indexLayout.xml
index 0710d7d7f..11cb44604 100644
--- a/.idea/.idea.Economy/.idea/indexLayout.xml
+++ b/.idea/.idea.Economy/.idea/indexLayout.xml
@@ -13,6 +13,7 @@
.git
.idea
+ GameData
Library
Logs
Server
diff --git a/Assembly-CSharp-Editor.csproj b/Assembly-CSharp-Editor.csproj
index a92bfae91..e381789a0 100644
--- a/Assembly-CSharp-Editor.csproj
+++ b/Assembly-CSharp-Editor.csproj
@@ -60,6 +60,7 @@
+
diff --git a/Assembly-CSharp.csproj b/Assembly-CSharp.csproj
index 767279a42..863b67659 100644
--- a/Assembly-CSharp.csproj
+++ b/Assembly-CSharp.csproj
@@ -60,15 +60,18 @@
+
+
+
-
+
@@ -555,30 +558,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
C:/Users/rwvens/Documents/GitHub/Aetheria-Economy/Library/ScriptAssemblies/Unity.TextMeshPro.Editor.dll
diff --git a/Assets/Gravity.renderTexture b/Assets/Gravity.renderTexture
new file mode 100644
index 000000000..aea473145
--- /dev/null
+++ b/Assets/Gravity.renderTexture
@@ -0,0 +1,34 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!84 &8400000
+RenderTexture:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_Name: Gravity
+ m_ImageContentsHash:
+ serializedVersion: 2
+ Hash: 00000000000000000000000000000000
+ m_ForcedFallbackFormat: 4
+ m_DownscaleFallback: 0
+ m_Width: 512
+ m_Height: 512
+ m_AntiAliasing: 1
+ m_DepthFormat: 0
+ m_ColorFormat: 14
+ m_MipMap: 1
+ m_GenerateMips: 1
+ m_SRGB: 0
+ m_UseDynamicScale: 0
+ m_BindMS: 0
+ m_TextureSettings:
+ serializedVersion: 2
+ m_FilterMode: 1
+ m_Aniso: 0
+ m_MipBias: 0
+ m_WrapU: 2
+ m_WrapV: 2
+ m_WrapW: 2
+ m_Dimension: 2
+ m_VolumeDepth: 1
diff --git a/Assets/Gravity.renderTexture.meta b/Assets/Gravity.renderTexture.meta
new file mode 100644
index 000000000..f2d9c7219
--- /dev/null
+++ b/Assets/Gravity.renderTexture.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 52760f4ab4dd58647b2947db37572725
+NativeFormatImporter:
+ externalObjects: {}
+ mainObjectFileID: 8400000
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Materials.meta b/Assets/Materials.meta
new file mode 100644
index 000000000..3ac234462
--- /dev/null
+++ b/Assets/Materials.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 3c50848eb7835204891c6f78524e3710
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Materials/Gravity Well.mat b/Assets/Materials/Gravity Well.mat
new file mode 100644
index 000000000..b0d8a3d3e
--- /dev/null
+++ b/Assets/Materials/Gravity Well.mat
@@ -0,0 +1,79 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!21 &2100000
+Material:
+ serializedVersion: 6
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_Name: Gravity Well
+ m_Shader: {fileID: 4800000, guid: 105a94389fb66cf4bb41ad040d8c5fdb, type: 3}
+ m_ShaderKeywords:
+ m_LightmapFlags: 4
+ m_EnableInstancingVariants: 0
+ m_DoubleSidedGI: 0
+ m_CustomRenderQueue: -1
+ stringTagMap: {}
+ disabledShaderPasses: []
+ m_SavedProperties:
+ serializedVersion: 3
+ m_TexEnvs:
+ - _BumpMap:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _DetailAlbedoMap:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _DetailMask:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _DetailNormalMap:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _EmissionMap:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _MainTex:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _MetallicGlossMap:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _OcclusionMap:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _ParallaxMap:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ m_Floats:
+ - _BumpScale: 1
+ - _Cutoff: 0.5
+ - _Depth: 100
+ - _DetailNormalMapScale: 1
+ - _DstBlend: 0
+ - _GlossMapScale: 1
+ - _Glossiness: 0.5
+ - _GlossyReflections: 1
+ - _Metallic: 0
+ - _Mode: 0
+ - _OcclusionStrength: 1
+ - _Parallax: 0.02
+ - _Power: 4
+ - _SmoothnessTextureChannel: 0
+ - _SpecularHighlights: 1
+ - _SrcBlend: 1
+ - _UVSec: 0
+ - _ZWrite: 1
+ m_Colors:
+ - _Color: {r: 1, g: 1, b: 1, a: 1}
+ - _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
diff --git a/Assets/Materials/Gravity Well.mat.meta b/Assets/Materials/Gravity Well.mat.meta
new file mode 100644
index 000000000..4dacfd423
--- /dev/null
+++ b/Assets/Materials/Gravity Well.mat.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 44a8bbb89acb4e34c9f41a9da5842bb4
+NativeFormatImporter:
+ externalObjects: {}
+ mainObjectFileID: 2100000
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Materials/Zone Background.mat b/Assets/Materials/Zone Background.mat
new file mode 100644
index 000000000..7aaaa2cd4
--- /dev/null
+++ b/Assets/Materials/Zone Background.mat
@@ -0,0 +1,84 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!21 &2100000
+Material:
+ serializedVersion: 6
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_Name: Zone Background
+ m_Shader: {fileID: 4800000, guid: 0ec0ecdb30ff1614698ae885ebcd873d, type: 3}
+ m_ShaderKeywords:
+ m_LightmapFlags: 4
+ m_EnableInstancingVariants: 0
+ m_DoubleSidedGI: 0
+ m_CustomRenderQueue: -1
+ stringTagMap: {}
+ disabledShaderPasses: []
+ m_SavedProperties:
+ serializedVersion: 3
+ m_TexEnvs:
+ - _BumpMap:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _DetailAlbedoMap:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _DetailMask:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _DetailNormalMap:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _EmissionMap:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _MainTex:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _MetallicGlossMap:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _OcclusionMap:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _ParallaxMap:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ m_Floats:
+ - _AngleFade: 8
+ - _AngleWidth: 0.001
+ - _BumpScale: 1
+ - _Cutoff: 0.5
+ - _DetailNormalMapScale: 1
+ - _DstBlend: 0
+ - _GlossMapScale: 1
+ - _Glossiness: 0.5
+ - _GlossyReflections: 1
+ - _HeightRange: 100
+ - _LineFade: 8
+ - _LineWidth: 0.001
+ - _Metallic: 0
+ - _Mode: 0
+ - _OcclusionStrength: 1
+ - _Parallax: 0.02
+ - _SmoothnessTextureChannel: 0
+ - _SpecularHighlights: 1
+ - _SrcBlend: 1
+ - _StartHeight: 0
+ - _UVSec: 0
+ - _ZWrite: 1
+ m_Colors:
+ - _AngleColor: {r: 0.053221796, g: 0.49056602, b: 0.29599926, a: 1}
+ - _Color: {r: 0.062299743, g: 0.2874376, b: 0.5283019, a: 1}
+ - _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
diff --git a/Assets/Materials/Zone Background.mat.meta b/Assets/Materials/Zone Background.mat.meta
new file mode 100644
index 000000000..fff065f2b
--- /dev/null
+++ b/Assets/Materials/Zone Background.mat.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 90cead50364300d47bb35194fb52c117
+NativeFormatImporter:
+ externalObjects: {}
+ mainObjectFileID: 2100000
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Resources.meta b/Assets/Resources.meta
new file mode 100644
index 000000000..a1a01fd7b
--- /dev/null
+++ b/Assets/Resources.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 766fda6a352c32f43bd8fa57c06042b0
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Resources/Icons.asset b/Assets/Resources/Icons.asset
new file mode 100644
index 000000000..362bf8ad8
--- /dev/null
+++ b/Assets/Resources/Icons.asset
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:59c9fde0f1bea591982eb8627d909806368bbf83c994b0737575faf8b4515d85
+size 435
diff --git a/Assets/Resources/Icons.asset.meta b/Assets/Resources/Icons.asset.meta
new file mode 100644
index 000000000..7c6fa0e74
--- /dev/null
+++ b/Assets/Resources/Icons.asset.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 50ac72e1e2474804287a2d4f1693f9b8
+NativeFormatImporter:
+ externalObjects: {}
+ mainObjectFileID: 11400000
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Resources/Sprites.meta b/Assets/Resources/Sprites.meta
new file mode 100644
index 000000000..0d4dfe244
--- /dev/null
+++ b/Assets/Resources/Sprites.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: f54a1a9bd4868164c851d251e87b1d73
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Resources/Sprites/add.png b/Assets/Resources/Sprites/add.png
new file mode 100644
index 000000000..67d0858c0
--- /dev/null
+++ b/Assets/Resources/Sprites/add.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:24800085053fb848f01c019ba76a1efb494669dafff4bf0fb880d6bf5f273d95
+size 22624
diff --git a/Assets/Resources/Sprites/add.png.meta b/Assets/Resources/Sprites/add.png.meta
new file mode 100644
index 000000000..ebbed7e21
--- /dev/null
+++ b/Assets/Resources/Sprites/add.png.meta
@@ -0,0 +1,110 @@
+fileFormatVersion: 2
+guid: 1d55ddcd5a3c2354faea7e99db862d21
+TextureImporter:
+ fileIDToRecycleName: {}
+ externalObjects: {}
+ serializedVersion: 9
+ mipmaps:
+ mipMapMode: 0
+ enableMipMap: 1
+ sRGBTexture: 1
+ linearTexture: 0
+ fadeOut: 0
+ borderMipMap: 0
+ mipMapsPreserveCoverage: 0
+ alphaTestReferenceValue: 0.5
+ mipMapFadeDistanceStart: 1
+ mipMapFadeDistanceEnd: 3
+ bumpmap:
+ convertToNormalMap: 0
+ externalNormalMap: 0
+ heightScale: 0.25
+ normalMapFilter: 0
+ isReadable: 0
+ streamingMipmaps: 0
+ streamingMipmapsPriority: 0
+ grayScaleToAlpha: 0
+ generateCubemap: 6
+ cubemapConvolution: 0
+ seamlessCubemap: 0
+ textureFormat: 1
+ maxTextureSize: 2048
+ textureSettings:
+ serializedVersion: 2
+ filterMode: -1
+ aniso: -1
+ mipBias: -100
+ wrapU: 1
+ wrapV: 1
+ wrapW: 1
+ nPOTScale: 0
+ lightmap: 0
+ compressionQuality: 50
+ spriteMode: 1
+ spriteExtrude: 1
+ spriteMeshType: 1
+ alignment: 0
+ spritePivot: {x: 0.5, y: 0.5}
+ spritePixelsToUnits: 100
+ spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+ spriteGenerateFallbackPhysicsShape: 1
+ alphaUsage: 2
+ alphaIsTransparency: 1
+ spriteTessellationDetail: -1
+ textureType: 8
+ textureShape: 1
+ singleChannelComponent: 0
+ maxTextureSizeSet: 0
+ compressionQualitySet: 0
+ textureFormatSet: 0
+ platformSettings:
+ - serializedVersion: 2
+ buildTarget: DefaultTexturePlatform
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ - serializedVersion: 2
+ buildTarget: Standalone
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ - serializedVersion: 2
+ buildTarget: WebGL
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ spriteSheet:
+ serializedVersion: 2
+ sprites: []
+ outline: []
+ physicsShape: []
+ bones: []
+ spriteID: e0989b2b95dfc1f41a5c3b899d889c0b
+ vertices: []
+ indices:
+ edges: []
+ weights: []
+ spritePackingTag:
+ pSDRemoveMatte: 0
+ pSDShowRemoveMatteOption: 0
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Resources/Sprites/remove.png b/Assets/Resources/Sprites/remove.png
new file mode 100644
index 000000000..0e460ecee
--- /dev/null
+++ b/Assets/Resources/Sprites/remove.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:64d91be4e1f920fd705bdd75fe55506f6fb1071bd84a53241495e0a3eac15dde
+size 22065
diff --git a/Assets/Resources/Sprites/remove.png.meta b/Assets/Resources/Sprites/remove.png.meta
new file mode 100644
index 000000000..66d5f55ae
--- /dev/null
+++ b/Assets/Resources/Sprites/remove.png.meta
@@ -0,0 +1,110 @@
+fileFormatVersion: 2
+guid: f1aad09b4bf42ba4aa13a9fa1d97f01c
+TextureImporter:
+ fileIDToRecycleName: {}
+ externalObjects: {}
+ serializedVersion: 9
+ mipmaps:
+ mipMapMode: 0
+ enableMipMap: 1
+ sRGBTexture: 1
+ linearTexture: 0
+ fadeOut: 0
+ borderMipMap: 0
+ mipMapsPreserveCoverage: 0
+ alphaTestReferenceValue: 0.5
+ mipMapFadeDistanceStart: 1
+ mipMapFadeDistanceEnd: 3
+ bumpmap:
+ convertToNormalMap: 0
+ externalNormalMap: 0
+ heightScale: 0.25
+ normalMapFilter: 0
+ isReadable: 0
+ streamingMipmaps: 0
+ streamingMipmapsPriority: 0
+ grayScaleToAlpha: 0
+ generateCubemap: 6
+ cubemapConvolution: 0
+ seamlessCubemap: 0
+ textureFormat: 1
+ maxTextureSize: 2048
+ textureSettings:
+ serializedVersion: 2
+ filterMode: -1
+ aniso: -1
+ mipBias: -100
+ wrapU: 1
+ wrapV: 1
+ wrapW: 1
+ nPOTScale: 0
+ lightmap: 0
+ compressionQuality: 50
+ spriteMode: 1
+ spriteExtrude: 1
+ spriteMeshType: 1
+ alignment: 0
+ spritePivot: {x: 0.5, y: 0.5}
+ spritePixelsToUnits: 100
+ spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+ spriteGenerateFallbackPhysicsShape: 1
+ alphaUsage: 2
+ alphaIsTransparency: 1
+ spriteTessellationDetail: -1
+ textureType: 8
+ textureShape: 1
+ singleChannelComponent: 0
+ maxTextureSizeSet: 0
+ compressionQualitySet: 0
+ textureFormatSet: 0
+ platformSettings:
+ - serializedVersion: 2
+ buildTarget: DefaultTexturePlatform
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ - serializedVersion: 2
+ buildTarget: Standalone
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ - serializedVersion: 2
+ buildTarget: WebGL
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ spriteSheet:
+ serializedVersion: 2
+ sprites: []
+ outline: []
+ physicsShape: []
+ bones: []
+ spriteID: fb43f50872fe9b242b150185ffa5335e
+ vertices: []
+ indices:
+ edges: []
+ weights: []
+ spritePackingTag:
+ pSDRemoveMatte: 0
+ pSDShowRemoveMatteOption: 0
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Scenes/Main.unity b/Assets/Scenes/Main.unity
index e5ecd0a00..ecbfc9733 100644
--- a/Assets/Scenes/Main.unity
+++ b/Assets/Scenes/Main.unity
@@ -50,7 +50,6 @@ LightmapSettings:
m_BounceScale: 1
m_IndirectOutputScale: 1
m_AlbedoBoost: 1
- m_TemporalCoherenceThreshold: 1
m_EnvironmentLightingMode: 0
m_EnableBakedLightmaps: 0
m_EnableRealtimeLightmaps: 0
@@ -113,40 +112,64 @@ NavMeshSettings:
debug:
m_Flags: 0
m_NavMeshData: {fileID: 0}
---- !u!1 &519420028
+--- !u!1 &408552537
GameObject:
m_ObjectHideFlags: 0
- m_PrefabParentObject: {fileID: 0}
- m_PrefabInternal: {fileID: 0}
- serializedVersion: 5
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
m_Component:
- - component: {fileID: 519420032}
- - component: {fileID: 519420031}
- - component: {fileID: 519420029}
+ - component: {fileID: 408552541}
+ - component: {fileID: 408552540}
+ - component: {fileID: 408552539}
+ - component: {fileID: 408552538}
m_Layer: 0
- m_Name: Main Camera
- m_TagString: MainCamera
+ m_Name: Gravity Camera
+ m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
---- !u!81 &519420029
+--- !u!114 &408552538
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 408552537}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: 04277e392af12204397c334ea824f957, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
+ BackgroundMaterial: {fileID: 2100000, guid: 90cead50364300d47bb35194fb52c117, type: 2}
+ GravityTexture: {fileID: 0}
+ GravityRenderer: {fileID: 1956833085}
+--- !u!81 &408552539
AudioListener:
m_ObjectHideFlags: 0
- m_PrefabParentObject: {fileID: 0}
- m_PrefabInternal: {fileID: 0}
- m_GameObject: {fileID: 519420028}
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 408552537}
m_Enabled: 1
---- !u!20 &519420031
+--- !u!20 &408552540
Camera:
m_ObjectHideFlags: 0
- m_PrefabParentObject: {fileID: 0}
- m_PrefabInternal: {fileID: 0}
- m_GameObject: {fileID: 519420028}
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 408552537}
m_Enabled: 1
serializedVersion: 2
m_ClearFlags: 2
- m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0}
+ m_BackGroundColor: {r: 0, g: 0, b: 0, a: 0}
+ m_projectionMatrixMode: 1
+ m_SensorSize: {x: 36, y: 24}
+ m_LensShift: {x: 0, y: 0}
+ m_GateFitMode: 2
+ m_FocalLength: 50
m_NormalizedViewPortRect:
serializedVersion: 2
x: 0
@@ -161,7 +184,89 @@ Camera:
m_Depth: -1
m_CullingMask:
serializedVersion: 2
- m_Bits: 4294967295
+ m_Bits: 256
+ m_RenderingPath: -1
+ m_TargetTexture: {fileID: 0}
+ m_TargetDisplay: 0
+ m_TargetEye: 0
+ m_HDR: 1
+ m_AllowMSAA: 0
+ m_AllowDynamicResolution: 0
+ m_ForceIntoRT: 0
+ m_OcclusionCulling: 0
+ m_StereoConvergence: 10
+ m_StereoSeparation: 0.022
+--- !u!4 &408552541
+Transform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 408552537}
+ m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+ m_LocalPosition: {x: 0, y: 0, z: -10}
+ m_LocalScale: {x: 1, y: 1, z: 1}
+ m_Children: []
+ m_Father: {fileID: 0}
+ m_RootOrder: 1
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!1 &519420028
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 519420032}
+ - component: {fileID: 519420031}
+ - component: {fileID: 519420029}
+ m_Layer: 0
+ m_Name: Main Camera
+ m_TagString: MainCamera
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!81 &519420029
+AudioListener:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 519420028}
+ m_Enabled: 1
+--- !u!20 &519420031
+Camera:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 519420028}
+ m_Enabled: 1
+ serializedVersion: 2
+ m_ClearFlags: 2
+ m_BackGroundColor: {r: 0, g: 0, b: 0, a: 0}
+ m_projectionMatrixMode: 1
+ m_SensorSize: {x: 36, y: 24}
+ m_LensShift: {x: 0, y: 0}
+ m_GateFitMode: 2
+ m_FocalLength: 50
+ m_NormalizedViewPortRect:
+ serializedVersion: 2
+ x: 0
+ y: 0
+ width: 1
+ height: 1
+ near clip plane: 0.3
+ far clip plane: 1000
+ field of view: 60
+ orthographic: 1
+ orthographic size: 5
+ m_Depth: 0
+ m_CullingMask:
+ serializedVersion: 2
+ m_Bits: 512
m_RenderingPath: -1
m_TargetTexture: {fileID: 0}
m_TargetDisplay: 0
@@ -176,8 +281,9 @@ Camera:
--- !u!4 &519420032
Transform:
m_ObjectHideFlags: 0
- m_PrefabParentObject: {fileID: 0}
- m_PrefabInternal: {fileID: 0}
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 519420028}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: -10}
@@ -186,3 +292,187 @@ Transform:
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!1 &1496237818
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 1496237822}
+ - component: {fileID: 1496237821}
+ - component: {fileID: 1496237820}
+ - component: {fileID: 1496237819}
+ m_Layer: 8
+ m_Name: Gravity Well
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!64 &1496237819
+MeshCollider:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1496237818}
+ m_Material: {fileID: 0}
+ m_IsTrigger: 0
+ m_Enabled: 1
+ serializedVersion: 3
+ m_Convex: 0
+ m_CookingOptions: 14
+ m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0}
+--- !u!23 &1496237820
+MeshRenderer:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1496237818}
+ m_Enabled: 1
+ m_CastShadows: 1
+ m_ReceiveShadows: 1
+ m_DynamicOccludee: 1
+ m_MotionVectors: 1
+ m_LightProbeUsage: 1
+ m_ReflectionProbeUsage: 1
+ m_RenderingLayerMask: 1
+ m_RendererPriority: 0
+ m_Materials:
+ - {fileID: 2100000, guid: 44a8bbb89acb4e34c9f41a9da5842bb4, type: 2}
+ m_StaticBatchInfo:
+ firstSubMesh: 0
+ subMeshCount: 0
+ m_StaticBatchRoot: {fileID: 0}
+ m_ProbeAnchor: {fileID: 0}
+ m_LightProbeVolumeOverride: {fileID: 0}
+ m_ScaleInLightmap: 1
+ m_PreserveUVs: 0
+ m_IgnoreNormalsForChartDetection: 0
+ m_ImportantGI: 0
+ m_StitchLightmapSeams: 0
+ m_SelectedEditorRenderState: 3
+ m_MinimumChartSize: 4
+ m_AutoUVMaxDistance: 0.5
+ m_AutoUVMaxAngle: 89
+ m_LightmapParameters: {fileID: 0}
+ m_SortingLayerID: 0
+ m_SortingLayer: 0
+ m_SortingOrder: 0
+--- !u!33 &1496237821
+MeshFilter:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1496237818}
+ m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0}
+--- !u!4 &1496237822
+Transform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1496237818}
+ m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+ m_LocalPosition: {x: 2.5, y: -0.01, z: 0}
+ m_LocalScale: {x: 10, y: 10, z: 1}
+ m_Children: []
+ m_Father: {fileID: 0}
+ m_RootOrder: 2
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!1 &1956833083
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 1956833087}
+ - component: {fileID: 1956833086}
+ - component: {fileID: 1956833085}
+ - component: {fileID: 1956833084}
+ m_Layer: 9
+ m_Name: Zone BG
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!64 &1956833084
+MeshCollider:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1956833083}
+ m_Material: {fileID: 0}
+ m_IsTrigger: 0
+ m_Enabled: 1
+ serializedVersion: 3
+ m_Convex: 0
+ m_CookingOptions: 14
+ m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0}
+--- !u!23 &1956833085
+MeshRenderer:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1956833083}
+ m_Enabled: 1
+ m_CastShadows: 1
+ m_ReceiveShadows: 1
+ m_DynamicOccludee: 1
+ m_MotionVectors: 1
+ m_LightProbeUsage: 1
+ m_ReflectionProbeUsage: 1
+ m_RenderingLayerMask: 1
+ m_RendererPriority: 0
+ m_Materials:
+ - {fileID: 2100000, guid: 90cead50364300d47bb35194fb52c117, type: 2}
+ m_StaticBatchInfo:
+ firstSubMesh: 0
+ subMeshCount: 0
+ m_StaticBatchRoot: {fileID: 0}
+ m_ProbeAnchor: {fileID: 0}
+ m_LightProbeVolumeOverride: {fileID: 0}
+ m_ScaleInLightmap: 1
+ m_PreserveUVs: 0
+ m_IgnoreNormalsForChartDetection: 0
+ m_ImportantGI: 0
+ m_StitchLightmapSeams: 0
+ m_SelectedEditorRenderState: 3
+ m_MinimumChartSize: 4
+ m_AutoUVMaxDistance: 0.5
+ m_AutoUVMaxAngle: 89
+ m_LightmapParameters: {fileID: 0}
+ m_SortingLayerID: 0
+ m_SortingLayer: 0
+ m_SortingOrder: 0
+--- !u!33 &1956833086
+MeshFilter:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1956833083}
+ m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0}
+--- !u!4 &1956833087
+Transform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1956833083}
+ m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+ m_LocalPosition: {x: -5.19, y: 0.07, z: 0.00390625}
+ m_LocalScale: {x: 11.261, y: 6.018, z: 1}
+ m_Children: []
+ m_Father: {fileID: 0}
+ m_RootOrder: 3
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
diff --git a/Assets/Scripts/Behaviors.cs b/Assets/Scripts/Behaviors.cs
new file mode 100644
index 000000000..5a84cc983
--- /dev/null
+++ b/Assets/Scripts/Behaviors.cs
@@ -0,0 +1,494 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using MessagePack;
+using UniRx;
+using Unity.Mathematics;
+using UnityEngine;
+using UnityEngine.Audio;
+using static Unity.Mathematics.math;
+using static Unity.Mathematics.noise;
+using Object = UnityEngine.Object;
+
+public interface IItemBehavior
+{
+ void Update(float delta);
+ void FixedUpdate(float delta);
+ Ship Ship { get; }
+ Gear Item { get; }
+ IItemBehaviorData Data { get; }
+}
+
+public interface IActivatedItemBehavior : IItemBehavior
+{
+ void Activate();
+ void Deactivate();
+}
+
+[Inspectable]
+[Union(0, typeof(CannonBehaviorData))]
+[Union(1, typeof(MissileBehaviorData))]
+[Union(2, typeof(ReactorBehaviorData))]
+// [Union(3, typeof(PlusUltraBehaviorData))]
+[Union(4, typeof(AfterburnerBehaviorData))]
+[Union(5, typeof(SensorBehaviorData))]
+public interface IItemBehaviorData
+{
+ IItemBehavior CreateInstance(Ship ship, Gear item);
+ // PerformanceStat[] DynamicStats { get; }
+ //Type ItemType { get; }
+}
+
+[Inspectable]
+[MessagePackObject]
+public class SensorBehaviorData : IItemBehaviorData
+{
+ [Inspectable] [Key("radiance")] public PerformanceStat Radiance;
+ [Inspectable] [Key("masking")] public PerformanceStat RadianceMasking;
+ [Inspectable] [Key("sensitivity")] public PerformanceStat Sensitivity;
+ [Inspectable] [Key("range")] public PerformanceStat Range;
+
+ public IItemBehavior CreateInstance(Ship ship, Gear item)
+ {
+ return new SensorBehavior(this, ship, item);
+ }
+
+ [IgnoreMember] public PerformanceStat[] DynamicStats => new[] {Radiance, Sensitivity};
+}
+
+public class SensorBehavior : IItemBehavior
+{
+ private SensorBehaviorData _data;
+
+ public Ship Ship { get; }
+ public Gear Item { get; }
+
+ public IItemBehaviorData Data => _data;
+
+ public SensorBehavior(SensorBehaviorData data, Ship ship, Gear item)
+ {
+ _data = data;
+ Ship = ship;
+ Item = item;
+ }
+
+ public void Update(float delta)
+ {
+ // var ship = Hardpoint.Ship.Ship.transform;
+ // var contacts =
+ // Physics.OverlapSphere(ship.position, _data.Range.Evaluate(Hardpoint)).Where(c=>c.attachedRigidbody?.GetComponent()!=null).Select(c=>c.attachedRigidbody.GetComponent());
+ // foreach (var contact in contacts)
+ // {
+ // var diff = (contact.transform.position - ship.position).Flatland();
+ // var angle = acos(dot(ship.forward.Flatland().normalized,
+ // diff.normalized)) / (float)PI;
+ // var sens = _data.Sensitivity.Evaluate(Hardpoint) *
+ // Hardpoint.Ship.HullData.VisibilityCurve.Evaluate(saturate(angle));
+ // var vis = contact.Visibility / diff.sqrMagnitude;
+ // if(vis > 1/sens)
+ // Hardpoint.Ship.Contacts[contact] = Time.time;
+ // }
+ //
+ // Hardpoint.Ship.VisibilitySources[this] = _data.Radiance.Evaluate(Hardpoint) / _data.RadianceMasking.Evaluate(Hardpoint);
+ // TODO: Handle Active Detection / Visibility From Reflected Radiance
+ }
+
+ public void FixedUpdate(float delta)
+ {
+ }
+}
+
+[Inspectable]
+[MessagePackObject]
+public class AfterburnerBehaviorData : IItemBehaviorData
+{
+ [Inspectable] [Key("thrust")] public PerformanceStat ThrustModifier;
+ [Inspectable] [Key("speed")] public PerformanceStat SpeedModifier;
+ [Inspectable] [Key("torque")] public PerformanceStat TorqueModifier;
+ public IItemBehavior CreateInstance(Ship ship, Gear item)
+ {
+ return new AfterburnerBehavior(this, ship, item);
+ }
+}
+
+public class AfterburnerBehavior : IActivatedItemBehavior
+{
+ private List> _modifiers = new List>();
+ private AfterburnerBehaviorData _data;
+
+ public Ship Ship { get; }
+ public Gear Item { get; }
+
+ public IItemBehaviorData Data => _data;
+
+ public AfterburnerBehavior(AfterburnerBehaviorData data, Ship ship, Gear item)
+ {
+ _data = data;
+ Ship = ship;
+ Item = item;
+ }
+
+ public void Update(float delta)
+ {
+ }
+
+ public void FixedUpdate(float delta)
+ {
+ }
+
+ public void Activate()
+ {
+ var thrustMod = (Ship.GetEquipped(HardpointType.Thruster).EquippedItemData as Thruster).Thrust.GetScaleModifiers(Ship);
+ _modifiers.Add(thrustMod);
+ thrustMod.Add(this,_data.ThrustModifier.Evaluate(Item, Ship));
+
+ var speedMod = (Ship.Hull.EquippedItemData as Hull).TopSpeed.GetScaleModifiers(Ship);
+ _modifiers.Add(speedMod);
+ speedMod.Add(this,_data.SpeedModifier.Evaluate(Item, Ship));
+
+ var torqueMod = (Ship.GetEquipped(HardpointType.Thruster).EquippedItemData as Thruster).Torque.GetScaleModifiers(Ship);
+ _modifiers.Add(torqueMod);
+ torqueMod.Add(this,_data.TorqueModifier.Evaluate(Item, Ship));
+
+ Ship.ForceThrust = true;
+ }
+
+ public void Deactivate()
+ {
+ Ship.ForceThrust = false;
+ foreach (var mod in _modifiers)
+ {
+ mod.Remove(this);
+ }
+ _modifiers.Clear();
+ }
+}
+
+[Inspectable]
+[MessagePackObject]
+public class CannonBehaviorData : IItemBehaviorData
+{
+ [MessagePackFormatter(typeof(UnityGameObjectFormatter))]
+ [Inspectable] [Key("bullet")] public GameObject BulletPrefab;
+ // [MessagePackFormatter(typeof(ClipListFormatter))]
+ // [Inspectable] [Key("sounds")] public List Sounds;
+ [Inspectable] [Key("damageType")] public ProjectileType DamageType;
+ [Inspectable] [Key("burstCount")] public int BurstCount;
+ [Inspectable] [Key("burstTime")] public PerformanceStat BurstTime;
+ [Inspectable] [Key("bulletRange")] public PerformanceStat Range;
+ [Inspectable] [Key("spread")] public PerformanceStat Spread;
+ [Inspectable] [Key("bulletInherit")] public float Inherit;
+ [Inspectable] [Key("deflection")] public float Deflection;
+ [Inspectable] [Key("visibility")] public PerformanceStat Visibility;
+ [Inspectable] [Key("visibilityDecay")]public PerformanceStat VisibilityDecay;
+ [Inspectable] [Key("bulletVelocity")] public PerformanceStat Velocity;
+ [Inspectable] [Key("cooldown")] public PerformanceStat Cooldown;
+ [Inspectable] [Key("damage")] public PerformanceStat Damage;
+ [Inspectable] [Key("heat")] public PerformanceStat Heat;
+
+ public IItemBehavior CreateInstance(Ship ship, Gear item)
+ {
+ return new CannonBehavior(this, ship, item);
+ }
+
+ [IgnoreMember] public PerformanceStat[] DynamicStats => new[] {BurstTime, Range, Spread, Velocity, Cooldown, Damage};
+}
+
+public class CannonBehavior : IActivatedItemBehavior
+{
+ private bool _firing;
+ private float _cooldown; // normalized
+ private CannonBehaviorData _cannon;
+ public Ship Ship { get; }
+ public Gear Item { get; }
+ private float _firingVisibility;
+
+ public CannonBehavior(CannonBehaviorData c, Ship ship, Gear item)
+ {
+ _cannon = c;
+ Ship = ship;
+ Item = item;
+ }
+
+ public void Activate()
+ {
+// Debug.Log("Activating Cannon");
+// _firing = true;
+// Observable.EveryUpdate().TakeWhile(_ => _firing).Subscribe(_ =>
+// {
+// // Debug.Log($"Updating Observable {_cooldown}");
+// if (_cooldown < 0)
+// {
+// _cooldown = 1;
+// Fire(0);
+// if(_cannon.BurstCount>1)
+// Observable.Interval(TimeSpan.FromSeconds(_cannon.BurstTime.Evaluate(Hardpoint) / (_cannon.BurstCount-1))).Take(_cannon.BurstCount-1)
+// .Subscribe(l => Fire(l+1));
+// }
+// });
+ }
+
+ private void Fire(long b)
+ {
+ // _firingVisibility += _cannon.Visibility.Evaluate(Hardpoint);
+ // Hardpoint.Temperature += _cannon.Heat.Evaluate(Hardpoint) / Hardpoint.HeatCapacity;
+ // var inst = GameObject.Instantiate(_cannon.BulletPrefab).transform;
+ // Physics.IgnoreCollision(Hardpoint.Ship.Ship.GetComponent(), inst.GetComponent());
+ // var bullet = inst.GetComponent();
+ // bullet.Target = Hardpoint.Ship.Ship.Target;
+ // bullet.Source = Hardpoint.Ship.Ship.Hitpoints;
+ // bullet.Lifetime = _cannon.Range.Evaluate(Hardpoint) / _cannon.Velocity.Evaluate(Hardpoint);
+ // bullet.Damage = _cannon.Damage.Evaluate(Hardpoint);
+ // inst.position = Hardpoint.Proxy.position;
+ // inst.rotation = Hardpoint.Proxy.rotation;
+ // inst.GetComponent().velocity = _cannon.Velocity.Evaluate(Hardpoint) * Vector3.RotateTowards(-inst.forward, Hardpoint.Ship.Ship.Direction, _cannon.Deflection * Mathf.Deg2Rad, 1);
+ // Hardpoint.Ship.Ship.AudioSource.PlayOneShot(_cannon.Sounds.RandomElement());
+// Debug.Log($"Firing bullet {b}");
+ }
+
+ public void Deactivate()
+ {
+ _firing = false;
+ }
+
+ public void Update(float delta)
+ {
+ _cooldown -= delta / _cannon.Cooldown.Evaluate(Item, Ship);
+
+ if (_firingVisibility < 0.01f)
+ {
+ Ship.VisibilitySources.Remove(this);
+ }
+ }
+
+ public void FixedUpdate(float delta)
+ {
+ _firingVisibility *= _cannon.VisibilityDecay.Evaluate(Item, Ship);
+ }
+
+ public IItemBehaviorData Data => _cannon;
+}
+
+[Inspectable]
+[MessagePackObject]
+public class MissileBehaviorData : IItemBehaviorData
+{
+ // [MessagePackFormatter(typeof(UnityGameObjectFormatter))]
+ // [Inspectable] [Key("missile")] public GameObject MissilePrefab;
+ // [MessagePackFormatter(typeof(ClipListFormatter))]
+ // [Inspectable] [Key("sounds")] public List Sounds;
+ // [MessagePackFormatter(typeof(UnityAudioClipFormatter))]
+ // [Inspectable] [Key("beepSound")] public AudioClip BeepSound;
+ // [Inspectable] [Key("beepCount")] public int Beeps;
+ [Inspectable] [Key("damageType")] public ProjectileType DamageType;
+ [Inspectable] [Key("burstCount")] public int BurstCount;
+ [Inspectable] [Key("burstTime")] public PerformanceStat BurstTime;
+ [Inspectable] [Key("range")] public PerformanceStat Range;
+ [Inspectable] [Key("guidance")] public AnimationCurve GuidanceCurve;
+ [Inspectable] [Key("thrustCurve")] public AnimationCurve ThrustCurve;
+ [Inspectable] [Key("liftCurve")] public AnimationCurve LiftCurve;
+ [Inspectable] [Key("thrust")] public PerformanceStat Thrust;
+ [Inspectable] [Key("deflection")] public float Deflection;
+ [Inspectable] [Key("lockOnBuffer")] public float LockOnDegrees;
+ [Inspectable] [Key("frequency")] public float DodgeFrequency;
+ [Inspectable] [Key("visibility")] public PerformanceStat Visibility;
+ [Inspectable] [Key("launchSpeed")] public PerformanceStat LaunchSpeed;
+ [Inspectable] [Key("missileSpeed")] public PerformanceStat MissileSpeed;
+ [Inspectable] [Key("cooldown")] public PerformanceStat Cooldown;
+ [Inspectable] [Key("lockOnTime")] public PerformanceStat LockOnTime;
+ [Inspectable] [Key("damage")] public PerformanceStat Damage;
+ [Inspectable] [Key("heat")] public PerformanceStat Heat;
+
+
+ public IItemBehavior CreateInstance(Ship ship, Gear item)
+ {
+ return new MissileBehavior(this, ship, item);
+ }
+
+ [IgnoreMember] public PerformanceStat[] DynamicStats => new[] {BurstTime, Range, Thrust, LaunchSpeed, MissileSpeed, Cooldown, Damage};
+}
+
+public class MissileBehavior : IActivatedItemBehavior
+{
+ private bool _locking;
+ private float _lockingTimer;
+ private float _cooldown; // normalized
+ private bool _locked;
+
+ private MissileBehaviorData _missile;
+ public Ship Ship { get; }
+ public Gear Item { get; }
+ private float _firingVisibility;
+ private AudioSource _audio;
+
+ public MissileBehavior(MissileBehaviorData m, Ship ship, Gear item)
+ {
+ _missile = m;
+ Ship = ship;
+ Item = item;
+ // _audio = hp.Proxy.GetComponent();
+ // if(_audio==null)
+ // _audio = hp.Proxy.gameObject.AddComponent();
+ // _audio.clip = _missile.BeepSound;
+ // _audio.loop = true;
+ // _audio.volume = .5f;
+ }
+
+ public void Activate()
+ {
+ _locking = true;
+ _lockingTimer = 1;
+ }
+
+ private void Fire(long b)
+ {
+
+ // _firingVisibility += _missile.Visibility.Evaluate(Hardpoint);
+ // Hardpoint.Temperature += _missile.Heat.Evaluate(Hardpoint) / Hardpoint.HeatCapacity;
+ // var inst = GameObject.Instantiate(_missile.MissilePrefab).transform;
+ // var missile = inst.GetComponent();
+ // missile.Target = Hardpoint.Ship.Ship.Target;
+ // missile.Source = Hardpoint.Ship.Ship.Hitpoints;
+ // missile.Lifetime = _missile.Range.Evaluate(Hardpoint) / _missile.MissileSpeed.Evaluate(Hardpoint);
+ // missile.Damage = _missile.Damage.Evaluate(Hardpoint);
+ // inst.position = Hardpoint.Proxy.position;
+ // inst.rotation = Hardpoint.Proxy.rotation;
+ // inst.GetComponent().velocity = _missile.LaunchSpeed.Evaluate(Hardpoint) * Hardpoint.Proxy.forward;
+ // Physics.IgnoreCollision(Hardpoint.Ship.Ship.GetComponent(), inst.GetComponent());
+ // var proj = inst.gameObject.AddComponent();
+ // proj.GuidanceCurve = _missile.GuidanceCurve;
+ // proj.ThrustCurve = _missile.ThrustCurve;
+ // proj.LiftCurve = _missile.LiftCurve;
+ // proj.TopSpeed = _missile.MissileSpeed.Evaluate(Hardpoint);
+ // proj.Frequency = _missile.DodgeFrequency;
+ // proj.Target = Hardpoint.Ship.Ship.Target;
+ // proj.Source = Hardpoint.Ship.Ship.Hitpoints;
+ // proj.Thrust = _missile.Thrust.Evaluate(Hardpoint);
+ // _audio.PlayOneShot(_missile.Sounds.RandomElement());
+// Debug.Log($"Firing bullet {b}");
+ }
+
+ public void Deactivate()
+ {
+ // if (_lockingTimer < 0)
+ // {
+ // Fire(0);
+ // if(_missile.BurstCount>1)
+ // Observable.Interval(TimeSpan.FromSeconds(_missile.BurstTime.Evaluate(Hardpoint) / (_missile.BurstCount-1))).Take(_missile.BurstCount-1)
+ // .Subscribe(l => Fire(l+1));
+ // _lockingTimer = _cooldown = 1;
+ // _locking = _locked = false;
+ // _audio.Stop();
+ // }
+ // _locking = false;
+ // _lockingTimer = 1;
+ }
+
+ public void Update(float delta)
+ {
+ // if (Ship.Target == null)
+ // return;
+ //
+ // if (_locking && _cooldown < 0)
+ // {
+ // //if the crosshair stays under a certain LockOnBuffer distance for a certain amount of time (LockOnTime)
+ // if (acos(Vector2.Dot(Ship.Direction, (Ship.Target.transform.position-Ship.transform.position).normalized)) * Mathf.Rad2Deg < _missile.LockOnDegrees)
+ // {
+ // var d = delta / _missile.LockOnTime.Evaluate(Hardpoint);
+ // _lockingTimer -= d;
+ // if (!_locked && _lockingTimer < 0)
+ // {
+ // _locked = true;
+ // _audio.Play();
+ // } else if(Mathf.Repeat(_lockingTimer,1.0f/(_missile.Beeps+1))-d<0)
+ // GameManager.Instance.InterfaceAudio.PlayOneShot(_missile.BeepSound);
+ // }
+ // else
+ // {
+ // _lockingTimer = 1;
+ // _audio.Stop();
+ // }
+ // }
+ // else
+ // {
+ // _cooldown -= delta / _missile.Cooldown.Evaluate(Hardpoint);
+ // }
+ //
+ //
+ // if (_firingVisibility > 0.01f)
+ // {
+ // Hardpoint.Ship.Visibility += _firingVisibility;
+ // _firingVisibility = 0;
+ // }
+
+
+ }
+
+ public void FixedUpdate(float delta)
+ {
+ }
+
+ public IItemBehaviorData Data => _missile;
+}
+
+[MessagePackObject]
+public class ReactorBehaviorData : IItemBehaviorData
+{
+ [Inspectable] [Key("charge")] public PerformanceStat Charge;
+ [Inspectable] [Key("capacitance")] public PerformanceStat Capacitance;
+ [Inspectable] [Key("efficiency")] public PerformanceStat Efficiency;
+ [Inspectable] [Key("overload")] public PerformanceStat OverloadEfficiency;
+ [Inspectable] [Key("underload")] public PerformanceStat UnderloadRecovery;
+
+ public IItemBehavior CreateInstance(Ship ship, Gear item)
+ {
+ return new ReactorBehavior(this, ship, item);
+ }
+
+ [IgnoreMember] public PerformanceStat[] DynamicStats => new[] {Charge, Efficiency};
+}
+
+public class ReactorBehavior : IItemBehavior
+{
+ private ReactorBehaviorData _data;
+
+ public Ship Ship { get; }
+ public Gear Item { get; }
+
+ public IItemBehaviorData Data => _data;
+
+ public ReactorBehavior(ReactorBehaviorData data, Ship ship, Gear item)
+ {
+ _data = data;
+ Ship = ship;
+ Item = item;
+ }
+
+ public void FixedUpdate(float delta)
+ {
+ var cap = _data.Capacitance.Evaluate(Item, Ship);
+ var charge = _data.Charge.Evaluate(Item, Ship) * delta;
+ var efficiency = _data.Efficiency.Evaluate(Item, Ship);
+
+ Ship.AddHeat(charge / efficiency);
+ Ship.Charge += charge;
+
+ if (Ship.Charge > cap)
+ {
+ Ship.AddHeat(-(Ship.Charge - cap) / efficiency * (1 - 1 / _data.UnderloadRecovery.Evaluate(Item, Ship)));
+ Ship.Charge = cap;
+ }
+
+ if (Ship.Charge < 0)
+ {
+ Ship.AddHeat( -Ship.Charge / (_data.OverloadEfficiency.Evaluate(Item, Ship)));
+ Ship.Charge = 0;
+ }
+
+ }
+
+ public void Update(float delta)
+ {
+ }
+}
\ No newline at end of file
diff --git a/Assets/Scripts/NIH/FastNoise.cs.meta b/Assets/Scripts/Behaviors.cs.meta
similarity index 83%
rename from Assets/Scripts/NIH/FastNoise.cs.meta
rename to Assets/Scripts/Behaviors.cs.meta
index 305c2f947..94270ffb4 100644
--- a/Assets/Scripts/NIH/FastNoise.cs.meta
+++ b/Assets/Scripts/Behaviors.cs.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
-guid: 53b469b8da6bd4e4bb62cb13d1ce301d
+guid: c15c37d98e3dc844aafd0dedc16ce0ae
MonoImporter:
externalObjects: {}
serializedVersion: 2
diff --git a/Assets/Scripts/Database.cs b/Assets/Scripts/Database.cs
index f24e8c09f..228a761e1 100644
--- a/Assets/Scripts/Database.cs
+++ b/Assets/Scripts/Database.cs
@@ -128,18 +128,4 @@ public class Database
}, null);
watcher.EnableRaisingEvents = true;
}
-}
-
-public interface IDatabaseEntry
-{
- DatabaseEntry Entry { get; }
-}
-
-[Inspectable]
-[MessagePackObject]
-public class DatabaseEntry
-{
- [Key("id")] public Guid ID = Guid.NewGuid();
- [Inspectable] [Key("name")] public string Name;
- [Inspectable] [Key("description")] public string Description;
}
\ No newline at end of file
diff --git a/Assets/Scripts/DatabaseItems.cs b/Assets/Scripts/DatabaseItems.cs
new file mode 100644
index 000000000..50105847b
--- /dev/null
+++ b/Assets/Scripts/DatabaseItems.cs
@@ -0,0 +1,596 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using MessagePack;
+using UnityEngine;
+using Unity.Mathematics;
+using UnityEngine.UI.Extensions;
+// TODO: USE THIS EVERYWHERE
+using static Unity.Mathematics.math;
+#if UNITY_EDITOR
+using UnityEditor;
+#endif
+
+public class NameAttribute : Attribute
+{
+ public string Name;
+
+ public NameAttribute(string name)
+ {
+ Name = name;
+ }
+}
+
+public class UpdateOrderAttribute : Attribute
+{
+ public int Order;
+
+ public UpdateOrderAttribute(int order)
+ {
+ Order = order;
+ }
+}
+
+public class GlobalData : IDatabaseEntry
+{
+ [Inspectable] [Key("entry")] public DatabaseEntry DatabaseEntry = new DatabaseEntry();
+
+ [Inspectable] [Key("targetPersistenceDuration")]
+ public float TargetPersistenceDuration;
+ [Inspectable] [Key("heatRadiationPower")]
+ public float HeatRadiationPower;
+ [Inspectable] [Key("heatRadiationMultiplier")]
+ public float HeatRadiationMultiplier;
+
+ [IgnoreMember] public static GlobalData Instance => Database.GetAll().FirstOrDefault();
+ [IgnoreMember] public DatabaseEntry Entry => DatabaseEntry;
+}
+
+[Union(5, typeof(Hull))]
+[Union(6, typeof(Shield))]
+[Union(9, typeof(Thruster))]
+[Union(12, typeof(EquippableItem))]
+public interface IEquippable : ICraftable
+{
+ HardpointType HardpointType { get; }
+ EquippableData Equippable { get; }
+}
+
+[Union(5, typeof(Hull))]
+[Union(6, typeof(Shield))]
+[Union(9, typeof(Thruster))]
+[Union(12, typeof(CraftedItem))]
+[Union(13, typeof(EquippableItem))]
+public interface ICraftable : IItem
+{
+ Dictionary CraftingIngredients { get; }
+}
+
+[Union(5, typeof(Hull))]
+[Union(6, typeof(Shield))]
+[Union(9, typeof(Thruster))]
+[Union(12, typeof(ItemData))]
+[Union(13, typeof(CraftedItem))]
+[Union(14, typeof(EquippableItem))]
+public interface IItem : IDatabaseEntry
+{
+ ItemData Data { get; }
+}
+
+[Union(5, typeof(Hull))]
+[Union(6, typeof(Shield))]
+[Union(9, typeof(Thruster))]
+[Union(12, typeof(ItemData))]
+[Union(13, typeof(CraftedItem))]
+[Union(14, typeof(LoadoutDefinition))]
+[Union(15, typeof(ZoneData))]
+[Union(16, typeof(SimpleCommodity))]
+[Union(17, typeof(CompoundCommodity))]
+[Union(18, typeof(Gear))]
+[Union(19, typeof(EquippableItem))]
+//[Union(21, typeof(ContractData))]
+//[Union(22, typeof(Station))]
+[Union(23, typeof(Corporation))]
+[Union(24, typeof(Player))]
+[Union(25, typeof(GlobalData))]
+public interface IDatabaseEntry
+{
+ DatabaseEntry Entry { get; }
+}
+
+[Union(0, typeof(SimpleCommodity))]
+[Union(1, typeof(CompoundCommodity))]
+[Union(2, typeof(Gear))]
+public interface IItemInstance : IDatabaseEntry
+{
+ Guid ItemGuid { get; }
+ IItem ItemData { get; }
+ float Mass { get; }
+}
+
+[Union(0, typeof(Gear))]
+[Union(1, typeof(CompoundCommodity))]
+public interface ICraftedItemInstance : IItemInstance
+{
+ float CraftedQuality { get; }
+ IEnumerable CraftedIngredients { get; }
+}
+
+[Inspectable]
+[MessagePackObject]
+public class DatabaseEntry
+{
+ [Key("id")] public Guid ID = Guid.NewGuid();
+ [Inspectable] [Key("name")] public string Name;
+ [Inspectable] [Key("description")] public string Description;
+}
+
+[Inspectable]
+[MessagePackObject]
+[Name("Simple Commodity")]
+public class ItemData : IItem
+{
+ [Inspectable] [Key("entry")] public DatabaseEntry DatabaseEntry = new DatabaseEntry();
+ [Inspectable] [Key("mass")] public float Mass;
+ [Inspectable] [Key("size")] public float Size;
+
+ [RangedIntInspectable(0, 20)] [Key("level")] public int TechLevel;
+
+ [IgnoreMember] public ItemData Data => this;
+
+ [IgnoreMember] public DatabaseEntry Entry => DatabaseEntry;
+}
+
+[MessagePackObject]
+public class EquippableItem : IEquippable
+{
+ [Inspectable] [Key("hardpointType")] public HardpointType Hardpoint;
+ [Inspectable] [Key("itemData")] public ItemData ItemData = new ItemData();
+ [Inspectable] [Key("equippableData")] public EquippableData EquippableData = new EquippableData();
+ [Inspectable] [Key("ingredients")] public Dictionary Ingredients = new Dictionary();
+
+ [IgnoreMember] public HardpointType HardpointType => Hardpoint;
+ [IgnoreMember] public EquippableData Equippable => EquippableData;
+ [IgnoreMember] public ItemData Data => ItemData;
+ [IgnoreMember] public Dictionary CraftingIngredients => Ingredients;
+ [IgnoreMember] public DatabaseEntry Entry => ItemData.Entry;
+
+}
+
+[Inspectable]
+[MessagePackObject]
+public class EquippableData
+{
+ [Inspectable] [Key("draw")] public PerformanceStat EnergyDraw;
+ // [Inspectable] [Key("conductivity")] public float ThermalConductivity;
+ // [Inspectable] [Key("specificHeat")] public float SpecificHeat;
+ [Inspectable] [Key("performance")] public AnimationCurve HeatPerformanceCurve;
+ [TemperatureInspectable] [Key("minTemp")] public float MinimumTemperature;
+ [TemperatureInspectable] [Key("maxTemp")] public float MaximumTemperature;
+ [Inspectable] [Key("ruggedness")] public float Ruggedness;
+ [Inspectable] [Key("durability")] public float Durability;
+ [Inspectable] [Key("durabilityExponent")] public PerformanceStat DurabilityExponent;
+ [Inspectable] [Key("heatExponent")] public PerformanceStat HeatExponent;
+ [Inspectable] [Key("behaviors")] public List Behaviors = new List();
+
+ [IgnoreMember] private const int STEPS = 64;
+
+ [IgnoreMember] private float? _optimum;
+ [IgnoreMember]
+ 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));
+ }
+ }
+}
+
+[MessagePackObject]
+[Name("Compound Commodity")]
+public class CraftedItem : ICraftable
+{
+ [Inspectable] [Key("itemData")] public ItemData ItemData = new ItemData();
+ [Inspectable] [Key("ingredients")] public Dictionary Ingredients = new Dictionary();
+
+ [IgnoreMember] public ItemData Data => ItemData;
+ [IgnoreMember] public Dictionary CraftingIngredients => Ingredients;
+ [IgnoreMember] public DatabaseEntry Entry => ItemData.Entry;
+}
+
+[MessagePackObject]
+public class Hull : IEquippable
+{
+ [Inspectable] [Key("itemData")] public ItemData ItemData = new ItemData();
+ [Inspectable] [Key("equippableData")] public EquippableData EquippableData = new EquippableData();
+ [Inspectable] [Key("ingredients")] public Dictionary Ingredients = new Dictionary();
+ [Inspectable] [Key("hullCapacity")] public PerformanceStat Capacity;
+ [Inspectable] [Key("traction")] public PerformanceStat Traction;
+ [Inspectable] [Key("topSpeed")] public PerformanceStat TopSpeed;
+ [Inspectable] [Key("emissivity")] public PerformanceStat Emissivity;
+ [Inspectable] [Key("crossSection")] public PerformanceStat CrossSection;
+ [Key("schemaSprite")] [MessagePackFormatter(typeof(UnitySpriteFormatter))]
+ public Sprite Schematic;
+ [Inspectable] [Key("hardpoints")] public List Hardpoints = new List();
+ [Inspectable] [Key("visibility")] public AnimationCurve VisibilityCurve;
+ [MessagePackFormatter(typeof(UnityGameObjectFormatter))]
+ [Inspectable] [Key("prefab")] public GameObject Prefab;
+
+ [IgnoreMember] public HardpointType HardpointType => HardpointType.Hull;
+ [IgnoreMember] public EquippableData Equippable => EquippableData;
+ [IgnoreMember] public ItemData Data => ItemData;
+ [IgnoreMember] public Dictionary CraftingIngredients => Ingredients;
+ [IgnoreMember] public DatabaseEntry Entry => ItemData.Entry;
+}
+
+//[MessagePackObject]
+//public class Sensor : IEquippable
+//{
+// [Key("itemData")] public ItemData ItemData = new ItemData();
+// [Key("equippableData")] public EquippableData EquippableData = new EquippableData();
+// [Key("ingredients")] public Dictionary Ingredients = new Dictionary();
+// [Key("radiance")] public PerformanceStat Radiance;
+// [Key("masking")] public PerformanceStat RadianceMasking;
+// [Key("sensitivity")] public PerformanceStat Sensitivity;
+//
+// [IgnoreMember] public HardpointType HardpointType => HardpointType.Sensors;
+// [IgnoreMember] public EquippableData Equippable => EquippableData;
+// [IgnoreMember] public ItemData Data => ItemData;
+// [IgnoreMember] public Dictionary CraftingIngredients => Ingredients;
+// [IgnoreMember] public DatabaseEntry Entry => ItemData.Entry;
+//}
+//
+[MessagePackObject]
+public class Shield : IEquippable
+{
+ [Inspectable] [Key("itemData")]
+ public ItemData ItemData = new ItemData();
+
+ [Inspectable] [Key("equippableData")]
+ public EquippableData EquippableData = new EquippableData();
+
+ [Inspectable] [Key("ingredients")]
+ public Dictionary Ingredients = new Dictionary();
+
+ [Inspectable] [Key("efficiency")]
+ public PerformanceStat Efficiency;
+
+ [Inspectable] [Key("shielding")]
+ public PerformanceStat Shielding;
+
+ [IgnoreMember] public HardpointType HardpointType => HardpointType.Shield;
+ [IgnoreMember] public EquippableData Equippable => EquippableData;
+ [IgnoreMember] public ItemData Data => ItemData;
+ [IgnoreMember] public Dictionary CraftingIngredients => Ingredients;
+ [IgnoreMember] public DatabaseEntry Entry => ItemData.Entry;
+}
+
+[MessagePackObject]
+public class Thruster : IEquippable
+{
+ [Inspectable] [Key("itemData")] public ItemData ItemData = new ItemData();
+ [Inspectable] [Key("equippableData")] public EquippableData EquippableData = new EquippableData();
+ [Inspectable] [Key("ingredients")] public Dictionary Ingredients = new Dictionary();
+ [Inspectable] [Key("thrust")] public PerformanceStat Thrust;
+ [Inspectable] [Key("torque")] public PerformanceStat Torque;
+ [Inspectable] [Key("visibility")] public PerformanceStat Visibility;
+ [Inspectable] [Key("thrusterHeat")] public PerformanceStat Heat;
+// [Inspectable] [Key("minSound")] public GranularEmitterStats MinSound;
+// [Inspectable] [Key("maxSound")] public GranularEmitterStats MaxSound;
+// [Inspectable] [Key("time")] public float SoundTransitionTime;
+// [Inspectable] [Key("perlin")] public bool OscillatorPerlin;
+ // [MessagePackFormatter(typeof(UnityAudioClipFormatter))]
+ // [Inspectable] [Key("clip")] public AudioClip Clip;
+
+ [IgnoreMember] public HardpointType HardpointType => HardpointType.Thruster;
+ [IgnoreMember] public EquippableData Equippable => EquippableData;
+ [IgnoreMember] public ItemData Data => ItemData;
+ [IgnoreMember] public Dictionary CraftingIngredients => Ingredients;
+ [IgnoreMember] public DatabaseEntry Entry => ItemData.Entry;
+}
+
+//[MessagePackObject]
+//public class Launcher : IEquippable
+//{
+// [Key("itemData")] public ItemData ItemData = new ItemData();
+// [Key("equippableData")] public EquippableData EquippableData = new EquippableData();
+//// [Key("weaponData")] public WeaponData WeaponData = new WeaponData();
+// [Key("ingredients")] public Dictionary Ingredients = new Dictionary();
+// [MessagePackFormatter(typeof(UnityGameObjectFormatter))]
+// [Key("projectile")] public GameObject ProjectilePrefab;
+// [Key("launcherCaliber")] public LauncherCaliber Caliber;
+// [Key("salvoDuration")] public PerformanceStat SalvoDuration;
+// [Key("salvoSize")] public int SalvoSize;
+//
+// [IgnoreMember] public HardpointType HardpointType => HardpointType.Launcher;
+// [IgnoreMember] public EquippableData Equippable => EquippableData;
+// [IgnoreMember] public ItemData Data => ItemData;
+// [IgnoreMember] public Dictionary CraftingIngredients => Ingredients;
+//// [IgnoreMember] public WeaponData Weapon => WeaponData;
+// [IgnoreMember] public DatabaseEntry Entry => ItemData.Entry;
+//}
+
+//[MessagePackObject]
+//public class Beam : IEquippable
+//{
+// [Key("itemData")] public ItemData ItemData = new ItemData();
+// [Key("equippableData")] public EquippableData EquippableData = new EquippableData();
+//// [Key("weaponData")] public WeaponData WeaponData = new WeaponData();
+// [Key("ingredients")] public Dictionary Ingredients = new Dictionary();
+// [Key("duration")] public PerformanceStat Duration;
+// [Key("diameter")] public PerformanceStat Diameter;
+// [Key("amplitude")] public AnimationCurve Amplitude;
+// [MessagePackFormatter(typeof(UnityMaterialFormatter))]
+// [Key("material")] public Material BeamMaterial;
+// [Key("damageType")] public ProjectileType DamageType;
+//
+// [IgnoreMember] public HardpointType HardpointType => DamageType==ProjectileType.Physical?HardpointType.Ballistic:HardpointType.Energy;
+// [IgnoreMember] public EquippableData Equippable => EquippableData;
+// [IgnoreMember] public ItemData Data => ItemData;
+// [IgnoreMember] public Dictionary CraftingIngredients => Ingredients;
+//// [IgnoreMember] public WeaponData Weapon => WeaponData;
+// [IgnoreMember] public DatabaseEntry Entry => ItemData.Entry;
+//}
+
+[MessagePackObject]
+public struct PerformanceStat
+{
+ [Key("min")]
+ public float Min;
+ [Key("max")]
+ public float Max;
+ [Key("durabilityDependent")]
+ public bool DurabilityDependent;
+ [Key("heatDependent")]
+ public bool HeatDependent;
+ [Key("qualityExponent")]
+ public float QualityExponent;
+ [Key("ingredient")]
+ public Guid Ingredient;
+
+ [IgnoreMember] private Dictionary> _scaleModifiers;
+ [IgnoreMember] private Dictionary> _constantModifiers;
+
+ [IgnoreMember]
+ private Dictionary> ScaleModifiers
+ {
+ get { return _scaleModifiers ?? (_scaleModifiers = new Dictionary>()); }
+ }
+
+ [IgnoreMember]
+ private Dictionary> ConstantModifiers
+ {
+ get { return _constantModifiers ?? (_constantModifiers = new Dictionary>()); }
+ }
+
+ public Dictionary GetScaleModifiers(Ship ship)
+ {
+ if(!ScaleModifiers.ContainsKey(ship))
+ ScaleModifiers[ship] = new Dictionary();
+
+ return ScaleModifiers[ship];
+ }
+
+ public Dictionary GetConstantModifiers(Ship ship)
+ {
+ if(!ConstantModifiers.ContainsKey(ship))
+ ConstantModifiers[ship] = new Dictionary();
+
+ return ConstantModifiers[ship];
+ }
+
+ // Determine quality of either the item itself or the specific ingredient this stat depends on
+ public float Quality(Gear item)
+ {
+ Guid ingredientID = Ingredient;
+ float quality;
+ if (ingredientID == Guid.Empty)
+ quality = item.CompoundQuality();
+ else
+ {
+ var ingredientInstance =
+ item.CraftedIngredients.FirstOrDefault(i => i.ItemGuid == ingredientID) as ICraftedItemInstance;
+ if (ingredientInstance == null)
+ throw new InvalidOperationException(
+ $"Item {item.Entry.Name} has invalid crafting ingredient set for performance stat.");
+ quality = ingredientInstance.CompoundQuality();
+ }
+
+ return quality;
+ }
+
+ // Returns stat when not equipped
+ public float Evaluate(Gear item)
+ {
+ var quality = pow(Quality(item), QualityExponent);
+
+ var result = lerp(Min, Max, quality);
+
+ if (float.IsNaN(result))
+ return Min;
+
+ return result;
+ }
+
+ // Returns stat using ship temperature and modifiers
+ public float Evaluate(Gear item, Ship ship)
+ {
+ var itemData = item.EquippedItemData;
+
+ var heat = !HeatDependent ? 1 : pow(itemData.Performance(ship.Temperature), itemData.Equippable.HeatExponent.Evaluate(item));
+ var durability = !DurabilityDependent ? 1 : pow(item.Durability / itemData.Equippable.Durability, itemData.Equippable.DurabilityExponent.Evaluate(item));
+ var quality = pow(Quality(item), QualityExponent);
+
+ var scaleModifier = 1.0f;
+ if (_scaleModifiers != null && _scaleModifiers.ContainsKey(ship))
+ {
+ foreach (var mod in _scaleModifiers[ship].Values)
+ {
+ scaleModifier *= mod;
+ }
+ }
+
+ var constantModifier = 0.0f;
+ if (_constantModifiers != null && _constantModifiers.ContainsKey(ship))
+ {
+ foreach (var mod in _constantModifiers[ship].Values)
+ {
+ scaleModifier += mod;
+ }
+ }
+
+ var result = lerp(Min, Max, heat * durability * quality) * scaleModifier + constantModifier;
+ if (float.IsNaN(result))
+ return Min;
+ return result;
+ }
+}
+
+[MessagePackObject]
+public class Hardpoint
+{
+ [Key("item")] public Gear Item;
+
+ // [IgnoreMember] public Ship Ship;
+ [IgnoreMember] public HardpointData HardpointData;
+
+ // [IgnoreMember]
+ // public float HeatCapacity => Item != null
+ // ? Item.EquippedItemData.Data.Mass * Item.EquippedItemData.Equippable.SpecificHeat
+ // : Ship.Hull.EquippedItemData.Data.Mass * Ship.Hull.EquippedItemData.Equippable.SpecificHeat / Ship.HullHardpointCount;
+}
+
+
+[Name("Loadout")]
+[MessagePackObject]
+public class LoadoutDefinition : IDatabaseEntry
+{
+ [Inspectable] [Key("entry")] public DatabaseEntry DatabaseEntry = new DatabaseEntry();
+ [InspectableDatabaseLink(typeof(Hull))] [Key("hull")] public Guid Hull;
+ [Key("items")] public List Items = new List();
+
+ [IgnoreMember] public DatabaseEntry Entry => DatabaseEntry;
+}
+
+[MessagePackObject]
+public class Player : IDatabaseEntry
+{
+ [Inspectable] [Key("entry")] public DatabaseEntry DatabaseEntry = new DatabaseEntry();
+ [Key("email")] public string Email;
+ [Key("password")] public string Password;
+
+ [IgnoreMember] public DatabaseEntry Entry => DatabaseEntry;
+}
+
+
+[MessagePackObject]
+public class HardpointData
+{
+ [Key("type")] public HardpointType Type;
+}
+
+[MessagePackObject]
+public class ZoneData : IDatabaseEntry
+{
+ [Inspectable] [Key("entry")] public DatabaseEntry DatabaseEntry = new DatabaseEntry();
+ [Inspectable] [Key("radius")] public float Radius = 500;
+ [Inspectable] [Key("radiusPower")] public float RadiusPower = 1.75f;
+ [Inspectable] [Key("mass")] public float Mass = 100000;
+ [Inspectable] [Key("massFloor")] public float MassFloor = 1;
+ [Inspectable] [Key("sunMass")] public float SunMass = 10000;
+ [Inspectable] [Key("gasGiantMass")] public float GasGiantMass = 2000;
+ [Inspectable] [Key("stations")] public List Stations = new List();
+
+ [InspectableDatabaseLink(typeof(ZoneData))] [Key("wormholes")]
+ public List Wormholes = new List();
+
+ [IgnoreMember] public DatabaseEntry Entry => DatabaseEntry;
+}
+
+[Inspectable]
+[MessagePackObject]
+public class Station
+{
+ [Inspectable] [Key("name")] public string Name;
+ [InspectableDatabaseLink(typeof(Corporation))] [Key("faction")] public Guid Faction;
+ [Inspectable] [Key("dockingDistance")] public float DockingDistance = 10;
+ [Inspectable] [Key("buying")] public Dictionary BuyPrices = new Dictionary();
+ [Inspectable] [Key("selling")] public Dictionary SellPrices = new Dictionary();
+ [MessagePackFormatter(typeof(UnityGameObjectFormatter))] [Inspectable] [Key("prefab")] public GameObject Prefab;
+}
+
+[MessagePackObject]
+public class Corporation : IDatabaseEntry
+{
+ [Inspectable] [Key("entry")] public DatabaseEntry DatabaseEntry = new DatabaseEntry();
+ [InspectableDatabaseLink(typeof(Corporation))] [Key("parent")] public Guid ParentCorporation;
+ [Inspectable] [MessagePackFormatter(typeof(UnitySpriteFormatter))] [Key("logo")] public Sprite Logo;
+ [Inspectable] [Key("livery")] public Skin Livery = new Skin();
+
+ [IgnoreMember] public DatabaseEntry Entry => DatabaseEntry;
+}
+
+[Inspectable]
+[MessagePackObject]
+public class Skin
+{
+ [Inspectable] [MessagePackFormatter(typeof(UnityMaterialFormatter))] [Key("primary")] public Material Primary;
+ [Inspectable] [MessagePackFormatter(typeof(UnityMaterialFormatter))] [Key("secondary")] public Material Secondary;
+ [Inspectable] [MessagePackFormatter(typeof(UnityMaterialFormatter))] [Key("trim")] public Material Trim;
+ [Inspectable] [MessagePackFormatter(typeof(UnityMaterialFormatter))] [Key("windshield")] public Material Windshield;
+}
+
+
+public enum ProjectileType
+{
+ Physical,
+ Energy
+}
+
+public enum LauncherCaliber
+{
+ Missile,
+ Torpedo,
+ Fighter
+}
+
+public enum HardpointType
+{
+ Hull,
+ Thruster,
+ WarpThruster,
+ Reactor,
+ Radiator,
+ Shield,
+ Cooler,
+ Sensors,
+ Tool,
+ Energy,
+ Ballistic,
+ Launcher
+}
+
+public enum DamageType
+{
+ Kinetic,
+ Energy,
+ Thermal,
+ Optical,
+ Ionizing
+}
\ No newline at end of file
diff --git a/Assets/Scripts/DatabaseItems.cs.meta b/Assets/Scripts/DatabaseItems.cs.meta
new file mode 100644
index 000000000..7e44aa10b
--- /dev/null
+++ b/Assets/Scripts/DatabaseItems.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 3bb4780bed7bb544dbf6ea2223dd8f06
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Scripts/Editor.meta b/Assets/Scripts/Editor.meta
new file mode 100644
index 000000000..16a350fab
--- /dev/null
+++ b/Assets/Scripts/Editor.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: e53b57c0f2cbafc4385bf8cffe68542a
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Scripts/Editor/DatabaseEditor.cs b/Assets/Scripts/Editor/DatabaseEditor.cs
new file mode 100644
index 000000000..fafa86db7
--- /dev/null
+++ b/Assets/Scripts/Editor/DatabaseEditor.cs
@@ -0,0 +1,1092 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using Unity.Mathematics;
+using UnityEditor;
+using UnityEngine;
+using UnityEngine.Serialization;
+// TODO: USE THIS EVERYWHERE
+using static Unity.Mathematics.math;
+using Object = UnityEngine.Object;
+
+public class DatabaseListView : EditorWindow
+{
+ // Singleton to avoid multiple instances of window.
+ private static DatabaseListView _instance;
+ public Guid SelectedItem;
+ public GUIStyle SelectedStyle;
+
+ private bool[] _gearFoldouts;
+ private bool _itemsFoldout;
+ private bool _compoundFoldout;
+ private bool _simpleFoldout;
+ private bool _commoditiesFoldout;
+ //private bool _consumablesFoldout;
+ private Type[] _itemTypes;
+ private bool _listItemStyle;
+ private GUIStyle _listStyleOdd;
+ private GUIStyle _listStyleEven;
+ private static DatabaseInspector _inspector;
+ private Type[] _entryTypes;
+ private bool[] _entryFoldouts;
+ private const float LineHeight = 20;
+
+ // Set instance on reloading the window, else it gets lost after script reload (due to PlayMode changes, ...).
+ public DatabaseListView()
+ {
+ _instance = this;
+ }
+
+ public static DatabaseListView ShowWindow()
+ {
+ if (_instance == null)
+ {
+ // "Get existing open window or if none, make a new one:" says documentation.
+ // But if called after script reloads a second instance will be opened! => Custom singleton required.
+ DatabaseListView window = EditorWindow.GetWindow();
+ window.titleContent = new GUIContent("DB List");
+ _instance = window;
+ _instance.InitStyles();
+ window.Show();
+ }
+ else
+ _instance.Focus();
+
+ return _instance;
+ }
+
+ public GUIStyle ListItemStyle =>
+ (_listItemStyle = !_listItemStyle) ? _listStyleEven : _listStyleOdd;
+
+ [MenuItem("Window/Aetheria Database Tools")]
+ static void Init()
+ {
+ ShowWindow();
+ }
+
+ void OnEnable()
+ {
+ _inspector = DatabaseInspector.ShowWindow();
+ _itemTypes = typeof(IItem).GetAllInterfaceClasses();
+ _entryTypes = typeof(IDatabaseEntry).GetAllInterfaceClasses().Where(t => !t.GetInterfaces().Contains(typeof(IItem))&& !t.GetInterfaces().Contains(typeof(IItemInstance))).ToArray();
+ _gearFoldouts = new bool[_itemTypes.Length];
+ _entryFoldouts = new bool[_entryTypes.Length];
+ InitStyles();
+ Database.OnDataUpdate += Repaint;
+ }
+
+ private void InitStyles()
+ {
+ _listStyleOdd = new GUIStyle
+ {
+ normal = {background = XKCDColors.LightGrey.ToTexture()},
+ margin = new RectOffset(0, 0, 0, 0)
+ };
+ _listStyleEven = new GUIStyle
+ {
+ normal = {background = Color.Lerp(XKCDColors.LightGrey,Color.white,.5f).ToTexture()},
+ margin = new RectOffset(0, 0, 0, 0)
+ };
+ SelectedStyle = new GUIStyle
+ {
+ normal = {background = XKCDColors.Greyblue.ToTexture()},
+ margin = new RectOffset(0, 0, 0, 0)
+ };
+ }
+
+ public void OnGUI()
+ {
+ Event currentEvent = Event.current;
+ EventType currentEventType = currentEvent.type;
+
+ if (currentEventType == EventType.DragUpdated)
+ // Indicate that we don't accept drags ourselves
+ DragAndDrop.visualMode = DragAndDropVisualMode.Rejected;
+
+ Action select = item =>
+ {
+ SelectedItem = item.GetId();
+ Repaint();
+ _inspector.entry = Database.Get(SelectedItem);
+ _inspector.Repaint();
+ };
+
+ using (var h = new EditorGUILayout.HorizontalScope(ListItemStyle))
+ {
+ _itemsFoldout = EditorGUILayout.Foldout(_itemsFoldout, "Items", true);
+ }
+ if (_itemsFoldout)
+ {
+ var items = Database.AllEntries.Where(item => item is IItem).Cast().ToArray();
+ for (var i = 0; i < _itemTypes.Length; i++)
+ {
+ using (var h = new EditorGUILayout.HorizontalScope(ListItemStyle))
+ {
+ GUILayout.Space(10);
+ _gearFoldouts[i] = EditorGUILayout.Foldout(_gearFoldouts[i],
+ ((NameAttribute) _itemTypes[i].GetCustomAttribute(typeof(NameAttribute)))?.Name ?? _itemTypes[i].Name,
+ true);
+ }
+ if (_gearFoldouts[i])
+ {
+ foreach (var item in items.Where(e=>e.GetType()==_itemTypes[i]))
+ {
+ var style = ListItemStyle;
+ var selected = SelectedItem == item.GetId();
+ using (var h = new EditorGUILayout.HorizontalScope(selected?SelectedStyle:style))
+ {
+ if (h.rect.Contains(currentEvent.mousePosition))
+ {
+ if (currentEventType == EventType.MouseDrag)
+ {
+ DragAndDrop.PrepareStartDrag();
+ DragAndDrop.SetGenericData("Item", item.GetId());
+ DragAndDrop.StartDrag("Database Item");
+ }
+ else if (currentEventType == EventType.MouseUp)
+ select(item);
+ }
+ GUILayout.Space(20);
+ GUILayout.Label(item.Entry.Name, selected ? EditorStyles.whiteLabel : GUI.skin.label);
+ }
+ }
+
+ using (var h = new EditorGUILayout.HorizontalScope(ListItemStyle))
+ {
+ if(GUI.Button(h.rect, GUIContent.none, GUIStyle.none))
+ CreateItem(_itemTypes[i]);
+ GUILayout.Space(20);
+ GUILayout.Label("New " + _itemTypes[i].Name);
+ var rect = EditorGUILayout.GetControlRect(false, GUILayout.Width(EditorGUIUtility.singleLineHeight));
+ GUI.DrawTexture(rect, Icons.Instance.plus, ScaleMode.StretchToFill, true, 1, Color.black, 0, 0);
+ }
+ }
+ }
+ }
+
+ var entries = Database.AllEntries.Where(item => !(item is IItem)).ToArray();
+ for (var i = 0; i < _entryTypes.Length; i++)
+ {
+ using (var h = new EditorGUILayout.HorizontalScope(ListItemStyle))
+ {
+ _entryFoldouts[i] = EditorGUILayout.Foldout(_entryFoldouts[i],
+ ((NameAttribute) _entryTypes[i].GetCustomAttribute(typeof(NameAttribute)))?.Name ?? _entryTypes[i].Name,
+ true);
+ }
+
+ if (_entryFoldouts[i])
+ {
+ foreach (var entry in entries.Where(e=>e.GetType()==_entryTypes[i]))
+ {
+ var style = ListItemStyle;
+ var selected = SelectedItem == entry.GetId();
+ using (var h = new EditorGUILayout.HorizontalScope(selected?SelectedStyle:style))
+ {
+ if (h.rect.Contains(currentEvent.mousePosition))
+ {
+ if (currentEventType == EventType.MouseDrag)
+ {
+ DragAndDrop.PrepareStartDrag();
+ DragAndDrop.SetGenericData("Item", entry.GetId());
+ DragAndDrop.StartDrag("Database Item");
+ }
+ else if (currentEventType == EventType.MouseUp)
+ select(entry);
+ }
+ GUILayout.Space(10);
+ GUILayout.Label(entry.Entry.Name, selected ? EditorStyles.whiteLabel : GUI.skin.label);
+ }
+ }
+
+ using (var h = new EditorGUILayout.HorizontalScope(ListItemStyle))
+ {
+ if(GUI.Button(h.rect, GUIContent.none, GUIStyle.none))
+ CreateItem(_entryTypes[i]);
+ GUILayout.Space(10);
+ GUILayout.Label("New " + _entryTypes[i].Name);
+ var rect = EditorGUILayout.GetControlRect(false, GUILayout.Width(EditorGUIUtility.singleLineHeight));
+ GUI.DrawTexture(rect, Icons.Instance.plus, ScaleMode.StretchToFill, true, 1, Color.black, 0, 0);
+ }
+ }
+ }
+
+// EditorGUILayout.BeginHorizontal(ListItemStyle);
+// _commoditiesFoldout = EditorGUILayout.Foldout(_commoditiesFoldout, "Commodities", true);
+// EditorGUILayout.EndHorizontal();
+// if (_commoditiesFoldout)
+// {
+// using (var h = new EditorGUILayout.HorizontalScope(ListItemStyle))
+// {
+// GUILayout.Space(10);
+// _simpleFoldout = EditorGUILayout.Foldout(_simpleFoldout, "Simple", true);
+// }
+// if (_simpleFoldout)
+// {
+// foreach (var item in Database.Items.Values.Where(e=>e.GetType()==typeof(ItemData)).Cast())
+// {
+// var style = ListItemStyle;
+// var selected = SelectedItem == item.ID;
+// using (var h = new EditorGUILayout.HorizontalScope(selected?_selectedStyle:style))
+// {
+// if(GUI.Button(h.rect, GUIContent.none, GUIStyle.none))
+// select(item);
+// GUILayout.Space(20);
+// GUILayout.Label(item.Name, selected ? EditorStyles.whiteLabel : GUI.skin.label);
+// }
+// }
+//
+// using (var h = new EditorGUILayout.HorizontalScope(ListItemStyle))
+// {
+// if(GUI.Button(h.rect, GUIContent.none, GUIStyle.none))
+// CreateItem(typeof(ItemData));
+// GUILayout.Space(20);
+// var rect = EditorGUILayout.GetControlRect(false, GUILayout.Width(EditorGUIUtility.singleLineHeight));
+// GUI.DrawTexture(rect, GlobalData.Instance.plus, ScaleMode.StretchToFill, true, 1, Color.black, 0, 0);
+// GUILayout.Label("New Simple Commodity");
+// }
+// }
+//
+// using (var h = new EditorGUILayout.HorizontalScope(ListItemStyle))
+// {
+// GUILayout.Space(10);
+// _compoundFoldout = EditorGUILayout.Foldout(_compoundFoldout, "Compound", true);
+// }
+// if (_compoundFoldout)
+// {
+// foreach (var item in Database.Items.Values.Where(e=>e.GetType()==typeof(CraftedItem)).Cast())
+// {
+// var style = ListItemStyle;
+// var selected = SelectedItem == item.GetId();
+// using (var h = new EditorGUILayout.HorizontalScope(selected?_selectedStyle:style))
+// {
+// if (GUI.Button(h.rect, GUIContent.none, GUIStyle.none))
+// select(item);
+// GUILayout.Space(20);
+// GUILayout.Label(item.Item.Name, selected ? EditorStyles.whiteLabel : GUI.skin.label);
+// }
+// }
+//
+// using (var h = new EditorGUILayout.HorizontalScope(ListItemStyle))
+// {
+// if(GUI.Button(h.rect, GUIContent.none, GUIStyle.none))
+// CreateItem(typeof(CraftedItem));
+// GUILayout.Space(20);
+// var rect = EditorGUILayout.GetControlRect(false, GUILayout.Width(EditorGUIUtility.singleLineHeight));
+// GUI.DrawTexture(rect, GlobalData.Instance.plus, ScaleMode.StretchToFill, true, 1, Color.black, 0, 0);
+// GUILayout.Label("New Compound Commodity");
+// }
+// }
+// }
+// EditorGUILayout.BeginHorizontal(ListItemStyle);
+// _consumablesFoldout = EditorGUILayout.Foldout(_consumablesFoldout, "Consumables", true);
+// EditorGUILayout.EndHorizontal();
+// if (_consumablesFoldout)
+// {
+//
+// }
+
+ // HACK: This ensures none of the controls in this window can be focused (usually from clicking foldouts)
+ GUI.SetNextControlName("");
+ GUI.FocusControl("");
+ }
+
+ private void CreateItem(Type type)
+ {
+ var newEntry = (IDatabaseEntry) Activator.CreateInstance(type);
+ SelectedItem = newEntry.GetId();
+ newEntry.Entry.Name = $"New {type.Name}";
+ Database.Save(newEntry);
+ }
+}
+
+public class DatabaseInspector : EditorWindow
+{
+ public IDatabaseEntry entry;
+
+ // Singleton to avoid multiple instances of window.
+ private static DatabaseInspector _instance;
+
+ private DatabaseListView _list;
+ private GUIStyle _labelStyle;
+ private Vector2 _view;
+ private const float IconSize = 1.0f / 16;
+ private static HardpointData _hardpoint;
+ private static float2 _dragOffset;
+ private bool _ctrlDown;
+ private string[] _hardpointTypes;
+ private const int width = 100;
+ private const int labelWidth = 20;
+
+ // Set instance on reloading the window, else it gets lost after script reload (due to PlayMode changes, ...).
+ public DatabaseInspector()
+ {
+ _instance = this;
+ }
+
+ public static DatabaseInspector ShowWindow()
+ {
+ if (_instance == null)
+ {
+ // "Get existing open window or if none, make a new one:" says documentation.
+ // But if called after script reloads a second instance will be opened! => Custom singleton required.
+ DatabaseInspector window = GetWindow();
+ window.titleContent = new GUIContent("DB Inspector");
+ _instance = window;
+ window.Show();
+ }
+ else
+ _instance.Focus();
+
+ return _instance;
+ }
+
+ void OnEnable()
+ {
+ _list = DatabaseListView.ShowWindow();
+ Database.OnDataUpdate += Repaint;
+ wantsMouseMove = true;
+ _hardpoint = null;
+ _hardpointTypes = Enum.GetNames(typeof(HardpointType));
+ }
+
+ public void Inspect(object obj, bool inspectablesOnly = false, ICraftable craftable = null)
+ {
+ foreach (var field in obj.GetType().GetFields())
+ {
+ Inspect(obj, field, inspectablesOnly, craftable);
+ }
+ }
+
+ public void Inspect(object obj, FieldInfo field, bool inspectablesOnly = false, ICraftable craftable = null)
+ {
+ var inspectable = field.GetCustomAttribute();
+ if (inspectable == null && inspectablesOnly) return;
+
+ var type = field.FieldType;
+ var value = field.GetValue(obj);
+
+ var link = inspectable as InspectableDatabaseLinkAttribute;
+ if (type == typeof(float))
+ {
+ if (inspectable is RangedFloatInspectableAttribute)
+ {
+ var range = inspectable as RangedFloatInspectableAttribute;
+ field.SetValue(obj, Inspect(field.Name.SplitCamelCase(), (float) value, range.Min, range.Max));
+ }
+ else if (inspectable is TemperatureInspectableAttribute)
+ field.SetValue(obj, InspectTemperature(field.Name.SplitCamelCase(), (float) value));
+ else
+ field.SetValue(obj, Inspect(field.Name.SplitCamelCase(), (float) value));
+ }
+ else if (type == typeof(int))
+ {
+ if (inspectable is RangedIntInspectableAttribute)
+ {
+ var range = inspectable as RangedIntInspectableAttribute;
+ field.SetValue(obj, Inspect(field.Name.SplitCamelCase(), (int) value, range.Min, range.Max));
+ }
+ else
+ field.SetValue(obj, Inspect(field.Name.SplitCamelCase(), (int) value));
+ }
+ else if (type.IsEnum) field.SetValue(obj, Inspect(field.Name.SplitCamelCase(), (int) field.GetValue(obj), Enum.GetNames(field.FieldType)));
+ //else if (field.FieldType == typeof(Color)) Inspect(field.Name, () => (Color) field.GetValue(obj), c => field.SetValue(obj, c));
+ else if (type == typeof(bool)) field.SetValue(obj, Inspect(field.Name.SplitCamelCase(), (bool) value));
+ else if (type == typeof(string)) field.SetValue(obj, Inspect(field.Name.SplitCamelCase(), (string) value, inspectable is InspectableTextAttribute));
+ else if (type == typeof(GameObject)) field.SetValue(obj, Inspect(field.Name.SplitCamelCase(), (GameObject) value));
+ else if (type == typeof(AnimationCurve)) field.SetValue(obj, Inspect(field.Name.SplitCamelCase(), (AnimationCurve) value));
+ else if (type == typeof(PerformanceStat)) field.SetValue(obj, Inspect(field.Name.SplitCamelCase(), (PerformanceStat) value, craftable));
+ else if (type == typeof(PerformanceStat[]))
+ {
+ EditorGUILayout.LabelField(field.Name.SplitCamelCase(), EditorStyles.boldLabel);
+ using (new EditorGUILayout.VerticalScope(GUI.skin.box))
+ {
+ var stats = (PerformanceStat[]) value;
+ var damageTypes = Enum.GetNames(typeof(DamageType));
+ if(stats==null || stats.Length!=damageTypes.Length)
+ stats = new PerformanceStat[damageTypes.Length];
+ for (var i = 0; i < stats.Length; i++)
+ {
+ stats[i] = Inspect(damageTypes[i].SplitCamelCase(), stats[i], craftable);
+ }
+ field.SetValue(obj, stats);
+ }
+ }
+ else if (type == typeof(Dictionary))
+ {
+ var dict = (Dictionary) field.GetValue(obj);
+ Inspect(field.Name.SplitCamelCase(), ref dict);
+ }
+ else if (type == typeof(Dictionary))
+ {
+ var dict = (Dictionary) field.GetValue(obj);
+ Inspect(field.Name.SplitCamelCase(), ref dict);
+ }
+ else if (type == typeof(List) && link != null)
+ {
+ var list = (List) field.GetValue(obj);
+ if(list==null) field.SetValue(obj, (list = new List()));
+ Inspect(field.Name.SplitCamelCase(), ref list, link.EntryType);
+ }
+ else if (type == typeof(Guid) && link != null) field.SetValue(obj, Inspect(field.Name.SplitCamelCase(), (Guid) value, link.EntryType));
+ else if (type.GetCustomAttribute() != null)
+ {
+ EditorGUILayout.Space();
+ using (new EditorGUILayout.HorizontalScope())
+ {
+ EditorGUILayout.LabelField(field.Name.SplitCamelCase(), EditorStyles.boldLabel);
+ if (type.IsInterface)
+ {
+ var subTypes = type.GetAllInterfaceClasses();
+ var selected = value != null ? Array.IndexOf(subTypes, value.GetType()) + 1 : 0;
+ var newSelection = EditorGUILayout.Popup(selected,
+ subTypes.Select(t => t.Name.SplitCamelCase()).Prepend("None").ToArray());
+ if(newSelection != selected)
+ field.SetValue(obj, value = newSelection==0?null:Activator.CreateInstance(subTypes[newSelection-1]));
+ } else if(value == null) field.SetValue(obj, value = Activator.CreateInstance(type));
+ }
+ if(value != null) Inspect(field.GetValue(obj), inspectablesOnly, craftable);
+ }
+ else if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(List<>))
+ {
+ var listType = field.FieldType.GenericTypeArguments[0];
+ if (listType.GetCustomAttribute() != null)
+ {
+ EditorGUILayout.Space();
+ using (new EditorGUILayout.VerticalScope(GUI.skin.box))
+ {
+ var list = (IList) field.GetValue(obj);
+ if (list == null)
+ {
+ list = (IList) Activator.CreateInstance(type);
+ field.SetValue(obj, list);
+ }
+ foreach (var o in list)
+ {
+ using (new EditorGUILayout.VerticalScope(_list.ListItemStyle))
+ {
+ using (new EditorGUILayout.HorizontalScope())
+ {
+ GUILayout.Label(o.GetType().Name.SplitCamelCase(), EditorStyles.boldLabel, GUILayout.ExpandWidth(true));
+
+ var rect = EditorGUILayout.GetControlRect(false,
+ GUILayout.Width(EditorGUIUtility.singleLineHeight));
+ GUI.DrawTexture(rect, Icons.Instance.minus, ScaleMode.StretchToFill, true, 1,
+ Color.black, 0, 0);
+ if (GUI.Button(rect, GUIContent.none, GUIStyle.none))
+ {
+ list.Remove(o);
+ break;
+ }
+ }
+
+ EditorGUILayout.Space();
+
+ Inspect(o, inspectablesOnly, craftable);
+ }
+ }
+ using (new EditorGUILayout.HorizontalScope(_list.ListItemStyle))
+ {
+ GUILayout.Label($"Add new {listType.Name}", GUILayout.ExpandWidth(true));
+ var rect = EditorGUILayout.GetControlRect(false, GUILayout.Width(EditorGUIUtility.singleLineHeight));
+ GUI.DrawTexture(rect, Icons.Instance.plus, ScaleMode.StretchToFill, true, 1, Color.black, 0, 0);
+ if (GUI.Button(rect, GUIContent.none, GUIStyle.none))
+ {
+ if (listType.IsInterface)
+ {
+ var menu = new GenericMenu();
+ foreach (var behaviorType in listType.GetAllInterfaceClasses())
+ {
+ menu.AddItem(new GUIContent(behaviorType.Name), false, () =>
+ {
+ list.Add(Activator.CreateInstance(behaviorType));
+ Database.Save(entry);
+ });
+ }
+ menu.ShowAsContext();
+ }
+ else
+ {
+ list.Add(Activator.CreateInstance(listType));
+ }
+ }
+ }
+ }
+ }
+ else if (typeof(Object).IsAssignableFrom(listType))
+ {
+ EditorGUILayout.Space();
+ using (var v = new EditorGUILayout.VerticalScope(GUI.skin.box))
+ {
+ var list = (IList) field.GetValue(obj);
+ if (list == null)
+ {
+ list = (IList) Activator.CreateInstance(type);
+ field.SetValue(obj, list);
+ }
+
+ if(list.Count==0)
+ using (new EditorGUILayout.HorizontalScope(_list.ListItemStyle))
+ GUILayout.Label($"Add a {listType.Name} by dragging from the project hierarchy.");
+
+ foreach (var oo in list)
+ {
+ var o = (Object) oo;
+ using (new EditorGUILayout.HorizontalScope(_list.ListItemStyle))
+ {
+ GUILayout.Label(o.name.SplitCamelCase(), EditorStyles.boldLabel, GUILayout.ExpandWidth(true));
+
+ var rect = EditorGUILayout.GetControlRect(false,
+ GUILayout.Width(EditorGUIUtility.singleLineHeight));
+ GUI.DrawTexture(rect, Icons.Instance.minus, ScaleMode.StretchToFill, true, 1,
+ Color.black, 0, 0);
+ if (GUI.Button(rect, GUIContent.none, GUIStyle.none))
+ {
+ list.Remove(o);
+ break;
+ }
+ }
+ }
+
+ if (v.rect.Contains(Event.current.mousePosition) && (Event.current.type == EventType.DragUpdated || Event.current.type == EventType.DragPerform))
+ {
+ var dragObj = DragAndDrop.objectReferences.FirstOrDefault();
+ //var dragEntry = Database.Get(guid);
+ if(Event.current.type == EventType.DragUpdated)
+ DragAndDrop.visualMode = dragObj?.GetType() == listType ? DragAndDropVisualMode.Copy : DragAndDropVisualMode.Rejected;
+ else if(Event.current.type == EventType.DragPerform)
+ {
+ if (dragObj?.GetType() == listType)
+ {
+ DragAndDrop.AcceptDrag();
+ GUI.changed = true;
+ list.Add(dragObj);
+ }
+ }
+ }
+ }
+ }
+ else Debug.Log($"Field \"{field.Name}\" is a list of non-Inspectable type {listType.Name}. No inspector was generated.");
+ }
+ else if (typeof(Object).IsAssignableFrom(type))
+ {
+ using (new EditorGUILayout.HorizontalScope())
+ {
+ GUILayout.Label(field.Name.SplitCamelCase(), GUILayout.Width(width));
+ field.SetValue(obj, EditorGUILayout.ObjectField((Object)field.GetValue(obj),type,false));
+ }
+ }
+// else if (type == typeof(AudioClip))
+// {
+// using (new EditorGUILayout.HorizontalScope())
+// {
+// GUILayout.Label(field.Name.SplitCamelCase(), GUILayout.Width(width));
+// field.SetValue(obj, EditorGUILayout.ObjectField((AudioClip)field.GetValue(obj),typeof(AudioClip),false));
+// }
+// }
+ else Debug.Log($"Field \"{field.Name}\" has unknown type {field.FieldType.Name}. No inspector was generated.");
+ }
+
+ public bool Inspect(string label, bool value)
+ {
+ using (var h = new EditorGUILayout.HorizontalScope())
+ {
+ GUILayout.Label(label, GUILayout.Width(width));
+ return EditorGUILayout.Toggle(value);
+ }
+ }
+
+ public float Inspect(string label, float value)
+ {
+ using (var h = new EditorGUILayout.HorizontalScope())
+ {
+ GUILayout.Label(label, GUILayout.Width(width));
+ return EditorGUILayout.DelayedFloatField(value);
+ }
+ }
+
+ public string Inspect(string label, string value, bool area = false)
+ {
+ using (var h = new EditorGUILayout.HorizontalScope())
+ {
+ GUILayout.Label(label, GUILayout.Width(width));
+ if(area)
+ return EditorGUILayout.TextArea(value,GUILayout.MaxWidth(300));
+ return EditorGUILayout.DelayedTextField(value);
+ }
+ }
+
+ public float InspectTemperature(string label, float value)
+ {
+ using (var h = new EditorGUILayout.HorizontalScope())
+ {
+ GUILayout.Label(label, GUILayout.Width(width));
+ GUILayout.Label("°K", _labelStyle, GUILayout.Width(labelWidth));
+ value = EditorGUILayout.DelayedFloatField(value);//, GUILayout.ExpandWidth(false)
+ GUILayout.Label("°C", _labelStyle, GUILayout.Width(labelWidth));
+ value = EditorGUILayout.DelayedFloatField(value - 273.15f) + 273.15f;
+ GUILayout.Label("°F", _labelStyle, GUILayout.Width(labelWidth));
+ value = (EditorGUILayout.DelayedFloatField((value - 273.15f) * 1.8f + 32) - 32) / 1.8f + 273.15f;
+
+ return value;
+ }
+ }
+
+ public float Inspect(string label, float value, float min, float max)
+ {
+ using (var h = new EditorGUILayout.HorizontalScope())
+ {
+ GUILayout.Label(label, GUILayout.Width(width));
+ return EditorGUILayout.Slider(value, min, max);
+ }
+ }
+
+ public int Inspect(string label, int value)
+ {
+ using (var h = new EditorGUILayout.HorizontalScope())
+ {
+ GUILayout.Label(label, GUILayout.Width(width));
+ return EditorGUILayout.DelayedIntField(value);
+ }
+ }
+
+ public int Inspect(string label, int value, int min, int max)
+ {
+ using (var h = new EditorGUILayout.HorizontalScope())
+ {
+ GUILayout.Label(label, GUILayout.Width(width));
+ return EditorGUILayout.IntSlider(value, min, max);
+ }
+ }
+
+ public int Inspect(string label, int value, string[] enumOptions)
+ {
+ using (var h = new EditorGUILayout.HorizontalScope())
+ {
+ GUILayout.Label(label, GUILayout.Width(width));
+ return EditorGUILayout.Popup(value, enumOptions);
+ }
+ }
+
+ public GameObject Inspect(string label, GameObject value)
+ {
+ using (var h = new EditorGUILayout.HorizontalScope())
+ {
+ GUILayout.Label(label, GUILayout.Width(width));
+ return (GameObject) EditorGUILayout.ObjectField(value, typeof(GameObject), false);
+ }
+ }
+
+ public AnimationCurve Inspect(string label, AnimationCurve value)
+ {
+ using (var h = new EditorGUILayout.HorizontalScope())
+ {
+ GUILayout.Label(label, GUILayout.Width(width));
+ if (value == null)
+ value = new AnimationCurve();
+ value = EditorGUILayout.CurveField(value, Color.yellow, new Rect(0, 0, 1, 1));
+ }
+
+ return value;
+ }
+
+ public Guid Inspect(string label, Guid value, Type entryType)
+ {
+ EditorGUILayout.LabelField(label, EditorStyles.boldLabel);
+ var valueEntry = Database.Get(value);
+ using (var h = new EditorGUILayout.HorizontalScope(GUI.skin.box))
+ {
+ GUILayout.Label(valueEntry?.Entry.Name ?? $"Assign a {entryType.Name} by dragging from the list panel.");
+
+ if (h.rect.Contains(Event.current.mousePosition) && (Event.current.type == EventType.DragUpdated || Event.current.type == EventType.DragPerform))
+ {
+ var guid = (Guid) DragAndDrop.GetGenericData("Item");
+ var dragEntry = Database.Get(guid);
+ if(Event.current.type == EventType.DragUpdated)
+ DragAndDrop.visualMode = dragEntry != null && dragEntry.GetType()==entryType ? DragAndDropVisualMode.Copy : DragAndDropVisualMode.Rejected;
+ else if(Event.current.type == EventType.DragPerform)
+ {
+ if (guid != Guid.Empty && dragEntry.GetType()==entryType)
+ {
+ DragAndDrop.AcceptDrag();
+ GUI.changed = true;
+ return guid;
+ }
+ }
+ }
+ }
+
+ return value;
+ }
+
+ public void Inspect(string label, ref Dictionary value)
+ {
+ EditorGUILayout.Space();
+ EditorGUILayout.LabelField(label, EditorStyles.boldLabel);
+
+ using (var v = new EditorGUILayout.VerticalScope(GUI.skin.box))
+ {
+ if (value.Count == 0)
+ {
+ using (var h = new EditorGUILayout.HorizontalScope(_list.ListItemStyle))
+ {
+ GUILayout.Label("Nothing Here! Add an item by dragging from the list panel.");
+ }
+ }
+ foreach (var ingredient in value.ToArray())
+ {
+ using (var h = new EditorGUILayout.HorizontalScope(_list.ListItemStyle))
+ {
+ GUILayout.Label(Database.Get(ingredient.Key).Entry.Name);
+ value[ingredient.Key] = EditorGUILayout.DelayedIntField(value[ingredient.Key], GUILayout.Width(50));
+
+ var rect = EditorGUILayout.GetControlRect(false, GUILayout.Width(EditorGUIUtility.singleLineHeight));
+ GUI.DrawTexture(rect, Icons.Instance.minus, ScaleMode.StretchToFill, true, 1, Color.black, 0, 0);
+ if (GUI.Button(rect, GUIContent.none, GUIStyle.none) || value[ingredient.Key]==0)
+ value.Remove(ingredient.Key);
+ }
+ }
+
+ if (v.rect.Contains(Event.current.mousePosition))
+ {
+ if(Event.current.type == EventType.DragUpdated)
+ DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
+ else if(Event.current.type == EventType.DragPerform)
+ {
+ var guid = DragAndDrop.GetGenericData("Item");
+ if (guid is Guid)
+ {
+ DragAndDrop.AcceptDrag();
+ value[(Guid) guid] = 1;
+ GUI.changed = true;
+ }
+ }
+ }
+ }
+ }
+
+ public void Inspect(string label, ref Dictionary value)
+ {
+ EditorGUILayout.Space();
+ EditorGUILayout.LabelField(label, EditorStyles.boldLabel);
+
+ using (var v = new EditorGUILayout.VerticalScope(GUI.skin.box))
+ {
+ if (value.Count == 0)
+ {
+ using (var h = new EditorGUILayout.HorizontalScope(_list.ListItemStyle))
+ {
+ GUILayout.Label("Nothing Here! Add an item by dragging from the list panel.");
+ }
+ }
+ foreach (var ingredient in value.ToArray())
+ {
+ using (var h = new EditorGUILayout.HorizontalScope(_list.ListItemStyle))
+ {
+ GUILayout.Label(Database.Get(ingredient.Key).Entry.Name);
+ value[ingredient.Key] = EditorGUILayout.DelayedFloatField(value[ingredient.Key], GUILayout.Width(50));
+
+ var rect = EditorGUILayout.GetControlRect(false, GUILayout.Width(EditorGUIUtility.singleLineHeight));
+ GUI.DrawTexture(rect, Icons.Instance.minus, ScaleMode.StretchToFill, true, 1, Color.black, 0, 0);
+ if (GUI.Button(rect, GUIContent.none, GUIStyle.none))
+ value.Remove(ingredient.Key);
+ }
+ }
+
+ if (v.rect.Contains(Event.current.mousePosition))
+ {
+ if(Event.current.type == EventType.DragUpdated)
+ DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
+ else if(Event.current.type == EventType.DragPerform)
+ {
+ var guid = DragAndDrop.GetGenericData("Item");
+ if (guid is Guid)
+ {
+ DragAndDrop.AcceptDrag();
+ value[(Guid) guid] = 1;
+ GUI.changed = true;
+ }
+ }
+ }
+ }
+ }
+
+ public void Inspect(string label, ref List value, Type entryType)
+ {
+ EditorGUILayout.Space();
+ EditorGUILayout.LabelField(label, EditorStyles.boldLabel);
+
+ using (var v = new EditorGUILayout.VerticalScope(GUI.skin.box))
+ {
+ if (value.Count == 0)
+ {
+ using (var h = new EditorGUILayout.HorizontalScope(_list.ListItemStyle))
+ {
+ GUILayout.Label($"Nothing Here! Add a {entryType.Name} by dragging from the list panel.");
+ }
+ }
+ foreach (var ingredient in value.ToArray())
+ {
+ using (var h = new EditorGUILayout.HorizontalScope(_list.ListItemStyle))
+ {
+ GUILayout.Label(Database.Get(ingredient).Entry.Name);
+
+ var rect = EditorGUILayout.GetControlRect(false, GUILayout.Width(EditorGUIUtility.singleLineHeight));
+ GUI.DrawTexture(rect, Icons.Instance.minus, ScaleMode.StretchToFill, true, 1, Color.black, 0, 0);
+ if (GUI.Button(rect, GUIContent.none, GUIStyle.none))
+ value.Remove(ingredient);
+ }
+ }
+
+ if (v.rect.Contains(Event.current.mousePosition))
+ {
+ var guid = DragAndDrop.GetGenericData("Item");
+ var dragObj = DragAndDrop.GetGenericData("Item") is Guid ? ((Guid) guid).Get() : null;
+ if(Event.current.type == EventType.DragUpdated)
+ DragAndDrop.visualMode = entryType.IsInstanceOfType(dragObj) ? DragAndDropVisualMode.Copy : DragAndDropVisualMode.Rejected;
+ else if(Event.current.type == EventType.DragPerform)
+ {
+ if (entryType.IsInstanceOfType(dragObj))
+ {
+ DragAndDrop.AcceptDrag();
+ value.Add((Guid) guid);
+ GUI.changed = true;
+ }
+ }
+ }
+ }
+ }
+
+ public PerformanceStat Inspect(string label, PerformanceStat value, ICraftable craftable)
+ {
+ using (new EditorGUILayout.VerticalScope())
+ {
+ using (new EditorGUILayout.HorizontalScope())
+ {
+ GUILayout.Label(label, GUILayout.Width(width));
+ GUILayout.Label("Min", _labelStyle, GUILayout.Width(labelWidth));
+ value.Min = EditorGUILayout.DelayedFloatField(value.Min);
+ GUILayout.Label("Max", _labelStyle, GUILayout.Width(labelWidth + 5));
+ value.Max = EditorGUILayout.DelayedFloatField(value.Max);
+ }
+
+ using (new EditorGUILayout.HorizontalScope())
+ {
+ GUILayout.Label("", GUILayout.Width(width));
+ GUILayout.Label("H", _labelStyle);
+ value.HeatDependent = EditorGUILayout.Toggle(value.HeatDependent);
+ GUILayout.Label("D", _labelStyle);
+ value.DurabilityDependent = EditorGUILayout.Toggle(value.DurabilityDependent);
+ GUILayout.Label("QEx", _labelStyle, GUILayout.Width(labelWidth + 5));
+ value.QualityExponent = EditorGUILayout.DelayedFloatField(value.QualityExponent);
+ }
+
+ using (new EditorGUILayout.HorizontalScope())
+ {
+ GUILayout.Label("", GUILayout.Width(width));
+ GUILayout.Label("Ingredient", GUILayout.ExpandWidth(false));
+ var ingredients = craftable.CraftingIngredients.Keys.Select(Database.Get).Where(i => i is CraftedItem).Cast().ToList();
+ var ingredient = Database.Get(value.Ingredient) as CraftedItem;
+ var names = ingredients.Select(i => i.Entry.Name).Append("None").ToArray();
+ var selected = value.Ingredient == Guid.Empty || !craftable.CraftingIngredients.ContainsKey(value.Ingredient)
+ ? names.Length - 1
+ : ingredients.IndexOf(ingredient);
+ var selection = EditorGUILayout.Popup(selected, names);
+ value.Ingredient = selection == names.Length - 1 ? Guid.Empty : ingredients[selection].GetId();
+ }
+
+ EditorGUILayout.Space();
+
+ return value;
+ }
+ }
+
+ public void OnGUI()
+ {
+ _labelStyle = new GUIStyle(EditorStyles.centeredGreyMiniLabel) {normal = {textColor = Color.black}};
+
+ Event current = Event.current;
+ EventType currentEventType = current.type;
+ if (currentEventType == EventType.KeyDown && current.keyCode == KeyCode.LeftControl)
+ _ctrlDown = true;
+ if (currentEventType == EventType.KeyUp && current.keyCode == KeyCode.LeftControl)
+ _ctrlDown = false;
+
+ if (entry==null)
+ {
+ EditorGUILayout.LabelField($"{(_list.SelectedItem==Guid.Empty?"No Entry Selected":"Selected Entry Not Found in Database")}\n{_list.SelectedItem}");
+ return;
+ }
+
+ _view = EditorGUILayout.BeginScrollView(
+ _view,
+ false,
+ false,
+ GUIStyle.none,
+ GUI.skin.verticalScrollbar,
+ GUI.skin.scrollView,
+ GUILayout.Width(EditorGUIUtility.currentViewWidth),
+ GUILayout.ExpandHeight(true));
+
+ EditorGUI.BeginChangeCheck();
+
+ var dataEntry = entry.Entry;
+
+ using (new EditorGUILayout.HorizontalScope())
+ {
+ if(GUILayout.Button("Print JSON"))
+ Debug.Log(entry.ToJson());
+ if (GUILayout.Button("Duplicate"))
+ {
+ Database.Duplicate(entry);
+ }
+ if (GUILayout.Button("Delete Entry"))
+ {
+ Database.Delete(entry);
+ entry = null;
+ return;
+ }
+ }
+
+ using (var h = new EditorGUILayout.HorizontalScope())
+ {
+ GUILayout.Label("ID");
+ EditorGUILayout.LabelField(dataEntry.ID.ToString());
+ }
+
+ Inspect(entry, true, entry as ICraftable);
+
+ #region Hull
+ var hull = entry as Hull;
+ if (hull != null)
+ {
+ EditorGUILayout.Space();
+
+ // TODO: Hull Hardpoints Inspector
+
+ }
+ #endregion
+
+ #region Loadout
+ var loadout = entry as LoadoutDefinition;
+ if (loadout != null)
+ {
+ EditorGUILayout.Space();
+ EditorGUILayout.LabelField("Loadout Hull", EditorStyles.boldLabel);
+
+ var loadoutHull = Database.Get(loadout.Hull) as Hull;
+
+ if (loadoutHull != null)
+ {
+ // Reserve slots in the loadout for all equippable (non-hull) hardpoints
+ var hardpoints = loadoutHull.Hardpoints.Where(h => h.Type != HardpointType.Hull).ToArray();
+ if (loadout.Items.Count < hardpoints.Length)
+ loadout.Items.AddRange(Enumerable.Repeat(Guid.Empty, hardpoints.Length - loadout.Items.Count));
+
+ EditorGUILayout.Space();
+ using (var h = new EditorGUILayout.HorizontalScope())
+ {
+ GUILayout.Label($"Equipped Items: {loadout.Items.Sum(i=>((IItem) Database.Get(i))?.Data.Size ?? 0)}/{loadoutHull.Capacity.Min}", EditorStyles.boldLabel);
+ GUILayout.Label($"Mass: {loadout.Items.Sum(i=>((IItem) Database.Get(i))?.Data.Mass ?? 0)}", EditorStyles.boldLabel, GUILayout.ExpandWidth(false));
+ }
+
+ int itemIndex = 0;
+ using (var v = new EditorGUILayout.VerticalScope(GUI.skin.box))
+ {
+ for (; itemIndex < hardpoints.Length; itemIndex++)
+ {
+ var hp = hardpoints[itemIndex];
+
+ var loadoutItem = Database.Get(loadout.Items[itemIndex]) as IEquippable;
+
+ if (loadoutItem != null && loadoutItem.HardpointType != hp.Type)
+ {
+ loadout.Items[itemIndex] = Guid.Empty;
+ Debug.Log($"Invalid Item \"{loadoutItem.Entry.Name}\" in {Enum.GetName(typeof(HardpointType),hp.Type)} hardpoint for loadout \"{loadout.Entry.Name}\"");
+ Database.Save(entry);
+ }
+
+ using (var h = new EditorGUILayout.HorizontalScope(_list.ListItemStyle))
+ {
+ if (h.rect.Contains(current.mousePosition) &&
+ (currentEventType == EventType.DragUpdated || currentEventType == EventType.DragPerform))
+ {
+ var guid = (Guid) DragAndDrop.GetGenericData("Item");
+ var draggedEquippable = Database.Get(guid) as IEquippable;
+ var good = draggedEquippable != null && draggedEquippable.HardpointType == hp.Type;
+ if (currentEventType == EventType.DragUpdated)
+ DragAndDrop.visualMode = good ? DragAndDropVisualMode.Copy : DragAndDropVisualMode.Rejected;
+ else if (currentEventType == EventType.DragPerform && good)
+ {
+ DragAndDrop.AcceptDrag();
+ loadout.Items[itemIndex] = guid;
+
+ Database.Save(entry);
+ }
+ }
+
+ GUILayout.Label(Enum.GetName(typeof(HardpointType), hp.Type));
+ if (loadoutItem == null || loadoutItem.HardpointType != hp.Type)
+ GUILayout.Label("Empty Hardpoint", GUILayout.ExpandWidth(false));
+ else
+ {
+ GUILayout.Label(loadoutItem.Entry.Name, GUILayout.ExpandWidth(false));
+ var rect = EditorGUILayout.GetControlRect(false, GUILayout.Width(EditorGUIUtility.singleLineHeight));
+ GUI.DrawTexture(rect, Icons.Instance.minus, ScaleMode.StretchToFill, true, 1, Color.black, 0, 0);
+ if (GUI.Button(rect, GUIContent.none, GUIStyle.none))
+ loadout.Items[itemIndex] = Guid.Empty;
+ }
+ }
+ }
+ }
+
+ EditorGUILayout.Space();
+ EditorGUILayout.LabelField("Cargo", EditorStyles.boldLabel);
+
+ using (var v = new EditorGUILayout.VerticalScope(GUI.skin.box))
+ {
+ if (v.rect.Contains(current.mousePosition) &&
+ (currentEventType == EventType.DragUpdated || currentEventType == EventType.DragPerform))
+ {
+ var guid = (Guid) DragAndDrop.GetGenericData("Item");
+ var dragItem = Database.Get(guid) as IItem;
+ if (currentEventType == EventType.DragUpdated)
+ DragAndDrop.visualMode = dragItem != null ? DragAndDropVisualMode.Copy : DragAndDropVisualMode.Rejected;
+ else if (currentEventType == EventType.DragPerform && dragItem != null)
+ {
+ DragAndDrop.AcceptDrag();
+
+ loadout.Items.Add(guid);
+ Database.Save(entry);
+ }
+ }
+ if(itemIndex == loadout.Items.Count)
+ GUILayout.Label("Nothing Here!");
+ for (; itemIndex < loadout.Items.Count; itemIndex++)
+ {
+ var loadoutItem = Database.Get(loadout.Items[itemIndex]) as IItem;
+ using (var h = new EditorGUILayout.HorizontalScope(_list.ListItemStyle))
+ {
+ GUILayout.Label(loadoutItem?.Entry.Name ?? "Invalid Item");
+ var rect = EditorGUILayout.GetControlRect(false, GUILayout.Width(EditorGUIUtility.singleLineHeight));
+ GUI.DrawTexture(rect, Icons.Instance.minus, ScaleMode.StretchToFill, true, 1, Color.black, 0, 0);
+ if (GUI.Button(rect, GUIContent.none, GUIStyle.none))
+ loadout.Items.RemoveAt(itemIndex--);
+ }
+ }
+ }
+ }
+ }
+ #endregion
+
+ if (EditorGUI.EndChangeCheck())
+ {
+ Database.Save(entry);
+ }
+
+ EditorGUILayout.EndScrollView();
+
+ }
+}
diff --git a/Assets/Scripts/Editor/DatabaseEditor.cs.meta b/Assets/Scripts/Editor/DatabaseEditor.cs.meta
new file mode 100644
index 000000000..17ec8bd15
--- /dev/null
+++ b/Assets/Scripts/Editor/DatabaseEditor.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: b514fcab25f3b914b89824efbe244591
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Scripts/Extensions.cs b/Assets/Scripts/Extensions.cs
index 06f530ba9..e0bba961b 100644
--- a/Assets/Scripts/Extensions.cs
+++ b/Assets/Scripts/Extensions.cs
@@ -9,6 +9,8 @@ using Unity.Mathematics;
using UnityEngine;
using Random = UnityEngine.Random;
+using static Unity.Mathematics.math;
+
public static class Extensions
{
public static void BroadcastMessageExt(this GameObject go, string methodName, object value = null, SendMessageOptions options = SendMessageOptions.RequireReceiver)
@@ -39,6 +41,15 @@ public static class Extensions
}
}
+ private static Dictionary InterfaceClasses = new Dictionary();
+ public static Type[] GetAllInterfaceClasses(this Type type)
+ {
+ if (InterfaceClasses.ContainsKey(type))
+ return InterfaceClasses[type];
+ return InterfaceClasses[type] = AppDomain.CurrentDomain.GetAssemblies()
+ .SelectMany(ass => ass.GetTypes()).Where(t => t.IsClass && t.GetInterfaces().Contains(type)).ToArray();
+ }
+
public static bool IsDefault(this T value) where T : struct
{
bool isDefault = value.Equals(default(T));
@@ -54,16 +65,6 @@ public static class Extensions
return result;
}
-
- public static Vector2 Flatland(this Vector3 v)
- {
- return new Vector2(v.x, v.z);
- }
-
- public static Vector3 Flatland(this Vector2 v)
- {
- return new Vector3(v.x, 0, v.y);
- }
public static string SplitCamelCase( this string str )
{
@@ -95,5 +96,39 @@ public static class Extensions
{
return baseType.GetInterfaces().Any(interfaceType.Equals);
}
-
+
+ private static readonly Dictionary Quality = new Dictionary();
+ public static float CompoundQuality(this ICraftedItemInstance item)
+ {
+ if (Quality.ContainsKey(item)) return Quality[item];
+
+ var quality = item.CraftedQuality;
+
+ var craftedIngredients = item.CraftedIngredients.Where(i => i is ICraftedItemInstance).ToArray();
+ if (craftedIngredients.Length > 0)
+ {
+ quality *= craftedIngredients.Cast().Average(CompoundQuality);
+ }
+
+ Quality[item] = quality;
+
+ return Quality[item];
+ }
+
+ private static readonly Dictionary Tier = new Dictionary();
+ public static int ItemTier(this ICraftable item)
+ {
+ if (Tier.ContainsKey(item)) return Tier[item];
+
+ Tier[item] = item.CraftingIngredients.Keys.Max(ci => (Database.Get(ci) as ICraftable)?.ItemTier() ?? 0);
+
+ return Tier[item];
+ }
+
+ public static float Performance(this IEquippable item, float temperature)
+ {
+ return saturate(item.Equippable.HeatPerformanceCurve.Evaluate(saturate(
+ (temperature - item.Equippable.MinimumTemperature) /
+ (item.Equippable.MaximumTemperature - item.Equippable.MinimumTemperature))));
+ }
}
diff --git a/Assets/Scripts/Galaxy.cs b/Assets/Scripts/Galaxy.cs
index 023e33311..92c5bc6aa 100644
--- a/Assets/Scripts/Galaxy.cs
+++ b/Assets/Scripts/Galaxy.cs
@@ -6,6 +6,10 @@ using System.Linq;
using UnityEngine;
using NaughtyAttributes;
using JM.LinqFaster;
+using Unity.Mathematics;
+using static Unity.Mathematics.math;
+using static Unity.Mathematics.noise;
+using static NoiseFbm;
[CreateAssetMenu(menuName = "Aetheria/Galaxy")]
public class Galaxy : ScriptableObject
@@ -77,12 +81,30 @@ public class StarData
public List Names = new List();
}
+public static class NoiseFbm
+{
+ public static float fBm(float2 p, int octaves, float frequency, float offset, float amplitude, float lacunarity, float gain)
+ {
+ float freq = frequency, amp = .5f;
+ float sum = 0;
+ for(int i = 0; i < octaves; i++)
+ {
+ sum += snoise(p * freq) * amp;
+ freq *= lacunarity;
+ amp *= gain;
+ }
+ return (sum + offset)*amplitude;
+ }
+}
+
[Serializable]
public class GalaxyMapLayerData
{
public float CoreBoost = 1.05f;
public float CoreBoostOffset = .1f;
public float CoreBoostPower = 2.25f;
+ public float SpokeScale = 1;
+ public float SpokeOffset = 0;
public float EdgeReduction = 3;
public float NoiseOffset = 0;
public float NoiseAmplitude = 1.5f;
@@ -90,25 +112,21 @@ public class GalaxyMapLayerData
public float NoiseLacunarity = 2;
public int NoiseOctaves = 7;
public float NoiseFrequency = 1;
- public int NoiseSeed = 1337;
-
- private FastNoise _noise = new FastNoise();
+ public float NoisePosition = 1337;
- public float Evaluate(Vector2 uv, GalaxyMapData galaxy)
+ public float Evaluate(float2 uv, GalaxyMapData galaxy)
{
- _noise.SetFractalGain(NoiseGain);
- _noise.SetFractalLacunarity(NoiseLacunarity);
- _noise.SetFractalOctaves(NoiseOctaves);
- _noise.SetFrequency(NoiseFrequency);
- _noise.SetSeed(NoiseSeed);
-
- Func offset = v => Vector2.one / 2 - v;
- Func circle = v => (.5f - v.magnitude) * 2;
- Func twist = v => v.Rotate(Mathf.Pow(v.magnitude*2,galaxy.TwistPower)*galaxy.Twist);
- Func spokes = v => Mathf.Sin(Mathf.Atan2(-v.y,v.x)*galaxy.Arms);
- var c = circle(offset(uv));
- return Mathf.Clamp01((Mathf.Lerp(spokes(twist(offset(uv))) - EdgeReduction * offset(uv).magnitude, 1,
- Mathf.Pow(c + CoreBoostOffset, CoreBoostPower) * CoreBoost) - (_noise.GetPerlin(uv.x,uv.y)+NoiseOffset) * NoiseAmplitude) * Mathf.Clamp01(c));
+ float2 offset = -float2(.5f, .5f)+uv;
+ float circle = (.5f-length(offset))*2;
+ float angle = pow(length(offset)*2,galaxy.TwistPower) * galaxy.Twist;
+ float2 twist = float2(offset.x*cos(angle) - offset.y*sin(angle), offset.x*sin(angle) + offset.y*cos(angle));
+ float atan = atan2(twist.y,twist.x);
+ float spokes = sin(atan*galaxy.Arms) * SpokeScale + SpokeOffset;
+ float noise = fBm(uv + float2(NoisePosition), NoiseOctaves, NoiseFrequency, NoiseOffset, NoiseAmplitude, NoiseLacunarity, NoiseGain);
+ float shape = lerp(spokes - EdgeReduction * length(offset), 1, pow(circle + CoreBoostOffset, CoreBoostPower) * CoreBoost);
+ float gal = max(shape - noise * saturate(circle), 0);
+
+ return gal;
}
}
diff --git a/Assets/Scripts/Icons.cs b/Assets/Scripts/Icons.cs
new file mode 100644
index 000000000..7a45928f4
--- /dev/null
+++ b/Assets/Scripts/Icons.cs
@@ -0,0 +1,16 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+[CreateAssetMenu(fileName = "Icons", menuName = "Aetheria/Icons")]
+public class Icons : ScriptableObject
+{
+ public Texture2D plus;
+ public Texture2D minus;
+
+ private const string AssetPath = "Icons";
+ private static Icons _instance;
+ public static Icons Instance {
+ get { return _instance ?? (_instance = Resources.Load(AssetPath)); }
+ }
+}
diff --git a/Assets/Scripts/Icons.cs.meta b/Assets/Scripts/Icons.cs.meta
new file mode 100644
index 000000000..e7556bb2e
--- /dev/null
+++ b/Assets/Scripts/Icons.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 32eff58a98b2e4c43a9a375c7db56e25
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Scripts/ItemInstance.cs b/Assets/Scripts/ItemInstance.cs
new file mode 100644
index 000000000..e96424dce
--- /dev/null
+++ b/Assets/Scripts/ItemInstance.cs
@@ -0,0 +1,336 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Runtime.Remoting.Messaging;
+using JM.LinqFaster;
+using MessagePack;
+using MessagePack.Formatters;
+using MIConvexHull;
+using UniRx;
+using UnityEngine;
+using Unity.Mathematics;
+using UnityEngine.UI.Extensions;
+using Object = UnityEngine.Object;
+// TODO: USE THIS EVERYWHERE
+using static Unity.Mathematics.math;
+using Random = UnityEngine.Random;
+#if UNITY_EDITOR
+using UnityEditor;
+#endif
+
+[MessagePackObject]
+public class Ship
+{
+ [Key("hull")]
+ public Gear Hull;
+ [Key("hardpoints")]
+ public List Hardpoints = new List();
+ [Key("cargo")]
+ public List Cargo = new List();
+
+ // [Key("bindings")] public Dictionary Bindings = new Dictionary();
+ //[IgnoreMember] public int HullHardpointCount;
+ [IgnoreMember] public Dictionary ItemBindings;
+ [IgnoreMember] public IItemBehavior[] ItemBehaviors;
+
+ [IgnoreMember] public bool ForceThrust;
+ //[IgnoreMember] public Ship Ship;
+ [IgnoreMember] public Dictionary Contacts = new Dictionary();
+ [IgnoreMember] public float Temperature;
+ [IgnoreMember] public float Charge;
+ [IgnoreMember] public Targetable Target;
+ [IgnoreMember] public Vector2 Direction;
+ [IgnoreMember] public Dictionary