Compare commits

...

2 Commits

Author SHA1 Message Date
d4a008ff2a Grunk alarm emits red when triggered
All checks were successful
linting & formatting / build (push) Successful in 21s
2025-04-19 17:31:21 -06:00
ed303fce4b Milestones have effects 2025-04-19 17:13:36 -06:00
10 changed files with 246 additions and 14 deletions

View File

@ -1772,7 +1772,7 @@ shape = SubResource("ConcavePolygonShape3D_if0c2")
[node name="MessHallMeetSpookSpawner" type="Marker3D" parent="BeastNav/Corridor1/T-Junction2"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.5, 0)
script = ExtResource("52_4akax")
mob_lifespan = 3.0
mob_lifespan = 2.2
[node name="Target" type="Marker3D" parent="BeastNav/Corridor1/T-Junction2/MessHallMeetSpookSpawner"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.90735e-06, 0, 21)
@ -2293,7 +2293,7 @@ spawners = [NodePath("../../Corridor1/T-Junction2/MessHallMeetSpookSpawner"), No
[node name="MedbayMeetSpookSpawner" type="Marker3D" parent="BeastNav/MessHall"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 3, 1.5, 2.1)
script = ExtResource("52_4akax")
mob_lifespan = 3.0
mob_lifespan = 2.2
[node name="Target" type="Marker3D" parent="BeastNav/MessHall/MedbayMeetSpookSpawner"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 6)
@ -2396,7 +2396,7 @@ mesh = SubResource("ArrayMesh_48a1a")
[node name="MessHallMeetSpookSpawner" type="Marker3D" parent="BeastNav/Corridor2/T-Junction1"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.5, 0)
script = ExtResource("52_4akax")
mob_lifespan = 3.0
mob_lifespan = 2.2
[node name="Target" type="Marker3D" parent="BeastNav/Corridor2/T-Junction1/MessHallMeetSpookSpawner"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -12)
@ -2404,7 +2404,7 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -12)
[node name="CrewQuartersMeetSpookSpawner" type="Marker3D" parent="BeastNav/Corridor2/T-Junction1"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.5, 0)
script = ExtResource("52_4akax")
mob_lifespan = 3.0
mob_lifespan = 2.2
[node name="Target" type="Marker3D" parent="BeastNav/Corridor2/T-Junction1/CrewQuartersMeetSpookSpawner"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 12, 0, 0)
@ -3227,7 +3227,7 @@ shape = SubResource("ConcavePolygonShape3D_if0c2")
[node name="CrewQuartersMeetSpookSpawner" type="Marker3D" parent="BeastNav/Corridor3/T-Junction1"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.5, 0)
script = ExtResource("52_4akax")
mob_lifespan = 3.0
mob_lifespan = 2.2
[node name="Target" type="Marker3D" parent="BeastNav/Corridor3/T-Junction1/CrewQuartersMeetSpookSpawner"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -2.62268e-06, 0, -30)
@ -3303,7 +3303,7 @@ shape = SubResource("ConcavePolygonShape3D_if0c2")
[node name="MedbayMeetSpookSpawner" type="Marker3D" parent="BeastNav/Corridor3/T-Junction3"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2.38419e-07, 1.5, 0)
script = ExtResource("52_4akax")
mob_lifespan = 3.0
mob_lifespan = 2.2
[node name="Target" type="Marker3D" parent="BeastNav/Corridor3/T-Junction3/MedbayMeetSpookSpawner"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -3.14722e-06, 0, 42)
@ -4078,7 +4078,7 @@ outline_size = 24
[node name="MessHallMeetSpookSpawner" type="Marker3D" parent="BeastNav/Medbay"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -3, 1.5, -12)
script = ExtResource("52_4akax")
mob_lifespan = 3.0
mob_lifespan = 2.2
[node name="Target" type="Marker3D" parent="BeastNav/Medbay/MessHallMeetSpookSpawner"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 6, 0, 15)

View File

@ -34,6 +34,11 @@ func idle() -> void:
_idle()
## Is this tool available to the player?
func unlocked() -> bool:
return true
func _physics_process(delta: float) -> void:
if hud_tool:
var weight := 1 - exp(-hud_accel * delta)

View File

@ -15,6 +15,10 @@ const BRUSH_SCALE := 0.2
@onready var resting_position: Marker3D = %RestingPosition
func unlocked() -> bool:
return Game.manager.toothbrush_unlocked
func _fire() -> void:
if raycast.is_colliding() and not Game.manager.is_tank_full():
brush_animation.play("brush")

View File

@ -23,8 +23,11 @@ signal player_dead
const MAX_ALERT := 6
const BASE_TANK_LIMIT := 96000
const BIG_TANK_LIMIT := 198000
## Maximum amount of grunk the player can carry in their tank.
@export var grunk_tank_limit := 120000
@export var grunk_tank_limit := BASE_TANK_LIMIT
# TODO figure this out
@export var grunk_quota := 2000000
@ -32,10 +35,19 @@ const MAX_ALERT := 6
## Grunk collection milestones
@export var vault_milestones: Dictionary[int, Milestone]
@export_group("Progress")
@export var mp3_player_unlocked := false
@export var toothbrush_unlocked := false
@export var stickers_unlocked := false
var debug_emit_alert_signal: int:
set(value):
alert_raised.emit(value)
var debug_unlock_milestone: Milestone:
set(value):
milestone_reached.emit(value)
## Amount of grunk the player is currently carrying.
var grunk_tank := 0.0
@ -123,6 +135,18 @@ func next_milestone_amount() -> int:
return -1
func _on_milestone(milestone: Milestone) -> void:
if milestone.mp3_player:
mp3_player_unlocked = true
elif milestone.toothbrush:
toothbrush_unlocked = true
elif milestone.stickers:
stickers_unlocked = true
elif milestone.big_tank:
grunk_tank_limit = BIG_TANK_LIMIT
# TODO the rest
## Called by Player on death.
func on_player_death() -> void:
player_dead.emit()

View File

@ -8,6 +8,15 @@ script = ExtResource("2_b83gw")
name = "[no reward]"
message = "Check the MANUAL for SWEET TIPZ
from the GRUNKIN' MASTERS!"
bonus_track = false
mp3_player = false
toothbrush = false
seminar = false
big_tank = false
stickers = false
quota = false
mystery = false
fiesta = false
metadata/_custom_type_script = "uid://ufxoxupdvyd5"
[sub_resource type="Resource" id="Resource_b83gw"]
@ -15,6 +24,15 @@ script = ExtResource("2_b83gw")
name = "MP3 PLAYER"
message = "MP3 PLAYER DECRYPTED. Enjoy some
light music whilst you GRUNK."
bonus_track = false
mp3_player = true
toothbrush = false
seminar = false
big_tank = false
stickers = false
quota = false
mystery = false
fiesta = false
metadata/_custom_type_script = "uid://ufxoxupdvyd5"
[sub_resource type="Resource" id="Resource_o6um0"]
@ -22,6 +40,15 @@ script = ExtResource("2_b83gw")
name = "TOOTHBRUSH"
message = "TOOTHBRUSH DECRYPTED.
Enjoy teethbrushing in moderation!"
bonus_track = false
mp3_player = false
toothbrush = true
seminar = false
big_tank = false
stickers = false
quota = false
mystery = false
fiesta = false
metadata/_custom_type_script = "uid://ufxoxupdvyd5"
[sub_resource type="Resource" id="Resource_vebb4"]
@ -29,6 +56,15 @@ script = ExtResource("2_b83gw")
name = "BONUS TRACK"
message = "BONUS TRACK DELIVERED
[TODO]"
bonus_track = true
mp3_player = false
toothbrush = false
seminar = false
big_tank = false
stickers = false
quota = false
mystery = false
fiesta = false
metadata/_custom_type_script = "uid://ufxoxupdvyd5"
[sub_resource type="Resource" id="Resource_aolyc"]
@ -36,6 +72,15 @@ script = ExtResource("2_b83gw")
name = "WELLNESS SEMINAR"
message = "SEMINAR DECRYPTED.
The FUTURE of WELLNESS is TODAY!"
bonus_track = false
mp3_player = false
toothbrush = false
seminar = true
big_tank = false
stickers = false
quota = false
mystery = false
fiesta = false
metadata/_custom_type_script = "uid://ufxoxupdvyd5"
[sub_resource type="Resource" id="Resource_36cpv"]
@ -43,6 +88,15 @@ script = ExtResource("2_b83gw")
name = "EL TANK GRANDE"
message = "\"EL TANK GRANDE\" DECRYPTED.
GRUNK carrying capacity increased."
bonus_track = false
mp3_player = false
toothbrush = false
seminar = false
big_tank = true
stickers = false
quota = false
mystery = false
fiesta = false
metadata/_custom_type_script = "uid://ufxoxupdvyd5"
[sub_resource type="Resource" id="Resource_pfnwj"]
@ -50,6 +104,15 @@ script = ExtResource("2_b83gw")
name = "STICKER PACK"
message = "NOW PRINTING... You can use
STICKERS to EXPRESS your \"SELF\""
bonus_track = false
mp3_player = false
toothbrush = false
seminar = false
big_tank = false
stickers = true
quota = false
mystery = false
fiesta = false
metadata/_custom_type_script = "uid://ufxoxupdvyd5"
[sub_resource type="Resource" id="Resource_p7jc6"]
@ -57,23 +120,49 @@ script = ExtResource("2_b83gw")
name = "QUOTA"
message = "QUOTA SATISFIED.
FINE WORK GRUNKER !"
bonus_track = false
mp3_player = false
toothbrush = false
seminar = false
big_tank = false
stickers = false
quota = true
mystery = false
fiesta = false
metadata/_custom_type_script = "uid://ufxoxupdvyd5"
[sub_resource type="Resource" id="Resource_2eyq5"]
script = ExtResource("2_b83gw")
name = "???"
message = "????? ?"
bonus_track = false
mp3_player = false
toothbrush = false
seminar = false
big_tank = false
stickers = false
quota = false
mystery = true
fiesta = false
metadata/_custom_type_script = "uid://ufxoxupdvyd5"
[sub_resource type="Resource" id="Resource_2qxxw"]
script = ExtResource("2_b83gw")
name = "TACO FIESTA"
name = "taco fiesta"
message = "ENJOY THE FIESTA GRUNKER !"
bonus_track = false
mp3_player = false
toothbrush = false
seminar = false
big_tank = false
stickers = false
quota = false
mystery = false
fiesta = true
metadata/_custom_type_script = "uid://ufxoxupdvyd5"
[node name="GameManager" type="Node"]
script = ExtResource("1_08e4a")
grunk_tank_limit = 96000
vault_milestones = Dictionary[int, ExtResource("2_b83gw")]({
0: SubResource("Resource_h4r54"),
100000: SubResource("Resource_b83gw"),
@ -91,3 +180,5 @@ vault_milestones = Dictionary[int, ExtResource("2_b83gw")]({
4200000: SubResource("Resource_vebb4"),
6400000: SubResource("Resource_2qxxw")
})
[connection signal="milestone_reached" from="." to="." method="_on_milestone"]

View File

@ -3,3 +3,14 @@ class_name Milestone extends Resource
@export var name: String
@export_multiline var message: String
@export_group("Effects")
@export var bonus_track := false
@export var mp3_player := false
@export var toothbrush := false
@export var seminar := false
@export var big_tank := false
@export var stickers := false
@export var quota := false
@export var mystery := false
@export var fiesta := false

View File

@ -75,6 +75,7 @@ static var instance: Player
func _ready() -> void:
Game.manager.milestone_reached.connect(_on_milestone)
instance = self
@ -157,6 +158,20 @@ func get_grabbed() -> void:
camera_pivot.reset_pitch(0.4)
#endregion
#region Event Handlers
func _on_milestone(milestone: Milestone) -> void:
if milestone.mp3_player:
pass # TODO equip mp3 player
if milestone.toothbrush:
tool_mount.set_active(toothbrush)
if milestone.stickers:
pass # TODO equip stickers
func _signal_death() -> void:
# Called from the death animation
Game.manager.on_player_death()

View File

@ -18,7 +18,11 @@ func get_active() -> Tool:
## Sets the given tool as active.
##
## The tool should be a child of this mount.
func set_active(tool: Tool) -> void:
## If the tool is not unlocked and `force` is false, this will have no effect.
func set_active(tool: Tool, force: bool = false) -> void:
if not force and not tool.unlocked():
return
for c: Node3D in get_children():
c.visible = false
# TODO unequip animation?
@ -32,5 +36,12 @@ func set_active(tool: Tool) -> void:
## Use this for "select next/prev tool" functions.
func set_active_relative(delta: int) -> void:
var active_idx := _active.get_index()
while true:
var new_idx := wrapi(active_idx + delta, 0, get_child_count())
set_active(get_child(new_idx) as Tool)
var tool := get_child(new_idx) as Tool
if tool.unlocked():
set_active(tool)
return
# If the next tool is not unlocked, try the one after
# NOTE: this will loop forever if the player has no tools unlocked!
active_idx = new_idx

View File

@ -14,6 +14,7 @@ var _busy := false
@onready var pulse_listener_timer: Timer = %PulseListenerTimer
@onready var animation_player: AnimationPlayer = $FrameSkipper/AlarmMesh/AnimationPlayer
@onready var effect_animation: AnimationPlayer = %EffectAnimation
@onready var bud: MeshInstance3D = $FrameSkipper/AlarmMesh/Armature/Skeleton3D/Bud
@onready var alarm_sfx: AudioStreamPlayer3D = %AlarmSFX
@ -26,6 +27,7 @@ func trigger() -> void:
_busy = true
Game.manager.raise_alert(ALERT_DELTA)
animation_player.play("trigger")
effect_animation.play("trigger")
alarm_sfx.play()

View File

@ -1,4 +1,4 @@
[gd_scene load_steps=10 format=4 uid="uid://dgeg3kkogm71m"]
[gd_scene load_steps=13 format=4 uid="uid://dgeg3kkogm71m"]
[ext_resource type="Script" uid="uid://djb5tabjcvwkt" path="res://src/world/mechanics/alarm/gunk_alarm.gd" id="1_piaxx"]
[ext_resource type="PackedScene" uid="uid://60ks4l42qxia" path="res://assets/grunk/alarm/alarm.gltf" id="2_6vdvf"]
@ -43,6 +43,67 @@ _surfaces = [{
}]
blend_shape_mode = 0
[sub_resource type="Animation" id="Animation_6vdvf"]
resource_name = "trigger"
length = 6.0
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("FrameSkipper/AlarmMesh/Armature/Skeleton3D/Bud:mesh:surface_0/material:shader_parameter/emission_color")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.333333, 5.3, 6),
"transitions": PackedFloat32Array(1, 1, 1, 1),
"update": 0,
"values": [Color(0.25, 0.88, 1, 1), Color(1, 0.25, 0.2625, 1), Color(1, 0.25, 0.2625, 1), Color(0.25, 0.88, 1, 1)]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("FrameSkipper/AlarmMesh/Armature/Skeleton3D/Bud:mesh:surface_0/material:shader_parameter/emission_strength")
tracks/1/interp = 2
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0, 0.333333, 0.9, 3.96667, 5.3, 6),
"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1),
"update": 0,
"values": [0.02, 0.05, 10.0, 10.0, 0.05, 0.02]
}
[sub_resource type="Animation" id="Animation_g4yos"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("FrameSkipper/AlarmMesh/Armature/Skeleton3D/Bud:mesh:surface_0/material:shader_parameter/emission_color")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Color(0.25, 0.88, 1, 1)]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("FrameSkipper/AlarmMesh/Armature/Skeleton3D/Bud:mesh:surface_0/material:shader_parameter/emission_strength")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [0.02]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_vokcn"]
_data = {
&"RESET": SubResource("Animation_g4yos"),
&"trigger": SubResource("Animation_6vdvf")
}
[sub_resource type="SphereMesh" id="SphereMesh_b6er8"]
radius = 0.285
height = 0.44
@ -102,6 +163,14 @@ mesh = SubResource("ArrayMesh_c5y52")
[node name="AnimationPlayer" parent="FrameSkipper/AlarmMesh" index="1"]
speed_scale = 7.4
[node name="EffectAnimation" type="AnimationPlayer" parent="FrameSkipper"]
unique_name_in_owner = true
root_node = NodePath("../..")
libraries = {
&"": SubResource("AnimationLibrary_vokcn")
}
speed_scale = 7.4
[node name="CollisionMesh" type="MeshInstance3D" parent="."]
transform = Transform3D(0.906308, 0, -0.422618, 0, 1, 0, 0.422618, 0, 0.906308, 0, 0.2, 0)
visible = false