multiplayer pretty much works now i think

This commit is contained in:
2023-11-17 20:49:38 +11:00
parent 2d123bd731
commit 9cf6944ac8
87 changed files with 1476 additions and 1223 deletions

View File

@ -26,6 +26,15 @@ func explode():
func hit(target):
target.damage(damage)
if owner_id == 0:
if Data.preferences.display_tower_damage_indicators:
spawn_damage_indicator(target.sprite.global_position)
if owner_id == multiplayer.get_unique_id():
if Data.preferences.display_self_damage_indicators:
spawn_damage_indicator(target.sprite.global_position)
if owner_id != 0 and owner_id != multiplayer.get_unique_id():
if Data.preferences.display_party_damage_indicators:
spawn_damage_indicator(target.sprite.global_position)
@rpc("reliable")

View File

@ -2,16 +2,17 @@ extends ExplosiveProjectile
class_name HomingProjectile
var target : Node3D
@export var acceleration := 40.0
@export var max_speed := 14.0
var acceleration := 50.0
var max_speed := 13.0
func _physics_process(_delta: float) -> void:
if is_instance_valid(target):
direction = global_position.direction_to(target.global_position)
direction = global_position.direction_to(target.sprite.global_position)
#apply_central_force(direction * acceleration)
func _integrate_forces(state: PhysicsDirectBodyState3D) -> void:
state.linear_velocity = state.linear_velocity.limit_length(state.linear_velocity.length() * (1.0 - 0.08))
state.linear_velocity += direction * acceleration * state.step
state.linear_velocity = state.linear_velocity.limit_length(max_speed)

View File

@ -3,6 +3,8 @@ class_name Projectile
@export var collision_shape : CollisionShape3D
var damage_particle_scene = preload("res://Scenes/damage_particle.tscn")
var owner_id = 0 #should be left unchanged by towers, 1 for host, peer_id on peers
var direction := Vector3.FORWARD
var force := 2.0
var damage := 0.0
@ -18,6 +20,14 @@ func _process(delta: float) -> void:
time_alive += delta
func spawn_damage_indicator(pos):
if damage > 0:
var marker = damage_particle_scene.instantiate()
get_tree().root.add_child(marker)
marker.set_number(damage)
marker.position = pos
func _on_body_entered(_body: Node) -> void:
pass # Replace with function body.

View File

@ -0,0 +1,38 @@
extends Resource
class_name PlayerGraphicsSettings
const SAVE_PATH := "user://graphics_settings.tres"
@export var hfov := 100.0
@export var vsync_mode := 1
@export var aa_mode := 0
@export var windowed_mode := 0
func apply_graphical_settings(viewport):
DisplayServer.window_set_vsync_mode(vsync_mode)
match aa_mode:
0:
viewport.use_taa = false
viewport.screen_space_aa = Viewport.SCREEN_SPACE_AA_DISABLED
1:
viewport.use_taa = false
viewport.screen_space_aa = Viewport.SCREEN_SPACE_AA_FXAA
2:
viewport.use_taa = true
viewport.screen_space_aa = Viewport.SCREEN_SPACE_AA_DISABLED
match windowed_mode:
0:
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED)
1:
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_FULLSCREEN)
2:
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_EXCLUSIVE_FULLSCREEN)
func save_profile_to_disk():
ResourceSaver.save(self, SAVE_PATH)
static func load_profile_from_disk() -> PlayerGraphicsSettings:
if ResourceLoader.exists(SAVE_PATH):
return ResourceLoader.load(SAVE_PATH)
return PlayerGraphicsSettings.new()

View File

@ -7,10 +7,6 @@ const SAVE_PATH := "user://preferences.tres"
@export var invert_lookY := false
@export var invert_lookX := false
@export var toggle_sprint := false
@export var vsync_mode := 1
@export var aa_mode := 0
@export var windowed_mode := 0
@export var hfov := 100.0
@export var fixed_minimap := false
@export var display_tower_damage_indicators := true
@export var display_self_damage_indicators := true
@ -18,27 +14,6 @@ const SAVE_PATH := "user://preferences.tres"
@export var display_status_effect_damage_indicators := true
func apply_graphical_settings(viewport):
DisplayServer.window_set_vsync_mode(vsync_mode)
match aa_mode:
0:
viewport.use_taa = false
viewport.screen_space_aa = Viewport.SCREEN_SPACE_AA_DISABLED
1:
viewport.use_taa = false
viewport.screen_space_aa = Viewport.SCREEN_SPACE_AA_FXAA
2:
viewport.use_taa = true
viewport.screen_space_aa = Viewport.SCREEN_SPACE_AA_DISABLED
match windowed_mode:
0:
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED)
1:
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_FULLSCREEN)
2:
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_EXCLUSIVE_FULLSCREEN)
func save_profile_to_disk():
ResourceSaver.save(self, SAVE_PATH)
static func load_profile_from_disk() -> PlayerPreferences:

View File

@ -6,6 +6,8 @@ func shoot():
super.shoot()
if targeted_enemy and is_instance_valid(targeted_enemy) and targeted_enemy.alive:
targeted_enemy.damage(damage)
if Data.preferences.display_tower_damage_indicators:
spawn_damage_indicator(targeted_enemy.sprite.global_position)
@rpc("reliable")

View File

@ -28,3 +28,4 @@ func networked_spawn_projectile(peer_id):
projectile.name = base_name + str(peer_id) + str(projectile_id)
get_tree().root.add_child(projectile)
projectile_id += 1
return projectile

View File

@ -0,0 +1,32 @@
extends StatusApplyingTower
class_name RangeAffectingTower
func _physics_process(_delta: float) -> void:
if !is_multiplayer_authority():
return
var enemies_in_range = []
for enemy in get_tree().get_nodes_in_group("Enemies"):
if !is_instance_valid(enemy) or !enemy.alive or global_position.distance_to(enemy.global_position) > target_range:
continue
enemies_in_range.append(enemy)
if time_since_firing >= time_between_shots:
time_since_firing -= time_between_shots
for enemy in enemies_in_range:
fire(enemy)
func fire(target):
if is_instance_valid(target) and target.alive:
target.damage(damage)
target.status_manager.add_effect(build_status_object())
if Data.preferences.display_tower_damage_indicators:
spawn_damage_indicator(target.sprite.global_position)
if is_multiplayer_authority():
networked_fire.rpc(get_tree().root.get_path_to(target))
@rpc("reliable")
func networked_fire(target_node_path):
var target = get_tree().root.get_node(target_node_path)
fire(target)

View File

@ -0,0 +1,48 @@
extends Tower
class_name ShapecastTower
@export var shapecast : ShapeCast3D
@export var particlesystem : GPUParticles3D
@export var status_stats : StatusStats
func _process(delta: float) -> void:
super._process(delta)
if targeted_enemy:
particlesystem.emitting = true
else:
particlesystem.emitting = false
func shoot():
for index in shapecast.get_collision_count():
var target = shapecast.get_collider(index) as CharacterBody3D
hit(target)
func aim():
yaw_model.look_at(targeted_enemy.global_position)
pitch_model.look_at(targeted_enemy.global_position)
pitch_model.rotation.x = 0.0
func hit(target):
if is_instance_valid(target) and target.alive:
target.damage(damage)
if Data.preferences.display_tower_damage_indicators:
spawn_damage_indicator(target.sprite.global_position)
target.status_manager.add_effect(build_status_object())
if is_multiplayer_authority():
networked_hit.rpc(get_tree().root.get_path_to(target))
func build_status_object() -> StatusEffect:
var status = StatusEffect.new()
status.stats = status_stats
return status
@rpc("reliable")
func networked_hit(target_node_path):
var target = get_tree().root.get_node(target_node_path)
hit(target)

View File

@ -7,6 +7,7 @@ class_name Tower
@export var yaw_model : MeshInstance3D
@export var range_indicator : CSGSphere3D
var damage_particle_scene = preload("res://Scenes/damage_particle.tscn")
var base_name
var targeted_enemy
var time_since_firing := 0.0
@ -82,6 +83,14 @@ func shoot():
networked_shoot.rpc()
func spawn_damage_indicator(pos):
if damage > 0:
var marker = damage_particle_scene.instantiate()
get_tree().root.add_child(marker)
marker.set_number(damage)
marker.position = pos
@rpc("reliable")
func networked_shoot():
shoot()

View File

@ -24,6 +24,7 @@ func networked_spawn_projectile(peer_id, direction):
projectile.damage = damage
projectile.direction = direction
projectile.force = force
projectile.owner_id = peer_id
projectile.name = str(peer_id) + str(projectile_id)
get_tree().root.add_child(projectile)
projectile_id += 1

View File

@ -0,0 +1,55 @@
extends Weapon
class_name ShapecastWeapon
@export var shapecast : ShapeCast3D
@export var range_debug_indicator : CSGSphere3D
@export var status_stats : StatusStats
@export var particles : GPUParticles3D
var attack_range := 0.0
func _ready() -> void:
super._ready()
attack_range = stats.get_attribute("Range")
range_debug_indicator.radius = attack_range
shapecast.shape.size.z = attack_range
shapecast.target_position = -hero.camera.basis.z * (attack_range / 2.0)
func _process(delta: float) -> void:
super._process(delta)
particles.emitting = trigger_held
func shoot():
super.shoot()
for index in shapecast.get_collision_count():
var target = shapecast.get_collider(index)
if target:
var target_hitbox = target.shape_owner_get_owner(shapecast.get_collider_shape(index))
if target_hitbox is Hitbox:
hit(target, target_hitbox)
if Data.preferences.display_self_damage_indicators:
spawn_damage_indicator(target.sprite.global_position)
networked_hit.rpc(get_tree().root.get_path_to(target), get_tree().root.get_path_to(target_hitbox))
func build_status_object() -> StatusEffect:
var status = StatusEffect.new()
status.stats = status_stats
return status
func hit(target, target_hitbox : Hitbox):
target_hitbox.damage(damage)
target.status_manager.add_effect(build_status_object())
@rpc("reliable")
func networked_hit(target_path : String, target_hitbox_path : String):
var target = get_tree().root.get_node(target_path)
var target_hitbox = get_tree().root.get_node(target_hitbox_path) as Hitbox
hit(target, target_hitbox)
if Data.preferences.display_party_damage_indicators:
spawn_damage_indicator(target.sprite.global_position)

View File

@ -30,4 +30,4 @@ func view_weapon():
func view_tower():
description.text = process_card_text(stats.tower_stats)
target_label.text = str(stats.tower_stats.target_type)
target_label.text = str(Data.TargetType.keys()[stats.tower_stats.target_type])

View File

@ -4,42 +4,70 @@ class_name Chatbox
signal opened
signal closed
@export var input_line : LineEdit
@export var textbox : RichTextLabel
@export var text_panel : PanelContainer
@export var fade_timer : Timer
var text_selected := false
var username := "default"
var color = Color.TOMATO
var fading = true
var time_to_fade = 2.0
var time_since_started_fading = 2.0
func _process(delta: float) -> void:
if fading:
time_since_started_fading += delta
else:
time_since_started_fading = 0.0
textbox.modulate.a = lerpf(1.0, 0.0, time_since_started_fading / time_to_fade)
text_panel.modulate.a = lerpf(1.0, 0.0, time_since_started_fading / time_to_fade)
func _input(event: InputEvent) -> void:
if !text_selected and event.is_action_pressed("Open Text Chat"):
get_viewport().set_input_as_handled()
opened.emit()
$VBoxContainer/LineEdit.visible = true
$VBoxContainer/LineEdit.grab_focus()
input_line.visible = true
input_line.grab_focus()
text_selected = true
fading = false
return
if text_selected and event is InputEventKey and event.pressed == true:
if event.keycode == KEY_ENTER:
get_viewport().set_input_as_handled()
closed.emit()
$VBoxContainer/LineEdit.deselect()
$VBoxContainer/LineEdit.visible = false
input_line.deselect()
input_line.visible = false
text_selected = false
if $VBoxContainer/LineEdit.text.length() != 0:
if $VBoxContainer/LineEdit.text.begins_with("/"):
Game.parse_command($VBoxContainer/LineEdit.text, multiplayer.get_unique_id())
if input_line.text.length() != 0:
if input_line.text.begins_with("/"):
Game.parse_command(input_line.text, multiplayer.get_unique_id())
fade_timer.start()
else:
rpc("append_message", username, $VBoxContainer/LineEdit.text)
$VBoxContainer/LineEdit.clear()
append_message.rpc(username, color, input_line.text)
input_line.clear()
if event.keycode == KEY_ESCAPE:
get_viewport().set_input_as_handled()
closed.emit()
$VBoxContainer/LineEdit.deselect()
$VBoxContainer/LineEdit.visible = false
input_line.deselect()
input_line.visible = false
text_selected = false
fade_timer.start()
func change_username(old_name, new_name):
append_message("server", old_name + " has changed their display name to " + new_name)
append_message("SERVER", Color.TOMATO, old_name + " has changed their display name to " + new_name)
@rpc("reliable","call_local","any_peer")
func append_message(user, content):
$VBoxContainer/RichTextLabel.append_text("[" + user + "] " + content + "\n")
func append_message(user, user_color, content):
textbox.append_text("[[color=" + user_color.to_html() + "]" + user + "[color=white]] " + content + "\n")
fading = false
fade_timer.start()
func _on_timer_timeout() -> void:
fading = true

View File

@ -4,6 +4,7 @@ var characters : Array[HeroClass]
var cards : Array[Card]
var enemies : Array[Enemy]
var keymaps : Array[PlayerKeymap]
var graphics : PlayerGraphicsSettings
var preferences : PlayerPreferences
var player_profile : PlayerProfile
var player_keymap : PlayerKeymap
@ -22,10 +23,11 @@ var rarity_weights = {
}
func _ready() -> void:
graphics = PlayerGraphicsSettings.load_profile_from_disk()
graphics.apply_graphical_settings(get_viewport())
player_profile = PlayerProfile.load_profile_from_disk()
preferences = PlayerPreferences.load_profile_from_disk()
player_keymap = PlayerKeymap.load_profile_from_disk()
preferences.apply_graphical_settings(get_viewport())
player_keymap.apply()
characters.append(preload("res://PCs/Red/red.tres"))
@ -39,10 +41,10 @@ func _ready() -> void:
cards.append(preload("res://PCs/Universal/ClassCards/RocketLauncher/card_rocket_launcher.tres"))
#Uncommon
cards.append(preload("res://PCs/Universal/ClassCards/Blowdart/card_blowdart.tres"))
#cards.append(preload("res://PCs/Universal/ClassCards/Refridgerator/card_refridgerator.tres"))
cards.append(preload("res://PCs/Universal/ClassCards/Refrigerator/card_refrigerator.tres"))
cards.append(preload("res://PCs/Universal/ClassCards/GlueLauncher/card_glue_launcher.tres"))
#Rare
#cards.append(preload("res://PCs/Universal/ClassCards/Flamethrower/card_flamethrower.tres"))
cards.append(preload("res://PCs/Universal/ClassCards/Flamethrower/card_flamethrower.tres"))
#cards.append(preload("res://PCs/Universal/ClassCards/DamageEnhancer/card_damage_enhancer.tres"))
#cards.append(preload("res://PCs/Universal/ClassCards/SpeedEnhancer/card_speed_enhancer.tres"))
#Epic
@ -51,7 +53,7 @@ func _ready() -> void:
#cards.append(preload("res://PCs/Universal/ClassCards/GammaLaser/card_gamma_laser.tres"))
#Legendary
cards.append(preload("res://PCs/Universal/ClassCards/Sniper/card_sniper.tres"))
#cards.append(preload("res://PCs/Universal/ClassCards/Reactor/card_reactor.tres"))
cards.append(preload("res://PCs/Universal/ClassCards/Reactor/card_reactor.tres"))
#cards.append(preload("res://PCs/Universal/ClassCards/Lightning/card_lightning.tres"))
enemies.append(preload("res://Worlds/GreenPlanet/Enemies/dog.tres"))

View File

@ -25,6 +25,7 @@ var wave := 0
var upcoming_wave
var pot : float
var UILayer : CanvasLayer
var chatbox : Chatbox
func _ready() -> void:
@ -41,6 +42,12 @@ func parse_command(text : String, peer_id : int):
if x.title == gift_name:
gift = x
connected_players_nodes[peer_id].inventory.add(gift)
if text.substr(1, 2) == "tr":
chatbox.append_message("SERVER", Color.TOMATO, "[color=#f7a8b8]t[color=#55cdfc]r[color=#ffffff]a[color=#55cdfc]n[color=#f7a8b8]s [color=#e50000]r[color=#ff8d00]i[color=#ffee00]g[color=#028121]h[color=#004cff]t[color=#760088]s[color=white]!!")
# if text.substr(1, 17) == "show tower ranges":
# pass
# if text.substr(1, 20) = "show gauntlet ranges":
# pass
func spawn_level():
@ -63,7 +70,6 @@ func spawn_players(player_array, player_profiles, chatbox_open_signal, chatbox_c
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]
print(player.hero_class.hero_name)
player.ready_state_changed.connect(ready_player)
if peer_id == multiplayer.get_unique_id():
chatbox_open_signal.connect(player.pause)
@ -99,7 +105,7 @@ func set_upcoming_wave():
if is_multiplayer_authority():
var spawn_power = WaveManager.calculate_spawn_power(wave + 1, connected_players_nodes.size())
var new_wave = WaveManager.generate_wave(spawn_power, level.enemy_pool)
networked_set_upcoming_wave.rpc(new_wave, 6 + floori(spawn_power / 100))
networked_set_upcoming_wave.rpc(new_wave, 6 + floori(spawn_power / 50))
@rpc("reliable", "call_local")

View File

@ -0,0 +1,46 @@
extends VBoxContainer
class_name GameplayOptionsMenu
@export var look_sens_slider : HSlider
@export var look_sens_input : SpinBox
@export var toggle_sprint_checkbox : CheckButton
@export var invert_lookY : CheckButton
@export var invert_lookX : CheckButton
@export var fixed_minimap : CheckButton
@export var tower_damage : Button
@export var self_damage : Button
@export var party_damage : Button
@export var status_damage : Button
func _ready() -> void:
look_sens_slider.value = Data.preferences.mouse_sens
look_sens_input.value = Data.preferences.mouse_sens
toggle_sprint_checkbox.button_pressed = Data.preferences.toggle_sprint
invert_lookY.button_pressed = Data.preferences.invert_lookY
invert_lookX.button_pressed = Data.preferences.invert_lookX
fixed_minimap.button_pressed = Data.preferences.fixed_minimap
tower_damage.button_pressed = Data.preferences.display_tower_damage_indicators
self_damage.button_pressed = Data.preferences.display_self_damage_indicators
party_damage.button_pressed = Data.preferences.display_party_damage_indicators
status_damage.button_pressed = Data.preferences.display_status_effect_damage_indicators
func save() -> void:
Data.preferences.mouse_sens = look_sens_slider.value
Data.preferences.toggle_sprint = toggle_sprint_checkbox.button_pressed
Data.preferences.invert_lookY = invert_lookY.button_pressed
Data.preferences.invert_lookX = invert_lookX.button_pressed
Data.preferences.fixed_minimap = fixed_minimap.button_pressed
Data.preferences.display_tower_damage_indicators = tower_damage.button_pressed
Data.preferences.display_self_damage_indicators = self_damage.button_pressed
Data.preferences.display_party_damage_indicators = party_damage.button_pressed
Data.preferences.display_status_effect_damage_indicators = status_damage.button_pressed
func _on_mouse_sens_spin_box_value_changed(value: float) -> void:
look_sens_slider.value = value
func _on_mouse_sens_h_slider_value_changed(value: float) -> void:
look_sens_input.value = value

View File

@ -0,0 +1,36 @@
extends VBoxContainer
class_name GraphicsOptionsMenu
@export var fov_input : SpinBox
@export var fov_slider : HSlider
@export var vsync_dropdown : OptionButton
@export var aa_dropdown : OptionButton
@export var window_dropdown : OptionButton
func _ready():
fov_input.value = Data.graphics.hfov
fov_slider.value = Data.graphics.hfov
vsync_dropdown.selected = Data.graphics.vsync_mode
aa_dropdown.selected = Data.graphics.aa_mode
func save():
Data.graphics.hfov = fov_slider.value
Data.graphics.vsync_mode = vsync_dropdown.selected
Data.graphics.aa_mode = aa_dropdown.selected
Data.graphics.windowed_mode = window_dropdown.selected
func _on_fov_spin_box_value_changed(value: float) -> void:
if value < 40.0:
value = 40.0
if value > 160.0:
value = 160.0
fov_slider.value = value
Data.graphics.hfov = value
func _on_fov_h_slider_value_changed(value: float) -> void:
fov_input.value = value
Data.graphics.hfov = value

View File

@ -0,0 +1,63 @@
extends VBoxContainer
var keybind_popup = load("res://Scenes/UI/keybind_popup.tscn")
var keybind_boxes = []
var keybind_buttons = {}
var key_event
var selected_button
var selected_button_button
var listening_for_key := false
func _ready() -> void:
for index in Data.keymaps.size():
var map = Data.keymaps[index]
var button = Button.new()
button.text = map.title
button.pressed.connect(set_keymap.bind(index))
$HBoxContainer.add_child(button)
load_keybind_labels()
func set_keymap(keymap_index):
Data.player_keymap = Data.keymaps[keymap_index]
Data.player_keymap.apply()
load_keybind_labels()
func load_keybind_labels():
for box in keybind_boxes:
box.queue_free()
keybind_boxes.clear()
for action in InputMap.get_actions():
if !action.begins_with("ui_"):
var box = HBoxContainer.new()
var alabel = Label.new()
var elabel = Button.new()
alabel.text = action
if InputMap.action_get_events(action).size() > 0:
elabel.text = InputMap.action_get_events(action)[0].as_text()
elabel.size_flags_horizontal += Control.SIZE_EXPAND
alabel.size_flags_horizontal += Control.SIZE_EXPAND
alabel.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
alabel.size_flags_stretch_ratio = 2.0
#elabel.horizontal_alignment = HORIZONTAL_ALIGNMENT_RIGHT
box.add_child(alabel)
box.add_child(elabel)
elabel.pressed.connect(_on_keybind_button_pressed.bind(elabel))
keybind_buttons[elabel] = action
$ScrollContainer/VBoxContainer.add_child(box)
keybind_boxes.append(box)
func _on_keybind_button_pressed(value: Button) -> void:
selected_button = keybind_buttons[value]
selected_button_button = value
var popup = keybind_popup.instantiate()
popup.event_detected.connect(change_key)
Game.UILayer.add_child(popup)
func change_key(event: InputEvent):
Data.player_keymap.replace_action_event(selected_button, event)
selected_button_button.text = event.as_text()

View File

@ -32,7 +32,7 @@ func _on_player_connected(peer_id):
func _on_player_disconnected(peer_id):
if chatbox:
chatbox.append_message("SERVER", connected_players_profiles[peer_id].display_name + " has disconnected!")
chatbox.append_message("SERVER", Color.TOMATO, connected_players_profiles[peer_id].display_name + " has disconnected!")
connected_players_profiles.erase(peer_id)
player_disconnected.emit(peer_id)
@ -64,6 +64,7 @@ func setup_game(peer_id):
Game.spawn_level()
scoreboard.all_players_ready.connect(start_game)
Game.game_restarted.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)
@ -116,7 +117,7 @@ func add_player(new_player_profile_dict):
var new_player_peer_id = multiplayer.get_remote_sender_id()
var new_player_profile = PlayerProfile.from_dict(new_player_profile_dict)
if chatbox:
chatbox.append_message("SERVER", new_player_profile.display_name + " has connected!")
chatbox.append_message("SERVER", Color.TOMATO, new_player_profile.display_name + " has connected!")
connected_players_profiles[new_player_peer_id] = new_player_profile
player_connected.emit(new_player_peer_id, new_player_profile)

View File

@ -1,137 +1,14 @@
extends Control
class_name OptionsMenu
@export var keybind_popup : PackedScene
@export var look_sens_slider : HSlider
@export var look_sens_input : SpinBox
@export var toggle_sprint_checkbox : CheckButton
@export var vsync_dropdown : OptionButton
@export var aa_dropdown : OptionButton
@export var window_dropdown : OptionButton
@export var invert_lookY : CheckButton
@export var invert_lookX : CheckButton
@export var fov_input : SpinBox
@export var fov_slider : HSlider
@export var fixed_minimap : CheckButton
@export var tower_damage : Button
@export var self_damage : Button
@export var party_damage : Button
@export var status_damage : Button
var keybind_boxes = []
var keybind_buttons = {}
var key_event
var selected_button
var selected_button_button
var listening_for_key := false
func _ready():
look_sens_slider.value = Data.preferences.mouse_sens
look_sens_input.value = Data.preferences.mouse_sens
toggle_sprint_checkbox.button_pressed = Data.preferences.toggle_sprint
vsync_dropdown.selected = Data.preferences.vsync_mode
aa_dropdown.selected = Data.preferences.aa_mode
invert_lookY.button_pressed = Data.preferences.invert_lookY
invert_lookX.button_pressed = Data.preferences.invert_lookX
fov_input.value = Data.preferences.hfov
fov_slider.value = Data.preferences.hfov
fixed_minimap.button_pressed = Data.preferences.fixed_minimap
tower_damage.button_pressed = Data.preferences.display_tower_damage_indicators
self_damage.button_pressed = Data.preferences.display_self_damage_indicators
party_damage.button_pressed = Data.preferences.display_party_damage_indicators
status_damage.button_pressed = Data.preferences.display_status_effect_damage_indicators
for index in Data.keymaps.size():
var map = Data.keymaps[index]
var button = Button.new()
button.text = map.title
button.pressed.connect(set_keymap.bind(index))
$VBoxContainer/TabContainer/Keybinds/HBoxContainer.add_child(button)
load_keybind_labels()
func set_keymap(keymap_index):
Data.player_keymap = Data.keymaps[keymap_index]
Data.player_keymap.apply()
load_keybind_labels()
func load_keybind_labels():
for box in keybind_boxes:
box.queue_free()
keybind_boxes.clear()
for action in InputMap.get_actions():
if !action.begins_with("ui_"):
var box = HBoxContainer.new()
var alabel = Label.new()
var elabel = Button.new()
alabel.text = action
if InputMap.action_get_events(action).size() > 0:
elabel.text = InputMap.action_get_events(action)[0].as_text()
elabel.size_flags_horizontal += Control.SIZE_EXPAND
alabel.size_flags_horizontal += Control.SIZE_EXPAND
alabel.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
alabel.size_flags_stretch_ratio = 2.0
#elabel.horizontal_alignment = HORIZONTAL_ALIGNMENT_RIGHT
box.add_child(alabel)
box.add_child(elabel)
elabel.pressed.connect(_on_keybind_button_pressed.bind(elabel))
keybind_buttons[elabel] = action
$VBoxContainer/TabContainer/Keybinds/ScrollContainer/VBoxContainer.add_child(box)
keybind_boxes.append(box)
func _on_cancel_pressed() -> void:
queue_free()
func _on_confirm_pressed() -> void:
Data.preferences.mouse_sens = look_sens_slider.value
Data.preferences.toggle_sprint = toggle_sprint_checkbox.button_pressed
Data.preferences.vsync_mode = vsync_dropdown.selected
Data.preferences.aa_mode = aa_dropdown.selected
Data.preferences.windowed_mode = window_dropdown.selected
Data.preferences.invert_lookY = invert_lookY.button_pressed
Data.preferences.invert_lookX = invert_lookX.button_pressed
Data.preferences.fixed_minimap = fixed_minimap.button_pressed
Data.preferences.display_tower_damage_indicators = tower_damage.button_pressed
Data.preferences.display_self_damage_indicators = self_damage.button_pressed
Data.preferences.display_party_damage_indicators = party_damage.button_pressed
Data.preferences.display_status_effect_damage_indicators = status_damage.button_pressed
Data.preferences.apply_graphical_settings(get_viewport())
Data.graphics.apply_graphical_settings(get_viewport())
Data.graphics.save_profile_to_disk()
Data.preferences.save_profile_to_disk()
Data.player_keymap.save_profile_to_disk()
queue_free()
func _on_mouse_sens_spin_box_value_changed(value: float) -> void:
look_sens_slider.value = value
func _on_mouse_sens_h_slider_value_changed(value: float) -> void:
look_sens_input.value = value
func _on_fov_spin_box_value_changed(value: float) -> void:
if value < 40.0:
value = 40.0
if value > 160.0:
value = 160.0
fov_slider.value = value
Data.preferences.hfov = value
func _on_fov_h_slider_value_changed(value: float) -> void:
fov_input.value = value
Data.preferences.hfov = value
func _on_keybind_button_pressed(value: Button) -> void:
selected_button = keybind_buttons[value]
selected_button_button = value
var popup = keybind_popup.instantiate()
popup.event_detected.connect(change_key)
add_child(popup)
func change_key(event: InputEvent):
Data.player_keymap.replace_action_event(selected_button, event)
selected_button_button.text = event.as_text()

View File

@ -19,6 +19,7 @@ func setup_game():
scoreboard.add_player(1, Data.player_profile)
scoreboard.all_players_ready.connect(start_game)
Game.game_restarted.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)

View File

@ -2,7 +2,7 @@ extends StaticBody3D
class_name TowerBase
@export var inventory : Inventory
@export var block : CSGBox3D
@export var block : Node3D
@export var collider : CollisionShape3D
@export var minimap_icon : Sprite3D
@ -27,7 +27,7 @@ func remove_card() -> Card:
func set_material(value: StandardMaterial3D):
block.material = value
block.material_override = value
func toggle_collision():
@ -40,7 +40,7 @@ func networked_spawn_tower():
tower.stats = inventory.selected_item.tower_stats
tower.name = "tower"
tower.base_name = name
tower.position = Vector3.UP
tower.position = Vector3(0, 1.2, 0)
minimap_icon.modulate = Color.RED
add_child(tower)