полнценая система прогресаа и конца уровне с началом и концом
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
[gd_scene format=3 uid="uid://cxckcssgallbx"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://dux8o5uwin1sy" path="res://addons/Misc/Scripts/level_trigger.gd" id="1_1g6t3"]
|
||||
[ext_resource type="ArrayMesh" uid="uid://dflmd4037fdqa" path="res://addons/custmode/untitled.obj" id="1_tam0r"]
|
||||
|
||||
[sub_resource type="SphereShape3D" id="SphereShape3D_pmktt"]
|
||||
|
||||
[sub_resource type="SphereShape3D" id="SphereShape3D_a2m1y"]
|
||||
radius = 6.0
|
||||
|
||||
[node name="LevelTrigger" type="StaticBody3D" unique_id=549172302]
|
||||
script = ExtResource("1_1g6t3")
|
||||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="." unique_id=1715081297]
|
||||
transform = Transform3D(6.355, 0, 0, 0, 6.355, 0, 0, 0, 6.355, 0, 0, 0)
|
||||
shape = SubResource("SphereShape3D_pmktt")
|
||||
|
||||
[node name="MeshInstance3D" type="MeshInstance3D" parent="CollisionShape3D" unique_id=1423996988]
|
||||
transform = Transform3D(0.06, 0, 0, 0, 0.06, 0, 0, 0, 0.06, 0, -0.47206923, 0)
|
||||
mesh = ExtResource("1_tam0r")
|
||||
|
||||
[node name="DetectArea" type="Area3D" parent="." unique_id=1314234424]
|
||||
collision_layer = 0
|
||||
collision_mask = 15
|
||||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="DetectArea" unique_id=1390638580]
|
||||
shape = SubResource("SphereShape3D_a2m1y")
|
||||
@@ -0,0 +1,57 @@
|
||||
[gd_scene format=3 uid="uid://c1v246tyt6bng"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://bojftnghiqd2g" path="res://addons/Misc/Scripts/results_screen.gd" id="1_esv6s"]
|
||||
|
||||
[node name="ResultsScreen" type="CanvasLayer" unique_id=2101110637]
|
||||
layer = 1000000000
|
||||
script = ExtResource("1_esv6s")
|
||||
|
||||
[node name="TitleLabel" type="Label" parent="." unique_id=864255331]
|
||||
anchors_preset = -1
|
||||
anchor_left = 0.586
|
||||
anchor_top = 0.45200002
|
||||
anchor_right = 0.586
|
||||
anchor_bottom = 0.45200002
|
||||
offset_left = -84.07202
|
||||
offset_top = -113.89603
|
||||
offset_right = 82.92798
|
||||
offset_bottom = -90.89603
|
||||
text = "УРОВЕНЬ ЗАВЕРШЕН"
|
||||
|
||||
[node name="KillsLabel" type="Label" parent="." unique_id=1676098116]
|
||||
anchors_preset = -1
|
||||
anchor_left = 0.56700003
|
||||
anchor_top = 0.43300003
|
||||
anchor_right = 0.56700003
|
||||
anchor_bottom = 0.43300003
|
||||
offset_left = -69.18402
|
||||
offset_top = 62.415985
|
||||
offset_right = 68.81598
|
||||
offset_bottom = 85.415985
|
||||
text = "Убито врагов: 0\"."
|
||||
|
||||
[node name="TimeLabel" type="Label" parent="." unique_id=466879962]
|
||||
anchors_preset = -1
|
||||
anchor_left = 0.60200006
|
||||
anchor_top = 0.46500003
|
||||
anchor_right = 0.60200006
|
||||
anchor_bottom = 0.46500003
|
||||
offset_left = -108.50409
|
||||
offset_top = 84.67999
|
||||
offset_right = 108.49591
|
||||
offset_bottom = 107.67999
|
||||
text = "Время прохождения: 00:00"
|
||||
|
||||
[node name="ContinueButton" type="Button" parent="." unique_id=1156988049]
|
||||
anchors_preset = -1
|
||||
anchor_left = 0.586
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.586
|
||||
anchor_bottom = 0.5
|
||||
offset_left = -92.07202
|
||||
offset_top = 122.0
|
||||
offset_right = 57.92798
|
||||
offset_bottom = 180.0
|
||||
text = "Далее"
|
||||
|
||||
[connection signal="pressed" from="ContinueButton" to="." method="_on_continue_button_pressed"]
|
||||
@@ -0,0 +1,65 @@
|
||||
extends Node
|
||||
|
||||
# Хранилище данных, которое живет между уровнями
|
||||
var saved_health: float = 100.0
|
||||
var saved_weapons: Array = []
|
||||
var saved_weapon_index: int = 0
|
||||
var saved_ammo_dict: Dictionary = {}
|
||||
|
||||
var is_transfer_ready: bool = false # Флаг, что у нас есть сохраненные данные
|
||||
|
||||
# --- ФУНКЦИЯ 1: СОХРАНЕНИЕ ДАННЫХ ПЕРЕД СМЕНОЙ СЦЕНЫ ---
|
||||
func save_player_data(player: Node) -> void:
|
||||
if player == null: return
|
||||
|
||||
# 1. Запоминаем Здоровье
|
||||
var health_comp = player.find_child("HealthComponent", true, false)
|
||||
if health_comp:
|
||||
saved_health = health_comp.current_health
|
||||
|
||||
# 2. Запоминаем Оружие и Патроны
|
||||
# Найди этот блок внутри save_player_data в GameTransfer.gd:
|
||||
var weapon_manager = player.find_child("WeaponManager", true, false)
|
||||
if weapon_manager:
|
||||
saved_weapons = weapon_manager.weaponStack.duplicate()
|
||||
saved_weapon_index = weapon_manager.weaponIndex
|
||||
|
||||
# ИСПРАВЛЕНО: Более глубокий поиск менеджера патронов, если автор спрятал его в детях
|
||||
var ammo_manager = weapon_manager.find_child("AmmoManager", true, false)
|
||||
if ammo_manager == null and "ammoManager" in weapon_manager:
|
||||
ammo_manager = weapon_manager.ammoManager
|
||||
|
||||
if ammo_manager and "ammoDict" in ammo_manager:
|
||||
saved_ammo_dict = ammo_manager.ammoDict.duplicate()
|
||||
|
||||
|
||||
is_transfer_ready = true
|
||||
print("[ПЕРЕНОС] Данные игрока успешно сохранены в кэш!")
|
||||
|
||||
# --- ФУНКЦИЯ 2: ВОССТАНОВЛЕНИЕ ДАННЫХ НА НОВОМ УРОВНЕ ---
|
||||
func load_player_data(player: Node) -> void:
|
||||
if player == null or not is_transfer_ready: return
|
||||
|
||||
# 1. Возвращаем Здоровье
|
||||
var health_comp = player.find_child("HealthComponent", true, false)
|
||||
if health_comp:
|
||||
health_comp.current_health = saved_health
|
||||
# Обновляем цифры на новом HUD
|
||||
var health_ui = player.find_child("PlayerHealthUI", true, false)
|
||||
if health_ui and health_ui.has_method("_process"):
|
||||
health_ui.notification(NOTIFICATION_PROCESS)
|
||||
|
||||
# 2. Возвращаем Оружие и Патроны
|
||||
var weapon_manager = player.find_child("WeaponManager", true, false)
|
||||
if weapon_manager:
|
||||
weapon_manager.weaponStack = saved_weapons.duplicate()
|
||||
weapon_manager.weaponIndex = saved_weapon_index
|
||||
|
||||
if "ammoManager" in weapon_manager and weapon_manager.ammoManager:
|
||||
weapon_manager.ammoManager.ammoDict = saved_ammo_dict.duplicate()
|
||||
|
||||
# Принудительно заставляем ассет достать правильное оружие из памяти
|
||||
if weapon_manager.has_method("changeWeapon"):
|
||||
weapon_manager.changeWeapon(saved_weapon_index)
|
||||
|
||||
print("[ПЕРЕНОС] Снаряжение и ХП успешно возвращены игроку на новом уровне!")
|
||||
@@ -0,0 +1 @@
|
||||
uid://dbnkrmxycgjrl
|
||||
@@ -0,0 +1,30 @@
|
||||
extends Node
|
||||
|
||||
var current_kills: int = 0
|
||||
var level_time: float = 0.0
|
||||
var is_timer_running: bool = false
|
||||
|
||||
func _ready() -> void:
|
||||
start_level_tracking()
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
if is_timer_running:
|
||||
level_time += delta
|
||||
|
||||
func start_level_tracking() -> void:
|
||||
current_kills = 0
|
||||
level_time = 0.0
|
||||
is_timer_running = true
|
||||
|
||||
func stop_level_tracking() -> void:
|
||||
is_timer_running = false
|
||||
|
||||
func register_kill() -> void:
|
||||
current_kills += 1
|
||||
print("[СТАТИСТИКА] Моб уничтожен! Всего убийств: ", current_kills)
|
||||
|
||||
# Функция для красивого форматирования времени (например, 01:23)
|
||||
func get_formatted_time() -> String:
|
||||
var minutes = int(level_time) / 60
|
||||
var seconds = int(level_time) % 60
|
||||
return "%02d:%02d" % [minutes, seconds]
|
||||
@@ -0,0 +1 @@
|
||||
uid://jbvxvnmbrhe8
|
||||
@@ -0,0 +1,55 @@
|
||||
extends StaticBody3D
|
||||
|
||||
@export_file("*.tscn") var next_scene_path: String = ""
|
||||
var is_triggered: bool = false
|
||||
var detect_area: Area3D = null
|
||||
|
||||
@export var results_screen_scene: PackedScene
|
||||
|
||||
func _ready() -> void:
|
||||
detect_area = $DetectArea
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
if is_triggered or detect_area == null:
|
||||
return
|
||||
|
||||
var overlapping_stuff: Array = []
|
||||
overlapping_stuff.append_array(detect_area.get_overlapping_bodies())
|
||||
overlapping_stuff.append_array(detect_area.get_overlapping_areas())
|
||||
|
||||
for node in overlapping_stuff:
|
||||
if node == self or node == detect_area or node is StaticBody3D or "CSG" in node.name:
|
||||
continue
|
||||
|
||||
var is_real_player = node.name == "PlayerCharacter"
|
||||
if not is_real_player and node.get_parent():
|
||||
is_real_player = node.get_parent().name == "PlayerCharacter"
|
||||
|
||||
if is_real_player:
|
||||
is_triggered = true
|
||||
print("[УРОВЕНЬ] МГНОВЕННЫЙ ФИНИШ! Полностью блокирую камеру и открываю курсор...")
|
||||
|
||||
# Отключаем сам триггер
|
||||
set_physics_process(false)
|
||||
|
||||
# Находим корневой узел игрока
|
||||
var main_player = node if node.name == "PlayerCharacter" else node.get_parent()
|
||||
|
||||
# --- МГНОВЕННАЯ ЗАМОРОЗКА ИНПУТОВ КАМЕРЫ И ОРУЖИЯ ---
|
||||
# Переводим игрока в режим PROCESS_MODE_DISABLED.
|
||||
# Это мгновенно отключает у него функции _process, _physics_process и ВСЕ _input функции мыши!
|
||||
# Камера намертво каменеет в ту же секунду, без необходимости кликать кнопками.
|
||||
if main_player:
|
||||
main_player.process_mode = Node.PROCESS_MODE_DISABLED
|
||||
# ----------------------------------------------------
|
||||
|
||||
# Аппаратно освобождаем мышь для клика по кнопке "Далее"
|
||||
Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
|
||||
|
||||
# Спавним экран результатов в корень игры
|
||||
if results_screen_scene:
|
||||
var results_instance = results_screen_scene.instantiate()
|
||||
get_tree().get_root().add_child(results_instance)
|
||||
if results_instance.has_method("show_results"):
|
||||
results_instance.show_results(next_scene_path)
|
||||
return
|
||||
@@ -0,0 +1 @@
|
||||
uid://dux8o5uwin1sy
|
||||
@@ -0,0 +1,79 @@
|
||||
extends CanvasLayer
|
||||
|
||||
var target_scene_path: String = ""
|
||||
|
||||
func _ready() -> void:
|
||||
# Ставим максимальный слой отрисовки, чтобы HUD игры не перекрывал меню
|
||||
layer = 120
|
||||
if has_node("Panel"):
|
||||
$Panel.visible = true
|
||||
print("[РЕЗУЛЬТАТЫ] Экран итогов успешно создан прямо на карте!")
|
||||
|
||||
func show_results(next_scene: String) -> void:
|
||||
target_scene_path = next_scene
|
||||
print("[РЕЗУЛЬТАТЫ] Данные получены. Путь к следующей сцене: ", target_scene_path)
|
||||
|
||||
# Останавливаем таймер уровня
|
||||
if LevelStats:
|
||||
LevelStats.stop_level_tracking()
|
||||
|
||||
# БРОНЕБОЙНОЕ ОБНОВЛЕНИЕ ТЕКСТА: Ищем узлы прямо в момент вызова функции
|
||||
var kills_label = find_child("KillsLabel", true, false)
|
||||
if kills_label == null: kills_label = find_child("kills_label", true, false)
|
||||
if kills_label:
|
||||
kills_label.text = "Убито врагов: " + str(LevelStats.current_kills)
|
||||
print("[РЕЗУЛЬТАТЫ] Текст убийств обновлен: ", kills_label.text)
|
||||
|
||||
var time_label = find_child("TimeLabel", true, false)
|
||||
if time_label == null: time_label = find_child("time_label", true, false)
|
||||
if time_label:
|
||||
time_label.text = "Время прохождения: " + LevelStats.get_formatted_time()
|
||||
print("[РЕЗУЛЬТАТЫ] Текст времени обновлен: ", time_label.text)
|
||||
|
||||
# ПРИНУДИТЕЛЬНО РАЗРЕШАЕМ ДВИГАТЬ КУРСОР МЫШИ
|
||||
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
|
||||
|
||||
func _on_continue_button_pressed() -> void:
|
||||
print("[РЕЗУЛЬТАТЫ] Кнопка 'Далее' зафиксирована! Запускаю плавное затемнение...")
|
||||
|
||||
if target_scene_path == "":
|
||||
print("[РЕЗУЛЬТАТЫ] ОШИБКА: Путь к следующей сцене пустой!")
|
||||
return
|
||||
|
||||
# --- НАШЕ КРИТИЧЕСКОЕ ДОБАВЛЕНИЕ: СОХРАНЯЕМ ИГРОКА ПЕРЕД УХОДОМ В ЗАТЕМНЕНИЕ ---
|
||||
var player = get_tree().current_scene.find_child("PlayerCharacter", true, false)
|
||||
if player and GameTransfer:
|
||||
GameTransfer.save_player_data(player)
|
||||
# --------------------------------------------------------------------------------
|
||||
|
||||
# Твой старый код затемнения и смены сцены...
|
||||
var fade_rect = find_child("FadeRect", true, false)
|
||||
if fade_rect and "visible" in fade_rect:
|
||||
fade_rect.visible = true
|
||||
fade_rect.modulate.a = 0.0
|
||||
var tween = create_tween()
|
||||
tween.tween_property(fade_rect, "modulate:a", 1.0, 1.0)
|
||||
await tween.finished
|
||||
|
||||
_set_ui_elements_visible(false)
|
||||
if LevelStats: LevelStats.start_level_tracking()
|
||||
|
||||
queue_free()
|
||||
get_tree().change_scene_to_file(target_scene_path)
|
||||
|
||||
# Полностью замени функцию в самом конце results_screen.gd на этот код:
|
||||
func _set_ui_elements_visible(is_visible: bool) -> void:
|
||||
# Находим и переключаем надпись убийств
|
||||
var k_label = find_child("KillsLabel", true, false)
|
||||
if k_label == null: k_label = find_child("kills_label", true, false)
|
||||
if k_label: k_label.visible = is_visible
|
||||
|
||||
# Находим и переключаем надпись времени
|
||||
var t_label = find_child("TimeLabel", true, false)
|
||||
if t_label == null: t_label = find_child("time_label", true, false)
|
||||
if t_label: t_label.visible = is_visible
|
||||
|
||||
# Находим и переключаем кнопку продолжения
|
||||
var c_button = find_child("ContinueButton", true, false)
|
||||
if c_button == null: c_button = find_child("continue_button", true, false)
|
||||
if c_button: c_button.visible = is_visible
|
||||
@@ -0,0 +1 @@
|
||||
uid://bojftnghiqd2g
|
||||
Reference in New Issue
Block a user