Compare commits

...
This repository has been archived on 2020-09-30. You can view files and clone it, but cannot push or open issues or pull requests.

40 commits
sslo ... master

Author SHA1 Message Date
a01a0215cd
Add item boxes, add asking 2020-07-28 09:54:04 +02:00
9383bc9803
Make text work better on smaller map zoom 2020-07-27 11:27:19 +02:00
745438e419
👀 2020-07-24 13:49:43 +02:00
922ab0ea7f
Add zooming in map 2020-07-24 13:49:22 +02:00
4997130d1f
Add inspect with SHIFT 2020-07-23 14:21:27 +02:00
4d1d37a169
Use format strings where it makes sense 2020-07-23 11:12:07 +02:00
f57e1c433b
Add chat format 2020-07-23 10:51:39 +02:00
6ddb52c27c
Add random name generation 2020-07-23 10:50:47 +02:00
b77326eb80
RIP GOTM 2020-07-22 17:34:04 +02:00
3d57f3d839
Add some UI sound effects 2020-07-22 15:58:17 +02:00
9d6b29a933
Start adding logging 2020-07-21 19:47:33 +02:00
995f2ab8b0
Small refactor 2020-07-21 10:51:15 +02:00
f8d6c29d06
Add door sounds 2020-07-20 15:04:56 +02:00
187a46eabd
Add area management 2020-07-20 11:15:39 +02:00
f53cf355bc
More symmetric 2020-07-17 02:26:08 +02:00
ac4bb87567
oh so this is why they were blurred 2020-07-17 02:25:55 +02:00
4e29c440ff
New tiles 2020-07-16 18:11:58 +02:00
a62da2f057
Try fixing the plugin problem + more odyssey 2020-07-16 17:08:30 +02:00
a7c35e24e8
Flooring on odyssey 2020-07-16 14:44:42 +02:00
d8f2e3f6f7
Hide computer light in editor 2020-07-16 14:44:35 +02:00
728c956f72
Don't make doors close on people! 2020-07-16 14:44:18 +02:00
db8a9ab1e4
Start rework on odyssey 2020-07-16 14:38:06 +02:00
92edab98c6
Add crew monitor computer type 2020-07-16 14:37:56 +02:00
bcbac84049
Heh 2020-07-16 14:37:46 +02:00
7dc9c90390
Add (slightly broken) mapping helper tool 2020-07-16 14:37:37 +02:00
e02d1e4cc3
Fix this damn navigation 2020-07-16 14:37:21 +02:00
e0797412c6
Import splash/icon as images and not textures 2020-07-16 14:36:38 +02:00
1ecbc87400
Make door automatically open when players bump into them 2020-07-16 14:36:08 +02:00
5316affe0e
Engines now suck energy juice. Also you can go places. Also readme and stuff 2020-07-14 23:28:13 +02:00
5ca3c191cd
Add WebGL and GOTM support 2020-07-14 16:20:06 +02:00
d021b3ab3b
WebGL friendly shader 2020-07-14 14:18:35 +02:00
546d83bf1d
Refresh master server entries every 5 seconds 2020-07-14 09:21:52 +02:00
6ea963f1f6
Minor things 2020-07-14 02:00:43 +02:00
6e6d9e2fa2
Disable collisions between players 2020-07-14 01:59:57 +02:00
40705ac661
Add master server dialog 2020-07-14 01:59:45 +02:00
9e6763d2bb
Fix activation range 2020-07-14 01:19:24 +02:00
b95246209a
Sync systems and go back to GLES2 for now 2020-07-13 22:18:02 +02:00
e1221af9ec
Add map serialization/deserialization (incomplete) 2020-07-13 21:01:36 +02:00
a13eb426ef
Add async loading and start work on joining servers 2020-07-13 11:20:51 +02:00
1c328e3e2e
Start adding async loading 2020-07-13 02:20:09 +02:00
111 changed files with 4456 additions and 888 deletions

1
.gitignore vendored
View file

@ -1,2 +1,3 @@
.import .import
export export
.vscode

View file

@ -19,14 +19,10 @@ var powered = false setget set_powered
func get_wired() -> bool: func get_wired() -> bool:
return socket != null return socket != null
func set_powered(val: bool) -> void: remotesync func set_powered(val: bool) -> void:
var current = powered var current = powered
powered = val powered = val
if current and not val: if current and not val:
emit_signal("power_disconnected") emit_signal("power_disconnected")
elif not current and val: elif not current and val:
emit_signal("power_connected") emit_signal("power_connected")
func _physics_process(_delta: float) -> void:
if wired:
pass

36
Actors/Meta/POI/POI.gd Normal file
View file

@ -0,0 +1,36 @@
tool
extends Node2D
class_name POI
enum POIType {
Null,
SpawnPoint
}
enum POIClass {
Null,
Player
}
export(POIType) var poitype = POIType.Null
export(POIClass) var poiclass = POIClass.Null
func _draw():
if Engine.editor_hint:
match poitype:
POIType.SpawnPoint:
match poiclass:
POIClass.Player:
draw_arc(Vector2.ZERO, 10, 0, PI*2, 16, Color.red, 2)
func serialize():
return {
"poitype": poitype,
"poiclass": poiclass
}
func deserialize(data):
poitype = data["poitype"]
poiclass = data["poiclass"]

9
Actors/Meta/POI/POI.tscn Normal file
View file

@ -0,0 +1,9 @@
[gd_scene load_steps=2 format=2]
[ext_resource path="res://Actors/Meta/POI/POI.gd" type="Script" id=1]
[node name="NullPOI" type="Node2D"]
position = Vector2( 208, 256 )
script = ExtResource( 1 )
poitype = 1
poiclass = 1

View file

@ -1,12 +0,0 @@
tool
extends Node2D
class_name SpawnpointPlayer
var poitype = POIData.POIType.SpawnPoint
var poiclass = POIData.POIClass.Player
func _draw():
if Engine.editor_hint:
draw_arc(Vector2.ZERO, 10, 0, PI*2, 16, Color.red)

View file

@ -5,8 +5,9 @@ extends StaticBody2D
class_name GameObjectComputer class_name GameObjectComputer
enum Direction { LEFT, RIGHT, UP, DOWN } enum Direction { LEFT, RIGHT, UP, DOWN }
enum ComputerType { ShipCommand, Comms, Medical, Research, Energy, ShipEngine, Atmos } enum ComputerType { ShipCommand, Comms, Medical, Research, Energy, ShipEngine, Atmos, Monitoring }
export var object_name = ""
export(Direction) var direction = Direction.DOWN setget set_direction export(Direction) var direction = Direction.DOWN setget set_direction
export(ComputerType) var computer_type = ComputerType.ShipCommand setget set_type export(ComputerType) var computer_type = ComputerType.ShipCommand setget set_type
@ -19,6 +20,7 @@ onready var manager = $PowerManager as PowerManager
func _ready(): func _ready():
if not Engine.editor_hint: if not Engine.editor_hint:
activationRange.visible = true activationRange.visible = true
$computer/screen/Light2D.visible = true
func set_type(val): func set_type(val):
computer_type = val computer_type = val
@ -37,6 +39,8 @@ func set_type(val):
screen_region_offset = Vector2(128, 192) screen_region_offset = Vector2(128, 192)
ComputerType.ShipEngine: ComputerType.ShipEngine:
screen_region_offset = Vector2(0, 256) screen_region_offset = Vector2(0, 256)
ComputerType.Monitoring:
screen_region_offset = Vector2(128, 32)
refresh_sprite() refresh_sprite()
@ -67,6 +71,8 @@ func manage_controls(show: bool):
match computer_type: match computer_type:
ComputerType.ShipCommand: ComputerType.ShipCommand:
$Control/ControlComp.visible = show $Control/ControlComp.visible = show
ComputerType.Energy:
$Control/EnergyComp.visible = show
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:
@ -95,6 +101,9 @@ func _force_close_ui():
if open: if open:
open = false open = false
$UIAnimation.play("fadeout") $UIAnimation.play("fadeout")
match computer_type:
ComputerType.ShipCommand:
$Control/ControlComp.force_close()
func _power_status_changed(powered: bool) -> void: func _power_status_changed(powered: bool) -> void:
activationRange.visible = powered activationRange.visible = powered
@ -102,3 +111,64 @@ func _power_status_changed(powered: bool) -> void:
$ScreenAnimation.play("on") $ScreenAnimation.play("on")
else: else:
$ScreenAnimation.play("off") $ScreenAnimation.play("off")
func serialize():
return {
"direction": direction,
"computer_type": computer_type
}
func deserialize(data):
set_direction(data["direction"])
set_type(data["computer_type"])
func inspect():
match computer_type:
ComputerType.ShipCommand:
return {
"type": "Control board computer",
"description": "A computer for moving the ship around the galaxy",
"interaction": "Click when near to interact"
}
ComputerType.Comms:
return {
"type": "Comms computer",
"description": "A computer for issuing and controlling communications",
"interaction": "Click when near to interact"
}
ComputerType.Medical:
return {
"type": "Medical computer",
"description": "A computer for checking health status and medical procedures",
"interaction": "Click when near to interact"
}
ComputerType.Research:
return {
"type": "R&D computer",
"description": "A computer for researching new tech and control printers",
"interaction": "Click when near to interact"
}
ComputerType.Energy:
return {
"type": "Energy supply computer",
"description": "A computer for monitoring and managing the energy grid",
"interaction": "Click when near to interact"
}
ComputerType.Atmos:
return {
"type": "Atmos computer",
"description": "A computer for monitoring and managing the air supply",
"interaction": "Click when near to interact"
}
ComputerType.ShipEngine:
return {
"type": "Engine control computer",
"description": "A computer for monitoring and managing the ship engines",
"interaction": "Click when near to interact"
}
ComputerType.Monitoring:
return {
"type": "Monitoring computer",
"description": "A computer for monitoring crew and ship status",
"interaction": "Click when near to interact"
}

View file

@ -1,4 +1,4 @@
[gd_scene load_steps=15 format=2] [gd_scene load_steps=16 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]
@ -7,6 +7,7 @@
[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] [ext_resource path="res://Actors/Components/PowerManager.gd" type="Script" id=7]
[ext_resource path="res://Actors/Objects/Computer/UI/EnergyComp.tscn" type="PackedScene" id=8]
[sub_resource type="RectangleShape2D" id=1] [sub_resource type="RectangleShape2D" id=1]
extents = Vector2( 16, 16 ) extents = Vector2( 16, 16 )
@ -126,6 +127,7 @@ extents = Vector2( 48, 48 )
[node name="Computer" type="StaticBody2D"] [node name="Computer" type="StaticBody2D"]
input_pickable = true input_pickable = true
collision_layer = 3
script = ExtResource( 3 ) script = ExtResource( 3 )
[node name="CollisionShape2D" type="CollisionShape2D" parent="."] [node name="CollisionShape2D" type="CollisionShape2D" parent="."]
@ -139,6 +141,7 @@ region_enabled = true
region_rect = Rect2( 0, 0, 32, 32 ) region_rect = Rect2( 0, 0, 32, 32 )
[node name="screen" type="Sprite" parent="computer"] [node name="screen" type="Sprite" parent="computer"]
modulate = Color( 0, 0, 0, 1 )
material = SubResource( 2 ) material = SubResource( 2 )
texture = ExtResource( 1 ) texture = ExtResource( 1 )
centered = false centered = false
@ -146,7 +149,9 @@ region_enabled = true
region_rect = Rect2( 0, 0, 32, 32 ) region_rect = Rect2( 0, 0, 32, 32 )
[node name="Light2D" type="Light2D" parent="computer/screen"] [node name="Light2D" type="Light2D" parent="computer/screen"]
visible = false
position = Vector2( 16, 16 ) position = Vector2( 16, 16 )
enabled = false
texture = ExtResource( 5 ) texture = ExtResource( 5 )
texture_scale = 0.5 texture_scale = 0.5
energy = 0.5 energy = 0.5
@ -165,14 +170,23 @@ z_index = 999
[node name="ControlComp" parent="Control" instance=ExtResource( 4 )] [node name="ControlComp" parent="Control" instance=ExtResource( 4 )]
visible = false visible = false
margin_left = -42.0 margin_left = -47.0
margin_top = -58.0 margin_top = -81.0
margin_right = 193.0 margin_right = 208.0
margin_bottom = 47.0 margin_bottom = 66.0
rect_scale = Vector2( 0.5, 0.5 )
[node name="EnergyComp" parent="Control" instance=ExtResource( 8 )]
visible = false
margin_left = -47.0
margin_top = -53.0
margin_right = 207.0
margin_bottom = 36.0
rect_scale = Vector2( 0.5, 0.5 ) rect_scale = Vector2( 0.5, 0.5 )
[node name="ActivationRange" type="Area2D" parent="."] [node name="ActivationRange" type="Area2D" parent="."]
visible = false visible = false
input_pickable = false
script = ExtResource( 6 ) script = ExtResource( 6 )
[node name="CollisionShape2D" type="CollisionShape2D" parent="ActivationRange"] [node name="CollisionShape2D" type="CollisionShape2D" parent="ActivationRange"]

View file

@ -3,13 +3,22 @@ extends Control
onready var scene = $"/root/scene" as GameInstance onready var scene = $"/root/scene" as GameInstance
func _physics_process(_delta): func _physics_process(_delta):
var speed_str = str(round(scene.world.map.current_ship_speed)) + " u/s" if not visible:
$Container/VelocityBox/HBoxContainer3/CurrentSpeed.text = speed_str return
var dir_str = str(round(rad2deg(scene.world.map.current_ship_direction))) + " deg" var speed_str = "%.0f u/s" % (scene.world.map.current_ship_speed * 10000)
$Container/VelocityBox/HBoxContainer2/CurrentDirection.text = dir_str $Margin/Container/VelocityBox/HBoxContainer3/CurrentSpeed.text = speed_str
var dir_str = "%.0f deg" % rad2deg(scene.world.map.current_ship_direction)
$Margin/Container/VelocityBox/HBoxContainer2/CurrentDirection.text = dir_str
var current_position_str = Coordinates.as_string(scene.world.map.current_ship_position + scene.world.map.current_ship_subpos, true)
$Margin/Container/VelocityBox/HBoxContainer4/CurrentPosition.text = current_position_str
var current_target_str = scene.world.map.current_ship_target
if current_target_str == null:
$Margin/Container/VelocityBox/HBoxContainer/CurrentTarget.text = "None"
else:
$Margin/Container/VelocityBox/HBoxContainer/CurrentTarget.text = Coordinates.as_string(current_target_str, true)
func _ship_velocity_changed(value): func _map_button_pressed():
scene.process_command(UICommand.new(UICommand.CommandType.SetShipSpeed, [value])) scene.ui.open_popup(GameUI.PopupName.SpaceMap)
func _ship_direction_changed(value): func force_close():
scene.process_command(UICommand.new(UICommand.CommandType.SetShipDirection, [deg2rad(value)])) scene.ui.close_popup(GameUI.PopupName.SpaceMap)

View file

@ -7,10 +7,12 @@
[node name="ControlComp" type="Control"] [node name="ControlComp" type="Control"]
material = ExtResource( 4 ) material = ExtResource( 4 )
margin_left = -121.0 margin_left = -157.0
margin_top = -150.0 margin_top = -160.0
margin_right = 121.0 margin_right = 156.0
margin_bottom = -20.0 margin_bottom = -20.0
grow_horizontal = 2
grow_vertical = 2
mouse_filter = 1 mouse_filter = 1
script = ExtResource( 1 ) script = ExtResource( 1 )
__meta__ = { __meta__ = {
@ -48,25 +50,38 @@ __meta__ = {
"_edit_use_anchors_": false "_edit_use_anchors_": false
} }
[node name="Container" type="VBoxContainer" parent="."] [node name="Margin" type="MarginContainer" parent="."]
material = ExtResource( 4 )
anchor_right = 1.0 anchor_right = 1.0
anchor_bottom = 1.0 anchor_bottom = 1.0
margin_left = 10.0 margin_left = 10.0
margin_top = 10.0 margin_top = 10.0
margin_right = -10.0 margin_right = -10.0
margin_bottom = -10.0 margin_bottom = -10.0
grow_horizontal = 2
grow_vertical = 2
size_flags_horizontal = 3 size_flags_horizontal = 3
size_flags_vertical = 3 size_flags_vertical = 3
custom_constants/separation = 20
__meta__ = { __meta__ = {
"_edit_use_anchors_": false "_edit_use_anchors_": false
} }
[node name="VelocityBox" type="VBoxContainer" parent="Container"] [node name="Container" type="VBoxContainer" parent="Margin"]
material = ExtResource( 4 ) material = ExtResource( 4 )
margin_right = 222.0 margin_right = 293.0
margin_bottom = 110.0 margin_bottom = 120.0
grow_horizontal = 2
grow_vertical = 2
size_flags_horizontal = 3
size_flags_vertical = 3
custom_constants/separation = 10
__meta__ = {
"_edit_use_anchors_": false
}
[node name="VelocityBox" type="VBoxContainer" parent="Margin/Container"]
material = ExtResource( 4 )
margin_right = 293.0
margin_bottom = 86.0
size_flags_horizontal = 3 size_flags_horizontal = 3
size_flags_vertical = 3 size_flags_vertical = 3
alignment = 1 alignment = 1
@ -74,16 +89,16 @@ __meta__ = {
"_edit_use_anchors_": false "_edit_use_anchors_": false
} }
[node name="HBoxContainer" type="HBoxContainer" parent="Container/VelocityBox"] [node name="HBoxContainer" type="HBoxContainer" parent="Margin/Container/VelocityBox"]
margin_top = 13.0 margin_top = 1.0
margin_right = 222.0 margin_right = 293.0
margin_bottom = 31.0 margin_bottom = 19.0
custom_constants/separation = 10 custom_constants/separation = 10
__meta__ = { __meta__ = {
"_edit_use_anchors_": false "_edit_use_anchors_": false
} }
[node name="ShipTarget" type="Label" parent="Container/VelocityBox/HBoxContainer"] [node name="ShipTarget" type="Label" parent="Margin/Container/VelocityBox/HBoxContainer"]
material = ExtResource( 4 ) material = ExtResource( 4 )
margin_right = 98.0 margin_right = 98.0
margin_bottom = 18.0 margin_bottom = 18.0
@ -91,10 +106,10 @@ mouse_filter = 1
theme = ExtResource( 3 ) theme = ExtResource( 3 )
text = "Current target" text = "Current target"
[node name="CurrentTarget" type="Label" parent="Container/VelocityBox/HBoxContainer"] [node name="CurrentTarget" type="Label" parent="Margin/Container/VelocityBox/HBoxContainer"]
material = ExtResource( 4 ) material = ExtResource( 4 )
margin_left = 108.0 margin_left = 108.0
margin_right = 222.0 margin_right = 293.0
margin_bottom = 18.0 margin_bottom = 18.0
mouse_filter = 1 mouse_filter = 1
size_flags_horizontal = 3 size_flags_horizontal = 3
@ -103,16 +118,16 @@ custom_colors/font_color = Color( 0.494118, 0.52549, 0.737255, 1 )
text = "2A.01/10" text = "2A.01/10"
align = 2 align = 2
[node name="HBoxContainer4" type="HBoxContainer" parent="Container/VelocityBox"] [node name="HBoxContainer4" type="HBoxContainer" parent="Margin/Container/VelocityBox"]
margin_top = 35.0 margin_top = 23.0
margin_right = 222.0 margin_right = 293.0
margin_bottom = 53.0 margin_bottom = 41.0
custom_constants/separation = 10 custom_constants/separation = 10
__meta__ = { __meta__ = {
"_edit_use_anchors_": false "_edit_use_anchors_": false
} }
[node name="ShipTarget" type="Label" parent="Container/VelocityBox/HBoxContainer4"] [node name="ShipTarget" type="Label" parent="Margin/Container/VelocityBox/HBoxContainer4"]
material = ExtResource( 4 ) material = ExtResource( 4 )
margin_right = 110.0 margin_right = 110.0
margin_bottom = 18.0 margin_bottom = 18.0
@ -120,10 +135,10 @@ mouse_filter = 1
theme = ExtResource( 3 ) theme = ExtResource( 3 )
text = "Current position" text = "Current position"
[node name="CurrentPosition" type="Label" parent="Container/VelocityBox/HBoxContainer4"] [node name="CurrentPosition" type="Label" parent="Margin/Container/VelocityBox/HBoxContainer4"]
material = ExtResource( 4 ) material = ExtResource( 4 )
margin_left = 120.0 margin_left = 120.0
margin_right = 222.0 margin_right = 293.0
margin_bottom = 18.0 margin_bottom = 18.0
mouse_filter = 1 mouse_filter = 1
size_flags_horizontal = 3 size_flags_horizontal = 3
@ -132,16 +147,16 @@ custom_colors/font_color = Color( 0.494118, 0.52549, 0.737255, 1 )
text = "0A.00/00" text = "0A.00/00"
align = 2 align = 2
[node name="HBoxContainer3" type="HBoxContainer" parent="Container/VelocityBox"] [node name="HBoxContainer3" type="HBoxContainer" parent="Margin/Container/VelocityBox"]
margin_top = 57.0 margin_top = 45.0
margin_right = 222.0 margin_right = 293.0
margin_bottom = 75.0 margin_bottom = 63.0
custom_constants/separation = 10 custom_constants/separation = 10
__meta__ = { __meta__ = {
"_edit_use_anchors_": false "_edit_use_anchors_": false
} }
[node name="ShipVelocityLabel" type="Label" parent="Container/VelocityBox/HBoxContainer3"] [node name="ShipVelocityLabel" type="Label" parent="Margin/Container/VelocityBox/HBoxContainer3"]
material = ExtResource( 4 ) material = ExtResource( 4 )
margin_right = 88.0 margin_right = 88.0
margin_bottom = 18.0 margin_bottom = 18.0
@ -149,10 +164,10 @@ mouse_filter = 1
theme = ExtResource( 3 ) theme = ExtResource( 3 )
text = "Ship velocity" text = "Ship velocity"
[node name="CurrentSpeed" type="Label" parent="Container/VelocityBox/HBoxContainer3"] [node name="CurrentSpeed" type="Label" parent="Margin/Container/VelocityBox/HBoxContainer3"]
material = ExtResource( 4 ) material = ExtResource( 4 )
margin_left = 98.0 margin_left = 98.0
margin_right = 222.0 margin_right = 293.0
margin_bottom = 18.0 margin_bottom = 18.0
mouse_filter = 1 mouse_filter = 1
size_flags_horizontal = 3 size_flags_horizontal = 3
@ -160,12 +175,12 @@ theme = ExtResource( 3 )
custom_colors/font_color = Color( 0.494118, 0.52549, 0.737255, 1 ) custom_colors/font_color = Color( 0.494118, 0.52549, 0.737255, 1 )
align = 2 align = 2
[node name="HBoxContainer2" type="HBoxContainer" parent="Container/VelocityBox"] [node name="HBoxContainer2" type="HBoxContainer" parent="Margin/Container/VelocityBox"]
margin_top = 79.0 margin_top = 67.0
margin_right = 222.0 margin_right = 293.0
margin_bottom = 97.0 margin_bottom = 85.0
[node name="ShipDirectionLabel" type="Label" parent="Container/VelocityBox/HBoxContainer2"] [node name="ShipDirectionLabel" type="Label" parent="Margin/Container/VelocityBox/HBoxContainer2"]
material = ExtResource( 4 ) material = ExtResource( 4 )
margin_right = 94.0 margin_right = 94.0
margin_bottom = 18.0 margin_bottom = 18.0
@ -173,13 +188,22 @@ mouse_filter = 1
theme = ExtResource( 3 ) theme = ExtResource( 3 )
text = "Ship direction" text = "Ship direction"
[node name="CurrentDirection" type="Label" parent="Container/VelocityBox/HBoxContainer2"] [node name="CurrentDirection" type="Label" parent="Margin/Container/VelocityBox/HBoxContainer2"]
material = ExtResource( 4 ) material = ExtResource( 4 )
margin_left = 98.0 margin_left = 98.0
margin_right = 222.0 margin_right = 293.0
margin_bottom = 18.0 margin_bottom = 18.0
mouse_filter = 1 mouse_filter = 1
size_flags_horizontal = 3 size_flags_horizontal = 3
theme = ExtResource( 3 ) theme = ExtResource( 3 )
custom_colors/font_color = Color( 0.494118, 0.52549, 0.737255, 1 ) custom_colors/font_color = Color( 0.494118, 0.52549, 0.737255, 1 )
align = 2 align = 2
[node name="Button" type="Button" parent="Margin/Container"]
material = ExtResource( 4 )
margin_top = 96.0
margin_right = 293.0
margin_bottom = 120.0
theme = ExtResource( 3 )
text = "Open map"
[connection signal="pressed" from="Margin/Container/Button" to="." method="_map_button_pressed"]

View file

@ -0,0 +1,26 @@
extends Control
onready var scene = $"/root/scene" as GameInstance
func _physics_process(_delta):
if not visible:
return
var children = scene.systems.get_children()
var total_sink = 0
var total_source = 0
var total_alerts = 0
for child in children:
if child is PowerNetwork:
var network = child as PowerNetwork
total_sink += network.total_usage
total_source += network.total_source
total_alerts += network.unpowered
$Margin/Container/EnergyBox/CurrentSource/Value.text = "%.0f kW" % total_source
$Margin/Container/EnergyBox/CurrentSink/Value.text = "%.0f kW" % total_sink
$Margin/Container/EnergyBox/CurrentAlerts/Value.text = str(total_alerts)
func _map_button_pressed():
scene.ui.open_popup(GameUI.PopupName.EnergyUsage)
func force_close():
scene.ui.close_popup(GameUI.PopupName.EnergyUsage)

View file

@ -0,0 +1,187 @@
[gd_scene load_steps=5 format=2]
[ext_resource path="res://Actors/Objects/Computer/UI/EnergyComp.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="EnergyComp" type="Control"]
material = ExtResource( 4 )
margin_left = -157.0
margin_top = -144.0
margin_right = 156.0
margin_bottom = -20.0
grow_horizontal = 2
grow_vertical = 2
mouse_filter = 1
script = ExtResource( 1 )
__meta__ = {
"_edit_use_anchors_": false
}
[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 = -16.5409
margin_right = 8.27014
margin_bottom = 15.4881
texture = ExtResource( 2 )
stretch_mode = 3
__meta__ = {
"_edit_use_anchors_": false
}
[node name="NinePatchRect" type="NinePatchRect" parent="."]
material = ExtResource( 4 )
anchor_right = 1.0
anchor_bottom = 1.0
texture = ExtResource( 2 )
region_rect = Rect2( 0, 0, 16, 16 )
patch_margin_left = 4
patch_margin_top = 4
patch_margin_right = 4
patch_margin_bottom = 5
axis_stretch_horizontal = 1
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Margin" type="MarginContainer" parent="."]
anchor_right = 1.0
anchor_bottom = 1.0
margin_left = 10.0
margin_top = 10.0
margin_right = -10.0
margin_bottom = -10.0
grow_horizontal = 2
grow_vertical = 2
size_flags_horizontal = 3
size_flags_vertical = 3
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Container" type="VBoxContainer" parent="Margin"]
material = ExtResource( 4 )
margin_right = 293.0
margin_bottom = 104.0
grow_horizontal = 2
grow_vertical = 2
size_flags_horizontal = 3
size_flags_vertical = 3
custom_constants/separation = 10
__meta__ = {
"_edit_use_anchors_": false
}
[node name="EnergyBox" type="VBoxContainer" parent="Margin/Container"]
material = ExtResource( 4 )
margin_right = 293.0
margin_bottom = 104.0
size_flags_horizontal = 3
size_flags_vertical = 3
alignment = 1
__meta__ = {
"_edit_use_anchors_": false
}
[node name="CurrentSource" type="HBoxContainer" parent="Margin/Container/EnergyBox"]
margin_top = 21.0
margin_right = 293.0
margin_bottom = 39.0
custom_constants/separation = 10
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Label" type="Label" parent="Margin/Container/EnergyBox/CurrentSource"]
material = ExtResource( 4 )
margin_right = 106.0
margin_bottom = 18.0
mouse_filter = 1
theme = ExtResource( 3 )
text = "Available power"
[node name="Value" type="Label" parent="Margin/Container/EnergyBox/CurrentSource"]
material = ExtResource( 4 )
margin_left = 116.0
margin_right = 293.0
margin_bottom = 18.0
mouse_filter = 1
size_flags_horizontal = 3
theme = ExtResource( 3 )
custom_colors/font_color = Color( 0.494118, 0.52549, 0.737255, 1 )
text = "2A.01/10"
align = 2
[node name="CurrentSink" type="HBoxContainer" parent="Margin/Container/EnergyBox"]
margin_top = 43.0
margin_right = 293.0
margin_bottom = 61.0
custom_constants/separation = 10
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Label" type="Label" parent="Margin/Container/EnergyBox/CurrentSink"]
material = ExtResource( 4 )
margin_right = 130.0
margin_bottom = 18.0
mouse_filter = 1
theme = ExtResource( 3 )
text = "Current power load"
[node name="Value" type="Label" parent="Margin/Container/EnergyBox/CurrentSink"]
material = ExtResource( 4 )
margin_left = 140.0
margin_right = 293.0
margin_bottom = 18.0
mouse_filter = 1
size_flags_horizontal = 3
theme = ExtResource( 3 )
custom_colors/font_color = Color( 0.494118, 0.52549, 0.737255, 1 )
text = "0A.00/00"
align = 2
[node name="CurrentAlerts" type="HBoxContainer" parent="Margin/Container/EnergyBox"]
margin_top = 65.0
margin_right = 293.0
margin_bottom = 83.0
custom_constants/separation = 10
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Label" type="Label" parent="Margin/Container/EnergyBox/CurrentAlerts"]
material = ExtResource( 4 )
margin_right = 130.0
margin_bottom = 18.0
mouse_filter = 1
theme = ExtResource( 3 )
text = "Unpowered devices"
[node name="Value" type="Label" parent="Margin/Container/EnergyBox/CurrentAlerts"]
material = ExtResource( 4 )
margin_left = 140.0
margin_right = 293.0
margin_bottom = 18.0
mouse_filter = 1
size_flags_horizontal = 3
theme = ExtResource( 3 )
custom_colors/font_color = Color( 0.494118, 0.52549, 0.737255, 1 )
text = "0A.00/00"
align = 2
[node name="Button" type="Button" parent="Margin/Container"]
visible = false
material = ExtResource( 4 )
margin_top = 80.0
margin_right = 293.0
margin_bottom = 104.0
theme = ExtResource( 3 )
text = "Open usage monitor"
[connection signal="pressed" from="Margin/Container/Button" to="." method="_map_button_pressed"]

View file

@ -2,9 +2,13 @@ extends StaticBody2D
class_name GameObjectDoor class_name GameObjectDoor
export var object_name = ""
export(NodePath) var interlockTargetPath export(NodePath) var interlockTargetPath
var interlockTarget: GameObjectDoor = null var interlockTarget: GameObjectDoor = null
var open_sound = preload("res://Sounds/SFX/effects/door-open.wav")
var close_sound = preload("res://Sounds/SFX/effects/door-close.wav")
export var idle_usage = 2 export var idle_usage = 2
export var active_usage = 10 export var active_usage = 10
@ -14,37 +18,50 @@ onready var manager = $PowerManager as PowerManager
signal changed(open) signal changed(open)
func _ready(): func _ready():
if is_network_master():
if interlockTargetPath != null: if interlockTargetPath != null:
interlockTarget = get_node_or_null(interlockTargetPath) interlockTarget = get_node_or_null(interlockTargetPath)
if not Engine.editor_hint: if not Engine.editor_hint:
activationRange.visible = true activationRange.visible = true
func set_open(open: bool): master func set_open(open: bool):
if not manager: if not manager:
return return
manager.power_usage = active_usage manager.power_usage = active_usage
if manager.powered: if manager.powered:
if open: if open:
$Sprite.play("open")
if interlockTarget != null: if interlockTarget != null:
interlockTarget.set_open(false) interlockTarget.set_open(false)
rpc("anim_open", open)
remotesync func anim_open(open: bool):
if open:
if $Sprite.animation != "open":
$AudioStreamPlayer2D.stream = open_sound
$AudioStreamPlayer2D.play()
$Sprite.play("open")
else: else:
if $Sprite.animation != "close":
$AudioStreamPlayer2D.stream = close_sound
$AudioStreamPlayer2D.play()
$Sprite.play("close") $Sprite.play("close")
func _animation_finished(): func _animation_finished():
if is_network_master():
if manager: if manager:
manager.power_usage = idle_usage manager.power_usage = idle_usage
if $Sprite.animation == "open": if $Sprite.animation == "open":
# Disable collider
collision_layer = 16
collision_mask = 16
emit_signal("changed", true)
# Start timer for auto-close # Start timer for auto-close
$Timer.start() $Timer.start()
if $Sprite.animation == "open":
# Disable collider
collision_layer &= ~1
collision_mask &= ~1
emit_signal("changed", true)
else: else:
# Enable collider # Enable collider
collision_mask = 1 collision_mask |= 1
collision_layer = 1 collision_layer |= 1
emit_signal("changed", false) emit_signal("changed", false)
func _input_event(_viewport, event, _shape_idx): func _input_event(_viewport, event, _shape_idx):
@ -52,7 +69,23 @@ func _input_event(_viewport, event, _shape_idx):
if event is InputEventMouseButton and event.pressed: if event is InputEventMouseButton and event.pressed:
# Must be in activation range # Must be in activation range
if activationRange.in_range(): if activationRange.in_range():
set_open($Sprite.animation == "close") rpc("set_open", $Sprite.animation == "close")
func _close_timer_triggered(): master func _close_timer_triggered():
$Sprite.play("close") rpc("set_open", false)
func serialize():
return {}
func deserialize(_data):
pass
func inspect():
return {
"type": "Airlock",
"description": "Allows you to move between rooms while keeping rooms air-tight sealed",
"interaction": "Click when close to manually open/close"
}
func _open_sensor_triggered():
rpc("set_open", true)

View file

@ -1,4 +1,4 @@
[gd_scene load_steps=13 format=2] [gd_scene load_steps=14 format=2]
[ext_resource path="res://Actors/Objects/Door/Door.gd" type="Script" id=1] [ext_resource path="res://Actors/Objects/Door/Door.gd" type="Script" id=1]
[ext_resource path="res://Graphics/tgstation/opening-sheet.png" type="Texture" id=2] [ext_resource path="res://Graphics/tgstation/opening-sheet.png" type="Texture" id=2]
@ -42,10 +42,14 @@ animations = [ {
} ] } ]
[sub_resource type="CircleShape2D" id=8] [sub_resource type="CircleShape2D" id=8]
radius = 64.0 radius = 42.0
[sub_resource type="CircleShape2D" id=9]
radius = 18.0
[node name="Door" type="StaticBody2D"] [node name="Door" type="StaticBody2D"]
input_pickable = true input_pickable = true
collision_layer = 19
script = ExtResource( 1 ) script = ExtResource( 1 )
[node name="CollisionShape2D" type="CollisionShape2D" parent="."] [node name="CollisionShape2D" type="CollisionShape2D" parent="."]
@ -64,15 +68,29 @@ wait_time = 5.0
one_shot = true one_shot = true
[node name="ActivationRange" type="Area2D" parent="."] [node name="ActivationRange" type="Area2D" parent="."]
visible = false input_pickable = false
script = ExtResource( 3 ) script = ExtResource( 3 )
[node name="CollisionShape2D" type="CollisionShape2D" parent="ActivationRange"] [node name="CollisionShape2D" type="CollisionShape2D" parent="ActivationRange"]
visible = false
position = Vector2( 16, 16 ) position = Vector2( 16, 16 )
shape = SubResource( 8 ) shape = SubResource( 8 )
[node name="CloseRange" type="Area2D" parent="."]
input_pickable = false
script = ExtResource( 3 )
[node name="CollisionShape2D" type="CollisionShape2D" parent="CloseRange"]
position = Vector2( 16, 16 )
shape = SubResource( 9 )
[node name="PowerManager" type="Node" parent="."] [node name="PowerManager" type="Node" parent="."]
script = ExtResource( 4 ) script = ExtResource( 4 )
power_usage = 2.0 power_usage = 2.0
[node name="AudioStreamPlayer2D" type="AudioStreamPlayer2D" parent="."]
max_distance = 512.0
attenuation = 3.0
[connection signal="animation_finished" from="Sprite" to="." method="_animation_finished"] [connection signal="animation_finished" from="Sprite" to="." method="_animation_finished"]
[connection signal="timeout" from="Timer" to="." method="_close_timer_triggered"] [connection signal="timeout" from="Timer" to="." method="_close_timer_triggered"]
[connection signal="player_entered" from="CloseRange" to="." method="_open_sensor_triggered"]

View file

@ -62,3 +62,23 @@ func refresh_sprite() -> void:
socket.material.set_shader_param("cable_color", sink_color) socket.material.set_shader_param("cable_color", sink_color)
Flow.BIDIRECTIONAL: Flow.BIDIRECTIONAL:
socket.material.set_shader_param("cable_color", bidirectional_color) socket.material.set_shader_param("cable_color", bidirectional_color)
func serialize():
var connection_paths = []
for conn in connections:
connection_paths.append({ "path": get_path_to(conn), "powered": conn.powered })
return {
"direction": direction,
"flow": flow,
"connections": connection_paths
}
func deserialize(data):
set_direction(data["direction"])
set_flow(data["flow"])
for node in data["connections"]:
var manager = get_node(node.path) as PowerManager
manager.socket = self
manager.powered = node.powered
connections.append(manager)

View file

@ -14,13 +14,13 @@ void fragment() {
if (col.r/col.g > 2.) { if (col.r/col.g > 2.) {
if (length(cable_color) == 0.) { if (length(cable_color) == 0.) {
if (UV.y > 0.6 && UV.y < 0.85) { if (UV.y > 0.6 && UV.y < 0.85) {
if (int(UV.x * 200.) % 12 > 4) { if (mod(UV.x * 200., 12.) > 4.) {
col.rgb = vec3(0.94, 0.08, 0.08) * length(col.rgb); col.rgb = vec3(0.94, 0.08, 0.08) * length(col.rgb);
} else { } else {
col.rgb = vec3(0.04, 0.58, 0.98) * length(col.rgb); col.rgb = vec3(0.04, 0.58, 0.98) * length(col.rgb);
} }
} else { } else {
if (int(UV.y * 200.) % 12 > 4) { if (mod(UV.y * 200., 12.) > 4.) {
col.rgb = vec3(0.94, 0.08, 0.08) * length(col.rgb); col.rgb = vec3(0.94, 0.08, 0.08) * length(col.rgb);
} else { } else {
col.rgb = vec3(0.04, 0.58, 0.98) * length(col.rgb); col.rgb = vec3(0.04, 0.58, 0.98) * length(col.rgb);
@ -32,32 +32,28 @@ void fragment() {
} }
COLOR = col; COLOR = col;
}" }"
custom_defines = ""
[sub_resource type="ShaderMaterial" id=2] [sub_resource type="ShaderMaterial" id=2]
shader = SubResource( 1 ) shader = SubResource( 1 )
shader_param/cable_color = Color( 0, 0, 0, 0 ) shader_param/cable_color = Color( 0.0901961, 0.533333, 0.960784, 1 )
[sub_resource type="CircleShape2D" id=3] [sub_resource type="CircleShape2D" id=3]
radius = 12.0 radius = 12.0
[node name="ElectricSocket" type="Area2D"] [node name="ElectricSocket" type="Area2D"]
z_index = -8
collision_layer = 4 collision_layer = 4
collision_mask = 2147483652 collision_mask = 2147483652
script = ExtResource( 2 ) script = ExtResource( 2 )
direction = 2
source_color = Color( 0.937255, 0.0823529, 0.0823529, 1 ) source_color = Color( 0.937255, 0.0823529, 0.0823529, 1 )
sink_color = Color( 0.0901961, 0.533333, 0.960784, 1 ) sink_color = Color( 0.0901961, 0.533333, 0.960784, 1 )
bidirectional_color = Color( 0, 0, 0, 0 ) bidirectional_color = Color( 0, 0, 0, 0 )
flow = 2
[node name="socket" type="Sprite" parent="."] [node name="socket" type="Sprite" parent="."]
material = SubResource( 2 ) material = SubResource( 2 )
texture = ExtResource( 1 ) texture = ExtResource( 1 )
centered = false centered = false
region_enabled = true region_enabled = true
region_rect = Rect2( 32, 0, 32, 32 ) region_rect = Rect2( 0, 0, 32, 32 )
[node name="CollisionShape2D" type="CollisionShape2D" parent="."] [node name="CollisionShape2D" type="CollisionShape2D" parent="."]
position = Vector2( 16, 16 ) position = Vector2( 16, 16 )

View file

@ -7,28 +7,34 @@ class_name GameObjectEngine
const LIGHT_STRENGTH_MULT = 0.002 const LIGHT_STRENGTH_MULT = 0.002
const MAX_ENERGY = 2 const MAX_ENERGY = 2
const MAX_USAGE = 0.5
enum Direction { LEFT, RIGHT, UP, DOWN } enum Direction { LEFT, RIGHT, UP, DOWN }
export(Direction) var direction = Direction.DOWN setget set_direction export(Direction) var direction = Direction.DOWN setget set_direction
onready var activationRange = $ActivationRange as ActivationRange onready var activationRange = $ActivationRange as ActivationRange
onready var manager = $PowerManager as PowerManager
export var strength = 1.0 setget set_strength export var strength = 1.0 setget set_strength
export var max_force = 0.05
func _ready(): var force = 0
func _ready() -> void:
if not Engine.editor_hint: if not Engine.editor_hint:
activationRange.visible = true activationRange.visible = true
$Light2D.visible = true
func set_direction(dir): func set_direction(dir) -> void:
direction = dir direction = dir
refresh_sprite() refresh_sprite()
func set_strength(val): func set_strength(val: float) -> void:
strength = val strength = val
$Light2D.energy = val * LIGHT_STRENGTH_MULT $Light2D.energy = val * LIGHT_STRENGTH_MULT
func refresh_sprite(): func refresh_sprite() -> void:
var rot = 0 var rot = 0
match direction: match direction:
Direction.DOWN: Direction.DOWN:
@ -46,6 +52,10 @@ func refresh_sprite():
$Light2D.rotation = rot $Light2D.rotation = rot
$ActivationRange.rotation = rot $ActivationRange.rotation = rot
func _physics_process(_delta: float) -> void:
if Engine.editor_hint:
return
manager.power_usage = max(1e-3, MAX_USAGE * strength)
func _input_event(_viewport, event, _shape_idx): func _input_event(_viewport, event, _shape_idx):
if Engine.editor_hint: if Engine.editor_hint:
@ -54,3 +64,21 @@ func _input_event(_viewport, event, _shape_idx):
if activationRange.in_range(): if activationRange.in_range():
# TODO # TODO
pass pass
func serialize():
return {
"direction": direction,
"strength": strength
}
func deserialize(data):
set_direction(data["direction"])
set_strength(data["strength"])
func _power_status_changed(powered):
if powered:
force = max_force
$Light2D.enabled = true
else:
force = 0
$Light2D.enabled = false

View file

@ -1,9 +1,10 @@
[gd_scene load_steps=7 format=2] [gd_scene load_steps=8 format=2]
[ext_resource path="res://Actors/Components/ActivationRange.gd" type="Script" id=1] [ext_resource path="res://Actors/Components/ActivationRange.gd" type="Script" id=1]
[ext_resource path="res://Actors/Objects/Engine/Engine.gd" type="Script" id=2] [ext_resource path="res://Actors/Objects/Engine/Engine.gd" type="Script" id=2]
[ext_resource path="res://Graphics/tgstation/engine-big.png" type="Texture" id=3] [ext_resource path="res://Graphics/tgstation/engine-big.png" type="Texture" id=3]
[ext_resource path="res://Graphics/light_shadow_light.png" type="Texture" id=4] [ext_resource path="res://Graphics/light_shadow_light.png" type="Texture" id=4]
[ext_resource path="res://Actors/Components/PowerManager.gd" type="Script" id=5]
[sub_resource type="RectangleShape2D" id=1] [sub_resource type="RectangleShape2D" id=1]
extents = Vector2( 48, 48 ) extents = Vector2( 48, 48 )
@ -25,6 +26,7 @@ region_enabled = true
region_rect = Rect2( 0, 0, 96, 96 ) region_rect = Rect2( 0, 0, 96, 96 )
[node name="Light2D" type="Light2D" parent="."] [node name="Light2D" type="Light2D" parent="."]
visible = false
position = Vector2( 48, 48 ) position = Vector2( 48, 48 )
texture = ExtResource( 4 ) texture = ExtResource( 4 )
offset = Vector2( 0, 50 ) offset = Vector2( 0, 50 )
@ -33,8 +35,15 @@ energy = 0.002
[node name="ActivationRange" type="Area2D" parent="."] [node name="ActivationRange" type="Area2D" parent="."]
visible = false visible = false
input_pickable = false
script = ExtResource( 1 ) script = ExtResource( 1 )
[node name="CollisionShape2D" type="CollisionShape2D" parent="ActivationRange"] [node name="CollisionShape2D" type="CollisionShape2D" parent="ActivationRange"]
position = Vector2( 48, 56 ) position = Vector2( 48, 56 )
shape = SubResource( 2 ) shape = SubResource( 2 )
[node name="PowerManager" type="Node" parent="."]
script = ExtResource( 5 )
power_usage = 1.0
[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

@ -17,11 +17,11 @@ func _ready():
activationRange.visible = true activationRange.visible = true
refresh_sprite() refresh_sprite()
func set_direction(dir): remotesync func set_direction(dir):
direction = dir direction = dir
refresh_sprite() refresh_sprite()
func set_lit(val): remotesync func set_lit(val):
lit = val lit = val
update_light() update_light()
refresh_sprite() refresh_sprite()
@ -48,13 +48,12 @@ func refresh_sprite():
$Light2D.rotation = rot $Light2D.rotation = rot
$ActivationRange.rotation = rot $ActivationRange.rotation = rot
func _input_event(_viewport, event, _shape_idx): func _input_event(_viewport, event, _shape_idx):
if Engine.editor_hint: if Engine.editor_hint:
return return
if event is InputEventMouseButton and event.pressed: if event is InputEventMouseButton and event.pressed:
if activationRange.in_range(): if activationRange.in_range():
set_lit(!lit) rpc("set_lit", !lit)
func _power_status_changed(_powered: bool) -> void: func _power_status_changed(_powered: bool) -> void:
update_light() update_light()
@ -62,3 +61,13 @@ func _power_status_changed(_powered: bool) -> void:
func update_light(): func update_light():
$Light2D.enabled = lit and (manager != null and manager.powered) $Light2D.enabled = lit and (manager != null and manager.powered)
func serialize():
return {
"direction": direction,
"lit": lit
}
func deserialize(data):
set_direction(data["direction"])
set_lit(data["lit"])

View file

@ -38,6 +38,7 @@ __meta__ = {
[node name="ActivationRange" type="Area2D" parent="."] [node name="ActivationRange" type="Area2D" parent="."]
visible = false visible = false
input_pickable = false
script = ExtResource( 4 ) script = ExtResource( 4 )
[node name="CollisionShape2D" type="CollisionShape2D" parent="ActivationRange"] [node name="CollisionShape2D" type="CollisionShape2D" parent="ActivationRange"]

View file

@ -2,7 +2,7 @@ extends StaticBody2D
class_name GameObjectPowerStorage class_name GameObjectPowerStorage
const MAX_CHARGE = 100000.0 const MAX_CHARGE = 5e5
var open = false var open = false
var attached = true var attached = true
@ -11,25 +11,41 @@ onready var manager = $PowerManager as PowerManager
export var current_charge = MAX_CHARGE setget set_charge export var current_charge = MAX_CHARGE setget set_charge
export var max_charge_rate = 0 setget set_max_charge export var max_charge_rate = 0 setget set_max_charge
export var max_discharge_rate = 200 setget set_max_discharge export var max_discharge_rate = 2000 setget set_max_discharge
var next_network_update = Multiplayer.SYSTEMS_UPDATE_INTERVAL
func _ready() -> void: func _ready() -> void:
if not Engine.editor_hint: if not Engine.editor_hint:
activationRange.visible = true activationRange.visible = true
$Control/PowerUI.set_current_charge(current_charge) $Control/PowerUI.set_current_charge(current_charge)
$Control/PowerUI.set_max_charge(MAX_CHARGE) $Control/PowerUI.set_max_charge(MAX_CHARGE)
$Control/PowerUI.init_values(max_charge_rate, max_discharge_rate)
set_max_charge(max_charge_rate) set_max_charge(max_charge_rate)
func _physics_process(delta: float) -> void: func _physics_process(delta: float) -> void:
if not is_network_master():
return
next_network_update -= 1
if next_network_update < 0:
next_network_update = Multiplayer.SYSTEMS_UPDATE_INTERVAL
if manager.wired: if manager.wired:
if current_charge > 0: if current_charge > 0:
manager.power_source = min(current_charge, max_discharge_rate) manager.power_source = min(current_charge, max_discharge_rate)
if manager.power_load > 0: if manager.power_load > 0:
set_charge(current_charge - manager.power_load * delta) var new_charge = current_charge - manager.power_load * delta
if next_network_update == 0:
rpc("set_charge", new_charge)
else:
set_charge(new_charge)
if PowerNetwork.DEBUG: if PowerNetwork.DEBUG:
update() update()
if manager.powered: if manager.powered:
set_charge(current_charge + max_charge_rate * delta) var new_charge = current_charge + max_charge_rate * delta
if next_network_update == 0:
rpc("set_charge", new_charge)
else:
set_charge(new_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:
@ -69,14 +85,26 @@ func _draw():
charge_color = Color.red charge_color = Color.red
draw_rect(Rect2(32, 32-charge_px, 4, charge_px), charge_color) draw_rect(Rect2(32, 32-charge_px, 4, charge_px), charge_color)
func set_max_discharge(val: float) -> void: remotesync func set_max_discharge(val: float) -> void:
max_discharge_rate = val max_discharge_rate = val
func set_max_charge(val: float) -> void: remotesync func set_max_charge(val: float) -> void:
max_charge_rate = val max_charge_rate = val
if manager != null: if manager != null:
manager.power_usage = val manager.power_usage = val
func set_charge(val: float) -> void: remotesync func set_charge(val: float) -> void:
current_charge = val current_charge = val
$Control/PowerUI.set_current_charge(current_charge) $Control/PowerUI.set_current_charge(current_charge)
func serialize():
return {
"current_charge": current_charge,
"max_charge_rate": max_charge_rate,
"max_discharge_rate": max_discharge_rate
}
func deserialize(data):
set_charge(data["current_charge"])
set_max_charge(data["max_charge_rate"])
set_max_discharge(data["max_discharge_rate"])

View file

@ -97,6 +97,7 @@ rect_scale = Vector2( 0.5, 0.5 )
[node name="ActivationRange" type="Area2D" parent="."] [node name="ActivationRange" type="Area2D" parent="."]
visible = false visible = false
position = Vector2( 16, 16 ) position = Vector2( 16, 16 )
input_pickable = false
script = ExtResource( 3 ) script = ExtResource( 3 )
[node name="CollisionShape2D" type="CollisionShape2D" parent="ActivationRange"] [node name="CollisionShape2D" type="CollisionShape2D" parent="ActivationRange"]

View file

@ -2,9 +2,13 @@ extends Control
onready var scene = $"/root/scene" as GameInstance onready var scene = $"/root/scene" as GameInstance
func set_current_charge(val): func set_current_charge(val: float):
$Container/CurrentBox/HBoxContainer/CurrentChargeLabel.text = "(" + str(round(val/10)/100) + "kJ)" $Container/CurrentBox/HBoxContainer/CurrentChargeLabel.text = "(%.2fMJ)" % (val / 1000.0)
$Container/CurrentBox/ProgressBar.value = val $Container/CurrentBox/ProgressBar.value = val
func set_max_charge(val: float): func set_max_charge(val: float):
$Container/CurrentBox/ProgressBar.max_value = val $Container/CurrentBox/ProgressBar.max_value = val
func init_values(max_charge: float, max_discharge: float):
$Container/ChargeBox/SpinBox.value = int(max_charge)
$Container/ChargeBox/SpinBox2.value = int(max_discharge)

View file

@ -129,7 +129,7 @@ margin_bottom = 28.0
mouse_filter = 1 mouse_filter = 1
theme = ExtResource( 3 ) theme = ExtResource( 3 )
max_value = 200.0 max_value = 200.0
suffix = "W" suffix = "kW"
[node name="Discharge" type="Label" parent="Container/ChargeBox"] [node name="Discharge" type="Label" parent="Container/ChargeBox"]
material = ExtResource( 4 ) material = ExtResource( 4 )
@ -148,6 +148,6 @@ margin_right = 186.0
margin_bottom = 60.0 margin_bottom = 60.0
mouse_filter = 1 mouse_filter = 1
theme = ExtResource( 3 ) theme = ExtResource( 3 )
max_value = 200.0 max_value = 2000.0
value = 200.0 value = 200.0
suffix = "W" suffix = "kW"

View file

@ -2,3 +2,8 @@ extends StaticBody2D
class_name GameObjectScanner class_name GameObjectScanner
func serialize():
return {}
func deserialize(_data):
pass

View file

@ -0,0 +1,5 @@
extends Node2D
const MAX_HEALTH = 100.0
var health = MAX_HEALTH

View file

@ -5,15 +5,22 @@ const EPSILON = 0.1
const MAX_STAMINA = 3.0 const MAX_STAMINA = 3.0
const BOOST_COEFF = 50.0 const BOOST_COEFF = 50.0
const STAMINA_RECOVER_RATE = 0.3 const STAMINA_RECOVER_RATE = 0.3
const NET_KEY_TRANSFORM_DELAY = 0.2
var velocity = Vector2.ZERO var velocity = Vector2.ZERO
var grip = 1.0 var grip = 1.0
var stamina = MAX_STAMINA var stamina = MAX_STAMINA
var speed_boost = 0 var speed_boost = 0
var transform_update_remaining = 0.0
puppet var pup_motion = Vector2.ZERO
puppet var pup_velocity = Vector2.ZERO
puppet var pup_transform = Transform()
onready var scene = $"/root/scene" onready var scene = $"/root/scene"
onready var world = $"/root/scene/world" onready var world = $"/root/scene/world"
onready var camera = $Camera onready var camera = $Camera
onready var netgame = $"/root/Multiplayer"
export var is_controlled = false setget set_is_controlled export var is_controlled = false setget set_is_controlled
@ -21,15 +28,16 @@ func _ready():
$Camera.current = is_controlled $Camera.current = is_controlled
func _physics_process(delta): func _physics_process(delta):
var motion = Vector2( var motion = Vector2.ZERO
if is_network_master():
if not scene.writing:
motion = Vector2(
Input.get_action_strength("ui_right")-Input.get_action_strength("ui_left"), Input.get_action_strength("ui_right")-Input.get_action_strength("ui_left"),
Input.get_action_strength("ui_down")-Input.get_action_strength("ui_up")) Input.get_action_strength("ui_down")-Input.get_action_strength("ui_up"))
if motion.length() > EPSILON:
$Sprite/AnimationTree.set("parameters/direction/blend_position", motion)
# Check sprinting # Check sprinting
var speed = BASE_SPEED var speed = BASE_SPEED
if Input.is_action_pressed("sprint"): if Input.is_action_pressed("sprint") and not scene.writing:
if motion.length() > EPSILON and stamina > 0: if motion.length() > EPSILON and stamina > 0:
speed_boost += BOOST_COEFF * delta * ease(stamina/MAX_STAMINA, 1.1) speed_boost += BOOST_COEFF * delta * ease(stamina/MAX_STAMINA, 1.1)
stamina -= delta stamina -= delta
@ -48,6 +56,21 @@ func _physics_process(delta):
# Set velocity # Set velocity
velocity = velocity * (1.0-grip) + motion.clamped(1.0) * speed * grip velocity = velocity * (1.0-grip) + motion.clamped(1.0) * speed * grip
rset("pup_motion", motion)
rset("pup_velocity", velocity)
rset("pup_transform", global_transform)
else:
velocity = pup_velocity
motion = pup_motion
if transform_update_remaining <= 0.0:
transform_update_remaining = NET_KEY_TRANSFORM_DELAY
global_transform = pup_transform
else:
transform_update_remaining -= delta
if motion.length() > EPSILON:
$Sprite/AnimationTree.set("parameters/direction/blend_position", motion)
velocity = move_and_slide(velocity) velocity = move_and_slide(velocity)
# Check what tile I'm on # Check what tile I'm on
@ -63,6 +86,7 @@ func set_is_controlled(val):
$Camera.current = val $Camera.current = val
func _draw(): func _draw():
if is_network_master():
if stamina+EPSILON < MAX_STAMINA: if stamina+EPSILON < MAX_STAMINA:
draw_circle_arc_poly(Vector2(-10, -30), 6, 0, stamina/MAX_STAMINA * 360, Color.orange) draw_circle_arc_poly(Vector2(-10, -30), 6, 0, stamina/MAX_STAMINA * 360, Color.orange)
@ -76,3 +100,6 @@ func draw_circle_arc_poly(center, radius, angle_from, angle_to, color):
var angle_point = deg2rad(angle_from + i * (angle_to - angle_from) / nb_points - 90) var angle_point = deg2rad(angle_from + i * (angle_to - angle_from) / nb_points - 90)
points_arc.push_back(center + Vector2(cos(angle_point), sin(angle_point)) * radius) points_arc.push_back(center + Vector2(cos(angle_point), sin(angle_point)) * radius)
draw_polygon(points_arc, colors) draw_polygon(points_arc, colors)
func get_info():
return netgame.player_info[get_network_master()]

View file

@ -1,14 +1,19 @@
[gd_scene load_steps=4 format=2] [gd_scene load_steps=6 format=2]
[ext_resource path="res://Graphics/tgstation/sprites/Player.tscn" type="PackedScene" id=1] [ext_resource path="res://Graphics/tgstation/sprites/Player.tscn" type="PackedScene" id=1]
[ext_resource path="res://Actors/Player/Player.gd" type="Script" id=2] [ext_resource path="res://Actors/Player/Player.gd" type="Script" id=2]
[ext_resource path="res://Actors/Player/BodyPart.gd" type="Script" id=3]
[sub_resource type="CapsuleShape2D" id=1] [sub_resource type="CapsuleShape2D" id=1]
radius = 10.4436 radius = 10.4436
height = 5.44386 height = 5.44386
[sub_resource type="RectangleShape2D" id=2]
extents = Vector2( 32, 32 )
[node name="Player" type="KinematicBody2D"] [node name="Player" type="KinematicBody2D"]
z_index = 10 z_index = 10
collision_layer = 8
script = ExtResource( 2 ) script = ExtResource( 2 )
[node name="Camera" type="Camera2D" parent="."] [node name="Camera" type="Camera2D" parent="."]
@ -18,3 +23,31 @@ position = Vector2( 0, -3 )
[node name="CollisionShape2D" type="CollisionShape2D" parent="."] [node name="CollisionShape2D" type="CollisionShape2D" parent="."]
shape = SubResource( 1 ) shape = SubResource( 1 )
[node name="Earing" type="Area2D" parent="."]
input_pickable = false
collision_layer = 32
collision_mask = 32
[node name="CollisionShape2D" type="CollisionShape2D" parent="Earing"]
shape = SubResource( 2 )
[node name="BodyParts" type="Node2D" parent="."]
[node name="Head" type="Node2D" parent="BodyParts"]
script = ExtResource( 3 )
[node name="Torso" type="Node2D" parent="BodyParts"]
script = ExtResource( 3 )
[node name="LeftArm" type="Node2D" parent="BodyParts"]
script = ExtResource( 3 )
[node name="RightArm" type="Node2D" parent="BodyParts"]
script = ExtResource( 3 )
[node name="LeftLeg" type="Node2D" parent="BodyParts"]
script = ExtResource( 3 )
[node name="RightLeg" type="Node2D" parent="BodyParts"]
script = ExtResource( 3 )

View file

@ -0,0 +1,136 @@
tool
extends Node2D
class_name ProbeArea
export(String) var area_name
export(NodePath) var wall_tilemap
export(NodePath) var base_tilemap
var debug_font = preload("res://Graphics/UI/uifont.tres")
const AREA_LAYER_ID = 16
onready var walls = get_node(wall_tilemap) as TileMap
onready var base = get_node(base_tilemap) as TileMap
onready var physics = get_world_2d().direct_space_state
onready var map = walls.get_parent() as GameMap
const TILE_SIZE = 32
var cells = {}
var bounds = {}
func _ready():
scout()
update()
func scout():
# Reset lists
cells = {}
bounds = {}
# Get origin and immediate neighbour of probe
var origin = Vector2(floor(position.x / TILE_SIZE), floor(position.y / TILE_SIZE))
cells[origin] = true
var queue = get_neighbours(origin)
# Use children probes for extra areas
for child in get_children():
var child_origin = Vector2(floor((position.x + child.position.x) / TILE_SIZE), floor((position.y + child.position.y) / TILE_SIZE))
cells[child_origin] = true
for neighbour in get_neighbours(child_origin):
queue.push_front(neighbour)
# Depth-first search
while not queue.empty():
var current = queue.pop_front()
# Have we checked this already?
if not is_valid(current):
continue
var wall_tile = walls.get_cellv(current)
if wall_tile == -1:
var objects = physics.intersect_point(current * TILE_SIZE + Vector2.ONE * TILE_SIZE / 2.0, 1, [], AREA_LAYER_ID)
if objects.size() > 0:
bounds[current] = true
else:
cells[current] = true
for neighbour in get_neighbours(current):
queue.push_front(neighbour)
else:
bounds[current] = true
# Join walls
var joined = []
for cell in bounds:
var sides = [
[Vector2(cell.x, cell.y-1),Vector2(cell.x, cell.y+1)],
[Vector2(cell.x-1, cell.y),Vector2(cell.x+1, cell.y)],
]
for side_pair in sides:
if cells.has(side_pair[0]) and cells.has(side_pair[1]):
# This bound is joined at one side, make it a cell and not a bound
joined.push_back(cell)
for wall in joined:
bounds.erase(wall)
cells[wall] = true
func is_valid(cell: Vector2) -> bool:
# Have we checked this already?
if cells.has(cell) or bounds.has(cell):
return false
# Is it a valid tile for an area
return base.get_cellv(cell) != -1
func get_neighbours(cell: Vector2) -> Array:
var neighbours = [
Vector2(cell.x-1, cell.y-1), Vector2(cell.x, cell.y-1), Vector2(cell.x+1, cell.y-1),
Vector2(cell.x-1, cell.y), Vector2(cell.x+1, cell.y),
Vector2(cell.x-1, cell.y+1), Vector2(cell.x, cell.y+1), Vector2(cell.x+1, cell.y+1)
]
var out = []
for neighbour in neighbours:
# Have we checked this already?
if not is_valid(neighbour):
continue
out.push_back(neighbour)
return out
func _draw():
if map == null or not map.debug_areas:
return
var origin = Vector2(floor(position.x / TILE_SIZE), floor(position.y / TILE_SIZE))
var draw_origin = origin * TILE_SIZE - position
var rect_size = Vector2.ONE * TILE_SIZE
draw_rect(Rect2(draw_origin, rect_size), Color.red, false, 2)
draw_string(debug_font, Vector2.ZERO, area_name, Color.blue)
for child in get_children():
var child_origin = Vector2(floor(child.position.x / TILE_SIZE), floor(child.position.y / TILE_SIZE))
draw_rect(Rect2(draw_origin + child_origin * TILE_SIZE, rect_size), Color.orange, false, 2)
draw_string(debug_font, child.position, area_name + "/" + child.name, Color.blue)
for wall in bounds:
draw_rect(Rect2(wall * TILE_SIZE - position + Vector2.ONE * (TILE_SIZE / 2.0 - TILE_SIZE / 4.0), rect_size/2.0), Color(0,0.5,1,0.5))
func _area_moved():
scout()
update()
func serialize():
var subareas = {}
for child in get_children():
subareas[child.name] = {
"transform": child.transform
}
return {
"name": area_name,
"wall_path": wall_tilemap,
"base_path": base_tilemap,
"subareas": subareas
}
func deserialize(data):
for subarea in data.subareas:
var node = Node2D.new()
node.name = subarea
node.transform = data.subareas[subarea].transform
add_child(node)
area_name = data.name
wall_tilemap = data.wall_path
base_tilemap = data.base_path

View file

@ -0,0 +1,7 @@
[gd_scene load_steps=2 format=2]
[ext_resource path="res://Actors/Systems/Area/AreaProbe.gd" type="Script" id=1]
[node name="AreaProbe" type="Sprite"]
script = ExtResource( 1 )
[connection signal="item_rect_changed" from="." to="." method="_area_moved"]

View file

@ -8,13 +8,13 @@ var neighbours = []
var network: PowerNetwork = null var network: PowerNetwork = null
func _ready(): master func _ready():
if network == null: if network == null:
network = PowerNetwork.new() network = PowerNetwork.new()
network.add_node(self) network.add_node(self)
$"/root/scene/systems".add_child(network, true) $"/root/scene/systems".add_child(network, true)
func _physics_process(_delta): master func _physics_process(_delta):
if PowerNetwork.DEBUG: if PowerNetwork.DEBUG:
update() update()
@ -25,13 +25,13 @@ func _draw():
var delta = (neighbour.global_position - global_position) / global_scale var delta = (neighbour.global_position - global_position) / global_scale
draw_line(center, delta + center, network.debugColor, 2) draw_line(center, delta + center, network.debugColor, 2)
func _got_neighbour(area: Area2D): master func _got_neighbour(area: Area2D):
if area == self: if area == self:
return return
if area.network == null: if area.network == null:
area.network = network area.network = network
network.add_node(area) network.rpc("add_node", area)
elif area.network != network: elif area.network != network:
# Merge networks # Merge networks
network.join(area.network) network.rpc("join", area.network)
neighbours.push_back(area) neighbours.push_back(area)

View file

@ -14,6 +14,7 @@ a = Vector2( -16, 16 )
b = Vector2( 48, 16 ) b = Vector2( 48, 16 )
[node name="ElProbe" type="Area2D"] [node name="ElProbe" type="Area2D"]
input_pickable = false
collision_layer = 4 collision_layer = 4
collision_mask = 4 collision_mask = 4
script = ExtResource( 1 ) script = ExtResource( 1 )

View file

@ -9,6 +9,7 @@ var sockets = []
var total_source = 0 var total_source = 0
var total_usage = 0 var total_usage = 0
var unpowered = 0
var debugColor = Color.cyan var debugColor = Color.cyan
@ -16,12 +17,12 @@ 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) -> void: remotesync func add_node(node) -> void:
nodes.append(node) nodes.append(node)
if "connections" in node: if "connections" in node:
sockets.append(node) sockets.append(node)
func remove_node(node) -> void: remotesync 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)
@ -31,7 +32,7 @@ func remove_node(node) -> void:
# Do other splitting here # Do other splitting here
node.network = null node.network = null
func join(network) -> void: remotesync 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
@ -42,6 +43,8 @@ func join(network) -> void:
network.queue_free() network.queue_free()
func _physics_process(_delta: float) -> void: func _physics_process(_delta: float) -> void:
if not is_network_master():
return
# Recalculate power availability and usage # Recalculate power availability and usage
total_source = 0 total_source = 0
total_usage = 0 total_usage = 0
@ -65,14 +68,18 @@ func _physics_process(_delta: float) -> void:
sources.append(manager) sources.append(manager)
# Update manager stats # Update manager stats
var available_supply = total_source var available_supply = total_source
unpowered = 0
for sink in sinks: for sink in sinks:
# Check if item can be powered this cycle # Check if item can be powered this cycle
if sink.power_usage > 0: if sink.power_usage > 0:
if available_supply > sink.power_usage: if available_supply > sink.power_usage:
available_supply -= sink.power_usage available_supply -= sink.power_usage
sink.powered = true if not sink.powered:
sink.rpc("set_powered", true)
else: else:
sink.powered = false if sink.powered:
sink.rpc("set_powered", false)
unpowered += 1
# Update available power to sinks # Update available power to sinks
for sink in sinks: for sink in sinks:
sink.available = available_supply sink.available = available_supply
@ -82,3 +89,18 @@ func _physics_process(_delta: float) -> void:
for source in sources: for source in sources:
var source_load = source.power_source / total_source * remaining_drain var source_load = source.power_source / total_source * remaining_drain
source.power_load = source_load source.power_load = source_load
func serialize():
var node_paths = []
var socket_paths = []
for node in nodes:
node_paths.append(get_path_to(node))
for socket in sockets:
socket_paths.append(get_path_to(socket))
return { "nodes": node_paths, "sockets": socket_paths }
func deserialize(data):
for node_path in data["nodes"]:
nodes.append(get_node(node_path))
for socket_path in data["sockets"]:
sockets.append(get_node(socket_path))

22
CREDITS.md Normal file
View file

@ -0,0 +1,22 @@
# Graphics
- Title screen background: [Star Nest by Pablo Roman Andrioli](https://www.shadertoy.com/view/XlfGRj) (MIT)
- All graphics in `Graphics/tgstation` is from [/tg/station](https://github.com/tgstation/tgstation) (CC BY-SA 3.0)
# Music
- Title screen music: [Je suis un Phoenix by BlueMillenium](http://ccmixter.org/files/Bluemillenium/61325) (CC BY-NC 3.0)
# Sound effects
- Door open/close sounds:
- [Hatch Seal.wav by Paul368 (freesound)](https://freesound.org/people/Paul368/sounds/264063/) (CC0 1.0)
- [SFX Door Open.wav by Paul368 (freesound)](https://freesound.org/people/Paul368/sounds/264061/) (CC0 1.0)
- Notification/beeps:
- [Chord Alert Notification by graham_makes (freesound)](https://freesound.org/people/graham_makes/sounds/457518/) (CC BY 3.0)
- [Messenger Notification Sounds by zzwerty (freesound)](https://freesound.org/people/zzwerty/sounds/315878/) (CC BY-NC 3.0)
- [Radio Sign Off by dylanh.sound (freesound)](https://freesound.org/people/dylanh.sound/sounds/524205/) (CC0 1.0)
# Code
- Uses the [GOTM API library](https://github.com/PlayGotm/GDGotm) from Macaroni Studios (MIT)

38
Classes/Coordinates.gd Normal file
View file

@ -0,0 +1,38 @@
class_name Coordinates
static func as_string(coord: Vector2, include_subcoord: bool = false) -> String:
var x = floor(coord.x)
var y = floor(coord.y)
var main = as_string_parts(coord)
var sector_name = main[0] + main[1]
if include_subcoord:
sector_name += ".%02d/%02d" % [(coord.x - x) * 100, (coord.y - y) * 100]
return sector_name
static func as_string_parts(coord: Vector2) -> Array:
var x = floor(coord.x)
var y = floor(coord.y)
var x_str = to_letter(int(x))
var y_str = ""
if y < 0:
y_str = to_letter(int(y))
else:
y_str = str(int(y))
return [x_str, y_str]
static func to_letter(num: int) -> String:
#var letters = "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ"
var letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
if num == 0:
return "Α"
elif num < 0:
letters = "αβγδεζηθικλμνξοπρστυφχψω"
if num < 0:
num = -num
var out = ""
var base = letters.length()
while num > 0:
out = letters.substr(num % base, 1) + out
num /= base
return out

531
Classes/Names.gd Normal file
View file

@ -0,0 +1,531 @@
class_name Names
const first_names = [
"aakash","aamir","aaron","abbas","abby","abdul","abdullah","abe","abel","abhay",
"abhijeet","abhijit","abhilash","abhinav","abhishek","abigail","abraham","abu","ace","ada",
"adam","adarsh","adeel","adel","adi","adil","aditi","aditya","adnan","adolfo",
"adrian","adriana","adriano","adrienne","agnes","agnieszka","ahmad","ahmed","ahmet","ahsan",
"aida","aidan","aileen","aimee","aisha","aj","ajay","ajit","akash","akhil",
"akshay","al","alaa","alain","alan","alana","albert","alberto","aldo","ale",
"alec","alejandra","alejandro","aleksandra","alessandra","alessandro","alex","alexa","alexander","alexandr",
"alexandra","alexandre","alexandria","alexandru","alexey","alexis","alfonso","alfred","alfredo","ali",
"alice","alicia","alina","aline","alireza","alisa","alisha","alison","alissa","alistair",
"allan","allen","allie","allison","ally","allyson","alma","alok","alvaro","alvin",
"alyssa","amal","aman","amanda","amar","amber","amelia","american","ami","amie",
"amin","amina","amine","amir","amit","amol","amos","amr","amy","ana",
"anand","anas","anastasia","anders","anderson","andi","andre","andrea","andreas","andreea",
"andrei","andres","andrew","andrey","andré","andrés","andy","angel","angela","angelica",
"angelina","angelo","angie","angus","anh","ani","anil","anish","anita","anjali",
"ankit","ankita","ankur","ann","anna","anne","annette","annie","anoop","anshul",
"anthony","antoine","antoinette","anton","antonia","antonio","antony","antónio","anu","anuj",
"anup","anurag","anwar","anya","apple","april","archie","ari","ariel","arif",
"arjun","arlene","armand","armando","arnaud","arnold","arpit","arshad","art","artem",
"arthur","artur","arturo","arun","arvind","asad","ash","asha","asher","ashish",
"ashleigh","ashley","ashok","ashraf","ashton","ashutosh","ashwin","asif","asim","astrid",
"athena","atif","atul","aubrey","audrey","augusto","aurora","austin","autumn","ava",
"avery","avi","avinash","axel","ayesha","ayman","ayush","aziz","bailey","bala",
"balaji","barb","barbara","barney","baron","barry","bart","basil","beatrice","beatriz",
"beau","becca","becky","bee","belinda","bella","ben","benedict","benjamin","benny",
"benoit","benson","bernadette","bernard","bernardo","bernie","bert","best","beth","bethany",
"betsy","betty","bev","beverly","bhanu","bharat","bianca","big","bilal","bill",
"billie","billy","bjorn","black","blaine","blair","blake","blanca","blue","bob",
"bobbi","bobbie","bobby","bogdan","bonnie","boris","boyd","brad","bradford","bradley",
"brady","brandi","brandon","brandy","brenda","brendan","brendon","brent","bret","brett",
"brian","brianna","bridget","bright","brigitte","britt","brittany","brittney","brock","brooke",
"bruce","bruno","bryan","bryant","bryce","buck","bud","butch","byron","caio",
"caitlin","cal","caleb","calvin","cam","cameron","camila","camilla","camille","camilo",
"candace","candice","candy","captain","cara","carey","cari","carina","carl","carla",
"carlo","carlos","carlton","carly","carmen","carol","carole","carolina","caroline","carolyn",
"carrie","carson","carter","cary","caryn","casey","cassandra","cassie","catalina","catherine",
"cathy","cecil","cecilia","cedric","celeste","celia","cesar","chad","chaitanya","chan",
"chance","chandan","chandler","chandra","chantal","charity","charlene","charles","charley","charlie",
"charlotte","charmaine","chas","chase","chaz","chelsea","chen","cheri","cherie","cherry",
"cheryl","chester","chet","chetan","chi","chiara","chip","chirag","chloe","chris",
"chrissy","christa","christi","christian","christie","christina","christine","christoph","christophe","christopher",
"christy","chuck","cindi","cindy","cj","claire","clara","clare","clarence","clark",
"claude","claudia","claudio","clay","clayton","clement","cliff","clifford","clifton","clint",
"clinton","clive","clyde","cody","cole","colette","colin","colleen","collin","collins",
"connie","connor","conor","conrad","constance","cora","corey","corinne","cory","courtney",
"craig","cris","cristian","cristiano","cristina","crystal","curt","curtis","cyndi","cynthia",
"cyril","cyrus","césar","daisy","dakota","dale","dalia","dallas","dalton","damian",
"damien","damon","dan","dana","dane","dani","daniel","daniela","daniele","daniella",
"danielle","danilo","danish","danny","dante","daphne","dara","darcy","daren","daria",
"darin","dario","darius","darla","darlene","darrel","darrell","darren","darrin","darryl",
"darshan","darwin","daryl","dave","david","davide","davis","dawn","dean","deanna",
"deb","debbie","debby","debi","deborah","debra","dee","deep","deepa","deepak",
"deirdre","dejan","delia","delores","dena","denis","denise","dennis","denny","derek",
"derrick","desiree","desmond","destiny","devendra","devin","devon","dexter","dheeraj","dhiraj",
"dhruv","diana","diane","dianna","dianne","dick","diego","dilip","dillon","dima",
"dimitri","dimitris","dina","dinesh","dino","diogo","dion","dirk","divya","dmitri",
"dmitriy","dmitry","dolly","dolores","dom","dominic","dominick","dominique","don","donald",
"donna","donnie","donny","donovan","dora","doreen","dorian","doris","dorothy","doug",
"douglas","drake","drew","duane","duke","duncan","dustin","dusty","dwayne","dwight",
"dylan","earl","ed","eddie","eddy","edgar","edith","edmond","edmund","edna",
"edson","eduard","eduardo","edward","edwin","ehsan","eileen","ekaterina","el","elaine",
"eleanor","elena","eleni","eli","elias","elie","elijah","elisa","elisabeth","elise",
"elisha","eliza","elizabeth","ella","elle","ellen","ellie","elliot","elliott","elmer",
"elsa","elsie","elvis","emanuel","emeka","emil","emilia","emilie","emilio","emily",
"emma","emmanuel","enrico","enrique","eric","erica","erich","erick","ericka","erik",
"erika","erin","ernest","ernesto","ernie","errol","erwin","esteban","esther","ethan",
"etienne","eugene","eunice","eva","evan","evans","eve","evelyn","everett","ezra",
"fabian","fabien","fabio","fadi","fahad","faisal","faith","farah","farhan","farid",
"fatima","faye","federico","felicia","felipe","felix","fernanda","fernando","filip","filipe",
"fiona","flavio","flora","florence","florian","floyd","forbes","forrest","fran","frances",
"francesca","francesco","francine","francis","francisco","franco","francois","frank","frankie","franklin",
"franz","fred","freddie","freddy","frederic","frederick","fredrick","fredrik","fritz","gabby",
"gabe","gabriel","gabriela","gabriele","gabriella","gabrielle","gaby","gail","gale","galina",
"ganesh","gareth","garrett","garry","gary","gaurav","gautam","gavin","gayle","gemma",
"gene","genevieve","geo","geoff","geoffrey","george","georges","georgia","georgina","gerald",
"geraldine","gerard","gerardo","geri","german","gerry","gideon","gigi","gil","gilbert",
"gilberto","gilles","gillian","gina","ginger","ginny","gino","gio","giorgi","giorgio",
"giovanni","girish","gisele","giuseppe","gladys","glen","glenda","glenn","gloria","godfrey",
"godwin","gonzalo","gopal","goran","gordon","govind","grace","graeme","graham","grant",
"green","greg","gregg","gregory","greta","gretchen","guido","guilherme","guillaume","guillermo",
"gus","gustavo","gwen","gwendolyn","hadi","hai","hal","haley","hamid","hamza",
"han","hana","hani","hank","hanna","hannah","hans","happy","hardik","hari",
"haris","harish","harley","harold","harriet","harris","harrison","harry","harsh","harsha",
"harvey","hasan","hassan","hayden","hayley","hazel","heath","heather","hector","heidi",
"helen","helena","helene","hemant","henri","henrik","henrique","henry","herb","herbert",
"herman","hilary","hillary","himanshu","hitesh","hoang","holly","hong","hope","howard",
"hubert","hugh","hugo","humberto","hung","hunter","hussain","hussein","huy","héctor",
"iain","ian","ibrahim","ida","ignacio","igor","ike","ilona","ilya","iman",
"imran","ina","inga","ingrid","inna","ioana","ira","irena","irene","irfan",
"irina","iris","irma","irving","isaac","isabel","isabella","isabelle","isaiah","ismael",
"ismail","israel","ivan","ivana","ivo","ivy","jack","jacki","jackie","jackson",
"jacky","jaclyn","jacob","jacqueline","jacquelyn","jacques","jacqui","jacquie","jade","jae",
"jai","jaime","jake","jakob","jakub","jamal","james","jami","jamie","jamil",
"jan","jana","jane","janelle","janet","janette","janice","janie","janine","janis",
"jared","jarrett","jarrod","jasmin","jasmine","jason","jasper","jatin","javier","jay",
"jayne","jayson","jc","jd","jean","jeanette","jeanie","jeanine","jeanne","jeannette",
"jeannie","jed","jeff","jefferson","jeffery","jeffrey","jelena","jen","jenifer","jenn",
"jenna","jenni","jennie","jennifer","jenny","jens","jeremiah","jeremy","jeri","jeroen",
"jerome","jerry","jesper","jess","jesse","jessica","jessie","jesus","jhon","jill",
"jillian","jim","jimmie","jimmy","jin","jing","jitendra","jo","joan","joana",
"joann","joanna","joanne","joao","joaquin","jocelyn","jodi","jodie","jody","joe",
"joel","joelle","joey","johan","johann","johanna","john","johnathan","johnnie","johnny",
"johnson","jojo","jon","jonah","jonas","jonathan","jonathon","joni","jonny","jordan",
"jordi","jorge","jose","josef","joseph","josephine","josh","joshua","josie","josue",
"josé","joy","joyce","joão","jp","jr","juan","juanita","jude","judi",
"judith","judy","jules","julia","julian","juliana","julie","julien","juliet","julio",
"julius","jun","junaid","june","junior","just","justin","justine","jyoti","kai",
"kaitlyn","kamal","kamil","kamran","kapil","kara","karan","kareem","karen","kari",
"karim","karin","karina","karl","karla","karolina","karthik","kartik","karyn","kasey",
"kashif","kasia","kat","katarina","kate","katelyn","katerina","katharine","katherine","kathi",
"kathie","kathleen","kathryn","kathy","katia","katie","katrina","katy","katya","kaushik",
"kay","kayla","kc","keisha","keith","kelley","kelli","kellie","kelly","kelsey",
"kelvin","ken","kendall","kendra","kennedy","kenneth","kenny","kent","keri","kerri",
"kerry","ketan","kevin","khaled","khalid","kieran","kim","kimberley","kimberly","king",
"kingsley","kira","kiran","kirk","kirsten","kishore","kit","kitty","klaus","kofi",
"konstantin","kris","krishna","krista","kristen","kristi","kristian","kristie","kristin","kristina",
"kristine","kristy","krystal","krzysztof","kumar","kunal","kurt","kwame","kyle","kylie",
"la","lacey","lady","lakshmi","lalit","lana","lance","lane","lara","larissa",
"larry","lars","laura","laurel","lauren","laurence","laurent","lauri","laurie","lawrence",
"le","lea","leah","leandro","leanne","lee","lei","leigh","leila","leland",
"len","lena","lenny","leo","leon","leonard","leonardo","leroy","lesley","leslie",
"lester","leticia","levi","lewis","lex","li","lia","liam","libby","lidia",
"lilian","liliana","lillian","lilly","lily","lim","lin","lina","lincoln","linda",
"lindsay","lindsey","linh","lionel","lisa","lise","little","liz","liza","lizzie",
"lloyd","logan","lois","lokesh","lola","long","lonnie","lora","lord","loren",
"lorena","lorenzo","loretta","lori","lorna","lorraine","lou","louie","louis","louisa",
"louise","lourdes","love","lowell","lu","luc","luca","lucas","lucia","luciana",
"luciano","lucky","lucy","luigi","luis","luisa","luiz","lukas","luke","luz",
"luís","lydia","lyle","lyn","lynda","lynette","lynn","lynne","ma","mac",
"mack","madeline","madhav","madison","magda","magdalena","maggie","magnus","mahendra","mahesh",
"mahmoud","mai","maja","malcolm","malik","mallory","mandy","mani","manish","manisha",
"manny","manoj","manu","manuel","manuela","mara","marc","marcel","marcela","marcelo",
"marci","marcia","marcie","marcin","marcio","marco","marcos","marcus","marcy","marek",
"margaret","margarita","margie","margo","mari","maria","mariah","mariam","marian","mariana",
"marianna","marianne","mariano","marie","marilyn","marina","mario","marion","marisa","marisol",
"marissa","maritza","marius","marjorie","mark","marko","markus","marla","marlene","marlon",
"marsha","marshall","marta","martha","marti","martin","martina","marty","marvin","mary",
"maryam","maryann","maría","mason","massimo","mat","matheus","mathew","mathieu","matt",
"matteo","matthew","matthias","maura","maureen","maurice","mauricio","mauro","max","maxim",
"maxine","maxwell","may","maya","mayank","mayra","mayur","md","md.","meagan",
"meg","megan","megha","meghan","mehdi","mehmet","mehul","mel","melanie","melinda",
"melissa","melody","melvin","mercedes","meredith","mia","micah","michael","michaela","michal",
"micheal","michel","michele","michelle","mick","mickey","miguel","mihaela","mihai","mikael",
"mike","mikey","mikhail","miki","mila","milan","milena","miles","millie","milos",
"milton","mimi","min","mina","mindy","ming","minh","mir","mira","miranda",
"miriam","miss","missy","mister","misty","mitch","mitchell","mj","mo","moe",
"mohamad","mohamed","mohammad","mohammed","mohan","mohd","mohit","mohsin","moises","molly",
"mona","monica","monika","monique","morgan","morris","morten","moses","moshe","mostafa",
"muhammad","muhammed","mukesh","murali","murat","murray","musa","mustafa","mustapha","my",
"myles","myra","myron","nabil","nadeem","nadia","nadine","nana","nancy","naomi",
"narendra","naresh","nasir","nat","natalia","natalie","natasha","nate","nathalie","nathan",
"nathaniel","naveed","naveen","navin","neal","ned","neeraj","neha","neil","nelly",
"nelson","neo","nestor","new","ng","nguyen","nic","nicholas","nichole","nick",
"nicki","nicky","nico","nicola","nicolas","nicole","nidhi","niels","nigel","nik",
"nikhil","niki","nikita","nikki","nikola","nikolay","nikos","nilesh","nina","nino",
"niraj","nirmal","nisha","nishant","nita","nitesh","nitin","noah","noel","noelle",
"nolan","noor","nora","norm","norma","norman","not","nuno","nur","oksana",
"ola","old","oleg","olga","oliver","olivia","olivier","omar","omer","orlando",
"osama","oscar","osman","osvaldo","otto","owen","pablo","paco","paige","pam",
"pamela","pankaj","paola","paolo","parker","parth","pascal","pastor","pat","patrice",
"patricia","patrick","patsy","patti","patty","paul","paula","paulette","paulina","pauline",
"paulo","pavan","pavel","pawan","pearl","pedro","peggy","penelope","penny","per",
"perry","pete","peter","petr","petra","phil","philip","philippe","phillip","phoebe",
"phoenix","phuong","phyllis","pia","pierre","pieter","piotr","piyush","pj","polly",
"pooja","poonam","pradeep","prakash","pramod","pranav","prasad","prasanna","prashant","prashanth",
"prateek","pratik","praveen","pravin","precious","preeti","prem","preston","prince","princess",
"priscilla","priya","priyanka","puneet","quang","quentin","quinn","rachael","rachel","rachelle",
"radu","rae","rafael","raghu","rahul","rainer","raj","raja","rajan","rajat",
"rajeev","rajendra","rajesh","rajiv","raju","rakesh","ralph","ram","rama","raman",
"ramesh","rami","ramiro","ramon","ramona","rana","randal","randall","randi","randolph",
"randy","ranjeet","raphael","raquel","rashid","rashmi","raul","raven","ravi","ravindra",
"ray","raymond","real","rebecca","rebekah","red","reed","reggie","regina","reginald",
"reid","rekha","renata","renato","rene","renee","rené","reuben","rex","rey",
"reza","rhonda","ria","ric","ricardo","riccardo","rich","richa","richard","richie",
"rick","ricky","rico","riley","rishabh","rishi","rita","ritesh","ritu","rizwan",
"rj","rob","robb","robbie","robby","robert","roberta","roberto","robin","robyn",
"rocco","rochelle","rocio","rocky","rod","roderick","rodger","rodney","rodolfo","rodrigo",
"rogelio","roger","rogerio","rohan","rohit","roland","rolando","rolf","roman","romeo",
"ron","ronald","ronaldo","ronda","roni","ronnie","ronny","rory","rosa","rosanne",
"rosario","rose","rosemarie","rosemary","roshan","rosie","ross","roxana","roxanne","roy",
"royce","ruben","ruby","rudy","rui","ruslan","russ","russell","rusty","ruth",
"ryan","saad","sabina","sabrina","sachin","saeed","sagar","sahil","sai","said",
"saif","sajid","sal","salah","salim","sally","salman","salvador","salvatore","sam",
"samantha","sameer","samer","sami","samir","sammy","samson","samuel","san","sana",
"sandeep","sandi","sandip","sandra","sandro","sandy","sanjay","sanjeev","santhosh","santiago",
"santosh","sara","sarah","sascha","sasha","satish","satya","saul","saurabh","saurav",
"savannah","sayed","scot","scott","sean","sebastian","sebastien","seema","senthil","serena",
"serge","sergei","sergey","sergio","seth","shah","shahid","shahzad","shan","shana",
"shane","shankar","shanna","shannon","shantanu","sharad","shari","sharon","shashank","shashi",
"shaun","shauna","shawn","shawna","shay","sheena","sheila","shelby","sheldon","shelley",
"shelly","sheri","sherif","sherman","sherri","sherrie","sherry","sheryl","shirley","shiv",
"shiva","shivam","shoaib","shruti","shubham","shweta","shyam","sid","siddharth","sidney",
"silver","silvia","simon","simona","simone","siobhan","siva","sky","skyler","smith",
"sneha","sofia","solomon","sonali","sonia","sonja","sonny","sonya","sophia","sophie",
"spencer","sri","sridhar","srikanth","srinivas","sriram","stacey","stacie","stacy","stan",
"stanley","star","stefan","stefanie","stefano","stella","steph","stephan","stephane","stephanie",
"stephen","sterling","steve","steven","stewart","stu","stuart","su","sudhir","sue",
"suman","sumit","sunil","sunny","suraj","suresh","surya","susan","susana","susanna",
"susanne","sushant","sushil","susie","suzan","suzanne","suzi","suzie","suzy","sven",
"svetlana","swapnil","swati","sydney","syed","sylvia","sérgio","tabitha","tam","tamara",
"tamer","tami","tammie","tammy","tan","tania","tanja","tanner","tanya","tara",
"tarek","tariq","tarun","taryn","tasha","tatiana","taylor","tech","ted","teddy",
"tee","tejas","terence","teresa","teri","terrance","terrence","terri","terry","tess",
"tessa","thanh","theo","theodore","theresa","therese","thiago","thierry","thom","thomas",
"tia","tiago","tiffany","tim","timmy","timothy","tin","tina","tj","tobias",
"toby","tod","todd","tom","tomas","tomasz","tommy","toni","tony","tonya",
"tori","tracey","traci","tracie","tracy","tran","travis","trent","trevor","trey",
"tricia","trina","trish","trisha","tristan","troy","trudy","tuan","tushar","tyler",
"tyrone","tyson","uday","uma","umair","umar","umesh","ursula","usman","vadim",
"vaibhav","val","valentina","valeria","valerie","van","vanessa","varun","vaughn","venkat",
"venkatesh","vera","vernon","veronica","veronika","vic","vicente","vicki","vickie","vicky",
"victor","victoria","vijay","vikas","vikram","viktor","vinay","vince","vincent","vineet",
"vinicius","vinny","vinod","vipin","vipul","virginia","vishal","vishnu","vitor","vivek",
"vivian","vlad","vladimir","wade","waleed","walid","wallace","wally","walt","walter",
"wan","wanda","wang","waqas","warren","wayne","wei","wendell","wendy","wes",
"wesley","whitney","wil","will","william","williams","willie","willis","willy","wilma",
"wilson","winnie","winston","wolf","wolfgang","wong","wyatt","xavier","xiao","yan",
"yana","yang","yash","yasir","yasmin","yasser","yi","ying","yogesh","yolanda",
"yong","young","youssef","yu","yulia","yuri","yusuf","yves","yvette","yvonne",
"zac","zach","zachary","zack","zain","zak","zane","zeeshan","zoe"
]
const last_names = [
"aakre","aardema","aas","abdelal","abdool","abe","abela","abington","abney","abramovitz",
"abrantes","acal","aceret","achane","acken","addiego","adkins","aeschliman","afshari","agee",
"agel","airington","akhavan","alampi","alas","albang","albee","alcala","alcine","aldarondo",
"alexakis","alexandre","alfson","aliotta","allegrini","allgire","alosa","alperin","altman","altomari",
"altrogge","alvarracin","alward","aman","amauty","amedro","amigon","amiri","amolsch","amon",
"amoros","amsberry","analla","andalora","andelman","anderst","andras","andreasen","anecelle","angel",
"angelbeck","angeloro","ankrapp","ankrum","ansbro","antillon","antinarelli","antonsen","antony","apker",
"appell","apt","aracena","aragus","arbuthnot","arciniega","ardizzone","ardon","areias","arena",
"arflack","argenziano","argrave","arhart","aristide","arizola","armagost","armbruster","arnoux","arnstein",
"aronhalt","aruizu","asam","asch","asenjo","aspell","asperheim","asselta","assum","astorino",
"astudillo","athayde","atkins","attwood","auld","auman","austria","auxier","auzston","avansino",
"avanzato","avera","aversano","awyie","ayalla","azua","azzopardi","babbin","babikian","bach",
"bachrodt","bacot","badey","badolato","baggesen","baham","bahnsen","bair","baisch","baitg",
"bajdas","bajwa","bakst","balboa","balerio","baltazor","balthrop","banco","banducci","bankowski",
"bann","bannister","banowetz","bansal","bantin","baptiste","bara","baranga","barbaro","barbella",
"barbie","barcus","barden","barentine","barkley","barmer","barner","barnett","barras","barsamian",
"bartholemew","bartles","bartsch","basley","bass","bastain","bathe","batiste","batrum","battani",
"battiato","baudino","baudoin","bauers","baugess","baurer","bayona","bazzle","beagley","bear",
"bears","beatley","beaty","bedeau","beerling","begg","beilinson","beine","beitzel","belasco",
"belich","bellingtier","bellion","belski","benedetti","beneke","benes","benett","bennice","benston",
"benyamin","berardo","berdecia","bergenstock","bergfield","berlinski","bernabe","bernheim","berschauer","bertschy",
"besser","bessire","betcher","bethany","betsinger","betters","beulah","beutler","bevard","beverlin",
"biasi","biber","biebel","biehle","bilger","billa","billiter","bing","birak","birchall",
"birdine","birdinground","biscardi","bisconer","bisset","black","blacksmith","blackstar","blagg","blailock",
"blakney","blankship","blann","blasen","blasko","blaylock","bleecker","bless","blinka","blondin",
"blood","bloschichak","bluemel","blurton","blute","boardley","boatner","bochenek","boches","boedecker",
"boenig","boese","boesel","bogacz","bogdanski","bogden","bohrer","boken","bolinder","bolinsky",
"bolitho","bomar","bombaci","bonebright","bonnell","bookman","borde","borell","borghi","borkenhagen",
"borquez","borries","borrow","boruvka","boshers","boston","botras","bouges","bouman","boushie",
"boutot","bouwens","bowels","bowne","boxley","braatz","bradd","braham","brame","branaugh",
"branch","branstrom","brassil","bratten","braund","brendeland","brennon","breslin","bresolin","breutzmann",
"bria","briano","brichetto","briede","brien","brigges","brinson","briskey","broddy","brode",
"brodfuehrer","brofman","bronsky","bronzo","brood","brookes","brozek","brozyna","bruccoleri","brugal",
"brumley","brumwell","brunjes","brustmann","brwon","bryars","bryson","brzostowski","buban","buccieri",
"buchinski","buchna","buckwald","buening","buffaloe","buffin","bukhari","bulin","bullivant","bunning",
"buntin","bunting","burdge","burford","burgardt","burget","burhans","burigsay","burkhalter","burkhead",
"burman","burrola","burruss","burttram","buscemi","buseman","busk","bussen","buteux","buther",
"buttimer","button","butzke","byker","byrom","cabugos","caddy","cadena","cafasso","cake",
"calamia","calderon","callagher","callam","calle","callo","calnick","calnimptewa","camack","camino",
"campus","campuzano","cancino","canedy","canela","cantor","capozzoli","cappelluti","cappetta","capriola",
"capurro","caraig","carbon","cardamone","carinio","carlberg","carlozzi","caronna","carrin","carrington",
"cartier","casagrande","casalenda","casalman","casareno","caselton","castellana","caston","catalanatto","cataldi",
"cates","catherman","catoire","caudy","caviggia","cavins","cayo","cecchinato","cecilio","cedillo",
"cellini","celso","cerami","ceraos","cerchia","cerdan","cerni","cerreta","cerverizzo","cervoni",
"chaboya","chadd","chafetz","chaidez","chanady","chanley","chareunsri","chaskey","chastain","chasteen",
"chatcho","chaudoin","chauhan","chavies","cheairs","cheeves","chelette","chernoff","cherny","chesla",
"chiaro","chichester","chindlund","chopp","christenbury","christoffer","chupp","churley","cichy","cidre",
"cinnamond","cinotti","cintra","ciocca","cippina","circle","cito","citrino","ciulla","civiello",
"civils","clairday","clapham","claussen","clayter","clem","clemmon","clester","clive","cloepfil",
"clopton","clutts","cobane","cockley","cofield","cohea","cokely","colbert","colclasure","colegrove",
"coleman","coleson","colletta","collette","colletti","colony","come","comisky","compono","conant",
"conboy","conceicao","condiff","cong","connaughton","conninghan","connon","conoly","conrow","cooperider",
"copps","corf","cornford","corporan","correia","corseri","corso","corvelli","costantini","cotterman",
"coulbourne","coult","coutcher","coven","cozine","crabill","craigen","cranor","crapp","crawshaw",
"cray","crazier","creason","credo","cremona","crepeau","crim","cripe","cristal","cristales",
"cronce","crumbliss","crumpton","cuadrado","cubie","cucuta","cuddington","culbreth","culliton","culverson",
"cunliffe","curboy","curi","curnow","curra","cussen","cuthbertson","cutillo","cutshaw","cuzman",
"cyler","czapla","czartoryski","dagostino","dahlman","dakin","dallam","dandurand","danehy","danese",
"danielovich","danley","danoski","dantuono","daprile","darbeau","darsch","darsey","dashner","datu",
"dausch","davel","davick","davidsmeyer","deaguero","dean","deardon","debettignies","debiew","debolt",
"debrita","decastro","decent","dechart","decourley","degele","degener","degori","degraffenreid","deibler",
"deichmann","deihl","deinhardt","dejes","dejongh","deleppo","delgado","delhoyo","delille","delilli",
"delio","dellbringge","delmonico","delorenzo","delsol","demasters","demeester","demello","demery","demirchyan",
"demling","demma","demmon","dempewolf","demske","dentler","depa","deperte","depoyster","deppner",
"dequattro","derer","derickson","derocco","derwin","deserio","deserres","desisles","desmet","desrevisseau",
"desrosier","dettmering","detty","deubler","deutschendorf","devai","devargas","devenport","devier","dewinter",
"dhaliwal","dhruva","diachenko","dibernardo","dicker","dietterick","digiulio","dignan","dijulio","dilbeck",
"dillworth","dimaggio","dimino","dingell","dinkin","dinn","diosdado","dirado","disher","diskind",
"divincenzo","dobrinin","doby","doe","dolby","dolder","dolecek","dolecki","dolezal","domann",
"domenick","dominiguez","donaldson","donelly","donning","dorantes","doriean","dorland","dorlando","dornellas",
"dorney","dose","dotie","doub","double","dougharity","douthit","dovalina","doxbeck","drach",
"drago","drayer","drennen","drenon","dreyfus","driesbach","droke","drow","dubiansky","dudek",
"dueno","dufek","duignan","dukes","dulatre","dumdei","duncanson","duncker","dunlavy","dunshie",
"dupuy","durrett","dust","dyba","dyer","dymke","dys","dzurnak","earheart","echavarria",
"edd","edenfield","edgman","edland","edmons","eggink","egidio","egland","egle","egvirre",
"eilbert","eisman","ekas","ekwall","eldreth","elery","elewa","elgas","eliezrie","elrod",
"elsey","emrich","eng","engebretsen","engelhard","engelmeyer","ennett","enrico","equils","erdelt",
"erichsen","ernstes","erp","ertel","escalera","escamilla","escober","escovedo","esenwein","esguerra",
"eskaran","eskin","espenoza","espina","essaid","estus","etters","eubank","eugley","evatt",
"everage","exantus","eylicio","ezpeleta","fabin","fagley","fahrenbruck","fahringer","faigin","fairbanks",
"falconi","falker","fallin","falling","fallon","faltin","fandino","fannin","fantasia","farah",
"farahkhan","fare","fargnoli","farish","faro","farran","fason","fassett","fauset","favela",
"fay","fazzinga","fearing","fearon","fechner","fechtig","fedoriw","fedorka","feduniewicz","fefer",
"feilbach","fellin","feltenberger","fendley","fenniwald","fent","ferandez","ferenc","ferlenda","fernette",
"ferrato","feurtado","fidell","figurelli","fili","fillion","finco","finkenbinder","finseth","firkins",
"firpi","fiser","fitchett","fitzgibbons","fitzsimons","fjetland","flagge","fleeger","fleeks","fletes",
"flinders","flister","flore","florek","florio","fluhman","fluitt","foersterling","foglia","foller",
"follick","fontenelle","forand","forehand","foriest","forpahl","fortunato","foss","fossati","fosser",
"fouracre","fower","foxman","fraine","franck","frankovich","franzoni","frayre","fredicks","freed",
"freitag","friddell","friedler","friehe","friess","frischkorn","fruehauf","fucile","fujita","fulena",
"fulfer","gaar","gabby","gable","gagarin","gagner","galanga","galdi","gale","galea",
"galla","gallaspy","gama","gambill","gammond","gappa","garacia","garate","garbe","garces",
"garcy","gargano","garis","garnette","garon","garrell","garrod","garwin","garwood","gasiewski",
"gather","gathman","gatliff","gaubert","gaukroger","gauron","gebel","gebo","geitner","gelbach",
"gellatly","gencarelli","gendreau","genetti","genous","gerdeman","gergen","gerhauser","gerich","geronime",
"gerosa","gettman","getzlaff","ghelfi","giacchi","gianopulos","gibbs","gica","giddins","gierman",
"gilbar","gilfillan","gimble","ging","gioe","girgenti","girouard","gittere","gjorven","gladstein",
"glascoe","glise","glista","glunz","gnerre","go","gobea","gobler","godard","godbe",
"godsey","goedicke","goettig","goffigan","gogan","goldhammer","goldklang","goliday","goligoski","goluba",
"gomillion","gonseth","gooden","goral","gordy","gorovitz","goshay","gosnell","gossack","goswami",
"gotlib","gottdenger","gottke","goudelock","goutremout","grabenstein","gradert","graef","grammes","granai",
"granger","granizo","gras","grav","greenwood","greeson","gremo","griffo","grismer","groeschel",
"grondin","groover","groshans","grove","grulke","gruska","grussing","grzesiak","guadarrama","guareno",
"gueits","guerriero","gugel","guggenheim","guilfoos","guillebeau","guire","guler","gundert","gunnell",
"gunstream","guntert","gussler","guster","gutreuter","guttenberg","gutteridge","guzowski","hable","hackbart",
"hade","hadley","hadsell","haegele","hafer","hagele","hagemeier","hagle","hahnert","haifley",
"haigwood","haimes","hainsworth","hairgrove","hairston","hakala","hakeem","haldiman","halfhill","hallahan",
"hallee","hallo","halo","halt","halverson","hamblin","hammonds","hammons","hanken","hanline",
"hansing","hansley","hanson","hanten","harbert","harbison","harbuck","harcey","hard","hardi",
"hardway","harer","harian","harke","harkenreader","harles","haroun","harrigan","hartlep","harvard",
"haseman","hasper","hass","hassel","hassick","haswell","hathorn","hatman","hauan","haughey",
"haury","haward","hawk","hawkes","hawthorne","haza","head","heartley","heberly","heddins",
"heeren","heflin","heidgerken","heinicke","heinis","heishman","heiss","hejl","helfen","helfritz",
"helgerman","helgeson","hellickson","helman","helphinstine","hemberger","hembry","hemker","hemmings","hemon",
"henzel","heraty","herkstroeter","herley","hermance","hernon","herrara","herrero","herres","herstad",
"hetcher","hett","hettenhausen","hetzler","heuett","heyne","hikel","hilaire","hillers","hinajosa",
"hinesley","hinh","hinley","hinman","hinokawa","hironaka","hirschhorn","hirschman","hiskey","hitsman",
"hittman","hjelle","hobgood","hoffelt","hogancamp","hohnstein","holderfield","holding","hollaway","holling",
"hollinger","hollow","holmlund","holstad","holtzlander","holzhauer","honeycott","honeycutt","hoopingarner","hooser",
"hopman","hoppenrath","hora","hortman","hotchkin","houpt","houston","hoven","hoye","hronick",
"hubert","huckins","huckle","hudelson","hudnut","huehn","huffines","hugee","hugel","hughes",
"hughey","huizenga","hulmes","humbles","hume","hunker","hurns","huskins","husmann","huxford",
"huyett","huynh","hwang","hylle","iacobellis","iadarola","iannuzzi","ida","iffert","ifill",
"ilalio","imdieke","imus","ingargiola","inghem","inghram","ingmire","ink","insogna","iqbal",
"irland","irsik","iwanejko","jaap","jackon","jaggers","jagoda","jagoe","jakubczak","jandrey",
"jandrin","janicki","jarecke","jarencio","jarosz","jarzynka","jaubert","jauregui","jauss","jeans",
"jehlicka","jendro","jennifer","jenniges","jeon","jergen","jeschke","jex","jividen","joehnck",
"jonassen","jone","jons","jordt","jorinscay","josephs","juariqui","jubie","juenemann","jukich",
"jumbo","jungbluth","jurica","justiss","ka","kadlec","kady","kaeding","kaercher","kagy",
"kajder","kalfayan","kalina","kaltefleiter","kaniecki","kao","kaopua","kapanke","kapps","kara",
"karren","karsh","kasahara","kassa","kassler","kaszynski","kaui","kazmierczak","keane","keba",
"keblish","keesey","keeter","keiper","keirstead","keiser","keitzer","kellam","kellin","kemick",
"kempker","kempner","kempon","kemppainen","keniry","kennington","keobaunleuang","keomanivong","kerechanko","kersh",
"kerss","kesley","ketcham","kettenring","kevan","kevwitch","keyon","khatak","khauv","khay",
"kho","khum","kickel","kientz","kieser","kiko","kilbert","kildare","kill","kilmon",
"kilty","kinas","kinatyan","kincannon","kingcade","kington","kinnion","kinroth","kinsley","kinzle",
"kirchoff","kirkman","kiser","kissell","kitner","klamm","klawinski","kleinsasser","klemke","klever",
"kliger","klimas","klitzner","kluttz","klyce","knaphus","knecht","knestrick","knoble","knobloch",
"knoblock","knotowicz","knudson","koba","kobashigawa","koch","kochanek","kocur","koening","koepper",
"kolber","kolling","kolodziej","kolodzik","konczak","konick","koo","kooistra","kool","koone",
"koors","koppen","kops","korinta","korvin","kosack","koskie","kosoff","kosse","kotowski",
"kouyate","kovacs","kovalovsky","kravec","krawiecz","krein","kress","kresse","kriegel","krissie",
"kroenke","krommes","krone","kropff","krows","krudop","kruizenga","krus","krysl","kubal",
"kuban","kubinski","kuchle","kuczkowski","kudrle","kuechle","kulas","kum","kung","kuntz",
"kuperman","kupfer","kuprewicz","kutlu","kvaternik","kyper","laabs","labove","lacasse","ladeau",
"lafountain","lafuente","lagonia","laguire","lair","lakes","lall","lalley","lalumiere","lamarr",
"lambino","lambright","lammey","lamontagne","lampo","lamprey","laney","langelier","lanosa","lanquist",
"laperle","lapinski","larabee","laramore","larman","larrick","lasseter","latassa","lathim","latona",
"lau","laube","laubscher","laudat","laukitis","laurenitis","lavatch","lavell","lavelle","lavey",
"lavina","lawery","lawis","lawn","lawver","lay","layher","layland","leach","leaming",
"leber","ledermann","ledezma","ledford","ledsinger","lefort","leftwich","legat","legore","legrow",
"leider","leitman","lemmond","lemus","leners","leng","lenherr","lenig","lenning","lenzini",
"leonardo","leppanen","lerner","lesueur","letendre","leuasseur","leubner","leuchs","levangie","leveille",
"levendosky","levenhagen","levens","levo","lezama","lichtenberg","lichtenfeld","licor","liebler","liechti",
"liehr","lieske","lifland","lifshitz","ligonis","likar","lile","limauro","limke","lindburg",
"lindell","lindenberg","linko","linley","linnane","linssen","linthicum","lips","liquet","liranzo",
"litherland","litvin","litza","livingston","lloyd","lobalbo","lockrem","locsin","logue","lolley",
"lombrana","lones","longman","longobardi","lonneman","lopey","lopinto","lopze","loretto","losado",
"losito","losneck","loth","louato","louderback","loughmiller","loukota","lovin","lowes","loze",
"lozier","lu","lubawy","lucca","luczkowiak","lueking","luescher","luk","lukianov","lule",
"lulewicz","lulic","lund","lundman","luneau","lunstrum","lutfy","lutke","luvene","luzell",
"lynam","lynch","lynds","lytal","maass","maccarthy","machen","maciak","mackedanz","mackowiak",
"macola","macrina","macvean","madagan","maedke","magaw","magaziner","maggio","maglio","maglott",
"mahlum","mahone","mahr","mainor","mairs","maisey","maisonet","makekau","makofsky","malakai",
"malaver","malcomb","malehorn","malia","malicoat","malin","malis","malkin","malpica","maltez",
"maltz","manard","manche","mancherian","manders","mandoza","mangicavallo","maniace","mannon","manolis",
"manza","marberry","marceaux","marcinka","marcoguisepp","marcus","marden","marfil","mariner","maritato",
"markevich","markey","markland","markos","marks","marlette","marling","marotte","marrapodi","marshal",
"marshbanks","martinelli","martinolli","martucci","marucci","maruschak","marzan","masek","mask","masri",
"masters","mastroianni","mathenia","matier","matkowski","mattimoe","mattlin","matzinger","maule","maxwell",
"maydew","mayhan","mazzocco","mcalarney","mcalmond","mcandrews","mcausland","mccaig","mccalpane","mccargar",
"mccartha","mccleary","mcclement","mcclenon","mccorry","mccovery","mccreedy","mccullen","mcdanial","mcdermett",
"mcelhattan","mcfadyen","mcgarey","mcgarrah","mcgoey","mcgraw","mcgurr","mchone","mcilhinney","mcinally",
"mckendree","mckin","mckinlay","mckissic","mckiver","mclean","mcmahen","mcnealy","mcneeley","mcnew",
"mcnitt","mcquaig","mcquillan","mcquirk","mcraney","mcratt","mcraven","mcveigh","mcvicar","meadow",
"mebane","medeiros","medill","mednis","megeath","megginson","mehrtens","meiggs","meile","meinzer",
"melino","mellard","mellecker","mellick","melstrom","mende","menes","menzella","merk","merseal",
"merta","messerschmidt","mevis","meyette","mezza","miazga","michalski","michell","michelli","mickley",
"miclette","mielke","miernik","mihalco","mihalios","mikola","mikulich","milam","milberger","milbrett",
"mileti","milinazzo","millard","milloway","minardo","minerich","minvielle","miraflores","miskovich","mittendorf",
"mitzel","mizrahi","modic","moellers","moglia","mohrbacher","mohseni","moisant","molen","mollere",
"mollo","molock","moment","monas","mondejar","monges","monjaras","monsees","monske","montalvan",
"montanari","monterrubio","montgonery","montoney","moorcroft","morawski","morelock","morely","moreno","morentin",
"morgenroth","morgon","morie","morones","morquecho","morrero","morriss","moryl","mosen","moudy",
"moulthrop","moulton","mowan","mowat","mowris","muchler","muffoletto","mujica","mulkin","mulkins",
"mullinex","mumper","munet","munshower","munzer","muraski","murden","murrufo","murzynski","muszar",
"muzzy","myles","nachbar","naegeli","nagode","naiman","nall","nalls","namer","nanes",
"nanney","narvaez","nasser","natt","nau","needham","neel","nehmer","neider","neill",
"nelles","nemes","nesbeth","nesler","netland","netley","nettle","neuhoff","neville","nickell",
"nickenberry","nickisch","niederhauser","night","nightwine","nilsby","nims","nocella","nogales","nole",
"nonemaker","nonu","nooner","nordlinger","noreiga","noriego","norley","norlund","normann","nostrand",
"nothacker","novelli","nowland","nowlen","nuckels","nuhn","nungesser","nunlee","nutley","nutter",
"nwagbara","oaxaca","obaker","obeid","obenshain","oby","occhino","oday","odore","oestreich",
"offley","oguendo","ogunyemi","ohl","ohlhauser","ohmit","ohnstad","ojano","okajima","okuna",
"olafson","olenick","oleson","olgvin","olinghouse","olivio","oller","olsby","oltremari","omer",
"onaga","ondersma","ondo","onks","onnen","onyeagu","opalka","ordaz","orduna","orengo",
"orlowsky","ormand","ororke","orrego","orsak","ortaga","osayande","oshita","ostler","ostrum",
"otta","otting","ottosen","ottoson","outler","outwater","ouzts","overly","overman","ow",
"owenby","pagett","pahls","pahulu","paladino","palczynski","palifka","palmeter","panah","panak",
"panchik","pandey","pangburn","paquette","parden","parisien","parlin","paro","parolari","paronto",
"parrillo","parsh","partin","partis","pasaya","pascal","pasko","passalacqua","passe","patch",
"pate","paterno","patry","patz","paullus","pavelich","pawlowski","pea","pead","pearlman",
"peckens","pedrick","pedrotti","peeters","peha","peixoto","pel","pelino","pellom","penceal",
"penington","penny","penuel","pepin","pereyra","peri","perlson","perotti","perschall","pershall",
"persichetti","perugini","pettay","pettey","pexton","pezzuti","pfeifle","pfisterer","pfleuger","pfliger",
"phare","philabaum","philhower","phillipson","pichon","picini","piedigrossi","piekos","piening","piertraccini",
"pietrini","pilat","pillot","pina","pinckley","pinette","pintello","pinuelas","piper","pirone",
"pirrello","pitchford","pitocco","pitorak","pixler","pizzico","plana","plank","plater","plaxico",
"pleasanton","plemel","plew","ploeger","poague","poblete","pock","podolsky","poetter","poissant",
"polian","pollan","pollart","pollinger","porch","poro","pottebaum","potter","pou","prange",
"prashad","prester","prestridge","primus","privateer","prizio","probasco","proch","protas","prunier",
"przybyla","puckett","pudlinski","puelo","pugliese","pulley","pundsack","pupa","pyeatt","pyscher",
"quails","quattrocchi","quay","quebedeaux","quinlan","quirion","quiroz","quiver","rabbe","rabenhorst",
"raby","racicot","raczka","rade","radlinski","rady","raebel","raffety","rafi","raguay",
"rainie","raio","rajan","rajaratnam","rall","rambert","ramdas","ramin","ramp","ran",
"ranallo","raney","ranney","ransford","rappenecker","rashdi","rathbone","rattanasinh","raught","rauschenberg",
"rausin","ravenel","ravitz","raychard","rayside","reagen","reagle","rebar","rebman","rebolledo",
"rebuldela","reckard","recker","redding","redican","redway","reff","regalado","reinbolt","reinhard",
"reinking","reisz","rekus","rella","rementer","remiasz","ren","renault","rendel","renfer",
"reninger","renison","renning","renz","resper","rettkowski","reuben","reuer","revak","reveron",
"revord","rexford","reza","ribao","ricciardone","richan","richerson","rickard","ricke","riddock",
"ridgle","ridings","riechman","rieder","rieger","riemersma","rietschlin","rieves","rigali","risha",
"risse","rissell","ristow","rizas","robak","robasciotti","robuck","rocker","rockett","rockhold",
"rodefer","rodeiguez","roesing","roffman","rohl","roker","rolf","rollie","rollock","roney",
"roose","rosendale","rosendorf","rosenkoetter","rosenlof","rossignol","rossing","rothlisberger","rotondi","routte",
"routzen","roux","rowley","rubalcaba","rubidoux","rubottom","ruddy","ruetz","ruggirello","rulon",
"ruminski","rump","rumpel","rusiecki","russett","rusteika","rutski","ryan","rydzewski","rysavy",
"ryser","ryu","saari","saathoff","sabad","sabastian","sadat","sadhu","sadorra","saeli",
"safranek","sagehorn","sagrera","sahni","sain","saison","sakamoto","sakata","salcedo","salis",
"saliva","sallach","salles","salois","salsberry","salvio","sama","samaan","samaha","sampair",
"sampogna","sanborn","sandefur","sandison","sanflippo","sanner","santarsiero","santheson","santino","santoli",
"santos","santy","saras","sarconi","sarra","sarracino","sarvey","sarzynski","saults","sauter",
"sauve","sawlivich","sawrey","saxbury","sayas","sayed","saylee","sboro","scagliotti","scalice",
"scandrett","scannapieco","scarberry","schaal","schadel","schaefers","schafer","schafersman","schaupp","scheele",
"schegetz","schei","scheman","schemonia","scherff","schertz","scheuerman","scheuren","schiffer","schleck",
"schleifer","schlein","schlepp","schlesselman","schlinker","schlotthauer","schluter","schmaling","schmelzle","schmiedeskamp",
"schmuhl","schnader","schnieders","schoel","schoening","schoepp","scholz","schoneck","schook","schrage",
"schrayter","schulder","schuller","schutt","schutzman","schwall","schwend","schweppe","schwerd","schweyen",
"scrobola","scroggy","seagroves","sealander","seber","secore","seel","seesholtz","segalla","seiser",
"seldomridge","seliga","selvig","sember","sembler","semrau","senecal","senesenes","senneker","sephus",
"serban","serles","serret","sespinosa","sestoso","setchell","seufert","sevedge","severo","sey",
"shaddock","shaffen","shafran","shafto","shanklin","shapero","shapin","sharber","sharon","sharrard",
"shaud","shawley","shazier","shearin","shears","sheeks","shelko","shellenbarger","shellenberger","shelling",
"sheltra","sherlock","sheumaker","sheward","shider","shieh","shigeta","shindo","shingles","shinkle",
"shiraishi","shiraki","shireman","shoddie","shone","shonerd","shont","shouse","shrigley","shuffleburg",
"shugars","shulick","shumay","shumski","shupp","shuter","shymske","sibille","siebe","siebens",
"siedel","siegel","siem","sienicki","siert","sifontes","siford","sigmon","signaigo","sikander",
"sillas","silsby","silverstein","simens","simiskey","simison","sine","singler","siracuse","sittloh",
"sitzes","sjogren","skillern","skufca","sleger","slemmons","slingland","slingluff","slonaker","slonski",
"slovacek","sluyter","smid","smink","smithhisler","smithwick","smuin","smykowski","smyntek","snaders",
"snare","snith","snowdy","soapes","soderlund","sogge","solas","sollman","sondelski","sonnee",
"sonstroem","sora","sorce","sorell","sorenson","sortino","sosbe","southard","sovel","sowada",
"spain","sparaco","sparr","sparrow","spaugh","speith","spencer","sperger","sperling","speth",
"spevak","spicknall","spieker","spielmann","spight","spike","spiney","spinney","spray","springs",
"springston","spurlin","spurr","spurrier","squair","srey","stadick","stake","stamand","stamour",
"stamp","stamper","stanciel","stanclift","stancoven","standafer","starcic","starghill","starkson","starley",
"starns","start","stasiuk","stauder","staudt","staum","stawasz","steagell","stecklair","steckline",
"steeber","steffani","steins","steinworth","stenback","stenseth","sterner","stindt","stjames","stjuste",
"stockholm","stoeber","stoey","stoffey","stokey","stooksbury","stopp","storz","stough","stracke",
"strassner","streat","streetman","strey","stricklen","strieter","strike","string","stringari","stromquist",
"strous","strouse","struck","strum","strutton","stubbolo","studebaker","studer","stumb","subia",
"sugiyama","sultemeier","summerour","sundeen","surrette","sutfin","suther","sutor","swanston","swarm",
"swayze","sweetland","swirsky","sword","szabo","szaflarski","taffer","tafuri","tagata","taggert",
"talaga","talahytewa","talat","tambasco","tamburrelli","tankard","tankersley","tannazzo","tappan","tarboro",
"tarbutton","tarmey","tarquinio","tasby","tatsak","taub","tavolario","teachey","tecuanhuey","teer",
"teissedre","teixeria","templeton","terlizzi","terrones","terry","tertinek","tetreau","tetro","teuteberg",
"tewolde","thain","thang","thaniel","tharrington","thay","therres","thetford","thews","thielbar",
"thiesse","thillet","thoman","thomen","thomley","thornburgh","thornley","thrapp","thrill","throop",
"tiegs","tigert","tijernia","tillberg","tilmon","tilus","tinajero","tintle","tirona","tischler",
"tlatelpa","tobola","todeschi","toelle","toews","tolmie","tomczak","tomkowicz","toney","toomey",
"tooms","tooze","torchio","tosti","touchton","townsley","traeger","traff","trafton","tramm",
"trapp","traux","traynham","treamer","trebilcock","treichler","tremore","trenor","trimm","triolo",
"trochesset","troester","troncoso","trowel","truby","trucco","truehart","truss","truxell","tryon",
"tuazon","tubeszewski","tuffey","tullar","tupy","turcotte","turdo","turja","twellman","twiet",
"twiggs","twyman","tyberg","tyl","tyo","tyrone","ubaldo","uc","ueno","ulbrich",
"ulicki","ulrick","ungerleider","unnewehr","uphoff","upson","urbanski","usina","uzun","vadner",
"valensuela","valenzuela","vallien","vanalst","vandagriff","vandenacre","vandergrift","vanderveer","vanderwoude","vandewalker",
"vandriel","vanduser","vandyne","vanfleet","vanfossan","vanhamlin","vanhook","vanhoozer","vankeuren","vanleeuwen",
"vanlier","vanloo","vannorden","vannuck","vanoni","vanpatton","vanslooten","vansteenhuyse","vanta","vanvuren",
"vanwagoner","vanwey","varughese","vautour","ve","vecchi","veile","velmontes","velunza","venzeio",
"venzon","verbasco","vercher","verdun","verduzco","veres","verfaille","verlin","vermeulen","verrelli",
"verunza","vessell","viar","vicks","vidaca","viebrock","vieweg","vigus","villamarin","villamayor",
"villante","villecus","viscera","visick","visker","vital","vitale","viverette","vizuete","vlasak",
"vlloa","vogland","vollette","vonarx","vonasek","voorheis","vorachek","vorholt","vormwald","votraw",
"wacker","wadusky","wagnon","wagster","wah","wake","waldrope","walk","wallaert","waller",
"wallo","walrond","wandell","wanner","warbington","wardell","warnasch","warnberg","warnick","warnken",
"warton","washpun","waska","wasowski","wassil","wates","wattenbarger","wauford","waybright","waynick",
"weadon","weatherwax","wedd","weers","weightman","weigle","weinland","weinman","weinreich","weisberger",
"weisenhorn","weishaupt","weissenborn","weissman","weiszbrod","welson","werber","werry","wertenberger","wethje",
"weyler","whelehan","whipps","whirry","whistle","whitis","whitlatch","whitsel","wice","wicher",
"wicinsky","wicklin","wideman","widmaier","widrig","wieand","wiechman","wiechmann","wieto","wigger",
"wikel","wikle","wilburn","wilderman","wilfahrt","wilhelmi","wilhoit","willardson","willick","willing",
"willmes","willwerth","wilmer","wilmouth","wilshusen","winchell","winick","winner","winterfeld","wisniowski",
"wison","wiszynski","witherite","witkus","wittich","wittlinger","wittmer","witvoet","wlodyka","woelk",
"wolfenbarger","wolkow","wonderling","woodley","woodside","worthy","wuebker","wuest","wunner","wurdeman",
"wyrosdick","yaftali","yagues","yahna","yanity","yann","yarboro","yard","yenner","yett",
"yetto","yiu","yoast","yokota","yoshimoto","yoshizawa","youkers","younge","youngkin","yovan",
"yovanovich","ypina","yusuf","zadina","zahri","zakowski","zambelli","zamborano","zangari","zange",
"zarcone","zavatson","zeanah","zebracki","zecchini","zelenka","zelinka","zendejas","zentz","zepf",
"zeto","ziadie","ziel","ziesman","zolty","zondlo","zsadanyi","zullinger","zunino","zwolak"
]
static func get_random_name():
return first_names[randi() % first_names.size()].capitalize() + " " + last_names[randi() % last_names.size()].capitalize()

View file

@ -1,9 +0,0 @@
class_name POIData
enum POIType {
SpawnPoint
}
enum POIClass {
Player
}

147
Classes/ResourceQueue.gd Normal file
View file

@ -0,0 +1,147 @@
class_name ResourceQueue
var thread
var mutex
var sem
var threaded = true
var time_max = 100 # Milliseconds.
var queue = []
var pending = {}
func _lock(_caller):
mutex.lock()
func _unlock(_caller):
mutex.unlock()
func _post(_caller):
sem.post()
func _wait(_caller):
sem.wait()
func queue_resource(path, p_in_front = false):
_lock("queue_resource")
if path in pending:
_unlock("queue_resource")
return
elif ResourceLoader.has_cached(path):
var res = ResourceLoader.load(path)
pending[path] = res
_unlock("queue_resource")
return
else:
var res = ResourceLoader.load_interactive(path)
res.set_meta("path", path)
if p_in_front:
queue.insert(0, res)
else:
queue.push_back(res)
pending[path] = res
_post("queue_resource")
_unlock("queue_resource")
return
func cancel_resource(path):
_lock("cancel_resource")
if path in pending:
if pending[path] is ResourceInteractiveLoader:
queue.erase(pending[path])
pending.erase(path)
_unlock("cancel_resource")
func get_progress(path):
if not threaded:
return 1.0
_lock("get_progress")
var ret = -1
if path in pending:
if pending[path] is ResourceInteractiveLoader:
ret = float(pending[path].get_stage()) / float(pending[path].get_stage_count())
else:
ret = 1.0
_unlock("get_progress")
return ret
func is_ready(path):
if not threaded:
return true
var ret
_lock("is_ready")
if path in pending:
ret = !(pending[path] is ResourceInteractiveLoader)
else:
ret = false
_unlock("is_ready")
return ret
func _wait_for_resource(res, path):
if not threaded:
return get_resource(path)
_unlock("wait_for_resource")
while true:
VisualServer.sync()
OS.delay_usec(16000) # Wait approximately 1 frame.
_lock("wait_for_resource")
if queue.size() == 0 || queue[0] != res:
return pending[path]
_unlock("wait_for_resource")
func get_resource(path):
if not threaded:
return load(path)
_lock("get_resource")
if path in pending:
if pending[path] is ResourceInteractiveLoader:
var res = pending[path]
if res != queue[0]:
var pos = queue.find(res)
queue.remove(pos)
queue.insert(0, res)
res = _wait_for_resource(res, path)
pending.erase(path)
_unlock("return")
return res
else:
var res = pending[path]
pending.erase(path)
_unlock("return")
return res
else:
_unlock("return")
return ResourceLoader.load(path)
func thread_process():
_wait("thread_process")
_lock("process")
while queue.size() > 0:
var res = queue[0]
_unlock("process_poll")
var ret = res.poll()
_lock("process_check_queue")
if ret == ERR_FILE_EOF || ret != OK:
var path = res.get_meta("path")
if path in pending: # Else, it was already retrieved.
pending[res.get_meta("path")] = res.get_resource()
# Something might have been put at the front of the queue while
# we polled, so use erase instead of remove.
queue.erase(res)
_unlock("process")
func thread_func(_u):
while true:
thread_process()
func start(use_threads: bool):
threaded = use_threads
if not threaded:
return
mutex = Mutex.new()
sem = Semaphore.new()
thread = Thread.new()
thread.start(self, "thread_func", 0)

View file

@ -1,8 +1,7 @@
class_name UICommand class_name UICommand
enum CommandType { enum CommandType {
SetShipSpeed, SetShipTarget
SetShipDirection
} }
var cmd_type = null var cmd_type = null
var cmd_args = [] var cmd_args = []

View file

@ -5,19 +5,20 @@ shader_type canvas_item;
render_mode unshaded; render_mode unshaded;
uniform int iterations = 17; const int volsteps = 20;
uniform float formuparam = 0.53; const int iterations = 17;
uniform int volsteps = 20; const float formuparam = 0.53;
uniform float stepsize = 0.1; const float stepsize = 0.1;
uniform float zoom = 0.80; const float brightness = 0.0015;
uniform float tile = 0.85; const float darkmatter = 0.300;
const float distfading = 0.730;
const float saturation = 0.850;
const float rotx = 0.;
const float roty = 0.001;
const float tile = 0.85;
uniform float speed = 0.001; uniform float speed = 0.001;
uniform float brightness = 0.0015; uniform float zoom = 0.80;
uniform float darkmatter = 0.300;
uniform float distfading = 0.730;
uniform float saturation = 0.850;
uniform float rotx = 0;
uniform float roty = 0.001;
void fragment() { void fragment() {
vec2 uv = FRAGCOORD.xy * SCREEN_PIXEL_SIZE - 0.5; vec2 uv = FRAGCOORD.xy * SCREEN_PIXEL_SIZE - 0.5;

BIN
Graphics/UI/handicons.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 293 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/handicons.png-8c76520aab77ec37eaad0980d02800ac.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Graphics/UI/handicons.png"
dest_files=[ "res://.import/handicons.png-8c76520aab77ec37eaad0980d02800ac.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=false
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Graphics/UI/selected.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 177 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/selected.png-edb67f7b3e4969e516febc7f79b42937.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Graphics/UI/selected.png"
dest_files=[ "res://.import/selected.png-edb67f7b3e4969e516febc7f79b42937.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=false
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

View file

@ -1,34 +1,13 @@
[remap] [remap]
importer="texture" importer="image"
type="StreamTexture" type="Image"
path="res://.import/splash.png-48a9249fadebd8f0056b1de9f1a63568.stex" path="res://.import/splash.png-48a9249fadebd8f0056b1de9f1a63568.image"
metadata={
"vram_texture": false
}
[deps] [deps]
source_file="res://Graphics/UI/splash.png" source_file="res://Graphics/UI/splash.png"
dest_files=[ "res://.import/splash.png-48a9249fadebd8f0056b1de9f1a63568.stex" ] dest_files=[ "res://.import/splash.png-48a9249fadebd8f0056b1de9f1a63568.image" ]
[params] [params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

View file

@ -1,19 +1,19 @@
[gd_resource type="TileSet" load_steps=2 format=2] [gd_resource type="TileSet" load_steps=2 format=2]
[ext_resource path="res://Graphics/tgstation/plating.png" type="Texture" id=1] [ext_resource path="res://Graphics/tgstation/floors.png" type="Texture" id=1]
[resource] [resource]
0/name = "Plating" 1/name = "Plating"
0/texture = ExtResource( 1 ) 1/texture = ExtResource( 1 )
0/tex_offset = Vector2( 0, 0 ) 1/tex_offset = Vector2( 0, 0 )
0/modulate = Color( 1, 1, 1, 1 ) 1/modulate = Color( 1, 1, 1, 1 )
0/region = Rect2( 0, 0, 32, 32 ) 1/region = Rect2( 96, 160, 32, 32 )
0/tile_mode = 0 1/tile_mode = 0
0/occluder_offset = Vector2( 0, 0 ) 1/occluder_offset = Vector2( 0, 0 )
0/navigation_offset = Vector2( 0, 0 ) 1/navigation_offset = Vector2( 0, 0 )
0/shape_offset = Vector2( 0, 0 ) 1/shape_offset = Vector2( 0, 0 )
0/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 ) 1/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 )
0/shape_one_way = false 1/shape_one_way = false
0/shape_one_way_margin = 0.0 1/shape_one_way_margin = 0.0
0/shapes = [ ] 1/shapes = [ ]
0/z_index = 0 1/z_index = 0

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -1,13 +1,27 @@
[gd_resource type="TileSet" load_steps=2 format=2] [gd_resource type="TileSet" load_steps=2 format=2]
[ext_resource path="res://Graphics/tgstation/floor.png" type="Texture" id=1] [ext_resource path="res://Graphics/tgstation/floors.png" type="Texture" id=1]
[resource] [resource]
1/name = "Floor" 0/name = "Iron"
0/texture = ExtResource( 1 )
0/tex_offset = Vector2( 0, 0 )
0/modulate = Color( 1, 1, 1, 1 )
0/region = Rect2( 160, 160, 32, 32 )
0/tile_mode = 0
0/occluder_offset = Vector2( 0, 0 )
0/navigation_offset = Vector2( 0, 0 )
0/shape_offset = Vector2( 0, 0 )
0/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 )
0/shape_one_way = false
0/shape_one_way_margin = 0.0
0/shapes = [ ]
0/z_index = 0
1/name = "Wood"
1/texture = ExtResource( 1 ) 1/texture = ExtResource( 1 )
1/tex_offset = Vector2( 0, 0 ) 1/tex_offset = Vector2( 0, 0 )
1/modulate = Color( 1, 1, 1, 1 ) 1/modulate = Color( 1, 1, 1, 1 )
1/region = Rect2( 0, 0, 32, 32 ) 1/region = Rect2( 0, 96, 32, 32 )
1/tile_mode = 0 1/tile_mode = 0
1/occluder_offset = Vector2( 0, 0 ) 1/occluder_offset = Vector2( 0, 0 )
1/navigation_offset = Vector2( 0, 0 ) 1/navigation_offset = Vector2( 0, 0 )
@ -17,3 +31,143 @@
1/shape_one_way_margin = 0.0 1/shape_one_way_margin = 0.0
1/shapes = [ ] 1/shapes = [ ]
1/z_index = 0 1/z_index = 0
2/name = "Grass"
2/texture = ExtResource( 1 )
2/tex_offset = Vector2( 0, 0 )
2/modulate = Color( 1, 1, 1, 1 )
2/region = Rect2( 160, 96, 32, 32 )
2/tile_mode = 0
2/occluder_offset = Vector2( 0, 0 )
2/navigation_offset = Vector2( 0, 0 )
2/shape_offset = Vector2( 0, 0 )
2/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 )
2/shape_one_way = false
2/shape_one_way_margin = 0.0
2/shapes = [ ]
2/z_index = 0
3/name = "LightCheck"
3/texture = ExtResource( 1 )
3/tex_offset = Vector2( 0, 0 )
3/modulate = Color( 1, 1, 1, 1 )
3/region = Rect2( 128, 32, 32, 32 )
3/tile_mode = 0
3/occluder_offset = Vector2( 0, 0 )
3/navigation_offset = Vector2( 0, 0 )
3/shape_offset = Vector2( 0, 0 )
3/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 )
3/shape_one_way = false
3/shape_one_way_margin = 0.0
3/shapes = [ ]
3/z_index = 0
4/name = "Reinforced"
4/texture = ExtResource( 1 )
4/tex_offset = Vector2( 0, 0 )
4/modulate = Color( 1, 1, 1, 1 )
4/region = Rect2( 96, 32, 32, 32 )
4/tile_mode = 0
4/occluder_offset = Vector2( 0, 0 )
4/navigation_offset = Vector2( 0, 0 )
4/shape_offset = Vector2( 0, 0 )
4/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 )
4/shape_one_way = false
4/shape_one_way_margin = 0.0
4/shapes = [ ]
4/z_index = 0
5/name = "PlatWhite"
5/texture = ExtResource( 1 )
5/tex_offset = Vector2( 0, 0 )
5/modulate = Color( 1, 1, 1, 1 )
5/region = Rect2( 32, 96, 32, 32 )
5/tile_mode = 0
5/occluder_offset = Vector2( 0, 0 )
5/navigation_offset = Vector2( 0, 0 )
5/shape_offset = Vector2( 0, 0 )
5/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 )
5/shape_one_way = false
5/shape_one_way_margin = 0.0
5/shapes = [ ]
5/z_index = 0
6/name = "PlatYellow"
6/texture = ExtResource( 1 )
6/tex_offset = Vector2( 0, 0 )
6/modulate = Color( 1, 1, 1, 1 )
6/region = Rect2( 32, 64, 32, 32 )
6/tile_mode = 0
6/occluder_offset = Vector2( 0, 0 )
6/navigation_offset = Vector2( 0, 0 )
6/shape_offset = Vector2( 0, 0 )
6/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 )
6/shape_one_way = false
6/shape_one_way_margin = 0.0
6/shapes = [ ]
6/z_index = 0
7/name = "PlatPurple"
7/texture = ExtResource( 1 )
7/tex_offset = Vector2( 0, 0 )
7/modulate = Color( 1, 1, 1, 1 )
7/region = Rect2( 32, 128, 32, 32 )
7/tile_mode = 0
7/occluder_offset = Vector2( 0, 0 )
7/navigation_offset = Vector2( 0, 0 )
7/shape_offset = Vector2( 0, 0 )
7/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 )
7/shape_one_way = false
7/shape_one_way_margin = 0.0
7/shapes = [ ]
7/z_index = 0
8/name = "PlatBlue"
8/texture = ExtResource( 1 )
8/tex_offset = Vector2( 0, 0 )
8/modulate = Color( 1, 1, 1, 1 )
8/region = Rect2( 32, 160, 32, 32 )
8/tile_mode = 0
8/occluder_offset = Vector2( 0, 0 )
8/navigation_offset = Vector2( 0, 0 )
8/shape_offset = Vector2( 0, 0 )
8/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 )
8/shape_one_way = false
8/shape_one_way_margin = 0.0
8/shapes = [ ]
8/z_index = 0
9/name = "PlayGrey"
9/texture = ExtResource( 1 )
9/tex_offset = Vector2( 0, 0 )
9/modulate = Color( 1, 1, 1, 1 )
9/region = Rect2( 32, 192, 32, 32 )
9/tile_mode = 0
9/occluder_offset = Vector2( 0, 0 )
9/navigation_offset = Vector2( 0, 0 )
9/shape_offset = Vector2( 0, 0 )
9/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 )
9/shape_one_way = false
9/shape_one_way_margin = 0.0
9/shapes = [ ]
9/z_index = 0
10/name = "InternalGrey"
10/texture = ExtResource( 1 )
10/tex_offset = Vector2( 0, 0 )
10/modulate = Color( 1, 1, 1, 1 )
10/region = Rect2( 128, 0, 32, 32 )
10/tile_mode = 0
10/occluder_offset = Vector2( 0, 0 )
10/navigation_offset = Vector2( 0, 0 )
10/shape_offset = Vector2( 0, 0 )
10/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 )
10/shape_one_way = false
10/shape_one_way_margin = 0.0
10/shapes = [ ]
10/z_index = 0
11/name = "InternalRed"
11/texture = ExtResource( 1 )
11/tex_offset = Vector2( 0, 0 )
11/modulate = Color( 1, 1, 1, 1 )
11/region = Rect2( 96, 192, 32, 32 )
11/tile_mode = 0
11/occluder_offset = Vector2( 0, 0 )
11/navigation_offset = Vector2( 0, 0 )
11/shape_offset = Vector2( 0, 0 )
11/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 )
11/shape_one_way = false
11/shape_one_way_margin = 0.0
11/shapes = [ ]
11/z_index = 0

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/floors.png-279dfb5ae1aa7c2899e8dc438ae741e5.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Graphics/tgstation/floors.png"
dest_files=[ "res://.import/floors.png-279dfb5ae1aa7c2899e8dc438ae741e5.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=false
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/midnight.png-3d811938da348be9b831f07b37a9d5f1.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Graphics/tgstation/midnight.png"
dest_files=[ "res://.import/midnight.png-3d811938da348be9b831f07b37a9d5f1.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=false
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 781 B

View file

@ -2,15 +2,15 @@
importer="texture" importer="texture"
type="StreamTexture" type="StreamTexture"
path="res://.import/floor.png-3bcc52916d51a4ca8cbe3f63cd3f1ef7.stex" path="res://.import/tcomm.png-d10359105f84709691a87ffd8437229d.stex"
metadata={ metadata={
"vram_texture": false "vram_texture": false
} }
[deps] [deps]
source_file="res://Graphics/tgstation/floor.png" source_file="res://Graphics/tgstation/tcomm.png"
dest_files=[ "res://.import/floor.png-3bcc52916d51a4ca8cbe3f63cd3f1ef7.stex" ] dest_files=[ "res://.import/tcomm.png-d10359105f84709691a87ffd8437229d.stex" ]
[params] [params]

View file

@ -4,7 +4,6 @@
code = "shader_type canvas_item; code = "shader_type canvas_item;
render_mode unshaded;" render_mode unshaded;"
custom_defines = ""
[resource] [resource]
shader = SubResource( 1 ) shader = SubResource( 1 )

5
LICENSE Normal file
View file

@ -0,0 +1,5 @@
Copyright 2020 Alessandro Gatti
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

13
README.md Normal file
View file

@ -0,0 +1,13 @@
# NSS Odyssey
**Warning: Toy project**
Co-op survival space sim, keep the NSS Odyssey alive and kicking while roaming in space.
Takes heavy inspiration (and for now, graphics) from Space Station 13 and FTL.
## Credits
See `CREDITS.md` for an exhaustive list of sources for all assets not made by me (Hamcha)
See `LICENSE` for code license (TL;DR it's [ISC](https://en.wikipedia.org/wiki/ISC_license))

View file

@ -0,0 +1,11 @@
[gd_scene load_steps=2 format=2]
[sub_resource type="GDScript" id=1]
script/source = "extends Node
func _ready():
$\"/root/Multiplayer\".host()
"
[node name="Node" type="Node"]
script = SubResource( 1 )

View file

@ -2,16 +2,81 @@ extends Node
class_name GameInstance class_name GameInstance
signal state_received()
onready var ui = $CanvasLayer/ui onready var ui = $CanvasLayer/ui
onready var world = $world onready var world = $world
onready var systems = $systems onready var systems = $systems
onready var netgame = $"/root/Multiplayer"
onready var physics = world.get_world_2d().direct_space_state as Physics2DDirectSpaceState
func _ready(): var writing = false
ui.connect("command", world, "process_command")
func process_command(cmd: UICommand): func _ready() -> void:
$"/root/Music/BGM".stop()
randomize()
if netgame.hosting:
world.load_map(netgame.get_current_map())
world.map.current_ship_position = Vector2(randf() * 1e4, randf() * 1e4)
world.map.current_ship_target = world.map.current_ship_position + Vector2(randf() * 1e2, randf() * 1e2)
rpc("spawn_player", 1)
else:
world.load_map(GameWorld.Map.EMPTY)
rpc_id(1, "send_map")
yield(self, "state_received")
rpc_id(1, "ready_to_spawn")
master func send_map() -> void:
var id = get_tree().get_rpc_sender_id()
var map_data = world.map.serialize()
var systems_data = systems.serialize()
print("sending map data to %d" % id)
rpc_id(id, "receive_data", {
"map": map_data,
"systems": systems_data
})
puppet func receive_data(data: Dictionary) -> void:
world.map.deserialize(data["map"])
systems.deserialize(data["systems"])
print("Received map data from master")
emit_signal("state_received")
master func ready_to_spawn() -> void:
var id = get_tree().get_rpc_sender_id()
print("%d is ready to spawn players" % id)
# Tell him everyone to spawn
var players = $world/players.get_children()
for player in players:
rpc_id(id, "spawn_player", player.get_network_master())
# Then spawn him as well
rpc("spawn_player", id)
master func broadcast_zone(message: String, origin: Vector2, radius: float) -> void:
var shape = CircleShape2D.new()
shape.radius = radius
var query = Physics2DShapeQueryParameters.new()
query.collide_with_areas = true
query.collide_with_bodies = false
query.collision_layer = 32
query.transform.origin = origin
query.set_shape(shape)
var res = physics.intersect_shape(query, 100)
for col in res:
rpc_id(col.collider.get_network_master(), "add_log", message)
master func broadcast(message: String) -> void:
rpc("add_log", message)
remotesync func add_log(message: String) -> void:
ui.logs.add_line(message)
remotesync func spawn_player(id: int) -> void:
world.spawn_player(id, multiplayer.get_network_unique_id() == id)
remotesync func process_command(cmd: UICommand) -> void:
match cmd.cmd_type: match cmd.cmd_type:
UICommand.CommandType.SetShipSpeed: UICommand.CommandType.SetShipTarget:
world.map.ship_speed = cmd.cmd_args[0] world.map.current_ship_target = cmd.cmd_args[0]
UICommand.CommandType.SetShipDirection:
world.map.ship_direction = cmd.cmd_args[0]

View file

@ -1,5 +1,6 @@
[gd_scene load_steps=4 format=2] [gd_scene load_steps=5 format=2]
[ext_resource path="res://Scenes/systems.gd" type="Script" id=1]
[ext_resource path="res://Scenes/UI.tscn" type="PackedScene" id=3] [ext_resource path="res://Scenes/UI.tscn" type="PackedScene" id=3]
[ext_resource path="res://Scenes/World.gd" type="Script" id=4] [ext_resource path="res://Scenes/World.gd" type="Script" id=4]
[ext_resource path="res://Scenes/Game.gd" type="Script" id=5] [ext_resource path="res://Scenes/Game.gd" type="Script" id=5]
@ -8,11 +9,11 @@
script = ExtResource( 5 ) script = ExtResource( 5 )
[node name="systems" type="Node" parent="."] [node name="systems" type="Node" parent="."]
script = ExtResource( 1 )
[node name="world" type="Node2D" parent="."] [node name="world" type="Node2D" parent="."]
scale = Vector2( 2, 2 ) scale = Vector2( 2, 2 )
script = ExtResource( 4 ) script = ExtResource( 4 )
mapToLoad = 1
[node name="players" type="Node2D" parent="world"] [node name="players" type="Node2D" parent="world"]

View file

@ -8,22 +8,32 @@ const SERVER_PORT = 5513
const MAX_PLAYERS = 30 const MAX_PLAYERS = 30
var port = SERVER_PORT var port = SERVER_PORT
# Throttle network updates of often-changed variables by this many physics frames
const SYSTEMS_UPDATE_INTERVAL = 10
# Master server data # Master server data
const MASTER_SERVER_ADDR = "fgms.zyg.ovh" const MASTER_SERVER_ADDR = "fgms.zyg.ovh"
const MASTER_SERVER_UDP_PORT = 9434 const MASTER_SERVER_UDP_PORT = 9434
const MS_GAME_CODE = "odyssey-0-a1" const MS_GAME_CODE = "odyssey-0-a2"
const GOTM_OVERRIDE = false
# Master server entry # Master server entry
var ms_active = false var ms_active = false
var ms_key = "" var ms_key = ""
var server_name = "" var server_name = ""
var hosting = false
export var player_name = "" export var player_name = ""
var player_info = {} var player_info = {}
var round_info = {}
onready var scene_manager = $"/root/SceneManager"
func _ready(): func _ready():
player_name = "tider-" + str(randi() % 1000) randomize()
player_name = Names.get_random_name()
func bind_events(): func bind_events():
get_tree().connect("network_peer_connected", self, "_player_connected") get_tree().connect("network_peer_connected", self, "_player_connected")
@ -44,7 +54,7 @@ func punch_nat():
yield(get_tree().create_timer(.3), "timeout") yield(get_tree().create_timer(.3), "timeout")
if socketUDP.get_available_packet_count() < 1: if socketUDP.get_available_packet_count() < 1:
failed += 1 failed += 1
print("no reply (attempt #", failed, ")") print("no reply (attempt #%d)" % failed)
continue continue
port = socketUDP.get_var(false) port = socketUDP.get_var(false)
print("Received ", port) print("Received ", port)
@ -56,7 +66,14 @@ func discover_upnp():
upnp.discover(2000, 2, "InternetGatewayDevice") upnp.discover(2000, 2, "InternetGatewayDevice")
return upnp.add_port_mapping(SERVER_PORT) return upnp.add_port_mapping(SERVER_PORT)
func host(): func host(map_name: String = "odyssey"):
scene_manager.enter_loader()
scene_manager.loading_text = "Starting server"
# Wait just a sec to draw
yield(get_tree().create_timer(0.3), "timeout")
# Run port forwarding/nat punchthrough if the platform doesn't do it already
print("Running UPNP magicks") print("Running UPNP magicks")
if discover_upnp() == UPNP.UPNP_RESULT_SUCCESS: if discover_upnp() == UPNP.UPNP_RESULT_SUCCESS:
print("UPNP mapping added") print("UPNP mapping added")
@ -64,8 +81,13 @@ func host():
push_warning("UPNP magicks fail, punching NAT in the face") push_warning("UPNP magicks fail, punching NAT in the face")
yield(punch_nat(), "completed") yield(punch_nat(), "completed")
server_name = "%s's server" % player_name
player_info[1] = { "name": player_name }
round_info = { "map": map_name }
bind_events() bind_events()
var peer = NetworkedMultiplayerENet.new() var peer = NetworkedMultiplayerENet.new()
peer.compression_mode = NetworkedMultiplayerENet.COMPRESS_FASTLZ
var server_res = peer.create_server(port, MAX_PLAYERS) var server_res = peer.create_server(port, MAX_PLAYERS)
if server_res != OK: if server_res != OK:
match server_res: match server_res:
@ -76,20 +98,33 @@ func host():
return return
get_tree().network_peer = peer get_tree().network_peer = peer
print("Hosting") print("Hosting")
server_name = player_name + "'s server" hosting = true
player_info[1] = { name=player_name }
get_tree().change_scene("res://Scenes/Game.tscn") scene_manager.loading_text = null
# Add to master server scene_manager.load_scene("res://Scenes/Game.tscn", [
"res://Scenes/Maps/%s.tscn" % map_name
])
# Add to master server after hosting
create_ms_entry() create_ms_entry()
func join(addr: String): func join(server):
scene_manager.enter_loader()
scene_manager.loading_text = "Joining server"
# Wait just a sec to draw
yield(get_tree().create_timer(0.3), "timeout")
bind_events() bind_events()
var peer = NetworkedMultiplayerENet.new() var peer = NetworkedMultiplayerENet.new()
peer.compression_mode = NetworkedMultiplayerENet.COMPRESS_FASTLZ
var addr = server.address
peer.create_client(addr, SERVER_PORT) peer.create_client(addr, SERVER_PORT)
get_tree().network_peer = peer get_tree().network_peer = peer
print("Connecting to ", addr) print("Connecting to %s" % addr)
func leave(): func leave():
var peer = get_tree().network_peer var peer = get_tree().network_peer
@ -103,18 +138,20 @@ func leave():
pass pass
get_tree().network_peer = null get_tree().network_peer = null
emit_signal("left") emit_signal("left")
func _player_connected(id): func _player_connected(id):
rpc_id(id, "register_player", player_name) rpc_id(id, "register_player", player_name)
if get_tree().is_network_server(): if get_tree().is_network_server():
pass rpc_id(id, "_handshake", { "round": round_info, "players": player_info })
#rpc_id(id, "spawn_players", mapLoader.map.all_players())
func _player_disconnected(id): func _player_disconnected(id):
print(player_info[id].name, " (", id, ") disconnected") print("%s (%d) disconnected" % [player_info[id].name, id])
player_info.erase(id) player_info.erase(id)
func _connected_ok(): func _connected_ok():
print("Connected to server") print("Connected to server")
scene_manager.loading_text = null
scene_manager.load_scene("res://Scenes/Game.tscn", [])
func _server_disconnected(): func _server_disconnected():
print("Disconnected from server") print("Disconnected from server")
@ -125,27 +162,35 @@ func _connected_fail():
remote func register_player(username: String): remote func register_player(username: String):
var id = get_tree().get_rpc_sender_id() var id = get_tree().get_rpc_sender_id()
player_info[id] = { name=username } player_info[id] = { name=username }
print(player_info[id].name, " (", id, ") connected") print("%s (%d) connected" % [player_info[id].name, id])
remote func spawn_players(players): remote func _handshake(infos):
for player_id in players: round_info = infos["round"]
pass player_info = infos["players"]
#mapLoader.map.spawn_player(player_id)
# Spawn myself as well
#mapLoader.map.rpc("spawn_player", get_tree().network_peer.get_unique_id())
func _ms_request(endpoint: String, data): func _ms_request(endpoint: String, data):
var http_request = HTTPRequest.new() var http_request = HTTPRequest.new()
add_child(http_request) add_child(http_request)
http_request.connect("request_completed", self, "_ms_response", [endpoint]) http_request.connect("request_completed", self, "_ms_response", [endpoint])
print_debug("Telling ms to " + endpoint) print_debug("Telling ms to %s" % endpoint)
var error = http_request.request( var error = http_request.request(
"https://" + MASTER_SERVER_ADDR + "/" + endpoint, "https://%s/%s" % [MASTER_SERVER_ADDR, endpoint],
["Content-Type: application/json"], ["Content-Type: application/json"],
true, HTTPClient.METHOD_POST, JSON.print(data)) true, HTTPClient.METHOD_POST, JSON.print(data))
if error != OK: if error != OK:
push_error("An error occurred in the HTTP request.") push_error("An error occurred in the HTTP request.")
func ms_get_entries():
var http_request = HTTPRequest.new()
add_child(http_request)
http_request.connect("request_completed", self, "_ms_response", ["list_games"])
var error = http_request.request(
"https://%s/%s" % [MASTER_SERVER_ADDR, MS_GAME_CODE],
["Content-Type: application/json"],
true, HTTPClient.METHOD_GET)
if error != OK:
push_error("An error occurred in the HTTP request.")
func get_game_data(): func get_game_data():
return { return {
"name": server_name, "name": server_name,
@ -159,7 +204,6 @@ func create_ms_entry():
"game_id": MS_GAME_CODE, "game_id": MS_GAME_CODE,
"data": get_game_data() "data": get_game_data()
}) })
update_ms_entry()
func update_ms_entry(): func update_ms_entry():
if ms_active: if ms_active:
@ -167,12 +211,20 @@ func update_ms_entry():
"key": ms_key, "key": ms_key,
"data": get_game_data() "data": get_game_data()
}) })
yield(get_tree().create_timer(20), "timeout")
var time_left = 30
func _process(delta):
if not ms_active:
return
time_left -= delta
if time_left < 0:
update_ms_entry()
time_left = 30
func _ms_response(_result: int, response_code: int, _headers: PoolStringArray, body: PoolByteArray, action: String): func _ms_response(_result: int, response_code: int, _headers: PoolStringArray, body: PoolByteArray, action: String):
print_debug("MS said " + str(response_code)) print_debug("MS said %s" % response_code)
if response_code > 299: if response_code > 299:
push_error("ms action \"" + action + "\" returned error: " + str(response_code) + " - " + body.get_string_from_utf8()) push_error("ms action '%s' returned error: %s - %s" % [action, response_code, body.get_string_from_utf8()])
return return
var json = JSON.parse(body.get_string_from_utf8()) var json = JSON.parse(body.get_string_from_utf8())
match action: match action:
@ -187,3 +239,12 @@ func _notification(what):
if what == MainLoop.NOTIFICATION_WM_QUIT_REQUEST: if what == MainLoop.NOTIFICATION_WM_QUIT_REQUEST:
leave() leave()
yield(self, "left") yield(self, "left")
func get_current_map():
match round_info.map:
"odyssey":
return GameWorld.Map.ODYSSEY
"runtime":
return GameWorld.Map.RUNTIME
_:
return GameWorld.Map.EMPTY

View file

@ -0,0 +1,49 @@
extends Node
var queue = ResourceQueue.new()
var target_scene = null
var loading_text = null
var loader = preload("res://Scenes/Loader.tscn")
onready var netgame = $"/root/Multiplayer"
func _ready() -> void:
var threads_supported = true
if OS.get_name() == "HTML5":
threads_supported = false
queue.start(threads_supported)
func enter_loader() -> void:
get_tree().change_scene_to(loader)
func load_scene(scene_path: String, dependencies: Array) -> void:
if queue.threaded:
target_scene = scene_path
queue.queue_resource(scene_path)
for dep in dependencies:
queue.queue_resource(dep)
else:
get_tree().change_scene(scene_path)
func _physics_process(_delta: float) -> void:
if queue.threaded:
if target_scene != null:
var remaining = queue.pending.size()
for path in queue.pending:
if queue.is_ready(path):
remaining -= 1
if remaining == 0:
get_tree().change_scene_to(queue.get_resource(target_scene))
target_scene = null
func get_progress() -> String:
if loading_text != null:
return loading_text
var count = queue.pending.size()
if count == 0:
return "Reticulating splines"
var current = 0
for path in queue.pending:
current += queue.get_progress(path)
return "Loading scene (%.0f%%)" % (current/count*100)

7
Scenes/Loader.gd Normal file
View file

@ -0,0 +1,7 @@
extends Control
onready var text = $BottomRight/Label
onready var scene_manager = $"/root/SceneManager"
func _physics_process(_delta):
text.text = str(scene_manager.get_progress())

139
Scenes/Loader.tscn Normal file
View file

@ -0,0 +1,139 @@
[gd_scene load_steps=12 format=2]
[ext_resource path="res://Graphics/UI/logo-temp-pixel.png" type="Texture" id=1]
[ext_resource path="res://Graphics/UI/iosevka-aile-regular.ttf" type="DynamicFontData" id=2]
[ext_resource path="res://Scenes/Loader.gd" type="Script" id=3]
[sub_resource type="Shader" id=1]
code = "shader_type canvas_item;
uniform vec2 tex_size;
uniform vec4 uv_rect;
void fragment() {
vec2 uv_adjusted = (UV - (uv_rect.xy / tex_size)) * (tex_size / uv_rect.zw);
float dist = distance(uv_adjusted, vec2(0.5));
if (dist < 0.26) {
COLOR = vec4(1.);
} else {
COLOR = texture(TEXTURE, UV);
}
}"
[sub_resource type="ShaderMaterial" id=2]
shader = SubResource( 1 )
shader_param/tex_size = Vector2( 240, 180 )
shader_param/uv_rect = Plane( 126, 16, 82, 84 )
[sub_resource type="AtlasTexture" id=3]
atlas = ExtResource( 1 )
region = Rect2( 126, 16, 82, 84 )
[sub_resource type="Shader" id=4]
code = "shader_type canvas_item;
uniform vec2 tex_size;
uniform vec4 uv_rect;
void fragment() {
vec4 tex = texture(TEXTURE, UV);
vec2 uv_adjusted = (UV - (uv_rect.xy / tex_size)) * (tex_size / uv_rect.zw);
float dist = distance(uv_adjusted, vec2(0.5));
if (dist > 0.56) {
discard;
} else {
COLOR = vec4(tex.aaa, 1.-tex.a);
}
}"
[sub_resource type="ShaderMaterial" id=5]
shader = SubResource( 4 )
shader_param/tex_size = Vector2( 240, 180 )
shader_param/uv_rect = Plane( 146, 39, 39, 38 )
[sub_resource type="AtlasTexture" id=6]
atlas = ExtResource( 1 )
region = Rect2( 146, 39, 39, 38 )
[sub_resource type="DynamicFont" id=7]
size = 32
font_data = ExtResource( 2 )
[sub_resource type="Animation" id=8]
length = 7.0
loop = true
tracks/0/type = "value"
tracks/0/path = NodePath("BottomRight/logo-temp-pixel2:rect_rotation")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/keys = {
"times": PoolRealArray( 0, 7 ),
"transitions": PoolRealArray( 1, 1 ),
"update": 0,
"values": [ 0.0, 360.0 ]
}
[node name="Loading" type="Control"]
anchor_right = 0.5
anchor_bottom = 0.5
rect_scale = Vector2( 2, 2 )
script = ExtResource( 3 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="BottomRight" type="Control" parent="."]
anchor_left = 1.0
anchor_top = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
margin_left = -114.5
margin_top = -109.5
margin_right = -2.5
margin_bottom = -1.5
__meta__ = {
"_edit_use_anchors_": false
}
[node name="logo-temp-pixel2" type="TextureRect" parent="BottomRight"]
material = SubResource( 2 )
margin_left = -7.11853
margin_top = -6.38116
margin_right = 92.8815
margin_bottom = 93.6188
rect_pivot_offset = Vector2( 50, 50 )
texture = SubResource( 3 )
stretch_mode = 4
__meta__ = {
"_edit_use_anchors_": false
}
[node name="logo-temp-pixel" type="TextureRect" parent="BottomRight"]
material = SubResource( 5 )
margin_left = -1.5
margin_top = -1.0
margin_right = 88.5
margin_bottom = 89.0
rect_pivot_offset = Vector2( 79, 59 )
texture = SubResource( 6 )
stretch_mode = 4
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Label" type="Label" parent="BottomRight"]
margin_left = -220.0
margin_top = 63.0
margin_right = 174.0
margin_bottom = 104.0
rect_scale = Vector2( 0.5, 0.5 )
custom_fonts/font = SubResource( 7 )
custom_colors/font_color = Color( 1, 1, 1, 1 )
align = 2
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
autoplay = "spinner"
anims/spinner = SubResource( 8 )

View file

@ -3,15 +3,30 @@ extends Node2D
class_name GameMap class_name GameMap
var debug_areas = false
var ship_direction = 0 var ship_direction = 0
var ship_speed = 0 var ship_speed = 0
var current_ship_direction = 0 var current_ship_position = Vector2.ZERO
var current_ship_speed = 0 var current_ship_subpos = Vector2.ZERO
var current_ship_target = Vector2.ZERO
const SPEED_EASE = 0.5 var current_ship_direction = 0.0
const DIRECTION_EASE = 0.5 var current_ship_speed = 0.0
const EPSILON = 0.01
puppet var pup_ship_position = Vector2.ZERO
puppet var pup_ship_subpos = Vector2.ZERO
puppet var pup_ship_target = Vector2.ZERO
puppet var pup_ship_direction = 0.0
puppet var pup_ship_speed = 0.0
const MAX_ACCELERATION = 0.03
const MAX_STEERING = 0.06
const EPSILON = 1e-3
const SCROLL_MULTIPLIER = 1e4
const ENGINE_MULTIPLIER = 5000
const NO_SPEED_THRESHOLD = 0.01
const ProbeElectricity = preload("res://Actors/Systems/Electricity/ElectricProbe.tscn") const ProbeElectricity = preload("res://Actors/Systems/Electricity/ElectricProbe.tscn")
@ -28,27 +43,191 @@ func _ready():
if Engine.editor_hint: if Engine.editor_hint:
return return
$editor.queue_free() $editor.queue_free()
set_unlit(false) set_unlit(true)
if not is_network_master():
return
# Run autotile conversions and generate occlusions
$walls.run_conversions()
# Electricity setup # Electricity setup
make_electric_probes($cables, "Wire") make_electric_probes($cables, "Wire")
# Set engines to expected power level
set_engine_strength(current_ship_speed)
func _process(delta: float): func _process(delta: float):
if Engine.editor_hint: if Engine.editor_hint:
return return
var engines = get_engine_count()
var max_speed = get_max_speed()
# Ease ship speed/direction changes # Ease ship speed/direction changes
if abs(ship_direction - current_ship_direction) < EPSILON: if abs(current_ship_direction) > PI*2:
current_ship_direction -= PI*2 * sign(current_ship_direction)
var direction_delta = ship_direction - current_ship_direction
if direction_delta < 0:
direction_delta += PI*2
if direction_delta > PI:
direction_delta -= PI*2
if abs(direction_delta) < 1e-3:
current_ship_direction = ship_direction current_ship_direction = ship_direction
else: else:
current_ship_direction = lerp(current_ship_direction, ship_direction, delta * DIRECTION_EASE) # Avoid stuttering by not turning until there's enough reason to
if abs(ship_speed - current_ship_speed) < EPSILON: if abs(direction_delta) > 0.1:
current_ship_direction += MAX_STEERING * engines * delta * sign(direction_delta)
var speed_delta = ship_speed - current_ship_speed
if abs(speed_delta) < EPSILON:
current_ship_speed = ship_speed current_ship_speed = ship_speed
else: else:
current_ship_speed = lerp(current_ship_speed, ship_speed, delta * SPEED_EASE) current_ship_speed += MAX_ACCELERATION * max_speed * delta * sign(speed_delta)
set_engine_strength(current_ship_speed) set_engine_strength(current_ship_speed * ENGINE_MULTIPLIER)
$deepspace.rotation = current_ship_direction-PI/2
$deepspace.region_rect.position += Vector2(sin(current_ship_direction), cos(current_ship_direction)) * current_ship_speed * delta $deepspace.rotation = -current_ship_direction-PI/2
$deepspace.region_rect.position += Vector2(-sin(current_ship_direction), cos(current_ship_direction)) * current_ship_speed * SCROLL_MULTIPLIER * delta
func _physics_process(delta):
if Engine.editor_hint:
return
if is_network_master():
var adj_position = current_ship_position+current_ship_subpos
if current_ship_target != null:
var distance = adj_position.distance_to(current_ship_target)
if distance > NO_SPEED_THRESHOLD:
ship_direction = current_ship_target.angle_to_point(adj_position)
var max_speed = get_max_speed()
if max_speed > 0:
var deceleration_time = current_ship_speed / (MAX_ACCELERATION * max_speed)
if current_ship_speed * deceleration_time < distance:
ship_speed = max_speed
else:
ship_speed = 0.0
else:
ship_speed = 0.0
rset("pup_ship_direction", ship_direction)
rset("pup_ship_speed", ship_speed)
else:
ship_speed = 0.0
rset("pup_ship_speed", ship_speed)
if current_ship_speed > EPSILON:
var pos_delta = (Vector2.RIGHT * current_ship_speed * delta).rotated(current_ship_direction)
current_ship_subpos += pos_delta
if current_ship_subpos.x >= 1.0:
var int_part = floor(current_ship_subpos.x)
current_ship_position.x += int_part
current_ship_subpos.x -= int_part
if current_ship_subpos.y >= 1.0:
var int_part = floor(current_ship_subpos.y)
current_ship_position.y += int_part
current_ship_subpos.y -= int_part
rset("pup_ship_position", current_ship_position)
rset("pup_ship_subpos", current_ship_subpos)
else:
ship_speed = 0.0
rset("pup_ship_speed", ship_speed)
else:
ship_direction = pup_ship_direction
ship_speed = pup_ship_speed
current_ship_position = pup_ship_position
current_ship_subpos = pup_ship_subpos
func get_engine_count():
var working_engines = 0
for child in $engines.get_children():
var engine = child as GameObjectEngine
if engine.force > 0:
working_engines += 1
return working_engines
func get_max_speed():
var max_speed = 0
for child in $engines.get_children():
var engine = child as GameObjectEngine
max_speed += engine.force
return max_speed
# Serialization / Deserialization
func serialize() -> Dictionary:
# Get tilemap data
var tilemapdata = {}
for tilemap in tilemaps:
var data = []
for cell in tilemap.get_used_cells():
data.append([cell, tilemap.get_cellv(cell)])
tilemapdata[tilemap.name] = data
return {
"tilemaps": tilemapdata,
"engines": serialize_children($engines),
"objects": serialize_children($objects),
"lights": serialize_children($lights),
"sockets": serialize_children($sockets),
"pois": serialize_children($pois),
"areas": serialize_children($areas),
"ship": {
"position": current_ship_position,
"target": current_ship_target,
"set_speed": ship_speed,
"set_direction": ship_direction,
"speed": current_ship_speed,
"direction": current_ship_direction
}
}
func deserialize(data: Dictionary) -> void:
# Create maps
for tilemap in data["tilemaps"]:
var tilemap_node = get_node(tilemap) as TileMap
for tile in data["tilemaps"][tilemap]:
tilemap_node.set_cellv(tile[0], tile[1])
tilemap_node.update_bitmask_region()
tilemap_node.update_dirty_quadrants()
# Create objects
deserialize_children($engines, data["engines"])
deserialize_children($objects, data["objects"])
deserialize_children($lights, data["lights"])
deserialize_children($pois, data["pois"])
deserialize_children($sockets, data["sockets"])
deserialize_children($sockets, data["sockets"])
deserialize_children($areas, data["areas"], true)
# Set ship parameters
current_ship_position = data["ship"]["position"]
current_ship_target = data["ship"]["target"]
ship_speed = data["ship"]["set_speed"]
ship_direction = data["ship"]["set_direction"]
current_ship_speed = data["ship"]["speed"]
current_ship_direction = data["ship"]["direction"]
# Run autotile conversions and generate occlusions
$walls.run_conversions()
func serialize_children(node: Node) -> Dictionary:
var data = {}
for child in node.get_children():
data[child.name] = {
"filename": child.filename,
"data": child.serialize(),
"transform": child.transform
}
return data
func deserialize_children(node: Node, data: Dictionary, deserialize_first: bool = false) -> void:
for node_name in data:
var node_data = data[node_name] as Dictionary
var node_scene = load(node_data.filename).instance()
node_scene.name = node_name
node_scene.transform = node_data.transform
if deserialize_first:
node_scene.deserialize(node_data.data)
node.add_child(node_scene, true)
if not deserialize_first:
node_scene.deserialize(node_data.data)
# Lighting # Lighting

View file

@ -1,17 +0,0 @@
extends TileMap
const objects = {
"Door": preload("res://Actors/Objects/Door/Door.tscn")
}
func _ready():
for cell in get_used_cells():
var id = get_cellv(cell)
var name = tile_set.tile_get_name(id)
if objects.has(name):
var obj = objects[name].instance() as Node2D
add_child(obj)
obj.transform.origin = map_to_world(cell)
else:
print("Placed object tile ", name, " at ", cell, " but has no object associated!")
set_cellv(cell, -1)

107
Scenes/Maps/empty.tscn Normal file
View file

@ -0,0 +1,107 @@
[gd_scene load_steps=10 format=2]
[ext_resource path="res://Graphics/tgstation/walls.tres" type="TileSet" id=1]
[ext_resource path="res://Graphics/tgstation/1x1.tres" type="TileSet" id=2]
[ext_resource path="res://Scenes/Rendering/MapTiles.gd" type="Script" id=3]
[ext_resource path="res://Scenes/Map.gd" type="Script" id=4]
[ext_resource path="res://Graphics/space.png" type="Texture" id=7]
[ext_resource path="res://Graphics/tgstation/floor.tres" type="TileSet" id=9]
[ext_resource path="res://Graphics/tgstation/base.tres" type="TileSet" id=11]
[ext_resource path="res://Graphics/tgstation/cables.tres" type="TileSet" id=13]
[sub_resource type="CanvasItemMaterial" id=1]
light_mode = 1
[node name="map" type="Node2D"]
script = ExtResource( 4 )
[node name="darkness" type="CanvasModulate" parent="."]
visible = false
color = Color( 0, 0, 0, 1 )
[node name="editor" type="Node2D" parent="."]
[node name="deepspace" type="Sprite" parent="."]
material = SubResource( 1 )
texture = ExtResource( 7 )
region_enabled = true
region_rect = Rect2( 0, 0, 10000, 10000 )
__meta__ = {
"_edit_group_": true,
"_edit_lock_": true
}
[node name="base" type="TileMap" parent="."]
z_index = 1
z_as_relative = false
tile_set = ExtResource( 11 )
cell_size = Vector2( 32, 32 )
cell_quadrant_size = 32
occluder_light_mask = -2147483647
format = 1
[node name="cables" type="TileMap" parent="."]
z_index = 2
z_as_relative = false
tile_set = ExtResource( 13 )
cell_size = Vector2( 32, 32 )
cell_quadrant_size = 32
occluder_light_mask = -2147483647
format = 1
[node name="floor" type="TileMap" parent="."]
z_index = 3
z_as_relative = false
tile_set = ExtResource( 9 )
cell_size = Vector2( 32, 32 )
cell_quadrant_size = 32
occluder_light_mask = -2147483647
format = 1
[node name="walls" type="TileMap" parent="."]
z_index = 4
z_as_relative = false
tile_set = ExtResource( 1 )
cell_size = Vector2( 32, 32 )
cell_quadrant_size = 32
occluder_light_mask = -2147483647
format = 1
script = ExtResource( 3 )
extended_tilemap_node = NodePath("../1x1")
[node name="1x1" type="TileMap" parent="."]
z_index = 5
z_as_relative = false
tile_set = ExtResource( 2 )
cell_size = Vector2( 16, 16 )
format = 1
[node name="engines" type="Node2D" parent="."]
modulate = Color( 0.980392, 0.980392, 0.980392, 1 )
__meta__ = {
"_edit_group_": true,
"_edit_lock_": true
}
[node name="objects" type="Node2D" parent="."]
z_index = 10
__meta__ = {
"_editor_description_": ""
}
[node name="sockets" type="Node2D" parent="."]
z_index = 2
z_as_relative = false
[node name="lights" type="Node2D" parent="."]
modulate = Color( 0.980392, 0.980392, 0.980392, 1 )
z_index = 11
__meta__ = {
"_edit_group_": true,
"_edit_lock_": true
}
[node name="pois" type="Node2D" parent="."]
z_index = 999
[node name="areas" type="Node2D" parent="."]

View file

@ -1,9 +0,0 @@
extends GameMap
func _ready():
tilemaps = [
$base,
$cables,
$floor,
$walls
]

File diff suppressed because one or more lines are too long

View file

@ -1,4 +0,0 @@
extends GameMap
func _ready():
set_unlit(true)

View file

@ -4,21 +4,28 @@
[ext_resource path="res://Graphics/tgstation/1x1.tres" type="TileSet" id=2] [ext_resource path="res://Graphics/tgstation/1x1.tres" type="TileSet" id=2]
[ext_resource path="res://Scenes/Rendering/MapTiles.gd" type="Script" id=3] [ext_resource path="res://Scenes/Rendering/MapTiles.gd" type="Script" id=3]
[ext_resource path="res://Graphics/tgstation/cables.tres" type="TileSet" id=4] [ext_resource path="res://Graphics/tgstation/cables.tres" type="TileSet" id=4]
[ext_resource path="res://Scenes/Maps/runtime.gd" type="Script" id=5] [ext_resource path="res://Actors/Meta/POI/POI.tscn" type="PackedScene" id=5]
[ext_resource path="res://Actors/Objects/Computer/Computer.tscn" type="PackedScene" id=6] [ext_resource path="res://Actors/Objects/Computer/Computer.tscn" type="PackedScene" id=6]
[ext_resource path="res://Graphics/space.png" type="Texture" id=7] [ext_resource path="res://Graphics/space.png" type="Texture" id=7]
[ext_resource path="res://Actors/Meta/POI/Spawnpoints/Player.gd" type="Script" id=8]
[ext_resource path="res://Graphics/tgstation/floor.tres" type="TileSet" id=9] [ext_resource path="res://Graphics/tgstation/floor.tres" type="TileSet" id=9]
[ext_resource path="res://Actors/Objects/Engine/Engine.tscn" type="PackedScene" id=10] [ext_resource path="res://Actors/Objects/Engine/Engine.tscn" type="PackedScene" id=10]
[ext_resource path="res://Graphics/tgstation/base.tres" type="TileSet" id=11] [ext_resource path="res://Graphics/tgstation/base.tres" type="TileSet" id=11]
[ext_resource path="res://Actors/Objects/PowerStorage/PowerStorage.tscn" type="PackedScene" id=12] [ext_resource path="res://Actors/Objects/PowerStorage/PowerStorage.tscn" type="PackedScene" id=12]
[ext_resource path="res://Actors/Objects/ElectricSocket/ElectricSocket.tscn" type="PackedScene" id=13] [ext_resource path="res://Actors/Objects/ElectricSocket/ElectricSocket.tscn" type="PackedScene" id=13]
[sub_resource type="CanvasItemMaterial" id=1] [sub_resource type="GDScript" id=1]
script/source = "extends GameMap
func _ready():
set_unlit(true)
"
[sub_resource type="CanvasItemMaterial" id=2]
light_mode = 1 light_mode = 1
[node name="map" type="Node2D"] [node name="map" type="Node2D"]
script = ExtResource( 5 ) z_as_relative = false
script = SubResource( 1 )
[node name="darkness" type="CanvasModulate" parent="."] [node name="darkness" type="CanvasModulate" parent="."]
visible = false visible = false
@ -27,7 +34,7 @@ color = Color( 0, 0, 0, 1 )
[node name="editor" type="Node2D" parent="."] [node name="editor" type="Node2D" parent="."]
[node name="deepspace" type="Sprite" parent="."] [node name="deepspace" type="Sprite" parent="."]
material = SubResource( 1 ) material = SubResource( 2 )
texture = ExtResource( 7 ) texture = ExtResource( 7 )
region_enabled = true region_enabled = true
region_rect = Rect2( 0, 0, 10000, 10000 ) region_rect = Rect2( 0, 0, 10000, 10000 )
@ -38,6 +45,7 @@ __meta__ = {
[node name="base" type="TileMap" parent="."] [node name="base" type="TileMap" parent="."]
z_index = 1 z_index = 1
z_as_relative = false
tile_set = ExtResource( 11 ) tile_set = ExtResource( 11 )
cell_size = Vector2( 32, 32 ) cell_size = Vector2( 32, 32 )
cell_quadrant_size = 32 cell_quadrant_size = 32
@ -47,6 +55,7 @@ tile_data = PoolIntArray( 262137, 0, 0, 262138, 0, 0, 262139, 0, 0, 262140, 0, 0
[node name="cables" type="TileMap" parent="."] [node name="cables" type="TileMap" parent="."]
z_index = 2 z_index = 2
z_as_relative = false
tile_set = ExtResource( 4 ) tile_set = ExtResource( 4 )
cell_size = Vector2( 32, 32 ) cell_size = Vector2( 32, 32 )
cell_quadrant_size = 32 cell_quadrant_size = 32
@ -56,6 +65,7 @@ tile_data = PoolIntArray( 393212, 0, 131072, 393213, 0, 65536, 393214, 0, 65536,
[node name="floor" type="TileMap" parent="."] [node name="floor" type="TileMap" parent="."]
z_index = 3 z_index = 3
z_as_relative = false
tile_set = ExtResource( 9 ) tile_set = ExtResource( 9 )
cell_size = Vector2( 32, 32 ) cell_size = Vector2( 32, 32 )
cell_quadrant_size = 32 cell_quadrant_size = 32
@ -64,6 +74,7 @@ format = 1
[node name="walls" type="TileMap" parent="."] [node name="walls" type="TileMap" parent="."]
z_index = 4 z_index = 4
z_as_relative = false
tile_set = ExtResource( 1 ) tile_set = ExtResource( 1 )
cell_size = Vector2( 32, 32 ) cell_size = Vector2( 32, 32 )
cell_quadrant_size = 32 cell_quadrant_size = 32
@ -75,6 +86,7 @@ extended_tilemap_node = NodePath("../1x1")
[node name="1x1" type="TileMap" parent="."] [node name="1x1" type="TileMap" parent="."]
z_index = 5 z_index = 5
z_as_relative = false
tile_set = ExtResource( 2 ) tile_set = ExtResource( 2 )
cell_size = Vector2( 16, 16 ) cell_size = Vector2( 16, 16 )
format = 1 format = 1
@ -134,44 +146,48 @@ position = Vector2( 128, 128 )
position = Vector2( 64, 128 ) position = Vector2( 64, 128 )
computer_type = 6 computer_type = 6
[node name="ElectricSocket4" parent="objects" instance=ExtResource( 13 )] [node name="sockets" type="Node2D" parent="."]
z_index = 2
z_as_relative = false
[node name="ElectricSocket4" parent="sockets" instance=ExtResource( 13 )]
position = Vector2( -128, 160 ) position = Vector2( -128, 160 )
connectionPaths = [ NodePath("../Computer6") ] connectionPaths = [ NodePath("../../objects/Computer6") ]
flow = 1 flow = 1
[node name="ElectricSocket5" parent="objects" instance=ExtResource( 13 )] [node name="ElectricSocket5" parent="sockets" instance=ExtResource( 13 )]
position = Vector2( -96, 160 ) position = Vector2( -96, 160 )
connectionPaths = [ NodePath("../Computer5") ] connectionPaths = [ NodePath("../../objects/Computer5") ]
flow = 1 flow = 1
[node name="ElectricSocket6" parent="objects" instance=ExtResource( 13 )] [node name="ElectricSocket6" parent="sockets" instance=ExtResource( 13 )]
position = Vector2( -64, 160 ) position = Vector2( -64, 160 )
connectionPaths = [ NodePath("../Computer") ] connectionPaths = [ NodePath("../../objects/Computer") ]
flow = 1 flow = 1
[node name="ElectricSocket7" parent="objects" instance=ExtResource( 13 )] [node name="ElectricSocket7" parent="sockets" instance=ExtResource( 13 )]
position = Vector2( -32, 160 ) position = Vector2( -32, 160 )
connectionPaths = [ NodePath("../Computer2") ] connectionPaths = [ NodePath("../../objects/Computer2") ]
flow = 1 flow = 1
[node name="ElectricSocket8" parent="objects" instance=ExtResource( 13 )] [node name="ElectricSocket8" parent="sockets" instance=ExtResource( 13 )]
position = Vector2( 0, 160 ) position = Vector2( 0, 160 )
connectionPaths = [ NodePath("../Computer3") ] connectionPaths = [ NodePath("../../objects/Computer3") ]
flow = 1 flow = 1
[node name="ElectricSocket9" parent="objects" instance=ExtResource( 13 )] [node name="ElectricSocket9" parent="sockets" instance=ExtResource( 13 )]
position = Vector2( 32, 160 ) position = Vector2( 32, 160 )
connectionPaths = [ NodePath("../Computer4") ] connectionPaths = [ NodePath("../../objects/Computer4") ]
flow = 1 flow = 1
[node name="ElectricSocket10" parent="objects" instance=ExtResource( 13 )] [node name="ElectricSocket10" parent="sockets" instance=ExtResource( 13 )]
position = Vector2( 64, 160 ) position = Vector2( 64, 160 )
connectionPaths = [ NodePath("../Computer7") ] connectionPaths = [ NodePath("../../objects/Computer7") ]
flow = 1 flow = 1
[node name="ElectricSocket3" parent="objects" instance=ExtResource( 13 )] [node name="ElectricSocket3" parent="sockets" instance=ExtResource( 13 )]
position = Vector2( 128, 160 ) position = Vector2( 128, 160 )
connectionPaths = [ NodePath("../SMES2") ] connectionPaths = [ NodePath("../../objects/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 )
@ -183,6 +199,5 @@ __meta__ = {
[node name="pois" type="Node2D" parent="."] [node name="pois" type="Node2D" parent="."]
z_index = 999 z_index = 999
[node name="SpawnpointPlayer" type="Node2D" parent="pois"] [node name="SpawnpointPlayer" parent="pois" instance=ExtResource( 5 )]
position = Vector2( 112, 272 ) position = Vector2( 80, 272 )
script = ExtResource( 8 )

View file

@ -1,42 +1,85 @@
extends Control extends Control
export var scale = 2 setget set_scale const REFRESH_SERVER_DELAY = 5.0
export var upThreshold = 1.0/Engine.iterations_per_second
export var scale = 4 setget set_scale
export var upThreshold = 1.0/59.0
export var downThreshold = 1.0/30.0 export var downThreshold = 1.0/30.0
export var delay = 1.0 export var delay = 1.0
export var refresh_server_remaining = REFRESH_SERVER_DELAY
func _ready(): onready var viewport = $Viewport
onready var background = $Background
onready var netgame = $"/root/Multiplayer"
onready var server_list = $Popup/MarginContainer/VBoxContainer/ItemList
onready var name_field = $CenterContainer/PanelContainer/HBoxContainer/HBoxContainer/NameField
var servers = []
func _ready() -> void:
name_field.text = netgame.player_name
set_scale(scale) set_scale(scale)
$"/root/Music/BGM".play() $"/root/Music/BGM".play()
netgame.connect("ms_updated", self, "_ms_update")
request_servers()
func _process(delta): func _process(delta: float) -> void:
refresh_server_remaining -= delta
if refresh_server_remaining <= 0:
request_servers()
refresh_server_remaining = REFRESH_SERVER_DELAY
# Give the system time to adjust # Give the system time to adjust
if delay > 0: if delay > 0:
delay -= delta delay -= delta
return return
if delta > downThreshold: if delta > downThreshold:
print("GPU is taking too much (", delta, "s < ", downThreshold, "s), adjusting shader scale") print("GPU is taking too much (%ss > %ss), adjusting shader scale" % [ delta, downThreshold ])
set_scale(scale+1) set_scale(scale+1)
elif delta < upThreshold and scale > 2: elif delta < upThreshold and scale > 2:
print("GPU is taking it easy (", delta, "s < ", upThreshold, "s), adjusting shader scale") print("GPU is taking it easy (%ss < %ss), adjusting shader scale" % [ delta, upThreshold ])
set_scale(scale-1) set_scale(scale-1)
func set_scale(val): func request_servers():
netgame.ms_get_entries()
const server_list_format = "{name} ({address}) - {players}/{max_players} players"
func _ms_update(action, result):
if action == "list_games":
# Reset server list
server_list.clear()
servers = result
for server in servers:
server.data.address = server.address
server_list.add_item(server_list_format.format(server.data))
func set_scale(val) -> void:
scale = val scale = val
$Viewport.size = rect_size / scale if viewport:
$Background.update() viewport.size = rect_size / scale
background.update()
func _on_resized(): func _on_resized() -> void:
$Viewport.size = rect_size / scale if viewport:
$Background.update() viewport.size = rect_size / scale
background.update()
func _host_pressed(): func _host_pressed() -> void:
$"/root/Music/BGM".stop()
$"/root/Multiplayer".host() $"/root/Multiplayer".host()
func _join_pressed(): func _join_pressed() -> void:
pass $Popup.popup_centered_ratio()
func _server_addr_changed(new_text: String): func join_server(server) -> void:
$CenterContainer/PanelContainer/HBoxContainer/JoinButton.disabled = new_text.length() < 1 $"/root/Music/BGM".stop()
netgame.join(server)
func _server_addr_changed(new_text: String) -> void:
$Popup/MarginContainer/VBoxContainer/HBoxContainer/Button.disabled = new_text.length() < 1
func _manual_join_pressed():
join_server({ "address": $Popup/MarginContainer/VBoxContainer/HBoxContainer/LineEdit.text })
func _server_item_clicked(index):
$"/root/Music/BGM".stop()
join_server(servers[index])

View file

@ -1,9 +1,10 @@
[gd_scene load_steps=10 format=2] [gd_scene load_steps=13 format=2]
[ext_resource path="res://Scenes/Menu.gd" type="Script" id=1] [ext_resource path="res://Scenes/Menu.gd" type="Script" id=1]
[ext_resource path="res://Graphics/UI/Background.shader" type="Shader" id=2] [ext_resource path="res://Graphics/UI/Background.shader" type="Shader" id=2]
[ext_resource path="res://Graphics/UI/logo-temp-pixel.png" type="Texture" id=3] [ext_resource path="res://Graphics/UI/logo-temp-pixel.png" type="Texture" id=3]
[ext_resource path="res://Graphics/UI/ui_theme.tres" type="Theme" id=4] [ext_resource path="res://Graphics/UI/ui_theme.tres" type="Theme" id=4]
[ext_resource path="res://Graphics/UI/iosevka-aile-regular.ttf" type="DynamicFontData" id=5]
[sub_resource type="ViewportTexture" id=1] [sub_resource type="ViewportTexture" id=1]
viewport_path = NodePath("Viewport") viewport_path = NodePath("Viewport")
@ -15,26 +16,14 @@ void fragment() {
vec4 tex = texture(TEXTURE, UV); vec4 tex = texture(TEXTURE, UV);
COLOR = vec4(tex.rgb * 0., tex.a * 0.5); COLOR = vec4(tex.rgb * 0., tex.a * 0.5);
}" }"
custom_defines = ""
[sub_resource type="ShaderMaterial" id=3] [sub_resource type="ShaderMaterial" id=3]
shader = SubResource( 2 ) shader = SubResource( 2 )
[sub_resource type="ShaderMaterial" id=4] [sub_resource type="ShaderMaterial" id=4]
shader = ExtResource( 2 ) shader = ExtResource( 2 )
shader_param/iterations = 17
shader_param/formuparam = 0.53
shader_param/volsteps = 20
shader_param/stepsize = 0.1
shader_param/zoom = 0.8
shader_param/tile = 0.85
shader_param/speed = 0.001 shader_param/speed = 0.001
shader_param/brightness = 0.0015 shader_param/zoom = 0.8
shader_param/darkmatter = 0.3
shader_param/distfading = 0.73
shader_param/saturation = 0.85
shader_param/rotx = 0.0
shader_param/roty = 0.001
[sub_resource type="StyleBoxFlat" id=5] [sub_resource type="StyleBoxFlat" id=5]
content_margin_left = 16.0 content_margin_left = 16.0
@ -46,12 +35,24 @@ border_width_left = 4
border_width_top = 4 border_width_top = 4
border_width_right = 4 border_width_right = 4
border_width_bottom = 4 border_width_bottom = 4
border_color = Color( 0.27301, 0.417506, 0.984375, 0.392157 ) border_color = Color( 0.27451, 0.415686, 0.984314, 0.392157 )
corner_radius_top_left = 4 corner_radius_top_left = 4
corner_radius_top_right = 4 corner_radius_top_right = 4
corner_radius_bottom_right = 4 corner_radius_bottom_right = 4
corner_radius_bottom_left = 4 corner_radius_bottom_left = 4
[sub_resource type="DynamicFont" id=6]
size = 20
extra_spacing_top = 5
extra_spacing_bottom = 5
font_data = ExtResource( 5 )
[sub_resource type="DynamicFont" id=7]
size = 20
extra_spacing_top = 10
extra_spacing_bottom = 10
font_data = ExtResource( 5 )
[node name="Control" type="Control"] [node name="Control" type="Control"]
anchor_right = 1.0 anchor_right = 1.0
anchor_bottom = 1.0 anchor_bottom = 1.0
@ -126,9 +127,9 @@ __meta__ = {
[node name="PanelContainer" type="PanelContainer" parent="CenterContainer"] [node name="PanelContainer" type="PanelContainer" parent="CenterContainer"]
margin_left = 390.0 margin_left = 390.0
margin_top = 43.0 margin_top = 8.0
margin_right = 690.0 margin_right = 690.0
margin_bottom = 207.0 margin_bottom = 241.0
rect_min_size = Vector2( 300, 0 ) rect_min_size = Vector2( 300, 0 )
custom_styles/panel = SubResource( 5 ) custom_styles/panel = SubResource( 5 )
@ -136,41 +137,160 @@ custom_styles/panel = SubResource( 5 )
margin_left = 16.0 margin_left = 16.0
margin_top = 20.0 margin_top = 20.0
margin_right = 284.0 margin_right = 284.0
margin_bottom = 144.0 margin_bottom = 213.0
custom_constants/separation = 10 custom_constants/separation = 10
[node name="HostButton" type="Button" parent="CenterContainer/PanelContainer/HBoxContainer"] [node name="HBoxContainer" type="HBoxContainer" parent="CenterContainer/PanelContainer/HBoxContainer"]
margin_right = 268.0 margin_right = 268.0
margin_bottom = 24.0 margin_bottom = 28.0
custom_constants/separation = 10
__meta__ = {
"_edit_use_anchors_": false
}
[node name="NameLabel" type="Label" parent="CenterContainer/PanelContainer/HBoxContainer/HBoxContainer"]
margin_top = 5.0
margin_right = 34.0
margin_bottom = 23.0
theme = ExtResource( 4 ) theme = ExtResource( 4 )
text = "Name"
[node name="NameField" type="LineEdit" parent="CenterContainer/PanelContainer/HBoxContainer/HBoxContainer"]
margin_left = 44.0
margin_right = 268.0
margin_bottom = 28.0
size_flags_horizontal = 3
theme = ExtResource( 4 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Panel" type="Panel" parent="CenterContainer/PanelContainer/HBoxContainer"]
margin_top = 38.0
margin_right = 268.0
margin_bottom = 43.0
rect_min_size = Vector2( 0, 5 )
[node name="HostButton" type="Button" parent="CenterContainer/PanelContainer/HBoxContainer"]
margin_top = 53.0
margin_right = 268.0
margin_bottom = 95.0
theme = ExtResource( 4 )
custom_fonts/font = SubResource( 6 )
text = "Start a new game" text = "Start a new game"
[node name="Label" type="Label" parent="CenterContainer/PanelContainer/HBoxContainer"] [node name="Label" type="Label" parent="CenterContainer/PanelContainer/HBoxContainer"]
margin_top = 34.0 margin_top = 105.0
margin_right = 268.0 margin_right = 268.0
margin_bottom = 52.0 margin_bottom = 141.0
theme = ExtResource( 4 ) theme = ExtResource( 4 )
custom_fonts/font = SubResource( 6 )
text = "or" text = "or"
align = 1 align = 1
__meta__ = { __meta__ = {
"_edit_use_anchors_": false "_edit_use_anchors_": false
} }
[node name="ServerAddr" type="LineEdit" parent="CenterContainer/PanelContainer/HBoxContainer"]
margin_top = 62.0
margin_right = 268.0
margin_bottom = 90.0
theme = ExtResource( 4 )
placeholder_text = "Server address or URL"
[node name="JoinButton" type="Button" parent="CenterContainer/PanelContainer/HBoxContainer"] [node name="JoinButton" type="Button" parent="CenterContainer/PanelContainer/HBoxContainer"]
margin_top = 100.0 margin_top = 151.0
margin_right = 268.0 margin_right = 268.0
margin_bottom = 124.0 margin_bottom = 193.0
theme = ExtResource( 4 ) theme = ExtResource( 4 )
disabled = true custom_fonts/font = SubResource( 6 )
text = "Join an existing game" text = "Join an existing game"
[node name="Popup" type="PopupDialog" parent="."]
anchor_right = 1.0
anchor_bottom = 1.0
margin_left = 100.0
margin_top = 100.0
margin_right = -100.0
margin_bottom = -100.0
custom_styles/panel = SubResource( 5 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="MarginContainer" type="MarginContainer" parent="Popup"]
anchor_right = 1.0
anchor_bottom = 1.0
margin_left = 20.0
margin_top = 20.0
margin_right = -20.0
margin_bottom = -20.0
__meta__ = {
"_edit_use_anchors_": false
}
[node name="VBoxContainer" type="VBoxContainer" parent="Popup/MarginContainer"]
margin_right = 1040.0
margin_bottom = 560.0
custom_constants/separation = 5
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Label" type="Label" parent="Popup/MarginContainer/VBoxContainer"]
margin_right = 1040.0
margin_bottom = 36.0
custom_fonts/font = SubResource( 6 )
text = "Server Browser"
__meta__ = {
"_edit_use_anchors_": false
}
[node name="ItemList" type="ItemList" parent="Popup/MarginContainer/VBoxContainer"]
margin_top = 41.0
margin_right = 1040.0
margin_bottom = 468.0
size_flags_vertical = 3
custom_fonts/font = SubResource( 7 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Label2" type="Label" parent="Popup/MarginContainer/VBoxContainer"]
margin_top = 473.0
margin_right = 1040.0
margin_bottom = 509.0
custom_fonts/font = SubResource( 6 )
text = "Join by IP/address"
__meta__ = {
"_edit_use_anchors_": false
}
[node name="HBoxContainer" type="HBoxContainer" parent="Popup/MarginContainer/VBoxContainer"]
margin_top = 514.0
margin_right = 1040.0
margin_bottom = 560.0
size_flags_horizontal = 3
custom_constants/separation = 10
[node name="LineEdit" type="LineEdit" parent="Popup/MarginContainer/VBoxContainer/HBoxContainer"]
margin_right = 300.0
margin_bottom = 46.0
rect_min_size = Vector2( 300, 0 )
custom_fonts/font = SubResource( 6 )
placeholder_text = "server.address"
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Button" type="Button" parent="Popup/MarginContainer/VBoxContainer/HBoxContainer"]
margin_left = 310.0
margin_right = 410.0
margin_bottom = 46.0
rect_min_size = Vector2( 100, 0 )
theme = ExtResource( 4 )
custom_fonts/font = SubResource( 6 )
disabled = true
text = "Join"
__meta__ = {
"_edit_use_anchors_": false
}
[connection signal="resized" from="." to="." method="_on_resized"] [connection signal="resized" from="." to="." method="_on_resized"]
[connection signal="pressed" from="CenterContainer/PanelContainer/HBoxContainer/HostButton" to="." method="_host_pressed"] [connection signal="pressed" from="CenterContainer/PanelContainer/HBoxContainer/HostButton" to="." method="_host_pressed"]
[connection signal="text_changed" from="CenterContainer/PanelContainer/HBoxContainer/ServerAddr" to="." method="_server_addr_changed"]
[connection signal="pressed" from="CenterContainer/PanelContainer/HBoxContainer/JoinButton" to="." method="_join_pressed"] [connection signal="pressed" from="CenterContainer/PanelContainer/HBoxContainer/JoinButton" to="." method="_join_pressed"]
[connection signal="item_activated" from="Popup/MarginContainer/VBoxContainer/ItemList" to="." method="_server_item_clicked"]
[connection signal="text_changed" from="Popup/MarginContainer/VBoxContainer/HBoxContainer/LineEdit" to="." method="_server_addr_changed"]
[connection signal="pressed" from="Popup/MarginContainer/VBoxContainer/HBoxContainer/Button" to="." method="_manual_join_pressed"]

View file

@ -12,7 +12,7 @@ export var shadow_intensity = 0.2
onready var extended_tilemap = get_node(extended_tilemap_node) as TileMap onready var extended_tilemap = get_node(extended_tilemap_node) as TileMap
func _ready(): func run_conversions():
# Make occluders # Make occluders
make_occluders() make_occluders()

View file

@ -1,18 +1,195 @@
extends Control extends Control
signal command(command) class_name GameUI
enum ServerMenuItem { enum ServerMenuItem {
SERVER_INFO ServerInfo
} }
enum PopupName {
SpaceMap,
EnergyUsage
}
onready var logs = $Logs
onready var inspect_box = $InspectBox as RichTextLabel
onready var item_slots_container = $ItemSlots
onready var map_popup = $MapPopup
onready var sever_info_popup = $ServerInfoPopup
onready var scene = $"/root/scene"
onready var netgame = $"/root/Multiplayer"
const ItemBox = preload("res://Scenes/UI/Items/ItemBox.tscn")
var left_selected = null
var right_selected = null
const WHISPER_RADIUS = 32*3
const CHAT_RADIUS = 32*10
const SHOUT_RADIUS = 32*14
var inspect_mode = false
var current_inspecting = null
func _ready() -> void: func _ready() -> void:
# Add options to menu buttons # Add options to menu buttons
var serverMenu = $Menu/Margins/Grid/Server.get_popup() var serverMenu = $Menu/Margins/Grid/Server.get_popup()
serverMenu.connect("id_pressed", self, "_server_option_chosen") serverMenu.connect("id_pressed", self, "_server_option_chosen")
serverMenu.add_item("Server info", ServerMenuItem.SERVER_INFO) serverMenu.add_item("Server info", ServerMenuItem.ServerInfo)
# Create item slots
for slot_id in range(4):
var item_slot = ItemBox.instance()
# By default, slot 2/3 are L/R, and 2 is selected
match slot_id:
1:
item_slot.selected = true
item_slot.current_hand = UIItemBox.CurrentHand.Left
left_selected = item_slot
2:
item_slot.current_hand = UIItemBox.CurrentHand.Right
right_selected = item_slot
# Connect signals
item_slot.connect("selected", self, "_itembox_selected", [item_slot])
item_slot.connect("used_in_hand", self, "_itembox_used", [item_slot])
item_slots_container.add_child(item_slot)
func _physics_process(_delta: float) -> void:
if inspect_mode:
var mouse_pos = scene.world.get_local_mouse_position() * scene.world.scale
var results = scene.physics.intersect_point(mouse_pos, 1, [], 2)
if results.size() > 0:
var obj = results[0].collider
if obj != current_inspecting:
current_inspecting = obj
if obj.has_method("inspect"):
var data = obj.inspect()
inspect_box.bbcode_text = ""
inspect_box.rect_size.y = 0
if "object_name" in obj and obj.object_name != "":
inspect_box.append_bbcode("[b]%s[/b] (%s)" % [obj.object_name, data.type])
else:
inspect_box.append_bbcode("A [b]%s[/b]" % data.type)
if "description" in data:
inspect_box.append_bbcode("\n" + data.description)
if "interaction" in data:
inspect_box.append_bbcode("\n\n[i]%s[/i]" % data.interaction)
inspect_box.visible = true
else:
current_inspecting = null
inspect_box.visible = false
func _server_option_chosen(id) -> void: func _server_option_chosen(id) -> void:
match id: match id:
ServerMenuItem.SERVER_INFO: ServerMenuItem.ServerInfo:
$ServerInfoPopup.popup_centered() $ServerInfoPopup.popup_centered()
func open_popup(popup_name) -> void:
match popup_name:
PopupName.SpaceMap:
$MapPopup.popup_centered_ratio()
PopupName.EnergyUsage:
pass
func close_popup(popup_name) -> void:
match popup_name:
PopupName.SpaceMap:
$MapPopup.visible = false
PopupName.EnergyUsage:
pass
const say_format = "%s says \"%s\"\n"
const ask_format = "%s asks \"%s\"\n"
const shout_format = "%s shouts \"[b]%s[/b]\"\n"
const whisper_format = "[i]%s whispers \"%s\"[/i]\n"
func _send_chat(text: String) -> void:
var escaped_text = text.replace("[", "[\u8203").strip_edges() # Hacky way to escape BBCode
if text.ends_with("?"):
scene.rpc("broadcast_zone", ask_format % [netgame.player_name, escaped_text], scene.world.player.global_position, SHOUT_RADIUS)
if text.ends_with("!!"):
scene.rpc("broadcast_zone", shout_format % [netgame.player_name, escaped_text], scene.world.player.global_position, SHOUT_RADIUS)
elif text.begins_with("#"):
scene.rpc("broadcast_zone", whisper_format % [netgame.player_name, escaped_text.substr(1)], scene.world.player.global_position, WHISPER_RADIUS)
else:
scene.rpc("broadcast_zone", say_format % [netgame.player_name, escaped_text], scene.world.player.global_position, CHAT_RADIUS)
var inspect_offset = Vector2(20, 20)
func set_inspect(active: bool) -> void:
inspect_box.visible = inspect_box.visible and active
inspect_mode = active
inspect_box.rect_global_position = get_viewport().get_mouse_position() + inspect_offset
func _input(event: InputEvent) -> void:
var no_popups = not check_popups()
if event.is_action_released("inspect"):
set_inspect(false)
elif event.is_action_pressed("inspect"):
set_inspect(true)
elif event.is_action_pressed("ui_scroll_left") and no_popups:
select_next_box(-1, Input.is_action_pressed("alt_hand"))
elif event.is_action_pressed("ui_scroll_right") and no_popups:
select_next_box(1, Input.is_action_pressed("alt_hand"))
elif event.is_action_pressed("swap_hands"):
swap_hands()
elif event is InputEventMouseMotion:
var mousemotion = event as InputEventMouseMotion
if inspect_mode:
inspect_box.rect_global_position = mousemotion.position + inspect_offset
func _itembox_selected(hand, item_box: UIItemBox) -> void:
left_selected.selected = false
right_selected.selected = false
match hand:
UIItemBox.CurrentHand.Left:
if item_box.current_hand != UIItemBox.CurrentHand.None:
left_selected.current_hand = item_box.current_hand
match item_box.current_hand:
UIItemBox.CurrentHand.Right:
right_selected = left_selected
else:
left_selected.current_hand = UIItemBox.CurrentHand.None
left_selected = item_box
UIItemBox.CurrentHand.Right:
if item_box.current_hand != UIItemBox.CurrentHand.None:
right_selected.current_hand = item_box.current_hand
match item_box.current_hand:
UIItemBox.CurrentHand.Left:
left_selected = right_selected
else:
right_selected.current_hand = UIItemBox.CurrentHand.None
right_selected = item_box
item_box.selected = true
item_box.current_hand = hand
func _itembox_used(item_box) -> void:
pass
func check_popups() -> bool:
return map_popup.visible or sever_info_popup.visible
func select_next_box(direction: int, right_hand: bool) -> void:
var box = left_selected as UIItemBox
if right_hand:
box = right_selected
var parent = box.get_parent()
var child_count = parent.get_child_count()
var index = box.get_index()
index += direction
if index < 0:
index = child_count + index
elif index >= child_count:
index -= child_count
var hand = UIItemBox.CurrentHand.Left
if right_hand:
hand = UIItemBox.CurrentHand.Right
_itembox_selected(hand, parent.get_child(index))
func swap_hands() -> void:
if left_selected.selected:
_itembox_selected(UIItemBox.CurrentHand.Left, right_selected)
else:
_itembox_selected(UIItemBox.CurrentHand.Right, left_selected)

View file

@ -1,10 +1,49 @@
[gd_scene load_steps=5 format=2] [gd_scene load_steps=16 format=2]
[ext_resource path="res://Scenes/UI/SpaceMap.tscn" type="PackedScene" id=1] [ext_resource path="res://Scenes/UI/SpaceMap.tscn" type="PackedScene" id=1]
[ext_resource path="res://Scenes/UI.gd" type="Script" id=2] [ext_resource path="res://Scenes/UI.gd" type="Script" id=2]
[ext_resource path="res://Scenes/UI/Widgets/ResizablePanel.tscn" type="PackedScene" id=3] [ext_resource path="res://Graphics/UI/iosevka-aile-regular.ttf" type="DynamicFontData" id=3]
[ext_resource path="res://Scenes/UI/Panels/ServerInfo.tscn" type="PackedScene" id=4]
[ext_resource path="res://Scenes/UI/Widgets/ResizablePanel.tscn" type="PackedScene" id=5]
[ext_resource path="res://Scenes/UI/Panels/Logs.gd" type="Script" id=6]
[ext_resource path="res://Graphics/UI/iosevka-aile-italic.ttf" type="DynamicFontData" id=7]
[ext_resource path="res://Graphics/UI/iosevka-aile-bold.ttf" type="DynamicFontData" id=8]
[ext_resource path="res://Graphics/UI/iosevka-aile-bolditalic.ttf" type="DynamicFontData" id=9]
[sub_resource type="StyleBoxFlat" id=1] [sub_resource type="DynamicFont" id=1]
size = 14
use_mipmaps = true
font_data = ExtResource( 9 )
[sub_resource type="DynamicFont" id=2]
size = 14
use_mipmaps = true
font_data = ExtResource( 7 )
[sub_resource type="DynamicFont" id=3]
size = 14
use_mipmaps = true
font_data = ExtResource( 8 )
[sub_resource type="DynamicFont" id=4]
size = 14
use_mipmaps = true
font_data = ExtResource( 3 )
[sub_resource type="StyleBoxFlat" id=5]
bg_color = Color( 0.133333, 0.12549, 0.203922, 0.705882 )
border_width_left = 4
border_width_top = 4
border_width_right = 4
border_width_bottom = 4
border_color = Color( 0.0941176, 0.0823529, 0.180392, 1 )
border_blend = true
corner_radius_top_left = 4
corner_radius_top_right = 4
corner_radius_bottom_right = 4
corner_radius_bottom_left = 4
[sub_resource type="StyleBoxFlat" id=6]
bg_color = Color( 0.133333, 0.12549, 0.203922, 0.705882 ) bg_color = Color( 0.133333, 0.12549, 0.203922, 0.705882 )
border_width_left = 4 border_width_left = 4
border_width_top = 4 border_width_top = 4
@ -30,10 +69,53 @@ __meta__ = {
[node name="MapPopup" parent="." instance=ExtResource( 1 )] [node name="MapPopup" parent="." instance=ExtResource( 1 )]
[node name="Logs" parent="." instance=ExtResource( 3 )] [node name="Logs" type="Control" parent="."]
margin_right = 392.0 margin_left = 10.0
margin_bottom = 256.0 margin_top = 10.0
title = "Log" margin_right = 475.0
margin_bottom = 273.0
script = ExtResource( 6 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="ResizablePanel" parent="Logs" instance=ExtResource( 5 )]
title = "Logs"
[node name="RichTextLabel" type="RichTextLabel" parent="Logs/ResizablePanel"]
anchor_right = 1.0
anchor_bottom = 1.0
margin_left = 10.0
margin_top = 40.0
margin_right = -10.0
margin_bottom = -40.0
focus_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
custom_fonts/bold_italics_font = SubResource( 1 )
custom_fonts/italics_font = SubResource( 2 )
custom_fonts/bold_font = SubResource( 3 )
custom_fonts/normal_font = SubResource( 4 )
bbcode_enabled = true
selection_enabled = true
__meta__ = {
"_edit_use_anchors_": false
}
[node name="LineEdit" type="LineEdit" parent="Logs/ResizablePanel"]
anchor_top = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
margin_left = 6.0
margin_top = -30.0
margin_right = -16.0
margin_bottom = -6.0
focus_mode = 1
caret_blink = true
caret_blink_speed = 0.5
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Menu" type="PanelContainer" parent="."] [node name="Menu" type="PanelContainer" parent="."]
anchor_left = 1.0 anchor_left = 1.0
@ -46,7 +128,7 @@ grow_horizontal = 0
grow_vertical = 0 grow_vertical = 0
size_flags_horizontal = 8 size_flags_horizontal = 8
size_flags_vertical = 8 size_flags_vertical = 8
custom_styles/panel = SubResource( 1 ) custom_styles/panel = SubResource( 5 )
__meta__ = { __meta__ = {
"_edit_use_anchors_": false "_edit_use_anchors_": false
} }
@ -83,13 +165,45 @@ margin_right = 144.0
margin_bottom = 20.0 margin_bottom = 20.0
text = "Preferences" text = "Preferences"
[node name="ServerInfoPopup" type="WindowDialog" parent="."] [node name="ServerInfoPopup" parent="." instance=ExtResource( 4 )]
margin_left = -278.587 visible = false
margin_top = 58.4538 margin_left = 31.2773
margin_right = -22.587 margin_top = 46.9222
margin_bottom = 226.454 margin_right = 287.277
window_title = "Server info" margin_bottom = 214.923
resizable = true
[node name="InspectBox" type="RichTextLabel" parent="."]
margin_left = 19.0
margin_top = -124.0
margin_right = 376.0
margin_bottom = -97.0
size_flags_horizontal = 15
size_flags_vertical = 15
custom_styles/normal = SubResource( 6 )
custom_fonts/bold_italics_font = SubResource( 1 )
custom_fonts/italics_font = SubResource( 2 )
custom_fonts/bold_font = SubResource( 3 )
custom_fonts/normal_font = SubResource( 4 )
fit_content_height = true
scroll_active = false
__meta__ = { __meta__ = {
"_edit_use_anchors_": false "_edit_use_anchors_": false
} }
[node name="ItemSlots" type="HBoxContainer" parent="."]
anchor_top = 1.0
anchor_right = 0.5
anchor_bottom = 1.0
margin_top = -100.0
margin_bottom = -50.0
rect_scale = Vector2( 2, 2 )
alignment = 1
__meta__ = {
"_edit_use_anchors_": false
}
[connection signal="chat_message_sent" from="Logs" to="." method="_send_chat"]
[connection signal="focus_entered" from="Logs/ResizablePanel/LineEdit" to="Logs" method="_chat_bar_status" binds= [ true ]]
[connection signal="focus_exited" from="Logs/ResizablePanel/LineEdit" to="Logs" method="_chat_bar_status" binds= [ false ]]
[connection signal="mouse_entered" from="Logs/ResizablePanel/LineEdit" to="Logs" method="_chat_bar_focus" binds= [ true ]]
[connection signal="mouse_exited" from="Logs/ResizablePanel/LineEdit" to="Logs" method="_chat_bar_focus" binds= [ false ]]
[connection signal="text_entered" from="Logs/ResizablePanel/LineEdit" to="Logs" method="_text_submitted"]

View file

@ -0,0 +1,64 @@
extends TextureRect
class_name UIItemBox
signal selected(hand)
signal used_in_hand()
enum CurrentHand {
None,
Left,
Right
}
var hovering = false
export var selected = false setget set_selected
export(CurrentHand) var current_hand = CurrentHand.None setget set_hand
const LEFT_Y_OFFSET = 0
const RIGHT_Y_OFFSET = 10
onready var hand_icon = $HandIcon
func _ready():
hand_icon.texture = hand_icon.texture.duplicate()
set_hand(current_hand)
func _mouse_hover(inside: bool) -> void:
hovering = inside
if hovering:
self_modulate.a = 1
else:
self_modulate.a = 0.86
func set_selected(val: bool) -> void:
selected = val
$SelectedOverlay.visible = selected
func set_hand(hand):
current_hand = hand
if hand_icon != null:
match hand:
CurrentHand.None:
hand_icon.visible = false
CurrentHand.Left:
hand_icon.visible = true
(hand_icon.texture as AtlasTexture).region.position.y = LEFT_Y_OFFSET
CurrentHand.Right:
hand_icon.visible = true
(hand_icon.texture as AtlasTexture).region.position.y = RIGHT_Y_OFFSET
func _gui_input(event):
if event is InputEventMouseButton:
var mouse_event = event as InputEventMouseButton
if mouse_event.pressed:
if mouse_event.button_index == BUTTON_LEFT:
if current_hand != CurrentHand.Left:
emit_signal("selected", CurrentHand.Left)
else:
emit_signal("used_in_hand")
elif mouse_event.button_index == BUTTON_RIGHT:
if current_hand != CurrentHand.Right:
emit_signal("selected", CurrentHand.Right)
else:
emit_signal("used_in_hand")

View file

@ -0,0 +1,53 @@
[gd_scene load_steps=7 format=2]
[ext_resource path="res://Graphics/tgstation/midnight.png" type="Texture" id=1]
[ext_resource path="res://Scenes/UI/Items/ItemBox.gd" type="Script" id=2]
[ext_resource path="res://Graphics/UI/selected.png" type="Texture" id=3]
[ext_resource path="res://Graphics/UI/handicons.png" type="Texture" id=4]
[sub_resource type="AtlasTexture" id=1]
atlas = ExtResource( 1 )
region = Rect2( 32, 32, 32, 32 )
margin = Rect2( 2, 2, 4, 4 )
[sub_resource type="AtlasTexture" id=2]
atlas = ExtResource( 4 )
region = Rect2( 1, 0, 21, 9 )
margin = Rect2( 2, 2, 4, 4 )
[node name="ItemBox" type="TextureRect"]
self_modulate = Color( 1, 1, 1, 0.862745 )
margin_left = -1.0
margin_right = 35.0
margin_bottom = 53.0
mouse_default_cursor_shape = 2
texture = SubResource( 1 )
stretch_mode = 4
script = ExtResource( 2 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="SelectedOverlay" type="TextureRect" parent="."]
visible = false
modulate = Color( 1, 1, 1, 0.5 )
anchor_right = 1.0
anchor_bottom = 1.0
mouse_filter = 2
texture = ExtResource( 3 )
stretch_mode = 4
__meta__ = {
"_edit_use_anchors_": false
}
[node name="HandIcon" type="TextureRect" parent="."]
visible = false
anchor_right = 1.0
margin_left = -0.176781
margin_top = -5.0
margin_right = -0.176781
mouse_filter = 2
texture = SubResource( 2 )
stretch_mode = 6
[connection signal="mouse_entered" from="." to="." method="_mouse_hover" binds= [ true ]]
[connection signal="mouse_exited" from="." to="." method="_mouse_hover" binds= [ false ]]

29
Scenes/UI/Panels/Logs.gd Normal file
View file

@ -0,0 +1,29 @@
extends Control
signal chat_message_sent(text)
onready var log_text = $ResizablePanel/RichTextLabel
onready var chat_bar = $ResizablePanel/LineEdit
func _input(event: InputEvent) -> void:
if event is InputEventMouseButton:
if not chat_bar_focus:
chat_bar.release_focus()
if event.is_action_released("ui_chat") and chat_bar_focus == false:
chat_bar.grab_focus()
func add_line(line: String) -> void:
log_text.append_bbcode(line)
var chat_bar_focus = false
func _chat_bar_status(editing: bool) -> void:
$"/root/scene".writing = editing
func _chat_bar_focus(entered: bool) -> void:
chat_bar_focus = entered
func _text_submitted(text):
emit_signal("chat_message_sent", text)
chat_bar.text = ""
chat_bar.release_focus()

View file

@ -0,0 +1,5 @@
extends WindowDialog
func _physics_process(_delta):
if not visible:
return

View file

@ -0,0 +1,23 @@
[gd_scene load_steps=2 format=2]
[ext_resource path="res://Scenes/UI/Panels/ServerInfo.gd" type="Script" id=1]
[node name="ServerInfoPopup" type="WindowDialog"]
visible = true
margin_left = 19.9312
margin_top = 34.9087
margin_right = 275.931
margin_bottom = 202.909
window_title = "Server info"
resizable = true
script = ExtResource( 1 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="ItemList" type="ItemList" parent="."]
anchor_right = 1.0
anchor_bottom = 1.0
size_flags_horizontal = 3
size_flags_vertical = 3

View file

@ -33,20 +33,80 @@ size_flags_horizontal = 3
size_flags_vertical = 3 size_flags_vertical = 3
custom_constants/separation = 10 custom_constants/separation = 10
[node name="Label" type="Label" parent="MarginContainer/VBoxContainer"] [node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer"]
margin_right = 528.0 margin_right = 528.0
margin_bottom = 18.0 margin_bottom = 18.0
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Label" type="Label" parent="MarginContainer/VBoxContainer/HBoxContainer"]
margin_right = 104.0
margin_bottom = 18.0
text = "S01\\AR SYSTEM" text = "S01\\AR SYSTEM"
__meta__ = { __meta__ = {
"_edit_use_anchors_": false "_edit_use_anchors_": false
} }
[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/HBoxContainer"]
margin_left = 108.0
margin_right = 528.0
margin_bottom = 18.0
size_flags_horizontal = 3
alignment = 2
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Label2" type="Label" parent="MarginContainer/VBoxContainer/HBoxContainer/HBoxContainer"]
margin_left = 330.0
margin_right = 368.0
margin_bottom = 18.0
text = "SPD: "
align = 2
__meta__ = {
"_edit_use_anchors_": false
}
[node name="CurrentSpeed" type="Label" parent="MarginContainer/VBoxContainer/HBoxContainer/HBoxContainer"]
margin_left = 372.0
margin_right = 372.0
margin_bottom = 18.0
custom_colors/font_color = Color( 0.494118, 0.52549, 0.737255, 1 )
align = 2
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Label3" type="Label" parent="MarginContainer/VBoxContainer/HBoxContainer/HBoxContainer"]
margin_left = 376.0
margin_right = 416.0
margin_bottom = 18.0
text = "ANGL:"
align = 2
__meta__ = {
"_edit_use_anchors_": false
}
[node name="CurrentAngle" type="Label" parent="MarginContainer/VBoxContainer/HBoxContainer/HBoxContainer"]
margin_left = 420.0
margin_right = 420.0
margin_bottom = 18.0
custom_colors/font_color = Color( 0.494118, 0.52549, 0.737255, 1 )
align = 2
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Map" type="Control" parent="MarginContainer/VBoxContainer"] [node name="Map" type="Control" parent="MarginContainer/VBoxContainer"]
margin_top = 28.0 margin_top = 28.0
margin_bottom = 28.0 margin_right = 528.0
margin_bottom = 446.0
rect_clip_content = true rect_clip_content = true
size_flags_horizontal = 3 size_flags_horizontal = 3
size_flags_vertical = 3 size_flags_vertical = 3
script = ExtResource( 4 ) script = ExtResource( 4 )
background = ExtResource( 2 ) background = ExtResource( 2 )
font = ExtResource( 3 ) font = ExtResource( 3 )
[connection signal="about_to_show" from="." to="MarginContainer/VBoxContainer/Map" method="_reset_position"]
[connection signal="popup_hide" from="." to="MarginContainer/VBoxContainer/Map" method="_on_hide"]

View file

@ -1,60 +1,157 @@
extends Control extends Control
export var cell_size = 100 export var cell_size = 150
export var bgzoom = 50 export var bgzoom = 50
const BORDER_WIDTH = 4
const BORDER_LENGTH = 30
const RADAR_EFFECT_DELAY = 1
const HALF_BORDER = BORDER_LENGTH/2
const MIN_ZOOM = 30
const ZOOM_STEP = 10
const MAX_ZOOM = 400
export(Texture) var background export(Texture) var background
export(Font) var font export(Font) var font
var dragging = false var dragging = false
var origin = Vector2(randf() * -1e4, randf() * -1e4) var origin = Vector2.ZERO
var last_origin = origin var last_origin = origin
var last_mouse_pos = Vector2.ZERO var last_mouse_pos = Vector2.ZERO
var set_position = true
var radar_next_remaining = RADAR_EFFECT_DELAY
var offset = Vector2.ZERO
var text_two_lines = false
onready var scene = $"/root/scene"
onready var speed_text = $"../HBoxContainer/HBoxContainer/CurrentSpeed"
onready var dir_text = $"../HBoxContainer/HBoxContainer/CurrentAngle"
onready var popup = $"../../.."
var last_pos = []
func _ready():
font = font.duplicate()
func _physics_process(delta):
radar_next_remaining -= delta
if radar_next_remaining < 0:
var current_position = (scene.world.map.current_ship_position + scene.world.map.current_ship_subpos)
last_pos.append(current_position)
if last_pos.size() > 20:
last_pos.pop_front()
radar_next_remaining = RADAR_EFFECT_DELAY
if not visible:
return
speed_text.text = "%.0f u/s" % (scene.world.map.current_ship_speed * 10000)
dir_text.text = "%.0f deg" % rad2deg(scene.world.map.current_ship_direction)
update()
func _draw(): func _draw():
var win_size = get_global_rect().size var win_size = get_global_rect().size
var current_position = (scene.world.map.current_ship_position + scene.world.map.current_ship_subpos) * cell_size
if set_position:
origin = current_position - win_size/2
last_origin = origin
if win_size.x > 0:
set_position = false
var cols = int(ceil(win_size.x/cell_size)) var cols = int(ceil(win_size.x/cell_size))
var rows = int(ceil(win_size.y/cell_size)) var rows = int(ceil(win_size.y/cell_size))
var xoffset = float(int(origin.x) % cell_size) var xoffset = float(int(origin.x) % cell_size)
var yoffset = float(int(origin.y) % cell_size) var yoffset = float(int(origin.y) % cell_size)
draw_texture_rect_region(background, Rect2(Vector2.ZERO, win_size), Rect2(-origin*bgzoom, win_size*bgzoom), Color(0.5,0.5,0.5,1)) draw_texture_rect_region(background, Rect2(Vector2.ZERO, win_size), Rect2(origin*bgzoom, win_size*bgzoom), Color(0.5,0.5,0.5,1))
for i in range(0, cols+1): for i in range(0, cols+1):
draw_line(Vector2(i * cell_size+xoffset, 0), Vector2(i * cell_size+xoffset, win_size.y), Color.white * 0.5) draw_line(Vector2(i * cell_size-xoffset, 0), Vector2(i * cell_size-xoffset, win_size.y), Color.white * 0.5)
for i in range(0, rows): for i in range(0, rows+1):
draw_line(Vector2(0, i * cell_size+yoffset), Vector2(win_size.x, i * cell_size+yoffset), Color.white * 0.5) draw_line(Vector2(0, i * cell_size-yoffset), Vector2(win_size.x, i * cell_size-yoffset), Color.white * 0.5)
for x in range(-1, cols+1): for x in range(-1, cols+1):
for y in range(-1, rows+1): for y in range(-1, rows+1):
var real_x = x - int(origin.x/cell_size) var real_x = x + int(origin.x/cell_size)
var real_y = y - int(origin.y/cell_size) var real_y = y + int(origin.y/cell_size)
var sector_name = to_letter(real_x) var sector = Coordinates.as_string_parts(Vector2(real_x, real_y))
if real_y < 0: if text_two_lines:
sector_name += to_letter(real_y) draw_string(font, Vector2(x * cell_size + 6 - xoffset, y * cell_size + 20 - yoffset), sector[0], Color(1,1,1,0.5))
draw_string(font, Vector2(x * cell_size + 6 - xoffset, y * cell_size + 20 - yoffset + font.size + 2), sector[1], Color(1,1,1,0.5))
else: else:
sector_name += str(real_y) draw_string(font, Vector2(x * cell_size + 6 - xoffset, y * cell_size + 20 - yoffset), sector[0] + sector[1], Color(1,1,1,0.5))
draw_string(font, Vector2(x * cell_size + 6 + xoffset, y * cell_size + 20 + yoffset), sector_name, Color(1,1,1,0.5))
var viewport = Rect2(origin, win_size)
var point_count = last_pos.size()
for pos_index in range(0, point_count):
draw_circle(last_pos[pos_index] * cell_size - origin, 2, Color(1, 0, 0, pos_index*1.0/point_count))
draw_target(viewport, current_position, Color.red)
# Debug directions:
#draw_line(current_position - viewport.position, current_position - viewport.position + Vector2.RIGHT.rotated(scene.world.map.ship_direction) * 100, Color.green)
#draw_line(current_position - viewport.position, current_position - viewport.position + Vector2.RIGHT.rotated(scene.world.map.current_ship_direction) * 100, Color.yellow)
var current_target = scene.world.map.current_ship_target
if current_target != null:
var current_target_adj = current_target * cell_size
draw_target(viewport, current_target_adj, Color.green)
draw_line(current_position - origin, current_target_adj - origin, Color.darkcyan)
func draw_target(viewport: Rect2, position: Vector2, color: Color):
# Check if target is in range
if viewport.has_point(position):
draw_circle(position - viewport.position, 5, color)
else:
# Draw line pointing to target
var relative_pos = position - viewport.position
var clamped = Vector2(clamp(relative_pos.x, 0, viewport.size.x), clamp(relative_pos.y, 0, viewport.size.y))
if relative_pos.x < 0:
draw_line(Vector2(0, clamped.y-HALF_BORDER), Vector2(0, clamped.y+HALF_BORDER), color, BORDER_WIDTH)
elif relative_pos.x > viewport.size.x:
draw_line(Vector2(viewport.size.x, clamped.y-HALF_BORDER), Vector2(viewport.size.x, clamped.y+HALF_BORDER), color, BORDER_WIDTH)
if relative_pos.y < 0:
draw_line(Vector2(clamped.x-HALF_BORDER, 0), Vector2(clamped.x+HALF_BORDER, 0), color, BORDER_WIDTH)
elif relative_pos.y > viewport.size.y:
draw_line(Vector2(clamped.x-HALF_BORDER, viewport.size.y), Vector2(clamped.x+HALF_BORDER, viewport.size.y), color, BORDER_WIDTH)
func _input(event): func _input(event):
if not visible:
return
if event.is_action_pressed("ui_zoomin"):
if cell_size < MAX_ZOOM:
_recalc_offset(ZOOM_STEP)
cell_size += ZOOM_STEP
update_font()
update()
return
if event.is_action_pressed("ui_zoomout"):
if cell_size > MIN_ZOOM:
_recalc_offset(-ZOOM_STEP)
cell_size -= ZOOM_STEP
update_font()
update()
return
if event is InputEventMouseButton: if event is InputEventMouseButton:
dragging = event.pressed dragging = event.pressed
last_origin = origin last_origin = origin
last_mouse_pos = event.position last_mouse_pos = event.position
update() update()
elif event is InputEventMouseMotion: return
if event is InputEventMouseMotion:
if dragging: if dragging:
origin = last_origin + (event.position - last_mouse_pos) origin = last_origin - (event.position - last_mouse_pos)
update() update()
return
func to_letter(num: int) -> String: func update_font():
#var letters = "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ" text_two_lines = cell_size < 70
var letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" if cell_size < 100:
if num == 0: font.size = 11
return "Α" else:
elif num < 0: font.size = 14
letters = "αβγδεζηθικλμνξοπρστυφχψω"
num = abs(num) func _recalc_offset(mult: float):
var out = "" var mouse = get_local_mouse_position()
var base = letters.length() origin = ((origin + mouse) / cell_size * (cell_size + mult)) - mouse
while num > 0:
out += letters.substr(num % base, 1) func _reset_position():
num /= base set_position = true
return out
func _on_hide():
popup.visible = false

View file

@ -26,9 +26,10 @@ func _handle_resize(event):
rect_size = last_origin + (event.global_position - last_mouse) rect_size = last_origin + (event.global_position - last_mouse)
func _input(event): func _input(event):
if dragging and event is InputEventMouseButton and not event.pressed: if event is InputEventMouseButton:
if dragging and not event.pressed:
dragging = false dragging = false
if resizing and event is InputEventMouseButton and not event.pressed: if resizing and not event.pressed:
resizing = false resizing = false
func set_title(val): func set_title(val):

View file

@ -16,10 +16,8 @@ corner_radius_bottom_right = 4
corner_radius_bottom_left = 4 corner_radius_bottom_left = 4
[node name="ResizablePanel" type="Panel"] [node name="ResizablePanel" type="Panel"]
margin_left = 10.0 anchor_right = 1.0
margin_top = 10.0 anchor_bottom = 1.0
margin_right = 376.0
margin_bottom = 336.0
custom_styles/panel = SubResource( 1 ) custom_styles/panel = SubResource( 1 )
script = ExtResource( 1 ) script = ExtResource( 1 )
__meta__ = { __meta__ = {

View file

@ -2,32 +2,38 @@ extends Node2D
class_name GameWorld class_name GameWorld
enum Map { RUNTIME, ODYSSEY } enum Map { RUNTIME, ODYSSEY, EMPTY }
export(Map) var mapToLoad = Map.RUNTIME
const runtimeRes = preload("res://Scenes/Maps/runtime.tscn")
const odysseyRes = preload("res://Scenes/Maps/odyssey.tscn")
const playerRes = preload("res://Actors/Player/Player.tscn") const playerRes = preload("res://Actors/Player/Player.tscn")
var map = null var map = null
var player = null var player = null
func _ready(): onready var scene_manager = $"/root/SceneManager"
match mapToLoad:
func load_map(map_name):
match map_name:
Map.RUNTIME: Map.RUNTIME:
map = runtimeRes.instance() map = scene_manager.queue.get_resource("res://Scenes/Maps/runtime.tscn").instance()
Map.ODYSSEY: Map.ODYSSEY:
map = odysseyRes.instance() map = scene_manager.queue.get_resource("res://Scenes/Maps/odyssey.tscn").instance()
Map.EMPTY:
map = preload("res://Scenes/Maps/empty.tscn").instance()
add_child(map) add_child(map)
player = playerRes.instance()
player.is_controlled = true func spawn_player(peer: int, is_current_user: bool):
var spawnpoints = map.get_pois(POIData.POIType.SpawnPoint, POIData.POIClass.Player) var playerNode = playerRes.instance()
playerNode.set_network_master(peer, true)
playerNode.is_controlled = is_current_user
var spawnpoints = map.get_pois(POI.POIType.SpawnPoint, POI.POIClass.Player)
if spawnpoints.size() > 0: if spawnpoints.size() > 0:
player.transform.origin = (spawnpoints[0] as Node2D).transform.origin playerNode.transform.origin = (spawnpoints[0] as Node2D).transform.origin
else: else:
print("Map does not have Player spawnpoint POI! Spawning at origin (very bad)") print("Map does not have Player spawnpoint POI! Spawning at origin (very bad)")
$players.add_child(player) $players.add_child(playerNode, true)
if is_current_user:
player = playerNode
for tilemap in map.tilemaps: for tilemap in map.tilemaps:
if tilemap is MapTiles: if tilemap is MapTiles:
tilemap.set_occluder_origin(player) tilemap.set_occluder_origin(playerNode)
return playerNode

18
Scenes/systems.gd Normal file
View file

@ -0,0 +1,18 @@
extends Node
func serialize() -> Dictionary:
var systems = {}
for child in get_children():
systems[child.name] = {
"script": child.script.resource_path,
"data": child.serialize()
}
return systems
func deserialize(data: Dictionary) -> void:
for system_name in data:
var system_data = data[system_name] as Dictionary
var system_node = load(system_data.script).new()
system_node.name = system_name
add_child(system_node, true)
system_node.deserialize(system_data.data)

Binary file not shown.

View file

@ -0,0 +1,21 @@
[remap]
importer="wav"
type="AudioStreamSample"
path="res://.import/door-close.wav-f2186a53d65333241246e455153168e4.sample"
[deps]
source_file="res://Sounds/SFX/effects/door-close.wav"
dest_files=[ "res://.import/door-close.wav-f2186a53d65333241246e455153168e4.sample" ]
[params]
force/8_bit=false
force/mono=false
force/max_rate=false
force/max_rate_hz=44100
edit/trim=true
edit/normalize=true
edit/loop=false
compress/mode=1

Binary file not shown.

View file

@ -0,0 +1,21 @@
[remap]
importer="wav"
type="AudioStreamSample"
path="res://.import/door-open.wav-50d5fc4e7eea744e9b203efe71dc9b86.sample"
[deps]
source_file="res://Sounds/SFX/effects/door-open.wav"
dest_files=[ "res://.import/door-open.wav-50d5fc4e7eea744e9b203efe71dc9b86.sample" ]
[params]
force/8_bit=false
force/mono=false
force/max_rate=false
force/max_rate_hz=44100
edit/trim=true
edit/normalize=true
edit/loop=false
compress/mode=1

Binary file not shown.

View file

@ -0,0 +1,21 @@
[remap]
importer="wav"
type="AudioStreamSample"
path="res://.import/door-sound.wav-a7dd359f7d7f7690a94b538a2bf51d4e.sample"
[deps]
source_file="res://Sounds/SFX/effects/door-sound.wav"
dest_files=[ "res://.import/door-sound.wav-a7dd359f7d7f7690a94b538a2bf51d4e.sample" ]
[params]
force/8_bit=false
force/mono=false
force/max_rate=false
force/max_rate_hz=44100
edit/trim=true
edit/normalize=true
edit/loop=false
compress/mode=1

View file

@ -0,0 +1,40 @@
<?xml version="1.0" standalone="no" ?>
<!DOCTYPE project PUBLIC "-//audacityproject-1.3.0//DTD//EN" "http://audacity.sourceforge.net/xml/audacityproject-1.3.0.dtd" >
<project xmlns="http://audacity.sourceforge.net/xml/" projname="door-sound_data" version="1.3.0" audacityversion="2.3.3" sel0="0.0000000000" sel1="0.0000000000" vpos="0" h="0.0000000000" zoom="300.2769352499" rate="48000.0" snapto="off" selectionformat="hh:mm:ss + milliseconds" frequencyformat="Hz" bandwidthformat="octaves">
<tags/>
<wavetrack name="door-sound" isSelected="1" height="150" minimized="0" channel="2" linked="0" mute="0" solo="1" rate="48000" gain="1.0" pan="0.0" colorindex="0">
<waveclip offset="0.00000000" colorindex="0">
<sequence maxsamples="262144" sampleformat="262159" numsamples="116852">
<waveblock start="0">
<simpleblockfile filename="e0808e31.au" len="116852" min="-1.0" max="1.0" rms="0.106046"/>
</waveblock>
</sequence>
<envelope numpoints="7">
<controlpoint t="0.725996486605" val="1.000000000000"/>
<controlpoint t="0.825904259991" val="0.620437979698"/>
<controlpoint t="0.855876592007" val="0.562043786049"/>
<controlpoint t="0.929142292490" val="0.445255458355"/>
<controlpoint t="1.049031620553" val="0.915492951870"/>
<controlpoint t="1.128957839262" val="1.429577469826"/>
<controlpoint t="1.308791831357" val="0.725352108479"/>
</envelope>
</waveclip>
</wavetrack>
<wavetrack name="264061__paul368__sfx-door-open" isSelected="0" height="150" minimized="0" channel="2" linked="0" mute="1" solo="0" rate="48000" gain="0.501187" pan="0.0" colorindex="0">
<waveclip offset="0.22643750" colorindex="0">
<sequence maxsamples="262144" sampleformat="262159" numsamples="85596">
<waveblock start="0">
<simpleblockfile filename="e0808367.au" len="85596" min="-0.316331" max="0.389588" rms="0.023447"/>
</waveblock>
</sequence>
<envelope numpoints="6">
<controlpoint t="0.046643747255" val="0.514084517956"/>
<controlpoint t="0.166533075318" val="1.000000000000"/>
<controlpoint t="0.476247172815" val="0.971830964088"/>
<controlpoint t="0.749328420070" val="0.816901445389"/>
<controlpoint t="0.885869043698" val="0.598591566086"/>
<controlpoint t="1.022409667325" val="0.267605662346"/>
</envelope>
</waveclip>
</wavetrack>
</project>

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,15 @@
[remap]
importer="ogg_vorbis"
type="AudioStreamOGGVorbis"
path="res://.import/neutral-bi-beep.ogg-b80d5dd9b7ca71aa0d191c8ef7940dc5.oggstr"
[deps]
source_file="res://Sounds/SFX/ui/neutral-bi-beep.ogg"
dest_files=[ "res://.import/neutral-bi-beep.ogg-b80d5dd9b7ca71aa0d191c8ef7940dc5.oggstr" ]
[params]
loop=false
loop_offset=0

Some files were not shown because too many files have changed in this diff Show more