Initial commit

This commit is contained in:
scorpion21211-cmd
2026-10-03 23:29:41 -04:00
commit e24bbbda5d
10586 changed files with 1030090 additions and 0 deletions
+7
View File
@@ -0,0 +1,7 @@
[gd_resource type="StandardMaterial3D" load_steps=2 format=3 uid="uid://3j8q2ljffqjp"]
[ext_resource type="Texture2D" uid="uid://bf63eg11cuqij" path="res://Kyle's Rock Pack/Kyle Fuji/Scenes/Textures/T_flag.png" id="1_3fh8f"]
[resource]
cull_mode = 2
albedo_texture = ExtResource("1_3fh8f")
+3
View File
@@ -0,0 +1,3 @@
[gd_resource type="StandardMaterial3D" format=3 uid="uid://c1mm1y80k6872"]
[resource]
BIN
View File
Binary file not shown.
+45
View File
@@ -0,0 +1,45 @@
[remap]
importer="scene"
importer_version=1
type="PackedScene"
uid="uid://j1hw1m4qj2at"
path="res://.godot/imported/flag.glb-fe545f4d774c55d809d86958009a1051.scn"
[deps]
source_file="res://Scenes/Models/flag.glb"
dest_files=["res://.godot/imported/flag.glb-fe545f4d774c55d809d86958009a1051.scn"]
[params]
nodes/root_type=""
nodes/root_name=""
nodes/root_script=null
mesh_library/use_node_names_as_mesh_names=false
array_mesh/deduplicate_surfaces=true
nodes/apply_root_scale=true
nodes/root_scale=1.0
nodes/import_as_skeleton_bones=false
nodes/use_name_suffixes=true
nodes/use_node_type_suffixes=true
meshes/ensure_tangents=true
meshes/generate_lods=true
meshes/create_shadow_meshes=true
meshes/light_baking=1
meshes/lightmap_texel_size=0.2
meshes/force_disable_compression=false
skins/use_named_skins=true
animation/import=true
animation/fps=30
animation/trimming=false
animation/remove_immutable_tracks=true
animation/import_rest_as_RESET=false
import_script/path=""
materials/extract=0
materials/extract_format=0
materials/extract_path=""
_subresources={}
gltf/naming_version=2
gltf/embedded_image_handling=1
gltf/texture_map_mode=0
Binary file not shown.
+45
View File
@@ -0,0 +1,45 @@
[remap]
importer="scene"
importer_version=1
type="PackedScene"
uid="uid://dlbqbjm60jqyc"
path="res://.godot/imported/flag_pole.glb-c5f6f3f40eba4f0eae5b3f172d409e4a.scn"
[deps]
source_file="res://Scenes/Models/flag_pole.glb"
dest_files=["res://.godot/imported/flag_pole.glb-c5f6f3f40eba4f0eae5b3f172d409e4a.scn"]
[params]
nodes/root_type=""
nodes/root_name=""
nodes/root_script=null
mesh_library/use_node_names_as_mesh_names=false
array_mesh/deduplicate_surfaces=true
nodes/apply_root_scale=true
nodes/root_scale=1.0
nodes/import_as_skeleton_bones=false
nodes/use_name_suffixes=true
nodes/use_node_type_suffixes=true
meshes/ensure_tangents=true
meshes/generate_lods=true
meshes/create_shadow_meshes=true
meshes/light_baking=1
meshes/lightmap_texel_size=0.2
meshes/force_disable_compression=false
skins/use_named_skins=true
animation/import=true
animation/fps=30
animation/trimming=false
animation/remove_immutable_tracks=true
animation/import_rest_as_RESET=false
import_script/path=""
materials/extract=0
materials/extract_format=0
materials/extract_path=""
_subresources={}
gltf/naming_version=2
gltf/embedded_image_handling=1
gltf/texture_map_mode=0
+8
View File
@@ -0,0 +1,8 @@
[gd_scene format=3 uid="uid://byn3aoaubhy14"]
[ext_resource type="PackedScene" uid="uid://b6eo746yujjtr" path="res://character assets/Characters/BlueSoldier_Male.gltf" id="1_igigs"]
[node name="Node3D" type="Node3D" unique_id=301609784]
[node name="BlueSoldier_Male" parent="." unique_id=1455949063 instance=ExtResource("1_igigs")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.46351385, 0, 0.793349)
@@ -0,0 +1,10 @@
[gd_scene load_steps=3 format=3 uid="uid://dsuep54iqmwqv"]
[ext_resource type="PackedScene" uid="uid://j1hw1m4qj2at" path="res://Kyle's Rock Pack/Kyle Fuji/Scenes/Models/flag.glb" id="1_s1rd0"]
[ext_resource type="Material" uid="uid://3j8q2ljffqjp" path="res://Kyle's Rock Pack/Kyle Fuji/Scenes/Materials/M_flag.tres" id="2_s1rd0"]
[node name="flag" instance=ExtResource("1_s1rd0")]
[node name="flag" parent="." index="0"]
transform = Transform3D(0.36920106, 0.00010158674, 0.00026268276, 0.00026271862, -0.00012781133, -0.36920106, -0.00010149403, 0.36920115, -0.00012788495, 0, 1.5941696, 0)
material_override = ExtResource("2_s1rd0")
@@ -0,0 +1,9 @@
[gd_scene load_steps=3 format=3 uid="uid://cfo28kg1g1tln"]
[ext_resource type="PackedScene" uid="uid://dlbqbjm60jqyc" path="res://Kyle's Rock Pack/Kyle Fuji/Scenes/Models/flag_pole.glb" id="1_0l7o7"]
[ext_resource type="Material" uid="uid://c1mm1y80k6872" path="res://Kyle's Rock Pack/Kyle Fuji/Scenes/Materials/M_flag_pole.tres" id="2_472wk"]
[node name="flag_pole" instance=ExtResource("1_0l7o7")]
[node name="flag_pole" parent="." index="0"]
material_override = ExtResource("2_472wk")
+20
View File
@@ -0,0 +1,20 @@
[gd_scene load_steps=4 format=3 uid="uid://d0l38f4125c54"]
[ext_resource type="PackedScene" uid="uid://dsuep54iqmwqv" path="res://Kyle's Rock Pack/Kyle Fuji/Scenes/Prefabs/flag helpers/flag_cloth.tscn" id="1_s1rd0"]
[ext_resource type="PackedScene" uid="uid://cfo28kg1g1tln" path="res://Kyle's Rock Pack/Kyle Fuji/Scenes/Prefabs/flag helpers/flag_pole.tscn" id="2_0bfkk"]
[sub_resource type="BoxShape3D" id="BoxShape3D_s1rd0"]
size = Vector3(1.0652161, 2.0059204, 0.19836426)
[node name="flag" type="Node3D" groups=["flag_group"]]
transform = Transform3D(2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0)
[node name="flag" parent="." groups=["flag_group"] instance=ExtResource("1_s1rd0")]
[node name="flag_pole" parent="." groups=["flag_group"] instance=ExtResource("2_0bfkk")]
[node name="StaticBody3D" type="StaticBody3D" parent="." groups=["flag_group"]]
[node name="CollisionShape3D" type="CollisionShape3D" parent="StaticBody3D" groups=["flag_group"]]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.43354797, 0.99716187, 0.0067749023)
shape = SubResource("BoxShape3D_s1rd0")
Binary file not shown.
+46
View File
@@ -0,0 +1,46 @@
[remap]
importer="scene"
importer_version=1
type="PackedScene"
uid="uid://ccu6j1dlrj0ll"
path="res://.godot/imported/RPG-Character-Bones.FBX-69d8ffcb296c2c499cb24733622b9379.scn"
[deps]
source_file="res://Scenes/RPG-Character-Bones.FBX"
dest_files=["res://.godot/imported/RPG-Character-Bones.FBX-69d8ffcb296c2c499cb24733622b9379.scn"]
[params]
nodes/root_type=""
nodes/root_name=""
nodes/root_script=null
mesh_library/use_node_names_as_mesh_names=false
array_mesh/deduplicate_surfaces=true
nodes/apply_root_scale=true
nodes/root_scale=1.0
nodes/import_as_skeleton_bones=false
nodes/use_name_suffixes=true
nodes/use_node_type_suffixes=true
meshes/ensure_tangents=true
meshes/generate_lods=true
meshes/create_shadow_meshes=true
meshes/light_baking=1
meshes/lightmap_texel_size=0.2
meshes/force_disable_compression=false
skins/use_named_skins=true
animation/import=true
animation/fps=30
animation/trimming=true
animation/remove_immutable_tracks=true
animation/import_rest_as_RESET=false
import_script/path=""
materials/extract=0
materials/extract_format=0
materials/extract_path=""
_subresources={}
fbx/importer=0
fbx/allow_geometry_helper_nodes=false
fbx/embedded_image_handling=1
fbx/naming_version=2
+9
View File
@@ -0,0 +1,9 @@
extends StaticBody3D
@export var health_restore: float = 25.0
func on_interact(player: Node) -> void:
if player.has_method("add_health"):
player.add_health(health_restore)
print("You rest for a while. Health restored.")
+1
View File
@@ -0,0 +1 @@
uid://d2cfgmuwrsr3y
+9
View File
@@ -0,0 +1,9 @@
extends StaticBody3D
@export var item_name: String = "Beer Can"
func on_interact(player: Node) -> void:
if player.has_method("add_item"):
player.add_item(item_name)
print("Picked up: ", item_name)
queue_free()
+1
View File
@@ -0,0 +1 @@
uid://4dys8ga8ap02
+16
View File
@@ -0,0 +1,16 @@
extends Camera3D
@onready var capsule: Node3D = get_node("/root/Node3D/EscapeCapsule")
func _physics_process(_delta):
if not capsule:
return
var nose_dir = capsule.global_transform.basis.y
var up_dir = -capsule.global_transform.basis.z
global_position = capsule.global_position + nose_dir * 4.0
look_at(capsule.global_position + nose_dir * 30.0, up_dir)
# Fix upside-down
rotate_object_local(Vector3.FORWARD, deg_to_rad(180))
+1
View File
@@ -0,0 +1 @@
uid://di78d53y38p67
+66
View File
@@ -0,0 +1,66 @@
extends CharacterBody3D
# How fast the player moves in meters per second.
@export var speed = 14
# The downward acceleration when in the air, in meters per second squared.
@export var fall_acceleration = 75
@export var mouse_sensitivity = 0.002
const JUMP_VELOCITY = 25
var target_velocity = Vector3.ZERO
# Reference to your camera pivot or camera
@onready var pivot = $Pivot
func _ready():
# Captures the mouse cursor so it stays in the game window
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
func _input(event):
if event is InputEventMouseMotion:
rotate_y(-event.relative.x * mouse_sensitivity)
pivot.rotate_x(-event.relative.y * mouse_sensitivity)
pivot.rotation.x = clamp(pivot.rotation.x, deg_to_rad(-60), deg_to_rad(60))
if event.is_action_pressed("ui_cancel"):
Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT:
if Input.get_mouse_mode() == Input.MOUSE_MODE_VISIBLE:
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
func _physics_process(delta):
var direction = Vector3.ZERO
# need to map to WASD to make it work with WASD
if Input.is_action_pressed("ui_right"):
direction.x += 1
if Input.is_action_pressed("ui_left"):
direction.x -= 1
if Input.is_action_pressed("ui_down"):
direction.z += 1
if Input.is_action_pressed("ui_up"):
direction.z -= 1
if direction != Vector3.ZERO:
direction = direction.normalized()
direction = (transform.basis * direction).normalized()
# Ground Velocity
target_velocity.x = direction.x * speed
target_velocity.z = direction.z * speed
# Vertical Velocity
if not is_on_floor(): # If in the air, fall towards the floor. Literally gravity
target_velocity.y = target_velocity.y - (fall_acceleration * delta)
if Input.is_action_just_pressed("ui_accept") and is_on_floor():
target_velocity.y = JUMP_VELOCITY
# Moving the Character
velocity = target_velocity
move_and_slide()
for i in get_slide_collision_count():
var collision = get_slide_collision(i)
var collided_object = collision.get_collider()
if collided_object.is_in_group("flag_group"):
$win_label.set_text("You Win!")
+1
View File
@@ -0,0 +1 @@
uid://flm6ps54u0c4
+459
View File
@@ -0,0 +1,459 @@
extends Control
## Look preview + culture/job lore. Compact grid. No Dock Chaplain.
var name_input: LineEdit
var background_list: Control
var confirm_button: Button
var back_button: Button
var description_label: Label
var bonus_label: Label
var culture_list: Control
var look_world: Node3D
var preview_cam: Camera3D
var sex_male: Button
var sex_female: Button
var name_head: Label
var name_body: Label
var name_legs: Label
var name_feet: Label
const MALE_FBX := "res://character assets/All together/FBX/Humans_Master.fbx"
const FEMALE_FBX := "res://character assets/All together/FBX women/All together.fbx"
const MALE_HEADS := ["Casual_Head", "Casual2_Head", "Worker_Head", "Farmer_Head", "Adventurer_Head", "Punk_Head", "Suit_Head", "Swat_Head", "SpaceSuit_Head"]
const MALE_BODIES := ["Casual_Body", "Casual2_Body", "Worker_Body", "Farmer_Body", "Adventurer_Body", "Punk_Body", "Suit_Body", "Swat_Body", "SpaceSuit_Body"]
const MALE_LEGS := ["Casual_Legs", "Casual2_Legs", "Worker_Legs", "Farmer_Pants", "Adventurer_Legs", "Punk_Legs", "Suit_Legs", "Swat_Legs", "SpaceSuit_Legs"]
const MALE_FEET := ["Casual_Feet", "Casual2_Feet", "Worker_Feet", "Farmer_Feet", "Adventurer_Feet", "Punk_Feet", "Suit_Feet", "Swat_Feet", "SpaceSuit_Feet"]
const FEMALE_HEADS := ["Casual_Head", "Worker_Head", "Suit_Head", "Formal_Head", "Formad_Head", "Adventurer_Head", "Punk_Head", "Soldier_Head", "SciFi_Head"]
const FEMALE_BODIES := ["Casual_Body", "Worker_Body", "Suit_Body", "Formal_Body", "Adventurer_Body", "Punk_Body", "Soldier_Body", "SciFi_Body"]
const FEMALE_LEGS := ["Casual_Legs", "Worker_Legs", "Suit_Legs", "Formal_Legs", "Adventurer_Legs", "Punk_Legs", "Soldier_Legs", "SciFi_Legs"]
const FEMALE_FEET := ["Casual_Feet", "Worker_Feet", "Suit_Feet", "Formal_Feet", "Adventurer_Feet", "Punk_Feet", "Soldier_Feet", "SciFi_Feet"]
var sex: String = "male"
var idx := {"head": 0, "body": 0, "legs": 0, "feet": 0}
var preview_male: Node3D = null
var preview_female: Node3D = null
var cultures := [
{"id": "naf", "name": "North American", "desc": "You grew up under the NAF eagle — Mexico to Panama welded into one machine. English and Spanish in the same breath, carriers in the black, and a simple article of faith: the hemisphere holds, or nothing does."},
{"id": "eaa", "name": "East Asian", "desc": "EAA orthodoxy: long plans, short mercy. Beijing's shadow, Korean steel, Vietnamese patience. You learned early that the loudest claim in the room is rarely the one that survives."},
{"id": "european", "name": "European", "desc": "Old flags, thin coalitions, and the sound of Russia testing the locks. Paris, Berlin, London, Warsaw — still arguing while the sky hardens. You left with a ticket and no illusions about unity."},
{"id": "russian", "name": "Russian", "desc": "Victory parades and rationed truth. Ukraine was the lesson; the Baltics are the rumor that keeps generals warm. Orthodox steel, long winters, and a state that still treats the map as unfinished business."},
{"id": "brazilian", "name": "Brazilian", "desc": "Southern empire blood. Industry, orbit yards, and a continent that refuses to kneel to the north. You carry the heat of a country that builds its own guns and names its own heroes."},
{"id": "independent", "name": "Independent", "desc": "No anthem owns you. Station brats, belt orphans, passport ghosts — you answer to contracts, crew, and the thin margin between air and vacuum."}
]
var backgrounds := [
{"id": "dock_worker", "name": "Dock Worker", "desc": "Hard vacuum on one side of the hatch, warehouse stink on the other. You stacked the mass that keeps Young alive and learned every lie a shipping manifest can tell.", "bonuses": {"money": 90}},
{"id": "junior_engineer", "name": "Junior Engineer", "desc": "When the lights brown out, they call you. Breakers, scrubbers, jury-rigged miracles — you keep the arcology's pulse steady with a multitool and bad coffee.", "bonuses": {"money": 100}},
{"id": "med_tech", "name": "Med Tech", "desc": "Blood on the deck plating, timers on the monitors. You stabilize what the station breaks and don't ask whether the patient salutes the same flag you do.", "bonuses": {"money": 95, "health": 10}},
{"id": "smuggler", "name": "Smuggler", "desc": "Customs is a suggestion; the real map is drawn in debts. You moved what official channels refused to name — and you got paid in silence and credits.", "bonuses": {"money": 120}},
{"id": "security_cadet", "name": "Security Cadet", "desc": "Badge, route, rules of engagement written by people who sleep in better modules. You've already learned how fast procedure burns when someone runs.", "bonuses": {"money": 85, "health": 5}},
{"id": "botanist", "name": "Botanist", "desc": "Oxygen has a green face. You worked the trays and towers that turn waste into breath — the quietest strategic asset on the Moon.", "bonuses": {"money": 80, "food": 15}},
{"id": "skiff_pilot", "name": "Skiff Pilot", "desc": "Low and fast over dead regolith. Hop routes, run supplies, and trust the aerospace skills that keep you off the crater floor.", "bonuses": {"money": 105}},
{"id": "life_support_tech", "name": "Life Support Tech", "desc": "Pressure, CO₂, water loops — the boring systems that kill everyone when they fail. You listened to the station the way a doctor listens to a chest.", "bonuses": {"money": 95}},
{"id": "university_aide", "name": "University Aide", "desc": "Tsiolkovsky Hall: fusion on the chalkboard, rumors in the aisle. Dr Ernesto talks brachistochrones like scripture. You fetched the data and heard the future early.", "bonuses": {"money": 75}},
{"id": "unemployed", "name": "Unemployed", "desc": "No contract, no module lease, no one to vouch. Just a name on a transit list and a short window to become necessary.", "bonuses": {"money": 40}}
]
var selected_culture: Dictionary = {}
var selected_background: Dictionary = {}
var background_buttons: Array[Button] = []
var culture_buttons: Array[Button] = []
func _ready() -> void:
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
name_input = _find("NameInput") as LineEdit
background_list = _find("BackgroundL") as Control
if background_list == null:
background_list = _find("BackgroundList") as Control
confirm_button = _find("ConfirmButton") as Button
back_button = _find("BackButton") as Button
description_label = _find("DescriptionL") as Label
if description_label == null:
description_label = _find("DescriptionLabel") as Label
bonus_label = _find("BonusLabel") as Label
culture_list = _find("CultureList") as Control
look_world = _find("LookWorld") as Node3D
preview_cam = _find("LookCam") as Camera3D
sex_male = _find("SexMale") as Button
sex_female = _find("SexFemale") as Button
name_head = _find("Name_Head") as Label
name_body = _find("Name_Body") as Label
name_legs = _find("Name_Legs") as Label
name_feet = _find("Name_Feet") as Label
var vp := _find("SubViewport") as SubViewport
if vp:
vp.own_world_3d = true
vp.transparent_bg = false
vp.render_target_update_mode = SubViewport.UPDATE_ALWAYS
if description_label:
description_label.visible = true
description_label.add_theme_font_size_override("font_size", 14)
description_label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
description_label.custom_minimum_size = Vector2(0, 88)
description_label.max_lines_visible = 8
description_label.clip_text = false
description_label.size_flags_vertical = Control.SIZE_EXPAND_FILL
if bonus_label:
bonus_label.visible = true
bonus_label.add_theme_font_size_override("font_size", 14)
bonus_label.custom_minimum_size = Vector2(0, 22)
bonus_label.max_lines_visible = 2
bonus_label.clip_text = false
if confirm_button:
confirm_button.pressed.connect(_on_confirm)
if back_button:
back_button.pressed.connect(_on_back)
if sex_male:
sex_male.pressed.connect(func() -> void: _set_sex("male"))
if sex_female:
sex_female.pressed.connect(func() -> void: _set_sex("female"))
_wire_cycle("Prev_Head", "Next_Head", "head")
_wire_cycle("Prev_Body", "Next_Body", "body")
_wire_cycle("Prev_Legs", "Next_Legs", "legs")
_wire_cycle("Prev_Feet", "Next_Feet", "feet")
if culture_list is GridContainer:
(culture_list as GridContainer).columns = 3
if background_list is GridContainer:
(background_list as GridContainer).columns = 2
_wire_culture_buttons()
_spawn_previews()
_build_background_buttons()
if cultures.size() > 0:
_select_culture(cultures[0])
if backgrounds.size() > 0:
_select_background(backgrounds[0])
_set_sex("male")
func _find(n: String) -> Node:
return find_child(n, true, false)
func _size_grid_button(btn: Button) -> void:
btn.custom_minimum_size = Vector2(0, 24)
btn.size_flags_horizontal = Control.SIZE_EXPAND_FILL
btn.size_flags_vertical = Control.SIZE_SHRINK_CENTER
func _wire_cycle(prev_name: String, next_name: String, slot: String) -> void:
var prev_b := _find(prev_name) as Button
var next_b := _find(next_name) as Button
if prev_b:
prev_b.pressed.connect(func() -> void: _cycle(slot, -1))
if next_b:
next_b.pressed.connect(func() -> void: _cycle(slot, 1))
func _wire_culture_buttons() -> void:
culture_buttons.clear()
if culture_list == null:
return
var map := {
"Culture_NA": "naf", "Culture_NAF": "naf",
"Culture_EA": "eaa", "Culture_EAA": "eaa",
"Culture_Eur": "european", "Culture_European": "european",
"Culture_Ru": "russian", "Culture_Russian": "russian",
"Culture_Br": "brazilian", "Culture_Brazilian": "brazilian",
"Culture_In": "independent", "Culture_Independent": "independent",
}
for child in culture_list.get_children():
if not (child is Button):
continue
var btn := child as Button
var cid: String = str(map.get(btn.name, ""))
if cid.is_empty():
continue
var data: Dictionary = {}
for c in cultures:
if c["id"] == cid:
data = c
break
if data.is_empty():
continue
btn.toggle_mode = true
_size_grid_button(btn)
btn.pressed.connect(_on_culture_pressed.bind(data, btn))
culture_buttons.append(btn)
func _on_culture_pressed(data: Dictionary, btn: Button) -> void:
_select_culture(data)
for b in culture_buttons:
b.button_pressed = (b == btn)
func _select_culture(data: Dictionary) -> void:
selected_culture = data
_refresh_desc()
func _build_background_buttons() -> void:
if background_list == null:
push_error("BackgroundL / BackgroundList missing — jobs cannot spawn")
return
for child in background_list.get_children():
child.queue_free()
background_buttons.clear()
for bg in backgrounds:
var btn := Button.new()
btn.text = str(bg["name"])
btn.toggle_mode = true
_size_grid_button(btn)
btn.pressed.connect(_on_background_pressed.bind(bg, btn))
background_list.add_child(btn)
background_buttons.append(btn)
func _on_background_pressed(bg: Dictionary, btn: Button) -> void:
_select_background(bg)
for b in background_buttons:
b.button_pressed = (b == btn)
func _select_background(bg: Dictionary) -> void:
selected_background = bg
_refresh_desc()
if bonus_label:
var bonuses: Dictionary = bg.get("bonuses", {})
var money: int = int(bonuses.get("money", 0))
var extra: PackedStringArray = []
if bonuses.has("food"):
extra.append("Food +%s" % str(bonuses["food"]))
if bonuses.has("health"):
extra.append("Health +%s" % str(bonuses["health"]))
var extra_txt := (", " + ", ".join(extra)) if extra.size() > 0 else ""
bonus_label.text = "Starting bonus: %d credits%s" % [money, extra_txt]
func _refresh_desc() -> void:
var parts: PackedStringArray = []
if not selected_culture.is_empty():
parts.append(str(selected_culture.get("desc", "")))
if not selected_background.is_empty():
parts.append(str(selected_background.get("desc", "")))
var body := "\n\n".join(parts)
if description_label:
description_label.visible = true
description_label.text = body
if bonus_label == null and description_label and not selected_background.is_empty():
var bonuses: Dictionary = selected_background.get("bonuses", {})
var money: int = int(bonuses.get("money", 0))
description_label.text = body + "\n\nStarting bonus: %d credits" % money
func _spawn_previews() -> void:
if look_world == null:
push_warning("LookWorld missing — Look preview will be empty")
return
_ensure_look_stage()
preview_male = _instance_fbx(MALE_FBX)
preview_female = _instance_fbx(FEMALE_FBX)
if preview_male:
preview_male.name = "PreviewMale"
look_world.add_child(preview_male)
if preview_female:
preview_female.name = "PreviewFemale"
look_world.add_child(preview_female)
print("Look spawn male=", preview_male, " female=", preview_female, " cam=", preview_cam)
if preview_cam:
preview_cam.current = true
preview_cam.position = Vector3(0.0, 1.08, 5.4)
preview_cam.rotation_degrees = Vector3(-4.0, 0.0, 0.0)
preview_cam.fov = 34.0
func _ensure_look_stage() -> void:
if look_world.get_node_or_null("LookFill") == null:
var fill := OmniLight3D.new()
fill.name = "LookFill"
fill.light_energy = 1.6
fill.omni_range = 14.0
fill.position = Vector3(0.5, 2.0, 2.2)
look_world.add_child(fill)
if look_world.get_node_or_null("LookEnv") == null:
var we := WorldEnvironment.new()
we.name = "LookEnv"
var env := Environment.new()
env.background_mode = Environment.BG_COLOR
env.background_color = Color(0.10, 0.11, 0.13)
env.ambient_light_source = Environment.AMBIENT_SOURCE_COLOR
env.ambient_light_color = Color(0.78, 0.78, 0.82)
env.ambient_light_energy = 1.0
we.environment = env
look_world.add_child(we)
func _instance_fbx(path: String) -> Node3D:
if not ResourceLoader.exists(path):
push_warning("Missing character file: " + path)
return null
var res = load(path)
if res == null:
return null
var inst: Node = res.instantiate()
if inst is Node3D:
(inst as Node3D).position = Vector3.ZERO
(inst as Node3D).rotation_degrees = Vector3.ZERO
(inst as Node3D).scale = Vector3.ONE
return inst as Node3D
return null
func _lists() -> Dictionary:
if sex == "male":
return {"head": MALE_HEADS, "body": MALE_BODIES, "legs": MALE_LEGS, "feet": MALE_FEET}
return {"head": FEMALE_HEADS, "body": FEMALE_BODIES, "legs": FEMALE_LEGS, "feet": FEMALE_FEET}
func _active_preview() -> Node3D:
return preview_male if sex == "male" else preview_female
func _set_sex(s: String) -> void:
sex = s
idx = {"head": 0, "body": 0, "legs": 0, "feet": 0}
if preview_male:
preview_male.visible = (s == "male")
if preview_female:
preview_female.visible = (s == "female")
_apply_look()
func _cycle(slot: String, dir: int) -> void:
var arr: Array = _lists()[slot]
if arr.is_empty():
return
idx[slot] = posmod(idx[slot] + dir, arr.size())
_apply_look()
func _apply_look() -> void:
var root := _active_preview()
if root == null:
return
var lists := _lists()
var keep: Array[String] = [
str(lists["head"][idx["head"]]),
str(lists["body"][idx["body"]]),
str(lists["legs"][idx["legs"]]),
str(lists["feet"][idx["feet"]]),
]
_hide_all_geometry(root)
for mesh_name in keep:
_show_mesh(root, mesh_name)
_hide_other_slots(root, keep)
if name_head:
name_head.text = lists["head"][idx["head"]].replace("_Head", "").replace("Formad", "Formal")
if name_body:
name_body.text = lists["body"][idx["body"]].replace("_Body", "")
if name_legs:
name_legs.text = lists["legs"][idx["legs"]].replace("_Legs", "").replace("_Pants", "")
if name_feet:
name_feet.text = lists["feet"][idx["feet"]].replace("_Feet", "")
_play_idle(root)
func _hide_all_geometry(root: Node) -> void:
var stack: Array[Node] = [root]
while stack.size() > 0:
var n: Node = stack.pop_back()
if n is VisualInstance3D:
n.visible = false
for c in n.get_children():
stack.append(c)
func _show_mesh(root: Node, mesh_name: String) -> void:
var node := root.find_child(mesh_name, true, false)
if node == null:
return
_show_tree(node)
func _show_tree(n: Node) -> void:
n.visible = true
if n is VisualInstance3D:
n.visible = true
for c in n.get_children():
_show_tree(c)
func _hide_other_slots(root: Node, keep: Array[String]) -> void:
var stack: Array[Node] = [root]
while stack.size() > 0:
var n: Node = stack.pop_back()
if _is_slot_root(n.name) and keep.find(n.name) == -1:
_hide_tree(n)
else:
for c in n.get_children():
stack.append(c)
func _hide_tree(n: Node) -> void:
n.visible = false
if n is VisualInstance3D:
n.visible = false
for c in n.get_children():
_hide_tree(c)
func _is_slot_root(mesh_name: String) -> bool:
return (
mesh_name.ends_with("_Head")
or mesh_name.ends_with("_Body")
or mesh_name.ends_with("_Legs")
or mesh_name.ends_with("_Feet")
or mesh_name.ends_with("_Pants")
)
func _play_idle(root: Node) -> void:
var anim: AnimationPlayer = root.find_child("AnimationPlayer", true, false)
if anim == null:
return
for clip in ["CharacterArmature|Idle", "Idle"]:
if anim.has_animation(clip):
anim.play(clip)
return
func _look_payload() -> Dictionary:
var lists := _lists()
return {
"sex": sex,
"head": lists["head"][idx["head"]],
"body": lists["body"][idx["body"]],
"legs": lists["legs"][idx["legs"]],
"feet": lists["feet"][idx["feet"]],
}
func _on_confirm() -> void:
var player_name := "Colonist"
if name_input:
player_name = name_input.text.strip_edges()
if player_name.is_empty():
player_name = "Colonist"
if selected_background.is_empty() and backgrounds.size() > 0:
selected_background = backgrounds[0]
if selected_culture.is_empty() and cultures.size() > 0:
selected_culture = cultures[0]
var data := {
"player_name": player_name,
"appearance": _look_payload(),
"culture_id": selected_culture.get("id", ""),
"culture_name": selected_culture.get("name", ""),
"background_id": selected_background.get("id", ""),
"background_name": selected_background.get("name", ""),
"bonuses": selected_background.get("bonuses", {}),
}
Engine.set_meta("player_creation_data", data)
print("Creation packed: ", data)
get_tree().change_scene_to_file("res://Scenes/main.tscn")
func _on_back() -> void:
get_tree().change_scene_to_file("res://Scenes/main_menu.tscn")
+1
View File
@@ -0,0 +1 @@
uid://cxrxrk0qt15dl
+9
View File
@@ -0,0 +1,9 @@
extends StaticBody3D
@export var item_name: String = "Circuit Board"
func on_interact(player: Node) -> void:
if player.has_method("add_item"):
player.add_item(item_name)
print("Picked up: ", item_name)
queue_free()
+1
View File
@@ -0,0 +1 @@
uid://b0oppy8q64xry
+9
View File
@@ -0,0 +1,9 @@
extends StaticBody3D
@export var item_name: String = "Cooking Knife"
func on_interact(player: Node) -> void:
if player.has_method("add_item"):
player.add_item(item_name)
print("Picked up: ", item_name)
queue_free()
+1
View File
@@ -0,0 +1 @@
uid://cley0rs8im7v3
+9
View File
@@ -0,0 +1,9 @@
extends StaticBody3D
@export var item_name: String = "Dried Noodles"
func on_interact(player: Node) -> void:
if player.has_method("add_item"):
player.add_item(item_name)
print("Picked up: ", item_name)
queue_free()
+1
View File
@@ -0,0 +1 @@
uid://c5j656olsdtjs
+68
View File
@@ -0,0 +1,68 @@
extends Node3D
## Earth impostor — from Luna you are always far; show a disc inside far plane.
@export var real_earth_path: NodePath = ^".."
@export var surface_path: NodePath = ^"../EarthSurface"
@export var impostor_mesh_path: NodePath = ^"ImposterSphere"
@export var switch_distance: float = 150000.0
@export var visual_distance: float = 120000.0
@export var real_radius: float = 637100.0
var _real: Node3D
var _surface: Node3D
var _mesh: MeshInstance3D
var _base_radius: float = 0.5
func _ready() -> void:
_real = get_node_or_null(real_earth_path) as Node3D
_surface = get_node_or_null(surface_path) as Node3D
_mesh = get_node_or_null(impostor_mesh_path) as MeshInstance3D
if _mesh and _mesh.mesh is SphereMesh:
_base_radius = maxf((_mesh.mesh as SphereMesh).radius, 0.5)
if _mesh:
_mesh.visible = false
# Keep YOUR material/texture; only force unshaded so it reads in space
var src_mat: Material = _mesh.get_active_material(0)
if src_mat is StandardMaterial3D:
var mat: StandardMaterial3D = (src_mat as StandardMaterial3D).duplicate()
mat.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED
_mesh.material_override = mat
print("EarthImposter ready | real=", _real, " surface=", _surface, " mesh=", _mesh)
set_process(true)
func _process(_delta: float) -> void:
if _real == null or _mesh == null:
return
var viewer: Node3D = FloatingOrigin.focus
if viewer == null or not is_instance_valid(viewer):
_mesh.visible = false
return
var to_body: Vector3 = _real.global_position - viewer.global_position
var dist: float = to_body.length()
if dist < 1.0:
_mesh.visible = false
return
# Close approach only: real surface
if dist < switch_distance:
_mesh.visible = false
if _surface:
_surface.visible = true
return
# Far (normal from Luna): impostor on
# Leave EarthSurface visible until you confirm the disc — then you can hide it
var dir: Vector3 = to_body / dist
_mesh.global_position = viewer.global_position + dir * visual_distance
var visual_radius: float = real_radius * (visual_distance / dist)
visual_radius = clampf(visual_radius, 8000.0, 150000.0)
_mesh.scale = Vector3.ONE * (visual_radius / _base_radius)
_mesh.visible = true
+1
View File
@@ -0,0 +1 @@
uid://ikbkmt7sby7a
+632
View File
@@ -0,0 +1,632 @@
extends CharacterBody3D
## Kestrel EC-01 capsule — flight, cameras, enter/exit.
## Hull clips + plumes live on child "Kestrel" via kestrel_driver.gd.
@onready var interaction_area: Area3D = $InteractionArea
@onready var camera_pivot: Node3D = get_node_or_null("CameraPivot")
@onready var capsule_camera: Camera3D = get_node_or_null("CameraPivot/CapsuleCamera")
@onready var third_person_camera: Camera3D = $ThirdPersonCamera
@onready var interact_prompt: Label = get_node_or_null("/root/Node3D/HUD/InteractPrompt")
@onready var pause_menu: Control = get_node_or_null("/root/Node3D/HUD/PauseMenu")
@onready var body_collision: CollisionShape3D = get_node_or_null("CollisionShape3D")
@onready var flight_label: Label = get_node_or_null("/root/Node3D/HUD/FlightLabel")
@onready var kestrel: Node3D = get_node_or_null("Kestrel")
var player_inside: bool = false
var player_ref: CharacterBody3D = null
var using_third_person: bool = false
var f_was_down: bool = false
var mass: float = 6500.0
var thrust_force: float = 180000.0
var rotation_speed: float = 1.8
var surface_friction: float = 6.0
const MOON_RADIUS: float = 173700.0
const MOON_G: float = 1.62
const MOON_SOI: float = 400000.0
const EARTH_RADIUS: float = 637100.0
const EARTH_G: float = 9.81
const EARTH_SOI: float = 20000000.0
const CAM_FAR: float = 1000000.0
const NEAR_SURFACE_MARGIN: float = 300.0
var _moon_colliders: Array[CollisionObject3D] = []
var _crust_exception: bool = false
var free_look: bool = false
var look_sensitivity: float = 0.003
var orbit_yaw: float = 0.0
var orbit_pitch: float = 0.4
var orbit_distance: float = 14.0
var orbit_pitch_min: float = -1.2
var orbit_pitch_max: float = 1.2
var cockpit_yaw: float = 0.0
var cockpit_pitch: float = 0.0
var cockpit_look_limit_yaw: float = 1.45
var cockpit_look_limit_up: float = 1.0
var cockpit_look_limit_down: float = 0.55
var head_local: Transform3D = Transform3D.IDENTITY
var telem_body: String = "—"
var telem_alt: float = 0.0
var telem_speed: float = 0.0
var telem_vspeed: float = 0.0
var telem_hspeed: float = 0.0
var telem_vcirc: float = 0.0
var telem_dh: float = 0.0
var telem_earth_rng: float = 0.0
var telem_thrust: bool = false
var telem_has_alt: bool = false
var _gear_down: bool = true
var _hatch_crew_open: bool = false
var _hatch_dock_open: bool = false
var _ladder_out: bool = false
var _cabin_dim: bool = false
var _v_was: bool = false
func _ready() -> void:
_ensure_actions()
if interaction_area:
interaction_area.monitoring = true
interaction_area.monitorable = true
interaction_area.body_entered.connect(_on_body_entered)
interaction_area.body_exited.connect(_on_body_exited)
if camera_pivot:
camera_pivot.top_level = false
head_local = camera_pivot.transform
if capsule_camera:
capsule_camera.near = 0.05
capsule_camera.far = CAM_FAR
capsule_camera.current = false
if third_person_camera:
third_person_camera.near = 0.1
third_person_camera.far = CAM_FAR
third_person_camera.current = false
if flight_label:
flight_label.visible = false
_bind_kestrel()
_collect_moon_colliders()
call_deferred("_update_crust_exception")
func _bind_kestrel() -> void:
if kestrel == null:
kestrel = get_node_or_null("Kestrel")
print("Kestrel hull=", kestrel, " driver=", kestrel.get_script() if kestrel else null)
func _hull() -> Node:
return kestrel if kestrel else null
func _set_hull(prop: String, value: Variant) -> void:
var h := _hull()
if h and prop in h:
h.set(prop, value)
func _moon() -> Node3D:
return get_node_or_null("/root/Node3D/SolarSystem/Moon") as Node3D
func _earth() -> Node3D:
return get_node_or_null("/root/Node3D/SolarSystem/Earth") as Node3D
func _habitat() -> Node3D:
return get_node_or_null("/root/Node3D/SolarSystem/Moon/LovellAnchor/Station/Habitat") as Node3D
func _collect_moon_colliders() -> void:
_moon_colliders.clear()
var moon := _moon()
if moon == null:
return
for n in moon.find_children("*", "PhysicsBody3D", true, false):
if n == self:
continue
if str(n.name).begins_with("Shell"):
continue
if str(n.name).begins_with("Moon") and n is CollisionObject3D:
_moon_colliders.append(n as CollisionObject3D)
func _inside_young() -> bool:
var habitat := _habitat()
if habitat == null:
return false
var lp: Vector3 = habitat.to_local(global_position)
var radial: float = Vector2(lp.x, lp.z).length()
return radial < 2000.0 and lp.y < 80.0 and lp.y > -120.0
func _update_crust_exception() -> void:
var want: bool = _inside_young()
if want == _crust_exception:
return
_crust_exception = want
for body in _moon_colliders:
if not is_instance_valid(body):
continue
if want:
add_collision_exception_with(body)
else:
remove_collision_exception_with(body)
func _active_gravity() -> Dictionary:
var moon := _moon()
if moon:
var d_m: float = global_position.distance_to(moon.global_position)
if d_m >= 1.0 and d_m <= MOON_SOI:
var to_c: Vector3 = moon.global_position - global_position
return {
"name": "Luna",
"center": moon.global_position,
"radius": MOON_RADIUS,
"g": MOON_G,
"accel": to_c.normalized() * MOON_G,
"dist": d_m
}
var earth := _earth()
if earth:
var d_e: float = global_position.distance_to(earth.global_position)
if d_e >= 1.0 and d_e <= EARTH_SOI:
var to_c2: Vector3 = earth.global_position - global_position
return {
"name": "Earth",
"center": earth.global_position,
"radius": EARTH_RADIUS,
"g": EARTH_G,
"accel": to_c2.normalized() * EARTH_G,
"dist": d_e
}
return {"name": "—", "center": Vector3.ZERO, "radius": 0.0, "g": 0.0, "accel": Vector3.ZERO, "dist": 0.0}
func _gravity_accel() -> Vector3:
return _active_gravity()["accel"]
func _update_telemetry() -> void:
telem_speed = velocity.length()
telem_thrust = Input.is_key_pressed(KEY_SPACE)
var earth := _earth()
if earth:
telem_earth_rng = maxf(0.0, global_position.distance_to(earth.global_position) - EARTH_RADIUS)
else:
telem_earth_rng = 0.0
var body: Dictionary = _active_gravity()
telem_body = str(body["name"])
if telem_body == "—":
telem_has_alt = false
telem_alt = 0.0
telem_vspeed = 0.0
telem_hspeed = telem_speed
telem_vcirc = 0.0
telem_dh = 0.0
return
telem_has_alt = true
var r: float = float(body["dist"])
var rad: float = float(body["radius"])
var g: float = float(body["g"])
telem_alt = r - rad
var radial: Vector3 = (global_position - body["center"]).normalized()
telem_vspeed = velocity.dot(radial)
telem_hspeed = (velocity - radial * telem_vspeed).length()
telem_vcirc = sqrt(g * rad * rad / r) if r > 1.0 else 0.0
telem_dh = telem_hspeed - telem_vcirc
func _update_flight_hud() -> void:
if flight_label == null or not player_inside:
return
flight_label.visible = true
var mode := "3P" if using_third_person else "1P"
var thr := "THRUST" if telem_thrust else "IDLE"
var vs_sign := "+" if telem_vspeed >= 0.0 else ""
var alt_line: String
var vcirc_line: String
var dh_line: String
if telem_has_alt:
alt_line = "ALT %8.0f m\n" % telem_alt
vcirc_line = "VCIRC %8.1f m/s\n" % telem_vcirc
var dh_sign := "+" if telem_dh >= 0.0 else ""
dh_line = "ΔH %s%7.1f m/s\n" % [dh_sign, telem_dh]
else:
alt_line = "ALT —\n"
vcirc_line = "VCIRC —\n"
dh_line = "ΔH —\n"
flight_label.text = (
"[%s] %s | BODY %s\n" % [mode, thr, telem_body]
+ alt_line
+ "SPD %8.1f m/s\n" % telem_speed
+ "VS %s%7.1f m/s\n" % [vs_sign, telem_vspeed]
+ "H %8.1f m/s\n" % telem_hspeed
+ vcirc_line
+ dh_line
+ "EARTH %8.0f m" % telem_earth_rng
)
func _clear_flight_hud() -> void:
if flight_label:
flight_label.visible = false
flight_label.text = ""
func _on_body_entered(body: Node3D) -> void:
if body.is_in_group("player"):
player_ref = body
if interact_prompt and not player_inside:
interact_prompt.text = "Press F to Enter"
interact_prompt.visible = true
func _on_body_exited(body: Node3D) -> void:
if body.is_in_group("player") and not player_inside:
player_ref = null
if interact_prompt:
interact_prompt.visible = false
func _unhandled_input(event: InputEvent) -> void:
if not player_inside:
return
if event.is_action_pressed("ui_cancel"):
if pause_menu and pause_menu.has_method("open_pause") and player_ref:
pause_menu.open_pause(player_ref)
get_viewport().set_input_as_handled()
return
if _event_toggles(event, "capsule_gear", KEY_G):
_gear_down = not _gear_down
_set_hull("gear_deploy", 1.0 if _gear_down else 0.0)
get_viewport().set_input_as_handled()
elif _event_toggles(event, "capsule_hatch_crew", KEY_H):
_hatch_crew_open = not _hatch_crew_open
_set_hull("hatch_crew_open", 1.0 if _hatch_crew_open else 0.0)
get_viewport().set_input_as_handled()
elif _event_toggles(event, "capsule_hatch_dock", KEY_J):
_hatch_dock_open = not _hatch_dock_open
_set_hull("hatch_dock_open", 1.0 if _hatch_dock_open else 0.0)
get_viewport().set_input_as_handled()
elif _event_toggles(event, "capsule_ladder", KEY_L):
_ladder_out = not _ladder_out
_set_hull("hatch_ladder_deploy", 1.0 if _ladder_out else 0.0)
get_viewport().set_input_as_handled()
elif _event_toggles(event, "capsule_instruments", KEY_I):
_set_hull("instruments_demo", 1.0)
get_viewport().set_input_as_handled()
elif _event_toggles(event, "capsule_cabin_light", KEY_K):
_cabin_dim = not _cabin_dim
_set_hull("cabin_dim", _cabin_dim)
get_viewport().set_input_as_handled()
func _ensure_actions() -> void:
var binds := {
"interact": KEY_F,
"toggle_first_person": KEY_V,
"capsule_gear": KEY_G,
"capsule_hatch_crew": KEY_H,
"capsule_hatch_dock": KEY_J,
"capsule_ladder": KEY_L,
"capsule_instruments": KEY_I,
"capsule_cabin_light": KEY_K,
}
for action in binds.keys():
if InputMap.has_action(action):
continue
InputMap.add_action(action)
var ev := InputEventKey.new()
ev.physical_keycode = binds[action]
InputMap.action_add_event(action, ev)
func _event_toggles(event: InputEvent, action: String, key: Key) -> bool:
if InputMap.has_action(action) and event.is_action_pressed(action):
return true
if event is InputEventKey and event.pressed and not event.echo and event.physical_keycode == key:
return true
return false
func _act_pressed(action: String) -> bool:
return InputMap.has_action(action) and Input.is_action_pressed(action)
func _act_just(action: String) -> bool:
return InputMap.has_action(action) and Input.is_action_just_pressed(action)
func _process(delta: float) -> void:
var interact_now := _act_just("interact") or _just_key(KEY_F)
if not player_inside and player_ref and interact_now:
f_was_down = true
enter_capsule()
return
if not player_inside:
f_was_down = Input.is_physical_key_pressed(KEY_F)
_update_crust_exception()
return
if interact_now and not f_was_down:
f_was_down = true
exit_capsule()
return
f_was_down = _act_pressed("interact") or Input.is_physical_key_pressed(KEY_F)
if _act_just("toggle_first_person"):
toggle_camera()
elif not InputMap.has_action("toggle_first_person") and _just_key(KEY_V):
toggle_camera()
var was_free = free_look
free_look = Input.is_mouse_button_pressed(MOUSE_BUTTON_RIGHT)
if was_free and not free_look and not using_third_person:
cockpit_yaw = 0.0
cockpit_pitch = 0.0
if Input.is_key_pressed(KEY_ALT):
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
else:
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
handle_flight(delta)
_update_telemetry()
_update_flight_hud()
if using_third_person:
update_third_person_camera()
if third_person_camera and not third_person_camera.current:
third_person_camera.make_current()
else:
update_cockpit_camera()
if capsule_camera and not capsule_camera.current:
capsule_camera.make_current()
func _just_key(key: Key) -> bool:
var down := Input.is_physical_key_pressed(key)
if key == KEY_V:
var edge := down and not _v_was
_v_was = down
return edge
return false
func _input(event: InputEvent) -> void:
if not player_inside:
return
if Input.is_key_pressed(KEY_ALT):
return
if event is InputEventMouseMotion:
if using_third_person:
orbit_yaw -= event.relative.x * look_sensitivity
orbit_pitch += event.relative.y * look_sensitivity
orbit_pitch = clampf(orbit_pitch, orbit_pitch_min, orbit_pitch_max)
elif free_look:
cockpit_yaw -= event.relative.x * look_sensitivity
cockpit_pitch -= event.relative.y * look_sensitivity
cockpit_yaw = clamp(cockpit_yaw, -cockpit_look_limit_yaw, cockpit_look_limit_yaw)
cockpit_pitch = clamp(cockpit_pitch, -cockpit_look_limit_down, cockpit_look_limit_up)
func enter_capsule() -> void:
if player_inside or player_ref == null:
return
player_inside = true
if interact_prompt:
interact_prompt.visible = false
player_ref.reparent(self)
player_ref.position = Vector3(0, 0.5, 0)
player_ref.rotation = Vector3.ZERO
player_ref.set_physics_process(false)
player_ref.set_process(true)
player_ref.set_process_input(false)
player_ref.set_process_unhandled_input(false)
if player_ref.has_method("set_in_vehicle"):
player_ref.set_in_vehicle(true)
var player_col = player_ref.get_node_or_null("CollisionShape3D")
if player_col:
player_col.disabled = true
var player_cam = player_ref.get_node_or_null("CameraPivot/Camera3D")
if player_cam:
player_cam.current = false
player_ref.visible = false
cockpit_yaw = 0.0
cockpit_pitch = 0.0
orbit_yaw = 0.0
orbit_pitch = 0.4
using_third_person = false
f_was_down = true
free_look = false
if camera_pivot:
camera_pivot.top_level = false
camera_pivot.transform = head_local
if third_person_camera:
third_person_camera.current = false
if capsule_camera:
capsule_camera.near = 0.05
capsule_camera.far = CAM_FAR
capsule_camera.current = true
capsule_camera.make_current()
velocity = Vector3.ZERO
FloatingOrigin.set_focus(self)
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
if flight_label:
flight_label.visible = true
_update_crust_exception()
func exit_capsule() -> void:
if not player_inside or player_ref == null:
return
var exiting_player: CharacterBody3D = player_ref
player_inside = false
velocity = Vector3.ZERO
free_look = false
f_was_down = false
using_third_person = false
_set_hull("abort_burn", false)
_set_hull("rcs_direction", 0)
_clear_flight_hud()
if body_collision:
body_collision.disabled = false
if is_instance_valid(camera_pivot):
camera_pivot.top_level = false
camera_pivot.transform = head_local
if is_instance_valid(capsule_camera):
capsule_camera.current = false
if is_instance_valid(third_person_camera):
third_person_camera.current = false
var station := get_node_or_null("/root/Node3D/SolarSystem/Moon/LovellAnchor/Station")
var dest: Node = station if station else get_tree().current_scene
exiting_player.reparent(dest)
exiting_player.global_position = global_position + global_transform.basis.y * 4.0
var player_cam_pivot = exiting_player.get_node_or_null("CameraPivot")
if player_cam_pivot:
player_cam_pivot.rotation = Vector3.ZERO
exiting_player.visible = true
exiting_player.set_physics_process(true)
exiting_player.set_process(true)
exiting_player.set_process_input(true)
exiting_player.set_process_unhandled_input(true)
exiting_player.process_mode = Node.PROCESS_MODE_INHERIT
var player_col = exiting_player.get_node_or_null("CollisionShape3D")
if player_col:
player_col.disabled = false
if exiting_player.has_method("set_in_vehicle"):
exiting_player.set_in_vehicle(false)
var player_cam = exiting_player.get_node_or_null("CameraPivot/Camera3D")
if player_cam:
player_cam.current = true
player_cam.make_current()
if exiting_player.has_method("restore_from_vehicle"):
exiting_player.restore_from_vehicle()
FloatingOrigin.set_focus(exiting_player)
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
player_ref = null
func toggle_camera() -> void:
using_third_person = not using_third_person
if using_third_person:
if capsule_camera:
capsule_camera.current = false
if third_person_camera:
third_person_camera.near = 0.1
third_person_camera.far = CAM_FAR
third_person_camera.make_current()
else:
if third_person_camera:
third_person_camera.current = false
if camera_pivot:
camera_pivot.top_level = false
camera_pivot.transform = head_local
if capsule_camera:
capsule_camera.make_current()
func update_cockpit_camera() -> void:
if not camera_pivot:
return
camera_pivot.top_level = false
var b: Basis = head_local.basis
b = b.rotated(b.x, cockpit_pitch)
b = b.rotated(b.y, cockpit_yaw)
b = b.orthonormalized()
if abs(b.determinant()) < 0.5:
camera_pivot.transform = head_local
return
camera_pivot.transform = Transform3D(b, head_local.origin)
func update_third_person_camera() -> void:
if not third_person_camera:
return
var cy := cos(orbit_yaw)
var sy := sin(orbit_yaw)
var cp := cos(orbit_pitch)
var sp := sin(orbit_pitch)
var offset := Vector3(sy * cp, sp, cy * cp) * orbit_distance
var local_off := Vector3(offset.x, -offset.z, offset.y)
var cam_pos := global_position + global_transform.basis * local_off
third_person_camera.global_position = cam_pos
var target := global_position + global_transform.basis.y * 1.5
var forward := target - cam_pos
if forward.length_squared() < 0.0001:
return
forward = forward.normalized()
var ref_up := global_transform.basis.z
if abs(forward.dot(ref_up)) > 0.92:
ref_up = global_transform.basis.x
var right := ref_up.cross(forward)
if right.length_squared() < 0.0001:
return
right = right.normalized()
var up := forward.cross(right).normalized()
var cam_basis := Basis(-right, up, -forward).orthonormalized()
if abs(cam_basis.determinant()) < 0.5:
return
third_person_camera.global_basis = cam_basis
func handle_flight(delta: float) -> void:
_update_crust_exception()
var input_pitch := 0.0
var input_roll := 0.0
var input_yaw := 0.0
if Input.is_key_pressed(KEY_W):
input_pitch -= 1.0
if Input.is_key_pressed(KEY_S):
input_pitch += 1.0
if Input.is_key_pressed(KEY_A):
input_yaw += 1.0
if Input.is_key_pressed(KEY_D):
input_yaw -= 1.0
if Input.is_key_pressed(KEY_Q):
input_roll -= 1.0
if Input.is_key_pressed(KEY_E):
input_roll += 1.0
rotate_object_local(Vector3.RIGHT, input_pitch * rotation_speed * delta)
rotate_object_local(Vector3.FORWARD, -input_yaw * rotation_speed * delta)
rotate_object_local(Vector3.UP, input_roll * rotation_speed * delta)
var thrusting := Input.is_key_pressed(KEY_SPACE)
_set_hull("abort_burn", thrusting)
_set_hull("att_pitch", input_pitch)
_set_hull("att_yaw", input_yaw)
_set_hull("att_roll", input_roll)
_set_hull("rcs_direction", 0)
var acceleration: Vector3 = _gravity_accel()
if thrusting:
acceleration += global_transform.basis.y * (thrust_force / mass)
velocity += acceleration * delta
var near_surface := is_on_floor() or _crust_exception
if not near_surface:
var moon := _moon()
if moon and global_position.distance_to(moon.global_position) < MOON_RADIUS + NEAR_SURFACE_MARGIN:
near_surface = true
var earth := _earth()
if earth and global_position.distance_to(earth.global_position) < EARTH_RADIUS + NEAR_SURFACE_MARGIN:
near_surface = true
if near_surface:
if body_collision:
body_collision.disabled = false
move_and_slide()
if is_on_floor():
velocity.x = move_toward(velocity.x, 0.0, surface_friction * delta)
velocity.z = move_toward(velocity.z, 0.0, surface_friction * delta)
if velocity.length() < 0.08:
velocity = Vector3.ZERO
else:
if body_collision:
body_collision.disabled = true
global_position += velocity * delta
PhysicsServer3D.body_set_state(
get_rid(),
PhysicsServer3D.BODY_STATE_TRANSFORM,
global_transform
)
PhysicsServer3D.body_set_state(
get_rid(),
PhysicsServer3D.BODY_STATE_LINEAR_VELOCITY,
velocity
)
+1
View File
@@ -0,0 +1 @@
uid://1udl42sp42sp
+94
View File
@@ -0,0 +1,94 @@
extends Node
## Sibling FO. Shift registered world roots.
## Move focus only when it is NOT already under a root (capsule = sibling).
## Never zero velocity.
const THRESHOLD: float = 50000.0
const COOLDOWN: float = 0.25
var focus: Node3D = null
var _shift_roots: Array[Node3D] = []
var _cooldown: float = 0.0
func _ready() -> void:
process_mode = Node.PROCESS_MODE_ALWAYS
func set_focus(node: Node3D) -> void:
focus = node
func register_root(node: Node3D) -> void:
if node == null:
return
if not _shift_roots.has(node):
_shift_roots.append(node)
print("FloatingOrigin registered: ", node.name)
func unregister_root(node: Node3D) -> void:
_shift_roots.erase(node)
func shift(offset: Vector3) -> void:
if offset.length_squared() < 1.0:
return
_apply_shift(offset)
_cooldown = COOLDOWN
func _physics_process(delta: float) -> void:
if _cooldown > 0.0:
_cooldown -= delta
return
if focus == null or not is_instance_valid(focus) or not focus.is_inside_tree():
return
if _shift_roots.is_empty():
return
var fp: Vector3 = focus.global_position
if fp.length() < THRESHOLD:
return
_apply_shift(-fp)
_cooldown = COOLDOWN
func _apply_shift(offset: Vector3) -> void:
for root in _shift_roots:
if is_instance_valid(root) and root.is_inside_tree():
root.global_position += offset
if is_instance_valid(focus) and focus.is_inside_tree() and not _focus_under_a_root():
focus.global_position += offset
_sync_focus_physics()
print("FloatingOrigin shift: ", offset, " focus now: ", focus.global_position if focus else Vector3.ZERO)
func _focus_under_a_root() -> bool:
var n: Node = focus
while n != null:
if n is Node3D and _shift_roots.has(n as Node3D):
return true
n = n.get_parent()
return false
func _sync_focus_physics() -> void:
if focus == null or not is_instance_valid(focus):
return
if not (focus is CharacterBody3D):
return
var body := focus as CharacterBody3D
var saved_vel: Vector3 = body.velocity
PhysicsServer3D.body_set_state(
body.get_rid(),
PhysicsServer3D.BODY_STATE_TRANSFORM,
body.global_transform
)
PhysicsServer3D.body_set_state(
body.get_rid(),
PhysicsServer3D.BODY_STATE_LINEAR_VELOCITY,
saved_vel
)
body.velocity = saved_vel
if body.has_method("reset_physics_interpolation"):
body.reset_physics_interpolation()
+1
View File
@@ -0,0 +1 @@
uid://ckl5inm8ugypo
+152
View File
@@ -0,0 +1,152 @@
extends Node
const SAVE_PATH := "user://save_slot_1.json"
var has_save: bool = false
var play_elapsed: float = 0.0
var demo_limit: float = 36000.0
var scramble_at: float = 35280.0
var scramble_started: bool = false
var clock_paused: bool = false
var game_year: int = 2066
var game_month: int = 9
var game_day: int = 14
var game_hour: float = 8.0
var time_scale: float = 1.0
signal scramble_begun
signal time_scale_changed(new_scale: float)
func _ready() -> void:
has_save = FileAccess.file_exists(SAVE_PATH)
process_mode = Node.PROCESS_MODE_PAUSABLE
func _process(delta: float) -> void:
if clock_paused:
return
var stepped: float = delta * time_scale
play_elapsed += stepped
_advance_game_clock(stepped)
if not scramble_started and play_elapsed >= scramble_at:
scramble_started = true
scramble_begun.emit()
print("SCRAMBLE: Unknown Vessels Inbound")
func set_time_scale(scale: float) -> void:
time_scale = clampf(scale, 0.0, 4.0)
time_scale_changed.emit(time_scale)
print("Time scale: x", time_scale)
func _advance_game_clock(game_seconds: float) -> void:
game_hour += game_seconds / 3600.0
while game_hour >= 24.0:
game_hour -= 24.0
game_day += 1
var days_in_month: int = _days_in_month(game_year, game_month)
if game_day > days_in_month:
game_day = 1
game_month += 1
if game_month > 12:
game_month = 1
game_year += 1
func _days_in_month(_year: int, month: int) -> int:
match month:
1, 3, 5, 7, 8, 10, 12:
return 31
4, 6, 9, 11:
return 30
2:
return 28
_:
return 30
func get_time_string() -> String:
var h: int = int(game_hour)
var m: int = int((game_hour - float(h)) * 60.0)
var s: int = int((game_hour - float(h) - float(m) / 60.0) * 3600.0)
var month_names := ["", "Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
var mon: String = month_names[game_month]
var scale_txt := ""
if time_scale == 0.0:
scale_txt = " PAUSED"
elif time_scale > 1.0:
scale_txt = " x%d" % int(time_scale)
return "%d %s %d %02d:%02d:%02d%s" % [game_day, mon, game_year, h, m, s, scale_txt]
func get_play_remaining_string() -> String:
var left: float = max(demo_limit - play_elapsed, 0.0)
var h: int = int(left / 3600.0)
var m: int = int((left - float(h) * 3600.0) / 60.0)
var sec: int = int(left) % 60
return "%02d:%02d:%02d" % [h, m, sec]
func save_game(player: Node) -> void:
if player == null:
return
var look = {}
if "appearance" in player:
look = player.appearance
var data := {
"player_name": player.player_name,
"background_id": player.background_id,
"background_name": player.background_name,
"culture_id": player.culture_id if "culture_id" in player else "",
"culture_name": player.culture_name if "culture_name" in player else "",
"appearance": look,
"money": player.money,
"food": player.food,
"health": player.health,
"oxygen": player.oxygen,
"inventory": player.inventory.duplicate(),
"position": {
"x": player.global_position.x,
"y": player.global_position.y,
"z": player.global_position.z
},
"play_elapsed": play_elapsed,
"scramble_started": scramble_started,
"game_year": game_year,
"game_month": game_month,
"game_day": game_day,
"game_hour": game_hour,
"time_scale": time_scale
}
var file := FileAccess.open(SAVE_PATH, FileAccess.WRITE)
if file:
file.store_string(JSON.stringify(data))
file.close()
has_save = true
print("Game saved")
func load_game_data() -> Dictionary:
if not FileAccess.file_exists(SAVE_PATH):
return {}
var file := FileAccess.open(SAVE_PATH, FileAccess.READ)
if file == null:
return {}
var text := file.get_as_text()
file.close()
var parsed = JSON.parse_string(text)
if typeof(parsed) == TYPE_DICTIONARY:
return parsed
return {}
func apply_loaded_clock(data: Dictionary) -> void:
play_elapsed = float(data.get("play_elapsed", 0.0))
scramble_started = bool(data.get("scramble_started", false))
game_year = int(data.get("game_year", 2066))
game_month = int(data.get("game_month", 9))
game_day = int(data.get("game_day", 14))
game_hour = float(data.get("game_hour", 8.0))
time_scale = float(data.get("time_scale", 1.0))
clock_paused = false
+1
View File
@@ -0,0 +1 @@
uid://b3o7ua8cv55tq
View File
+1
View File
@@ -0,0 +1 @@
uid://br0vxsoinqwe1
+9
View File
@@ -0,0 +1,9 @@
extends StaticBody3D
@export var item_name: String = "Dried Noodles"
func on_interact(player: Node) -> void:
if player.has_method("add_item"):
player.add_item(item_name)
print("Picked up: ", item_name)
queue_free()
+1
View File
@@ -0,0 +1 @@
uid://bigf78nt5im5v
+646
View File
@@ -0,0 +1,646 @@
extends Node3D
## Player/Body look loader. PASTE 2026-09-12 22:54 — 1P always gun-out eye ride
## 8-way = yaw CreatedBody toward the stick + Walk/Run.
## No AnimationTree. Waist fold AFTER clip via SkeletonModifier3D.
const MALE_FBX := "res://character assets/All together/FBX/Humans_Master.fbx"
const FEMALE_FBX := "res://character assets/All together/FBX women/All together.fbx"
const CLIP_ALIASES := {
"Idle": ["Idle"],
"Walk": ["Walk"],
"Run": ["Run"],
"Run_Back": ["Run_Back", "RunBack"],
"Run_Left": ["Run_Left", "RunLeft"],
"Run_Right": ["Run_Right", "RunRight"],
"Jump": ["Jump"],
"Interact": ["Interact", "Pickup", "PickUp"],
"Idle_Gun": ["Idle_Gun", "Idle_Gun_Pointing", "Gun_Idle"],
"AimIdle": ["Idle_Gun_Pointing", "Idle_Gun", "Gun_Idle", "Aim_Idle"],
"AimWalk": ["Walk_Shoot", "WalkShoot", "Gun_Walk", "Walk_Gun", "Walk"],
"Walk_Shoot": ["Walk_Shoot", "WalkShoot", "Gun_Walk", "Walk"],
"AimRun": ["Run_Shoot", "RunShoot", "Gun_Run", "Run_Gun", "Run"],
"Run_Shoot": ["Run_Shoot", "RunShoot", "Run"],
"Gun_Shoot": ["Gun_Shoot", "Pistol_Shoot", "Shoot", "Idle_Gun_Shoot"],
"Idle_Gun_Shoot": ["Idle_Gun_Shoot", "Gun_Shoot", "Idle_Gun_Pointing"],
}
var current: Node3D = null
var anim: AnimationPlayer = null
var last_keep: Array[String] = []
var _logged_names: bool = false
var hide_head: bool = false
var show_pistol: bool = false
var _skel: Skeleton3D = null
var _bone_abdomen: int = -1
var _bone_torso: int = -1
var _bone_chest: int = -1
var _bone_head: int = -1
var _bone_rarm: int = -1
var _bone_larm: int = -1
var _bone_rfore: int = -1
var _bone_lfore: int = -1
var _aim_pitch: float = 0.0
var _aim_enabled: bool = false
var _logged_bones: bool = false
var _mod: SkeletonModifier3D = null
var _dbg: float = 0.0
var tree: AnimationTree = null
var _walk_bs: AnimationNodeBlendSpace2D = null
var _run_bs: AnimationNodeBlendSpace2D = null
var _aim_walk_bs: AnimationNodeBlendSpace2D = null
var _aim_run_bs: AnimationNodeBlendSpace2D = null
var _mode: String = ""
var _blend_pos: Vector2 = Vector2.ZERO
var _run_amt: float = 0.0
var _aiming: bool = false
var _fire_lock: float = 0.0
var _ride_fp: bool = false
var _fp_cam: Camera3D = null
var _fp_pivot: Node3D = null
var arm_axis_id: int = 2
class AimBend extends SkeletonModifier3D:
var host: Node
func _process_modification() -> void:
if host and host.has_method("_apply_waist_now"):
host._apply_waist_now()
func apply_look(appearance: Dictionary) -> AnimationPlayer:
_clear_old()
var sex := str(appearance.get("sex", "male"))
var path := MALE_FBX if sex == "male" else FEMALE_FBX
if not ResourceLoader.exists(path):
push_warning("Look file missing: " + path)
return null
var packed = load(path)
if packed == null:
return null
var inst: Node = packed.instantiate()
if not (inst is Node3D):
return null
current = inst as Node3D
current.name = "CreatedBody"
current.position = Vector3.ZERO
current.rotation_degrees = Vector3.ZERO
current.scale = Vector3.ONE * 1.3
add_child(current)
last_keep = [
str(appearance.get("head", "Casual_Head")),
str(appearance.get("body", "Casual_Body")),
str(appearance.get("legs", "Casual_Legs")),
str(appearance.get("feet", "Casual_Feet")),
]
anim = current.find_child("AnimationPlayer", true, false) as AnimationPlayer
if anim:
anim.speed_scale = 1.0
anim.root_motion_track = NodePath()
_loop_locomotion(anim)
print("Look clips: ", anim.get_animation_list())
_cache_skeleton()
_build_loco_tree()
_apply_keep(current, last_keep)
call_deferred("_apply_keep_deferred")
return anim
func _resolve_clip(logical: String) -> String:
if anim == null:
return ""
var names: Array = CLIP_ALIASES.get(logical, [logical])
var candidates: Array[String] = []
for n in names:
candidates.append("CharacterArmature|%s" % n)
candidates.append(str(n))
for clip in candidates:
if anim.has_animation(clip):
return clip
for clip in anim.get_animation_list():
for n in names:
if clip.ends_with(str(n)) or clip.contains(str(n)):
return clip
return ""
func play_clip(logical: String, speed_scale: float = 1.0) -> void:
if anim == null:
return
if tree:
tree.active = false
var clip := _resolve_clip(logical)
if clip.is_empty():
return
var a: Animation = anim.get_animation(clip)
if a:
var looped := logical in [
"Idle", "Walk", "Run", "Run_Back", "Run_Left", "Run_Right",
"Idle_Gun", "AimIdle", "AimWalk", "AimRun", "Walk_Shoot", "Run_Shoot"
]
a.loop_mode = Animation.LOOP_LINEAR if looped else Animation.LOOP_NONE
anim.speed_scale = speed_scale
if anim.current_animation != clip:
anim.play(clip)
elif not anim.is_playing():
anim.play(clip)
_apply_keep(current, last_keep)
func _loop_locomotion(player: AnimationPlayer) -> void:
for logical in [
"Idle", "Walk", "Run", "Run_Back", "Run_Left", "Run_Right",
"Idle_Gun", "AimIdle", "AimWalk", "AimRun", "Walk_Shoot", "Run_Shoot"
]:
var clip := _resolve_clip(logical)
if clip.is_empty():
continue
var a: Animation = player.get_animation(clip)
if a:
a.loop_mode = Animation.LOOP_LINEAR
func _clip_node(logical: String) -> AnimationNodeAnimation:
var n := AnimationNodeAnimation.new()
var clip := _resolve_clip(logical)
if clip.is_empty():
clip = _resolve_clip("Idle")
if clip.is_empty():
clip = logical
n.animation = StringName(clip)
n.resource_name = logical
return n
func _add_pt(bs: AnimationNodeBlendSpace2D, logical: String, pos: Vector2, label: String) -> void:
var node := _clip_node(logical)
bs.add_blend_point(node, pos)
var idx: int = bs.get_blend_point_count() - 1
if bs.has_method("set_blend_point_name"):
bs.call("set_blend_point_name", idx, StringName(label))
func _make_space(_idle: String, fwd: String, back: String, left: String, right: String) -> AnimationNodeBlendSpace2D:
var bs := AnimationNodeBlendSpace2D.new()
# Discrete = one whole clip. Interpolating Walk with Run_Left is clown shoes.
bs.blend_mode = AnimationNodeBlendSpace2D.BLEND_MODE_DISCRETE_CARRY
bs.min_space = Vector2(-1.0, -1.0)
bs.max_space = Vector2(1.0, 1.0)
bs.snap = Vector2(0.0, 0.0)
_add_pt(bs, fwd, Vector2(0.0, -1.0), "fwd")
_add_pt(bs, back, Vector2(0.0, 1.0), "back")
_add_pt(bs, left, Vector2(-1.0, 0.0), "left")
_add_pt(bs, right, Vector2(1.0, 0.0), "right")
_add_pt(bs, fwd, Vector2(-0.71, -0.71), "fwd_left")
_add_pt(bs, fwd, Vector2(0.71, -0.71), "fwd_right")
_add_pt(bs, back, Vector2(-0.71, 0.71), "back_left")
_add_pt(bs, back, Vector2(0.71, 0.71), "back_right")
return bs
func _build_loco_tree() -> void:
# No AnimationTree. Quaternius has no Walk_Left/Walk_Right — blending
# Walk with Run_Left is clown shoes. One clip per octant instead.
if tree and is_instance_valid(tree):
tree.queue_free()
tree = null
_walk_bs = null
_run_bs = null
_aim_walk_bs = null
_aim_run_bs = null
_mode = "idle"
_blend_pos = Vector2.ZERO
_run_amt = 0.0
print("Loco clips walk=", _resolve_clip("Walk"),
" left=", _resolve_clip("Run_Left"),
" right=", _resolve_clip("Run_Right"),
" back=", _resolve_clip("Run_Back"),
" run=", _resolve_clip("Run"),
" aimIdle=", _resolve_clip("AimIdle"))
func play_fire(aiming_now: bool = false) -> void:
var logical: String = "Idle_Gun_Shoot" if aiming_now else "Gun_Shoot"
play_clip(logical)
var clip := _resolve_clip(logical)
var dur: float = 0.26
if anim and not clip.is_empty() and anim.has_animation(clip):
dur = maxf(0.16, anim.get_animation(clip).length * 0.82)
_fire_lock = dur
func set_loco(strafe: float, back: float, run_amount: float, delta: float = 0.016, aiming: bool = false) -> void:
_aiming = aiming
if tree and tree.active:
tree.active = false
if _fire_lock > 0.0:
_fire_lock = maxf(_fire_lock - delta, 0.0)
if aiming:
_face_move(0.0, delta, 14.0)
return
if aiming:
_face_move(0.0, delta, 14.0)
var aim_stick := Vector2(clampf(strafe, -1.0, 1.0), clampf(back, -1.0, 1.0))
_blend_pos = aim_stick.normalized() if aim_stick.length() >= 0.16 else Vector2.ZERO
_run_amt = run_amount if aim_stick.length() >= 0.16 else 0.0
if aim_stick.length() < 0.16:
_mode = "aim_idle"
play_clip("AimIdle")
elif run_amount > 0.5:
_mode = "aim_run"
play_clip("AimRun")
else:
_mode = "aim_walk"
play_clip("AimWalk")
return
var target := Vector2(clampf(strafe, -1.0, 1.0), clampf(back, -1.0, 1.0))
if target.length() < 0.16:
_face_move(0.0, delta, 10.0)
_blend_pos = Vector2.ZERO
_run_amt = 0.0
if show_pistol or hide_head:
_mode = "idle_gun"
play_clip("Idle_Gun")
else:
_mode = "idle"
play_clip("Idle")
return
_blend_pos = target.normalized()
_run_amt = 1.0 if run_amount > 0.5 else 0.0
# S / SA / SD — backpedal, no 180 spin
if _blend_pos.y > 0.2:
_face_move(0.0, delta, 12.0)
_mode = "Run_Back"
play_clip("Run_Back")
return
# Pure A / D — sidestep, keep facing camera-forward
if absf(_blend_pos.x) >= 0.62 and absf(_blend_pos.y) <= 0.42:
_face_move(0.0, delta, 14.0)
var side: String = "Run_Left" if _blend_pos.x < 0.0 else "Run_Right"
_mode = side
play_clip(side)
return
# W / WA / WD — face the stick + Walk/Run
var yaw := atan2(-_blend_pos.x, maxf(-_blend_pos.y, 0.001))
yaw = clampf(yaw, deg_to_rad(-90.0), deg_to_rad(90.0))
_face_move(yaw, delta, 16.0)
var logical: String = "Run" if _run_amt > 0.5 else "Walk"
_mode = logical
var pace: float = 0.92 + _run_amt * 0.18 if logical == "Run" else 0.88 + target.length() * 0.14
play_clip(logical, pace)
func _face_move(yaw: float, delta: float, rate: float) -> void:
if current == null or not is_instance_valid(current):
return
current.rotation.y = lerp_angle(current.rotation.y, yaw, clampf(rate * delta, 0.0, 1.0))
func set_first_person(fp: bool) -> void:
hide_head = fp
print("Look 1P=", fp, " idle=Idle_Gun" if fp else " idle=Idle")
if current != null and is_instance_valid(current):
_apply_keep(current, last_keep)
func set_pistol_drawn(drawn: bool) -> void:
show_pistol = drawn
if current != null and is_instance_valid(current):
_apply_keep(current, last_keep)
func set_meshes_visible(v: bool) -> void:
if current == null:
return
if v:
_apply_keep(current, last_keep)
else:
_hide_all_visuals(current)
func set_aim_pitch(radians: float) -> void:
if not _aim_enabled:
_aim_pitch = 0.0
return
_aim_pitch = clampf(radians, deg_to_rad(-50.0), deg_to_rad(65.0))
func get_head_global_pos() -> Vector3:
if _skel == null or not is_instance_valid(_skel) or _bone_head < 0:
return Vector3.INF
var pose: Transform3D = _skel.get_bone_global_pose(_bone_head)
return _skel.to_global(pose.origin)
func set_fp_ride(cam: Camera3D, pivot: Node3D, on: bool) -> void:
_fp_cam = cam
_fp_pivot = pivot
_ride_fp = on and cam != null
func set_aim_enabled(on: bool) -> void:
_aim_enabled = on
if not on:
_aim_pitch = 0.0
if _mod:
_mod.active = on
func _process(delta: float) -> void:
_dbg += delta
if _dbg < 4.0:
return
_dbg = 0.0
print("Loco dbg mode=", _mode,
" pos=", snapped(_blend_pos, Vector2(0.01, 0.01)),
" run=", snappedf(_run_amt, 0.01),
" aim=", _aiming,
" player=", anim.current_animation if anim else "?")
if _aim_enabled:
print("AimFold on pitch=", snappedf(rad_to_deg(_aim_pitch), 0.1),
" abd=", _bone_name(_bone_abdomen),
" torso=", _bone_name(_bone_torso),
" chest=", _bone_name(_bone_chest),
" mod=", _mod != null, " active=", _mod.active if _mod else false)
func _cache_skeleton() -> void:
_skel = null
_bone_abdomen = -1
_bone_torso = -1
_bone_chest = -1
_bone_head = -1
_bone_rarm = -1
_bone_larm = -1
_bone_rfore = -1
_bone_lfore = -1
_mod = null
if current == null:
return
_skel = current.find_child("Skeleton3D", true, false) as Skeleton3D
if _skel == null:
push_warning("Look: no Skeleton3D on CreatedBody")
return
_bone_abdomen = _find_exact(["Abdomen", "mixamorig_Spine", "mixamorig:Spine", "Spine"])
_bone_torso = _find_exact(["Torso", "mixamorig_Spine1", "mixamorig:Spine1", "Spine1"])
_bone_chest = _find_exact(["Chest", "mixamorig_Spine2", "mixamorig:Spine2", "Spine2", "UpperChest"])
_bone_head = _find_exact(["Head", "mixamorig_Head", "mixamorig:Head"])
_bone_rarm = _find_limb(["mixamorig_RightArm", "mixamorig:RightArm", "RightArm", "Arm.R"])
_bone_larm = _find_limb(["mixamorig_LeftArm", "mixamorig:LeftArm", "LeftArm", "Arm.L"])
_bone_rfore = _find_limb(["mixamorig_RightForeArm", "mixamorig:RightForeArm", "RightForeArm", "ForeArm.R"])
_bone_lfore = _find_limb(["mixamorig_LeftForeArm", "mixamorig:LeftForeArm", "LeftForeArm", "ForeArm.L"])
_mod = AimBend.new()
_mod.name = "AimBend"
_mod.host = self
_mod.active = false
_skel.add_child(_mod)
if not _logged_bones:
_logged_bones = true
print("Look skeleton=", _skel.name,
" abd=", _bone_name(_bone_abdomen),
" torso=", _bone_name(_bone_torso),
" chest=", _bone_name(_bone_chest),
" head=", _bone_name(_bone_head),
" rarm=", _bone_name(_bone_rarm),
" larm=", _bone_name(_bone_larm),
" modifier=AimBend")
func _find_exact(names: Array[String]) -> int:
if _skel == null:
return -1
for bone_key in names:
var idx: int = _skel.find_bone(bone_key)
if idx >= 0:
var low := _skel.get_bone_name(idx).to_lower()
var want_head := "head" in bone_key.to_lower()
if "shoulder" in low or "arm" in low or "neck" in low:
continue
if "head" in low and not want_head:
continue
return idx
return -1
func _find_limb(names: Array[String]) -> int:
if _skel == null:
return -1
for bone_key in names:
var idx: int = _skel.find_bone(bone_key)
if idx >= 0:
return idx
for i in range(_skel.get_bone_count()):
var raw: String = _skel.get_bone_name(i)
var low: String = raw.to_lower()
for bone_key in names:
var want: String = bone_key.to_lower()
if low == want or low.contains(want):
return i
return -1
func _bone_name(idx: int) -> String:
if _skel == null or idx < 0:
return str(idx)
return "%s(%d)" % [_skel.get_bone_name(idx), idx]
func _apply_waist_now() -> void:
if _skel == null:
return
if _aim_enabled:
var pitch: float = -_aim_pitch
if hide_head:
# 1P: lean the whole torso so the gun and shoes enter the lens.
_set_fold(_bone_abdomen, pitch * 0.40)
_set_fold(_bone_torso, pitch * 0.22)
_set_fold(_bone_chest, pitch * 0.08)
var axis: Vector3 = Vector3.FORWARD
match arm_axis_id:
0:
axis = Vector3.RIGHT
1:
axis = Vector3.UP
_:
axis = Vector3.FORWARD
var arm_amt: float = 0.22
if _aim_pitch > 0.0:
arm_amt = 0.36
_set_fold_axis(_bone_rarm, pitch * arm_amt, axis)
_set_fold_axis(_bone_larm, pitch * arm_amt * 0.55, axis)
else:
_set_fold(_bone_abdomen, pitch * 0.42)
_set_fold(_bone_torso, pitch * 0.38)
_set_fold(_bone_chest, pitch * 0.28)
_snap_fp_eye()
func _snap_fp_eye() -> void:
if not _ride_fp or _fp_pivot == null or _skel == null or _bone_head < 0:
return
var pose: Transform3D = _skel.get_bone_global_pose(_bone_head)
var xf: Transform3D = _skel.global_transform * pose
var body: Node3D = _fp_pivot.get_parent() as Node3D
var face := Vector3.FORWARD
var up := Vector3.UP
if body:
face = -body.global_transform.basis.z
face.y = 0.0
if face.length_squared() < 0.0001:
face = -body.global_transform.basis.z
face = face.normalized()
up = body.global_transform.basis.y.normalized()
else:
face = xf.basis.z.normalized()
up = xf.basis.y.normalized()
_fp_pivot.global_position = xf.origin + face * 0.03 + up * 0.12
func _set_fold(idx: int, angle: float) -> void:
_set_fold_axis(idx, angle, Vector3.RIGHT)
func _set_fold_axis(idx: int, angle: float, axis: Vector3) -> void:
if idx < 0 or _skel == null:
return
if absf(angle) < 0.0005:
return
var pose: Quaternion = _skel.get_bone_pose_rotation(idx)
_skel.set_bone_pose_rotation(idx, pose * Quaternion(axis.normalized(), angle))
func cycle_arm_axis() -> void:
arm_axis_id = (arm_axis_id + 1) % 3
print("ARM AXIS ", ["X (RIGHT)", "Y (UP)", "Z (FORWARD)"][arm_axis_id])
func _apply_keep_deferred() -> void:
if current != null and is_instance_valid(current):
_apply_keep(current, last_keep)
if _skel == null:
_cache_skeleton()
func _clear_old() -> void:
current = null
anim = null
if tree and is_instance_valid(tree):
tree.queue_free()
tree = null
_walk_bs = null
_run_bs = null
_aim_walk_bs = null
_aim_run_bs = null
_mode = ""
_blend_pos = Vector2.ZERO
_run_amt = 0.0
_aiming = false
_fire_lock = 0.0
_skel = null
_mod = null
_bone_abdomen = -1
_bone_torso = -1
_bone_chest = -1
_bone_head = -1
_bone_rarm = -1
_bone_larm = -1
_bone_rfore = -1
_bone_lfore = -1
_logged_bones = false
_aim_enabled = false
_aim_pitch = 0.0
_ride_fp = false
_fp_cam = null
_fp_pivot = null
for child in get_children():
child.hide()
child.queue_free()
func _hide_all_visuals(root: Node) -> void:
var stack: Array[Node] = [root]
while stack.size() > 0:
var n: Node = stack.pop_back()
if n is GeometryInstance3D:
n.visible = false
for c in n.get_children():
stack.append(c)
func _apply_keep(root: Node, keep: Array[String]) -> void:
if root == null or keep.is_empty():
return
var shown: PackedStringArray = []
var hidden: PackedStringArray = []
var stack: Array[Node] = [root]
while stack.size() > 0:
var n: Node = stack.pop_back()
if n is GeometryInstance3D:
var lab := _label(n)
var keep_this := _matches_keep(n, keep) and not _is_banned(lab)
if show_pistol and _is_pistol_label(lab):
keep_this = true
if hide_head and _is_head_label(lab):
keep_this = false
n.visible = keep_this
if keep_this:
shown.append(_label(n))
else:
hidden.append(_label(n))
for c in n.get_children():
stack.append(c)
if not _logged_names:
_logged_names = true
print("Look keep=", keep)
print("Look SHOWN (", shown.size(), "): ", shown)
print("Look HIDDEN (", hidden.size(), "): ", hidden)
func _label(n: Node) -> String:
var label := n.name
if n is MeshInstance3D:
var mi := n as MeshInstance3D
if mi.mesh and not mi.mesh.resource_name.is_empty():
label = "%s|%s" % [n.name, mi.mesh.resource_name]
return label
func _matches_keep(n: Node, keep: Array[String]) -> bool:
var labels: Array[String] = [n.name]
if n is MeshInstance3D:
var mi := n as MeshInstance3D
if mi.mesh and not mi.mesh.resource_name.is_empty():
labels.append(mi.mesh.resource_name)
for label in labels:
for k in keep:
if k.is_empty():
continue
if label == k or label.begins_with(k):
return true
return false
func _is_head_label(mesh_name: String) -> bool:
var low := mesh_name.to_lower()
if "pistol" in low:
return false
return ("_head" in low) or low.ends_with("head") or ("hair" in low) or ("hat" in low) or ("neck" in low)
func _is_pistol_label(mesh_name: String) -> bool:
return mesh_name.contains("Pistol") or mesh_name.contains("pistol")
func _is_banned(mesh_name: String) -> bool:
var n := mesh_name
return (
n.begins_with("Horse")
or n.contains("Horse")
or n.begins_with("King")
or n.begins_with("Witch")
or n.begins_with("Medieval")
or n.begins_with("Beach")
or n.begins_with("Sword")
)
+1
View File
@@ -0,0 +1 @@
uid://bh5kr1365v1bq
+30
View File
@@ -0,0 +1,30 @@
extends Control
@onready var new_game_button: Button = $CenterRoot/MenuColumn/NewGameButton
@onready var continue_button: Button = $CenterRoot/MenuColumn/ContinueButton
@onready var quit_button: Button = $CenterRoot/MenuColumn/QuitButton
func _ready() -> void:
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
if new_game_button:
new_game_button.pressed.connect(_on_new_game)
if continue_button:
continue_button.pressed.connect(_on_continue)
if quit_button:
quit_button.pressed.connect(_on_quit)
if continue_button:
continue_button.disabled = not GameState.has_save
func _on_new_game() -> void:
get_tree().change_scene_to_file("res://Scenes/character_creation.tscn")
func _on_continue() -> void:
Engine.set_meta("load_save", true)
get_tree().change_scene_to_file("res://Scenes/main.tscn")
func _on_quit() -> void:
get_tree().quit()
+1
View File
@@ -0,0 +1 @@
uid://cb6r3wpwg73jg
+10
View File
@@ -0,0 +1,10 @@
extends StaticBody3D
@export var item_name: String = "Marijuana Seeds"
func on_interact(player: Node) -> void:
if player.has_method("add_item"):
player.add_item(item_name)
print("Picked up: ", item_name)
queue_free()
+1
View File
@@ -0,0 +1 @@
uid://03eo5b1lwlm7
+87
View File
@@ -0,0 +1,87 @@
extends Node3D
## Swap only when the real Moon is about to leave the far plane.
## At handover the disc matches the real angular size. It shrinks with distance.
## A late boost only kicks in when the disc would become a speck (Earth).
@export var real_moon_path: NodePath = ^".."
@export var surface_high_path: NodePath = ^"../SurfaceHigh"
@export var impostor_mesh_path: NodePath = ^"ImposterSphere"
@export var switch_distance: float = 850000.0
@export var visual_distance: float = 280000.0
@export var real_radius: float = 173700.0
@export var far_boost_start: float = 2500000.0
@export var far_boost_end: float = 20000000.0
@export var far_boost: float = 5.0
var _real_moon: Node3D
var _surface_high: Node3D
var _surface_low: Node3D
var _mesh: MeshInstance3D
var _base_radius: float = 0.5
func _ready() -> void:
_real_moon = get_node_or_null(real_moon_path) as Node3D
_surface_high = get_node_or_null(surface_high_path) as Node3D
if _surface_high == null and _real_moon:
_surface_high = _real_moon.get_node_or_null("SurfaceHigh") as Node3D
if _real_moon:
_surface_low = _real_moon.get_node_or_null("SurfaceLow") as Node3D
_mesh = get_node_or_null(impostor_mesh_path) as MeshInstance3D
if _mesh == null:
_mesh = find_child("ImposterSphere", true, false) as MeshInstance3D
if _mesh:
_mesh.top_level = true
_mesh.visible = false
_mesh.cast_shadow = GeometryInstance3D.SHADOW_CASTING_SETTING_OFF
if _mesh.mesh is SphereMesh:
var sm := _mesh.mesh as SphereMesh
_base_radius = maxf(sm.radius, 0.5)
sm.radial_segments = maxi(sm.radial_segments, 32)
sm.rings = maxi(sm.rings, 16)
var mat := _mesh.get_active_material(0)
if mat == null:
mat = _mesh.material_override
if mat is StandardMaterial3D:
var copy := (mat as StandardMaterial3D).duplicate() as StandardMaterial3D
copy.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED
_mesh.material_override = copy
print("MoonImposter ready switch=", switch_distance, " mesh=", _mesh)
set_process(true)
func _hide_real(hide: bool) -> void:
if _surface_high:
_surface_high.visible = not hide
if _surface_low:
_surface_low.visible = not hide
func _process(_delta: float) -> void:
if _real_moon == null or _mesh == null:
return
var viewer: Node3D = FloatingOrigin.focus
if viewer == null or not is_instance_valid(viewer):
_mesh.visible = false
return
if _real_moon.has_meta("hide_crust") and bool(_real_moon.get_meta("hide_crust")):
_mesh.visible = false
_hide_real(true)
return
var to_moon: Vector3 = _real_moon.global_position - viewer.global_position
var dist: float = to_moon.length()
if dist < switch_distance:
_mesh.visible = false
_hide_real(false)
return
_hide_real(true)
var dir: Vector3 = to_moon / maxf(dist, 1.0)
_mesh.global_position = viewer.global_position + dir * visual_distance
var exact: float = real_radius * (visual_distance / dist)
var t: float = 0.0
if dist > far_boost_start:
t = clampf((dist - far_boost_start) / maxf(far_boost_end - far_boost_start, 1.0), 0.0, 1.0)
var visual_radius: float = exact * lerpf(1.0, far_boost, t)
visual_radius = clampf(visual_radius, 200.0, visual_distance * 0.85)
_mesh.scale = Vector3.ONE * (visual_radius / _base_radius)
_mesh.visible = true
+1
View File
@@ -0,0 +1 @@
uid://db5dujh3xfuky
+9
View File
@@ -0,0 +1,9 @@
extends StaticBody3D
@export var item_name: String = "Multitool"
func on_interact(player: Node) -> void:
if player.has_method("add_item"):
player.add_item(item_name)
print("Picked up: ", item_name)
queue_free()
+1
View File
@@ -0,0 +1 @@
uid://dc246e7164y2f
+63
View File
@@ -0,0 +1,63 @@
extends Control
@onready var resume_button: Button = $PauseButtons/ResumeButton
@onready var save_button: Button = $PauseButtons/SaveButton
@onready var quit_button: Button = $PauseButtons/QuitToMenuButton
var player: Node = null
func _ready() -> void:
visible = false
process_mode = Node.PROCESS_MODE_ALWAYS
if resume_button:
resume_button.pressed.connect(_on_resume)
if save_button:
save_button.pressed.connect(_on_save)
if quit_button:
quit_button.pressed.connect(_on_quit_to_menu)
func _input(event: InputEvent) -> void:
if not event.is_action_pressed("ui_cancel"):
return
var banner := get_node_or_null("/root/Node3D/HUD/ScrambleBanner")
if banner and banner.visible:
return
if visible or get_tree().paused:
_on_resume()
get_viewport().set_input_as_handled()
return
var p := get_tree().get_first_node_in_group("player")
if p == null:
p = get_node_or_null("/root/Node3D/Player")
if p:
open_pause(p)
get_viewport().set_input_as_handled()
func open_pause(player_ref: Node) -> void:
player = player_ref
visible = true
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
get_tree().paused = true
func _on_resume() -> void:
visible = false
get_tree().paused = false
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
func _on_save() -> void:
if player:
GameState.save_game(player)
else:
var p := get_tree().get_first_node_in_group("player")
if p:
GameState.save_game(p)
func _on_quit_to_menu() -> void:
get_tree().paused = false
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
get_tree().change_scene_to_file("res://Scenes/main_menu.tscn")
+1
View File
@@ -0,0 +1 @@
uid://soef5g0d1u0a
+10
View File
@@ -0,0 +1,10 @@
extends StaticBody3D
@export var item_name: String = "Beer Can"
func on_interact(player: Node) -> void:
if player.has_method("add_item"):
player.add_item(item_name)
print("Picked up: ", item_name)
queue_free()
+1
View File
@@ -0,0 +1 @@
uid://dfqr8db8q1y4b
+134
View File
@@ -0,0 +1,134 @@
@tool
extends Node3D
## Hollow planet collision. Attach to Moon or Earth.
## SphereShape3D is a SOLID ball — anything inside the radius gets ejected.
## This builds a concave surface (triangles only) with an optional station hole.
## Visual mesh stays on SurfaceHigh. Collision matches that radius.
@export var surface_mesh_path: NodePath = ^"SurfaceHigh"
@export var old_body_path: NodePath = ^"MoonBody"
@export var hole_anchor_path: NodePath = ^"LovellAnchor"
@export var hole_radius_m: float = 205.0
@export var segments: int = 48
@export var rings: int = 32
@export var rebuild_shell: bool = false:
set(v):
rebuild_shell = false
if v:
build()
func _ready() -> void:
build()
func build() -> void:
var radius: float = _visual_radius()
if radius < 10.0:
push_warning("PlanetShell: no radius from SurfaceHigh")
return
_disable_solid_body()
var hole_dir := Vector3.ZERO
var hole_cos := 1.0
var anchor := get_node_or_null(hole_anchor_path) as Node3D
if anchor and hole_radius_m > 1.0:
var to_a: Vector3 = anchor.global_position - global_position
if to_a.length() > 1.0:
hole_dir = global_transform.basis.inverse() * to_a.normalized()
hole_dir = hole_dir.normalized()
var ang: float = atan(hole_radius_m / radius)
hole_cos = cos(ang)
var faces := _make_faces(radius, hole_dir, hole_cos)
var body := get_node_or_null("ShellBody") as StaticBody3D
if body == null:
body = StaticBody3D.new()
body.name = "ShellBody"
add_child(body)
body.owner = _scene_root()
body.transform = Transform3D()
body.collision_layer = 1
body.collision_mask = 1
var col := body.get_node_or_null("CollisionShape3D") as CollisionShape3D
if col == null:
col = CollisionShape3D.new()
col.name = "CollisionShape3D"
body.add_child(col)
col.owner = body.owner
var shape := ConcavePolygonShape3D.new()
shape.set_faces(faces)
col.shape = shape
col.transform = Transform3D()
print("PlanetShell ", name, " radius=", radius, " faces=", faces.size() / 3, " hole=", hole_dir != Vector3.ZERO, " anchor=", anchor)
func _visual_radius() -> float:
var high := get_node_or_null(surface_mesh_path) as MeshInstance3D
if high and high.mesh is SphereMesh:
var sm := high.mesh as SphereMesh
var rad: float = sm.radius
if sm.height > rad * 1.5:
rad = sm.height * 0.5
var scl: float = maxf(high.scale.x, maxf(high.scale.y, high.scale.z))
rad *= scl
if rad > 100.0:
return rad
return 173700.0
func _disable_solid_body() -> void:
var old := get_node_or_null(old_body_path)
if old == null:
return
var col := old.get_node_or_null("CollisionShape3D") as CollisionShape3D
if col:
col.disabled = true
if old is CollisionObject3D:
(old as CollisionObject3D).collision_layer = 0
(old as CollisionObject3D).collision_mask = 0
print("PlanetShell: MoonBody DISABLED (solid sphere ejects)")
func _make_faces(radius: float, hole_dir: Vector3, hole_cos: float) -> PackedVector3Array:
var faces := PackedVector3Array()
var segs: int = maxi(12, segments)
var rgs: int = maxi(8, rings)
var use_hole: bool = hole_dir.length_squared() > 0.5
for lat in range(rgs):
var t0: float = float(lat) / float(rgs) * PI - PI * 0.5
var t1: float = float(lat + 1) / float(rgs) * PI - PI * 0.5
var y0: float = sin(t0)
var y1: float = sin(t1)
var r0: float = cos(t0)
var r1: float = cos(t1)
for lon in range(segs):
var a0: float = float(lon) / float(segs) * TAU
var a1: float = float(lon + 1) / float(segs) * TAU
var p00 := Vector3(r0 * cos(a0), y0, r0 * sin(a0)) * radius
var p10 := Vector3(r0 * cos(a1), y0, r0 * sin(a1)) * radius
var p01 := Vector3(r1 * cos(a0), y1, r1 * sin(a0)) * radius
var p11 := Vector3(r1 * cos(a1), y1, r1 * sin(a1)) * radius
_add_tri(faces, p00, p01, p11, hole_dir, hole_cos, use_hole)
_add_tri(faces, p00, p11, p10, hole_dir, hole_cos, use_hole)
return faces
func _add_tri(faces: PackedVector3Array, a: Vector3, b: Vector3, c: Vector3, hole_dir: Vector3, hole_cos: float, use_hole: bool) -> void:
if use_hole:
var mid: Vector3 = (a + b + c) / 3.0
if mid.length_squared() < 0.001:
return
if mid.normalized().dot(hole_dir) >= hole_cos:
return
# Both windings. Concave shells are one-sided; a flipped face is a hole you fall through.
faces.append(a)
faces.append(b)
faces.append(c)
faces.append(a)
faces.append(c)
faces.append(b)
func _scene_root() -> Node:
if Engine.is_editor_hint() and get_tree() and get_tree().edited_scene_root:
return get_tree().edited_scene_root
return owner if owner else self
+1
View File
@@ -0,0 +1 @@
uid://2fx6webb7m8d
+9
View File
@@ -0,0 +1,9 @@
extends StaticBody3D
@export var item_name: String = "Plasma Cutter (Damaged)"
func on_interact(player: Node) -> void:
if player.has_method("add_item"):
player.add_item(item_name)
print("Picked up: ", item_name)
queue_free()
+1
View File
@@ -0,0 +1 @@
uid://cdo20owmglm22
File diff suppressed because it is too large Load Diff
+1
View File
@@ -0,0 +1 @@
uid://bqssr0j8iphme
+9
View File
@@ -0,0 +1,9 @@
extends StaticBody3D
@export var item_name: String = "Protein Paste"
func on_interact(player: Node) -> void:
if player.has_method("add_item"):
player.add_item(item_name)
print("Picked up: ", item_name)
queue_free()
+1
View File
@@ -0,0 +1 @@
uid://ch56mng5ltaqf
+10
View File
@@ -0,0 +1,10 @@
extends StaticBody3D
@export var item_name: String = "Ration Pack"
func on_interact(player: Node) -> void:
if player.has_method("add_item"):
player.add_item(item_name)
print("Picked up: ", item_name)
queue_free()
+1
View File
@@ -0,0 +1 @@
uid://cl275qnxinw8q
@@ -0,0 +1,26 @@
extends Node
var rng = RandomNumberGenerator.new()
var materials = [
"res://Kyle's Rock Pack/Kyle Fuji/Materials/M_arid_rocks_1.tres",
"res://Kyle's Rock Pack/Kyle Fuji/Materials/M_arid_rocks_2.tres",
"res://Kyle's Rock Pack/Kyle Fuji/Materials/M_arid_rocks_3.tres",
"res://Kyle's Rock Pack/Kyle Fuji/Materials/M_mossy_rocks_1.tres",
"res://Kyle's Rock Pack/Kyle Fuji/Materials/M_mossy_rocks_2.tres",
"res://Kyle's Rock Pack/Kyle Fuji/Materials/M_sand_stone_rocks.tres",
"res://Kyle's Rock Pack/Kyle Fuji/Materials/M_snow_rocks_1.tres",
"res://Kyle's Rock Pack/Kyle Fuji/Materials/M_snow_rocks_2.tres",
"res://Kyle's Rock Pack/Kyle Fuji/Materials/M_snow_rocks_3.tres"
]
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
rng.randomize()
var my_random_number = rng.randi_range(0, len(materials) - 1)
var NEW_MATERIAL = load(materials[my_random_number])
var nodes = get_tree().get_nodes_in_group("change_material")
for node in nodes:
for child in node.get_children():
if child is MeshInstance3D:
child.material_override = NEW_MATERIAL
@@ -0,0 +1 @@
uid://b6oobwtp7lnw0
+46
View File
@@ -0,0 +1,46 @@
extends Control
var alarm_label: Label
var dismiss_button: Button
func _ready() -> void:
visible = false
process_mode = Node.PROCESS_MODE_ALWAYS
mouse_filter = Control.MOUSE_FILTER_STOP
alarm_label = find_child("AlarmLabel", true, false) as Label
dismiss_button = find_child("DismissButton", true, false) as Button
if dismiss_button:
dismiss_button.pressed.connect(hide_banner)
if not GameState.scramble_begun.is_connected(_on_scramble):
GameState.scramble_begun.connect(_on_scramble)
func _on_scramble() -> void:
visible = true
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
if alarm_label == null:
alarm_label = find_child("AlarmLabel", true, false) as Label
if alarm_label:
alarm_label.modulate = Color.WHITE
alarm_label.self_modulate = Color.WHITE
alarm_label.add_theme_color_override("font_color", Color.WHITE)
alarm_label.add_theme_font_size_override("font_size", 22)
alarm_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
alarm_label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
alarm_label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
alarm_label.mouse_filter = Control.MOUSE_FILTER_IGNORE
alarm_label.text = "PRIORITY ALERT — PEOPLE'S PRIVATEER FLEET INBOUND\nUnregistered prize crews on approach. All hands to extraction. ~10 minutes."
print("SCRAMBLE: PPF inbound")
func hide_banner() -> void:
if not visible:
return
visible = false
if not get_tree().paused:
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
print("SCRAMBLE banner dismissed")
+1
View File
@@ -0,0 +1 @@
uid://b1brrhkbw71xg
+9
View File
@@ -0,0 +1,9 @@
extends StaticBody3D
@export var item_name: String = "Scrap Metal"
func on_interact(player: Node) -> void:
if player.has_method("add_item"):
player.add_item(item_name)
print("Picked up: ", item_name)
queue_free()
+1
View File
@@ -0,0 +1 @@
uid://oljblbitud3n
+9
View File
@@ -0,0 +1,9 @@
extends StaticBody3D
@export var item_name: String = "Soy Bean Seeds"
func on_interact(player: Node) -> void:
if player.has_method("add_item"):
player.add_item(item_name)
print("Picked up: ", item_name)
queue_free()
+1
View File
@@ -0,0 +1 @@
uid://dobhysl1n6hi1
+38
View File
@@ -0,0 +1,38 @@
extends HBoxContainer
@onready var btn_pause: Button = $BtnPause
@onready var btn_x1: Button = $BtnX1
@onready var btn_x2: Button = $BtnX2
@onready var btn_x4: Button = $BtnX4
func _ready() -> void:
process_mode = Node.PROCESS_MODE_ALWAYS
btn_pause.pressed.connect(_on_pause)
btn_x1.pressed.connect(_on_x1)
btn_x2.pressed.connect(_on_x2)
btn_x4.pressed.connect(_on_x4)
if GameState.has_signal("time_scale_changed"):
GameState.time_scale_changed.connect(_on_scale_changed)
_on_scale_changed(GameState.time_scale)
func _on_pause() -> void:
GameState.set_time_scale(0.0)
func _on_x1() -> void:
GameState.set_time_scale(1.0)
func _on_x2() -> void:
GameState.set_time_scale(2.0)
func _on_x4() -> void:
GameState.set_time_scale(4.0)
func _on_scale_changed(new_scale: float) -> void:
btn_pause.disabled = is_equal_approx(new_scale, 0.0)
btn_x1.disabled = is_equal_approx(new_scale, 1.0)
btn_x2.disabled = is_equal_approx(new_scale, 2.0)
btn_x4.disabled = is_equal_approx(new_scale, 4.0)
+1
View File
@@ -0,0 +1 @@
uid://sxr03xjwmthe
+47
View File
@@ -0,0 +1,47 @@
extends Node3D
## Keep the sun disc inside the cockpit far plane. Aim SunLight.
## Never leave the disc sitting on the Moon.
@export var sun_disc_path: NodePath = ^"SunDisc"
@export var sun_light_path: NodePath = ^"../SunLight"
@export var sun_direction: Vector3 = Vector3(-0.82, 0.45, 0.35)
@export var visual_distance: float = 220000.0
@export var visual_radius: float = 9000.0
var _mesh: MeshInstance3D
var _light: DirectionalLight3D
var _base_radius: float = 0.5
func _ready() -> void:
_mesh = get_node_or_null(sun_disc_path) as MeshInstance3D
if _mesh == null:
_mesh = find_child("SunDisc", true, false) as MeshInstance3D
if _mesh and _mesh.mesh is SphereMesh:
_base_radius = maxf((_mesh.mesh as SphereMesh).radius, 0.5)
_light = get_node_or_null(sun_light_path) as DirectionalLight3D
if _light == null:
_light = get_node_or_null("../SunLight") as DirectionalLight3D
sun_direction = sun_direction.normalized()
_aim_light()
set_process(true)
func _aim_light() -> void:
if _light == null:
return
var target: Vector3 = _light.global_position - sun_direction
if target.is_equal_approx(_light.global_position):
return
_light.look_at(target, Vector3.UP)
func _process(_delta: float) -> void:
if _mesh == null:
return
var viewer: Node3D = FloatingOrigin.focus
var origin: Vector3 = viewer.global_position if viewer and is_instance_valid(viewer) else global_position
_mesh.global_position = origin + sun_direction * visual_distance
_mesh.scale = Vector3.ONE * (visual_radius / _base_radius)
_mesh.visible = true
_aim_light()
+1
View File
@@ -0,0 +1 @@
uid://d1o7uwk5jbs5j
+11
View File
@@ -0,0 +1,11 @@
extends StaticBody3D
func on_interact(player: Node) -> void:
print("Terminal accessed by player")
# Simple reaction for now
if player.has_method("add_oxygen"):
player.add_oxygen(15.0) # restore a little oxygen
print("Oxygen partially restored")
# Later this will open a real menu
+1
View File
@@ -0,0 +1 @@
uid://drvd2kgxl2l2s
+9
View File
@@ -0,0 +1,9 @@
extends StaticBody3D
func on_interact(player: Node) -> void:
var menu = get_node_or_null("/root/Node3D/VendorUI/VendorMenu")
if menu and menu.has_method("open_menu"):
menu.open_menu(player)
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
else:
print("Vendor menu not found")
+1
View File
@@ -0,0 +1 @@
uid://dnf3scbnf3qvx
+117
View File
@@ -0,0 +1,117 @@
extends Control
var player: Node = null
@onready var close_button: Button = $MenuPanel/MainVBox/CloseButton
# ===== SELL BUTTONS =====
@onready var sell_buttons = {
"Marijuana Seeds": $MenuPanel/MainVBox/MainColumns/SellVBox/Sell_MarijuanaSeeds,
"Soy Bean Seeds": $MenuPanel/MainVBox/MainColumns/SellVBox/Sell_SoyBeanSeeds,
"Ration Pack": $MenuPanel/MainVBox/MainColumns/SellVBox/Sell_RationPack,
"Dried Noodles": $MenuPanel/MainVBox/MainColumns/SellVBox/Sell_DriedNoodles,
"Protein Paste": $MenuPanel/MainVBox/MainColumns/SellVBox/Sell_ProteinPaste,
"Scrap Metal": $MenuPanel/MainVBox/MainColumns/SellVBox/Sell_ScrapMetal,
"Multitool": $MenuPanel/MainVBox/MainColumns/SellVBox/Sell_Multitool,
"Plasma Cutter (Damaged)": $MenuPanel/MainVBox/MainColumns/SellVBox/Sell_PlasmaCutter,
"Cooking Knife": $MenuPanel/MainVBox/MainColumns/SellVBox/Sell_CookingKnife,
"Circuit Board": $MenuPanel/MainVBox/MainColumns/SellVBox/Sell_CircuitBoard,
"Beer Can": $MenuPanel/MainVBox/MainColumns/SellVBox/Sell_BeerCan,
"Hotdog": $MenuPanel/MainVBox/MainColumns/SellVBox/Sell_Hotdog
}
# ===== BUY BUTTONS =====
@onready var buy_buttons = {
"Ration Pack": $MenuPanel/MainVBox/MainColumns/BuyVBox/Buy_RationPack,
"Dried Noodles": $MenuPanel/MainVBox/MainColumns/BuyVBox/Buy_DriedNoodles,
"Protein Paste": $MenuPanel/MainVBox/MainColumns/BuyVBox/Buy_ProteinPaste,
"Beer Can": $MenuPanel/MainVBox/MainColumns/BuyVBox/Buy_BeerCan,
"Hotdog": $MenuPanel/MainVBox/MainColumns/BuyVBox/Buy_Hotdog
}
var sell_prices = {
"Marijuana Seeds": 40,
"Soy Bean Seeds": 25,
"Ration Pack": 18,
"Dried Noodles": 10,
"Protein Paste": 14,
"Scrap Metal": 15,
"Multitool": 50,
"Plasma Cutter (Damaged)": 65,
"Cooking Knife": 28,
"Circuit Board": 42,
"Beer Can": 8,
"Hotdog": 8
}
var buy_prices = {
"Ration Pack": 15,
"Dried Noodles": 12,
"Protein Paste": 16,
"Beer Can": 10,
"Hotdog": 15
}
func _ready() -> void:
for item_name in sell_buttons.keys():
var button = sell_buttons[item_name]
if button:
button.pressed.connect(_sell.bind(item_name, sell_prices[item_name]))
else:
print("Missing sell button for: ", item_name)
for item_name in buy_buttons.keys():
var button = buy_buttons[item_name]
if button:
button.pressed.connect(_buy.bind(item_name, buy_prices[item_name]))
else:
print("Missing buy button for: ", item_name)
if close_button:
close_button.pressed.connect(_on_close_pressed)
visible = false
func open_menu(player_ref: Node) -> void:
player = player_ref
visible = true
_update_button_states()
print("Vendor menu opened")
func _update_button_states() -> void:
if player == null:
return
for item_name in sell_buttons.keys():
var button = sell_buttons[item_name]
if button:
button.disabled = not player.inventory.has(item_name)
for item_name in buy_buttons.keys():
var button = buy_buttons[item_name]
if button:
button.disabled = player.money < buy_prices[item_name]
func _sell(item_name: String, price: int) -> void:
if player == null:
return
if player.remove_item(item_name):
player.add_money(price)
print("Sold ", item_name, " for ", price, " credits")
_update_button_states()
else:
print("You don't have ", item_name)
func _buy(item_name: String, price: int) -> void:
if player == null:
return
if player.money >= price:
player.add_money(-price)
player.add_item(item_name)
print("Bought ", item_name)
_update_button_states()
else:
print("Not enough credits")
func _on_close_pressed() -> void:
visible = false
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
+1
View File
@@ -0,0 +1 @@
uid://bbr0judkwyfhb
Binary file not shown.
+41
View File
@@ -0,0 +1,41 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bf63eg11cuqij"
path.s3tc="res://.godot/imported/T_flag.png-1a69bfd8a15b78e7f98590a98c6f7426.s3tc.ctex"
metadata={
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
[deps]
source_file="res://Scenes/Textures/T_flag.png"
dest_files=["res://.godot/imported/T_flag.png-1a69bfd8a15b78e7f98590a98c6f7426.s3tc.ctex"]
[params]
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
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/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
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
View File
Binary file not shown.
File diff suppressed because it is too large Load Diff
BIN
View File
Binary file not shown.
+45
View File
@@ -0,0 +1,45 @@
[remap]
importer="scene"
importer_version=1
type="PackedScene"
uid="uid://dy4q76vua88y"
path="res://.godot/imported/Unarmed_RM.glb-ba307165329601e24032bf470389b5ea.scn"
[deps]
source_file="res://Scenes/Unarmed_RM.glb"
dest_files=["res://.godot/imported/Unarmed_RM.glb-ba307165329601e24032bf470389b5ea.scn"]
[params]
nodes/root_type=""
nodes/root_name=""
nodes/root_script=null
mesh_library/use_node_names_as_mesh_names=false
array_mesh/deduplicate_surfaces=true
nodes/apply_root_scale=true
nodes/root_scale=1.0
nodes/import_as_skeleton_bones=false
nodes/use_name_suffixes=true
nodes/use_node_type_suffixes=true
meshes/ensure_tangents=true
meshes/generate_lods=true
meshes/create_shadow_meshes=true
meshes/light_baking=1
meshes/lightmap_texel_size=0.2
meshes/force_disable_compression=false
skins/use_named_skins=true
animation/import=true
animation/fps=30
animation/trimming=false
animation/remove_immutable_tracks=true
animation/import_rest_as_RESET=false
import_script/path=""
materials/extract=0
materials/extract_format=0
materials/extract_path=""
_subresources={}
gltf/naming_version=2
gltf/embedded_image_handling=1
gltf/texture_map_mode=1
+268
View File
@@ -0,0 +1,268 @@
[gd_scene format=3 uid="uid://ccio4xdkkad5u"]
[ext_resource type="Script" uid="uid://cxrxrk0qt15dl" path="res://Scenes/Scripts/character_creation.gd" id="1_r633d"]
[node name="CharacterCreation" type="Control" unique_id=436175007]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_r633d")
[node name="Background" type="ColorRect" parent="." unique_id=1949662708]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
color = Color(0.043137256, 0.05490196, 0.078431375, 1)
[node name="CenterRoot" type="MarginContainer" parent="." unique_id=464110165]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
theme_override_constants/margin_left = 24
theme_override_constants/margin_top = 24
theme_override_constants/margin_right = 24
theme_override_constants/margin_bottom = 24
[node name="Page" type="VBoxContainer" parent="CenterRoot" unique_id=1781904031]
layout_mode = 2
[node name="Title" type="Label" parent="CenterRoot/Page" unique_id=382334510]
custom_minimum_size = Vector2(400, 36)
layout_mode = 2
text = "Create Your Character"
horizontal_alignment = 1
[node name="NameInput" type="LineEdit" parent="CenterRoot/Page" unique_id=1431403709]
custom_minimum_size = Vector2(360, 0)
layout_mode = 2
size_flags_horizontal = 4
placeholder_text = "Enter Name..."
alignment = 1
[node name="MainSplit" type="HBoxContainer" parent="CenterRoot/Page" unique_id=1268834436]
layout_mode = 2
size_flags_vertical = 3
[node name="LookRow" type="HBoxContainer" parent="CenterRoot/Page/MainSplit" unique_id=883755372]
layout_mode = 2
[node name="LookPreview" type="SubViewportContainer" parent="CenterRoot/Page/MainSplit/LookRow" unique_id=1109688710]
custom_minimum_size = Vector2(360, 420)
layout_mode = 2
size_flags_vertical = 4
stretch = true
[node name="SubViewport" type="SubViewport" parent="CenterRoot/Page/MainSplit/LookRow/LookPreview" unique_id=905654693]
own_world_3d = true
handle_input_locally = false
size = Vector2i(360, 420)
render_target_update_mode = 4
[node name="LookWorld" type="Node3D" parent="CenterRoot/Page/MainSplit/LookRow/LookPreview/SubViewport" unique_id=2053829353]
[node name="LookCam" type="Camera3D" parent="CenterRoot/Page/MainSplit/LookRow/LookPreview/SubViewport/LookWorld" unique_id=1932382112]
transform = Transform3D(1, 0, 0, 0, 0.99026805, 0.1391731, 0, -0.1391731, 0.99026805, 0, 1.5, 3.5)
current = true
[node name="LookKey" type="DirectionalLight3D" parent="CenterRoot/Page/MainSplit/LookRow/LookPreview/SubViewport/LookWorld" unique_id=254093398]
transform = Transform3D(0.76604444, -0.3686878, 0.52654076, 0, 0.81915206, 0.57357645, -0.6427876, -0.43938506, 0.62750685, 0, 0, 0)
[node name="LookControls" type="VBoxContainer" parent="CenterRoot/Page/MainSplit/LookRow" unique_id=2037784678]
custom_minimum_size = Vector2(168, 0)
layout_mode = 2
[node name="SexRow" type="HBoxContainer" parent="CenterRoot/Page/MainSplit/LookRow/LookControls" unique_id=369989045]
layout_mode = 2
alignment = 1
[node name="SexMale" type="Button" parent="CenterRoot/Page/MainSplit/LookRow/LookControls/SexRow" unique_id=505283771]
layout_mode = 2
text = "Male"
[node name="SexFemale" type="Button" parent="CenterRoot/Page/MainSplit/LookRow/LookControls/SexRow" unique_id=1592599057]
layout_mode = 2
text = "Female"
[node name="LabHead" type="Label" parent="CenterRoot/Page/MainSplit/LookRow/LookControls" unique_id=2104734069]
layout_mode = 2
text = "Head"
horizontal_alignment = 1
[node name="RowHead" type="HBoxContainer" parent="CenterRoot/Page/MainSplit/LookRow/LookControls" unique_id=1403190168]
custom_minimum_size = Vector2(140, 32)
layout_mode = 2
alignment = 1
[node name="Prev_Head" type="Button" parent="CenterRoot/Page/MainSplit/LookRow/LookControls/RowHead" unique_id=2040372778]
custom_minimum_size = Vector2(36, 32)
layout_mode = 2
text = "<"
[node name="Name_Head" type="Label" parent="CenterRoot/Page/MainSplit/LookRow/LookControls/RowHead" unique_id=506497795]
layout_mode = 2
text = "Casual"
[node name="Next_Head" type="Button" parent="CenterRoot/Page/MainSplit/LookRow/LookControls/RowHead" unique_id=487423449]
custom_minimum_size = Vector2(36, 32)
layout_mode = 2
text = ">"
[node name="LabBody" type="Label" parent="CenterRoot/Page/MainSplit/LookRow/LookControls" unique_id=1014135234]
layout_mode = 2
text = "Body"
horizontal_alignment = 1
[node name="RowBody" type="HBoxContainer" parent="CenterRoot/Page/MainSplit/LookRow/LookControls" unique_id=1422286663]
layout_mode = 2
alignment = 1
[node name="Prev_Body" type="Button" parent="CenterRoot/Page/MainSplit/LookRow/LookControls/RowBody" unique_id=1417818257]
custom_minimum_size = Vector2(36, 32)
layout_mode = 2
text = "<"
[node name="Name_Body" type="Label" parent="CenterRoot/Page/MainSplit/LookRow/LookControls/RowBody" unique_id=797862923]
layout_mode = 2
text = "Casual"
[node name="Next_Body" type="Button" parent="CenterRoot/Page/MainSplit/LookRow/LookControls/RowBody" unique_id=1566826248]
custom_minimum_size = Vector2(36, 32)
layout_mode = 2
text = ">"
[node name="LabLegs" type="Label" parent="CenterRoot/Page/MainSplit/LookRow/LookControls" unique_id=734720409]
layout_mode = 2
text = "Legs"
horizontal_alignment = 1
[node name="RowLegs" type="HBoxContainer" parent="CenterRoot/Page/MainSplit/LookRow/LookControls" unique_id=393100881]
layout_mode = 2
alignment = 1
[node name="Prev_Legs" type="Button" parent="CenterRoot/Page/MainSplit/LookRow/LookControls/RowLegs" unique_id=462280303]
custom_minimum_size = Vector2(36, 32)
layout_mode = 2
text = "<"
[node name="Name_Legs" type="Label" parent="CenterRoot/Page/MainSplit/LookRow/LookControls/RowLegs" unique_id=1084594247]
layout_mode = 2
text = "Casual"
[node name="Next_Legs" type="Button" parent="CenterRoot/Page/MainSplit/LookRow/LookControls/RowLegs" unique_id=402072381]
custom_minimum_size = Vector2(36, 32)
layout_mode = 2
text = ">"
[node name="LabFeet" type="Label" parent="CenterRoot/Page/MainSplit/LookRow/LookControls" unique_id=1826945463]
layout_mode = 2
text = "Feet"
horizontal_alignment = 1
[node name="RowFeet" type="HBoxContainer" parent="CenterRoot/Page/MainSplit/LookRow/LookControls" unique_id=816382406]
layout_mode = 2
alignment = 1
[node name="Prev_Feet" type="Button" parent="CenterRoot/Page/MainSplit/LookRow/LookControls/RowFeet" unique_id=1638885196]
custom_minimum_size = Vector2(36, 32)
layout_mode = 2
text = "<"
[node name="Name_Feet" type="Label" parent="CenterRoot/Page/MainSplit/LookRow/LookControls/RowFeet" unique_id=1924000265]
layout_mode = 2
text = "Casual"
[node name="Next_Feet" type="Button" parent="CenterRoot/Page/MainSplit/LookRow/LookControls/RowFeet" unique_id=1591763969]
custom_minimum_size = Vector2(36, 32)
layout_mode = 2
text = ">"
[node name="Scroll" type="ScrollContainer" parent="CenterRoot/Page/MainSplit" unique_id=273031910]
custom_minimum_size = Vector2(480, 560)
layout_mode = 2
size_flags_horizontal = 3
[node name="FormColumn" type="VBoxContainer" parent="CenterRoot/Page/MainSplit/Scroll" unique_id=1432553215]
layout_mode = 2
size_flags_horizontal = 3
theme_override_constants/separation = 8
[node name="CultureLabel" type="Label" parent="CenterRoot/Page/MainSplit/Scroll/FormColumn" unique_id=1835217621]
layout_mode = 2
text = "Culture"
horizontal_alignment = 1
[node name="CultureList" type="GridContainer" parent="CenterRoot/Page/MainSplit/Scroll/FormColumn" unique_id=684724774]
layout_mode = 2
columns = 3
[node name="Culture_NAF" type="Button" parent="CenterRoot/Page/MainSplit/Scroll/FormColumn/CultureList" unique_id=849092527]
custom_minimum_size = Vector2(0, 36)
layout_mode = 2
text = "North American"
[node name="Culture_EAA" type="Button" parent="CenterRoot/Page/MainSplit/Scroll/FormColumn/CultureList" unique_id=44970011]
custom_minimum_size = Vector2(0, 36)
layout_mode = 2
text = "East Asian"
[node name="Culture_Russian" type="Button" parent="CenterRoot/Page/MainSplit/Scroll/FormColumn/CultureList" unique_id=1133102118]
custom_minimum_size = Vector2(0, 36)
layout_mode = 2
text = "Russian"
[node name="Culture_European" type="Button" parent="CenterRoot/Page/MainSplit/Scroll/FormColumn/CultureList" unique_id=677544509]
custom_minimum_size = Vector2(0, 36)
layout_mode = 2
text = "European"
[node name="Culture_Brazilian" type="Button" parent="CenterRoot/Page/MainSplit/Scroll/FormColumn/CultureList" unique_id=1802695568]
custom_minimum_size = Vector2(0, 36)
layout_mode = 2
text = "Brazilian"
[node name="Culture_Independent" type="Button" parent="CenterRoot/Page/MainSplit/Scroll/FormColumn/CultureList" unique_id=576443035]
custom_minimum_size = Vector2(0, 36)
layout_mode = 2
text = "Independent "
[node name="JobLabel" type="Label" parent="CenterRoot/Page/MainSplit/Scroll/FormColumn" unique_id=1978424005]
layout_mode = 2
text = "Starting Profession"
horizontal_alignment = 1
vertical_alignment = 1
[node name="BackgroundList" type="GridContainer" parent="CenterRoot/Page/MainSplit/Scroll/FormColumn" unique_id=452359861]
layout_mode = 2
columns = 2
[node name="DescriptionLabel" type="Label" parent="CenterRoot/Page/MainSplit/Scroll/FormColumn" unique_id=1359111642]
custom_minimum_size = Vector2(80, 64)
layout_mode = 2
text = "Select a culture and profession."
autowrap_mode = 2
[node name="BonusLabel" type="Label" parent="CenterRoot/Page/MainSplit/Scroll/FormColumn" unique_id=613114403]
custom_minimum_size = Vector2(22, 24)
layout_mode = 2
text = "Starting bonus: —"
autowrap_mode = 2
[node name="ConfirmButton" type="Button" parent="CenterRoot/Page/MainSplit/Scroll/FormColumn" unique_id=224306]
custom_minimum_size = Vector2(32, 0)
layout_mode = 2
size_flags_horizontal = 4
text = "Begin"
[node name="BackButton" type="Button" parent="CenterRoot/Page/MainSplit/Scroll/FormColumn" unique_id=1012112632]
layout_mode = 2
size_flags_horizontal = 4
text = "Back"
+343
View File
@@ -0,0 +1,343 @@
[gd_scene format=3 uid="uid://tqhk0a248g5k"]
[ext_resource type="Script" uid="uid://1udl42sp42sp" path="res://Scenes/Scripts/escape_capsule.gd" id="1_mfps1"]
[ext_resource type="PackedScene" uid="uid://dg0yewov2bymm" path="res://kestrel_ec01_godot/kestrel.tscn" id="2_85cng"]
[ext_resource type="Script" uid="uid://ond7pwt03hgd" path="res://kestrel_driver.gd" id="3_81abi"]
[sub_resource type="CylinderShape3D" id="CylinderShape3D_j65qs"]
height = 3.795288
radius = 2.2
[sub_resource type="CylinderShape3D" id="CylinderShape3D_81abi"]
height = 2.0190659
radius = 0.10839844
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_kq58d"]
albedo_color = Color(0.3529412, 0.36862746, 0.4, 1)
[sub_resource type="CylinderMesh" id="CylinderMesh_18y2q"]
material = SubResource("StandardMaterial3D_kq58d")
top_radius = 1.8
bottom_radius = 2.2
height = 3.5
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_ryguw"]
albedo_color = Color(0.017732391, 0.017732391, 0.01773239, 1)
metallic = 0.56
[sub_resource type="CylinderMesh" id="CylinderMesh_3jrso"]
material = SubResource("StandardMaterial3D_ryguw")
top_radius = 2.3
bottom_radius = 2.3
height = 0.25
[sub_resource type="SphereShape3D" id="SphereShape3D_crvdt"]
radius = 3.5
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_58fjt"]
transparency = 1
cull_mode = 2
shading_mode = 0
albedo_color = Color(0.2347951, 0.2347951, 0.2347951, 0.060000002)
[sub_resource type="BoxMesh" id="BoxMesh_ijs7n"]
material = SubResource("StandardMaterial3D_58fjt")
size = Vector3(1.4949585, 0.8827637, 0.16409448)
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_a6jrf"]
albedo_color = Color(0.101960786, 0.13725491, 0.19607843, 1)
emission = Color(0, 0.9704087, 1, 1)
emission_energy_multiplier = 0.2
[sub_resource type="BoxMesh" id="BoxMesh_xuqvo"]
material = SubResource("StandardMaterial3D_a6jrf")
size = Vector3(1.2497559, 0.6052246, 0.04)
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_1u8w0"]
albedo_color = Color(0.37187055, 0.11207495, 0.050708726, 1)
[sub_resource type="BoxMesh" id="BoxMesh_d13ii"]
material = SubResource("StandardMaterial3D_1u8w0")
size = Vector3(0.65, 0.12, 0.65)
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_l6148"]
albedo_color = Color(0.88857853, 0.025840001, 0, 1)
[sub_resource type="BoxMesh" id="BoxMesh_ts8u1"]
material = SubResource("StandardMaterial3D_l6148")
size = Vector3(0.65, 0.85, 0.1)
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_wqh1g"]
albedo_color = Color(0.05882353, 0.05882353, 0.05882353, 1)
metallic = 0.51
[sub_resource type="BoxMesh" id="BoxMesh_l6148"]
material = SubResource("StandardMaterial3D_wqh1g")
size = Vector3(1, 0.7, 0.5)
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_kx67c"]
albedo_color = Color(0.101960786, 0.13725491, 0.19607843, 1)
emission_enabled = true
emission = Color(0.101960786, 0.22745098, 0.36078432, 1)
emission_energy_multiplier = 2.0
[sub_resource type="BoxMesh" id="BoxMesh_wqh1g"]
material = SubResource("StandardMaterial3D_kx67c")
size = Vector3(0.35, 0.25, 0.02)
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_r6cyv"]
albedo_color = Color(0.16470589, 0.16470589, 0.16470589, 1)
[sub_resource type="BoxMesh" id="BoxMesh_kx67c"]
material = SubResource("StandardMaterial3D_r6cyv")
size = Vector3(0.15, 0.08, 0.02)
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_omqyl"]
albedo_color = Color(0.039215688, 0.0627451, 0.09411765, 1)
emission_enabled = true
emission = Color(0.101960786, 0.22745098, 0.36078432, 1)
emission_energy_multiplier = 2.0
[sub_resource type="BoxMesh" id="BoxMesh_52c6f"]
material = SubResource("StandardMaterial3D_omqyl")
size = Vector3(0.24501038, 0.20367628, 0.01890625)
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_0odxb"]
albedo_color = Color(0.07058824, 0.07058824, 0.07058824, 1)
[sub_resource type="BoxMesh" id="BoxMesh_r6cyv"]
material = SubResource("StandardMaterial3D_0odxb")
size = Vector3(0.08, 2.1133926, 3.2745347)
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_d13ii"]
albedo_color = Color(0.07058824, 0.07058824, 0.07058824, 1)
[sub_resource type="BoxMesh" id="BoxMesh_4yprg"]
material = SubResource("StandardMaterial3D_d13ii")
size = Vector3(2.7717957, 0.04, 3.2841797)
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_52c6f"]
albedo_color = Color(0.07058824, 0.07058824, 0.07058824, 1)
[sub_resource type="BoxMesh" id="BoxMesh_o0dcp"]
material = SubResource("StandardMaterial3D_52c6f")
size = Vector3(1.187207, 0.06, 0.35)
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_p2ucw"]
albedo_color = Color(0.05882353, 0.05882353, 0.05882353, 1)
[sub_resource type="BoxMesh" id="BoxMesh_omqyl"]
material = SubResource("StandardMaterial3D_p2ucw")
size = Vector3(2.9555702, 0.75, 0.08)
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_ucmdv"]
albedo_color = Color(0.05882353, 0.05882353, 0.05882353, 1)
[sub_resource type="BoxMesh" id="BoxMesh_p2ucw"]
material = SubResource("StandardMaterial3D_ucmdv")
size = Vector3(2.9560547, 0.7133789, 0.08)
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_seu75"]
albedo_color = Color(0.05882353, 0.05882353, 0.05882353, 1)
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_81jjf"]
albedo_color = Color(0.05882353, 0.05882353, 0.05882353, 1)
[sub_resource type="BoxMesh" id="BoxMesh_ucmdv"]
material = SubResource("StandardMaterial3D_81jjf")
size = Vector3(0.65, 0.05, 3.2439454)
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_ijs7n"]
albedo_color = Color(0.05882353, 0.05882353, 0.05882353, 1)
[sub_resource type="BoxMesh" id="BoxMesh_81jjf"]
material = SubResource("StandardMaterial3D_ijs7n")
size = Vector3(0.64851075, 0.05, 3.2384765)
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_nei3f"]
albedo_color = Color(0.05882353, 0.05882353, 0.05882353, 1)
[node name="EscapeCapsule" type="CharacterBody3D" unique_id=900802887 groups=["interactable"]]
script = ExtResource("1_mfps1")
[node name="Kestrel" parent="." unique_id=193910237 instance=ExtResource("2_85cng")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -2.0820568, 0)
script = ExtResource("3_81abi")
[node name="CameraPivot" type="Node3D" parent="." unique_id=1263006067]
transform = Transform3D(1, 8.742278e-08, -8.7422784e-08, -8.742278e-08, -4.371139e-08, -1, -8.7422784e-08, 1, -4.371138e-08, -0.6827204, -1.8933923, 1.2853639)
[node name="CapsuleCamera" type="Camera3D" parent="CameraPivot" unique_id=1044956475]
transform = Transform3D(1, 0, -3.2840569e-15, 0, 1, 0, -3.2840569e-15, 0, 1, 0, -0.21693517, -0.4030409)
far = 1000000.0
[node name="CollisionShape3D" type="CollisionShape3D" parent="." unique_id=640959005]
shape = SubResource("CylinderShape3D_j65qs")
[node name="CollisionShape3D2" type="CollisionShape3D" parent="." unique_id=2080610717]
transform = Transform3D(0.81112194, -0.30945623, 0.49630463, 0.077922754, 0.89817417, 0.43267947, -0.57966334, -0.31228232, 0.75264233, 1.8034304, -2.742339, 1.8590356)
shape = SubResource("CylinderShape3D_81abi")
[node name="CollisionShape3D5" type="CollisionShape3D" parent="." unique_id=908124294]
transform = Transform3D(-0.7822406, 0.32521898, -0.53135055, 0.012437973, 0.8609036, 0.5086148, 0.6228521, 0.39124995, -0.6774788, -1.945058, -2.6434186, -1.9002763)
shape = SubResource("CylinderShape3D_81abi")
[node name="CollisionShape3D4" type="CollisionShape3D" parent="." unique_id=1939084631]
transform = Transform3D(0.89748794, 0.3169628, -0.30667582, -0.17042562, 0.89057636, 0.42169732, 0.4067809, -0.32620275, 0.8533001, -1.7836877, -2.70675, 1.7776158)
shape = SubResource("CylinderShape3D_81abi")
[node name="CollisionShape3D3" type="CollisionShape3D" parent="." unique_id=1979004740]
transform = Transform3D(-0.792779, -0.34827715, -0.5002045, -0.45405236, 0.8849464, 0.10347074, 0.40661794, 0.30914834, -0.85970277, 1.929804, -2.7048826, -1.8303667)
shape = SubResource("CylinderShape3D_81abi")
[node name="Body" type="MeshInstance3D" parent="." unique_id=683390934]
visible = false
mesh = SubResource("CylinderMesh_18y2q")
[node name="ExternalView" type="SubViewport" parent="Body" unique_id=1265488610]
handle_input_locally = false
size = Vector2i(3840, 2160)
render_target_update_mode = 4
[node name="Camera3D" type="Camera3D" parent="Body/ExternalView" unique_id=698867349]
transform = Transform3D(1, 0, 0, 0, -4.371139e-08, -1, 0, 1, -4.371139e-08, 18.911898, 5.1233277, -0.039017588)
visible = false
fov = 72.0
far = 1000000.0
[node name="HeatShield" type="MeshInstance3D" parent="." unique_id=2080285390]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1.9, 0)
visible = false
mesh = SubResource("CylinderMesh_3jrso")
[node name="InteractionArea" type="Area3D" parent="." unique_id=1761123778]
[node name="CollisionShape3D" type="CollisionShape3D" parent="InteractionArea" unique_id=1229487990]
shape = SubResource("SphereShape3D_crvdt")
[node name="ThirdPersonCamera" type="Camera3D" parent="." unique_id=284479039]
transform = Transform3D(1, 0, 0, 0, -4.371139e-08, -1, 0, 1, -4.371139e-08, 0, -9.5, 3.5)
far = 1000000.0
[node name="Cockpit" type="Node3D" parent="." unique_id=1933795690]
transform = Transform3D(-1, 8.742278e-08, 3.821371e-15, 0, -4.371139e-08, 1, 8.742278e-08, 1, 4.371139e-08, 0, -0.94330907, -0.62695575)
visible = false
[node name="WindowGlass" type="MeshInstance3D" parent="Cockpit" unique_id=99141125]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.0015087128, 1.5509896, 2.2775838)
mesh = SubResource("BoxMesh_ijs7n")
[node name="HudShape" type="MeshInstance3D" parent="Cockpit" unique_id=1572026781]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.0777357, 1.8649361)
visible = false
mesh = SubResource("BoxMesh_xuqvo")
[node name="CockpitLight" type="OmniLight3D" parent="Cockpit" unique_id=1492843635]
transform = Transform3D(-1, 0, 8.742278e-08, 8.742278e-08, -4.371139e-08, 1, 3.821371e-15, 1, 4.371139e-08, 0, 2.1579213, 0.00050091743)
light_color = Color(1, 0.89411765, 0.76862746, 1)
omni_range = 3.5
[node name="Seat" type="MeshInstance3D" parent="Cockpit" unique_id=123094182]
mesh = SubResource("BoxMesh_d13ii")
[node name="SeatBack" type="MeshInstance3D" parent="Cockpit" unique_id=1553533167]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.38205957, -0.36825216)
mesh = SubResource("BoxMesh_ts8u1")
[node name="MainPanel" type="MeshInstance3D" parent="Cockpit" unique_id=2127997099]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.42596802, 1.6161394)
mesh = SubResource("BoxMesh_l6148")
[node name="GlassCockpitPanel" type="MeshInstance3D" parent="Cockpit/MainPanel" unique_id=56681667]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.16014825, -0.25493002)
mesh = SubResource("BoxMesh_wqh1g")
[node name="LeftInstrument" type="MeshInstance3D" parent="Cockpit/MainPanel" unique_id=944149313]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.294096, 0.21341178, -0.25256205)
mesh = SubResource("BoxMesh_kx67c")
[node name="RightInstrument" type="MeshInstance3D" parent="Cockpit/MainPanel" unique_id=1061352713]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.294, 0.213, -0.253)
mesh = SubResource("BoxMesh_kx67c")
[node name="ForwardDisplay" type="MeshInstance3D" parent="Cockpit/MainPanel" unique_id=1977279423]
transform = Transform3D(0.9999994, -5.728489e-05, -0.0011173013, 5.5921435e-05, 0.99999917, -0.0012259485, 0.0011173704, 0.0012257855, 0.9999986, 0.32665062, 0.049695313, -0.25658345)
mesh = SubResource("BoxMesh_52c6f")
[node name="LeftWall" type="MeshInstance3D" parent="Cockpit" unique_id=1514749488]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.4201202, 0.6709095, 0.801975)
mesh = SubResource("BoxMesh_r6cyv")
[node name="RightWall" type="MeshInstance3D" parent="Cockpit" unique_id=1764263004]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.4199867, 0.67109835, 0.79347587)
mesh = SubResource("BoxMesh_r6cyv")
[node name="Floor" type="MeshInstance3D" parent="Cockpit" unique_id=1998677292]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.0061683655, -0.25959706, 0.80126953)
mesh = SubResource("BoxMesh_4yprg")
[node name="OverheadConsole" type="MeshInstance3D" parent="Cockpit" unique_id=976403028]
transform = Transform3D(-4.371139e-08, 0, -1, 0, 1, 0, 1, 0, -4.371139e-08, 0, 2.2589908, 0.95627284)
mesh = SubResource("BoxMesh_o0dcp")
[node name="ForwardBulkhead" type="MeshInstance3D" parent="Cockpit" unique_id=1582033665]
transform = Transform3D(1, -6.905431e-09, -3.4056352e-08, -6.905438e-09, 0.92101103, -0.38953644, 3.4054356e-08, 0.38953644, 0.92101103, -0.0020980835, 0.10092795, 2.3168466)
visible = false
mesh = SubResource("BoxMesh_omqyl")
[node name="ForwardBulkhead2" type="MeshInstance3D" parent="Cockpit/ForwardBulkhead" unique_id=1004286348]
transform = Transform3D(1, -6.9062125e-09, 3.4056193e-08, -6.905424e-09, 0.9210111, 0.38953647, -3.405436e-08, -0.38953647, 0.9210111, 0.018800735, 0.70290273, -0.13796377)
mesh = SubResource("BoxMesh_omqyl")
[node name="MeshInstance3D" type="MeshInstance3D" parent="Cockpit/ForwardBulkhead" unique_id=411181651]
transform = Transform3D(1, -7.2910282e-09, 3.4950116e-08, -7.2894153e-09, 0.91661024, 0.39978403, -3.4950364e-08, -0.39978403, 0.91661024, 0.021972656, 1.129911, -0.3276949)
mesh = SubResource("BoxMesh_p2ucw")
[node name="FrontBulkhead" type="CSGCombiner3D" parent="Cockpit/ForwardBulkhead" unique_id=1462779310]
transform = Transform3D(1, -6.9062196e-09, 3.40562e-08, -6.905424e-09, 0.92101115, 0.3895365, -3.405436e-08, -0.3895365, 0.92101115, 0.0020980835, -0.0909484, 0.044061184)
visible = false
[node name="BulkheadShape" type="CSGPolygon3D" parent="Cockpit/ForwardBulkhead/FrontBulkhead" unique_id=991532318]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.9277502, 0.22244406)
polygon = PackedVector2Array(-1.55, -0.345, 1.55, -0.345, 0.72924423, 0.34169006, -0.75127983, 0.3621254)
depth = 0.12
material = SubResource("StandardMaterial3D_seu75")
[node name="RoofLeft" type="MeshInstance3D" parent="Cockpit" unique_id=1535690315]
transform = Transform3D(0.7071067, 0.7071067, 0, -0.7071067, 0.7071067, 0, 0, 0, 1, 1.1796818, 1.8760827, 0.79144645)
mesh = SubResource("BoxMesh_ucmdv")
[node name="RoofLeft1" type="MeshInstance3D" parent="Cockpit/RoofLeft" unique_id=1785270765]
transform = Transform3D(0.8763269, -0.4817174, 9.8520925e-09, 0.4817174, 0.8763269, 7.3968387e-09, -1.2196834e-08, -1.7361046e-09, 1, -0.6168623, -0.15812302, 0.005322695)
mesh = SubResource("BoxMesh_ucmdv")
[node name="RoofRight" type="MeshInstance3D" parent="Cockpit" unique_id=10541876]
transform = Transform3D(0.7071067, -0.7071067, 0, 0.7071067, 0.7071067, 0, 0, 0, 1, -1.18, 1.876, 0.791)
mesh = SubResource("BoxMesh_ucmdv")
[node name="RoofRight1" type="MeshInstance3D" parent="Cockpit/RoofRight" unique_id=597720853]
transform = Transform3D(0.87630665, 0.4817537, 0, -0.4817537, 0.87630665, 0, 3.543832e-13, 0, 1, 0.6105108, -0.15750027, -0.0017383099)
mesh = SubResource("BoxMesh_81jjf")
[node name="RoofTop" type="MeshInstance3D" parent="Cockpit" unique_id=974546659]
transform = Transform3D(0.9999999, 0, 0, 0, 0.9999999, 0, 0, 0, 1, -0.00787735, 2.2835252, 0.79144645)
mesh = SubResource("BoxMesh_ucmdv")
[node name="ForwardBulkhead2" type="CSGCombiner3D" parent="Cockpit" unique_id=1803926178]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.14711916, 2.8341548)
[node name="BulkTop" type="CSGPolygon3D" parent="Cockpit/ForwardBulkhead2" unique_id=1704103664]
transform = Transform3D(1, -1.4087291e-09, 1.562843e-08, -1.4074928e-09, 0.9838952, 0.17874739, -1.5626552e-08, -0.17874739, 0.9838952, 0.0020980835, 1.7711809, -0.50199556)
polygon = PackedVector2Array(-1.55, -0.345, 1.55, -0.345, 0.72924423, 0.34169006, -0.75127983, 0.3621254)
depth = 0.12
material = SubResource("StandardMaterial3D_seu75")
[node name="BulkBottom" type="CSGBox3D" parent="Cockpit/ForwardBulkhead2" unique_id=1217332907]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.0018692017, 0.49510977, -0.49700785)
size = Vector3(2.788086, 1.8628662, 0.08208008)
material = SubResource("StandardMaterial3D_nei3f")
[node name="WindowCutout" type="CSGBox3D" parent="Cockpit/ForwardBulkhead2" unique_id=1392835612]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.4177693, -0.5765586)
operation = 2
size = Vector3(1.5, 0.89470214, 0.2836914)
+316
View File
@@ -0,0 +1,316 @@
[gd_scene format=3 uid="uid://dbva2yw4g016o"]
[ext_resource type="Script" uid="uid://1udl42sp42sp" path="res://Scenes/Scripts/escape_capsule.gd" id="1_r50ee"]
[sub_resource type="CylinderShape3D" id="CylinderShape3D_j65qs"]
height = 3.795288
radius = 2.2
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_kq58d"]
albedo_color = Color(0.3529412, 0.36862746, 0.4, 1)
[sub_resource type="CylinderMesh" id="CylinderMesh_18y2q"]
material = SubResource("StandardMaterial3D_kq58d")
top_radius = 1.8
bottom_radius = 2.2
height = 3.5
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_ryguw"]
albedo_color = Color(0.017732391, 0.017732391, 0.01773239, 1)
metallic = 0.56
[sub_resource type="CylinderMesh" id="CylinderMesh_3jrso"]
material = SubResource("StandardMaterial3D_ryguw")
top_radius = 2.3
bottom_radius = 2.3
height = 0.25
[sub_resource type="SphereShape3D" id="SphereShape3D_crvdt"]
radius = 3.5
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_58fjt"]
transparency = 1
cull_mode = 2
shading_mode = 0
albedo_color = Color(0.2347951, 0.2347951, 0.2347951, 0.060000002)
[sub_resource type="BoxMesh" id="BoxMesh_ijs7n"]
material = SubResource("StandardMaterial3D_58fjt")
size = Vector3(1.4949585, 0.8827637, 0.16409448)
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_a6jrf"]
albedo_color = Color(0.101960786, 0.13725491, 0.19607843, 1)
emission = Color(0, 0.9704087, 1, 1)
emission_energy_multiplier = 0.2
[sub_resource type="BoxMesh" id="BoxMesh_xuqvo"]
material = SubResource("StandardMaterial3D_a6jrf")
size = Vector3(1.2497559, 0.6052246, 0.04)
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_1u8w0"]
albedo_color = Color(0.37187055, 0.11207495, 0.050708726, 1)
[sub_resource type="BoxMesh" id="BoxMesh_d13ii"]
material = SubResource("StandardMaterial3D_1u8w0")
size = Vector3(0.65, 0.12, 0.65)
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_l6148"]
albedo_color = Color(0.88857853, 0.025840001, 0, 1)
[sub_resource type="BoxMesh" id="BoxMesh_ts8u1"]
material = SubResource("StandardMaterial3D_l6148")
size = Vector3(0.65, 0.85, 0.1)
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_wqh1g"]
albedo_color = Color(0.05882353, 0.05882353, 0.05882353, 1)
metallic = 0.51
[sub_resource type="BoxMesh" id="BoxMesh_l6148"]
material = SubResource("StandardMaterial3D_wqh1g")
size = Vector3(1, 0.7, 0.5)
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_kx67c"]
albedo_color = Color(0.101960786, 0.13725491, 0.19607843, 1)
emission_enabled = true
emission = Color(0.101960786, 0.22745098, 0.36078432, 1)
emission_energy_multiplier = 2.0
[sub_resource type="BoxMesh" id="BoxMesh_wqh1g"]
material = SubResource("StandardMaterial3D_kx67c")
size = Vector3(0.35, 0.25, 0.02)
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_r6cyv"]
albedo_color = Color(0.16470589, 0.16470589, 0.16470589, 1)
[sub_resource type="BoxMesh" id="BoxMesh_kx67c"]
material = SubResource("StandardMaterial3D_r6cyv")
size = Vector3(0.15, 0.08, 0.02)
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_omqyl"]
albedo_color = Color(0.039215688, 0.0627451, 0.09411765, 1)
emission_enabled = true
emission = Color(0.101960786, 0.22745098, 0.36078432, 1)
emission_energy_multiplier = 2.0
[sub_resource type="BoxMesh" id="BoxMesh_52c6f"]
material = SubResource("StandardMaterial3D_omqyl")
size = Vector3(0.24501038, 0.20367628, 0.01890625)
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_0odxb"]
albedo_color = Color(0.07058824, 0.07058824, 0.07058824, 1)
[sub_resource type="BoxMesh" id="BoxMesh_r6cyv"]
material = SubResource("StandardMaterial3D_0odxb")
size = Vector3(0.08, 2.1133926, 3.2745347)
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_d13ii"]
albedo_color = Color(0.07058824, 0.07058824, 0.07058824, 1)
[sub_resource type="BoxMesh" id="BoxMesh_4yprg"]
material = SubResource("StandardMaterial3D_d13ii")
size = Vector3(2.7717957, 0.04, 3.2841797)
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_52c6f"]
albedo_color = Color(0.07058824, 0.07058824, 0.07058824, 1)
[sub_resource type="BoxMesh" id="BoxMesh_o0dcp"]
material = SubResource("StandardMaterial3D_52c6f")
size = Vector3(1.187207, 0.06, 0.35)
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_p2ucw"]
albedo_color = Color(0.05882353, 0.05882353, 0.05882353, 1)
[sub_resource type="BoxMesh" id="BoxMesh_omqyl"]
material = SubResource("StandardMaterial3D_p2ucw")
size = Vector3(2.9555702, 0.75, 0.08)
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_ucmdv"]
albedo_color = Color(0.05882353, 0.05882353, 0.05882353, 1)
[sub_resource type="BoxMesh" id="BoxMesh_p2ucw"]
material = SubResource("StandardMaterial3D_ucmdv")
size = Vector3(2.9560547, 0.7133789, 0.08)
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_seu75"]
albedo_color = Color(0.05882353, 0.05882353, 0.05882353, 1)
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_81jjf"]
albedo_color = Color(0.05882353, 0.05882353, 0.05882353, 1)
[sub_resource type="BoxMesh" id="BoxMesh_ucmdv"]
material = SubResource("StandardMaterial3D_81jjf")
size = Vector3(0.65, 0.05, 3.2439454)
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_ijs7n"]
albedo_color = Color(0.05882353, 0.05882353, 0.05882353, 1)
[sub_resource type="BoxMesh" id="BoxMesh_81jjf"]
material = SubResource("StandardMaterial3D_ijs7n")
size = Vector3(0.64851075, 0.05, 3.2384765)
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_nei3f"]
albedo_color = Color(0.05882353, 0.05882353, 0.05882353, 1)
[node name="EscapeCapsule" type="CharacterBody3D" unique_id=900802887 groups=["interactable"]]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.9409914, -1.1106515, 0.90658)
script = ExtResource("1_r50ee")
[node name="CollisionShape3D" type="CollisionShape3D" parent="." unique_id=640959005]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.12550688, 0)
shape = SubResource("CylinderShape3D_j65qs")
[node name="Body" type="MeshInstance3D" parent="." unique_id=683390934]
mesh = SubResource("CylinderMesh_18y2q")
[node name="ExternalView" type="SubViewport" parent="Body" unique_id=1265488610]
handle_input_locally = false
size = Vector2i(3840, 2160)
render_target_update_mode = 4
[node name="Camera3D" type="Camera3D" parent="Body/ExternalView" unique_id=698867349]
transform = Transform3D(1, 0, 0, 0, -4.371139e-08, -1, 0, 1, -4.371139e-08, 18.911898, 5.1233277, -0.039017588)
visible = false
fov = 72.0
far = 1000000.0
[node name="HeatShield" type="MeshInstance3D" parent="." unique_id=2080285390]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1.9, 0)
mesh = SubResource("CylinderMesh_3jrso")
[node name="InteractionArea" type="Area3D" parent="." unique_id=1761123778]
[node name="CollisionShape3D" type="CollisionShape3D" parent="InteractionArea" unique_id=1229487990]
shape = SubResource("SphereShape3D_crvdt")
[node name="ThirdPersonCamera" type="Camera3D" parent="." unique_id=284479039]
transform = Transform3D(1, 0, 0, 0, -4.371139e-08, -1, 0, 1, -4.371139e-08, 0, -9.5, 3.5)
far = 1000000.0
[node name="Cockpit" type="Node3D" parent="." unique_id=1933795690]
transform = Transform3D(-1, 8.742278e-08, 3.821371e-15, 0, -4.371139e-08, 1, 8.742278e-08, 1, 4.371139e-08, 0, -0.94330907, -0.62695575)
[node name="WindowGlass" type="MeshInstance3D" parent="Cockpit" unique_id=99141125]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.0015087128, 1.5509896, 2.2775838)
mesh = SubResource("BoxMesh_ijs7n")
[node name="HudShape" type="MeshInstance3D" parent="Cockpit" unique_id=1572026781]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.0777357, 1.8649361)
visible = false
mesh = SubResource("BoxMesh_xuqvo")
[node name="CockpitLight" type="OmniLight3D" parent="Cockpit" unique_id=1492843635]
transform = Transform3D(-1, 0, 8.742278e-08, 8.742278e-08, -4.371139e-08, 1, 3.821371e-15, 1, 4.371139e-08, 0, 2.1579213, 0.00050091743)
light_color = Color(1, 0.89411765, 0.76862746, 1)
omni_range = 3.5
[node name="CameraPivot" type="Node3D" parent="Cockpit" unique_id=1263006067]
transform = Transform3D(-1, 0, 8.742278e-08, 0, 1, 0, -8.742278e-08, 0, -1, 0, 1.4656192, -0.07458353)
[node name="CapsuleCamera" type="Camera3D" parent="Cockpit/CameraPivot" unique_id=1044956475]
transform = Transform3D(1, 0, -3.2840569e-15, 0, 1, 0, -3.2840569e-15, 0, 1, 0, -0.21693517, -0.4030409)
far = 1000000.0
[node name="Seat" type="MeshInstance3D" parent="Cockpit" unique_id=123094182]
mesh = SubResource("BoxMesh_d13ii")
[node name="SeatBack" type="MeshInstance3D" parent="Cockpit" unique_id=1553533167]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.38205957, -0.36825216)
mesh = SubResource("BoxMesh_ts8u1")
[node name="MainPanel" type="MeshInstance3D" parent="Cockpit" unique_id=2127997099]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.42596802, 1.6161394)
mesh = SubResource("BoxMesh_l6148")
[node name="GlassCockpitPanel" type="MeshInstance3D" parent="Cockpit/MainPanel" unique_id=56681667]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.16014825, -0.25493002)
mesh = SubResource("BoxMesh_wqh1g")
[node name="LeftInstrument" type="MeshInstance3D" parent="Cockpit/MainPanel" unique_id=944149313]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.294096, 0.21341178, -0.25256205)
mesh = SubResource("BoxMesh_kx67c")
[node name="RightInstrument" type="MeshInstance3D" parent="Cockpit/MainPanel" unique_id=1061352713]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.294, 0.213, -0.253)
mesh = SubResource("BoxMesh_kx67c")
[node name="ForwardDisplay" type="MeshInstance3D" parent="Cockpit/MainPanel" unique_id=1977279423]
transform = Transform3D(0.9999994, -5.728489e-05, -0.0011173013, 5.5921435e-05, 0.99999917, -0.0012259485, 0.0011173704, 0.0012257855, 0.9999986, 0.32665062, 0.049695313, -0.25658345)
mesh = SubResource("BoxMesh_52c6f")
[node name="LeftWall" type="MeshInstance3D" parent="Cockpit" unique_id=1514749488]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.4201202, 0.6709095, 0.801975)
mesh = SubResource("BoxMesh_r6cyv")
[node name="RightWall" type="MeshInstance3D" parent="Cockpit" unique_id=1764263004]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.4199867, 0.67109835, 0.79347587)
mesh = SubResource("BoxMesh_r6cyv")
[node name="Floor" type="MeshInstance3D" parent="Cockpit" unique_id=1998677292]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.0061683655, -0.25959706, 0.80126953)
mesh = SubResource("BoxMesh_4yprg")
[node name="OverheadConsole" type="MeshInstance3D" parent="Cockpit" unique_id=976403028]
transform = Transform3D(-4.371139e-08, 0, -1, 0, 1, 0, 1, 0, -4.371139e-08, 0, 2.2589908, 0.95627284)
mesh = SubResource("BoxMesh_o0dcp")
[node name="ForwardBulkhead" type="MeshInstance3D" parent="Cockpit" unique_id=1582033665]
transform = Transform3D(1, -6.905431e-09, -3.4056352e-08, -6.905438e-09, 0.92101103, -0.38953644, 3.4054356e-08, 0.38953644, 0.92101103, -0.0020980835, 0.10092795, 2.3168466)
visible = false
mesh = SubResource("BoxMesh_omqyl")
[node name="ForwardBulkhead2" type="MeshInstance3D" parent="Cockpit/ForwardBulkhead" unique_id=1004286348]
transform = Transform3D(1, -6.9062125e-09, 3.4056193e-08, -6.905424e-09, 0.9210111, 0.38953647, -3.405436e-08, -0.38953647, 0.9210111, 0.018800735, 0.70290273, -0.13796377)
mesh = SubResource("BoxMesh_omqyl")
[node name="MeshInstance3D" type="MeshInstance3D" parent="Cockpit/ForwardBulkhead" unique_id=411181651]
transform = Transform3D(1, -7.2910282e-09, 3.4950116e-08, -7.2894153e-09, 0.91661024, 0.39978403, -3.4950364e-08, -0.39978403, 0.91661024, 0.021972656, 1.129911, -0.3276949)
mesh = SubResource("BoxMesh_p2ucw")
[node name="FrontBulkhead" type="CSGCombiner3D" parent="Cockpit/ForwardBulkhead" unique_id=1462779310]
transform = Transform3D(1, -6.9062196e-09, 3.40562e-08, -6.905424e-09, 0.92101115, 0.3895365, -3.405436e-08, -0.3895365, 0.92101115, 0.0020980835, -0.0909484, 0.044061184)
visible = false
[node name="BulkheadShape" type="CSGPolygon3D" parent="Cockpit/ForwardBulkhead/FrontBulkhead" unique_id=991532318]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.9277502, 0.22244406)
polygon = PackedVector2Array(-1.55, -0.345, 1.55, -0.345, 0.72924423, 0.34169006, -0.75127983, 0.3621254)
depth = 0.12
material = SubResource("StandardMaterial3D_seu75")
[node name="RoofLeft" type="MeshInstance3D" parent="Cockpit" unique_id=1535690315]
transform = Transform3D(0.7071067, 0.7071067, 0, -0.7071067, 0.7071067, 0, 0, 0, 1, 1.1796818, 1.8760827, 0.79144645)
mesh = SubResource("BoxMesh_ucmdv")
[node name="RoofLeft1" type="MeshInstance3D" parent="Cockpit/RoofLeft" unique_id=1785270765]
transform = Transform3D(0.8763269, -0.4817174, 9.8520925e-09, 0.4817174, 0.8763269, 7.3968387e-09, -1.2196834e-08, -1.7361046e-09, 1, -0.6168623, -0.15812302, 0.005322695)
mesh = SubResource("BoxMesh_ucmdv")
[node name="RoofRight" type="MeshInstance3D" parent="Cockpit" unique_id=10541876]
transform = Transform3D(0.7071067, -0.7071067, 0, 0.7071067, 0.7071067, 0, 0, 0, 1, -1.18, 1.876, 0.791)
mesh = SubResource("BoxMesh_ucmdv")
[node name="RoofRight1" type="MeshInstance3D" parent="Cockpit/RoofRight" unique_id=597720853]
transform = Transform3D(0.87630665, 0.4817537, 0, -0.4817537, 0.87630665, 0, 3.543832e-13, 0, 1, 0.6105108, -0.15750027, -0.0017383099)
mesh = SubResource("BoxMesh_81jjf")
[node name="RoofTop" type="MeshInstance3D" parent="Cockpit" unique_id=974546659]
transform = Transform3D(0.9999999, 0, 0, 0, 0.9999999, 0, 0, 0, 1, -0.00787735, 2.2835252, 0.79144645)
mesh = SubResource("BoxMesh_ucmdv")
[node name="ForwardBulkhead2" type="CSGCombiner3D" parent="Cockpit" unique_id=1803926178]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.14711916, 2.8341548)
[node name="BulkTop" type="CSGPolygon3D" parent="Cockpit/ForwardBulkhead2" unique_id=1704103664]
transform = Transform3D(1, -1.4087291e-09, 1.562843e-08, -1.4074928e-09, 0.9838952, 0.17874739, -1.5626552e-08, -0.17874739, 0.9838952, 0.0020980835, 1.7711809, -0.50199556)
polygon = PackedVector2Array(-1.55, -0.345, 1.55, -0.345, 0.72924423, 0.34169006, -0.75127983, 0.3621254)
depth = 0.12
material = SubResource("StandardMaterial3D_seu75")
[node name="BulkBottom" type="CSGBox3D" parent="Cockpit/ForwardBulkhead2" unique_id=1217332907]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.0018692017, 0.49510977, -0.49700785)
size = Vector3(2.788086, 1.8628662, 0.08208008)
material = SubResource("StandardMaterial3D_nei3f")
[node name="WindowCutout" type="CSGBox3D" parent="Cockpit/ForwardBulkhead2" unique_id=1392835612]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.4177693, -0.5765586)
operation = 2
size = Vector3(1.5, 0.89470214, 0.2836914)
+234453
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+67
View File
@@ -0,0 +1,67 @@
[gd_scene format=3 uid="uid://pno8hiqhq6xi"]
[ext_resource type="Script" uid="uid://cb6r3wpwg73jg" path="res://Scenes/Scripts/main_menu.gd" id="1_06t4h"]
[sub_resource type="SystemFont" id="SystemFont_yrfit"]
font_names = PackedStringArray("Bahnschrift")
[sub_resource type="LabelSettings" id="LabelSettings_exgid"]
font = SubResource("SystemFont_yrfit")
font_size = 72
[node name="MainMenu" type="Control" unique_id=1053850081]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_06t4h")
[node name="Background" type="ColorRect" parent="." unique_id=1984614366]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
color = Color(0.043137256, 0.05490196, 0.078431375, 1)
[node name="CenterRoot" type="CenterContainer" parent="." unique_id=592913464]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="MenuColumn" type="VBoxContainer" parent="CenterRoot" unique_id=2068598455]
layout_mode = 2
theme_override_constants/separation = 16
[node name="Title" type="Label" parent="CenterRoot/MenuColumn" unique_id=23462532]
custom_minimum_size = Vector2(500, 90)
custom_maximum_size = Vector2(800, 120)
layout_mode = 2
text = "Brachistochrone"
label_settings = SubResource("LabelSettings_exgid")
horizontal_alignment = 1
vertical_alignment = 1
[node name="NewGameButton" type="Button" parent="CenterRoot/MenuColumn" unique_id=213011095]
custom_minimum_size = Vector2(220, 0)
layout_mode = 2
size_flags_horizontal = 4
text = "New Game"
[node name="ContinueButton" type="Button" parent="CenterRoot/MenuColumn" unique_id=1113818523]
custom_minimum_size = Vector2(220, 0)
layout_mode = 2
size_flags_horizontal = 4
text = "Continue"
[node name="QuitButton" type="Button" parent="CenterRoot/MenuColumn" unique_id=1893640044]
custom_minimum_size = Vector2(220, 0)
layout_mode = 2
size_flags_horizontal = 4
text = "Quit"
BIN
View File
Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More