diff --git a/PlayerBoard.gd b/PlayerBoard.gd index e52cb28..4607cc1 100644 --- a/PlayerBoard.gd +++ b/PlayerBoard.gd @@ -2,11 +2,3 @@ class_name PlayerBoard extends Node2D -# Called when the node enters the scene tree for the first time. -func _ready() -> void: - pass # Replace with function body. - - -# Called every frame. 'delta' is the elapsed time since the previous frame. -func _process(delta: float) -> void: - pass diff --git a/Scenes/Table.tscn b/Scenes/Table.tscn index a1828ed..34ff530 100644 --- a/Scenes/Table.tscn +++ b/Scenes/Table.tscn @@ -1,8 +1,7 @@ -[gd_scene load_steps=5 format=3 uid="uid://x8fd0k3qhn1x"] +[gd_scene load_steps=4 format=3 uid="uid://x8fd0k3qhn1x"] [ext_resource type="Texture2D" uid="uid://crk6m37iy1itk" path="res://Assets/table.png" id="1_gchuv"] [ext_resource type="Script" path="res://Scripts/game.gd" id="1_ne3d3"] -[ext_resource type="Script" path="res://Scripts/chat.gd" id="4_dww8o"] [ext_resource type="PackedScene" uid="uid://y2i3u6n1oowh" path="res://Scenes/deck.tscn" id="4_ugbip"] [node name="Table" type="Node2D" node_paths=PackedStringArray("worker_deck", "client_deck", "worker_discard", "client_discard", "seat1", "seat2", "seat3", "seat4")] @@ -47,22 +46,3 @@ position = Vector2(-1341, -737) position = Vector2(1313, -747) [node name="Players" type="Node2D" parent="."] - -[node name="LobbyCamera" type="Camera2D" parent="."] -zoom = Vector2(0.225, 0.225) - -[node name="RichTextLabel" type="RichTextLabel" parent="LobbyCamera"] -offset_left = -2563.0 -offset_top = 687.0 -offset_right = -1417.0 -offset_bottom = 1259.0 -theme_override_font_sizes/normal_font_size = 50 -scroll_following = true -script = ExtResource("4_dww8o") - -[node name="LineEdit" type="LineEdit" parent="LobbyCamera"] -offset_left = -2547.0 -offset_top = 1276.0 -offset_right = -1421.0 -offset_bottom = 1421.0 -theme_override_font_sizes/font_size = 50 diff --git a/Scenes/human_player.tscn b/Scenes/human_player.tscn index cce7a66..a74caaa 100644 --- a/Scenes/human_player.tscn +++ b/Scenes/human_player.tscn @@ -3,74 +3,91 @@ [ext_resource type="Script" path="res://Scripts/PlayerStateMachine/human_controller.gd" id="1_4thxs"] [ext_resource type="Theme" uid="uid://d26ldkm1br1bo" path="res://UI_Theme.tres" id="2_ja0q8"] -[node name="HumanPlayer" type="Node2D"] +[node name="HumanPlayer" type="Node2D" node_paths=PackedStringArray("hand_position")] script = ExtResource("1_4thxs") +hand_position = NodePath("Node2D") + +[node name="Node2D" type="Node2D" parent="."] [node name="Camera2D" type="Camera2D" parent="."] -visible = false -zoom = Vector2(0.4, 0.4) +zoom = Vector2(0.501, 0.501) -[node name="UI" type="Control" parent="."] -visible = false +[node name="CanvasLayer" type="CanvasLayer" parent="."] + +[node name="UI" type="Control" parent="CanvasLayer"] layout_mode = 3 -anchors_preset = 0 -offset_right = 40.0 -offset_bottom = 40.0 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 theme = ExtResource("2_ja0q8") -[node name="Cash" type="Label" parent="UI"] -visible = false -layout_mode = 0 -offset_left = -561.0 -offset_top = -27.0 -offset_right = -521.0 -offset_bottom = -1.0 -text = "$100" +[node name="Cash" type="Label" parent="CanvasLayer/UI"] +layout_mode = 2 +offset_top = 312.0 +offset_right = 1152.0 +offset_bottom = 335.0 -[node name="Profit" type="Label" parent="UI"] -visible = false -layout_mode = 0 -offset_left = -521.0 -offset_top = -27.0 -offset_right = -481.0 -offset_bottom = -1.0 +[node name="Profit" type="Label" parent="CanvasLayer/UI"] +layout_mode = 2 +offset_top = 311.0 +offset_right = 1152.0 +offset_bottom = 337.0 theme_override_colors/font_color = Color(0, 0.870588, 0, 1) -text = "+23 +text = " " -[node name="Loss" type="Label" parent="UI"] -visible = false -layout_mode = 0 -offset_left = -491.0 -offset_top = -27.0 -offset_right = -451.0 -offset_bottom = -1.0 +[node name="Loss" type="Label" parent="CanvasLayer/UI"] +layout_mode = 2 +offset_top = 312.0 +offset_right = 1152.0 +offset_bottom = 335.0 theme_override_colors/font_color = Color(0.909804, 0, 0, 1) -text = "-38" -[node name="Phase" type="Label" parent="UI"] -visible = false -layout_mode = 0 -offset_left = -113.0 -offset_top = -311.0 -offset_right = 103.0 -offset_bottom = -285.0 -text = "{Management / Shift} Phase" +[node name="Phase" type="Label" parent="CanvasLayer/UI"] +layout_mode = 2 +offset_top = 312.0 +offset_right = 1152.0 +offset_bottom = 335.0 -[node name="LobbyReadyButton" type="Button" parent="UI"] -layout_mode = 0 -offset_left = -26.0 -offset_top = -313.0 -offset_right = 30.0 -offset_bottom = -282.0 +[node name="HBoxContainer" type="HBoxContainer" parent="CanvasLayer/UI"] +layout_mode = 1 +anchors_preset = -1 +anchor_left = 0.5 +anchor_right = 0.5 +offset_left = -42.5 +offset_top = 21.0 +offset_right = 42.5 +offset_bottom = 31.0 +grow_horizontal = 2 +alignment = 1 + +[node name="LobbyReadyButton" type="Button" parent="CanvasLayer/UI/HBoxContainer"] +layout_mode = 2 text = "Ready" -[node name="LobbyReadyLabel" type="Label" parent="UI"] -layout_mode = 0 -offset_left = 39.0 -offset_top = -309.0 -offset_right = 79.0 -offset_bottom = -283.0 -text = "0/4" +[node name="LobbyReadyLabel" type="Label" parent="CanvasLayer/UI/HBoxContainer"] +layout_mode = 2 +text = "0/1" +horizontal_alignment = 1 +vertical_alignment = 1 -[connection signal="pressed" from="UI/LobbyReadyButton" to="." method="_on_lobby_ready_button_pressed"] +[node name="VBoxContainer" type="VBoxContainer" parent="CanvasLayer/UI"] +layout_mode = 1 +anchors_preset = -1 +anchor_top = 1.0 +anchor_bottom = 1.0 +offset_top = -178.0 +offset_right = 254.0 +grow_vertical = 0 + +[node name="RichTextLabel" type="RichTextLabel" parent="CanvasLayer/UI/VBoxContainer"] +layout_mode = 2 +size_flags_vertical = 3 + +[node name="LineEdit" type="LineEdit" parent="CanvasLayer/UI/VBoxContainer"] +layout_mode = 2 + +[connection signal="pressed" from="CanvasLayer/UI/HBoxContainer/LobbyReadyButton" to="." method="_on_lobby_ready_button_pressed"] +[connection signal="text_submitted" from="CanvasLayer/UI/VBoxContainer/LineEdit" to="." method="_on_line_edit_text_submitted"] diff --git a/Scripts/PlayerStateMachine/bot_controller.gd b/Scripts/PlayerStateMachine/bot_controller.gd index 44fef53..13b9531 100644 --- a/Scripts/PlayerStateMachine/bot_controller.gd +++ b/Scripts/PlayerStateMachine/bot_controller.gd @@ -1,2 +1,4 @@ class_name BotController extends PlayerController + + diff --git a/Scripts/PlayerStateMachine/human_controller.gd b/Scripts/PlayerStateMachine/human_controller.gd index f1f6a1c..3a778d1 100644 --- a/Scripts/PlayerStateMachine/human_controller.gd +++ b/Scripts/PlayerStateMachine/human_controller.gd @@ -1,25 +1,42 @@ class_name HumanController extends PlayerController +signal ready_button_pressed(int) +signal chat_message_submitted(String) + +@onready var ready_button = $CanvasLayer/UI/HBoxContainer/LobbyReadyButton +@onready var ready_label = $CanvasLayer/UI/HBoxContainer/LobbyReadyLabel +@onready var canvas = $CanvasLayer +@onready var chat_box = $CanvasLayer/UI/VBoxContainer/RichTextLabel + func _ready() -> void: if not is_multiplayer_authority(): + canvas.visible = false return $Camera2D.make_current() - $UI.visible = true @rpc("call_local") -func ready_player(): - game.ready_player(own_id) +func ready_self(): + ready_button_pressed.emit(player_info["id"]) @rpc("any_peer") -func update_ready_label(): - $UI/LobbyReadyLabel.text = str(game.readied_players.size()) + "/" + str(game.players.size()) +func update_ready_label(readied_players, total_players): + ready_label.text = str(readied_players) + "/" + str(total_players) func _on_lobby_ready_button_pressed() -> void: - rpc("ready_player") - $UI/LobbyReadyButton.visible = false - update_ready_label() + rpc("ready_self") + ready_button.visible = false + + +func add_chat_line(line: String) -> void: + chat_box.text += line + + +func _on_line_edit_text_submitted(new_text: String) -> void: + var msg = "[" + player_info["username"] + "] " + new_text + "\n" + $CanvasLayer/UI/VBoxContainer/LineEdit.text = "" + chat_message_submitted.emit(msg) diff --git a/Scripts/PlayerStateMachine/player_controller.gd b/Scripts/PlayerStateMachine/player_controller.gd index 445b70b..9fa9b4a 100644 --- a/Scripts/PlayerStateMachine/player_controller.gd +++ b/Scripts/PlayerStateMachine/player_controller.gd @@ -1,6 +1,16 @@ class_name PlayerController extends Node -var game: Game -var board: PlayerBoard -var own_id: int +var player_info +@export var hand_position: Node2D +var hand = [] + + +func draft(cards, _pick): + var xxx = (250.0 * cards.size()) / 2.0 + for x in cards.size(): + var card = cards[x] + var ratio = float(x) / float(cards.size() - 1) + var xx = lerpf(-1 * xxx, xxx, ratio) + card.slide_to_position(hand_position.global_position.x + xx, hand_position.global_position.y, 0.0, 0.2) + hand.append(card) diff --git a/Scripts/deck.gd b/Scripts/deck.gd index 3d7fef7..b1ff93d 100644 --- a/Scripts/deck.gd +++ b/Scripts/deck.gd @@ -36,7 +36,7 @@ func _on_area_2d_mouse_exited() -> void: mouse_exited.emit() -func draw() -> Card: +func draw_card() -> Card: return cards.pop_back() @@ -51,3 +51,9 @@ func place(card: Card) -> void: func shuffle() -> void: cards.shuffle() + + +func order(node_paths) -> void: + cards = [] + for path in node_paths: + cards.append(get_node(path)) diff --git a/Scripts/game.gd b/Scripts/game.gd index 9e650a5..43fbff1 100644 --- a/Scripts/game.gd +++ b/Scripts/game.gd @@ -21,8 +21,9 @@ const CLIENT_DECK_SAVE_PATH = "user://client_deck.json" @export var seat4: Node2D var networked_controllers: Array[HumanController] = [] -var players = [] -var readied_players = [] +var current_player := 0 +var players: Array[PlayerController] = [] +var readied_players: Array[int] = [] var _worker_scene = preload("res://Scenes/worker_card.tscn") var _client_scene = preload("res://Scenes/client_card.tscn") @@ -96,17 +97,30 @@ func add_player(id: int, username: String, type: PlayerType) -> void: PlayerType.HUMAN: controller = _human_scene.instantiate() networked_controllers.append(controller) + controller.ready_button_pressed.connect(ready_player) + controller.chat_message_submitted.connect(message) + var player_info = {} + player_info["id"] = id + player_info["username"] = username + controller.player_info = player_info PlayerType.BOT: controller = _bot_scene.instantiate() controller.name = str(id) controller.set_multiplayer_authority(id) - controller.own_id = id - controller.game = self as Game - controller.board = board as PlayerBoard board.add_child(controller) - players.append(id) + players.append(controller) for player in networked_controllers: - player.rpc("update_ready_label") + player.rpc("update_ready_label", readied_players.size(), players.size()) + + +@rpc("call_local", "any_peer") #called from message() by player signals +func relay_chat_message(msg): + for player in networked_controllers: + player.add_chat_line(msg) + + +func message(msg): + rpc("relay_chat_message", msg) func ready_player(id): @@ -115,8 +129,40 @@ func ready_player(id): if readied_players.size() == players.size(): start_game() for player in networked_controllers: - player.rpc("update_ready_label") + player.rpc("update_ready_label", readied_players.size(), players.size()) func start_game(): - print("Game started!") + #Only the host should shuffle the decks + if is_multiplayer_authority(): + randomize() + var deck_order = [] + for card in worker_deck.cards: + deck_order.append(card.get_path()) + rpc("send_worker_order", deck_order) + deck_order = [] + for card in client_deck.cards: + deck_order.append(card.get_path()) + rpc("send_client_order", deck_order) + for player in players: + rpc("draft_workers", player.player_info["username"], 4, 2) + + +@rpc +func send_worker_order(node_paths): + worker_deck.order(node_paths) + + +@rpc +func send_client_order(node_paths): + client_deck.order(node_paths) + + +@rpc("call_local") +func draft_workers(player, draw_amount, pick_amount): + var cards = [] + for x in draw_amount: + cards.append(worker_deck.draw_card()) + for x in players: + if x.player_info["username"] == player: + x.draft(cards, pick_amount) diff --git a/Scripts/network_lobby.gd b/Scripts/network_lobby.gd index ee875fe..b57670c 100644 --- a/Scripts/network_lobby.gd +++ b/Scripts/network_lobby.gd @@ -15,7 +15,6 @@ var players_connected = 0 func _ready() -> void: game = game_scene.instantiate() as Game - func host_server() -> void: @@ -28,12 +27,10 @@ func host_server() -> void: player_info[1] = $UI/Username.text add_player(1, player_info[1]) - game.get_node("LobbyCamera/LineEdit").text_submitted.connect(text_message) multiplayer.peer_connected.connect( func(new_peer_id): rpc_id(new_peer_id, "add_previous_players", connected_players) - #rpc("add_new_player", new_peer_id) ) @@ -48,6 +45,7 @@ func connect_to_server() -> void: add_child(game) player_info[multiplayer.get_unique_id()] = $UI/Username.text + func add_player(peer_id, username): connected_players[peer_id] = username game.add_player(peer_id, username, game.PlayerType.HUMAN) @@ -58,15 +56,11 @@ func add_new_player(peer_id, username): add_player(peer_id, username) -func text_message(new_text): - game.get_node("LobbyCamera/RichTextLabel").rpc("add_line", player_info[multiplayer.get_unique_id()], new_text) - game.get_node("LobbyCamera/LineEdit").text = "" - - @rpc func add_previous_players(players): for key in players: + if players[key] == player_info[multiplayer.get_unique_id()]: + player_info[multiplayer.get_unique_id()] += "_" add_player(key, players[key]) rpc_id(key, "add_new_player", multiplayer.get_unique_id(), player_info[multiplayer.get_unique_id()]) add_player(multiplayer.get_unique_id(), player_info[multiplayer.get_unique_id()]) - game.get_node("LobbyCamera/LineEdit").text_submitted.connect(text_message) diff --git a/Scripts/player.gd b/Scripts/player.gd index ef35da6..056a1ad 100644 --- a/Scripts/player.gd +++ b/Scripts/player.gd @@ -168,22 +168,6 @@ func select_slot(slot): selected_worker.slide_to_position(slot.position.x, slot.position.y, 0.0, 0.3) selected_worker = null -#Shift Phase - #1. Swap 1 time token on each worker over to the stress side - #2. Pick up the next client card in the deck, and either assign it to - # a worker or place it in the no service pile - #3. If a worker both has no client, and at least one stress token, remove - # a stress token - -#Management Phase - #Market Research - #Look at the 10 clients, and place them back in the same order - #Targeted Advertising - #Search through the client discard deck, and add all clients - #with one extra type to your shift deck - #Roster Worker - #Add 1 worker from your hand into the next open slot on your board - func _on_area_2d_input_event(_viewport, event, _shape_idx): if event is InputEventMouseButton and event.pressed: diff --git a/export_presets.cfg b/export_presets.cfg index 3a7c5b6..02b05fa 100644 --- a/export_presets.cfg +++ b/export_presets.cfg @@ -130,7 +130,7 @@ custom_template/release="" debug/export_console_script=1 application/icon="" application/icon_interpolation=4 -application/bundle_identifier="" +application/bundle_identifier="com.sowelijanpona.bordello" application/signature="" application/app_category="Games" application/short_version="1.0" diff --git a/ideas.txt b/ideas.txt index 6fbf33c..95ca3c9 100644 --- a/ideas.txt +++ b/ideas.txt @@ -1,10 +1,26 @@ -#Ideas okay? -#Make the client cards have a little progress track thats like how much they like their service right, -#put the poor/good/great blocks along that track, and instead of the services having that each service -#contributes a different number of points along that other track, so the money you recieve for making -#the match can be the same across all clients, but it shows how some clients value one more over the other -#without actually requiring you to have any specific one as long as you have enough turns to get them along -#the track, so a short session with all the perks can be a great service but a less special or less -#stress inducing session needs to be longer so the same worker needs to remain occupied longer, and it gives -#you more to do on your turn because you get to decide what all your little workers do rather than them only -#being interacted with when you're placing down a client card +Ideas okay? +Make the client cards have a little progress track thats like how much they like their service right, +put the poor/good/great blocks along that track, and instead of the services having that each service +contributes a different number of points along that other track, so the money you recieve for making +the match can be the same across all clients, but it shows how some clients value one more over the other +without actually requiring you to have any specific one as long as you have enough turns to get them along +the track, so a short session with all the perks can be a great service but a less special or less +stress inducing session needs to be longer so the same worker needs to remain occupied longer, and it gives +you more to do on your turn because you get to decide what all your little workers do rather than them only +being interacted with when you're placing down a client card + +Shift Phase + 1. Swap 1 time token on each worker over to the stress side + 2. Pick up the next client card in the deck, and either assign it to + a worker or place it in the no service pile + 3. If a worker both has no client, and at least one stress token, remove + a stress token + +Management Phase + Market Research + Look at the 10 clients, and place them back in the same order + Targeted Advertising + Search through the client discard deck, and add all clients + with one extra type to your shift deck + Roster Worker + Add 1 worker from your hand into the next open slot on your board