feat: Implement core player entity with multiplayer state synchronization, character selection, movement, and manager-based input.
This commit is contained in:
+11
-6
@@ -13,6 +13,7 @@ var powerup_manager
|
|||||||
var score: int = 0
|
var score: int = 0
|
||||||
|
|
||||||
signal position_changed
|
signal position_changed
|
||||||
|
signal tekton_carried_changed(is_carrying)
|
||||||
|
|
||||||
# Display name (synced across network)
|
# Display name (synced across network)
|
||||||
var _display_name: String = ""
|
var _display_name: String = ""
|
||||||
@@ -46,6 +47,7 @@ var is_carrying_tekton: bool:
|
|||||||
get: return is_carried_tekton
|
get: return is_carried_tekton
|
||||||
set(value):
|
set(value):
|
||||||
is_carried_tekton = value
|
is_carried_tekton = value
|
||||||
|
emit_signal("tekton_carried_changed", value)
|
||||||
# Visual/Logic side effects if any
|
# Visual/Logic side effects if any
|
||||||
|
|
||||||
var is_carried_tekton: bool = false
|
var is_carried_tekton: bool = false
|
||||||
@@ -2126,20 +2128,19 @@ func update_active_player_indicator():
|
|||||||
sync_modulate(color) # Apply locally if offline/not ready
|
sync_modulate(color) # Apply locally if offline/not ready
|
||||||
|
|
||||||
func knock_tekton():
|
func knock_tekton():
|
||||||
# ... legacy or helper function ...
|
|
||||||
pass
|
|
||||||
if not is_multiplayer_authority() or is_frozen or is_stop_frozen:
|
if not is_multiplayer_authority() or is_frozen or is_stop_frozen:
|
||||||
return
|
return
|
||||||
|
|
||||||
# Requirement: Full Powerup Bar
|
# Requirement: Full Powerup Bar (or we are already in knock mode)
|
||||||
if not powerup_manager or not powerup_manager.can_use_special():
|
if not is_knock_mode and (not powerup_manager or not powerup_manager.can_use_special()):
|
||||||
NotificationManager.send_message(self , "Need Full Boost to Knock!", NotificationManager.MessageType.WARNING)
|
NotificationManager.send_message(self , "Need Full Boost to Knock!", NotificationManager.MessageType.WARNING)
|
||||||
return
|
return
|
||||||
|
|
||||||
var tekton = _find_nearby_tekton()
|
var tekton = _find_nearby_tekton()
|
||||||
if tekton:
|
if tekton:
|
||||||
# Consume Boost
|
# Consume Boost if we haven't already (or just consume it now if we are in mode)
|
||||||
powerup_manager.consume_boost(100.0)
|
if powerup_manager:
|
||||||
|
powerup_manager.consume_boost(100.0)
|
||||||
|
|
||||||
if is_multiplayer_authority():
|
if is_multiplayer_authority():
|
||||||
rpc("sync_knock_tekton", tekton.get_path())
|
rpc("sync_knock_tekton", tekton.get_path())
|
||||||
@@ -2148,6 +2149,10 @@ func knock_tekton():
|
|||||||
is_knock_mode = false
|
is_knock_mode = false
|
||||||
NotificationManager.send_message(self, "Knock Successful!", NotificationManager.MessageType.POWERUP)
|
NotificationManager.send_message(self, "Knock Successful!", NotificationManager.MessageType.POWERUP)
|
||||||
update_active_player_indicator()
|
update_active_player_indicator()
|
||||||
|
else:
|
||||||
|
# If we called knock_tekton but nothing was nearby, maybe we just enter the mode?
|
||||||
|
# But usually this is called by movement_manager which knows something is there.
|
||||||
|
pass
|
||||||
|
|
||||||
@rpc("any_peer", "call_local", "reliable")
|
@rpc("any_peer", "call_local", "reliable")
|
||||||
func sync_knock_tekton(tekton_path: NodePath):
|
func sync_knock_tekton(tekton_path: NodePath):
|
||||||
|
|||||||
@@ -138,12 +138,10 @@ func handle_unhandled_input(event):
|
|||||||
player.grab_tekton()
|
player.grab_tekton()
|
||||||
KEY_B:
|
KEY_B:
|
||||||
if player.powerup_manager and player.powerup_manager.can_use_special():
|
if player.powerup_manager and player.powerup_manager.can_use_special():
|
||||||
if player.has_method("enter_knock_mode"):
|
if player.has_method("_find_nearby_tekton") and player._find_nearby_tekton():
|
||||||
player.enter_knock_mode()
|
|
||||||
player.powerup_manager.reset_boost()
|
|
||||||
else:
|
|
||||||
player.knock_tekton()
|
player.knock_tekton()
|
||||||
player.powerup_manager.reset_boost()
|
elif player.has_method("enter_knock_mode"):
|
||||||
|
player.enter_knock_mode()
|
||||||
|
|
||||||
# Handle spawn point selection if not yet selected
|
# Handle spawn point selection if not yet selected
|
||||||
|
|
||||||
|
|||||||
@@ -44,6 +44,10 @@ func initialize(p_main: Node3D):
|
|||||||
func set_player(p_player: Node3D):
|
func set_player(p_player: Node3D):
|
||||||
local_player = p_player
|
local_player = p_player
|
||||||
|
|
||||||
|
# Connect to Tekton status updates
|
||||||
|
if not local_player.tekton_carried_changed.is_connected(_on_tekton_carried_changed):
|
||||||
|
local_player.tekton_carried_changed.connect(_on_tekton_carried_changed)
|
||||||
|
|
||||||
# Connect to PowerUpManager if it exists (for boost updates)
|
# Connect to PowerUpManager if it exists (for boost updates)
|
||||||
var powerup_mgr = local_player.get_node_or_null("PowerUpManager")
|
var powerup_mgr = local_player.get_node_or_null("PowerUpManager")
|
||||||
if powerup_mgr:
|
if powerup_mgr:
|
||||||
@@ -351,18 +355,21 @@ func _on_button_pressed(button_name: String):
|
|||||||
"TektonKnock":
|
"TektonKnock":
|
||||||
var powerup_mgr = local_player.get_node_or_null("PowerUpManager")
|
var powerup_mgr = local_player.get_node_or_null("PowerUpManager")
|
||||||
if powerup_mgr and powerup_mgr.can_use_special():
|
if powerup_mgr and powerup_mgr.can_use_special():
|
||||||
if local_player.has_method("enter_knock_mode"):
|
# Proactive: If nearby, knock immediately. Else enter mode.
|
||||||
local_player.enter_knock_mode()
|
if local_player.has_method("_find_nearby_tekton") and local_player._find_nearby_tekton():
|
||||||
powerup_mgr.reset_boost()
|
|
||||||
elif local_player.has_method("knock_tekton"):
|
|
||||||
local_player.knock_tekton()
|
local_player.knock_tekton()
|
||||||
powerup_mgr.reset_boost()
|
elif local_player.has_method("enter_knock_mode"):
|
||||||
|
local_player.enter_knock_mode()
|
||||||
"TektonThrow":
|
"TektonThrow":
|
||||||
var powerup_mgr = local_player.get_node_or_null("PowerUpManager")
|
if local_player.is_carrying_tekton:
|
||||||
if powerup_mgr and powerup_mgr.can_use_special():
|
var powerup_mgr = local_player.get_node_or_null("PowerUpManager")
|
||||||
if local_player.has_method("throw_tekton"):
|
if powerup_mgr and powerup_mgr.can_use_special():
|
||||||
local_player.throw_tekton()
|
if local_player.has_method("throw_tekton"):
|
||||||
powerup_mgr.reset_boost()
|
local_player.throw_tekton()
|
||||||
|
powerup_mgr.reset_boost()
|
||||||
|
else:
|
||||||
|
if local_player.has_method("grab_tekton"):
|
||||||
|
local_player.grab_tekton()
|
||||||
|
|
||||||
func _on_button_released(button_name: String):
|
func _on_button_released(button_name: String):
|
||||||
var btn: Button
|
var btn: Button
|
||||||
@@ -543,7 +550,16 @@ func _on_boost_points_changed(current_points: int, max_points: int):
|
|||||||
_update_boost_button_state(attack_mode_button, is_full)
|
_update_boost_button_state(attack_mode_button, is_full)
|
||||||
_update_boost_button_state(spawn_boost_button, is_full)
|
_update_boost_button_state(spawn_boost_button, is_full)
|
||||||
_update_boost_button_state(tekton_knock_button, is_full)
|
_update_boost_button_state(tekton_knock_button, is_full)
|
||||||
_update_boost_button_state(tekton_throw_button, is_full)
|
|
||||||
|
# TektonThrow can be used for "Grab" even without full boost
|
||||||
|
var can_throw_or_grab = is_full or (local_player and not local_player.is_carrying_tekton)
|
||||||
|
_update_boost_button_state(tekton_throw_button, can_throw_or_grab)
|
||||||
|
|
||||||
|
func _on_tekton_carried_changed(_is_carrying: bool):
|
||||||
|
# Refresh button states when player grabs/throws a tekton
|
||||||
|
var powerup_mgr = local_player.get_node_or_null("PowerUpManager")
|
||||||
|
if powerup_mgr:
|
||||||
|
_on_boost_points_changed(powerup_mgr.current_boost, powerup_mgr.MAX_BOOST)
|
||||||
|
|
||||||
func _update_boost_button_state(btn: Button, is_enabled: bool):
|
func _update_boost_button_state(btn: Button, is_enabled: bool):
|
||||||
if not btn: return
|
if not btn: return
|
||||||
|
|||||||
Reference in New Issue
Block a user