Clubs access is controlled by ClubCatalog

This commit is contained in:
Rob Kelly 2024-11-11 14:45:47 -07:00
parent 1d86d49c7d
commit 37e3cb2677
24 changed files with 506 additions and 86 deletions

BIN
asset_dev/characters/clubs/clubs.blend (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

View File

@ -15,7 +15,12 @@
"nodes":[
{
"mesh":0,
"name":"Driver"
"name":"Driver",
"translation":[
0,
1.2000000476837158,
0
]
}
],
"materials":[
@ -56,13 +61,13 @@
"componentType":5126,
"count":164,
"max":[
0.6112575531005859,
1.8250000476837158,
0.4176815152168274
0.4176812469959259,
1.9800440073013306,
0.6112575531005859
],
"min":[
-0.05376402288675308,
-1.9800440073013306,
-0.05376391485333443,
-1.8250000476837158,
-0.05376402288675308
],
"type":"VEC3"

Binary file not shown.

View File

@ -15,7 +15,12 @@
"nodes":[
{
"mesh":0,
"name":"Iron"
"name":"Iron",
"translation":[
0,
1.2000000476837158,
0
]
}
],
"materials":[
@ -56,13 +61,13 @@
"componentType":5126,
"count":126,
"max":[
0.5181902050971985,
1.8250000476837158,
0.13040459156036377
0.13040433824062347,
1.8918243646621704,
0.5181902050971985
],
"min":[
-0.05376402288675308,
-1.8918243646621704,
-0.05376391485333443,
-1.8250000476837158,
-0.05376402288675308
],
"type":"VEC3"

Binary file not shown.

View File

@ -0,0 +1,126 @@
{
"asset":{
"generator":"Khronos glTF Blender I/O v4.2.60",
"version":"2.0"
},
"scene":0,
"scenes":[
{
"name":"Scene",
"nodes":[
0
]
}
],
"nodes":[
{
"mesh":0,
"name":"Putter",
"translation":[
0,
1.2000000476837158,
0
]
}
],
"materials":[
{
"doubleSided":true,
"name":"Material",
"pbrMetallicRoughness":{
"baseColorFactor":[
0.800000011920929,
0.800000011920929,
0.800000011920929,
1
],
"metallicFactor":0,
"roughnessFactor":0.5
}
}
],
"meshes":[
{
"name":"Cube.003",
"primitives":[
{
"attributes":{
"POSITION":0,
"NORMAL":1,
"TEXCOORD_0":2
},
"indices":3,
"material":0
}
]
}
],
"accessors":[
{
"bufferView":0,
"componentType":5126,
"count":152,
"max":[
0.07092801481485367,
1.8706790208816528,
0.4318830966949463
],
"min":[
-0.05810827389359474,
-1.8250000476837158,
-0.14764030277729034
],
"type":"VEC3"
},
{
"bufferView":1,
"componentType":5126,
"count":152,
"type":"VEC3"
},
{
"bufferView":2,
"componentType":5126,
"count":152,
"type":"VEC2"
},
{
"bufferView":3,
"componentType":5123,
"count":228,
"type":"SCALAR"
}
],
"bufferViews":[
{
"buffer":0,
"byteLength":1824,
"byteOffset":0,
"target":34962
},
{
"buffer":0,
"byteLength":1824,
"byteOffset":1824,
"target":34962
},
{
"buffer":0,
"byteLength":1216,
"byteOffset":3648,
"target":34962
},
{
"buffer":0,
"byteLength":456,
"byteOffset":4864,
"target":34963
}
],
"buffers":[
{
"byteLength":5320,
"uri":"putter.bin"
}
]
}

View File

@ -0,0 +1,36 @@
[remap]
importer="scene"
importer_version=1
type="PackedScene"
uid="uid://bo41mkkc70fcl"
path="res://.godot/imported/putter.gltf-d47ba94a31e007cbe787ab5368371790.scn"
[deps]
source_file="res://assets/models/clubs/putter.gltf"
dest_files=["res://.godot/imported/putter.gltf-d47ba94a31e007cbe787ab5368371790.scn"]
[params]
nodes/root_type=""
nodes/root_name=""
nodes/apply_root_scale=true
nodes/root_scale=1.0
nodes/import_as_skeleton_bones=false
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=""
_subresources={}
gltf/naming_version=1
gltf/embedded_image_handling=1

Binary file not shown.

View File

@ -0,0 +1,126 @@
{
"asset":{
"generator":"Khronos glTF Blender I/O v4.2.60",
"version":"2.0"
},
"scene":0,
"scenes":[
{
"name":"Scene",
"nodes":[
0
]
}
],
"nodes":[
{
"mesh":0,
"name":"Wedge",
"translation":[
0,
1.2000000476837158,
0
]
}
],
"materials":[
{
"doubleSided":true,
"name":"Material",
"pbrMetallicRoughness":{
"baseColorFactor":[
0.800000011920929,
0.800000011920929,
0.800000011920929,
1
],
"metallicFactor":0,
"roughnessFactor":0.5
}
}
],
"meshes":[
{
"name":"Cube.002",
"primitives":[
{
"attributes":{
"POSITION":0,
"NORMAL":1,
"TEXCOORD_0":2
},
"indices":3,
"material":0
}
]
}
],
"accessors":[
{
"bufferView":0,
"componentType":5126,
"count":180,
"max":[
0.22545579075813293,
1.951971173286438,
0.49008044600486755
],
"min":[
-0.08979124575853348,
-1.8250000476837158,
-0.05376402288675308
],
"type":"VEC3"
},
{
"bufferView":1,
"componentType":5126,
"count":180,
"type":"VEC3"
},
{
"bufferView":2,
"componentType":5126,
"count":180,
"type":"VEC2"
},
{
"bufferView":3,
"componentType":5123,
"count":258,
"type":"SCALAR"
}
],
"bufferViews":[
{
"buffer":0,
"byteLength":2160,
"byteOffset":0,
"target":34962
},
{
"buffer":0,
"byteLength":2160,
"byteOffset":2160,
"target":34962
},
{
"buffer":0,
"byteLength":1440,
"byteOffset":4320,
"target":34962
},
{
"buffer":0,
"byteLength":516,
"byteOffset":5760,
"target":34963
}
],
"buffers":[
{
"byteLength":6276,
"uri":"wedge.bin"
}
]
}

View File

@ -0,0 +1,36 @@
[remap]
importer="scene"
importer_version=1
type="PackedScene"
uid="uid://d4bnvf34xenya"
path="res://.godot/imported/wedge.gltf-0b94d38ac8af3aeedd25f97520851d66.scn"
[deps]
source_file="res://assets/models/clubs/wedge.gltf"
dest_files=["res://.godot/imported/wedge.gltf-0b94d38ac8af3aeedd25f97520851d66.scn"]
[params]
nodes/root_type=""
nodes/root_name=""
nodes/apply_root_scale=true
nodes/root_scale=1.0
nodes/import_as_skeleton_bones=false
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=""
_subresources={}
gltf/naming_version=1
gltf/embedded_image_handling=1

View File

@ -16,6 +16,10 @@ run/main_scene="res://levels/debug_level/debug_level.tscn"
config/features=PackedStringArray("4.3", "Forward Plus")
run/max_fps=60
[autoload]
ClubCatalog="*res://src/equipment/clubs/club_catalog.tscn"
[debug]
gdscript/warnings/untyped_declaration=2

View File

@ -5,6 +5,20 @@ class_name CharacterController extends Node3D
@onready
var animation_state: AnimationNodeStateMachinePlayback = animation_tree["parameters/playback"]
@onready var right_hand_grip: Node3D = %RightHandGrip
## Snap the given node to the character's right hand grip.
## Anything currently held in the right hand will be freed.
## If `node` is null, the character's right hand grip will just be cleared.
func hold_right(node: Node3D = null) -> void:
for c: Node in right_hand_grip.get_children():
c.queue_free()
if node:
right_hand_grip.add_child(node)
node.transform = Transform3D.IDENTITY
func reset() -> void:
animation_state.start("stand_to_idle")

View File

@ -1,9 +1,7 @@
[gd_scene load_steps=20 format=3 uid="uid://1s3gywmoi20e"]
[gd_scene load_steps=18 format=3 uid="uid://1s3gywmoi20e"]
[ext_resource type="PackedScene" uid="uid://ha6jxf4v5845" path="res://assets/models/characters/gfolf_girl/gfolf_girl.gltf" id="1_j80rr"]
[ext_resource type="Script" path="res://src/characters/character_controller.gd" id="2_7o84v"]
[ext_resource type="PackedScene" uid="uid://bfugnkuyflxrd" path="res://src/equipment/clubs/iron.tscn" id="3_fqr7u"]
[ext_resource type="PackedScene" uid="uid://cc5npwiq3m21c" path="res://src/equipment/clubs/driver.tscn" id="4_s7iyi"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_fokhu"]
albedo_color = Color(0.226707, 0.226707, 0.226707, 1)
@ -106,7 +104,7 @@ bones/23/rotation = Quaternion(0.000222673, 0.707107, 0.707107, -0.000222504)
bones/23/scale = Vector3(1, 1, 1)
[node name="BoneAttachment3D" type="BoneAttachment3D" parent="Armature/Skeleton3D" index="6"]
transform = Transform3D(-0.942953, 0.303928, 0.135893, -0.265659, -0.932915, 0.243093, 0.20066, 0.193124, 0.960437, -0.315494, 3.01329, 0.865057)
transform = Transform3D(-0.944824, 0.316851, -0.0831416, -0.325832, -0.935181, 0.138814, -0.0337689, 0.158246, 0.986822, -0.1687, 3.15143, 0.849092)
bone_name = "Hand.R"
bone_idx = 11
@ -114,23 +112,16 @@ bone_idx = 11
unique_name_in_owner = true
transform = Transform3D(0.934826, 0.266239, -0.23498, -0.336326, 0.876157, -0.345298, 0.113948, 0.401823, 0.908599, -0.0340219, 0.535822, -0.0310692)
[node name="DebugClub" type="MeshInstance3D" parent="Armature/Skeleton3D/BoneAttachment3D/RightHandGrip" index="0"]
[node name="ReferenceClub" type="MeshInstance3D" parent="Armature/Skeleton3D/BoneAttachment3D/RightHandGrip" index="0"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.205, 0)
visible = false
mesh = SubResource("BoxMesh_363n0")
skeleton = NodePath("../..")
[node name="MeshInstance3D" type="MeshInstance3D" parent="Armature/Skeleton3D/BoneAttachment3D/RightHandGrip/DebugClub" index="0"]
[node name="MeshInstance3D" type="MeshInstance3D" parent="Armature/Skeleton3D/BoneAttachment3D/RightHandGrip/ReferenceClub" index="0"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.705, 0.3)
mesh = SubResource("BoxMesh_oll6x")
[node name="Iron" parent="Armature/Skeleton3D/BoneAttachment3D/RightHandGrip" index="1" instance=ExtResource("3_fqr7u")]
transform = Transform3D(-7.54979e-08, 8.74228e-08, 1, -8.74228e-08, -1, 8.74228e-08, 1, -8.74228e-08, 7.54979e-08, 0, 1.2, 0)
visible = false
[node name="Driver" parent="Armature/Skeleton3D/BoneAttachment3D/RightHandGrip" index="2" instance=ExtResource("4_s7iyi")]
transform = Transform3D(-7.63685e-08, 8.75443e-08, 1, -8.9407e-08, -1, 8.84756e-08, 1, -1.78814e-07, 7.82311e-08, -7.45058e-09, 1.2, 2.38419e-07)
[node name="AnimationTree" type="AnimationTree" parent="." index="2"]
tree_root = SubResource("AnimationNodeStateMachine_yepp7")
anim_player = NodePath("../AnimationPlayer")

View File

@ -0,0 +1,23 @@
class_name Club extends Node
## Base type for gfolf clubs
enum Type {
NONE,
DRIVER,
IRON,
WEDGE,
PUTTER,
SPECIAL,
}
@export var type: Club.Type
@export var _model: PackedScene
## Global typesafe accessor for club catalog
static var catalog: ClubCatalogType:
get:
return ClubCatalog
func get_model() -> Node3D:
return _model.instantiate() as Node3D if _model else null

View File

@ -0,0 +1,7 @@
class_name ClubCatalogType extends Node
## Provides access to Club equipment
@onready var debug_driver: Club = %"DEBUG Driver"
@onready var debug_iron: Club = %"DEBUG Iron"
@onready var debug_wedge: Club = %"DEBUG Wedge"
@onready var debug_putter: Club = %"DEBUG Putter"

View File

@ -0,0 +1,35 @@
[gd_scene load_steps=7 format=3 uid="uid://f5qw4losi1ag"]
[ext_resource type="Script" path="res://src/equipment/clubs/club_catalog.gd" id="1_omf4k"]
[ext_resource type="Script" path="res://src/equipment/clubs/club.gd" id="2_hl4eh"]
[ext_resource type="PackedScene" uid="uid://dekwor3a7kqio" path="res://assets/models/clubs/driver.gltf" id="3_gocak"]
[ext_resource type="PackedScene" uid="uid://btpn1j6jwv4pr" path="res://assets/models/clubs/iron.gltf" id="4_ile8w"]
[ext_resource type="PackedScene" uid="uid://d4bnvf34xenya" path="res://assets/models/clubs/wedge.gltf" id="5_qa3by"]
[ext_resource type="PackedScene" uid="uid://bo41mkkc70fcl" path="res://assets/models/clubs/putter.gltf" id="6_8bavt"]
[node name="ClubCatalog" type="Node"]
script = ExtResource("1_omf4k")
[node name="DEBUG Driver" type="Node" parent="."]
unique_name_in_owner = true
script = ExtResource("2_hl4eh")
type = 1
_model = ExtResource("3_gocak")
[node name="DEBUG Iron" type="Node" parent="."]
unique_name_in_owner = true
script = ExtResource("2_hl4eh")
type = 2
_model = ExtResource("4_ile8w")
[node name="DEBUG Wedge" type="Node" parent="."]
unique_name_in_owner = true
script = ExtResource("2_hl4eh")
type = 3
_model = ExtResource("5_qa3by")
[node name="DEBUG Putter" type="Node" parent="."]
unique_name_in_owner = true
script = ExtResource("2_hl4eh")
type = 4
_model = ExtResource("6_8bavt")

View File

@ -1,5 +0,0 @@
[gd_scene load_steps=2 format=3 uid="uid://cc5npwiq3m21c"]
[ext_resource type="PackedScene" uid="uid://dekwor3a7kqio" path="res://assets/models/clubs/driver.gltf" id="1_8gkvl"]
[node name="Driver" instance=ExtResource("1_8gkvl")]

View File

@ -1,5 +0,0 @@
[gd_scene load_steps=2 format=3 uid="uid://bfugnkuyflxrd"]
[ext_resource type="PackedScene" uid="uid://btpn1j6jwv4pr" path="res://assets/models/clubs/iron.gltf" id="1_dnro0"]
[node name="Iron" instance=ExtResource("1_dnro0")]

View File

@ -8,14 +8,14 @@ const LABEL_SCALE_TIME := 0.3
const HUB_ROTATION_TIME := 0.2
const CLUB_ROTATION := {
T.Club.DRIVER: 0.0,
T.Club.IRON: -16.0,
T.Club.WEDGE: -32.0,
T.Club.SPECIAL: -48.0,
T.Club.PUTTER: -64.0,
Club.Type.DRIVER: 0.0,
Club.Type.IRON: -16.0,
Club.Type.WEDGE: -32.0,
Club.Type.SPECIAL: -48.0,
Club.Type.PUTTER: -64.0,
}
@export var value: T.Club:
@export var value: Club.Type:
set = _set_value
@onready var club_hub: Control = %ClubHub
@ -27,20 +27,20 @@ const CLUB_ROTATION := {
@onready var putter_label: Label = %PutterLabel
func _get_club_label(club: T.Club) -> Label:
func _get_club_label(club: Club.Type) -> Label:
match club:
T.Club.DRIVER:
Club.Type.DRIVER:
return driver_label
T.Club.IRON:
Club.Type.IRON:
return iron_label
T.Club.WEDGE:
Club.Type.WEDGE:
return wedge_label
T.Club.SPECIAL:
Club.Type.SPECIAL:
return special_label
T.Club.PUTTER:
Club.Type.PUTTER:
return putter_label
assert(false, "Unknown club %d" % club)
return
print_debug("Unknown club: ", club)
return null
func _reset_label_scale() -> void:
@ -48,22 +48,24 @@ func _reset_label_scale() -> void:
c.scale = UNSELECTED_SCALE
func _set_value(new_value: T.Club) -> void:
#_reset_label_scale()
var old_label := _get_club_label(value)
var new_label := _get_club_label(new_value)
var hub_rotation: float = CLUB_ROTATION[new_value]
func _set_value(new_value: Club.Type) -> void:
var tween := get_tree().create_tween()
tween.set_parallel()
tween.tween_property(old_label, "scale", UNSELECTED_SCALE, LABEL_SCALE_TIME).set_trans(
Tween.TRANS_SINE
)
tween.tween_property(new_label, "scale", SELECTED_SCALE, LABEL_SCALE_TIME).set_trans(
Tween.TRANS_SINE
)
tween.tween_property(club_hub, "rotation_degrees", hub_rotation, HUB_ROTATION_TIME).set_trans(
Tween.TRANS_QUAD
)
var old_label := _get_club_label(value)
if old_label:
tween.tween_property(old_label, "scale", UNSELECTED_SCALE, LABEL_SCALE_TIME).set_trans(
Tween.TRANS_SINE
)
var new_label := _get_club_label(new_value)
if new_label:
tween.tween_property(new_label, "scale", SELECTED_SCALE, LABEL_SCALE_TIME).set_trans(
Tween.TRANS_SINE
)
var theta: float = CLUB_ROTATION[new_value]
tween.tween_property(club_hub, "rotation_degrees", theta, HUB_ROTATION_TIME).set_trans(
Tween.TRANS_QUAD
)
value = new_value

View File

@ -103,6 +103,7 @@ offset_top = -19.5
offset_right = 461.0
offset_bottom = 19.5
grow_vertical = 2
scale = Vector2(0.618, 0.618)
pivot_offset = Vector2(0, 20)
theme_type_variation = &"ClubSelectLabel"
text = "DRIVER"

View File

@ -27,6 +27,9 @@ const CAMERA_SNAP_TIME := 0.3
## In Driving Range mode, the ball can be retrieved in the shot phase.
@export var driving_range := false
## Initially-selected club
@export var initial_club: Club.Type = Club.Type.DRIVER
@export_category("Shot Parameters")
@export var base_power := 2.5
@export var base_curve := 0.0
@ -56,7 +59,7 @@ var phase: Phase:
_on_phase_change(value)
phase = value
var club: T.Club:
var club: Club.Type:
set(value):
if value != club:
_on_club_change(value)
@ -97,6 +100,8 @@ var _tracking_camera: OrbitalCamera
@onready var drive_arrow: Node3D = %DriveArrow
@onready var putt_ref: RayCast3D = %PuttRef
@onready var putt_arrow: Node3D = %PuttArrow
@onready var wedge_ref: RayCast3D = %WedgeRef
@onready var club_selector: ClubSelector = %ClubSelector
@onready var nice_animation: AnimationPlayer = %NiceAnimation
@ -117,7 +122,7 @@ var _tracking_camera: OrbitalCamera
func _ready() -> void:
_on_phase_change(phase)
_on_club_change(club)
club = initial_club
func _set_camera_distance(value: float) -> void:
@ -230,17 +235,39 @@ func end_shot_track() -> void:
## Called immediately before `club` is mutated.
func _on_club_change(new_club: T.Club) -> void:
func _on_club_change(new_club: Club.Type) -> void:
# Hide all arrows
# TODO animate?
drive_arrow.hide()
putt_arrow.hide()
club_selector.value = new_club
match new_club:
T.Club.DRIVER:
Club.Type.DRIVER:
shot_ref = drive_ref
drive_arrow.show()
putt_arrow.hide()
T.Club.PUTTER:
# TODO get this from player loadout
# TODO club change animation
character.hold_right(Club.catalog.debug_driver.get_model())
Club.Type.PUTTER:
shot_ref = putt_ref
putt_arrow.show()
drive_arrow.hide()
character.hold_right(Club.catalog.debug_putter.get_model())
Club.Type.WEDGE:
# TODO
shot_ref = wedge_ref
drive_arrow.show()
character.hold_right(Club.catalog.debug_wedge.get_model())
Club.Type.IRON:
# TODO
shot_ref = drive_ref
drive_arrow.show()
character.hold_right(Club.catalog.debug_iron.get_model())
Club.Type.SPECIAL:
# TODO
print_debug("TODO: implement special clubs!")
_:
print_debug("Not sure how to equip club type: ", new_club)
## Called immediately before `phase` is mutated.
@ -330,15 +357,15 @@ func _process(delta: float) -> void:
# Club select
if Input.is_action_just_pressed("select_driver"):
club = T.Club.DRIVER
club = Club.Type.DRIVER
if Input.is_action_just_pressed("select_iron"):
club = T.Club.IRON
club = Club.Type.IRON
if Input.is_action_just_pressed("select_wedge"):
club = T.Club.WEDGE
club = Club.Type.WEDGE
if Input.is_action_just_pressed("select_special"):
club = T.Club.SPECIAL
club = Club.Type.SPECIAL
if Input.is_action_just_pressed("select_putter"):
club = T.Club.PUTTER
club = Club.Type.PUTTER
# Switch to free cam
if (

View File

@ -1,10 +1,2 @@
class_name T extends Object
## Library for shared game enum types
enum Club {
DRIVER,
IRON,
SPECIAL,
WEDGE,
PUTTER,
}