feat: add deterministic goat routine

This commit is contained in:
Rijad Zuzo
2026-07-26 23:52:56 +02:00
parent f79c2bb630
commit e3aa3440a2
61 changed files with 1393 additions and 1057 deletions
-66
View File
@@ -1,66 +0,0 @@
extends Node3D
const HUNGER_CUE_BASE_Y := 2.05
const FED_RESPONSE_BASE_Y := 1.8
@onready var head_root: Node3D = $HeadRoot
@onready var tail_root: Node3D = $TailRoot
@onready var hunger_cue_root: Node3D = $HungerCueRoot
@onready var fed_response_root: Node3D = $FedResponseRoot
var idle_phase := 0.0
var is_hungry := false
var fed_tween: Tween
var head_base_position: Vector3
func _ready() -> void:
head_base_position = head_root.position
reset_transient_feedback()
func _process(delta: float) -> void:
idle_phase = fmod(idle_phase + delta, TAU)
var breath := sin(idle_phase * 1.7) * 0.025
var hungry_drop := -0.12 if is_hungry else 0.0
head_root.position.y = head_base_position.y + breath + hungry_drop
head_root.rotation_degrees.x = (
8.0 + sin(idle_phase * 1.2) * 2.0 if is_hungry else -3.0 + sin(idle_phase * 1.4) * 2.5
)
tail_root.rotation_degrees.z = sin(idle_phase * 3.1) * (4.0 if is_hungry else 13.0)
if hunger_cue_root.visible:
hunger_cue_root.position.y = HUNGER_CUE_BASE_Y + sin(idle_phase * 2.2) * 0.07
func set_hungry(value: bool) -> void:
is_hungry = value
hunger_cue_root.visible = value
func reset_transient_feedback() -> void:
if fed_tween != null:
fed_tween.kill()
fed_tween = null
fed_response_root.visible = false
fed_response_root.position.y = FED_RESPONSE_BASE_Y
fed_response_root.scale = Vector3(0.2, 0.2, 0.2)
func play_fed_response() -> void:
reset_transient_feedback()
fed_response_root.visible = true
fed_tween = create_tween()
fed_tween.set_trans(Tween.TRANS_BACK).set_ease(Tween.EASE_OUT)
fed_tween.tween_property(fed_response_root, "scale", Vector3.ONE, 0.34)
fed_tween.parallel().tween_property(
fed_response_root, "position:y", FED_RESPONSE_BASE_Y + 0.22, 0.34
)
fed_tween.set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN)
fed_tween.tween_interval(0.7)
fed_tween.tween_property(fed_response_root, "scale", Vector3(0.2, 0.2, 0.2), 0.42)
fed_tween.finished.connect(_on_fed_response_finished)
func _on_fed_response_finished() -> void:
fed_response_root.visible = false
fed_tween = null
-1
View File
@@ -1 +0,0 @@
uid://byx6pyisksbtg
-329
View File
@@ -1,329 +0,0 @@
[gd_scene load_steps=26 format=3]
[ext_resource type="Script" path="res://world/animals/AnimalNode.gd" id="1_animal"]
[ext_resource type="Script" path="res://world/jajce/CozyGoat.gd" id="2_visual"]
[sub_resource type="StandardMaterial3D" id="Material_wool"]
albedo_color = Color(0.88, 0.82, 0.67, 1)
roughness = 0.96
[sub_resource type="StandardMaterial3D" id="Material_face"]
albedo_color = Color(0.58, 0.43, 0.29, 1)
roughness = 0.92
[sub_resource type="StandardMaterial3D" id="Material_dark"]
albedo_color = Color(0.13, 0.09, 0.065, 1)
roughness = 0.9
[sub_resource type="StandardMaterial3D" id="Material_horn"]
albedo_color = Color(0.78, 0.68, 0.5, 1)
roughness = 0.86
[sub_resource type="StandardMaterial3D" id="Material_collar"]
albedo_color = Color(0.12, 0.5, 0.5, 1)
roughness = 0.72
[sub_resource type="StandardMaterial3D" id="Material_wood"]
albedo_color = Color(0.35, 0.19, 0.09, 1)
roughness = 0.96
[sub_resource type="StandardMaterial3D" id="Material_hunger"]
transparency = 1
shading_mode = 0
albedo_color = Color(0.98, 0.62, 0.22, 0.9)
emission_enabled = true
emission = Color(0.92, 0.36, 0.08, 1)
emission_energy_multiplier = 0.32
[sub_resource type="StandardMaterial3D" id="Material_fed"]
transparency = 1
shading_mode = 0
albedo_color = Color(0.72, 0.92, 0.5, 0.92)
emission_enabled = true
emission = Color(0.45, 0.78, 0.28, 1)
emission_energy_multiplier = 0.38
[sub_resource type="CapsuleMesh" id="Mesh_body"]
material = SubResource("Material_wool")
radius = 0.48
height = 1.55
radial_segments = 12
rings = 4
[sub_resource type="SphereMesh" id="Mesh_fluff"]
material = SubResource("Material_wool")
radius = 0.42
height = 0.72
radial_segments = 12
rings = 6
[sub_resource type="CapsuleMesh" id="Mesh_leg"]
material = SubResource("Material_face")
radius = 0.105
height = 0.62
radial_segments = 8
rings = 3
[sub_resource type="BoxMesh" id="Mesh_hoof"]
material = SubResource("Material_dark")
size = Vector3(0.2, 0.13, 0.28)
[sub_resource type="SphereMesh" id="Mesh_head"]
material = SubResource("Material_face")
radius = 0.34
height = 0.58
radial_segments = 12
rings = 6
[sub_resource type="SphereMesh" id="Mesh_snout"]
material = SubResource("Material_wool")
radius = 0.21
height = 0.32
radial_segments = 10
rings = 5
[sub_resource type="SphereMesh" id="Mesh_ear"]
material = SubResource("Material_face")
radius = 0.24
height = 0.42
radial_segments = 10
rings = 5
[sub_resource type="SphereMesh" id="Mesh_eye"]
material = SubResource("Material_dark")
radius = 0.045
height = 0.075
radial_segments = 8
rings = 4
[sub_resource type="CylinderMesh" id="Mesh_horn"]
material = SubResource("Material_horn")
top_radius = 0.035
bottom_radius = 0.09
height = 0.42
radial_segments = 8
[sub_resource type="CylinderMesh" id="Mesh_beard"]
material = SubResource("Material_wool")
top_radius = 0.015
bottom_radius = 0.11
height = 0.34
radial_segments = 8
[sub_resource type="CylinderMesh" id="Mesh_tail"]
material = SubResource("Material_wool")
top_radius = 0.07
bottom_radius = 0.12
height = 0.42
radial_segments = 8
[sub_resource type="TorusMesh" id="Mesh_collar"]
material = SubResource("Material_collar")
inner_radius = 0.27
outer_radius = 0.32
rings = 14
ring_segments = 8
[sub_resource type="CylinderMesh" id="Mesh_bowl"]
material = SubResource("Material_wood")
top_radius = 0.36
bottom_radius = 0.28
height = 0.13
radial_segments = 12
[sub_resource type="TorusMesh" id="Mesh_hunger_bowl"]
material = SubResource("Material_hunger")
inner_radius = 0.18
outer_radius = 0.27
rings = 14
ring_segments = 8
[sub_resource type="SphereMesh" id="Mesh_hunger_food"]
material = SubResource("Material_hunger")
radius = 0.09
height = 0.14
radial_segments = 8
rings = 4
[sub_resource type="TorusMesh" id="Mesh_fed_ring"]
material = SubResource("Material_fed")
inner_radius = 0.32
outer_radius = 0.42
rings = 16
ring_segments = 8
[sub_resource type="SphereMesh" id="Mesh_fed_mote"]
material = SubResource("Material_fed")
radius = 0.075
height = 0.13
radial_segments = 8
rings = 4
[node name="CozyGoat" type="Node3D"]
script = ExtResource("1_animal")
animal_id = &"goat_dunja"
display_name = "Dunja"
species_id = &"goat"
initial_hunger = 72.0
[node name="Visual" type="Node3D" parent="."]
script = ExtResource("2_visual")
[node name="Body" type="MeshInstance3D" parent="Visual"]
position = Vector3(0, 0.95, 0)
rotation_degrees = Vector3(90, 0, 0)
mesh = SubResource("Mesh_body")
[node name="FluffFront" type="MeshInstance3D" parent="Visual"]
position = Vector3(0, 1.02, 0.42)
scale = Vector3(1.08, 1.05, 1)
mesh = SubResource("Mesh_fluff")
[node name="FluffBack" type="MeshInstance3D" parent="Visual"]
position = Vector3(0, 1.02, -0.42)
scale = Vector3(1.08, 1.05, 1)
mesh = SubResource("Mesh_fluff")
[node name="LegFrontLeft" type="MeshInstance3D" parent="Visual"]
position = Vector3(-0.3, 0.43, 0.48)
mesh = SubResource("Mesh_leg")
[node name="Hoof" type="MeshInstance3D" parent="Visual/LegFrontLeft"]
position = Vector3(0, -0.29, 0.035)
mesh = SubResource("Mesh_hoof")
[node name="LegFrontRight" type="MeshInstance3D" parent="Visual"]
position = Vector3(0.3, 0.43, 0.48)
mesh = SubResource("Mesh_leg")
[node name="Hoof" type="MeshInstance3D" parent="Visual/LegFrontRight"]
position = Vector3(0, -0.29, 0.035)
mesh = SubResource("Mesh_hoof")
[node name="LegBackLeft" type="MeshInstance3D" parent="Visual"]
position = Vector3(-0.3, 0.43, -0.48)
mesh = SubResource("Mesh_leg")
[node name="Hoof" type="MeshInstance3D" parent="Visual/LegBackLeft"]
position = Vector3(0, -0.29, 0.035)
mesh = SubResource("Mesh_hoof")
[node name="LegBackRight" type="MeshInstance3D" parent="Visual"]
position = Vector3(0.3, 0.43, -0.48)
mesh = SubResource("Mesh_leg")
[node name="Hoof" type="MeshInstance3D" parent="Visual/LegBackRight"]
position = Vector3(0, -0.29, 0.035)
mesh = SubResource("Mesh_hoof")
[node name="HeadRoot" type="Node3D" parent="Visual"]
position = Vector3(0, 1.28, 0.88)
rotation_degrees = Vector3(-3, 0, 0)
[node name="Head" type="MeshInstance3D" parent="Visual/HeadRoot"]
mesh = SubResource("Mesh_head")
[node name="Snout" type="MeshInstance3D" parent="Visual/HeadRoot"]
position = Vector3(0, -0.08, 0.31)
scale = Vector3(1.05, 0.72, 0.9)
mesh = SubResource("Mesh_snout")
[node name="EyeLeft" type="MeshInstance3D" parent="Visual/HeadRoot"]
position = Vector3(-0.18, 0.08, 0.285)
mesh = SubResource("Mesh_eye")
[node name="EyeRight" type="MeshInstance3D" parent="Visual/HeadRoot"]
position = Vector3(0.18, 0.08, 0.285)
mesh = SubResource("Mesh_eye")
[node name="EarLeft" type="MeshInstance3D" parent="Visual/HeadRoot"]
position = Vector3(-0.35, 0.13, 0)
rotation_degrees = Vector3(8, 0, 67)
scale = Vector3(0.82, 0.28, 1)
mesh = SubResource("Mesh_ear")
[node name="EarRight" type="MeshInstance3D" parent="Visual/HeadRoot"]
position = Vector3(0.35, 0.13, 0)
rotation_degrees = Vector3(8, 0, -67)
scale = Vector3(0.82, 0.28, 1)
mesh = SubResource("Mesh_ear")
[node name="HornLeft" type="MeshInstance3D" parent="Visual/HeadRoot"]
position = Vector3(-0.17, 0.34, -0.06)
rotation_degrees = Vector3(-24, 0, -20)
mesh = SubResource("Mesh_horn")
[node name="HornRight" type="MeshInstance3D" parent="Visual/HeadRoot"]
position = Vector3(0.17, 0.34, -0.06)
rotation_degrees = Vector3(-24, 0, 20)
mesh = SubResource("Mesh_horn")
[node name="Beard" type="MeshInstance3D" parent="Visual/HeadRoot"]
position = Vector3(0, -0.35, 0.08)
mesh = SubResource("Mesh_beard")
[node name="Collar" type="MeshInstance3D" parent="Visual/HeadRoot"]
position = Vector3(0, -0.31, -0.16)
rotation_degrees = Vector3(90, 0, 0)
scale = Vector3(0.85, 0.85, 0.85)
mesh = SubResource("Mesh_collar")
[node name="TailRoot" type="Node3D" parent="Visual"]
position = Vector3(0, 1.16, -0.92)
rotation_degrees = Vector3(60, 0, 0)
[node name="Tail" type="MeshInstance3D" parent="Visual/TailRoot"]
position = Vector3(0, 0.18, 0)
mesh = SubResource("Mesh_tail")
[node name="FeedBowl" type="MeshInstance3D" parent="Visual"]
position = Vector3(0.72, 0.08, 1.43)
mesh = SubResource("Mesh_bowl")
[node name="HungerCueRoot" type="Node3D" parent="Visual"]
position = Vector3(0, 2.05, 0.18)
[node name="EmptyBowl" type="MeshInstance3D" parent="Visual/HungerCueRoot"]
rotation_degrees = Vector3(72, 0, 0)
scale = Vector3(1.1, 0.72, 1.1)
mesh = SubResource("Mesh_hunger_bowl")
[node name="FoodMoteLeft" type="MeshInstance3D" parent="Visual/HungerCueRoot"]
position = Vector3(-0.13, 0.22, 0)
mesh = SubResource("Mesh_hunger_food")
[node name="FoodMoteRight" type="MeshInstance3D" parent="Visual/HungerCueRoot"]
position = Vector3(0.13, 0.29, 0)
scale = Vector3(0.82, 0.82, 0.82)
mesh = SubResource("Mesh_hunger_food")
[node name="FedResponseRoot" type="Node3D" parent="Visual"]
visible = false
position = Vector3(0, 1.8, 0.12)
scale = Vector3(0.2, 0.2, 0.2)
[node name="Halo" type="MeshInstance3D" parent="Visual/FedResponseRoot"]
rotation_degrees = Vector3(74, 0, 0)
mesh = SubResource("Mesh_fed_ring")
[node name="MoteLeft" type="MeshInstance3D" parent="Visual/FedResponseRoot"]
position = Vector3(-0.34, 0.18, 0)
mesh = SubResource("Mesh_fed_mote")
[node name="MoteRight" type="MeshInstance3D" parent="Visual/FedResponseRoot"]
position = Vector3(0.34, 0.28, 0)
scale = Vector3(0.82, 0.82, 0.82)
mesh = SubResource("Mesh_fed_mote")
[node name="InteractionPoint" type="Marker3D" parent="."]
position = Vector3(0, 0, 2.05)
[node name="DebugLabel" type="Label3D" parent="."]
position = Vector3(0, 2.55, 0)
billboard = 1
no_depth_test = true
font_size = 22
outline_size = 5
text = "Dunja"
modulate = Color(1, 0.94, 0.78, 1)
pixel_size = 0.006
-16
View File
@@ -1,16 +0,0 @@
[gd_scene load_steps=3 format=3]
[ext_resource type="PackedScene" path="res://world/jajce/JajceWorld.tscn" id="1_world"]
[ext_resource type="Script" path="res://world/jajce/beauty_camera.gd" id="2_camera"]
[node name="JajceGoatLookdev" type="Node3D"]
[node name="JajceWorld" parent="." instance=ExtResource("1_world")]
[node name="GoatCamera" type="Camera3D" parent="."]
position = Vector3(0.2, 2.9, -7)
current = true
fov = 32.0
script = ExtResource("2_camera")
focus_point = Vector3(-4, 1.15, -11.5)
animate_orbit = false
+10 -4
View File
@@ -1,4 +1,4 @@
[gd_scene load_steps=60 format=3]
[gd_scene load_steps=61 format=3]
[ext_resource type="Terrain3DAssets" path="res://terrain/jajce/assets.tres" id="1_assets"]
[ext_resource type="PackedScene" path="res://world/resource_nodes/ResourceNode.tscn" id="2_resource"]
@@ -27,7 +27,8 @@
[ext_resource type="Material" path="res://world/jajce/materials/cozy_grass_process_material.tres" id="25_grass_process"]
[ext_resource type="PackedScene" path="res://world/jajce/RiverbankResourceCluster.tscn" id="26_resource_cluster"]
[ext_resource type="PackedScene" path="res://world/jajce/ForestEdgeResourceCluster.tscn" id="27_forest_cluster"]
[ext_resource type="PackedScene" path="res://world/jajce/CozyGoat.tscn" id="28_goat"]
[ext_resource type="PackedScene" path="res://world/animals/goat/cozy_goat.tscn" id="28_goat"]
[ext_resource type="PackedScene" path="res://world/animals/goat/dunja_habitat.tscn" id="29_habitat"]
[sub_resource type="Terrain3DMaterial" id="Terrain3DMaterial_jajce"]
_shader_parameters = {
@@ -462,8 +463,13 @@ phase = 4.4
[node name="Animals" type="Node3D" parent="WorldObjects"]
[node name="Dunja" parent="WorldObjects/Animals" instance=ExtResource("28_goat")]
position = Vector3(-4, 0, -11.5)
rotation_degrees = Vector3(0, -18, 0)
position = Vector3(0, 0, -15.5)
rotation_degrees = Vector3(0, 150, 0)
[node name="AnimalHabitats" type="Node3D" parent="WorldObjects"]
[node name="DunjaHabitat" parent="WorldObjects/AnimalHabitats" instance=ExtResource("29_habitat")]
position = Vector3(0, 0, -17)
[node name="ResourceNodes" type="Node3D" parent="WorldObjects"]
+3 -1
View File
@@ -21,7 +21,9 @@ func _initialize_world_presentation() -> void:
groups_to_snap.append(child)
if has_node("WorldObjects"):
var wo := $WorldObjects
for group_name in ["Animals", "ResourceNodes", "StorageSites", "ActivitySites"]:
for group_name in [
"Animals", "AnimalHabitats", "ResourceNodes", "StorageSites", "ActivitySites"
]:
if wo.has_node(group_name):
groups_to_snap.append_array(wo.get_node(group_name).get_children())