You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
93 lines
2.7 KiB
93 lines
2.7 KiB
extends RigidBody3D |
|
|
|
## If this heart were to exist for longer than 1 minute for some reason, destroy it. |
|
## The heart should also disappear if it falls low enough. |
|
var lifetime := 60.0 # 1 minute |
|
|
|
## If this heart has impacted another object already. |
|
## Prevents repeated impact sounds and sticking. |
|
var impacted := false |
|
|
|
## Relative size of the heart. Affects audio pitch. |
|
## Used later to decide how impactful a collision was. |
|
var size := 1.0 |
|
|
|
## Whether the heart will stick to avatars when colliding. |
|
var sticky := false |
|
|
|
## How long the heart will be sticking before falling off again. |
|
@onready var sticky_timer := randf_range(3, 6) # 3 to 6 seconds |
|
|
|
# Remember the original parent this node was created under, so if the |
|
# heart sticks to a character, it can return here once it unsticks. |
|
@onready var original_parent: Node = get_parent() |
|
|
|
static var stream_normal: AudioStream = load("res://Mods/copyThrower/Resources/normal_randomizer.tres") |
|
static var stream_sticky: AudioStream = load("res://Mods/copyThrower/Resources/sticky_randomizer.tres") |
|
|
|
func _ready() -> void: |
|
body_entered.connect(on_body_entered) |
|
|
|
# Give it a little bit of random spin. |
|
var random_vector := Vector3(randf() - 0.5, randf() - 0.5, randf() - 0.5).normalized() |
|
angular_velocity = random_vector * randf_range(0, 25) * TAU |
|
angular_damp = 5.0 |
|
|
|
|
|
func set_size(value: float) -> void: |
|
size = value |
|
$Model.scale *= value |
|
$CollisionShape3D.scale *= value |
|
$AudioStreamPlayer3D.pitch_scale = 1 / lerpf(1, value, 0.5) |
|
|
|
func set_sticky(value: bool) -> void: |
|
sticky = value |
|
if value: $AudioStreamPlayer3D.stream = stream_sticky |
|
else: $AudioStreamPlayer3D.stream = stream_normal |
|
|
|
func set_material(material: StandardMaterial3D) -> void: |
|
$Model/Heart.material_override = material |
|
|
|
|
|
func _process(delta: float) -> void: |
|
# Kill heart if it ever lives too long. |
|
lifetime -= delta |
|
if lifetime <= 0: queue_free(); return |
|
|
|
# Kill heart if it falls too low. |
|
if global_position.y < -10: queue_free(); return |
|
|
|
# Unsticky heart after some time. |
|
if get_parent() is CharacterBody3D: |
|
sticky_timer -= delta |
|
if sticky_timer <= 0: |
|
set_physics_active(true) |
|
reparent(original_parent) |
|
|
|
func on_body_entered(body: Node) -> void: |
|
if not (body is CharacterBody3D): return |
|
if impacted: return |
|
impacted = true |
|
|
|
$AudioStreamPlayer3D.play() |
|
original_parent.on_collide(self, body) |
|
|
|
if sticky: |
|
await get_tree().process_frame; |
|
set_physics_active(false) |
|
set_gravity_scale(0.0) |
|
reparent(body) |
|
|
|
|
|
func set_physics_active(active: bool) -> void: |
|
if active: |
|
sleeping = false |
|
collision_mask = 1 |
|
set_gravity_scale(1.0) |
|
else: |
|
sleeping = true |
|
linear_velocity = Vector3.ZERO |
|
angular_velocity = Vector3.ZERO |
|
collision_mask = 0 |
|
collision_layer = 0 |
|
set_gravity_scale(0.0)
|
|
|