diff --git a/Assets/Prefabs/FixSystemPrefabs/Clinic System.prefab b/Assets/Prefabs/FixSystemPrefabs/Clinic System.prefab index 891b751a1..8e80287e3 100644 --- a/Assets/Prefabs/FixSystemPrefabs/Clinic System.prefab +++ b/Assets/Prefabs/FixSystemPrefabs/Clinic System.prefab @@ -1406,11 +1406,64 @@ Transform: m_Children: - {fileID: 3619849418667778924} - {fileID: 6121709156540084727} + - {fileID: 9102307160016725311} - {fileID: 6249684167985838438} - {fileID: 7931034805346183671} - {fileID: 6274499368345295635} m_Father: {fileID: 9073824794961298310} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &9102307160016725310 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 9102307160016725311} + - component: {fileID: 9102307160016725312} + m_Layer: 0 + m_Name: Actor Entrance + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &9102307160016725311 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 9102307160016725310} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: -1.55, y: 0.15, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 9111904319609796187} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &9102307160016725312 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 9102307160016725310} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: bbc0dde0e8b8a9c498545e1b5b508241, type: 3} + m_Name: + m_EditorClassIdentifier: + data: + slotPosition: {x: 0, y: 0, z: 0} + actorRole: 2 + idx: 1 + maxWidth: 800 + minWidth: 300 + bubbleStyle: {fileID: 11400000, guid: e3f425b45fd35cc4caf1939eaea2f7bc, type: 2} + pivotType: 5 --- !u!1 &5345859371557614914 GameObject: m_ObjectHideFlags: 0 diff --git a/Assets/Prefabs/FixSystemPrefabs/维修面板.prefab b/Assets/Prefabs/FixSystemPrefabs/维修面板.prefab index 6d9719f77..26f0b0989 100644 --- a/Assets/Prefabs/FixSystemPrefabs/维修面板.prefab +++ b/Assets/Prefabs/FixSystemPrefabs/维修面板.prefab @@ -8626,6 +8626,9 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: environmentLight: {fileID: 7098573010793440161} + deepEnvironmentLight: {fileID: 3788564698077470635} + deepEnvironmentNormalIntensity: 0.9 + deepEnvironmentAlpha: 0.8509804 isEnvironmentLightFlickering: 0 normalEnvironmentIntensity: 2 warningEnvironmentIntensity: 1.25 @@ -8646,6 +8649,10 @@ MonoBehaviour: warningAlarmLightColor: {r: 1, g: 0.42, b: 0.35, a: 1} alarmBlinkSpeed: 0.5 alarmLightColor: {r: 1, g: 0, b: 0, a: 1} + emergencyIntroDipDuration: 0.08 + emergencyIntroRiseDuration: 0.18 + emergencyOutroDuration: 0.18 + emergencyIntroDipIntensityScale: 0.55 --- !u!1 &7297538176355823427 GameObject: m_ObjectHideFlags: 0 diff --git a/Assets/Scripts/FixSystemNew/Open/OpenYarnCommand.cs b/Assets/Scripts/FixSystemNew/Open/OpenYarnCommand.cs index 1b066d37a..2415b2017 100644 --- a/Assets/Scripts/FixSystemNew/Open/OpenYarnCommand.cs +++ b/Assets/Scripts/FixSystemNew/Open/OpenYarnCommand.cs @@ -16,6 +16,12 @@ namespace AibisDream.FixSystem ShockSystem.StartCoroutine(ShockSystem.PlayFlashEffect()); } + [YarnCommand("play_shock_flash_and_wait")] + public static IEnumerator PlayShockFlashAndWait() + { + yield return ShockSystem.PlayFlashEffect(); + } + [YarnCommand("play_shock_flashback")] public static IEnumerator PlayShockFlashback(string imagePath) { @@ -69,4 +75,4 @@ namespace AibisDream.FixSystem ShockSystem.SetAbnormalState(false); } } -} \ No newline at end of file +} diff --git a/Assets/Scripts/FixSystemNew/Screen System/Core/FixPanelLight.cs b/Assets/Scripts/FixSystemNew/Screen System/Core/FixPanelLight.cs index 037235e1f..a5e8b1453 100644 --- a/Assets/Scripts/FixSystemNew/Screen System/Core/FixPanelLight.cs +++ b/Assets/Scripts/FixSystemNew/Screen System/Core/FixPanelLight.cs @@ -28,6 +28,8 @@ namespace AibisDream.FixSystem private const float ALARM_LIGHT_MAX_INTENSITY = 4f; private const float MIN_FLICKER_BLINK_COUNT = 2; private const float MAX_FLICKER_BLINK_COUNT = 4; + private const string PANEL_LIGHT_ON_SFX = "event:/ActionFB/light_flicker_on"; + private const string PANEL_LIGHT_OFF_SFX = "event:/ActionFB/light_flicker_off"; private const float MIN_FLICKER_INTERVAL = 3f; private const float MAX_FLICKER_INTERVAL = 8f; @@ -37,6 +39,9 @@ namespace AibisDream.FixSystem [Header("环境灯设置")] [SerializeField] private Light2D environmentLight; + [SerializeField] private Light2D deepEnvironmentLight; + [SerializeField, Min(0.01f)] private float deepEnvironmentNormalIntensity = 0.9f; + [SerializeField, Range(0f, 1f)] private float deepEnvironmentAlpha = 0.8509804f; [SerializeField] private bool isEnvironmentLightFlickering = false; [SerializeField] private float normalEnvironmentIntensity = 2f; [SerializeField] private float warningEnvironmentIntensity = 1.25f; @@ -62,15 +67,29 @@ namespace AibisDream.FixSystem [SerializeField] private float alarmBlinkSpeed = 0.5f; [SerializeField] private Color alarmLightColor = Color.red; + [Header("紧急状态转场")] + [SerializeField] private float emergencyIntroDipDuration = 0.08f; + [SerializeField] private float emergencyIntroRiseDuration = 0.18f; + [SerializeField] private float emergencyOutroDuration = 0.18f; + [SerializeField, Range(0f, 1f)] private float emergencyIntroDipIntensityScale = 0.55f; + private Tween alarmTween; + private Tween lightStateTransitionTween; private LightState currentState = LightState.Normal; #endregion #region 生命周期 + private void LateUpdate() + { + SyncDeepEnvironmentLight(); + } + private void OnDisable() { + lightStateTransitionTween?.Kill(); + lightStateTransitionTween = null; StopAlarmLight(); StopAllCoroutines(); } @@ -79,9 +98,54 @@ namespace AibisDream.FixSystem #region 光照系统 - 公共方法 - public void Initialize(bool isSystemOn) + public void Initialize(bool isSystemOn, LightState state = LightState.Normal) { - panelLight.intensity = isSystemOn ? panelLightIntensity : 0f; + lightStateTransitionTween?.Kill(); + lightStateTransitionTween = null; + alarmTween?.Kill(); + alarmTween = null; + StopAllCoroutines(); + + currentState = state; + + if (!isSystemOn) + { + if (panelLight != null) + { + panelLight.color = panelLightColor; + panelLight.intensity = 0f; + } + if (environmentLight != null) + { + environmentLight.color = normalEnvironmentColor; + environmentLight.intensity = SYSTEM_OFF_ENVIRONMENT_INTENSITY; + } + if (alarmLight != null) + { + alarmLight.intensity = 0f; + } + SyncDeepEnvironmentLight(); + return; + } + + UpdateLightsState(); + if (isEnvironmentLightFlickering) + { + StartCoroutine(EnvironmentLightFlickerRoutine()); + } + SyncDeepEnvironmentLight(); + } + + private void SyncDeepEnvironmentLight() + { + if (deepEnvironmentLight == null || environmentLight == null) return; + + Color deepColor = environmentLight.color; + deepColor.a = deepEnvironmentAlpha; + deepEnvironmentLight.color = deepColor; + float intensityRatio = Mathf.Max(0f, + environmentLight.intensity / Mathf.Max(0.01f, normalEnvironmentIntensity)); + deepEnvironmentLight.intensity = deepEnvironmentNormalIntensity * intensityRatio; } /// @@ -91,8 +155,9 @@ namespace AibisDream.FixSystem { if (currentState != newState) { + LightState previousState = currentState; currentState = newState; - UpdateLightsState(); + TransitionLightsState(previousState, newState); Debug.Log($"灯光状态已切换为: {newState}"); } } @@ -150,6 +215,8 @@ namespace AibisDream.FixSystem // 如果当前正在闪烁,立即使用新速度重启。 if (currentState != LightState.Normal && alarmLight != null) { + lightStateTransitionTween?.Kill(); + lightStateTransitionTween = null; StartAlarmLightBlink(GetStateConfig(currentState)); } } @@ -172,6 +239,151 @@ namespace AibisDream.FixSystem #region 光照系统 - 状态更新方法 + /// + /// 根据紧急状态的进入/退出选择短转场,其他状态保持即时切换。 + /// + private void TransitionLightsState(LightState previousState, LightState newState) + { + lightStateTransitionTween?.Kill(); + lightStateTransitionTween = null; + + alarmTween?.Kill(); + alarmTween = null; + + var stateConfig = GetStateConfig(newState); + UpdatePanelLight(); + + if (newState == LightState.Emergency) + { + PlayEmergencyIntro(stateConfig); + } + else if (previousState == LightState.Emergency) + { + PlayEmergencyOutro(stateConfig); + } + else + { + UpdateAlarmLight(stateConfig); + UpdateEnvironmentLight(stateConfig); + } + } + + /// + /// Emergency 进入:极短压暗后快速升起红光,再接循环警报。 + /// + private void PlayEmergencyIntro((bool alarmEnabled, Color alarmColor, float alarmMaxIntensity, + float alarmBlinkDuration, Color envColor, float envIntensity) config) + { + float dipDuration = Mathf.Max(0.01f, emergencyIntroDipDuration); + float riseDuration = Mathf.Max(0.01f, emergencyIntroRiseDuration); + DG.Tweening.Sequence sequence = DOTween.Sequence(); + + if (environmentLight != null) + { + float dipIntensity = environmentLight.intensity * emergencyIntroDipIntensityScale; + Color dipColor = Color.Lerp(environmentLight.color, config.envColor, 0.35f); + + sequence.Append(DOTween.To( + () => environmentLight.intensity, + value => environmentLight.intensity = value, + dipIntensity, + dipDuration).SetEase(Ease.OutQuad)); + sequence.Join(DOTween.To( + () => environmentLight.color, + value => environmentLight.color = value, + dipColor, + dipDuration).SetEase(Ease.OutQuad)); + sequence.Append(DOTween.To( + () => environmentLight.intensity, + value => environmentLight.intensity = value, + config.envIntensity, + riseDuration).SetEase(Ease.OutCubic)); + sequence.Join(DOTween.To( + () => environmentLight.color, + value => environmentLight.color = value, + config.envColor, + riseDuration).SetEase(Ease.OutCubic)); + } + else + { + sequence.AppendInterval(dipDuration + riseDuration); + } + + if (alarmLight != null) + { + alarmLight.color = config.alarmColor; + alarmLight.intensity = 0f; + sequence.Insert(dipDuration, DOTween.To( + () => alarmLight.intensity, + value => alarmLight.intensity = value, + config.alarmMaxIntensity, + riseDuration).SetEase(Ease.OutCubic)); + } + + lightStateTransitionTween = sequence.OnComplete(() => + { + lightStateTransitionTween = null; + if (currentState == LightState.Emergency) + { + StartAlarmLightBlink(config, true); + } + }); + } + + /// + /// Emergency 退出:快速收起紧急红光,平滑落到目标状态。 + /// + private void PlayEmergencyOutro((bool alarmEnabled, Color alarmColor, float alarmMaxIntensity, + float alarmBlinkDuration, Color envColor, float envIntensity) config) + { + float duration = Mathf.Max(0.01f, emergencyOutroDuration); + DG.Tweening.Sequence sequence = DOTween.Sequence(); + + if (environmentLight != null) + { + sequence.Join(DOTween.To( + () => environmentLight.intensity, + value => environmentLight.intensity = value, + config.envIntensity, + duration).SetEase(Ease.OutQuad)); + sequence.Join(DOTween.To( + () => environmentLight.color, + value => environmentLight.color = value, + config.envColor, + duration).SetEase(Ease.OutQuad)); + } + + if (alarmLight != null) + { + sequence.Join(DOTween.To( + () => alarmLight.intensity, + value => alarmLight.intensity = value, + 0f, + duration).SetEase(Ease.OutQuad)); + } + + if (environmentLight == null && alarmLight == null) + { + sequence.AppendInterval(duration); + } + + LightState targetState = currentState; + lightStateTransitionTween = sequence.OnComplete(() => + { + lightStateTransitionTween = null; + if (currentState != targetState) return; + + if (config.alarmEnabled) + { + StartAlarmLightBlink(config); + } + else + { + StopAlarmLight(); + } + }); + } + /// /// 更新所有灯光状态 /// @@ -225,17 +437,17 @@ namespace AibisDream.FixSystem /// 启动警报灯闪烁 /// private void StartAlarmLightBlink((bool alarmEnabled, Color alarmColor, float alarmMaxIntensity, - float alarmBlinkDuration, Color envColor, float envIntensity) config) + float alarmBlinkDuration, Color envColor, float envIntensity) config, bool startLit = false) { if (alarmLight == null) return; alarmTween?.Kill(); - alarmLight.intensity = 0f; + alarmLight.intensity = startLit ? config.alarmMaxIntensity : 0f; alarmLight.color = config.alarmColor; alarmTween = DOTween.To( () => alarmLight.intensity, x => alarmLight.intensity = x, - config.alarmMaxIntensity, + startLit ? 0f : config.alarmMaxIntensity, config.alarmBlinkDuration ) .SetLoops(-1, LoopType.Yoyo) @@ -349,6 +561,7 @@ namespace AibisDream.FixSystem for (int i = 0; i < panelLightBlinkCount; i++) { // 渐亮 + AudioManager.Instance?.PlaySfx(PANEL_LIGHT_ON_SFX); DOTween.To(() => panelLight.intensity, x => panelLight.intensity = x, panelLightIntensity, panelLightBlinkDuration * 0.5f) .SetEase(Ease.InOutQuad); if (environmentLight != null) @@ -359,6 +572,7 @@ namespace AibisDream.FixSystem yield return new WaitForSeconds(panelLightBlinkDuration); // 渐暗 + AudioManager.Instance?.PlaySfx(PANEL_LIGHT_OFF_SFX); DOTween.To(() => panelLight.intensity, x => panelLight.intensity = x, 0f, panelLightBlinkDuration * 0.5f) .SetEase(Ease.InOutQuad); if (environmentLight != null) @@ -370,13 +584,19 @@ namespace AibisDream.FixSystem } // 最后渐亮到常亮状态 - DOTween.To(() => panelLight.intensity, x => panelLight.intensity = x, panelLightIntensity, panelLightBlinkDuration * 0.5f) - .SetEase(Ease.InOutQuad); + AudioManager.Instance?.PlaySfx(PANEL_LIGHT_ON_SFX); + DG.Tweening.Sequence finalRise = DOTween.Sequence(); + finalRise.Join(DOTween.To(() => panelLight.intensity, x => panelLight.intensity = x, + panelLightIntensity, panelLightBlinkDuration * 0.5f) + .SetEase(Ease.InOutQuad)); if (environmentLight != null) { - DOTween.To(() => environmentLight.intensity, x => environmentLight.intensity = x, normalEnvironmentIntensity, panelLightBlinkDuration * 0.5f) - .SetEase(Ease.InOutQuad); + finalRise.Join(DOTween.To(() => environmentLight.intensity, x => environmentLight.intensity = x, + normalEnvironmentIntensity, panelLightBlinkDuration * 0.5f) + .SetEase(Ease.InOutQuad)); } + + yield return finalRise.WaitForCompletion(); } #endregion diff --git a/Assets/Scripts/FixSystemNew/Screen System/Core/FixPanelSystem.cs b/Assets/Scripts/FixSystemNew/Screen System/Core/FixPanelSystem.cs index c05fc6ace..8d320af29 100644 --- a/Assets/Scripts/FixSystemNew/Screen System/Core/FixPanelSystem.cs +++ b/Assets/Scripts/FixSystemNew/Screen System/Core/FixPanelSystem.cs @@ -7,6 +7,12 @@ using DG.Tweening; namespace AibisDream.FixSystem { + public enum SystemStartupMode + { + AutoOnHead, + Deferred + } + /// /// 维修面板系统 - 统一管理所有侧边栏面板 /// 包括常驻面板(对话、任务)和随状态切换的游戏面板 @@ -57,17 +63,24 @@ namespace AibisDream.FixSystem [Header("光照系统")] [SerializeField] private bool isSystemOn = false; public bool IsSystemOn => isSystemOn; + public bool ShouldAutoStartOnHeadEntry => + !isSystemOn && (!isStartupPrepared || startupMode == SystemStartupMode.AutoOnHead); [SerializeField] private FixPanelLight panelLight; public FixPanelLight PanelLight => panelLight; + private bool isStarting; + private bool isStartupPrepared; + private SystemStartupMode startupMode = SystemStartupMode.AutoOnHead; + private LightState targetLightState = LightState.Normal; + [Header("维修切换管理")] [SerializeField] private RepairSystemManager repairSystemManager; public RepairSystemManager RepairSystemManager => repairSystemManager; private void InitLight() { - panelLight.Initialize(isSystemOn); + panelLight.Initialize(isSystemOn, targetLightState); GetRepairPanel().InitLight(isSystemOn); // 无光环境下屏幕也不能亮 if (!isSystemOn) @@ -80,11 +93,36 @@ namespace AibisDream.FixSystem #region 系统启动协调 + /// + /// 为指定剧情准备一次系统启动。只有显式调用该接口的 YarnProject 会改变默认表现。 + /// + public void PrepareSystemStartup(SystemStartupMode mode) + { + startupMode = mode; + isStartupPrepared = true; + targetLightState = LightState.Normal; + ApplySystemOnImmediate(false); + taskPanel?.HidePanelImmediate(); + } + /// /// 启动所有系统(协调灯光系统和 CablePanel 的启动顺序) /// public IEnumerator StartAllSystems() { + if (isSystemOn) yield break; + + if (isStarting) + { + while (isStarting) + { + yield return null; + } + yield break; + } + + isStarting = true; + // 1. 先启动 CablePanel 的系统自检 var cablePanel = GetRepairPanel(); if (cablePanel != null) @@ -102,12 +140,27 @@ namespace AibisDream.FixSystem screenPanel.gameObject.SetActive(true); isSystemOn = true; + isStarting = false; + isStartupPrepared = false; + + // 开机动画使用 Normal 表现,完成后再进入 Yarn 在关机期间缓存的目标状态。 + ApplyLightState(targetLightState); } /// /// 设置灯光状态,并同步更新相关面板的灯光效果 /// public void SetLightState(LightState newState) + { + targetLightState = newState; + + // 关机时只缓存目标状态,避免序章的 Warning 提前点亮面板。 + if (!isSystemOn) return; + + ApplyLightState(newState); + } + + private void ApplyLightState(LightState newState) { // 1. 更新主灯光系统 if (panelLight != null) @@ -134,6 +187,7 @@ namespace AibisDream.FixSystem var dto = new FixPanelSnapshotDto { isSystemOn = isSystemOn, + lightState = targetLightState.ToString(), currentRepairSystemType = repairSystemManager?.GetCurrentSystemType()?.Name, isCableRetracted = cablePanel != null && cablePanel.isCableRetracted }; @@ -161,6 +215,17 @@ namespace AibisDream.FixSystem { if (dto == null) return; + // 读档恢复的是稳定终态,不继承可能仍留在场景中的待启动模式。 + isStartupPrepared = false; + startupMode = SystemStartupMode.AutoOnHead; + targetLightState = LightState.Normal; + if (!string.IsNullOrEmpty(dto.lightState) + && !System.Enum.TryParse(dto.lightState, true, out targetLightState)) + { + Debug.LogWarning($"[FixPanelSystem] Unknown saved light state '{dto.lightState}'; using Normal."); + targetLightState = LightState.Normal; + } + ApplySystemOnImmediate(dto.isSystemOn); if (repairSystemManager != null) @@ -177,10 +242,11 @@ namespace AibisDream.FixSystem public void ApplySystemOnImmediate(bool isOn) { isSystemOn = isOn; + isStarting = false; if (panelLight != null) { - panelLight.Initialize(isOn); + panelLight.Initialize(isOn, targetLightState); } var cablePanel = GetRepairPanel(); diff --git a/Assets/Scripts/FixSystemNew/Screen System/FixPanel/TaskPanel.cs b/Assets/Scripts/FixSystemNew/Screen System/FixPanel/TaskPanel.cs index d81ebe74c..e56f304fc 100644 --- a/Assets/Scripts/FixSystemNew/Screen System/FixPanel/TaskPanel.cs +++ b/Assets/Scripts/FixSystemNew/Screen System/FixPanel/TaskPanel.cs @@ -33,6 +33,12 @@ namespace AibisDream.FixSystem taskRoot.DOLocalMoveX(ShownLocalX, 1f); } + public void HidePanelImmediate() + { + taskRoot.DOKill(); + SetPanelVisibleImmediate(false); + } + public void CompleteTask(string lineId) { if (_taskDict.Remove(lineId, out var taskItem)) diff --git a/Assets/Scripts/FixSystemNew/Screen System/ScreenYarnCommand.cs b/Assets/Scripts/FixSystemNew/Screen System/ScreenYarnCommand.cs index 8e5add39f..a7672371b 100644 --- a/Assets/Scripts/FixSystemNew/Screen System/ScreenYarnCommand.cs +++ b/Assets/Scripts/FixSystemNew/Screen System/ScreenYarnCommand.cs @@ -1,6 +1,7 @@ using AibisDream.FixSystem; using Yarn.Unity; using System.Collections; +using UnityEngine; namespace AibisDream { @@ -101,6 +102,19 @@ namespace AibisDream yield return FixPanelSystem.Instance.StartAllSystems(); } + [YarnCommand("prepare_system_startup")] + public static void PrepareSystemStartup(string mode) + { + if (FixPanelSystem.Instance == null) return; + if (!System.Enum.TryParse(mode, true, out SystemStartupMode startupMode)) + { + Debug.LogWarning($"[Yarn] Unknown system startup mode '{mode}'. Expected AutoOnHead or Deferred."); + return; + } + + FixPanelSystem.Instance.PrepareSystemStartup(startupMode); + } + #endregion } -} \ No newline at end of file +} diff --git a/Assets/Scripts/FixSystemNew/States/CoreFixCues.cs b/Assets/Scripts/FixSystemNew/States/CoreFixCues.cs index 5f506ab97..475c08bbb 100644 --- a/Assets/Scripts/FixSystemNew/States/CoreFixCues.cs +++ b/Assets/Scripts/FixSystemNew/States/CoreFixCues.cs @@ -63,19 +63,24 @@ namespace AibisDream.FixSystem var cablePanel = FixPanelSystem.GetRepairPanel(); // 拔出插头 // 切换Body或Head - if (Enum.TryParse(transition.Args, out var moduleState)) + bool hasModuleState = Enum.TryParse(transition.Args, out ModuleState moduleState); + bool isHeadEntry = hasModuleState && moduleState == ModuleState.Head; + if (hasModuleState) { bodyModuleSystem.SwitchModuleGroup(moduleState); } - if (cablePanel != null && !FixPanelSystem.Instance.IsSystemOn) + if (!FixPanelSystem.Instance.IsSystemOn && isHeadEntry) { // 切换相机 yield return CameraKit.Instance.SwitchCamera(CameraEnum.BodyModuleCenter); yield return UIManager.Instance.GetPanel().FadeOutAsync(0.5f); yield return new WaitForSeconds(0.5f); yield return CameraKit.Instance.SwitchCamera(CameraEnum.BodyModule); - yield return FixPanelSystem.Instance.StartAllSystems(); + if (FixPanelSystem.Instance.ShouldAutoStartOnHeadEntry) + { + yield return FixPanelSystem.Instance.StartAllSystems(); + } } else { diff --git a/Assets/Scripts/SaveSystem/SaveSnapshot.cs b/Assets/Scripts/SaveSystem/SaveSnapshot.cs index c21ffa9af..4312b9195 100644 --- a/Assets/Scripts/SaveSystem/SaveSnapshot.cs +++ b/Assets/Scripts/SaveSystem/SaveSnapshot.cs @@ -222,6 +222,9 @@ namespace AibisDream.SaveSystem { public bool isSystemOn; + /// 当前目标灯态;旧存档缺失时按 Normal 处理。 + public string lightState; + /// RepairSystemManager 当前激活系统类型名;空则默认 BodyModuleSystem。 public string currentRepairSystemType; diff --git a/Assets/Yarn/FP/FP_Prologue/Center.yarn b/Assets/Yarn/FP/FP_Prologue/Center.yarn index de94d58a2..e93bd976d 100644 --- a/Assets/Yarn/FP/FP_Prologue/Center.yarn +++ b/Assets/Yarn/FP/FP_Prologue/Center.yarn @@ -18,17 +18,13 @@ position: 205,199 ///在这里决定这次诊疗的目标是什么,以及目标判断相关的数值 //【流程相关】 -//gamestage:1-引入对话;2-检查;3-检查后对话;4-调速;5-调速后对话(冷却液) +//gamestage:1-开场;2-插线检查(镇静→溃解→隔离);3-切割记忆;6-螺旋;999-结束 <> -<> -<> -<> -<> -<> -<> <> <> +<> <> +<> ///【流程逻辑】 @@ -62,10 +58,6 @@ colorID: 1 <> <> <> -<> - <> -<> - <> <> <> <> @@ -73,4 +65,4 @@ colorID: 1 <> // 结束,进入下一个Yarn <> -=== \ No newline at end of file +=== diff --git a/Assets/Yarn/FP/FP_Prologue/EventNode.yarn b/Assets/Yarn/FP/FP_Prologue/EventNode.yarn index 34b4c922c..c0c43f7b5 100644 --- a/Assets/Yarn/FP/FP_Prologue/EventNode.yarn +++ b/Assets/Yarn/FP/FP_Prologue/EventNode.yarn @@ -3,7 +3,10 @@ tags: event colorID: 8 position: -2,-3039 --- -// <> +<> + // 找记忆阶段:情绪模块已关机 + <> +<> <> <> <> @@ -14,6 +17,10 @@ tags: event colorID: 8 position: 240,-2640 --- +<> + // 找记忆阶段:表达模块非目标 + <> +<> <> === @@ -22,7 +29,10 @@ tags: event colorID: 8 position: 480,-3040 --- -// <> +<> + // 找记忆阶段:逻辑模块已关机 + <> +<> <> <> <> @@ -33,7 +43,10 @@ tags: event colorID: 8 position: 240,-3040 --- -// <> +<> + // 找记忆阶段:插中记忆,直接进入切割 + <> +<> <> <> <> @@ -47,22 +60,6 @@ tags: event === -title: EmoCutDown -tags: event ---- -<> -=== - - - - -title: LogicCutDown -tags: event ---- -<> -=== - - title: 拿起插头 tags: event @@ -74,6 +71,12 @@ tags: event title: ShockEffect tags: event --- +<> + <> + <> + <> + <> +<> <> //<> === diff --git a/Assets/Yarn/FP/FP_Prologue/Stage2-5_切割.yarn b/Assets/Yarn/FP/FP_Prologue/Stage2-5_切割.yarn index fdd4e5da0..cd1dbcdc6 100644 --- a/Assets/Yarn/FP/FP_Prologue/Stage2-5_切割.yarn +++ b/Assets/Yarn/FP/FP_Prologue/Stage2-5_切割.yarn @@ -8,8 +8,13 @@ position: 569,-3402 ////需要用两种跳字效果来区分两个人格 <> <> +<> + <> +<> <> -<> +<> +<> +<> <> <> dn: 系统已就绪。#auto_next @@ -73,7 +78,7 @@ group:插线检查 position: 1108,-2261 --- <> -<> +<> <> gotash?: 啊…啊! #line:037a594 // <> @@ -110,63 +115,6 @@ me: 出现异常状况。现在重新通电。 -title: 第二次切除 -tags: -colorID: 8 -group:插线检查 -position: 1111,-2544 ---- -<> -<> -Task: 切除{$currentCheckModule}模块 #line:0b94b47 -me: 会有点疼。 #line:04b0c1b -<> -<> -=== - - - - -title: 第二次切除后 -tags: -colorID: 8 -group:插线检查 -position: 1115,-2127 ---- -// <> -<> -gotash?: 呃…啊 #line:0e795e0 -<> -<> -<> -<> -// 【背景中更多蓝色液体流出】 #line:095103b -<> -<> -<> -<> -gotash?: 它还…它还活着……
为什么!还在这个身体里……
#line:0a0aea0 -<> -<> -gotash?: 这是梦…这是梦。我必须醒来,我必须醒来…… #line:0d70b5d -<> -<> -<> -<> -<> -gotash?:醒来吧…醒来… #line:067a91c -<> -me: 生命体征正在溃解,得先稳定下来。 #line:015ac4e - -<> -<> -<> - -=== - - - - title:电击后 tags: colorID: 8 @@ -175,7 +123,6 @@ position: 788,-1825 --- <> <> - <> <> <> dn: 电流过载#auto_next @@ -265,48 +212,6 @@ position: 788,-1825 -title: 第三次切除 -tags: -colorID: 8 -group:插线检查 -position: 1110,-2412 ---- -<> -<> -Task: 切除{$currentCheckModule}模块 #line:014f73d -me: 坚持住。 #line:0352590 -<> -=== - - - -title: 第三次切除后 -tags: -colorID: 8 -group:插线检查 -position: 1100,-1980 ---- -<> -<> -gotash?: 呃呃呃呃呃呃呃呃#auto_next #line:0cf6d36 -<> -<> -me:污染源全部排除了。现在应该… #line:0c23843 -<> -<> -<> -gotash?:不……我…死……死……我要…#auto_next #line:060f2e3 -<> -me:为什么…不起作用? #line:0b93ed1 -<> -<> -<> -<> -=== - - - - title: 第一次检查 tags: colorID: 8 @@ -319,10 +224,9 @@ Linking: 正在建立连接… #line:08a3591 // <> // <> //gotash?: 啊!痛…痛! #line:0681cac -EmoModule: 已与{$currentCheckModule}模块建立连接! #line:0e05aec +EmoModule: 已与{$currentCheckModule}模块建立连接! #line:0e05aec <> -<> -Error: 检测到排异性坏死!请尽快处理。 #line:06122b9 +Error: 检测到排异性坏死!请尽快处理。 #line:06122b9 Error: 模块完整度:44.9% #line:0862409 Error: 原型泄漏:27.8% 已污染 #line:0c259fd gotash?: 医生… @@ -343,7 +247,10 @@ me: 很快就好了。 EmoModule: 指令执行完成!正在刷新... Error: 原型泄漏:35.2% <> -【模块闪火花】 +// 情绪/逻辑/记忆进入损坏状态:文字闪烁+间歇火花 +<> +<> +<> <> gotash?: 咳…咳咳… Error: 警告!检测到溃解数据流! #auto_next @@ -367,11 +274,13 @@ Linking: 已收到紧急隔离指令。 Linking: 正在隔离逻辑模块… <> <> +<> Linking: 逻辑模块已隔离。 Linking: 原型泄漏:43.1% Linking: 正在隔离情绪模块… <> <> +<> Linking: 情绪模块已隔离。 Linking: 原型泄漏:61.2% Linking: 正在隔离记忆模块… @@ -404,7 +313,50 @@ gotash?: [[size]]不[[/size]]!医生!我不想死… gotash?: 必须[[size]]死[[/size]],回收必须完成… #line:0ab8d02 gotash?: 我想回家…妈妈…… me: 很抱歉。没有什么妈妈。 -->执行切除术 #line:0cc9043 +<> + // 插着的就是记忆模块,直接切割 + ->执行切除术 #line:0cc9043 + <> + <> + <> + <> + <> +<> + // 插着的不是记忆模块,需要重新插线连接记忆 + me: 等等…刚才连接的是{$currentCheckModule}模块。 + me: 得直接连接记忆模块,才能进行切除。 + Task: 插线连接记忆模块 + <> + <> + <> +<> +=== + + + + +title: 连接记忆切除 +tags: +colorID: 8 +group:插线检查 +description: 找记忆阶段插中记忆模块,触发切割 +position: 1101,-2974 +--- +<> +<> +<> +<> +Linking: 正在建立连接… +<> +MemModule: 已与记忆模块建立连接! +<> +<> +gotash?: 没用的…没用的。 #line:01f682e +Error: 检测到模块发生递归性坏死!请尽快处理。 #line:0c297b0 +Error: 模块核心完整度:让我死吧 #line:0a13a1b +Error: 这一定是个噩梦:让我死吧 #line:037d57d +me: 我得再快些。 #line:048cfa4 +->执行切除术 #line:06dd480 <> <> <> @@ -415,55 +367,19 @@ me: 很抱歉。没有什么妈妈。 -title: 第二次检查 -tags: -colorID: 8 -group:插线检查 -position: 1101,-2974 ---- -<> -Linking: 正在建立连接… #line:0e63512 -<> -LogicModule: 已与{$currentCheckModule}模块建立连接! #line:08d3946 -<> -Error: 检测到非法字符串扰。 #line:05804d7 -<> -Error: 检测到排异性坏死!请尽快处理。 #line:0740cff -Error: 模块完整度:73.9% #line:00274a3 -Error: 原型泄漏:74.00%73这是个_6噩5梦/r #line:0489e3a -me: 我得再快些。 #line:048cfa4 -->执行切除术 #line:06dd480 - <> - <> -<> -<> -=== - - - - -title: 第三次检查 -tags: +title: 未检测到信号 +tags: colorID: 8 group:插线检查 +description: 找记忆阶段误插已关机模块或表达模块 position: 1090,-2816 --- <> -Linking: 正在建立连接… #line:0fd4c6f +Linking: 正在建立连接… #line:0fd4c6f <> -MemModule: 已与{$currentCheckModule}模块建立连接! #line:008fd04 <> -gotash?: 没用的…没用的。 #line:01f682e -Error: 检测到模块发生递归性坏死!请尽快处理。 #line:0c297b0 -Error: 模块核心完整度:让我死吧 #line:0a13a1b -Error: 这一定是个噩梦:让我死吧 #line:037d57d -Error: 求求你让我死吧#line:0797a17 -Error: 求求你让我死吧#line:0d5406c -->执行模块切除 #line:0a88566 - <> - <> -<> -<> +Error: 未检测到信号。 +<> === @@ -475,13 +391,7 @@ colorID: 8 group:插线检查 position: 758,-2965 --- -<> - <> -<> - <> -<> - <> -<> +<> === @@ -495,14 +405,7 @@ position: 769,-2682 --- <> <> -<> - <> -<> - <> -<> - <> -<> - +<> === @@ -516,13 +419,7 @@ position: 774,-2287 --- <> <> -<> - <> -<> - <> -<> - <> -<> +<> === @@ -545,4 +442,4 @@ Error: 请定位坏死模块以中止溃解。 #line:0668599 ->结束检查 #line:0b1d611 <> <> -=== \ No newline at end of file +===