diff --git a/Actors/Components/PowerManager.gd b/Actors/Components/PowerManager.gd index 7cc98aa..1fba19e 100644 --- a/Actors/Components/PowerManager.gd +++ b/Actors/Components/PowerManager.gd @@ -12,11 +12,21 @@ var wired setget , get_wired export var power_usage = 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: 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: pass diff --git a/Actors/Objects/Computer/Computer.gd b/Actors/Objects/Computer/Computer.gd index 56f106b..32d4975 100644 --- a/Actors/Objects/Computer/Computer.gd +++ b/Actors/Objects/Computer/Computer.gd @@ -14,6 +14,7 @@ var screen_region_offset = Vector2.ZERO var open = false onready var activationRange = $ActivationRange as ActivationRange +onready var manager = $PowerManager as PowerManager func _ready(): if not Engine.editor_hint: @@ -77,7 +78,7 @@ func _input_event(_viewport, event, _shape_idx): return if event is InputEventMouseButton and event.pressed and not open: # Must be in range - if activationRange.in_range(): + if activationRange.in_range() and manager.powered: open = true manage_controls(true) $UIAnimation.play("fadein") @@ -94,3 +95,10 @@ func _force_close_ui(): if open: open = false $UIAnimation.play("fadeout") + +func _power_status_changed(powered: bool) -> void: + activationRange.visible = powered + if powered: + $ScreenAnimation.play("on") + else: + $ScreenAnimation.play("off") diff --git a/Actors/Objects/Computer/Computer.tscn b/Actors/Objects/Computer/Computer.tscn index 6b412e9..a7657ef 100644 --- a/Actors/Objects/Computer/Computer.tscn +++ b/Actors/Objects/Computer/Computer.tscn @@ -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.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://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/PowerManager.gd" type="Script" id=7] [sub_resource type="RectangleShape2D" id=1] extents = Vector2( 16, 16 ) @@ -14,6 +15,7 @@ extents = Vector2( 16, 16 ) blend_mode = 1 [sub_resource type="Animation" id=3] +loop = true tracks/0/type = "value" tracks/0/path = NodePath("computer/screen:modulate") tracks/0/interp = 1 @@ -127,7 +129,7 @@ texture_scale = 0.5 energy = 0.5 [node name="ScreenAnimation" type="AnimationPlayer" parent="."] -autoplay = "on" +autoplay = "off" anims/off = SubResource( 3 ) anims/on = SubResource( 4 ) @@ -155,7 +157,13 @@ script = ExtResource( 6 ) [node name="CollisionShape2D" type="CollisionShape2D" parent="ActivationRange"] position = Vector2( 16, 16 ) 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="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="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 ]] diff --git a/Actors/Objects/ElectricSocket/ElectricSocket.gd b/Actors/Objects/ElectricSocket/ElectricSocket.gd index b60b5f2..0730a7b 100644 --- a/Actors/Objects/ElectricSocket/ElectricSocket.gd +++ b/Actors/Objects/ElectricSocket/ElectricSocket.gd @@ -1,9 +1,9 @@ tool -class_name ElectricSocket - extends Area2D +class_name ElectricSocket + enum Direction { LEFT, RIGHT, UP, DOWN } enum Flow { SOURCE, SINK, BIDIRECTIONAL } @@ -22,25 +22,28 @@ onready var socket = $socket var network = null -func _ready(): +func _ready() -> void: socket.material = socket.material.duplicate() refresh_sprite() + if Engine.editor_hint: + return for connection in connectionPaths: add_connection(get_node(connection)) -func add_connection(node: Node): +func add_connection(node: Node) -> void: var manager = node.get_node("PowerManager") as PowerManager manager.socket = self + connections.append(manager) -func set_direction(dir): +func set_direction(dir) -> void: direction = dir refresh_sprite() -func set_flow(val): +func set_flow(val) -> void: flow = val refresh_sprite() -func refresh_sprite(): +func refresh_sprite() -> void: if socket == null: return match direction: diff --git a/Actors/Objects/PowerStorage/PowerStorage.gd b/Actors/Objects/PowerStorage/PowerStorage.gd index f912aa6..ddea03a 100644 --- a/Actors/Objects/PowerStorage/PowerStorage.gd +++ b/Actors/Objects/PowerStorage/PowerStorage.gd @@ -2,22 +2,29 @@ extends StaticBody2D class_name GameObjectPowerStorage -const MAX_CHARGE = 5000.0 +const MAX_CHARGE = 100000.0 var open = false var attached = true 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(): if not Engine.editor_hint: activationRange.visible = true -func _physics_process(_delta): - if $PowerManager.wired: - if $PowerManager.DEBUG: +func _physics_process(delta: float): + if manager.wired: + 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() + $Control/PowerUI.displayed_charge = current_charge func _input(event): if event is InputEventMouseButton and event.pressed and not is_inside and open: @@ -48,7 +55,7 @@ func _force_close_ui(): $UIAnimation.play("fadeout") 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_color = Color.greenyellow if charge_px < 20: diff --git a/Actors/Objects/PowerStorage/PowerStorage.tscn b/Actors/Objects/PowerStorage/PowerStorage.tscn index bd8bd8a..c231cd5 100644 --- a/Actors/Objects/PowerStorage/PowerStorage.tscn +++ b/Actors/Objects/PowerStorage/PowerStorage.tscn @@ -60,7 +60,7 @@ tracks/1/keys = { "times": PoolRealArray( 0, 0.2 ) } -[sub_resource type="CircleShape2D" id=5] +[sub_resource type="CircleShape2D" id=4] radius = 56.0 [node name="StaticBody2D" type="StaticBody2D"] @@ -89,7 +89,7 @@ z_index = 999 [node name="PowerUI" parent="Control" instance=ExtResource( 4 )] visible = false margin_left = -50.0 -margin_top = -73.0 +margin_top = -85.0 margin_right = 150.0 margin_bottom = 57.0 rect_scale = Vector2( 0.5, 0.5 ) @@ -100,7 +100,7 @@ position = Vector2( 16, 16 ) script = ExtResource( 3 ) [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_exited" from="Control/PowerUI" to="." method="_ui_focus_changed" binds= [ false ]] [connection signal="player_left" from="ActivationRange" to="." method="_force_close_ui"] diff --git a/Actors/Objects/PowerStorage/UI/PowerUI.gd b/Actors/Objects/PowerStorage/UI/PowerUI.gd index 7eb8f8a..49c7a5b 100644 --- a/Actors/Objects/PowerStorage/UI/PowerUI.gd +++ b/Actors/Objects/PowerStorage/UI/PowerUI.gd @@ -2,5 +2,12 @@ extends Control onready var scene = $"/root/scene" as GameInstance -func _physics_process(_delta): - pass +var displayed_charge = 0 setget set_current_charge +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 diff --git a/Actors/Objects/PowerStorage/UI/PowerUI.tscn b/Actors/Objects/PowerStorage/UI/PowerUI.tscn index f19916f..1f25dde 100644 --- a/Actors/Objects/PowerStorage/UI/PowerUI.tscn +++ b/Actors/Objects/PowerStorage/UI/PowerUI.tscn @@ -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://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] [node name="PowerUI" type="Control"] material = ExtResource( 4 ) -margin_left = -100.0 -margin_top = -150.0 -margin_right = 100.0 +margin_left = -110.0 +margin_top = -160.0 +margin_right = 110.0 margin_bottom = -20.0 mouse_filter = 1 script = ExtResource( 1 ) @@ -19,11 +20,13 @@ __meta__ = { [node name="TextureRect" type="TextureRect" parent="."] material = ExtResource( 4 ) anchor_left = 0.5 +anchor_top = 1.0 anchor_right = 0.5 +anchor_bottom = 1.0 margin_left = -8.0 -margin_top = 111.826 +margin_top = -18.0 margin_right = 8.27014 -margin_bottom = 143.855 +margin_bottom = 14.182 texture = ExtResource( 2 ) stretch_mode = 3 __meta__ = { @@ -34,6 +37,7 @@ __meta__ = { material = ExtResource( 4 ) anchor_right = 1.0 anchor_bottom = 1.0 +mouse_filter = 1 texture = ExtResource( 2 ) region_rect = Rect2( 0, 0, 16, 16 ) patch_margin_left = 4 @@ -59,3 +63,81 @@ custom_constants/separation = 20 __meta__ = { "_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" diff --git a/Actors/Objects/Scanner/Scanner.tscn b/Actors/Objects/Scanner/Scanner.tscn index 6953de7..d8a97f5 100644 --- a/Actors/Objects/Scanner/Scanner.tscn +++ b/Actors/Objects/Scanner/Scanner.tscn @@ -21,3 +21,4 @@ centered = false [node name="PowerManager" type="Node" parent="."] script = ExtResource( 3 ) +power_usage = 10.0 diff --git a/Actors/Systems/Electricity/PowerNetwork.gd b/Actors/Systems/Electricity/PowerNetwork.gd index 2e388a2..da1bf0e 100644 --- a/Actors/Systems/Electricity/PowerNetwork.gd +++ b/Actors/Systems/Electricity/PowerNetwork.gd @@ -2,23 +2,26 @@ extends Node class_name PowerNetwork -const DEBUG = true +const DEBUG = false var nodes = [] var sockets = [] +var total_source = 0 +var total_usage = 0 + var debugColor = Color.cyan func _ready(): name = "PowerNetwork" debugColor = Color.from_hsv(randf(), 0.8, 0.8) -func add_node(node): +func add_node(node) -> void: nodes.append(node) - if node is ElectricSocket: + if "connections" in node: sockets.append(node) -func remove_node(node): +func remove_node(node) -> void: var node_idx = nodes.find(node) if node_idx >= 0: nodes.remove(node_idx) @@ -28,19 +31,53 @@ func remove_node(node): # Do other splitting here node.network = null -func join(network): +func join(network) -> void: for node in network.nodes: nodes.append(node) node.network = self + for socket in network.sockets: + sockets.append(socket) + socket.network = self # Do other merging here network.queue_free() -func _physics_process(_delta): +func _physics_process(_delta: float) -> void: # Recalculate power availability and usage - var total_source = 0 - var total_usage = 0 + total_source = 0 + total_usage = 0 + var sources = [] + var sinks = [] + # Calculate totals for socket in sockets: for connection in socket.connections: var manager = connection as PowerManager - total_source += manager.power_source - total_usage += manager.power_usage + match socket.flow: + ElectricSocket.Flow.SINK: + 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 diff --git a/Scenes/Maps/runtime.tscn b/Scenes/Maps/runtime.tscn index 117a753..9998076 100644 --- a/Scenes/Maps/runtime.tscn +++ b/Scenes/Maps/runtime.tscn @@ -50,7 +50,7 @@ cell_size = Vector2( 32, 32 ) cell_quadrant_size = 32 occluder_light_mask = -2147483647 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="."] tile_set = ExtResource( 9 ) @@ -121,8 +121,8 @@ computer_type = 4 position = Vector2( -128, 128 ) computer_type = 5 -[node name="StaticBody2D2" parent="objects" instance=ExtResource( 12 )] -position = Vector2( 193, 128 ) +[node name="SMES2" parent="objects" instance=ExtResource( 12 )] +position = Vector2( 128, 128 ) [node name="SMES1" parent="objects" instance=ExtResource( 12 )] position = Vector2( 128, 256 ) @@ -137,6 +137,7 @@ position = Vector2( 288, 320 ) [node name="ElectricSocket" parent="objects" instance=ExtResource( 13 )] position = Vector2( 128, 288 ) connectionPaths = [ NodePath("../SMES1") ] +flow = 0 [node name="ElectricSocket2" parent="objects" instance=ExtResource( 13 )] position = Vector2( 256, 320 ) @@ -144,6 +145,45 @@ direction = 1 connectionPaths = [ NodePath("../Scanner") ] 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="."] modulate = Color( 0.980392, 0.980392, 0.980392, 1 ) __meta__ = {