Power grid works!

This commit is contained in:
Hamcha 2020-07-09 16:50:34 +02:00
parent db74d4135d
commit 2283afbf51
Signed by: hamcha
GPG key ID: 41467804B19A3315
11 changed files with 245 additions and 42 deletions

View file

@ -12,11 +12,21 @@ var wired setget , get_wired
export var power_usage = 0.0 export var power_usage = 0.0
export var power_source = 0.0 export var power_source = 0.0
const DEBUG = true var power_load = 0.0
var available = 0.0
var powered = false setget set_powered
func get_wired() -> bool: func get_wired() -> bool:
return socket != null return socket != null
func _physics_process(_delta): func set_powered(val: bool) -> void:
var current = powered
powered = val
if current and not val:
emit_signal("power_disconnected")
elif not current and val:
emit_signal("power_connected")
func _physics_process(_delta: float) -> void:
if wired: if wired:
pass pass

View file

@ -14,6 +14,7 @@ var screen_region_offset = Vector2.ZERO
var open = false var open = false
onready var activationRange = $ActivationRange as ActivationRange onready var activationRange = $ActivationRange as ActivationRange
onready var manager = $PowerManager as PowerManager
func _ready(): func _ready():
if not Engine.editor_hint: if not Engine.editor_hint:
@ -77,7 +78,7 @@ func _input_event(_viewport, event, _shape_idx):
return return
if event is InputEventMouseButton and event.pressed and not open: if event is InputEventMouseButton and event.pressed and not open:
# Must be in range # Must be in range
if activationRange.in_range(): if activationRange.in_range() and manager.powered:
open = true open = true
manage_controls(true) manage_controls(true)
$UIAnimation.play("fadein") $UIAnimation.play("fadein")
@ -94,3 +95,10 @@ func _force_close_ui():
if open: if open:
open = false open = false
$UIAnimation.play("fadeout") $UIAnimation.play("fadeout")
func _power_status_changed(powered: bool) -> void:
activationRange.visible = powered
if powered:
$ScreenAnimation.play("on")
else:
$ScreenAnimation.play("off")

View file

@ -1,4 +1,4 @@
[gd_scene load_steps=14 format=2] [gd_scene load_steps=15 format=2]
[ext_resource path="res://Graphics/tgstation/computer-screens.png" type="Texture" id=1] [ext_resource path="res://Graphics/tgstation/computer-screens.png" type="Texture" id=1]
[ext_resource path="res://Graphics/tgstation/computer.png" type="Texture" id=2] [ext_resource path="res://Graphics/tgstation/computer.png" type="Texture" id=2]
@ -6,6 +6,7 @@
[ext_resource path="res://Actors/Objects/Computer/UI/ControlComp.tscn" type="PackedScene" id=4] [ext_resource path="res://Actors/Objects/Computer/UI/ControlComp.tscn" type="PackedScene" id=4]
[ext_resource path="res://Graphics/light_shadow_light.png" type="Texture" id=5] [ext_resource path="res://Graphics/light_shadow_light.png" type="Texture" id=5]
[ext_resource path="res://Actors/Components/ActivationRange.gd" type="Script" id=6] [ext_resource path="res://Actors/Components/ActivationRange.gd" type="Script" id=6]
[ext_resource path="res://Actors/Components/PowerManager.gd" type="Script" id=7]
[sub_resource type="RectangleShape2D" id=1] [sub_resource type="RectangleShape2D" id=1]
extents = Vector2( 16, 16 ) extents = Vector2( 16, 16 )
@ -14,6 +15,7 @@ extents = Vector2( 16, 16 )
blend_mode = 1 blend_mode = 1
[sub_resource type="Animation" id=3] [sub_resource type="Animation" id=3]
loop = true
tracks/0/type = "value" tracks/0/type = "value"
tracks/0/path = NodePath("computer/screen:modulate") tracks/0/path = NodePath("computer/screen:modulate")
tracks/0/interp = 1 tracks/0/interp = 1
@ -127,7 +129,7 @@ texture_scale = 0.5
energy = 0.5 energy = 0.5
[node name="ScreenAnimation" type="AnimationPlayer" parent="."] [node name="ScreenAnimation" type="AnimationPlayer" parent="."]
autoplay = "on" autoplay = "off"
anims/off = SubResource( 3 ) anims/off = SubResource( 3 )
anims/on = SubResource( 4 ) anims/on = SubResource( 4 )
@ -155,7 +157,13 @@ script = ExtResource( 6 )
[node name="CollisionShape2D" type="CollisionShape2D" parent="ActivationRange"] [node name="CollisionShape2D" type="CollisionShape2D" parent="ActivationRange"]
position = Vector2( 16, 16 ) position = Vector2( 16, 16 )
shape = SubResource( 7 ) shape = SubResource( 7 )
[node name="PowerManager" type="Node" parent="."]
script = ExtResource( 7 )
power_usage = 20.0
[connection signal="animation_finished" from="UIAnimation" to="." method="_ui_fade_completed"] [connection signal="animation_finished" from="UIAnimation" to="." method="_ui_fade_completed"]
[connection signal="mouse_entered" from="Control/ControlComp" to="." method="_ui_focus_changed" binds= [ true ]] [connection signal="mouse_entered" from="Control/ControlComp" to="." method="_ui_focus_changed" binds= [ true ]]
[connection signal="mouse_exited" from="Control/ControlComp" to="." method="_ui_focus_changed" binds= [ false ]] [connection signal="mouse_exited" from="Control/ControlComp" to="." method="_ui_focus_changed" binds= [ false ]]
[connection signal="player_left" from="ActivationRange" to="." method="_force_close_ui"] [connection signal="player_left" from="ActivationRange" to="." method="_force_close_ui"]
[connection signal="power_connected" from="PowerManager" to="." method="_power_status_changed" binds= [ true ]]
[connection signal="power_disconnected" from="PowerManager" to="." method="_power_status_changed" binds= [ false ]]

View file

@ -1,9 +1,9 @@
tool tool
class_name ElectricSocket
extends Area2D extends Area2D
class_name ElectricSocket
enum Direction { LEFT, RIGHT, UP, DOWN } enum Direction { LEFT, RIGHT, UP, DOWN }
enum Flow { SOURCE, SINK, BIDIRECTIONAL } enum Flow { SOURCE, SINK, BIDIRECTIONAL }
@ -22,25 +22,28 @@ onready var socket = $socket
var network = null var network = null
func _ready(): func _ready() -> void:
socket.material = socket.material.duplicate() socket.material = socket.material.duplicate()
refresh_sprite() refresh_sprite()
if Engine.editor_hint:
return
for connection in connectionPaths: for connection in connectionPaths:
add_connection(get_node(connection)) add_connection(get_node(connection))
func add_connection(node: Node): func add_connection(node: Node) -> void:
var manager = node.get_node("PowerManager") as PowerManager var manager = node.get_node("PowerManager") as PowerManager
manager.socket = self manager.socket = self
connections.append(manager)
func set_direction(dir): func set_direction(dir) -> void:
direction = dir direction = dir
refresh_sprite() refresh_sprite()
func set_flow(val): func set_flow(val) -> void:
flow = val flow = val
refresh_sprite() refresh_sprite()
func refresh_sprite(): func refresh_sprite() -> void:
if socket == null: if socket == null:
return return
match direction: match direction:

View file

@ -2,22 +2,29 @@ extends StaticBody2D
class_name GameObjectPowerStorage class_name GameObjectPowerStorage
const MAX_CHARGE = 5000.0 const MAX_CHARGE = 100000.0
var open = false var open = false
var attached = true var attached = true
onready var activationRange = $ActivationRange as ActivationRange onready var activationRange = $ActivationRange as ActivationRange
onready var manager = $PowerManager as PowerManager
var current_charge = MAX_CHARGE export var current_charge = MAX_CHARGE
export var max_discharge_rate = 200
func _ready(): func _ready():
if not Engine.editor_hint: if not Engine.editor_hint:
activationRange.visible = true activationRange.visible = true
func _physics_process(_delta): func _physics_process(delta: float):
if $PowerManager.wired: if manager.wired:
if $PowerManager.DEBUG: if current_charge > 0:
manager.power_source = min(current_charge, max_discharge_rate)
if manager.power_load > 0:
current_charge -= manager.power_load * delta
if PowerNetwork.DEBUG:
update() update()
$Control/PowerUI.displayed_charge = current_charge
func _input(event): func _input(event):
if event is InputEventMouseButton and event.pressed and not is_inside and open: if event is InputEventMouseButton and event.pressed and not is_inside and open:
@ -48,7 +55,7 @@ func _force_close_ui():
$UIAnimation.play("fadeout") $UIAnimation.play("fadeout")
func _draw(): func _draw():
if $PowerManager.DEBUG and $PowerManager.wired: if PowerNetwork.DEBUG and manager.wired:
var charge_px = int(current_charge / MAX_CHARGE * 32) var charge_px = int(current_charge / MAX_CHARGE * 32)
var charge_color = Color.greenyellow var charge_color = Color.greenyellow
if charge_px < 20: if charge_px < 20:

View file

@ -60,7 +60,7 @@ tracks/1/keys = {
"times": PoolRealArray( 0, 0.2 ) "times": PoolRealArray( 0, 0.2 )
} }
[sub_resource type="CircleShape2D" id=5] [sub_resource type="CircleShape2D" id=4]
radius = 56.0 radius = 56.0
[node name="StaticBody2D" type="StaticBody2D"] [node name="StaticBody2D" type="StaticBody2D"]
@ -89,7 +89,7 @@ z_index = 999
[node name="PowerUI" parent="Control" instance=ExtResource( 4 )] [node name="PowerUI" parent="Control" instance=ExtResource( 4 )]
visible = false visible = false
margin_left = -50.0 margin_left = -50.0
margin_top = -73.0 margin_top = -85.0
margin_right = 150.0 margin_right = 150.0
margin_bottom = 57.0 margin_bottom = 57.0
rect_scale = Vector2( 0.5, 0.5 ) rect_scale = Vector2( 0.5, 0.5 )
@ -100,7 +100,7 @@ position = Vector2( 16, 16 )
script = ExtResource( 3 ) script = ExtResource( 3 )
[node name="CollisionShape2D" type="CollisionShape2D" parent="ActivationRange"] [node name="CollisionShape2D" type="CollisionShape2D" parent="ActivationRange"]
shape = SubResource( 5 ) shape = SubResource( 4 )
[connection signal="mouse_entered" from="Control/PowerUI" to="." method="_ui_focus_changed" binds= [ true ]] [connection signal="mouse_entered" from="Control/PowerUI" to="." method="_ui_focus_changed" binds= [ true ]]
[connection signal="mouse_exited" from="Control/PowerUI" to="." method="_ui_focus_changed" binds= [ false ]] [connection signal="mouse_exited" from="Control/PowerUI" to="." method="_ui_focus_changed" binds= [ false ]]
[connection signal="player_left" from="ActivationRange" to="." method="_force_close_ui"] [connection signal="player_left" from="ActivationRange" to="." method="_force_close_ui"]

View file

@ -2,5 +2,12 @@ extends Control
onready var scene = $"/root/scene" as GameInstance onready var scene = $"/root/scene" as GameInstance
func _physics_process(_delta): var displayed_charge = 0 setget set_current_charge
pass var max_charge = 1 setget set_max_charge
func set_current_charge(val):
$Container/CurrentBox/HBoxContainer/CurrentChargeLabel.text = "(" + str(round(val/10)/100) + "kJ)"
$Container/CurrentBox/ProgressBar.value = val
func set_max_charge(val: float):
$Container/CurrentBox/ProgressBar.max_value = max_charge

View file

@ -1,14 +1,15 @@
[gd_scene load_steps=4 format=2] [gd_scene load_steps=5 format=2]
[ext_resource path="res://Actors/Objects/PowerStorage/UI/PowerUI.gd" type="Script" id=1] [ext_resource path="res://Actors/Objects/PowerStorage/UI/PowerUI.gd" type="Script" id=1]
[ext_resource path="res://Graphics/UI/ui-popup-panel.png" type="Texture" id=2] [ext_resource path="res://Graphics/UI/ui-popup-panel.png" type="Texture" id=2]
[ext_resource path="res://Graphics/UI/ui_theme.tres" type="Theme" id=3]
[ext_resource path="res://Graphics/unshaded_mat.tres" type="Material" id=4] [ext_resource path="res://Graphics/unshaded_mat.tres" type="Material" id=4]
[node name="PowerUI" type="Control"] [node name="PowerUI" type="Control"]
material = ExtResource( 4 ) material = ExtResource( 4 )
margin_left = -100.0 margin_left = -110.0
margin_top = -150.0 margin_top = -160.0
margin_right = 100.0 margin_right = 110.0
margin_bottom = -20.0 margin_bottom = -20.0
mouse_filter = 1 mouse_filter = 1
script = ExtResource( 1 ) script = ExtResource( 1 )
@ -19,11 +20,13 @@ __meta__ = {
[node name="TextureRect" type="TextureRect" parent="."] [node name="TextureRect" type="TextureRect" parent="."]
material = ExtResource( 4 ) material = ExtResource( 4 )
anchor_left = 0.5 anchor_left = 0.5
anchor_top = 1.0
anchor_right = 0.5 anchor_right = 0.5
anchor_bottom = 1.0
margin_left = -8.0 margin_left = -8.0
margin_top = 111.826 margin_top = -18.0
margin_right = 8.27014 margin_right = 8.27014
margin_bottom = 143.855 margin_bottom = 14.182
texture = ExtResource( 2 ) texture = ExtResource( 2 )
stretch_mode = 3 stretch_mode = 3
__meta__ = { __meta__ = {
@ -34,6 +37,7 @@ __meta__ = {
material = ExtResource( 4 ) material = ExtResource( 4 )
anchor_right = 1.0 anchor_right = 1.0
anchor_bottom = 1.0 anchor_bottom = 1.0
mouse_filter = 1
texture = ExtResource( 2 ) texture = ExtResource( 2 )
region_rect = Rect2( 0, 0, 16, 16 ) region_rect = Rect2( 0, 0, 16, 16 )
patch_margin_left = 4 patch_margin_left = 4
@ -59,3 +63,81 @@ custom_constants/separation = 20
__meta__ = { __meta__ = {
"_edit_use_anchors_": false "_edit_use_anchors_": false
} }
[node name="CurrentBox" type="VBoxContainer" parent="Container"]
margin_right = 200.0
margin_bottom = 40.0
[node name="HBoxContainer" type="HBoxContainer" parent="Container/CurrentBox"]
margin_right = 200.0
margin_bottom = 18.0
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Label" type="Label" parent="Container/CurrentBox/HBoxContainer"]
margin_right = 102.0
margin_bottom = 18.0
mouse_filter = 1
theme = ExtResource( 3 )
text = "Current charge"
[node name="CurrentChargeLabel" type="Label" parent="Container/CurrentBox/HBoxContainer"]
margin_left = 106.0
margin_right = 106.0
margin_bottom = 18.0
mouse_filter = 1
theme = ExtResource( 3 )
[node name="ProgressBar" type="ProgressBar" parent="Container/CurrentBox"]
margin_top = 22.0
margin_right = 200.0
margin_bottom = 40.0
mouse_filter = 1
size_flags_horizontal = 3
size_flags_vertical = 3
theme = ExtResource( 3 )
[node name="ChargeBox" type="GridContainer" parent="Container"]
margin_top = 60.0
margin_right = 200.0
margin_bottom = 120.0
size_flags_horizontal = 3
size_flags_vertical = 3
columns = 2
[node name="Charge rate" type="Label" parent="Container/ChargeBox"]
margin_top = 5.0
margin_right = 84.0
margin_bottom = 23.0
mouse_filter = 1
theme = ExtResource( 3 )
text = "Limit charge"
[node name="SpinBox" type="SpinBox" parent="Container/ChargeBox"]
margin_left = 88.0
margin_right = 186.0
margin_bottom = 28.0
mouse_filter = 1
theme = ExtResource( 3 )
max_value = 200.0
suffix = "W"
[node name="Discharge" type="Label" parent="Container/ChargeBox"]
margin_top = 37.0
margin_right = 84.0
margin_bottom = 55.0
mouse_filter = 1
theme = ExtResource( 3 )
text = "Limit output"
[node name="SpinBox2" type="SpinBox" parent="Container/ChargeBox"]
margin_left = 88.0
margin_top = 32.0
margin_right = 186.0
margin_bottom = 60.0
mouse_filter = 1
theme = ExtResource( 3 )
max_value = 200.0
value = 200.0
suffix = "W"

View file

@ -21,3 +21,4 @@ centered = false
[node name="PowerManager" type="Node" parent="."] [node name="PowerManager" type="Node" parent="."]
script = ExtResource( 3 ) script = ExtResource( 3 )
power_usage = 10.0

View file

@ -2,23 +2,26 @@ extends Node
class_name PowerNetwork class_name PowerNetwork
const DEBUG = true const DEBUG = false
var nodes = [] var nodes = []
var sockets = [] var sockets = []
var total_source = 0
var total_usage = 0
var debugColor = Color.cyan var debugColor = Color.cyan
func _ready(): func _ready():
name = "PowerNetwork" name = "PowerNetwork"
debugColor = Color.from_hsv(randf(), 0.8, 0.8) debugColor = Color.from_hsv(randf(), 0.8, 0.8)
func add_node(node): func add_node(node) -> void:
nodes.append(node) nodes.append(node)
if node is ElectricSocket: if "connections" in node:
sockets.append(node) sockets.append(node)
func remove_node(node): func remove_node(node) -> void:
var node_idx = nodes.find(node) var node_idx = nodes.find(node)
if node_idx >= 0: if node_idx >= 0:
nodes.remove(node_idx) nodes.remove(node_idx)
@ -28,19 +31,53 @@ func remove_node(node):
# Do other splitting here # Do other splitting here
node.network = null node.network = null
func join(network): func join(network) -> void:
for node in network.nodes: for node in network.nodes:
nodes.append(node) nodes.append(node)
node.network = self node.network = self
for socket in network.sockets:
sockets.append(socket)
socket.network = self
# Do other merging here # Do other merging here
network.queue_free() network.queue_free()
func _physics_process(_delta): func _physics_process(_delta: float) -> void:
# Recalculate power availability and usage # Recalculate power availability and usage
var total_source = 0 total_source = 0
var total_usage = 0 total_usage = 0
var sources = []
var sinks = []
# Calculate totals
for socket in sockets: for socket in sockets:
for connection in socket.connections: for connection in socket.connections:
var manager = connection as PowerManager var manager = connection as PowerManager
total_source += manager.power_source match socket.flow:
ElectricSocket.Flow.SINK:
total_usage += manager.power_usage total_usage += manager.power_usage
sinks.append(manager)
ElectricSocket.Flow.SOURCE:
total_source += manager.power_source
sources.append(manager)
ElectricSocket.Flow.BIDIRECTIONAL:
total_usage += manager.power_usage
total_source += manager.power_source
sinks.append(manager)
sources.append(manager)
# Update manager stats
var available_supply = total_source
for sink in sinks:
# Check if item can be powered this cycle
if sink.power_usage > 0:
if available_supply > sink.power_usage:
available_supply -= sink.power_usage
sink.powered = true
else:
sink.powered = false
# Update available power to sinks
for sink in sinks:
sink.available = available_supply
# Check how much we actually need to drain from sources
var remaining_drain = total_source - available_supply
for source in sources:
var source_load = source.power_source / total_source * remaining_drain
source.power_load = source_load

View file

@ -50,7 +50,7 @@ cell_size = Vector2( 32, 32 )
cell_quadrant_size = 32 cell_quadrant_size = 32
occluder_light_mask = -2147483647 occluder_light_mask = -2147483647
format = 1 format = 1
tile_data = PoolIntArray( 393214, 0, 327681, 393215, 0, 262145, 327680, 0, 458752, 458749, 0, 65537, 458750, 0, 262150, 458751, 0, 458754, 393216, 0, 393218, 524284, 0, 327681, 524285, 0, 131078, 524287, 0, 262151, 458752, 0, 458755, 458755, 0, 131072, 458756, 0, 0, 589820, 0, 262151, 589821, 0, 6, 589822, 0, 1, 589823, 0, 196611, 655355, 0, 131072, 655356, 0, 131074, 655358, 0, 65539, 589828, 0, 131073, 720892, 0, 65538, 720893, 0, 1, 720894, 0, 2, 720895, 0, 262144, 655363, 0, 131072, 655364, 0, 2, 655365, 0, 65536, 655366, 0, 65536, 655367, 0, 1, 655368, 0, 262144, 786429, 0, 131075, 720903, 0, 131075 ) tile_data = PoolIntArray( 393212, 0, 131072, 393213, 0, 65536, 393214, 0, 65536, 393215, 0, 65536, 327680, 0, 65536, 327681, 0, 65536, 327682, 0, 65536, 327683, 0, 65536, 327684, 0, 262144, 589828, 0, 131073, 655364, 0, 65538, 655365, 0, 65536, 655366, 0, 65536, 655367, 0, 1, 655368, 0, 262144, 720903, 0, 131075 )
[node name="floor" type="TileMap" parent="."] [node name="floor" type="TileMap" parent="."]
tile_set = ExtResource( 9 ) tile_set = ExtResource( 9 )
@ -121,8 +121,8 @@ computer_type = 4
position = Vector2( -128, 128 ) position = Vector2( -128, 128 )
computer_type = 5 computer_type = 5
[node name="StaticBody2D2" parent="objects" instance=ExtResource( 12 )] [node name="SMES2" parent="objects" instance=ExtResource( 12 )]
position = Vector2( 193, 128 ) position = Vector2( 128, 128 )
[node name="SMES1" parent="objects" instance=ExtResource( 12 )] [node name="SMES1" parent="objects" instance=ExtResource( 12 )]
position = Vector2( 128, 256 ) position = Vector2( 128, 256 )
@ -137,6 +137,7 @@ position = Vector2( 288, 320 )
[node name="ElectricSocket" parent="objects" instance=ExtResource( 13 )] [node name="ElectricSocket" parent="objects" instance=ExtResource( 13 )]
position = Vector2( 128, 288 ) position = Vector2( 128, 288 )
connectionPaths = [ NodePath("../SMES1") ] connectionPaths = [ NodePath("../SMES1") ]
flow = 0
[node name="ElectricSocket2" parent="objects" instance=ExtResource( 13 )] [node name="ElectricSocket2" parent="objects" instance=ExtResource( 13 )]
position = Vector2( 256, 320 ) position = Vector2( 256, 320 )
@ -144,6 +145,45 @@ direction = 1
connectionPaths = [ NodePath("../Scanner") ] connectionPaths = [ NodePath("../Scanner") ]
flow = 1 flow = 1
[node name="ElectricSocket4" parent="objects" instance=ExtResource( 13 )]
position = Vector2( -128, 160 )
connectionPaths = [ NodePath("../Computer6") ]
flow = 1
[node name="ElectricSocket5" parent="objects" instance=ExtResource( 13 )]
position = Vector2( -96, 160 )
connectionPaths = [ NodePath("../Computer5") ]
flow = 1
[node name="ElectricSocket6" parent="objects" instance=ExtResource( 13 )]
position = Vector2( -64, 160 )
connectionPaths = [ NodePath("../Computer") ]
flow = 1
[node name="ElectricSocket7" parent="objects" instance=ExtResource( 13 )]
position = Vector2( -32, 160 )
connectionPaths = [ NodePath("../Computer2") ]
flow = 1
[node name="ElectricSocket8" parent="objects" instance=ExtResource( 13 )]
position = Vector2( 0, 160 )
connectionPaths = [ NodePath("../Computer3") ]
flow = 1
[node name="ElectricSocket9" parent="objects" instance=ExtResource( 13 )]
position = Vector2( 32, 160 )
connectionPaths = [ NodePath("../Computer4") ]
flow = 1
[node name="ElectricSocket10" parent="objects" instance=ExtResource( 13 )]
position = Vector2( 64, 160 )
connectionPaths = [ NodePath("../Computer7") ]
flow = 1
[node name="ElectricSocket3" parent="objects" instance=ExtResource( 13 )]
position = Vector2( 128, 160 )
connectionPaths = [ NodePath("../SMES2") ]
[node name="lights" type="Node2D" parent="."] [node name="lights" type="Node2D" parent="."]
modulate = Color( 0.980392, 0.980392, 0.980392, 1 ) modulate = Color( 0.980392, 0.980392, 0.980392, 1 )
__meta__ = { __meta__ = {