Solar Panels (#936)

This commit is contained in:
20kdc
2020-05-21 20:08:03 +01:00
committed by GitHub
parent b270c69512
commit 0cfd2f3bb2
7 changed files with 187 additions and 1 deletions

View File

@@ -65,7 +65,7 @@ namespace Content.Server.GameObjects.Components.Power
{ {
_supply = value; _supply = value;
var node = Owner.GetComponent<PowerNodeComponent>(); var node = Owner.GetComponent<PowerNodeComponent>();
node.Parent.UpdateGenerator(this); node?.Parent?.UpdateGenerator(this);
} }
/// <summary> /// <summary>

View File

@@ -0,0 +1,91 @@
using System;
using Content.Server.GameObjects.Components.Damage;
using Content.Server.GameObjects.EntitySystems;
using Content.Shared.Audio;
using Robust.Server.GameObjects;
using Robust.Server.GameObjects.EntitySystems;
using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Random;
using Robust.Shared.IoC;
using Robust.Shared.Maths;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
using Robust.Shared.Serialization;
using Robust.Shared.ViewVariables;
namespace Content.Server.GameObjects.Components.Power
{
/// <summary>
/// This is a solar panel.
/// It generates power from the sun based on coverage.
/// </summary>
[RegisterComponent]
public class SolarPanelComponent : Component, IBreakAct
{
public override string Name => "SolarPanel";
private PowerGeneratorComponent _powerGenerator;
/// <summary>
/// Maximum supply output by this panel (coverage = 1)
/// </summary>
private float _maxSupply = 1500;
[ViewVariables(VVAccess.ReadWrite)]
public float MaxSupply
{
get => _maxSupply;
set {
_maxSupply = value;
UpdateSupply();
}
}
/// <summary>
/// Current coverage of this panel (from 0 to 1).
/// This is updated by <see cref='PowerSolarSystem'/>.
/// </summary>
private float _coverage = 0;
[ViewVariables]
public float Coverage
{
get => _coverage;
set {
// This gets updated once-per-tick, so avoid updating it if truly unnecessary
if (_coverage != value) {
_coverage = value;
UpdateSupply();
}
}
}
private void UpdateSupply()
{
if (_powerGenerator != null)
_powerGenerator.Supply = _maxSupply * _coverage;
}
public override void Initialize()
{
base.Initialize();
_powerGenerator = Owner.GetComponent<PowerGeneratorComponent>();
UpdateSupply();
}
public override void ExposeData(ObjectSerializer serializer)
{
base.ExposeData(serializer);
serializer.DataField(ref _maxSupply, "maxsupply", 1500);
}
public void OnBreak(BreakageEventArgs args)
{
var sprite = Owner.GetComponent<SpriteComponent>();
sprite.LayerSetState(0, "broken");
MaxSupply = 0;
}
}
}

View File

@@ -0,0 +1,65 @@
using Content.Server.GameObjects.Components.Power;
using JetBrains.Annotations;
using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.Systems;
using Robust.Shared.Maths;
using System;
namespace Content.Server.GameObjects.EntitySystems
{
/// <summary>
/// Responsible for maintaining the solar-panel sun angle and updating <see cref='SolarPanelComponent'/> coverage.
/// </summary>
[UsedImplicitly]
public class PowerSolarSystem: EntitySystem
{
/// <summary>
/// The current sun angle.
/// </summary>
public Angle TowardsSun = Angle.South;
public override void Initialize()
{
EntityQuery = new TypeEntityQuery(typeof(SolarPanelComponent));
}
public override void Update(float frameTime)
{
TowardsSun += Angle.FromDegrees(frameTime / 10);
TowardsSun = TowardsSun.Reduced();
foreach (var entity in RelevantEntities)
{
// In the 'sunRelative' coordinate system:
// the sun is considered to be an infinite distance directly up.
// this is the rotation of the panel relative to that.
// directly upwards (theta = 0) = coverage 1
// left/right 90 degrees (abs(theta) = (pi / 2)) = coverage 0
// directly downwards (abs(theta) = pi) = coverage -1
// as TowardsSun + = CCW,
// panelRelativeToSun should - = CW
var panelRelativeToSun = entity.Transform.WorldRotation - TowardsSun;
// essentially, given cos = X & sin = Y & Y is 'downwards',
// then for the first 90 degrees of rotation in either direction,
// this plots the lower-right quadrant of a circle.
// now basically assume a line going from the negated X/Y to there,
// and that's the hypothetical solar panel.
//
// since, again, the sun is considered to be an infinite distance upwards,
// this essentially means Cos(panelRelativeToSun) is half of the cross-section,
// and since the full cross-section has a max of 2, effectively-halving it is fine.
//
// as for when it goes negative, it only does that when (abs(theta) > pi)
// and that's expected behavior.
float coverage = (float) Math.Max(0, Math.Cos(panelRelativeToSun));
// Would determine occlusion, but that requires raytraces.
// And I'm not sure where those are in the codebase.
// Luckily, auto-rotation isn't in yet, so it won't matter anyway.
// Total coverage calculated; apply it to the panel.
var panel = entity.GetComponent<SolarPanelComponent>();
panel.Coverage = coverage;
}
}
}
}

View File

@@ -62,6 +62,35 @@
- type: SnapGrid - type: SnapGrid
offset: Center offset: Center
- type: entity
id: SolarPanel
name: Solar Panel
description: Generates power from sunlight. Usually used to power replacements for sunlight. Fragile.
placement:
mode: SnapgridCenter
components:
- type: Clickable
- type: InteractionOutline
- type: Collidable
shapes:
- !type:PhysShapeAabb
layer: 31
- type: Sprite
sprite: Buildings/solar_panel.rsi
state: normal
- type: Icon
sprite: Buildings/solar_panel.rsi
state: normal
- type: PowerGenerator
- type: SolarPanel
supply: 1500
- type: Rotatable
- type: SnapGrid
offset: Center
- type: Damageable
- type: Breakable
thresholdvalue: 100
- type: entity - type: entity
id: WPPnobattery id: WPPnobattery
name: WPPnobattery name: WPPnobattery

Binary file not shown.

After

Width:  |  Height:  |  Size: 291 B

View File

@@ -0,0 +1 @@
{"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":"normal","select":[],"flags":{},"directions":8},{"name":"broken","select":[],"flags":{},"directions":1}]}

Binary file not shown.

After

Width:  |  Height:  |  Size: 886 B