138 lines
4.5 KiB
GDScript
138 lines
4.5 KiB
GDScript
class_name Module extends OrbitalBody3D
|
|
|
|
@export var ship_name: String = "Unnamed Ship" # Only relevant for the root module
|
|
@export var hull_integrity: float = 100.0 # This could also be a calculated property later
|
|
|
|
const COMPONENT_GRID_SIZE = 64.0
|
|
|
|
func _ready():
|
|
super._ready()
|
|
|
|
child_entered_tree.connect(_on_child_entered_tree)
|
|
|
|
# Handle existing children (if any existed before ready)
|
|
for child in get_children():
|
|
_enforce_child_physics_mode(child)
|
|
|
|
func _on_child_entered_tree(node: Node):
|
|
_enforce_child_physics_mode(node)
|
|
|
|
func _enforce_child_physics_mode(node: Node):
|
|
# Only affect OrbitalBody3D children that are NOT the module itself
|
|
if node is OrbitalBody3D and node != self:
|
|
# We only enforce ANCHORED if this Module is a COMPOSITE (Root)
|
|
if physics_mode == PhysicsMode.COMPOSITE:
|
|
node.physics_mode = PhysicsMode.ANCHORED
|
|
# print("Module '%s' enforced ANCHORED mode on child '%s'" % [name, node.name])
|
|
|
|
# --- Helper functions to get children by type ---
|
|
func get_structural_pieces() -> Array[StructuralPiece]:
|
|
var pieces: Array[StructuralPiece]
|
|
for child in get_children():
|
|
if child is StructuralPiece:
|
|
pieces.append(child)
|
|
return pieces
|
|
|
|
func get_components() -> Array[Component]:
|
|
var components: Array[Component]
|
|
for child in get_children():
|
|
if child is Component:
|
|
components.append(child)
|
|
return components
|
|
|
|
func set_initial_velocity(velocity: Vector3):
|
|
linear_velocity = velocity
|
|
for piece in get_structural_pieces():
|
|
piece.linear_velocity = velocity
|
|
|
|
# --- UPDATED: Logic now uses the helper function ---
|
|
func get_attachment_points() -> Array:
|
|
var points = []
|
|
|
|
# Iterate through all StructuralPiece children directly
|
|
for piece in get_structural_pieces():
|
|
var piece_center = piece.global_position
|
|
|
|
# --- Hullplates (Interior Grid) ---
|
|
# if piece is Hullplate:
|
|
# for i in range(-1, 2, 2):
|
|
# for j in range(-1, 2, 2):
|
|
# var offset = Vector2(i, j) * (COMPONENT_GRID_SIZE / 2.0)
|
|
# points.append({
|
|
# "position": piece_center + offset,
|
|
# "type": Component.AttachmentType.INTERIOR_WALL,
|
|
# "piece": piece
|
|
# })
|
|
|
|
# # --- Bulkheads (Interior and Exterior Edge Attachments) ---
|
|
# elif piece is Bulkhead:
|
|
# var interior_point = piece_center + piece.transform.origin.y * (COMPONENT_GRID_SIZE / 2.0)
|
|
# points.append({
|
|
# "position": interior_point,
|
|
# "type": Component.AttachmentType.INTERIOR_WALL,
|
|
# "piece": piece
|
|
# })
|
|
|
|
# var exterior_point = piece_center - piece.transform.origin.y * (COMPONENT_GRID_SIZE / 2.0)
|
|
# points.append({
|
|
# "position": exterior_point,
|
|
# "type": Component.AttachmentType.EXTERIOR_HULL,
|
|
# "piece": piece
|
|
# })
|
|
|
|
return points
|
|
|
|
# --- This function remains largely the same ---
|
|
func attach_component(component: Component, global_pos: Vector3, parent_piece: StructuralPiece):
|
|
component.position = global_pos - global_position
|
|
component.attached_piece = parent_piece
|
|
add_child(component)
|
|
component.owner = self
|
|
component.physics_mode = PhysicsMode.ANCHORED
|
|
recalculate_physical_properties()
|
|
|
|
# --- UPDATED: Logic now uses the helper function ---
|
|
func _recalculate_collision_shape():
|
|
# This logic is much simpler now. We just iterate over relevant children.
|
|
var _combined_polygons = []
|
|
|
|
for piece in get_structural_pieces():
|
|
# You would use logic here to transform the piece's local shape
|
|
# into the Module's local space and add it to the list.
|
|
# Example Placeholder (requires full implementation):
|
|
# var piece_collision_shape = piece.find_child("CollisionShape2D")
|
|
# if piece_collision_shape:
|
|
# combined_polygons.append(piece_collision_shape.shape.points)
|
|
pass
|
|
|
|
# NOTE: The OrbitalBody3D's _update_mass_and_inertia() takes care of mass!
|
|
pass
|
|
|
|
# --- UPDATED: Clear module now iterates over all relevant children ---
|
|
func clear_module():
|
|
# We queue_free both structural pieces and components
|
|
for piece in get_structural_pieces():
|
|
piece.queue_free()
|
|
for component in get_components():
|
|
component.queue_free()
|
|
|
|
_recalculate_collision_shape()
|
|
|
|
# Damage can have a position for breach effects.
|
|
func take_damage(amount: float, damage_position: Vector2):
|
|
hull_integrity -= amount
|
|
print("%s hull integrity at %.1f%%" % [ship_name, hull_integrity])
|
|
|
|
if hull_integrity <= 0:
|
|
destroy_ship()
|
|
else:
|
|
# Find the LifeSupport component and check for a breach
|
|
for child in get_children():
|
|
if child is LifeSupport: # Assuming LifeSupport becomes a Component class
|
|
child.check_for_breach(damage_position, self)
|
|
|
|
func destroy_ship():
|
|
print("%s has been destroyed!" % ship_name)
|
|
# Add explosion/destruction effects here
|
|
queue_free()
|