No commits in common. 'pre_alpha_1' and 'master' have entirely different histories.

  1. 2
      .gitignore
  2. BIN
      assets/blender/loop.blend
  3. BIN
      assets/blender/loop.blend1
  4. 137356
      assets/road/roadLoop.obj
  5. 51
      ext/server.py
  6. 45
      project.godot
  7. 145
      resources/ui/i18n.csv
  8. BIN
      resources/ui/i18n.de.translation
  9. BIN
      resources/ui/i18n.en.translation
  10. 9
      resources/ui/theme.tres
  11. 15
      scenes/menus/BaseMenu.tscn
  12. 75
      scenes/menus/DirectHostMenu.tscn
  13. 3
      scenes/menus/DirectJoinMenu.tscn
  14. 20
      scenes/menus/IngameMenu.tscn
  15. 8
      scenes/menus/LobbyMenu.tscn
  16. 58
      scenes/menus/LocalGameMenu.tscn
  17. 53
      scenes/menus/MainMenu.tscn
  18. 24
      scenes/menus/MultiplayerMenu.tscn
  19. 34
      scenes/menus/ServerCreateGameMenu.tscn
  20. 36
      scenes/menus/SettingsControlsMenu.tscn
  21. 53
      scenes/menus/SettingsGameMenu.tscn
  22. 44
      scenes/menus/SettingsGraphicsMenu.tscn
  23. 151
      scenes/menus/SettingsMenu.tscn
  24. 12
      scenes/menus/SettingsPlayerMenu.tscn
  25. 62
      scenes/menus/SettingsSystemMenu.tscn
  26. 7
      scenes/player/BotPlayer.tscn
  27. 74
      scenes/player/HumanPlayer.tscn
  28. 1
      scenes/player/Player.tscn
  29. 2
      scenes/road/roadCornerLarge.tscn
  30. 4
      scenes/road/roadCornerLargeFlipped.tscn
  31. 4
      scenes/road/roadCornerLarger.tscn
  32. 4
      scenes/road/roadCornerLargerFlipped.tscn
  33. 6
      scenes/road/roadCornerSmall.tscn
  34. 6
      scenes/road/roadCornerSmallFlipped.tscn
  35. 2
      scenes/road/roadRamp.tscn
  36. 2
      scenes/road/roadRampFlipped.tscn
  37. 4
      scenes/road/roadRampLong.tscn
  38. 2
      scenes/road/roadRampLongCurved.tscn
  39. 2
      scenes/road/roadRampLongFlipped.tscn
  40. 12
      scripts/Util.gd
  41. 27
      scripts/game/config.gd
  42. 63
      scripts/game/config_apply.gd
  43. 19
      scripts/game/game.gd
  44. 41
      scripts/game/gamestate.gd
  45. 58
      scripts/game/local_storage.gd
  46. 33
      scripts/game/route.gd
  47. 18
      scripts/menus/direct_host_menu.gd
  48. 4
      scripts/menus/direct_join_menu.gd
  49. 25
      scripts/menus/ingame.gd
  50. 21
      scripts/menus/ingame_menu.gd
  51. 16
      scripts/menus/lobby_menu.gd
  52. 12
      scripts/menus/local_game.gd
  53. 9
      scripts/menus/main_menu.gd
  54. 18
      scripts/menus/server_create_menu.gd
  55. 6
      scripts/menus/server_menu.gd
  56. 67
      scripts/menus/settings.gd
  57. 89
      scripts/menus/settings_controls.gd
  58. 128
      scripts/menus/settings_controls_menu.gd
  59. 17
      scripts/menus/settings_game_menu.gd
  60. 24
      scripts/menus/settings_graphics_menu.gd
  61. 46
      scripts/menus/settings_menu.gd
  62. 14
      scripts/menus/settings_player.gd
  63. 14
      scripts/menus/settings_player_menu.gd
  64. 55
      scripts/menus/settings_system_menu.gd
  65. 33
      scripts/networking/game_server.gd
  66. 8
      scripts/networking/game_server_requests.gd
  67. 56
      scripts/networking/server.gd
  68. 50
      scripts/player/base_inventory.gd
  69. 77
      scripts/player/bot_controls.gd
  70. 3
      scripts/player/bot_inventory.gd
  71. 41
      scripts/player/human_controls.gd
  72. 14
      scripts/player/human_inventory.gd
  73. 4
      scripts/player/inventory_preview.gd
  74. 99
      scripts/player/player.gd
  75. 25
      scripts/road/road.gd
  76. 53
      scripts/screen_capture.gd
  77. 36
      scripts/util.gd

2
.gitignore

@ -5,6 +5,7 @@ export_presets.cfg
dist/
*.import
*.translation
# Mono-specific ignores
.mono/
@ -12,3 +13,4 @@ dist/
# System/tool-specific ignores
.directory
*~
.~lock*

BIN
assets/blender/loop.blend

BIN
assets/blender/loop.blend1

137356
assets/road/roadLoop.obj
File diff suppressed because it is too large
View File

51
ext/server.py

@ -5,20 +5,26 @@ import secrets
from flask import Flask, abort, request, jsonify
START_PORT = 8128
GAME_EXEC = '/opt/godot/Godot_v3.1.1-stable_linux_server.64'
MAX_GAMES = 10
GAME_EXEC = 'godot_server'
GAME_EXEC_ARG_PACK = '--main-pack'
GAME_EXEC_ARG_PACK_PATH = '/opt/godot/Muffrace Pre Alpha.pck'
GAME_EXEC_ARG_PACK_PATH = '/opt/godot/MUR.pck'
GAME_EXEC_ARG_PORT = '--port={0}'
GAME_EXEC_ARG_ID = '--server-id={0}'
GAME_EXEC_ARG_SECRET = '--secret={0}'
GAME_EXEC_ARG_BOTS = '--bots={0}'
GAME_EXEC_ARG_BOT_DIFFICULTY = '--bot-difficulty={0}'
GAME_EXEC_ARG_SERVER_ADDR = '--server-addr={0}'
GAME_EXEC_ARG_API_ADDR = '--api-addr={0}'
games = {}
try:
with sqlite3.connect("database.db") as con:
cur = con.cursor()
cur.execute(
'CREATE TABLE IF NOT EXISTS games (id INTEGER PRIMARY KEY, name TEXT, secret TEXT, ip TEXT, running INTEGER, port INTEGER, player_count INTEGER, bots INTEGER)')
'CREATE TABLE IF NOT EXISTS games (id INTEGER PRIMARY KEY, name TEXT, secret TEXT, ip TEXT, running INTEGER, port INTEGER, player_count INTEGER, bots INTEGER, bot_difficulty REAL)')
con.commit()
except:
con.rollback()
@ -37,10 +43,15 @@ def create_game():
abort(400)
bots = False
bot_difficulty = -1
name = request.json.get('name')
if 'bots' in request.json:
bots = request.json.get('bots')
if 'bot-difficulty' in request.json:
bot_difficulty = request.json.get('bot-difficulty')
game_count = 0
try:
with sqlite3.connect("database.db") as con:
# check free port
@ -50,9 +61,13 @@ def create_game():
rows = cur.fetchall()
while rows:
port += 1
game_count += 1
cur.execute("SELECT * FROM games WHERE port=?", (port,))
rows = cur.fetchall()
if game_count >= MAX_GAMES:
return
# check duplicate name
base_name = name
base_name_count = 1
@ -66,20 +81,40 @@ def create_game():
# gen secret
secret = secrets.token_hex(32)
cur.execute("INSERT INTO games (name,secret,ip,port,bots,running) VALUES (?,?,?,?,?,0)",
(name, secret, request.remote_addr, port, bots))
remote_addr = request.remote_addr
if 'X-Forwarded-For' in request.headers:
remote_addr = request.headers.getlist(
"X-Forwarded-For")[0].rpartition(' ')[-1]
cur.execute("INSERT INTO games (name,secret,ip,port,bots,bot_difficulty,player_count,running) VALUES (?,?,?,?,?,?,0,0)",
(name, secret, remote_addr, port, bots, bot_difficulty))
con.commit()
cur.execute("SELECT id FROM games WHERE secret=?",
(secret,))
result = cur.fetchone()
if result[0]:
games[result[0]] = subprocess.Popen([GAME_EXEC, GAME_EXEC_ARG_PACK, GAME_EXEC_ARG_PACK_PATH, GAME_EXEC_ARG_ID.format(int(result[0])), GAME_EXEC_ARG_PORT.format(
port), GAME_EXEC_ARG_SECRET.format(secret), GAME_EXEC_ARG_BOTS.format(int(bots))])
games[result[0]] = subprocess.Popen([GAME_EXEC,
GAME_EXEC_ARG_PACK, GAME_EXEC_ARG_PACK_PATH,
GAME_EXEC_ARG_ID.format(
int(result[0])),
GAME_EXEC_ARG_PORT.format(
port),
GAME_EXEC_ARG_SECRET.format(
secret),
GAME_EXEC_ARG_BOTS.format(
int(bots)),
GAME_EXEC_ARG_BOT_DIFFICULTY.format(
float(bot_difficulty)),
GAME_EXEC_ARG_SERVER_ADDR.format(
'127.0.0.1'), # localhost
GAME_EXEC_ARG_API_ADDR.format('http://127.0.0.1:5000/')])
except:
con.rollback()
abort(500)
finally:
con.close()
if game_count >= MAX_GAMES:
abort(403)
return jsonify({'name': name, 'port': port})
@ -168,4 +203,4 @@ def close_game():
if __name__ == '__main__':
app.run(debug=True)
app.run(debug=True, host='0.0.0.0', port=5000)

45
project.godot

@ -15,6 +15,11 @@ _global_script_classes=[ {
"path": "res://scripts/player/base_inventory.gd"
}, {
"base": "Spatial",
"class": "BotPlayer",
"language": "GDScript",
"path": "res://scripts/player/bot_controls.gd"
}, {
"base": "Spatial",
"class": "Game",
"language": "GDScript",
"path": "res://scripts/game/game.gd"
@ -53,14 +58,10 @@ _global_script_classes=[ {
"class": "TracksFactory",
"language": "GDScript",
"path": "res://scripts/road/roads_factory.gd"
}, {
"base": "Node",
"class": "Util",
"language": "GDScript",
"path": "res://scripts/Util.gd"
} ]
_global_script_class_icons={
"BaseInventory": "",
"BotPlayer": "",
"Game": "",
"GameServer": "",
"GameServerRequests": "",
@ -68,13 +69,12 @@ _global_script_class_icons={
"Preview": "",
"Road": "",
"Route": "",
"TracksFactory": "",
"Util": ""
"TracksFactory": ""
}
[application]
config/name="MUR (public)"
config/name="MUR_pre_alpha"
run/main_scene="res://scenes/menus/MainMenu.tscn"
boot_splash/fullsize=false
config/icon="res://icon.png"
@ -86,8 +86,17 @@ client="*res://scripts/networking/client.gd"
server="*res://scripts/networking/server.gd"
game_server="*res://scripts/networking/game_server.gd"
roads_factory="*res://scripts/road/roads_factory.gd"
local_storage="*res://scripts/game/local_storage.gd"
Util="*res://scripts/Util.gd"
config="*res://scripts/game/config.gd"
config_apply="*res://scripts/game/config_apply.gd"
util="*res://scripts/util.gd"
[display]
window/size/width=1920
window/size/height=1080
window/size/resizable=false
window/stretch/mode="2d"
window/stretch/aspect="expand"
[input]
@ -112,7 +121,7 @@ controls_break={
controls_add_road={
"deadzone": 0.5,
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":32,"unicode":0,"echo":false,"script":null)
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":5,"pressure":0.0,"pressed":false,"script":null)
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":4,"pressure":0.0,"pressed":false,"script":null)
]
}
controls_next_road_type={
@ -142,7 +151,7 @@ controls_prev_road_variant={
controls_reset={
"deadzone": 0.5,
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":69,"unicode":0,"echo":false,"script":null)
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":4,"pressure":0.0,"pressed":false,"script":null)
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":3,"pressure":0.0,"pressed":false,"script":null)
]
}
debug_camera_1={
@ -165,6 +174,18 @@ debug_camera_4={
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":52,"unicode":0,"echo":false,"script":null)
]
}
controls_menu={
"deadzone": 0.5,
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777217,"unicode":0,"echo":false,"script":null)
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":11,"pressure":0.0,"pressed":false,"script":null)
]
}
controls_capture={
"deadzone": 0.5,
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":80,"unicode":0,"echo":false,"script":null)
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":10,"pressure":0.0,"pressed":false,"script":null)
]
}
[layer_names]

145
resources/ui/i18n.csv

@ -1,45 +1,58 @@
,en,de
BACK,back,Zurück
MULTIPLAYER,multiplayer,Multiplayer
PRACTISE,practise,Training
SETTINGS,settings,Einstellungen
DEBUG,debug EN,Debug DE
HOST,host,Host
JOIN,join,Beitreten
QUIT,quit,Beenden
DIRECT_HOST,direct host,Direkt hosten
DIRECT_JOIN,direct join,Direkt beitreten
OPEN_GAMES_ONLY,open games only,Nur offene Spiele
REFRESH,refresh,Aktualisieren
CREATE_GAME,create game,Spiel erstellen
PLAYER_NAME,name,Name
PLAYER_COLOR,color,Farbe
BOTS,bots,Bots
GAME,game,Spiel
PORT,port,Port
IP,IP,IP
RESUME,resume,Fortsetzen
END_GAME,end game,Spiel beenden
START_GAME,start game,Spiel starten
GAME_NAME,name,Name
READY,ready,Bereit
BACK,Back,Zurück
MULTIPLAYER,Multiplayer,Multiplayer
PRACTISE,Practise,Training
SETTINGS,Settings,Einstellungen
DEBUG,Debug EN,Debug DE
HOST,Host,Host
JOIN,Join,Beitreten
QUIT,Quit,Beenden
DIRECT_HOST,Direct host,Direkt hosten
DIRECT_JOIN,Direct join,Direkt beitreten
OPEN_GAMES_ONLY,Open games only,Nur offene Spiele
REFRESH,Refresh,Aktualisieren
CREATE_GAME,Create game,Spiel erstellen
PLAYER_NAME,Name,Name
PLAYER_COLOR,Color,Farbe
BOTS,Bots,Bots
BOT_DIFFICULTY,Difficulty,Schwierigkeit
DIFFICULTY_EASY,Easy,Einfach
DIFFICULTY_DIFFUCULT,Difficult,Schwierig
GAME,Game,Spiel
PORT,Port,Port
IP,Ip,IP
RESUME,Resume,Fortsetzen
END_GAME,End game,Spiel beenden
START_GAME,Start game,Spiel starten
GAME_NAME,Name,Name
READY,Ready,Bereit
ALERT,Alert!,Fehler!
CONTROLS,controls,Steuerung
RESET,reset,Zurücksetzen
CONTROLS,Controls,Steuerung
RESET,Press reset,Zurücksetzen drücken…
PRESS_KEY,Press any key...,Taste drücken…
ERROR_SERVER_CREATION,Cannot create Server!,Server konnte nicht erstellt werden!
INVALID_IP4,Invalid IPv4 address!,Ungültige IPv4 Adresse!
KEY_ALREADY_TAKEN,Key already in use:,Taste wird bereits verwendet:
ERROR_SERVER_CREATION,Cannot create server!,Server konnte nicht erstellt werden!
ERROR_GAME_CREATION,"Cannot create game!
(Server full or blocked?)","Spiel konnte nicht erstellt werden!
(Server voll oder blockiert?)"
INVALID_IP4,Invalid ipv4 address!,Ungültige IPv4 Adresse!
SERVER_DISCONNECTED,Server disconnected!,Serververbindung getrennt!
SERVER_NO_CONNECTION,No connection to server!,Keine Verbindung zu Server!
CONNECTION_FAILED,Connection failed!,Verbindung fehlgeschlagen!
SYSTEM,system,System
LOCALE,language,Sprache
LOCALE_EN,english,Englisch (english)
LOCALE_DE,german (Deutsch),Deutsch
GRAPHICS,graphics,Grafik
SAVE,save,Speichern
KEYBOARD,keyboard,Tastatur
JOYPAD,joypad,Joypad
SYSTEM,System,System
LOCALE,Language,Sprache
LOCALE_EN,English,Englisch (english)
LOCALE_DE,German (deutsch),Deutsch
GRAPHICS,Graphics,Grafik
FULLSCREEN,Fullscreen,Vollbild
LIGHT,Light,Licht
SHADOWS,Shadows,Schatten
SAVE,Save,Speichern
APPLY,Apply,Übernehmen
KEYBOARD,Keyboard,Tastatur
JOYPAD,Joypad,Joypad
SERVER_ADDR,Server address,Server Adresse
API_ADDR,API adress,API Adresse
Up,,Hoch
Down,,Runter
Left,,Links
@ -53,33 +66,35 @@ Delete,,Entf
Home,,Pos 1
End,,Ende
,,
StraightLong,straight,Gerade
Straight,short straight,kurze Gerade
CornerLarge,right corner,Rechtskurve
CornerLargeFlipped,left corner,Linkskurve
CornerLarger,long right corner,lange Rechtskurve
CornerLargerFlipped,long left corner,lange Linkskurve
CornerSmall,short right corner,kurze Rechtskurve
CornerSmallFlipped,short left corner,kurze Linkskurve
StraightLongBump,bump,Bodenwelle
Bump,small bump,kurze Bodenwelle
StraightSkew,right skew,rechte Schräge
StraightSkewFlipped,left skew,linke Schräge
RampLong,ramp up,Rampe hoch
RampLongFlipped,ramp down,Rampe runter
RampLongCurved,curved ramp up,Rundung hoch
RampLongCurvedFlipped,curved ramp down,Rundung runter
Ramp,short ramp up,kurze Rampe hoch
RampFlipped,short ramp down,kurze Rampe runter
CurvedFlipped,shicane right,Schikane rechts
Curved,shicane left,Schikane links
Loop,looping,Looping
StraightLong,Straight,Gerade
Straight,Short straight,kurze Gerade
CornerLarge,Right corner,Rechtskurve
CornerLargeFlipped,Left corner,Linkskurve
CornerLarger,Long right corner,lange Rechtskurve
CornerLargerFlipped,Long left corner,lange Linkskurve
CornerSmall,Short right corner,kurze Rechtskurve
CornerSmallFlipped,Short left corner,kurze Linkskurve
StraightLongBump,Bump,Bodenwelle
Bump,Small bump,kurze Bodenwelle
StraightSkew,Right skew,rechte Schräge
StraightSkewFlipped,Left skew,linke Schräge
RampLong,Ramp up,Rampe hoch
RampLongFlipped,Ramp down,Rampe runter
RampLongCurved,Curved ramp up,Rundung hoch
RampLongCurvedFlipped,Curved ramp down,Rundung runter
Ramp,Short ramp up,kurze Rampe hoch
RampFlipped,Short ramp down,kurze Rampe runter
CurvedFlipped,Shicane right,Schikane rechts
Curved,Shicane left,Schikane links
Loop,Looping,Looping
,,
controls_thrust,thrust,Beschleunigen
controls_break,break,Bremsen
controls_add_road,add,Setzen
controls_next_road_type,next type,Nächste Kategorie
controls_prev_road_type,previous type,Vorherige Kategorie
controls_next_road_variant,next variant,Nächste Variante
controls_prev_road_variant,previous variant,Vorherige Variante
controls_reset,reset,Zurücksetzen
controls_thrust,Thrust,Beschleunigen
controls_break,Break,Bremsen
controls_add_road,Add,Setzen
controls_next_road_type,Next type,Nächste Kategorie
controls_prev_road_type,Previous type,Vorherige Kategorie
controls_next_road_variant,Next variant,Nächste Variante
controls_prev_road_variant,Previous variant,Vorherige Variante
controls_reset,Reset,Zurücksetzen
controls_menu,Menu,Menu
controls_capture,Screen Capture,Aufzeichnung

BIN
resources/ui/i18n.de.translation

BIN
resources/ui/i18n.en.translation

9
resources/ui/theme.tres

@ -1,7 +1,10 @@
[gd_resource type="Theme" load_steps=2 format=2]
[gd_resource type="Theme" load_steps=3 format=2]
[ext_resource path="res://resources/ui/font.tres" type="DynamicFont" id=1]
[sub_resource type="StyleBoxFlat" id=1]
bg_color = Color( 0.184314, 0.188235, 0.211765, 1 )
[resource]
default_font = ExtResource( 1 )
Button/colors/font_color = Color( 0.878431, 0.878431, 0.878431, 1 )
@ -15,6 +18,8 @@ Button/styles/focus = null
Button/styles/hover = null
Button/styles/normal = null
Button/styles/pressed = null
Icons/icons/close = null
Icons/icons/logo = null
ItemList/colors/font_color = Color( 0.627451, 0.627451, 0.627451, 1 )
ItemList/colors/font_color_selected = Color( 1, 1, 1, 1 )
ItemList/colors/guide_color = Color( 0, 0, 0, 0.1 )
@ -29,6 +34,6 @@ ItemList/styles/cursor = null
ItemList/styles/cursor_unfocused = null
ItemList/styles/selected = null
ItemList/styles/selected_focus = null
Panel/styles/panel = null
Panel/styles/panel = SubResource( 1 )
Panel/styles/panelf = null
Panel/styles/panelnc = null

15
scenes/menus/BaseMenu.tscn

@ -1,7 +1,8 @@
[gd_scene load_steps=3 format=2]
[gd_scene load_steps=4 format=2]
[ext_resource path="res://resources/ui/font.tres" type="DynamicFont" id=1]
[ext_resource path="res://assets/icons/return.png" type="Texture" id=2]
[ext_resource path="res://resources/ui/theme.tres" type="Theme" id=1]
[ext_resource path="res://resources/ui/font.tres" type="DynamicFont" id=2]
[ext_resource path="res://assets/icons/return.png" type="Texture" id=3]
[node name="menu" type="Panel"]
anchor_left = 0.5
@ -17,13 +18,17 @@ grow_vertical = 2
rect_clip_content = true
size_flags_horizontal = 6
size_flags_vertical = 6
theme = ExtResource( 1 )
[node name="back" type="Button" parent="."]
anchor_top = 1.0
anchor_bottom = 1.0
margin_top = -56.0
margin_right = 132.0
custom_fonts/font = ExtResource( 1 )
size_flags_horizontal = 6
size_flags_vertical = 6
custom_fonts/font = ExtResource( 2 )
text = "BACK"
icon = ExtResource( 2 )
icon = ExtResource( 3 )
flat = true
align = 0

75
scenes/menus/DirectHostMenu.tscn

@ -1,7 +1,7 @@
[gd_scene load_steps=6 format=2]
[ext_resource path="res://resources/ui/theme.tres" type="Theme" id=1]
[ext_resource path="res://scripts/menus/direct_host.gd" type="Script" id=2]
[ext_resource path="res://scripts/menus/direct_host_menu.gd" type="Script" id=2]
[ext_resource path="res://resources/ui/font.tres" type="DynamicFont" id=3]
[ext_resource path="res://assets/icons/exitRight.png" type="Texture" id=4]
[ext_resource path="res://assets/icons/return.png" type="Texture" id=5]
@ -23,45 +23,67 @@ anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
margin_left = -217.5
margin_top = -53.5
margin_right = 217.5
margin_bottom = 53.5
margin_left = -217.0
margin_top = -53.0
margin_right = 218.0
margin_bottom = 94.0
grow_horizontal = 2
grow_vertical = 2
[node name="GridContainer" type="GridContainer" parent="menu"]
margin_left = 16.0
margin_top = 12.0
margin_right = 429.0
margin_bottom = 52.0
columns = 3
[node name="VBoxContainer" type="VBoxContainer" parent="menu"]
margin_left = 12.0
margin_top = 11.0
margin_right = 423.0
margin_bottom = 92.0
[node name="port_label" type="Label" parent="menu/GridContainer"]
margin_top = 6.0
[node name="HBoxContainer" type="HBoxContainer" parent="menu/VBoxContainer"]
margin_right = 411.0
margin_bottom = 37.0
[node name="port_label" type="Label" parent="menu/VBoxContainer/HBoxContainer"]
margin_top = 5.0
margin_right = 65.0
margin_bottom = 33.0
margin_bottom = 32.0
text = "PORT"
[node name="port" type="SpinBox" parent="menu/GridContainer"]
[node name="port" type="SpinBox" parent="menu/VBoxContainer/HBoxContainer"]
margin_left = 69.0
margin_right = 266.0
margin_bottom = 40.0
focus_neighbour_right = NodePath("../bots")
focus_neighbour_bottom = NodePath("../../back")
margin_right = 411.0
margin_bottom = 37.0
focus_neighbour_bottom = NodePath("../../HBoxContainer2/bots")
focus_mode = 2
size_flags_horizontal = 3
max_value = 65535.0
value = 8128.0
align = 2
[node name="bots" type="CheckButton" parent="menu/GridContainer"]
margin_left = 270.0
margin_right = 413.0
[node name="HBoxContainer2" type="HBoxContainer" parent="menu/VBoxContainer"]
margin_top = 41.0
margin_right = 411.0
margin_bottom = 81.0
[node name="bots" type="CheckButton" parent="menu/VBoxContainer/HBoxContainer2"]
margin_right = 143.0
margin_bottom = 40.0
focus_neighbour_left = NodePath("../port")
focus_neighbour_bottom = NodePath("../../host")
focus_neighbour_top = NodePath("../../HBoxContainer/port")
focus_neighbour_right = NodePath("../bot_difficulty")
focus_neighbour_bottom = NodePath("../../../back")
text = "BOTS"
[node name="bot_difficulty" type="HSlider" parent="menu/VBoxContainer/HBoxContainer2"]
margin_left = 147.0
margin_right = 411.0
margin_bottom = 40.0
focus_neighbour_left = NodePath("../bots")
focus_neighbour_top = NodePath("../../HBoxContainer/port")
focus_neighbour_bottom = NodePath("../../../host")
size_flags_horizontal = 3
size_flags_vertical = 1
max_value = 1.0
step = 0.1
tick_count = 11
ticks_on_borders = true
[node name="host" type="Button" parent="menu"]
anchor_left = 1.0
anchor_top = 1.0
@ -73,7 +95,7 @@ grow_horizontal = 0
grow_vertical = 0
rect_pivot_offset = Vector2( 1.89856, 0.845154 )
focus_neighbour_left = NodePath("../back")
focus_neighbour_top = NodePath("../GridContainer/bots")
focus_neighbour_top = NodePath("../VBoxContainer/HBoxContainer2/bot_difficulty")
custom_fonts/font = ExtResource( 3 )
text = "HOST"
icon = ExtResource( 4 )
@ -85,11 +107,12 @@ anchor_bottom = 1.0
margin_top = -56.0
margin_right = 132.0
rect_pivot_offset = Vector2( 0.606262, -0.447205 )
focus_neighbour_top = NodePath("../GridContainer/port")
focus_neighbour_top = NodePath("../VBoxContainer/HBoxContainer2/bots")
focus_neighbour_right = NodePath("../host")
custom_fonts/font = ExtResource( 3 )
text = "BACK"
icon = ExtResource( 5 )
flat = true
[connection signal="toggled" from="menu/VBoxContainer/HBoxContainer2/bots" to="." method="_on_bots_toggled"]
[connection signal="pressed" from="menu/host" to="." method="_on_host_pressed"]
[connection signal="pressed" from="menu/back" to="." method="_on_back_pressed"]

3
scenes/menus/DirectJoinMenu.tscn

@ -1,7 +1,7 @@
[gd_scene load_steps=6 format=2]
[ext_resource path="res://resources/ui/theme.tres" type="Theme" id=1]
[ext_resource path="res://scripts/menus/direct_join.gd" type="Script" id=2]
[ext_resource path="res://scripts/menus/direct_join_menu.gd" type="Script" id=2]
[ext_resource path="res://resources/ui/font.tres" type="DynamicFont" id=3]
[ext_resource path="res://assets/icons/exitRight.png" type="Texture" id=4]
[ext_resource path="res://assets/icons/return.png" type="Texture" id=5]
@ -69,6 +69,7 @@ margin_right = 407.0
margin_bottom = 78.0
focus_neighbour_top = NodePath("../ip")
focus_neighbour_bottom = NodePath("../../join")
focus_mode = 2
max_value = 65535.0
value = 8128.0
align = 2

20
scenes/menus/IngameMenu.tscn

@ -1,7 +1,7 @@
[gd_scene load_steps=6 format=2]
[ext_resource path="res://resources/ui/theme.tres" type="Theme" id=1]
[ext_resource path="res://scripts/menus/ingame.gd" type="Script" id=2]
[ext_resource path="res://scripts/menus/ingame_menu.gd" type="Script" id=2]
[ext_resource path="res://assets/icons/open.png" type="Texture" id=3]
[ext_resource path="res://assets/icons/wrench.png" type="Texture" id=4]
[ext_resource path="res://assets/icons/arrowLeft.png" type="Texture" id=5]
@ -26,11 +26,11 @@ margin_bottom = 100.5
grow_horizontal = 2
grow_vertical = 2
[node name="GridContainer" type="GridContainer" parent="menu"]
[node name="VBoxContainer" type="VBoxContainer" parent="menu"]
anchor_right = 1.0
anchor_bottom = 1.0
[node name="resume" type="Button" parent="menu/GridContainer"]
[node name="resume" type="Button" parent="menu/VBoxContainer"]
margin_right = 310.0
margin_bottom = 64.0
focus_neighbour_top = NodePath("../end")
@ -41,7 +41,7 @@ text = "RESUME"
icon = ExtResource( 3 )
flat = true
[node name="settings" type="Button" parent="menu/GridContainer"]
[node name="settings" type="Button" parent="menu/VBoxContainer"]
margin_top = 68.0
margin_right = 310.0
margin_bottom = 132.0
@ -53,17 +53,17 @@ text = "SETTINGS"
icon = ExtResource( 4 )
flat = true
[node name="end" type="Button" parent="menu/GridContainer"]
[node name="end" type="Button" parent="menu/VBoxContainer"]
margin_top = 136.0
margin_right = 310.0
margin_bottom = 200.0
margin_bottom = 201.0
focus_neighbour_top = NodePath("../settings")
focus_neighbour_bottom = NodePath(".")
focus_neighbour_bottom = NodePath("../resume")
size_flags_horizontal = 3
size_flags_vertical = 3
text = "END_GAME"
icon = ExtResource( 5 )
flat = true
[connection signal="pressed" from="menu/GridContainer/resume" to="." method="_on_resume_pressed"]
[connection signal="pressed" from="menu/GridContainer/settings" to="." method="_on_settings_pressed"]
[connection signal="pressed" from="menu/GridContainer/end" to="." method="_on_end_pressed"]
[connection signal="pressed" from="menu/VBoxContainer/resume" to="." method="_on_resume_pressed"]
[connection signal="pressed" from="menu/VBoxContainer/settings" to="." method="_on_settings_pressed"]
[connection signal="pressed" from="menu/VBoxContainer/end" to="." method="_on_end_pressed"]

8
scenes/menus/LobbyMenu.tscn

@ -1,13 +1,14 @@
[gd_scene load_steps=9 format=2]
[ext_resource path="res://resources/ui/theme.tres" type="Theme" id=1]
[ext_resource path="res://scripts/menus/lobby.gd" type="Script" id=2]
[ext_resource path="res://scripts/menus/lobby_menu.gd" type="Script" id=2]
[ext_resource path="res://scenes/menus/BaseMenu.tscn" type="PackedScene" id=3]
[ext_resource path="res://assets/icons/checkmark.png" type="Texture" id=4]
[ext_resource path="res://assets/icons/question.png" type="Texture" id=5]
[ext_resource path="res://scenes/menus/SettingsPlayerMenu.tscn" type="PackedScene" id=6]
[ext_resource path="res://assets/fonts/Kenney Future Narrow.ttf" type="DynamicFontData" id=7]
[sub_resource type="DynamicFont" id=1]
size = 100
font_data = ExtResource( 7 )
@ -27,12 +28,11 @@ script = ExtResource( 2 )
[node name="back" parent="menu" index="0"]
focus_neighbour_right = NodePath("../ready")
[node name="top_bar" type="GridContainer" parent="menu"]
[node name="top_bar" type="HBoxContainer" parent="menu"]
margin_left = 14.0
margin_top = 12.0
margin_right = 940.0
margin_bottom = 52.0
columns = 2
[node name="server_name" type="Label" parent="menu/top_bar"]
margin_right = 779.0
@ -59,6 +59,7 @@ margin_bottom = 397.0
columns = 3
[node name="players" type="ItemList" parent="menu/mid"]
editor/display_folded = true
margin_right = 456.0
margin_bottom = 340.0
size_flags_horizontal = 3
@ -81,6 +82,7 @@ margin_right = 464.0
margin_bottom = 340.0
[node name="player_settings" parent="menu/mid" instance=ExtResource( 6 )]
editor/display_folded = true
margin_left = 468.0
margin_top = 0.0
margin_right = 924.0

58
scenes/menus/LocalGameMenu.tscn

@ -23,57 +23,76 @@ anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
margin_left = -217.5
margin_top = -130.5
margin_top = -136.5
margin_right = 217.5
margin_bottom = 130.5
margin_bottom = 136.5
grow_horizontal = 2
grow_vertical = 2
[node name="GridContainer" type="GridContainer" parent="menu"]
[node name="VBoxContainer" type="VBoxContainer" parent="menu"]
margin_left = 19.0
margin_top = 21.0
margin_right = 418.0
margin_bottom = 197.0
margin_bottom = 210.0
[node name="player_settings" parent="menu/GridContainer" instance=ExtResource( 3 )]
[node name="player_settings" parent="menu/VBoxContainer" instance=ExtResource( 3 )]
margin_left = 0.0
margin_top = 0.0
margin_right = 399.0
margin_bottom = 132.0
margin_bottom = 145.0
[node name="name_label" parent="menu/GridContainer/player_settings/GridContainer" index="0"]
[node name="name_label" parent="menu/VBoxContainer/player_settings/VBoxContainer" index="0"]
margin_right = 399.0
margin_bottom = 27.0
[node name="name" parent="menu/GridContainer/player_settings/GridContainer" index="1"]
[node name="name" parent="menu/VBoxContainer/player_settings/VBoxContainer" index="1"]
margin_top = 31.0
margin_right = 399.0
margin_bottom = 68.0
focus_neighbour_bottom = NodePath("../color")
[node name="color_label" parent="menu/GridContainer/player_settings/GridContainer" index="2"]
[node name="color_label" parent="menu/VBoxContainer/player_settings/VBoxContainer" index="2"]
margin_top = 72.0
margin_right = 399.0
margin_bottom = 99.0
[node name="color" parent="menu/GridContainer/player_settings/GridContainer" index="3"]
[node name="color" parent="menu/VBoxContainer/player_settings/VBoxContainer" index="3"]
margin_top = 103.0
margin_right = 399.0
margin_bottom = 136.0
focus_neighbour_top = NodePath("../name")
focus_neighbour_bottom = NodePath("../../../bots")
focus_neighbour_bottom = NodePath("../../../HBoxContainer/bots")
[node name="bots" type="CheckButton" parent="menu/GridContainer"]
margin_top = 136.0
[node name="HBoxContainer" type="HBoxContainer" parent="menu/VBoxContainer"]
margin_top = 149.0
margin_right = 399.0
margin_bottom = 189.0
[node name="bots" type="CheckButton" parent="menu/VBoxContainer/HBoxContainer"]
margin_right = 143.0
margin_bottom = 176.0
focus_neighbour_top = NodePath("../player_settings/GridContainer/color")
focus_neighbour_bottom = NodePath("../../start")
margin_bottom = 40.0
focus_neighbour_top = NodePath("../../player_settings/VBoxContainer/color")
focus_neighbour_right = NodePath("../bot_difficulty")
focus_neighbour_bottom = NodePath("../../../back")
size_flags_horizontal = 0
pressed = true
text = "BOTS"
flat = true
[node name="bot_difficulty" type="HSlider" parent="menu/VBoxContainer/HBoxContainer"]
margin_left = 147.0
margin_right = 399.0
margin_bottom = 40.0
focus_neighbour_left = NodePath("../bots")
focus_neighbour_top = NodePath("../../player_settings/VBoxContainer/color")
focus_neighbour_bottom = NodePath("../../../start")
size_flags_horizontal = 3
size_flags_vertical = 1
max_value = 1.0
step = 0.1
tick_count = 11
ticks_on_borders = true
[node name="start" type="Button" parent="menu"]
anchor_left = 1.0
anchor_top = 1.0
@ -84,7 +103,7 @@ margin_top = -56.0
grow_horizontal = 0
rect_pivot_offset = Vector2( 1.89856, 0.845154 )
focus_neighbour_left = NodePath("../back")
focus_neighbour_top = NodePath("../GridContainer/bots")
focus_neighbour_top = NodePath("../VBoxContainer/HBoxContainer/bot_difficulty")
custom_fonts/font = ExtResource( 4 )
text = "START_GAME"
icon = ExtResource( 5 )
@ -96,13 +115,14 @@ anchor_bottom = 1.0
margin_top = -56.0
margin_right = 132.0
rect_pivot_offset = Vector2( 0.606262, -0.447205 )
focus_neighbour_top = NodePath("../GridContainer/bots")
focus_neighbour_top = NodePath("../VBoxContainer/HBoxContainer/bots")
focus_neighbour_right = NodePath("../start")
custom_fonts/font = ExtResource( 4 )
text = "BACK"
icon = ExtResource( 6 )
flat = true
[connection signal="toggled" from="menu/VBoxContainer/HBoxContainer/bots" to="." method="_on_bots_toggled"]
[connection signal="pressed" from="menu/start" to="." method="_on_start_pressed"]
[connection signal="pressed" from="menu/back" to="." method="_on_back_pressed"]
[editable path="menu/GridContainer/player_settings"]
[editable path="menu/VBoxContainer/player_settings"]

53
scenes/menus/MainMenu.tscn

@ -1,11 +1,12 @@
[gd_scene load_steps=7 format=2]
[gd_scene load_steps=8 format=2]
[ext_resource path="res://resources/ui/theme.tres" type="Theme" id=1]
[ext_resource path="res://scripts/menus/main.gd" type="Script" id=2]
[ext_resource path="res://scripts/menus/main_menu.gd" type="Script" id=2]
[ext_resource path="res://assets/icons/massiveMultiplayer.png" type="Texture" id=3]
[ext_resource path="res://assets/icons/singleplayer.png" type="Texture" id=4]
[ext_resource path="res://assets/icons/wrench.png" type="Texture" id=5]
[ext_resource path="res://assets/icons/power.png" type="Texture" id=6]
[ext_resource path="res://assets/icons/question.png" type="Texture" id=7]
[node name="main_menu" type="Control"]
anchor_right = 1.0
@ -27,11 +28,11 @@ margin_bottom = 132.5
grow_horizontal = 2
grow_vertical = 2
[node name="GridContainer" type="GridContainer" parent="menu"]
[node name="VBoxContainer" type="VBoxContainer" parent="menu"]
anchor_right = 1.0
anchor_bottom = 1.0
[node name="multiplayer" type="Button" parent="menu/GridContainer"]
[node name="multiplayer" type="Button" parent="menu/VBoxContainer"]
margin_right = 310.0
margin_bottom = 63.0
focus_neighbour_top = NodePath("../quit")
@ -42,7 +43,7 @@ text = "MULTIPLAYER"
icon = ExtResource( 3 )
flat = true
[node name="practice" type="Button" parent="menu/GridContainer"]
[node name="practice" type="Button" parent="menu/VBoxContainer"]
margin_top = 67.0
margin_right = 310.0
margin_bottom = 130.0
@ -54,7 +55,7 @@ text = "PRACTISE"
icon = ExtResource( 4 )
flat = true
[node name="settings" type="Button" parent="menu/GridContainer"]
[node name="settings" type="Button" parent="menu/VBoxContainer"]
margin_top = 134.0
margin_right = 310.0
margin_bottom = 197.0
@ -66,10 +67,10 @@ text = "SETTINGS"
icon = ExtResource( 5 )
flat = true
[node name="quit" type="Button" parent="menu/GridContainer"]
[node name="quit" type="Button" parent="menu/VBoxContainer"]
margin_top = 201.0
margin_right = 310.0
margin_bottom = 264.0
margin_bottom = 265.0
focus_neighbour_top = NodePath("../settings")
focus_neighbour_bottom = NodePath("../multiplayer")
size_flags_horizontal = 3
@ -78,13 +79,37 @@ text = "QUIT"
icon = ExtResource( 6 )
flat = true
[node name="version" type="Label" parent="."]
anchor_top = 1.0
anchor_bottom = 1.0
margin_top = -27.0
margin_right = 40.0
text = "v.0.0.3"
[node name="info" type="Button" parent="."]
anchor_left = 1.0
anchor_top = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
margin_left = -62.0
margin_top = -56.0
icon = ExtResource( 7 )
flat = true
[node name="info_popup" type="WindowDialog" parent="."]
margin_left = 805.0
margin_top = 407.5
margin_right = 853.0
margin_bottom = 447.5
[node name="error_dialog" type="AcceptDialog" parent="."]
margin_right = 138.0
margin_right = 324.0
margin_bottom = 84.0
window_title = "ALERT"
dialog_text = "Server disconnected!"
[connection signal="pressed" from="menu/GridContainer/multiplayer" to="." method="_on_multiplayer_pressed"]
[connection signal="pressed" from="menu/GridContainer/multiplayer" to="." method="_on_online_pressed"]
[connection signal="pressed" from="menu/GridContainer/practice" to="." method="_on_practice_pressed"]
[connection signal="pressed" from="menu/GridContainer/settings" to="." method="_on_settings_pressed"]
[connection signal="pressed" from="menu/GridContainer/quit" to="." method="_on_quit_pressed"]
[connection signal="pressed" from="menu/VBoxContainer/multiplayer" to="." method="_on_online_pressed"]
[connection signal="pressed" from="menu/VBoxContainer/multiplayer" to="." method="_on_multiplayer_pressed"]
[connection signal="pressed" from="menu/VBoxContainer/practice" to="." method="_on_practice_pressed"]
[connection signal="pressed" from="menu/VBoxContainer/settings" to="." method="_on_settings_pressed"]
[connection signal="pressed" from="menu/VBoxContainer/quit" to="." method="_on_quit_pressed"]
[connection signal="pressed" from="info" to="." method="_on_info_pressed"]

24
scenes/menus/MultiplayerMenu.tscn

@ -1,7 +1,7 @@
[gd_scene load_steps=11 format=2]
[ext_resource path="res://resources/ui/theme.tres" type="Theme" id=1]
[ext_resource path="res://scripts/menus/server.gd" type="Script" id=2]
[ext_resource path="res://scripts/menus/server_menu.gd" type="Script" id=2]
[ext_resource path="res://scenes/menus/BaseMenu.tscn" type="PackedScene" id=3]
[ext_resource path="res://assets/icons/cpu.png" type="Texture" id=4]
[ext_resource path="res://assets/icons/exitRight.png" type="Texture" id=5]
@ -11,6 +11,7 @@
[ext_resource path="res://assets/icons/massiveMultiplayer.png" type="Texture" id=9]
[ext_resource path="res://assets/icons/fistPlus.png" type="Texture" id=10]
[node name="multiplayer_menu" type="Control"]
anchor_right = 1.0
anchor_bottom = 1.0
@ -27,12 +28,11 @@ script = ExtResource( 2 )
focus_neighbour_top = NodePath("../games")
focus_neighbour_right = NodePath("../bottom_bar/refresh")
[node name="top_bar" type="GridContainer" parent="menu"]
[node name="HBoxContainer" type="HBoxContainer" parent="menu"]
anchor_right = 1.0
margin_bottom = 56.0
columns = 3
[node name="direct_host" type="Button" parent="menu/top_bar"]
[node name="direct_host" type="Button" parent="menu/HBoxContainer"]
margin_right = 239.0
margin_bottom = 56.0
focus_neighbour_right = NodePath("../direct_join")
@ -41,7 +41,7 @@ text = "DIRECT_HOST"
icon = ExtResource( 4 )
flat = true
[node name="direct_join" type="Button" parent="menu/top_bar"]
[node name="direct_join" type="Button" parent="menu/HBoxContainer"]
margin_left = 243.0
margin_right = 473.0
margin_bottom = 56.0
@ -52,7 +52,7 @@ text = "DIRECT_JOIN"
icon = ExtResource( 5 )
flat = true
[node name="open" type="CheckButton" parent="menu/top_bar"]
[node name="open" type="CheckButton" parent="menu/HBoxContainer"]
margin_left = 477.0
margin_right = 945.0
margin_bottom = 56.0
@ -90,14 +90,16 @@ margin_right = 12.0
margin_bottom = 33.0
icon = ExtResource( 8 )
[node name="bottom_bar" type="GridContainer" parent="menu"]
[node name="bottom_bar" type="HBoxContainer" parent="menu"]
anchor_top = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
margin_left = 380.0
margin_top = -56.0
grow_horizontal = 0
columns = 3
size_flags_horizontal = 6
size_flags_vertical = 6
alignment = 2
[node name="refresh" type="Button" parent="menu/bottom_bar"]
margin_right = 183.0
@ -146,9 +148,9 @@ wait_time = 5.0
autostart = true
[connection signal="draw" from="." to="." method="_on_multiplayer_menu_draw"]
[connection signal="hide" from="." to="." method="_on_multiplayer_menu_hide"]
[connection signal="pressed" from="menu/top_bar/direct_host" to="." method="_on_direct_host_pressed"]
[connection signal="pressed" from="menu/top_bar/direct_join" to="." method="_on_direct_join_pressed"]
[connection signal="toggled" from="menu/top_bar/open" to="." method="_on_open_toggled"]
[connection signal="pressed" from="menu/HBoxContainer/direct_host" to="." method="_on_direct_host_pressed"]
[connection signal="pressed" from="menu/HBoxContainer/direct_join" to="." method="_on_direct_join_pressed"]
[connection signal="toggled" from="menu/HBoxContainer/open" to="." method="_on_open_toggled"]
[connection signal="item_selected" from="menu/games" to="." method="_on_games_item_selected"]
[connection signal="nothing_selected" from="menu/games" to="." method="_on_games_nothing_selected"]
[connection signal="pressed" from="menu/bottom_bar/refresh" to="." method="_on_refresh_pressed"]

34
scenes/menus/ServerCreateGameMenu.tscn

@ -1,7 +1,7 @@
[gd_scene load_steps=6 format=2]
[ext_resource path="res://resources/ui/theme.tres" type="Theme" id=1]
[ext_resource path="res://scripts/menus/server_create.gd" type="Script" id=2]
[ext_resource path="res://scripts/menus/server_create_menu.gd" type="Script" id=2]
[ext_resource path="res://resources/ui/font.tres" type="DynamicFont" id=3]
[ext_resource path="res://assets/icons/fistPlus.png" type="Texture" id=4]
[ext_resource path="res://assets/icons/return.png" type="Texture" id=5]
@ -23,9 +23,9 @@ anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
margin_left = -217.5
margin_left = -296.5
margin_top = -68.5
margin_right = 217.5
margin_right = 296.5
margin_bottom = 68.5
grow_horizontal = 2
grow_vertical = 2
@ -33,7 +33,7 @@ grow_vertical = 2
[node name="GridContainer" type="GridContainer" parent="menu"]
margin_left = 12.0
margin_top = 11.0
margin_right = 427.0
margin_right = 584.0
margin_bottom = 92.0
columns = 2
@ -45,7 +45,7 @@ text = "GAME_NAME"
[node name="name" type="LineEdit" parent="menu/GridContainer"]
margin_left = 166.0
margin_right = 415.0
margin_right = 572.0
margin_bottom = 37.0
focus_neighbour_left = NodePath("../../back")
focus_neighbour_right = NodePath("../../create")
@ -56,13 +56,27 @@ size_flags_horizontal = 3
margin_top = 41.0
margin_right = 143.0
margin_bottom = 81.0
focus_neighbour_left = NodePath("../../back")
focus_neighbour_top = NodePath("../name")
focus_neighbour_right = NodePath("../../create")
focus_neighbour_bottom = NodePath("../../create")
focus_neighbour_right = NodePath("../bot_difficulty")
focus_neighbour_bottom = NodePath("../../back")
size_flags_horizontal = 0
text = "BOTS"
[node name="bot_difficulty" type="HSlider" parent="menu/GridContainer"]
margin_left = 166.0
margin_top = 41.0
margin_right = 572.0
margin_bottom = 81.0
focus_neighbour_left = NodePath("../bots")
focus_neighbour_top = NodePath("../name")
focus_neighbour_bottom = NodePath("../../create")
size_flags_horizontal = 3
size_flags_vertical = 1
max_value = 1.0
step = 0.1
tick_count = 11
ticks_on_borders = true
[node name="create" type="Button" parent="menu"]
anchor_left = 1.0
anchor_top = 1.0
@ -75,8 +89,7 @@ grow_horizontal = 0
grow_vertical = 0
rect_pivot_offset = Vector2( 1.89856, 0.845154 )
focus_neighbour_left = NodePath("../back")
focus_neighbour_top = NodePath("../GridContainer/bots")
focus_neighbour_right = NodePath("../GridContainer/name")
focus_neighbour_top = NodePath("../GridContainer/bot_difficulty")
custom_fonts/font = ExtResource( 3 )
text = "CREATE_GAME"
icon = ExtResource( 4 )
@ -95,5 +108,6 @@ text = "Back"
icon = ExtResource( 5 )
flat = true
[connection signal="text_changed" from="menu/GridContainer/name" to="." method="_on_name_text_changed"]
[connection signal="toggled" from="menu/GridContainer/bots" to="." method="_on_bots_toggled"]
[connection signal="pressed" from="menu/create" to="." method="_on_create_pressed"]
[connection signal="pressed" from="menu/back" to="." method="_on_back_pressed"]

36
scenes/menus/SettingsControlsMenu.tscn

@ -1,6 +1,6 @@
[gd_scene load_steps=20 format=2]
[ext_resource path="res://scripts/menus/settings_controls.gd" type="Script" id=1]
[ext_resource path="res://scripts/menus/settings_controls_menu.gd" type="Script" id=1]
[ext_resource path="res://assets/icons/keySmall_3d.png" type="Texture" id=2]
[ext_resource path="res://assets/icons/buttonA.png" type="Texture" id=3]
[ext_resource path="res://assets/icons/buttonB.png" type="Texture" id=4]
@ -20,24 +20,14 @@
[ext_resource path="res://assets/icons/DPAD_right.png" type="Texture" id=18]
[ext_resource path="res://assets/icons/fightJ.png" type="Texture" id=19]
[node name="settings_controls_menu" type="Control"]
[node name="settings_controls_menu" type="Tabs"]
margin_left = 12.0
margin_top = 8.0
margin_right = 858.0
margin_bottom = 335.0
script = ExtResource( 1 )
[node name="key_dialog" type="ConfirmationDialog" parent="."]
margin_left = 18.0
margin_top = 16.0
margin_right = 311.0
margin_bottom = 100.0
popup_exclusive = true
window_title = ""
dialog_text = "Press any key..."
[node name="ScrollContainer" type="ScrollContainer" parent="."]
editor/display_folded = true
anchor_right = 1.0
anchor_bottom = 1.0
@ -70,6 +60,7 @@ align = 1
valign = 1
[node name="icons" type="GridContainer" parent="."]
editor/display_folded = true
visible = false
margin_right = 40.0
margin_bottom = 40.0
@ -187,3 +178,24 @@ margin_top = 960.0
margin_right = 62.0
margin_bottom = 1016.0
icon = ExtResource( 19 )
[node name="key_dialog" type="ConfirmationDialog" parent="."]
margin_left = 57.9108
margin_top = 57.5398
margin_right = 367.911
margin_bottom = 216.54
popup_exclusive = true
window_title = ""
[node name="action_button" type="Button" parent="key_dialog"]
margin_left = 8.0
margin_top = 8.0
margin_right = 302.0
margin_bottom = 123.0
grow_horizontal = 2
grow_vertical = 2
size_flags_horizontal = 12
size_flags_vertical = 12
flat = true
clip_text = true
align = 0

53
scenes/menus/SettingsGameMenu.tscn

@ -0,0 +1,53 @@
[gd_scene load_steps=3 format=2]
[ext_resource path="res://scripts/menus/settings_game_menu.gd" type="Script" id=1]
[ext_resource path="res://scenes/menus/SettingsPlayerMenu.tscn" type="PackedScene" id=2]
[node name="settings_game_menu" type="Tabs"]
anchor_right = 1.0
anchor_bottom = 1.0
margin_left = 4.0
margin_top = 45.0
margin_right = -4.0
margin_bottom = -4.0
focus_neighbour_right = NodePath("../controls")
focus_neighbour_bottom = NodePath("GridContainer/settings_player/VBoxContainer/name")
focus_mode = 2
script = ExtResource( 1 )
[node name="GridContainer" type="GridContainer" parent="."]
margin_left = 9.0
margin_top = 10.0
margin_right = 416.0
margin_bottom = 202.0
[node name="settings_player" parent="GridContainer" instance=ExtResource( 2 )]
margin_left = 0.0
margin_top = 0.0
margin_right = 407.0
margin_bottom = 148.0
[node name="HBoxContainer" type="HBoxContainer" parent="GridContainer"]
margin_top = 152.0
margin_right = 407.0
margin_bottom = 192.0
[node name="bots" type="CheckButton" parent="GridContainer/HBoxContainer"]
margin_right = 109.0
margin_bottom = 40.0
focus_neighbour_top = NodePath("../settings_player/VBoxContainer/color")
focus_neighbour_bottom = NodePath("../../../../HBoxContainer/apply")
size_flags_horizontal = 0
size_flags_vertical = 0
text = "Bots"
[node name="bot_difficulty" type="HSlider" parent="GridContainer/HBoxContainer"]
margin_left = 113.0
margin_right = 407.0
margin_bottom = 40.0
size_flags_horizontal = 3
size_flags_vertical = 1
max_value = 1.0
step = 0.1
tick_count = 11
ticks_on_borders = true

44
scenes/menus/SettingsGraphicsMenu.tscn

@ -0,0 +1,44 @@
[gd_scene load_steps=2 format=2]
[ext_resource path="res://scripts/menus/settings_graphics_menu.gd" type="Script" id=1]
[node name="settings_graphics_menu" type="Tabs"]
anchor_right = 1.0
anchor_bottom = 1.0
margin_left = 4.0
margin_top = 45.0
margin_right = -4.0
margin_bottom = -4.0
focus_neighbour_left = NodePath("../controls")
focus_neighbour_right = NodePath("../system")
focus_mode = 2
script = ExtResource( 1 )
[node name="VBoxContainer" type="VBoxContainer" parent="."]
margin_right = 40.0
margin_bottom = 40.0
[node name="resolution" type="OptionButton" parent="VBoxContainer"]
margin_right = 192.0
margin_bottom = 20.0
[node name="fullscreen" type="CheckButton" parent="VBoxContainer"]
margin_top = 24.0
margin_right = 192.0
margin_bottom = 64.0
pressed = true
text = "FULLSCREEN"
[node name="light" type="CheckButton" parent="VBoxContainer"]
margin_top = 68.0
margin_right = 192.0
margin_bottom = 108.0
text = "LIGHT"
[node name="shadows" type="CheckButton" parent="VBoxContainer"]
margin_top = 112.0
margin_right = 192.0
margin_bottom = 152.0
disabled = true
text = "SHADOWS"
[connection signal="toggled" from="VBoxContainer/light" to="." method="_on_light_toggled"]

151
scenes/menus/SettingsMenu.tscn

@ -1,11 +1,14 @@
[gd_scene load_steps=7 format=2]
[gd_scene load_steps=10 format=2]
[ext_resource path="res://resources/ui/theme.tres" type="Theme" id=1]
[ext_resource path="res://scripts/menus/settings.gd" type="Script" id=2]
[ext_resource path="res://scripts/menus/settings_menu.gd" type="Script" id=2]
[ext_resource path="res://scenes/menus/BaseMenu.tscn" type="PackedScene" id=3]
[ext_resource path="res://scenes/menus/SettingsPlayerMenu.tscn" type="PackedScene" id=4]
[ext_resource path="res://scenes/menus/SettingsGameMenu.tscn" type="PackedScene" id=4]
[ext_resource path="res://scenes/menus/SettingsControlsMenu.tscn" type="PackedScene" id=5]
[ext_resource path="res://assets/icons/save.png" type="Texture" id=6]
[ext_resource path="res://scenes/menus/SettingsGraphicsMenu.tscn" type="PackedScene" id=6]
[ext_resource path="res://scenes/menus/SettingsSystemMenu.tscn" type="PackedScene" id=7]
[ext_resource path="res://assets/icons/checkmark.png" type="Texture" id=8]
[ext_resource path="res://assets/icons/save.png" type="Texture" id=9]
[node name="settings_menu" type="Control"]
anchor_right = 1.0
@ -19,6 +22,10 @@ script = ExtResource( 2 )
[node name="menu" parent="." instance=ExtResource( 3 )]
[node name="back" parent="menu" index="0"]
focus_neighbour_top = NodePath("../tabs/game")
focus_neighbour_right = NodePath("../HBoxContainer/apply")
[node name="tabs" type="TabContainer" parent="menu"]
anchor_left = 0.5
anchor_top = 0.5
@ -30,58 +37,14 @@ margin_right = 459.5
margin_bottom = 177.5
grow_horizontal = 2
grow_vertical = 2
focus_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
tab_align = 0
[node name="game" type="Tabs" parent="menu/tabs"]
anchor_right = 1.0
anchor_bottom = 1.0
margin_left = 4.0
margin_top = 45.0
margin_right = -4.0
margin_bottom = -4.0
[node name="GridContainer" type="GridContainer" parent="menu/tabs/game"]
margin_left = 9.0
margin_top = 10.0
margin_right = 416.0
margin_bottom = 200.0
[node name="settings_player" parent="menu/tabs/game/GridContainer" instance=ExtResource( 4 )]
margin_left = 0.0
margin_top = 0.0
margin_right = 407.0
margin_bottom = 146.0
[node name="name_label" parent="menu/tabs/game/GridContainer/settings_player/GridContainer" index="0"]
margin_right = 407.0
margin_bottom = 27.0
[node name="name" parent="menu/tabs/game/GridContainer/settings_player/GridContainer" index="1"]
margin_top = 31.0
margin_right = 407.0
margin_bottom = 68.0
[node name="game" parent="menu/tabs" instance=ExtResource( 4 )]
[node name="color_label" parent="menu/tabs/game/GridContainer/settings_player/GridContainer" index="2"]
margin_top = 72.0
margin_right = 407.0
margin_bottom = 99.0
[node name="color" parent="menu/tabs/game/GridContainer/settings_player/GridContainer" index="3"]
margin_top = 103.0
margin_right = 407.0
margin_bottom = 136.0
[node name="bots" type="CheckButton" parent="menu/tabs/game/GridContainer"]
margin_top = 150.0
margin_right = 143.0
margin_bottom = 190.0
size_flags_horizontal = 0
size_flags_vertical = 0
text = "Bots"
[node name="controls" type="Tabs" parent="menu/tabs"]
[node name="controls" parent="menu/tabs" instance=ExtResource( 5 )]
visible = false
anchor_right = 1.0
anchor_bottom = 1.0
@ -90,67 +53,55 @@ margin_top = 45.0
margin_right = -4.0
margin_bottom = -4.0
[node name="settings_controls" parent="menu/tabs/controls" instance=ExtResource( 5 )]
[node name="graphics" type="Tabs" parent="menu/tabs"]
[node name="graphics" parent="menu/tabs" instance=ExtResource( 6 )]
visible = false
anchor_right = 1.0
anchor_bottom = 1.0
margin_left = 4.0
margin_top = 45.0
margin_right = -4.0
margin_bottom = -4.0
[node name="system" type="Tabs" parent="menu/tabs"]
[node name="system" parent="menu/tabs" instance=ExtResource( 7 )]
visible = false
anchor_right = 1.0
anchor_bottom = 1.0
margin_left = 4.0
margin_top = 45.0
margin_right = -4.0
margin_bottom = -4.0
[node name="GridContainer" type="GridContainer" parent="menu/tabs/system"]
margin_left = 12.0
margin_top = 8.0
margin_right = 476.0
margin_bottom = 124.0
columns = 2
[node name="locale_label" type="Label" parent="menu/tabs/system/GridContainer"]
margin_right = 102.0
margin_bottom = 27.0
text = "LOCALE"
valign = 1
[node name="locales" type="ItemList" parent="menu/tabs/system/GridContainer"]
margin_left = 106.0
margin_right = 464.0
margin_bottom = 27.0
size_flags_horizontal = 3
auto_height = true
[node name="save" type="Button" parent="menu"]
[node name="HBoxContainer" type="HBoxContainer" parent="menu"]
anchor_left = 1.0
anchor_top = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
margin_left = -147.0
margin_left = -286.0
margin_top = -56.0
grow_horizontal = 0
grow_vertical = 0
size_flags_horizontal = 3
size_flags_vertical = 3
size_flags_horizontal = 8
size_flags_vertical = 8
alignment = 2
[node name="apply" type="Button" parent="menu/HBoxContainer"]
margin_right = 150.0
margin_bottom = 56.0
grow_horizontal = 0
grow_vertical = 0
focus_neighbour_left = NodePath("../../back")
focus_neighbour_top = NodePath("../../tabs/game")
focus_neighbour_right = NodePath("../save")
size_flags_horizontal = 10
size_flags_vertical = 10
text = "APPLY"
icon = ExtResource( 8 )
flat = true
align = 0
[node name="save" type="Button" parent="menu/HBoxContainer"]
margin_left = 154.0
margin_right = 286.0
margin_bottom = 56.0
grow_horizontal = 0
grow_vertical = 0
focus_neighbour_left = NodePath("../apply")
focus_neighbour_top = NodePath("../../tabs/game")
size_flags_horizontal = 10
size_flags_vertical = 10
text = "SAVE"
icon = ExtResource( 6 )
icon = ExtResource( 9 )
flat = true
[connection signal="item_selected" from="menu/tabs/system/GridContainer/locales" to="." method="_on_locales_item_selected"]
[connection signal="tree_exiting" from="menu/tabs/system/GridContainer/locales" to="." method="_on_locales_tree_exiting"]
[connection signal="visibility_changed" from="menu/tabs/system/GridContainer/locales" to="." method="_init_locales"]
[connection signal="pressed" from="menu/save" to="." method="_on_save_pressed"]
align = 0
[connection signal="pressed" from="menu/HBoxContainer/apply" to="." method="_on_apply_pressed"]
[connection signal="pressed" from="menu/HBoxContainer/save" to="." method="_on_save_pressed"]
[editable path="menu"]
[editable path="menu/tabs/game/GridContainer/settings_player"]
[editable path="menu/tabs/controls/settings_controls"]

12
scenes/menus/SettingsPlayerMenu.tscn

@ -1,6 +1,6 @@
[gd_scene load_steps=2 format=2]
[ext_resource path="res://scripts/menus/settings_player.gd" type="Script" id=1]
[ext_resource path="res://scripts/menus/settings_player_menu.gd" type="Script" id=1]
[node name="settings_player_menu" type="Control"]
margin_left = 513.0
@ -11,28 +11,28 @@ size_flags_horizontal = 3
size_flags_vertical = 3
script = ExtResource( 1 )
[node name="GridContainer" type="GridContainer" parent="."]
[node name="VBoxContainer" type="VBoxContainer" parent="."]
anchor_right = 1.0
anchor_bottom = 1.0
[node name="name_label" type="Label" parent="GridContainer"]
[node name="name_label" type="Label" parent="VBoxContainer"]
margin_right = 365.0
margin_bottom = 14.0
text = "PLAYER_NAME"
[node name="name" type="LineEdit" parent="GridContainer"]
[node name="name" type="LineEdit" parent="VBoxContainer"]
margin_top = 18.0
margin_right = 365.0
margin_bottom = 42.0
size_flags_horizontal = 3
[node name="color_label" type="Label" parent="GridContainer"]
[node name="color_label" type="Label" parent="VBoxContainer"]
margin_top = 46.0
margin_right = 365.0
margin_bottom = 60.0
text = "PLAYER_COLOR"
[node name="color" type="ColorPickerButton" parent="GridContainer"]
[node name="color" type="ColorPickerButton" parent="VBoxContainer"]
margin_top = 64.0
margin_right = 365.0
margin_bottom = 84.0

62
scenes/menus/SettingsSystemMenu.tscn

@ -0,0 +1,62 @@
[gd_scene load_steps=2 format=2]
[ext_resource path="res://scripts/menus/settings_system_menu.gd" type="Script" id=1]
[node name="system_settings_menu" type="Tabs"]
anchor_right = 1.0
anchor_bottom = 1.0
margin_left = 4.0
margin_top = 45.0
margin_right = -4.0
margin_bottom = -4.0
focus_neighbour_left = NodePath("../graphics")
focus_mode = 2
script = ExtResource( 1 )
[node name="GridContainer" type="GridContainer" parent="."]
margin_left = 12.0
margin_top = 8.0
margin_right = 907.0
margin_bottom = 124.0
columns = 2
[node name="locale_label" type="Label" parent="GridContainer"]
margin_right = 88.0
margin_bottom = 14.0
text = "LOCALE"
valign = 1
[node name="locales" type="ItemList" parent="GridContainer"]
margin_left = 92.0
margin_right = 895.0
margin_bottom = 14.0
size_flags_horizontal = 3
auto_height = true
[node name="server_addr_label" type="Label" parent="GridContainer"]
margin_top = 23.0
margin_right = 88.0
margin_bottom = 37.0
text = "SERVER_ADDR"
valign = 1
[node name="server_addr" type="LineEdit" parent="GridContainer"]
margin_left = 92.0
margin_top = 18.0
margin_right = 895.0
margin_bottom = 42.0
[node name="api_addr_label" type="Label" parent="GridContainer"]
margin_top = 51.0
margin_right = 88.0
margin_bottom = 65.0
text = "API_ADDR"
valign = 1
[node name="api_addr" type="LineEdit" parent="GridContainer"]
margin_left = 92.0
margin_top = 46.0
margin_right = 895.0
margin_bottom = 70.0
[connection signal="tree_exiting" from="." to="." method="_on_system_settings_menu_tree_exiting"]
[connection signal="item_selected" from="GridContainer/locales" to="." method="_on_locales_item_selected"]

7
scenes/player/BotPlayer.tscn

@ -3,10 +3,13 @@
[ext_resource path="res://scripts/player/bot_controls.gd" type="Script" id=1]
[ext_resource path="res://scripts/player/bot_inventory.gd" type="Script" id=2]
[node name="BotPlayer" type="Spatial"]
script = ExtResource( 1 )
[node name="inventory" type="Spatial" parent="."]
script = ExtResource( 2 )
[node name="rate_timer" type="Timer" parent="."]
wait_time = 0.1
autostart = true
[connection signal="timeout" from="rate_timer" to="." method="_on_rate_timer_timeout"]

74
scenes/player/HumanPlayer.tscn

@ -1,41 +1,73 @@
[gd_scene load_steps=11 format=2]
[gd_scene load_steps=14 format=2]
[ext_resource path="res://scripts/player/human_controls.gd" type="Script" id=1]
[ext_resource path="res://assets/fonts/Kenney Future Narrow.ttf" type="DynamicFontData" id=2]
[ext_resource path="res://resources/ui/theme.tres" type="Theme" id=3]
[ext_resource path="res://scenes/menus/IngameMenu.tscn" type="PackedScene" id=4]
[ext_resource path="res://scripts/player/human_inventory.gd" type="Script" id=5]
[ext_resource path="res://scenes/road/roadStraightLong.tscn" type="PackedScene" id=6]
[ext_resource path="res://scripts/player/inventory_preview.gd" type="Script" id=7]
[ext_resource path="res://scripts/screen_capture.gd" type="Script" id=2]
[ext_resource path="res://assets/icons/save.png" type="Texture" id=3]
[ext_resource path="res://resources/ui/theme.tres" type="Theme" id=4]
[ext_resource path="res://assets/fonts/Kenney Future Narrow.ttf" type="DynamicFontData" id=5]
[ext_resource path="res://scenes/menus/IngameMenu.tscn" type="PackedScene" id=6]
[ext_resource path="res://scripts/player/human_inventory.gd" type="Script" id=7]
[ext_resource path="res://scenes/road/roadStraightLong.tscn" type="PackedScene" id=8]
[ext_resource path="res://scripts/player/inventory_preview.gd" type="Script" id=9]
[sub_resource type="StyleBoxFlat" id=4]
bg_color = Color( 1, 0, 0, 1 )
[sub_resource type="ViewportTexture" id=1]
viewport_path = NodePath("inventory/viewport")
[sub_resource type="DynamicFont" id=2]
size = 14
font_data = ExtResource( 2 )
font_data = ExtResource( 5 )
[sub_resource type="DynamicFont" id=3]
size = 85
font_data = ExtResource( 2 )
font_data = ExtResource( 5 )
[node name="HumanPlayer" type="Spatial"]
script = ExtResource( 1 )
[node name="hud" type="CanvasLayer" parent="."]
[node name="screen_capture" type="Control" parent="hud"]
anchor_right = 1.0
anchor_bottom = 1.0
script = ExtResource( 2 )
[node name="recording" type="ColorRect" parent="hud/screen_capture"]
visible = false
anchor_left = 1.0
anchor_right = 1.0
margin_left = -50.0
margin_bottom = 50.0
color = Color( 1, 0, 0, 1 )
[node name="saving" type="Button" parent="hud/screen_capture"]
visible = false
anchor_left = 1.0
anchor_right = 1.0
margin_left = -50.0
margin_bottom = 50.0
custom_styles/normal = SubResource( 4 )
disabled = true
shortcut_in_tooltip = false
icon = ExtResource( 3 )
flat = true
[node name="inventory" type="Control" parent="hud"]
editor/display_folded = true
anchor_right = 1.0
anchor_bottom = 1.0
theme = ExtResource( 4 )
[node name="background" type="ColorRect" parent="hud/inventory"]
[node name="track_container" type="Panel" parent="hud/inventory"]
anchor_left = 0.5
anchor_right = 0.5
margin_left = -75.0
margin_right = 75.0
margin_bottom = 150.0
[node name="track" type="TextureRect" parent="hud/inventory"]
[node name="track" type="TextureRect" parent="hud/inventory/track_container"]
anchor_left = 0.5
anchor_right = 0.5
margin_left = -75.0
@ -43,7 +75,7 @@ margin_right = 75.0
margin_bottom = 150.0
texture = SubResource( 1 )
[node name="type" type="Label" parent="hud/inventory"]
[node name="type" type="Label" parent="hud/inventory/track_container"]
anchor_left = 0.5
anchor_right = 0.5
margin_left = -74.0
@ -52,10 +84,15 @@ margin_bottom = 58.0
grow_horizontal = 2
grow_vertical = 2
custom_fonts/font = SubResource( 2 )
custom_colors/font_color = Color( 0, 0, 0, 1 )
align = 1
valign = 1
[node name="speed_slider" type="VSlider" parent="hud"]
anchor_bottom = 1.0
margin_right = 16.0
max_value = 250.0
step = 0.5
[node name="speed" type="Label" parent="hud"]
anchor_left = 0.5
anchor_top = 1.0
@ -66,7 +103,7 @@ margin_top = -39.0
margin_right = 77.0
grow_horizontal = 2
grow_vertical = 2
theme = ExtResource( 3 )
theme = ExtResource( 4 )
align = 1
valign = 1
@ -86,11 +123,12 @@ align = 1
valign = 1
uppercase = true
[node name="ingame_menu" parent="hud" instance=ExtResource( 4 )]
[node name="ingame_menu" parent="hud" instance=ExtResource( 6 )]
visible = false
[node name="inventory" type="Spatial" parent="."]
script = ExtResource( 5 )
editor/display_folded = true
script = ExtResource( 7 )
[node name="viewport" type="Viewport" parent="inventory"]
size = Vector2( 150, 150 )
@ -108,11 +146,11 @@ far = 20.0
[node name="view" type="Spatial" parent="inventory"]
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, -50, -1000, 0 )
[node name="roadStraightLong" parent="inventory/view" instance=ExtResource( 6 )]
[node name="roadStraightLong" parent="inventory/view" instance=ExtResource( 8 )]
transform = Transform( -4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 0, 0, 0 )
[node name="preview" type="Spatial" parent="inventory"]
script = ExtResource( 7 )
script = ExtResource( 9 )
[node name="camera" type="InterpolatedCamera" parent="."]
fov = 100.0

1
scenes/player/Player.tscn

@ -31,7 +31,6 @@ rotation_mode = 4
loop = false
[node name="raceCar" type="KinematicBody" parent="Path/PathFollow"]
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 )
collision_layer = 31
collision_mask = 31
script = ExtResource( 2 )

2
scenes/road/roadCornerLarge.tscn

@ -13,7 +13,7 @@ script = ExtResource( 2 )
end_rotation = Vector3( 0, -1.571, 0 )
speed_constrains = PoolVector3Array( 0.2, 0.6, 0.13, 0.6, 1.5, 0.1, 1.5, 2.36, 0.13 )
force_penalties = PoolVector3Array( 2, 0, 8 )
torque_penalties = PoolVector3Array( 0.5, 0.1, 0.1 )
torque_penalties = PoolVector3Array( 0.1, 0.1, -0.5 )
[node name="Path" type="Path" parent="."]
curve = ExtResource( 3 )

4
scenes/road/roadCornerLargeFlipped.tscn

@ -12,8 +12,8 @@ material/2 = null
script = ExtResource( 2 )
end_rotation = Vector3( 0, 1.571, 0 )
speed_constrains = PoolVector3Array( 0.2, 0.6, 0.13, 0.6, 1.5, 0.1, 1.5, 2.36, 0.13 )
force_penalties = PoolVector3Array( 1, 0, 5 )
torque_penalties = PoolVector3Array( 0, 1, 1.5 )
force_penalties = PoolVector3Array( 2, 0, 8 )
torque_penalties = PoolVector3Array( 0.1, 0.1, 0.5 )
[node name="Path" type="Path" parent="."]
curve = ExtResource( 3 )

4
scenes/road/roadCornerLarger.tscn

@ -12,8 +12,8 @@ material/2 = null
script = ExtResource( 2 )
end_rotation = Vector3( 0, -1.571, 0 )
speed_constrains = PoolVector3Array( 0.3, 1, 0.16, 1, 2.7, 0.13, 2.7, 3.93, 0.16 )
force_penalties = PoolVector3Array( 0, 0, 5 )
torque_penalties = PoolVector3Array( 0, 0, 1 )
force_penalties = PoolVector3Array( 2, 0, 8 )
torque_penalties = PoolVector3Array( 0.1, 0.1, -0.5 )
[node name="Path" type="Path" parent="."]
curve = ExtResource( 3 )

4
scenes/road/roadCornerLargerFlipped.tscn

@ -12,8 +12,8 @@ material/2 = null
script = ExtResource( 2 )
end_rotation = Vector3( 0, 1.571, 0 )
speed_constrains = PoolVector3Array( 0.3, 1, 0.16, 1, 2.7, 0.13, 2.7, 3.93, 0.16 )
force_penalties = PoolVector3Array( 0, 0, 5 )
torque_penalties = PoolVector3Array( 0, 0, -1 )
force_penalties = PoolVector3Array( 2, 0, 8 )
torque_penalties = PoolVector3Array( 0.1, 0.1, 0.5 )
[node name="Path" type="Path" parent="."]
curve = ExtResource( 3 )

6
scenes/road/roadCornerSmall.tscn

@ -11,9 +11,9 @@ material/1 = null
material/2 = null
script = ExtResource( 2 )
end_rotation = Vector3( 0, -1.571, 0 )
speed_constrains = PoolVector3Array( 0.1, 0.79, 0.08 )
force_penalties = PoolVector3Array( 0, 0, 5 )
torque_penalties = PoolVector3Array( 0, 0, 1 )
speed_constrains = PoolVector3Array( 0.1, 0.6, 0.08 )
force_penalties = PoolVector3Array( 2, 0, 8 )
torque_penalties = PoolVector3Array( 0.1, 0.1, -0.5 )
[node name="Path" type="Path" parent="."]
curve = ExtResource( 3 )

6
scenes/road/roadCornerSmallFlipped.tscn

@ -11,9 +11,9 @@ material/1 = null
material/2 = null
script = ExtResource( 2 )
end_rotation = Vector3( 0, 1.571, 0 )
speed_constrains = PoolVector3Array( 0.1, 0.79, 0.08 )
force_penalties = PoolVector3Array( 0, 0, 5 )
torque_penalties = PoolVector3Array( 0, 0, -1 )
speed_constrains = PoolVector3Array( 0.1, 0.6, 0.08 )
force_penalties = PoolVector3Array( 2, 0, 8 )
torque_penalties = PoolVector3Array( 0.1, 0.1, 0.5 )
[node name="Path" type="Path" parent="."]
curve = ExtResource( 3 )

2
scenes/road/roadRamp.tscn

@ -11,7 +11,7 @@ material/1 = null
material/2 = null
script = ExtResource( 2 )
reset_index = 1
speed_constrains = PoolVector3Array( 0, 1, -0.05 )
speed_constrains = PoolVector3Array( 0.5, 0.9, -0.025 )
path_penalties = [ 1.0 ]
[node name="Path" type="Path" parent="."]

2
scenes/road/roadRampFlipped.tscn

@ -10,7 +10,7 @@ material/0 = null
material/1 = null
material/2 = null
script = ExtResource( 2 )
speed_constrains = PoolVector3Array( 0, 0.3, 0.12 )
speed_constrains = PoolVector3Array( 0, 0.1, 0.12 )
force_penalties = PoolVector3Array( 0, 0, 4 )
[node name="Path" type="Path" parent="."]

4
scenes/road/roadRampLong.tscn

@ -11,8 +11,10 @@ material/1 = null
material/2 = null
script = ExtResource( 2 )
reset_index = 1
speed_constrains = PoolVector3Array( 0, 2, -0.05 )
speed_constrains = PoolVector3Array( 0.7, 1.9, -0.03 )
path_penalties = [ 2.0 ]
[node name="Path" type="Path" parent="."]
curve = ExtResource( 3 )
[node name="PathFollow" type="PathFollow" parent="Path"]

2
scenes/road/roadRampLongCurved.tscn

@ -11,7 +11,7 @@ material/1 = null
material/2 = null
script = ExtResource( 2 )
reset_index = 1
speed_constrains = PoolVector3Array( 0.25, 1.5, -0.05 )
speed_constrains = PoolVector3Array( 0.7, 1.5, -0.03 )
path_penalties = [ 1.25 ]
[node name="Path" type="Path" parent="."]

2
scenes/road/roadRampLongFlipped.tscn

@ -10,7 +10,7 @@ material/0 = null
material/1 = null
material/2 = null
script = ExtResource( 2 )
speed_constrains = PoolVector3Array( 0, 0.1, 0.12 )
speed_constrains = PoolVector3Array( 0.1, 0.3, 0.12 )
force_penalties = PoolVector3Array( 0, 0, 4 )
[node name="Path" type="Path" parent="."]

12
scripts/Util.gd

@ -1,12 +0,0 @@
extends Node
class_name Util
static func clear_node(node:Node):
for idx in range(node.get_child_count()):
node.remove_child(node.get_child(0))
static func curve_get_last_point(curve:Curve3D):
return curve.get_point_position(curve.get_point_count() - 1)

27
scripts/game/config.gd

@ -0,0 +1,27 @@
extends Node
const FILE_PATH = "user://local_storage"
const RESOLUTIONS = [Vector2(1920,1080),Vector2(1600,900),Vector2(1366,758),Vector2(1280,720),Vector2(1136,640),Vector2(1024,576)]
const CONTROL_ACTIONS = ["controls_thrust", "controls_break", "controls_add_road", "controls_next_road_type", "controls_prev_road_type", "controls_next_road_variant", "controls_prev_road_variant", "controls_reset", "controls_menu", "controls_capture"]
const INPUT_UI_MAPPING = {"ui_accept" : "controls_add_road", "ui_select" : "controls_add_road", "ui_up" : "controls_next_road_variant", "ui_down" : "controls_prev_road_variant", "ui_left" : "controls_prev_road_type", "ui_right" : "controls_next_road_type"}
var config_file:ConfigFile = ConfigFile.new()
func _ready():
config_file.load(FILE_PATH)
func save():
config_file.save(FILE_PATH)
func get_value(section:String, key:String, default = null):
return config_file.get_value(section,key,default)
func set_value(section:String, key:String, value):
config_file.set_value(section,key,value)

63
scripts/game/config_apply.gd

@ -0,0 +1,63 @@
extends Node
const FILE_PATH = "user://local_storage"
func _ready():
apply_settings()
func apply_settings():
apply_locale()
apply_game_server()
apply_resolution()
apply_controls()
func apply_locale():
TranslationServer.set_locale(config.get_value("system","locale","en"))
func apply_game_server():
var server_addr = config.get_value("system", "server_addr")
if server_addr != null && not server_addr.empty():
game_server.set_server_addr(server_addr)
var api_addr = config.get_value("system","api_addr")
if api_addr != null && not api_addr.empty():
game_server.set_api_addr(api_addr)
func apply_resolution():
var view_port = get_tree().get_root()
OS.set_window_fullscreen(config.get_value("graphics","fullscreen", true))
var resolution = config.get_value("graphics","resolution",config.RESOLUTIONS[0])
if OS.is_window_fullscreen():
var base_size = Vector2(1920, 1080)
var scale= base_size.x / resolution.x
get_tree().set_screen_stretch(SceneTree.STRETCH_MODE_2D,SceneTree.STRETCH_ASPECT_EXPAND,base_size,scale)
else:
OS.set_window_size(resolution)
OS.set_window_position(Vector2((OS.get_screen_size().x - resolution.x) / 2, (OS.get_screen_size().y - resolution.y) / 2)) # center screen
get_tree().set_screen_stretch(SceneTree.STRETCH_MODE_VIEWPORT,SceneTree.STRETCH_ASPECT_IGNORE,OS.get_window_size(),1)
func apply_controls():
InputMap.load_from_globals()
var control_map = config.get_value("controls","mapping",{})
for action in InputMap.get_actions():
if control_map.has(action):
for event in InputMap.get_action_list(action):
if event is InputEventKey && control_map[action].has("key"):
InputMap.action_erase_event(action, event)
event.set_scancode(OS.find_scancode_from_string(control_map[action]["key"]))
InputMap.action_add_event(action,event)
elif event is InputEventJoypadButton && control_map[action].has("joypad"):
InputMap.action_erase_event(action, event)
event.set_button_index(control_map[action]["joypad"])
InputMap.action_add_event(action,event)
for ui_mapping in config.INPUT_UI_MAPPING:
for event in InputMap.get_action_list(config.INPUT_UI_MAPPING[ui_mapping]):
InputMap.action_add_event(ui_mapping, event)

19
scripts/game/game.gd

@ -12,8 +12,12 @@ const REMOVE_LAST = 2
func _ready():
route = get_node("route")
find_node("sun").set_visible(config.get_value("graphics","light", false))
if find_node("sun").is_visible_in_tree():
find_node("sun").set_shadow(config.get_value("graphics","shadows", false))
if is_network_master():
route.rpc("add_road",roads_factory.START, -1)
route.set_road(roads_factory.START, -1)
route.rpc("set_road",roads_factory.START, -1)
func _physics_process(delta):
@ -22,6 +26,16 @@ func _physics_process(delta):
check_autotrack()
func get_player(player_id:String):
if get_node("players") != null && get_node("players").has_node(player_id):
return get_node("players").get_node(player_id)
return null
func get_player_by_network_id(network_id:int):
return get_player(str(network_id))
func set_player_order():
players = get_node("players").get_children()
players.sort_custom(PlayerSorter,"sort")
@ -42,7 +56,8 @@ func check_autotrack():
if first != null:
if first.position.x != -1 && route.get_last_road() != null:
if first.position.x == route.get_last_road().get_index():
route.rpc("add_road", roads_factory.STRAIGHT, -1)
route.set_road(roads_factory.STRAIGHT, -1)
route.rpc("set_road", roads_factory.STRAIGHT, -1)
class PlayerSorter:

41
scripts/game/gamestate.gd

@ -3,6 +3,8 @@ extends Node
const MAX_PEERS = 4
const LOBBY_READY_WAIT_TIME = 3
const DEFAULT_BOT_DIFFICULTY = 0.5
var Game = preload("res://scenes/game/Game.tscn")
var Player = preload("res://scenes/player/Player.tscn")
var HumanPlayer = preload("res://scenes/player/HumanPlayer.tscn")
@ -13,6 +15,7 @@ var players = {}
var game_name = ""
var bots:bool = false
var bot_difficulty:float = DEFAULT_BOT_DIFFICULTY
var game_running:bool = false
signal players_changed(players)
@ -24,11 +27,11 @@ signal game_ended()
remote func set_player(id, new_name:String = " ", new_color:Color = Color.black, new_ready:bool = false):
players[id] = {"name" : new_name, "color" : new_color, "ready" : new_ready, "prepared" : false}
emit_signal("players_changed", players)
if get_tree().is_network_server():
var all_ready = true
for p_id in players:
rpc_id(id, "set_player", p_id, players[p_id].name, players[p_id].color, players[p_id].ready)
for p_id in players:
rpc_id(id, "set_player", p_id, players[p_id].name, players[p_id].color, players[p_id].ready)
rpc_id(p_id, "set_player", id, new_name, new_color, new_ready)
all_ready = all_ready && players[p_id].ready
rpc("game_ready", all_ready)
@ -43,12 +46,12 @@ func update_player(new_name:String = " ", new_color:Color = Color.black, new_rea
remotesync func remove_player(id):
players.erase(id)
if game != null:
var game_players = game.get_node("players")
if game_players.has_node(str(id)):
game_players.remove_child(game_players.get_node(str(id)))
emit_signal("players_changed", players)
@ -63,32 +66,32 @@ remotesync func game_ready(all_ready:bool):
remotesync func prepare_game():
get_tree().set_pause(true)
game = Game.instance()
get_tree().get_root().add_child(game)
get_tree().get_root().get_node("main_menu").hide()
for p_id in players:
var controls
var player = players[p_id]
var player_scene = Player.instance()
player_scene.set_network_master(p_id)
# player_scene.set_network_master(p_id)
player_scene.set_name(str(p_id))
game.get_node("players").add_child(player_scene)
player_scene.set_player_name(player.name)
player_scene.set_player_color(player.color)
if p_id == get_tree().get_network_unique_id():
controls = HumanPlayer.instance()
controls.set_name("HumanControl_" + str(p_id))
game.add_child(controls)
controls.set_player(player_scene.get_path())
controls.set_network_master(p_id)
player_scene.set_start(player_scene.get_index())
if bots:
for index in range(MAX_PEERS-players.size()):
var bot_index = players.size() + index
@ -96,13 +99,14 @@ remotesync func prepare_game():
player_scene.set_name("bot_player" + str(bot_index))
game.get_node("players").add_child(player_scene)
player_scene.set_player_name("Bot " + str(bot_index))
player_scene.set_player_color(Color(randf(),randf(),randf()))
player_scene.set_player_color(Color(util.randf(),util.randf(),util.randf()))
player_scene.add_to_group("bots")
if get_tree().is_network_server():
var bot = BotPlayer.instance()
bot.set_name("bot" + str(bot_index))
game.add_child(bot)
bot.set_player(player_scene.get_path())
bot.set_difficulty(bot_difficulty)
bot.set_network_master(get_tree().get_network_unique_id())
player_scene.set_start(bot_index)
if players.has(get_tree().get_network_unique_id()):
@ -119,7 +123,7 @@ remotesync func player_prepared(id):
if get_tree().is_network_server():
players[id].prepared = true
var all_prepared = true
for p_id in players:
for p_id in players:
all_prepared = all_prepared && players[p_id].prepared
if all_prepared:
rpc("post_start_game")
@ -134,8 +138,13 @@ remotesync func set_bots(has_bots:bool):
bots = has_bots
remotesync func set_bot_difficulty(new_bot_difficulty:float):
if new_bot_difficulty >= 0 && new_bot_difficulty <= 1:
bot_difficulty = new_bot_difficulty
func quit_game():
if game != null:
if game != null:
game.queue_free()
game = null
@ -148,5 +157,5 @@ func quit_game():
game_running = false
bots = false
game_name = ""
emit_signal("game_ended")

58
scripts/game/local_storage.gd

@ -1,58 +0,0 @@
extends Node
const FILE_PATH = "user://local_storage"
func _ready():
TranslationServer.set_locale(read_value("locale","en"))
func read_content():
var f = File.new()
var err = f.open(FILE_PATH, File.READ)
var content = {}
if err == OK:
content = parse_json(f.get_as_text())
f.close()
if content == null:
content = {}
return content
func write_content(content:Dictionary):
var f = File.new()
var err = f.open(FILE_PATH, File.WRITE)
#var err = f.open_encrypted_with_pass(FILE_PATH, File.WRITE, OS.get_unique_id())
f.store_string(to_json(content))
f.close()
func write_value(key:String, value):
var content = read_content()
content[key] = value
write_content(content)
func read_value(key:String, default = null):
var content = read_content()
if content.has(key) && content.get(key) != null:
return content.get(key)
else:
return default
func delete_value(key:String):
var content = read_content()
content.erase(key)
write_content(content)
func write_values(new_content:Dictionary):
var content = read_content()
for key in new_content:
content[key] = new_content[key]
write_content(content)
func read_values():
return read_content()

33
scripts/game/route.gd

@ -14,10 +14,24 @@ func get_last_road():
func get_road(road_index):
return get_child(road_index)
if road_index >= 0 && get_child_count() > road_index:
return get_child(road_index)
else:
return null
master func add_road(type):
if is_network_master():
var sender_id = get_tree().get_rpc_sender_id()
if sender_id == 0:
sender_id = 1
var creator = gamestate.game.get_player_by_network_id(sender_id)
if creator != null && creator.is_in_group("first"):
set_road(type,creator.get_name())
rpc("set_road", type, creator.get_name())
remotesync func add_road(type, creator):
puppet func set_road(type, creator):
var transform = get_global_transform()
var last_road = get_last_road()
if last_road != null:
@ -26,19 +40,18 @@ remotesync func add_road(type, creator):
transform = transform.translated(curve.get_point_position(curve.get_point_count() - 1))
if last_road.get_end_rotation().length() != 0:
transform.basis = transform.basis.rotated(last_road.get_end_rotation().normalized(), last_road.get_end_rotation().length())
var new_road = roads_factory.get_road_instance(type)
new_road.set_global_transform(transform)
new_road.set_preview(false)
new_road.set_creator(creator)
if creator > 0:
var player = gamestate.game.get_node(str(creator))
if player != null:
new_road.set_color(player.get_player_color())
var player = gamestate.game.get_player(str(creator))
if player != null:
new_road.set_color(player.get_player_color())
add_child(new_road)
emit_signal("road_added", new_road)

18
scripts/menus/direct_host.gd → scripts/menus/direct_host_menu.gd

@ -4,7 +4,10 @@ var LobbyMenu = preload("res://scenes/menus/LobbyMenu.tscn")
func _ready():
find_node("bots").set_pressed(local_storage.read_value("bots", true))
find_node("bots").set_pressed(config.get_value("game","bots", true))
find_node("bot_difficulty").set_value(config.get_value("game","bot_difficulty", gamestate.DEFAULT_BOT_DIFFICULTY))
find_node("bot_difficulty").set_editable(find_node("bots").is_pressed())
find_node("bot_difficulty").set_tooltip(tr("BOT_DIFFICULTY"))
func _draw():
@ -14,14 +17,15 @@ func _draw():
func _on_host_pressed():
var port = find_node("port").get_value()
var bots = find_node("bots").is_pressed()
var err = server.host_game(int(port), bots)
var bot_difficulty = find_node("bot_difficulty").get_value()
var err = server.host_game(int(port), bots, bot_difficulty)
if err == OK:
var lobby_menu = LobbyMenu.instance()
get_tree().get_root().add_child(lobby_menu)
gamestate.set_player(get_tree().get_network_unique_id())
queue_free()
else:
_on_back_pressed()
@ -31,3 +35,7 @@ func _on_host_pressed():
func _on_back_pressed():
queue_free()
get_tree().get_root().get_node("multiplayer_menu").show()
func _on_bots_toggled(button_pressed):
find_node("bot_difficulty").set_editable(button_pressed)

4
scripts/menus/direct_join.gd → scripts/menus/direct_join_menu.gd

@ -6,8 +6,8 @@ func _draw():
func _on_join_pressed():
var ip = find_node("ip").text
var port = find_node("port").get_value()
var ip = find_node("ip").text
var port = find_node("port").get_value()
client.join_game(ip, int(port))
queue_free()

25
scripts/menus/ingame.gd

@ -1,25 +0,0 @@
extends Control
func _draw():
find_node("resume").grab_focus()
func _physics_process(delta):
if Input.is_action_just_pressed("ui_cancel"):
if is_visible_in_tree():
hide()
else:
show()
func _on_resume_pressed():
hide()
func _on_settings_pressed():
pass
func _on_end_pressed():
gamestate.quit_game()

21
scripts/menus/ingame_menu.gd

@ -0,0 +1,21 @@
extends Control
var SettingsMenu = preload("res://scenes/menus/SettingsMenu.tscn")
func _draw():
find_node("resume").grab_focus()
func _on_resume_pressed():
hide()
func _on_settings_pressed():
var settings_menu = SettingsMenu.instance()
get_parent().add_child(settings_menu)
hide()
func _on_end_pressed():
gamestate.quit_game()

16
scripts/menus/lobby.gd → scripts/menus/lobby_menu.gd

@ -10,21 +10,21 @@ func _ready():
get_tree().get_root().get_node("multiplayer_menu").hide()
if get_tree().get_root().has_node("main_menu"):
get_tree().get_root().get_node("main_menu").hide()
get_node("menu/back").connect("pressed",self,"_on_back_pressed")
gamestate.connect("players_changed", self, "_players_changed")
gamestate.connect("game_ready", self, "_game_ready")
gamestate.connect("game_started", self, "_game_started")
client.connect("server_disconnected", self, "_server_disconnected")
player_settings.get_name_node().connect("text_changed",self,"_on_name_text_changed")
player_settings.get_color_node().connect("color_changed",self,"_on_color_color_changed")
player_settings.get_color_node().connect("draw",self,"_on_player_changed")
countdown_timer.set_wait_time(server.LOBBY_READY_WAIT_TIME)
if gamestate.game_name:
if gamestate.game_name:
find_node("server_name").set_text(gamestate.game_name)
find_node("server_name").set_tooltip(gamestate.game_name)
@ -33,7 +33,7 @@ func _draw():
find_node("ready").grab_focus()
func _physics_process(delta):
func _process(delta):
if not countdown_timer.is_stopped():
get_node("countdown").text = str(int(countdown_timer.get_time_left()) + 1)
@ -61,7 +61,7 @@ func _game_ready(all_ready):
else:
countdown_timer.stop()
get_node("countdown").hide()
func _game_started():
queue_free()

12
scripts/menus/local_game.gd

@ -4,7 +4,10 @@ onready var player_settings = find_node("player_settings")
func _ready():
find_node("bots").set_pressed(local_storage.read_value("bots", true))
find_node("bots").set_pressed(config.get_value("game","bots", true))
find_node("bot_difficulty").set_value(config.get_value("game","bot_difficulty", gamestate.DEFAULT_BOT_DIFFICULTY))
find_node("bot_difficulty").set_editable(find_node("bots").is_pressed())
find_node("bot_difficulty").set_tooltip(tr("BOT_DIFFICULTY"))
func _draw():
@ -15,10 +18,15 @@ func _on_start_pressed():
var name = player_settings.get_name_node().text
var color = player_settings.get_color_node().color
var bots = find_node("bots").is_pressed()
var bot_difficulty = find_node("bot_difficulty").get_value()
queue_free()
server.local_game(name,color,bots)
server.local_game(name,color,bots,bot_difficulty)
func _on_back_pressed():
queue_free()
get_tree().get_root().get_node("main_menu").show()
func _on_bots_toggled(button_pressed):
find_node("bot_difficulty").set_editable(button_pressed)

9
scripts/menus/main.gd → scripts/menus/main_menu.gd

@ -8,9 +8,11 @@ var SettingsMenu = preload("res://scenes/menus/SettingsMenu.tscn")
func _ready():
gamestate.connect("server_disconnected", self, "_server_disconnected")
func _draw():
find_node("multiplayer").grab_focus()
func _on_multiplayer_pressed():
var multiplayer_menu = MultiplayerMenu.instance()
get_tree().get_root().add_child(multiplayer_menu)
@ -40,4 +42,9 @@ func _server_disconnected():
func show_error_dialog(text:String):
var dialog = get_node("error_dialog")
dialog.set_text(text)
dialog.popup_centered()
dialog.popup_centered()
func _on_info_pressed():
var dialog = get_node("info_popup")
dialog.popup_centered()

18
scripts/menus/server_create.gd → scripts/menus/server_create_menu.gd

@ -2,12 +2,15 @@ extends Control
func _ready():
var player_name = local_storage.read_value("player_name", false)
var player_name = config.get_value("game","player_name", false)
var game_title = "New Game"
if player_name:
game_title += " by " + player_name
find_node("name").set_text(game_title)
find_node("bots").set_pressed(local_storage.read_value("bots", true))
find_node("bots").set_pressed(config.get_value("game","bots", true))
find_node("bot_difficulty").set_value(config.get_value("game","bot_difficulty", gamestate.DEFAULT_BOT_DIFFICULTY))
find_node("bot_difficulty").set_editable(find_node("bots").is_pressed())
find_node("bot_difficulty").set_tooltip(tr("BOT_DIFFICULTY"))
func _draw():
@ -21,14 +24,17 @@ func _on_create_pressed():
var bots = 0
if find_node("bots").is_pressed():
bots = 1
req.post_request('client/game/create', to_json({'name' : server_name, 'bots' : bots}))
var bot_difficulty = find_node("bot_difficulty").get_value()
req.post_request('client/game/create', to_json({'name' : server_name, 'bots' : bots, 'bot_difficulty' : bot_difficulty}))
func _on_game_created(result, response_code, headers, body):
if result == OK && response_code == HTTPClient.RESPONSE_OK:
var json = JSON.parse(body.get_string_from_utf8())
gamestate.game_name = json.result['name']
client.join_game(game_server.SERVER_ADDR, int(json.result['port']))
client.join_game(game_server.get_server_addr(), int(json.result['port']))
else:
get_tree().get_root().get_node("multiplayer_menu").show_error_dialog(tr("ERROR_GAME_CREATION"))
queue_free()
@ -42,3 +48,7 @@ func _on_name_text_changed(new_text):
func _on_back_pressed():
queue_free()
get_tree().get_root().get_node("multiplayer_menu").show()
func _on_bots_toggled(button_pressed):
find_node("bot_difficulty").set_editable(button_pressed)

6
scripts/menus/server.gd → scripts/menus/server_menu.gd

@ -77,7 +77,7 @@ func get_games(only_open:bool):
if only_open:
req.get_request('client/games?open')
else:
req.get_request('client/games')
req.get_request('client/games')
func _on_get_games(result, response_code, headers, body):
@ -94,7 +94,7 @@ func _on_get_games(result, response_code, headers, body):
name += "/4)"
if game.bots:
name += " [with Bots]"
games_list.add_item(name)
games_list.add_item(name)
if game.running:
games_list.set_item_icon(games_list.get_item_count()-1, games_list.get_node("running_icon").get_button_icon())
elif game.has('private') && game.private:
@ -116,7 +116,7 @@ func _on_create_pressed():
func _on_join_pressed():
client.join_game(game_server.SERVER_ADDR, int(selected_game['port']))
client.join_game(game_server.get_server_addr(), int(selected_game['port']))
func _connection_succeeded():

67
scripts/menus/settings.gd

@ -1,67 +0,0 @@
extends Control
onready var player_settings = find_node("settings_player")
onready var game_tab = find_node("game")
onready var controls_tab = find_node("controls")
onready var graphics_tab = find_node("graphics")
onready var system_tab = find_node("system")
var locale
func _ready():
get_node("menu/back").connect("pressed",self,"_on_back_pressed")
find_node("bots").set_pressed(local_storage.read_value("bots", true))
game_tab.set_name(tr("GAME"))
controls_tab.set_name(tr("CONTROLS"))
graphics_tab.set_name(tr("GRAPHICS"))
system_tab.set_name(tr("SYSTEM"))
func _on_back_pressed():
queue_free()
get_tree().get_root().get_node("main_menu").show()
func _on_locales_item_selected(index):
match index:
0:
locale = "en"
1:
locale = "de"
_:
locale = "en"
TranslationServer.set_locale(locale)
game_tab.set_name(tr("GAME"))
controls_tab.set_name(tr("CONTROLS"))
graphics_tab.set_name(tr("GRAPHICS"))
system_tab.set_name(tr("SYSTEM"))
func _init_locales():
var locales = find_node("locales")
locales.clear()
locales.add_item(tr("LOCALE_EN"))
locales.add_item(tr("LOCALE_DE"))
locale = local_storage.read_value("locale","en")
match locale:
"en":
locales.select(0)
_on_locales_item_selected(0)
"de":
locales.select(1)
_on_locales_item_selected(1)
func _on_locales_tree_exiting():
TranslationServer.set_locale(local_storage.read_value("locale","en"))
func _on_save_pressed():
var values = {}
values['player_name'] = player_settings.get_name_node().text
values['player_color'] = player_settings.get_color_node().color.to_html()
values['bots'] = find_node("bots").is_pressed()
values['locale'] = locale
local_storage.write_values(values)
_on_back_pressed()

89
scripts/menus/settings_controls.gd

@ -1,89 +0,0 @@
tool
extends Control
onready var grid = find_node("grid")
onready var key_dialog = get_node("key_dialog")
const INPUT_TYPE_KEY = 0
const INPUT_TYPE_JOYPAD = 1
var last_action:String
var last_event:InputEvent
var new_inputs = {}
func _ready():
init_mapping()
func init_mapping():
new_inputs = {}
for action in InputMap.get_actions():
if action.begins_with("controls_"):
var action_label = Label.new()
action_label.set_name(action + "_label")
action_label.set_text(action)
grid.add_child(action_label)
var key_action_button = Button.new()
key_action_button.set_h_size_flags(SIZE_SHRINK_CENTER)
key_action_button.set_flat(true)
key_action_button.set_meta("action",action)
key_action_button.set_button_icon(get_node("icons/key").get_button_icon())
var joypad_action_button = Button.new()
joypad_action_button.set_h_size_flags(SIZE_SHRINK_CENTER)
joypad_action_button.set_flat(true)
joypad_action_button.set_meta("action",action)
for mapping in InputMap.get_action_list(action):
if mapping is InputEventKey:
key_action_button.set_text(mapping.as_text())
key_action_button.set_tooltip(mapping.as_text())
elif mapping is InputEventJoypadButton:
joypad_action_button.set_tooltip(str(mapping.button_index))
if has_node("icons/joypad/" + str(mapping.button_index)):
joypad_action_button.set_button_icon(get_node("icons/joypad/" + str(mapping.button_index)).get_button_icon())
else:
joypad_action_button.set_button_icon(get_node("icons/joypad/other").get_button_icon())
joypad_action_button.set_text(str(mapping.button_index))
grid.add_child(key_action_button)
key_action_button.connect("pressed",self,"_on_button_pressed",[action, INPUT_TYPE_KEY])
grid.add_child(joypad_action_button)
joypad_action_button.connect("pressed",self,"_on_button_pressed",[action, INPUT_TYPE_JOYPAD])
func _unhandled_input(event):
if key_dialog.is_visible_in_tree():
if key_dialog.get_meta("type") == INPUT_TYPE_KEY && event is InputEventKey:
last_event = event
key_dialog.set_text(tr(last_event.as_text()))
key_dialog.get_ok().set_disabled(false)
elif key_dialog.get_meta("type") == INPUT_TYPE_JOYPAD && event is InputEventJoypadButton:
last_event = event
key_dialog.set_text(last_event.as_text())
key_dialog.get_ok().set_disabled(false)
func _on_button_pressed(action, type):
last_action = action
last_event = null
key_dialog.set_text(tr("PRESS_KEY"))
key_dialog.set_meta("type", type)
key_dialog.connect("confirmed",self,"_on_dialog_confirmed")
key_dialog.get_ok().set_disabled(true)
key_dialog.popup_centered()
func _on_dialog_confirmed(type):
if not new_inputs.has(last_action):
new_inputs[last_action] = {}
match key_dialog.get_meta("type"):
INPUT_TYPE_KEY:
if last_event is InputEventKey:
new_inputs[last_action]["key"] = OS.get_scancode_string(last_event.scancode)
INPUT_TYPE_JOYPAD:
if last_event is InputEventJoypadButton:
new_inputs[last_action]["joypad"] = last_event.button_index

128
scripts/menus/settings_controls_menu.gd

@ -0,0 +1,128 @@
extends Control
onready var grid = find_node("grid")
onready var key_dialog = get_node("key_dialog")
const INPUT_TYPE_KEY = 0
const INPUT_TYPE_JOYPAD = 1
var last_action:String
var last_event:InputEvent
var new_inputs = {}
func _ready():
init_mapping()
func apply():
config.set_value("controls","mapping",new_inputs)
func init_mapping():
new_inputs = {}
for action in config.CONTROL_ACTIONS:
var action_label = Label.new()
action_label.set_name(action + "_label")
action_label.set_text(action)
grid.add_child(action_label)
var key_action_button = Button.new()
key_action_button.set_h_size_flags(SIZE_SHRINK_CENTER)
key_action_button.set_flat(true)
key_action_button.set_meta("action",action)
key_action_button.set_button_icon(get_node("icons/key").get_button_icon())
var joypad_action_button = Button.new()
joypad_action_button.set_h_size_flags(SIZE_SHRINK_CENTER)
joypad_action_button.set_flat(true)
joypad_action_button.set_meta("action",action)
for event in InputMap.get_action_list(action):
if event is InputEventKey:
key_action_button.set_text(event.as_text())
key_action_button.set_tooltip(event.as_text())
elif event is InputEventJoypadButton:
joypad_action_button.set_tooltip(str(event.button_index))
if has_node("icons/joypad/" + str(event.button_index)):
joypad_action_button.set_button_icon(get_node("icons/joypad/" + str(event.button_index)).get_button_icon())
else:
joypad_action_button.set_button_icon(get_node("icons/joypad/other").get_button_icon())
joypad_action_button.set_text(str(event.button_index))
grid.add_child(key_action_button)
key_action_button.connect("pressed",self,"_on_button_pressed",[key_action_button, INPUT_TYPE_KEY])
grid.add_child(joypad_action_button)
joypad_action_button.connect("pressed",self,"_on_button_pressed",[joypad_action_button, INPUT_TYPE_JOYPAD])
func _unhandled_input(event):
if key_dialog.is_visible_in_tree():
var action_button = key_dialog.find_node("action_button")
var check_usage = false
if key_dialog.get_meta("type") == INPUT_TYPE_KEY && event is InputEventKey:
check_usage = true
last_event = event
action_button.set_button_icon(get_node("icons/key").get_button_icon())
action_button.set_text(event.as_text())
action_button.set_tooltip(event.as_text())
elif key_dialog.get_meta("type") == INPUT_TYPE_JOYPAD && event is InputEventJoypadButton:
check_usage = true
last_event = event
action_button.set_tooltip(str(event.button_index))
if has_node("icons/joypad/" + str(event.button_index)):
action_button.set_text("")
action_button.set_button_icon(get_node("icons/joypad/" + str(event.button_index)).get_button_icon())
else:
action_button.set_button_icon(get_node("icons/joypad/other").get_button_icon())
action_button.set_text(str(event.button_index))
if check_usage:
var has_event = ""
for action in config.CONTROL_ACTIONS:
if InputMap.event_is_action(event, action):
has_event = action
if not has_event == "" && not has_event == last_action:
key_dialog.set_text(tr("KEY_ALREADY_TAKEN") + '\n\'' + tr(has_event) + '\'')
key_dialog.get_ok().set_disabled(true)
else:
key_dialog.set_text(tr("PRESS_KEY"))
key_dialog.get_ok().set_disabled(false)
func _on_button_pressed(button, type):
last_action = button.get_meta("action")
last_event = null
var action_button = key_dialog.find_node("action_button")
action_button.set_text("")
action_button.set_button_icon(null)
key_dialog.set_text(tr("PRESS_KEY"))
key_dialog.set_meta("type", type)
key_dialog.connect("confirmed",self,"_on_dialog_confirmed",[button])
key_dialog.get_ok().set_disabled(true)
key_dialog.get_label().set_align(HALIGN_CENTER)
key_dialog.popup_centered()
func _on_dialog_confirmed(button):
if not new_inputs.has(last_action):
new_inputs[last_action] = {}
match key_dialog.get_meta("type"):
INPUT_TYPE_KEY:
if last_event is InputEventKey:
new_inputs[last_action]["key"] = OS.get_scancode_string(last_event.scancode)
button.set_text(last_event.as_text())
button.set_tooltip(last_event.as_text())
INPUT_TYPE_JOYPAD:
if last_event is InputEventJoypadButton:
new_inputs[last_action]["joypad"] = last_event.button_index
button.set_tooltip(str(last_event.button_index))
if has_node("icons/joypad/" + str(last_event.button_index)):
button.set_button_icon(get_node("icons/joypad/" + str(last_event.button_index)).get_button_icon())
else:
button.set_button_icon(get_node("icons/joypad/other").get_button_icon())
button.set_text(str(last_event.button_index))

17
scripts/menus/settings_game_menu.gd

@ -0,0 +1,17 @@
extends Tabs
onready var player_settings = find_node("settings_player")
func _ready():
# game
find_node("bots").set_pressed(config.get_value("game","bots", true))
find_node("bot_difficulty").set_value(config.get_value("game","bot_difficulty", gamestate.DEFAULT_BOT_DIFFICULTY))
find_node("bot_difficulty").set_tooltip(tr("BOT_DIFFICULTY"))
func apply():
config.set_value("game","player_name",player_settings.get_name_node().get_text())
config.set_value("game","player_color",player_settings.get_color_node().color)
config.set_value("game","bots",find_node("bots").is_pressed())
config.set_value("game","bot_difficulty",find_node("bot_difficulty").get_value())

24
scripts/menus/settings_graphics_menu.gd

@ -0,0 +1,24 @@
extends Tabs
func _ready():
find_node("fullscreen").set_pressed(config.get_value("graphics","fullscreen", true))
find_node("light").set_pressed(config.get_value("graphics","light", false))
find_node("shadows").set_pressed(config.get_value("graphics","shadows", false))
find_node("shadows").set_disabled(not find_node("light").is_pressed())
for resolution in config.RESOLUTIONS:
find_node("resolution").add_item(str(resolution.x) + " * " + str(resolution.y))
find_node("resolution").select(config.RESOLUTIONS.find(config.get_value("graphics","resolution", config.RESOLUTIONS[0])))
func apply():
config.set_value("graphics","resolution",config.RESOLUTIONS[find_node("resolution").get_selected()])
config.set_value("graphics","fullscreen",find_node("fullscreen").is_pressed())
config.set_value("graphics","light",find_node("light").is_pressed())
config.set_value("graphics","shadows",find_node("shadows").is_pressed())
func _on_light_toggled(button_pressed):
find_node("shadows").set_disabled(not button_pressed)

46
scripts/menus/settings_menu.gd

@ -0,0 +1,46 @@
extends Control
onready var game_tab = find_node("game")
onready var controls_tab = find_node("controls")
onready var graphics_tab = find_node("graphics")
onready var system_tab = find_node("system")
func _ready():
get_node("menu/back").connect("pressed",self,"_on_back_pressed")
system_tab.connect("locale_changed", self, "on_locale_changed")
func _draw():
game_tab.grab_focus()
func _on_back_pressed():
queue_free()
if get_parent().has_node("ingame_menu"):
get_parent().get_node("ingame_menu").show()
get_tree().get_root().get_node("main_menu").hide()
elif get_tree().get_root().has_node("main_menu"):
get_tree().get_root().get_node("main_menu").show()
func on_locale_changed():
game_tab.set_name(tr("GAME"))
controls_tab.set_name(tr("CONTROLS"))
graphics_tab.set_name(tr("GRAPHICS"))
system_tab.set_name(tr("SYSTEM"))
func _on_save_pressed():
_on_apply_pressed()
_on_back_pressed()
func _on_apply_pressed():
game_tab.apply()
graphics_tab.apply()
controls_tab.apply()
system_tab.apply()
config.save()
config_apply.apply_settings()

14
scripts/menus/settings_player.gd

@ -1,14 +0,0 @@
extends Control
func _ready():
get_name_node().set_text(local_storage.read_value("player_name", "Player"))
get_color_node().set_pick_color(Color(local_storage.read_value("player_color", "#000000")))
func get_name_node():
return find_node("name")
func get_color_node():
return find_node("color")

14
scripts/menus/settings_player_menu.gd

@ -0,0 +1,14 @@
extends Control
func _ready():
get_name_node().set_text(config.get_value("game","player_name", "Player"))
get_color_node().set_pick_color(config.get_value("game","player_color", Color.black))
func get_name_node():
return find_node("name")
func get_color_node():
return find_node("color")

55
scripts/menus/settings_system_menu.gd

@ -0,0 +1,55 @@
extends Tabs
var locale
signal locale_changed()
func _ready():
find_node("server_addr").set_text(game_server.get_server_addr())
find_node("api_addr").set_text(game_server.get_api_addr())
_init_locales()
func apply():
config.set_value("system","locale",locale)
var server_addr = find_node("server_addr").get_text()
if server_addr.empty():
server_addr = game_server.SERVER_ADDR
config.set_value("system","server_addr",server_addr)
var api_addr = find_node("api_addr").get_text()
if api_addr.empty():
api_addr = game_server.API_ADDR
config.set_value("system","api_addr",api_addr)
func _on_locales_item_selected(index):
match index:
0:
locale = "en"
1:
locale = "de"
_:
locale = "en"
TranslationServer.set_locale(locale)
emit_signal("locale_changed")
func _init_locales():
var locales = find_node("locales")
locales.clear()
locales.add_item(tr("LOCALE_EN"))
locales.add_item(tr("LOCALE_DE"))
locale = config.get_value("system","locale","en")
match locale:
"en":
locales.select(0)
_on_locales_item_selected(0)
"de":
locales.select(1)
_on_locales_item_selected(1)
func _on_system_settings_menu_tree_exiting():
config_apply.apply_locale()

33
scripts/networking/game_server.gd

@ -7,8 +7,39 @@ const API_ADDR = "https://" + SERVER_ADDR + "/"
const HEADERS = ["Content-Type: application/json"]
const SSL = false
var server_addr:String = SERVER_ADDR
var api_addr:String = API_ADDR
var headers:Array = HEADERS
var ssl:bool = SSL
func http():
var game_server_requests = GameServerRequests.new()
add_child(game_server_requests)
return game_server_requests
return game_server_requests
func get_server_addr():
return server_addr
func set_server_addr(new_server_addr:String):
server_addr = new_server_addr
func get_api_addr():
return api_addr
func set_api_addr(new_api_addr:String):
if not new_api_addr.ends_with("/"):
new_api_addr += "/"
api_addr = new_api_addr
func get_headers():
return headers
func get_ssl():
return ssl

8
scripts/networking/game_server_requests.gd

@ -16,19 +16,19 @@ func connect_http(node,function):
func get_request(path:String):
http.request(game_server.API_ADDR + path, game_server.HEADERS, game_server.SSL, HTTPClient.METHOD_GET)
http.request(game_server.get_api_addr() + path, game_server.get_headers(), game_server.get_ssl(), HTTPClient.METHOD_GET)
func post_request(path:String, data:String = ""):
http.request(game_server.API_ADDR + path, game_server.HEADERS, game_server.SSL, HTTPClient.METHOD_POST, data)
http.request(game_server.get_api_addr() + path, game_server.get_headers(), game_server.get_ssl(), HTTPClient.METHOD_POST, data)
func put_request(path:String, data:String = ""):
http.request(game_server.API_ADDR + path, game_server.HEADERS, game_server.SSL, HTTPClient.METHOD_PUT, data)
http.request(game_server.get_api_addr() + path, game_server.get_headers(), game_server.get_ssl(), HTTPClient.METHOD_PUT, data)
func delete_request(path:String, data:String = ""):
http.request(game_server.API_ADDR + path, game_server.HEADERS, game_server.SSL, HTTPClient.METHOD_DELETE, data)
http.request(game_server.get_api_addr() + path, game_server.get_headers(), game_server.get_ssl(), HTTPClient.METHOD_DELETE, data)
func _self_destroy(result, response_code, headers, body):

56
scripts/networking/server.gd

@ -3,6 +3,7 @@ extends Node
const MAX_PEERS = 4
const LOBBY_READY_WAIT_TIME = 3
const EMPTY_WAIT_TIME = 30
const EMPTY_CLOSING_TIME = 60
var port:int = -1
var dedicated_server:bool = false
@ -25,31 +26,44 @@ func _ready():
server_secret=argument.split("=")[1]
if argument.split("=")[0] == "--bots":
gamestate.set_bots(bool(int(argument.split("=")[1])))
if argument.split("=")[0] == "--bot-difficulty":
gamestate.set_bot_difficulty(float(argument.split("=")[1]))
if argument.split("=")[0] == "--server-addr":
game_server.set_server_addr(str(argument.split("=")[1]))
if argument.split("=")[0] == "--api-addr":
game_server.set_api_addr(str(argument.split("=")[1]))
if dedicated_server:
var err = host_game(port)
if err == OK:
print(server_id + "New game hosted: port=" + str(port) + " secret=" + str(server_secret) + " bots=" + str(gamestate.bots))
print(server_id + "New game hosted: port=" + str(port) + " secret=" + str(server_secret) + " bots=" + str(gamestate.bots) + " server-addr=" + game_server.get_server_addr() + " api-addr=" + game_server.get_api_addr())
print(server_id + "Waiting for connection, closing server in " + str(EMPTY_CLOSING_TIME) + " seconds")
timer.set_wait_time(EMPTY_CLOSING_TIME)
timer.connect("timeout",self,"quit_server",[true])
timer.start()
else:
print(server_id + "Could not create Server! (port=" + str(port) + " secret=" + str(server_secret) + ")")
push_error(server_id + "Could not create Server! (port=" + str(port) + " secret=" + str(server_secret) + " server-addr=" + game_server.get_server_addr() + " api-addr=" + game_server.get_api_addr() + ")")
quit_server()
func host_game(port:int, set_bots:bool = false):
func host_game(port:int, set_bots:bool = false, bot_difficulty:float = gamestate.DEFAULT_BOT_DIFFICULTY):
var host = NetworkedMultiplayerENet.new()
var err = host.create_server(port, MAX_PEERS)
get_tree().set_network_peer(host)
get_tree().connect("network_peer_connected", self, "_client_connected")
get_tree().connect("network_peer_disconnected", self,"_client_disconnected")
gamestate.connect("players_changed",self,"_players_changed")
gamestate.connect("game_ready",self,"_game_ready")
gamestate.connect("game_ended",self,"_game_ended")
if set_bots:
gamestate.bots = true
if set_bots && bot_difficulty != gamestate.DEFAULT_BOT_DIFFICULTY:
gamestate.bot_difficulty = bot_difficulty
if timer == null:
timer = Timer.new()
timer.set_name("timer")
@ -57,18 +71,19 @@ func host_game(port:int, set_bots:bool = false):
timer.set_one_shot(true)
timer.set_autostart(false)
add_child(timer)
if err != OK:
if err != OK:
emit_signal("server_error", "HOST", err)
return err
func local_game(name:String, color:Color, bots:bool):
func local_game(name:String, color:Color, bots:bool, bot_difficulty:float):
var localhost = NetworkedMultiplayerENet.new()
localhost.create_server(0, 0)
get_tree().set_network_peer(localhost)
gamestate.bots = bots
gamestate.bot_difficulty = bot_difficulty
gamestate.set_player(get_tree().get_network_unique_id(), name, color)
gamestate.prepare_game()
gamestate.post_start_game()
@ -76,13 +91,18 @@ func local_game(name:String, color:Color, bots:bool):
func update_server_data():
var req = game_server.http()
req.put_request("game",to_json({'secret' : server_secret, 'player_count' : gamestate.players.size(), 'running' : gamestate.game_running}))
var player_count = 0
if gamestate.players != null:
player_count = gamestate.players.size()
req.put_request("game",to_json({'secret' : server_secret, 'player_count' : player_count, 'running' : gamestate.game_running}))
func _client_connected(id):
if get_tree().is_network_server():
if dedicated_server:
print(server_id + "peer connected: " + str(id))
gamestate.rpc_id(id, "set_bots" ,gamestate.bots)
gamestate.rpc_id(id, "bot_difficulty" ,gamestate.bot_difficulty)
if not timer.is_stopped():
timer.disconnect("timeout",self,"quit_server")
timer.stop()
@ -95,11 +115,11 @@ func _client_disconnected(id):
if gamestate.game_running:
emit_signal("server_error", "DISCONNECTED", [id])
gamestate.rpc("remove_player" ,id)
else:
else:
gamestate.rpc("remove_player" ,id)
func _players_changed(players):
func _players_changed(players):
if get_tree().is_network_server():
if dedicated_server:
update_server_data()
@ -148,10 +168,10 @@ func _game_ready(all_ready):
func _game_ended():
get_tree().disconnect("network_peer_connected", self, "_client_connected")
get_tree().disconnect("network_peer_disconnected", self,"_client_disconnected")
gamestate.disconnect("players_changed",self,"_players_changed")
gamestate.disconnect("game_ready",self,"_game_ready")
gamestate.disconnect("game_ended",self,"_game_ended")
get_tree().set_refuse_new_network_connections(false)
get_tree().set_network_peer(null)

50
scripts/player/base_inventory.gd

@ -3,45 +3,45 @@ extends Spatial
class_name BaseInventory
var road_straights = [
roads_factory.BUMP,
roads_factory.BUMP_SMALL,
roads_factory.STRAIGHT,
roads_factory.STRAIGHT_SMALL,
]
var roads_left = [
roads_factory.CURVE_LEFT,
roads_factory.CURVE_LARGE_LEFT,
roads_factory.CURVE_SMALL_LEFT,
roads_factory.SKEW_LEFT,
roads_factory.CURVED_LEFT,
roads_factory.BUMP,
roads_factory.BUMP_SMALL,
roads_factory.STRAIGHT,
roads_factory.STRAIGHT_SMALL,
]
var roads_right = [
roads_factory.CURVE_RIGHT,
roads_factory.CURVE_LARGE_RIGHT,
roads_factory.CURVE_SMALL_RIGHT,
roads_factory.SKEW_RIGHT,
roads_factory.CURVE_RIGHT,
roads_factory.CURVE_LARGE_RIGHT,
roads_factory.CURVE_SMALL_RIGHT,
roads_factory.SKEW_RIGHT,
roads_factory.CURVED_RIGHT,
]
var roads_left = [
roads_factory.CURVE_LEFT,
roads_factory.CURVE_LARGE_LEFT,
roads_factory.CURVE_SMALL_LEFT,
roads_factory.SKEW_LEFT,
roads_factory.CURVED_LEFT,
]
var roads_up = [
roads_factory.RAMP_UP,
roads_factory.RAMP_CURVED_UP,
roads_factory.RAMP_SMALL_UP,
]
roads_factory.RAMP_UP,
roads_factory.RAMP_CURVED_UP,
roads_factory.RAMP_SMALL_UP,
]
var roads_down = [
roads_factory.RAMP_DOWN,
roads_factory.RAMP_CURVED_DOWN,
roads_factory.RAMP_SMALL_DOWN,
]
]
var roads_special = [
roads_factory.LOOP,
]
var roads = [ road_straights, roads_left, roads_right, roads_up, roads_down, roads_special ]
var roads = [ road_straights, roads_right, roads_left, roads_up, roads_down, roads_special ]
var player:Player
var route:Route
@ -65,10 +65,10 @@ func set_item():
if item:
item.free()
item = roads_factory.get_road_instance(roads[type][index])
if player != null:
item.set_color(player.get_player_color())
item.rotate_y(PI/2)
emit_signal("item_changed", roads[type][index], player)

77
scripts/player/bot_controls.gd

@ -1,44 +1,63 @@
extends Spatial
class_name BotPlayer
var player:Player
const MAX_ROAD_INDEX = 1
var error_rate:float = 0.00
var underspeed_rate:float = 0.00
const MAX_OFFSET = 8.0
const OFFSET_STEPS = 0.1
const PRE_BREAK_DISTANCE = 3.0
var break_constrain = 0.0
var break_distance = 0.0
var thrust_distance = 0.0
func _ready():
randomize()
export var difficulty:float = 0.0
var rate = 0.0
func _physics_process(delta):
func _process(delta):
if is_network_master() && player != null:
if player.is_out:
if player.is_out():
if player.is_resetable:
player.reset()
else:
if player.get_road() != null:
var rate = randf()
var road = player.get_road()
var road_index = 0
var speed_constrain = 0.0
while road != null && road_index < MAX_ROAD_INDEX:
for index in range(road.speed_constrains.size()):
var constrain = road.speed_constrains[index]
if constrain.z > 0:
speed_constrain = max(speed_constrain, constrain.z)
elif constrain.z < 0:
speed_constrain = min(speed_constrain, constrain.z)
road = player.route.get_road(road.get_index() + 1)
road_index += 1
var speed = player.current_speed
if speed_constrain < 0:
player.thrust = 1
elif speed_constrain > 0 && speed > speed_constrain:
var offset = 0
var distance = player.follow.get_offset() - OFFSET_STEPS
var tmp_constrain = 0.0
break_constrain = 0.0
break_distance = 0.0
thrust_distance = 0.0
while offset <= MAX_OFFSET && road != null:
var constrain_index = road.get_constrain_index(distance)
var road_length = road.get_lane_curve(player.lane).get_baked_length()
if constrain_index >= 0:
tmp_constrain = road.speed_constrains[constrain_index].z
if tmp_constrain > 0 && (break_constrain == 0.0 || tmp_constrain < break_constrain):
break_constrain = tmp_constrain
if break_distance == 0:
break_distance = offset
if tmp_constrain < 0 && thrust_distance == 0:
thrust_distance = offset
distance += OFFSET_STEPS
offset += OFFSET_STEPS
if distance >= road_length && gamestate.game != null:
distance = 0
road = gamestate.game.route.get_road(road.get_index()+1)
if break_constrain > 0 && speed > break_constrain - 0.005 && break_distance < thrust_distance + PRE_BREAK_DISTANCE && rate < difficulty:
player.thrust = -1
elif rate > underspeed_rate:
player.thrust = 1
elif speed - 0.01 < break_constrain:
player.thrust = 1
elif break_constrain == 0.0 && rate < difficulty || speed < 0.02:
player.thrust = 1
else:
player.thrust = 0
@ -48,9 +67,9 @@ func set_player(path:String):
get_node("inventory").set_player(player)
func set_error_rate(new_error_rate:float):
error_rate = new_error_rate
func set_difficulty(new_difficulty:float):
difficulty = new_difficulty
func set_underspeed_rate(new_underspeed_rate:float):
underspeed_rate = new_underspeed_rate
func _on_rate_timer_timeout():
rate = util.randf()

3
scripts/player/bot_inventory.gd

@ -14,7 +14,8 @@ func _on_raceCar_road_entered(road):
if route.get_last_road().get_index() <= (road.get_index() +2):
type = rand.randi_range(0,roads.size() -2) # TODO: remove special, loop need fixes!
index = rand.randi_range(0, roads[type].size() -1)
route.rpc("add_road", roads[type][index], player.get_index())
route.set_road(roads[type][index], -1)
route.rpc("set_road", roads[type][index], -1)
func set_player(new_player:Player):

41
scripts/player/human_controls.gd

@ -2,38 +2,41 @@ extends Spatial
var player:Player
onready var camera:InterpolatedCamera = get_node("camera")
onready var ingame_menu:Spatial = find_node("ingame_menu")
func _physics_process(delta):
func _process(delta):
if is_network_master() && player != null:
if player.is_out:
if Input.is_action_just_pressed("controls_menu"):
ingame_menu.set_visible(not ingame_menu.is_visible_in_tree())
if player.is_out():
camera.set_speed(0.1)
if player.timer.get_time_left() > 0:
get_node("hud/reset").set_text(str(int(player.timer.get_time_left()) + 1))
else:
get_node("hud/reset").set_text(tr("RESET"))
get_node("hud/reset").set_text(tr("RESET"))
if Input.is_action_pressed("controls_reset"):
if player.reset():
camera.set_speed(10)
get_node("hud/reset").set_text("")
else:
player.rpc("reset")
elif not ingame_menu.is_visible_in_tree():
camera.set_speed(10)
get_node("hud/reset").set_text("")
if Input.is_action_pressed("controls_thrust"):
player.thrust = 1
player.rpc_unreliable("set_thrust",1)
elif Input.is_action_pressed("controls_break"):
player.thrust = -1
player.rpc_unreliable("set_thrust",-1)
else:
player.thrust = 0
get_node("hud/speed").set_text(str(player.current_speed))
player.rpc_unreliable("set_thrust",0)
get_node("hud/speed_slider").set_value(player.current_speed * 1000)
if Input.is_action_pressed("debug_camera_1"):
set_debug_camera(0)
set_debug_camera(0)
elif Input.is_action_pressed("debug_camera_2"):
set_debug_camera(1)
set_debug_camera(1)
elif Input.is_action_pressed("debug_camera_3"):
set_debug_camera(2)
set_debug_camera(2)
elif Input.is_action_pressed("debug_camera_4"):
set_debug_camera(3)
set_debug_camera(3)
func set_player(path:String):
@ -45,5 +48,5 @@ func set_player(path:String):
func set_debug_camera(idx):
if idx < gamestate.game.players.get_child_count():
camera.set_target_path(gamestate.game.players.get_child(idx).find_node("CameraTarget").get_path())
if idx < gamestate.game.get_node("players").get_child_count():
camera.set_target_path(gamestate.game.get_node("players").get_child(idx).find_node("CameraTarget").get_path())

14
scripts/player/human_inventory.gd

@ -7,23 +7,23 @@ var preview:Spatial
func _ready():
view = get_node("view")
preview = get_node("preview")
var hud_track = get_node("../hud/inventory/track")
var hud_track = get_node("../hud/inventory/track_container/track")
hud_track.get_texture().set_viewport_path_in_scene(str(get_path()) + "/viewport")
connect("item_changed",self,"_on_item_changed")
connect("item_changed",preview,"_on_inventory_item_changed")
func _physics_process(delta):
func _process(delta):
if is_network_master():
if player != null:
if not player.is_out && player.is_in_group("first"):
if not player.is_out() && player.is_in_group("first"):
get_node("../hud/inventory").show()
if item == null:
set_item()
if preview.item:
preview.item.show()
if Input.is_action_just_pressed("controls_add_road"):
route.rpc("add_road", roads[type][index], player.get_index())
route.rpc("add_road", roads[type][index])
if Input.is_action_just_pressed("controls_prev_road_type"):
type -= 1
if type < 0:
@ -56,7 +56,7 @@ func _on_item_changed(road_identifier, player):
if is_network_master():
if view.get_child_count() > 0:
view.remove_child(view.get_child(0))
view.add_child(item)
get_node("../hud/inventory/type").set_text(tr(road_identifier))
get_node("../hud/inventory/track_container/type").set_text(tr(road_identifier))

4
scripts/player/inventory_preview.gd

@ -6,12 +6,12 @@ var player:Player
var item:Road
func _ready():
func _ready():
gamestate.game.route.connect("road_added",self,"_on_route_road_added")
func _on_route_road_added(road):
if is_network_master() && item:
if is_network_master() && item && road:
var transform = road.get_global_transform();
var curve = road.get_curve()
transform = transform.translated(curve.get_point_position(curve.get_point_count() -1))

99
scripts/player/player.gd

@ -53,39 +53,38 @@ func _physics_process(delta):
if is_network_master():
if not is_out:
var max_speed = MAX_SPEED
if get_road() != null:
var road = get_road()
if is_in_group("first"):
max_speed *= road.get_first_speed_factor()
if road.get_creator() == get_index():
elif road.get_creator() == get_index():
max_speed *= road.get_creator_speed_factor()
else:
max_speed *= road.get_chasers_speed_factor()
if thrust == 1:
current_speed += speed_factor
elif thrust == -1:
current_speed -= speed_factor * brake_factor
else:
current_speed -= speed_factor * friction_brake_factor
if current_speed >= max_speed:
current_speed = max_speed
elif current_speed < 0:
current_speed = 0
follow.set_offset(follow.get_offset() + current_speed)
if follow.get_offset() < 0:
follow.set_offset(0)
if has_next && (path.curve.get_point_count() == 0 || follow.get_unit_offset() >= 1.0):
has_next = false
if path.curve.get_point_count() > 0:
path.curve.clear_points()
path.curve.set_bake_interval(0.05)
for i in range(buffered_curve.get_point_count()):
var _pos = buffered_curve.get_point_position(i)
@ -105,17 +104,16 @@ func _physics_process(delta):
if get_road() != null:
var road = get_road()
var penalty_index = road.penalty_index(follow.get_offset(), current_speed)
if penalty_index >= 0:
torque_penalty = road.get_torque_penalty(penalty_index)
force_penalty = road.get_force_penalty(penalty_index)
path_penalty = road.get_path_penalty(penalty_index)
is_out = true
is_resetable = false
timer.start()
rpc("set_out")
check_position()
else:
var road = get_road()
race_car.get_node("ray").set_enabled(false)
if force_penalty.length() != 0:
race_car.move_and_slide(force_penalty * current_speed + Vector3(0,-0.5,0))
@ -136,21 +134,21 @@ func get_road():
func _on_raceCar_road_entered(road):
var prev_road = route.get_road(road.get_index()-1)
if prev_road != null:
prev_road.body.set_collision_layer_bit(get_index(),0)
buffered_curve = road.get_lane_curve(lane)
buffered_rotation = last_rotation
if path.curve.get_point_count() > 0:
buffered_translate = Util.curve_get_last_point(path.curve)
buffered_translate = util.curve_get_last_point(path.curve)
if road.get_end_rotation().length() != 0:
last_rotation += road.get_end_rotation()
has_next = true
@ -173,11 +171,27 @@ func set_player_color(new_color):
race_car.get_node("body").set_surface_material(1,material)
func is_out():
return is_out
remotesync func set_out():
is_out = true
is_resetable = false
timer.start()
remotesync func set_in():
is_out = false
is_resetable = false
remotesync func set_first(is_first:bool):
if is_first:
add_to_group("first")
else:
remove_from_group("first")
if get_tree().get_rpc_sender_id() == 0 || get_tree().get_rpc_sender_id() == get_network_master():
if is_first:
add_to_group("first")
else:
remove_from_group("first")
master func check_position():
@ -185,40 +199,43 @@ master func check_position():
rset("slave_position", position)
master func set_thrust(new_thrust:int):
var sender_id = get_tree().get_rpc_sender_id()
if is_network_master() || gamestate.game.get_player_by_network_id(sender_id) == self && [-1,0,1].has(new_thrust):
thrust = new_thrust
master func reset():
if is_resetable:
var sender_id = get_tree().get_rpc_sender_id()
if (is_network_master() || gamestate.game.get_player_by_network_id(sender_id) == self) && is_resetable:
has_next = false
current_speed = 0
var road = race_car.road
road.body.set_collision_layer_bit(get_index(),1)
while road.reset_index != 0:
road = route.get_road(road.get_index() - road.reset_index)
var reset_index = road.reset_index
for i in range(reset_index):
road = route.get_road(road.get_index() - 1)
road.body.set_collision_layer_bit(get_index(),1)
path.curve.clear_points()
force_penalty = Vector3(0,0,0)
torque_penalty = Vector3(0,0,0)
buffered_translate = road.get_translation()
last_rotation = road.get_rotation()
race_car.road_index = road.get_index()
race_car.road = null
race_car.collider = null
race_car.transform = Transform()
race_car.get_node("ray").set_enabled(true)
follow.set_transform(road.get_transform())
is_out = false
is_resetable = false
return true
else:
return false
rpc("set_in")
func set_start(new_lane:int):

25
scripts/road/road.gd

@ -85,12 +85,20 @@ func get_next_lane(lane):
return lane
func penalty_index(distance:float, speed:float):
func get_constrain_index(distance:float):
for index in range(speed_constrains.size()):
var constrain = speed_constrains[index]
if constrain.x <= distance && constrain.y >= distance:
if constrain.z < 0 && speed < constrain.z * -1 || constrain.z > 0 && speed > constrain.z:
return index
return index
return -1
func penalty_index(distance:float, speed:float):
var constrain_index = get_constrain_index(distance)
if constrain_index >= 0:
var constrain = speed_constrains[constrain_index]
if constrain.z < 0 && speed < constrain.z * -1 || constrain.z > 0 && speed > constrain.z:
return constrain_index
return -1
@ -98,10 +106,7 @@ func get_torque_penalty(index:int):
if index >= 0:
if torque_penalties.size() < (index + 1):
return get_torque_penalty(index - 1)
if get_rotation().length() != 0:
return torque_penalties[index].rotated(get_rotation().normalized(), get_rotation().length())
else:
return torque_penalties[index]
return torque_penalties[index]
return Vector3(0,0,0)
@ -113,7 +118,7 @@ func get_force_penalty(index:int):
return force_penalties[index].rotated(get_rotation().normalized(), get_rotation().length())
else:
return force_penalties[index]
return Vector3(0,0,0)
@ -121,9 +126,9 @@ func get_path_penalty(index:int):
if index >= 0:
if path_penalties.size() < (index + 1):
return get_path_penalty(index - 1)
return path_penalties[index]
return 0.0

53
scripts/screen_capture.gd

@ -0,0 +1,53 @@
extends Node
export(float) var frames_per_second = 5.0
var is_active:bool = false
var is_saving:bool = false
var _frametick = 1.0/frames_per_second
var _thread:Thread
var images = []
func _ready():
_thread = Thread.new()
func _process(delta):
if Input.is_action_just_pressed("controls_capture") && not is_saving:
is_active = not is_active
find_node("recording").set_visible(is_active)
if not is_active:
is_saving = true
find_node("saving").set_visible(true)
_thread.start(self, "save_images")
if is_active:
_frametick += delta
if (_frametick > 1.0/frames_per_second):
get_viewport().set_clear_mode(Viewport.CLEAR_MODE_ONLY_NEXT_FRAME)
var img = get_viewport().get_texture().get_data()
img.flip_y()
images.append(img)
func save_images(userdata):
var dir = Directory.new()
var timestamp = OS.get_unix_time()
if dir.open("user://capture/") != OK:
dir.open("user://")
dir.make_dir("capture")
dir.open("user://capture/")
dir.make_dir(str(timestamp))
for img in images:
img.save_png("user://capture/" + str(timestamp) + "/" + str(img) + ".png")
images = []
is_saving = false
find_node("saving").set_visible(false)
if(_thread.is_active()):
_thread.wait_to_finish()

36
scripts/util.gd

@ -0,0 +1,36 @@
extends Node
var random_number_generator:RandomNumberGenerator = RandomNumberGenerator.new()
func _ready():
random_number_generator.randomize()
func randf():
return random_number_generator.randf()
func randf_range (from:float, to:float ):
return random_number_generator.randf_range(from,to)
func randfn (mean:float=0.0, deviation:float=1.0 ):
return random_number_generator.randfn(mean, deviation)
func randi():
return random_number_generator.randi()
func randi_range ( from:int, to:int ):
return random_number_generator.randi_range( from, to)
func clear_node(node:Node):
for idx in range(node.get_child_count()):
node.remove_child(node.get_child(0))
func curve_get_last_point(curve:Curve3D):
return curve.get_point_position(curve.get_point_count() - 1)
Loading…
Cancel
Save