Files
aibis-dream/Assets/Scripts/MiniGame/HuoShan/Language/LanguageYarnCommand.cs
T

898 lines
38 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System.Collections;
using System.Collections.Generic;
using AibisDream.FixSystem;
using AibisDream;
using Yarn.Unity;
namespace AibisDream.MiniGame.Language
{
/// <summary>
/// 表达系统的 Yarn 命令接口(原语言系统)
/// </summary>
public static class LanguageYarnCommand
{
private static AibisDream.ExpressionManager ExpressionManager => FixSystemCenter.SystemDic.Get<AibisDream.ExpressionManager>();
private static bool TryGetPresentation(out LogReleasePresentationController presentation)
{
presentation = ExpressionManager != null
? ExpressionManager.LogReleasePresentation
: null;
if (presentation != null)
return true;
UnityEngine.Debug.LogError(
"[LanguageYarnCommand] LogReleasePresentationController 未找到;演出命令安全结束。");
return false;
}
/// <summary>
/// 启动表达粒子系统(在打开视图后调用),等待火山表达panel播完再返回。
/// 流程:若有上一轮则先淡出字与连线 → 再淡入火山释放 log → 再启动新一轮并等表达 panel 就绪。
/// 注意:Yarn Spinner 2.x 对同名 <see cref="YarnCommand"/> 重载支持不可靠,只保留一个注册入口,用可选参数区分 3/4 参调用。
/// <<start_expression "哈哈|嘿嘿|呵呵" "我很害怕" "ExpressionCompleted">>
/// <<start_expression "哈哈|嘿嘿|呵呵" "我很害怕" "ExpressionCompleted" 24>>
/// (第四项为「非目标」候选粒子总数,候选池 = 目标句字数 + 该值;不写第四项则用 Inspector 的 Candidate Count
/// </summary>
/// <param name="anxietyPhrasesStr">干扰短句(笑话等),用 | 分隔,用于非目标粒子字符池,如:"哈哈|嘿嘿|呵呵"</param>
/// <param name="targetSentence">目标句子</param>
/// <param name="completionNode">完成时触发的对话节点(可空字符串)</param>
/// <param name="nonTargetParticleTotal">非目标候选粒子总数;&lt;0 表示使用 Inspector 默认</param>
[YarnCommand("start_expression")]
public static IEnumerator StartExpression(
string anxietyPhrasesStr,
string targetSentence,
string completionNode = "",
float nonTargetParticleTotal = -1f)
{
return RunStartExpression(
anxietyPhrasesStr,
targetSentence,
completionNode ?? "",
UnityEngine.Mathf.RoundToInt(nonTargetParticleTotal));
}
private static IEnumerator RunStartExpression(string anxietyPhrasesStr, string targetSentence, string completionNode, int nonTargetParticleTotal)
{
if (ExpressionManager == null)
{
UnityEngine.Debug.LogError("ExpressionManager 未找到!请确保场景中有 ExpressionManager 组件。");
yield break;
}
string[] phrases = null;
if (!string.IsNullOrEmpty(anxietyPhrasesStr))
{
phrases = anxietyPhrasesStr.Split('|');
for (int i = 0; i < phrases.Length; i++)
{
phrases[i] = phrases[i].Trim();
}
}
// 先清理上一轮演出,再淡出旧文字/连线并恢复 Log 操作界面。
yield return ExpressionManager.PreparePresentationForNextRound();
yield return ExpressionManager.FadeOutParticlesBeforeNewRound(0f);
yield return ExpressionManager.EnsureReleaseLogFadedIn(1f);
ExpressionManager.StartSystem(phrases, targetSentence, completionNode, nonTargetParticleTotal);
yield return ExpressionManager.WaitUntilExpressionFlowReady();
}
/// <summary>
/// 关闭表达系统
/// <<close_expression>>
/// </summary>
[YarnCommand("close_expression")]
public static void CloseExpression()
{
if (ExpressionManager == null)
{
UnityEngine.Debug.LogError("ExpressionManager 未找到!");
return;
}
ExpressionManager.CloseView();
}
/// <summary>
/// 重置表达系统(使用当前配置)
/// <<reset_expression>>
/// 或
/// <<reset_expression false>> // 不播放入场动画
/// </summary>
/// <param name="playEntranceEffect">是否播放入场效果</param>
[YarnCommand("reset_expression")]
public static void ResetExpression(bool playEntranceEffect = true)
{
if (ExpressionManager == null)
{
UnityEngine.Debug.LogError("ExpressionManager 未找到!");
return;
}
ExpressionManager.ResetSystem(playEntranceEffect);
}
/// <summary>
/// 开发预览:粒子系统就绪后跳过玩法,直接进入 FocusHolding。
/// <<expression_skip_to_focus>>
/// </summary>
[YarnCommand("expression_skip_to_focus")]
public static IEnumerator ExpressionSkipToFocus()
{
if (ExpressionManager == null)
{
UnityEngine.Debug.LogError("ExpressionManager 未找到!");
yield break;
}
yield return ExpressionManager.StartCoroutine(ExpressionManager.SkipToFocusHoldingPreview());
}
/// <summary>
/// 触发聚焦稳定化(从文字飘动保持态 → 概率递增 → 文字锁定 → 排列),等待全流程完成后返回
/// <<resolve_expression_focus>>
/// </summary>
[YarnCommand("resolve_expression_focus")]
public static IEnumerator ResolveExpressionFocus()
{
if (ExpressionManager == null)
{
UnityEngine.Debug.LogError("ExpressionManager 未找到!");
yield break;
}
yield return ExpressionManager.StartCoroutine(ExpressionManager.ResolveFocusAndWait());
}
/// <summary>
/// 聚焦干扰传播,并等待传播结束。
/// in:从最不稳定的目标字向最稳定的目标字传播红色强烈摇摆。
/// characterPool 可传入用空格或 | 分隔的等长词组变体;每个目标字只在对应字位间跳跃。
/// adjust:只调整已被干扰文字的参数,不重排或重播传播链;传空字符串/-1 可保留对应现值。
/// out:从最稳定的目标字反向传播,恢复固定目标色。
/// <<expression_focus_interference "in" 1.8 "没问题 帽问题 冇问题">>
/// <<expression_focus_interference "in" 1.8 "没问题 帽问题 冇问题" "#FF304D" 0.2 30 0.045 0.35>>
/// <<expression_focus_interference "adjust" 0.5 "" "" 0.28 38 0.035>>
/// <<expression_focus_interference "out" 1.2>>
/// </summary>
[YarnCommand("expression_focus_interference")]
public static IEnumerator ExpressionFocusInterference(
string direction = "in",
float duration = 1.5f,
string characterPool = "",
string colorHex = "",
float shakeAmplitude = -1f,
float shakeSpeed = -1f,
float changeInterval = -1f,
float transitionRatio = -1f)
{
if (ExpressionManager == null)
{
UnityEngine.Debug.LogError("ExpressionManager 未找到!");
yield break;
}
yield return ExpressionManager.StartCoroutine(
ExpressionManager.PlayFocusInterferenceAndWait(
direction,
duration,
characterPool,
colorHex,
shakeAmplitude,
shakeSpeed,
changeInterval,
transitionRatio));
}
/// <summary>
/// 淡入 ExpressionManager 的 Sprite 图片
/// <<expression_sprite_fade_in>>
/// <<expression_sprite_fade_in 1.5>>
/// </summary>
/// <param name="duration">淡入时长(秒),默认 1</param>
[YarnCommand("expression_sprite_fade_in")]
public static IEnumerator ExpressionSpriteFadeIn(float duration = 1f)
{
if (ExpressionManager == null)
{
UnityEngine.Debug.LogError("ExpressionManager 未找到!");
yield break;
}
yield return ExpressionManager.StartCoroutine(ExpressionManager.FadeInSpriteOverlay(duration));
}
/// <summary>
/// 淡出 ExpressionManager 的 Sprite 图片
/// <<expression_sprite_fade_out>>
/// <<expression_sprite_fade_out 1.5>>
/// </summary>
/// <param name="duration">淡出时长(秒),默认 1</param>
[YarnCommand("expression_sprite_fade_out")]
public static IEnumerator ExpressionSpriteFadeOut(float duration = 1f)
{
if (ExpressionManager == null)
{
UnityEngine.Debug.LogError("ExpressionManager 未找到!");
yield break;
}
yield return ExpressionManager.StartCoroutine(ExpressionManager.FadeOutSpriteOverlay(duration));
}
/// <summary>
/// Glitch 噪波过渡,等待完成后再继续下一步。
/// <<glitch_transition 0.95 2>> -- 从 0 到 0.952 秒
/// <<glitch_transition 0.95>> -- 立即到 0.95duration 默认 0
/// <<glitch_transition 0.3 0.45 1>> -- 从 0.3 到 0.451 秒
/// </summary>
[YarnCommand("glitch_transition")]
public static IEnumerator GlitchTransition(float to, float duration = 0f)
{
if (ExpressionManager == null)
{
UnityEngine.Debug.LogError("ExpressionManager 未找到!");
yield break;
}
yield return ExpressionManager.StartCoroutine(ExpressionManager.TransitionGlitchAndWait(to, duration));
}
/// <summary>
/// 记忆淡入(非阻塞):透明度在 fadeDuration 内显现,画面同时按 pushSpeed 持续推近;
/// targetOpacity 是本次淡入的目标透明度。horizontalSpeed 为旧 Yarn 兼容参数,基础层不再横移。
/// 争夺段的 jolt / tear / impact 仍会叠加。
/// </summary>
[YarnCommand("expression_memory_begin")]
public static void ExpressionMemoryBegin(
string memoryKey,
float fadeDuration = -1f,
float pushSpeed = -1f,
float horizontalSpeed = -1f,
bool preserveGlitch = false,
float targetOpacity = 1f)
{
if (ExpressionManager == null)
{
UnityEngine.Debug.LogError("ExpressionManager 未找到!");
return;
}
ExpressionManager.StartCoroutine(
ExpressionManager.BeginExpressionMemory(
memoryKey,
fadeDuration,
pushSpeed,
horizontalSpeed,
preserveGlitch,
targetOpacity));
}
/// <summary>
/// 随对白把当前记忆透明度推进到目标值(非阻塞)。
/// <<expression_memory_alpha 0.65 0.45>>
/// </summary>
[YarnCommand("expression_memory_alpha")]
public static void ExpressionMemoryAlpha(float target, float duration = 0.4f)
{
if (TryGetPresentation(out LogReleasePresentationController presentation))
presentation.SetActiveMemoryOpacity(target, duration);
}
/// <summary>
/// 显式淡入火山脸,并等待淡入完成。
/// <<expression_face_fade_in 0.45>>
/// </summary>
[YarnCommand("expression_face_fade_in")]
public static IEnumerator ExpressionFaceFadeIn(float duration = 0.45f)
{
if (!TryGetPresentation(out LogReleasePresentationController presentation))
yield break;
yield return ExpressionManager.StartCoroutine(
presentation.BeginFaceEntry(duration));
}
[YarnCommand("expression_lie_begin")]
public static IEnumerator ExpressionLieBegin(string keyword, string preset)
{
if (ExpressionManager == null)
{
UnityEngine.Debug.LogError("ExpressionManager 未找到!");
yield break;
}
yield return ExpressionManager.StartCoroutine(
ExpressionManager.BeginExpressionLie(keyword, preset));
}
[YarnCommand("expression_lie_break")]
public static IEnumerator ExpressionLieBreak()
{
if (ExpressionManager == null)
{
UnityEngine.Debug.LogError("ExpressionManager 未找到!");
yield break;
}
yield return ExpressionManager.StartCoroutine(ExpressionManager.BreakExpressionLie());
}
[YarnCommand("expression_truth_reveal")]
public static IEnumerator ExpressionTruthReveal()
{
if (ExpressionManager == null)
{
UnityEngine.Debug.LogError("ExpressionManager 未找到!");
yield break;
}
yield return ExpressionManager.StartCoroutine(ExpressionManager.RevealExpressionTruth());
}
// 以下命令是一动作一命令。非 IEnumerator 命令只启动效果,节拍由 Yarn 的 wait 控制。
[YarnCommand("expression_lie_prepare")]
public static void ExpressionLiePrepare(float freezeDuration, float noiseTarget)
{
if (TryGetPresentation(out LogReleasePresentationController presentation))
presentation.PrepareLieVisuals(freezeDuration, noiseTarget);
}
[YarnCommand("expression_truth_squeeze")]
public static void ExpressionTruthSqueeze(float duration, float jitter, float alpha)
{
if (TryGetPresentation(out LogReleasePresentationController presentation))
presentation.SqueezeTruthCharacters(duration, jitter, alpha);
}
[YarnCommand("expression_lie_crack_begin")]
public static void ExpressionLieCrackBegin(float lieAlpha)
{
if (TryGetPresentation(out LogReleasePresentationController presentation))
presentation.BeginLieCracking(lieAlpha);
}
[YarnCommand("expression_screen_dim")]
public static void ExpressionScreenDim(float alpha, float riseDuration, float fallDuration)
{
if (TryGetPresentation(out LogReleasePresentationController presentation))
presentation.PlayScreenDim(alpha, riseDuration, fallDuration);
}
[YarnCommand("expression_memory_jolt")]
public static void ExpressionMemoryJolt(float offset, float duration, float tear)
{
if (TryGetPresentation(out LogReleasePresentationController presentation))
presentation.PlayMemoryJolt(offset, duration, tear);
}
/// <summary>
/// 调节记忆的轻微失真扰动(非阻塞)。默认强度由演出预设决定,本命令用于演出中微调。
/// <<expression_memory_sim 0.55 0.3>>
/// </summary>
[YarnCommand("expression_memory_sim")]
public static void ExpressionMemorySim(float target, float duration = 0.3f)
{
if (TryGetPresentation(out LogReleasePresentationController presentation))
presentation.SetSimulationGlitch(target, duration);
}
/// <summary>
/// 真话聚合尝试(非阻塞):目标字被慢慢拉向最终位置并按字序逐个锁定成真心话。
/// target 小于 1 时最后几个字永远差一点锁不住——"感觉快要成功了"。
/// <<expression_truth_gather 0.9 3.2>>
/// </summary>
[YarnCommand("expression_truth_gather")]
public static void ExpressionTruthGather(float target = 0.9f, float duration = 3f)
{
if (TryGetPresentation(out LogReleasePresentationController presentation))
presentation.BeginTruthGatherAttempt(target, duration);
}
/// <summary>
/// 真话聚合被打断(非阻塞):目标字向外爆散并恢复乱跳。burst 为世界单位的爆散距离。
/// <<expression_truth_scatter 0.9>>
/// </summary>
[YarnCommand("expression_truth_scatter")]
public static void ExpressionTruthScatter(float burst = 0.9f)
{
if (TryGetPresentation(out LogReleasePresentationController presentation))
presentation.ScatterTruthGatherAttempt(burst);
}
/// <summary>
/// 真话聚合挣扎(非阻塞):向 target 推进的途中反复"够到一点又被拽回去",
/// 已锁的字会崩开重新乱跳。挣扎感来自聚合曲线本身,不使用任何颜色或额外特效。
/// <<expression_truth_strain 0.86 3.2 3>>
/// </summary>
/// <param name="target">最终停留的聚合进度</param>
/// <param name="duration">整段时长</param>
/// <param name="tugs">回抽次数(0~4);&lt;=0 时退化为 expression_truth_gather</param>
[YarnCommand("expression_truth_strain")]
public static void ExpressionTruthStrain(float target = 0.85f, float duration = 3f, float tugs = 2f)
{
if (TryGetPresentation(out LogReleasePresentationController presentation))
{
presentation.BeginTruthStrainAttempt(
target,
duration,
UnityEngine.Mathf.RoundToInt(tugs));
}
}
/// <summary>
/// 真话聚合崩塌(非阻塞):进度被一口气拽回 0,字沿原路退回悬浮位并恢复乱跳。
/// 与 expression_truth_scatter 的区别:scatter 是径向爆散,collapse 是"被拽回去"。
/// <<expression_truth_collapse 0.45>>
/// </summary>
[YarnCommand("expression_truth_collapse")]
public static void ExpressionTruthCollapse(float duration = 0.45f)
{
if (TryGetPresentation(out LogReleasePresentationController presentation))
presentation.CollapseTruthGatherAttempt(duration);
}
/// <summary>
/// 火山脸错误闪红(非阻塞):聚合失败时短暂替换红屏 Sprite,随后恢复,并轻微下沉。
/// 注意:LOG1/LOG2 的失败信号已明确不使用红色与脸部报错,此命令仅保留兼容。
/// <<expression_face_error 0.5 0.85>>
/// </summary>
[YarnCommand("expression_face_error")]
public static void ExpressionFaceError(float duration = 0.5f, float intensity = 0.85f)
{
if (TryGetPresentation(out LogReleasePresentationController presentation))
presentation.PlayFaceErrorFlash(duration, intensity);
}
/// <summary>
/// 结尾真假快速闪切(非阻塞,节奏由同长度 wait 控制):真心话与谎话交替独占屏幕,
/// 两者的屏幕底色(电视头背景)不同,越到后面切得越快,结束定格在真话帧。
/// <<expression_truth_lie_flicker "没问题|冇问题|帽问题" "我就是个笑话" 3.2 0.24 12>>
/// </summary>
[YarnCommand("expression_truth_lie_flicker")]
public static void ExpressionTruthLieFlicker(
string liePhrases,
string truthPhrase,
float duration,
float interval = 0.24f,
float fontSize = 12f)
{
if (TryGetPresentation(out LogReleasePresentationController presentation))
presentation.StartTruthLieFlicker(liePhrases, truthPhrase, duration, interval, fontSize);
}
/// <summary>
/// 定格的谎话被 glitch 翻转成真话(阻塞):大字乱跳中长度从谎话渐变到真话、真假底色抢闪,
/// 最后落在暖色真话。紧接 expression_memory_cut + expression_truth_snap 收尾。
/// <<expression_lie_morph_truth "没问题" "我就是个笑话" 0.9>>
/// </summary>
[YarnCommand("expression_lie_morph_truth")]
public static IEnumerator ExpressionLieMorphTruth(
string lieText,
string truthText,
float duration = 0.9f)
{
if (!TryGetPresentation(out LogReleasePresentationController presentation))
yield break;
yield return ExpressionManager.StartCoroutine(
presentation.MorphLieToTruth(lieText, truthText, duration));
}
[YarnCommand("expression_truth_leak")]
public static IEnumerator ExpressionTruthLeak(string fragment, float duration)
{
if (!TryGetPresentation(out LogReleasePresentationController presentation))
yield break;
yield return ExpressionManager.StartCoroutine(
presentation.LeakTruthFragment(fragment, duration));
}
[YarnCommand("expression_lie_shuffle")]
public static void ExpressionLieShuffle(
string characterPool,
float duration,
float interval)
{
if (TryGetPresentation(out LogReleasePresentationController presentation))
presentation.StartLieCharacterShuffle(characterPool, duration, interval);
}
/// <summary>
/// 演员大字闪现(阻塞):抖动的粒子字瞬间隐藏,屏幕中央出现白色大字(红青色散双影+急速缩放),
/// 停顿 holdDuration 秒后始终恢复粒子字抖动;结尾定格请使用 expression_actor_flash_in。
/// <<expression_actor_flash "没问题" 0.6 10.5 1.15 1.60 0.03 0.22 0.5 0.2>>
/// </summary>
[YarnCommand("expression_actor_flash")]
public static IEnumerator ExpressionActorFlash(
string text,
float holdDuration = 0.6f,
float fontSize = 10.5f,
float settledScale = -1f,
float punchScale = -1f,
float chromaDistance = -1f,
float chromaAlpha = -1f,
float impact = -1f,
float glitchPeak = -1f)
{
if (!TryGetPresentation(out LogReleasePresentationController presentation))
yield break;
yield return ExpressionManager.StartCoroutine(
presentation.FlashActorLie(
text,
holdDuration,
fontSize,
settledScale,
punchScale,
chromaDistance,
chromaAlpha,
impact,
glitchPeak));
}
/// <summary>
/// 演员大字入场并保持(阻塞):入场表现与 expression_actor_flash 相同,但不执行退场,
/// 适合在段落结尾定格。后续清场命令仍会正常移除它。
/// <<expression_actor_flash_in "没问题" 0.35 10.5 1.1 1.45 0.008 0.06 0.5 0>>
/// </summary>
[YarnCommand("expression_actor_flash_in")]
public static IEnumerator ExpressionActorFlashIn(
string text,
float holdDuration = 0.35f,
float fontSize = 10.5f,
float settledScale = -1f,
float punchScale = -1f,
float chromaDistance = -1f,
float chromaAlpha = -1f,
float impact = -1f,
float glitchPeak = -1f)
{
if (!TryGetPresentation(out LogReleasePresentationController presentation))
yield break;
yield return ExpressionManager.StartCoroutine(
presentation.FlashActorLie(
text,
holdDuration,
fontSize,
settledScale,
punchScale,
chromaDistance,
chromaAlpha,
impact,
glitchPeak,
true));
}
/// <summary>
/// 非阻塞启动“没问题 → 冇问题 → 帽问题”三拍无限闪现循环。
/// <<expression_actor_flash_loop_start>>
/// </summary>
[YarnCommand("expression_actor_flash_loop_start")]
public static void ExpressionActorFlashLoopStart()
{
if (TryGetPresentation(out LogReleasePresentationController presentation))
presentation.StartActorFlashLoop();
}
/// <summary>
/// 立即停止无限闪现循环、清除当前大字,并恢复晃动粒子字。
/// <<expression_actor_flash_loop_stop>>
/// </summary>
[YarnCommand("expression_actor_flash_loop_stop")]
public static void ExpressionActorFlashLoopStop()
{
if (TryGetPresentation(out LogReleasePresentationController presentation))
presentation.StopActorFlashLoop();
}
/// <summary>
/// 真话闪现(阻塞):谎话大字之间,暖色完整真话带细微抖动挣扎浮现一拍;
/// "被掐断"由紧随其后的 expression_glitch_pulse 表现。不推进谎话冲击等级。
/// <<expression_actor_truth_flash "我就是个笑话" 0.35 8.5 0.55 0.02>>
/// </summary>
[YarnCommand("expression_actor_truth_flash")]
public static IEnumerator ExpressionActorTruthFlash(
string text,
float holdDuration = 0.35f,
float fontSize = 8.5f,
float alpha = 0.8f,
float jitter = 0.02f)
{
if (!TryGetPresentation(out LogReleasePresentationController presentation))
yield break;
yield return ExpressionManager.StartCoroutine(
presentation.FlashActorTruth(text, holdDuration, fontSize, alpha, jitter));
}
/// <summary>
/// 老虎机换字(非阻塞,节拍由 Yarn wait 控制):聚焦字在 duration 内只从 charPool 里疯狂换字。
/// truthPool 非空时其字符也混入换字池,并以真话暖色显示。
/// <<expression_actor_slot "没问题冇" 5 0.05 14 "我就是个笑话">>
/// </summary>
[YarnCommand("expression_actor_slot")]
public static void ExpressionActorSlot(
string charPool,
float duration,
float interval = 0.05f,
float fontSize = 14f,
string truthPool = "")
{
if (TryGetPresentation(out LogReleasePresentationController presentation))
presentation.StartActorSlotMachine(charPool, duration, interval, fontSize, truthPool);
}
/// <summary>
/// 将 Glitch、记忆冲击与画面推近缓慢堆到峰值,停住后保持峰值,等待后续硬切。
/// <<expression_overload_peak 0.75 0.22 1.10 1 1>>
/// </summary>
[YarnCommand("expression_overload_peak")]
public static IEnumerator ExpressionOverloadPeak(
float riseDuration = 0.75f,
float holdDuration = 0.22f,
float zoom = 1.10f,
float glitchPeak = 1f,
float impact = 1f)
{
if (!TryGetPresentation(out LogReleasePresentationController presentation))
yield break;
yield return ExpressionManager.StartCoroutine(
presentation.BuildActorOverloadPeak(
riseDuration,
holdDuration,
zoom,
glitchPeak,
impact));
}
/// <summary>
/// 单字/短词满屏重击,并等待该拍结束。
/// <<expression_actor_word_hit "没" 0.16 18 1.55>>
/// </summary>
[YarnCommand("expression_actor_word_hit")]
public static IEnumerator ExpressionActorWordHit(
string text,
float holdDuration = 0.16f,
float fontSize = 18f,
float punchScale = 1.55f)
{
if (!TryGetPresentation(out LogReleasePresentationController presentation))
yield break;
yield return ExpressionManager.StartCoroutine(
presentation.PlayActorWordHit(text, holdDuration, fontSize, punchScale));
}
/// <summary>
/// 单列词组严格裁在表情屏内,像字幕一样无缝向下滚动。
/// <<expression_actor_scroll "没问题|冇问题|帽问题" 1.8 0.85 0.45 5.2>>
/// </summary>
[YarnCommand("expression_actor_scroll")]
public static IEnumerator ExpressionActorScroll(
string phraseList,
float scrollDuration = 1.8f,
float loopDuration = 0.85f,
float holdDuration = 0.45f,
float fontSize = 5.2f)
{
if (!TryGetPresentation(out LogReleasePresentationController presentation))
yield break;
yield return ExpressionManager.StartCoroutine(
presentation.ScrollActorLies(
phraseList,
scrollDuration,
loopDuration,
holdDuration,
fontSize));
}
[YarnCommand("expression_memory_cut")]
public static void ExpressionMemoryCut()
{
if (TryGetPresentation(out LogReleasePresentationController presentation))
presentation.CutMemoryAndGlitchImmediate();
}
[YarnCommand("expression_truth_snap")]
public static void ExpressionTruthSnap(float peripheral, float calmRadius)
{
if (TryGetPresentation(out LogReleasePresentationController presentation))
presentation.SnapTruthImmediate(peripheral, calmRadius);
}
[YarnCommand("expression_glitch_pulse")]
public static void ExpressionGlitchPulse(float peak, float riseDuration, float fallDuration)
{
if (TryGetPresentation(out LogReleasePresentationController presentation))
presentation.PlayGlitchPulse(peak, riseDuration, fallDuration);
}
/// <summary>
/// 火山「屏幕」Sprite 直驱撕裂花屏(非阻塞)。作用在屏幕材质,不是叠一层噪波。
/// <paramref name="level"/> 是 01 的目标档位,<paramref name="duration"/> 是推到该档位的时间;
/// 到位后一直保持(Shader 自带憋气/发力循环,不会变成静止花屏),要收掉就再调一次 level=0。
/// <<expression_screen_glitch 0.55 1.2>> … <<expression_screen_glitch 0 1.5>>
/// </summary>
[YarnCommand("expression_screen_glitch")]
public static void ExpressionScreenGlitch(
float level = 0.5f,
float duration = 1f)
{
if (ExpressionManager == null)
{
UnityEngine.Debug.LogError(
"[LanguageYarnCommand] expression_screen_glitch 找不到 ExpressionManager;已安全跳过。");
return;
}
ExpressionManager.SetScreenGlitchLevel(level, duration);
}
/// <summary>
/// 用现有目标粒子完整显示一个红色攻击词,并等待确定性的冲击动作结束。
/// 超过目标粒子数量时会安全跳过,不会截断。
/// <<expression_truth_attack "为什么" 0.34 0.45>>
/// </summary>
[YarnCommand("expression_truth_attack")]
public static IEnumerator ExpressionTruthAttack(
string text,
float duration = 0.34f,
float impact = 0.5f)
{
if (!TryGetPresentation(out LogReleasePresentationController presentation))
yield break;
yield return ExpressionManager.StartCoroutine(
presentation.PlayTruthAttack(text, duration, impact));
}
/// <summary>
/// Keep an already resolved truth phrase in place while it gradually becomes unstable and red.
/// <<expression_truth_destabilize "不要那样看我" 1.6 0.13 22 "FF304D">>
/// </summary>
[YarnCommand("expression_truth_destabilize")]
public static IEnumerator ExpressionTruthDestabilize(
string text,
float duration = 1.6f,
float shakeAmplitude = 0.13f,
float shakeSpeed = 22f,
string colorHex = "FF304D")
{
if (!TryGetPresentation(out LogReleasePresentationController presentation))
yield break;
yield return ExpressionManager.StartCoroutine(
presentation.DestabilizeTruthPhrase(
text,
duration,
shakeAmplitude,
shakeSpeed,
colorHex));
}
/// <summary>
/// 将当前攻击词重组为固定青绿色真话,并等待稳定完成。
/// <<expression_truth_settle "我想赢一次" 0.8>>
/// </summary>
[YarnCommand("expression_truth_settle")]
public static IEnumerator ExpressionTruthSettle(
string text,
float duration = 0.8f)
{
if (!TryGetPresentation(out LogReleasePresentationController presentation))
yield break;
yield return ExpressionManager.StartCoroutine(
presentation.SettleTruthPhrase(text, duration));
}
[YarnCommand("expression_truth_blackout")]
public static IEnumerator ExpressionTruthBlackout(float duration, float alpha)
{
if (!TryGetPresentation(out LogReleasePresentationController presentation))
yield break;
yield return ExpressionManager.StartCoroutine(
presentation.HoldTruthBlackout(duration, alpha));
}
[YarnCommand("expression_lie_split")]
public static void ExpressionLieSplit(
float duration,
float distanceRatio,
float stretchX,
float squashY)
{
if (TryGetPresentation(out LogReleasePresentationController presentation))
{
presentation.SplitLieVisual(
duration,
distanceRatio,
stretchX,
squashY);
}
}
[YarnCommand("expression_truth_flash")]
public static void ExpressionTruthFlash(
float alpha,
float riseDuration,
float holdDuration,
float fallDuration)
{
if (TryGetPresentation(out LogReleasePresentationController presentation))
{
presentation.PlayTruthFlash(
alpha,
riseDuration,
holdDuration,
fallDuration);
}
}
[YarnCommand("expression_memory_brightness_pulse")]
public static void ExpressionMemoryBrightnessPulse(
float amount,
float riseDuration,
float fallDuration)
{
if (TryGetPresentation(out LogReleasePresentationController presentation))
presentation.PlayMemoryBrightnessPulse(amount, riseDuration, fallDuration);
}
[YarnCommand("expression_memory_tear")]
public static void ExpressionMemoryTear(float peak, float duration)
{
if (TryGetPresentation(out LogReleasePresentationController presentation))
presentation.PlayMemoryTear(peak, duration);
}
[YarnCommand("expression_face_dip")]
public static void ExpressionFaceDip(float duration, float ratio)
{
if (TryGetPresentation(out LogReleasePresentationController presentation))
presentation.PlayFaceDip(duration, ratio);
}
[YarnCommand("expression_truth_release")]
public static void ExpressionTruthRelease(float alphaDuration)
{
if (TryGetPresentation(out LogReleasePresentationController presentation))
presentation.ReleaseTruthCharacters(alphaDuration);
}
[YarnCommand("expression_truth_resolve")]
public static IEnumerator ExpressionTruthResolve(
float duration,
float peripheral,
float calmRadius)
{
if (!TryGetPresentation(out LogReleasePresentationController presentation))
yield break;
yield return ExpressionManager.StartCoroutine(
presentation.ResolveTruthCharacters(duration, peripheral, calmRadius));
}
[YarnCommand("expression_memory_end")]
public static IEnumerator ExpressionMemoryEnd()
{
if (ExpressionManager == null)
{
UnityEngine.Debug.LogError("ExpressionManager 未找到!");
yield break;
}
yield return ExpressionManager.StartCoroutine(ExpressionManager.EndExpressionMemory());
}
[YarnCommand("expression_truth_impact")]
public static void ExpressionTruthImpact()
{
if (ExpressionManager == null)
{
UnityEngine.Debug.LogError("ExpressionManager 未找到!");
return;
}
ExpressionManager.ImpactExpressionTruth();
}
// /// <summary>
// /// Glitch 噪波过渡(指定起止值),等待完成后再继续下一步。
// /// </summary>
// [YarnCommand("glitch_transition")]
// public static IEnumerator GlitchTransition(float from, float to, float duration)
// {
// if (ExpressionManager == null)
// {
// UnityEngine.Debug.LogError("ExpressionManager 未找到!");
// yield break;
// }
// yield return ExpressionManager.StartCoroutine(ExpressionManager.TransitionGlitchAndWait(from, to, duration));
// }
}
}