diff --git a/actors/ai/ai_navigation.gd b/actors/ai/ai_navigation.gd index f360eaed..fb485965 100644 --- a/actors/ai/ai_navigation.gd +++ b/actors/ai/ai_navigation.gd @@ -1,7 +1,9 @@ extends Node3D class_name AINavigation -## Automatically navigates a [RigidBody3D] to a particular position using a [RigidBodyThruster] and a [RigidBodyDirection]. +## Automatically navigates a [Ship] to a particular position using a [RigidBodyThruster] and a [RigidBodyDirection]. +## +## [b]This script expects the parent node to be a [Ship].[/b] @export var rigid_body_thruster: RigidBodyThruster @export var rigid_body_direction: RigidBodyDirection @@ -43,7 +45,7 @@ var navigating: bool: else: self._state = State.IDLE -@onready var _rigid_body := rigid_body_thruster.get_parent() as RigidBody3D +@onready var _ship := get_parent() as Ship var _state: State = State.IDLE var _target_direction: Vector3 @@ -56,7 +58,7 @@ func _ready() -> void: self.navigating = true func _physics_process(_delta: float) -> void: - if not self.navigating: + if not self.navigating or self._ship.controls_disabled(): return match self._state: @@ -76,7 +78,7 @@ func _idle() -> void: self.rigid_body_thruster.throttle = 0.0 func _rotate_to_accelerate() -> void: - self._target_direction = (self.destination - self._rigid_body.global_position).normalized() + self._target_direction = (self.destination - self._ship.global_position).normalized() self.rigid_body_direction.direction = self._target_direction self.rigid_body_thruster.throttle = 0.0 @@ -86,19 +88,19 @@ func _rotate_to_accelerate() -> void: func _accelerate_toward_destination() -> void: self.rigid_body_thruster.throttle = 1.0 - var distance_to_destination := self._rigid_body.global_position.distance_to(self.destination) - var stopping_distance := self._calculate_stopping_distance(self._rigid_body.linear_velocity.length()) + var distance_to_destination := self._ship.global_position.distance_to(self.destination) + var stopping_distance := self._calculate_stopping_distance(self._ship.linear_velocity.length()) # Account for rotation time in stopping distance - var rotation_time := self._estimate_rotation_time(-self._rigid_body.linear_velocity.normalized()) - var rotation_distance := self._rigid_body.linear_velocity.length() * rotation_time + var rotation_time := self._estimate_rotation_time(-self._ship.linear_velocity.normalized()) + var rotation_distance := self._ship.linear_velocity.length() * rotation_time stopping_distance += rotation_distance if stopping_distance >= distance_to_destination: self._state = State.ROTATING_TO_DECELERATE func _rotate_to_decelerate() -> void: - self._target_direction = -self._rigid_body.linear_velocity.normalized() + self._target_direction = -self._ship.linear_velocity.normalized() self.rigid_body_direction.direction = self._target_direction self.rigid_body_thruster.throttle = 0.0 @@ -106,7 +108,7 @@ func _rotate_to_decelerate() -> void: self._state = State.DECELERATING_TO_STOP func _decelerate_to_stop() -> void: - self._target_direction = -self._rigid_body.linear_velocity.normalized() + self._target_direction = -self._ship.linear_velocity.normalized() self.rigid_body_direction.direction = self._target_direction if self._pointing_in_direction(self._target_direction): @@ -114,8 +116,8 @@ func _decelerate_to_stop() -> void: else: self.rigid_body_thruster.throttle = 0.0 - var distance_to_destination := self._rigid_body.global_position.distance_to(self.destination) - if distance_to_destination <= self.arrival_distance_tolerance and self._rigid_body.linear_velocity.length() <= self.stopping_velocity_tolerance: + var distance_to_destination := self._ship.global_position.distance_to(self.destination) + if distance_to_destination <= self.arrival_distance_tolerance and self._ship.linear_velocity.length() <= self.stopping_velocity_tolerance: self.navigating = false self.rigid_body_thruster.throttle = 0.0 @@ -123,15 +125,15 @@ func _decelerate_to_stop() -> void: self.destination_reached.emit(self) func _pointing_in_direction(direction: Vector3) -> bool: - var current_direction := -self._rigid_body.global_transform.basis.z + var current_direction := -self._ship.global_transform.basis.z return current_direction.angle_to(direction) <= self.direction_tolerance func _calculate_stopping_distance(current_velocity: float) -> float: - var acceleration := self.rigid_body_thruster.thruster.thrust_force / self._rigid_body.mass + var acceleration := self.rigid_body_thruster.thruster.thrust_force / self._ship.mass return (current_velocity * current_velocity) / (2 * acceleration) func _estimate_rotation_time(target_direction: Vector3) -> float: - var current_direction := -self._rigid_body.global_transform.basis.z + var current_direction := -self._ship.global_transform.basis.z var angle_to_rotate := current_direction.angle_to(target_direction) return angle_to_rotate / self.rigid_body_direction.spin_thruster.turning_rate diff --git a/actors/ai/archetypes/pirate.gd b/actors/ai/archetypes/pirate.gd index 063a77d3..767806fe 100644 --- a/actors/ai/archetypes/pirate.gd +++ b/actors/ai/archetypes/pirate.gd @@ -59,6 +59,10 @@ func _select_new_patrol_target() -> void: self._patrol_target = MathUtils.random_unit_vector() * self.patrol_radius func _physics_process(delta: float) -> void: + if self._ship.controls_disabled(): + self._ship.set_firing(false) + return + if not self._ship.targeting_system.target: self._current_state = State.PATROL @@ -85,7 +89,7 @@ func _pointing_in_direction(direction: Vector3) -> bool: return current_direction.angle_to(direction) <= self.direction_tolerance func _patrol_behavior(_delta: float) -> void: - self._set_firing(false) + self._ship.set_firing(false) var target := self._find_closest_target() self._ship.targeting_system.target = target @@ -105,12 +109,12 @@ func _patrol_behavior(_delta: float) -> void: func _engage_behavior(_delta: float) -> void: var target := self._ship.targeting_system.target if not target: - self._set_firing(false) + self._ship.set_firing(false) self._current_state = State.PATROL return if not self._pointing_in_direction(self._desired_direction()): - self._set_firing(false) + self._ship.set_firing(false) self._ship.rigid_body_thruster.throttle = 0.0 return @@ -127,10 +131,10 @@ func _engage_behavior(_delta: float) -> void: else: self._ship.rigid_body_thruster.throttle = 0.0 - self._set_firing(distance <= self.fire_range) + self._ship.set_firing(distance <= self.fire_range) func _retreat_behavior(_delta: float) -> void: - self._set_firing(false) + self._ship.set_firing(false) var target := self._ship.targeting_system.target if not target: @@ -146,10 +150,6 @@ func _retreat_behavior(_delta: float) -> void: if distance >= self.preferred_distance: self._current_state = State.ENGAGE -func _set_firing(firing: bool) -> void: - for weapon_mount in self._ship.weapon_mounts: - weapon_mount.firing = firing - func _find_closest_target() -> CombatObject: var available_targets := self._ship.targeting_system.get_available_targets() available_targets.erase(self._ship.combat_object) diff --git a/actors/player.gd b/actors/player.gd index 9e06ec5d..a174691f 100644 --- a/actors/player.gd +++ b/actors/player.gd @@ -26,6 +26,9 @@ signal shield_changed(player: Player, shield: Shield) ## Fires when the ship's power level changes. signal power_changed(player: Player, battery: Battery) +## Fires when the ship's heat level changes. +signal heat_changed(player: Player, heat_sink: HeatSink) + ## Fires when the player's ship is destroyed. signal ship_destroyed(player: Player) @@ -107,6 +110,7 @@ func _ready() -> void: self.ship.hull.changed.connect(_on_hull_changed) self.ship.hull.hull_destroyed.connect(_on_hull_destroyed) self.ship.battery.changed.connect(_on_power_changed) + self.ship.heat_sink.changed.connect(_on_heat_changed) self.ship.targeting_system.target_changed.connect(_on_target_changed) InputEventBroadcaster.input_event.connect(_on_broadcasted_input_event) @@ -114,6 +118,7 @@ func _ready() -> void: # Initial notifications so the UI can update. self._on_hull_changed() self._on_power_changed() + self._on_heat_changed() if self.ship.shield: self.ship.shield.changed.connect(_on_shield_changed) @@ -145,6 +150,9 @@ func _on_shield_changed() -> void: func _on_power_changed() -> void: self.power_changed.emit(self, self.ship.battery) +func _on_heat_changed() -> void: + self.heat_changed.emit(self, self.ship.heat_sink) + func _on_hull_destroyed(hull: Hull) -> void: assert(hull == self.ship.hull, "Received hull_destroyed signal from incorrect hull") self.ship_destroyed.emit(self) @@ -206,7 +214,7 @@ func _closest_landing_target() -> Celestial: return nearest_celestial func _unhandled_input(event: InputEvent) -> void: - if self.ship.hyperdrive_system.jumping: + if self.ship.controls_disabled(): return var motion_event := event as InputEventMouseMotion @@ -321,6 +329,7 @@ func _depart_from_port(port: Port) -> void: if self.ship.shield: self.ship.shield.integrity = self.ship.shield.max_integrity self.ship.hull.integrity = self.ship.hull.max_integrity + self.ship.heat_sink.heat = 0 self._reset_controls() self._reset_velocity() @@ -358,16 +367,18 @@ func _mouse_joystick_input() -> Vector2: return offset.normalized() * normalized_distance func _physics_process(_delta: float) -> void: - if not self.ship.hyperdrive_system or self.ship.hyperdrive_system.jumping: + if self.ship.controls_disabled(): + self.ship.set_firing(false) + self.ship.rigid_body_thruster.throttle = 0.0 + self.ship.rigid_body_direction.direction = Vector3.ZERO + self._rigid_body_turner.turning = 0.0 return if Input.is_action_pressed("jump"): self._jump_to_hyperspace() return - var firing := Input.is_action_pressed("fire") - for weapon_mount in self.ship.weapon_mounts: - weapon_mount.firing = firing + self.ship.set_firing(Input.is_action_pressed("fire")) match UserPreferences.control_scheme: UserPreferences.ControlScheme.RELATIVE: diff --git a/mechanics/combat/combat_object.gd b/mechanics/combat/combat_object.gd index e6567700..37a31ecf 100644 --- a/mechanics/combat/combat_object.gd +++ b/mechanics/combat/combat_object.gd @@ -49,6 +49,9 @@ var hull: Hull: ## An optional shield protecting the object. var shield: Shield +## A heat sink to dump heat to. +var heat_sink: HeatSink + ## Fires when this object is targeted, or stops being targeted, by a new [TargetingSystem]. ## ## See [method get_targeted_by] @@ -106,6 +109,8 @@ func damage(dmg: Damage) -> void: if apply_hull_dmg_pct > 0.0: self.hull.integrity -= dmg.hull_damage * apply_hull_dmg_pct + + self.heat_sink.heat += dmg.heat ## Checks whether [param node] contains a [CombatObject], and damages it if so. static func damage_combat_object_inside(node: Node, dmg: Damage) -> bool: diff --git a/mechanics/combat/damage.gd b/mechanics/combat/damage.gd index 5c596b8a..8ed714bf 100644 --- a/mechanics/combat/damage.gd +++ b/mechanics/combat/damage.gd @@ -12,3 +12,8 @@ class_name Damage ## ## If a damageable object has shields, damage is applied to the shields first, then the hull, in proportion. @export var hull_damage: float + +## How much heat will be inflicted on the target. +## +## Heat is not directly damaging, but can result in a ship becoming disabled. +@export var heat: float diff --git a/mechanics/combat/weapons/blaster/blaster.tres b/mechanics/combat/weapons/blaster/blaster.tres index 0e9225b8..8a696c2e 100644 --- a/mechanics/combat/weapons/blaster/blaster.tres +++ b/mechanics/combat/weapons/blaster/blaster.tres @@ -8,4 +8,5 @@ script = ExtResource("1_h0068") fire_interval = 0.2 fire_force = 2.0 power_consumption = 5.0 +heat = 10.0 projectile = ExtResource("1_upvwn") diff --git a/mechanics/combat/weapons/blaster/blaster_bolt.tscn b/mechanics/combat/weapons/blaster/blaster_bolt.tscn index ae4468ae..3f211571 100644 --- a/mechanics/combat/weapons/blaster/blaster_bolt.tscn +++ b/mechanics/combat/weapons/blaster/blaster_bolt.tscn @@ -10,6 +10,7 @@ script = ExtResource("2_eoln0") shield_damage = 80.0 hull_damage = 40.0 +heat = 20.0 [sub_resource type="CapsuleShape3D" id="CapsuleShape3D_5b1vh"] diff --git a/mechanics/combat/weapons/weapon.gd b/mechanics/combat/weapons/weapon.gd index 9de13add..8475de1e 100644 --- a/mechanics/combat/weapons/weapon.gd +++ b/mechanics/combat/weapons/weapon.gd @@ -14,5 +14,8 @@ class_name Weapon ## If the containing ship's available power is less than this amount, the weapon won't be able to fire. @export var power_consumption: float +## The amount of heat generated when firing the weapon. +@export var heat: float + ## The projectile that this weapon fires. The root node [b]must[/b] be a [RigidBody3D]. @export var projectile: PackedScene diff --git a/mechanics/combat/weapons/weapon_mount.gd b/mechanics/combat/weapons/weapon_mount.gd index eda6e6bd..42791a0f 100644 --- a/mechanics/combat/weapons/weapon_mount.gd +++ b/mechanics/combat/weapons/weapon_mount.gd @@ -22,6 +22,9 @@ class_name WeaponMount ## The [Battery] to power the weapon from. var battery: Battery +## The [HeatSink] to dump heat into. +var heat_sink: HeatSink + ## Set to true when this weapon should automatically fire; set to false to stop firing. var firing: bool = false: set(value): @@ -67,3 +70,4 @@ func _physics_process(_delta: float) -> void: projectile_instance.apply_central_impulse(projectile_instance.transform.basis * self.weapon.fire_force * Vector3.FORWARD) self._last_fired_usec = now + self.heat_sink.heat += self.weapon.heat diff --git a/mechanics/heat/heat_sink.gd b/mechanics/heat/heat_sink.gd new file mode 100644 index 00000000..3e72f45b --- /dev/null +++ b/mechanics/heat/heat_sink.gd @@ -0,0 +1,27 @@ +extends SaveableResource +class_name HeatSink + +## Accumulates heat that is generated by ship functions and inflicted in combat. +## +## When heat exceeds the maximum capacity of the heat sink, the ship's controls become inoperable. + +## The maximum heat capacity for this sink. +@export var max_heat: float: + set(value): + assert(value >= 0.0, "Heat capacity must be non-negative") + if is_equal_approx(max_heat, value): + return + + max_heat = value + self.emit_changed() + +## The current heat level. +## +## Unlike other, similar mechanics, this value can exceed [member max_heat], at which point the ship controls are disabled. +@export var heat: float: + set(value): + if is_equal_approx(heat, value): + return + + heat = maxf(value, 0.0) + self.emit_changed() diff --git a/mechanics/heat/radiator.gd b/mechanics/heat/radiator.gd new file mode 100644 index 00000000..08f542c7 --- /dev/null +++ b/mechanics/heat/radiator.gd @@ -0,0 +1,12 @@ +extends Node3D +class_name Radiator + +## Radiates heat away from a [HeatSink] into vacuum. + +## How much heat is radiated away per second. +@export var rate: float + +var heat_sink: HeatSink + +func _physics_process(delta: float) -> void: + self.heat_sink.heat -= self.rate * delta diff --git a/mechanics/outfitting/outfit.gd b/mechanics/outfitting/outfit.gd index 261f5dbe..1d56f713 100644 --- a/mechanics/outfitting/outfit.gd +++ b/mechanics/outfitting/outfit.gd @@ -56,6 +56,11 @@ class_name Outfit ## If negative, the output of the ship's [PowerGenerator] will be reduced by this amount. The outfit cannot be installed if the [PowerGenerator] is insufficient. @export var modified_power_generation: float = 0 +## A modification this outfit makes to heat sink capacity. +## +## If negative, the capacity of the ship's [HeatSink] will be reduced. The outfit cannot be installed if the available heat capacity is insufficient. +@export var modified_heat_capacity: float = 0 + ## A weapon provided by this outfit. @export var weapon: Weapon @@ -110,6 +115,11 @@ func can_install_onto_ship(ship: Ship) -> bool: if generator.rate_of_power < self.modified_power_generation: return false + + if not is_zero_approx(self.modified_heat_capacity): + # Include some epsilon so the ship doesn't end up overheated and inoperable + if ship.heat_sink.max_heat + self.modified_heat_capacity < 0.01: + return false if self.weapon: var mount_available := false @@ -143,6 +153,7 @@ func apply_to_ship(ship: Ship) -> void: ship.shield.recharge_rate *= self.shield_recharge_multiplier ship.hull.max_integrity += self.modified_hull_capacity + ship.heat_sink.max_heat += self.modified_heat_capacity if ship.power_management_unit.power_generator: ship.power_management_unit.power_generator.rate_of_power += self.modified_power_generation @@ -175,6 +186,7 @@ func remove_from_ship(ship: Ship) -> void: ship.shield.recharge_rate /= self.shield_recharge_multiplier ship.hull.max_integrity -= self.modified_hull_capacity + ship.heat_sink.max_heat -= self.modified_heat_capacity if ship.power_management_unit.power_generator: ship.power_management_unit.power_generator.rate_of_power -= self.modified_power_generation @@ -220,6 +232,9 @@ func get_effects() -> PackedStringArray: effects.push_back("[b]Fire interval:[/b] %ss" % [self.weapon.fire_interval]) effects.push_back("[b]Power consumption per shot:[/b] %s" % [self.weapon.power_consumption]) + if not is_zero_approx(self.modified_heat_capacity): + effects.push_back("[b]Heat:[/b] %s" % self._signed_string(-self.modified_heat_capacity)) + return effects func _signed_string(value: float) -> String: diff --git a/mechanics/outfitting/outfits/blaster.tres b/mechanics/outfitting/outfits/blaster.tres index 26876a67..8f4f99a6 100644 --- a/mechanics/outfitting/outfits/blaster.tres +++ b/mechanics/outfitting/outfits/blaster.tres @@ -10,8 +10,11 @@ description = "Commonly installed by traders heading into more dangerous reaches mass = 2.0 price_in_credits = 12000.0 modified_cargo_capacity = 0.0 +modified_passenger_capacity = 0 modified_fuel_capacity = 0.0 +modified_hull_capacity = 0.0 modified_shield_capacity = 0.0 shield_recharge_multiplier = 1.0 modified_power_generation = -1.0 +modified_heat_capacity = 0.0 weapon = ExtResource("2_womhg") diff --git a/mechanics/outfitting/outfits/cargo_pod.tres b/mechanics/outfitting/outfits/cargo_pod.tres index 8e69248c..5e42f323 100644 --- a/mechanics/outfitting/outfits/cargo_pod.tres +++ b/mechanics/outfitting/outfits/cargo_pod.tres @@ -9,7 +9,10 @@ description = "Traders frequently like to expand their available cargo space, to mass = 10.0 price_in_credits = 7000.0 modified_cargo_capacity = 10.0 +modified_passenger_capacity = 0 modified_fuel_capacity = -1.0 +modified_hull_capacity = 0.0 modified_shield_capacity = 0.0 shield_recharge_multiplier = 1.0 modified_power_generation = 0.0 +modified_heat_capacity = -5.0 diff --git a/mechanics/outfitting/outfits/fuel_tank.tres b/mechanics/outfitting/outfits/fuel_tank.tres index b9c5b78f..64d2c4ce 100644 --- a/mechanics/outfitting/outfits/fuel_tank.tres +++ b/mechanics/outfitting/outfits/fuel_tank.tres @@ -9,7 +9,10 @@ description = "For the spacefaring captain making long haul journeys, extra fuel mass = 1.0 price_in_credits = 5000.0 modified_cargo_capacity = 0.0 +modified_passenger_capacity = 0 modified_fuel_capacity = 1.0 +modified_hull_capacity = 0.0 modified_shield_capacity = 0.0 shield_recharge_multiplier = 1.0 modified_power_generation = -1.0 +modified_heat_capacity = -5.0 diff --git a/mechanics/outfitting/outfits/hull_plating.tres b/mechanics/outfitting/outfits/hull_plating.tres index e47769fd..54952af4 100644 --- a/mechanics/outfitting/outfits/hull_plating.tres +++ b/mechanics/outfitting/outfits/hull_plating.tres @@ -15,3 +15,4 @@ modified_hull_capacity = 20.0 modified_shield_capacity = 0.0 shield_recharge_multiplier = 1.0 modified_power_generation = 0.0 +modified_heat_capacity = -10.0 diff --git a/mechanics/outfitting/outfits/shield_booster.tres b/mechanics/outfitting/outfits/shield_booster.tres index 90cf848d..09b00449 100644 --- a/mechanics/outfitting/outfits/shield_booster.tres +++ b/mechanics/outfitting/outfits/shield_booster.tres @@ -15,3 +15,4 @@ modified_hull_capacity = 0.0 modified_shield_capacity = 50.0 shield_recharge_multiplier = 1.1 modified_power_generation = -3.0 +modified_heat_capacity = -10.0 diff --git a/mechanics/physics/rigid_body_thruster.gd b/mechanics/physics/rigid_body_thruster.gd index 1ec9e6d7..1a945af6 100644 --- a/mechanics/physics/rigid_body_thruster.gd +++ b/mechanics/physics/rigid_body_thruster.gd @@ -23,6 +23,9 @@ class_name RigidBodyThruster ## The [Battery] to power the thruster from. var battery: Battery +## The [HeatSink] to dump heat to. +var heat_sink: HeatSink + ## The current level of throttle (where 1.0 is full throttle), which corresponds to the magnitude of the thrust to apply, as well as the amount of power to be consumed. var throttle: float: set(value): @@ -75,6 +78,8 @@ func _physics_process(delta: float) -> void: var desired_power := self.thruster.power_consumption_rate * self.throttle * delta var power_consumed := self.battery.consume_up_to(desired_power) var magnitude := self.throttle * (power_consumed / desired_power) + + self.heat_sink.heat += self.thruster.heat_generation_rate * magnitude * delta self._animate_transparency(1.0 - magnitude) self._rigid_body.apply_central_force(self._rigid_body.transform.basis * Vector3.FORWARD * self.thruster.thrust_force * magnitude) diff --git a/mechanics/physics/thruster.gd b/mechanics/physics/thruster.gd index 08361124..8887e1c9 100644 --- a/mechanics/physics/thruster.gd +++ b/mechanics/physics/thruster.gd @@ -8,3 +8,6 @@ class_name Thruster ## How much power the thruster consumes per second when thrusting at full power. @export var power_consumption_rate: float + +## How much heat the thruster generates per second when thrusting at full power. +@export var heat_generation_rate: float diff --git a/mechanics/power/power_generator.gd b/mechanics/power/power_generator.gd index b60ba346..aa883c86 100644 --- a/mechanics/power/power_generator.gd +++ b/mechanics/power/power_generator.gd @@ -12,3 +12,13 @@ class_name PowerGenerator rate_of_power = value self.emit_changed() + +## How much heat this generator produces per second. +@export var rate_of_heat: float: + set(value): + assert(value >= 0.0, "Heat generation rate must be non-negative") + if is_equal_approx(rate_of_heat, value): + return + + rate_of_heat = value + self.emit_changed() diff --git a/mechanics/power/power_management_unit.gd b/mechanics/power/power_management_unit.gd index 0b33d937..8ae6789f 100644 --- a/mechanics/power/power_management_unit.gd +++ b/mechanics/power/power_management_unit.gd @@ -7,13 +7,14 @@ class_name PowerManagementUnit @export var power_generator: PowerGenerator: set(value): power_generator = value - self.set_physics_process(self.battery != null and power_generator != null) + self.set_physics_process(power_generator != null) ## A battery storing power. -var battery: Battery: - set(value): - battery = value - self.set_physics_process(battery != null and self.power_generator != null) +var battery: Battery + +## A sink for absorbing heat. +var heat_sink: HeatSink func _physics_process(delta: float) -> void: self.battery.recharge(self.power_generator.rate_of_power * delta) + self.heat_sink.heat += self.power_generator.rate_of_heat * delta diff --git a/screens/game/game.tscn b/screens/game/game.tscn index 8d65bd9c..67a8a965 100644 --- a/screens/game/game.tscn +++ b/screens/game/game.tscn @@ -1,7 +1,8 @@ -[gd_scene load_steps=77 format=3 uid="uid://sunhu71swcs2"] +[gd_scene load_steps=80 format=3 uid="uid://sunhu71swcs2"] [ext_resource type="Environment" uid="uid://b7t3opwr35xen" path="res://fx/environment.tres" id="1_pqled"] [ext_resource type="Script" path="res://mechanics/hyperspace/hyperspace_scene_switcher.gd" id="4_yyrkm"] +[ext_resource type="Script" path="res://mechanics/heat/heat_sink.gd" id="6_hv4l5"] [ext_resource type="Material" uid="uid://tpd4rufhhe4h" path="res://fx/starfield/starfield.tres" id="7_gr6ce"] [ext_resource type="Script" path="res://mechanics/economy/passenger_quarters.gd" id="8_bkgwh"] [ext_resource type="Script" path="res://fx/starfield/starfield_parallax.gd" id="8_ueist"] @@ -78,6 +79,12 @@ script = ExtResource("15_sjw8q") max_power = 300.0 power = 300.0 +[sub_resource type="Resource" id="Resource_dr1mv"] +resource_local_to_scene = true +script = ExtResource("6_hv4l5") +max_heat = 400.0 +heat = 0.0 + [sub_resource type="Resource" id="Resource_rcbfw"] resource_local_to_scene = true script = ExtResource("14_bcf1o") @@ -99,6 +106,12 @@ script = ExtResource("15_sjw8q") max_power = 100.0 power = 100.0 +[sub_resource type="Resource" id="Resource_s186x"] +resource_local_to_scene = true +script = ExtResource("6_hv4l5") +max_heat = 100.0 +heat = 0.0 + [sub_resource type="Resource" id="Resource_on6n3"] script = ExtResource("11_ag0i7") max_volume = 10.0 @@ -182,6 +195,14 @@ message_log = NodePath("../InGameGUI/MarginContainer/HBoxContainer/MessageLog") hull = SubResource("Resource_p7sh0") shield = SubResource("Resource_dhynb") battery = SubResource("Resource_ubt7x") +heat_sink = SubResource("Resource_dr1mv") +outfits = null + +[node name="AINavigation" parent="HyperspaceSceneSwitcher/Sol/Freighter" index="8"] +direction_tolerance = null +arrival_distance_tolerance = null +stopping_velocity_tolerance = null +auto_start = null [node name="PlayerCorvette" parent="HyperspaceSceneSwitcher/Sol" node_paths=PackedStringArray("hyperdrive_system") instance=ExtResource("12_bj83b")] physics_material_override = null @@ -189,9 +210,11 @@ hyperdrive_system = NodePath("HyperdriveSystem") hull = SubResource("Resource_rcbfw") shield = SubResource("Resource_7husa") battery = SubResource("Resource_i5r8g") +heat_sink = SubResource("Resource_s186x") cargo_hold = SubResource("Resource_on6n3") passenger_quarters = SubResource("Resource_ksma2") hyperdrive = SubResource("Resource_un4md") +outfits = null [node name="CombatObject" parent="HyperspaceSceneSwitcher/Sol/PlayerCorvette" index="3" node_paths=PackedStringArray("targeted_sound")] targeted_sound = NodePath("../Player/TargetedSound") @@ -230,6 +253,9 @@ message_log = NodePath("../../../../../InGameGUI/MarginContainer/HBoxContainer/M script = ExtResource("15_cfr6f") rigid_body_thruster = NodePath("../RigidBodyThruster") rigid_body_direction = NodePath("../RigidBodyDirection") +direction_tolerance = null +destination = null +arrival_distance_tolerance = null stopping_velocity_tolerance = 0.5 auto_start = false @@ -362,6 +388,8 @@ mouse_filter = 2 [node name="MinimapContainer" type="PanelContainer" parent="InGameGUI/MarginContainer/HBoxContainer/Sidebar"] custom_minimum_size = Vector2(100, 100) layout_mode = 2 +size_flags_horizontal = 4 +size_flags_vertical = 4 mouse_filter = 2 theme_override_styles/panel = SubResource("StyleBoxTexture_7gqif") @@ -465,15 +493,16 @@ theme_override_font_sizes/font_size = 10 text = "Ship systems" uppercase = true -[node name="PlayerVitals" type="GridContainer" parent="InGameGUI/MarginContainer/HBoxContainer/Sidebar/PlayerVitalsContainer/VBoxContainer" node_paths=PackedStringArray("hull_bar", "shield_bar", "power_bar")] +[node name="PlayerVitals" type="GridContainer" parent="InGameGUI/MarginContainer/HBoxContainer/Sidebar/PlayerVitalsContainer/VBoxContainer" node_paths=PackedStringArray("hull_bar", "shield_bar", "power_bar", "heat_bar")] layout_mode = 2 size_flags_horizontal = 4 -theme_override_constants/h_separation = 16 -columns = 3 +theme_override_constants/h_separation = 8 +columns = 4 script = ExtResource("27_mar8l") hull_bar = NodePath("HullBar") shield_bar = NodePath("ShieldBar") power_bar = NodePath("PowerBar") +heat_bar = NodePath("HeatBar") [node name="HullLabel" type="Label" parent="InGameGUI/MarginContainer/HBoxContainer/Sidebar/PlayerVitalsContainer/VBoxContainer/PlayerVitals"] layout_mode = 2 @@ -493,6 +522,12 @@ theme_type_variation = &"HUDLabel" text = "PWR" horizontal_alignment = 1 +[node name="HeatLabel" type="Label" parent="InGameGUI/MarginContainer/HBoxContainer/Sidebar/PlayerVitalsContainer/VBoxContainer/PlayerVitals"] +layout_mode = 2 +theme_type_variation = &"HUDLabel" +text = "HEAT" +horizontal_alignment = 1 + [node name="HullBar" parent="InGameGUI/MarginContainer/HBoxContainer/Sidebar/PlayerVitalsContainer/VBoxContainer/PlayerVitals" instance=ExtResource("28_7l7fi")] layout_mode = 2 @@ -502,6 +537,9 @@ layout_mode = 2 [node name="PowerBar" parent="InGameGUI/MarginContainer/HBoxContainer/Sidebar/PlayerVitalsContainer/VBoxContainer/PlayerVitals" instance=ExtResource("28_7l7fi")] layout_mode = 2 +[node name="HeatBar" parent="InGameGUI/MarginContainer/HBoxContainer/Sidebar/PlayerVitalsContainer/VBoxContainer/PlayerVitals" instance=ExtResource("28_7l7fi")] +layout_mode = 2 + [node name="TargetInfoContainer" type="PanelContainer" parent="InGameGUI/MarginContainer/HBoxContainer/Sidebar" node_paths=PackedStringArray("target_label", "target_viewport", "hull_bar", "shield_bar", "pick_sound")] custom_minimum_size = Vector2(200, 194) layout_mode = 2 @@ -670,6 +708,7 @@ script = ExtResource("37_e11x7") [connection signal="jump_destination_loaded" from="HyperspaceSceneSwitcher" to="InGameGUI/MarginContainer/HBoxContainer/Sidebar/SystemName" method="_on_jump_destination_loaded"] [connection signal="jump_path_changed" from="HyperspaceSceneSwitcher/Sol/PlayerCorvette/HyperdriveSystem" to="InGameGUI/MarginContainer/HBoxContainer/Sidebar/PanelContainer/VBoxContainer/JumpDestinationName" method="_on_jump_path_changed"] [connection signal="jumping_changed" from="HyperspaceSceneSwitcher/Sol/PlayerCorvette/HyperdriveSystem" to="MainCameraTransform/MainCamera/HyperspaceEffect" method="_on_jumping_changed"] +[connection signal="heat_changed" from="HyperspaceSceneSwitcher/Sol/PlayerCorvette/Player" to="InGameGUI/MarginContainer/HBoxContainer/Sidebar/PlayerVitalsContainer/VBoxContainer/PlayerVitals" method="_on_player_heat_changed"] [connection signal="hull_changed" from="HyperspaceSceneSwitcher/Sol/PlayerCorvette/Player" to="InGameGUI/MarginContainer/HBoxContainer/Sidebar/PlayerVitalsContainer/VBoxContainer/PlayerVitals" method="_on_player_hull_changed"] [connection signal="hyperdrive_changed" from="HyperspaceSceneSwitcher/Sol/PlayerCorvette/Player" to="InGameGUI/MarginContainer/HBoxContainer/Sidebar/PanelContainer/VBoxContainer/FuelBar" method="_on_player_hyperdrive_changed"] [connection signal="landing_target_changed" from="HyperspaceSceneSwitcher/Sol/PlayerCorvette/Player" to="InGameGUI/MarginContainer/HBoxContainer/Sidebar/LandingTargetName" method="_on_landing_target_changed"] diff --git a/screens/game/hud/player_vitals.gd b/screens/game/hud/player_vitals.gd index 60f3bc76..dc2a55e8 100644 --- a/screens/game/hud/player_vitals.gd +++ b/screens/game/hud/player_vitals.gd @@ -3,6 +3,7 @@ extends GridContainer @export var hull_bar: VitalsFillBar @export var shield_bar: VitalsFillBar @export var power_bar: VitalsFillBar +@export var heat_bar: VitalsFillBar func _on_player_hull_changed(_player: Player, hull: Hull) -> void: self.hull_bar.max_value = hull.max_integrity @@ -15,3 +16,7 @@ func _on_player_shield_changed(_player: Player, shield: Shield) -> void: func _on_player_power_changed(_player: Player, battery: Battery) -> void: self.power_bar.max_value = maxf(1.0, battery.max_power) self.power_bar.value = battery.power + +func _on_player_heat_changed(_player: Player, heat_sink: HeatSink) -> void: + self.heat_bar.max_value = heat_sink.max_heat + self.heat_bar.value = heat_sink.heat diff --git a/ships/corvette01/corvette01.tscn b/ships/corvette01/corvette01.tscn index 4ac6e13c..3beca2e5 100644 --- a/ships/corvette01/corvette01.tscn +++ b/ships/corvette01/corvette01.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=32 format=3 uid="uid://dsuln1s4j366a"] +[gd_scene load_steps=35 format=3 uid="uid://dsuln1s4j366a"] [ext_resource type="PackedScene" uid="uid://c0eitctnmmfyq" path="res://ships/ship.tscn" id="1_cmgif"] [ext_resource type="ArrayMesh" uid="uid://40a23nnu1j37" path="res://ships/corvette01/corvette01_mesh.tres" id="1_yacfo"] @@ -8,6 +8,7 @@ [ext_resource type="AudioStream" uid="uid://5iqc5o8p02l5" path="res://ships/audio/THRUSTER LOW.wav" id="4_xrdjv"] [ext_resource type="Script" path="res://mechanics/economy/cargo_hold.gd" id="5_kmsu1"] [ext_resource type="Script" path="res://mechanics/combat/hull.gd" id="5_uewxf"] +[ext_resource type="Script" path="res://mechanics/heat/heat_sink.gd" id="5_vh7sc"] [ext_resource type="Script" path="res://mechanics/economy/passenger_quarters.gd" id="6_a0tra"] [ext_resource type="Script" path="res://mechanics/hyperspace/hyperdrive.gd" id="6_wd6xk"] [ext_resource type="Script" path="res://mechanics/physics/spin_thruster.gd" id="8_4hne6"] @@ -20,6 +21,7 @@ [ext_resource type="Script" path="res://mechanics/combat/weapons/weapon_mount.gd" id="15_douxu"] [ext_resource type="Resource" uid="uid://cw1tu3qdxdgfi" path="res://mechanics/combat/weapons/blaster/blaster.tres" id="16_17v50"] [ext_resource type="Script" path="res://mechanics/physics/rigid_body_cargo.gd" id="19_f3xy8"] +[ext_resource type="Script" path="res://mechanics/heat/radiator.gd" id="22_o7v2x"] [sub_resource type="Resource" id="Resource_5twpq"] resource_local_to_scene = true @@ -42,6 +44,12 @@ script = ExtResource("9_8bmn0") max_power = 100.0 power = 100.0 +[sub_resource type="Resource" id="Resource_8nr6w"] +resource_local_to_scene = true +script = ExtResource("5_vh7sc") +max_heat = 100.0 +heat = 0.0 + [sub_resource type="Resource" id="Resource_qh2kh"] resource_local_to_scene = true script = ExtResource("5_kmsu1") @@ -76,19 +84,23 @@ power_consumption_rate = 5.0 script = ExtResource("10_ffov7") thrust_force = 200.0 power_consumption_rate = 8.0 +heat_generation_rate = 2.0 [sub_resource type="Resource" id="Resource_csuav"] script = ExtResource("13_n5lfa") rate_of_power = 5.0 +rate_of_heat = 1.0 -[node name="Corvette" node_paths=PackedStringArray("shield_recharger", "weapon_mounts", "rigid_body_cargo") instance=ExtResource("1_cmgif")] +[node name="Corvette" node_paths=PackedStringArray("radiator", "shield_recharger", "weapon_mounts", "rigid_body_cargo") instance=ExtResource("1_cmgif")] mass = 10.0 +radiator = NodePath("Radiator") shield_recharger = NodePath("ShieldRecharger") weapon_mounts = [NodePath("Blaster"), NodePath("LeftWeaponMount"), NodePath("RightWeaponMount")] rigid_body_cargo = NodePath("RigidBodyCargo") hull = SubResource("Resource_5twpq") shield = SubResource("Resource_alskh") battery = SubResource("Resource_ftwkb") +heat_sink = SubResource("Resource_8nr6w") cargo_hold = SubResource("Resource_qh2kh") passenger_quarters = SubResource("Resource_7u7qk") hyperdrive = SubResource("Resource_br02e") @@ -160,4 +172,8 @@ transform = Transform3D(1, -1.21652e-31, 0, -1.21652e-31, 1, 0, 0, 0, 1, 0.199, script = ExtResource("15_douxu") fire_offset = 0.5 +[node name="Radiator" type="Node3D" parent="." index="13"] +script = ExtResource("22_o7v2x") +rate = 4.0 + [editable path="CombatObject/TargetOverlay"] diff --git a/ships/freighter/freighter.tscn b/ships/freighter/freighter.tscn index 2c84f808..eaf8f40c 100644 --- a/ships/freighter/freighter.tscn +++ b/ships/freighter/freighter.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=30 format=3 uid="uid://dqrul5pyjbxjc"] +[gd_scene load_steps=33 format=3 uid="uid://dqrul5pyjbxjc"] [ext_resource type="PackedScene" uid="uid://c0eitctnmmfyq" path="res://ships/ship.tscn" id="1_r6j4w"] [ext_resource type="PackedScene" uid="uid://co3rcmgurh2gb" path="res://ships/freighter/freighter.glb" id="2_qliud"] @@ -7,6 +7,7 @@ [ext_resource type="Script" path="res://mechanics/combat/shield.gd" id="3_ti3ck"] [ext_resource type="Script" path="res://mechanics/combat/hull.gd" id="4_n1hc8"] [ext_resource type="Shader" path="res://fx/shield/shield.gdshader" id="4_unqrx"] +[ext_resource type="Script" path="res://mechanics/heat/heat_sink.gd" id="5_0dh7p"] [ext_resource type="PackedScene" uid="uid://cdyo800b83x5i" path="res://fx/explosions/explosion002.tscn" id="5_bgpiu"] [ext_resource type="Script" path="res://mechanics/combat/shield_recharger.gd" id="5_s17ip"] [ext_resource type="Script" path="res://mechanics/physics/spin_thruster.gd" id="8_ngx4b"] @@ -16,6 +17,7 @@ [ext_resource type="AudioStream" uid="uid://5iqc5o8p02l5" path="res://ships/audio/THRUSTER LOW.wav" id="11_5uksh"] [ext_resource type="PackedScene" uid="uid://dbc2usdmy5wf3" path="res://fx/engine_glow/engine_glow.tscn" id="12_8a1b6"] [ext_resource type="Shader" path="res://fx/engine_glow/engine_glow.gdshader" id="13_0qykh"] +[ext_resource type="Script" path="res://mechanics/heat/radiator.gd" id="18_jmrpj"] [sub_resource type="Resource" id="Resource_t05wf"] resource_local_to_scene = true @@ -38,6 +40,12 @@ script = ExtResource("8_w8qvs") max_power = 300.0 power = 300.0 +[sub_resource type="Resource" id="Resource_10qq0"] +resource_local_to_scene = true +script = ExtResource("5_0dh7p") +max_heat = 400.0 +heat = 0.0 + [sub_resource type="CylinderShape3D" id="CylinderShape3D_23xxj"] height = 3.88505 radius = 0.973661 @@ -74,6 +82,7 @@ power_consumption_rate = 5.0 script = ExtResource("10_8eiax") thrust_force = 60.0 power_consumption_rate = 5.0 +heat_generation_rate = 5.0 [sub_resource type="ShaderMaterial" id="ShaderMaterial_jl6dq"] render_priority = 0 @@ -89,13 +98,16 @@ orientation = 1 [sub_resource type="Resource" id="Resource_ku887"] script = ExtResource("9_277l5") rate_of_power = 3.0 +rate_of_heat = 1.0 -[node name="Freighter" node_paths=PackedStringArray("shield_recharger") instance=ExtResource("1_r6j4w")] +[node name="Freighter" node_paths=PackedStringArray("radiator", "shield_recharger") instance=ExtResource("1_r6j4w")] mass = 150.0 +radiator = NodePath("Radiator") shield_recharger = NodePath("ShieldRecharger") hull = SubResource("Resource_t05wf") shield = SubResource("Resource_ln8ln") battery = SubResource("Resource_lo26u") +heat_sink = SubResource("Resource_10qq0") [node name="Model" parent="." index="0" instance=ExtResource("2_qliud")] transform = Transform3D(-1, 3.48787e-16, -8.74228e-08, 3.48787e-16, 1, -3.48787e-16, 8.74228e-08, -3.48787e-16, -1, 0, 0, 0) @@ -153,4 +165,8 @@ power_generator = SubResource("Resource_ku887") [node name="ShieldRecharger" type="Node3D" parent="." index="7"] script = ExtResource("5_s17ip") +[node name="Radiator" type="Node3D" parent="." index="8"] +script = ExtResource("18_jmrpj") +rate = 6.0 + [editable path="CombatObject/TargetOverlay"] diff --git a/ships/frigate03/frigate03.tscn b/ships/frigate03/frigate03.tscn index 270e2e8d..1582d091 100644 --- a/ships/frigate03/frigate03.tscn +++ b/ships/frigate03/frigate03.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=32 format=3 uid="uid://cdvbol3xj7jr5"] +[gd_scene load_steps=35 format=3 uid="uid://cdvbol3xj7jr5"] [ext_resource type="PackedScene" uid="uid://c0eitctnmmfyq" path="res://ships/ship.tscn" id="1_w0piq"] [ext_resource type="PackedScene" uid="uid://cdyo800b83x5i" path="res://fx/explosions/explosion002.tscn" id="2_xcc1t"] @@ -6,6 +6,7 @@ [ext_resource type="PackedScene" uid="uid://gcf8fo4e36c4" path="res://ships/frigate03/target_view.tscn" id="3_bcien"] [ext_resource type="Script" path="res://mechanics/combat/hull.gd" id="4_6j23n"] [ext_resource type="AudioStream" uid="uid://5iqc5o8p02l5" path="res://ships/audio/THRUSTER LOW.wav" id="4_xrdjv"] +[ext_resource type="Script" path="res://mechanics/heat/heat_sink.gd" id="5_e20uk"] [ext_resource type="ArrayMesh" uid="uid://c2y60nf8m25ka" path="res://ships/frigate03/frigate03_mesh.tres" id="6_g7bx0"] [ext_resource type="Script" path="res://mechanics/physics/spin_thruster.gd" id="8_74gsh"] [ext_resource type="PackedScene" uid="uid://dbc2usdmy5wf3" path="res://fx/engine_glow/engine_glow.tscn" id="8_ibdmx"] @@ -18,6 +19,7 @@ [ext_resource type="Script" path="res://mechanics/combat/shield_recharger.gd" id="15_ik8m4"] [ext_resource type="Script" path="res://mechanics/combat/weapons/weapon_mount.gd" id="16_xra8r"] [ext_resource type="Resource" uid="uid://cw1tu3qdxdgfi" path="res://mechanics/combat/weapons/blaster/blaster.tres" id="17_h1u5w"] +[ext_resource type="Script" path="res://mechanics/heat/radiator.gd" id="20_0bm6k"] [sub_resource type="Resource" id="Resource_am8dk"] resource_local_to_scene = true @@ -40,6 +42,12 @@ script = ExtResource("9_7c238") max_power = 300.0 power = 300.0 +[sub_resource type="Resource" id="Resource_kynkv"] +resource_local_to_scene = true +script = ExtResource("5_e20uk") +max_heat = 200.0 +heat = 0.0 + [sub_resource type="BoxShape3D" id="BoxShape3D_ou7uu"] size = Vector3(1.98299, 0.832642, 1.04932) @@ -75,6 +83,7 @@ power_consumption_rate = 5.0 script = ExtResource("10_6f48k") thrust_force = 100.0 power_consumption_rate = 5.0 +heat_generation_rate = 3.0 [sub_resource type="ShaderMaterial" id="ShaderMaterial_rurkt"] render_priority = 0 @@ -90,14 +99,17 @@ orientation = 1 [sub_resource type="Resource" id="Resource_0m3cu"] script = ExtResource("14_ccaul") rate_of_power = 2.0 +rate_of_heat = 1.0 -[node name="Frigate" node_paths=PackedStringArray("shield_recharger", "weapon_mounts") instance=ExtResource("1_w0piq")] +[node name="Frigate" node_paths=PackedStringArray("radiator", "shield_recharger", "weapon_mounts") instance=ExtResource("1_w0piq")] mass = 100.0 +radiator = NodePath("Radiator") shield_recharger = NodePath("ShieldRecharger") weapon_mounts = [NodePath("Blaster")] hull = SubResource("Resource_am8dk") shield = SubResource("Resource_rw3nb") battery = SubResource("Resource_p601o") +heat_sink = SubResource("Resource_kynkv") [node name="MeshInstance3D" type="MeshInstance3D" parent="." index="0"] transform = Transform3D(-0.4, 1.39515e-16, 3.49691e-08, 1.39515e-16, 0.4, -1.39515e-16, -3.49691e-08, -1.39515e-16, -0.4, 1.40849e-16, -1.40849e-16, -0.199324) @@ -153,4 +165,8 @@ transform = Transform3D(1, -1.21652e-31, 0, -1.21652e-31, 1, 0, 0, 0, 1, 3.78906 script = ExtResource("16_xra8r") weapon = ExtResource("17_h1u5w") +[node name="Radiator" type="Node3D" parent="." index="9"] +script = ExtResource("20_0bm6k") +rate = 8.0 + [editable path="CombatObject/TargetOverlay"] diff --git a/ships/ship.gd b/ships/ship.gd index f9cc4ca9..cf5392fc 100644 --- a/ships/ship.gd +++ b/ships/ship.gd @@ -21,6 +21,9 @@ class_name Ship ## This ship's power management unit. @export var power_management_unit: PowerManagementUnit +## The ship's radiator to dissipate heat. +@export var radiator: Radiator + ## An object for representing this ship on radar. @export var radar_object: RadarObject @@ -51,6 +54,9 @@ class_name Ship ## The [Battery] powering the ship. @export var battery: Battery +## The [HeatSink] which accumulates ship heat. +@export var heat_sink: HeatSink + ## An optional cargo hold for this ship. @export var cargo_hold: CargoHold @@ -83,14 +89,18 @@ var save_node_path_override: NodePath func _ready() -> void: self.combat_object.hull = self.hull self.combat_object.shield = self.shield + self.combat_object.heat_sink = self.heat_sink if self.hero: self.combat_object.combat_name = self.hero.name self.hull.hull_destroyed.connect(func(_hull: Hull) -> void: self.hero.killed.emit(self.hero)) self.rigid_body_thruster.battery = self.battery + self.rigid_body_thruster.heat_sink = self.heat_sink self.rigid_body_direction.battery = self.battery self.power_management_unit.battery = self.battery + self.power_management_unit.heat_sink = self.heat_sink + self.radiator.heat_sink = self.heat_sink if self.shield_recharger: self.shield_recharger.shield = self.shield @@ -101,6 +111,7 @@ func _ready() -> void: for weapon_mount in self.weapon_mounts: weapon_mount.battery = self.battery + weapon_mount.heat_sink = self.heat_sink if self.rigid_body_cargo: self.rigid_body_cargo.cargo_hold = self.cargo_hold @@ -109,6 +120,21 @@ func _ready() -> void: func _to_string() -> String: return "Ship:%s (%s)" % [self.name, self.combat_object] +## Whether this ship's controls should be disabled. +func controls_disabled() -> bool: + if self.heat_sink.heat >= self.heat_sink.max_heat: + return true + + if self.hyperdrive_system and self.hyperdrive_system.jumping: + return true + + return false + +## Starts or stops firing on all weapon mounts. +func set_firing(firing: bool) -> void: + for weapon_mount in self.weapon_mounts: + weapon_mount.firing = firing + ## Add an outfit to the ship and apply its effects. func add_outfit(outfit: Outfit) -> void: outfit.apply_to_ship(self) @@ -128,6 +154,7 @@ func save_to_dict() -> Dictionary: SaveGame.save_resource_property_into_dict(self, result, "hull") SaveGame.save_resource_property_into_dict(self, result, "battery") + SaveGame.save_resource_property_into_dict(self, result, "heat_sink") SaveGame.save_resource_property_into_dict(self, result, "shield") SaveGame.save_resource_property_into_dict(self, result, "hyperdrive") SaveGame.save_resource_property_into_dict(self, result, "cargo_hold") @@ -146,6 +173,7 @@ func load_from_dict(dict: Dictionary) -> void: SaveGame.load_resource_property_from_dict(self, dict, "hull") SaveGame.load_resource_property_from_dict(self, dict, "battery") + SaveGame.load_resource_property_from_dict(self, dict, "heat_sink") SaveGame.load_resource_property_from_dict(self, dict, "shield") SaveGame.load_resource_property_from_dict(self, dict, "hyperdrive") SaveGame.load_resource_property_from_dict(self, dict, "cargo_hold")