APC & SMES appearances. (#78)

* CEV-Eris SMES sprite as RSI.

Has been modified so that the light overlay states use alpha blending.

* Add tiny glow to SMES display sprite.

* Appearances work v2

* More WiP

* RoundToLevels works correctly on even level counts now.

* SMES -> Smes because MS guidelines.

* CEV-Eris APC sprite.

* APC visuals.

* Reduce SMES scale again to normal levels.

* Update submodule
This commit is contained in:
Pieter-Jan Briers
2018-07-17 11:39:55 +02:00
committed by GitHub
parent 7629d447aa
commit ad5c82fec9
69 changed files with 1253 additions and 29 deletions

View File

@@ -108,5 +108,7 @@
<ItemGroup>
<None Include="app.config" />
<None Include="packages.config" />
<Compile Include="GameObjects\Components\Power\SmesVisualizer2D.cs" />
<Compile Include="GameObjects\Components\Power\ApcVisualizer2D.cs" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,67 @@
using Content.Shared.GameObjects.Components.Power;
using SS14.Client.GameObjects;
using SS14.Client.Interfaces.GameObjects.Components;
using SS14.Shared.Interfaces.GameObjects;
namespace Content.Client.GameObjects.Components.Power
{
public class ApcVisualizer2D : AppearanceVisualizer
{
public override void InitializeEntity(IEntity entity)
{
base.InitializeEntity(entity);
var sprite = entity.GetComponent<ISpriteComponent>();
sprite.LayerMapSet(Layers.ChargeState, sprite.AddLayerState("apco3-0"));
sprite.LayerSetShader(Layers.ChargeState, "unshaded");
sprite.LayerMapSet(Layers.Lock, sprite.AddLayerState("apcox-0"));
sprite.LayerSetShader(Layers.Lock, "unshaded");
sprite.LayerMapSet(Layers.Equipment, sprite.AddLayerState("apco0-3"));
sprite.LayerSetShader(Layers.Equipment, "unshaded");
sprite.LayerMapSet(Layers.Lighting, sprite.AddLayerState("apco1-3"));
sprite.LayerSetShader(Layers.Lighting, "unshaded");
sprite.LayerMapSet(Layers.Environment, sprite.AddLayerState("apco2-3"));
sprite.LayerSetShader(Layers.Environment, "unshaded");
}
public override void OnChangeData(AppearanceComponent component)
{
base.OnChangeData(component);
var sprite = component.Owner.GetComponent<ISpriteComponent>();
if (component.TryGetData<ApcChargeState>(ApcVisuals.ChargeState, out var state))
{
switch (state)
{
case ApcChargeState.Lack:
sprite.LayerSetState(Layers.ChargeState, "apco3-0");
break;
case ApcChargeState.Charging:
sprite.LayerSetState(Layers.ChargeState, "apco3-1");
break;
case ApcChargeState.Full:
sprite.LayerSetState(Layers.ChargeState, "apco3-2");
break;
}
}
else
{
sprite.LayerSetState(Layers.ChargeState, "apco3-0");
}
}
enum Layers
{
ChargeState,
Lock,
Equipment,
Lighting,
Environment,
}
}
}

View File

@@ -10,6 +10,7 @@ namespace Content.Client.GameObjects.Components.Power
{
public class PowerDebugTool : SharedPowerDebugTool
{
SS14Window LastWindow;
public override void HandleMessage(ComponentMessage message, INetChannel netChannel = null, IComponent component = null)
{
base.HandleMessage(message, netChannel, component);
@@ -17,13 +18,17 @@ namespace Content.Client.GameObjects.Components.Power
switch (message)
{
case OpenDataWindowMsg msg:
var window = new SS14Window
if (LastWindow != null && !LastWindow.Disposed)
{
Title = "Power Debug Tool"
LastWindow.Dispose();
}
LastWindow = new SS14Window
{
Title = "Power Debug Tool",
};
window.Contents.AddChild(new Label() { Text = msg.Data });
window.AddToScreen();
window.Open();
LastWindow.Contents.AddChild(new Label() { Text = msg.Data });
LastWindow.AddToScreen();
LastWindow.Open();
break;
}
}

View File

@@ -0,0 +1,77 @@
using Content.Shared.GameObjects.Components.Power;
using SS14.Client.GameObjects;
using SS14.Client.Interfaces.GameObjects.Components;
using SS14.Shared.Interfaces.GameObjects;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Content.Client.GameObjects.Components.Power
{
public class SmesVisualizer2D : AppearanceVisualizer
{
public override void InitializeEntity(IEntity entity)
{
base.InitializeEntity(entity);
var sprite = entity.GetComponent<ISpriteComponent>();
sprite.LayerMapSet(Layers.Input, sprite.AddLayerState("smes-oc0"));
sprite.LayerSetShader(Layers.Input, "unshaded");
sprite.LayerMapSet(Layers.Charge, sprite.AddLayerState("smes-og1"));
sprite.LayerSetShader(Layers.Charge, "unshaded");
sprite.LayerSetVisible(Layers.Charge, false);
sprite.LayerMapSet(Layers.Output, sprite.AddLayerState("smes-op0"));
sprite.LayerSetShader(Layers.Output, "unshaded");
}
public override void OnChangeData(AppearanceComponent component)
{
base.OnChangeData(component);
var sprite = component.Owner.GetComponent<ISpriteComponent>();
if (!component.TryGetData<int>(SmesVisuals.LastChargeLevel, out var level) || level == 0)
{
sprite.LayerSetVisible(Layers.Charge, false);
}
else
{
sprite.LayerSetVisible(Layers.Charge, true);
sprite.LayerSetState(Layers.Charge, $"smes-og{level}");
}
if (component.TryGetData<ChargeState>(SmesVisuals.LastChargeState, out var state))
{
switch (state)
{
case ChargeState.Still:
sprite.LayerSetState(Layers.Input, "smes-oc0");
sprite.LayerSetState(Layers.Output, "smes-op1");
break;
case ChargeState.Charging:
sprite.LayerSetState(Layers.Input, "smes-oc1");
sprite.LayerSetState(Layers.Output, "smes-op1");
break;
case ChargeState.Discharging:
sprite.LayerSetState(Layers.Input, "smes-oc0");
sprite.LayerSetState(Layers.Output, "smes-op2");
break;
}
}
else
{
sprite.LayerSetState(Layers.Input, "smes-oc0");
sprite.LayerSetState(Layers.Output, "smes-op1");
}
}
enum Layers
{
Input,
Charge,
Output,
}
}
}

View File

@@ -140,5 +140,7 @@
<ItemGroup>
<None Include="app.config" />
<None Include="packages.config" />
<Compile Include="GameObjects\Components\Power\SmesComponent.cs" />
<Compile Include="GameObjects\Components\Power\ApcComponent.cs" />
</ItemGroup>
</Project>

View File

@@ -91,6 +91,8 @@ namespace Content.Server
factory.Register<PowerDebugTool>();
factory.Register<PoweredLightComponent>();
factory.Register<SmesComponent>();
factory.Register<ApcComponent>();
}
/// <inheritdoc />

View File

@@ -0,0 +1,50 @@
using Content.Shared.GameObjects.Components.Power;
using SS14.Server.GameObjects;
using SS14.Shared.GameObjects;
namespace Content.Server.GameObjects.Components.Power
{
public class ApcComponent : Component
{
public override string Name => "Apc";
PowerStorageComponent Storage;
AppearanceComponent Appearance;
ApcChargeState LastChargeState;
public override void Initialize()
{
base.Initialize();
Storage = Owner.GetComponent<PowerStorageComponent>();
Appearance = Owner.GetComponent<AppearanceComponent>();
}
public override void Update(float frameTime)
{
var newState = CalcChargeState();
if (newState != LastChargeState)
{
LastChargeState = newState;
Appearance.SetData(ApcVisuals.ChargeState, newState);
}
}
ApcChargeState CalcChargeState()
{
var storageCharge = Storage.GetChargeState();
if (storageCharge == ChargeState.Discharging)
{
return ApcChargeState.Lack;
}
if (storageCharge == ChargeState.Charging)
{
return ApcChargeState.Charging;
}
// Still.
return Storage.Full ? ApcChargeState.Full : ApcChargeState.Lack;
}
}
}

View File

@@ -1,3 +1,4 @@
using System;
using System.Text;
using Content.Server.GameObjects.EntitySystems;
using Content.Shared.GameObjects.Components.Power;
@@ -61,9 +62,11 @@ namespace Content.Server.GameObjects.Components.Power
if (attacked.TryGetComponent<PowerStorageComponent>(out var storage))
{
var stateSeconds = (DateTime.Now - storage.LastChargeStateChange).TotalSeconds;
builder.AppendFormat(@"Power Storage:
Capacity: {0}, Charge: {1}, ChargeRate: {2}, DistributionRate: {3}, ChargePowernet: {4}
", storage.Capacity, storage.Charge, storage.ChargeRate, storage.DistributionRate, storage.ChargePowernet);
LastChargeState: {5} ({6}), LastChargeStateChange: {7:0.00} seconds ago.
", storage.Capacity, storage.Charge, storage.ChargeRate, storage.DistributionRate, storage.ChargePowernet, storage.LastChargeState, storage.GetChargeState(), stateSeconds);
}
if (attacked.TryGetComponent<PowerTransferComponent>(out var transfer))

View File

@@ -1,4 +1,5 @@
using SS14.Shared.GameObjects;
using Content.Shared.GameObjects.Components.Power;
using SS14.Shared.GameObjects;
using SS14.Shared.Interfaces.GameObjects;
using SS14.Shared.IoC;
using SS14.Shared.Utility;
@@ -14,6 +15,9 @@ namespace Content.Server.GameObjects.Components.Power
{
public override string Name => "PowerStorage";
public ChargeState LastChargeState { get; private set; } = ChargeState.Still;
public DateTime LastChargeStateChange { get; private set; }
/// <summary>
/// Maximum amount of energy the internal battery can store.
/// In Joules.
@@ -38,6 +42,8 @@ namespace Content.Server.GameObjects.Components.Power
/// </summary>
public float DistributionRate { get; private set; } = 1000;
public bool Full => Charge >= Capacity;
private bool _chargepowernet = false;
/// <summary>
@@ -129,15 +135,19 @@ namespace Content.Server.GameObjects.Components.Power
public void DeductCharge(float todeduct)
{
Charge = Math.Max(0, Charge - todeduct);
LastChargeState = ChargeState.Discharging;
LastChargeStateChange = DateTime.Now;
}
public void AddCharge(float charge)
{
Charge = Math.Min(Capacity, Charge + charge);
LastChargeState = ChargeState.Charging;
LastChargeStateChange = DateTime.Now;
}
/// <summary>
/// Returns the charge available from the energy storage
/// Returns the amount of energy that can be taken in by this storage in the specified amount of time.
/// </summary>
public float RequestCharge(float frameTime)
{
@@ -145,15 +155,33 @@ namespace Content.Server.GameObjects.Components.Power
}
/// <summary>
/// Returns the charge available from the energy storage
/// Returns the amount of energy available for discharge in the specified amount of time.
/// </summary>
public float AvailableCharge(float frameTime)
{
return Math.Min(DistributionRate * frameTime, Charge);
}
public ChargeState GetChargeState()
{
return GetChargeState(TimeSpan.FromSeconds(1));
}
public ChargeState GetChargeState(TimeSpan timeout)
{
if (LastChargeStateChange + timeout > DateTime.Now)
{
return LastChargeState;
}
return ChargeState.Still;
}
public void ChargePowerTick(float frameTime)
{
if (Full)
{
return;
}
AddCharge(RequestCharge(frameTime));
}

View File

@@ -145,6 +145,10 @@ namespace Content.Server.GameObjects.Components.Power
break;
}
var demand = consumer.RequestCharge(frameTime);
if (demand == 0)
{
continue;
}
var taken = Math.Min(demand, totalRemaining);
totalRemaining -= taken;
consumer.AddCharge(taken);
@@ -155,6 +159,10 @@ namespace Content.Server.GameObjects.Components.Power
foreach (var supplier in PowerStorageSupplierList)
{
var load = supplier.AvailableCharge(frameTime);
if (load == 0)
{
continue;
}
var added = Math.Min(load, supplierUsed);
supplierUsed -= added;
supplier.DeductCharge(added);

View File

@@ -0,0 +1,53 @@
using System;
using Content.Shared.GameObjects.Components.Power;
using Content.Shared.Utility;
using SS14.Server.GameObjects;
using SS14.Shared.GameObjects;
namespace Content.Server.GameObjects.Components.Power
{
/// <summary>
/// Handles the "user-facing" side of the actual SMES object.
/// This is operations that are specific to the SMES, like UI and visuals.
/// Code interfacing with the powernet is handled in <see cref="PowerStorageComponent" />.
/// </summary>
public class SmesComponent : Component
{
public override string Name => "Smes";
PowerStorageComponent Storage;
AppearanceComponent Appearance;
int LastChargeLevel = 0;
ChargeState LastChargeState;
public override void Initialize()
{
base.Initialize();
Storage = Owner.GetComponent<PowerStorageComponent>();
Appearance = Owner.GetComponent<AppearanceComponent>();
}
public override void Update(float frameTime)
{
var newLevel = CalcChargeLevel();
if (newLevel != LastChargeLevel)
{
LastChargeLevel = newLevel;
Appearance.SetData(SmesVisuals.LastChargeLevel, newLevel);
}
var newState = Storage.GetChargeState();
if (newState != LastChargeState)
{
LastChargeState = newState;
Appearance.SetData(SmesVisuals.LastChargeState, newState);
}
}
int CalcChargeLevel()
{
return ContentHelpers.RoundToLevels(Storage.Charge, Storage.Capacity, 6);
}
}
}

View File

@@ -67,6 +67,7 @@
<Compile Include="GameObjects\Components\Inventory\EquipmentSlotDefinitions.cs" />
<Compile Include="GameObjects\Components\Inventory\InventoryTemplates.cs" />
<Compile Include="GameObjects\Components\Inventory\SharedInventoryComponent.cs" />
<Compile Include="GameObjects\Components\Power\PowerShared.cs" />
<Compile Include="GameObjects\Components\Storage\SharedStorageComponent.cs" />
<Compile Include="GameObjects\ContentNetIDs.cs" />
<Compile Include="GameObjects\PhysicalConstants.cs" />
@@ -100,6 +101,9 @@
<None Include="app.config" />
<None Include="packages.config" />
<Compile Include="Input\ContentKeyFunctions.cs" />
<Compile Include="Utility\ContentHelpers.cs" />
<Compile Include="GameObjects\Components\Power\SharedSmesComponent.cs" />
<Compile Include="GameObjects\Components\Power\SharedApcComponent.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SS14.Shared.Serialization;
namespace Content.Shared.GameObjects.Components.Power
{
[Serializable, NetSerializable]
public enum ChargeState
{
Still,
Charging,
Discharging,
}
}

View File

@@ -0,0 +1,30 @@
using System;
using SS14.Shared.Serialization;
namespace Content.Shared.GameObjects.Components.Power
{
[Serializable, NetSerializable]
public enum ApcVisuals
{
ChargeState
}
[Serializable, NetSerializable]
public enum ApcChargeState
{
/// <summary>
/// APC does not have enough power to charge cell (if necessary) and keep powering the area.
/// </summary>
Lack,
/// <summary>
/// APC is not full but has enough power.
/// </summary>
Charging,
/// <summary>
/// APC battery is full and has enough power.
/// </summary>
Full,
}
}

View File

@@ -0,0 +1,16 @@
using SS14.Shared.Serialization;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Content.Shared.GameObjects.Components.Power
{
[Serializable, NetSerializable]
public enum SmesVisuals
{
LastChargeState,
LastChargeLevel,
}
}

View File

@@ -0,0 +1,60 @@
using System;
namespace Content.Shared.Utility
{
public static class ContentHelpers
{
/// <summary>
/// Assigns the value <paramref name="actual" /> going from 0 to <paramref name="max" />
/// such that it is divided into a set of (amount <paramref name="levels" />) "levels".
/// Rounding is performed to the "middle" so that the highest and lowest levels are only assigned
/// if <paramref name="actual" /> is exactly <paramref name="max" /> or 0.
/// </summary>
/// <example>
/// Say you have a progress bar going from 0 -> 100 inclusive and you want to map this to 6 sprite states (0, 4 intermediates and full).
/// This method allows you to easily map this progress bar to the sprite states.
/// </example>
/// <param name="levels">The amount of levels to subdivide into.</param>
/// <returns>An integer from 0 to <paramref name="levels" />-1.</returns>
/// <exception cref="ArgumentException">
/// Thrown if levels is less than 1.
/// </exception>
public static int RoundToLevels(double actual, double max, int levels)
{
if (levels <= 0)
{
throw new ArgumentException("Levels must be greater than 0.", nameof(levels));
}
if (actual >= max)
{
return levels - 1;
}
if (actual <= 0)
{
return 0;
}
var toOne = actual / max;
double threshold;
if (levels % 2 == 0)
{
// Basically, if we have an even count of levels, there's no exact "mid point".
// Thus, I nominate the first one below the 50% mark.
threshold = ((levels / 2f) - 1) / (levels - 1);
}
else
{
threshold = 0.5f;
}
var preround = toOne * (levels - 1);
if (toOne <= threshold)
{
return (int)Math.Ceiling(preround);
}
else
{
return (int)Math.Floor(preround);
}
}
}
}

View File

@@ -0,0 +1,126 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<Import Project="$(SolutionDir)packages\NUnit.3.10.1\build\NUnit.props" Condition="Exists('$(SolutionDir)packages\NUnit.3.10.1\build\NUnit.props')" />
<Import Project="$(SolutionDir)packages\NUnit3TestAdapter.3.10.0\build\net35\NUnit3TestAdapter.props" Condition="Exists('$(SolutionDir)packages\NUnit3TestAdapter.3.10.0\build\net35\NUnit3TestAdapter.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{8EDF4429-251A-416D-BB68-93F227191BCF}</ProjectGuid>
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Content.Tests</RootNamespace>
<AssemblyName>Content.Tests</AssemblyName>
<TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TestProjectType>UnitTest</TestProjectType>
<OutputPath>..\bin\Content.Tests\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<ItemGroup>
<Reference Include="nunit.framework, Version=3.10.1.0, Culture=neutral, PublicKeyToken=2638cd05610744eb, processorArchitecture=MSIL">
<HintPath>$(SolutionDir)packages\NUnit.3.10.1\lib\net45\nunit.framework.dll</HintPath>
</Reference>
<Reference Include="System.ValueTuple">
<HintPath>$(SolutionDir)packages\System.ValueTuple.4.4.0\lib\netstandard1.0\System.ValueTuple.dll</HintPath>
</Reference>
<Reference Include="System" />
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Shared\Utility\ContentHelpers_Test.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup />
<ItemGroup>
<ProjectReference Include="..\Content.Client\Content.Client.csproj">
<Project>{a2e5f175-78af-4ddd-8f97-e2d2552372ed}</Project>
<Name>Content.Client</Name>
</ProjectReference>
<ProjectReference Include="..\Content.Server\Content.Server.csproj">
<Project>{b38dbbd0-04c2-4d1a-84e2-b3446f6adf2a}</Project>
<Name>Content.Server</Name>
</ProjectReference>
<ProjectReference Include="..\Content.Shared\Content.Shared.csproj">
<Project>{26aeebb3-dde7-443a-9f43-7bc7f4acf6b5}</Project>
<Name>Content.Shared</Name>
</ProjectReference>
<ProjectReference Include="..\engine\Lidgren.Network\Lidgren.Network.csproj">
<Project>{59250baf-0000-0000-0000-000000000000}</Project>
<Name>Lidgren.Network</Name>
</ProjectReference>
<ProjectReference Include="..\engine\SS14.Client.Godot\SS14.Client.Godot.csproj">
<Project>{8af31169-49b1-4a12-b8f4-2a0674a9e7cb}</Project>
<Name>SS14.Client.Godot</Name>
</ProjectReference>
<ProjectReference Include="..\engine\SS14.Client\SS14.Client.csproj">
<Project>{83429bd6-6358-4b18-be51-401df8ea2673}</Project>
<Name>SS14.Client</Name>
</ProjectReference>
<ProjectReference Include="..\engine\SS14.Server\SS14.Server.csproj">
<Project>{b04aae71-0000-0000-0000-000000000000}</Project>
<Name>SS14.Server</Name>
</ProjectReference>
<ProjectReference Include="..\engine\SS14.Shared\SS14.Shared.csproj">
<Project>{0529f740-0000-0000-0000-000000000000}</Project>
<Name>SS14.Shared</Name>
</ProjectReference>
<ProjectReference Include="..\engine\SS14.UnitTesting\SS14.UnitTesting.csproj">
<Project>{f0ada779-40b8-4f7e-ba6c-cdb19f3065d9}</Project>
<Name>SS14.UnitTesting</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -0,0 +1,33 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Content.Tests")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("nunit.tests")]
[assembly: AssemblyCopyright("Copyright © 2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@@ -0,0 +1,60 @@
using Content.Shared.Utility;
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Content.Tests.Shared.Utility
{
[Parallelizable]
[TestFixture]
[TestOf(typeof(ContentHelpers))]
public class ContentHelpers_Test
{
public static readonly IEnumerable<(double val, double max, int levels, int expected)> TestData = new(double, double, int, int)[]
{
// Testing odd level counts. These are easy.
(-1, 10, 5, 0),
( 0, 10, 5, 0),
( 0.01f, 10, 5, 1),
( 1, 10, 5, 1),
( 2, 10, 5, 1),
( 2.5f, 10, 5, 1),
( 2.51f, 10, 5, 2),
( 3, 10, 5, 2),
( 4, 10, 5, 2),
( 5, 10, 5, 2),
( 6, 10, 5, 2),
( 7, 10, 5, 2),
( 7.49f, 10, 5, 2),
( 7.5f, 10, 5, 3),
( 8, 10, 5, 3),
( 9, 10, 5, 3),
(10, 10, 5, 4),
(11, 10, 5, 4),
// Even level counts though..
( 1, 10, 6, 1),
( 2, 10, 6, 1),
( 3, 10, 6, 2),
( 4, 10, 6, 2),
( 5, 10, 6, 2),
( 6, 10, 6, 3),
( 7, 10, 6, 3),
( 8, 10, 6, 4),
( 9, 10, 6, 4),
(10, 10, 6, 5),
};
[Parallelizable]
[Test]
public void Test([ValueSource(nameof(TestData))] (double val, double max, int levels, int expected) data)
{
(double val, double max, int levels, int expected) = data;
Assert.That(ContentHelpers.RoundToLevels(val, max, levels), Is.EqualTo(expected));
}
}
}

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="NUnit" version="3.10.1" targetFramework="net45" />
<package id="NUnit.ConsoleRunner" version="3.8.0" targetFramework="net451" />
<package id="NUnit3TestAdapter" version="3.10.0" targetFramework="net451" />
<package id="System.ValueTuple" version="4.4.0" targetFramework="net451" />
</packages>

View File

@@ -1745,6 +1745,8 @@
- &1206253354
type: &1921049841 PowerStorage
- type: PowerNode
- type: Smes
- type: Appearance
- type: entity
id: SMES
name: SMES
@@ -1760,6 +1762,8 @@
- type: Sprite
- type: PowerStorage
- type: PowerNode
- type: Smes
- type: Appearance
- type: entity
id: &400177229 BlueWire
name: BlueWire
@@ -2236,8 +2240,8 @@
- type: PowerDevice
- type: PoweredLight
- type: entity
id: &692485458 WPP
name: WPP
id: &692485458 APC
name: APC
components:
- type: PowerStorage
- type: PowerNode
@@ -2251,9 +2255,11 @@
- type: Sprite
- &1938028994
type: &323998104 PowerProvider
- type: Apc
- type: Appearance
- type: entity
id: WPP
name: WPP
id: APC
name: APC
components:
- type: PowerStorage
- type: PowerNode
@@ -2266,6 +2272,8 @@
- type: BoundingBox
- type: Sprite
- type: PowerProvider
- type: Apc
- type: Appearance
- type: entity
id: Wire
name: Wire
@@ -2369,8 +2377,8 @@
- type: PowerDevice
- type: PoweredLight
- type: entity
id: WPP
name: WPP
id: APC
name: APC
components:
- type: PowerStorage
- type: PowerNode
@@ -2382,6 +2390,8 @@
- type: BoundingBox
- type: Sprite
- type: PowerProvider
- type: Apc
- type: Appearance
- type: entity
id: Wire
name: Wire
@@ -2396,8 +2406,8 @@
color: '#FF0000FF'
- type: PowerTransfer
- type: entity
id: WPP
name: WPP
id: APC
name: APC
components:
- type: PowerStorage
- type: PowerNode
@@ -2409,6 +2419,8 @@
- type: BoundingBox
- type: Sprite
- type: PowerProvider
- type: Apc
- type: Appearance
- type: entity
id: Wire
name: Wire
@@ -2649,8 +2661,8 @@
color: '#FF0000FF'
- type: PowerTransfer
- type: entity
id: WPP
name: WPP
id: APC
name: APC
components:
- type: PowerStorage
- type: PowerNode
@@ -2663,9 +2675,11 @@
- type: BoundingBox
- type: Sprite
- type: PowerProvider
- type: Apc
- type: Appearance
- type: entity
id: WPP
name: WPP
id: APC
name: APC
components:
- type: PowerStorage
- type: PowerNode
@@ -2678,6 +2692,8 @@
- type: BoundingBox
- type: Sprite
- type: PowerProvider
- type: Apc
- type: Appearance
- type: entity
id: Wire
name: Wire

View File

@@ -70,25 +70,49 @@
chargerate: 200
chargepowernet: false
- type: entity
parent: WPP
id: APC
name: APC
components:
- type: Apc
- type: Sprite
netsync: false
texture: ""
sprite: "Buildings/apc.rsi"
state: apc0
- type: Appearance
visuals:
- type: ApcVisualizer2D
- type: entity
id: SMES
name: SMES
description: Stores power in its supermagnetic cells
name: Smes
description: Stores power in its super-magnetic cells
components:
- type: Transform
- type: Clickable
- type: BoundingBox
- type: Sprite
texture: Objects/storage.png
netsync: false
sprite: Buildings/smes.rsi
state: smes
layers:
- state: smes-display
shader: unshaded
- type: Icon
texture: Objects/storage.png
sprite: Buildings/smes.rsi
state: smes
- type: PowerStorage
capacity: 3000
charge: 1000
chargerate: 200
distributionrate: 400
chargepowernet: true
- type: Smes
- type: Appearance
visuals:
- type: SmesVisualizer2D
- type: entity
id: WiredMachine

Binary file not shown.

After

Width:  |  Height:  |  Size: 704 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 966 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 408 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 296 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 299 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 536 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 329 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 335 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 575 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 523 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 470 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 483 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 257 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 358 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 280 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 B

View File

@@ -0,0 +1,344 @@
{
"version": 1,
"license": "CC-BY-SA-3.0",
"copyright": "Taken from https://github.com/discordia-space/CEV-Eris/blob/d1e0161af146835f4fb79d21a6200caa9cc842d0/icons/obj/power.dmi",
"size": {
"x": 32,
"y": 32
},
"states": [
{
"name": "apc-b",
"select": [],
"flags": {},
"directions": 1,
"delays": [
[
1.0
]
]
},
{
"name": "apc-spark",
"select": [],
"flags": {},
"directions": 1,
"delays": [
[
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1
]
]
},
{
"name": "apc0",
"select": [],
"flags": {},
"directions": 1,
"delays": [
[
1.0
]
]
},
{
"name": "apc1",
"select": [],
"flags": {},
"directions": 1,
"delays": [
[
1.0
]
]
},
{
"name": "apc1-b-nocover",
"select": [],
"flags": {},
"directions": 1,
"delays": [
[
1.0
]
]
},
{
"name": "apc1-nocover",
"select": [],
"flags": {},
"directions": 1,
"delays": [
[
1.0
]
]
},
{
"name": "apc2",
"select": [],
"flags": {},
"directions": 1,
"delays": [
[
1.0
]
]
},
{
"name": "apc2-b-nocover",
"select": [],
"flags": {},
"directions": 1,
"delays": [
[
1.0
]
]
},
{
"name": "apc2-nocover",
"select": [],
"flags": {},
"directions": 1,
"delays": [
[
1.0
]
]
},
{
"name": "apcemag",
"select": [],
"flags": {},
"directions": 1,
"delays": [
[
0.5,
0.5
]
]
},
{
"name": "apcewires",
"select": [],
"flags": {},
"directions": 1,
"delays": [
[
1.0
]
]
},
{
"name": "apcmaint",
"select": [],
"flags": {},
"directions": 1,
"delays": [
[
1.0
]
]
},
{
"name": "apco0-0",
"select": [],
"flags": {},
"directions": 1,
"delays": [
[
1.0
]
]
},
{
"name": "apco0-1",
"select": [],
"flags": {},
"directions": 1,
"delays": [
[
1.0
]
]
},
{
"name": "apco0-2",
"select": [],
"flags": {},
"directions": 1,
"delays": [
[
1.0
]
]
},
{
"name": "apco0-3",
"select": [],
"flags": {},
"directions": 1,
"delays": [
[
1.0
]
]
},
{
"name": "apco1-0",
"select": [],
"flags": {},
"directions": 1,
"delays": [
[
1.0
]
]
},
{
"name": "apco1-1",
"select": [],
"flags": {},
"directions": 1,
"delays": [
[
1.0
]
]
},
{
"name": "apco1-2",
"select": [],
"flags": {},
"directions": 1,
"delays": [
[
1.0
]
]
},
{
"name": "apco1-3",
"select": [],
"flags": {},
"directions": 1,
"delays": [
[
1.0
]
]
},
{
"name": "apco2-0",
"select": [],
"flags": {},
"directions": 1,
"delays": [
[
1.0
]
]
},
{
"name": "apco2-1",
"select": [],
"flags": {},
"directions": 1,
"delays": [
[
1.0
]
]
},
{
"name": "apco2-2",
"select": [],
"flags": {},
"directions": 1,
"delays": [
[
1.0
]
]
},
{
"name": "apco2-3",
"select": [],
"flags": {},
"directions": 1,
"delays": [
[
1.0
]
]
},
{
"name": "apco3-0",
"select": [],
"flags": {},
"directions": 1,
"delays": [
[
1.0,
2.0
]
]
},
{
"name": "apco3-1",
"select": [],
"flags": {},
"directions": 1,
"delays": [
[
0.1,
0.1,
0.1,
0.1,
0.1,
0.2
]
]
},
{
"name": "apco3-2",
"select": [],
"flags": {},
"directions": 1,
"delays": [
[
1.0,
1.0
]
]
},
{
"name": "apcox-0",
"select": [],
"flags": {},
"directions": 1,
"delays": [
[
1.0
]
]
},
{
"name": "apcox-1",
"select": [],
"flags": {},
"directions": 1,
"delays": [
[
1.0
]
]
}
]
}

View File

@@ -0,0 +1,170 @@
{
"version": 1,
"license": "CC-BY-SA-3.0",
"copyright": "Taken from https://github.com/discordia-space/CEV-Eris/blob/d1e0161af146835f4fb79d21a6200caa9cc842d0/icons/obj/power.dmi and modified.",
"size": {
"x": 32,
"y": 32
},
"states": [
{
"name": "smes",
"select": [],
"flags": {},
"directions": 1
},
{
"name": "smes-display",
"select": [],
"flags": {},
"directions": 1,
"delays": [
[
0.2,
0.2,
0.2,
0.2,
0.2
]
]
},
{
"name": "smes-crit",
"select": [],
"flags": {},
"directions": 1,
"delays": [
[
0.2,
0.2,
0.2,
0.2
]
]
},
{
"name": "smes-oc0",
"select": [],
"flags": {},
"directions": 1,
"delays": [
[
1.0
]
]
},
{
"name": "smes-oc1",
"select": [],
"flags": {},
"directions": 1,
"delays": [
[
0.5,
0.5
]
]
},
{
"name": "smes-oc2",
"select": [],
"flags": {},
"directions": 1,
"delays": [
[
0.5,
0.5
]
]
},
{
"name": "smes-og1",
"select": [],
"flags": {},
"directions": 1,
"delays": [
[
1.0
]
]
},
{
"name": "smes-og2",
"select": [],
"flags": {},
"directions": 1,
"delays": [
[
1.0
]
]
},
{
"name": "smes-og3",
"select": [],
"flags": {},
"directions": 1,
"delays": [
[
1.0
]
]
},
{
"name": "smes-og4",
"select": [],
"flags": {},
"directions": 1,
"delays": [
[
1.0
]
]
},
{
"name": "smes-og5",
"select": [],
"flags": {},
"directions": 1,
"delays": [
[
1.0
]
]
},
{
"name": "smes-op0",
"select": [],
"flags": {},
"directions": 1,
"delays": [
[
1.0
]
]
},
{
"name": "smes-op1",
"select": [],
"flags": {},
"directions": 1,
"delays": [
[
1.0,
1.0
]
]
},
{
"name": "smes-op2",
"select": [],
"flags": {},
"directions": 1,
"delays": [
[
1.0
]
]
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 721 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 514 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 162 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 171 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 171 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 146 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 181 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 198 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 230 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 255 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 146 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 146 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -40,6 +40,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SS14.Client", "engine\SS14.
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SS14.Client.Godot", "engine\SS14.Client.Godot\SS14.Client.Godot.csproj", "{8AF31169-49B1-4A12-B8F4-2A0674A9E7CB}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Content.Tests", "Content.Tests\Content.Tests.csproj", "{8EDF4429-251A-416D-BB68-93F227191BCF}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -233,6 +235,24 @@ Global
{8AF31169-49B1-4A12-B8F4-2A0674A9E7CB}.Tools|x64.Build.0 = Tools|Any CPU
{8AF31169-49B1-4A12-B8F4-2A0674A9E7CB}.Tools|x86.ActiveCfg = Tools|Any CPU
{8AF31169-49B1-4A12-B8F4-2A0674A9E7CB}.Tools|x86.Build.0 = Tools|Any CPU
{8EDF4429-251A-416D-BB68-93F227191BCF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8EDF4429-251A-416D-BB68-93F227191BCF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8EDF4429-251A-416D-BB68-93F227191BCF}.Debug|x64.ActiveCfg = Debug|x64
{8EDF4429-251A-416D-BB68-93F227191BCF}.Debug|x64.Build.0 = Debug|x64
{8EDF4429-251A-416D-BB68-93F227191BCF}.Debug|x86.ActiveCfg = Debug|x86
{8EDF4429-251A-416D-BB68-93F227191BCF}.Debug|x86.Build.0 = Debug|x86
{8EDF4429-251A-416D-BB68-93F227191BCF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8EDF4429-251A-416D-BB68-93F227191BCF}.Release|Any CPU.Build.0 = Release|Any CPU
{8EDF4429-251A-416D-BB68-93F227191BCF}.Release|x64.ActiveCfg = Release|x64
{8EDF4429-251A-416D-BB68-93F227191BCF}.Release|x64.Build.0 = Release|x64
{8EDF4429-251A-416D-BB68-93F227191BCF}.Release|x86.ActiveCfg = Release|x86
{8EDF4429-251A-416D-BB68-93F227191BCF}.Release|x86.Build.0 = Release|x86
{8EDF4429-251A-416D-BB68-93F227191BCF}.Tools|Any CPU.ActiveCfg = Debug|Any CPU
{8EDF4429-251A-416D-BB68-93F227191BCF}.Tools|Any CPU.Build.0 = Debug|Any CPU
{8EDF4429-251A-416D-BB68-93F227191BCF}.Tools|x64.ActiveCfg = Debug|x64
{8EDF4429-251A-416D-BB68-93F227191BCF}.Tools|x64.Build.0 = Debug|x64
{8EDF4429-251A-416D-BB68-93F227191BCF}.Tools|x86.ActiveCfg = Debug|x86
{8EDF4429-251A-416D-BB68-93F227191BCF}.Tools|x86.Build.0 = Debug|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

2
engine

Submodule engine updated: f6d01c5d61...92f12334b4