Initial commit
This commit is contained in:
@@ -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")
|
||||
@@ -0,0 +1,3 @@
|
||||
[gd_resource type="StandardMaterial3D" format=3 uid="uid://c1mm1y80k6872"]
|
||||
|
||||
[resource]
|
||||
BIN
Binary file not shown.
@@ -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
|
||||
BIN
Binary file not shown.
@@ -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
|
||||
@@ -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")
|
||||
@@ -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.
@@ -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
|
||||
@@ -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.")
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
uid://d2cfgmuwrsr3y
|
||||
@@ -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()
|
||||
@@ -0,0 +1 @@
|
||||
uid://4dys8ga8ap02
|
||||
@@ -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))
|
||||
@@ -0,0 +1 @@
|
||||
uid://di78d53y38p67
|
||||
@@ -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!")
|
||||
@@ -0,0 +1 @@
|
||||
uid://flm6ps54u0c4
|
||||
@@ -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")
|
||||
@@ -0,0 +1 @@
|
||||
uid://cxrxrk0qt15dl
|
||||
@@ -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()
|
||||
@@ -0,0 +1 @@
|
||||
uid://b0oppy8q64xry
|
||||
@@ -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()
|
||||
@@ -0,0 +1 @@
|
||||
uid://cley0rs8im7v3
|
||||
@@ -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()
|
||||
@@ -0,0 +1 @@
|
||||
uid://c5j656olsdtjs
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
uid://ikbkmt7sby7a
|
||||
@@ -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
|
||||
)
|
||||
@@ -0,0 +1 @@
|
||||
uid://1udl42sp42sp
|
||||
@@ -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()
|
||||
@@ -0,0 +1 @@
|
||||
uid://ckl5inm8ugypo
|
||||
@@ -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
|
||||
@@ -0,0 +1 @@
|
||||
uid://b3o7ua8cv55tq
|
||||
@@ -0,0 +1 @@
|
||||
uid://br0vxsoinqwe1
|
||||
@@ -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()
|
||||
@@ -0,0 +1 @@
|
||||
uid://bigf78nt5im5v
|
||||
@@ -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")
|
||||
)
|
||||
@@ -0,0 +1 @@
|
||||
uid://bh5kr1365v1bq
|
||||
@@ -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()
|
||||
@@ -0,0 +1 @@
|
||||
uid://cb6r3wpwg73jg
|
||||
@@ -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()
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
uid://03eo5b1lwlm7
|
||||
@@ -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
|
||||
@@ -0,0 +1 @@
|
||||
uid://db5dujh3xfuky
|
||||
@@ -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()
|
||||
@@ -0,0 +1 @@
|
||||
uid://dc246e7164y2f
|
||||
@@ -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")
|
||||
@@ -0,0 +1 @@
|
||||
uid://soef5g0d1u0a
|
||||
@@ -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()
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
uid://dfqr8db8q1y4b
|
||||
@@ -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
|
||||
@@ -0,0 +1 @@
|
||||
uid://2fx6webb7m8d
|
||||
@@ -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()
|
||||
@@ -0,0 +1 @@
|
||||
uid://cdo20owmglm22
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1 @@
|
||||
uid://bqssr0j8iphme
|
||||
@@ -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()
|
||||
@@ -0,0 +1 @@
|
||||
uid://ch56mng5ltaqf
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
@@ -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")
|
||||
@@ -0,0 +1 @@
|
||||
uid://b1brrhkbw71xg
|
||||
@@ -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()
|
||||
@@ -0,0 +1 @@
|
||||
uid://oljblbitud3n
|
||||
@@ -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()
|
||||
@@ -0,0 +1 @@
|
||||
uid://dobhysl1n6hi1
|
||||
@@ -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)
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
uid://sxr03xjwmthe
|
||||
@@ -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()
|
||||
@@ -0,0 +1 @@
|
||||
uid://d1o7uwk5jbs5j
|
||||
@@ -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
|
||||
@@ -0,0 +1 @@
|
||||
uid://drvd2kgxl2l2s
|
||||
@@ -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")
|
||||
@@ -0,0 +1 @@
|
||||
uid://dnf3scbnf3qvx
|
||||
@@ -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
|
||||
@@ -0,0 +1 @@
|
||||
uid://bbr0judkwyfhb
|
||||
BIN
Binary file not shown.
@@ -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
Binary file not shown.
File diff suppressed because it is too large
Load Diff
BIN
Binary file not shown.
@@ -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
|
||||
@@ -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"
|
||||
@@ -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)
|
||||
@@ -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
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
@@ -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
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user