multiplayer pretty much works now i think
This commit is contained in:
@ -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")
|
||||
|
@ -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)
|
||||
|
@ -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.
|
||||
|
||||
|
38
Scripts/Resources/player_graphics_settings.gd
Normal file
38
Scripts/Resources/player_graphics_settings.gd
Normal 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()
|
@ -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:
|
||||
|
@ -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")
|
||||
|
@ -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
|
||||
|
32
Scripts/Towers/range_affecting_tower.gd
Normal file
32
Scripts/Towers/range_affecting_tower.gd
Normal 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)
|
48
Scripts/Towers/shapecast_tower.gd
Normal file
48
Scripts/Towers/shapecast_tower.gd
Normal 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)
|
@ -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()
|
||||
|
@ -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
|
||||
|
55
Scripts/Weapons/shapecast_weapon.gd
Normal file
55
Scripts/Weapons/shapecast_weapon.gd
Normal 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)
|
@ -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])
|
||||
|
@ -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
|
||||
|
@ -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"))
|
||||
|
@ -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")
|
||||
|
46
Scripts/gameplay_options.gd
Normal file
46
Scripts/gameplay_options.gd
Normal 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
|
36
Scripts/graphics_options.gd
Normal file
36
Scripts/graphics_options.gd
Normal 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
|
63
Scripts/keybind_options.gd
Normal file
63
Scripts/keybind_options.gd
Normal 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()
|
@ -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)
|
||||
|
||||
|
@ -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()
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
||||
|
Reference in New Issue
Block a user