-
Notifications
You must be signed in to change notification settings - Fork 117
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Simplifies interaction input handling and refactors reload logic to be more performant #169
Merged
Phazorknight
merged 4 commits into
Phazorknight:main
from
aronand:PlayerInteractionComponentRefactor
Apr 30, 2024
Merged
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
9248f5a
refactor: Simplifies PlayerInteractionComponent
aronand 56c9425
refactor: Simplifies attempt_reload()
aronand 0e8d0aa
fix: Changes reload to account for reload ammount of ammo type
aronand 3ca9a08
refactor: Removes a ceili() that was used for testing
aronand File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -33,7 +33,7 @@ var is_changing_wieldables : bool = false #Used to avoid any input acitons while | |
@export var wieldable_nodes : Array[Node] | ||
@export var wieldable_container : Node3D | ||
# Various variables used for wieldable handling | ||
var equipped_wieldable_item = null | ||
var equipped_wieldable_item: WieldableItemPD = null | ||
var equipped_wieldable_node = null | ||
var is_wielding : bool | ||
var player_rid | ||
|
@@ -78,47 +78,29 @@ func interactive_object_exit(): | |
object_detected = false | ||
|
||
|
||
func _input(event): | ||
if event.is_action_pressed("interact"): | ||
|
||
# if carrying an object, drop it. | ||
if is_carrying and is_instance_valid(carried_object) and carried_object.input_map_action == "interact": | ||
carried_object.throw(throw_power) | ||
elif is_carrying and !is_instance_valid(carried_object): | ||
stop_carrying() | ||
|
||
# Checks if raycast is hitting an interactable object that has an interaction for this input action. | ||
if interaction_raycast.is_colliding(): | ||
interactable = interaction_raycast.get_collider() | ||
if interactable.is_in_group("interactable"): | ||
for node in interactable.interaction_nodes: | ||
if node.input_map_action == "interact": | ||
node.interact(self) | ||
interactive_object_exit() | ||
if is_wielding: | ||
equipped_wieldable_item.update_wieldable_data(self) | ||
|
||
|
||
if event.is_action_pressed("interact2"): | ||
func _input(event: InputEvent) -> void: | ||
if event.is_action_pressed("interact") or event.is_action_pressed("interact2"): | ||
var action: String = "interact" if event.is_action_pressed("interact") else "interact2" | ||
|
||
# if carrying an object, drop it. | ||
if is_carrying and is_instance_valid(carried_object) and carried_object.input_map_action == "interact2": | ||
if is_carrying and is_instance_valid(carried_object) and carried_object.input_map_action == action: | ||
carried_object.throw(throw_power) | ||
elif is_carrying and !is_instance_valid(carried_object): | ||
stop_carrying() | ||
|
||
|
||
|
||
# Checks if raycast is hitting an interactable object that has an interaction for this input action. | ||
if interaction_raycast.is_colliding(): | ||
interactable = interaction_raycast.get_collider() | ||
if interactable.is_in_group("interactable"): | ||
for node in interactable.interaction_nodes: | ||
if node.input_map_action == "interact2": | ||
node.interact(self) | ||
# This could be run each frame instead and the key be checked when finding an interactable, | ||
# which would be slower, but would easily allow any key to be used in the | ||
# interaction component and help reduce the nesting. | ||
interactable = interaction_raycast.get_collider() | ||
if interactable != null and interactable.is_in_group("interactable"): | ||
for node: InteractionComponent in interactable.interaction_nodes: | ||
if node.input_map_action == action: | ||
node.interact(self) | ||
interactive_object_exit() | ||
if is_wielding: | ||
equipped_wieldable_item.update_wieldable_data(self) | ||
|
||
|
||
|
||
# Wieldable primary Action Input | ||
if !get_parent().is_movement_paused: | ||
if is_wielding and Input.is_action_just_pressed("action_primary"): | ||
|
@@ -222,51 +204,56 @@ func attempt_action_secondary(is_released:bool): | |
|
||
|
||
func attempt_reload(): | ||
var inventory = get_parent().inventory_data | ||
var inventory: InventoryPD = get_parent().inventory_data | ||
# Some safety checks if reload should even be triggered. | ||
if inventory == null: | ||
print("Player inventory was null!") | ||
return | ||
|
||
if equipped_wieldable_node.animation_player.is_playing(): | ||
print("Can't interrupt current action / animation") | ||
return | ||
|
||
# If the item doesn't use reloading, return. | ||
if equipped_wieldable_item.no_reload: | ||
return | ||
var ammo_needed : int = abs(equipped_wieldable_item.charge_max - equipped_wieldable_item.charge_current) | ||
|
||
var ammo_needed: int = abs(equipped_wieldable_item.charge_max - equipped_wieldable_item.charge_current) | ||
if ammo_needed <= 0: | ||
print("Wieldable is fully charged.") | ||
return | ||
|
||
if equipped_wieldable_item.get_item_amount_in_inventory(equipped_wieldable_item.ammo_item_name) <= 0: | ||
print("You have no ammo for this wieldable.") | ||
return | ||
|
||
if !equipped_wieldable_node.animation_player.is_playing(): #Make sure reload isn't interrupting another animation. | ||
equipped_wieldable_node.reload() | ||
|
||
while ammo_needed > 0: | ||
if equipped_wieldable_item.get_item_amount_in_inventory(equipped_wieldable_item.ammo_item_name) <=0: | ||
print("No more ammo in inventory.") | ||
break | ||
for slot in inventory.inventory_slots: | ||
if slot != null and slot.inventory_item.name == equipped_wieldable_item.ammo_item_name and ammo_needed > 0: | ||
inventory.remove_item_from_stack(slot) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. InventoryPD.remove_item_from_stack() consumes one item at a time, making this loop take longer than is necessary. A possible refactor to it would be to allow the user to define the amount to remove as well. |
||
ammo_needed -= slot.inventory_item.reload_amount | ||
if ammo_needed < 0: | ||
ammo_needed = 0 | ||
|
||
equipped_wieldable_item.charge_current += slot.inventory_item.reload_amount | ||
if equipped_wieldable_item.charge_current > equipped_wieldable_item.charge_max: | ||
equipped_wieldable_item.charge_current = equipped_wieldable_item.charge_max | ||
|
||
print("RELOAD: Found ", slot.inventory_item.name, ". Removed one and added ", slot.inventory_item.reload_amount, " charge. Still needed: ", ammo_needed) | ||
|
||
inventory.inventory_updated.emit(inventory) | ||
equipped_wieldable_item.update_wieldable_data(self) | ||
|
||
if equipped_wieldable_node.animation_player.is_playing(): # Make sure reload isn't interrupting another animation. | ||
return | ||
|
||
equipped_wieldable_node.reload() | ||
|
||
for slot: InventorySlotPD in inventory.inventory_slots: | ||
if ammo_needed <= 0: | ||
break | ||
if slot == null or slot.inventory_item.name != equipped_wieldable_item.ammo_item_name: | ||
continue | ||
|
||
var ammo_used: int | ||
var slot_ammo: AmmoItemPD = slot.inventory_item | ||
var quantity_needed: int = ceili(float(ammo_needed) / slot_ammo.reload_amount) | ||
|
||
if slot.quantity <= quantity_needed: | ||
ammo_used = slot_ammo.reload_amount * slot.quantity | ||
inventory.remove_slot_data(slot) | ||
elif slot.quantity > quantity_needed: | ||
ammo_used = slot_ammo.reload_amount * quantity_needed | ||
slot.quantity -= quantity_needed | ||
|
||
equipped_wieldable_item.add(ammo_used) | ||
ammo_needed -= ammo_used | ||
|
||
inventory.inventory_updated.emit(inventory) | ||
equipped_wieldable_item.update_wieldable_data(self) | ||
|
||
|
||
func on_death(): | ||
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Input and InputEvent don't seem to have a way to return the action name, thus a bit hacky way of getting the action name. Needs a different solution if more interaction keys are introduced, or moving the interaction check to Node._process() instead, and/or checking action via:
This change alone seems to partially work, as the UI updates to reflect the new key, but the interaction itself doesn't seem to work with this change alone (EDIT: Probably because it's within a conditional checking for the two interaction keys 😄).