seated_vehicle.gd 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. class_name SeatedVehicle
  2. extends VehicleBody3D
  3. const CRASH_EFFECT: Resource = preload("res://effect/crash/crash.tscn")
  4. const MINIMAL_CRASH_SPEED: float = 1.0 # m2/s2
  5. var _current_commander: LocalInput = null
  6. var _current_driver: Walker
  7. var _has_collided: bool = false
  8. @onready var _seat: Node3D = find_child("*Seat")
  9. @onready var _doors: Array = find_children("*Door", "Node3D") # Array[Node3D]
  10. func _init() -> void:
  11. body_shape_entered.connect(_on_body_shape_entered)
  12. func _ready() -> void:
  13. assert(_doors.all(func(door): return door is Node3D))
  14. ## Signal a new driver
  15. func become_driven_by(driver: Walker) -> void:
  16. _current_driver = driver
  17. ## Make the vehicle responds to driver commands
  18. func drive_with(commander: LocalInput) -> void:
  19. commander.dir_changed.connect(_on_dir_changed)
  20. commander.main_action.connect(_on_main_action)
  21. commander.stop_action.connect(_on_stop_action)
  22. commander.analog_action.connect(_on_analog_action)
  23. _current_commander = commander
  24. func get_out() -> void:
  25. _current_commander.dir_changed.disconnect(_on_dir_changed)
  26. _current_commander.main_action.disconnect(_on_main_action)
  27. _current_commander.stop_action.disconnect(_on_stop_action)
  28. _current_commander.analog_action.disconnect(_on_analog_action)
  29. _current_commander = null
  30. _current_driver = null
  31. func _integrate_forces(state: PhysicsDirectBodyState3D) -> void:
  32. if state.get_contact_count() <= 0:
  33. return
  34. if _has_collided and linear_velocity.length_squared() > MINIMAL_CRASH_SPEED:
  35. _crash_on(state.get_contact_collider_position(0))
  36. _has_collided = false
  37. func _on_body_shape_entered(_body_rid, body: Node, _body_shape_index, _local_shape_index) -> void:
  38. if body.is_in_group("walker"):
  39. return
  40. _has_collided = true
  41. func _crash_on(pos: Vector3) -> void:
  42. var crash_effect: CrashEffect = CRASH_EFFECT.instantiate()
  43. crash_effect.position = pos
  44. get_parent_node_3d().add_child(crash_effect)
  45. func get_free_seat() -> Node3D:
  46. return _seat
  47. ## Can be overridden to return a specific door
  48. func get_door() -> Node3D:
  49. return _doors[0] as Node3D
  50. func get_closest_door(from: Vector3) -> Node3D:
  51. var distance = func distance_lambda(door: Node3D) -> float:
  52. return (door.get_position() - from).length_squared()
  53. var closest = func closest_lambda(previous_closest: Node3D, maybe_closest: Node3D) -> Node3D:
  54. if distance.call(maybe_closest) < distance.call(previous_closest):
  55. return maybe_closest
  56. else:
  57. return previous_closest
  58. return _doors.reduce(closest)
  59. ## Return current walker who is driving the vehicle, null if none
  60. func get_current_driver() -> Walker:
  61. return _current_driver
  62. ## Need to be overridden to react to direction changed
  63. func _on_dir_changed(_dir: Vector2) -> void:
  64. pass
  65. ## Need to be overridden to react to main action
  66. func _on_main_action(_pressed: bool) -> void:
  67. pass
  68. ## Need to be overridden to react to stop action
  69. func _on_stop_action(_pressed: bool) -> void:
  70. pass
  71. ## Need to be overridden to react to analog actions
  72. func _on_analog_action(_side: int, _value: float) -> void:
  73. pass