71 lines
2.4 KiB
GDScript
71 lines
2.4 KiB
GDScript
extends Area3D
|
|
class_name GripArea3D
|
|
|
|
## Signal emitted when a pawn successfully grabs this grip.
|
|
signal grabbed(pawn: CharacterPawn3D)
|
|
## Signal emitted when a pawn releases this grip.
|
|
signal released(pawn: CharacterPawn3D)
|
|
|
|
## Enum to differentiate grip types. Add more as needed.
|
|
enum GripType { POINT, BAR, LADDER_RUNG, SEAT_HANDLE }
|
|
|
|
## The type of this specific grip. Should be set by inheriting classes.
|
|
@export var grip_type: GripType
|
|
|
|
## Can more than one pawn grab this simultaneously? (Usually false)
|
|
@export var allow_multiple_occupants: bool = false
|
|
|
|
## Tracks the pawn currently holding this grip.
|
|
var occupant: CharacterPawn3D = null
|
|
|
|
# --- Virtual Methods (to be overridden by subclasses) ---
|
|
|
|
## Calculates the ideal global transform (position and orientation)
|
|
## the pawn should aim for when grabbing *this specific* grip.
|
|
## The pawn_global_pos helps determine the closest point on extended grips like bars.
|
|
func get_grip_transform(_pawn_global_pos: Vector3) -> Transform3D:
|
|
# Default implementation: return the grip's own global transform.
|
|
# Subclasses (like BarGrip) MUST override this for correct behavior.
|
|
return global_transform
|
|
|
|
## Determines the direction the pawn should push off from this grip.
|
|
## Usually the opposite of the surface normal or grip's forward direction.
|
|
func get_push_off_normal() -> Vector3:
|
|
# Default: Push directly away along the grip's local -Z axis (assuming Z points into the wall)
|
|
return -global_transform.basis.z.normalized()
|
|
|
|
# --- Public API ---
|
|
|
|
## Check if a specific pawn *can* grab this grip right now.
|
|
func can_grab(pawn: CharacterPawn3D) -> bool:
|
|
if not is_instance_valid(pawn):
|
|
return false
|
|
if occupant != null and not allow_multiple_occupants:
|
|
return false # Already occupied
|
|
# Add distance checks or other conditions if needed
|
|
return true
|
|
|
|
## Called by the pawn to initiate grabbing.
|
|
func grab(pawn: CharacterPawn3D):
|
|
if can_grab(pawn):
|
|
occupant = pawn
|
|
emit_signal("grabbed", pawn)
|
|
# Disable collision? Monitor input? Subclasses might override.
|
|
print(pawn.name, " grabbed ", name)
|
|
return true
|
|
return false
|
|
|
|
## Called by the pawn to release the grip.
|
|
func release(pawn: CharacterPawn3D):
|
|
if occupant == pawn:
|
|
var released_pawn = occupant
|
|
occupant = null
|
|
emit_signal("released", released_pawn)
|
|
print(pawn.name, " released ", name)
|
|
# Re-enable collision?
|
|
return true
|
|
return false
|
|
|
|
func is_occupied() -> bool:
|
|
return occupant != null
|