From 64befd8ec71f3cebc1a8a256ffc1da252bc49bc8 Mon Sep 17 00:00:00 2001 From: Lexi Quinn Date: Tue, 24 Jun 2025 01:14:50 +1000 Subject: [PATCH] make Game.gd not rely on autoload/global --- PCs/PathEditTool/path_edit_tool.gd | 29 +- PCs/hero.gd | 8 +- PCs/hud.gd | 12 +- Resources/Enemies/airenemy2.tres | 14 +- Resources/Enemies/dog.tres | 14 +- Scenes/CardPrinter/card_printer.gd | 4 +- Scenes/Menus/GameEndScreen/game_end_screen.gd | 18 +- Scenes/Menus/MainMenu/main_menu.gd | 18 +- Scenes/Menus/PauseMenu/pause_menu.gd | 10 +- Scenes/ShopStand/shop_stand.gd | 12 +- Scenes/TowerBase/tower_base.gd | 5 +- Scripts/EnemyAI/enemy_movement.gd | 1 - Scripts/a_star_graph_3d.gd | 266 ------------------ Scripts/a_star_graph_3d.gd.uid | 1 - Scripts/chatbox.gd | 5 +- Scripts/data.gd | 17 +- Scripts/enemy_spawner.gd | 9 +- Scripts/game.gd | 42 ++- Scripts/keybind_options.gd | 3 +- Scripts/level.gd | 8 +- Scripts/lobby.gd | 8 +- Scripts/multiplayer_lobby.gd | 14 +- Scripts/noise_random.gd | 21 ++ Scripts/noise_random.gd.uid | 1 + Scripts/options_menu.gd | 5 + Scripts/server_form.gd | 3 +- Scripts/singleplayer_lobby.gd | 3 +- Scripts/wave_manager.gd | 2 +- .../GreenPlanet/Enemies/enemy_controller.gd | 5 +- gif_animation.gd | 4 +- main.gd | 28 +- project.godot | 1 - psx.gdshader | 14 +- 33 files changed, 194 insertions(+), 411 deletions(-) delete mode 100644 Scripts/a_star_graph_3d.gd delete mode 100644 Scripts/a_star_graph_3d.gd.uid create mode 100644 Scripts/noise_random.gd create mode 100644 Scripts/noise_random.gd.uid diff --git a/PCs/PathEditTool/path_edit_tool.gd b/PCs/PathEditTool/path_edit_tool.gd index 6a35fbc..7952b85 100644 --- a/PCs/PathEditTool/path_edit_tool.gd +++ b/PCs/PathEditTool/path_edit_tool.gd @@ -7,13 +7,14 @@ class_name PathEditTool extends Node3D @export var progress_bar: TextureProgressBar var enabled: bool = true -var point: FlowNode = null +var level: Level +var point: FlowNode var obstacle_last_point: int = -1 var valid_point: bool = false # a point is valid if the path would still be traversable overall if this point was made untraversable var tower_preview: Tower var ray_collider: Object var ray_point: Vector3 -var last_point: FlowNode = null +var last_point: FlowNode var last_tower_base: TowerBase var interact_key_held: bool = false @@ -66,13 +67,13 @@ func _process(delta: float) -> void: if !interact_key_held: wall_preview.set_visible(true) if is_instance_valid(ray_collider) and ray_collider is TowerBase: - Game.level.walls[ray_collider.point].set_float(1.0) + level.walls[ray_collider.point].set_float(1.0) ray_collider = ray.get_collider() ray_point = ray.get_collision_point() if ray_collider is TowerBase: process_looking_at_tower() - elif Game.level: + elif level: process_looking_at_level() elif !interact_key_held: reset() @@ -84,8 +85,8 @@ func _process(delta: float) -> void: func reset() -> void: - if is_instance_valid(ray_collider) and ray_collider is TowerBase and Game.level.walls.has(ray_collider.point): - Game.level.walls[ray_collider.point].set_float(1.0) + if is_instance_valid(ray_collider) and ray_collider is TowerBase and level.walls.has(ray_collider.point): + level.walls[ray_collider.point].set_float(1.0) ray_collider = null delete_tower_preview() wall_preview.set_visible(false) @@ -96,8 +97,8 @@ func reset() -> void: func process_looking_at_level() -> void: if tower_preview: delete_tower_preview() - point = Game.level.flow_field.get_closest_buildable_point(ray_point) - if Game.level.walls.has(point) or !point.buildable or hero.currency < Data.wall_cost: + point = level.flow_field.get_closest_buildable_point(ray_point) + if level.walls.has(point) or !point.buildable or hero.currency < Data.wall_cost: wall_preview.set_visible(false) valid_point = false clear_previous_point() @@ -106,8 +107,8 @@ func process_looking_at_level() -> void: if last_point != point: clear_previous_point() last_point = point - if !Game.level.walls.has(point) and Game.level.flow_field.traversable_after_blocking_point(point): - Game.level.flow_field.toggle_traversable(point) + if !level.walls.has(point) and level.flow_field.traversable_after_blocking_point(point): + level.flow_field.toggle_traversable(point) wall_preview.set_float(0.0) valid_point = true else: @@ -115,8 +116,8 @@ func process_looking_at_level() -> void: func clear_previous_point() -> void: - if last_point and !Game.level.walls.has(last_point) and !last_point.traversable: - Game.level.flow_field.toggle_traversable(last_point) + if last_point and !level.walls.has(last_point) and !last_point.traversable: + level.flow_field.toggle_traversable(last_point) func process_looking_at_tower() -> void: @@ -162,7 +163,7 @@ func interact() -> void: func build_wall() -> void: if point and valid_point and hero.currency >= Data.wall_cost: hero.currency -= Data.wall_cost - Game.level.set_wall(point, multiplayer.get_unique_id()) + level.set_wall(point, multiplayer.get_unique_id()) wall_preview.visible = false @@ -171,7 +172,7 @@ func refund_wall(wall: TowerBase) -> void: return if wall.has_card: wall.remove_card() - Game.level.remove_wall(wall.point) + level.remove_wall(wall.point) func put_card_in_tower_base(tower_base: TowerBase) -> void: diff --git a/PCs/hero.gd b/PCs/hero.gd index adbef42..6c7bc76 100644 --- a/PCs/hero.gd +++ b/PCs/hero.gd @@ -35,6 +35,7 @@ signal ready_state_changed(state: bool) @export var swap_off_audio: AudioStreamPlayer @export var swap_on_audio: AudioStreamPlayer +var game_manager: GameManager var hovering_item: InteractButton = null var weapons_spawn_count: int = 0 #Used to prevent node name collisions for multiplayer var inventory_selected_index: int = 0 @@ -191,10 +192,10 @@ func _process(delta: float) -> void: camera.fov = Data.graphics.hfov * (1.0 / movement.zoom_factor) if Input.is_action_just_pressed("View Map"): - hud.maximise_minimap(Game.level) + hud.maximise_minimap() #Input.mouse_mode = Input.MOUSE_MODE_VISIBLE if Input.is_action_just_released("View Map"): - hud.minimize_minimap(self) + hud.minimize_minimap() #Input.mouse_mode = Input.MOUSE_MODE_CAPTURED check_left_hand_valid() @@ -222,6 +223,9 @@ func _unhandled_input(event: InputEvent) -> void: if event.is_action_pressed("Pause"): var menu: PauseMenu = pause_menu_scene.instantiate() as PauseMenu pause() + menu.game_manager = game_manager + menu.quit_to_desktop_pressed.connect(game_manager.quit_to_desktop) + menu.quit_to_main_menu_pressed.connect(game_manager.scene_switch_main_menu) menu.closed.connect(unpause) hud.add_child(menu) diff --git a/PCs/hud.gd b/PCs/hud.gd index 9483609..ef59043 100644 --- a/PCs/hud.gd +++ b/PCs/hud.gd @@ -12,7 +12,6 @@ var last_lives_count: int = 120 @export var minimap_viewport: SubViewport @export var fps_label: Label @export var hover_text: RichTextLabel -var minimap_anchor: Node3D var enemy_names: Array[String] @export var enemy_sprites: Array[TextureRect] @export var enemy_counts: Array[Label] @@ -25,6 +24,7 @@ var enemy_names: Array[String] @export var enemy_card_scene: PackedScene @export var new_energy_bar: EnergyBar +var map_anchor: Node3D var audio_guard: bool = false var cards: Array[EnemyCardUI] = [] @@ -131,7 +131,7 @@ func set_upcoming_wave(value: Dictionary) -> void: var wave: Dictionary = {} for key: String in value: var new_enemy: Enemy - for enemy: Enemy in Data.enemies: + for enemy: Enemy in player.game_manager.level.enemy_pool: if enemy.title == key: new_enemy = enemy wave[new_enemy] = value[key] @@ -169,8 +169,8 @@ func set_weapon_energy(value: int, energy_type: Data.EnergyType) -> void: audio_guard = false -func maximise_minimap(anchor: Node3D) -> void: - minimap_cam.anchor = anchor +func maximise_minimap() -> void: + minimap_cam.anchor = map_anchor minimap.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) minimap.offset_bottom = -40 minimap.offset_top = 40 @@ -182,8 +182,8 @@ func maximise_minimap(anchor: Node3D) -> void: currency_count.set_visible(false) -func minimize_minimap(anchor: Node3D) -> void: - minimap_cam.anchor = anchor +func minimize_minimap() -> void: + minimap_cam.anchor = player minimap.set_anchors_and_offsets_preset(Control.PRESET_TOP_RIGHT) minimap.offset_right = -40 minimap.offset_top = 40 diff --git a/Resources/Enemies/airenemy2.tres b/Resources/Enemies/airenemy2.tres index c33289c..58ff216 100644 --- a/Resources/Enemies/airenemy2.tres +++ b/Resources/Enemies/airenemy2.tres @@ -19,13 +19,13 @@ health = 120 penalty = 7 movement_speed = 1.0 spawn_cooldown = 1.0 -common_group = 3 +common_group = 5 common_cost = 2 -uncommon_group = 6 +uncommon_group = 10 uncommon_cost = 3 -rare_group = 10 +rare_group = 18 rare_cost = 4 -epic_group = 16 -epic_cost = 5 -legendary_group = 25 -legendary_cost = 6 +epic_group = 26 +epic_cost = 6 +legendary_group = 42 +legendary_cost = 8 diff --git a/Resources/Enemies/dog.tres b/Resources/Enemies/dog.tres index 3f8604e..ba89000 100644 --- a/Resources/Enemies/dog.tres +++ b/Resources/Enemies/dog.tres @@ -25,13 +25,13 @@ health = 180 penalty = 10 movement_speed = 1.2 spawn_cooldown = 1.2 -common_group = 4 +common_group = 8 common_cost = 1 -uncommon_group = 6 +uncommon_group = 12 uncommon_cost = 2 -rare_group = 8 +rare_group = 18 rare_cost = 3 -epic_group = 10 -epic_cost = 4 -legendary_group = 12 -legendary_cost = 5 +epic_group = 26 +epic_cost = 5 +legendary_group = 34 +legendary_cost = 6 diff --git a/Scenes/CardPrinter/card_printer.gd b/Scenes/CardPrinter/card_printer.gd index 93e4716..ccef37f 100644 --- a/Scenes/CardPrinter/card_printer.gd +++ b/Scenes/CardPrinter/card_printer.gd @@ -22,7 +22,7 @@ func generate_rarity() -> int: for rarity: String in Data.Rarity: weight_total += Data.rarity_weights[rarity] - var generated_rarity: int = Game.randi_in_range(4 * cards_generated, 0, weight_total) + var generated_rarity: int = NoiseRandom.randi_in_range(4 * cards_generated, 0, weight_total) cards_generated += 1 var decided_rarity: int = 0 @@ -53,7 +53,7 @@ func randomize_cards(faction: Card.Faction) -> void: decided_rarity -= 1 var card: Card if card_array.size() > 0: - card = card_array[Game.randi_in_range(132 * cards_generated, 0, card_array.size() - 1)] + card = card_array[NoiseRandom.randi_in_range(132 * cards_generated, 0, card_array.size() - 1)] cards_generated += 1 card_array.erase(card) var item: CardItem = reply_player.hero_class.card_item.instantiate() as CardItem diff --git a/Scenes/Menus/GameEndScreen/game_end_screen.gd b/Scenes/Menus/GameEndScreen/game_end_screen.gd index 2a86bc5..dd7e0c2 100644 --- a/Scenes/Menus/GameEndScreen/game_end_screen.gd +++ b/Scenes/Menus/GameEndScreen/game_end_screen.gd @@ -9,18 +9,20 @@ class_name GameEndScreen extends PanelContainer @export var total_losses_label: Label @export var undefeated_enemies: VBoxContainer +var game_manager: GameManager + func _ready() -> void: winrate_label.text = "Your 20-game winrate is now: " + str(Data.save_data.winrate) + "%!" total_games_label.text = "Total games: " + str(Data.save_data.wins + Data.save_data.losses) total_wins_label.text = "Total wins: " + str(Data.save_data.wins) total_losses_label.text = "Total losses: " + str(Data.save_data.losses) - for wave_key: int in Game.stats.enemies_undefeated: + for wave_key: int in game_manager.stats.enemies_undefeated: var spawned_box: EnemyBox = box.instantiate() as EnemyBox undefeated_enemies.add_child(spawned_box) spawned_box.set_wave(wave_key) - for enemy_key: Enemy in Game.stats.enemies_undefeated[wave_key]: - spawned_box.add_enemy_tag(enemy_key, Game.stats.enemies_undefeated[wave_key][enemy_key]) + for enemy_key: Enemy in game_manager.stats.enemies_undefeated[wave_key]: + spawned_box.add_enemy_tag(enemy_key, game_manager.stats.enemies_undefeated[wave_key][enemy_key]) func set_outcome_message(message: String) -> void: @@ -28,15 +30,15 @@ func set_outcome_message(message: String) -> void: func _on_quit_button_pressed() -> void: - Game.scene_switch_main_menu() + game_manager.scene_switch_main_menu() queue_free() func _on_play_button_pressed() -> void: - if Game.gamemode.daily == false and !Game.gamemode.seeded: - Game.gamemode.rng_seed = randi() - Game.setup() - Game.start() + if game_manager.gamemode.daily == false and !game_manager.gamemode.seeded: + game_manager.gamemode.rng_seed = randi() + game_manager.setup() + game_manager.start() queue_free() diff --git a/Scenes/Menus/MainMenu/main_menu.gd b/Scenes/Menus/MainMenu/main_menu.gd index c488841..9e05e56 100644 --- a/Scenes/Menus/MainMenu/main_menu.gd +++ b/Scenes/Menus/MainMenu/main_menu.gd @@ -1,5 +1,8 @@ class_name MainMenu extends Control +signal singleplayer_game_requested +signal multiplayer_game_requested + @export var bg_level: Level @export var game_select_menu: Control @export var main_controls: Control @@ -7,6 +10,7 @@ class_name MainMenu extends Control @export var profile_controls: Control @export var mods_controls: ModMenu +var game: GameManager var gamemode: GameMode = GameMode.new() var confirmation_popup_scene: PackedScene = preload("res://Scenes/Menus/confirmation_popup.tscn") @@ -24,7 +28,7 @@ func _ready() -> void: #bg_level.a_star_graph_3d.build_random_maze(70) #bg_level.a_star_graph_3d.place_random_towers(30) #bg_level.a_star_graph_3d.disable_all_tower_frames() - Game.level = bg_level + #Game.level = bg_level #WaveManager.generate_wave(WaveManager.calculate_spawn_power(50, 4), bg_level.enemy_pool, bg_level.enemy_spawns) #for spawn: EnemySpawner in bg_level.enemy_spawns: # spawn.enemy_died_callback = enemy_died @@ -67,6 +71,7 @@ func quit_game(confirmation: bool) -> void: func _on_options_button_pressed() -> void: var menu: OptionsMenu = options_menu_scene.instantiate() + menu.game_manager = game add_child(menu) @@ -75,12 +80,11 @@ func _on_button_mouse_entered() -> void: func start_game() -> void: - Game.level = null - Game.gamemode = gamemode - if gamemode.multiplayer: - Game.scene_switch_to_multiplayer_lobby() + game.gamemode = gamemode + if !gamemode.multiplayer: + singleplayer_game_requested.emit() else: - Game.scene_switch_to_singleplayer_lobby() + multiplayer_game_requested.emit() func _on_play_button_pressed() -> void: @@ -96,7 +100,7 @@ func _on_multiplayer_button_pressed() -> void: func open_game_menu() -> void: main_controls.visible = false game_select_menu.visible = true - + func _on_back_button_pressed() -> void: main_controls.visible = true diff --git a/Scenes/Menus/PauseMenu/pause_menu.gd b/Scenes/Menus/PauseMenu/pause_menu.gd index eea1b3e..3a5742f 100644 --- a/Scenes/Menus/PauseMenu/pause_menu.gd +++ b/Scenes/Menus/PauseMenu/pause_menu.gd @@ -1,9 +1,12 @@ class_name PauseMenu extends Control -signal closed() +signal closed +signal quit_to_main_menu_pressed +signal quit_to_desktop_pressed var options_menu_scene: PackedScene = preload("res://Scenes/Menus/options_menu.tscn") var confirmation_popup_scene: PackedScene = preload("res://Scenes/Menus/confirmation_popup.tscn") +var game_manager: GameManager func _unhandled_input(event: InputEvent) -> void: @@ -19,6 +22,7 @@ func _on_resume_pressed() -> void: func _on_options_pressed() -> void: var menu: OptionsMenu = options_menu_scene.instantiate() + menu.game_manager = game_manager add_child(menu) @@ -31,7 +35,7 @@ func _on_quit_to_main_menu_pressed() -> void: func return_to_menu(confirmation: bool) -> void: if confirmation: - Game.scene_switch_main_menu() + quit_to_main_menu_pressed.emit() func _on_quit_to_desktop_pressed() -> void: @@ -43,7 +47,7 @@ func _on_quit_to_desktop_pressed() -> void: func quit_game(confirmation: bool) -> void: if confirmation: - Game.quit_to_desktop() + quit_to_desktop_pressed.emit() func _on_button_mouse_entered() -> void: diff --git a/Scenes/ShopStand/shop_stand.gd b/Scenes/ShopStand/shop_stand.gd index 8054ee6..b2ba21d 100644 --- a/Scenes/ShopStand/shop_stand.gd +++ b/Scenes/ShopStand/shop_stand.gd @@ -42,7 +42,7 @@ func randomize_cards() -> void: var chosen_card: Card = null for x: int in 3: if cheap_cards.size() > 0: - chosen_card = cheap_cards[Game.randi_in_range(12 * cards_generated, 0, cheap_cards.size() - 1)] + chosen_card = cheap_cards[NoiseRandom.randi_in_range(12 * cards_generated, 0, cheap_cards.size() - 1)] cards_generated += 1 if chosen_card != null: cards[x].set_card(chosen_card) @@ -53,9 +53,9 @@ func randomize_cards() -> void: Data.save_data.saw_mage_card_in_shop() for x: int in 2: if medium_cards.size() > 0: - chosen_card = medium_cards[Game.randi_in_range(9 * cards_generated, 0, medium_cards.size() - 1)] + chosen_card = medium_cards[NoiseRandom.randi_in_range(9 * cards_generated, 0, medium_cards.size() - 1)] elif cheap_cards.size() > 0: - chosen_card = cheap_cards[Game.randi_in_range(9 * cards_generated, 0, cheap_cards.size() - 1)] + chosen_card = cheap_cards[NoiseRandom.randi_in_range(9 * cards_generated, 0, cheap_cards.size() - 1)] cards_generated += 1 if chosen_card != null: cards[x+3].set_card(chosen_card) @@ -66,11 +66,11 @@ func randomize_cards() -> void: Data.save_data.saw_mage_card_in_shop() for x: int in 1: if pricey_cards.size() > 0: - chosen_card = pricey_cards[Game.randi_in_range(50 * cards_generated, 0, pricey_cards.size() - 1)] + chosen_card = pricey_cards[NoiseRandom.randi_in_range(50 * cards_generated, 0, pricey_cards.size() - 1)] elif medium_cards.size() > 0: - chosen_card = medium_cards[Game.randi_in_range(50 * cards_generated, 0, medium_cards.size() - 1)] + chosen_card = medium_cards[NoiseRandom.randi_in_range(50 * cards_generated, 0, medium_cards.size() - 1)] elif cheap_cards.size() > 0: - chosen_card = cheap_cards[Game.randi_in_range(50 * cards_generated, 0, cheap_cards.size() - 1)] + chosen_card = cheap_cards[NoiseRandom.randi_in_range(50 * cards_generated, 0, cheap_cards.size() - 1)] cards_generated += 1 if chosen_card != null: cards[x+5].set_card(chosen_card) diff --git a/Scenes/TowerBase/tower_base.gd b/Scenes/TowerBase/tower_base.gd index c3b6a56..5a5fef9 100644 --- a/Scenes/TowerBase/tower_base.gd +++ b/Scenes/TowerBase/tower_base.gd @@ -5,6 +5,7 @@ class_name TowerBase extends StaticBody3D @export var collider: CollisionShape3D @export var minimap_icon: Sprite3D +var game_manager: GameManager var owner_id: int var point: FlowNode var tower: Tower = null @@ -51,8 +52,8 @@ func networked_spawn_tower(card_index: int, caller_id: int) -> void: @rpc("reliable", "call_local", "any_peer") func networked_remove_tower() -> void: - Game.connected_players_nodes[tower.owner_id].add_card(inventory.remove_at(0)) - Game.connected_players_nodes[tower.owner_id].unready_self() + game_manager.connected_players_nodes[tower.owner_id].add_card(inventory.remove_at(0)) + game_manager.connected_players_nodes[tower.owner_id].unready_self() tower.queue_free() tower = null minimap_icon.modulate = Color.GREEN diff --git a/Scripts/EnemyAI/enemy_movement.gd b/Scripts/EnemyAI/enemy_movement.gd index b15029b..3bcbff4 100644 --- a/Scripts/EnemyAI/enemy_movement.gd +++ b/Scripts/EnemyAI/enemy_movement.gd @@ -2,7 +2,6 @@ class_name EnemyMovement extends Node @export var character: EnemyController -var astar: AStarGraph3D var distance_remaining: float = 0.0 var speed: float = 0.0 diff --git a/Scripts/a_star_graph_3d.gd b/Scripts/a_star_graph_3d.gd deleted file mode 100644 index 535f9f6..0000000 --- a/Scripts/a_star_graph_3d.gd +++ /dev/null @@ -1,266 +0,0 @@ -class_name AStarGraph3D extends Node3D - -@export var grid_size: Vector2i = Vector2i(15, 7) -@export var point_gap: float = 2.0 -var non_build_locations: Array = [] -var astar: AStar3D = AStar3D.new() - -#TODO generalize this better -@export var end: Node3D -@export var spawners: Array[EnemySpawner] -@export var tower_path: Node -var tower_base_scene: PackedScene = load("res://Scenes/TowerBase/tower_base.tscn") -var tower_frame_scene: PackedScene = load("res://Scenes/tower_frame.tscn") -var tower_bases: Array = [] -var tower_base_ids: Dictionary = {} -var tower_frames: Array = [] -var wall_id: int = 0 - - -func _ready() -> void: - for spawner: EnemySpawner in spawners: - spawner.astar = self - - -func toggle_point(point_id: int, caller_id: int) -> void: - networked_toggle_point.rpc(point_id, caller_id) - - -func remove_wall(wall: TowerBase) -> void: - networked_remove_wall.rpc(wall.point_id) - toggle_point(wall.point_id, multiplayer.get_unique_id()) - - -func point_is_build_location(point_id: int) -> bool: - return !non_build_locations.has(point_id) - - -func test_path_if_point_toggled(point_id: int) -> bool: - if astar.is_point_disabled(point_id): - astar.set_point_disabled(point_id, false) - else: - astar.set_point_disabled(point_id, true) - var result: bool = find_path() - if astar.is_point_disabled(point_id): - astar.set_point_disabled(point_id, false) - else: - astar.set_point_disabled(point_id, true) - return result - - -@rpc("reliable", "any_peer", "call_local") -func networked_toggle_point(point_id: int, caller_id: int) -> void: - if astar.is_point_disabled(point_id): - astar.set_point_disabled(point_id, false) - else: - astar.set_point_disabled(point_id, true) - find_path() - enable_non_path_tower_frames() - if is_multiplayer_authority() and astar.is_point_disabled(point_id): - networked_spawn_wall.rpc(astar.get_point_position(point_id), wall_id, caller_id) - wall_id += 1 - - -func get_north_point(point_id: int) -> int: - var x: int = floori(float(point_id) / float(grid_size.y)) - var y: int = point_id % grid_size.y - if x - 1 >= 0: #if the north point id could possibly exist as a neighbor - return (x - 1) * grid_size.y + y - return -1 - - -func get_south_point(point_id: int) -> int: - var x: int = floori(float(point_id) / float(grid_size.y)) - var y: int = point_id % grid_size.y - if x + 1 <= grid_size.x - 1: #if the south point id could possibly exist as a neighbor - return (x + 1) * grid_size.y + y - return -1 - - -func get_west_point(point_id: int) -> int: - var x: int = floori(float(point_id) / float(grid_size.y)) - var y: int = point_id % grid_size.y - if y + 1 <= grid_size.y - 1: #if the east point id could possibly exist as a neighbor - return x * grid_size.y + y + 1 - return -1 - - -func get_east_point(point_id: int) -> int: - var x: int = floori(float(point_id) / float(grid_size.y)) - var y: int = point_id % grid_size.y - if y - 1 >= 0: #if the west point id could possibly exist as a neighbor - return x * grid_size.y + y - 1 - return -1 - - -func count_valid_neighbours(point_id: int) -> int: - if !point_id: - return 0 - var valid_neighbours: int = 0 - var north_point: int = get_north_point(point_id) - var south_point: int = get_south_point(point_id) - var east_point: int = get_east_point(point_id) - var west_point: int = get_west_point(point_id) - - if north_point and !astar.is_point_disabled(north_point): - valid_neighbours += 1 - else: #add the spawn point which is always valid - valid_neighbours += 1 - - if south_point and !astar.is_point_disabled(south_point): - valid_neighbours += 1 - else: #add the goal point which is always valid - valid_neighbours += 1 - - if east_point and !astar.is_point_disabled(east_point): - valid_neighbours += 1 - - if west_point and !astar.is_point_disabled(west_point): - valid_neighbours += 1 - return valid_neighbours - - -func disable_all_tower_frames() -> void: - for frame: Node3D in tower_frames: - frame.set_visible(false) - - -func enable_non_path_tower_frames() -> void: - for frame: Node3D in tower_frames: - if !astar.is_point_disabled(tower_frames.find(frame)): - frame.set_visible(true) - disable_path_tower_frames() - - -func disable_path_tower_frames() -> void: - for id: int in astar.get_id_path(astar.get_point_count() - 2, astar.get_point_count() - 1): - if id < (grid_size.x * grid_size.y) and !test_path_if_point_toggled(id): - tower_frames[id].set_visible(false) - - -@rpc("reliable", "call_local") -func networked_spawn_wall(pos: Vector3, name_id: int, caller_id: int) -> void: - var base: TowerBase = tower_base_scene.instantiate() as TowerBase - base.position = pos - base.name = "Wall" + str(name_id) - base.owner_id = caller_id - var point_id: int = astar.get_closest_point(pos, true) - base.point_id = point_id - tower_base_ids[point_id] = base - tower_bases.append(base) - tower_path.add_child(base) - var north_point: int = get_north_point(point_id) - var south_point: int = get_south_point(point_id) - var east_point: int = get_east_point(point_id) - var west_point: int = get_west_point(point_id) - if north_point >= 0 and tower_base_ids.has(north_point) and astar.is_point_disabled(north_point): - base.set_north_wall(true) - tower_base_ids[north_point].set_south_wall(true) - if south_point >= 0 and tower_base_ids.has(south_point) and astar.is_point_disabled(south_point): - base.set_south_wall(true) - tower_base_ids[south_point].set_north_wall(true) - if east_point >= 0 and tower_base_ids.has(east_point) and astar.is_point_disabled(east_point): - base.set_east_wall(true) - tower_base_ids[east_point].set_west_wall(true) - if west_point >= 0 and tower_base_ids.has(west_point) and astar.is_point_disabled(west_point): - base.set_west_wall(true) - tower_base_ids[west_point].set_east_wall(true) - - -@rpc("reliable", "call_local", "any_peer") -func networked_remove_wall(new_wall_id: int) -> void: - var wall: TowerBase = tower_base_ids[new_wall_id] - Game.connected_players_nodes[wall.owner_id].currency += Data.wall_cost - Game.connected_players_nodes[wall.owner_id].unready_self() - tower_bases.erase(wall) - tower_base_ids.erase(new_wall_id) - wall.queue_free() - var north_point: int = get_north_point(new_wall_id) - var south_point: int = get_south_point(new_wall_id) - var east_point: int = get_east_point(new_wall_id) - var west_point: int = get_west_point(new_wall_id) - if north_point >= 0 and tower_base_ids.has(north_point) and astar.is_point_disabled(north_point): - tower_base_ids[north_point].set_south_wall(false) - if south_point >= 0 and tower_base_ids.has(south_point) and astar.is_point_disabled(south_point): - tower_base_ids[south_point].set_north_wall(false) - if east_point >= 0 and tower_base_ids.has(east_point) and astar.is_point_disabled(east_point): - tower_base_ids[east_point].set_west_wall(false) - if west_point >= 0 and tower_base_ids.has(west_point) and astar.is_point_disabled(west_point): - tower_base_ids[west_point].set_east_wall(false) - - -func build_random_maze(block_limit: int) -> void: - var untested_point_ids: Array = [] - for index: int in (grid_size.x * grid_size.y): - untested_point_ids.append(index) - if block_limit <= 0 or block_limit > untested_point_ids.size(): - block_limit = untested_point_ids.size() - for index: int in block_limit: - var random_point: int = untested_point_ids.pick_random() - untested_point_ids.erase(random_point) - if test_path_if_point_toggled(random_point): - networked_toggle_point.rpc(random_point, multiplayer.get_unique_id()) - - -func place_random_towers(tower_limit: int) -> void: - var untowered_bases: Array = tower_bases.duplicate() - if tower_limit <= 0 or tower_limit > untowered_bases.size(): - tower_limit = untowered_bases.size() - for index: int in tower_limit: - var random_base: TowerBase = untowered_bases.pick_random() as TowerBase - untowered_bases.erase(random_base) - random_base.add_card(Data.cards.pick_random(), multiplayer.get_unique_id()) - - -func find_path() -> bool: - for spawn: EnemySpawner in spawners: - var path: PackedVector3Array = astar.get_point_path(spawn.astar_point_id, astar.get_point_count() - 1) - if !path.is_empty(): - var curve: Curve3D = Curve3D.new() - for point: Vector3 in path: - curve.add_point(point) - spawn.path.global_position = Vector3.ZERO - spawn.path.curve = curve - else: - return false - spawners[0].path.spawn_visualizer_points() - return true - - -func make_grid() -> void: - for x: int in grid_size.x: - for y: int in grid_size.y: - var point_position: Vector3 = Vector3((x - floori(grid_size.x / 2.0)) * point_gap, 0, (y - floori(grid_size.y / 2.0)) * point_gap) - point_position += global_position - astar.add_point(int(x * grid_size.y + y), point_position) - var frame: Node3D = tower_frame_scene.instantiate() - tower_frames.append(frame) - add_child(frame) - frame.global_position = point_position - - for x: int in grid_size.x: - for y: int in grid_size.y: - var point_id: int = grid_size.y * x + y - if x > 0: - var north_point_id: int = grid_size.y * (x - 1) + y - astar.connect_points(point_id, north_point_id, false) - if x < grid_size.x - 1: - var south_point_id: int = grid_size.y * (x + 1) + y - astar.connect_points(point_id, south_point_id, false) - if y > 0: - var east_point_id: int = grid_size.y * x + (y - 1) - astar.connect_points(point_id, east_point_id, false) - if y < grid_size.y - 1: - var west_point_id: int = grid_size.y * x + (y + 1) - astar.connect_points(point_id, west_point_id, false) - - for spawn: EnemySpawner in spawners: - non_build_locations.append(astar.get_point_count()) - spawn.astar_point_id = astar.get_point_count() - astar.add_point(astar.get_point_count(), spawn.global_position) - for x: int in grid_size.y: - astar.connect_points(int(astar.get_point_count() - 1), x) - non_build_locations.append(astar.get_point_count()) - astar.add_point(astar.get_point_count(), end.global_position) - for x: int in grid_size.y: - astar.connect_points(astar.get_point_count() - 1, int(grid_size.y * (grid_size.x - 1) + x)) diff --git a/Scripts/a_star_graph_3d.gd.uid b/Scripts/a_star_graph_3d.gd.uid deleted file mode 100644 index 58a6553..0000000 --- a/Scripts/a_star_graph_3d.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://u404brdoaku diff --git a/Scripts/chatbox.gd b/Scripts/chatbox.gd index b8b58ca..a6081d8 100644 --- a/Scripts/chatbox.gd +++ b/Scripts/chatbox.gd @@ -13,7 +13,8 @@ var username: String = "default" var color: Color = Color.TOMATO var fading: bool = true var time_to_fade: float = 2.0 -var time_since_started_fading:float = 2.0 +var time_since_started_fading: float = 2.0 +var game_manager: GameManager func _process(delta: float) -> void: @@ -43,7 +44,7 @@ func _input(event: InputEvent) -> void: text_selected = false if input_line.text.length() != 0: if input_line.text.begins_with("/"): - Game.parse_command(input_line.text, multiplayer.get_unique_id()) + game_manager.parse_command(input_line.text, multiplayer.get_unique_id()) else: append_message.rpc(username, color, input_line.text) input_line.clear() diff --git a/Scripts/data.gd b/Scripts/data.gd index cc3d987..205f6fa 100644 --- a/Scripts/data.gd +++ b/Scripts/data.gd @@ -2,7 +2,6 @@ extends Node var characters: Array[HeroClass] var cards: Array[Card] -var enemies: Array[Enemy] #var keymaps: Array[PlayerKeymap] var mods: Dictionary[String, String] var graphics: PlayerGraphicsSettings @@ -13,14 +12,14 @@ var save_data: SaveData var keymap_data: KeymapData const DEFAULT_SERVER_PORT: int = 58008 - -var wall_cost: int = 1 -var printer_cost: int = 15 enum EnergyType {UNDEFINED = 0, DISCRETE = 1, CONTINUOUS = 2} enum TargetType {UNDEFINED = 0, LAND = 1, AIR = 2, BOTH = 3} enum EnemyType {UNDEFINED = 0, LAND = 1, AIR = 2} enum Rarity {COMMON = 0, UNCOMMON = 1, RARE = 2, EPIC = 3, LEGENDARY = 4} -var rarity_weights: Dictionary = { + +static var wall_cost: int = 1 +static var printer_cost: int = 15 +static var rarity_weights: Dictionary = { "COMMON" = 50, "UNCOMMON" = 30, "RARE" = 10, @@ -114,11 +113,3 @@ func _ready() -> void: load_classes() load_cards("res://Cards") - - enemies.append(preload("res://Resources/Enemies/dog.tres")) - enemies.append(preload("res://Resources/Enemies/dog_fast.tres")) - enemies.append(preload("res://Resources/Enemies/dog_heavy.tres")) - enemies.append(preload("res://Resources/Enemies/dog_boss.tres")) - enemies.append(preload("res://Resources/Enemies/airenemy.tres")) - enemies.append(preload("res://Resources/Enemies/airenemy2.tres")) - enemies.append(preload("res://Resources/Enemies/leapfrog.tres")) diff --git a/Scripts/enemy_spawner.gd b/Scripts/enemy_spawner.gd index c8b45b8..60b0bdb 100644 --- a/Scripts/enemy_spawner.gd +++ b/Scripts/enemy_spawner.gd @@ -6,14 +6,12 @@ signal enemy_spawned() @export var leap_enemy_scene: PackedScene @export var air_enemy_scene: PackedScene @export var path: VisualizedPath -var astar: AStarGraph3D @export var flow_field: FlowField @export var own_id: int = 0 @export var type: Data.EnemyType @export var dest: Node3D @export var enemy_path: Node -var astar_point_id: int = 0 var enemy_died_callback: Callable var enemy_reached_goal_callback: Callable var current_wave: Array[EnemyCard] @@ -25,6 +23,7 @@ var done_spawning: bool = true var enemy_id: int = 0 var new_path: Path3D var path_polygon: PackedScene = preload("res://path_polygon.tscn") +var game_manager: GameManager func _ready() -> void: @@ -63,11 +62,12 @@ func _process(delta: float) -> void: @rpc("reliable", "call_local") func networked_spawn_land_enemy(enemy_stats: String, id1: int, id2: int) -> void: var e_stats: Enemy = null - for enemy: Enemy in Data.enemies: + for enemy: Enemy in game_manager.level.enemy_pool: if enemy.title == enemy_stats: e_stats = enemy var enemy: EnemyController enemy = e_stats.scene.instantiate() + enemy.corpse_root = game_manager.level.corpses enemy.name = str(id1) + str(id2) enemy.stats = e_stats enemy.died.connect(enemy_died_callback) @@ -110,11 +110,12 @@ func update_path() -> void: @rpc("reliable", "call_local") func networked_spawn_air_enemy(enemy_stats: String, pos: Vector3, id1: int, id2: int) -> void: var e_stats: Enemy = null - for enemy: Enemy in Data.enemies: + for enemy: Enemy in game_manager.level.enemy_pool: if enemy.title == enemy_stats: e_stats = enemy var enemy: EnemyController enemy = e_stats.scene.instantiate() + enemy.corpse_root = game_manager.level.corpses enemy.name = str(id1) + str(id2) enemy.position = pos + global_position enemy.stats = e_stats diff --git a/Scripts/game.gd b/Scripts/game.gd index 36750fe..2f2b4bd 100644 --- a/Scripts/game.gd +++ b/Scripts/game.gd @@ -1,13 +1,14 @@ +class_name GameManager extends Node signal wave_started(wave_number: int) signal wave_finished(wave_number: int) signal base_took_damage(remaining_health: int) -signal rng_seeded signal game_setup signal game_started signal lost_game signal won_game +signal rng_seeded signal switch_to_single_player signal switch_to_multi_player signal switch_to_main_menu @@ -29,7 +30,7 @@ var wave_limit: int = 20 var starting_cash: int = 25 var shop_chance: float = 0.0 var stats: RoundStats -var rng: FastNoiseLite + #TODO: Create a reference to some generic Lobby object that wraps the multiplayer players list stuff var connected_player_profiles: Dictionary = {} @@ -52,25 +53,6 @@ func _ready() -> void: Input.set_custom_mouse_cursor(load("res://Assets/Textures/bracket_b_vertical.png"), Input.CURSOR_IBEAM, Vector2(16, 16)) -@rpc("reliable", "call_local") -func set_seed(value: int) -> void: - rng = FastNoiseLite.new() - rng.noise_type = FastNoiseLite.TYPE_VALUE - rng.frequency = 30 - rng.fractal_octaves = 2 - rng.fractal_gain = 0.1 - rng.seed = value - rng_seeded.emit() - - -func randi_in_range(sample: float, output_start: int, output_end: int) -> int: - return floori(remap(rng.get_noise_1d(sample), -1.0, 1.0, float(output_start), float(output_end + 1))) - - -func randf_in_range(sample: float, output_start: float, output_end: float) -> float: - return remap(rng.get_noise_1d(sample), -1.0, 1.0, output_start, output_end) - - func parse_command(text: String, peer_id: int) -> void: if text.substr(1, 4) == "give": var gift_name: String = text.substr(6) as String @@ -110,7 +92,7 @@ func parse_command(text: String, peer_id: int) -> void: else: chatbox.append_message("SERVER", Color.TOMATO, "Unable to set wave") elif text.substr(1, 4) == "seed": - chatbox.append_message("SERVER", Color.TOMATO, str(rng.seed)) + chatbox.append_message("SERVER", Color.TOMATO, str(NoiseRandom.noise.seed)) # if text.substr(1, 17) == "show tower ranges": # pass # if text.substr(1, 20) = "show gauntlet ranges": @@ -128,8 +110,10 @@ func networked_set_wave(wave_number: int) -> void: func spawn_level() -> void: level = level_scene.instantiate() as Level + level.game_manager = self for x: EnemySpawner in level.enemy_spawns: #x.path = level.a_star_graph_3d.visualized_path + x.game_manager = self x.enemy_died_callback = enemy_died x.enemy_reached_goal_callback = damage_goal x.enemy_spawned.connect(increase_enemy_count) @@ -143,6 +127,9 @@ func spawn_players() -> void: for peer_id: int in player_array: var player: Hero = player_scene.instantiate() as Hero player.name = str(peer_id) + player.game_manager = self + player.edit_tool.level = level + player.hud.map_anchor = level player.player_name_tag.text = connected_player_profiles[peer_id].display_name player.position = level.player_spawns[p_i].global_position player.profile = connected_player_profiles[peer_id] @@ -264,7 +251,7 @@ func end_wave() -> void: #level.a_star_graph_3d.enable_non_path_tower_frames() level.enable_non_path_tower_frames() if is_multiplayer_authority(): - if randf_in_range(23 * wave, 0.0, 1.0) <= shop_chance: + if NoiseRandom.randf_in_range(23 * wave, 0.0, 1.0) <= shop_chance: networked_spawn_shop.rpc() shop_chance = 0.0 else: @@ -305,6 +292,12 @@ func setup() -> void: game_setup.emit() +@rpc("reliable", "call_local") +func set_seed(value: int) -> void: + NoiseRandom.set_seed(value) + rng_seeded.emit() + + func start() -> void: if is_multiplayer_authority(): set_seed.rpc(gamemode.rng_seed) @@ -329,7 +322,7 @@ func start() -> void: #Start game game_active = true - chatbox.append_message("SERVER", Color.TOMATO, "Started with seed: " + str(rng.seed)) + chatbox.append_message("SERVER", Color.TOMATO, "Started with seed: " + str(NoiseRandom.noise.seed)) game_started.emit() #print("started game with seed: " + str(gamemode.rng_seed)) @@ -341,6 +334,7 @@ func end(outcome: bool) -> void: Data.save_data.add_game_outcome(outcome) Data.save_data.save_to_disc() var menu: GameEndScreen = game_end_scene.instantiate() as GameEndScreen + menu.game_manager = self match outcome: false: menu.set_outcome_message("You lost...") diff --git a/Scripts/keybind_options.gd b/Scripts/keybind_options.gd index 37e4eb9..fd4f65c 100644 --- a/Scripts/keybind_options.gd +++ b/Scripts/keybind_options.gd @@ -7,6 +7,7 @@ var keybind_boxes: Array[KeybindEntry] = [] var key_event: InputEvent var selected_entry: KeybindEntry var listening_for_key: bool = false +var ui_layer: CanvasLayer func _ready() -> void: @@ -44,7 +45,7 @@ func load_keybind_labels() -> void: func _on_keybind_button_pressed(button: Button, keybind_entry: KeybindEntry) -> void: var popup: KeybindPopup = keybind_popup.instantiate() popup.event_detected.connect(keybind_entry.set_button_bind.bind(button)) - Game.UILayer.add_child(popup) + ui_layer.add_child(popup) func save() -> void: diff --git a/Scripts/level.gd b/Scripts/level.gd index 15d158b..845bc0c 100644 --- a/Scripts/level.gd +++ b/Scripts/level.gd @@ -16,6 +16,7 @@ var wall_id: int = 0 var tower_base_scene: PackedScene = load("res://Scenes/TowerBase/tower_base.tscn") var tower_frame_scene: PackedScene = load("res://Scenes/tower_frame.tscn") var tower_frames: Dictionary[FlowNode, Node3D] = {} +var game_manager: GameManager func _ready() -> void: @@ -56,8 +57,8 @@ func set_wall(point: FlowNode, caller_id: int) -> void: func remove_wall(point: FlowNode) -> void: var wall: TowerBase = walls[point] - Game.connected_players_nodes[wall.owner_id].currency += Data.wall_cost - Game.connected_players_nodes[wall.owner_id].unready_self() + game_manager.connected_players_nodes[wall.owner_id].currency += Data.wall_cost + game_manager.connected_players_nodes[wall.owner_id].unready_self() walls.erase(point) wall.queue_free() point.traversable = true @@ -68,6 +69,7 @@ func remove_wall(point: FlowNode) -> void: func spawn_wall(point: FlowNode, name_id: int, caller_id: int) -> void: var base: TowerBase = tower_base_scene.instantiate() as TowerBase + base.game_manager = game_manager base.position = point.global_position base.name = "Wall" + str(name_id) base.owner_id = caller_id @@ -79,7 +81,7 @@ func spawn_wall(point: FlowNode, name_id: int, caller_id: int) -> void: func generate_obstacles() -> void: #print(str(multiplayer.get_unique_id()) + " spawning obstacles with seed: " + str(Game.rng.seed)) - var obstacle_count: int = Game.randi_in_range(1, 0, 5) + var obstacle_count: int = NoiseRandom.randi_in_range(1, 0, 5) obstacle_count = 0 # for index: int in obstacle_count: # #var x: int = Game.randi_in_range(10 * index, 1 - a_star_graph_3d.grid_size.x, a_star_graph_3d.grid_size.x - 1) diff --git a/Scripts/lobby.gd b/Scripts/lobby.gd index 26d38cf..4ff4714 100644 --- a/Scripts/lobby.gd +++ b/Scripts/lobby.gd @@ -6,6 +6,7 @@ class_name Lobby extends Control #@export var ready_button: Button @export var audio_player: AudioStreamPlayer +var game_manager: GameManager var gamemode: GameMode = null var loadout_editor: CharacterSelect = null var connected_players_profiles: Dictionary = {} @@ -16,16 +17,17 @@ func setup_the_ui() -> void: #scoreboard.set_visible(true) loadout_editor.set_visible(true) chatbox.set_visible(true) + chatbox.game_manager = game_manager #ready_button.set_visible(true) func start_game() -> void: - Game.setup() + game_manager.setup() #scoreboard.set_visible(false) loadout_editor.queue_free() #ready_button.set_visible(false) - Game.connected_player_profiles = connected_players_profiles - Game.start() + game_manager.connected_player_profiles = connected_players_profiles + game_manager.start() func _on_button_mouse_entered() -> void: diff --git a/Scripts/multiplayer_lobby.gd b/Scripts/multiplayer_lobby.gd index 21c2075..eafe26d 100644 --- a/Scripts/multiplayer_lobby.gd +++ b/Scripts/multiplayer_lobby.gd @@ -53,9 +53,9 @@ func create_server() -> void: func setup_game(peer_id: int) -> void: loadout_editor = character_select_screen.instantiate() as CharacterSelect add_child(loadout_editor) - player_disconnected.connect(Game.remove_player) - scoreboard.all_players_ready.connect(start_game) - Game.chatbox = chatbox + player_disconnected.connect(game_manager.remove_player) + #scoreboard.all_players_ready.connect(start_game) + game_manager.chatbox = chatbox chatbox.username = Data.player_profile.display_name Data.player_profile.display_name_changed.connect(chatbox.change_username) loadout_editor.hero_selected.connect(Data.player_profile.set_preferred_class) @@ -72,7 +72,7 @@ func connect_to_server() -> void: func ready_player() -> void: var peer_id: int = multiplayer.get_unique_id() - networked_ready_player.rpc(peer_id) + #networked_ready_player.rpc(peer_id) func start_game() -> void: @@ -102,6 +102,6 @@ func add_player(new_player_profile_dict: Dictionary) -> void: player_connected.emit(new_player_peer_id, new_player_profile) -@rpc("any_peer", "reliable", "call_local") -func networked_ready_player(peer_id: int) -> void: - scoreboard.set_player_ready_state(peer_id, true) +#@rpc("any_peer", "reliable", "call_local") +#func networked_ready_player(peer_id: int) -> void: + #scoreboard.set_player_ready_state(peer_id, true) diff --git a/Scripts/noise_random.gd b/Scripts/noise_random.gd new file mode 100644 index 0000000..cf1d525 --- /dev/null +++ b/Scripts/noise_random.gd @@ -0,0 +1,21 @@ +class_name NoiseRandom +extends Object + +static var noise: FastNoiseLite + + +static func set_seed(value: int) -> void: + noise = FastNoiseLite.new() + noise.noise_type = FastNoiseLite.TYPE_VALUE + noise.frequency = 30 + noise.fractal_octaves = 2 + noise.fractal_gain = 0.1 + noise.seed = value + + +static func randi_in_range(sample: float, output_start: int, output_end: int) -> int: + return floori(remap(noise.get_noise_1d(sample), -1.0, 1.0, float(output_start), float(output_end + 1))) + + +static func randf_in_range(sample: float, output_start: float, output_end: float) -> float: + return remap(noise.get_noise_1d(sample), -1.0, 1.0, output_start, output_end) diff --git a/Scripts/noise_random.gd.uid b/Scripts/noise_random.gd.uid new file mode 100644 index 0000000..ba2358f --- /dev/null +++ b/Scripts/noise_random.gd.uid @@ -0,0 +1 @@ +uid://cbpbqh6mocg73 diff --git a/Scripts/options_menu.gd b/Scripts/options_menu.gd index 79b1ad2..98562f0 100644 --- a/Scripts/options_menu.gd +++ b/Scripts/options_menu.gd @@ -3,6 +3,11 @@ class_name OptionsMenu extends Control @export var gameplay: GameplayOptionsMenu @export var graphics: GraphicsOptionsMenu @export var keybinds: KeybindsOptionsMenu +var game_manager: GameManager + + +func _ready() -> void: + keybinds.ui_layer = game_manager.UILayer func _on_cancel_pressed() -> void: diff --git a/Scripts/server_form.gd b/Scripts/server_form.gd index aa424b1..3fe609a 100644 --- a/Scripts/server_form.gd +++ b/Scripts/server_form.gd @@ -12,6 +12,7 @@ signal host_button_pressed @export var players_field: HBoxContainer @export var start_button: Button +var game_manager: GameManager var menu: int = 0 var hosting: bool = false @@ -40,7 +41,7 @@ func _on_button_mouse_entered() -> void: func _on_button_pressed() -> void: if menu == 0: - Game.scene_switch_main_menu() + game_manager.scene_switch_main_menu() else: menu -= 1 host_button.visible = true diff --git a/Scripts/singleplayer_lobby.gd b/Scripts/singleplayer_lobby.gd index d358609..1bd06f3 100644 --- a/Scripts/singleplayer_lobby.gd +++ b/Scripts/singleplayer_lobby.gd @@ -5,14 +5,13 @@ func _ready() -> void: enet_peer.create_server(Data.DEFAULT_SERVER_PORT, 1) multiplayer.multiplayer_peer = enet_peer enet_peer.refuse_new_connections = true - setup_game() func setup_game() -> void: loadout_editor = character_select_screen.instantiate() as CharacterSelect loadout_editor.hero_confirmed.connect(start_game) add_child(loadout_editor) - Game.chatbox = chatbox + game_manager.chatbox = chatbox chatbox.username = Data.player_profile.display_name Data.player_profile.display_name_changed.connect(chatbox.change_username) loadout_editor.hero_selected.connect(Data.player_profile.set_preferred_class) diff --git a/Scripts/wave_manager.gd b/Scripts/wave_manager.gd index 1b739c2..7dd04c5 100644 --- a/Scripts/wave_manager.gd +++ b/Scripts/wave_manager.gd @@ -12,7 +12,7 @@ class_name WaveManager extends Object ## Takes in wave number and number of players and returns a spawn power value ## intended for passing into the generate_wave method static func calculate_spawn_power(wave_number: int, number_of_players: int) -> int: - return (40 * number_of_players) + (6 * wave_number) + return (30 * number_of_players) + (6 * wave_number) ## Takes in wave number and number of players and returns the amount of coins diff --git a/Worlds/GreenPlanet/Enemies/enemy_controller.gd b/Worlds/GreenPlanet/Enemies/enemy_controller.gd index 64d11a6..3a5884b 100644 --- a/Worlds/GreenPlanet/Enemies/enemy_controller.gd +++ b/Worlds/GreenPlanet/Enemies/enemy_controller.gd @@ -11,6 +11,7 @@ signal died(enemy: Enemy) #@export var sprite: Sprite3D @export var corpse_scene: PackedScene +var corpse_root: Node var movement_speed: float var movement_speed_penalty: float = 1.0 var alive: bool = true @@ -41,9 +42,9 @@ func goal_entered() -> void: func die() -> void: if alive: alive = false - died.emit(stats) var corpse: RigidBody3D = corpse_scene.instantiate() corpse.set_sprite(stats.death_sprite) corpse.position = global_position - Game.level.corpses.add_child(corpse) + corpse_root.add_child(corpse) + died.emit(stats) queue_free() diff --git a/gif_animation.gd b/gif_animation.gd index 755ffcc..2085942 100644 --- a/gif_animation.gd +++ b/gif_animation.gd @@ -5,7 +5,6 @@ signal animation_finished() var time: float = 0.0 var x: int = 0 var y: int = 0 -var loops: int = 0 var signalled: bool = false @export var color_rect: ColorRect @@ -26,8 +25,7 @@ func _process(delta: float) -> void: if y == 8 and x == 4: y = 7 x = 5 - loops += 1 - if !signalled and loops >= 3: + if !signalled: signalled = true animation_finished.emit() texture.region = Rect2(256.0 * x, 256.0 * y, 256.0, 256.0) diff --git a/main.gd b/main.gd index 04114dd..2b2d697 100644 --- a/main.gd +++ b/main.gd @@ -1,30 +1,47 @@ class_name Main extends Node +signal loaded_scene + @export var scene: Node @export var movies: Node +var game_manager: GameManager var loaded: bool = false var main_menu_scene_path: String = "res://Scenes/Menus/MainMenu/main_menu.tscn" var multiplayer_lobby_scene_path: String = "res://Scenes/Menus/multiplayer_lobby.tscn" var singleplayer_lobby_scene_path: String = "res://Scenes/Menus/singleplayer_lobby.tscn" -func _ready() -> void: - Game.switch_to_main_menu.connect(load_main_menu) - Game.switch_to_single_player.connect(load_singleplayer) - Game.switch_to_multi_player.connect(load_multiplayer) - func load_main_menu() -> void: load_scene(main_menu_scene_path) + await loaded_scene + if game_manager: + game_manager.queue_free() + game_manager = GameManager.new() + add_child(game_manager) + game_manager.switch_to_main_menu.connect(load_main_menu) + game_manager.switch_to_single_player.connect(load_singleplayer) + game_manager.switch_to_multi_player.connect(load_multiplayer) + var main_menu: MainMenu = scene.get_child(0) as MainMenu + main_menu.multiplayer_game_requested.connect(load_multiplayer) + main_menu.singleplayer_game_requested.connect(load_singleplayer) + main_menu.game = game_manager func load_singleplayer() -> void: load_scene(singleplayer_lobby_scene_path) + await loaded_scene + var single_player_lobby: SinglePlayerLobby = scene.get_child(0) as SinglePlayerLobby + single_player_lobby.game_manager = game_manager + single_player_lobby.setup_game() func load_multiplayer() -> void: load_scene(multiplayer_lobby_scene_path) + await loaded_scene + var multi_player_lobby: MultiplayerLobby = scene.get_child(0) as MultiplayerLobby + multi_player_lobby.game_manager = game_manager func load_scene(scene_path: String) -> void: @@ -42,3 +59,4 @@ func load_scene(scene_path: String) -> void: movies = null $CanvasLayer.visible = true scene.add_child(new_scene.instantiate()) + loaded_scene.emit() diff --git a/project.godot b/project.godot index fa13b1e..9b2f392 100644 --- a/project.godot +++ b/project.godot @@ -20,7 +20,6 @@ config/icon="res://Assets/Textures/icon.svg" [autoload] Data="*res://Scripts/data.gd" -Game="*res://Scripts/game.gd" [debug] diff --git a/psx.gdshader b/psx.gdshader index 2f5acaf..40e9585 100644 --- a/psx.gdshader +++ b/psx.gdshader @@ -11,15 +11,15 @@ uniform int dither_size: hint_range(1, 8) = 1; float dithering_pattern(ivec2 fragcoord) { const float pattern[] = { - 0.00, 0.50, 0.10, 0.65, - 0.75, 0.25, 0.90, 0.35, - 0.20, 0.70, 0.05, 0.50, + 0.00, 0.50, 0.10, 0.65, + 0.75, 0.25, 0.90, 0.35, + 0.20, 0.70, 0.05, 0.50, 0.95, 0.40, 0.80, 0.30 }; - + int x = fragcoord.x % 4; int y = fragcoord.y % 4; - + return pattern[y * 4 + x]; } @@ -38,7 +38,7 @@ float reduce_color(float raw, float dither, int depth) { if (raw * float(depth) - float(i) <= dither * 0.999) { val = div * float(i); - } + } else { val = div * float(i + 1); @@ -61,7 +61,7 @@ void fragment() { { dithering_value = dithering_pattern(uv); } - + COLOR.r = reduce_color(raw.r, (dithering_value - 0.5) * dithering_value + 0.5, colors - 1); COLOR.g = reduce_color(raw.g, (dithering_value - 0.5) * dithering_value + 0.5, colors - 1); COLOR.b = reduce_color(raw.b, (dithering_value - 0.5) * dithering_value + 0.5, colors - 1);