mirror of
https://github.com/jcreek/CosmicClash.git
synced 2026-09-13 02:42:03 +00:00
feat: add Nebula and Asteroid Field arenas
Introduce arena_02 (Nebula) and arena_03 (Asteroid Field) alongside arena_01, listed in a new ArenaRegistry (scripts/arena_registry.gd) as the single source of truth for available arenas. Free Play lets the player pick an arena from the main menu; Match/Spectate each pick one at random per session; Training keeps its own fixed arena_01. Nebula gets an RL-style visual treatment: a near-invisible glass boundary material shared by all arenas, a baked equirect nebula sky texture, a drifting-dust particle system, and a Blender-modeled station/debris/planet decoration set. GameMode gains a _get_arena_scene_path() hook so modes can instantiate their arena in code instead of hardcoding it in the scene.
This commit is contained in:
Binary file not shown.
@@ -0,0 +1,63 @@
|
||||
[remap]
|
||||
|
||||
importer="scene"
|
||||
importer_version=1
|
||||
type="PackedScene"
|
||||
uid="uid://d2mrvrt1h305x"
|
||||
path="res://.godot/imported/nebula_decoration.blend-2f6fe244eedad258eac5faa9b1684142.scn"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/blender_models/nebula_decoration.blend"
|
||||
dest_files=["res://.godot/imported/nebula_decoration.blend-2f6fe244eedad258eac5faa9b1684142.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={}
|
||||
blender/nodes/visible=0
|
||||
blender/nodes/active_collection_only=false
|
||||
blender/nodes/punctual_lights=true
|
||||
blender/nodes/cameras=true
|
||||
blender/nodes/custom_properties=true
|
||||
blender/nodes/modifiers=1
|
||||
blender/meshes/vertex_colors=1
|
||||
blender/meshes/uvs=true
|
||||
blender/meshes/normals=true
|
||||
blender/meshes/export_geometry_nodes_instances=false
|
||||
blender/meshes/gpu_instances=false
|
||||
blender/meshes/tangents=true
|
||||
blender/meshes/skins=2
|
||||
blender/meshes/export_bones_deforming_mesh_only=false
|
||||
blender/materials/unpack_enabled=true
|
||||
blender/materials/export_materials=1
|
||||
blender/animation/limit_playback=true
|
||||
blender/animation/always_sample=true
|
||||
blender/animation/group_tracks=true
|
||||
gltf/naming_version=2
|
||||
gltf/texture_map_mode=1
|
||||
Binary file not shown.
@@ -0,0 +1,45 @@
|
||||
[remap]
|
||||
|
||||
importer="scene"
|
||||
importer_version=1
|
||||
type="PackedScene"
|
||||
uid="uid://fc85v6374c1"
|
||||
path="res://.godot/imported/nebula_debris.glb-39af77a17c0998b5b73172577d906cb9.scn"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/models/nebula_debris.glb"
|
||||
dest_files=["res://.godot/imported/nebula_debris.glb-39af77a17c0998b5b73172577d906cb9.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
|
||||
Binary file not shown.
@@ -0,0 +1,45 @@
|
||||
[remap]
|
||||
|
||||
importer="scene"
|
||||
importer_version=1
|
||||
type="PackedScene"
|
||||
uid="uid://bpfwv7fse77wk"
|
||||
path="res://.godot/imported/nebula_planet.glb-2431590907ff85cf1057e7d6ad614ed7.scn"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/models/nebula_planet.glb"
|
||||
dest_files=["res://.godot/imported/nebula_planet.glb-2431590907ff85cf1057e7d6ad614ed7.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
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.2 MiB |
@@ -0,0 +1,43 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://cr3feyv7yldjc"
|
||||
path="res://.godot/imported/nebula_planet_planet_surface.png-4b68cca75d2d22d25510c7eb277c0b85.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
generator_parameters={
|
||||
"md5": "44a2e26010b529339e264deecde957e0"
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/models/nebula_planet_planet_surface.png"
|
||||
dest_files=["res://.godot/imported/nebula_planet_planet_surface.png-4b68cca75d2d22d25510c7eb277c0b85.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
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=1
|
||||
Binary file not shown.
@@ -0,0 +1,45 @@
|
||||
[remap]
|
||||
|
||||
importer="scene"
|
||||
importer_version=1
|
||||
type="PackedScene"
|
||||
uid="uid://dn8tj3iw0io7e"
|
||||
path="res://.godot/imported/nebula_station.glb-fa9a6dd87ae3789d04205b52215e2e76.scn"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/models/nebula_station.glb"
|
||||
dest_files=["res://.godot/imported/nebula_station.glb-fa9a6dd87ae3789d04205b52215e2e76.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
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
@@ -0,0 +1,40 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://damajpvo00prm"
|
||||
path="res://.godot/imported/particle_glow.png-e6c07ae4c700896e29ebe96adf51fa5c.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/textures/particle_glow.png"
|
||||
dest_files=["res://.godot/imported/particle_glow.png-e6c07ae4c700896e29ebe96adf51fa5c.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
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=false
|
||||
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=1
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.2 MiB |
@@ -0,0 +1,40 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://bxsadfd04v6r2"
|
||||
path="res://.godot/imported/planet_surface.png-d3aaf8310508e4c85b26a3d093bcf9c8.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/textures/planet_surface.png"
|
||||
dest_files=["res://.godot/imported/planet_surface.png-d3aaf8310508e4c85b26a3d093bcf9c8.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
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=false
|
||||
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=1
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 3.9 MiB |
@@ -0,0 +1,40 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://dc445qysyxwwv"
|
||||
path="res://.godot/imported/sky_nebula.png-70f974ab520aaa5206eef67a936b662e.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/textures/sky_nebula.png"
|
||||
dest_files=["res://.godot/imported/sky_nebula.png-70f974ab520aaa5206eef67a936b662e.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
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=false
|
||||
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=1
|
||||
@@ -10,7 +10,7 @@ roughness = 0.6
|
||||
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_field"]
|
||||
transparency = 1
|
||||
shading_mode = 0
|
||||
albedo_color = Color(0, 0.368627, 1, 0.08)
|
||||
albedo_color = Color(0.6, 0.75, 1, 0.035)
|
||||
|
||||
[sub_resource type="BoxMesh" id="BoxMesh_floor"]
|
||||
material = SubResource("StandardMaterial3D_floor")
|
||||
|
||||
@@ -118,4 +118,5 @@ common/physics_interpolation=true
|
||||
|
||||
[autoload]
|
||||
|
||||
|
||||
GameSettings="*res://scripts/game_settings.gd"
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
[gd_scene load_steps=15 format=3]
|
||||
|
||||
[ext_resource type="Script" path="res://scripts/arena.gd" id="1_iywne"]
|
||||
[ext_resource type="PackedScene" path="res://objects/arena_boundary.tscn" id="2_bndry"]
|
||||
[ext_resource type="PackedScene" uid="uid://cofdcxo5170rs" path="res://objects/goal.tscn" id="6_p57ef"]
|
||||
[ext_resource type="Texture2D" path="res://assets/textures/sky_nebula.png" id="7_nebula"]
|
||||
[ext_resource type="PackedScene" path="res://assets/models/nebula_station.glb" id="8_station"]
|
||||
[ext_resource type="PackedScene" path="res://assets/models/nebula_debris.glb" id="9_debris"]
|
||||
[ext_resource type="Texture2D" path="res://assets/textures/particle_glow.png" id="10_dust"]
|
||||
[ext_resource type="PackedScene" path="res://assets/models/nebula_planet.glb" id="11_planet"]
|
||||
|
||||
[sub_resource type="PanoramaSkyMaterial" id="PanoramaSkyMaterial_nebula"]
|
||||
panorama = ExtResource("7_nebula")
|
||||
|
||||
[sub_resource type="Sky" id="Sky_nebula"]
|
||||
sky_material = SubResource("PanoramaSkyMaterial_nebula")
|
||||
|
||||
[sub_resource type="Environment" id="Environment_nebula"]
|
||||
background_mode = 2
|
||||
sky = SubResource("Sky_nebula")
|
||||
ambient_light_source = 2
|
||||
ambient_light_color = Color(0.65, 0.35, 0.75, 1)
|
||||
ambient_light_energy = 0.45
|
||||
|
||||
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_dust"]
|
||||
transparency = 1
|
||||
shading_mode = 0
|
||||
billboard_mode = 1
|
||||
vertex_color_use_as_albedo = true
|
||||
albedo_color = Color(1, 0.75, 0.9, 1)
|
||||
albedo_texture = ExtResource("10_dust")
|
||||
emission_enabled = true
|
||||
emission = Color(1, 0.6, 0.85, 1)
|
||||
emission_energy_multiplier = 2.5
|
||||
|
||||
[sub_resource type="QuadMesh" id="QuadMesh_dust"]
|
||||
material = SubResource("StandardMaterial3D_dust")
|
||||
size = Vector2(0.4, 0.4)
|
||||
|
||||
[sub_resource type="Gradient" id="Gradient_dust"]
|
||||
offsets = PackedFloat32Array(0, 0.15, 0.85, 1)
|
||||
colors = PackedColorArray(1, 1, 1, 0, 1, 1, 1, 0.55, 1, 1, 1, 0.55, 1, 1, 1, 0)
|
||||
|
||||
[sub_resource type="GradientTexture1D" id="GradientTexture1D_dust"]
|
||||
gradient = SubResource("Gradient_dust")
|
||||
|
||||
[sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_dust"]
|
||||
emission_shape = 3
|
||||
emission_box_extents = Vector3(26, 11, 28)
|
||||
direction = Vector3(0, 1, 0)
|
||||
spread = 180.0
|
||||
initial_velocity_min = 0.1
|
||||
initial_velocity_max = 0.45
|
||||
gravity = Vector3(0, 0, 0)
|
||||
turbulence_enabled = true
|
||||
turbulence_noise_strength = 0.7
|
||||
turbulence_noise_scale = 0.6
|
||||
turbulence_influence_min = 0.35
|
||||
turbulence_influence_max = 0.65
|
||||
scale_min = 0.5
|
||||
scale_max = 1.6
|
||||
color_ramp = SubResource("GradientTexture1D_dust")
|
||||
|
||||
[node name="Arena" type="Node3D"]
|
||||
script = ExtResource("1_iywne")
|
||||
|
||||
[node name="Boundary" parent="." instance=ExtResource("2_bndry")]
|
||||
|
||||
[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."]
|
||||
transform = Transform3D(0.866025, -0.383022, 0.321394, 0, 0.642788, 0.766044, -0.5, -0.663414, 0.55667, 0, 11, 0)
|
||||
light_color = Color(0.85, 0.75, 1, 1)
|
||||
shadow_enabled = true
|
||||
|
||||
[node name="WorldEnvironment" type="WorldEnvironment" parent="."]
|
||||
environment = SubResource("Environment_nebula")
|
||||
|
||||
[node name="GoalTeam0" parent="." instance=ExtResource("6_p57ef")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.79, 18)
|
||||
|
||||
[node name="GoalTeam1" parent="." instance=ExtResource("6_p57ef")]
|
||||
transform = Transform3D(-1, 0, 0, 0, 1, 0, 0, 0, -1, 0, 0.79, -18)
|
||||
team = 1
|
||||
|
||||
[node name="BallSpawn" type="Marker3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2, 0)
|
||||
|
||||
[node name="SpawnsTeam0" type="Node3D" parent="."]
|
||||
|
||||
[node name="Spawn1" type="Marker3D" parent="SpawnsTeam0"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.8, 13.5)
|
||||
|
||||
[node name="SpawnsTeam1" type="Node3D" parent="."]
|
||||
|
||||
[node name="Spawn1" type="Marker3D" parent="SpawnsTeam1"]
|
||||
transform = Transform3D(-1, 0, 0, 0, 1, 0, 0, 0, -1, 0, 2.8, -13.5)
|
||||
|
||||
[node name="NebulaDust" type="GPUParticles3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 5, 0)
|
||||
amount = 500
|
||||
lifetime = 22.0
|
||||
preprocess = 8.0
|
||||
randomness = 1.0
|
||||
visibility_aabb = AABB(-30, -14, -32, 60, 28, 64)
|
||||
process_material = SubResource("ParticleProcessMaterial_dust")
|
||||
draw_pass_1 = SubResource("QuadMesh_dust")
|
||||
|
||||
[node name="Decoration" type="Node3D" parent="."]
|
||||
|
||||
[node name="NebulaStationA" parent="Decoration" instance=ExtResource("8_station")]
|
||||
transform = Transform3D(1.8, 0, 0, 0, 1.8, 0, 0, 0, 1.8, 28, 5, -6)
|
||||
rotation = Vector3(0, -0.436332, 0)
|
||||
|
||||
[node name="NebulaDebrisA" parent="Decoration" instance=ExtResource("9_debris")]
|
||||
transform = Transform3D(1.2, 0, 0, 0, 1.2, 0, 0, 0, 1.2, -22, 9, 11)
|
||||
rotation = Vector3(0.261799, 0.698132, 0.087266)
|
||||
|
||||
[node name="NebulaDebrisB" parent="Decoration" instance=ExtResource("9_debris")]
|
||||
transform = Transform3D(0.8, 0, 0, 0, 0.8, 0, 0, 0, 0.8, 34, 3, 15)
|
||||
rotation = Vector3(-0.174533, 1.919862, 0.349066)
|
||||
|
||||
[node name="NebulaDebrisC" parent="Decoration" instance=ExtResource("9_debris")]
|
||||
transform = Transform3D(1.5, 0, 0, 0, 1.5, 0, 0, 0, 1.5, -30, 11, -21)
|
||||
rotation = Vector3(0.087266, -1.047198, -0.261799)
|
||||
|
||||
[node name="NebulaStationB" parent="Decoration" instance=ExtResource("8_station")]
|
||||
transform = Transform3D(1.5, 0, 0, 0, 1.5, 0, 0, 0, 1.5, -32, 7, 9)
|
||||
rotation = Vector3(0.05, 1.134464, -0.02)
|
||||
|
||||
[node name="NebulaStationC" parent="Decoration" instance=ExtResource("8_station")]
|
||||
transform = Transform3D(1.3, 0, 0, 0, 1.3, 0, 0, 0, 1.3, 9, 8, 42)
|
||||
rotation = Vector3(-0.03, 2.740167, 0.06)
|
||||
|
||||
[node name="NebulaDebrisD" parent="Decoration" instance=ExtResource("9_debris")]
|
||||
transform = Transform3D(1.0, 0, 0, 0, 1.0, 0, 0, 0, 1.0, 13, 15, -35)
|
||||
rotation = Vector3(0.4, 1.3, -0.2)
|
||||
|
||||
[node name="NebulaDebrisE" parent="Decoration" instance=ExtResource("9_debris")]
|
||||
transform = Transform3D(0.9, 0, 0, 0, 0.9, 0, 0, 0, 0.9, -11, 4, 33)
|
||||
rotation = Vector3(-0.3, -0.9, 0.15)
|
||||
|
||||
[node name="NebulaPlanet" parent="Decoration" instance=ExtResource("11_planet")]
|
||||
transform = Transform3D(30, 0, 0, 0, 30, 0, 0, 0, 30, -55, 38, -80)
|
||||
@@ -0,0 +1,54 @@
|
||||
[gd_scene load_steps=6 format=3]
|
||||
|
||||
[ext_resource type="Script" path="res://scripts/arena.gd" id="1_iywne"]
|
||||
[ext_resource type="PackedScene" path="res://objects/arena_boundary.tscn" id="2_bndry"]
|
||||
[ext_resource type="PackedScene" uid="uid://cofdcxo5170rs" path="res://objects/goal.tscn" id="6_p57ef"]
|
||||
[ext_resource type="Shader" path="res://shaders/sky_asteroid_field.gdshader" id="7_asteroid"]
|
||||
|
||||
[sub_resource type="ShaderMaterial" id="ShaderMaterial_asteroid"]
|
||||
shader = ExtResource("7_asteroid")
|
||||
|
||||
[sub_resource type="Sky" id="Sky_asteroid"]
|
||||
sky_material = SubResource("ShaderMaterial_asteroid")
|
||||
|
||||
[sub_resource type="Environment" id="Environment_asteroid"]
|
||||
background_mode = 2
|
||||
sky = SubResource("Sky_asteroid")
|
||||
ambient_light_source = 2
|
||||
ambient_light_color = Color(0.6, 0.45, 0.3, 1)
|
||||
ambient_light_energy = 0.3
|
||||
|
||||
[node name="Arena" type="Node3D"]
|
||||
script = ExtResource("1_iywne")
|
||||
|
||||
[node name="Boundary" parent="." instance=ExtResource("2_bndry")]
|
||||
|
||||
[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."]
|
||||
transform = Transform3D(0.866025, -0.383022, 0.321394, 0, 0.642788, 0.766044, -0.5, -0.663414, 0.55667, 0, 11, 0)
|
||||
light_color = Color(1, 0.85, 0.65, 1)
|
||||
shadow_enabled = true
|
||||
|
||||
[node name="WorldEnvironment" type="WorldEnvironment" parent="."]
|
||||
environment = SubResource("Environment_asteroid")
|
||||
|
||||
[node name="GoalTeam0" parent="." instance=ExtResource("6_p57ef")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.79, 18)
|
||||
|
||||
[node name="GoalTeam1" parent="." instance=ExtResource("6_p57ef")]
|
||||
transform = Transform3D(-1, 0, 0, 0, 1, 0, 0, 0, -1, 0, 0.79, -18)
|
||||
team = 1
|
||||
|
||||
[node name="BallSpawn" type="Marker3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2, 0)
|
||||
|
||||
[node name="SpawnsTeam0" type="Node3D" parent="."]
|
||||
|
||||
[node name="Spawn1" type="Marker3D" parent="SpawnsTeam0"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.8, 13.5)
|
||||
|
||||
[node name="SpawnsTeam1" type="Node3D" parent="."]
|
||||
|
||||
[node name="Spawn1" type="Marker3D" parent="SpawnsTeam1"]
|
||||
transform = Transform3D(-1, 0, 0, 0, 1, 0, 0, 0, -1, 0, 2.8, -13.5)
|
||||
|
||||
[node name="Decoration" type="Node3D" parent="."]
|
||||
@@ -1,12 +1,10 @@
|
||||
[gd_scene load_steps=4 format=3]
|
||||
[gd_scene load_steps=3 format=3]
|
||||
|
||||
[ext_resource type="Script" path="res://scripts/free_play.gd" id="1_fp"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/arena_01.tscn" id="2_fp"]
|
||||
[ext_resource type="PackedScene" uid="uid://c8kak2l3m4n5" path="res://scenes/HUD.tscn" id="3_fp"]
|
||||
|
||||
[node name="FreePlay" type="Node3D"]
|
||||
script = ExtResource("1_fp")
|
||||
|
||||
[node name="Arena" parent="." instance=ExtResource("2_fp")]
|
||||
|
||||
[node name="HUD" parent="." instance=ExtResource("3_fp")]
|
||||
|
||||
@@ -53,6 +53,20 @@ theme_override_font_sizes/font_size = 13
|
||||
text = "Solo practice — no timer, R resets the ball"
|
||||
horizontal_alignment = 1
|
||||
|
||||
[node name="ArenaRow" type="HBoxContainer" parent="CenterContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 10
|
||||
|
||||
[node name="ArenaLabel" type="Label" parent="CenterContainer/VBoxContainer/ArenaRow"]
|
||||
layout_mode = 2
|
||||
text = "Arena"
|
||||
|
||||
[node name="ArenaDropdown" type="OptionButton" parent="CenterContainer/VBoxContainer/ArenaRow"]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(0, 40)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
|
||||
[node name="MatchSeparator" type="HSeparator" parent="CenterContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
[gd_scene load_steps=4 format=3]
|
||||
[gd_scene load_steps=3 format=3]
|
||||
|
||||
[ext_resource type="Script" path="res://scripts/match_mode.gd" id="1_m"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/arena_01.tscn" id="2_m"]
|
||||
[ext_resource type="PackedScene" uid="uid://c8kak2l3m4n5" path="res://scenes/HUD.tscn" id="3_m"]
|
||||
|
||||
[node name="Match" type="Node3D"]
|
||||
script = ExtResource("1_m")
|
||||
bot_model_path = "res://bots/promoted/easy.json"
|
||||
|
||||
[node name="Arena" parent="." instance=ExtResource("2_m")]
|
||||
|
||||
[node name="HUD" parent="." instance=ExtResource("3_m")]
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
[gd_scene load_steps=4 format=3]
|
||||
[gd_scene load_steps=3 format=3]
|
||||
|
||||
[ext_resource type="Script" path="res://scripts/spectate_mode.gd" id="1_s"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/arena_01.tscn" id="2_s"]
|
||||
[ext_resource type="PackedScene" uid="uid://c8kak2l3m4n5" path="res://scenes/HUD.tscn" id="3_s"]
|
||||
|
||||
[node name="Spectate" type="Node3D"]
|
||||
@@ -9,6 +8,5 @@ script = ExtResource("1_s")
|
||||
bot_a_model_path = "res://bots/promoted/easy.json"
|
||||
bot_b_model_path = "res://bots/promoted/easy.json"
|
||||
|
||||
[node name="Arena" parent="." instance=ExtResource("2_s")]
|
||||
|
||||
[node name="HUD" parent="." instance=ExtResource("3_s")]
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
class_name ArenaRegistry
|
||||
|
||||
# Single source of truth for available arenas: the Free Play menu dropdown
|
||||
# lists these, and Match/Spectate pick one at random each session. Training
|
||||
# is exempt — training.tscn keeps its own fixed arena_01 child.
|
||||
const ARENAS := [
|
||||
{"name": "Starfield", "path": "res://scenes/arena_01.tscn"},
|
||||
{"name": "Nebula", "path": "res://scenes/arena_02.tscn"},
|
||||
{"name": "Asteroid Field", "path": "res://scenes/arena_03.tscn"},
|
||||
]
|
||||
|
||||
|
||||
static func random_path() -> String:
|
||||
return ARENAS[randi() % ARENAS.size()]["path"]
|
||||
@@ -0,0 +1 @@
|
||||
uid://orkh5g5828cv
|
||||
@@ -4,6 +4,12 @@ extends GameMode
|
||||
# Rocket League's free play. R resets the ball, Esc returns to the menu.
|
||||
|
||||
|
||||
func _get_arena_scene_path() -> String:
|
||||
if not GameSettings.selected_arena_path.is_empty():
|
||||
return GameSettings.selected_arena_path
|
||||
return ArenaRegistry.ARENAS[0]["path"]
|
||||
|
||||
|
||||
func _start() -> void:
|
||||
spawn_ball()
|
||||
var player_ship := spawn_ship(0, 0, PlayerShipController.new())
|
||||
|
||||
@@ -26,6 +26,11 @@ func _ready():
|
||||
if child is Arena:
|
||||
arena = child
|
||||
break
|
||||
if not arena:
|
||||
var path := _get_arena_scene_path()
|
||||
if not path.is_empty():
|
||||
arena = (load(path) as PackedScene).instantiate()
|
||||
add_child(arena)
|
||||
if not arena:
|
||||
push_error("GameMode: scene has no Arena child")
|
||||
return
|
||||
@@ -34,6 +39,13 @@ func _ready():
|
||||
_start()
|
||||
|
||||
|
||||
# Virtual: subclasses whose scene has no fixed Arena child override this to
|
||||
# pick which arena scene to instantiate in code (see ArenaRegistry). Modes
|
||||
# that keep a fixed Arena child (training.tscn) never call this.
|
||||
func _get_arena_scene_path() -> String:
|
||||
return ""
|
||||
|
||||
|
||||
# Virtual: subclasses spawn their ball/ships/camera here.
|
||||
func _start() -> void:
|
||||
pass
|
||||
|
||||
@@ -21,3 +21,7 @@ var dev_bot_override_path: String = ""
|
||||
# Spectate (bot vs bot) policies chosen in the main menu; empty = mode export.
|
||||
var spectate_bot_a_path: String = ""
|
||||
var spectate_bot_b_path: String = ""
|
||||
|
||||
# Arena chosen in the main menu for Free Play; empty = ArenaRegistry's default.
|
||||
# Match/Spectate ignore this and pick a random arena each session instead.
|
||||
var selected_arena_path: String = ""
|
||||
|
||||
@@ -18,6 +18,7 @@ const DIFFICULTIES := [
|
||||
]
|
||||
|
||||
@onready var difficulty_dropdown: OptionButton = %DifficultyDropdown
|
||||
@onready var arena_dropdown: OptionButton = %ArenaDropdown
|
||||
@onready var dev_section: Control = %DevSection
|
||||
@onready var dev_bot_dropdown: OptionButton = %DevBotDropdown
|
||||
@onready var bot_a_dropdown: OptionButton = %BotADropdown
|
||||
@@ -26,6 +27,7 @@ const DIFFICULTIES := [
|
||||
|
||||
func _ready() -> void:
|
||||
_populate_difficulty_dropdown()
|
||||
_populate_arena_dropdown()
|
||||
dev_section.visible = OS.is_debug_build()
|
||||
if dev_section.visible:
|
||||
var bots := _list_bots()
|
||||
@@ -47,6 +49,19 @@ func _populate_difficulty_dropdown() -> void:
|
||||
difficulty_dropdown.select(selected)
|
||||
|
||||
|
||||
# Free Play only — Match/Spectate pick a random arena in code instead.
|
||||
func _populate_arena_dropdown() -> void:
|
||||
arena_dropdown.clear()
|
||||
for tier in ArenaRegistry.ARENAS:
|
||||
arena_dropdown.add_item(tier["name"])
|
||||
var selected := 0
|
||||
for i in ArenaRegistry.ARENAS.size():
|
||||
if ArenaRegistry.ARENAS[i]["path"] == GameSettings.selected_arena_path:
|
||||
selected = i
|
||||
break
|
||||
arena_dropdown.select(selected)
|
||||
|
||||
|
||||
# Lists bot checkpoints as paths relative to BOTS_DIR, including the
|
||||
# top-level curriculum checkpoints and anything under promoted/.
|
||||
func _list_bots() -> Array[String]:
|
||||
@@ -93,6 +108,8 @@ func _selected_path(dropdown: OptionButton) -> String:
|
||||
|
||||
|
||||
func _on_free_play_pressed() -> void:
|
||||
var chosen: Dictionary = ArenaRegistry.ARENAS[0] if arena_dropdown.selected < 0 else ArenaRegistry.ARENAS[arena_dropdown.selected]
|
||||
GameSettings.selected_arena_path = chosen["path"]
|
||||
get_tree().change_scene_to_file("res://scenes/free_play.tscn")
|
||||
|
||||
|
||||
|
||||
@@ -32,6 +32,10 @@ var match_timer: Timer
|
||||
var _in_overtime := false
|
||||
|
||||
|
||||
func _get_arena_scene_path() -> String:
|
||||
return ArenaRegistry.random_path()
|
||||
|
||||
|
||||
func _start() -> void:
|
||||
spawn_ball()
|
||||
var player_ship := spawn_ship(0, 0, PlayerShipController.new())
|
||||
|
||||
@@ -19,6 +19,10 @@ signal score_changed(score: Dictionary)
|
||||
var score := {0: 0, 1: 0}
|
||||
|
||||
|
||||
func _get_arena_scene_path() -> String:
|
||||
return ArenaRegistry.random_path()
|
||||
|
||||
|
||||
func _start() -> void:
|
||||
spawn_ball()
|
||||
# The main menu's dropdown selections (GameSettings autoload) win over the
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
shader_type sky;
|
||||
|
||||
// Procedural dusty void: dim rocky-belt haze with a warm horizon glow, sparser
|
||||
// stars than arena_01 for a grittier, more enclosed feel.
|
||||
void sky() {
|
||||
vec3 dir = EYEDIR;
|
||||
vec3 col = vec3(0.015, 0.012, 0.01);
|
||||
col += vec3(0.09, 0.05, 0.02) * pow(1.0 - abs(dir.y), 4.0);
|
||||
vec3 cell = floor(dir * 220.0);
|
||||
float h = fract(sin(dot(cell, vec3(12.9898, 78.233, 45.164))) * 43758.5453);
|
||||
if (h > 0.9985) {
|
||||
vec3 in_cell = fract(dir * 220.0) - 0.5;
|
||||
float star = smoothstep(0.35, 0.0, length(in_cell));
|
||||
col += vec3(star * (0.4 + fract(h * 999.0)) * 0.8);
|
||||
}
|
||||
COLOR = col;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
uid://bg7diy2ywqkbd
|
||||
Reference in New Issue
Block a user