added selling cards and made shop items cheaper

This commit is contained in:
2024-03-31 19:32:00 +11:00
parent e84496dcf8
commit 05914a3c64
22 changed files with 354 additions and 413 deletions

View File

@ -3,9 +3,9 @@ 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 rng_seeded
signal game_setup
signal game_started
signal game_restarted
signal lost_game
signal won_game
@ -14,8 +14,7 @@ var player_scene: PackedScene = load("res://PCs/hero.tscn")
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"
var won_game_scene: PackedScene = load("res://Scenes/Menus/won_game_screen.tscn")
var lose_game_scene: PackedScene = load("res://Scenes/Menus/lost_game_screen.tscn")
var game_end_scene: PackedScene = load("res://Scenes/Menus/GameEndScreen/game_end_screen.tscn")
var connected_players_nodes: Dictionary = {}
var game_active: bool = false
var level: Level
@ -30,9 +29,12 @@ var chatbox: Chatbox
var wave_limit: int = 20
var starting_cash: int = 16
var shop_chance: float = 0.0
var stats: RoundStats = RoundStats.new()
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 = {}
func _ready() -> void:
UILayer = CanvasLayer.new()
@ -44,13 +46,19 @@ func _ready() -> void:
func set_seed(value: int) -> void:
rng = FastNoiseLite.new()
rng.noise_type = FastNoiseLite.TYPE_VALUE
rng.frequency = 1
rng.frequency = 30
rng.fractal_octaves = 2
rng.fractal_gain = 0.1
rng.seed = value
rng_seeded.emit()
func randi_in_range(sample: float, start: float, end: float) -> int:
return floori(remap(rng.get_noise_1d(sample), -1.0, 1.0, start, end + 1))
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:
@ -118,20 +126,21 @@ func spawn_level() -> void:
add_child(level)
func spawn_players(player_array: Array, player_profiles: Dictionary, chatbox_open_signal: Signal, chatbox_closed_signal: Signal) -> void:
func spawn_players() -> void:
var p_i: int = 0
var player_array: Array = connected_player_profiles.keys()
player_array.sort()
for peer_id: int in player_array:
var player: Hero = player_scene.instantiate() as Hero
player.name = str(peer_id)
player.player_name_tag.text = player_profiles[peer_id].display_name
player.player_name_tag.text = connected_player_profiles[peer_id].display_name
player.position = level.player_spawns[p_i].global_position
player.profile = player_profiles[peer_id]
player.hero_class = Data.characters[player_profiles[peer_id].preferred_class]
player.profile = connected_player_profiles[peer_id]
player.hero_class = Data.characters[connected_player_profiles[peer_id].preferred_class]
player.ready_state_changed.connect(ready_player)
if peer_id == multiplayer.get_unique_id():
chatbox_open_signal.connect(player.pause)
chatbox_closed_signal.connect(player.unpause)
chatbox.opened.connect(player.pause)
chatbox.closed.connect(player.unpause)
player.set_multiplayer_authority(peer_id)
connected_players_nodes[peer_id] = player
wave_started.connect(player.exit_editing_mode)
@ -140,7 +149,6 @@ func spawn_players(player_array: Array, player_profiles: Dictionary, chatbox_ope
add_child(player)
p_i += 1
level.cinematic_cam.does_its_thing = false
start_game()
func ready_player(player_ready_true: bool) -> void:
@ -154,7 +162,7 @@ func ready_player(player_ready_true: bool) -> void:
ready_players += 1
if ready_players == connected_players_nodes.size():
spawn_enemy_wave()
chatbox.append_message("SERVER", Color.TOMATO, "Wave Started!")
#chatbox.append_message("SERVER", Color.TOMATO, "Wave Started!")
else:
chatbox.append_message("SERVER", Color.TOMATO, str(ready_players) + "/" + str(connected_players_nodes.size()) + " Players ready")
@ -208,7 +216,7 @@ func enemy_died(enemy: Enemy) -> void:
if enemies == 0:
end_wave()
if !endless_mode and wave >= wave_limit:
win_game()
end(true)
func damage_goal(enemy: Enemy, penalty: int) -> void:
@ -219,11 +227,11 @@ func damage_goal(enemy: Enemy, penalty: int) -> void:
objective_health -= penalty
base_took_damage.emit(objective_health)
if objective_health <= 0:
lose_game()
end(false)
elif enemies == 0:
end_wave()
if !endless_mode and wave >= wave_limit:
win_game()
end(true)
func end_wave() -> void:
@ -233,11 +241,11 @@ func end_wave() -> void:
level.a_star_graph_3d.visualized_path.enable_visualization()
level.a_star_graph_3d.enable_non_path_tower_frames()
if is_multiplayer_authority():
if randf() <= shop_chance:
if randf_in_range(23 * wave, 0.0, 1.0) <= shop_chance:
networked_spawn_shop.rpc()
shop_chance = 0.0
else:
shop_chance += 0.05
shop_chance += 0.07
wave_finished.emit(wave)
set_upcoming_wave()
@ -254,68 +262,68 @@ func remove_player(peer_id: int) -> void:
connected_players_nodes.erase(peer_id)
func start_game() -> void:
if is_multiplayer_authority():
set_seed.rpc(randi())
else:
await rng_seeded
game_active = true
func setup() -> void:
#clean up old stuff
if level:
level.queue_free()
for peer_id: int in connected_players_nodes:
connected_players_nodes[peer_id].queue_free()
connected_players_nodes.clear()
#Spawn new stuff
spawn_level()
#Set starting parameters
game_active = false
enemies = 0
objective_health = 120
wave = 0
stats = RoundStats.new()
game_setup.emit()
func start(rng_seed: int = randi()) -> void:
if is_multiplayer_authority():
set_seed.rpc(rng_seed)
else:
await rng_seeded
#Relies on player list having been decided
spawn_players()
for peer_id: int in connected_players_nodes:
connected_players_nodes[peer_id].currency = ceili(float(starting_cash) / float(connected_players_nodes.size()))
#Relies on rng having been seeded
set_upcoming_wave()
level.a_star_graph_3d.make_grid()
level.generate_obstacles()
level.a_star_graph_3d.disable_all_tower_frames()
level.a_star_graph_3d.enable_non_path_tower_frames()
level.a_star_graph_3d.find_path()
set_upcoming_wave()
for peer_id: int in connected_players_nodes:
connected_players_nodes[peer_id].currency = roundi(float(starting_cash) / float(connected_players_nodes.size()))
#Start game
game_active = true
chatbox.append_message("SERVER", Color.TOMATO, "Started with seed: " + str(rng.seed))
game_started.emit()
func restart_game() -> void:
#implement game reloading system
for peer_id: int in connected_players_nodes:
connected_players_nodes[peer_id].queue_free()
connected_players_nodes.clear()
level.queue_free()
enemies = 0
objective_health = 120
wave = 0
stats = RoundStats.new()
spawn_level()
game_restarted.emit()
pass
func lose_game() -> void:
func end(outcome: bool) -> void:
if game_active == false:
return
game_active = false
Data.save_stats.add_game_outcome(false)
Data.save_stats.add_game_outcome(outcome)
Data.save_stats.save_profile_to_disk()
var menu: Control = lose_game_scene.instantiate()
var menu: GameEndScreen = game_end_scene.instantiate() as GameEndScreen
match outcome:
false:
menu.set_outcome_message("You lost...")
lost_game.emit()
true:
menu.set_outcome_message("You win!")
won_game.emit()
UILayer.add_child(menu)
lost_game.emit()
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
for peer_id: int in connected_players_nodes:
connected_players_nodes[peer_id].pause()
func win_game() -> void:
if game_active == false:
return
game_active = false
Data.save_stats.add_game_outcome(true)
Data.save_stats.save_profile_to_disk()
var menu: Control = won_game_scene.instantiate()
UILayer.add_child(menu)
won_game.emit()
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
for peer_id: int in connected_players_nodes:
connected_players_nodes[peer_id].pause()
connected_players_nodes[multiplayer.get_unique_id()].pause()
func quit_to_desktop() -> void:
@ -327,6 +335,8 @@ func quit_to_desktop() -> void:
func scene_switch_main_menu() -> void:
for node: Node in get_children():
node.queue_free()
level = null
connected_players_nodes.clear()
multiplayer.multiplayer_peer.close()
multiplayer.multiplayer_peer = null
get_tree().change_scene_to_file(main_menu_scene_path)

View File

@ -4,7 +4,7 @@ signal button_interacted(value: int, callback: Hero)
@export var button_press_value: int = 0
@export var press_cost: int = 0
@export var hover_text: String = "Press [Interact]"
@export var hover_text: String = "#Interact# to [do thing]"
func press(callback_player: Hero) -> void:

View File

@ -33,7 +33,7 @@ func generate_obstacles() -> void:
func cell_coord_to_astar_point(x: int, y: int) -> int:
var center_point_x: int = floori(a_star_graph_3d.grid_size.x / 2.0) * a_star_graph_3d.grid_size.y
var center_point_y: int = a_star_graph_3d.grid_size.y / 2.0
var center_point_y: int = floori(a_star_graph_3d.grid_size.y / 2.0)
return (center_point_x + ((x / 2.0) * a_star_graph_3d.grid_size.y)) + (center_point_y + (y / 2.0))

View File

@ -1,33 +0,0 @@
class_name LostGameScreen extends Control
@export var box: PackedScene
func _ready() -> void:
var wins: float = float(Data.save_stats.twenty_game_history.count(true))
var games: float = float(Data.save_stats.twenty_game_history.size())
var winrate: int = int((wins / games) * 100.0)
$Label2.text = "Your 20-game winrate is now: " + str(winrate) + "%!"
$Label3.text = "Total games: " + str(Data.save_stats.wins + Data.save_stats.losses)
$Label4.text = "Total wins: " + str(Data.save_stats.wins)
$Label5.text = "Total losses: " + str(Data.save_stats.losses)
for wave_key: int in Game.stats.enemies_undefeated:
var spawned_box: EnemyBox = box.instantiate() as EnemyBox
$VBoxContainer.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])
func _on_quit_button_pressed() -> void:
Game.scene_switch_main_menu()
queue_free()
func _on_restart_button_pressed() -> void:
Game.restart_game()
queue_free()
func _on_button_mouse_entered() -> void:
$AudioStreamPlayer.play()

View File

@ -60,17 +60,16 @@ func create_server() -> void:
func setup_game(peer_id: int) -> void:
player_disconnected.connect(Game.remove_player)
Game.spawn_level()
scoreboard.all_players_ready.connect(start_game)
Game.game_restarted.connect(setup_the_ui)
Game.game_setup.connect(setup_the_ui)
Game.chatbox = chatbox
setup_the_ui()
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)
loadout_editor.hero_selected.connect(edit_player_profile)
connected_players_profiles[peer_id] = Data.player_profile
player_connected.emit(peer_id, Data.player_profile)
Game.setup()
func setup_the_ui() -> void:
@ -95,9 +94,10 @@ func ready_player() -> void:
func start_game() -> void:
enet_peer.refuse_new_connections = true
Game.spawn_players(connected_players_profiles.keys(), connected_players_profiles, chatbox.opened, chatbox.closed)
scoreboard.set_visible(false)
loadout_editor.set_visible(false)
Game.connected_player_profiles = connected_players_profiles
Game.start()
#TODO: what the fuck is this doing lol

View File

@ -3,6 +3,9 @@ class_name SinglePlayerLobby extends Control
@export var scoreboard: Scoreboard
@export var loadout_editor: HeroSelector
@export var chatbox: Chatbox
@export var seed_entry: LineEdit
@export var ready_button: Button
@export var daily_button: Button
var connected_players_profiles: Dictionary = {}
var enet_peer: ENetMultiplayerPeer = ENetMultiplayerPeer.new()
@ -16,22 +19,33 @@ func _ready() -> void:
func setup_game() -> void:
Game.spawn_level()
scoreboard.add_player(1, Data.player_profile)
scoreboard.all_players_ready.connect(start_game)
Game.game_restarted.connect(setup_the_ui)
Game.game_setup.connect(setup_the_ui)
Game.chatbox = chatbox
setup_the_ui()
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)
connected_players_profiles[1] = Data.player_profile
Game.setup()
func start_game() -> void:
Game.spawn_players(connected_players_profiles.keys(), connected_players_profiles, chatbox.opened, chatbox.closed)
scoreboard.set_visible(false)
loadout_editor.set_visible(false)
seed_entry.set_visible(false)
daily_button.set_visible(false)
ready_button.set_visible(false)
Game.connected_player_profiles = connected_players_profiles
var chosen_seed: int
if seed_entry.text != "":
if seed_entry.text.is_valid_int():
chosen_seed = int(seed_entry.text)
else:
chosen_seed = hash(seed_entry.text)
Game.start(chosen_seed)
else:
Game.start()
func setup_the_ui() -> void:
@ -40,7 +54,20 @@ func setup_the_ui() -> void:
loadout_editor.set_visible(true)
$ReadyButton.set_visible(true)
chatbox.set_visible(true)
seed_entry.set_visible(true)
daily_button.set_visible(true)
ready_button.set_visible(true)
func _on_button_mouse_entered() -> void:
$AudioStreamPlayer.play()
func _on_daily_button_pressed() -> void:
scoreboard.set_visible(false)
loadout_editor.set_visible(false)
seed_entry.set_visible(false)
daily_button.set_visible(false)
ready_button.set_visible(false)
Game.connected_player_profiles = connected_players_profiles
Game.start(hash(Time.get_date_string_from_system(true)))

View File

@ -1,33 +0,0 @@
class_name WonGameScreen extends Control
@export var box: PackedScene
func _ready() -> void:
var wins: int = Data.save_stats.twenty_game_history.count(true)
var games: int = Data.save_stats.twenty_game_history.size()
var winrate: int = int((float(wins) / float(games)) * 100.0)
$Label2.text = "Your 20-game winrate is now: " + str(winrate) + "%!"
$Label3.text = "Total games: " + str(Data.save_stats.wins + Data.save_stats.losses)
$Label4.text = "Total wins: " + str(Data.save_stats.wins)
$Label5.text = "Total losses: " + str(Data.save_stats.losses)
for wave_key: int in Game.stats.enemies_undefeated:
var spawned_box: EnemyBox = box.instantiate() as EnemyBox
$VBoxContainer.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])
func _on_quit_button_pressed() -> void:
Game.scene_switch_main_menu()
queue_free()
func _on_play_button_pressed() -> void:
Game.restart_game()
queue_free()
func _on_button_mouse_entered() -> void:
$AudioStreamPlayer.play()