From 1cf3afd4404db2c6eb76a8a916c832f9b3a5164a Mon Sep 17 00:00:00 2001 From: JonShard Date: Thu, 6 Aug 2026 14:51:49 +0200 Subject: [PATCH] Add DayController and QueueController to handle spawning of customer through out a day --- Prefabs/build_mode_controller.tscn | 6 ++++ Prefabs/day_controller.tscn | 6 ++++ Scenes/day_controller.gd | 57 ++++++++++++++++++++++++++++++ Scenes/day_controller.gd.uid | 1 + Scenes/queue_controller.gd | 49 +++++++++++++++++++++++++ Scenes/queue_controller.gd.uid | 1 + Scenes/test_small.tscn | 53 ++++++++++++++++----------- Stations/table.gd | 25 +++++++++---- documentation/Notes.md | 16 ++++++++- global/GameManager.gd | 13 ++++++- global/Signals.gd | 2 ++ kanban_tasks_data.kanban | 20 +++++++++-- recipes.yaml.uid | 1 - 13 files changed, 217 insertions(+), 33 deletions(-) create mode 100644 Prefabs/build_mode_controller.tscn create mode 100644 Prefabs/day_controller.tscn create mode 100644 Scenes/day_controller.gd create mode 100644 Scenes/day_controller.gd.uid create mode 100644 Scenes/queue_controller.gd create mode 100644 Scenes/queue_controller.gd.uid delete mode 100644 recipes.yaml.uid diff --git a/Prefabs/build_mode_controller.tscn b/Prefabs/build_mode_controller.tscn new file mode 100644 index 0000000..e932a68 --- /dev/null +++ b/Prefabs/build_mode_controller.tscn @@ -0,0 +1,6 @@ +[gd_scene format=3 uid="uid://bnwb7imcotkod"] + +[ext_resource type="Script" uid="uid://bsdpd18i1i17s" path="res://prefabs/build_mode_controller.gd" id="1_7i0c4"] + +[node name="BuildModeController" type="Node" unique_id=552013109] +script = ExtResource("1_7i0c4") diff --git a/Prefabs/day_controller.tscn b/Prefabs/day_controller.tscn new file mode 100644 index 0000000..a5527c0 --- /dev/null +++ b/Prefabs/day_controller.tscn @@ -0,0 +1,6 @@ +[gd_scene format=3 uid="uid://dm70ynyuw1a5u"] + +[ext_resource type="Script" uid="uid://bbr5arulbeuvq" path="res://scenes/day_controller.gd" id="1_lna8j"] + +[node name="DayController" type="Node" unique_id=1418639156] +script = ExtResource("1_lna8j") diff --git a/Scenes/day_controller.gd b/Scenes/day_controller.gd new file mode 100644 index 0000000..4da49f5 --- /dev/null +++ b/Scenes/day_controller.gd @@ -0,0 +1,57 @@ +class_name DayController +extends Node + +# DayController Emits singals to spawn customers. + +var day_time_remaining: float = 0.0 +var customers_spawned: int = 0 +var customers_served: int = 0 + + +func _ready() -> void: + GameManager.game_state = GameManager.GameState.BUILDING + Signals.game_state_changed.connect(_on_game_state_changed) + + +func _on_game_state_changed(new_state: GameManager.GameState) -> void: + if new_state == GameManager.GameState.RUNNING: + start_next_day() + + +# Returns 0-1 progress of the day time +func get_day_progression() -> float: + return 1 - (day_time_remaining / GameManager.day_length_seconds) + + +func _reset_values() -> void: + day_time_remaining = GameManager.day_length_seconds + customers_spawned = 0 + customers_served = 0 + + +func start_next_day() -> void: + print("DayController: start_next_day") + _reset_values() + GameManager.customers_per_day += GameManager.customers_count_increase_per_day + GameManager.day_number += 1 + + +func finish_current_day() -> void: + print("DayController: finish_current_day") + _reset_values() + + +func _process(delta: float) -> void: + if GameManager.game_state != GameManager.GameState.RUNNING: + return + day_time_remaining -= delta + var customers_at_this_time = GameManager.customers_per_day * get_day_progression() + #print("DayController: customers_at_this_time: ", customers_at_this_time) + if customers_spawned < customers_at_this_time: + customers_spawned += 1 + print("DayController: spawning customer") + Signals.request_customer_spawn.emit() + # If day complete + if GameManager.customers_per_day == customers_served and customers_spawned == GameManager.customers_per_day: + print("DayController: Day complete") + finish_current_day() diff --git a/Scenes/day_controller.gd.uid b/Scenes/day_controller.gd.uid new file mode 100644 index 0000000..cc36e18 --- /dev/null +++ b/Scenes/day_controller.gd.uid @@ -0,0 +1 @@ +uid://bbr5arulbeuvq diff --git a/Scenes/queue_controller.gd b/Scenes/queue_controller.gd new file mode 100644 index 0000000..5682f10 --- /dev/null +++ b/Scenes/queue_controller.gd @@ -0,0 +1,49 @@ +extends Node3D + +@export var queue_patience: float = 120 + +@export var progress_bar_3d: ProgressBar3D +@export var label_3d: Label3D + + +var _customers: Array[float] = [] # Temp. Array of their patience + + +func _ready() -> void: + progress_bar_3d.override_fill_color(Color.YELLOW) + progress_bar_3d.exponential = true + Signals.request_customer_spawn.connect(_on_request_customer_spawn) + Signals.consumed_customer.connect(on_consumed_customer) + +func _on_request_customer_spawn() -> void: + spawn_customer() + + +func on_consumed_customer() -> void: + _customers.pop_front() + + +func spawn_customer() -> void: + _customers.append(queue_patience) + + +func _process(delta: float) -> void: + # Process customers patience + for i in range(0, _customers.size()): + _customers[i] -= delta + if _customers[i] <= 0: + GameManager.game_over() + + # Try to assign customers to tables + for customer in _customers: + get_tree().call_group("table", "try_consume_customer") + + + # Update visuals + if not _customers.is_empty(): + label_3d.text = "Customers in queue: " + str(_customers.size()) + progress_bar_3d.set_progress(_customers.front() / queue_patience) + else: + progress_bar_3d.set_progress(0) + label_3d.text = "No Customers" + diff --git a/Scenes/queue_controller.gd.uid b/Scenes/queue_controller.gd.uid new file mode 100644 index 0000000..d0ba0f4 --- /dev/null +++ b/Scenes/queue_controller.gd.uid @@ -0,0 +1 @@ +uid://dww2icfivdsai diff --git a/Scenes/test_small.tscn b/Scenes/test_small.tscn index f16ec29..c84f974 100644 --- a/Scenes/test_small.tscn +++ b/Scenes/test_small.tscn @@ -6,15 +6,17 @@ [ext_resource type="Material" uid="uid://cmia50cfqxxo4" path="res://textures/dev_material_3d.tres" id="4_kpgm6"] [ext_resource type="PackedScene" uid="uid://j7caslh27nor" path="res://stations/Hob.tscn" id="5_gfdi7"] [ext_resource type="PackedScene" uid="uid://efaec6ymgabo" path="res://stations/Counter.tscn" id="7_jnxsa"] -[ext_resource type="PackedScene" uid="uid://drwuhqb3pjtiy" path="res://items/potato.tscn" id="8_1qeqw"] -[ext_resource type="PackedScene" uid="uid://dlw5geheupgpt" path="res://stations/hatch.tscn" id="8_atgwk"] -[ext_resource type="Script" uid="uid://bsdpd18i1i17s" path="res://prefabs/build_mode_controller.gd" id="9_atgwk"] -[ext_resource type="PackedScene" uid="uid://dvrk268s7gkxh" path="res://stations/sink.tscn" id="10_dhas4"] +[ext_resource type="PackedScene" uid="uid://bnwb7imcotkod" path="res://prefabs/build_mode_controller.tscn" id="9_hooyg"] [ext_resource type="PackedScene" uid="uid://caf0xanmxbshy" path="res://stations/table.tscn" id="11_gaw43"] +[ext_resource type="PackedScene" uid="uid://cwnwo4i28upap" path="res://stations/raw_burger_dispenser.tscn" id="12_hooyg"] [ext_resource type="PackedScene" uid="uid://clujaf3u776a3" path="res://addons/godot-xr-tools/objects/viewport_2d_in_3d.tscn" id="12_n58f2"] +[ext_resource type="PackedScene" uid="uid://c6rift56ql3f8" path="res://stations/BurgerBunsDispenser.tscn" id="13_cqmpj"] [ext_resource type="PackedScene" uid="uid://xtcei2uvd5li" path="res://UI/game_over_panel.tscn" id="13_hooyg"] +[ext_resource type="PackedScene" uid="uid://ck5tuftqmyiue" path="res://stations/plate_dispenser.tscn" id="14_bjwcu"] [ext_resource type="Script" uid="uid://cwijoksyou1ey" path="res://prefabs/GameOvercontroler.gd" id="14_cqmpj"] -[ext_resource type="PackedScene" uid="uid://sc6i0i1f0o48" path="res://stations/potato_dispenser.tscn" id="15_hooyg"] +[ext_resource type="Script" uid="uid://dww2icfivdsai" path="res://scenes/queue_controller.gd" id="15_cqmpj"] +[ext_resource type="PackedScene" uid="uid://bxbocxdaayvwx" path="res://UI/progress_bar.tscn" id="15_hooyg"] +[ext_resource type="PackedScene" uid="uid://dm70ynyuw1a5u" path="res://prefabs/day_controller.tscn" id="17_bjwcu"] [sub_resource type="Environment" id="Environment_bvwq1"] background_mode = 2 @@ -97,20 +99,7 @@ shape = SubResource("BoxShape3D_24d3s") [node name="Counter" parent="." unique_id=1487893288 instance=ExtResource("7_jnxsa")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.6, 0, 0) -[node name="Potato" parent="." unique_id=962444046 instance=ExtResource("8_1qeqw")] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.273382, 1.5940565, -0.036002517) - -[node name="Hatch" parent="." unique_id=1341321603 instance=ExtResource("8_atgwk")] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.2, 0, 0) - -[node name="Hatch2" parent="." unique_id=1755144529 instance=ExtResource("8_atgwk")] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.6, 0, 0) - -[node name="BuildModeController" type="Node" parent="." unique_id=1876729190] -script = ExtResource("9_atgwk") - -[node name="Sink" parent="." unique_id=1559059799 instance=ExtResource("10_dhas4")] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.2, 0, 0) +[node name="BuildModeController" parent="." unique_id=552013109 instance=ExtResource("9_hooyg")] [node name="Table" parent="." unique_id=1863572470 instance=ExtResource("11_gaw43")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.8, 0, 1.8) @@ -126,5 +115,27 @@ scene_properties_keys = PackedStringArray("game_over_panel.gd") [node name="controler" type="Node" parent="GameOverPanel" unique_id=1442195864] script = ExtResource("14_cqmpj") -[node name="PotatoDispenser" parent="." unique_id=1410160280 instance=ExtResource("15_hooyg")] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.8000002, 0, 0) +[node name="RawBurgerDispenser" parent="." unique_id=383615587 instance=ExtResource("12_hooyg")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.6, 0, 0) + +[node name="BurgerBunsDispenser" parent="." unique_id=1410160280 instance=ExtResource("13_cqmpj")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.2, 0, 0) + +[node name="PlateDispenser" parent="." unique_id=53391541 instance=ExtResource("14_bjwcu")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.8000001, 0, 0.6) + +[node name="QueueController" type="Node3D" parent="." unique_id=1490726434 node_paths=PackedStringArray("progress_bar_3d", "label_3d")] +transform = Transform3D(-1, 0, -8.742278e-08, 0, 1, 0, 8.742278e-08, 0, -1, -1.2, 0, 4.8) +script = ExtResource("15_cqmpj") +progress_bar_3d = NodePath("ProgressBar3D") +label_3d = NodePath("Label3D") + +[node name="ProgressBar3D" parent="QueueController" unique_id=654673176 instance=ExtResource("15_hooyg")] +transform = Transform3D(2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 2.4, 0) +exponential = true + +[node name="Label3D" type="Label3D" parent="QueueController" unique_id=1060766769] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.147749, 0) +text = "X customers in queue" + +[node name="DayController" parent="." unique_id=1418639156 instance=ExtResource("17_bjwcu")] diff --git a/Stations/table.gd b/Stations/table.gd index 4e0231b..d36a224 100644 --- a/Stations/table.gd +++ b/Stations/table.gd @@ -22,7 +22,6 @@ const lbl_gameover: String = "Game Over!" const lbl_eating: String = "Eating..." ### Finite State Machine #### - enum TableState { IDLE, # Don't update table. incorrect GameState EMPTY, # Just finished eating or havent eaten yet @@ -50,10 +49,11 @@ var _players_count: int = 0 func place_order() -> void: print("Table place_order()") var new_orders: Array[String] = _unsatisfied_orders.duplicate() - for _i in range(0, randi_range(1, 2)): - new_orders.append(GameManager.get_random_meal()) - for _i in range(0, randi_range(0, 1)): - new_orders.append(GameManager.get_random_side()) + # for _i in range(0, randi_range(1, 2)): + # new_orders.append(GameManager.get_random_meal()) + # for _i in range(0, randi_range(0, 1)): + # new_orders.append(GameManager.get_random_side()) + new_orders.append(GameManager.get_random_meal()) _unsatisfied_orders = new_orders _original_orders = _unsatisfied_orders.duplicate() @@ -95,6 +95,13 @@ func clearAllFood() -> void: NetworkManager.despawn_item(held_object) +# Group called from Queue when trying to assign customers to tables +func try_consume_customer(): + if _state == TableState.EMPTY: + print("Table try_consume_customer, consumed a customer") + _state_end(TableState.EMPTY) + Signals.consumed_customer.emit() + func _ready() -> void: if not label_3d: @@ -266,8 +273,6 @@ func _set_state(newState: TableState) -> void: _state = newState customers.visible = false TableState.EMPTY: - _state_time = randf_range(3, 7) - _state_duration = _state_time customers.visible = false _state = newState TableState.THINKING: @@ -364,6 +369,8 @@ func _refresh_display() -> void: func _process(delta: float) -> void: _refresh_display() + if GameManager.game_state == GameManager.GameState.GAME_OVER: + return _place_order_if_player() # If build mode, set, exit loop, be idle @@ -378,6 +385,10 @@ func _process(delta: float) -> void: elif _state == TableState.IDLE: return + # No counting down if wer're empty + if _state == TableState.EMPTY: + return + # Wait for state to finish if _state_time > 0.0: _state_time = max(0.0, _state_time - delta) diff --git a/documentation/Notes.md b/documentation/Notes.md index fbfe3b6..cc7f382 100644 --- a/documentation/Notes.md +++ b/documentation/Notes.md @@ -58,7 +58,21 @@ Shared INventory list +## Customer design +- A customer is a simple goto point object. has queue_patience float +- A customer is spawned in street, told to move to QueueController Area +- A QueueController tracks the entered customer and tells it to take a queue position +- A QueueController displays a progress bar above door of queue_patience of the customer in the Area3D with the least patience. +- On new table available, QueueController tells front customer in queue to sit at table + + + ## Modifiers -- Disposable plates. no washing. much less money \ No newline at end of file +- Disposable plates. no washing. much less money + + + +## Weird ideas +- carry 4 plates. A snapzone on forearm that only accept plate, and drops it if tilted too much. Real waiter feel. \ No newline at end of file diff --git a/global/GameManager.gd b/global/GameManager.gd index 3f0d3ae..626aaff 100644 --- a/global/GameManager.gd +++ b/global/GameManager.gd @@ -1,17 +1,28 @@ class_name GameManager extends Node +const STAR_DAY_FREQUENCY: int = 3 + static var money: int = 1000 +static var day_number: int = 1 static var meals_in_play: Array[String] static var sides_in_play: Array[String] +# GameConfig - difficulty settings +static var day_length_seconds: float = 60.0 +static var customers_per_day: float = 5.0 +static var customers_count_increase_per_day: float = 1.0 +static var group_min_size: int = 1 +static var group_max_size: int = 2 + + enum GameState { RUNNING, GAME_OVER, BUILDING } -static var game_state: GameState = GameState.RUNNING: set = _set_game_state +static var game_state: GameState = GameState.BUILDING: set = _set_game_state static func _set_game_state(value: GameState): game_state = value diff --git a/global/Signals.gd b/global/Signals.gd index fcb91ae..fb955d8 100644 --- a/global/Signals.gd +++ b/global/Signals.gd @@ -4,3 +4,5 @@ signal game_over signal restart_game signal game_state_changed(new_state: GameManager.GameState) signal station_bought(instance: Node3D) +signal request_customer_spawn() +signal consumed_customer() # When a table consumes a customer from the queue diff --git a/kanban_tasks_data.kanban b/kanban_tasks_data.kanban index 813bb22..002c7ab 100644 --- a/kanban_tasks_data.kanban +++ b/kanban_tasks_data.kanban @@ -22,14 +22,16 @@ "uuid": "211e4050-31cd-4425-a2ba-8ca56b4764cd", "title": "Todo", "tasks": [ - "55ac73b8-4378-4b58-bf3c-33f64590c804" + "55ac73b8-4378-4b58-bf3c-33f64590c804", + "dcdef6be-39f9-44b3-a892-b74afe880909" ] }, { "uuid": "fab8a81b-7ca9-4026-96bb-ed66ea58ef2e", "title": "Doing", "tasks": [ - "f8073eb2-8786-47b7-b63f-fa70c3f7115a" + "f8073eb2-8786-47b7-b63f-fa70c3f7115a", + "ba3c1f0c-1d34-431a-9e42-f80f8d8159a4" ] }, { @@ -274,6 +276,20 @@ "description": "", "category": "bf4ec62e-526e-4027-876f-0b22bd17f79a", "steps": [] + }, + { + "uuid": "ba3c1f0c-1d34-431a-9e42-f80f8d8159a4", + "title": "QueueController", + "description": "- A customer is a simple goto point object. has queue_patience float\n- A customer is spawned in street, told to move to QueueController Area\n- A QueueController tracks the entered customer and tells it to take a queue position \n- A QueueController displays a progress bar above door of queue_patience of the customer in the Area3D with the least patience.\n- On new table available, QueueController tells front customer in queue to sit at table\n\n", + "category": "bf4ec62e-526e-4027-876f-0b22bd17f79a", + "steps": [] + }, + { + "uuid": "dcdef6be-39f9-44b3-a892-b74afe880909", + "title": "Customer Pathfinder", + "description": "- A customer is a simple goto point object. has queue_patience float\n- A customer is spawned in street, told to move to QueueController Area\n- A QueueController tracks the entered customer and tells it to take a queue position \n- A QueueController displays a progress bar above door of queue_patience of the customer in the Area3D with the least patience.\n- On new table available, QueueController tells front customer in queue to sit at table\n\n", + "category": "bf4ec62e-526e-4027-876f-0b22bd17f79a", + "steps": [] } ], "layout": { diff --git a/recipes.yaml.uid b/recipes.yaml.uid deleted file mode 100644 index 26c7014..0000000 --- a/recipes.yaml.uid +++ /dev/null @@ -1 +0,0 @@ -uid://be8o8m6xpp3kc