credit
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
extends CharacterBody3D
|
||||
|
||||
@onready var anim_player: AnimationPlayer = $cow/AnimationPlayer
|
||||
|
||||
@export var dest_array:Array[Marker3D]
|
||||
@onready var navigation_agent: NavigationAgent3D = $NavigationAgent3D
|
||||
@onready var idle_timer: Timer = $Timer
|
||||
enum NPCSTATE {
|
||||
IDLE,
|
||||
WALKING
|
||||
}
|
||||
var cur_state : NPCSTATE
|
||||
var cur_destination: Marker3D
|
||||
var speed = 4
|
||||
|
||||
@onready var audio_moo: AudioStreamPlayer3D = $AudioMoo
|
||||
@onready var moo_timer: Timer = $MooTimer
|
||||
|
||||
var one_time_each : bool = false
|
||||
|
||||
func _ready() -> void:
|
||||
_set_state( NPCSTATE.IDLE )
|
||||
|
||||
func _on_timer_timeout() -> void:
|
||||
decide_next_state()
|
||||
|
||||
func _set_state(new_state:NPCSTATE):
|
||||
cur_state = new_state
|
||||
match cur_state:
|
||||
NPCSTATE.IDLE:
|
||||
idle_timer.start( randf_range(3, 5) )
|
||||
anim_player.play("metarig|metarig|walking", -1, .7 )
|
||||
|
||||
NPCSTATE.WALKING:
|
||||
anim_player.play("metarig|metarig|walking", -1, 1.7 )
|
||||
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
match cur_state:
|
||||
NPCSTATE.IDLE:
|
||||
pass
|
||||
NPCSTATE.WALKING:
|
||||
var next_path_pos:Vector3 = navigation_agent.get_next_path_position()
|
||||
var new_vel : Vector3 = global_position.direction_to( next_path_pos ) * speed
|
||||
velocity = new_vel
|
||||
var look_at_target : Vector3 = Vector3( next_path_pos.x, global_position.y, next_path_pos.z )
|
||||
if not global_position.is_equal_approx( look_at_target ):
|
||||
look_at( look_at_target )
|
||||
|
||||
move_and_slide()
|
||||
|
||||
|
||||
|
||||
func decide_next_state():
|
||||
if cur_state == NPCSTATE.IDLE:
|
||||
cur_destination = dest_array.pick_random()
|
||||
navigation_agent.target_position = cur_destination.global_position
|
||||
_set_state( NPCSTATE.WALKING )
|
||||
|
||||
func _on_navigation_agent_3d_navigation_finished() -> void:
|
||||
_set_state( NPCSTATE.IDLE )
|
||||
|
||||
|
||||
func _on_moo_timer_timeout() -> void:
|
||||
moo_timer.wait_time = randf_range(40, 60)
|
||||
audio_moo.pitch_scale = randf_range( .8, 1.2 )
|
||||
audio_moo.play()
|
||||
@@ -0,0 +1 @@
|
||||
uid://xqjom65pdi52
|
||||
@@ -0,0 +1,157 @@
|
||||
extends CharacterBody3D
|
||||
|
||||
## --- Paramètres à régler dans l'inspecteur ---
|
||||
|
||||
@export var player: Node3D # Référence au joueur (à assigner dans l'inspecteur ou via groupe)
|
||||
@export var flee_enabled: bool = false # Si false, l'animal ne fuit jamais, il se balade juste dans sa zone
|
||||
@export var move_speed: float = 4.8
|
||||
@export var acceleration: float = 12
|
||||
@export var rotation_speed: float = 5
|
||||
|
||||
@export_group("Zone de confinement")
|
||||
@export var zone_center: Vector3 = Vector3.ZERO # Centre de la zone (en coordonnées globales)
|
||||
@export var zone_size: Vector2 = Vector2(30.0, 30.0) # Largeur (x) et profondeur (z) du rectangle
|
||||
@export var zone_rotation_degrees: float = 0.0 # Rotation du rectangle autour de l'axe Y
|
||||
@export var zone_margin: float = 1.5 # Marge de sécurité avant le bord
|
||||
|
||||
@export_group("Comportement idle")
|
||||
@export var wander_enabled: bool = true
|
||||
@export var wander_radius: float = 5.0
|
||||
@export var wander_interval: float = 3.0
|
||||
|
||||
var _wander_target: Vector3
|
||||
var _wander_timer: float = 0.0
|
||||
var _state: String = "idle" # "idle" ou "flee"
|
||||
|
||||
# --- NOUVEAU : Variables pour gérer le déblocage sur les bords ---
|
||||
var _stuck_timer: float = 0.0
|
||||
var _sidestep_direction: float = 1.0 # 1.0 pour droite, -1.0 pour gauche
|
||||
|
||||
@onready var anim_player: AnimationPlayer = $foxes/AnimationPlayer
|
||||
|
||||
func _ready() -> void:
|
||||
_wander_target = global_position
|
||||
if player == null:
|
||||
var players := get_tree().get_nodes_in_group("player")
|
||||
if players.size() > 0:
|
||||
player = players[0]
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
if not player == null:
|
||||
# --- Détermine l'état ---
|
||||
if flee_enabled:
|
||||
_state = "flee"
|
||||
else:
|
||||
_state = "idle"
|
||||
|
||||
var desired_direction: Vector3
|
||||
|
||||
if _state == "flee":
|
||||
desired_direction = _get_flee_direction(delta)
|
||||
else:
|
||||
desired_direction = _get_wander_direction(delta)
|
||||
|
||||
_apply_movement(desired_direction, delta)
|
||||
_update_animation()
|
||||
|
||||
|
||||
func _get_flee_direction(delta: float) -> Vector3:
|
||||
# Direction opposée au joueur (sur le plan horizontal)
|
||||
var away := (global_position - player.global_position)
|
||||
away.y = 0.0
|
||||
away = away.normalized()
|
||||
|
||||
var target_pos := global_position + away * 5.0
|
||||
var clamped_target = _clamp_to_zone(target_pos)
|
||||
|
||||
# Détection de blocage : si la cible calculée est quasiment la même que notre position
|
||||
# ou si on est bloqué contre un bord (la cible clampée diffère fortement de la cible brute)
|
||||
if target_pos.distance_to(clamped_target) > 0.5:
|
||||
_stuck_timer += delta
|
||||
if _stuck_timer > 0.3: # Si bloqué pendant plus de 0.3 secondes
|
||||
# On choisit aléatoirement ou on alterne gauche/droite pour longer le bord
|
||||
if randf() < 0.02:
|
||||
_sidestep_direction *= -1.0
|
||||
|
||||
# On décale la fuite perpendiculairement (à gauche ou à droite de la fuite)
|
||||
var perpendicular = Vector3(-away.z, 0.0, away.x) * _sidestep_target_sign()
|
||||
away = (away + perpendicular).normalized()
|
||||
clamped_target = _clamp_to_zone(global_position + away * 5.0)
|
||||
else:
|
||||
_stuck_timer = 0.0
|
||||
|
||||
return (clamped_target - global_position).normalized()
|
||||
|
||||
|
||||
func _sidestep_target_sign() -> float:
|
||||
return _sidestep_direction
|
||||
|
||||
|
||||
func _get_wander_direction(delta: float) -> Vector3:
|
||||
if not wander_enabled:
|
||||
return Vector3.ZERO
|
||||
|
||||
_wander_timer -= delta
|
||||
if _wander_timer <= 0.0 or global_position.distance_to(_wander_target) < 0.5:
|
||||
_wander_timer = wander_interval
|
||||
_wander_target = _pick_random_point_in_zone()
|
||||
|
||||
var dir := (_wander_target - global_position)
|
||||
dir.y = 0.0
|
||||
if dir.length() < 0.1:
|
||||
return Vector3.ZERO
|
||||
return dir.normalized()
|
||||
|
||||
|
||||
func _pick_random_point_in_zone() -> Vector3:
|
||||
var angle := randf() * TAU
|
||||
var radius := randf() * wander_radius
|
||||
var offset := Vector3(cos(angle), 0.0, sin(angle)) * radius
|
||||
var point := global_position + offset
|
||||
return _clamp_to_zone(point)
|
||||
|
||||
|
||||
func _clamp_to_zone(point: Vector3) -> Vector3:
|
||||
var half_width := (zone_size.x * 0.5) - zone_margin
|
||||
var half_depth := (zone_size.y * 0.5) - zone_margin
|
||||
|
||||
var rot_rad := deg_to_rad(zone_rotation_degrees)
|
||||
var local_point := (point - zone_center).rotated(Vector3.UP, -rot_rad)
|
||||
|
||||
local_point.x = clamp(local_point.x, -half_width, half_width)
|
||||
local_point.z = clamp(local_point.z, -half_depth, half_depth)
|
||||
|
||||
return zone_center + local_point.rotated(Vector3.UP, rot_rad)
|
||||
|
||||
|
||||
func _apply_movement(direction: Vector3, delta: float) -> void:
|
||||
var speed := move_speed
|
||||
if _state == "flee":
|
||||
speed *= 1.6
|
||||
|
||||
var target_velocity := direction * speed
|
||||
target_velocity.y = velocity.y
|
||||
|
||||
velocity.x = move_toward(velocity.x, target_velocity.x, acceleration * delta)
|
||||
velocity.z = move_toward(velocity.z, target_velocity.z, acceleration * delta)
|
||||
|
||||
if not is_on_floor():
|
||||
velocity.y -= 9.8 * delta
|
||||
|
||||
if direction.length() > 0.1:
|
||||
var target_angle := atan2(direction.x, direction.z)
|
||||
rotation.y = lerp_angle(rotation.y, target_angle, rotation_speed * delta)
|
||||
|
||||
move_and_slide()
|
||||
|
||||
|
||||
func _update_animation() -> void:
|
||||
if anim_player.current_animation != "dog_rig_Canter":
|
||||
anim_player.play("dog_rig_Canter")
|
||||
|
||||
|
||||
func _on_area_3d_body_entered(body: Node3D) -> void:
|
||||
if body.is_in_group("player"):
|
||||
#if body.can_run:
|
||||
body.fox_grabbed += 1
|
||||
queue_free()
|
||||
@@ -0,0 +1 @@
|
||||
uid://csjajikq0yq7g
|
||||
@@ -0,0 +1,67 @@
|
||||
@tool
|
||||
extends MeshInstance3D
|
||||
|
||||
## Dessine un rectangle (contour) représentant une zone de confinement.
|
||||
## À attacher sur un MeshInstance3D vide, placé n'importe où dans la scène.
|
||||
## Utilise les mêmes valeurs (zone_center / zone_size) que FleeingAnimal.gd.
|
||||
|
||||
@export var zone_center: Vector3 = Vector3.ZERO:
|
||||
set(value):
|
||||
zone_center = value
|
||||
_update_rectangle()
|
||||
|
||||
@export var zone_size: Vector2 = Vector2(30.0, 30.0): # largeur (x) et profondeur (z)
|
||||
set(value):
|
||||
zone_size = value
|
||||
_update_rectangle()
|
||||
|
||||
@export var zone_rotation_degrees: float = 0.0: # rotation du rectangle autour de l'axe Y
|
||||
set(value):
|
||||
zone_rotation_degrees = value
|
||||
_update_rectangle()
|
||||
|
||||
@export var line_color: Color = Color(1.0, 0.2, 0.2):
|
||||
set(value):
|
||||
line_color = value
|
||||
_update_material()
|
||||
|
||||
@export var height_offset: float = 0.05 # légère élévation pour éviter le z-fighting avec le sol
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
_update_rectangle()
|
||||
_update_material()
|
||||
|
||||
|
||||
func _update_rectangle() -> void:
|
||||
var immediate := ImmediateMesh.new()
|
||||
immediate.surface_begin(Mesh.PRIMITIVE_LINE_STRIP)
|
||||
|
||||
var half_width := zone_size.x * 0.5
|
||||
var half_depth := zone_size.y * 0.5
|
||||
var rot_rad := deg_to_rad(zone_rotation_degrees)
|
||||
|
||||
var local_corners := [
|
||||
Vector3(-half_width, 0.0, -half_depth),
|
||||
Vector3(half_width, 0.0, -half_depth),
|
||||
Vector3(half_width, 0.0, half_depth),
|
||||
Vector3(-half_width, 0.0, half_depth),
|
||||
Vector3(-half_width, 0.0, -half_depth),
|
||||
]
|
||||
|
||||
for corner in local_corners:
|
||||
var rotated_corner: Vector3 = corner.rotated(Vector3.UP, rot_rad)
|
||||
var final_point := zone_center + rotated_corner
|
||||
final_point.y += height_offset
|
||||
immediate.surface_add_vertex(final_point)
|
||||
|
||||
immediate.surface_end()
|
||||
mesh = immediate
|
||||
|
||||
|
||||
func _update_material() -> void:
|
||||
var mat := StandardMaterial3D.new()
|
||||
mat.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED
|
||||
mat.albedo_color = line_color
|
||||
mat.vertex_color_use_as_albedo = false
|
||||
material_override = mat
|
||||
@@ -0,0 +1 @@
|
||||
uid://p0sr27jji18b
|
||||
@@ -0,0 +1,9 @@
|
||||
extends Node
|
||||
|
||||
@onready var audio_snort: AudioStreamPlayer3D = $AudioStreamPlayer3D
|
||||
@onready var snort_timer: Timer = $SnortTimer
|
||||
|
||||
func _on_snort_timer_timeout() -> void:
|
||||
snort_timer.wait_time = randf_range(25, 35)
|
||||
audio_snort.pitch_scale = randf_range( .9, 1.1 )
|
||||
audio_snort.play()
|
||||
@@ -0,0 +1 @@
|
||||
uid://mnf6fljk6624
|
||||
@@ -0,0 +1,65 @@
|
||||
extends Camera3D
|
||||
|
||||
## Fait légèrement trembler la caméra pour simuler les secousses d'une voiture.
|
||||
## Attache ce script directement sur chaque Camera3D du groupe "cinematic_cams"
|
||||
|
||||
@export_group("Intensité")
|
||||
@export var position_amplitude: float = 0.01 # amplitude du déplacement (en mètres)
|
||||
@export var rotation_amplitude: float = 0.2 # amplitude de la rotation (en degrés)
|
||||
@export var frequency: float = 0.5 # vitesse du tremblement (plus haut = plus nerveux)
|
||||
|
||||
var _noise: FastNoiseLite
|
||||
var _time: float = 0.0
|
||||
var _last_offset_pos: Vector3 = Vector3.ZERO
|
||||
var _last_offset_rot: Vector3 = Vector3.ZERO
|
||||
var _shaking: bool = false
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
_noise = FastNoiseLite.new()
|
||||
_noise.seed = randi()
|
||||
_noise.frequency = 1.0
|
||||
|
||||
start_shake()
|
||||
|
||||
|
||||
func start_shake() -> void:
|
||||
_shaking = true
|
||||
|
||||
|
||||
func stop_shake() -> void:
|
||||
_shaking = false
|
||||
# retire proprement le dernier offset appliqué pour ne pas laisser la caméra décalée
|
||||
position -= _last_offset_pos
|
||||
rotation -= _last_offset_rot
|
||||
_last_offset_pos = Vector3.ZERO
|
||||
_last_offset_rot = Vector3.ZERO
|
||||
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
if not _shaking:
|
||||
return
|
||||
|
||||
_time += delta * frequency
|
||||
|
||||
# retire l'offset de la frame précédente avant d'en calculer un nouveau
|
||||
position -= _last_offset_pos
|
||||
rotation -= _last_offset_rot
|
||||
|
||||
var offset_pos := Vector3(
|
||||
_noise.get_noise_2d(_time, 0.0),
|
||||
_noise.get_noise_2d(0.0, _time),
|
||||
_noise.get_noise_2d(_time, _time)
|
||||
) * position_amplitude
|
||||
|
||||
var offset_rot := Vector3(
|
||||
_noise.get_noise_2d(_time, 100.0),
|
||||
_noise.get_noise_2d(100.0, _time),
|
||||
_noise.get_noise_2d(_time, -_time)
|
||||
) * deg_to_rad(rotation_amplitude)
|
||||
|
||||
position += offset_pos
|
||||
rotation += offset_rot
|
||||
|
||||
_last_offset_pos = offset_pos
|
||||
_last_offset_rot = offset_rot
|
||||
@@ -0,0 +1 @@
|
||||
uid://dpg4fpvcr5rnl
|
||||
@@ -3,18 +3,22 @@ extends Node3D
|
||||
@onready var cinematic_camera: Node3D = $cinematic_camera
|
||||
@onready var car_anim_player: AnimationPlayer = $cinematic_camera/car/AnimationPlayer
|
||||
@onready var player_anim_player: AnimationPlayer = $cinematic_camera/player_driving/AnimationPlayer
|
||||
@onready var audio_stream_player: AudioStreamPlayer3D = $cinematic_camera/AudioStreamPlayer3D
|
||||
|
||||
func _ready() -> void:
|
||||
Dialogic.start("timeline")
|
||||
Dialogic.timeline_ended.connect( change_scene )
|
||||
|
||||
func change_scene():
|
||||
audio_stream_player.stream = load("res://assets/audio/sound-effects/car/door-open.mp3")
|
||||
audio_stream_player.play()
|
||||
|
||||
Transition.change_scene("res://scenes/main.scn")
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
car_anim_player.play("driving")
|
||||
player_anim_player.play("driving")
|
||||
if cinematic_camera.global_position.x < 490:
|
||||
cinematic_camera.global_position.x += 16 * delta
|
||||
cinematic_camera.global_position.x += 13 * delta
|
||||
else:
|
||||
cinematic_camera.global_position.x += 10 * delta
|
||||
cinematic_camera.global_position.x += 9 * delta
|
||||
|
||||
+25
-9
@@ -1,11 +1,14 @@
|
||||
extends CharacterBody3D
|
||||
|
||||
@export var have_dialog : bool = false
|
||||
@export var dialog : String = ""
|
||||
@export var alrdy_talking : bool = false
|
||||
@export var can_wander : bool = false
|
||||
|
||||
@onready var sprite_label: Sprite3D = $Sprite3D
|
||||
@onready var label: Label = $Sprite3D/SubViewport/Label
|
||||
@onready var anim_player: AnimationPlayer = $character/AnimationPlayer
|
||||
@onready var mesh: MeshInstance3D = $character/Root/Skeleton3D/characterMedium
|
||||
|
||||
# navigation
|
||||
@export var dest_array:Array[Marker3D]
|
||||
@@ -19,11 +22,21 @@ var cur_state : NPCSTATE
|
||||
var cur_destination: Marker3D
|
||||
var speed = 2
|
||||
|
||||
var first_time : bool = false
|
||||
|
||||
func _ready() -> void:
|
||||
mesh.set_instance_shader_parameter("skin_index", randi_range(1, 16))
|
||||
|
||||
sprite_label.visible = false
|
||||
if alrdy_talking:
|
||||
await get_tree().create_timer( randf_range(1.0, 2.5) ).timeout
|
||||
anim_player.play("RootAction")
|
||||
if !first_time:
|
||||
first_time = true
|
||||
else:
|
||||
await get_tree().create_timer( randf_range(1.0, 2.5) ).timeout
|
||||
anim_player.play("talking")
|
||||
|
||||
if have_dialog:
|
||||
anim_player.play("Idling")
|
||||
|
||||
if can_wander:
|
||||
_set_state( NPCSTATE.IDLE )
|
||||
@@ -35,10 +48,14 @@ func _set_state(new_state:NPCSTATE):
|
||||
cur_state = new_state
|
||||
match cur_state:
|
||||
NPCSTATE.IDLE:
|
||||
idle_timer.start( randf_range(1, 2) )
|
||||
anim_player.play("RootAction", -1, 10)
|
||||
if !first_time:
|
||||
first_time = true
|
||||
idle_timer.start( 0 )
|
||||
else:
|
||||
idle_timer.start( randf_range(10, 20) )
|
||||
anim_player.play("Idling", -1, 1)
|
||||
NPCSTATE.WALKING:
|
||||
anim_player.play("RootAction_001", -1, 2.5)
|
||||
anim_player.play("walking", -1, randf_range(2, 2.5) )
|
||||
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
@@ -66,12 +83,11 @@ func decide_next_state():
|
||||
func _on_area_3d_body_entered(body: Node3D) -> void:
|
||||
if have_dialog and body.is_in_group("player"):
|
||||
sprite_label.visible = true
|
||||
label.text = dialog
|
||||
body.set_dialog_mode( global_position )
|
||||
|
||||
func _on_area_3d_body_exited(body: Node3D) -> void:
|
||||
if have_dialog and body.is_in_group("player"):
|
||||
await get_tree().create_timer( 3 ).timeout
|
||||
body.set_dialog_mode( )
|
||||
sprite_label.visible = false
|
||||
body.set_dialog_mode()
|
||||
|
||||
|
||||
func _on_navigation_agent_3d_navigation_finished() -> void:
|
||||
|
||||
@@ -1,8 +1,15 @@
|
||||
extends MultiMeshInstance3D
|
||||
|
||||
@onready var anim_player: AnimationPlayer = $"../AnimationPlayer"
|
||||
|
||||
func _ready() -> void:
|
||||
anim_player.play("will_turning", -1, .5)
|
||||
|
||||
var characters_seating:Array = get_tree().get_nodes_in_group("char_seat")
|
||||
for char in characters_seating:
|
||||
char.get_node("AnimationPlayer").play("mixamo_com")
|
||||
char.get_node("AnimationPlayer").play("talk_seating")
|
||||
var mesh = char.get_node("Root").get_node("Skeleton3D").get_node("characterMedium")
|
||||
mesh.set_instance_shader_parameter("skin_index", randi_range(1, 16))
|
||||
|
||||
await get_tree().create_timer( randf_range(0.1, 1.5) ).timeout
|
||||
|
||||
|
||||
@@ -3,22 +3,27 @@ extends CharacterBody3D
|
||||
@onready var sprite_label: Sprite3D = $Sprite3D
|
||||
@onready var label: Label = $Sprite3D/SubViewport/Label
|
||||
@onready var area_3d: Area3D = $Area3D
|
||||
@onready var collision_shape_3d: CollisionShape3D = $Area3D/CollisionShape3D
|
||||
|
||||
@onready var anim_player: AnimationPlayer = $character/AnimationPlayer
|
||||
@onready var camera_zoom: Camera3D = $CameraZoom
|
||||
@onready var player: CharacterBody3D = $"../../Player"
|
||||
@onready var frog: CharacterBody3D = $"../../frog"
|
||||
@onready var area_3d_zoom: Area3D = $Area3DZoom
|
||||
|
||||
@onready var indicateur_tarte: CSGTorus3D = $"../indicateur_tarte"
|
||||
@onready var client_spawner: Node3D = $"../client_spawner"
|
||||
|
||||
@onready var fox: CharacterBody3D = $"../../Animals/Foxes/fox"
|
||||
@onready var fox_2: CharacterBody3D = $"../../Animals/Foxes/fox2"
|
||||
|
||||
var zoom_active : bool = false
|
||||
|
||||
func zoom_dialog():
|
||||
label.text = Sauvegarde.get_text("coco" + str( 0 ) )
|
||||
camera_zoom.make_current()
|
||||
zoom_active = true
|
||||
anim_player.play("RootAction")
|
||||
anim_player.play("talking")
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
if zoom_active:
|
||||
@@ -29,22 +34,31 @@ func _process(delta: float) -> void:
|
||||
player.camera.make_current()
|
||||
player.can_play = true
|
||||
|
||||
anim_player.stop()
|
||||
anim_player.play("Idling")
|
||||
|
||||
|
||||
func dialog():
|
||||
rotation.y = deg_to_rad( 180 )
|
||||
anim_player.play("RootAction")
|
||||
if !player.is_client_game_launched:
|
||||
rotation.y = deg_to_rad( 180 )
|
||||
anim_player.play("talking")
|
||||
|
||||
for i in range(1,3):
|
||||
var p
|
||||
if player.is_client_game_launched:
|
||||
p = range(4, 8)
|
||||
else:
|
||||
p = range(1, 4)
|
||||
for i in p:
|
||||
label.text = Sauvegarde.get_text("coco" + str( i ) )
|
||||
await get_tree().create_timer( 1 ).timeout
|
||||
await get_tree().create_timer( 6 ).timeout
|
||||
|
||||
anim_player.play("Idling")
|
||||
|
||||
rotation.y = deg_to_rad( -90 )
|
||||
if !player.is_client_game_launched:
|
||||
rotation.y = deg_to_rad( -90 )
|
||||
anim_player.stop()
|
||||
sprite_label.visible = false
|
||||
player.set_dialog_mode()
|
||||
player.is_client_game_launched = true
|
||||
|
||||
indicateur_tarte.visible = true
|
||||
client_spawner.start_timer()
|
||||
@@ -57,7 +71,7 @@ func _on_area_3d_body_entered(body: Node3D) -> void:
|
||||
sprite_label.visible = true
|
||||
player.set_dialog_mode( global_position, 0)
|
||||
dialog()
|
||||
area_3d.queue_free()
|
||||
collision_shape_3d.disabled = true
|
||||
|
||||
|
||||
func _on_area_3d_zoom_body_entered(body: Node3D) -> void:
|
||||
@@ -65,3 +79,11 @@ func _on_area_3d_zoom_body_entered(body: Node3D) -> void:
|
||||
player.can_play = false
|
||||
area_3d_zoom.queue_free()
|
||||
zoom_dialog()
|
||||
|
||||
func reactivate_area3D():
|
||||
collision_shape_3d.disabled = false
|
||||
anim_player.stop()
|
||||
fox.flee_enabled = true
|
||||
fox_2.flee_enabled = true
|
||||
player.can_run = true
|
||||
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
#@tool
|
||||
#extends EditorScript
|
||||
#
|
||||
#func _run():
|
||||
#var paths = [
|
||||
#"res://assets/img/textures/faces/face_bis1.png",
|
||||
#"res://assets/img/textures/faces/face_bis2.png",
|
||||
#"res://assets/img/textures/faces/face_bis3.png",
|
||||
#"res://assets/img/textures/faces/face_bis4.png",
|
||||
#"res://assets/img/textures/faces/face_bis5.png",
|
||||
#"res://assets/img/textures/faces/face_bis6.png",
|
||||
#"res://assets/img/textures/faces/face_bis7.png",
|
||||
#"res://assets/img/textures/faces/face_bis8.png",
|
||||
#"res://assets/img/textures/faces/face_bis9.png",
|
||||
#"res://assets/img/textures/faces/face_bis10.png",
|
||||
#"res://assets/img/textures/faces/face_bis11.png",
|
||||
#"res://assets/img/textures/faces/face_bis12.png",
|
||||
#"res://assets/img/textures/faces/face_bis13.png",
|
||||
#"res://assets/img/textures/faces/face_bis14.png",
|
||||
#"res://assets/img/textures/faces/face_bis15.png",
|
||||
#"res://assets/img/textures/faces/face_bis16.png",
|
||||
#]
|
||||
#var images: Array[Image] = []
|
||||
#for p in paths:
|
||||
#print("p: ", p)
|
||||
#images.append(load(p).get_image())
|
||||
#
|
||||
#var tex_array = Texture2DArray.new()
|
||||
#tex_array.create_from_images(images)
|
||||
#
|
||||
#ResourceSaver.save(tex_array, "res://assets/img/textures/faces.tres")
|
||||
#print("Saved skin_array.tres with ", images.size(), " layers")
|
||||
@@ -0,0 +1 @@
|
||||
uid://cy6xfc3foi1oy
|
||||
@@ -11,12 +11,13 @@ var player
|
||||
|
||||
func _ready() -> void:
|
||||
doggo_anim_player.play("sleep")
|
||||
anim_player.play("Idling")
|
||||
|
||||
func dialog():
|
||||
anim_player.play("RootAction")
|
||||
anim_player.play("talking")
|
||||
for i in range(1, 7):
|
||||
label.text = Sauvegarde.get_text("neige" + str( i ) )
|
||||
await get_tree().create_timer( 7 ).timeout
|
||||
await get_tree().create_timer( 5 ).timeout
|
||||
|
||||
anim_player.stop()
|
||||
sprite_label.visible = false
|
||||
@@ -27,7 +28,7 @@ func _on_area_3d_body_entered(body: Node3D) -> void:
|
||||
if body.is_in_group("player"):
|
||||
player = body
|
||||
sprite_label.visible = true
|
||||
player.set_dialog_mode( global_position, 0)
|
||||
player.set_dialog_mode( global_position)
|
||||
dialog()
|
||||
area_3d.queue_free()
|
||||
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
@tool
|
||||
extends EditorScript
|
||||
|
||||
# Path to your new NPC scene
|
||||
const NEW_NPC_SCENE := preload("res://scenes/character_seat_talking.tscn")
|
||||
|
||||
func _run():
|
||||
var root := get_scene()
|
||||
if root == null:
|
||||
push_error("Open the scene in the editor before running this script.")
|
||||
return
|
||||
|
||||
var seating := root.find_child("characters-seating", true, false)
|
||||
if seating == null:
|
||||
push_error("Could not find 'characters-seating' node.")
|
||||
return
|
||||
|
||||
var replaced := 0
|
||||
|
||||
for grp in seating.get_children():
|
||||
# Snapshot the children first, since we'll be modifying the group as we go
|
||||
var old_npcs := grp.get_children()
|
||||
|
||||
for old_npc in old_npcs:
|
||||
if not (old_npc is Node3D):
|
||||
push_warning(old_npc.name + " in " + grp.name + " is not a Node3D, skipping.")
|
||||
continue
|
||||
|
||||
var old_transform: Transform3D = old_npc.transform
|
||||
var old_name := old_npc.name
|
||||
|
||||
var new_npc: Node3D = NEW_NPC_SCENE.instantiate()
|
||||
|
||||
grp.remove_child(old_npc)
|
||||
old_npc.queue_free()
|
||||
|
||||
grp.add_child(new_npc)
|
||||
new_npc.owner = root
|
||||
new_npc.transform = old_transform
|
||||
new_npc.name = old_name
|
||||
|
||||
replaced += 1
|
||||
|
||||
print("Replaced ", replaced, " NPC(s).")
|
||||
@@ -0,0 +1 @@
|
||||
uid://btaqj1ucp5j8n
|
||||
+88
-29
@@ -5,26 +5,21 @@ enum State { ENTERING, WAITING, LEAVING }
|
||||
var current_state: State = State.ENTERING
|
||||
|
||||
# --- PARAMÈTRES ---
|
||||
@export var speed: float = 12
|
||||
@export var speed: float = 4
|
||||
@export var entry_path: Array[Marker3D]
|
||||
@export var exit_path: Array[Marker3D]
|
||||
|
||||
var current_path_index: int = 0
|
||||
|
||||
var possible_pies = [Sauvegarde.get_text("pie1"), Sauvegarde.get_text("pie2"), Sauvegarde.get_text("pie3")]
|
||||
var possible_toppings = [Sauvegarde.get_text("topping1"), Sauvegarde.get_text("topping2"), "Aucun"]
|
||||
var pie_icons = {
|
||||
Sauvegarde.get_text("pie1"): "res://assets/img/ui/client/orange.png",
|
||||
Sauvegarde.get_text("pie2"): "res://assets/img/ui/client/yellow.png",
|
||||
Sauvegarde.get_text("pie3"): "res://assets/img/ui/client/purple.png",
|
||||
}
|
||||
var topping_icons = {
|
||||
Sauvegarde.get_text("topping1"): "res://assets/img/ui/client/meringue.png",
|
||||
Sauvegarde.get_text("topping2"): "res://assets/img/ui/client/croisillon.png",
|
||||
}
|
||||
var possible_pies = []
|
||||
var possible_toppings = []
|
||||
var possible_language = [ Sauvegarde.language, "jap", "all", "jap", "all" ]
|
||||
var pie_icons = {}
|
||||
var topping_icons = {}
|
||||
|
||||
var desired_pie: String = ""
|
||||
var desired_topping: String = ""
|
||||
var choosen_lang : String = Sauvegarde.language
|
||||
|
||||
var ready_to_take_pie : bool = false
|
||||
|
||||
@@ -32,23 +27,64 @@ var ready_to_take_pie : bool = false
|
||||
@onready var sprite: Sprite3D = $Sprite3D
|
||||
@onready var label: RichTextLabel = $Sprite3D/SubViewport/RichTextLabel
|
||||
|
||||
@onready var mesh: MeshInstance3D = $character/Root/Skeleton3D/characterMedium
|
||||
|
||||
@onready var anim_player: AnimationPlayer = $character/AnimationPlayer
|
||||
|
||||
@onready var sprite_e: Sprite3D = $Sprite3DE
|
||||
|
||||
|
||||
var player # given by client_spwaner
|
||||
|
||||
var is_close_to_waiting = false
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
mesh.set_instance_shader_parameter("skin_index", randi_range(1, 16))
|
||||
|
||||
sprite.visible = false
|
||||
|
||||
if player.cpt_client > 1:
|
||||
choosen_lang = possible_language.pick_random()
|
||||
|
||||
possible_pies = [Sauvegarde.get_text("pie1", choosen_lang), Sauvegarde.get_text("pie2", choosen_lang), Sauvegarde.get_text("pie3", choosen_lang)]
|
||||
possible_toppings = [Sauvegarde.get_text("topping1", choosen_lang), Sauvegarde.get_text("topping2", choosen_lang), "Aucun"]
|
||||
|
||||
pie_icons = {
|
||||
Sauvegarde.get_text("pie1", choosen_lang): "res://assets/img/ui/client/orange.png",
|
||||
Sauvegarde.get_text("pie2", choosen_lang): "res://assets/img/ui/client/yellow.png",
|
||||
Sauvegarde.get_text("pie3", choosen_lang): "res://assets/img/ui/client/purple.png",
|
||||
}
|
||||
topping_icons = {
|
||||
Sauvegarde.get_text("topping1", choosen_lang): "res://assets/img/ui/client/meringue.png",
|
||||
Sauvegarde.get_text("topping2", choosen_lang): "res://assets/img/ui/client/croisillon.png",
|
||||
}
|
||||
|
||||
desired_pie = possible_pies.pick_random()
|
||||
desired_topping = possible_toppings.pick_random()
|
||||
|
||||
var p_icon
|
||||
var order_text
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
if !player.one_time_cpt_feather:
|
||||
queue_free()
|
||||
if not is_on_floor():
|
||||
velocity.y -= 9.8 * delta
|
||||
|
||||
|
||||
match current_state:
|
||||
State.ENTERING:
|
||||
if is_close_to_waiting:
|
||||
anim_player.play("talking")
|
||||
else:
|
||||
anim_player.play("walking")
|
||||
move_along_path(entry_path, delta)
|
||||
State.WAITING:
|
||||
anim_player.play("talking")
|
||||
velocity.x = move_toward(velocity.x, 0, speed)
|
||||
velocity.z = move_toward(velocity.z, 0, speed)
|
||||
State.LEAVING:
|
||||
anim_player.play("walking")
|
||||
move_along_path(exit_path, delta)
|
||||
|
||||
move_and_slide()
|
||||
@@ -61,7 +97,17 @@ func move_along_path(path_array: Array[Marker3D], delta: float) -> void:
|
||||
elif current_state == State.LEAVING:
|
||||
queue_free()
|
||||
return
|
||||
|
||||
|
||||
# special pour l'attente
|
||||
if current_path_index >= path_array.size()-1:
|
||||
var targ = path_array[current_path_index].global_position
|
||||
if global_position.distance_to(Vector3(targ.x, global_position.y, targ.z)) < 4:
|
||||
is_close_to_waiting = true
|
||||
else:
|
||||
is_close_to_waiting = false
|
||||
look_at( targ )
|
||||
|
||||
|
||||
var target = path_array[current_path_index].global_position
|
||||
var direction = global_position.direction_to(target)
|
||||
direction.y = 0
|
||||
@@ -81,14 +127,13 @@ func start_waiting() -> void:
|
||||
current_state = State.WAITING
|
||||
velocity = Vector3.ZERO
|
||||
|
||||
var p_icon = pie_icons[ desired_pie ]
|
||||
var order_text = Sauvegarde.get_text("desire") + desired_pie
|
||||
p_icon = pie_icons[ desired_pie ]
|
||||
order_text = Sauvegarde.get_text("desire", choosen_lang) + desired_pie
|
||||
order_text += " [img=60]" + p_icon + "[/img]"
|
||||
if desired_topping != "Aucun":
|
||||
var t_icon = topping_icons[ desired_topping ]
|
||||
order_text += "\n+ " + desired_topping + " [img=80]" + t_icon + "[/img]"
|
||||
set_dialogue(order_text)
|
||||
sprite.visible = true
|
||||
show_order()
|
||||
|
||||
# pour tests
|
||||
#await get_tree().create_timer( 3 ).timeout
|
||||
@@ -99,20 +144,25 @@ func give_item(pie_given: String, topping_given: String) -> void:
|
||||
if current_state != State.WAITING:
|
||||
return
|
||||
|
||||
#print("pie_given: ", pie_given, " | topping_given:", topping_given)
|
||||
#print("desired_pie: ", desired_pie, " | desired_topping:", desired_topping)
|
||||
sprite_e.visible = false
|
||||
|
||||
# On vérifie les deux conditions
|
||||
if pie_given == desired_pie and topping_given == desired_topping:
|
||||
set_dialogue( Sauvegarde.get_text("goodpie") )
|
||||
set_dialogue( Sauvegarde.get_text("goodpie", choosen_lang) )
|
||||
leave_store()
|
||||
elif pie_given == desired_pie and topping_given != desired_topping:
|
||||
set_dialogue( Sauvegarde.get_text("mixpie") )
|
||||
set_dialogue( Sauvegarde.get_text("mixpie", choosen_lang) )
|
||||
await get_tree().create_timer(4).timeout
|
||||
show_order()
|
||||
else:
|
||||
set_dialogue( Sauvegarde.get_text("badpie") )
|
||||
|
||||
leave_store()
|
||||
set_dialogue( Sauvegarde.get_text("badpie", choosen_lang) )
|
||||
await get_tree().create_timer(4).timeout
|
||||
show_order()
|
||||
|
||||
|
||||
func leave_store() -> void:
|
||||
player._end_action()
|
||||
|
||||
ready_to_take_pie = false
|
||||
await get_tree().create_timer(2.0).timeout
|
||||
sprite.visible = false
|
||||
@@ -121,7 +171,16 @@ func leave_store() -> void:
|
||||
|
||||
func set_dialogue(text: String) -> void:
|
||||
label.text = text
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
func show_order():
|
||||
set_dialogue(order_text)
|
||||
sprite.visible = true
|
||||
|
||||
func _on_area_3de_body_entered(body: Node3D) -> void:
|
||||
if body.is_in_group("player"):
|
||||
if current_state == State.WAITING:
|
||||
sprite_e.visible = true
|
||||
|
||||
func _on_area_3de_body_exited(body: Node3D) -> void:
|
||||
if body.is_in_group("player"):
|
||||
sprite_e.visible = false
|
||||
|
||||
@@ -8,18 +8,32 @@ extends Node3D
|
||||
@onready var timer: Timer = $Timer
|
||||
@onready var water_mill: MultiMeshInstance3D = $".."
|
||||
|
||||
@onready var player: CharacterBody3D = $"../../Player"
|
||||
@onready var frog: CharacterBody3D = $"../../frog"
|
||||
|
||||
var x_seconds: float = 15:
|
||||
set(value):
|
||||
x_seconds = value
|
||||
timer.wait_time = value
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
sprite_3d.visible = false
|
||||
|
||||
func _on_timer_timeout() -> void:
|
||||
func _on_timer_timeout() -> void:
|
||||
var new_client = client.instantiate()
|
||||
new_client.player = player
|
||||
water_mill.add_child(new_client)
|
||||
|
||||
new_client.global_position = global_position
|
||||
|
||||
new_client.entry_path = entry_path
|
||||
new_client.exit_path = exit_path
|
||||
|
||||
player._start_action()
|
||||
|
||||
if !player.one_time_cpt_feather:
|
||||
timer.stop()
|
||||
|
||||
func start_timer():
|
||||
timer.start()
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
extends Control
|
||||
|
||||
@onready var all: Control = $ALL
|
||||
@onready var musique: AudioStreamPlayer2D = $Musique
|
||||
|
||||
var can_scroll : bool = false
|
||||
var one_time_menu : bool = true
|
||||
|
||||
func _ready() -> void:
|
||||
AudioServer.set_bus_volume_db(2, 0) # reset car fade out durant cinematique
|
||||
musique.play()
|
||||
await get_tree().create_timer( 3 ).timeout
|
||||
can_scroll = true
|
||||
|
||||
Sauvegarde.can_see_credit = true
|
||||
|
||||
await get_tree().create_timer( 33 ).timeout
|
||||
musique.stream = load("res://assets/audio/music/menu.wav")
|
||||
musique.play()
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
if can_scroll:
|
||||
if all.position.y > -2900:
|
||||
all.position.y -= delta * 1000
|
||||
elif one_time_menu:
|
||||
one_time_menu = false
|
||||
await get_tree().create_timer( 5 ).timeout
|
||||
Transition.change_scene("res://ui/menu.tscn")
|
||||
|
||||
func _input(event: InputEvent) -> void:
|
||||
if event is InputEventMouseButton:
|
||||
if event.button_index == MOUSE_BUTTON_LEFT and event.pressed:
|
||||
Transition.change_scene("res://ui/menu.tscn")
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
uid://wxjumpbfy7sr
|
||||
@@ -0,0 +1,17 @@
|
||||
extends CharacterBody3D
|
||||
|
||||
@export var texture : CompressedTexture2D
|
||||
|
||||
@onready var anim_player: AnimationPlayer = $character/AnimationPlayer
|
||||
@onready var mesh_instance: MeshInstance3D = $character/Root/Skeleton3D/characterMedium
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
var mat = mesh_instance.mesh.surface_get_material(0)
|
||||
|
||||
var new_mat: StandardMaterial3D = mat.duplicate()
|
||||
new_mat.albedo_texture = texture
|
||||
mesh_instance.set_surface_override_material(0, new_mat)
|
||||
|
||||
await get_tree().create_timer( randf_range(1.0, 2.5) ).timeout
|
||||
anim_player.play("talking")
|
||||
@@ -0,0 +1 @@
|
||||
uid://cv3koo5rdgsgv
|
||||
+37
-10
@@ -2,23 +2,32 @@ extends CanvasLayer
|
||||
|
||||
@onready var game_area: ColorRect = $BackGround/GameArea
|
||||
@onready var target_rect: ColorRect = $BackGround/GameArea/TargetRect
|
||||
@onready var feather: ColorRect = $BackGround/GameArea/Feather
|
||||
@onready var feather: TextureRect = $BackGround/GameArea/Feather
|
||||
|
||||
@onready var player: CharacterBody3D = $".."
|
||||
@onready var frog: CharacterBody3D = $"../../frog"
|
||||
|
||||
@onready var audio_player: AudioStreamPlayer2D = $AudioStreamPlayer2D
|
||||
|
||||
|
||||
var cpt_col : int = -1
|
||||
var is_playing : bool = false
|
||||
var is_flashing : bool = false
|
||||
var default_target_color : Color = Color(1.0, 1.0, 1.0, 0.6)
|
||||
var tween : Tween
|
||||
|
||||
var one_time : bool = true
|
||||
var first_time : bool = true
|
||||
|
||||
func _ready():
|
||||
hide()
|
||||
target_rect.color = default_target_color
|
||||
|
||||
func _input(event):
|
||||
if Input.is_action_just_pressed("ui_accept") and player.can_play:
|
||||
if one_time:
|
||||
one_time = false
|
||||
player.tuto.show_text( "tuto2", true)
|
||||
toggle_minigame()
|
||||
|
||||
# Contrôle de la plume avec la souris (uniquement sur Y)
|
||||
@@ -31,17 +40,30 @@ func toggle_minigame():
|
||||
is_playing = !is_playing
|
||||
if is_playing:
|
||||
show()
|
||||
|
||||
AudioServer.set_bus_effect_enabled( 0, 0, true )
|
||||
AudioServer.set_bus_volume_db( 2, AudioServer.get_bus_volume_db(2)-20 )
|
||||
|
||||
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
|
||||
player.camera_pov.make_current()
|
||||
target_rect.position.y = game_area.size.y - target_rect.size.y
|
||||
|
||||
await get_tree().create_timer( 2 ).timeout
|
||||
if first_time:
|
||||
await get_tree().create_timer( 15 ).timeout
|
||||
first_time = false
|
||||
else:
|
||||
await get_tree().create_timer( 2 ).timeout
|
||||
if is_playing:
|
||||
player.can_play = false
|
||||
|
||||
|
||||
|
||||
get_tree().paused = true
|
||||
start_pattern()
|
||||
else:
|
||||
AudioServer.set_bus_effect_enabled( 0, 0, false )
|
||||
AudioServer.set_bus_volume_db( 2, AudioServer.get_bus_volume_db(2)+20 )
|
||||
|
||||
get_tree().paused = false
|
||||
player.can_play = true
|
||||
player.camera.make_current()
|
||||
hide()
|
||||
@@ -54,13 +76,15 @@ func toggle_minigame():
|
||||
return
|
||||
cpt_col/= 2
|
||||
if cpt_col < 2:
|
||||
frog.size = 1
|
||||
frog.size = .5
|
||||
elif cpt_col == 2 or cpt_col == 3:
|
||||
if frog.size > 1.5:
|
||||
frog.size = 1.5
|
||||
if frog.size > .7:
|
||||
frog.size = .7
|
||||
else:
|
||||
if frog.size > 2:
|
||||
frog.size = 2
|
||||
|
||||
player.cpt_feather += 1
|
||||
|
||||
|
||||
func start_pattern():
|
||||
@@ -72,13 +96,15 @@ func start_pattern():
|
||||
else:
|
||||
return
|
||||
|
||||
audio_player.play()
|
||||
|
||||
var bottom_y = game_area.size.y - target_rect.size.y
|
||||
var top_y = 0.0
|
||||
|
||||
tween.tween_property(target_rect, "position:y", top_y, 5)
|
||||
tween.tween_interval(4.0)
|
||||
tween.tween_property(target_rect, "position:y", bottom_y, 5)
|
||||
tween.tween_interval(4.0)
|
||||
tween.tween_property(target_rect, "position:y", top_y, 5) # 5
|
||||
tween.tween_interval(4.0) # 4
|
||||
tween.tween_property(target_rect, "position:y", bottom_y, 5) # 5
|
||||
tween.tween_interval(4.0) # 4
|
||||
|
||||
await tween.finished
|
||||
if cpt_col == -1:
|
||||
@@ -88,6 +114,7 @@ func start_pattern():
|
||||
|
||||
|
||||
func _process(delta):
|
||||
|
||||
if not is_playing:
|
||||
return
|
||||
|
||||
|
||||
+38
-4
@@ -1,13 +1,13 @@
|
||||
extends CharacterBody3D
|
||||
|
||||
@export var player: Node3D
|
||||
@export var follow_speed: float = 4.0
|
||||
@export var follow_speed: float = 5.6
|
||||
@export var right_offset: float = 2.5
|
||||
@export var forward_offset: float = 1
|
||||
@export var car_cinematic : bool = false
|
||||
|
||||
@onready var anim_player: AnimationPlayer = $frog/AnimationPlayer
|
||||
var size : float = 0.5
|
||||
var size : float = .7
|
||||
|
||||
@onready var arms: MeshInstance3D = $frog/Armature/Skeleton3D/arms
|
||||
@onready var body: MeshInstance3D = $frog/Armature/Skeleton3D/body
|
||||
@@ -17,10 +17,18 @@ var size : float = 0.5
|
||||
@onready var legs: MeshInstance3D = $frog/Armature/Skeleton3D/legs
|
||||
@onready var mesh = [ arms, body, eyes, feet, hands, legs ]
|
||||
|
||||
@onready var audio_player: AudioStreamPlayer3D = $AudioStreamPlayer3D
|
||||
@onready var frog_launch_step = load("res://assets/audio/sound-effects/frog/frog_launch_step.mp3")
|
||||
@onready var frog_quiet_step = load("res://assets/audio/sound-effects/frog/frog_quiet_step.mp3")
|
||||
@onready var frog_loud_step = load("res://assets/audio/sound-effects/frog/frog_loud_step.wav")
|
||||
|
||||
@onready var audio_croak: AudioStreamPlayer3D = $AudioCroak
|
||||
@onready var croak_timer: Timer = $CroakTimer
|
||||
|
||||
# Variables pour la gravité
|
||||
var gravity = ProjectSettings.get_setting("physics/3d/default_gravity")
|
||||
|
||||
var can_scale : bool = false
|
||||
|
||||
func _ready() -> void:
|
||||
if !car_cinematic:
|
||||
scale = Vector3( size, size, size )
|
||||
@@ -42,10 +50,18 @@ func _process(delta: float) -> void:
|
||||
func _physics_process(delta):
|
||||
if not player or car_cinematic:
|
||||
return
|
||||
|
||||
if can_scale:
|
||||
if player.is_client_game_launched:
|
||||
size += 0.00025
|
||||
else:
|
||||
size += 0.00012
|
||||
|
||||
|
||||
# Appliquer la gravité
|
||||
if not is_on_floor():
|
||||
velocity.y -= gravity * delta
|
||||
|
||||
|
||||
var target_position = player.global_position + (player.global_transform.basis.x * right_offset) + (-player.global_transform.basis.z * forward_offset)
|
||||
global_position.y = target_position.y
|
||||
@@ -73,12 +89,13 @@ func _physics_process(delta):
|
||||
var real_speed = Vector2(get_real_velocity().x, get_real_velocity().z).length()
|
||||
# Si frog n'est pas bloquée par un mur
|
||||
if real_speed > 0.1:
|
||||
size += 0.0
|
||||
if anim_player.current_animation != "walk":
|
||||
anim_player.play("walk", 0.2)
|
||||
_play_jump_sound()
|
||||
else:
|
||||
if anim_player.current_animation != "idle":
|
||||
anim_player.play("idle", 0.2)
|
||||
_play_land_sound()
|
||||
|
||||
move_and_slide()
|
||||
|
||||
@@ -87,3 +104,20 @@ func scale_frog():
|
||||
var final_scale = Vector3(size, size, size)
|
||||
|
||||
tween.tween_property(self, "scale", final_scale, 2)
|
||||
|
||||
func _play_jump_sound() -> void:
|
||||
audio_player.stream = frog_launch_step
|
||||
audio_player.play()
|
||||
|
||||
func _play_land_sound() -> void:
|
||||
if size < 2:
|
||||
audio_player.stream = frog_quiet_step
|
||||
else:
|
||||
audio_player.stream = frog_loud_step
|
||||
audio_player.play()
|
||||
|
||||
func _on_timer_timeout() -> void:
|
||||
croak_timer.wait_time = randf_range(30, 45)
|
||||
audio_croak.pitch_scale = randf_range( .9, 1.1 )
|
||||
audio_croak.play()
|
||||
|
||||
|
||||
+90
-5
@@ -1,5 +1,11 @@
|
||||
extends Node
|
||||
|
||||
var player
|
||||
var corinne
|
||||
var music_player # pour balavoine
|
||||
|
||||
# pour corinne-help
|
||||
|
||||
func _ready() -> void:
|
||||
#Dialogic.timeline_ended.connect(set_player_cam)
|
||||
pass
|
||||
@@ -9,9 +15,88 @@ func change_cinematic_cam(camera_name:String):
|
||||
for cam in all_cinematic_cams:
|
||||
if cam.name == camera_name:
|
||||
cam.make_current()
|
||||
# car cinematic
|
||||
if cam.name == "deathseat":
|
||||
var audio = cam.get_parent().get_node("AudioStreamPlayer3D")
|
||||
audio.stream = load("res://assets/audio/sound-effects/car/inside-car.mp3")
|
||||
audio.play()
|
||||
elif cam.name == "road_view":
|
||||
var audio = cam.get_parent().get_node("AudioStreamPlayer3D")
|
||||
audio.stream = load("res://assets/audio/sound-effects/car/outside-car.wav")
|
||||
audio.play()
|
||||
elif cam.name == "frog_view":
|
||||
var audio = cam.get_parent().get_node("AudioStreamPlayer3D")
|
||||
audio.stream = load("res://assets/audio/sound-effects/car/inside-car.mp3")
|
||||
audio.play()
|
||||
elif cam.name == "top_view":
|
||||
var audio = cam.get_parent().get_node("AudioStreamPlayer3D")
|
||||
audio.stream = load("res://assets/audio/sound-effects/car/outside-car.wav")
|
||||
audio.play()
|
||||
|
||||
# other cinematics
|
||||
elif cam.name == "croissants":
|
||||
corinne = get_tree().get_first_node_in_group("corinne")
|
||||
var marker_player = cam.get_node("MarkerPlayer")
|
||||
var marker_corinne = cam.get_node("MarkerCorinne")
|
||||
|
||||
player.global_position = marker_player.global_position
|
||||
player.global_rotation = marker_player.global_rotation
|
||||
|
||||
func set_player_cam():
|
||||
return
|
||||
var player = get_tree().get_first_node_in_group("player")
|
||||
if player:
|
||||
player.set_default_cam()
|
||||
corinne.global_position = marker_corinne.global_position
|
||||
corinne.global_rotation = marker_corinne.global_rotation
|
||||
player.anim_player.play("Idling")
|
||||
corinne.anim_player.play("Idling")
|
||||
|
||||
music_player.global_position = cam.global_position
|
||||
elif cam.name == "stairs":
|
||||
var path_follow = cam.get_node("Path3D").get_node("PathFollow3D")
|
||||
corinne.reparent( path_follow )
|
||||
corinne.position = Vector3.ZERO
|
||||
corinne.rotation = Vector3.ZERO
|
||||
|
||||
var tween := create_tween()
|
||||
tween.tween_property(path_follow, "progress_ratio", 1.0, 35)
|
||||
tween.finished.connect( corinne.reactivate_area3D )
|
||||
corinne.anim_player.play( "walking" )
|
||||
|
||||
music_player.global_position = cam.global_position
|
||||
elif cam.name == "large":
|
||||
var marker_player = cam.get_node("MarkerPlayer")
|
||||
|
||||
#player = get_tree().get_first_node_in_group("player")
|
||||
#corinne = get_tree().get_first_node_in_group("corinne")
|
||||
#music_player = player.musique
|
||||
|
||||
player.global_position = marker_player.global_position
|
||||
player.global_rotation = marker_player.global_rotation
|
||||
|
||||
music_player.global_position = cam.global_position
|
||||
elif cam.name == "watermill":
|
||||
music_player.global_position = cam.global_position
|
||||
elif cam.name == "city":
|
||||
var marker_player = cam.get_node("MarkerPlayer")
|
||||
var marker_corinne = cam.get_node("MarkerCorinne")
|
||||
|
||||
player.global_position = marker_player.global_position
|
||||
player.global_rotation = marker_player.global_rotation
|
||||
|
||||
corinne.global_position = marker_corinne.global_position
|
||||
corinne.global_rotation = marker_corinne.global_rotation
|
||||
player.anim_player.play("Idling")
|
||||
corinne.anim_player.play("Idling")
|
||||
|
||||
music_player.global_position = cam.global_position
|
||||
|
||||
return
|
||||
|
||||
|
||||
func set_player_cam(pov:bool=true):
|
||||
if !player:
|
||||
player = get_tree().get_first_node_in_group("player")
|
||||
if pov:
|
||||
player.set_pov_cam()
|
||||
else:
|
||||
player.set_default_cam()
|
||||
music_player = player.musique
|
||||
player.reset_musique_position()
|
||||
|
||||
|
||||
+44
-24
@@ -3,20 +3,27 @@ extends Node3D
|
||||
@onready var camera: Camera3D = $Camera3D
|
||||
|
||||
# BOUTONS
|
||||
@onready var start: Button = $HBoxContainer/Start
|
||||
@onready var quit: Button = $HBoxContainer/Quit
|
||||
@onready var credit: Button = $HBoxContainer/Credit
|
||||
@onready var start: Button = $MenuUI/HBoxContainer/Start
|
||||
@onready var quit: Button = $MenuUI/HBoxContainer/Quit
|
||||
@onready var credit: Button = $MenuUI/HBoxContainer/Credit
|
||||
|
||||
@onready var fr: TextureButton = $HBoxContainer/fr
|
||||
@onready var en: TextureButton = $HBoxContainer/en
|
||||
@onready var screen: Button = $HBoxContainer2/Screen
|
||||
@onready var fr: TextureButton = $MenuUI/HBoxContainer/fr
|
||||
@onready var en: TextureButton = $MenuUI/HBoxContainer/en
|
||||
@onready var screen: Button = $MenuUI/HBoxContainer2/Screen
|
||||
|
||||
@onready var credit_label: Label = $Sprite3D/SubViewport/credit_label
|
||||
@onready var credit_label: Label = $MenuUI/Sprite3D/SubViewport/credit_label
|
||||
|
||||
var but_credit_exist : bool = true
|
||||
@onready var car: Node3D = $partie3D/car
|
||||
@onready var anim_player_car: AnimationPlayer = $partie3D/car/AnimationPlayer
|
||||
@onready var anim_player_char: AnimationPlayer = $partie3D/car/player_driving/AnimationPlayer
|
||||
|
||||
@onready var musique: AudioStreamPlayer3D = $Musique
|
||||
|
||||
# pour option
|
||||
@onready var menu_ui: Control = $MenuUI
|
||||
@onready var option: CanvasLayer = $Option
|
||||
@onready var optionexit: Button = $Option/optionexit
|
||||
|
||||
var cible_rot_y
|
||||
var cible_rot_x
|
||||
|
||||
func _ready() -> void:
|
||||
Sauvegarde.is_in_menu = true
|
||||
@@ -26,10 +33,18 @@ func _ready() -> void:
|
||||
en.texture_normal = preload("uid://bdcehsogmfiv2")
|
||||
fr.texture_normal = preload("uid://dusujvur4igj4")
|
||||
screen.text = Sauvegarde.get_text("window_screen")
|
||||
if Sauvegarde.can_see_credit:
|
||||
credit.visible = true
|
||||
else:
|
||||
credit.visible = false
|
||||
|
||||
cible_rot_y = deg_to_rad( 147.8 )
|
||||
cible_rot_x = deg_to_rad( -6.1 )
|
||||
anim_player_car.play("driving")
|
||||
anim_player_char.play("driving")
|
||||
|
||||
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
car.position.z += 16 * delta
|
||||
|
||||
func _on_start_pressed() -> void:
|
||||
get_tree().change_scene_to_file( "res://scenes/main.scn" )
|
||||
@@ -38,15 +53,8 @@ func _on_start_pressed() -> void:
|
||||
func _on_quit_pressed() -> void:
|
||||
get_tree().quit()
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
camera.rotation.y = lerp_angle(camera.rotation.y, cible_rot_y, 3 * delta)
|
||||
camera.rotation.x = lerp_angle(camera.rotation.x, cible_rot_x, 3 * delta)
|
||||
|
||||
func _on_credit_pressed() -> void:
|
||||
cible_rot_y = deg_to_rad(100)
|
||||
cible_rot_x = deg_to_rad(16)
|
||||
credit.queue_free()
|
||||
but_credit_exist = false
|
||||
Transition.change_scene("res://ui/credit.tscn")
|
||||
|
||||
|
||||
func _on_fr_pressed() -> void:
|
||||
@@ -73,11 +81,23 @@ func load_lang(l):
|
||||
Sauvegarde.language = l
|
||||
start.text = Sauvegarde.get_text("start")
|
||||
quit.text = Sauvegarde.get_text("quit")
|
||||
if but_credit_exist :
|
||||
credit.text = Sauvegarde.get_text("credit")
|
||||
credit.text = Sauvegarde.get_text("credit")
|
||||
optionexit.text = Sauvegarde.get_text("resume")
|
||||
|
||||
if get_window().mode == Window.MODE_FULLSCREEN:
|
||||
screen.text = Sauvegarde.get_text("window_screen")
|
||||
else:
|
||||
screen.text = Sauvegarde.get_text("full_screen")
|
||||
|
||||
credit_label.text = Sauvegarde.get_text("credit_detail")
|
||||
|
||||
|
||||
func _on_timer_timeout() -> void:
|
||||
musique.play()
|
||||
|
||||
|
||||
func _on_option_pressed() -> void:
|
||||
option.visible = true
|
||||
menu_ui.visible = false
|
||||
|
||||
func _on_optionexit_pressed() -> void:
|
||||
option.visible = false
|
||||
menu_ui.visible = true
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
extends CanvasLayer
|
||||
|
||||
@onready var h_slider_master: HSlider = $VBoxContainer/HSliderMaster
|
||||
@onready var h_slider_music: HSlider = $VBoxContainer/HSliderMusic
|
||||
@onready var h_slider_effects: HSlider = $VBoxContainer/HSliderEffects
|
||||
|
||||
@onready var label: Label = $VBoxContainer/Label
|
||||
@onready var label_2: Label = $VBoxContainer/Label2
|
||||
@onready var label_3: Label = $VBoxContainer/Label3
|
||||
|
||||
func _ready() -> void:
|
||||
h_slider_master.value = db_to_linear( AudioServer.get_bus_volume_db(0) )
|
||||
h_slider_music.value = db_to_linear( AudioServer.get_bus_volume_db(2) )
|
||||
h_slider_effects.value = db_to_linear( AudioServer.get_bus_volume_db(1) )
|
||||
|
||||
label.text = Sauvegarde.get_text("option_master")
|
||||
label_2.text = Sauvegarde.get_text("option_music")
|
||||
label_3.text = Sauvegarde.get_text("option_effects")
|
||||
|
||||
func _on_h_slider_master_value_changed(value: float) -> void:
|
||||
AudioServer.set_bus_volume_db( 0, linear_to_db( value ) )
|
||||
|
||||
func _on_h_slider_music_value_changed(value: float) -> void:
|
||||
AudioServer.set_bus_volume_db( 2, linear_to_db( value ) )
|
||||
|
||||
func _on_h_slider_effects_value_changed(value: float) -> void:
|
||||
AudioServer.set_bus_volume_db( 1, linear_to_db( value ) )
|
||||
@@ -0,0 +1 @@
|
||||
uid://b5tyf08t05tdo
|
||||
+20
-10
@@ -1,39 +1,49 @@
|
||||
extends Control
|
||||
extends CanvasLayer
|
||||
|
||||
# Buttons
|
||||
@onready var resume_but: Button = $ColorRect/PanelContainer/VBoxContainer/Resume
|
||||
@onready var restart: Button = $ColorRect/PanelContainer/VBoxContainer/Restart
|
||||
@onready var menu: Button = $ColorRect/PanelContainer/VBoxContainer/Menu
|
||||
@onready var continuer: Button = $Option/Continuer
|
||||
|
||||
@onready var color_rect: ColorRect = $ColorRect
|
||||
@onready var option: CanvasLayer = $Option
|
||||
|
||||
func _ready() -> void:
|
||||
hide()
|
||||
$AnimationPlayer.play("RESET")
|
||||
|
||||
resume_but.text = Sauvegarde.get_text("resume")
|
||||
restart.text = Sauvegarde.get_text("restart")
|
||||
menu.text = Sauvegarde.get_text("menu")
|
||||
|
||||
continuer.text = Sauvegarde.get_text("resume")
|
||||
|
||||
func resume():
|
||||
get_tree().paused = false
|
||||
hide()
|
||||
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
|
||||
$AnimationPlayer.play_backwards("blur")
|
||||
|
||||
AudioServer.set_bus_effect_enabled( 1, 0, false )
|
||||
|
||||
func pause():
|
||||
get_tree().paused = true
|
||||
show()
|
||||
Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
|
||||
$AnimationPlayer.play("blur")
|
||||
|
||||
AudioServer.set_bus_effect_enabled( 1, 0, true )
|
||||
|
||||
|
||||
func _on_resume_pressed() -> void:
|
||||
resume()
|
||||
|
||||
func _on_restart_pressed() -> void:
|
||||
resume()
|
||||
get_tree().reload_current_scene()
|
||||
|
||||
|
||||
func _on_menu_pressed() -> void:
|
||||
get_tree().paused = false
|
||||
get_tree().change_scene_to_file( "res://scenes/menu.tscn" )
|
||||
Transition.change_scene("res://ui/menu.tscn")
|
||||
|
||||
func _on_option_pressed() -> void:
|
||||
color_rect.visible = false
|
||||
option.visible = true
|
||||
|
||||
func _on_button_pressed() -> void:
|
||||
color_rect.visible = true
|
||||
option.visible = false
|
||||
|
||||
+128
-24
@@ -1,10 +1,11 @@
|
||||
extends CharacterBody3D
|
||||
|
||||
|
||||
var SPEED = 7
|
||||
var speed = 6
|
||||
|
||||
@onready var arm: Node3D = $arm
|
||||
@onready var model: Node3D = $model
|
||||
@onready var mesh_instance: MeshInstance3D = $character/Root/Skeleton3D/characterMedium
|
||||
|
||||
# GESTION CAMERA --------------------------
|
||||
@onready var spring_arm: SpringArm3D = $arm/SpringArm3D
|
||||
@@ -17,15 +18,16 @@ var third_person : bool = true
|
||||
|
||||
@onready var audio_footstep: AudioStreamPlayer3D = $Audio_Footstep
|
||||
var footstep_sounds: Array[AudioStream] = [
|
||||
preload("res://assets/audio/footsteps/dirt_step_1.wav"),
|
||||
preload("res://assets/audio/footsteps/dirt_step_2.wav"),
|
||||
preload("res://assets/audio/footsteps/dirt_step_3.wav"),
|
||||
preload("res://assets/audio/footsteps/dirt_step_4.wav")
|
||||
preload("res://assets/audio/sound-effects/footsteps/dirt_step_1.wav"),
|
||||
preload("res://assets/audio/sound-effects/footsteps/dirt_step_2.wav"),
|
||||
preload("res://assets/audio/sound-effects/footsteps/dirt_step_3.wav"),
|
||||
preload("res://assets/audio/sound-effects/footsteps/dirt_step_4.wav")
|
||||
]
|
||||
var footstep_timer: float = 0.0
|
||||
const FOOTSTEP_DELAY: float = 0.24
|
||||
var FOOTSTEP_DELAY: float = 0.35
|
||||
|
||||
@onready var pause: Control = $pause
|
||||
@onready var pause: CanvasLayer = $pause
|
||||
@onready var tuto: CanvasLayer = $tuto
|
||||
|
||||
# animations
|
||||
@onready var anim_player: AnimationPlayer = $character/AnimationPlayer
|
||||
@@ -35,6 +37,36 @@ var item : int = 0 # 0 rien, 1 abricot, 2 citron, 3 mirtylle
|
||||
var topping : int = 0 # 0 rien, 1 meringue, 2 croisillon
|
||||
@onready var area_tarte: Area3D = $Area3DTarte
|
||||
@onready var tarte_holded: StaticBody3D = $tarte
|
||||
# tps pour servir un client
|
||||
@onready var client_spawner: Node3D = $"../WaterMILL/client_spawner"
|
||||
var action_start_time: int = 0
|
||||
func _start_action() -> void:
|
||||
action_start_time = Time.get_ticks_msec()
|
||||
func _end_action() -> void:
|
||||
var duration_ms := Time.get_ticks_msec() - action_start_time
|
||||
var duration_sec := duration_ms / 1000.0
|
||||
if duration_sec < 6:
|
||||
duration_sec = 6
|
||||
elif duration_sec > 35:
|
||||
duration_sec = 34
|
||||
client_spawner.x_seconds = duration_sec
|
||||
|
||||
var cpt_client : int = 0
|
||||
var is_client_game_launched : bool = false
|
||||
var one_time_client_game : bool = true
|
||||
var one_time_cpt_feather : bool = true
|
||||
var cpt_feather : int = 0
|
||||
|
||||
var one_time_fox_grabbed : bool = true
|
||||
var fox_grabbed : int = 0
|
||||
var can_run : bool = false
|
||||
|
||||
@onready var frog: CharacterBody3D = $"../frog"
|
||||
@onready var area_3d_tuto_3: Area3D = $"../WaterMILL/Area3DTuto3"
|
||||
|
||||
@onready var musique: AudioStreamPlayer3D = $Musique
|
||||
@onready var zip_effect: AudioStreamPlayer3D = $ZipEffect
|
||||
|
||||
|
||||
var can_play : bool = true
|
||||
|
||||
@@ -48,6 +80,9 @@ func _ready():
|
||||
camera_pov.make_current()
|
||||
model.visible = false
|
||||
|
||||
await get_tree().create_timer( .5 ).timeout
|
||||
tuto.show_text( "tuto1" )
|
||||
|
||||
func _input(_event):
|
||||
if Input.is_action_just_pressed("ui_cancel"):
|
||||
if !get_tree().paused:
|
||||
@@ -66,6 +101,7 @@ func _process(delta: float) -> void:
|
||||
if obj.get_parent().ready_to_take_pie:
|
||||
var l = get_conversion_pie()
|
||||
obj.get_parent().give_item( l[0], l[1] )
|
||||
cpt_client += 1
|
||||
|
||||
reset_pie()
|
||||
return
|
||||
@@ -77,19 +113,42 @@ func _process(delta: float) -> void:
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
#print("global position; ", global_position)
|
||||
|
||||
|
||||
if can_run:
|
||||
speed = 8
|
||||
FOOTSTEP_DELAY = 0.25
|
||||
|
||||
if is_client_game_launched:
|
||||
if one_time_client_game:
|
||||
var mat = mesh_instance.mesh.surface_get_material(0)
|
||||
mat.albedo_texture = load("res://assets/img/textures/faces/player_employe.png")
|
||||
mesh_instance.set_surface_override_material(0, mat)
|
||||
zip_effect.play()
|
||||
|
||||
cpt_feather = 0
|
||||
one_time_client_game = false
|
||||
if cpt_feather == 2:
|
||||
if one_time_cpt_feather:
|
||||
AudioServer.set_bus_volume_db( 1, -10.0)
|
||||
musique.stream = load("res://assets/audio/music/Daniel Balavoine - Tous les cris les S.O.S.mp3")
|
||||
musique.play()
|
||||
set_dialog_mode( Vector3.ZERO, true )
|
||||
Dialogic.start("corinne_help")
|
||||
Dialogic.timeline_ended.connect( corinne_help_cinematic_end )
|
||||
one_time_cpt_feather = false
|
||||
if fox_grabbed == 2:
|
||||
if one_time_fox_grabbed:
|
||||
set_dialog_mode( Vector3.ZERO, true )
|
||||
Dialogic.start("fin")
|
||||
Dialogic.timeline_ended.connect( fin_cinematic_end )
|
||||
one_time_fox_grabbed = false
|
||||
fade_out_music()
|
||||
|
||||
if not is_on_floor():
|
||||
velocity += get_gravity() * delta
|
||||
|
||||
# Get the input direction and handle the movement/deceleration.
|
||||
var input_dir := Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
|
||||
#var direction := (transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
|
||||
#if direction:
|
||||
#velocity.x = direction.x * SPEED
|
||||
#velocity.z = direction.z * SPEED
|
||||
#else:
|
||||
#velocity.x = move_toward(velocity.x, 0, SPEED)
|
||||
#velocity.z = move_toward(velocity.z, 0, SPEED)
|
||||
|
||||
if input_dir.length() < 0.1:
|
||||
input_dir = Vector2.ZERO
|
||||
@@ -98,9 +157,12 @@ func _physics_process(delta: float) -> void:
|
||||
# On ne déplace et on ne tourne le joueur que si une vraie direction est donnée
|
||||
if can_play:
|
||||
if direction.length() > 0.1:
|
||||
anim_player.play("RootAction_001", -1, 3)
|
||||
velocity.x = direction.x * SPEED
|
||||
velocity.z = direction.z * SPEED
|
||||
if can_run:
|
||||
anim_player.play("walking", -1, 2)
|
||||
else:
|
||||
anim_player.play("walking", -1, 1.5)
|
||||
velocity.x = direction.x * speed
|
||||
velocity.z = direction.z * speed
|
||||
|
||||
# 2. CORRECTION DE LA ROTATION INVERSÉE
|
||||
# Si le joueur tourne toujours à l'envers, enlève les signes "-" devant velocity.x et velocity.z
|
||||
@@ -109,10 +171,10 @@ func _physics_process(delta: float) -> void:
|
||||
# Le 10.0 est bien, il permet au modèle 3D de se tourner vite sans faire de coup sec.
|
||||
rotation.y = lerp_angle(rotation.y, target_angle, 10.0 * delta)
|
||||
else:
|
||||
anim_player.stop()
|
||||
anim_player.play("Idling")
|
||||
# Le joueur s'arrête doucement
|
||||
velocity.x = move_toward(velocity.x, 0, SPEED)
|
||||
velocity.z = move_toward(velocity.z, 0, SPEED)
|
||||
velocity.x = move_toward(velocity.x, 0, speed)
|
||||
velocity.z = move_toward(velocity.z, 0, speed)
|
||||
else:
|
||||
anim_player.stop()
|
||||
|
||||
@@ -128,7 +190,34 @@ func _physics_process(delta: float) -> void:
|
||||
|
||||
if can_play:
|
||||
move_and_slide()
|
||||
|
||||
|
||||
func corinne_help_cinematic_end():
|
||||
set_dialog_mode( Vector3.ZERO, true )
|
||||
set_default_cam()
|
||||
frog.size = .5
|
||||
frog.can_scale = false
|
||||
|
||||
func fade_out_music() -> void:
|
||||
var fade_tween = create_tween()
|
||||
|
||||
if fade_tween and fade_tween.is_valid():
|
||||
fade_tween.kill()
|
||||
|
||||
var start_db := AudioServer.get_bus_volume_db(2)
|
||||
|
||||
fade_tween = create_tween()
|
||||
fade_tween.tween_method(
|
||||
func(db: float): AudioServer.set_bus_volume_db(2, db),
|
||||
start_db,
|
||||
-20,
|
||||
30
|
||||
)
|
||||
|
||||
func fin_cinematic_end():
|
||||
Sauvegarde.can_see_credit = true
|
||||
Transition.change_scene("res://ui/credit.tscn")
|
||||
|
||||
|
||||
# PARTIE BOULANGERIE MOULIN
|
||||
func set_item_topping( new_item : int, new_topping : int, reset:bool ):
|
||||
if reset:
|
||||
@@ -169,12 +258,27 @@ func play_random_footstep( pitch=[0.85, 1.15] ) -> void:
|
||||
audio_footstep.pitch_scale = randf_range( pitch[0], pitch[1] )
|
||||
audio_footstep.play()
|
||||
|
||||
func set_dialog_mode( npc_pos=Vector3.ZERO, force_pos=-1):
|
||||
func set_dialog_mode( npc_pos=Vector3.ZERO, is_cinematic=false):
|
||||
can_play = !can_play
|
||||
spring_arm.set_dialog_mode( npc_pos, force_pos )
|
||||
if !is_cinematic:
|
||||
spring_arm.set_dialog_mode( npc_pos)
|
||||
anim_player.play("talking")
|
||||
|
||||
func set_default_cam():
|
||||
if third_person:
|
||||
camera.set_current(true)
|
||||
else:
|
||||
camera_pov.set_current(true)
|
||||
|
||||
func set_pov_cam():
|
||||
camera_pov.set_current(true)
|
||||
|
||||
func reset_musique_position():
|
||||
await get_tree().create_timer( .2 ).timeout
|
||||
musique.global_position = global_position
|
||||
musique.volume_db += 10
|
||||
|
||||
func _on_area_3d_tuto_3_body_entered(body: Node3D) -> void:
|
||||
if body.is_in_group("player"):
|
||||
tuto.show_text( "tuto3", true)
|
||||
area_3d_tuto_3.queue_free()
|
||||
|
||||
@@ -3,6 +3,8 @@ var is_in_menu : bool = false
|
||||
|
||||
var language = "fr"
|
||||
|
||||
var can_see_credit : bool = false
|
||||
|
||||
var trad
|
||||
func _ready() -> void:
|
||||
var file = FileAccess.open("res://lang.json", FileAccess.READ)
|
||||
@@ -11,5 +13,5 @@ func _ready() -> void:
|
||||
var error = json.parse(json_text)
|
||||
trad = json.data
|
||||
|
||||
func get_text(key):
|
||||
return trad[language][key]
|
||||
func get_text(key, lang=language):
|
||||
return trad[lang][key]
|
||||
|
||||
+34
-29
@@ -3,15 +3,15 @@ extends SpringArm3D
|
||||
@onready var player: CharacterBody3D = $"../.."
|
||||
|
||||
# --- Paramètres de mouvement ---
|
||||
@export var max_follow_speed: float = 3.0
|
||||
@export var speed_acceleration: float = 2.0
|
||||
@export var max_follow_speed: float = 3
|
||||
@export var speed_acceleration: float = 2.5
|
||||
@export var height_offset: float = 2.5
|
||||
@export var wait_time: float = 0.5
|
||||
|
||||
# --- Paramètres de Dialogue ---
|
||||
@export var dialog_zoom_length: float = 2.0
|
||||
@export var dialog_side_offset: float = 1.0
|
||||
@export var transition_speed: float = 4.0 # Gère la vitesse du zoom, du décalage ET de la rotation en dialog
|
||||
@export var dialog_zoom_length: float = 3.5
|
||||
@export var dialog_side_offset: float = 2.0
|
||||
@export var transition_speed: float = 4.0
|
||||
|
||||
@onready var normal_spring_length: float = spring_length
|
||||
|
||||
@@ -21,25 +21,26 @@ var current_side_offset: float = 0.0
|
||||
var target_side_offset: float = 0.0
|
||||
var is_in_dialog: bool = false
|
||||
|
||||
# Variables pour le dialogue
|
||||
var dialog_target_position: Vector3 = Vector3.ZERO
|
||||
var target_dialog_rotation_y: float = 0.0
|
||||
var dialog_weight: float = 0.0 # Permet une transition ultra-fluide (0.0 = Exploration, 1.0 = Dialogue)
|
||||
|
||||
func _ready() -> void:
|
||||
top_level = true
|
||||
|
||||
func set_dialog_mode(npc_position: Vector3 = Vector3.ZERO, force_pos=-1) -> void:
|
||||
func set_dialog_mode(npc_position: Vector3 = Vector3.ZERO) -> void:
|
||||
is_in_dialog = !is_in_dialog
|
||||
|
||||
if is_in_dialog:
|
||||
var direction_to_npc = (npc_position - player.global_position).normalized()
|
||||
var right_dot = global_transform.basis.x.dot(direction_to_npc)
|
||||
dialog_target_position = npc_position
|
||||
|
||||
if right_dot >= 0 :
|
||||
target_side_offset = dialog_side_offset
|
||||
else:
|
||||
target_side_offset = -dialog_side_offset
|
||||
|
||||
if force_pos == 0 :
|
||||
target_side_offset = dialog_side_offset
|
||||
elif force_pos == 1 :
|
||||
target_side_offset = -dialog_side_offset
|
||||
var dir_to_npc = (npc_position - player.global_position)
|
||||
dir_to_npc.y = 0
|
||||
dir_to_npc = dir_to_npc.normalized()
|
||||
|
||||
target_dialog_rotation_y = atan2(-dir_to_npc.x, -dir_to_npc.z)
|
||||
target_side_offset = dialog_side_offset
|
||||
else:
|
||||
target_side_offset = 0.0
|
||||
|
||||
@@ -47,22 +48,23 @@ func _physics_process(delta: float) -> void:
|
||||
if not is_instance_valid(player):
|
||||
return
|
||||
|
||||
var target_rotation_y = player.global_rotation.y
|
||||
# Mise à jour progressive du poids de transition du dialogue (de 0 à 1)
|
||||
var target_weight = 1.0 if is_in_dialog else 0.0
|
||||
dialog_weight = lerp(dialog_weight, target_weight, transition_speed * delta)
|
||||
|
||||
# ==========================================
|
||||
# 1. GESTION DE LA ROTATION (Avant la position !)
|
||||
# 1. GESTION DE LA ROTATION
|
||||
# ==========================================
|
||||
if is_in_dialog:
|
||||
if is_in_dialog or dialog_weight > 0.01:
|
||||
delay_timer = 0.3
|
||||
current_follow_speed = 0.5
|
||||
|
||||
# La caméra tourne doucement pour se mettre dans le dos du joueur.
|
||||
# On utilise transition_speed pour que ça se finisse en même temps que le zoom.
|
||||
global_rotation.y = lerp_angle(global_rotation.y, target_rotation_y, transition_speed * delta)
|
||||
# On interpole la rotation vers l'angle de dialogue en utilisant le poids
|
||||
global_rotation.y = lerp_angle(global_rotation.y, target_dialog_rotation_y, transition_speed * delta)
|
||||
|
||||
else:
|
||||
if not is_in_dialog and dialog_weight <= 0.01:
|
||||
var target_rotation_y = player.global_rotation.y
|
||||
if player.can_play:
|
||||
# Comportement normal d'exploration (Le vieux Zelda)
|
||||
var angle_diff = abs(angle_difference(global_rotation.y, target_rotation_y))
|
||||
|
||||
if angle_diff > 0.02 and player.velocity.length() > 0.1:
|
||||
@@ -77,15 +79,18 @@ func _physics_process(delta: float) -> void:
|
||||
|
||||
|
||||
# ==========================================
|
||||
# 2. GESTION DU ZOOM ET DU DECALAGE
|
||||
# 2. GESTION DU ZOOM, DU DECALAGE ET DE LA POSITION
|
||||
# ==========================================
|
||||
var target_length = dialog_zoom_length if is_in_dialog else normal_spring_length
|
||||
|
||||
spring_length = lerp(spring_length, target_length, transition_speed * delta)
|
||||
current_side_offset = lerp(current_side_offset, target_side_offset, transition_speed * delta)
|
||||
|
||||
# On récupère le vecteur "Droite" MAINTENANT, car la rotation vient juste d'être mise à jour au-dessus.
|
||||
var right_direction = global_transform.basis.x
|
||||
|
||||
# On applique la position finale (Joueur + Hauteur + Décalage latéral)
|
||||
global_position = player.global_position + Vector3(0, height_offset, 0) + (right_direction * current_side_offset)
|
||||
# Transition fluide du point de pivot (de la position du joueur vers le point intermédiaire du dialogue)
|
||||
var normal_base = player.global_position
|
||||
var dialog_base = player.global_position.lerp(dialog_target_position, 0.3)
|
||||
var current_base = normal_base.lerp(dialog_base, dialog_weight)
|
||||
|
||||
global_position = current_base + Vector3(0, height_offset, 0) + (right_direction * current_side_offset)
|
||||
|
||||
@@ -12,6 +12,8 @@ extends StaticBody3D
|
||||
|
||||
@onready var label: Label = $Sprite3D/SubViewport/Label
|
||||
|
||||
@onready var sprite_e: Sprite3D = $Sprite3DE
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready() -> void:
|
||||
setup_color_and_name()
|
||||
@@ -53,3 +55,13 @@ func _reset():
|
||||
creme_myrtille.visible = false
|
||||
meringue.visible = false
|
||||
croisillon.visible = false
|
||||
|
||||
|
||||
func _on_area_3e_body_entered(body: Node3D) -> void:
|
||||
if body.is_in_group("player"):
|
||||
sprite_e.visible = true
|
||||
|
||||
|
||||
func _on_area_3e_body_exited(body: Node3D) -> void:
|
||||
if body.is_in_group("player"):
|
||||
sprite_e.visible = false
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
extends CanvasLayer
|
||||
|
||||
@onready var label: Label = $VBoxContainer/Label
|
||||
@onready var player: CharacterBody3D = $".."
|
||||
@onready var continue_button: Button = $continue
|
||||
|
||||
@onready var frog: CharacterBody3D = $"../../frog"
|
||||
|
||||
var paused
|
||||
|
||||
func _ready() -> void:
|
||||
continue_button.text = Sauvegarde.get_text("tuto_continue")
|
||||
|
||||
func show_text( text, pause=false ):
|
||||
layer = 2
|
||||
paused = pause
|
||||
if paused:
|
||||
get_tree().paused = true
|
||||
else:
|
||||
player.can_play = false
|
||||
show()
|
||||
Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
|
||||
label.text = Sauvegarde.get_text( text )
|
||||
|
||||
func _on_button_pressed() -> void:
|
||||
if paused:
|
||||
get_tree().paused = false
|
||||
if label.text[0] == "E":
|
||||
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
|
||||
hide()
|
||||
layer = 0
|
||||
await get_tree().create_timer( 20 ).timeout
|
||||
frog.can_scale = true
|
||||
else:
|
||||
player.can_play = true
|
||||
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
|
||||
hide()
|
||||
layer = 0
|
||||
@@ -0,0 +1 @@
|
||||
uid://cvbdr64ea5ieu
|
||||
Reference in New Issue
Block a user