Grunk milestones & text terminal

This commit is contained in:
Rob Kelly 2025-03-21 19:13:17 -06:00
parent 36645dd09b
commit 8343b69cdd
39 changed files with 2318 additions and 96 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,2 @@
# Blender 4.3.2 MTL File: 'monitor.blend'
# www.blender.org

View File

@ -0,0 +1,60 @@
# Blender 4.3.2
# www.blender.org
mtllib monitor.mtl
o Cube
v -0.250000 -0.200000 0.100000
v -0.250000 0.200000 0.100000
v -0.250000 -0.200000 -0.100000
v -0.250000 0.200000 -0.100000
v 0.250000 -0.200000 0.100000
v 0.250000 0.200000 0.100000
v 0.250000 -0.200000 -0.100000
v 0.250000 0.200000 -0.100000
v -0.150000 -0.200000 0.300000
v -0.150000 0.040000 0.300000
v 0.150000 0.040000 0.300000
v 0.150000 -0.200000 0.300000
vn -1.0000 -0.0000 -0.0000
vn -0.0000 -0.0000 -1.0000
vn 1.0000 -0.0000 -0.0000
vn -0.8944 -0.0000 0.4472
vn -0.0000 -1.0000 -0.0000
vn -0.0000 1.0000 -0.0000
vn -0.0000 -0.0000 1.0000
vn -0.0000 0.7809 0.6247
vn 0.8944 -0.0000 0.4472
vt 1.000000 0.828125
vt 0.703125 0.828125
vt 0.703125 0.687500
vt 1.000000 0.687500
vt 0.703125 0.312500
vt 1.000000 0.312500
vt 0.703125 0.171875
vt 1.000000 0.171875
vt 1.000000 1.000000
vt 0.812500 1.000000
vt 0.328125 0.625000
vt 0.328125 1.000000
vt 0.187500 1.000000
vt 0.187500 0.625000
vt 0.546875 0.687500
vt 0.546875 0.312500
vt 0.187500 0.390625
vt 0.359375 0.390625
vt 0.359375 0.609375
vt 0.187500 0.609375
vt 0.031250 0.921875
vt 0.031250 0.703125
vt 0.812500 0.000000
vt 1.000000 0.000000
s 0
f 1/1/1 2/2/1 4/3/1 3/4/1
f 3/4/2 4/3/2 8/5/2 7/6/2
f 7/6/3 8/5/3 6/7/3 5/8/3
f 2/2/4 1/1/4 9/9/4 10/10/4
f 3/11/5 7/12/5 5/13/5 1/14/5
f 8/5/6 4/3/6 2/15/6 6/16/6
f 12/17/7 11/18/7 10/19/7 9/20/7
f 1/14/5 5/13/5 12/21/5 9/22/5
f 6/16/8 2/15/8 10/19/8 11/18/8
f 5/8/9 6/7/9 11/23/9 12/24/9

View File

@ -0,0 +1,25 @@
[remap]
importer="wavefront_obj"
importer_version=1
type="Mesh"
uid="uid://bscl1xlxe6vo5"
path="res://.godot/imported/monitor.obj-26d4ed536e05da2141bb0d2583969316.mesh"
[deps]
files=["res://.godot/imported/monitor.obj-26d4ed536e05da2141bb0d2583969316.mesh"]
source_file="res://assets/props/monitor/monitor.obj"
dest_files=["res://.godot/imported/monitor.obj-26d4ed536e05da2141bb0d2583969316.mesh", "res://.godot/imported/monitor.obj-26d4ed536e05da2141bb0d2583969316.mesh"]
[params]
generate_tangents=true
generate_lods=true
generate_shadow_mesh=true
generate_lightmap_uv2=false
generate_lightmap_uv2_texel_size=0.2
scale_mesh=Vector3(1, 1, 1)
offset_mesh=Vector3(0, 0, 0)
force_disable_mesh_compression=false

BIN
assets/props/monitor/monitor_C.png (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://b4rgjafpr6ly7"
path="res://.godot/imported/monitor_C.png-50f626613d69b93efbf6acda1fef975e.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/props/monitor/monitor_C.png"
dest_files=["res://.godot/imported/monitor_C.png-50f626613d69b93efbf6acda1fef975e.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=true
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=0

BIN
assets/props/monitor/monitor_E.png (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bv2xppqri874x"
path="res://.godot/imported/monitor_E.png-ebfbd9e0aa5eed5aa458c331281125d1.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/props/monitor/monitor_E.png"
dest_files=["res://.godot/imported/monitor_E.png-ebfbd9e0aa5eed5aa458c331281125d1.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=true
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=0

BIN
assets/props/monitor/monitor_M.png (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://b48cvc83xgm5v"
path="res://.godot/imported/monitor_M.png-a1edfdf10b29b844e1928ca5ec8267c5.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/props/monitor/monitor_M.png"
dest_files=["res://.godot/imported/monitor_M.png-a1edfdf10b29b844e1928ca5ec8267c5.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=true
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=0

BIN
assets/props/monitor/monitor_N.png (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://ddh6u8v3jmqt7"
path="res://.godot/imported/monitor_N.png-ad232babe5829704ac11aef7d6d8a99e.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/props/monitor/monitor_N.png"
dest_files=["res://.godot/imported/monitor_N.png-ad232babe5829704ac11aef7d6d8a99e.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=1
compress/channel_pack=0
mipmaps/generate=true
mipmaps/limit=-1
roughness/mode=1
roughness/src_normal="res://assets/props/monitor/monitor_N.png"
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=0

BIN
assets/props/monitor/monitor_R.png (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://te8jgudhv1lb"
path="res://.godot/imported/monitor_R.png-0736da5da458d7a3678f16ac83a97333.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/props/monitor/monitor_R.png"
dest_files=["res://.godot/imported/monitor_R.png-0736da5da458d7a3678f16ac83a97333.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=true
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=0

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,67 @@
extends Node3D
const MESSAGE_FMT := (
"-= H E L L O G R U N K E R =-\n"
+ "Your GRUNK QUOTA today:\n"
+ ".... {0} g\n"
+ "GRUNK collected:\n"
+ ".... {1} g\n"
+ "-================================-\n"
+ "{2}\n"
+ "{3}\n"
+ "Look forward to: {4}\n"
+ ".... at {5} g\n"
+ "-= YOUR BENEFACTORS THANK YOU =-"
)
const STALLING_MSG := "\n\n\n\n\n. . . C a l c u l a t i n G . . ."
@onready var text_terminal: TextTerminal = %TextTerminal
@onready var stall_timer: Timer = %StallTimer
func _ready() -> void:
Game.manager.grunk_emptied.connect(_on_tank_emptied)
recompute()
func _next_milestone_name() -> String:
var next_milestone := Game.manager.next_milestone()
return next_milestone.name if next_milestone else "NOTHING"
func _next_milestone_amount() -> String:
var next_milestone_amt := Game.manager.next_milestone_amount()
return str(next_milestone_amt) if next_milestone_amt >= 0 else "NEVER"
func build_message() -> String:
var msg_lines := Game.manager.latest_milestone().message.split("\n")
var line_1 := msg_lines[0]
var line_2 := msg_lines[1] if len(msg_lines) >= 2 else ""
return MESSAGE_FMT.format(
[
int(Game.manager.grunk_quota),
int(Game.manager.grunk_vault),
line_1,
line_2,
_next_milestone_name(),
_next_milestone_amount()
]
)
## Trigger a recompute.
##
## Under the hood this is instantaneous, but we want to stall for dramatic effect.
func recompute() -> void:
text_terminal.text = STALLING_MSG
stall_timer.start()
func _update_terminal() -> void:
text_terminal.text = build_message()
func _on_tank_emptied(_amount: float) -> void:
recompute()

View File

@ -0,0 +1 @@
uid://tot4ru3nbxfn

View File

@ -0,0 +1,17 @@
[gd_scene load_steps=3 format=3 uid="uid://mgygam1kakb7"]
[ext_resource type="PackedScene" uid="uid://c7ljflq1eehym" path="res://src/props/text_terminal/text_terminal.tscn" id="1_gcu0e"]
[ext_resource type="Script" uid="uid://tot4ru3nbxfn" path="res://levels/ghost_ship/player_ship/grunk_terminal/grunk_terminal.gd" id="1_q4cc8"]
[node name="GrunkTerminal" type="Node3D"]
script = ExtResource("1_q4cc8")
[node name="TextTerminal" parent="." instance=ExtResource("1_gcu0e")]
unique_name_in_owner = true
[node name="StallTimer" type="Timer" parent="."]
unique_name_in_owner = true
wait_time = 4.0
one_shot = true
[connection signal="timeout" from="StallTimer" to="." method="_update_terminal"]

View File

@ -2,7 +2,7 @@ extends Node3D
# The player's ship, a safe zone where they can deposit grunk, save their game, and relax. # The player's ship, a safe zone where they can deposit grunk, save their game, and relax.
# TODO figure out whatever this is lol # TODO figure out whatever this is lol
const MAX_GRUNK := 6000000.0 const MAX_GRUNK := 6400000.0
const LIQUID_FACTOR := 2.8 const LIQUID_FACTOR := 2.8
const TANK_FILL_TIME := 1.0 const TANK_FILL_TIME := 1.0

View File

@ -1,4 +1,4 @@
[gd_scene load_steps=21 format=3 uid="uid://oowut88kr2ox"] [gd_scene load_steps=22 format=3 uid="uid://oowut88kr2ox"]
[ext_resource type="Script" uid="uid://lfd36ps52xgk" path="res://levels/ghost_ship/player_ship/player_ship.gd" id="1_0r2ng"] [ext_resource type="Script" uid="uid://lfd36ps52xgk" path="res://levels/ghost_ship/player_ship/player_ship.gd" id="1_0r2ng"]
[ext_resource type="ArrayMesh" uid="uid://dq4aj5ph31rce" path="res://assets/level/player_ship/player_ship.obj" id="1_nafoa"] [ext_resource type="ArrayMesh" uid="uid://dq4aj5ph31rce" path="res://assets/level/player_ship/player_ship.obj" id="1_nafoa"]
@ -12,6 +12,7 @@
[ext_resource type="ArrayMesh" uid="uid://bc8457r4rxpey" path="res://assets/level/player_ship/grunk_liquid.obj" id="8_xuj2g"] [ext_resource type="ArrayMesh" uid="uid://bc8457r4rxpey" path="res://assets/level/player_ship/grunk_liquid.obj" id="8_xuj2g"]
[ext_resource type="Texture2D" uid="uid://cm1jrvx7ftx4c" path="res://assets/black.png" id="9_xuj2g"] [ext_resource type="Texture2D" uid="uid://cm1jrvx7ftx4c" path="res://assets/black.png" id="9_xuj2g"]
[ext_resource type="FastNoiseLite" uid="uid://cnlvdtx68giv6" path="res://assets/materials/gunk_noise.tres" id="10_2mvif"] [ext_resource type="FastNoiseLite" uid="uid://cnlvdtx68giv6" path="res://assets/materials/gunk_noise.tres" id="10_2mvif"]
[ext_resource type="PackedScene" uid="uid://mgygam1kakb7" path="res://levels/ghost_ship/player_ship/grunk_terminal/grunk_terminal.tscn" id="13_3trrp"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_xpsdy"] [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_xpsdy"]
transparency = 1 transparency = 1
@ -125,4 +126,7 @@ light_energy = 2.0
light_indirect_energy = 8.0 light_indirect_energy = 8.0
omni_range = 10.0 omni_range = 10.0
[node name="GrunkTerminal" parent="." instance=ExtResource("13_3trrp")]
transform = Transform3D(-0.707107, 0.183013, 0.683013, 0, 0.965926, -0.258819, -0.707107, -0.183013, -0.683013, -1.87678, 1.71247, 4.17322)
[connection signal="activated" from="TankInteractor" to="." method="deposit_grunk"] [connection signal="activated" from="TankInteractor" to="." method="deposit_grunk"]

View File

@ -24,5 +24,6 @@ func draw_vector(vec: Vector3, origin: Vector3) -> void:
func _draw() -> void: func _draw() -> void:
while lines: while lines:
var line: Array[Vector2] = [] var line: Array[Vector2] = []
@warning_ignore("unsafe_cast")
line.assign(lines.pop_back() as Array) line.assign(lines.pop_back() as Array)
draw_line(line[0], line[1], COLOR, WIDTH) draw_line(line[0], line[1], COLOR, WIDTH)

View File

@ -13,14 +13,20 @@ signal alert_raised(new_value: int)
## Emitted just before the alert level is reset to zero. ## Emitted just before the alert level is reset to zero.
signal alert_cleared signal alert_cleared
## Emitted just after the player collects an item. ## Emitted after the player's grunk vault reaches a new milestone.
signal item_collected(item: Item) signal milestone_reached(milestone: Milestone)
const MAX_ALERT := 6 const MAX_ALERT := 6
## Maximum amount of grunk the player can carry in their tank. ## Maximum amount of grunk the player can carry in their tank.
@export var grunk_tank_limit := 120000 @export var grunk_tank_limit := 120000
# TODO figure this out
@export var grunk_quota := 2000000
## Grunk collection milestones
@export var vault_milestones: Dictionary[int, Milestone]
## Amount of grunk the player is currently carrying. ## Amount of grunk the player is currently carrying.
var grunk_tank := 0.0 var grunk_tank := 0.0
@ -46,8 +52,12 @@ func empty_tank() -> void:
## Deposit the player's grunk in the vault, emptying the player's tank. ## Deposit the player's grunk in the vault, emptying the player's tank.
func deposit_tank() -> void: func deposit_tank() -> void:
var prev_milestone := latest_milestone()
grunk_vault += grunk_tank grunk_vault += grunk_tank
empty_tank() empty_tank()
var new_milestone := latest_milestone()
if new_milestone != prev_milestone:
milestone_reached.emit(new_milestone)
func is_tank_full() -> bool: func is_tank_full() -> bool:
@ -70,3 +80,35 @@ func raise_alert(delta: int) -> void:
func clear_alert() -> void: func clear_alert() -> void:
alert_cleared.emit() alert_cleared.emit()
alert_level = 0 alert_level = 0
## Returns the latest vault milestone reached by the player.
##
## Returns null if the player has not reached a milestone (shouldn't be possible).
func latest_milestone() -> Milestone:
var prev: Milestone = null
for milestone_amt: int in vault_milestones:
if grunk_vault < milestone_amt:
return prev
prev = vault_milestones[milestone_amt]
return prev
## Returns the next vault milestone for the player to reach.
##
## Returns null if all milestones have been reached.
func next_milestone() -> Milestone:
var amt := next_milestone_amount()
if amt >= 0:
return vault_milestones[amt]
return null
## Returns the grunk amount needed for the player to reach the next milestone.
##
## Returns <0 if all milestones have been reached.
func next_milestone_amount() -> int:
for milestone_amt: int in vault_milestones:
if grunk_vault < milestone_amt:
return milestone_amt
return -1

View File

@ -1,6 +1,93 @@
[gd_scene load_steps=2 format=3 uid="uid://cnrtgmanw40ei"] [gd_scene load_steps=13 format=3 uid="uid://cnrtgmanw40ei"]
[ext_resource type="Script" uid="uid://c1i5gnht15x0e" path="res://src/game/game_manager.gd" id="1_08e4a"] [ext_resource type="Script" uid="uid://c1i5gnht15x0e" path="res://src/game/game_manager.gd" id="1_08e4a"]
[ext_resource type="Script" uid="uid://ufxoxupdvyd5" path="res://src/game/milestone.gd" id="2_b83gw"]
[sub_resource type="Resource" id="Resource_h4r54"]
script = ExtResource("2_b83gw")
name = "[no reward]"
message = "Check the MANUAL for SWEET TIPZ
from the GRUNKIN' MASTERS!"
metadata/_custom_type_script = "uid://ufxoxupdvyd5"
[sub_resource type="Resource" id="Resource_b83gw"]
script = ExtResource("2_b83gw")
name = "MP3 PLAYER"
message = "MP3 PLAYER DECRYPTED. Enjoy some
light music whilst you GRUNK."
metadata/_custom_type_script = "uid://ufxoxupdvyd5"
[sub_resource type="Resource" id="Resource_o6um0"]
script = ExtResource("2_b83gw")
name = "TOOTHBRUSH"
message = "TOOTHBRUSH DECRYPTED.
Enjoy teethbrushing in moderation!"
metadata/_custom_type_script = "uid://ufxoxupdvyd5"
[sub_resource type="Resource" id="Resource_vebb4"]
script = ExtResource("2_b83gw")
name = "BONUS TRACK"
message = "BONUS TRACK DELIVERED
[TODO]"
metadata/_custom_type_script = "uid://ufxoxupdvyd5"
[sub_resource type="Resource" id="Resource_aolyc"]
script = ExtResource("2_b83gw")
name = "WELLNESS SEMINAR"
message = "SEMINAR DECRYPTED.
The FUTURE of WELLNESS is TODAY!"
metadata/_custom_type_script = "uid://ufxoxupdvyd5"
[sub_resource type="Resource" id="Resource_36cpv"]
script = ExtResource("2_b83gw")
name = "EL TANK GRANDE"
message = "\"EL TANK GRANDE\" DECRYPTED.
GRUNK carrying capacity increased."
metadata/_custom_type_script = "uid://ufxoxupdvyd5"
[sub_resource type="Resource" id="Resource_pfnwj"]
script = ExtResource("2_b83gw")
name = "STICKER PACK"
message = "NOW PRINTING... You can use
STICKERS to EXPRESS your \"SELF\""
metadata/_custom_type_script = "uid://ufxoxupdvyd5"
[sub_resource type="Resource" id="Resource_p7jc6"]
script = ExtResource("2_b83gw")
name = "QUOTA"
message = "QUOTA SATISFIED.
FINE WORK GRUNKER !"
metadata/_custom_type_script = "uid://ufxoxupdvyd5"
[sub_resource type="Resource" id="Resource_2eyq5"]
script = ExtResource("2_b83gw")
name = "???"
message = "????? ?"
metadata/_custom_type_script = "uid://ufxoxupdvyd5"
[sub_resource type="Resource" id="Resource_2qxxw"]
script = ExtResource("2_b83gw")
name = "TACO FIESTA"
message = "ENJOY THE FIESTA GRUNKER !"
metadata/_custom_type_script = "uid://ufxoxupdvyd5"
[node name="GameManager" type="Node"] [node name="GameManager" type="Node"]
script = ExtResource("1_08e4a") script = ExtResource("1_08e4a")
grunk_tank_limit = 96000
vault_milestones = Dictionary[int, ExtResource("2_b83gw")]({
0: SubResource("Resource_h4r54"),
100000: SubResource("Resource_b83gw"),
200000: SubResource("Resource_o6um0"),
300000: SubResource("Resource_vebb4"),
400000: SubResource("Resource_aolyc"),
500000: SubResource("Resource_vebb4"),
600000: SubResource("Resource_36cpv"),
800000: SubResource("Resource_vebb4"),
1000000: SubResource("Resource_pfnwj"),
1400000: SubResource("Resource_vebb4"),
2000000: SubResource("Resource_p7jc6"),
2500000: SubResource("Resource_vebb4"),
3200000: SubResource("Resource_2eyq5"),
4200000: SubResource("Resource_vebb4"),
6400000: SubResource("Resource_2qxxw")
})

5
src/game/milestone.gd Normal file
View File

@ -0,0 +1,5 @@
class_name Milestone extends Resource
## Grunk collection milestones
@export var name: String
@export_multiline var message: String

View File

@ -0,0 +1 @@
uid://ufxoxupdvyd5

View File

@ -60,8 +60,6 @@ func get_tool() -> Tool:
## Add the given item to the player's inventory. ## Add the given item to the player's inventory.
func add_item(item: Item, amount: int = 1) -> void: func add_item(item: Item, amount: int = 1) -> void:
inventory[item] = inventory.get(item, 0) + amount inventory[item] = inventory.get(item, 0) + amount
if inventory[item] > 0:
Game.manager.item_collected.emit(item)
## Remove the given item from the player's inventory. ## Remove the given item from the player's inventory.

View File

@ -46,7 +46,7 @@ collision_mask = 2
[node name="OmniLight3D" type="OmniLight3D" parent="CameraPivot/Camera3D"] [node name="OmniLight3D" type="OmniLight3D" parent="CameraPivot/Camera3D"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0.1) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0.1)
light_energy = 0.05 light_energy = 0.08
light_indirect_energy = 4.0 light_indirect_energy = 4.0
light_specular = 0.01 light_specular = 0.01
light_cull_mask = 4294967293 light_cull_mask = 4294967293

View File

@ -0,0 +1,65 @@
[gd_scene load_steps=10 format=4 uid="uid://bve6iya13lhah"]
[ext_resource type="Texture2D" uid="uid://b4rgjafpr6ly7" path="res://assets/props/monitor/monitor_C.png" id="1_71u53"]
[ext_resource type="Texture2D" uid="uid://bv2xppqri874x" path="res://assets/props/monitor/monitor_E.png" id="2_f6xlw"]
[ext_resource type="Texture2D" uid="uid://b48cvc83xgm5v" path="res://assets/props/monitor/monitor_M.png" id="3_wucr7"]
[ext_resource type="Texture2D" uid="uid://ddh6u8v3jmqt7" path="res://assets/props/monitor/monitor_N.png" id="4_68co8"]
[ext_resource type="Texture2D" uid="uid://te8jgudhv1lb" path="res://assets/props/monitor/monitor_R.png" id="5_l3uuy"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_2trc8"]
albedo_texture = ExtResource("1_71u53")
metallic = 1.0
metallic_texture = ExtResource("3_wucr7")
roughness_texture = ExtResource("5_l3uuy")
emission_enabled = true
emission_energy_multiplier = 0.2
emission_texture = ExtResource("2_f6xlw")
normal_enabled = true
normal_texture = ExtResource("4_68co8")
texture_filter = 2
[sub_resource type="ArrayMesh" id="ArrayMesh_pyf08"]
_surfaces = [{
"aabb": AABB(-0.25, -0.2, -0.1, 0.5, 0.4, 0.4),
"format": 34896613377,
"index_count": 60,
"index_data": PackedByteArray("BgAHAAAAAAAHAAEAAAABAAIAAAACAAYAAgABAAUABwAGAAMABgACAAgAAgAFAAgABQABAAkACQABAAcACAAFAAkAAwAGAAoABgAIAAoABAAHAAMACQAHAAQACgAEAAMACAAJAAsACgAIAAsACwAJAAQACwAEAAoA"),
"lods": [0.112699, PackedByteArray("AAABAAIAAQAAAAMAAAACAAMABAABAAMAAwACAAQAAgABAAUABQABAAQAAgAFAAQA")],
"name": "Cube",
"primitive": 3,
"uv_scale": Vector4(0, 0, 0, 0),
"vertex_count": 12,
"vertex_data": PackedByteArray("AAD//wAAAAAAAAAAAAAAAP////8AAAAAMjMAAP//AADMzAAA//8AAP//AAAAAAAAAAD///9/AAAAAAAA/38AAP//////fwAA//8AAP9/AAAyM5mZ//8AAMzMmZn//wAA")
}]
blend_shape_mode = 0
[sub_resource type="ArrayMesh" id="ArrayMesh_xfnq5"]
_surfaces = [{
"aabb": AABB(-0.25, -0.2, -0.1, 0.5, 0.4, 0.4),
"attribute_data": PackedByteArray("/7P/T////0//s/+v////r/+z/6////+v/////////0//s/9P//8AAP9TAAD/U/9f/wf/E/8H/0v/s/9P/7P/r/8v/2P/L/+b/7P/K////yv/s//T////0////yv/s/8r/88AAP8vAAD/L/9f/4v/T/+L/6//W/+b/1v/Y/+L/0//i/+v/1v/Y/9b/5v/s//T////0//P//8="),
"format": 34896613399,
"index_count": 60,
"index_data": PackedByteArray("EgATAAgACAATAAcAAAABAAIAAgABAAMABAAFABQAFAAFABUAFgAXAAkACQAXABgACgALABkAGQALABoAGQAaAAwADAAaAA0ADgAPABsAGwAPABwAHQARAB4AHgARABAAHwAgACEAIQAgACIAIwAkACUAJQAkAAYA"),
"lods": [0.112699, PackedByteArray("AAABAAIAAgABAAMABAAFAAYABwAIAAkACgALAAwADAALAA0ADgAPABAAEAAPABEA")],
"material": SubResource("StandardMaterial3D_2trc8"),
"name": "Cube",
"primitive": 3,
"uv_scale": Vector4(0, 0, 0, 0),
"vertex_count": 38,
"vertex_data": PackedByteArray("AAD//wAA//8AAAAAAAD///////8AAP////8AAAAA////////AABU1f//AAAAAFTVzMwAAP//aMsAAAAAAABU1QAA//8AAFTVMjMAAP//aMv//wAAAABU1QAAAAAAAFTVzMwAAP//hNUyMwAA//9+1AAA//8AAFTV/////wAAVNUyMwAA////v8zMAAD///+/AAD///9/VNUAAAAA/39U1f//////f1TV//8AAP9/VNUAAAAA/39oywAA////f2jLMjOZmf//aMv//wAA/3+I1QAAAAD/fzbVAAD///9/VNX//////39U1czMmZn///+/MjOZmf///78AAP///38kx///////f+vHMjOZmf//k8fMzJmZ//+hyP//////f2jL//8AAP9/aMvMzJmZ//9oy/8//7//P/+//z//v/8//7+qqlRVqqpUVWCjnlxUVaqqVFWqqp5cYKNUVVRVVFVUVY5VOFVPVNdVVNWqKlTVqir//////////1RVqqpUVaqqqqpUVaqqVFWeXGCjnlxgo55cYKOTVTVVMFVnVVTVqipU1aoq///////////B4MEfk+A0H6fgch9q4LYeYKOeXGCjnlxgo55c")
}]
blend_shape_mode = 0
shadow_mesh = SubResource("ArrayMesh_pyf08")
[sub_resource type="ConcavePolygonShape3D" id="ConcavePolygonShape3D_71u53"]
data = PackedVector3Array(-0.25, 0.2, 0.1, -0.25, -0.2, 0.1, -0.25, 0.2, -0.1, -0.25, 0.2, -0.1, -0.25, -0.2, 0.1, -0.25, -0.2, -0.1, -0.25, 0.2, -0.1, -0.25, -0.2, -0.1, 0.25, 0.2, -0.1, 0.25, 0.2, -0.1, -0.25, -0.2, -0.1, 0.25, -0.2, -0.1, 0.25, 0.2, -0.1, 0.25, -0.2, -0.1, 0.25, 0.2, 0.1, 0.25, 0.2, 0.1, 0.25, -0.2, -0.1, 0.25, -0.2, 0.1, -0.25, -0.2, 0.1, -0.25, 0.2, 0.1, -0.15, -0.2, 0.3, -0.15, -0.2, 0.3, -0.25, 0.2, 0.1, -0.15, 0.04, 0.3, 0.25, -0.2, -0.1, -0.25, -0.2, -0.1, 0.25, -0.2, 0.1, 0.25, -0.2, 0.1, -0.25, -0.2, -0.1, -0.25, -0.2, 0.1, 0.25, -0.2, 0.1, -0.25, -0.2, 0.1, 0.15, -0.2, 0.3, 0.15, -0.2, 0.3, -0.25, -0.2, 0.1, -0.15, -0.2, 0.3, -0.25, 0.2, -0.1, 0.25, 0.2, -0.1, -0.25, 0.2, 0.1, -0.25, 0.2, 0.1, 0.25, 0.2, -0.1, 0.25, 0.2, 0.1, 0.15, 0.04, 0.3, 0.15, -0.2, 0.3, -0.15, 0.04, 0.3, -0.15, 0.04, 0.3, 0.15, -0.2, 0.3, -0.15, -0.2, 0.3, -0.25, 0.2, 0.1, 0.25, 0.2, 0.1, -0.15, 0.04, 0.3, -0.15, 0.04, 0.3, 0.25, 0.2, 0.1, 0.15, 0.04, 0.3, 0.25, 0.2, 0.1, 0.25, -0.2, 0.1, 0.15, 0.04, 0.3, 0.15, 0.04, 0.3, 0.25, -0.2, 0.1, 0.15, -0.2, 0.3)
[node name="Monitor" type="Node3D"]
[node name="MeshInstance3D" type="MeshInstance3D" parent="."]
mesh = SubResource("ArrayMesh_xfnq5")
[node name="StaticBody3D" type="StaticBody3D" parent="MeshInstance3D"]
[node name="CollisionShape3D" type="CollisionShape3D" parent="MeshInstance3D/StaticBody3D"]
shape = SubResource("ConcavePolygonShape3D_71u53")

View File

@ -0,0 +1,50 @@
[gd_scene load_steps=5 format=3 uid="uid://ccj5ohaw85uwt"]
[ext_resource type="PackedScene" uid="uid://bve6iya13lhah" path="res://src/props/monitor/monitor.tscn" id="1_jcssa"]
[sub_resource type="Animation" id="Animation_f6xlw"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("MeshInstance3D:mesh:surface_0/material:emission_energy_multiplier")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [1.0]
}
[sub_resource type="Animation" id="Animation_71u53"]
resource_name = "flicker"
length = 0.01
loop_mode = 1
step = 0.005
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("MeshInstance3D:mesh:surface_0/material:emission_energy_multiplier")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.005),
"transitions": PackedFloat32Array(1, 1),
"update": 0,
"values": [1.6, 1.8]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_wucr7"]
_data = {
&"RESET": SubResource("Animation_f6xlw"),
&"flicker": SubResource("Animation_71u53")
}
[node name="MonitorOn" instance=ExtResource("1_jcssa")]
[node name="FlickerAnimation" type="AnimationPlayer" parent="." index="1"]
libraries = {
&"": SubResource("AnimationLibrary_wucr7")
}
autoplay = "flicker"

View File

@ -0,0 +1,62 @@
@tool
class_name TextTerminal extends Node3D
## An in-game terminal that can display diegetic text
const CHAR_LIMIT := 34
const LINE_LIMIT := 11
@export var char_speed := 0.01
@export var cursor_sym := "_"
@export var cursor_blink_speed := 0.4
@export_multiline var text: String:
set = _set_text
var _text_buffer: String
var _text_out: String:
set(value):
_text_out = value
_update_label()
var _cursor_on := false:
set(value):
_cursor_on = value
_update_label()
@onready var label_3d: Label3D = %Label3D
@onready var output_interval: Timer = %OutputInterval
@onready var cursor_blinker: Timer = %CursorBlinker
func _ready() -> void:
cursor_blinker.start(cursor_blink_speed)
if text:
_set_text(text)
func _update_label() -> void:
label_3d.text = _text_out
if _cursor_on:
label_3d.text += cursor_sym
func _set_text(value: String) -> void:
text = value
_text_out = ""
_text_buffer = text
if _text_buffer:
output_interval.start(char_speed)
func _blink_cursor() -> void:
_cursor_on = not _cursor_on
cursor_blinker.start(cursor_blink_speed)
func _show_next_char() -> void:
var head := _text_buffer[0]
_text_out += head
_text_buffer = _text_buffer.substr(1)
if _text_buffer:
output_interval.start(char_speed)

View File

@ -0,0 +1 @@
uid://dxyn2db6jmna2

View File

@ -0,0 +1,40 @@
[gd_scene load_steps=4 format=3 uid="uid://c7ljflq1eehym"]
[ext_resource type="PackedScene" uid="uid://ccj5ohaw85uwt" path="res://src/props/monitor/monitor_on.tscn" id="1_3vdx1"]
[ext_resource type="Script" uid="uid://dxyn2db6jmna2" path="res://src/props/text_terminal/text_terminal.gd" id="1_25jpy"]
[sub_resource type="SystemFont" id="SystemFont_twqjh"]
font_names = PackedStringArray("Monospace")
[node name="TextTerminal" type="Node3D"]
transform = Transform3D(2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0)
script = ExtResource("1_25jpy")
[node name="MonitorOn" parent="." instance=ExtResource("1_3vdx1")]
transform = Transform3D(-1, 0, -8.74228e-08, 0, 1, 0, 8.74228e-08, 0, -1, 0, 0, 0)
[node name="Label3D" type="Label3D" parent="."]
unique_name_in_owner = true
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.184204, 0.138956, 0.102927)
pixel_size = 0.0002
modulate = Color(0, 1, 0.301961, 1)
text = "_"
font = SubResource("SystemFont_twqjh")
font_size = 90
outline_size = 36
horizontal_alignment = 0
vertical_alignment = 0
line_spacing = -19.0
[node name="OutputInterval" type="Timer" parent="."]
unique_name_in_owner = true
wait_time = 0.015
one_shot = true
[node name="CursorBlinker" type="Timer" parent="."]
unique_name_in_owner = true
wait_time = 0.4
one_shot = true
[connection signal="timeout" from="OutputInterval" to="." method="_show_next_char"]
[connection signal="timeout" from="CursorBlinker" to="." method="_blink_cursor"]

View File

@ -29,3 +29,9 @@ size_flags_horizontal = 4
size_flags_vertical = 8 size_flags_vertical = 8
text = "0" text = "0"
horizontal_alignment = 2 horizontal_alignment = 2
[node name="Label2" type="Label" parent="."]
texture_filter = 6
layout_mode = 2
size_flags_horizontal = 0
text = " g"

View File

@ -11,9 +11,9 @@ extends GunkNode
func _process(delta: float) -> void: func _process(delta: float) -> void:
super._process(delta) super._process(delta)
var shader: ShaderMaterial = mesh_instance.mesh.surface_get_material(0) var shader: ShaderMaterial = mesh_instance.mesh.surface_get_material(0)
var value := pct_damage() var damage := pct_damage()
shader.set_shader_parameter("jitter_time_scale", pow(value * jitter_scale_factor, 1.2)) shader.set_shader_parameter("jitter_time_scale", pow(damage * jitter_scale_factor, 1.2))
shader.set_shader_parameter("vertex_inflation", pow(value * jitter_inflation_factor, 3)) shader.set_shader_parameter("vertex_inflation", pow(damage * jitter_inflation_factor, 3))
func _destroy() -> void: func _destroy() -> void:

View File

@ -3,19 +3,18 @@ The player can deposit collected [[grunk]] in the grunk tank back at their ship.
- When the player meets their quota, they're allowed to leave (good end) - When the player meets their quota, they're allowed to leave (good end)
- Their ship's ignition is locked out until quota is met - Their ship's ignition is locked out until quota is met
- Within the #lore, the player is incentivized to collect grunk with a series of (useless and asinine) milestones: - Within the #lore, the player is incentivized to collect grunk with a series of (useless and asinine) milestones:
1. [[mp3 player|Bonus MP3]] 1. [[mp3 player]]
2. [[Toothbrush]] (_Advanced Grunk Reticulation System_) 2. [[mp3 player|Bonus MP3]]
3. [[mp3 player|Bonus MP3]] 3. [[Toothbrush]] (_Advanced Grunk Reticulation System_)
4. STICKERS! 4. [[mp3 player|Bonus MP3]]
5. [[mp3 player|Bonus MP3]] 5. STICKERS!
6. Wellness Seminar 6. [[mp3 player|Bonus MP3]]
7. [[mp3 player|Bonus MP3]] 7. Wellness Seminar
8. ??? 8. [[mp3 player|Bonus MP3]]
9. [[mp3 player|Bonus MP3]] 9. QUOTA (& commemorative pin)
10. QUOTA (& commemorative pin) 10. [[mp3 player|Bonus MP3]]
11. [[mp3 player|Bonus MP3]] 11. ???
12. ??? 12. [[mp3 player|Bonus MP3]]
13. [[mp3 player|Bonus MP3]] 13. ???
14. ??? 14. [[mp3 player|Bonus MP3]]
15. [[mp3 player|Bonus MP3]] 15. Taco Fiesta
16. Taco Fiesta

View File

@ -4,4 +4,4 @@ By the power vested in me by the United Corporations of Earth, for your crimes I
# GRUNK # GRUNK
Player is sent to a derelict space station ( #maybe underwater research station?) and employed to harvest [[grunk]]. Player is sent to a derelict cargo ship (_The GURKN_) and employed to harvest [[grunk]]. They may not leave until they meet their quota.

View File

@ -10,7 +10,8 @@
{"id":"be3415e76c0603f6","type":"file","file":"level/airlock.md","x":-1000,"y":-735,"width":406,"height":320}, {"id":"be3415e76c0603f6","type":"file","file":"level/airlock.md","x":-1000,"y":-735,"width":406,"height":320},
{"id":"bbfc75ce368543fc","type":"file","file":"level/player ship.md","x":-957,"y":-320,"width":320,"height":400}, {"id":"bbfc75ce368543fc","type":"file","file":"level/player ship.md","x":-957,"y":-320,"width":320,"height":400},
{"id":"55780df8c38e6693","type":"file","file":"level/cargo bay.md","x":0,"y":-1402,"width":391,"height":350}, {"id":"55780df8c38e6693","type":"file","file":"level/cargo bay.md","x":0,"y":-1402,"width":391,"height":350},
{"id":"1800ef4d498a530f","type":"file","file":"level/ops center.md","x":-300,"y":-2160,"width":300,"height":396} {"id":"1800ef4d498a530f","type":"file","file":"level/ops center.md","x":-300,"y":-2160,"width":300,"height":396},
{"id":"f92e4ff7439ba3b9","x":-1304,"y":-2080,"width":246,"height":50,"type":"text","text":"# THE GURKN"}
], ],
"edges":[ "edges":[
{"id":"f88a68cbe1935f27","fromNode":"bbfc75ce368543fc","fromSide":"top","toNode":"be3415e76c0603f6","toSide":"bottom","toEnd":"none"}, {"id":"f88a68cbe1935f27","fromNode":"bbfc75ce368543fc","fromSide":"top","toNode":"be3415e76c0603f6","toSide":"bottom","toEnd":"none"},