feat: Implement core game systems including settings management, player input, and initial gameplay mechanics with associated UI.
This commit is contained in:
+5
-1
@@ -21,7 +21,6 @@ config/icon="res://icon.svg"
|
||||
|
||||
[autoload]
|
||||
|
||||
SettingsManager="*res://scripts/managers/settings_manager.gd"
|
||||
Nakama="*uid://bueyqhhvxe0tx"
|
||||
NakamaManager="*res://scripts/nakama_manager.gd"
|
||||
AuthManager="*res://scripts/managers/auth_manager.gd"
|
||||
@@ -33,6 +32,7 @@ GoalManager="*res://scripts/managers/goal_manager.gd"
|
||||
PlayerManager="*res://scripts/managers/player_manager.gd"
|
||||
GoalsCycleManager="*res://scripts/managers/goals_cycle_manager.gd"
|
||||
Satori="*uid://b8vev00s34b7"
|
||||
SettingsManager="*uid://c1ouaaqnn0lrc"
|
||||
|
||||
[display]
|
||||
|
||||
@@ -69,24 +69,28 @@ move_north={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":87,"physical_keycode":0,"key_label":0,"unicode":119,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194320,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":1,"axis_value":-1.0,"script":null)
|
||||
]
|
||||
}
|
||||
move_south={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":83,"physical_keycode":0,"key_label":0,"unicode":115,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194322,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":1,"axis_value":1.0,"script":null)
|
||||
]
|
||||
}
|
||||
move_west={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":65,"physical_keycode":0,"key_label":0,"unicode":97,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194319,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":0,"axis_value":-1.0,"script":null)
|
||||
]
|
||||
}
|
||||
move_east={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":68,"physical_keycode":0,"key_label":0,"unicode":100,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194321,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":0,"axis_value":1.0,"script":null)
|
||||
]
|
||||
}
|
||||
move_northeast={
|
||||
|
||||
@@ -1161,24 +1161,20 @@ grow_horizontal = 0
|
||||
grow_vertical = 0
|
||||
|
||||
[node name="ActionButtonContainer" type="VBoxContainer" parent="ActionMenu" unique_id=1026460846]
|
||||
visible = false
|
||||
layout_mode = 0
|
||||
offset_right = 40.0
|
||||
offset_bottom = 40.0
|
||||
|
||||
[node name="MoveButton" type="Button" parent="ActionMenu/ActionButtonContainer" unique_id=1233901451]
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
text = "Move"
|
||||
|
||||
[node name="GrabButton" type="Button" parent="ActionMenu/ActionButtonContainer" unique_id=1584219139]
|
||||
visible = false
|
||||
custom_minimum_size = Vector2(100, 100)
|
||||
layout_mode = 2
|
||||
text = "Grab"
|
||||
|
||||
[node name="PutButton" type="Button" parent="ActionMenu/ActionButtonContainer" unique_id=508990607]
|
||||
visible = false
|
||||
custom_minimum_size = Vector2(100, 100)
|
||||
layout_mode = 2
|
||||
text = "Put"
|
||||
|
||||
+14
-8
@@ -1012,6 +1012,20 @@ func activate_powerup(effect_id: int):
|
||||
if st_manager:
|
||||
st_manager.activate_effect(effect_id)
|
||||
|
||||
func activate_held_powerup():
|
||||
"""Finds whichever powerup is currently held and activates it."""
|
||||
var active_effect = -1
|
||||
if special_tiles_manager:
|
||||
for effect_key in special_tiles_manager.inventory:
|
||||
if special_tiles_manager.inventory[effect_key]:
|
||||
active_effect = effect_key
|
||||
break
|
||||
|
||||
if active_effect != -1:
|
||||
activate_powerup(active_effect)
|
||||
else:
|
||||
print("[Player] No powerup currently held to activate.")
|
||||
|
||||
|
||||
func _process(delta):
|
||||
# Failsafe: Ensure player is visible if spawn point is selected and random spawn is active
|
||||
@@ -1118,14 +1132,6 @@ func _physics_process(delta):
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
func _unhandled_input(event):
|
||||
# Handle power-up usage
|
||||
if event.is_action_pressed("use_powerup") and is_multiplayer_authority():
|
||||
if is_frozen or is_stop_frozen:
|
||||
return
|
||||
if powerup_manager and powerup_manager.can_use_special():
|
||||
powerup_manager.use_special_effect()
|
||||
return
|
||||
|
||||
if input_manager:
|
||||
input_manager.handle_unhandled_input(event)
|
||||
|
||||
|
||||
@@ -300,7 +300,22 @@ label_settings = SubResource("LabelSettings_section")
|
||||
layout_mode = 2
|
||||
theme_override_constants/h_separation = 20
|
||||
theme_override_constants/v_separation = 10
|
||||
columns = 2
|
||||
columns = 3
|
||||
|
||||
[node name="ColH1" type="Label" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls/VBox/MoveGrid"]
|
||||
layout_mode = 2
|
||||
text = "Action"
|
||||
label_settings = SubResource("LabelSettings_section")
|
||||
|
||||
[node name="ColH2" type="Label" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls/VBox/MoveGrid"]
|
||||
layout_mode = 2
|
||||
text = "Primary"
|
||||
label_settings = SubResource("LabelSettings_section")
|
||||
|
||||
[node name="ColH3" type="Label" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls/VBox/MoveGrid"]
|
||||
layout_mode = 2
|
||||
text = "Secondary"
|
||||
label_settings = SubResource("LabelSettings_section")
|
||||
|
||||
[node name="UpLabel" type="Label" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls/VBox/MoveGrid" unique_id=100000007]
|
||||
layout_mode = 2
|
||||
@@ -314,6 +329,12 @@ custom_minimum_size = Vector2(150, 40)
|
||||
layout_mode = 2
|
||||
text = "W"
|
||||
|
||||
[node name="MoveUpAltBtn" type="Button" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls/VBox/MoveGrid" unique_id=100000108]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(150, 40)
|
||||
layout_mode = 2
|
||||
text = "Up"
|
||||
|
||||
[node name="DownLabel" type="Label" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls/VBox/MoveGrid" unique_id=100000009]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
@@ -326,6 +347,12 @@ custom_minimum_size = Vector2(150, 40)
|
||||
layout_mode = 2
|
||||
text = "S"
|
||||
|
||||
[node name="MoveDownAltBtn" type="Button" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls/VBox/MoveGrid" unique_id=100000110]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(150, 40)
|
||||
layout_mode = 2
|
||||
text = "Down"
|
||||
|
||||
[node name="LeftLabel" type="Label" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls/VBox/MoveGrid" unique_id=100000011]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
@@ -338,6 +365,12 @@ custom_minimum_size = Vector2(150, 40)
|
||||
layout_mode = 2
|
||||
text = "A"
|
||||
|
||||
[node name="MoveLeftAltBtn" type="Button" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls/VBox/MoveGrid" unique_id=100000112]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(150, 40)
|
||||
layout_mode = 2
|
||||
text = "Left"
|
||||
|
||||
[node name="RightLabel" type="Label" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls/VBox/MoveGrid" unique_id=100000013]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
@@ -350,6 +383,12 @@ custom_minimum_size = Vector2(150, 40)
|
||||
layout_mode = 2
|
||||
text = "D"
|
||||
|
||||
[node name="MoveRightAltBtn" type="Button" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls/VBox/MoveGrid" unique_id=100000114]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(150, 40)
|
||||
layout_mode = 2
|
||||
text = "Right"
|
||||
|
||||
[node name="PowerUpSection" type="PanelContainer" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls/VBox" unique_id=100000015]
|
||||
layout_mode = 2
|
||||
theme_override_styles/panel = SubResource("StyleBoxFlat_section_header")
|
||||
@@ -363,55 +402,25 @@ label_settings = SubResource("LabelSettings_section")
|
||||
layout_mode = 2
|
||||
theme_override_constants/h_separation = 20
|
||||
theme_override_constants/v_separation = 10
|
||||
columns = 2
|
||||
columns = 3
|
||||
|
||||
[node name="P1Label" type="Label" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls/VBox/PowerUpGrid" unique_id=100000018]
|
||||
[node name="UsePowerupLabel" type="Label" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls/VBox/PowerUpGrid" unique_id=100000118]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "PowerUp 1 (Speed)"
|
||||
text = "Activate PowerUp (Universal)"
|
||||
label_settings = SubResource("LabelSettings_heading")
|
||||
|
||||
[node name="Powerup1Btn" type="Button" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls/VBox/PowerUpGrid" unique_id=100000019]
|
||||
[node name="UsePowerupBtn" type="Button" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls/VBox/PowerUpGrid" unique_id=100000119]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(150, 40)
|
||||
layout_mode = 2
|
||||
text = "1"
|
||||
text = "F"
|
||||
|
||||
[node name="P2Label" type="Label" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls/VBox/PowerUpGrid" unique_id=100000020]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "PowerUp 2 (Freeze/Ghost)"
|
||||
label_settings = SubResource("LabelSettings_heading")
|
||||
|
||||
[node name="Powerup2Btn" type="Button" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls/VBox/PowerUpGrid" unique_id=100000021]
|
||||
[node name="UsePowerupAltBtn" type="Button" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls/VBox/PowerUpGrid" unique_id=100000120]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(150, 40)
|
||||
layout_mode = 2
|
||||
text = "2"
|
||||
|
||||
[node name="P3Label" type="Label" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls/VBox/PowerUpGrid" unique_id=100000022]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "PowerUp 3 (Wall)"
|
||||
label_settings = SubResource("LabelSettings_heading")
|
||||
|
||||
[node name="Powerup3Btn" type="Button" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls/VBox/PowerUpGrid" unique_id=100000023]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(150, 40)
|
||||
layout_mode = 2
|
||||
text = "3"
|
||||
|
||||
[node name="P4Label" type="Label" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls/VBox/PowerUpGrid" unique_id=100000024]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "PowerUp 4 (Ghost)"
|
||||
label_settings = SubResource("LabelSettings_heading")
|
||||
|
||||
[node name="Powerup4Btn" type="Button" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls/VBox/PowerUpGrid" unique_id=100000025]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(150, 40)
|
||||
layout_mode = 2
|
||||
text = "4"
|
||||
text = "N/A"
|
||||
|
||||
[node name="PowerBarSection" type="PanelContainer" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls/VBox" unique_id=100000026]
|
||||
layout_mode = 2
|
||||
@@ -426,7 +435,7 @@ label_settings = SubResource("LabelSettings_section")
|
||||
layout_mode = 2
|
||||
theme_override_constants/h_separation = 20
|
||||
theme_override_constants/v_separation = 10
|
||||
columns = 2
|
||||
columns = 3
|
||||
|
||||
[node name="AttackLabel" type="Label" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls/VBox/PowerBarGrid" unique_id=100000029]
|
||||
layout_mode = 2
|
||||
@@ -440,6 +449,12 @@ custom_minimum_size = Vector2(150, 40)
|
||||
layout_mode = 2
|
||||
text = "Q"
|
||||
|
||||
[node name="AttackModeAltBtn" type="Button" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls/VBox/PowerBarGrid" unique_id=100000130]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(150, 40)
|
||||
layout_mode = 2
|
||||
text = "N/A"
|
||||
|
||||
[node name="SpawnBoostLabel" type="Label" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls/VBox/PowerBarGrid" unique_id=100000031]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
@@ -452,6 +467,12 @@ custom_minimum_size = Vector2(150, 40)
|
||||
layout_mode = 2
|
||||
text = "E"
|
||||
|
||||
[node name="SpawnBoostAltBtn" type="Button" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls/VBox/PowerBarGrid" unique_id=100000132]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(150, 40)
|
||||
layout_mode = 2
|
||||
text = "N/A"
|
||||
|
||||
[node name="OtherSection" type="PanelContainer" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls/VBox" unique_id=100000033]
|
||||
layout_mode = 2
|
||||
theme_override_styles/panel = SubResource("StyleBoxFlat_section_header")
|
||||
@@ -465,7 +486,7 @@ label_settings = SubResource("LabelSettings_section")
|
||||
layout_mode = 2
|
||||
theme_override_constants/h_separation = 20
|
||||
theme_override_constants/v_separation = 10
|
||||
columns = 2
|
||||
columns = 3
|
||||
|
||||
[node name="GrabLabel" type="Label" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls/VBox/OtherGrid" unique_id=100000036]
|
||||
layout_mode = 2
|
||||
@@ -479,6 +500,12 @@ custom_minimum_size = Vector2(150, 40)
|
||||
layout_mode = 2
|
||||
text = "Space"
|
||||
|
||||
[node name="GrabAltBtn" type="Button" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls/VBox/OtherGrid" unique_id=100000137]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(150, 40)
|
||||
layout_mode = 2
|
||||
text = "N/A"
|
||||
|
||||
[node name="PutLabel" type="Label" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls/VBox/OtherGrid" unique_id=100000038]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
@@ -491,6 +518,12 @@ custom_minimum_size = Vector2(150, 40)
|
||||
layout_mode = 2
|
||||
text = "R"
|
||||
|
||||
[node name="PutAltBtn" type="Button" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls/VBox/OtherGrid" unique_id=100000139]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(150, 40)
|
||||
layout_mode = 2
|
||||
text = "N/A"
|
||||
|
||||
[node name="TektonGrabLabel" type="Label" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls/VBox/OtherGrid" unique_id=100000040]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
@@ -502,3 +535,9 @@ unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(150, 40)
|
||||
layout_mode = 2
|
||||
text = "G"
|
||||
|
||||
[node name="TektonGrabAltBtn" type="Button" parent="PanelContainer/VBoxContainer/ContentSection/TabContainer/Controls/VBox/OtherGrid" unique_id=100000141]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(150, 40)
|
||||
layout_mode = 2
|
||||
text = "N/A"
|
||||
|
||||
@@ -82,7 +82,7 @@ func _process(delta):
|
||||
player.highlight_cells_if_authorized(area, highlight_id)
|
||||
|
||||
func handle_unhandled_input(event):
|
||||
# Early return if not authorized human playersa
|
||||
# Early return if not authorized human player
|
||||
if not player.is_multiplayer_authority() or player.is_bot or player.is_in_group("Bots"):
|
||||
player.set_process_unhandled_input(false)
|
||||
return
|
||||
@@ -97,66 +97,37 @@ func handle_unhandled_input(event):
|
||||
|
||||
# --- Keyboard Shortcuts (Event-based) ---
|
||||
if event is InputEventKey and event.pressed and not event.echo:
|
||||
var mode = LobbyManager.get_game_mode()
|
||||
var is_sng = mode == GameMode.Mode.STOP_N_GO
|
||||
|
||||
# Safety check for SettingsManager
|
||||
if not SettingsManager:
|
||||
return
|
||||
|
||||
# Get dynamic keybinds
|
||||
var key_p1 = SettingsManager.get_control_keycode("powerup_1")
|
||||
var key_p2 = SettingsManager.get_control_keycode("powerup_2")
|
||||
var key_p3 = SettingsManager.get_control_keycode("powerup_3")
|
||||
var key_p4 = SettingsManager.get_control_keycode("powerup_4")
|
||||
|
||||
var ek = event.keycode
|
||||
|
||||
# Unified check for PowerUp keys
|
||||
if ek == key_p1:
|
||||
# Single Slot Logic: Find whatever powerup is currently set to 'true' and activate it
|
||||
var active_effect = -1
|
||||
if player.special_tiles_manager:
|
||||
for effect_key in player.special_tiles_manager.inventory:
|
||||
if player.special_tiles_manager.inventory[effect_key]:
|
||||
active_effect = effect_key
|
||||
break
|
||||
|
||||
if active_effect != -1:
|
||||
player.activate_powerup(active_effect)
|
||||
else:
|
||||
print("No powerup in slot 1 to activate.")
|
||||
|
||||
# KP Fallback
|
||||
elif ek == KEY_KP_1:
|
||||
var active_effect = -1
|
||||
if player.special_tiles_manager:
|
||||
for effect_key in player.special_tiles_manager.inventory:
|
||||
if player.special_tiles_manager.inventory[effect_key]:
|
||||
active_effect = effect_key
|
||||
break
|
||||
if active_effect != -1:
|
||||
player.activate_powerup(active_effect)
|
||||
|
||||
# Action Buttons (Remappable)
|
||||
elif ek == SettingsManager.get_control_keycode("attack_mode"):
|
||||
# 1. Unified check for POWER-UP Activation
|
||||
if event.is_action_pressed("use_powerup"):
|
||||
player.activate_held_powerup()
|
||||
get_viewport().set_input_as_handled()
|
||||
return
|
||||
|
||||
|
||||
# 3. Action Buttons (Remappable via InputMap)
|
||||
if event.is_action_pressed("action_knock_tekton"):
|
||||
if player.powerup_manager:
|
||||
player.powerup_manager.use_special_effect()
|
||||
if player.is_attack_mode and player.has_method("enter_attack_mode"):
|
||||
player.enter_attack_mode()
|
||||
get_viewport().set_input_as_handled()
|
||||
|
||||
elif ek == SettingsManager.get_control_keycode("spawn_boost"):
|
||||
elif event.is_action_pressed("spawn_boost"):
|
||||
if player.is_carrying_tekton and player.powerup_manager:
|
||||
if player.powerup_manager.has_method("spawn_boost_reward"):
|
||||
player.powerup_manager.spawn_boost_reward()
|
||||
get_viewport().set_input_as_handled()
|
||||
|
||||
elif ek == SettingsManager.get_control_keycode("tekton_grab"):
|
||||
elif event.is_action_pressed("action_grab_tekton"):
|
||||
if not player.is_carrying_tekton and player.powerup_manager:
|
||||
if player.powerup_manager.can_use_special():
|
||||
if player.powerup_manager.has_method("can_use_special"): # Corrected method name
|
||||
player.grab_tekton()
|
||||
|
||||
# Handle spawn point selection if not yet selected
|
||||
|
||||
get_viewport().set_input_as_handled()
|
||||
|
||||
# Handle spawn point selection if not yet selected
|
||||
if not player.spawn_point_selected and player.highlighted_spawn_points.size() > 0:
|
||||
if event is InputEventMouseButton and event.pressed and event.button_index == MOUSE_BUTTON_LEFT:
|
||||
|
||||
@@ -31,23 +31,33 @@ var settings = {
|
||||
},
|
||||
"controls": {
|
||||
"use_controller": false,
|
||||
# Movement (Keybinds are typically fixed to WASD/Arrows in Input Map, but we show them)
|
||||
# Movement
|
||||
"move_up": KEY_W,
|
||||
"move_up_alt": KEY_UP,
|
||||
"move_down": KEY_S,
|
||||
"move_down_alt": KEY_DOWN,
|
||||
"move_left": KEY_A,
|
||||
"move_left_alt": KEY_LEFT,
|
||||
"move_right": KEY_D,
|
||||
"move_right_alt": KEY_RIGHT,
|
||||
|
||||
# Actions
|
||||
"grab": KEY_SPACE,
|
||||
"grab_alt": KEY_J,
|
||||
"put": KEY_R,
|
||||
"put_alt": KEY_K,
|
||||
"tekton_grab": KEY_G,
|
||||
"tekton_grab_alt": KEY_L,
|
||||
|
||||
# Power-Up Controls
|
||||
"powerup_1": KEY_1,
|
||||
"powerup_2": KEY_2,
|
||||
"powerup_3": KEY_3,
|
||||
"powerup_4": KEY_4,
|
||||
"use_powerup": KEY_F,
|
||||
"use_powerup_alt": KEY_SHIFT,
|
||||
|
||||
# Power Bar Controls / Special
|
||||
"attack_mode": KEY_Q,
|
||||
"spawn_boost": KEY_E
|
||||
"attack_mode_alt": KEY_U,
|
||||
"spawn_boost": KEY_E,
|
||||
"spawn_boost_alt": KEY_I
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,6 +90,7 @@ func save_settings():
|
||||
func apply_all_settings():
|
||||
apply_video_settings()
|
||||
apply_audio_settings()
|
||||
apply_control_settings()
|
||||
emit_signal("settings_applied")
|
||||
|
||||
func apply_video_settings():
|
||||
@@ -149,9 +160,62 @@ func set_bus_volume(bus_name: String, volume_linear: float):
|
||||
AudioServer.set_bus_volume_db(bus_idx, linear_to_db(volume_linear))
|
||||
AudioServer.set_bus_mute(bus_idx, volume_linear <= 0.001)
|
||||
|
||||
func apply_control_settings():
|
||||
# Sync custom settings with InputMap
|
||||
var mapping = {
|
||||
"move_up": "move_north",
|
||||
"move_down": "move_south",
|
||||
"move_left": "move_west",
|
||||
"move_right": "move_east",
|
||||
"grab": "action_grab",
|
||||
"put": "action_put",
|
||||
"use_powerup": "use_powerup",
|
||||
"tekton_grab": "action_grab_tekton",
|
||||
"attack_mode": "action_knock_tekton",
|
||||
"spawn_boost": "spawn_boost"
|
||||
}
|
||||
|
||||
for setting_key in mapping.keys():
|
||||
var action_name = mapping[setting_key]
|
||||
if not InputMap.has_action(action_name):
|
||||
InputMap.add_action(action_name)
|
||||
|
||||
InputMap.action_erase_events(action_name)
|
||||
|
||||
# Add Primary
|
||||
var primary_key = settings.controls.get(setting_key)
|
||||
if primary_key:
|
||||
var event = InputEventKey.new()
|
||||
event.keycode = primary_key
|
||||
InputMap.action_add_event(action_name, event)
|
||||
|
||||
# Add Secondary
|
||||
var secondary_key = settings.controls.get(setting_key + "_alt")
|
||||
if secondary_key:
|
||||
var event = InputEventKey.new()
|
||||
event.keycode = secondary_key
|
||||
InputMap.action_add_event(action_name, event)
|
||||
|
||||
# Add Joypad defaults for movement
|
||||
if action_name.begins_with("move_"):
|
||||
var joy_axis = -1
|
||||
var axis_val = 0.0
|
||||
match action_name:
|
||||
"move_north": joy_axis = JOY_AXIS_LEFT_Y; axis_val = -1.0
|
||||
"move_south": joy_axis = JOY_AXIS_LEFT_Y; axis_val = 1.0
|
||||
"move_west": joy_axis = JOY_AXIS_LEFT_X; axis_val = -1.0
|
||||
"move_east": joy_axis = JOY_AXIS_LEFT_X; axis_val = 1.0
|
||||
|
||||
if joy_axis != -1:
|
||||
var joy_event = InputEventJoypadMotion.new()
|
||||
joy_event.axis = joy_axis
|
||||
joy_event.axis_value = axis_val
|
||||
InputMap.action_add_event(action_name, joy_event)
|
||||
|
||||
func set_control(action_name: String, keycode: int):
|
||||
if settings.controls.has(action_name):
|
||||
settings.controls[action_name] = keycode
|
||||
apply_control_settings() # Apply immediately
|
||||
emit_signal("control_remapped", action_name, keycode)
|
||||
save_settings()
|
||||
|
||||
|
||||
@@ -206,11 +206,6 @@ func activate_effect(effect: int, target_player: Node3D = null):
|
||||
print("PowerUp %s not found in inventory or false. Inventory: %s" % [effect, inventory])
|
||||
return
|
||||
|
||||
# Check Cooldown
|
||||
if powerup_cooldowns.get(effect, 0.0) > 0:
|
||||
print("PowerUp %s on cooldown." % SpecialEffect.keys()[effect])
|
||||
return
|
||||
|
||||
# Check Attack Mode Restriction
|
||||
if player.get("is_attack_mode") and effect == SpecialEffect.INVISIBLE_MODE:
|
||||
NotificationManager.send_message(player, "Cannot enter Ghost mode while in Attack Mode!", NotificationManager.MessageType.WARNING)
|
||||
@@ -221,16 +216,8 @@ func activate_effect(effect: int, target_player: Node3D = null):
|
||||
NotificationManager.send_message(player, "Cannot use this power while carrying a Tekton!", NotificationManager.MessageType.WARNING)
|
||||
return
|
||||
|
||||
# Calculate Cooldown based on Level
|
||||
var level = powerup_levels.get(effect, 1)
|
||||
# Linear Interp: Lvl 1 = 15s, Lvl 8 = 5s
|
||||
# Slope = (5 - 15) / (8 - 1) = -10 / 7 = -1.428...
|
||||
var cooldown_time = COOLDOWN_L1 + ((level - 1) * (COOLDOWN_L8 - COOLDOWN_L1) / 7.0)
|
||||
|
||||
powerup_cooldowns[effect] = cooldown_time
|
||||
emit_signal("cooldown_updated", effect, cooldown_time, cooldown_time)
|
||||
|
||||
print("[SpecialTiles] Player %s activated %s (Lvl %d). Cooldown: %.1fs" % [player.name, SpecialEffect.keys()[effect], level, cooldown_time])
|
||||
print("[SpecialTiles] Player %s activated %s (Lvl %d). No cooldown applied." % [player.name, SpecialEffect.keys()[effect], level])
|
||||
|
||||
match effect:
|
||||
SpecialEffect.FASTER_SPEED:
|
||||
@@ -555,19 +542,6 @@ func _check_for_icy_floor():
|
||||
pass
|
||||
|
||||
func _process(delta):
|
||||
# Update Cooldowns
|
||||
for effect in powerup_cooldowns.keys():
|
||||
if powerup_cooldowns[effect] > 0:
|
||||
powerup_cooldowns[effect] -= delta
|
||||
# Emit signal occasionally or only on change? Every frame might be too much for UI?
|
||||
# Optimization: Emit every 0.1s or if diff is significant?
|
||||
# For snappy UI text, frame sync is okay for local player.
|
||||
emit_signal("cooldown_updated", effect, powerup_cooldowns[effect], 0.0) # max unused for tick
|
||||
|
||||
if powerup_cooldowns[effect] <= 0:
|
||||
powerup_cooldowns[effect] = 0
|
||||
emit_signal("cooldown_updated", effect, 0, 0)
|
||||
|
||||
# Update Active Buffs (Speed)
|
||||
if active_buffs.has(SpecialEffect.FASTER_SPEED):
|
||||
active_buffs[SpecialEffect.FASTER_SPEED] -= delta
|
||||
|
||||
@@ -15,6 +15,7 @@ var attack_mode_button: Button # Renamed from special_button
|
||||
var spawn_boost_button: Button
|
||||
var settings_button: Button
|
||||
var tekton_grab_button: Button
|
||||
|
||||
@onready var SettingsManager = get_node_or_null("/root/SettingsManager")
|
||||
|
||||
# Settings - persisted to config file
|
||||
@@ -30,6 +31,7 @@ var button_positions: Dictionary = {
|
||||
"attack_mode": Vector2(-200, -80), # Renamed
|
||||
"spawn_boost": Vector2(-120, -80)
|
||||
}
|
||||
|
||||
var button_scale: float = 1.0
|
||||
|
||||
# Reference to main scene and player
|
||||
@@ -163,6 +165,7 @@ func _create_touch_ui():
|
||||
put_button = _find_or_create_action_button(actions_container, "Put", "📦", button_positions.put)
|
||||
|
||||
tekton_grab_button = _find_or_create_action_button(actions_container, "TektonGrab", "👋", Vector2(-280, -80))
|
||||
|
||||
|
||||
# Order: AttackMode, SpawnBoost, Grab, TektonGrab
|
||||
if attack_mode_button:
|
||||
@@ -184,6 +187,7 @@ func _create_touch_ui():
|
||||
actions_container.move_child(tekton_grab_button, 3)
|
||||
tekton_grab_button.icon = load("res://assets/graphics/touch_control/grab_tekton.png")
|
||||
tekton_grab_button.expand_icon = true
|
||||
|
||||
|
||||
# Hide Put Button
|
||||
if put_button:
|
||||
@@ -306,6 +310,7 @@ func _ensure_shortcut_label(btn: Button, button_name: String):
|
||||
"AttackMode": existing_lbl.text = SettingsManager.get_control_text("attack_mode")
|
||||
"SpawnBoost": existing_lbl.text = SettingsManager.get_control_text("spawn_boost")
|
||||
"TektonGrab": existing_lbl.text = SettingsManager.get_control_text("tekton_grab")
|
||||
|
||||
|
||||
print("[TouchControls] Updated %s shortcut label to: %s" % [button_name, existing_lbl.text])
|
||||
|
||||
@@ -338,6 +343,7 @@ func _ensure_shortcut_label(btn: Button, button_name: String):
|
||||
"AttackMode": shortcut_lbl.text = SettingsManager.get_control_text("attack_mode") if SettingsManager else "Q"
|
||||
"SpawnBoost": shortcut_lbl.text = SettingsManager.get_control_text("spawn_boost") if SettingsManager else "E"
|
||||
"TektonGrab": shortcut_lbl.text = SettingsManager.get_control_text("tekton_grab") if SettingsManager else "G"
|
||||
|
||||
|
||||
btn.add_child(shortcut_lbl)
|
||||
|
||||
@@ -358,6 +364,7 @@ func _on_button_pressed(button_name: String):
|
||||
"AttackMode": btn = attack_mode_button
|
||||
"SpawnBoost": btn = spawn_boost_button
|
||||
"TektonGrab": btn = tekton_grab_button
|
||||
|
||||
|
||||
if btn:
|
||||
var tween = create_tween()
|
||||
@@ -396,6 +403,7 @@ func _on_button_pressed(button_name: String):
|
||||
if local_player.has_method("grab_tekton"):
|
||||
local_player.grab_tekton()
|
||||
|
||||
|
||||
func _on_button_released(button_name: String):
|
||||
var btn: Button
|
||||
match button_name:
|
||||
@@ -404,6 +412,7 @@ func _on_button_released(button_name: String):
|
||||
"AttackMode": btn = attack_mode_button
|
||||
"SpawnBoost": btn = spawn_boost_button
|
||||
"TektonGrab": btn = tekton_grab_button
|
||||
|
||||
|
||||
if btn:
|
||||
var tween = create_tween()
|
||||
@@ -445,7 +454,12 @@ func _load_settings():
|
||||
attack_mode_pos = config.get_value("touch_controls", "special_position", Vector2(-200, -80))
|
||||
|
||||
var spawn_boost_pos = config.get_value("touch_controls", "spawn_boost_position", Vector2(-120, -80))
|
||||
button_positions = {"grab": grab_pos, "put": put_pos, "attack_mode": attack_mode_pos, "spawn_boost": spawn_boost_pos}
|
||||
button_positions = {
|
||||
"grab": grab_pos,
|
||||
"put": put_pos,
|
||||
"attack_mode": attack_mode_pos,
|
||||
"spawn_boost": spawn_boost_pos
|
||||
}
|
||||
|
||||
# Apply loaded settings
|
||||
_apply_settings()
|
||||
|
||||
@@ -146,7 +146,7 @@ func _update_btn_shortcut(_effect_id: int, btn: Button):
|
||||
return
|
||||
|
||||
# Show only Shortcut 1 as per single-slot request
|
||||
sc_lbl.text = "[%s]" % SettingsManager.get_control_text("powerup_1")
|
||||
sc_lbl.text = "[%s]" % SettingsManager.get_control_text("use_powerup")
|
||||
|
||||
func _on_btn_pressed(effect_id: int):
|
||||
print("[PowerUpUI] Clicked Button %d" % effect_id)
|
||||
@@ -228,21 +228,6 @@ func _on_powerup_unlocked(effect: int, level: int):
|
||||
else:
|
||||
print("[PowerUpUI] ERROR: Unlocked Effect %d but no UI button found! Keys: %s" % [effect, icon_containers.keys()])
|
||||
|
||||
func _on_cooldown_updated(effect: int, time_left: float, max_time: float):
|
||||
if icon_containers.has(effect):
|
||||
var btn = icon_containers[effect]
|
||||
var cd_lbl = btn.get_node_or_null("CooldownLabel")
|
||||
if cd_lbl:
|
||||
if time_left > 0:
|
||||
cd_lbl.text = "%d" % int(time_left)
|
||||
btn.disabled = true
|
||||
btn.modulate = Color(0.7, 0.7, 0.7, 0.8)
|
||||
else:
|
||||
cd_lbl.text = ""
|
||||
# Re-enable if we own it
|
||||
if special_manager_ref and special_manager_ref.inventory.get(effect, false):
|
||||
btn.disabled = false
|
||||
btn.modulate = Color.WHITE
|
||||
|
||||
func _on_inventory_updated(inventory: Dictionary):
|
||||
# Update UI icons (Only show ONE active slot as per user request)
|
||||
|
||||
@@ -105,16 +105,26 @@ func _connect_signals():
|
||||
# Close
|
||||
close_button.pressed.connect(func(): visible = false)
|
||||
|
||||
# Connect remapping buttons (exclude non-keybinds like use_controller)
|
||||
# Connect remapping buttons
|
||||
for action_name in SettingsManager.settings.controls.keys():
|
||||
if action_name == "use_controller":
|
||||
continue
|
||||
|
||||
var btn = get_node_or_null("%" + action_name.to_pascal_case() + "Btn")
|
||||
if btn:
|
||||
if btn.pressed.is_connected(_on_remap_button_pressed):
|
||||
btn.pressed.disconnect(_on_remap_button_pressed)
|
||||
btn.pressed.connect(_on_remap_button_pressed.bind(action_name))
|
||||
# Check Primary Button
|
||||
var primary_btn = get_node_or_null("%" + action_name.to_pascal_case() + "Btn")
|
||||
if primary_btn:
|
||||
if primary_btn.pressed.is_connected(_on_remap_button_pressed):
|
||||
primary_btn.pressed.disconnect(_on_remap_button_pressed)
|
||||
primary_btn.pressed.connect(_on_remap_button_pressed.bind(action_name))
|
||||
|
||||
# Check Alt Button
|
||||
if not action_name.ends_with("_alt"):
|
||||
var alt_action = action_name + "_alt"
|
||||
var alt_btn = get_node_or_null("%" + action_name.to_pascal_case() + "AltBtn")
|
||||
if alt_btn:
|
||||
if alt_btn.pressed.is_connected(_on_remap_button_pressed):
|
||||
alt_btn.pressed.disconnect(_on_remap_button_pressed)
|
||||
alt_btn.pressed.connect(_on_remap_button_pressed.bind(alt_action))
|
||||
|
||||
func _on_video_setting_changed(_unused = false):
|
||||
SettingsManager.settings.video.fullscreen = fullscreen_toggle.button_pressed
|
||||
|
||||
Reference in New Issue
Block a user