diff options
Diffstat (limited to 'client')
-rw-r--r-- | client/game.gd | 60 | ||||
-rw-r--r-- | client/map/tiles/floor.gd | 5 | ||||
-rw-r--r-- | client/menu/blur_setup.gd | 1 | ||||
-rw-r--r-- | client/menu/character.gd | 12 | ||||
-rw-r--r-- | client/menu/communicate/popup_message/popup_message.gd | 117 | ||||
-rw-r--r-- | client/menu/communicate/popup_message/popup_message.tscn | 86 | ||||
-rw-r--r-- | client/menu/communicate/popup_message/server_message.gd | 13 | ||||
-rw-r--r-- | client/menu/communicate/popup_message/server_message.tscn | 6 | ||||
-rw-r--r-- | client/menu/hairstyle_preview.gd | 2 | ||||
-rw-r--r-- | client/menu/ingame.gd | 39 | ||||
-rw-r--r-- | client/menu/lobby.gd | 42 | ||||
-rw-r--r-- | client/menu/menu_background.gd | 32 | ||||
-rw-r--r-- | client/menu/play.gd | 1 | ||||
-rw-r--r-- | client/player/character/character.gd | 106 | ||||
-rw-r--r-- | client/player/character/character.tscn | 8 | ||||
-rw-r--r-- | client/player/controllable_player.gd | 13 | ||||
-rw-r--r-- | client/player/player.gd | 2 |
17 files changed, 302 insertions, 243 deletions
diff --git a/client/game.gd b/client/game.gd index 76bb271a..fe1e9ba6 100644 --- a/client/game.gd +++ b/client/game.gd @@ -21,9 +21,8 @@ extends Node3D signal update_players(players: Dictionary) signal data_updated() signal in_lobby_updated(in_lobby: bool) +signal join_state_updated(state: JoinState) signal text_message(player: int, text: String, timeout_initial: float, timeout_remaining: float) -signal joined() -signal left() signal update_tutorial_running(running: bool) enum SpectatingMode { @@ -31,6 +30,12 @@ enum SpectatingMode { FREE, } +enum JoinState { + SPECTATING, + WAITING, + JOINED, +} + var player_id: int = -1 var item_names: Array = [] var item_index_by_name: Dictionary = {} @@ -42,10 +47,10 @@ var maps: Array = [] var bot_algos: Array var text_message_history: Array[Array] = [] +var join_state: JoinState = JoinState.SPECTATING + var in_lobby := false var is_replay := false -var is_joined := false -var join_sent := false var tutorial_running := false var tutorial_queue := [] var last_position := Vector2(0, 0) @@ -99,8 +104,7 @@ func handle_packet(p): in_lobby_updated.connect(player_instance.onscreen_controls.in_lobby_updated) player_instance.onscreen_controls.in_lobby_updated(in_lobby) camera.target = player_instance.movement_base - is_joined = true - joined.emit() + set_join_state(JoinState.JOINED) else: player_instance = Player.new(p.id, p.name, p.position, p.character, self) players[p.id] = player_instance @@ -114,8 +118,7 @@ func handle_packet(p): tutorial_queue.erase(player.current_item_message) pinned_items.clear_item(p.id) if p.id == player_id: - is_joined = false - left.emit() + set_join_state(JoinState.SPECTATING) camera.target = $Center if player.hand != null: player.hand.queue_free() @@ -244,18 +247,15 @@ func handle_packet(p): map.gi_bake() await get_parent()._menu_open() map.autobake = true - - if in_lobby: popup_message.lobby() - else: popup_message.ingame() + + in_lobby_updated.emit(in_lobby) else: map.autobake = false await get_parent()._menu_exit() - + lobby.visible = in_lobby - if lobby and not join_sent: - join() - - in_lobby_updated.emit(in_lobby) + if lobby and join_state == JoinState.SPECTATING: + toggle_join() "score": if p.time_remaining != null: overlay.update(p.demands_failed, p.demands_completed, p.points, p.time_remaining) @@ -291,7 +291,7 @@ func handle_packet(p): "server_message": var mstr := get_message_str(p.message) if p.error: - # popup_message.display_server_msg(tr("c.error.server").format([mstr])) + popup_message.display_server_msg(tr("c.error.server").format([mstr])) push_error(tr("c.error.server").format([mstr])) else: popup_message.display_server_msg(mstr) @@ -310,7 +310,7 @@ func handle_packet(p): else: # Positional hint message if message == null: - popup_message.clear_server_msg() + popup_message.clear_server_msg(position_) else: popup_message.display_server_msg_positional(get_message_str(message), position_, false) "environment": @@ -323,16 +323,20 @@ func handle_packet(p): _: push_error("Unrecognized packet type: %s" % p.type) -func join(): - if join_sent: - push_error("Join was already sent. Tried to join twice.") - return - join_sent = true - mp.send_join(Global.get_profile("username"), Global.get_profile("character")) +func set_join_state(state: JoinState): + join_state = state + join_state_updated.emit(state) -func leave(): - join_sent = false - mp.send_leave(player_id) +func toggle_join(): + match join_state: + JoinState.SPECTATING: + set_join_state(JoinState.WAITING) + mp.send_join(Global.get_profile("username"), Global.get_profile("character")) + JoinState.WAITING: + push_error("Join/Leave action already toggled.") + JoinState.JOINED: + set_join_state(JoinState.WAITING) + mp.send_leave(player_id) func _process(delta): update_center() @@ -359,7 +363,7 @@ func get_tile_interactive(pos: Vector2i) -> bool: func update_center(): - if is_joined: + if join_state != JoinState.SPECTATING: return if Input.get_vector("left", "right", "forwards", "backwards").normalized().length() > .1: spectating_mode = SpectatingMode.FREE diff --git a/client/map/tiles/floor.gd b/client/map/tiles/floor.gd index 8e75834b..dd51c928 100644 --- a/client/map/tiles/floor.gd +++ b/client/map/tiles/floor.gd @@ -16,11 +16,12 @@ class_name Floor extends Tile -var opt +var opt: bool + func _init(ctx: TileFactory.TileCC): opt = ctx.floor_mesher != null super(ctx) - if opt: ctx.floor_mesher.add_tile(ctx.position) + if not base_mesh: ctx.floor_mesher.add_tile(ctx.position) func get_base_mesh(): if opt: return null diff --git a/client/menu/blur_setup.gd b/client/menu/blur_setup.gd index 331d1f47..9d55a9d4 100644 --- a/client/menu/blur_setup.gd +++ b/client/menu/blur_setup.gd @@ -14,6 +14,7 @@ # along with this program. If not, see <https://www.gnu.org/licenses/>. # extends Control +class_name BlurSetup func _ready(): update(Global.get_setting("graphics.ui_blur")) diff --git a/client/menu/character.gd b/client/menu/character.gd index 6af30250..dd3bc5cd 100644 --- a/client/menu/character.gd +++ b/client/menu/character.gd @@ -18,7 +18,6 @@ extends Menu @onready var character: Character = $Node3D/Character -@onready var num_hairstyles := character.hairstyles.keys().size() @onready var back_button := $VBoxContainer/bottom_panel/back @onready var map: Map = $Node3D/Map @onready var username_edit = $VBoxContainer/top_panel/a/username @@ -26,7 +25,7 @@ extends Menu func _ready(): super() $VBoxContainer/top_panel/a/username.text = Global.get_profile("username") - character.select_hairstyle(Global.get_profile("character")) + character.set_style(Global.get_profile("character")) init_map() func init_map(): @@ -53,6 +52,7 @@ func init_map(): for y in tiles.size(): for x in tiles[y].size(): map.set_tile(Vector2i(x,y) - co, gt.call([x,y]), [[x,y-1],[x-1,y],[x,y+1],[x+1,y]].map(gt)) + map.flush() func _input(_event): if Input.is_action_just_pressed("ui_cancel"): @@ -68,9 +68,9 @@ func _on_back_pressed(): replace_menu("res://menu/main.tscn") func _on_character_back_pressed(): - Global.set_profile("character", (Global.get_profile("character") - 1) % num_hairstyles) - character.select_hairstyle(Global.get_profile("character")) + Global.set_profile("character", max(Global.get_profile("character") - 1, 0)) + character.set_style(Global.get_profile("character")) func _on_character_forward_pressed(): - Global.set_profile("character", (Global.get_profile("character") + 1) % num_hairstyles) - character.select_hairstyle(Global.get_profile("character")) + Global.set_profile("character", max(Global.get_profile("character") + 1, 0)) + character.set_style(Global.get_profile("character")) diff --git a/client/menu/communicate/popup_message/popup_message.gd b/client/menu/communicate/popup_message/popup_message.gd index 6c2c2c0e..98bd94e3 100644 --- a/client/menu/communicate/popup_message/popup_message.gd +++ b/client/menu/communicate/popup_message/popup_message.gd @@ -14,45 +14,34 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <https://www.gnu.org/licenses/>. # -extends MarginContainer +extends Control class_name PopupMessage +const SERVER_MESSAGE_SCENE = preload("res://menu/communicate/popup_message/server_message.tscn") + var is_ingame := false var is_joined := false -@onready var server_msg = $VBox/ServerMessage -@onready var server_msg_positional = $ServerMessagePositional -@onready var hint_msg = $VBox/HintMessage - -@onready var server_msg_timer: Timer = $ServerTimer -@onready var hint_msg_timer: Timer = $HintTimer - -@onready var server_msg_label: Label = $VBox/ServerMessage/CenterContainer/Label -@onready var server_msg_positional_label: Label = $ServerMessagePositional/ServerMessage/CenterContainer/Label -@onready var hint_msg_label: Label = $VBox/HintMessage/CenterContainer/Label +var positional_messages = {} -@onready var server_msg_positional_panel: PanelContainer = $ServerMessagePositional/ServerMessage +@onready var positional_messages_node: Control = $Positional +@onready var server_msg = $Static/VBox/ServerMessage +@onready var hint_msg = $Static/VBox/HintMessage -@onready var auto_hint_timers: Node = $AutoHintTimers +@onready var server_msg_label: Label = $Static/VBox/ServerMessage/CenterContainer/Label +@onready var hint_msg_label: Label = $Static/VBox/HintMessage/CenterContainer/Label -@onready var reset_timer = $Reset -@onready var join_while_running_timer = $JoinWhileRunning +@onready var auto_hint_timers: Node = $Timers/AutoHints +@onready var server_msg_timer: Timer = $Timers/Server +@onready var hint_msg_timer: Timer = $Timers/Hint +@onready var reset_timer = $Timers/Reset +@onready var join_while_running_timer = $Timers/JoinWhileRunning @onready var game: Game = $"../Game" -var server_message_position := Vector2.ZERO -var last_server_message_panel_size := Vector2.ZERO - func _ready(): - game.joined.connect( - func player_joined(): - is_joined = true - update_state() - ) - game.left.connect( - func player_joined(): - is_joined = false - update_state() + game.join_state_updated.connect(func(state: Game.JoinState): + is_joined = state == Game.JoinState.JOINED ) game.update_tutorial_running.connect( func a(running: bool): @@ -61,25 +50,26 @@ func _ready(): else: update_state() ) + game.in_lobby_updated.connect( + func a(in_lobby): + is_ingame = not in_lobby + update_state() + ) func _process(_delta: float): - if server_msg_positional.visible: - var pos_3d = Vector3(server_message_position.x + 0.5, 1.5, server_message_position.y + 0.5) + for pos: Vector2 in positional_messages.keys(): + var msg: PositionalMessage = positional_messages[pos] + var pos_3d = Vector3(pos.x + 0.5, 1.5, pos.y + 0.5) var pos_2d = get_viewport().get_camera_3d().unproject_position(pos_3d) - var server_message_panel_size = server_msg_positional_panel.size - server_msg_positional.position = pos_2d.clamp(Vector2.ZERO + 0.5 * server_message_panel_size, Vector2(get_viewport_rect().size) - 0.5 * server_message_panel_size) - if server_message_panel_size != last_server_message_panel_size: - last_server_message_panel_size = server_message_panel_size - server_msg_positional_panel.position = -0.5 * last_server_message_panel_size - -func ingame(): - is_ingame = true - update_state() - -func lobby(): - is_ingame = false - update_state() + msg.node_2d.position = pos_2d.clamp( + Vector2.ZERO + 0.5 * msg.node.size, + Vector2(get_viewport_rect().size) - 0.5 * msg.node.size + ) + + if msg.node.size != msg.last_size: + msg.last_size = msg.node.size + msg.node.position = -0.5 * msg.last_size func update_state(): if is_ingame and is_joined: @@ -91,30 +81,35 @@ func update_state(): stop_game_hints() func display_server_msg(msg: String, auto_remove := true): - clear_server_msg() server_msg.show() server_msg_label.text = msg if auto_remove: server_msg_timer.start() -func display_server_msg_positional(msg: String, pos: Vector2, auto_remove := true): +func _on_server_timeout() -> void: clear_server_msg() - server_msg_positional.show() - server_message_position = pos - server_msg_positional_label.text = msg - server_msg_positional_panel.size = Vector2.ZERO - - if auto_remove: - server_msg_timer.start() -func clear_server_msg(): - server_msg_timer.stop() - server_msg.hide() - server_msg_positional.hide() +func display_server_msg_positional(text: String, pos: Vector2, use_monospace: bool): + var msg := PositionalMessage.new() + msg.node = SERVER_MESSAGE_SCENE.instantiate() + msg.node_2d = Node2D.new() + positional_messages_node.add_child(msg.node_2d) + msg.node_2d.add_child(msg.node) + msg.node.set_text(text, use_monospace) + msg.node.size = Vector2.ZERO + msg.position = pos + positional_messages[pos] = msg -func _on_server_timer_timeout(): - clear_server_msg() +func clear_server_msg(position_ = null): + if position_ == null: + server_msg_timer.stop() + server_msg.hide() + else: + if position_ in positional_messages: + var msg: PositionalMessage = positional_messages[position_] + msg.node_2d.queue_free() + positional_messages.erase(position_) func display_hint_msg(msg: String): hint_msg.show() @@ -220,7 +215,7 @@ func _on_rotate_camera_timeout(): )])) func _on_join_while_running_timeout(): - if not game.is_joined and not Global.get_hint("has_seen_join_while_running"): + if not game.join_state == Game.JoinState.JOINED and not Global.get_hint("has_seen_join_while_running"): Global.set_hint("has_seen_join_while_running", true) display_hint_msg(tr("c.hint.join_while_running").format([display_keybind("menu")])) @@ -228,3 +223,9 @@ func _on_performance_timeout() -> void: if not Global.get_hint("has_seen_performance") and Engine.get_frames_per_second() < DisplayServer.screen_get_refresh_rate() * 0.75: Global.set_hint("has_seen_performance", true) display_hint_msg(tr("c.hint.framerate_low")) + +class PositionalMessage: + var node: ServerMessage + var node_2d: Node2D + var position: Vector2 + var last_size: Vector2 diff --git a/client/menu/communicate/popup_message/popup_message.tscn b/client/menu/communicate/popup_message/popup_message.tscn index 799712e1..880e8670 100644 --- a/client/menu/communicate/popup_message/popup_message.tscn +++ b/client/menu/communicate/popup_message/popup_message.tscn @@ -33,25 +33,35 @@ content_margin_top = 8.0 content_margin_right = 32.0 content_margin_bottom = 8.0 -[node name="PopupMessage" type="MarginContainer"] +[node name="PopupMessage" type="Control"] +layout_mode = 3 anchors_preset = 15 anchor_right = 1.0 anchor_bottom = 1.0 grow_horizontal = 2 grow_vertical = 2 mouse_filter = 2 -theme = ExtResource("1_a1566") script = ExtResource("2_sbew6") -[node name="VBox" type="VBoxContainer" parent="."] +[node name="Static" type="MarginContainer" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 +theme = ExtResource("1_a1566") + +[node name="VBox" type="VBoxContainer" parent="Static"] layout_mode = 2 mouse_filter = 2 -[node name="ServerMessage" parent="VBox" instance=ExtResource("3_m3rok")] +[node name="ServerMessage" parent="Static/VBox" instance=ExtResource("3_m3rok")] visible = false layout_mode = 2 -[node name="HintMessage" type="PanelContainer" parent="VBox"] +[node name="HintMessage" type="PanelContainer" parent="Static/VBox"] visible = false material = SubResource("ShaderMaterial_k0m35") layout_mode = 2 @@ -60,12 +70,12 @@ mouse_filter = 2 theme_override_styles/panel = SubResource("StyleBoxFlat_vq4dg") script = ExtResource("4_pvwmw") -[node name="CenterContainer" type="HBoxContainer" parent="VBox/HintMessage"] +[node name="CenterContainer" type="HBoxContainer" parent="Static/VBox/HintMessage"] layout_mode = 2 mouse_filter = 2 alignment = 1 -[node name="MarginContainer" type="MarginContainer" parent="VBox/HintMessage/CenterContainer"] +[node name="MarginContainer" type="MarginContainer" parent="Static/VBox/HintMessage/CenterContainer"] layout_mode = 2 mouse_filter = 2 theme_override_constants/margin_left = 4 @@ -73,7 +83,7 @@ theme_override_constants/margin_top = 4 theme_override_constants/margin_right = 4 theme_override_constants/margin_bottom = 4 -[node name="TextureRect" type="TextureRect" parent="VBox/HintMessage/CenterContainer/MarginContainer"] +[node name="TextureRect" type="TextureRect" parent="Static/VBox/HintMessage/CenterContainer/MarginContainer"] custom_minimum_size = Vector2(28, 28) layout_mode = 2 mouse_filter = 2 @@ -81,7 +91,7 @@ texture = ExtResource("5_2dxsd") expand_mode = 1 stretch_mode = 4 -[node name="Label" type="Label" parent="VBox/HintMessage/CenterContainer"] +[node name="Label" type="Label" parent="Static/VBox/HintMessage/CenterContainer"] layout_mode = 2 size_flags_horizontal = 3 theme_override_fonts/font = SubResource("FontVariation_qfltj") @@ -89,60 +99,66 @@ theme_override_styles/normal = SubResource("StyleBoxEmpty_3rgop") text = "A hint is worth more than a thousand manuals" autowrap_mode = 3 -[node name="ServerTimer" type="Timer" parent="."] +[node name="Positional" type="Control" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 + +[node name="Timers" type="Node" parent="."] + +[node name="Server" type="Timer" parent="Timers"] wait_time = 5.0 one_shot = true -[node name="HintTimer" type="Timer" parent="."] +[node name="Hint" type="Timer" parent="Timers"] wait_time = 10.0 one_shot = true -[node name="AutoHintTimers" type="Node" parent="."] +[node name="AutoHints" type="Node" parent="Timers"] -[node name="Move" type="Timer" parent="AutoHintTimers"] +[node name="Move" type="Timer" parent="Timers/AutoHints"] wait_time = 2.0 one_shot = true -[node name="Performance" type="Timer" parent="AutoHintTimers"] +[node name="Performance" type="Timer" parent="Timers/AutoHints"] wait_time = 20.0 one_shot = true -[node name="Boost" type="Timer" parent="AutoHintTimers"] +[node name="Boost" type="Timer" parent="Timers/AutoHints"] wait_time = 90.0 one_shot = true -[node name="Interact" type="Timer" parent="AutoHintTimers"] +[node name="Interact" type="Timer" parent="Timers/AutoHints"] wait_time = 15.0 one_shot = true -[node name="RotateCamera" type="Timer" parent="AutoHintTimers"] +[node name="RotateCamera" type="Timer" parent="Timers/AutoHints"] wait_time = 120.0 one_shot = true -[node name="Zoom" type="Timer" parent="AutoHintTimers"] +[node name="Zoom" type="Timer" parent="Timers/AutoHints"] wait_time = 135.0 one_shot = true -[node name="Reset" type="Timer" parent="."] +[node name="Reset" type="Timer" parent="Timers"] wait_time = 10.0 one_shot = true -[node name="JoinWhileRunning" type="Timer" parent="."] +[node name="JoinWhileRunning" type="Timer" parent="Timers"] wait_time = 5.0 one_shot = true -[node name="ServerMessagePositional" type="Node2D" parent="."] -visible = false - -[node name="ServerMessage" parent="ServerMessagePositional" instance=ExtResource("3_m3rok")] - -[connection signal="timeout" from="ServerTimer" to="." method="_on_server_timer_timeout"] -[connection signal="timeout" from="HintTimer" to="." method="_on_hint_timer_timeout"] -[connection signal="timeout" from="AutoHintTimers/Move" to="." method="_on_move_timeout"] -[connection signal="timeout" from="AutoHintTimers/Performance" to="." method="_on_performance_timeout"] -[connection signal="timeout" from="AutoHintTimers/Boost" to="." method="_on_boost_timeout"] -[connection signal="timeout" from="AutoHintTimers/Interact" to="." method="_on_interact_timeout"] -[connection signal="timeout" from="AutoHintTimers/RotateCamera" to="." method="_on_rotate_camera_timeout"] -[connection signal="timeout" from="AutoHintTimers/Zoom" to="." method="_on_zoom_timeout"] -[connection signal="timeout" from="Reset" to="." method="_on_reset_timeout"] -[connection signal="timeout" from="JoinWhileRunning" to="." method="_on_join_while_running_timeout"] +[connection signal="timeout" from="Timers/Server" to="." method="_on_server_timeout"] +[connection signal="timeout" from="Timers/Hint" to="Static" method="_on_hint_timer_timeout"] +[connection signal="timeout" from="Timers/AutoHints/Move" to="Static" method="_on_move_timeout"] +[connection signal="timeout" from="Timers/AutoHints/Performance" to="Static" method="_on_performance_timeout"] +[connection signal="timeout" from="Timers/AutoHints/Boost" to="Static" method="_on_boost_timeout"] +[connection signal="timeout" from="Timers/AutoHints/Interact" to="Static" method="_on_interact_timeout"] +[connection signal="timeout" from="Timers/AutoHints/RotateCamera" to="Static" method="_on_rotate_camera_timeout"] +[connection signal="timeout" from="Timers/AutoHints/Zoom" to="Static" method="_on_zoom_timeout"] +[connection signal="timeout" from="Timers/Reset" to="Static" method="_on_reset_timeout"] +[connection signal="timeout" from="Timers/JoinWhileRunning" to="Static" method="_on_join_while_running_timeout"] diff --git a/client/menu/communicate/popup_message/server_message.gd b/client/menu/communicate/popup_message/server_message.gd new file mode 100644 index 00000000..fc12ee76 --- /dev/null +++ b/client/menu/communicate/popup_message/server_message.gd @@ -0,0 +1,13 @@ +extends BlurSetup +class_name ServerMessage + +const DEFAULT_FONT = preload("res://menu/theme/font-josefin-sans.woff2") +const MONOSPACE_FONT = preload("res://menu/theme/font-azaret-mono.woff2") + +@onready var label: Label = $CenterContainer/Label + +func set_text(text: String, use_monospace := true): + label.text = text + var font: FontVariation = label.get_theme_font("font") + font.base_font = MONOSPACE_FONT if use_monospace else DEFAULT_FONT + label.add_theme_font_size_override("font_size", 16 if use_monospace else 20) diff --git a/client/menu/communicate/popup_message/server_message.tscn b/client/menu/communicate/popup_message/server_message.tscn index 63160942..2a848419 100644 --- a/client/menu/communicate/popup_message/server_message.tscn +++ b/client/menu/communicate/popup_message/server_message.tscn @@ -1,7 +1,7 @@ [gd_scene load_steps=8 format=3 uid="uid://dq61p3a8og2b6"] [ext_resource type="Shader" path="res://menu/blur_mix.gdshader" id="1_qv8ew"] -[ext_resource type="Script" path="res://menu/blur_setup.gd" id="2_80a6b"] +[ext_resource type="Script" path="res://menu/communicate/popup_message/server_message.gd" id="2_csqo8"] [ext_resource type="FontFile" uid="uid://bk704sc5gkrb3" path="res://menu/theme/font-azaret-mono.woff2" id="3_dw20j"] [sub_resource type="ShaderMaterial" id="ShaderMaterial_q3bbd"] @@ -20,6 +20,7 @@ corner_radius_bottom_right = 16 corner_radius_bottom_left = 16 [sub_resource type="FontVariation" id="FontVariation_qfltj"] +resource_local_to_scene = true base_font = ExtResource("3_dw20j") variation_embolden = 0.75 @@ -35,7 +36,7 @@ size_flags_horizontal = 4 size_flags_vertical = 0 mouse_filter = 2 theme_override_styles/panel = SubResource("StyleBoxFlat_vq4dg") -script = ExtResource("2_80a6b") +script = ExtResource("2_csqo8") [node name="CenterContainer" type="CenterContainer" parent="."] layout_mode = 2 @@ -45,5 +46,6 @@ mouse_filter = 2 layout_mode = 2 theme_override_colors/font_color = Color(0, 0, 0, 1) theme_override_fonts/font = SubResource("FontVariation_qfltj") +theme_override_font_sizes/font_size = 16 theme_override_styles/normal = SubResource("StyleBoxEmpty_3rgop") text = "Server message" diff --git a/client/menu/hairstyle_preview.gd b/client/menu/hairstyle_preview.gd index 5a9cce68..08b6aab9 100644 --- a/client/menu/hairstyle_preview.gd +++ b/client/menu/hairstyle_preview.gd @@ -19,7 +19,7 @@ extends VBoxContainer signal selected(character: int) func setup(character: int, group: ButtonGroup): - $HairViewport/Node3D/Character.select_hairstyle(character) + $HairViewport/Node3D/Character.set_style(character) $Select.button_group = group $Select.text = tr("c.setup.uniform.value").format([character + 1]) $Select.pressed.connect(func(): selected.emit(character)) diff --git a/client/menu/ingame.gd b/client/menu/ingame.gd index 7052f237..ba365f8e 100644 --- a/client/menu/ingame.gd +++ b/client/menu/ingame.gd @@ -26,19 +26,16 @@ extends Menu var opened func _ready(): opened = Time.get_ticks_msec() - game.joined.connect(_on_game_joined) - game.left.connect(_on_game_left) - update_button_text() - game.joined.connect(update_lobby_button) - game.left.connect(update_lobby_button) + game.join_state_updated.connect(_on_game_join_state_changed) + _on_game_join_state_changed(game.join_state) update_lobby_button() super() func update_lobby_button(): - lobby_button.disabled = game.in_lobby or not game.is_joined + lobby_button.disabled = game.in_lobby or game.join_state == Game.JoinState.SPECTATING if game.in_lobby: lobby_button.tooltip_text = "Cannot cancel game since no game is running." - elif not game.is_joined: + elif not game.join_state == Game.JoinState.JOINED: lobby_button.tooltip_text = "You must join in order to be able to cancel the current game." else: lobby_button.tooltip_text = "" @@ -71,21 +68,15 @@ func _on_lobby_pressed(): exit() func _on_leave_pressed(): - if game.is_joined: - game.mp.send_leave(game.player_id) - elif not game.join_sent: - leave_button.disabled = true - game.join() + game.toggle_join() -func _on_game_joined(): - leave_button.disabled = false - update_button_text() - -func _on_game_left(): - update_button_text() - -func update_button_text(): - if game.is_joined: - leave_button.text = tr("c.menu.ingame.leave") - else: - leave_button.text = tr("c.menu.ingame.join") +func _on_game_join_state_changed(state: Game.JoinState): + match state: + Game.JoinState.JOINED: + leave_button.disabled = false + leave_button.text = tr("c.menu.ingame.leave") + Game.JoinState.SPECTATING: + leave_button.disabled = false + leave_button.text = tr("c.menu.ingame.join") + Game.JoinState.WAITING: + leave_button.disabled = true diff --git a/client/menu/lobby.gd b/client/menu/lobby.gd index 0dca6f4c..d595444e 100644 --- a/client/menu/lobby.gd +++ b/client/menu/lobby.gd @@ -52,8 +52,8 @@ func _ready(): game.update_players.connect(update_players) initialize() game.data_updated.connect(initialize) - game.joined.connect(_on_game_joined) - game.left.connect(_on_game_left) + game.join_state_updated.connect(_on_game_join_state_updated) + _on_game_join_state_updated(game.join_state) check_for_music() func initialize(): @@ -145,18 +145,6 @@ func _input(_event): elif Input.is_action_just_pressed("next") and not next_map.disabled: next_map.emit_signal("pressed") -func _on_game_joined(): - map_selector.show() - map_list.show() - bots_container.show() - start_button.disabled = false - -func _on_game_left(): - map_selector.hide() - map_list.hide() - bots_container.hide() - start_button.disabled = true - func _on_left_pressed(): selected_map = (selected_map - 1) % map_count select_map(selected_map) @@ -177,13 +165,27 @@ func _on_controller_button_pressed(): game.mp.send_chat(game.player_id, start_msg) Sound.play_music("stop") # TODO: Game music enter +func _on_game_join_state_updated(state: Game.JoinState): + match state: + Game.JoinState.JOINED: + map_selector.show() + map_list.show() + bots_container.show() + start_button.disabled = false + join_spectate.disabled = false + join_spectate.text = tr("c.menu.ingame.spectate") + Game.JoinState.SPECTATING: + map_selector.hide() + map_list.hide() + bots_container.hide() + start_button.disabled = true + join_spectate.disabled = false + join_spectate.text = tr("c.menu.ingame.join") + Game.JoinState.WAITING: + join_spectate.disabled = true + func _on_join_spectate_pressed(): - if game.is_joined: - game.leave() - join_spectate.text = tr("c.menu.ingame.join") - elif not game.join_sent: - game.join() - join_spectate.text = tr("c.menu.ingame.spectate") + game.toggle_join() func check_for_music(): if visible: diff --git a/client/menu/menu_background.gd b/client/menu/menu_background.gd index 33ec6e43..77fb123f 100644 --- a/client/menu/menu_background.gd +++ b/client/menu/menu_background.gd @@ -17,8 +17,8 @@ # extends Node3D -const NULLS = [null,null,null,null] -const BUCKETS = [[], ["floor","floor","floor","floor","tomato-crate", "steak-crate"], ["table", "chair", "counter"], ["sink", "stove"]] +const CRATES = ["tomato-crate", "steak-crate", "cheese-crate", "lettuce-crate", "flour-crate", "coconut-crate"] +const TOOLS = ["sink", "cuttingboard", "stove", "oven", "freezer"] @onready var environment: WorldEnvironment = $Environment @onready var map: Map = $Map @@ -27,12 +27,26 @@ func _ready(): if !Global.on_vulkan(): environment.environment.tonemap_exposure = 0.25 - for x in range(-10,11): - for y in range(-10,11): - var w = exp(-sqrt(x*x+y*y) * 0.15) + var tiles = {} + for x in range(-10, 11): + for y in range(-10, 11): + var w = exp(-sqrt(x * x + y * y) * 0.15) var k = randf() * w - var bucket = BUCKETS[int(floor(k * BUCKETS.size())) % BUCKETS.size()] - if bucket.size() == 0: continue - var tile_name = bucket[randi() % bucket.size()] - map.set_tile(Vector2i(x,y), tile_name) + var tn = null + if k > 0.25: tn = "floor" + if k > 0.4: tn = choose(CRATES) if randf() > 0.3 else "counter" + if k > 0.6: tn = choose(TOOLS) + if tn != null: tiles[str(Vector2i(x,y))] = [tn,[x,y]] + + var gt = func (cs): + var t = tiles.get(str(Vector2i(cs[0],cs[1]))) + return null if t == null else t[0] + for pk in tiles.keys(): + var x = tiles[pk][1][0] + var y = tiles[pk][1][1] + var t = gt.call([x,y]) + if t != null: map.set_tile(Vector2i(x,y), t, [[x,y-1],[x-1,y],[x,y+1],[x+1,y]].map(gt)) + map.flush() + +func choose(a): return a[floor(a.size() * randf())] diff --git a/client/menu/play.gd b/client/menu/play.gd index 1fe19224..b117d6a4 100644 --- a/client/menu/play.gd +++ b/client/menu/play.gd @@ -19,7 +19,6 @@ extends Menu var url_regex: RegEx = RegEx.new() -@onready var req: HTTPRequest = $HTTPRequest @onready var server_list: VBoxContainer = $side/margin/options/second/ScrollContainerCustom/ServerList @onready var server_list_loading: Label = $side/margin/options/second/Loading @onready var connect_uri = $side/margin/options/second/connect/uri diff --git a/client/player/character/character.gd b/client/player/character/character.gd index 66a3435b..65275549 100644 --- a/client/player/character/character.gd +++ b/client/player/character/character.gd @@ -42,11 +42,16 @@ var current_animation := "idle" @onready var tie = $Main/Tie @onready var knife = $Main/HandRight/Knife -@onready var hairstyles := { - "Brown": $Main/HeadDefault/Hair, - "Blond": $Main/HeadDefault/Hair2, - "E. Parsley": $Main/HeadDefault/Hair3 -} +const NUM_COLORS = 5; +const NUM_HAIRS = 3; +@onready var hairstyles := [$Main/HeadDefault/Hair, $Main/HeadDefault/Hair2, $Main/HeadDefault/Hair3] +var colors = [ + Color(0.204, 0.361, 0.624), + Color(0.568, 0.256, 0.602), + Color(0.575, 0.341, 0.117), + Color(0.3, 0.455, 0.221), + Color(0.101, 0.452, 0.521) +] @onready var head_default: MeshInstance3D = $Main/HeadDefault @onready var head_robot: MeshInstance3D = $Main/HeadRobot @@ -54,28 +59,41 @@ var current_animation := "idle" @onready var step_sounds: PlayRandom = $Steps @onready var boost_sounds: PlayRandom = $Boosts +class ParsedStyle: + var color: int + var hair: int + var robot: bool + var customer: bool + func _init(n: int) -> void: + customer = n < 0 + if customer: n *= -1 + if n == 51: robot = true + else: + hair = n % NUM_HAIRS + color = n / NUM_HAIRS % NUM_COLORS + func pack() -> int: + if robot: return 51 + return (hair + color * NUM_HAIRS) * (-1 if customer else 1) + func _ready(): play_animation("idle") var t := 0.0 func _process(delta): - if walking: - t += delta - main_height_target = default_height + sin(t * WALK_ANIM_SPEED) * WALK_ANIM_STRENGTH - else: - t = 0 + t += delta + if walking: main_height_target = default_height + sin(t * WALK_ANIM_SPEED) * WALK_ANIM_STRENGTH + else: t = 0 main.position.y = main_height_target # Update animation: var next_animation: String - if holding: - next_animation = "hold" - elif cutting: - next_animation = "cut" - elif walking: - next_animation = "walk" - else: - next_animation = "idle" + if holding: next_animation = "hold" + elif cutting: next_animation = "cut" + elif walking: next_animation = "walk" + else: next_animation = "idle" + + if current_animation != next_animation: + play_animation(next_animation) walking_particles.emitting = walking if boosting and walking and not was_boosting: @@ -85,47 +103,31 @@ func _process(delta): boosting_particles.emitting = false was_boosting = boosting and walking - if current_animation != next_animation: - play_animation(next_animation) - -func select_hairstyle(id: int): - if id == 51: - toggle_robot(true) - return - if id < 0: - to_customer() - id *= -1 - var hairstyle_count = hairstyles.keys().size() - id = id % hairstyle_count - var target = hairstyles.keys()[id] - for k in hairstyles.keys(): - if k == target: - hairstyles[k].show() - else: - hairstyles[k].hide() - -func to_customer(): - main.mesh = CUSTOMER_MAIN_MESH - tie.queue_free() +func set_style(id: int): + var p = ParsedStyle.new(id) + set_customer(p.customer) + set_robot(p.robot) + for h in hairstyles: h.hide() + hairstyles[p.hair].show() + $Main.get_active_material(0).albedo_color = colors[p.color] -func toggle_robot(b: bool): +func set_customer(b: bool): if b: - head_robot.show() - head_default.hide() - main.mesh = ROBOT_MAIN_MESH - else: - head_robot.hide() - head_default.show() - main.mesh = DEFAULT_MAIN_MESH + main.mesh = CUSTOMER_MAIN_MESH + tie.queue_free() + else: pass # TODO + +func set_robot(b: bool): + head_robot.visible = b + head_default.visible = not b + main.mesh = ROBOT_MAIN_MESH if b else DEFAULT_MAIN_MESH func play_animation(name_: String): current_animation = name_ hand_animations.play(name_) - if name_ == "walk": - step_sounds.start_autoplay() - else: - step_sounds.stop_autoplay() + if name_ == "walk": step_sounds.start_autoplay() + else: step_sounds.stop_autoplay() knife.visible = name_ == "cut" diff --git a/client/player/character/character.tscn b/client/player/character/character.tscn index a7c09c01..aca0658a 100644 --- a/client/player/character/character.tscn +++ b/client/player/character/character.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=27 format=3 uid="uid://b3hhir2fvnunu"] +[gd_scene load_steps=28 format=3 uid="uid://b3hhir2fvnunu"] [ext_resource type="Script" path="res://player/character/character.gd" id="1_12lbh"] [ext_resource type="ArrayMesh" uid="uid://bnmm01yjwultj" path="res://player/character/default/main.res" id="2_uovyg"] @@ -18,6 +18,11 @@ [ext_resource type="AudioStream" uid="uid://1jsqpnk3igj3" path="res://player/sounds/woosh1.ogg" id="14_ikcec"] [ext_resource type="AudioStream" uid="uid://cwme7eatip0jc" path="res://player/sounds/woosh2.ogg" id="15_iv4wu"] +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_7ojaw"] +resource_local_to_scene = true +resource_name = "main" +cull_mode = 2 + [sub_resource type="Animation" id="Animation_tdhvg"] length = 0.001 tracks/0/type = "bezier" @@ -729,6 +734,7 @@ script = ExtResource("1_12lbh") transform = Transform3D(0.33, 0, 0, 0, 0.33, 0, 0, 0, 0.33, 0, 0.33, 0) mesh = ExtResource("2_uovyg") skeleton = NodePath("") +surface_material_override/0 = SubResource("StandardMaterial3D_7ojaw") [node name="HandRight" type="MeshInstance3D" parent="Main"] transform = Transform3D(0.287144, 0.2864, -1.17785e-06, 0.402357, -0.133775, 0.337554, 0.292329, -0.0971941, -0.464603, -1.302, -0.17, 0) diff --git a/client/player/controllable_player.gd b/client/player/controllable_player.gd index 0cabcb64..131bc55d 100644 --- a/client/player/controllable_player.gd +++ b/client/player/controllable_player.gd @@ -43,7 +43,7 @@ func _ready(): add_child(timer) timer.start() timer.connect("timeout", func(): - if game.mp != null and game.join_sent: + if game.mp != null and game.join_state == Game.JoinState.JOINED: game.mp.send_movement(game.player_id, position_, direction, boosting) ) add_child(onscreen_controls) @@ -60,13 +60,20 @@ func _process(delta): update_touch_scrolls() var moving_duration = 0 +var fps_rotation_target = 0 func _process_movement(delta): var input = Input.get_vector("left", "right", "forwards", "backwards") if is_input_enabled() else Vector2.ZERO if Global.get_setting("gameplay.first_person"): - input.x *= 0.1 + fps_rotation_target += input.x * delta * 3. + if abs(input.x) > 0.1: input.y -= 0.5 + input.x = 0. input.y = min(input.y, 0) + input = input.rotated(fps_rotation_target) + else: + input = input.rotated(input_rotation) + var boost = Input.is_action_pressed("boost") or (Global.get_setting("gameplay.latch_boost") and boosting) - input = input.rotated(input_rotation) + # if Input.is_action_pressed("interact") or Input.is_action_just_released("interact"): input *= 0 else: diff --git a/client/player/player.gd b/client/player/player.gd index 31a7a337..6ff28e81 100644 --- a/client/player/player.gd +++ b/client/player/player.gd @@ -79,7 +79,7 @@ func _init(_id: int, new_name: String, pos: Vector2, new_character_idx: int, new is_customer = character_idx < 0 func _ready(): - character.select_hairstyle(character_idx) + character.set_style(character_idx) clear_timer.timeout.connect(clear_message) Settings.hook_changed_init("gameplay.usernames", false, update_username_tag) |