Solar Panels (#936)
This commit is contained in:
@@ -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>
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
65
Content.Server/GameObjects/EntitySystems/PowerSolarSystem.cs
Normal file
65
Content.Server/GameObjects/EntitySystems/PowerSolarSystem.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
|||||||
BIN
Resources/Textures/Buildings/solar_panel.rsi/broken.png
Normal file
BIN
Resources/Textures/Buildings/solar_panel.rsi/broken.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 291 B |
1
Resources/Textures/Buildings/solar_panel.rsi/meta.json
Normal file
1
Resources/Textures/Buildings/solar_panel.rsi/meta.json
Normal 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}]}
|
||||||
BIN
Resources/Textures/Buildings/solar_panel.rsi/normal.png
Normal file
BIN
Resources/Textures/Buildings/solar_panel.rsi/normal.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 886 B |
Reference in New Issue
Block a user