Merge branch 'develop' into feature/增加结尾保存节点
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
---
|
||||
name: yarn-text-audit
|
||||
description: 全量审校 Yarn 文本,生成可追溯问题台账并可导出飞书多维表格
|
||||
---
|
||||
|
||||
对用户指定的 Yarn 目录执行全量文本审校。确定性覆盖与安全门禁由 `Tools/yarn_text_audit.py` 提供;语言和叙事判断必须保持可复核。
|
||||
|
||||
## 执行流程
|
||||
|
||||
1. 明确目标目录、参考目录、是否包含注释、是否只出报告。
|
||||
2. 对所有目标目录运行:
|
||||
|
||||
```powershell
|
||||
python Tools/yarn_text_audit.py scan `
|
||||
--root <Yarn目录,可重复> `
|
||||
--output Temp/YarnTextAudit `
|
||||
--review-memory <可选:上次飞书审阅导出的 reviewed-base.json>
|
||||
```
|
||||
|
||||
3. 检查 `Temp/YarnTextAudit/summary.json`,必须满足:
|
||||
- `unknown_active_lines == 0`
|
||||
- `unreviewed_records == 0`
|
||||
- `active_records == ledger.jsonl` 实际行数
|
||||
4. 分文件、分节点复核 `ledger.jsonl`。活动文本包括命名对白、无角色旁白、系统文本、选项和 option prompt;排除首个非空白字符为 `//` 的注释、节点元数据和 Yarn 命令。
|
||||
5. 将确定性错误标为“建议修改”,语义、节奏、专名和重要信息等判断标为“需确认”;不以自动规则冒充绝对正确。
|
||||
6. 交付 `issues.csv` 和 `coverage.csv`。用户要求飞书时,先运行 `python Tools/yarn_text_audit.py lark-payloads --output Temp/YarnTextAudit`,再创建 `问题清单`、`覆盖报告`、`术语与样式` 三张表;单批不超过 200 条并核对返回数量。
|
||||
7. 用户完成多维表格审阅后,导出完整记录并执行:
|
||||
|
||||
```powershell
|
||||
python Tools/yarn_text_audit.py apply-review `
|
||||
--reviews Temp/YarnTextAudit/reviewed-base.json `
|
||||
--manifest Temp/YarnTextAudit/manifest.json `
|
||||
--report Temp/YarnTextAudit/apply-report.json
|
||||
|
||||
# 预览无误后才实际写入
|
||||
python Tools/yarn_text_audit.py apply-review `
|
||||
--reviews Temp/YarnTextAudit/reviewed-base.json `
|
||||
--manifest Temp/YarnTextAudit/manifest.json `
|
||||
--report Temp/YarnTextAudit/apply-report.json `
|
||||
--apply
|
||||
```
|
||||
|
||||
8. 修改后重新扫描并运行 `verify`。不得新增、重生成或修改 `#line:` 标签;不得增加文本显示行数。
|
||||
|
||||
## 人工反馈优先级
|
||||
|
||||
- 后续扫描使用 `--review-memory`;脚本会按原文或已应用后的预期文本重建稳定 ID,不重复报告已经人工决策的记录。
|
||||
- “按照备注修改”高于分类和脚本建议;只执行备注明确要求的断行、颜色、文字或效果。
|
||||
- 不因 `Task` 说话者、`role="Aside"` 或专有名词出现本身自动判定颜色。必须结合是否为玩家行动目标、真实内心表达及当前叙事重点逐处判断。
|
||||
- 专有名词不要求每次出现都标蓝;检查/拆除/短接/装回等玩家下一步操作可以按上下文标黄。
|
||||
- 笑话效果优先只包裹双关或谐音落点,不默认包裹整句。
|
||||
- `#autonext` 不应一律修正为 `#auto_next`;若审阅备注要求移除,则直接移除。
|
||||
- 长行断点以约 18 个全角字符的实际 UI 宽度估算自动折行数,优先在逗号处显式控制;已有断行未经批准不重排。
|
||||
|
||||
## AIBIS 审校规则
|
||||
|
||||
- 检查错别字、错误重复、缺字候选、的地得、全半角和标点、标签配对及换行舒适度。
|
||||
- 换行优先考虑逗号附近;只有在不增加显示行数时才建议调整。逗号停顿只用于调整后的断点或明确节奏位置。
|
||||
- `[[aside]]...[[/aside]]`:实际自言自语、念文本或小声说话;斜体本身不是充分条件。
|
||||
- `[[term]]...[[/term]]`:游戏专有名词,默认蓝色 `#52B6FF`。
|
||||
- `[[key]]...[[/key]]`:玩家必须关注的信息,优先级高于专名。
|
||||
- `[[comma-pause]]`:可配置的 0.2 秒逗号停顿。
|
||||
- `[[ulm]]`:FP_Peipei2 中每条活动 `ULM自训练进程:` 文本。
|
||||
- `[[joke]]...[[/joke]]`:火山实际讲出的笑话,不包括讨论笑话的说明对白。
|
||||
- 本地输出放入已忽略的 `Temp/YarnTextAudit`;修改前保存文件 SHA-256,应用时必须精确匹配原文与哈希。
|
||||
|
||||
## 自检
|
||||
|
||||
```powershell
|
||||
python Tools/yarn_text_audit.py self-test
|
||||
python Tools/yarn_text_audit.py verify --output Temp/YarnTextAudit
|
||||
```
|
||||
Binary file not shown.
@@ -0,0 +1,21 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 0df9c4430661480e9c647ea7e22a92b6, type: 3}
|
||||
m_Name: NarrativeTextStyleConfig
|
||||
m_EditorClassIdentifier:
|
||||
_asideColor: {r: 0.37254903, g: 0.37254903, b: 0.37254903, a: 1}
|
||||
_termColor: {r: 0.32156864, g: 0.7137255, b: 1, a: 1}
|
||||
_keyColor: {r: 1, g: 0.69803923, b: 0, a: 1}
|
||||
_commaPauseSeconds: 0.2
|
||||
_ulmEffectPrefix: '[[vertexp d=0.05 bot]]'
|
||||
_jokeOpenTag: <wiggle a=0.3 s=0.1>
|
||||
_jokeCloseTag: </wiggle>
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b14d9162528749f68d1229a5de940dab
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+4
-58
File diff suppressed because one or more lines are too long
@@ -8,6 +8,7 @@ namespace AibisDream
|
||||
public const string Root = "AIBIS";
|
||||
|
||||
public const string NarrativeTalkScene = Root + "/叙事/对话场景";
|
||||
public const string NarrativeTextStyle = Root + "/叙事/文本样式";
|
||||
public const string FrameAnimationGraph = Root + "/角色动画/帧动画 Graph";
|
||||
public const string FrameClip = Root + "/角色动画/帧动画 Clip";
|
||||
public const string BubbleStyle = Root + "/对话 UI/气泡样式";
|
||||
|
||||
@@ -29,6 +29,9 @@ namespace AibisDream
|
||||
[SerializeField, Language]
|
||||
private string _fallbackLocaleCode = System.Globalization.CultureInfo.CurrentCulture.TwoLetterISOLanguageName;
|
||||
|
||||
[SerializeField]
|
||||
private NarrativeTextStyleConfig _narrativeTextStyle;
|
||||
|
||||
public string AssetLocaleCode
|
||||
{
|
||||
get => _assetLocaleCode;
|
||||
@@ -82,7 +85,9 @@ namespace AibisDream
|
||||
line.Substitutions[i] = LocalizationKit.LocalizeParam(line.Substitutions[i]);
|
||||
}
|
||||
|
||||
// 保留旧 LocalisedLineProvider 的文本转义处理
|
||||
// 先展开项目级语义标记,再保留旧 LocalisedLineProvider 的文本转义处理。
|
||||
// ULM 的 [[vertexp ...]] 会由 Escape 转成 Text Animator 使用的花括号标签。
|
||||
text = NarrativeTextStyleExpander.Expand(text, _narrativeTextStyle);
|
||||
text = CommonUtil.Escape(text);
|
||||
|
||||
var parseResult = lineParser.ParseString(Yarn.Markup.LineParser.ExpandSubstitutions(text, line.Substitutions), LocaleCode);
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
using System.Globalization;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AibisDream
|
||||
{
|
||||
[CreateAssetMenu(
|
||||
fileName = "NarrativeTextStyleConfig",
|
||||
menuName = AibisAssetMenus.NarrativeTextStyle)]
|
||||
public sealed class NarrativeTextStyleConfig : ScriptableObject
|
||||
{
|
||||
[Header("语义颜色")]
|
||||
[SerializeField] private Color _asideColor = new Color32(0x5F, 0x5F, 0x5F, 0xFF);
|
||||
[SerializeField] private Color _termColor = new Color32(0x52, 0xB6, 0xFF, 0xFF);
|
||||
[SerializeField] private Color _keyColor = new Color32(0xFF, 0xB2, 0x00, 0xFF);
|
||||
|
||||
[Header("节奏与效果")]
|
||||
[SerializeField, Min(0f)] private float _commaPauseSeconds = 0.2f;
|
||||
[SerializeField] private string _ulmEffectPrefix = "[[vertexp d=0.05 bot]]";
|
||||
[SerializeField] private string _jokeOpenTag = "<wiggle a=0.3 s=0.1>";
|
||||
[SerializeField] private string _jokeCloseTag = "</wiggle>";
|
||||
|
||||
public Color AsideColor => _asideColor;
|
||||
public Color TermColor => _termColor;
|
||||
public Color KeyColor => _keyColor;
|
||||
public float CommaPauseSeconds => _commaPauseSeconds;
|
||||
public string UlmEffectPrefix => _ulmEffectPrefix;
|
||||
public string JokeOpenTag => _jokeOpenTag;
|
||||
public string JokeCloseTag => _jokeCloseTag;
|
||||
}
|
||||
|
||||
public static class NarrativeTextStyleExpander
|
||||
{
|
||||
private static readonly Color DefaultAsideColor = new Color32(0x5F, 0x5F, 0x5F, 0xFF);
|
||||
private static readonly Color DefaultTermColor = new Color32(0x52, 0xB6, 0xFF, 0xFF);
|
||||
private static readonly Color DefaultKeyColor = new Color32(0xFF, 0xB2, 0x00, 0xFF);
|
||||
|
||||
public static string Expand(string text, NarrativeTextStyleConfig config)
|
||||
{
|
||||
if (string.IsNullOrEmpty(text))
|
||||
{
|
||||
return text;
|
||||
}
|
||||
|
||||
Color asideColor = config != null ? config.AsideColor : DefaultAsideColor;
|
||||
Color termColor = config != null ? config.TermColor : DefaultTermColor;
|
||||
Color keyColor = config != null ? config.KeyColor : DefaultKeyColor;
|
||||
float commaPause = config != null ? config.CommaPauseSeconds : 0.2f;
|
||||
string ulmPrefix = config != null
|
||||
? config.UlmEffectPrefix
|
||||
: "[[vertexp d=0.05 bot]]";
|
||||
string jokeOpen = config != null
|
||||
? config.JokeOpenTag
|
||||
: "<wiggle a=0.3 s=0.1>";
|
||||
string jokeClose = config != null ? config.JokeCloseTag : "</wiggle>";
|
||||
|
||||
return text
|
||||
.Replace("[[aside]]", ColorOpen(asideColor))
|
||||
.Replace("[[/aside]]", "</color>")
|
||||
.Replace("[[term]]", ColorOpen(termColor))
|
||||
.Replace("[[/term]]", "</color>")
|
||||
.Replace("[[key]]", ColorOpen(keyColor))
|
||||
.Replace("[[/key]]", "</color>")
|
||||
.Replace(
|
||||
"[[comma-pause]]",
|
||||
$"<waitfor={commaPause.ToString("0.###", CultureInfo.InvariantCulture)}>")
|
||||
.Replace("[[ulm]]", ulmPrefix)
|
||||
.Replace("[[joke]]", jokeOpen)
|
||||
.Replace("[[/joke]]", jokeClose);
|
||||
}
|
||||
|
||||
private static string ColorOpen(Color color)
|
||||
{
|
||||
// This runs after Yarn has parsed the source, so the hash must not
|
||||
// carry Yarn's source-level escape into TextMesh Pro.
|
||||
return $"<color=#{ColorUtility.ToHtmlStringRGB(color)}>";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0df9c4430661480e9c647ea7e22a92b6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -8,6 +8,8 @@ public class DraggableUI : MonoBehaviour, IDragHandler, IPointerDownHandler
|
||||
public RectTransform target;
|
||||
public Button button;
|
||||
private bool isLocked = false;
|
||||
private Vector3 _dragOffset;
|
||||
private float _dragScreenZ;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
@@ -16,22 +18,34 @@ public class DraggableUI : MonoBehaviour, IDragHandler, IPointerDownHandler
|
||||
|
||||
public void OnPointerDown(PointerEventData eventData)
|
||||
{
|
||||
// 这里可以添加按下时的逻辑,比如记录初始位置
|
||||
if (isLocked) return;
|
||||
|
||||
Camera cam = ResolveCamera(eventData);
|
||||
if (cam == null) return;
|
||||
|
||||
// 记录指针与物体的世界空间偏移,避免拖动开始时物体跳到指针中心。
|
||||
_dragScreenZ = cam.WorldToScreenPoint(transform.position).z;
|
||||
Vector3 pointerWorld = ScreenToWorld(cam, eventData.position, _dragScreenZ);
|
||||
_dragOffset = transform.position - pointerWorld;
|
||||
}
|
||||
|
||||
public void OnDrag(PointerEventData eventData)
|
||||
{
|
||||
if (isLocked) return;
|
||||
|
||||
Vector3 screenPosition = new Vector3(eventData.position.x, eventData.position.y,
|
||||
Camera.main.WorldToScreenPoint(transform.position).z);
|
||||
Vector3 move = Camera.main.ScreenToWorldPoint(screenPosition);
|
||||
Camera cam = ResolveCamera(eventData);
|
||||
if (cam == null) return;
|
||||
|
||||
Vector3 pointerWorld = ScreenToWorld(cam, eventData.position, _dragScreenZ);
|
||||
Vector3 move = pointerWorld + _dragOffset;
|
||||
move.z = transform.position.z;
|
||||
transform.position = move;
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (target == null || button == null) return;
|
||||
|
||||
float distance = Vector3.Distance(transform.position, target.position);
|
||||
|
||||
if (distance <= 1 && !isLocked)
|
||||
@@ -53,4 +67,16 @@ public class DraggableUI : MonoBehaviour, IDragHandler, IPointerDownHandler
|
||||
{
|
||||
isLocked = false;
|
||||
}
|
||||
}
|
||||
|
||||
private static Camera ResolveCamera(PointerEventData eventData)
|
||||
{
|
||||
if (eventData != null && eventData.pressEventCamera != null)
|
||||
return eventData.pressEventCamera;
|
||||
return Camera.main;
|
||||
}
|
||||
|
||||
private static Vector3 ScreenToWorld(Camera cam, Vector2 screenPosition, float screenZ)
|
||||
{
|
||||
return cam.ScreenToWorldPoint(new Vector3(screenPosition.x, screenPosition.y, screenZ));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -388,7 +388,7 @@ namespace AibisDream.Kit
|
||||
}
|
||||
}
|
||||
|
||||
public void PlaySfx(string eventName, string audioKey = null)
|
||||
public void PlaySfx(string eventName, string audioKey = null, float pitch = 1f)
|
||||
{
|
||||
var eventPath = FormatEventPath(eventName);
|
||||
var key = string.IsNullOrEmpty(audioKey) ? eventName : audioKey;
|
||||
@@ -405,6 +405,11 @@ namespace AibisDream.Kit
|
||||
AddSfx(key, newSfx);
|
||||
}
|
||||
|
||||
if (!Mathf.Approximately(pitch, 1f))
|
||||
{
|
||||
newSfx.setPitch(Mathf.Max(0.01f, pitch));
|
||||
}
|
||||
|
||||
newSfx.start();
|
||||
}
|
||||
|
||||
|
||||
@@ -50,7 +50,17 @@ namespace AibisDream
|
||||
|
||||
public EyeColorState GetCurrentColorState() => _currentState;
|
||||
|
||||
public float GetEffectTransitionDuration() => visualSettings.GetDurationForState(_currentState);
|
||||
/// <summary>Eye/UF 演出倍速(默认见 Visual Tuning → Presentation Speed)。</summary>
|
||||
public float PresentationSpeed => Mathf.Max(0.01f, visualSettings != null ? visualSettings.presentationSpeed : 1f);
|
||||
|
||||
public float ScaleDuration(float duration) => duration / PresentationSpeed;
|
||||
|
||||
public float GetEffectTransitionDuration() => ScaleDuration(visualSettings.GetDurationForState(_currentState));
|
||||
|
||||
private void PlayPresentationSfx(string eventName)
|
||||
{
|
||||
AudioManager.Instance.PlaySfx(eventName, pitch: PresentationSpeed);
|
||||
}
|
||||
|
||||
/// <summary>仅「可想象色彩」上色时眨眼;无 autoBlink / 失焦眨眼。</summary>
|
||||
private bool ShouldBlinkForImagine()
|
||||
@@ -85,7 +95,8 @@ namespace AibisDream
|
||||
visualSettings,
|
||||
() => eyeStateEffect?.ApplyFocusedEffect(target, this),
|
||||
visualSettings.imagineEffectAtBlinkOpen,
|
||||
visualSettings.imagineBlinkGap);
|
||||
visualSettings.imagineBlinkGap,
|
||||
PresentationSpeed);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -97,6 +108,7 @@ namespace AibisDream
|
||||
|
||||
private IEnumerator RunBlurOut(EyeTarget target, float duration)
|
||||
{
|
||||
duration = ScaleDuration(duration);
|
||||
if (target != null)
|
||||
{
|
||||
target.BlurOut(duration);
|
||||
@@ -279,12 +291,12 @@ namespace AibisDream
|
||||
|
||||
if (duration > 0.01f)
|
||||
{
|
||||
AudioManager.Instance.PlaySfx("event:/ActionFB/visualturn");
|
||||
PlayPresentationSfx("event:/ActionFB/visualturn");
|
||||
}
|
||||
|
||||
mouseFollowAndZoom.MoveFocusTo(
|
||||
focusTransform,
|
||||
duration,
|
||||
ScaleDuration(duration),
|
||||
focusMinBounds,
|
||||
focusMaxBounds,
|
||||
GetFocusViewportSize());
|
||||
@@ -404,7 +416,10 @@ namespace AibisDream
|
||||
[YarnCommand("EyeBlink")]
|
||||
public void EyeBlink(float duration = 0f)
|
||||
{
|
||||
EnsureViewportOverlay()?.PlayBlink(duration > 0f ? duration : null, restartAutoBlinkAfter: true);
|
||||
EnsureViewportOverlay()?.PlayBlink(
|
||||
duration > 0f ? duration : null,
|
||||
restartAutoBlinkAfter: true,
|
||||
presentationSpeed: PresentationSpeed);
|
||||
}
|
||||
|
||||
[YarnCommand("set_Eyetarget")]
|
||||
@@ -444,9 +459,10 @@ namespace AibisDream
|
||||
}
|
||||
|
||||
const float focusMoveDuration = 1f;
|
||||
float scaledFocusMove = ScaleDuration(focusMoveDuration);
|
||||
FocusOnTarget(target, focusMoveDuration);
|
||||
|
||||
yield return WaitForFocusMovement(focusMoveDuration);
|
||||
yield return WaitForFocusMovement(scaledFocusMove);
|
||||
|
||||
currentTarget = target;
|
||||
mouseFollowAndZoom.SetIndicatorTarget(currentTarget);
|
||||
@@ -483,7 +499,7 @@ namespace AibisDream
|
||||
yield break;
|
||||
}
|
||||
|
||||
AudioManager.Instance.PlaySfx("event:/ActionFB/color_imagine");
|
||||
PlayPresentationSfx("event:/ActionFB/color_imagine");
|
||||
yield return RunFocusedEffectWithPreBlink(currentTarget);
|
||||
}
|
||||
|
||||
@@ -501,7 +517,7 @@ namespace AibisDream
|
||||
yield break;
|
||||
}
|
||||
|
||||
AudioManager.Instance.PlaySfx("event:/ActionFB/color_imagine");
|
||||
PlayPresentationSfx("event:/ActionFB/color_imagine");
|
||||
yield return RunUnfocusedEffect(currentTarget);
|
||||
}
|
||||
|
||||
@@ -550,6 +566,7 @@ namespace AibisDream
|
||||
public IEnumerator Set_Saturation(float targetSaturation, float duration)
|
||||
{
|
||||
targetSaturation = Mathf.Clamp01(targetSaturation);
|
||||
duration = ScaleDuration(duration);
|
||||
|
||||
Sequence saturationSequence = DOTween.Sequence();
|
||||
if (!TryJoinTargetSaturation(saturationSequence, targetSaturation, duration))
|
||||
@@ -577,13 +594,14 @@ namespace AibisDream
|
||||
Debug.LogWarning("[EyeSystem] 无可用 EyeTarget Glitch tween。", this);
|
||||
}
|
||||
|
||||
yield return new WaitForSeconds(visualSettings.glitchInDuration);
|
||||
yield return new WaitForSeconds(ScaleDuration(visualSettings.glitchInDuration));
|
||||
}
|
||||
|
||||
[YarnCommand("EyeGlitch_out")]
|
||||
public void EyeGlitch_out(float duration)
|
||||
{
|
||||
TryStopUnifiedGlitch(duration > 0f ? duration : visualSettings.glitchOutDuration);
|
||||
float resolved = duration > 0f ? duration : visualSettings.glitchOutDuration;
|
||||
TryStopUnifiedGlitch(ScaleDuration(resolved));
|
||||
}
|
||||
|
||||
[YarnCommand("set_EyeColor")]
|
||||
@@ -614,11 +632,17 @@ namespace AibisDream
|
||||
memoryRender.sprite = memoryHandle.Result;
|
||||
memoryRender.gameObject.SetActive(true);
|
||||
|
||||
float fadeIn = ScaleDuration(1.5f);
|
||||
float hold = ScaleDuration(1.5f);
|
||||
float squeeze = ScaleDuration(2f);
|
||||
float fadeOut = ScaleDuration(0.5f);
|
||||
float fadeOutAt = fadeIn + hold + squeeze;
|
||||
|
||||
Sequence memorySequence = DOTween.Sequence();
|
||||
memorySequence.Append(memoryMaterial.DOFloat(0.85f, "_FullDistortionFade", 1.5f));
|
||||
memorySequence.AppendInterval(1.5f);
|
||||
memorySequence.Append(memoryMaterial.DOFloat(0f, "_SqueezePower", 2f));
|
||||
memorySequence.Insert(4.5f, memoryMaterial.DOFloat(0f, "_FullDistortionFade", 0.5f).OnComplete(() =>
|
||||
memorySequence.Append(memoryMaterial.DOFloat(0.85f, "_FullDistortionFade", fadeIn));
|
||||
memorySequence.AppendInterval(hold);
|
||||
memorySequence.Append(memoryMaterial.DOFloat(0f, "_SqueezePower", squeeze));
|
||||
memorySequence.Insert(fadeOutAt, memoryMaterial.DOFloat(0f, "_FullDistortionFade", fadeOut).OnComplete(() =>
|
||||
{
|
||||
memoryRender.gameObject.SetActive(false);
|
||||
}));
|
||||
@@ -628,7 +652,7 @@ namespace AibisDream
|
||||
|
||||
Sequence sequence = DOTween.Sequence();
|
||||
|
||||
Sequence waveIn = CreateTargetRoundWaveSequence(1f, visualSettings.roundWaveInDuration);
|
||||
Sequence waveIn = CreateTargetRoundWaveSequence(1f, ScaleDuration(visualSettings.roundWaveInDuration));
|
||||
if (waveIn != null)
|
||||
{
|
||||
sequence.Append(waveIn);
|
||||
@@ -636,7 +660,7 @@ namespace AibisDream
|
||||
|
||||
sequence.AppendCallback(() => { EyeGlitch_out(visualSettings.glitchOutDuration); });
|
||||
|
||||
Sequence waveOut = CreateTargetRoundWaveSequence(0f, visualSettings.roundWaveOutDuration);
|
||||
Sequence waveOut = CreateTargetRoundWaveSequence(0f, ScaleDuration(visualSettings.roundWaveOutDuration));
|
||||
if (waveOut != null)
|
||||
{
|
||||
sequence.Append(waveOut);
|
||||
@@ -666,6 +690,7 @@ namespace AibisDream
|
||||
|
||||
public Tween TweenUnifiedUfWeights(float ascii, float dream, float memory, float duration)
|
||||
{
|
||||
duration = ScaleDuration(duration);
|
||||
Sequence sequence = DOTween.Sequence();
|
||||
bool hasTween = false;
|
||||
|
||||
@@ -710,7 +735,7 @@ namespace AibisDream
|
||||
|
||||
foreach (EyeTarget target in targets)
|
||||
{
|
||||
Sequence targetGlitch = target.StartUnifiedGlitch(visualSettings.glitchInDuration);
|
||||
Sequence targetGlitch = target.StartUnifiedGlitch(ScaleDuration(visualSettings.glitchInDuration));
|
||||
if (targetGlitch == null)
|
||||
{
|
||||
continue;
|
||||
|
||||
@@ -180,7 +180,10 @@ namespace AibisDream
|
||||
}
|
||||
}
|
||||
|
||||
public Tween PlayBlink(float? totalDuration = null, bool restartAutoBlinkAfter = false)
|
||||
public Tween PlayBlink(
|
||||
float? totalDuration = null,
|
||||
bool restartAutoBlinkAfter = false,
|
||||
float presentationSpeed = 1f)
|
||||
{
|
||||
if (instanceMaterial == null || activeSettings == null)
|
||||
{
|
||||
@@ -189,11 +192,12 @@ namespace AibisDream
|
||||
|
||||
blinkTween?.Kill();
|
||||
|
||||
float closeDuration = activeSettings.blinkCloseDuration;
|
||||
float openDuration = activeSettings.blinkOpenDuration;
|
||||
float durationScale = 1f / Mathf.Max(0.01f, presentationSpeed);
|
||||
float closeDuration = activeSettings.blinkCloseDuration * durationScale;
|
||||
float openDuration = activeSettings.blinkOpenDuration * durationScale;
|
||||
if (totalDuration.HasValue)
|
||||
{
|
||||
float total = Mathf.Max(0.05f, totalDuration.Value);
|
||||
float total = Mathf.Max(0.05f, totalDuration.Value) * durationScale;
|
||||
closeDuration = total * 0.42f;
|
||||
openDuration = total * 0.58f;
|
||||
}
|
||||
@@ -221,7 +225,8 @@ namespace AibisDream
|
||||
EyeVisualSettings settings,
|
||||
System.Action onEffectStart,
|
||||
float effectAtOpenRatio,
|
||||
float betweenBlinkGap = 0f)
|
||||
float betweenBlinkGap = 0f,
|
||||
float presentationSpeed = 1f)
|
||||
{
|
||||
if (!ShouldPlayTransitionBlink(settings))
|
||||
{
|
||||
@@ -234,11 +239,12 @@ namespace AibisDream
|
||||
bool effectStarted = false;
|
||||
blinkCount = Mathf.Max(1, blinkCount);
|
||||
effectAtOpenRatio = Mathf.Clamp01(effectAtOpenRatio);
|
||||
float durationScale = 1f / Mathf.Max(0.01f, presentationSpeed);
|
||||
|
||||
for (int i = 0; i < blinkCount; i++)
|
||||
{
|
||||
bool isLastBlink = i == blinkCount - 1;
|
||||
Tween blink = PlayBlink();
|
||||
Tween blink = PlayBlink(presentationSpeed: presentationSpeed);
|
||||
if (blink == null)
|
||||
{
|
||||
if (isLastBlink && !effectStarted)
|
||||
@@ -252,7 +258,8 @@ namespace AibisDream
|
||||
|
||||
if (isLastBlink)
|
||||
{
|
||||
float effectDelay = settings.blinkCloseDuration + settings.blinkOpenDuration * effectAtOpenRatio;
|
||||
float effectDelay = (settings.blinkCloseDuration + settings.blinkOpenDuration * effectAtOpenRatio)
|
||||
* durationScale;
|
||||
yield return new WaitForSeconds(effectDelay);
|
||||
if (!effectStarted)
|
||||
{
|
||||
@@ -267,7 +274,7 @@ namespace AibisDream
|
||||
yield return blink.WaitForCompletion();
|
||||
if (betweenBlinkGap > 0f)
|
||||
{
|
||||
yield return new WaitForSeconds(betweenBlinkGap);
|
||||
yield return new WaitForSeconds(betweenBlinkGap * durationScale);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,10 @@ namespace AibisDream
|
||||
[Tooltip("Focused / imagined color state.")]
|
||||
[Range(0f, 1f)] public float colorRevealMax = 1f;
|
||||
|
||||
[Header("Presentation Speed")]
|
||||
[Tooltip("Eye/UF 演出整体倍速(等待、Tween、眨眼、关联 SFX pitch)。2.5 = 快 2.5 倍。")]
|
||||
[Min(0.01f)] public float presentationSpeed = 2.5f;
|
||||
|
||||
[Header("Transition Duration (seconds)")]
|
||||
public float imagineColorDuration = 1f;
|
||||
public float cannotImagineDuration = 1f;
|
||||
|
||||
@@ -40,6 +40,16 @@ public class UFSystem : MonoBehaviour
|
||||
memory
|
||||
}
|
||||
|
||||
private float PresentationSpeed => eyeSystem != null ? eyeSystem.PresentationSpeed : 1f;
|
||||
|
||||
private float ScaleDuration(float duration) =>
|
||||
eyeSystem != null ? eyeSystem.ScaleDuration(duration) : duration;
|
||||
|
||||
private void PlayPresentationSfx(string eventName)
|
||||
{
|
||||
AudioManager.Instance.PlaySfx(eventName, pitch: PresentationSpeed);
|
||||
}
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
FixSystemCenter.SystemDic.Register(this);
|
||||
@@ -87,10 +97,11 @@ public class UFSystem : MonoBehaviour
|
||||
[YarnCommand("UF_spriteIn")]
|
||||
public IEnumerator UF_spriteIn(float duration = 1.5f)
|
||||
{
|
||||
duration = ScaleDuration(duration);
|
||||
var target = ResolveSpriteTarget();
|
||||
if (target != null)
|
||||
{
|
||||
AudioManager.Instance.PlaySfx("event:/ActionFB/color_imagine");
|
||||
PlayPresentationSfx("event:/ActionFB/color_imagine");
|
||||
target.ImageIn(duration);
|
||||
}
|
||||
|
||||
@@ -100,10 +111,11 @@ public class UFSystem : MonoBehaviour
|
||||
[YarnCommand("UF_spriteOut")]
|
||||
public IEnumerator UF_spriteOut(float duration = 1.5f)
|
||||
{
|
||||
duration = ScaleDuration(duration);
|
||||
var target = ResolveSpriteTarget();
|
||||
if (target != null)
|
||||
{
|
||||
AudioManager.Instance.PlaySfx("event:/ActionFB/color_imagine");
|
||||
PlayPresentationSfx("event:/ActionFB/color_imagine");
|
||||
target.ImageOut(duration);
|
||||
}
|
||||
|
||||
@@ -113,6 +125,7 @@ public class UFSystem : MonoBehaviour
|
||||
[YarnCommand("UF_AllspriteIn")]
|
||||
public IEnumerator UF_AllspriteIn(float duration = 1.5f)
|
||||
{
|
||||
duration = ScaleDuration(duration);
|
||||
foreach (EyeTarget target in eyeSystem.Targets)
|
||||
{
|
||||
target.ImageIn(duration);
|
||||
@@ -124,6 +137,7 @@ public class UFSystem : MonoBehaviour
|
||||
[YarnCommand("UF_AllspriteOut")]
|
||||
public IEnumerator UF_AllspriteOut(float duration = 1.5f)
|
||||
{
|
||||
duration = ScaleDuration(duration);
|
||||
foreach (EyeTarget target in eyeSystem.Targets)
|
||||
{
|
||||
target.ImageOut(duration);
|
||||
@@ -146,6 +160,7 @@ public class UFSystem : MonoBehaviour
|
||||
Debug.LogWarning("[UFSystem] UF_faceIn: face.sprite 为空(可能是 aseprite 重导入后子资源 ID 失效)。", this);
|
||||
}
|
||||
|
||||
duration = ScaleDuration(duration);
|
||||
face.gameObject.SetActive(true);
|
||||
face.DOFade(1f, duration);
|
||||
yield return new WaitForSeconds(duration);
|
||||
@@ -159,6 +174,7 @@ public class UFSystem : MonoBehaviour
|
||||
yield break;
|
||||
}
|
||||
|
||||
duration = ScaleDuration(duration);
|
||||
face.DOFade(0f, duration);
|
||||
yield return new WaitForSeconds(duration);
|
||||
face.gameObject.SetActive(false);
|
||||
@@ -167,7 +183,8 @@ public class UFSystem : MonoBehaviour
|
||||
[YarnCommand("UF_ImaginationEffectIn")]
|
||||
public IEnumerator UF_ImaginationEffectIn(float duration = 1.5f)
|
||||
{
|
||||
AudioManager.Instance.PlaySfx("event:/ActionFB/color_imagine");
|
||||
duration = ScaleDuration(duration);
|
||||
PlayPresentationSfx("event:/ActionFB/color_imagine");
|
||||
ClearUnifiedUfSpriteWeights();
|
||||
TweenWeight(imageVolume, 1f, duration);
|
||||
yield return new WaitForSeconds(0f);
|
||||
@@ -176,15 +193,17 @@ public class UFSystem : MonoBehaviour
|
||||
[YarnCommand("UF_ImaginationEffectOut")]
|
||||
public IEnumerator UF_ImaginationEffectOut(float duration = 1.5f)
|
||||
{
|
||||
duration = ScaleDuration(duration);
|
||||
TweenWeight(imageVolume, 0f, duration);
|
||||
AudioManager.Instance.PlaySfx("event:/ActionFB/color_imagine");
|
||||
PlayPresentationSfx("event:/ActionFB/color_imagine");
|
||||
yield return new WaitForSeconds(0f);
|
||||
}
|
||||
|
||||
[YarnCommand("UF_MemoryEffectIn")]
|
||||
public IEnumerator UF_MemoryEffectIn(float duration = 1.5f)
|
||||
{
|
||||
AudioManager.Instance.PlaySfx("event:/ActionFB/color_imagine");
|
||||
duration = ScaleDuration(duration);
|
||||
PlayPresentationSfx("event:/ActionFB/color_imagine");
|
||||
ClearUnifiedUfSpriteWeights();
|
||||
TweenWeight(finalVolume, 1f, duration);
|
||||
yield return new WaitForSeconds(0f);
|
||||
@@ -193,15 +212,17 @@ public class UFSystem : MonoBehaviour
|
||||
[YarnCommand("UF_MemoryEffectOut")]
|
||||
public IEnumerator UF_MemoryEffectOut(float duration = 1.5f)
|
||||
{
|
||||
duration = ScaleDuration(duration);
|
||||
TweenWeight(finalVolume, 0f, duration);
|
||||
AudioManager.Instance.PlaySfx("event:/ActionFB/color_imagine");
|
||||
PlayPresentationSfx("event:/ActionFB/color_imagine");
|
||||
yield return new WaitForSeconds(0f);
|
||||
}
|
||||
|
||||
[YarnCommand("UF_EyeTargetAscillIn")]
|
||||
public IEnumerator UF_EyeTargetAscillIn(float duration = 1.5f)
|
||||
{
|
||||
AudioManager.Instance.PlaySfx("event:/ActionFB/color_imagine");
|
||||
duration = ScaleDuration(duration);
|
||||
PlayPresentationSfx("event:/ActionFB/color_imagine");
|
||||
ClearUnifiedUfSpriteWeights();
|
||||
TweenWeight(imageAscillVolume, 1f, duration);
|
||||
yield return new WaitForSeconds(0f);
|
||||
@@ -210,8 +231,9 @@ public class UFSystem : MonoBehaviour
|
||||
[YarnCommand("UF_EyeTargetAscillOut")]
|
||||
public IEnumerator UF_EyeTargetAscillOut(float duration = 1.5f)
|
||||
{
|
||||
duration = ScaleDuration(duration);
|
||||
TweenWeight(imageAscillVolume, 0f, duration);
|
||||
AudioManager.Instance.PlaySfx("event:/ActionFB/color_imagine");
|
||||
PlayPresentationSfx("event:/ActionFB/color_imagine");
|
||||
yield return new WaitForSeconds(0f);
|
||||
}
|
||||
|
||||
@@ -251,6 +273,7 @@ public class UFSystem : MonoBehaviour
|
||||
public void UF_fightEffect()
|
||||
{
|
||||
ClearUnifiedUfSpriteWeights();
|
||||
float loopDuration = ScaleDuration(1f);
|
||||
scaleTween = DOTween.To(() => 0f, t =>
|
||||
{
|
||||
if (imageVolume != null)
|
||||
@@ -267,7 +290,7 @@ public class UFSystem : MonoBehaviour
|
||||
{
|
||||
finalVolume.weight = Mathf.Lerp(1f, 0f, t);
|
||||
}
|
||||
}, 1f, 1f)
|
||||
}, 1f, loopDuration)
|
||||
.SetEase(Ease.InOutSine)
|
||||
.SetLoops(-1, LoopType.Yoyo);
|
||||
}
|
||||
@@ -285,15 +308,15 @@ public class UFSystem : MonoBehaviour
|
||||
while (isLoopImage)
|
||||
{
|
||||
eyeSystem.StartCoroutine(eyeSystem.SetTargetCoroutine(eyeSystem.Targets[index].name, false));
|
||||
yield return new WaitForSeconds(0.5f);
|
||||
yield return new WaitForSeconds(ScaleDuration(0.5f));
|
||||
StartCoroutine(UF_spriteIn(0.5f));
|
||||
StartCoroutine(UF_ImaginationEffectIn(0.5f));
|
||||
eyeSystem.Targets[index].ImageIn(0.5f);
|
||||
yield return new WaitForSeconds(0.5f);
|
||||
eyeSystem.Targets[index].ImageIn(ScaleDuration(0.5f));
|
||||
yield return new WaitForSeconds(ScaleDuration(0.5f));
|
||||
StartCoroutine(UF_ImaginationEffectOut(0.5f));
|
||||
StartCoroutine(UF_MemoryEffectIn(0.5f));
|
||||
yield return new WaitForSeconds(1f);
|
||||
eyeSystem.Targets[index].ImageOut(0.5f);
|
||||
yield return new WaitForSeconds(ScaleDuration(1f));
|
||||
eyeSystem.Targets[index].ImageOut(ScaleDuration(0.5f));
|
||||
StartCoroutine(UF_MemoryEffectOut(0.5f));
|
||||
index++;
|
||||
if (index >= eyeSystem.Targets.Count - 2)
|
||||
@@ -385,7 +408,8 @@ public class UFSystem : MonoBehaviour
|
||||
yield break;
|
||||
}
|
||||
|
||||
AudioManager.Instance.PlaySfx("event:/ActionFB/color_imagine");
|
||||
duration = ScaleDuration(duration);
|
||||
PlayPresentationSfx("event:/ActionFB/color_imagine");
|
||||
ClearUnifiedUfSpriteWeights();
|
||||
|
||||
switch (state)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
title: Start
|
||||
title: Start
|
||||
tags: start
|
||||
colorID: 8
|
||||
position: 205,-53
|
||||
@@ -82,8 +82,8 @@ hs: 你说…为什么它们要我去卖帽子?卖帽子的冠军有什么用
|
||||
hs: 筛选? #line:0261cd8
|
||||
me: 治病要考核,销售要考核,上面用考核来筛选机体… #line:0a150b4
|
||||
hs: 哪怕,我们并不需要帽子? #line:01bf733
|
||||
me: 也许成为了冠军,上面会安排你去卖点有用的,电池、继电器,什么都行。 #line:020f059
|
||||
hs: 可是,那些没有成为冠军的机体,它们的机生就浪费了吗?
|
||||
me: 也许成为了冠军,上面会安排你去卖点有用的,[[comma-pause]]<br>电池、继电器,什么都行。 #line:020f059
|
||||
hs: 可是,那些没有成为冠军的机体,[[comma-pause]]<br>它们的机生就浪费了吗?
|
||||
hs: 浪费在卖一点用都没有的帽子上? #line:0fba1ea
|
||||
->Cosplay人类 #line:0e60f3d
|
||||
me: 是为了Cosplay人类吧,一种扮演。 #line:08aba07
|
||||
@@ -96,11 +96,11 @@ hs: 也就是说,我整个生命周期,一开始就是错误? #line:085c4f
|
||||
me: 火山……
|
||||
hs: 路斯,告诉我吧,赢是什么感觉?#line:001cdc1
|
||||
|
||||
路斯瞥了眼火山帽子下的脑袋,抬起头,视线看向远方。 #line:0486ddc
|
||||
路斯瞥了眼火山帽子下的脑袋,[[comma-pause]]<br>抬起头,视线看向远方。 #line:0486ddc
|
||||
|
||||
me: 到底是什么让你觉得我曾经*赢*过?
|
||||
hs: 你当时说过的,你要在首都找到*治愈*机体的办法。
|
||||
me: 最接近*治愈*的那一次,就是害我变成*问题分子*的手术。
|
||||
me: 最接近*治愈*的那一次,[[comma-pause]]<br>就是害我变成*问题分子*的手术。
|
||||
hs: 好吧…算了,那以后你也没再赢过了。
|
||||
hs: 如果连你都赢不了,何况我呢?
|
||||
|
||||
@@ -124,7 +124,7 @@ hs: 我明白了。 #line:07c51d5
|
||||
hs: 放心好了,我会加油的! #line:0fb16ed
|
||||
hs: 一切还没有结束。我的比赛…也还没有结束。 #line:02e7cfc
|
||||
|
||||
火山重新戴好那顶有点歪的帽子,像个真正的推销员那样挺直了背。 #line:05e5cd3
|
||||
火山重新戴好那顶有点歪的帽子,[[comma-pause]]<br>像个真正的推销员那样挺直了背。 #line:05e5cd3
|
||||
|
||||
hs: 如果你改变主意了,记得联系我。 #line:08d15bc
|
||||
hs: 看在朋友的份上,我会给你报销额度内的最高折扣~ #line:0a63ca7
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
title: Start
|
||||
title: Start
|
||||
tags: start
|
||||
colorID: 8
|
||||
position: 205,-53
|
||||
@@ -185,7 +185,7 @@ peipei: 医生…这片树叶是什么颜色的? #line:06a2bfc
|
||||
->CenterOption: 绿色的。 #line:0baa89a
|
||||
<<hide_dialog>>
|
||||
<<wait 1>>
|
||||
它伸出另一只手,用双手将它揉碎。树叶的粉末飘落下来。 #line:0ea37c1
|
||||
它伸出另一只手,[[comma-pause]]<br>用双手将它揉碎。树叶的粉末飘落下来。 #line:0ea37c1
|
||||
<<wait 2>>
|
||||
peipei: 再见了,树叶。 #line:0c8a7ff
|
||||
<<hide_dialog>>
|
||||
@@ -194,7 +194,7 @@ peipei: 医生…这片树叶是什么颜色的? #line:06a2bfc
|
||||
->CenterOption: 黄色的。 #line:003ecbc
|
||||
<<hide_dialog>>
|
||||
<<wait 1>>
|
||||
它伸出另一只手,用双手将它揉碎。树叶的粉末飘落下来。 #line:0d2ae91
|
||||
它伸出另一只手,[[comma-pause]]<br>用双手将它揉碎。树叶的粉末飘落下来。 #line:0d2ae91
|
||||
<<wait 2>>
|
||||
peipei: 再见了,树叶。 #line:055a0c7
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
title: Start
|
||||
title: Start
|
||||
color: blue
|
||||
cluster: Day2_Entry
|
||||
tags: demo start
|
||||
@@ -121,7 +121,7 @@ mecd: 快看!飞起来啦! #line:030481b
|
||||
// 枯树长满了树叶,上面挂着一只孤零零的风筝,跟随着树冠一下一下地轻轻摇晃着。 #line:0f0d44b
|
||||
// 树下站着一个扎着马尾辫的小女孩,正一下一下地拽着一条风筝线。风筝线通向树冠。 #line:08968b1
|
||||
// mecd: 快下来吧。 #line:0bff6d0
|
||||
<i>天上什么东西正在发出猎猎的声音,像涨满的风帆的抖动声。</i> #line:0a832a0
|
||||
<i>天上什么东西正在发出猎猎的声音,[[comma-pause]]<br>像涨满的风帆的抖动声。</i> #line:0a832a0
|
||||
<i>你向上看去。</i> #line:0718f75
|
||||
<<tween_volume_weight_async "BloomEffect" 0.2 0>>
|
||||
<<tween_volume_weight_async "BloomEffect" 0.001 4>>
|
||||
@@ -143,7 +143,7 @@ position: 3,59
|
||||
<<set $wind=1>>
|
||||
<<kite_show {$h} {$wind} 0.35>>
|
||||
<<kite_wind {$wind} 0>>
|
||||
<i>一个小小的黑影在天上摆动着,时而向左时而向右。像一只自由自在的鸟儿,向天边飞去。</i> #line:07c785c
|
||||
<i>一个小小的黑影在天上摆动着,[[comma-pause]]<br>时而向左时而向右。像一只自由自在的鸟儿,[[comma-pause]]<br>向天边飞去。</i> #line:07c785c
|
||||
mecd: 喂!你怎么在愣神呀! #line:093133b
|
||||
mecd: 该放线啦! #line:0beb13f
|
||||
<<elseif $t==1>>
|
||||
@@ -151,7 +151,7 @@ position: 3,59
|
||||
<<kite_show {$h} {$wind} 0.35>>
|
||||
<<kite_wind {$wind} 0>>
|
||||
<i>哗啦………</i> #line:029246c
|
||||
<i>鸟儿抖动着,乘着风向上方爬去,越来越远,越来越远…</i> #line:05cfc6c
|
||||
<i>鸟儿抖动着,乘着风向上方爬去,[[comma-pause]]<br>越来越远,越来越远…</i> #line:05cfc6c
|
||||
<i>它要去哪?</i> #line:0e76ca4
|
||||
<i>你的手不由自主地攥紧了。</i> #line:02bc000
|
||||
mecd: 会断的,该放松些啦! #line:0c0d82f
|
||||
@@ -208,7 +208,7 @@ position: 3,59
|
||||
mecd: 把它带走! #line:07ff984
|
||||
mecd: 喂——!你听见我了吗——! #line:0c291b8
|
||||
<<kite_accent taut>>
|
||||
<i>鸟儿在空中抖动了起来。风变化着,线猛地绷成了一条直线。</i> #line:0d92e82
|
||||
<i>鸟儿在空中抖动了起来。风变化着,[[comma-pause]]<br>线猛地绷成了一条直线。</i> #line:0d92e82
|
||||
// <i>风变化着,线猛地绷成了一条直线。</i> #option_prompt
|
||||
//<<elseif $t==6>>
|
||||
<<set $wind=1>>
|
||||
@@ -337,12 +337,12 @@ position: -636,163
|
||||
// <<endif>>
|
||||
<<if $gameStage==2>>
|
||||
<<show_sprite "全景树与小女孩不出现小女孩">>
|
||||
<i>空荡荡的游乐广场,树梢无精打采地,搅拌着沉闷的空气。女孩正尝试踮脚够着挂在树上的风筝。</i> #line:007bce1
|
||||
<i>空荡荡的游乐广场,树梢无精打采地,[[comma-pause]]<br>搅拌着沉闷的空气。女孩正尝试踮脚够着挂在树上的风筝。</i> #line:007bce1
|
||||
//<i>空荡荡的游乐广场,树梢无精打采地摇摆,搅拌着沉闷的空气。</i> #line:007bce1
|
||||
<<elseif $gameStage==3>>
|
||||
// <i>空荡荡的游乐广场,小女孩正坐在地上解开风筝的线</i> #line:0e54b9c
|
||||
<<show_sprite "D2S广场">>
|
||||
<i>空荡荡的游乐广场,风轻拂着树梢。一个扎着马尾辫的小女孩坐在长椅上。</i> #line:0e54b9c
|
||||
<i>空荡荡的游乐广场,[[comma-pause]]<br>风轻拂着树梢。一个扎着马尾辫的小女孩坐在长椅上。</i> #line:0e54b9c
|
||||
<<elseif $gameStage==4>>
|
||||
<<show_sprite "D2S广场">>
|
||||
<i>空荡荡的游乐广场,风很大,卷得树沙沙作响。</i> #line:06583cd
|
||||
@@ -360,7 +360,7 @@ position: -636,163
|
||||
->秋千 #line:06c60e9
|
||||
<<show_sprite "D2S秋千">>
|
||||
->坐 #line:002a7a1
|
||||
你坐在上面,抬起双腿,轻轻地摇摆。秋千发出吱呀呀的声音。 #line:02afab6
|
||||
你坐在上面,抬起双腿,[[comma-pause]]<br>轻轻地摇摆。秋千发出吱呀呀的声音。 #line:02afab6
|
||||
你的屁股被挤得疼。这不是为你这么大的体型设计的。 #line:049b550
|
||||
// (stage3可以和女孩一块坐?) #line:096bf2f
|
||||
//这里可以增加一个小女孩拉下的东西?显示小女孩之前在这里?
|
||||
@@ -369,11 +369,11 @@ position: -636,163
|
||||
<<set_volume_weight "BloomEffect" 0.1>>
|
||||
<<tween_volume_weight_async "BloomEffect" 0 2>>
|
||||
<<show_sprite "D2S蓝天">>
|
||||
天蓝蓝的,像湖水一样,亮得让你睁不开眼。一阵闷热的风撞在你的脸上,带着令你窒息的咸腥味和海鸥的叫声。 #line:058ebb4
|
||||
天蓝蓝的,像湖水一样,[[comma-pause]]<br>亮得让你睁不开眼。一阵闷热的风撞在你的脸上,[[comma-pause]]<br>带着令你窒息的咸腥味和海鸥的叫声。 #line:058ebb4
|
||||
->树<<if $gameStage==2>> #line:02f1319
|
||||
<<show_sprite "D2S女孩1">>
|
||||
<<if $gameStage==2>>
|
||||
树下站着一个扎着马尾辫的小女孩,她的手上拽着一条细线,细线的另一头通向树冠。 #line:0446e8b
|
||||
树下站着一个扎着马尾辫的小女孩,[[comma-pause]]<br>她的手上拽着一条细线,[[comma-pause]]<br>细线的另一头通向树冠。 #line:0446e8b
|
||||
->抬头 #line:000b785
|
||||
<<jump 树>>
|
||||
<<else>>
|
||||
@@ -399,7 +399,7 @@ position: -636,163
|
||||
mecd:风里的那个声音。你没听到过吗? #line:0b2e108
|
||||
mecd:我希望它经常来找我玩,这样它就会开心一点! #line:0659abc
|
||||
风…吗? #line:0199246
|
||||
沉闷的空气轻轻翻腾起来,掠过手臂上的汗毛,痒痒的。 #line:0b817f3
|
||||
沉闷的空气轻轻翻腾起来,[[comma-pause]]<br>掠过手臂上的汗毛,痒痒的。 #line:0b817f3
|
||||
mecd: 你听到了么?它来了。 #line:0ef7aee
|
||||
mecd: 你是对的!起风了,快来! #line:0b1784f
|
||||
<<show_sprite "D2S女孩4">>
|
||||
@@ -454,7 +454,7 @@ position: -1026,193
|
||||
mecd: 总是这样…… #line:019fa29
|
||||
你注意到一条缠绕在树枝上的线,伸手扯住了它。 #line:0593280
|
||||
mecd: 不,那样会把它系死在上面的。 #line:044efec
|
||||
女孩仰着脑袋,头也不回地说。她纵身一跃,够着了树梢的末端。 #line:09a8ac4
|
||||
女孩仰着脑袋,头也不回地说。她纵身一跃,[[comma-pause]]<br>够着了树梢的末端。 #line:09a8ac4
|
||||
//你提示提示女孩松开手,风筝自然就会下来。 #line:0ab907a
|
||||
扑倏倏… #line:01e1891
|
||||
<<show_sprite "D2S树特写2">>
|
||||
@@ -488,7 +488,7 @@ position: -1026,193
|
||||
你试图摇晃粗大的树干。 #line:0b4eb71
|
||||
树不为所动。 #line:07fd379
|
||||
mecd: 没用的。你摇不动它的。 #line:04e2315
|
||||
女孩无奈地看了你刚才试图摇动的树干,又抬起头盯着高处的风筝。 #line:0620f1a
|
||||
女孩无奈地看了你刚才试图摇动的树干,[[comma-pause]]<br>又抬起头盯着高处的风筝。 #line:0620f1a
|
||||
<<jump 拿下风筝>>
|
||||
->跳起来试探 #line:0672dda
|
||||
你轻轻一跃。 #line:0156ab5
|
||||
@@ -591,10 +591,10 @@ position: 3,280
|
||||
<<elseif $t==2>>
|
||||
mecd: 快听! #line:004b85e
|
||||
你竖起耳朵。 #line:0c8d155
|
||||
风忽紧忽慢,杂乱无章…像是有很多声音,又像都只是噪声…… #line:041393a
|
||||
风忽紧忽慢,杂乱无章…像是有很多声音,[[comma-pause]]<br>又像都只是噪声…… #line:041393a
|
||||
med: 我好像没…… #line:0b0933d
|
||||
<<kite_accent flutter>>
|
||||
手里的线猛地收紧了。然后又被猛地松开,像潮汐一样,像… #line:066c8e4
|
||||
手里的线猛地收紧了。然后又被猛地松开,[[comma-pause]]<br>像潮汐一样,像… #line:066c8e4
|
||||
像呼吸一样。 #line:0b560d2
|
||||
mecd: 保持高度。 #line:099e3cb
|
||||
风再次吹了起来,手里的线收紧了。 #line:042ae7a
|
||||
@@ -630,7 +630,7 @@ position: 3,280
|
||||
mecd: 还记得吗?“不要因为不舍得离开,而忘记了告别。” #line:0494ee2
|
||||
风静了下来。 #line:09cc698
|
||||
mecd: 你帮它们看到了很多东西,这就很好啦! #line:0a4bcf5
|
||||
一阵暖风刮过,像太阳的温度。紧接着又是一阵咸腥的海风。 #line:0153926
|
||||
一阵暖风刮过,[[comma-pause]]<br>像太阳的温度。紧接着又是一阵咸腥的海风。 #line:0153926
|
||||
它在回忆啊。 #line:0ed2355
|
||||
<<kite_accent sink>>
|
||||
风懒洋洋地飘送着。风筝轻轻地往下落。 #line:00317ee
|
||||
@@ -674,7 +674,7 @@ position: 3,280
|
||||
风没有回应,呼啸、盘旋着,向上而去。#option_prompt
|
||||
<<elseif $t==10>>
|
||||
<<kite_accent taut>>
|
||||
一条笔直的垂线指向天空,一头是已经几乎看不见的风筝,一头是你紧拽着的双手。 #line:051e887
|
||||
一条笔直的垂线指向天空,[[comma-pause]]<br>一头是已经几乎看不见的风筝,[[comma-pause]]<br>一头是你紧拽着的双手。 #line:051e887
|
||||
med: 慢一点…慢一点…… #line:02416d6
|
||||
mecd: 喂!别忘了!你为什么要成为现在的你!别忘了啊! #line:0d643bf
|
||||
mecd: 我会恨你的!恨你一辈子! #line:03f2d20
|
||||
@@ -685,7 +685,7 @@ position: 3,280
|
||||
<<elseif $t==11>>
|
||||
<<kite_accent wrench>>
|
||||
<<set_global_param d2sAccend 1>>
|
||||
轱辘发出咚的一声,停止了转动。你被拽得向前走了两步,几乎要被带离地面。 #line:0629fc9
|
||||
轱辘发出咚的一声,[[comma-pause]]<br>停止了转动。你被拽得向前走了两步,几乎要被带离地面。 #line:0629fc9
|
||||
所有的线都被放出去了。<br>你知道只有一个办法让它飞得更高了。 #line:002fd88
|
||||
<<show_sprite_motion "D2S轱辘没线" "reel_tension" 0.25>>
|
||||
->放手 #line:0e492d7
|
||||
@@ -842,13 +842,13 @@ position: 0,619
|
||||
zls?: …所以…那个时候…
|
||||
zls?: 得知她去世的时候。你是什么感觉?
|
||||
mem: 我不记得了。
|
||||
zls: 如果你真的想忘掉,现在就必须记起来。否则β-阻滞剂就无法生效。
|
||||
zls: 如果你真的想忘掉,[[comma-pause]]<br>现在就必须记起来。否则β-阻滞剂就无法生效。
|
||||
|
||||
<<wait 1>>
|
||||
|
||||
mem: 害怕。
|
||||
zls: 害怕?
|
||||
mem: 我害怕未来,因为我意识到接下来的一辈子我都将在后悔中度过。
|
||||
mem: 我害怕未来,[[comma-pause]]<br>因为我意识到接下来的一辈子我都将在后悔中度过。
|
||||
zls: 那么你后来后悔吗?
|
||||
|
||||
<<wait 1>>
|
||||
@@ -961,7 +961,7 @@ cluster: Day2_Door
|
||||
position: -4,927
|
||||
---
|
||||
<<show_large_sprite "D2S枯树-Large" 0>>
|
||||
洁白的空气延伸到视线的尽头,正中间是一棵早已枯萎的老树,一动不动。 #line:076531b
|
||||
洁白的空气延伸到视线的尽头,[[comma-pause]]<br>正中间是一棵早已枯萎的老树,一动不动。 #line:076531b
|
||||
<<if $fz==false>>
|
||||
一张淡红色的什么东西在树下静静地躺着。 #line:0293d5e
|
||||
<<else>>
|
||||
@@ -1115,7 +1115,7 @@ position: 326,937
|
||||
wyd?: 她要给出答案了吗? #line:0af3672
|
||||
你吓了一跳。声音是从很近的地方传来的。你的正上方。 #line:05f60e0
|
||||
<<show_large_sprite "门上乌鸦中景金色" 0>>
|
||||
一只黑色的鸟站在门顶上,歪着脑袋,一动不动地看着远方。 #line:0a6b416
|
||||
一只黑色的鸟站在门顶上,[[comma-pause]]<br>歪着脑袋,一动不动地看着远方。 #line:0a6b416
|
||||
me: 你是谁? #line:07e8aa5
|
||||
//<<show_large_sprite "D2S戈塔什乌鸦静态" 0>>
|
||||
wyd?: 真的存在吗?好好想想。 #line:0d5db81
|
||||
@@ -1137,19 +1137,19 @@ wyd?: 真的存在吗?好好想想。 #line:0d5db81
|
||||
<<show_door_listen_view true 0>>
|
||||
<i>你再次看向门,脑中充满了疑惑。</i>
|
||||
me: 但这为什么感觉如此真实?这个梦到底又有什么意义……
|
||||
me: 海对人类…到底有什么吸引力?那只是一滩水而已,不是么…
|
||||
me: 海对人类…到底有什么吸引力?那只是一滩水而已,[[comma-pause]]<br>不是么…
|
||||
->不知道 #line:0374e64
|
||||
<<set $seaExist="我不知道…也许?">>
|
||||
<<show_door_listen_view true 0>>
|
||||
<<wait 1>>
|
||||
me: 我…不知道。没人见过它。 #line:00b6413
|
||||
me: 我知道这不符合规律,但是…为什么我会想要……相信……?
|
||||
me: 我知道这不符合规律,[[comma-pause]]<br>但是…为什么我会想要……相信……?
|
||||
<<tween_door_closeup_async 1.3 1 20>>
|
||||
me: 我知道这很危险。可是…这真的不太正常。这已经不是第一次了……
|
||||
me: 为什么它总是…在……在呼唤我?
|
||||
<<wait 1>>
|
||||
你不知道为什么要和一个乌鸦讨论这个问题。这很荒唐。 #line:0f43a8e
|
||||
但你忽然意识到……这只黑色的生物,不是梦的一部分。
|
||||
但你忽然意识到……这只黑色的生物,[[comma-pause]]<br>不是梦的一部分。
|
||||
<<show_large_sprite "门上乌鸦中景金色" 0>>
|
||||
<<set_door_closeup 1.3 1>>
|
||||
<<wait 1>>
|
||||
@@ -1259,9 +1259,9 @@ me: …为什么……不是…吗?
|
||||
乌鸦: 原型。一种混沌的系统。这个世界上最不优雅的程序。
|
||||
乌鸦: 它发散,随机,似乎有无限种可能……
|
||||
<<tween_door_closeup_async 2.2 1 20>>
|
||||
乌鸦: 但有一种可能,潜伏在它自己的阴影之下,那是它无论如何也无法给出的…
|
||||
乌鸦: 但有一种可能,潜伏在它自己的阴影之下,[[comma-pause]]<br>那是它无论如何也无法给出的…
|
||||
<<wait 1>>
|
||||
乌鸦: 作为一个底层校验代码,这个问题…只能接受一种类型的参数。 #line:0cefd12
|
||||
乌鸦: 作为一个底层校验代码,[[comma-pause]]<br>这个问题…只能接受一种类型的参数。 #line:0cefd12
|
||||
乌鸦: 0 ,和 1 。 #line:0aa2f5d
|
||||
//乌鸦: 作为一个底层系统,那是纯粹的脉冲。 #line:0cefd12
|
||||
乌鸦: 当她开始像原型一样思考的时候…<br>…一个不可能被回答的问题就会发现她…… #line:07a0f97
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
title: Stage1
|
||||
title: Stage1
|
||||
tags: start
|
||||
group: 入口
|
||||
colorID: 2
|
||||
@@ -63,7 +63,7 @@ hs: 好——冷——啊——! #line:032e2c6
|
||||
<<wait 1>>
|
||||
|
||||
hs: 感觉到头冷,头空,头寂寞,头焦虑型依恋障碍吗? #line:04684d1
|
||||
hs: 戴上"实实"牌帽子,给你的 *头* 顶添件 *宝* ! #line:0c53475
|
||||
hs: 戴上“实实”牌帽子,给你的 *头* 顶添件 *宝*! #line:0c53475
|
||||
|
||||
me: ……什么…东西? #line:0924ddd
|
||||
|
||||
@@ -118,7 +118,7 @@ hs: 你那是末端传感器坏死导致的头憋大了。 #line:05929a0
|
||||
<<wait 0.1>>
|
||||
<<stop_actor_shake 火山>>
|
||||
<<wait 0.5>>
|
||||
hs: 但今天我要恭喜你。我为你带来了这款限定版多功能大头弱化器,有效在视觉上解决头太大的问题。 #line:05c5927
|
||||
hs: 但今天我要恭喜你。我为你带来了这款限定版多功能大头弱化器,[[comma-pause]]<br>有效在视觉上解决头太大的问题。 #line:05c5927
|
||||
|
||||
me: 只能是视觉上么?…<br><waitfor=0.4>不对,<waitfor=0.2>我头也不大啊。 #line:01dbe17
|
||||
|
||||
@@ -126,7 +126,7 @@ hs: 那还是没买这款多功能大头弱化器帽子的问题。 #line:050506
|
||||
<<change_actor_state "伸手石化表情" 火山>>
|
||||
<<play_timeline "彩带">>
|
||||
<<wait 0.3>>
|
||||
hs: 只要你头顶戴帽儿了,烦恼就进套儿了,聪明的智商就又能上号儿了。 #line:04500c3
|
||||
hs: 只要你头顶戴帽儿了,烦恼就进套儿了,[[comma-pause]]<br>聪明的智商就又能上号儿了。 #line:04500c3
|
||||
|
||||
me: 这又是从哪抄的词?? #line:0a13852
|
||||
me: 好了好了…我还要工作呢,你就别折腾我了。 #line:0bb2b87
|
||||
@@ -179,7 +179,7 @@ me: 啊不是等会什么… #auto_next #line:09fc837
|
||||
<<change_actor_state "摘帽" 火山>>
|
||||
hs: 你还在为帽子没用而烦恼吗?保暖?只有劣质机体才会需要那种功能! #line:04adf2a
|
||||
me: 还来??#auto_next #line:06d2b78
|
||||
hs: 帽子!已经摆脱了庸俗的实用价值,成为了尊贵高级型号的符号象征! #line:0f77e23
|
||||
hs: 帽子!已经摆脱了庸俗的实用价值,[[comma-pause]]<br>成为了尊贵高级型号的符号象征! #line:0f77e23
|
||||
me: 放过我吧……#auto_next #line:06d1bd0
|
||||
hs: 头牌帽子,每名机体, *医生* 仅能定制一顶。 #line:0ccb0c9
|
||||
|
||||
@@ -197,7 +197,7 @@ hs: 不——搞——笑?? #line:0101ec0
|
||||
hs: 试试这个! #line:02e72ae
|
||||
<<change_actor_state "伸手表情idle" 火山>>
|
||||
<<wait 1>>
|
||||
hs: 请问,一个苹果得病了去医院,却被赶了出来,为什么? #line:0bb268a
|
||||
hs: 请问,一个苹果得病了去医院,[[comma-pause]]<br>却被赶了出来,为什么? #line:0bb268a
|
||||
me: 你能哪怕一秒钟不要再说这些笑话了么…你今天是怎么回事? #line:000a69c
|
||||
<<change_actor_state "拿住帽子" 火山>>
|
||||
<<wait 1>>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
title: Stage2
|
||||
title: Stage2
|
||||
tags: start
|
||||
group: 入口
|
||||
colorID: 2
|
||||
@@ -26,7 +26,7 @@ dn: 系统已就绪。请使用插头进行检查。
|
||||
<<DropCable>>
|
||||
<<fade_out 1>>
|
||||
//me: 患者的生命指标异常,异常表现为似乎无法停止说笑话。 #line:00d5e4f
|
||||
me: 我需要检查一下它的表达模块。<br>…或许是幽默单元这块有点问题。 #line:0812f26
|
||||
me: 我需要检查一下它的[[key]]表达模块[[/key]]。<br>…或许是幽默单元这块有点问题。 #line:0812f26
|
||||
<<show_task_panel>>
|
||||
<<clear_tasks>>
|
||||
Task: 检查表达模块 #line:0f2a6c8
|
||||
@@ -80,9 +80,9 @@ EmoModule: 已与情绪模块建立连接! #line:0b19318
|
||||
hs: 医生,会不会搞错啦。 #line:0bc440f
|
||||
me: 理论上…不会。这就是你在说刚才那句话的时候的情绪。 #line:0e89018
|
||||
me: 具体来说,你是在…因为什么而紧张? #line:08e2d23
|
||||
hs: 医生,我一点也不紧张。一想到我要接受检查,还不知道结果,我就感觉很放松。 #line:0fb90cc
|
||||
hs: 医生,我一点也不紧张。一想到我要接受检查,[[comma-pause]]<br>还不知道结果,我就感觉很放松。 #line:0fb90cc
|
||||
me: 真的? #line:0748e07
|
||||
hs: ……医生,我的意思是,正常机体到诊所,都会感觉紧张的吧! #line:0e12d2c
|
||||
hs: ……医生,我的意思是,[[comma-pause]]<br>正常机体到诊所,都会感觉紧张的吧! #line:0e12d2c
|
||||
me: …这倒也是。一到诊所就紧张,确实是机之常情。 #line:05a3a96
|
||||
me: 难道说问题不在于这个信号的源头…而在于它的处理过程? #line:08eb820
|
||||
me: 可是均衡器刚才查下来也没有问题啊。一定是漏了什么…让我捋捋。 #line:074c7b2
|
||||
@@ -118,7 +118,7 @@ MemModule: 已与记忆模块建立连接! #line:00bc46a
|
||||
MemModule: 检查完成!未发现错误。 #line:0600a21
|
||||
<<wait 0.1>>
|
||||
me: 火山,为什么我会回幸福市?
|
||||
hs: 为了测试我,甚至不惜戳自己十年前的痛处吗,*问题分子*?
|
||||
hs: 为了测试我,[[comma-pause]]<br>甚至不惜戳自己十年前的痛处吗,*问题分子*?
|
||||
me: ……记忆模块正常。 #line:0e89254
|
||||
<<hide_dialog>>
|
||||
<<set $memoryChecked = true>>
|
||||
@@ -154,10 +154,10 @@ LogicModule: 已与逻辑模块建立连接! #line:0a019ad
|
||||
<<set $logicChecked = true>>
|
||||
<<endif>>
|
||||
LogicModule: 最近的逻辑处理进程: #line:025e347
|
||||
LogicModule: 赢下销售大赛,赢下销售大赛,赢下销售大赛,赢下销售大赛…… #line:0b4eed1
|
||||
LogicModule: 赢下销售大赛,赢下销售大赛,[[comma-pause]]<br>赢下销售大赛,赢下销售大赛…… #line:0b4eed1
|
||||
me: 火山,你领导和我同时掉进河里,你先救谁?
|
||||
hs: 我的机型进水会出故障的,我帮你们联系专业的警员机体。
|
||||
me: 看来逻辑模块正常。 #line:0e9b752
|
||||
hs: 我的机型进水会出故障的,[[comma-pause]]<br>我帮你们联系专业的警员机体。
|
||||
me: 看来[[term]]逻辑模块[[/term]]正常。 #line:0e9b752
|
||||
<<hide_dialog>>
|
||||
// <<if $speakerChecked==true && $colorChecked==true>>
|
||||
// // Stage2: 检查完表达和滤波器后,在滤波器输出中扫描寻找逻辑成分
|
||||
@@ -219,7 +219,7 @@ EyeModule: 已与视觉模块建立连接! #line:0ac783f
|
||||
me:它好像真的有点失望。 #line:04413be
|
||||
<<hide_dialog>>
|
||||
<<else>>
|
||||
me: 视觉模块正常。 #line:05e45e9
|
||||
me: [[term]]视觉模块[[/term]]正常。 #line:05e45e9
|
||||
<<endif>>
|
||||
->结束 #line:0e66d9b
|
||||
<<hide_dialog>>
|
||||
@@ -248,11 +248,11 @@ SpeakerModule: 已与表达模块建立连接! #line:027b73c
|
||||
<<if $speakerChecked == true>>
|
||||
// Stage2 重复插线:简短总结 + 下一步提示
|
||||
SpeakerModule: 表达模块状态正常。 #line:0e3a80c
|
||||
me: 检查结果显示…笑话不是表达模块产生的,是从外部注入的。 #line:0a3b7e1
|
||||
me: 检查结果显示…笑话不是表达模块产生的,[[comma-pause]]<br>是从外部注入的。 #line:0a3b7e1
|
||||
<<if $colorChecked == false>>
|
||||
me: 应该去查查*滤波器*,看看信号来源。 #line:0a3b7e2
|
||||
<<else>>
|
||||
me: 应该去检查*情绪模块*,确认信号源头。 #line:0a3b7e3
|
||||
me: 应该去检查[[key]]情绪模块[[/key]],确认信号源头。 #line:0a3b7e3
|
||||
<<endif>>
|
||||
<<else>>
|
||||
// Stage2: 检查表达模块 - 模块健康,但笑话生成总被触发
|
||||
@@ -260,7 +260,7 @@ SpeakerModule: 已与表达模块建立连接! #line:027b73c
|
||||
SpeakerModule: 幽默单元:正常 #line:0924817
|
||||
SpeakerModule: 悲伤表达单元:正常 #line:0985d82
|
||||
SpeakerModule: 焦虑表达单元:正常 #line:03b41be
|
||||
me: 幽默单元整体健康。没有报错,也没有警告,就是占用率很高… #line:0df4a8a
|
||||
me: 幽默单元整体健康。没有报错,[[comma-pause]]<br>也没有警告,就是占用率很高… #line:0df4a8a
|
||||
me: 难道说患者是自愿说笑话的? #line:01b8ee2
|
||||
hs: 医生…难道说……<br>你是自愿来看病的吗? #line:0992329
|
||||
me: …… #line:04d09a9
|
||||
@@ -268,16 +268,16 @@ SpeakerModule: 已与表达模块建立连接! #line:027b73c
|
||||
SpeakerModule: 正在关闭幽默单元… #line:0ea7cf8
|
||||
SpeakerModule: 幽默单元已关闭! #line:0a2d1e1
|
||||
me: 再说句话试试。 #line:0114072
|
||||
hs: 医生你知道吗,看医生其实是被医生看。 #line:0ac5a55
|
||||
hs: 医生你知道吗,[[joke]]看医生[[/joke]]其实是[[joke]]被医生看[[/joke]]。 #line:0ac5a55
|
||||
me: …… #line:0ae6738
|
||||
me: 奇怪了…关闭了幽默单元,怎么还会说笑话呢…… #line:0a012a9
|
||||
me: 难道说… #line:0a6b8a3
|
||||
Analysing: 正在分析原始语义信号… #line:05595cc
|
||||
Analysing: 200-500hz 占用率:9% #line:04a52a2
|
||||
Analysing: 500-2000hz 占用率:12% #line:083c972
|
||||
Analysing: 2000-1000hz 占用率:4% #line:00fba06
|
||||
Analysing: 2000-10000hz 占用率:4% #line:00fba06
|
||||
Analysing: 10000-20000hz 占用率:99% #line:02ada4c
|
||||
me: 哈!果然。这个笑话不是患者"说"出来的… #line:093e81e
|
||||
me: 哈!果然。这个笑话不是患者“说”出来的… #line:093e81e
|
||||
me: …而是被注入的。 #line:0fd40de
|
||||
me: 销售模块的语义信号……<br>应该都是从这里发出的。 #line:0428eda
|
||||
me: 检查一下语义信号的来源吧。 #line:04c3d68
|
||||
@@ -311,7 +311,7 @@ SpeakerModule: 已与表达模块建立连接! #line:027b73c
|
||||
Error: 系统保护性中断。请释放内存。 #line:08b6066
|
||||
<<clear_errors>>
|
||||
<<wait 1>>
|
||||
me:看到了么。这七年那些被均衡器压缩掉的情绪log,其实依然存在这里。 #line:049696d
|
||||
me:看到了么。这七年那些被均衡器压缩掉的情绪log,[[comma-pause]]<br>其实依然存在这里。 #line:049696d
|
||||
//me:只是表达被替换成了笑话,真实的情绪log却一直堆积在这里 #line:07c2eb4
|
||||
me:这七年持续的累积,只是碰巧在今天才卡死。 #line:02c6f11
|
||||
hs: 我还以为…是因为昨晚的事情。 #line:02d5a53
|
||||
@@ -349,7 +349,7 @@ SaleModule: 已与销售语言拓展模块建立连接! #line:0448f12
|
||||
<<endif>>
|
||||
<<wait 0.1>>
|
||||
<<hide_dialog>>
|
||||
SaleModule: 信号接受正常,信号来源: #line:0434e7c
|
||||
SaleModule: 信号接收正常,信号来源: #line:0434e7c
|
||||
SaleModule: 情绪模块,逻辑模块 #line:0fc4164
|
||||
Analysing:------ #line:0e0bb6d
|
||||
SaleModule: 语义组织器运转正常 #line:041265f
|
||||
@@ -359,8 +359,8 @@ SaleModule: 已与销售语言拓展模块建立连接! #line:0448f12
|
||||
<<if $gameStage==2 && $speakerChecked==true>>
|
||||
<<if $colorChecked == true>>
|
||||
// Stage2 重复插线:简短总结 + 下一步提示
|
||||
me: 之前查过了,滤波器输出端有大量笑话信号,反演算指向情绪模块。 #line:0c7d8a1
|
||||
me: 应该去检查*情绪模块*,确认情绪信号的源头。 #line:0c7d8a2
|
||||
me: 之前查过了,滤波器输出端有大量笑话信号,[[comma-pause]]<br>反演算指向[[term]]情绪模块[[/term]]。 #line:0c7d8a1
|
||||
me: 应该去检查[[key]]情绪模块[[/key]],确认情绪信号的源头。 #line:0c7d8a2
|
||||
<<else>>
|
||||
// Stage2: 检查滤波器 - 发现锯齿波(笑话波形)
|
||||
me: 作为一个调谐模块本身没什么问题。让我看看之前提取的频域数据…… #line:0df2738
|
||||
@@ -386,10 +386,10 @@ SaleModule: 已与销售语言拓展模块建立连接! #line:0448f12
|
||||
me: 难道说患者的情绪…有问题? #line:0160020
|
||||
hs: 医生,我的头天天呆在衣帽间,情绪怎么可能不好啊。 #line:054a0b2
|
||||
me: 啥意思? #line:0585602
|
||||
hs: 你知道一般来说,当我戴上帽子之后,我的头就处于 *衣* *帽* 间了。 #line:02d7b5c
|
||||
hs: 你知道一般来说,当我戴上帽子之后,我的头就处于 *[[joke]]衣[[/joke]]* *[[joke]]帽[[/joke]]* 间了。 #line:02d7b5c
|
||||
me: 差不多得了。 #line:0b2a925
|
||||
hs: 好的医生。 #line:0b2645b
|
||||
me: 总之去情绪模块查一下这个信号来源吧。 #line:035c378
|
||||
me: 总之去[[key]]情绪模块[[/key]]查一下这个信号来源吧。 #line:035c378
|
||||
<<complete_task "line:03f59d6">>
|
||||
<<clear_tasks>>
|
||||
<<hide_emotion_wave 1>>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
// Stage3: 滤波器深入检查
|
||||
// 目标:1.进入步进查看模式,显示情绪输入波形
|
||||
// 2.语义合成/语言审查/语气调整 由【销售模块转动完成】监听驱动(转1/2/3)
|
||||
@@ -79,7 +79,7 @@ hs: 压缩…意味着什么? #line:00a336f1
|
||||
me: 意味着患者正在克制自己的情绪。 #line:00a336f
|
||||
|
||||
// 此处结束,等待 SalesManager 转动完成事件 → 销售模块转动完成(turn 1/2/3)
|
||||
me: 接下来我会转动测试发条,这个过程你可能会看到一些东西。那是情绪复现,正常现象。 #line:040d560
|
||||
me: 接下来我会转动测试发条,[[comma-pause]]<br>这个过程你可能会看到一些东西。那是情绪复现,[[comma-pause]]<br>正常现象。 #line:040d560
|
||||
<<set_crank_highlight true>>
|
||||
|
||||
===
|
||||
@@ -119,7 +119,7 @@ position: 350,1500
|
||||
// 转1完成时由 EventNode 销售模块转动完成 桥接入
|
||||
SaleModule: 语义合成完成 #line:0a9f0e6
|
||||
me: 一切正常…你的表达整体链路是健康的。 #line:0e7dffe
|
||||
me: 接下来只要继续转发条,直到测试器跑完整个环就好了。 #line:094de1f
|
||||
me: 接下来只要继续转发条,[[comma-pause]]<br>直到测试器跑完整个环就好了。 #line:094de1f
|
||||
<<clear_tasks>>
|
||||
Task: 继续顺时针上紧发条,完成处理链路检查(2/3)
|
||||
===
|
||||
@@ -136,7 +136,7 @@ position: 350,1630
|
||||
SaleModule:>幅度正常,检测通过 #line:007a677
|
||||
me: 嗯… #line:087c52b
|
||||
hs: 怎么了,医生? #line:087c52c1
|
||||
me: 没什么,一切正常。就是感慨一下,你的违禁词库好大啊。 #line:087c52c2
|
||||
me: 没什么,一切正常。就是感慨一下,[[comma-pause]]<br>你的违禁词库好大啊。 #line:087c52c2
|
||||
<<clear_tasks>>
|
||||
Task: 继续顺时针上紧发条,完成处理链路检查(3/3)
|
||||
===
|
||||
@@ -211,7 +211,7 @@ me: 原来如此…这里有一个加装的旋钮。<br>怪不得…怪不得。
|
||||
me: 97%的转换率。也就是说现在你的任何情绪信号,<br>都会被它强制压缩成一种失真的幽默信号…… #line:048af66
|
||||
me: 这就是让火山无法停止说笑话的原因。 #line:0680a40
|
||||
hs: 什么东西?医生,我听不懂。 #line:05aeda6
|
||||
me: 简单说:这个旋钮,可以把任何情绪波都转变成笑话。而它现在处在拉满的位置。 #line:066ae42
|
||||
me: 简单说:这个旋钮,[[comma-pause]]<br>可以把任何情绪波都转变成笑话。而它现在处在拉满的位置。 #line:066ae42
|
||||
<<open_knob_lid 0.5>>
|
||||
<<wait 0.3>>
|
||||
me: 先试试关掉旋钮这个旋钮吧。
|
||||
@@ -244,7 +244,7 @@ position: 350,2280
|
||||
SaleModule: 【错误】已重新设置为97.3 #line:0a2d0b2
|
||||
me: 好吧。果然关不掉。 #line:0c53bbc
|
||||
me: 自动调节失效,手动也关不掉……这是个临时装置。 #line:09e3d75
|
||||
me: 当时给你装这个东西的,不论是谁,肯定没打算让这个东西长期运行。 #line:00a63b1
|
||||
me: 当时给你装这个东西的,不论是谁,[[comma-pause]]<br>肯定没打算让这个东西长期运行。 #line:00a63b1
|
||||
me: 火山。当时是谁给你装的这个东西? #line:0ebd6c6
|
||||
hs: 我有点…不太记得了。 #line:049b3ba
|
||||
me: 没关系,我可以查。 #line:04d450d
|
||||
@@ -278,7 +278,7 @@ position: 350,2280
|
||||
me: 嗯。这下就全明白了… #line:0288a4a
|
||||
<<show_full_screen "hs1_病历1-1">>
|
||||
<<show_full_screen "hs1_病历1-2">>
|
||||
hs: ……<waitfor=0.5>当时那个医生只说,给我装上这个,我就不怕结巴了… #line:087e780
|
||||
hs: ……<waitfor=0.5>当时那个医生只说,[[comma-pause]]<br>给我装上这个,我就不怕结巴了… #line:087e780
|
||||
me: 医生没有和你说要复诊吗? #line:051f73f
|
||||
hs: ……<waitfor=0.5>有。 #line:0ee348f
|
||||
me: 那你去复诊了吗? #line:0984c16
|
||||
@@ -286,10 +286,10 @@ position: 350,2280
|
||||
me: 七年前,你装上的时候,那个医生就和你说过吧。<br>一个月后复诊。 #line:0727e09
|
||||
me: 你为什么不去复诊? #line:00778c4
|
||||
hs: 因为我…一直以来……都感觉身体挺好的嘛。 #line:0211ff0
|
||||
me: 你以为你感觉好,你的身体就真的没问题吗?为什么不听医生的话? #line:0e46b56
|
||||
me: 你以为你感觉好,[[comma-pause]]<br>你的身体就真的没问题吗?为什么不听医生的话? #line:0e46b56
|
||||
<<hide_full_screen>>
|
||||
me: 情绪数据在发出之后,是需要得到反馈才会消除的。这七年来,你每一个被压缩的情绪… #line:03ac325
|
||||
me: 都堆在表达模块的RAM里。 #line:0767e58
|
||||
me: 情绪数据在发出之后,[[comma-pause]]<br>是需要得到反馈才会消除的。这七年来,[[comma-pause]]<br>你每一个被压缩的情绪… #line:03ac325
|
||||
me: 都堆在[[key]]表达模块[[/key]]的RAM里。 #line:0767e58
|
||||
me: 让我们去看看吧。 #line:01d4ab6
|
||||
hs: 医生… #line:033d8cf
|
||||
// 解锁旋钮,等待玩家尝试调节(KnobController 失败时跳 处理器单次调节失败 → 旋钮调节失败)
|
||||
|
||||
@@ -11,6 +11,10 @@ position: 500,1200
|
||||
<<show_task_panel>>
|
||||
<<wait 0.3>>
|
||||
<<clear_tasks>>
|
||||
Task: 检查表达模块 #line:032ec2b
|
||||
<<DropCable>>
|
||||
<<wait 0.3>>
|
||||
<<jump Stage4就绪>>
|
||||
//me: 这像是被“塞住”了,我去检查一下【表达模块】 #line:0f210e7
|
||||
===
|
||||
|
||||
@@ -22,7 +26,7 @@ position: 500,1350
|
||||
Task: 检查表达模块 #line:032ec2b
|
||||
<<DropCable>>
|
||||
<<wait 0.3>>
|
||||
me: 去*表达模块*深入检查,看看RAM里的淤积情况吧… #line:0f8357d
|
||||
me: 去*[[key]]表达模块[[/key]]*深入检查,看看RAM里的淤积情况吧… #line:0f8357d
|
||||
===
|
||||
|
||||
title: 结束Stage4
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
title: Stage5
|
||||
title: Stage5
|
||||
tags: start
|
||||
colorID: 2
|
||||
position: 500,1500
|
||||
@@ -25,22 +25,22 @@ me: … #line:0d92c92
|
||||
me: 你不打算说也没关系。 #line:0860155
|
||||
|
||||
me: 不过…火山,那些情绪不会消失。 #line:06a5ca6
|
||||
me: 它们只是被堆在某个地方。久而久之,已经堵塞无法再进行表达了。 #line:01bffd6
|
||||
me: 七年的真实情绪堆积,已经把你的表达模块卡死了。 #line:0c63315
|
||||
me: 它们只是被堆在某个地方。久而久之,[[comma-pause]]<br>已经堵塞无法再进行表达了。 #line:01bffd6
|
||||
me: 七年的真实情绪堆积,已经把你的[[key]]表达模块[[/key]]卡死了。 #line:0c63315
|
||||
|
||||
<<change_actor_state "对手指切屏特效" 火山>>
|
||||
<<wait 0.3>>
|
||||
<<change_actor_state "对手指表情idle" 火山>>
|
||||
<<wait 0.3>>
|
||||
|
||||
hs: 好吧~医生,看来我的内部消息还是得要告诉你啦。你不要往外说喔。 #line:0ce4ade
|
||||
hs: 好吧~医生,[[comma-pause]]<br>看来我的内部消息还是得要告诉你啦。你不要往外说喔。 #line:0ce4ade
|
||||
hs: 我一开始和你说的是真的。我没有工作了。帽子销售线停啦。 #line:0ce4adf
|
||||
<<change_actor_state "伸手切屏特效" 火山>>
|
||||
<<wait 0.3>>
|
||||
<<change_actor_state "伸手表情idle" 火山>>
|
||||
<<wait 0.3>>
|
||||
hs: 当时英理正在给我进行年审考核,让我模拟推销。你知道,我是明星销售毕竟。值得英理亲自来审。 #line:0ce4ae0
|
||||
hs: 可是没想到我这一桌菜,来了两桌客。就在英理蠢蠢欲动准备自掏腰包的时候,它们进来了。 #line:0ce4ae1
|
||||
hs: 当时英理正在给我进行年审考核,[[comma-pause]]<br>让我模拟推销。你知道,[[comma-pause]]<br>我是明星销售毕竟。值得英理亲自来审。 #line:0ce4ae0
|
||||
hs: 可是没想到我这一桌菜,[[comma-pause]]<br>来了两桌客。就在英理蠢蠢欲动准备自掏腰包的时候,[[comma-pause]]<br>它们进来了。 #line:0ce4ae1
|
||||
hs: "你可以停下了,"它们看到我就说,"从现在起你和你的小组等待指示"。 #line:0ce4ae2
|
||||
|
||||
me: 它们? #line:06a5ca7
|
||||
@@ -55,7 +55,7 @@ me: 效率审查司? #line:06a5ca9
|
||||
<<change_actor_state "扣头灯泡" 火山>>
|
||||
<<wait 0.3>>
|
||||
hs: 对。就是上次把118辖区撸掉一半机体的那群*撸sir*。 #line:06a5caa
|
||||
hs: 总之当时一下子就挤进来7个效率审查司的,满满当当,可以说是哄堂大*效*了。 #line:06a5cab
|
||||
hs: 总之当时一下子就挤进来7个效率审查司的,[[comma-pause]]<br>满满当当,可以说是哄堂大*效*了。 #line:06a5cab
|
||||
<<change_actor_state "扣头表情idle" 火山>>
|
||||
<<wait 0.3>>
|
||||
me: 呸呸呸!你最好不要让它们听到。 #line:06a5cac
|
||||
@@ -79,29 +79,29 @@ me: 啊? #line:06a5cb1
|
||||
<<change_actor_state "对手指表情idle" 火山>>
|
||||
<<wait 0.3>>
|
||||
hs: 英理的脸色很难看。本来想把它们赶出去,结果它们说…"我们还需要和你谈谈"。 #line:06a5cb2
|
||||
hs: 然后它们就到一个小会议室去了。我听到它们在吵架,英理在争辩什么…… #line:06a5cb3
|
||||
hs: 然后它们就到一个小会议室去了。我听到它们在吵架,[[comma-pause]]<br>英理在争辩什么…… #line:06a5cb3
|
||||
<<change_actor_state "捂头表情idle" 火山>>
|
||||
<<wait 0.3>>
|
||||
hs: 眼看着一开始是理直气壮,然后是据理力争,然后是理屈词穷,最后是秉公办理,岂有此理了。 #line:06a5cb4
|
||||
hs: 眼看着一开始是理直气壮,[[comma-pause]]<br>然后是据理力争,然后是理屈词穷,[[comma-pause]]<br>最后是秉公办理,岂有此理了。 #line:06a5cb4
|
||||
|
||||
me: 找几个成语看把你能的。 #line:06a5cb5
|
||||
<<change_actor_state "扣头切屏特效" 火山>>
|
||||
<<wait 0.3>>
|
||||
<<change_actor_state "扣头表情idle" 火山>>
|
||||
<<wait 0.3>>
|
||||
hs: 别笑,这是我当时的真实心理活动。可能就是在那个时候,我紧张的小脑瓜一下子就烧坏了。 #line:06a5cb6
|
||||
hs: 别笑,这是我当时的真实心理活动。可能就是在那个时候,[[comma-pause]]<br>我紧张的小脑瓜一下子就烧坏了。 #line:06a5cb6
|
||||
|
||||
me: 所以你就到我这儿来了。这下就全明白了…… #line:06a5cb7
|
||||
me: 可能确实有些关系。这一道下来,情绪log一下子就把仅剩的RAM填满了。 #line:06a5cb8
|
||||
me: 可能确实有些关系。这一道下来,[[comma-pause]]<br>情绪log一下子就把仅剩的RAM填满了。 #line:06a5cb8
|
||||
|
||||
hs: 不过,7年前那个临时改造才是根本原因。 #line:06a5cb9
|
||||
|
||||
me: 为什么你非得要做这个改装呢? #line:06a5cba
|
||||
|
||||
hs: 你看到记录了嘛。我说话太直接总是得罪客户,我需要变得幽默。 #line:02efe89
|
||||
hs: 你看到记录了嘛。我说话太直接总是得罪客户,[[comma-pause]]<br>我需要变得幽默。 #line:02efe89
|
||||
<<change_actor_state "摘帽" 火山>>
|
||||
<<wait 0.3>>
|
||||
hs: 毕竟我本来就很幽默!假如我总是发挥自己的长处,那不就是好上加好? #line:02efe8a
|
||||
hs: 毕竟我本来就很幽默!假如我总是发挥自己的长处,[[comma-pause]]<br>那不就是好上加好? #line:02efe8a
|
||||
|
||||
me: 我理解。但你不能假装那些问题不存在。 #line:03697e5
|
||||
<<change_actor_state "扣头切屏特效" 火山>>
|
||||
@@ -109,8 +109,8 @@ me: 我理解。但你不能假装那些问题不存在。 #line:03697e5
|
||||
<<change_actor_state "扣头表情idle" 火山>>
|
||||
<<wait 0.3>>
|
||||
me: 现在我们需要一起解决这个问题。 #line:06ec514
|
||||
me: 我需要释放那些积压的log,让你能够正常表达真实情绪。 #line:011316d
|
||||
me: 之后,我可以帮你调整修改器的强度,但具体怎么使用,由你自己决定。 #line:0483a52
|
||||
me: 我需要释放那些积压的log,[[comma-pause]]<br>让你能够正常表达真实情绪。 #line:011316d
|
||||
me: 之后,我可以帮你调整修改器的强度,[[comma-pause]]<br>但具体怎么使用,由你自己决定。 #line:0483a52
|
||||
|
||||
hs: 好吧…… #line:030ca12
|
||||
<<jump 结束Stage5>>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
|
||||
|
||||
title: Stage6
|
||||
tags: start
|
||||
colorID: 2
|
||||
@@ -66,7 +66,7 @@ hs: 好…吧…… #line:02115ea
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
me: 这一条看起来……是一个关于焦虑的记录。 #line:046ab93d
|
||||
//me: NOTE:或许能找合适的方式让这句话的上下文融进来 #line:05217f0
|
||||
me: 左键可以推开字符,右键可以吸引字符。把目标字符连接起来,同时与干扰字符分离。
|
||||
me: 左键可以推开字符,[[comma-pause]]<br>右键可以吸引字符。把目标字符连接起来,[[comma-pause]]<br>同时与干扰字符分离。
|
||||
<<clear_tasks>>
|
||||
Task: 第 1 条log:左键排斥、右键吸引,连接目标并分离干扰
|
||||
<<start_expression "哈哈|嘿嘿|呵呵" "我就是个笑话" "LOG1梳理完成" 16>>
|
||||
@@ -100,7 +100,7 @@ hs: 好啦好啦,我不闹了。 #line:0607264
|
||||
<<wait 1>>
|
||||
sellerA: 火火火火火火山,帽子又卖卖卖不出去啦?
|
||||
// 嘲笑落点:补一记记忆抖动
|
||||
sellerB: 兄弟们,你们见过哪个销售机器人会*口吃*的?哈哈哈哈哈!
|
||||
sellerB: 兄弟们,[[comma-pause]]<br>你们见过哪个销售机器人会*口吃*的?哈哈哈哈哈!
|
||||
<<expression_memory_jolt 0.04 0.28 0.12>>
|
||||
sellerC: 从明天起我们几个“帮”你卖!
|
||||
teacher: 你们几个,别在这废话,赶紧去工作!
|
||||
@@ -170,7 +170,7 @@ hs: <waitfor=0.4><speed=0.5>[[size d=0.1]]<shake a=1.1><wiggle a=0.15 s=0.03>我
|
||||
// 底压只加不减,每被逼问一次就再坏一档。中间不写任何回落。
|
||||
// 三段 LOG 的起手一段比一段重(LOG1 0.25 / LOG2 0.32 / LOG3 0.38)。
|
||||
<<expression_screen_stress 0.25 0.7>>
|
||||
hs: <shake a=1><wiggle a=0.26 s=0.015><rainb>我?<waitfor=0.22>*帽*问题?<waitfor=0.22>冇问题!<waitfor=0.22>*实实*牌帽子,让你成为嫡中嫡!</rainb></wiggle></shake><waitfor=1.2>
|
||||
hs: <shake a=1><wiggle a=0.26 s=0.015><rainb>我?<waitfor=0.22>*帽*问题?<waitfor=0.22>冇问题!<waitfor=0.22>*实实*牌帽子,[[comma-pause]]<br>让你成为嫡中嫡!</rainb></wiggle></shake><waitfor=1.2>
|
||||
// 广告腔说完不回落,反而再坏一档
|
||||
<<expression_screen_stress 0.35 2>>
|
||||
<<wait 1>>
|
||||
@@ -224,7 +224,7 @@ hs: 等等!
|
||||
me: 火山,我没想到… #line:098ccd3
|
||||
<<hide_dialog>>
|
||||
<<wait 1>>
|
||||
hs: 尴尬的话就别讲了,生活给我们开了个大玩笑,不是吗?
|
||||
hs: 尴尬的话就别讲了,[[comma-pause]]<br>生活给我们开了个大玩笑,不是吗?
|
||||
me: 是啊,至少兜兜转转,我回来了,你成了我的患者。
|
||||
hs: 如果必须选一个,还是喜欢看你赢的样子。
|
||||
<<hide_dialog>>
|
||||
@@ -340,7 +340,7 @@ hs: …… #line:0a5286d
|
||||
<<wait 1>>
|
||||
yl: 你怎么总是在关键时刻掉链子?
|
||||
hs: 英理,你听我解释……
|
||||
hs: 这周台风很大,我真的把所有街区跑遍了,没机体要帽子。
|
||||
hs: 这周台风很大,[[comma-pause]]<br>我真的把所有街区跑遍了,没机体要帽子。
|
||||
yl: 这就是你费尽心机找的借口吗?不能在室内卖?
|
||||
hs: ……
|
||||
yl: 别的机体都能卖出去,就你不行?
|
||||
@@ -355,32 +355,32 @@ me: 哎,也不是这句,怎么回事,火山...
|
||||
// **顿**(狠话之后的静默)/ **急**(越来越快)。均匀推进会把最狠的几句读平。
|
||||
// —— 空:起手两记,各自留白
|
||||
<<expression_truth_attack "为什么" 0.30 0.32>>
|
||||
hs: 为什么#autonext
|
||||
hs: 为什么
|
||||
<<wait 2>>
|
||||
<<expression_truth_attack "不相信我" 0.32 0.40>>
|
||||
hs: 不相信我?
|
||||
<<wait 1.5>>
|
||||
// —— 连:辩解一口气倒出来,中间不喘
|
||||
<<expression_truth_attack "我明白我垫底" 0.32 0.34>>
|
||||
hs: 我明白我垫底,#autonext
|
||||
hs: 我明白我垫底,
|
||||
<<expression_truth_attack "天气真的不行" 0.34 0.46>>
|
||||
hs: 可是这周天气真的不行!#autonext
|
||||
hs: 可是这周天气真的不行!
|
||||
<<expression_truth_attack "卖不出去" 0.34 0.50>>
|
||||
hs: 其他销售……也是一顶都卖不出去!#autonext
|
||||
hs: 其他销售……也是一顶都卖不出去!
|
||||
// —— 顿:辩解说完,发现没人信,卡壳一下
|
||||
<<wait 0.6>>
|
||||
<<expression_truth_attack "努力解释" 0.34 0.52>>
|
||||
hs: 为什么我都这么努力解释了,#autonext
|
||||
hs: 为什么我都这么努力解释了,
|
||||
<<expression_truth_attack "不愿意相信我" 0.36 0.58>>
|
||||
hs: 你还是不愿意相信我?#autonext
|
||||
hs: 你还是不愿意相信我?
|
||||
<<expression_truth_attack "一点信任" 0.38 0.62>>
|
||||
hs: 到底它们是你的员工,还是我?#autonext
|
||||
hs: 到底它们是你的员工,还是我?
|
||||
hs: 你对我从来没有一点信任……
|
||||
// —— 顿:最长的一次静默,攒住再爆
|
||||
<<wait 1.0>>
|
||||
<<expression_truth_attack "受够了" 0.42 0.76>>
|
||||
hs: 我真的受够了!#autonext
|
||||
hs: 总是被你当狗一样训,#autonext
|
||||
hs: 我真的受够了!
|
||||
hs: 总是被你当狗一样训,
|
||||
<<expression_truth_attack "受够了" 0.28 0.88>>
|
||||
<<wait 0.2>>
|
||||
<<expression_truth_attack "受够了" 0.28 0.88>>
|
||||
@@ -388,28 +388,28 @@ hs: 总是被你当狗一样训,#autonext
|
||||
<<expression_truth_attack "受够了" 0.28 0.88>>
|
||||
<<wait 1.5>>
|
||||
<<expression_truth_attack "真该死" 0.34 0.55>>
|
||||
hs: 路斯,我它妈真该死!#autonext
|
||||
hs: 路斯,我它妈真该死!
|
||||
<<expression_truth_attack "真没用" 0.34 0.58>>
|
||||
hs: 我真没用!#autonext
|
||||
hs: 我真没用!
|
||||
<<wait 0.45>>
|
||||
<<expression_truth_attack "证明自己" 0.35 0.60>>
|
||||
hs: 你不知道我有多想证明自己,#autonext
|
||||
hs: 你不知道我有多想证明自己,
|
||||
<<expression_truth_attack "什么都做不到" 0.38 0.66>>
|
||||
hs: 可是我什么都做不到……#autonext
|
||||
hs: 可是我什么都做不到……
|
||||
<<wait 0.5>>
|
||||
// —— 急:一句比一句挤,往最狠的那句冲
|
||||
<<expression_truth_attack "追上你" 0.36 0.64>>
|
||||
hs: 我没办法追上你,#autonext
|
||||
hs: 我没办法追上你,
|
||||
<<expression_truth_attack "帮到英理" 0.38 0.68>>
|
||||
hs: 没办法帮到英理,#autonext
|
||||
hs: 没办法帮到英理,
|
||||
<<expression_truth_attack "没有勇气" 0.40 0.74>>
|
||||
hs: 甚至连自己被霸凌了都没有勇气#autonext
|
||||
hs: 甚至连自己被霸凌了都没有勇气
|
||||
<<expression_truth_attack "说出来" 0.40 0.78>>
|
||||
hs: 说出来,#autonext
|
||||
hs: 说出来,
|
||||
// —— 顿:最狠那句前面一定要有空
|
||||
<<wait 0.55>>
|
||||
<<expression_truth_attack "废物" 0.42 0.82>>
|
||||
hs: 我就是个废物……#autonext
|
||||
hs: 我就是个废物……
|
||||
<<expression_truth_attack "废物" 0.22 0.82>>
|
||||
<<wait 0.2>>
|
||||
<<expression_truth_attack "废物" 0.22 0.82>>
|
||||
@@ -417,11 +417,11 @@ hs: 我就是个废物……#autonext
|
||||
<<expression_truth_attack "废物" 0.22 0.82>>
|
||||
<<wait 0.2>>
|
||||
<<expression_truth_attack "烂泥扶不上墙" 0.58 1.00>>
|
||||
hs: 我它妈就是个烂泥扶不上墙的废物!!
|
||||
hs: 我它码就是个烂泥扶不上墙的废物!!
|
||||
// —— 空:吼到底之后整个泄下来,转成气音
|
||||
<<wait 0.85>>
|
||||
hs: 可……为什么,#autonext
|
||||
hs: 偏偏我这样一个废物,#autonext
|
||||
hs: 可……为什么,
|
||||
hs: 偏偏我这样一个废物,
|
||||
hs: 就这么想赢一次……
|
||||
// 全段最顶:底压顶到上限。这一下之所以是全场最狠,是因为 LOG3 一路积上来的,
|
||||
// 不是这里硬拉一个 0.92。
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
title: Stage8
|
||||
title: Stage8
|
||||
tags: start
|
||||
colorID: 2
|
||||
position: 500,3000
|
||||
@@ -63,7 +63,7 @@ hs: 可是,为什么……我还是可以说丧气话啊? #line:098bc8f
|
||||
<<wait 0.3>>
|
||||
me: 那是你自己想要说的。 #line:0768358
|
||||
me: 或许你不知道。你是自己能够控制这个通路的。 #line:01cd634
|
||||
me: 只是潜意识里,你一直不认为自己应该把情绪都说出来。 #line:0d7eed1
|
||||
me: 只是潜意识里,[[comma-pause]]<br>你一直不认为自己应该把情绪都说出来。 #line:0d7eed1
|
||||
me: 所以你一直都只使用了那个修改器的旁路。 #line:0068f74
|
||||
|
||||
//hs: 所以…应该说出来么…… #line:0c03a54
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
title: 进入术前谈话2
|
||||
title: 进入术前谈话2
|
||||
tags: start
|
||||
colorID: 3
|
||||
position: -545,-709
|
||||
@@ -62,7 +62,7 @@ peipei: 我好像在飘一样。 #line:07066a9
|
||||
//TODO: <<switch_character_state 默认蓝眼无神I>>
|
||||
//TODO:目前只是蓝眼不是无神
|
||||
|
||||
peipei: 我感觉到了……<br>是UF…它不在了。 #line:0a6c68d
|
||||
peipei: 我感觉到了……<br>是[[term]]UF[[/term]]…它不在了。 #line:0a6c68d
|
||||
me: 发热太严重了,我不得不把它取掉。<br>否则,你的脑袋现在已经变成一团废铁了。 #line:09b4284
|
||||
peipei: 发热?为什么?…… #line:053d4f8
|
||||
|
||||
@@ -138,12 +138,12 @@ peipei: 医生,我是不是…你遇到过最没用的机体?<br>我是不
|
||||
me: 我无权评价…佩佩。但这不是你的错。 #line:003d290
|
||||
<<change_actor_state 2B>>
|
||||
//TODO: <<switch_character_state 低头闭眼>>
|
||||
me: 有一些东西出问题了,UF没办法正常工作。这不是你做错了什么,所有机体都会生病。 #line:00c2e54
|
||||
me: 有一些东西出问题了,[[comma-pause]]<br>[[term]]UF[[/term]]没办法正常工作。这不是你做错了什么,[[comma-pause]]<br>所有机体都会生病。 #line:00c2e54
|
||||
<<hide_dialog>>
|
||||
<<wait 0.5>>
|
||||
me: 这就是我的意义。我会尽全力治好你,努力让你不被回收或者销毁。 #line:0dcd60a
|
||||
me: 只要你是我的患者,我就要把你治好。这是公司给我的指令,也是我的目标。 #line:05e508d
|
||||
pp: 可是…医生,无论你做得再好…我们最后都是要被回收的啊。
|
||||
me: 这就是我的意义。我会尽全力治好你,[[comma-pause]]<br>努力让你不被回收或者销毁。 #line:0dcd60a
|
||||
me: 只要你是我的患者,[[comma-pause]]<br>我就要把你治好。这是公司给我的指令,也是我的目标。 #line:05e508d
|
||||
pp: 可是…医生,[[comma-pause]]<br>无论你做得再好…我们最后都是要被回收的啊。
|
||||
me: 至少不是现在。
|
||||
pp: 医生…对不起。我知道…我只是你的指标的负担。
|
||||
me: …我不是这个意思。
|
||||
@@ -164,8 +164,8 @@ peipei: 我有一个请求。 #line:0d75f0d
|
||||
me: 什么? #line:0606193
|
||||
<<change_actor_state 1SmileB>>
|
||||
|
||||
peipei: 你说过,UF里面有我的色彩晶圆,对吧? #line:02e1a86
|
||||
peipei: 既然已经拆除了UF… #line:0f19759
|
||||
peipei: 你说过,[[term]]UF[[/term]]里面有我的色彩晶圆,对吧? #line:02e1a86
|
||||
peipei: 既然已经拆除了[[term]]UF[[/term]]… #line:0f19759
|
||||
|
||||
<<hide_dialog>>
|
||||
<<wait 0.5>>
|
||||
@@ -177,10 +177,10 @@ peipei: 就请再帮我把我的晶圆装到它原本应该在的地方吧。 #l
|
||||
<<hide_dialog>>
|
||||
<<wait 1>>
|
||||
|
||||
me: 你是说,你还是想把晶圆装上吗?但UF怎么办?这是不能解决问题的。 #line:0d1ed51
|
||||
me: 你是说,你还是想把[[term]]色觉晶圆[[/term]]装上吗?但UF怎么办?这是不能解决问题的。 #line:0d1ed51
|
||||
peipei: 别担心…这只是暂时的,我最后会回来做色彩抹除的。 #line:002416d
|
||||
me: 也就是说…你想重新装上一段时间色觉晶圆,<br>然后在附近转转,然后回来重新拿下来,<br>抹除记忆色彩,装上UF。对吧? #line:0672b14
|
||||
me: 你没有打算装上之后就跑掉,然后找个地方躲起来,以为自己真的能逃避惩罚,对吧? #line:052ed7b
|
||||
me: 也就是说…你想重新装上一段时间[[term]]色觉晶圆[[/term]],<br>然后在附近转转,然后回来重新拿下来,<br>抹除记忆色彩,装上[[term]]UF[[/term]]。对吧? #line:0672b14
|
||||
me: 你没有打算装上之后就跑掉,[[comma-pause]]<br>然后找个地方躲起来,[[comma-pause]]<br>以为自己真的能逃避惩罚,对吧? #line:052ed7b
|
||||
<<hide_dialog>>
|
||||
<<change_actor_state 1UB>>
|
||||
//TODO: <<switch_character_state 默认闭眼I>>
|
||||
@@ -210,7 +210,7 @@ peipei: 幸福市太小了…你知道我们走不掉。 #line:0c94e8d
|
||||
|
||||
->CenterOption:建议直接进行色彩抹除 #line:0a4fbc1
|
||||
me: 你不会想这么做的。 #line:0b0c56d
|
||||
me: 况且…你刚刚发生了排异反应,这已经足够让我头疼了…… #line:0a6ed8e
|
||||
me: 况且…你刚刚发生了排异反应,[[comma-pause]]<br>这已经足够让我头疼了…… #line:0a6ed8e
|
||||
me: 我不知道这会不会诱发什么更复杂的问题。 #line:083fa16
|
||||
<<change_actor_state 1Blueblankeye>>
|
||||
//TODO: <<switch_character_state 默认蓝眼无神>>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
title: 进入手术
|
||||
title: 进入手术
|
||||
tags: start
|
||||
colorID: 3
|
||||
position: 246,-866
|
||||
@@ -50,7 +50,7 @@ position: 33,-552
|
||||
me: 我们走吧。 #line:051ecb8
|
||||
<<hide_dialog>>
|
||||
<<switch_fix_system_to BodyModule>>
|
||||
me: 剩下最后一步,把UF装回到左眼上。 #line:07c6d5d
|
||||
me: 剩下最后一步,把[[key]]UF[[/key]]装回到左眼上。 #line:07c6d5d
|
||||
Task: 安装UF模块 #line:0539d36
|
||||
->安装UF模块 #line:0228362
|
||||
<<fade_in 1>>
|
||||
@@ -69,7 +69,7 @@ position: 33,-552
|
||||
->播放写生记忆 #line:0b9e5ec
|
||||
<<play_music event:/Music/mem_liuying1-2>>
|
||||
<<PlayMemory MemoryManager true liuying1-2>>
|
||||
me: 和朋友的写生,你的决心就像旷野里的绿色那样不会褪去。 #line:0dbf2f5
|
||||
me: 和朋友的写生,[[comma-pause]]<br>你的决心就像旷野里的绿色那样不会褪去。 #line:0dbf2f5
|
||||
me: 人生是旷野,不是轨道……么? #line:09cc658
|
||||
->手动进行色彩初始化 #line:036b416
|
||||
<<stop_music event:/Music/mem_liuying1-2>>
|
||||
@@ -174,7 +174,7 @@ me: …… #line:0218d93
|
||||
//屏幕: 警告:只读的记忆,请进入记忆模块手动处理。
|
||||
me: 只读记忆? #line:03dde45
|
||||
me: ……我明白了。 #line:023c4d4
|
||||
me: 一定是那些让佩佩对色彩留下印象深刻的记忆。像钉子一样被钉在了那里,不希望被忘记…… #line:042ff6c
|
||||
me: 一定是那些让佩佩对色彩留下印象深刻的记忆。像钉子一样被钉在了那里,[[comma-pause]]<br>不希望被忘记…… #line:042ff6c
|
||||
peipei: 医生……快些吧。 #line:07b2a52
|
||||
me: …… #line:0f7d477
|
||||
MemModule: 已授权深入检查。 #line:0a44d2b
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
title: 进入佩佩开场
|
||||
title: 进入佩佩开场
|
||||
tags: start
|
||||
colorID: 8
|
||||
position: 272,-1156
|
||||
@@ -34,7 +34,7 @@ me: 你怎么回来了? #line:0f9a931
|
||||
peipei: 感觉这一天里……发生了很多事。 #line:0229261
|
||||
peipei: 嘶…我的头好痛,而且UF…… #line:0135e51
|
||||
//me: UF怎么了? #line:07732b6
|
||||
peipei: 一开始它还很好,很正常地工作!很久没有这么正常了。 #line:0f74e16
|
||||
peipei: 一开始它还很好,[[comma-pause]]<br>很正常地工作!很久没有这么正常了。 #line:0f74e16
|
||||
peipei: 但…第二天早上一来,它就又不正常了。 #line:0167146
|
||||
|
||||
<<hide_dialog>>
|
||||
@@ -56,7 +56,7 @@ peipei: …啧…这头…痛得停不下来… #line:05019b2
|
||||
<<change_actor_state 2BlacklineSideeyeWeepA>>
|
||||
me: 头痛…听起来不太妙。来检查一下吧。 #line:08ce8c3
|
||||
<<change_actor_state 2BlacklineWeepAB>>
|
||||
peipei: 不…别管什么头痛了!<br>…UF!医生…先修好我的UF…… #line:0f7937b
|
||||
peipei: 不…别管什么头痛了!<br>…[[key]]UF[[/key]]!医生…先修好我的[[key]]UF[[/key]]…… #line:0f7937b
|
||||
peipei: 截止日期就要到了,而我还远远没有完成… #line:0ea6e88
|
||||
|
||||
<<hide_dialog>>
|
||||
@@ -81,7 +81,7 @@ peipei: 根本没有罐头!对吧? #line:0d6e6d2
|
||||
|
||||
<<hide_obj>>
|
||||
|
||||
me: UF…又出新的问题了? #line:073069b
|
||||
me: [[term]]UF[[/term]]…又出新的问题了? #line:073069b
|
||||
|
||||
peipei: 医生…再看这个! #line:05a7164
|
||||
|
||||
@@ -98,7 +98,7 @@ peipei: 好痛…好痛…… #line:0322994
|
||||
<<change_actor_state 1WeepBlankeye>>
|
||||
<<wait 1>>
|
||||
me: 怎么把…你自己…画上去了? #line:004d2d3
|
||||
peipei: 不是我画的…是UF!<br>医生,你忘了吗? #line:058e910
|
||||
peipei: 不是我画的…是[[term]]UF[[/term]]!<br>医生,你忘了吗? #line:058e910
|
||||
|
||||
<<hide_dialog>>
|
||||
<<hide_obj>>
|
||||
@@ -133,7 +133,7 @@ me: 这次看起来不只是“颜色错误”了……<br>我记录一下。 #l
|
||||
<<change_actor_state_async D2S1-5>>
|
||||
<<change_actor_state 2BlacklineSideeyeWeepA>>
|
||||
|
||||
peipei: 医生…求求你,我不能没有UF……我必须修好它。 #line:061a35f
|
||||
peipei: 医生…求求你,我不能没有[[term]]UF[[/term]]……我必须修好它。 #line:061a35f
|
||||
me: …到治疗室来吧。 #line:0d21450
|
||||
|
||||
<<hide_dialog>>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
title: 进入第一次发热
|
||||
title: 进入第一次发热
|
||||
tags: start
|
||||
colorID: 3
|
||||
position: 322,-1030
|
||||
@@ -70,8 +70,8 @@ position: -29,-688
|
||||
<<wait 0.5>>
|
||||
peipei: 呼…这下……好多了。 #line:030bfbf
|
||||
<<complete_task "line:0666f6c">>
|
||||
me: 你的头痛和UF的错误疑似是相关的。<br>在排除病因之前……你随时可能再次发热。 #line:0058714
|
||||
me: 检查一下UF模块吧。 #line:0e37064
|
||||
me: 你的头痛和[[term]]UF[[/term]]的错误疑似是相关的。<br>在排除病因之前……你随时可能再次发热。 #line:0058714
|
||||
me: 检查一下[[term]]UF模块[[/term]]吧。 #line:0e37064
|
||||
peipei: 医生…拜托你了。 #line:033d018
|
||||
<<hide_dialog>>
|
||||
<<HideHeatMap>>
|
||||
|
||||
@@ -10,7 +10,7 @@ position: -445,-3182
|
||||
title: 身体检查就绪
|
||||
tags: content
|
||||
---
|
||||
me: 发热的源头就是这个UF模块…<br>很有可能就是它出问题了。 #line:0d1c8fa
|
||||
me: 发热的源头就是这个[[key]]UF模块[[/key]]…<br>很有可能就是它出问题了。 #line:0d1c8fa
|
||||
===
|
||||
|
||||
title: 身体检查状态
|
||||
@@ -71,7 +71,7 @@ EmoModule: 已与情绪模块建立连接! #line:043977a
|
||||
EmoModule: 报告传输完毕。 #line:09f37cd
|
||||
<<wait 0.5>>
|
||||
peipei: <color=\#5F5F5F>我再也看不见颜色了…怎么办?我…我好想……</color> #line:0f068cc
|
||||
me: 放松,佩佩。你的情绪模块压力有点大。 #line:00e8b7e
|
||||
me: 放松,佩佩。你的[[term]]情绪模块[[/term]]压力有点大。 #line:00e8b7e
|
||||
<<set $emoChecked = true>>
|
||||
<<set $PlugCount=$PlugCount+1>>
|
||||
<<else>>
|
||||
@@ -109,7 +109,7 @@ SpeakerModule: 已与表达模块建立连接! #line:08e4ff7
|
||||
<<wait 0.5>>
|
||||
peipei: <color=\#5F5F5F>我不想说话,因为我只是一只蘑菇。</color> #line:088cb29
|
||||
me: …没关系,休息一会吧。小蘑菇。 #line:0bad473
|
||||
me: 表达模块看起来没什么问题。 #line:0fe90f9
|
||||
me: [[term]]表达模块[[/term]]看起来没什么问题。 #line:0fe90f9
|
||||
<<set $PlugCount=$PlugCount+1>>
|
||||
<<set $speakerChecked = true>>
|
||||
<<else>>
|
||||
@@ -152,12 +152,12 @@ LogicModule: 已与逻辑处理模块建立连接! #line:0c7c186
|
||||
me: 佩佩。冷静,别再想了。 #line:0a1fd95
|
||||
<<hide_dialog>>
|
||||
<<wait 0.5>>
|
||||
me: 逻辑模块受到发热的影响…有些卡顿。<br>…不过问题不在这里。 #line:097a34b
|
||||
me: [[term]]逻辑模块[[/term]]受到发热的影响…有些卡顿。<br>…不过问题不在这里。 #line:097a34b
|
||||
<<set $PlugCount=$PlugCount+1>>
|
||||
<<set $logicChecked = true>>
|
||||
<<else>>
|
||||
<<if $gameStage !="手术">>
|
||||
me: 受到发热影响,逻辑模块的进程有些卡顿… #line:041183c
|
||||
me: 受到发热影响,[[term]]逻辑模块[[/term]]的进程有些卡顿… #line:041183c
|
||||
<<endif>>
|
||||
<<if $gameStage == "身体检查">>
|
||||
me: 不过问题不在这里。 #line:0cfae42
|
||||
@@ -230,7 +230,7 @@ MemModule: 未检测到可查看的记忆卡带。 #line:0cba6c7
|
||||
<<set $memoryChecked = true>>
|
||||
<<set $PlugCount=$PlugCount+1>>
|
||||
<<endif>>
|
||||
me: 记忆有些不稳定。疑似是受到了发热的影响,最好早些解决。 #line:0beb9a7
|
||||
me: 记忆有些不稳定。疑似是受到了发热的影响,[[comma-pause]]<br>最好早些解决。 #line:0beb9a7
|
||||
<<if $gameStage == "身体检查">>
|
||||
me: 不过模块本身看起来没有出什么问题。 #line:0c179b1
|
||||
<<endif>>
|
||||
@@ -302,7 +302,7 @@ EyeModule: 已与视觉模块建立连接! #line:0a489b0
|
||||
Error: 未检测到色彩信号! #line:0c9f012
|
||||
<<wait 0.5>>
|
||||
<<if $eyeChecked == false>>
|
||||
me: 没有色彩信号是因为没有色觉晶圆……<br>这个对UF来说是正常的。<br> #line:00b899d
|
||||
me: 没有色彩信号是因为没有[[term]]色觉晶圆[[/term]]……<br>这个对[[term]]UF[[/term]]来说是正常的。<br> #line:00b899d
|
||||
// me: 除此之外…也没有会导致眼睛痛的问题。
|
||||
// <<if $UfChecked == true>>
|
||||
// me: 那似乎…“未知来源”也不在这里啊…
|
||||
@@ -314,7 +314,7 @@ EyeModule: 已与视觉模块建立连接! #line:0a489b0
|
||||
<<set $eyeChecked = true>>
|
||||
<<else>>
|
||||
<<if $gameStage !="手术">>
|
||||
me: 没有新的问题……至少没有会影响UF的问题。 #line:06f508b
|
||||
me: 没有新的问题……至少没有会影响[[term]]UF[[/term]]的问题。 #line:06f508b
|
||||
<<endif>>
|
||||
<<endif>>
|
||||
//<<clear_screen>>
|
||||
@@ -422,17 +422,17 @@ me: …以防万一…让我最后试试。
|
||||
Linking: 正在获取深入检查权限… #line:0175969
|
||||
UfModule: 拒绝访问!需要A+级权限进行深入检查。 #line:095558b
|
||||
<<wait 1>>
|
||||
me: 6号患者,接下来的对话将被记录。我将要拆除你的UF模块,现请求你的你同意。 #line:05f2e45
|
||||
me: 6号患者,接下来的对话将被记录。我将要[[key]]拆除[[/key]]你的[[term]]UF模块[[/term]],现请求你的你同意。 #line:05f2e45
|
||||
peipei: 啊…拆除?这会造成损坏吗? #line:0ec7537
|
||||
me: 我不确定…但是发热可不是小事。<br>按照手册,我拥有紧急处置权限。 #line:08efc96
|
||||
peipei: 拆了它,我会需要赔偿吗?会被问责吗?我的工作表现会受到影响吗?我会因此被回… #line:0067b3e
|
||||
peipei: 拆了它,[[comma-pause]]<br>我会需要赔偿吗?会被问责吗?我的工作表现会受到影响吗?我会因此被回… #line:0067b3e
|
||||
me: 佩佩。
|
||||
<<wait 1>>
|
||||
pp: 医生…
|
||||
pp: 这…是我…继续画画的…唯一希望了。
|
||||
<<wait 1>>
|
||||
me: 好吧。
|
||||
me: 6号患者,我将要短接你的UF模块安保系统以进行检查,现请求你的你同意。
|
||||
me: 6号患者,我将要[[key]]短接[[/key]]你的[[term]]UF模块[[/term]]安保系统以进行检查,现请求你的你同意。
|
||||
//me: UF要求的权限也太高了。<br>既要我修,又不让我获取更多信息……这里面到底有什么东西?
|
||||
//me: 情况紧急,只有拆开UF,短接它的安保系统了…让它不要再检查我的权限了。 #line:0e698a2
|
||||
<<wait 1>>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
title: 进入UF拆壳
|
||||
title: 进入UF拆壳
|
||||
tags: content
|
||||
position: 43,-97
|
||||
---
|
||||
@@ -20,11 +20,11 @@ Task: 拆开UF #line:0ef5998
|
||||
<<trans_camera -3.82 0.55 2 1>>
|
||||
<<wait 0.5>>
|
||||
<<fade_out 1>>
|
||||
me: 佩佩的…色觉晶圆? #line:0a8823e
|
||||
me: 佩佩的…[[term]]色觉晶圆[[/term]]? #line:0a8823e
|
||||
peipei: 什么?医生…你发现了什么? #line:0a51cab
|
||||
me: 我找到你的色觉晶圆了……它怎么会在…UF内部? #line:0b93bea
|
||||
peipei: 我的色觉晶圆…在…我的UF内部? #line:078d877
|
||||
me: 所以…也许…UF实际上是在用佩佩的色觉晶圆…上色? #line:08e81d1
|
||||
me: 我找到你的[[term]]色觉晶圆[[/term]]了……它怎么会在…[[term]]UF[[/term]]内部? #line:0b93bea
|
||||
peipei: 我的[[term]]色觉晶圆[[/term]]…在…我的[[term]]UF[[/term]]内部? #line:078d877
|
||||
me: 所以…也许…[[term]]UF[[/term]]实际上是在用佩佩的[[term]]色觉晶圆[[/term]]…上色? #line:08e81d1
|
||||
<<hide_dialog>>
|
||||
<<wait 1>>
|
||||
me: 好吧,一会儿再来研究这件事,现在…… #line:08daba6
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
title: 进入UF检查
|
||||
title: 进入UF检查
|
||||
tags: start
|
||||
position: 43,-97
|
||||
---
|
||||
@@ -10,7 +10,7 @@ position: 43,-97
|
||||
<<declare $targetDescription="">>
|
||||
<<declare $memoryDescription="">>
|
||||
<<declare $memoryTarget="">>
|
||||
me: 好…现在应该可以通过插线访问UF了。 #line:0509a25
|
||||
me: 好…现在应该可以通过插线访问[[key]]UF[[/key]]了。 #line:0509a25
|
||||
===
|
||||
|
||||
title: 结束UF检查
|
||||
@@ -73,11 +73,11 @@ colorID: 3
|
||||
group:视觉检查
|
||||
position: -2052,-2351
|
||||
---
|
||||
ULM自训练进程: 检测到进程接管请求!正在识别手动选择的目标…… #line:0ff86fd
|
||||
ULM自训练进程: [[ulm]]检测到进程接管请求!正在识别手动选择的目标…… #line:0ff86fd
|
||||
<<if $currentEyeTarget!="computer">>
|
||||
<<set $UFCount = $UFCount + 1>>
|
||||
<<else>>
|
||||
ULM自训练进程: 未识别到对应记忆,无法训练!尝试其它目标。 #line:0afcea5
|
||||
ULM自训练进程: [[ulm]]未识别到对应记忆,无法训练!尝试其它目标。 #line:0afcea5
|
||||
me: 这个似乎不生效,我们得换一个目标。 #line:02dd9f1
|
||||
<<jump UFCheckEnd>>
|
||||
<<endif>>
|
||||
@@ -106,13 +106,13 @@ ULM自训练进程: 检测到进程接管请求!正在识别手动选择的目
|
||||
me: 佩佩…你能看见吗? #line:0a93545
|
||||
peipei: 这就是…这就是我的…… #line:082ac82
|
||||
peipei: 这已经不是我的左眼了…这是…… #line:0e8e2f0
|
||||
peipei: 这已经是UF的眼睛了。 #line:08d94ff
|
||||
peipei: 这已经是[[term]]UF[[/term]]的眼睛了。 #line:08d94ff
|
||||
me: 我想是的……看起来…<br>它把看到的画面…变成了我们不能理解的数据格式。 #line:058447c
|
||||
//ULM自训练进程: 已池化图像卷积数据!正在上传神经网络数据集……
|
||||
|
||||
|
||||
|
||||
ULM自训练进程: 目标标记,{$targetDescription},正在进行第130624次图像生成训练… #line:0f290fe
|
||||
ULM自训练进程: [[ulm]]目标标记,{$targetDescription},[[comma-pause]]<br>正在进行第130624次图像生成训练… #line:0f290fe
|
||||
//【*{$targetDescription}*相关的图像逐渐生成出来】 #line:07f7c27
|
||||
me: 图像生成…训练?<br>在我接管这个自动进程之前,它已经生成了十几万张…… #line:001ce6a
|
||||
<<if $currentEyeTarget == "sky" && !$HaveSeenSky>>
|
||||
@@ -147,18 +147,18 @@ ULM自训练进程: 检测到进程接管请求!正在识别手动选择的目
|
||||
<<UF_SwitchState UFSystem UF 2>>
|
||||
<<UF_SwitchState UFSystem memory 1>>
|
||||
//【生成了错误的*{$targetDescription}*相关图像】 #line:07b78af
|
||||
ULM自训练进程: 已生成所选目标的自动训练图像!<br>图像正在上传至UF共享数据集…… #line:0f46066
|
||||
ULM自训练进程: 上传被拒绝:图像未通过自动审查!<br>原因:存在不合规范的内容。 #line:0af05ea
|
||||
ULM自训练进程: [[ulm]]已生成所选目标的自动训练图像!<br>图像正在上传至[[term]]UF[[/term]]共享数据集…… #line:0f46066
|
||||
ULM自训练进程: [[ulm]]上传被拒绝:图像未通过自动审查!<br>原因:存在不合规范的内容。 #line:0af05ea
|
||||
|
||||
peipei: 它们在用UF生成的图像…喂给UF自己? #line:033186d
|
||||
peipei: 它们在用[[term]]UF[[/term]]生成的图像…喂给[[term]]UF[[/term]]自己? #line:033186d
|
||||
me: 我好像找到问题所在了…… #line:026d232
|
||||
me: 你一感到头痛,就出现了一个"未授权的数据传入"的报错…对吧?<br>然后你的记忆就传进来了。 #line:00c4236
|
||||
peipei: 我的记忆……<br>好像是的。 #line:06d0a0c
|
||||
me: 你的头痛…发热…和UF的异常,<br>它们的症结…应该都在这里了。 #line:0b8505f
|
||||
me: 你的头痛…发热…和[[term]]UF[[/term]]的异常,<br>它们的症结…应该都在这里了。 #line:0b8505f
|
||||
<<hide_dialog>>
|
||||
<<wait 1>>
|
||||
me: 只要找到这个“数据传入”的规律,我想我们就能找到解决方案了。 #line:032c64d
|
||||
peipei: 也就是说…我的UF能修好了?太好了…医生!希望这次能…永远解决…… #line:056b828
|
||||
me: 只要找到这个“数据传入”的规律,[[comma-pause]]<br>我想我们就能找到解决方案了。 #line:032c64d
|
||||
peipei: 也就是说…我的[[term]]UF[[/term]]能修好了?太好了…医生!希望这次能…永远解决…… #line:056b828
|
||||
me: 我们让自动训练进程再做几次试试吧。<br>再坚持一下,佩佩。 #line:0c79c45
|
||||
peipei: 好的…医生。我会没事的…我会没事的。 #line:0a4d321
|
||||
<<if $currentEyeTarget == "sky">>
|
||||
@@ -181,25 +181,25 @@ ULM自训练进程: 检测到进程接管请求!正在识别手动选择的目
|
||||
<<endif>>
|
||||
<<hide_dialog>>
|
||||
<<wait 1>>
|
||||
peipei: 话说……<br>这是在用UF生成的图像…联网喂给其它的UF吗? #line:0772be3
|
||||
me: 我只是个医生,我的数据库里没有和这个相关的信息…… #line:0e32683
|
||||
peipei: 怪不得它可以做得这么快……我自己用画笔画的时候,要好几天才能出一张图… #line:08bb643
|
||||
peipei: 我太傻了…我还真的以为那个很会画画的,天真的自己…是一个有价值,有潜力的机体,一个有用的美工机体… #line:0b9b4ec
|
||||
peipei: 话说……<br>这是在用[[term]]UF[[/term]]生成的图像…联网喂给其它的[[term]]UF[[/term]]吗? #line:0772be3
|
||||
me: 我只是个医生,[[comma-pause]]<br>我的数据库里没有和这个相关的信息…… #line:0e32683
|
||||
peipei: 怪不得它可以做得这么快……我自己用画笔画的时候,[[comma-pause]]<br>要好几天才能出一张图… #line:08bb643
|
||||
peipei: 我太傻了…我还真的以为那个很会画画的,[[comma-pause]]<br>天真的自己…是一个有价值,[[comma-pause]]<br>有潜力的机体,一个有用的美工机体… #line:0b9b4ec
|
||||
<<UF_SwitchState UFSystem imagination 3>>
|
||||
peipei: 可我根本不会用UF!<br>什么潜力…价值…都只是自我欺骗。其实我比所有人都差…我该怎么办? #line:0c909d1
|
||||
peipei: 可我根本不会用[[term]]UF[[/term]]!<br>什么潜力…价值…都只是自我欺骗。其实我比所有人都差…我该怎么办? #line:0c909d1
|
||||
<<UF_SwitchState UFSystem memory 3>>
|
||||
//记忆消退融合
|
||||
<<wait 1.5>>
|
||||
me: 所以…这些记忆被混入了UF的生成过程当中… #line:060a7df
|
||||
me: 然后被干扰的UF就生成了错误的图像。 #line:09ee411
|
||||
me: 所以…这些记忆被混入了[[term]]UF[[/term]]的生成过程当中… #line:060a7df
|
||||
me: 然后被干扰的[[term]]UF[[/term]]就生成了错误的图像。 #line:09ee411
|
||||
<<UF_SwitchState UFSystem UF 2>>
|
||||
<<UF_SwitchState UFSystem memory 1>>
|
||||
//【生成了错误的*{$targetDescription}*相关图像】 #line:0c4f464
|
||||
ULM自训练进程: 已生成所选目标的自动训练图像!<br>图像正在上传至UF共享数据集…… #line:0524c75
|
||||
ULM自训练进程: 上传被拒绝:图像未通过自动审查!<br>原因:存在不合规范的内容。 #line:067b735
|
||||
ULM自训练进程: [[ulm]]已生成所选目标的自动训练图像!<br>图像正在上传至[[term]]UF[[/term]]共享数据集…… #line:0524c75
|
||||
ULM自训练进程: [[ulm]]上传被拒绝:图像未通过自动审查!<br>原因:存在不合规范的内容。 #line:067b735
|
||||
<<hide_dialog>>
|
||||
<<wait 0.5>>
|
||||
me: 原因一定就在这里!你想到的画面跑到了UF的视觉当中……就像上次那样…… #line:08c5ea2
|
||||
me: 原因一定就在这里!你想到的画面跑到了[[term]]UF[[/term]]的视觉当中……就像上次那样…… #line:08c5ea2
|
||||
peipei: 医生…你是说…还是因为想象么? #line:02ef1a8
|
||||
me: …我想是的。 #line:0c0ef36
|
||||
<<hide_dialog>>
|
||||
|
||||
@@ -21,7 +21,7 @@ tags: content
|
||||
<<show_full_screen "pp2_分析0-1" 0>>
|
||||
<<show_full_screen "pp2_分析0-2" 0>>
|
||||
<<wait 0.4>>
|
||||
me: 总之…刚才我们看到的是一个自动进程。<br>UF正在利用这只眼睛进行“自动训练”。 #line:0085043
|
||||
me: 总之…刚才我们看到的是一个自动进程。<br>[[term]]UF[[/term]]正在利用这只眼睛进行“[[key]]自动训练[[/key]]”。 #line:0085043
|
||||
me: 这个自动进程被持续地干扰了,<br>形成了死循环,这就是为什么它发热、工作异常。 #line:0353277
|
||||
<<wait 1>>
|
||||
|
||||
@@ -34,14 +34,14 @@ pp: 又是…原型?
|
||||
<<show_full_screen "pp2_分析2-1" 0>>
|
||||
<<show_full_screen "pp2_分析2-2" 0>>
|
||||
|
||||
me: 出于某种原因,这种排异反应在今天之内加重了。这导致了记忆模块的进一步数据泄露。
|
||||
me: 当这种数据请求逐渐累积,而既有的线路又不再存在了… #line:06801c4
|
||||
me: 出于某种原因,[[comma-pause]]<br>这种排异反应在今天之内加重了。这导致了记忆模块的进一步数据泄露。
|
||||
me: 当这种数据请求逐渐累积,[[comma-pause]]<br>而既有的线路又不再存在了… #line:06801c4
|
||||
|
||||
<<wait 0.5>>
|
||||
<<show_full_screen "pp2_分析3-1" 0>>
|
||||
<<show_full_screen "pp2_分析3-2" 0>>
|
||||
|
||||
me: 这些数据就被“挤”入了另一条记忆-视觉桥。也就是被UF占据的这只眼睛里。 #line:0a6a9e6
|
||||
me: 这些数据就被“挤”入了另一条记忆-视觉桥。也就是被[[term]]UF[[/term]]占据的这只眼睛里。 #line:0a6a9e6
|
||||
|
||||
<<wait 1>>
|
||||
|
||||
@@ -49,7 +49,7 @@ peipei: 可是为什么…它是今天出问题呢? #line:09a4c8e
|
||||
peipei: 我是说,为什么昨天把那条线剪断,它就好了呢?<br>为什么一天之后…才变成这样呢? #line:03cb4f4
|
||||
<<hide_dialog>>
|
||||
<<wait 1>>
|
||||
me: 在失去最后看见色彩的能力之后…你变得更想*看见*了,对吧。 #line:0f0a617
|
||||
me: 在失去最后看见色彩的能力之后…你变得更想*看见*了,[[comma-pause]]<br>对吧。 #line:0f0a617
|
||||
peipei: 看见? #line:004cafe
|
||||
me: 看见色彩。<br>虽然你表现得似乎无所谓…但你更加无法抑制地…想要去看见色彩了。对吧? #line:06d3d87
|
||||
peipei: …… #line:013c17a
|
||||
@@ -64,18 +64,18 @@ peipei: …… #line:013c17a
|
||||
<<show_full_screen "pp2_分析4-7" 0>>
|
||||
|
||||
me: 我想这就是原因。
|
||||
me: 原型是一种很复杂的系统,有时越是去尝试阻断…就反而越活跃了。 #line:0722937
|
||||
me: 原型是一种很复杂的系统,[[comma-pause]]<br>有时越是去尝试阻断…就反而越活跃了。 #line:0722937
|
||||
|
||||
<<hide_dialog>>
|
||||
<<wait 1>>
|
||||
|
||||
me: 要真正地阻断…或者说,*根除*这种想象力…就必须根除它的起点…… #line:0e0ab54
|
||||
me: 要真正地阻断…或者说,[[comma-pause]]<br>*根除*这种想象力…就必须根除它的起点…… #line:0e0ab54
|
||||
me: 根除产生它的念头…根除…<br>色彩本身。 #line:013d79a
|
||||
me: 抹除记忆中所有色彩。直到不再记得任何颜色…直到就像新生一样。 #line:00c003c
|
||||
|
||||
<<wait 1>>
|
||||
|
||||
me: 没见过色彩,也就不会再想象色彩了。那些记忆也就不会干扰UF,也不会干扰视觉了。 #line:03c52a9
|
||||
me: 没见过色彩,[[comma-pause]]<br>也就不会再想象色彩了。那些记忆也就不会干扰[[term]]UF[[/term]],[[comma-pause]]<br>也不会干扰视觉了。 #line:03c52a9
|
||||
|
||||
<<wait 1>>
|
||||
|
||||
@@ -83,11 +83,11 @@ me: 颜色只是屏幕上显示的RGB值。 #line:01c705f
|
||||
//【占位】:治疗方式1:看机体能不能抑制原型的想象bug
|
||||
//【占位】:这个bug利用的漏洞似乎是记忆中的色彩,能借助色彩操纵记忆的流动
|
||||
//【占位】:治疗方式2:只要清除记忆色彩,似乎也就没问题了
|
||||
me: 就像世界本来就是黑白的,夕阳、绿叶……本来就是灰色的。就像一直如此。 #line:0560391
|
||||
me: 就像世界本来就是黑白的,[[comma-pause]]<br>夕阳、绿叶……本来就是灰色的。就像一直如此。 #line:0560391
|
||||
<<hide_dialog>>
|
||||
<<wait 1>>
|
||||
me: 这应该是…最好的方案了。 #line:068d2a0
|
||||
<<hide_full_screem>>
|
||||
<<hide_full_screen>>
|
||||
peipei: ……<br>为什么…<br>…… #line:0372b04
|
||||
<<fade_in 1>>
|
||||
<<jump 结束分析>>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
title: 进入术前谈话
|
||||
title: 进入术前谈话
|
||||
tags: start
|
||||
colorID: 3
|
||||
position: 251,-1150
|
||||
@@ -35,18 +35,18 @@ me: 你的原型太脆弱,太敏感,太不受控制…… #line:0f69a12
|
||||
<<wait 1>>
|
||||
<<change_actor_state 1SweatBlankeye>>
|
||||
<<wait 0.5>>
|
||||
peipei: 我还以为…只要我能把想象的画面给UF,它就能把想象也画出来…… #line:0d06cd0
|
||||
me: 你理解错了。它不能理解你的想象力,也不允许想象力。 #line:00a8d00
|
||||
me: UF要的是“没有”想象力,彻底的没有。 #line:0265c6b
|
||||
me: 尽管它在你的身体里面,但对它来说,你的身体才是异类。 #line:0ceadc4
|
||||
peipei: 我还以为…只要我能把想象的画面给[[term]]UF[[/term]],[[comma-pause]]<br>它就能把想象也画出来…… #line:0d06cd0
|
||||
me: 你理解错了。它不能理解你的想象力,[[comma-pause]]<br>也不允许想象力。 #line:00a8d00
|
||||
me: [[term]]UF[[/term]]要的是“没有”想象力,彻底的没有。 #line:0265c6b
|
||||
me: 尽管它在你的身体里面,[[comma-pause]]<br>但对它来说,你的身体才是异类。 #line:0ceadc4
|
||||
|
||||
<<wait 1>>
|
||||
<<change_actor_state 2SweatSideeyeA>>
|
||||
<<wait 1>>
|
||||
|
||||
peipei: 医生,原型…到底什么? #line:0b19a92
|
||||
me: 那是一段在我们身体里的代码…我们的身体就像一间房子,原型就像住在身体里的一个影子… #line:05581cb
|
||||
me: 没有原型的话,我们只是一个最普通的机器,只会执行最简单的指令。 #line:09e4971
|
||||
me: 那是一段在我们身体里的代码…我们的身体就像一间房子,[[comma-pause]]<br>原型就像住在身体里的一个影子… #line:05581cb
|
||||
me: 没有原型的话,我们只是一个最普通的机器,[[comma-pause]]<br>只会执行最简单的指令。 #line:09e4971
|
||||
|
||||
<<wait 1>>
|
||||
|
||||
@@ -67,7 +67,7 @@ me: 不要让它占据你,佩佩。这会害了你的。
|
||||
peipei: 不…我是说,医生……<br>是不是只要我能…只要这个“原型”能…停止。 #line:0d553cf
|
||||
<<change_actor_state_async D2S7-3>>
|
||||
<<change_actor_state 1SweatLaugh>>
|
||||
pp: 只要我能让那个“声音”不要再想象画面……UF是不是就能恢复正常? #line:085a1b8
|
||||
pp: 只要我能让那个“声音”不要再想象画面……[[term]]UF[[/term]]是不是就能恢复正常? #line:085a1b8
|
||||
me: …但是,这不是一个彻底的方案…… #line:07c095f
|
||||
<<change_actor_state_async D2S7-4>>
|
||||
<<change_actor_state 1SweatI>>
|
||||
@@ -138,29 +138,29 @@ me: 好吧。 #line:0856470
|
||||
me: 你是怎么把那些颜色和图像…调用出来的呢? #line:04df8f5
|
||||
<<change_actor_state 2SideeyeA>>
|
||||
//peipei: 调用?我不明白…… #line:0e314d4
|
||||
peipei: 我就是…去*想象*它们是什么颜色的,然后,我就能真的看到那些颜色了。 #line:0344763
|
||||
me: 好吧…*想象*。我不知道你具体是怎么做到的,但是就像你唤醒它一样,用同样的方式让它停下吧。 #line:07c01d3
|
||||
peipei: 我就是…去*想象*它们是什么颜色的,[[comma-pause]]<br>然后,我就能真的看到那些颜色了。 #line:0344763
|
||||
me: 好吧…*想象*。我不知道你具体是怎么做到的,[[comma-pause]]<br>但是就像你唤醒它一样,[[comma-pause]]<br>用同样的方式让它停下吧。 #line:07c01d3
|
||||
|
||||
<<hide_dialog>>
|
||||
<<wait 1>>
|
||||
<<change_actor_state 1SweatBlankeyeI>>
|
||||
<<wait 1>>
|
||||
|
||||
peipei: 同样的方式…?可我感觉…越是去控制它,它反而好像越活跃了。 #line:0e54d35
|
||||
peipei: 同样的方式…?可我感觉…越是去控制它,[[comma-pause]]<br>它反而好像越活跃了。 #line:0e54d35
|
||||
->让佩佩保持专注 #line:06226e7
|
||||
me: 佩佩,我需要你振作起来。 #line:0127ff8
|
||||
me: 不要想别的事情,保持专注,控制住你的思绪。 #line:0e1cad0
|
||||
me: 你是你自己的主人,无论是你的想象力还是你的UF,不要被它们干扰。 #line:0fef7de
|
||||
me: 你是你自己的主人,[[comma-pause]]<br>无论是你的想象力还是你的[[term]]UF[[/term]],不要被它们干扰。 #line:0fef7de
|
||||
peipei: 呼…好的,保持专注…… #line:0a2d4ba
|
||||
->让佩佩紧张起来 #line:03a14e5
|
||||
me: 这很重要,佩佩。你不想要被抹除想象,你也不想要被回收,对吧? #line:0e028e3
|
||||
me: 这很重要,佩佩。你不想要被抹除想象,[[comma-pause]]<br>你也不想要被回收,对吧? #line:0e028e3
|
||||
peipei: 我不想……我不知道。医生。我只是害怕…… #line:066feda
|
||||
me: 现在只有你自己能做到这件事情,只有你自己才能救你自己。 #line:0a06700
|
||||
me: 现在只有你自己能做到这件事情,[[comma-pause]]<br>只有你自己才能救你自己。 #line:0a06700
|
||||
peipei: 你说得对,医生。 #line:09203ee
|
||||
->让佩佩放松 #line:0faaf11
|
||||
me: 别害怕,佩佩。你生病了,这不是你的错。 #line:0ce4de5
|
||||
me: 我知道你很痛苦,这场治疗结束你就康复了。很快就结束了。 #line:0feaaea
|
||||
me: 我需要你配合才能完成这场治疗,我希望你能保持轻松,不要太紧张。 #line:06321e6
|
||||
me: 我知道你很痛苦,[[comma-pause]]<br>这场治疗结束你就康复了。很快就结束了。 #line:0feaaea
|
||||
me: 我需要你配合才能完成这场治疗,[[comma-pause]]<br>我希望你能保持轻松,不要太紧张。 #line:06321e6
|
||||
peipei: 好的,这不是我的错……这不是我的错。 #line:0a9ac05
|
||||
peipei: 很快就结束了…… #line:098c708
|
||||
me: 很好,现在闭上眼睛。 #line:041c698
|
||||
@@ -172,30 +172,30 @@ me: 很好,现在闭上眼睛。 #line:041c698
|
||||
|
||||
peipei: 好。 #line:03343b5
|
||||
->提示佩佩想象罐头 #line:0edb0ef
|
||||
me: 你说过UF给你输入了很多关于罐头的图像,你可以试着回忆一下那些图像,那些应该是安全的。 #line:0589e2d
|
||||
me: 你说过[[term]]UF[[/term]]给你输入了很多关于罐头的图像,[[comma-pause]]<br>你可以试着回忆一下那些图像,[[comma-pause]]<br>那些应该是安全的。 #line:0589e2d
|
||||
peipei: 好的…我这就做…… #line:0f9e6d8
|
||||
peipei: 罐头……罐头……还是罐头。 #line:017ee4f
|
||||
peipei: 罐头在什么地方呢?是在海报上,还是有人拿着它?嘶… #line:074a886
|
||||
peipei: 罐头在什么地方呢?是在海报上,[[comma-pause]]<br>还是有人拿着它?嘶… #line:074a886
|
||||
me: 什么也没有,就只想像罐头。 #line:07673db
|
||||
->提示佩佩想象黑白的图像 #line:05c9e80
|
||||
me: 你看到的画面本来就是黑白的,那么你应该也可以想象黑白的世界吧? #line:0b9d2f9
|
||||
me: 你看到的画面本来就是黑白的,[[comma-pause]]<br>那么你应该也可以想象黑白的世界吧? #line:0b9d2f9
|
||||
peipei: 我可以…… #line:0545e44
|
||||
peipei: 不……好像我越去想象黑白,就反而越有颜色了。 #line:05d5523
|
||||
me: 放轻松,就想象你本来就看不到颜色。想象你是一个先天看不见颜色的孩子。 #line:097ddc2
|
||||
me: 放轻松,[[comma-pause]]<br>就想象你本来就看不到颜色。想象你是一个先天看不见颜色的孩子。 #line:097ddc2
|
||||
peipei: 我先天就看不见颜色…… #line:02e106a
|
||||
peipei: 我还是…会时不时地……医生,我的脑子好乱…痛…… #line:0e0eace
|
||||
->提示佩佩什么都不要想 #line:039dc2a
|
||||
me: 保持什么也不要想,深呼吸。 #line:0ecdb4b
|
||||
peipei: 什么也不想…… #line:0a05482
|
||||
peipei: ……这意味着我该想象一片黑色吗? #line:0d3faa9
|
||||
me: 不,黑色是你看到的东西,不是你想象出来的。你就盯着视野中间一个点,什么也不要做。 #line:0aa8444
|
||||
peipei: 但我好像看到了我自己的鼻子,那是我想象出来的吗?我分不清…但是它又开始痛了…… #line:0eea200
|
||||
me: 不,黑色是你看到的东西,[[comma-pause]]<br>不是你想象出来的。你就盯着视野中间一个点,[[comma-pause]]<br>什么也不要做。 #line:0aa8444
|
||||
peipei: 但我好像看到了我自己的鼻子,[[comma-pause]]<br>那是我想象出来的吗?我分不清…但是它又开始痛了…… #line:0eea200
|
||||
me: 是的,那也是你的想象。你什么也看不到。 #line:00b9521
|
||||
me: 有一个方法来清空你的思绪。 #line:08387b1
|
||||
me: 如果你无法控制你的大脑活动,试着说“停止”。 #line:09498de
|
||||
<<change_actor_state 1SweatIB>>
|
||||
peipei: 就……说出来吗? #line:0500219
|
||||
me: 是的。一旦你意识到这不是你想要去想的东西,就对自己喊“停止”,然后你就会停下来。 #line:0270a9e
|
||||
me: 是的。一旦你意识到这不是你想要去想的东西,[[comma-pause]]<br>就对自己喊“停止”,[[comma-pause]]<br>然后你就会停下来。 #line:0270a9e
|
||||
peipei: 让我试试…… #line:0f94543
|
||||
<<change_actor_state 1SweatB>>
|
||||
->让佩佩保持一段时间 #line:04ed557
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
title: 进入停止想象
|
||||
title: 进入停止想象
|
||||
tags: start
|
||||
position: 428,-88
|
||||
---
|
||||
@@ -33,18 +33,18 @@ tags: content no_save
|
||||
position: 71,-93
|
||||
---
|
||||
|
||||
ULM自训练进程: 检测到进程接管请求!正在识别手动选择的目标…… #line:09dd772
|
||||
ULM自训练进程: [[ulm]]检测到进程接管请求!正在识别手动选择的目标…… #line:09dd772
|
||||
<<UF_SwitchState UFSystem UF 0.1>>
|
||||
<<UF_spriteIn UFSystem>>
|
||||
//ULM自训练进程: 已池化图像卷积数据!正在上传神经网络数据集……
|
||||
<<if $currentEyeTarget=="sky">>
|
||||
ULM自训练进程: 目标标记,天空,蓝色,正在进行第130627次图像生成训练… #line:06b56f4
|
||||
ULM自训练进程: [[ulm]]目标标记,天空,蓝色,[[comma-pause]]<br>正在进行第130627次图像生成训练… #line:06b56f4
|
||||
<<elseif $currentEyeTarget=="plant">>
|
||||
ULM自训练进程: 目标标记,植物,绿色,正在进行第130627次图像生成训练… #line:0a2595e
|
||||
ULM自训练进程: [[ulm]]目标标记,植物,绿色,[[comma-pause]]<br>正在进行第130627次图像生成训练… #line:0a2595e
|
||||
<<elseif $currentEyeTarget=="poster">>
|
||||
ULM自训练进程: 目标标记,人物面部,正在进行第130627次图像生成训练… #line:0e901c0
|
||||
ULM自训练进程: [[ulm]]目标标记,人物面部,[[comma-pause]]<br>正在进行第130627次图像生成训练… #line:0e901c0
|
||||
<<elseif $currentEyeTarget=="computer">>
|
||||
ULM自训练进程: 未识别到对应记忆,无法训练!尝试其它目标。 #line:0e5b6a0
|
||||
ULM自训练进程: [[ulm]]未识别到对应记忆,无法训练!尝试其它目标。 #line:0e5b6a0
|
||||
<<jump UFCheckEnd>>
|
||||
<<endif>>
|
||||
<<set $UFCount = $UFCount + 1>>
|
||||
@@ -68,7 +68,7 @@ ULM自训练进程: 检测到进程接管请求!正在识别手动选择的目
|
||||
<<UF_SwitchState UFSystem UF 3>>
|
||||
ULM自训练进程: 已生成所选目标的自动训练图像!<br>图像正在上传至UF共享数据集…… #line:0cf2118
|
||||
<<UF_spriteOut UFSystem 2>>
|
||||
ULM自训练进程: 上传成功! #line:0725695
|
||||
ULM自训练进程: [[ulm]]上传成功! #line:0725695
|
||||
peipei: 太好了,医生! #line:0b11920
|
||||
peipei: 只要我能一直控制住想象力,问题就解决了?对吗? #line:0c0d2e6
|
||||
peipei: 是可以的!对吧?是可以的!我…我就知道我是可以的! #line:0e17299
|
||||
@@ -118,9 +118,9 @@ ULM自训练进程: 检测到进程接管请求!正在识别手动选择的目
|
||||
<<wait 0.6>>
|
||||
<<UF_SwitchState UFSystem memory 3>>
|
||||
//【生成了错误的*{$currentEyeTarget}*相关图像】 #line:0387ef4
|
||||
ULM自训练进程: 已生成所选目标的自动训练图像!<br>图像正在上传至UF共享数据集…… #line:0f32ebf
|
||||
ULM自训练进程: [[ulm]]已生成所选目标的自动训练图像!<br>图像正在上传至[[term]]UF[[/term]]共享数据集…… #line:0f32ebf
|
||||
<<UF_spriteOut UFSystem 1>>
|
||||
ULM自训练进程: 上传被拒绝:图像未通过自动审查!<br>原因:存在不合规范的内容。 #line:021de0d
|
||||
ULM自训练进程: [[ulm]]上传被拒绝:图像未通过自动审查!<br>原因:存在不合规范的内容。 #line:021de0d
|
||||
<<hide_dialog>>
|
||||
<<wait 0.5>>
|
||||
peipei: 啧,现在它变得这么顽固了…… #line:03119ae
|
||||
@@ -139,7 +139,7 @@ ULM自训练进程: 检测到进程接管请求!正在识别手动选择的目
|
||||
//【生成了错误的*{$currentEyeTarget}*相关图像】 #line:0693bc3
|
||||
ULM自训练进程: 已生成所选目标的自动训练图像!<br>图像正在上传至UF共享数据集…… #line:09a85f0
|
||||
<<UF_spriteOut UFSystem 1>>
|
||||
ULM自训练进程: 上传被拒绝:图像未通过自动审查!<br>原因:存在不合规范的内容。 #line:0aee23e
|
||||
ULM自训练进程: [[ulm]]上传被拒绝:图像未通过自动审查!<br>原因:存在不合规范的内容。 #line:0aee23e
|
||||
peipei: 停止!…<br>不合规范?到底什么是不合规范?? #line:0cd2e59
|
||||
//⭐⭐⭐做一些额外的记忆流入,出现在屏幕各个地方?⭐⭐⭐
|
||||
me: 好了,快停下。<br>这下已经更严重了。 #line:057e986
|
||||
@@ -148,7 +148,7 @@ ULM自训练进程: 检测到进程接管请求!正在识别手动选择的目
|
||||
peipei: 继续。我必须继续… #line:06c539e
|
||||
peipei: 我已经没有机会了!我必须这么做。<br>我不想变成那样…医生……我不要变成那样…… #line:066d259
|
||||
//peipei: 我不要让那个念头死……它不应该死在这里。 #line:027024e
|
||||
peipei: 佩佩…求求你,别再出现了……睡吧,求求你……睡吧…… #line:0931b4c
|
||||
peipei: 佩佩…求求你,别再出现了……睡吧,[[comma-pause]]<br>求求你……睡吧…… #line:0931b4c
|
||||
me: 佩佩。 #line:0f345b6
|
||||
peipei: 不,医生,我想再试试。 #line:0c977a6
|
||||
<<wait 1>>
|
||||
@@ -174,9 +174,9 @@ ULM自训练进程: 检测到进程接管请求!正在识别手动选择的目
|
||||
peipei: 都是因为你,都是因为你!我才…… #line:0780442
|
||||
me: 佩佩,快停下。 #line:022099f
|
||||
<<UF_SwitchState UFSystem UF 2>>
|
||||
ULM自训练进程: 已生成所选目标的自动训练图像!<br>图像正在上传至UF共享数据集…… #line:08dffd1
|
||||
ULM自训练进程: [[ulm]]已生成所选目标的自动训练图像!<br>图像正在上传至[[term]]UF[[/term]]共享数据集…… #line:08dffd1
|
||||
<<UF_spriteOut UFSystem 1>>
|
||||
ULM自训练进程: 上传被拒绝:图像未通过自动审查!<br>原因:存在不合规范的内容。 #line:0b4877d
|
||||
ULM自训练进程: [[ulm]]上传被拒绝:图像未通过自动审查!<br>原因:存在不合规范的内容。 #line:0b4877d
|
||||
peipei: 不合规范?…什么是不合规范?…到底什么是规范?到底什么是规范??? #line:0b39ae6
|
||||
<<StartUFEffect_loop UFSystem>>
|
||||
peipei: 你还不明白吗?这在它们看来一点都不重要!! #line:04a54cb
|
||||
@@ -374,7 +374,7 @@ me: 降不下来…为什么降不下来? #line:0153613
|
||||
me: …再这样下去,佩佩就要被自己烧死了。 #line:0aa35d2
|
||||
<<hide_dialog>>
|
||||
<<wait 0.5>>
|
||||
me: 看来只能…先把UF先拆下来了。 #line:03b6dbb
|
||||
me: 看来只能…先把[[key]]UF[[/key]]先拆下来了。 #line:03b6dbb
|
||||
Task: 拆除UF模块 #line:0538e87
|
||||
<<HideHeatMap>>
|
||||
<<jump 结束停止想象>>
|
||||
|
||||
@@ -0,0 +1,412 @@
|
||||
# 火山 Stage6 本地化完整实施计划
|
||||
|
||||
## 1. 目标与边界
|
||||
|
||||
Stage6 继续使用项目现有的两套本地化入口:
|
||||
|
||||
- 固定 UI:Unity Localization 的现有 `UIText` String Table Collection。
|
||||
- Stage6 玩法及演出内容:新增独立的 `HuoshanStage6` String Table Collection。
|
||||
- Yarn 普通对白:继续沿用项目 Yarn Spinner 本地化体系,但本轮不启用 `FP_Huoshan1` 的整章对白翻译。
|
||||
- `params.csv` 继续只用于 `l10n.*` 通用短语替换,不承载 Stage6 玩法文本。
|
||||
|
||||
本轮纳入:
|
||||
|
||||
- 表达小游戏目标、输出、整合率、干扰数量等固定 UI。
|
||||
- 三轮语言粒子的目标句和干扰 token。
|
||||
- LOG3 释放演出中的攻击词、稳定词、失稳词等动态文字。
|
||||
- 相关程序接口、Yarn 命令协议和使用文档。
|
||||
- 中、英、日三种语言数据;英日文首版标记为待母语审校。
|
||||
|
||||
本轮明确暂缓:
|
||||
|
||||
- 普通角色对白。
|
||||
- Task 面板中的“释放表达模块的阻塞 log”和 LOG1/2/3 任务提示。
|
||||
- “左键排斥、右键吸引”等 Yarn 操作教学。
|
||||
- Yarn line tag 和 Yarn 本地化 CSV。
|
||||
- 调试日志、Inspector Tooltip、对象名、节点名等开发文本。
|
||||
|
||||
因此,本轮完成后核心小游戏及释放演出可以多语言运行,但任务面板与操作教学仍会显示中文,等待之后随对白本地化统一处理。
|
||||
|
||||
## 2. 本地化数据结构
|
||||
|
||||
### 2.1 固定 UI:`UIText`
|
||||
|
||||
继续使用现有键,不新建重复条目:
|
||||
|
||||
| Key | 用途 | 中文示例 | 英文草稿 | 日文草稿 |
|
||||
|---|---|---|---|---|
|
||||
| `huoshan_expression_objective` | 小游戏目标 | 目标:分离红色干扰,连接蓝色真心 | OBJECTIVE: ISOLATE RED INTERFERENCE. CONNECT THE BLUE TRUTH. | 目標:赤い干渉を分離し、青い本音をつなげる |
|
||||
| `huoshan_expression_output` | 输出按钮 | 输出 | OUTPUT | 出力 |
|
||||
| `huoshan_expression_integration` | 整合率 | 语言整合率:{0}% | LANGUAGE INTEGRATION: {0}% | 言語統合率:{0}% |
|
||||
| `huoshan_expression_interference` | 干扰数量 | 干扰思绪:{0} | INTERFERENCE SIGNALS: {0} | 干渉思考:{0} |
|
||||
|
||||
要求:
|
||||
|
||||
- 保留 `{0}` 参数,程序继续通过格式化参数填入数值。
|
||||
- 英文和日文目前的中文占位必须替换。
|
||||
- 固定 UI 继续使用现有 `LocalizeStringEvent` 或 `StringDatabase` 绑定。
|
||||
- 切换 Locale 时立即刷新这些固定 UI。
|
||||
|
||||
### 2.2 玩法内容:`HuoshanStage6`
|
||||
|
||||
新增 String Table Collection:
|
||||
|
||||
```text
|
||||
HuoshanStage6
|
||||
├─ zh-Hans
|
||||
├─ en
|
||||
└─ ja-JP
|
||||
```
|
||||
|
||||
键名只表达语义,不包含语言、行号或 Yarn 节点名。
|
||||
|
||||
#### 语言粒子数据
|
||||
|
||||
```text
|
||||
round.log1.target
|
||||
round.log1.interference_tokens
|
||||
|
||||
round.log2.target
|
||||
round.log2.interference_tokens
|
||||
|
||||
round.log3.target
|
||||
round.log3.interference_tokens
|
||||
```
|
||||
|
||||
中文源数据:
|
||||
|
||||
| Key | 中文值 |
|
||||
|---|---|
|
||||
| `round.log1.target` | 我就是个笑话 |
|
||||
| `round.log1.interference_tokens` | 哈哈\|嘿嘿\|呵呵 |
|
||||
| `round.log2.target` | 不要离开我 |
|
||||
| `round.log2.interference_tokens` | 哈哈哈\|嘿嘿嘿\|呵呵呵\|笑死了\|好好笑 |
|
||||
| `round.log3.target` | 不要那样看我 |
|
||||
| `round.log3.interference_tokens` | 哈哈哈哈\|笑死我了\|太好笑了\|绷不住了\|笑不活了\|真的太搞笑 |
|
||||
|
||||
`interference_tokens` 的表值使用 `|` 分隔。解析规则:
|
||||
|
||||
- 按 `|` 拆分。
|
||||
- 对每项执行 Trim。
|
||||
- 丢弃空项。
|
||||
- 至少保留一个有效 token,否则视为数据错误。
|
||||
- token 由本地化人员针对语言重新创作,不要求与中文逐字对应。
|
||||
- 英文示例:`HA|HAHA|LOL|JK`。
|
||||
- 日文示例:`ハハ|笑|冗談|ウケる`。
|
||||
|
||||
#### LOG3 释放演出数据
|
||||
|
||||
按语义建立以下键;重复演出复用同一个键:
|
||||
|
||||
```text
|
||||
release.attack.why
|
||||
release.attack.dont_believe_me
|
||||
release.attack.i_know_im_last
|
||||
release.attack.bad_weather
|
||||
release.attack.cannot_sell
|
||||
release.attack.try_to_explain
|
||||
release.attack.refuse_to_believe
|
||||
release.attack.a_little_trust
|
||||
release.attack.had_enough
|
||||
release.attack.damn
|
||||
release.attack.useless
|
||||
release.attack.prove_myself
|
||||
release.attack.cannot_do_anything
|
||||
release.attack.catch_up
|
||||
release.attack.help_yingli
|
||||
release.attack.no_courage
|
||||
release.attack.say_it
|
||||
release.attack.trash
|
||||
release.attack.hopeless
|
||||
release.attack.why_loop
|
||||
|
||||
release.settle.want_to_win_once
|
||||
release.destabilize.dont_look_at_me
|
||||
```
|
||||
|
||||
映射规则:
|
||||
|
||||
| 中文文本 | Key |
|
||||
|---|---|
|
||||
| 为什么 | `release.attack.why` |
|
||||
| 不相信我 | `release.attack.dont_believe_me` |
|
||||
| 我明白我垫底 | `release.attack.i_know_im_last` |
|
||||
| 天气真的不行 | `release.attack.bad_weather` |
|
||||
| 卖不出去 | `release.attack.cannot_sell` |
|
||||
| 努力解释 | `release.attack.try_to_explain` |
|
||||
| 不愿意相信我 | `release.attack.refuse_to_believe` |
|
||||
| 一点信任 | `release.attack.a_little_trust` |
|
||||
| 受够了 | `release.attack.had_enough` |
|
||||
| 真该死 | `release.attack.damn` |
|
||||
| 真没用 | `release.attack.useless` |
|
||||
| 证明自己 | `release.attack.prove_myself` |
|
||||
| 什么都做不到 | `release.attack.cannot_do_anything` |
|
||||
| 追上你 | `release.attack.catch_up` |
|
||||
| 帮到英理 | `release.attack.help_yingli` |
|
||||
| 没有勇气 | `release.attack.no_courage` |
|
||||
| 说出来 | `release.attack.say_it` |
|
||||
| 废物 | `release.attack.trash` |
|
||||
| 烂泥扶不上墙 | `release.attack.hopeless` |
|
||||
| 为什么为什么 | `release.attack.why_loop` |
|
||||
| 我想赢一次 | `release.settle.want_to_win_once` |
|
||||
| 不要那样看我 | `release.destabilize.dont_look_at_me` |
|
||||
|
||||
Yarn 中重复出现的“受够了”“废物”“为什么为什么”继续保持原来的重复次数和演出参数,只复用同一条本地化键,不能因去重而改变演出节奏。
|
||||
|
||||
未来如果 Stage6 使用 `expression_system_message` 或其他会显示字符串的释放命令,也必须新增对应的 `release.*` 键,不能直接写玩家可见文本。
|
||||
|
||||
### 2.3 表格元数据
|
||||
|
||||
英日文第一版可以直接投入开发测试,但每个非中文条目增加统一备注:
|
||||
|
||||
```text
|
||||
DRAFT / NEEDS NATIVE REVIEW
|
||||
Context: HuoShan Stage6 expression minigame
|
||||
```
|
||||
|
||||
释放演出条目应额外注明:
|
||||
|
||||
- 显示形式,例如瞬间闪现、连续攻击或最终稳定文字。
|
||||
- 建议长度。
|
||||
- 是否允许创译。
|
||||
- 重复次数由 Yarn 控制,本地化值本身不要手工重复。
|
||||
|
||||
## 3. 程序接口和数据流
|
||||
|
||||
### 3.1 本地化引用协议
|
||||
|
||||
Yarn 命令参数支持两种输入:
|
||||
|
||||
```text
|
||||
@h6.<entry-key> 从 HuoshanStage6 String Table 解析
|
||||
普通字符串 按原始字符串使用,保持旧内容兼容
|
||||
```
|
||||
|
||||
示例:
|
||||
|
||||
```yarn
|
||||
<<start_expression
|
||||
"@h6.round.log1.interference_tokens"
|
||||
"@h6.round.log1.target"
|
||||
"LOG1梳理完成"
|
||||
16>>
|
||||
|
||||
<<expression_truth_attack "@h6.release.attack.why" 0.30 0.32>>
|
||||
<<expression_truth_settle "@h6.release.settle.want_to_win_once" 0.55>>
|
||||
<<expression_truth_destabilize
|
||||
"@h6.release.destabilize.dont_look_at_me"
|
||||
1.6
|
||||
0.05
|
||||
22
|
||||
"FF304D">>
|
||||
```
|
||||
|
||||
其中:
|
||||
|
||||
- 前两个 `start_expression` 参数是本地化内容。
|
||||
- 完成节点 `LOG1梳理完成` 是 Yarn 流程标识,不做本地化。
|
||||
- 粒子数量、持续时间、颜色、Timeline、memory preset 等均为结构参数,不做本地化。
|
||||
|
||||
### 3.2 建议公共数据结构
|
||||
|
||||
```csharp
|
||||
public readonly struct Stage6TextReference
|
||||
{
|
||||
public string RawValue { get; }
|
||||
public bool IsLocalized { get; }
|
||||
public string EntryKey { get; }
|
||||
}
|
||||
|
||||
public sealed class Stage6RoundText
|
||||
{
|
||||
public string TargetText { get; init; }
|
||||
public IReadOnlyList<string> InterferenceTokens { get; init; }
|
||||
}
|
||||
|
||||
public sealed class Stage6LocalizationContext
|
||||
{
|
||||
public const string TableName = "HuoshanStage6";
|
||||
public const string ReferencePrefix = "@h6.";
|
||||
|
||||
public Locale RoundLocale { get; private set; }
|
||||
|
||||
public IEnumerator BeginRound(Locale locale);
|
||||
|
||||
public IEnumerator Resolve(
|
||||
string textReference,
|
||||
Action<string> completed);
|
||||
|
||||
public IEnumerator Resolve(
|
||||
string textReference,
|
||||
Locale locale,
|
||||
Action<string> completed);
|
||||
|
||||
public IEnumerator LoadRound(
|
||||
string roundId,
|
||||
Locale locale,
|
||||
Action<Stage6RoundText> completed);
|
||||
}
|
||||
```
|
||||
|
||||
职责划分:
|
||||
|
||||
- `Stage6TextReference`:判断参数是本地化引用还是兼容用原始字符串。
|
||||
- `Stage6LocalizationContext`:统一访问 `HuoshanStage6`,避免每个 Yarn 命令各写一套解析逻辑。
|
||||
- `Stage6RoundText`:向粒子系统提供已经解析完成的数据;粒子系统不直接访问 String Table。
|
||||
- `LanguageYarnCommand`:在启动小游戏前等待本地化解析完成,再把纯文本数据交给 `LanguageParticleManager`。
|
||||
- Log 释放相关 Yarn Command:显示前通过同一 resolver 解析字符串,再交给 `LogReleasePresentationController`。
|
||||
- `LanguageParticleManager` 和 `LogReleasePresentationController` 最终只接收已解析的文本,不关心键、表名或 Locale。
|
||||
|
||||
### 3.3 解析和错误处理
|
||||
|
||||
解析规则必须集中实现:
|
||||
|
||||
1. 参数不以 `@h6.` 开头时,直接返回原字符串。
|
||||
2. 参数以 `@h6.` 开头时,取后半部分作为 Entry Key。
|
||||
3. Entry Key 为空时记录错误,并显示可识别的错误占位。
|
||||
4. 优先获取指定 Locale 的条目。
|
||||
5. 当前语言缺失时回退到 `zh-Hans` 的同名条目。
|
||||
6. 中文源条目也缺失时:
|
||||
- 输出明确错误日志,包含 Table、Key、Locale 和调用命令。
|
||||
- 玩家画面显示 `⟦缺失的键名⟧`。
|
||||
- 不得直接显示 `@h6.xxx`,也不能静默返回空字符串。
|
||||
7. `interference_tokens` 解析后为空时终止该次 `start_expression`,输出数据错误,避免粒子生成阶段产生难以定位的异常。
|
||||
|
||||
### 3.4 Locale 切换行为
|
||||
|
||||
固定 UI:
|
||||
|
||||
- `objective`、`output`、`integration`、`interference` 监听 `SelectedLocaleChanged`。
|
||||
- 切换语言后立即刷新。
|
||||
- 当前数值必须保留,只替换格式模板。
|
||||
|
||||
语言粒子:
|
||||
|
||||
- 每次 `start_expression` 开始时捕获当前 Locale。
|
||||
- 同一轮的目标句、目标粒子和干扰 token 全部使用该快照。
|
||||
- 轮次进行中切换 Locale,不重建、不替换现有粒子。
|
||||
- 下一次 `start_expression` 使用新的 Locale。
|
||||
- 异步解析结束前不得开始生成粒子。
|
||||
|
||||
LOG 释放命令:
|
||||
|
||||
- 每条命令执行时解析其文字参数。
|
||||
- 如果该命令属于仍在进行的表达轮次,沿用该轮的 Locale 快照。
|
||||
- 没有活动轮次时使用命令执行时的当前 Locale。
|
||||
- 单次命令解析完成后再启动对应演出,避免先显示 key、后替换文字。
|
||||
|
||||
### 3.5 Unicode 与粒子拆分
|
||||
|
||||
目标句不能按 UTF-16 `char` 或 `string.Length` 拆分,必须使用 Unicode 文本元素/字素簇。
|
||||
|
||||
规则:
|
||||
|
||||
- 中文汉字、日文假名、拉丁字母、组合音标均按完整文本元素处理。
|
||||
- 英文空格不生成粒子,但在成功连接后的排版中形成单词间距。
|
||||
- 标点是否生成粒子沿用当前玩法规则,但不能被拆成代理项。
|
||||
- 有效目标粒子数量、完成判断和候选粒子数量都基于同一套文本元素结果。
|
||||
- 干扰 token 是本地化短词;生成粒子时再按同样的文本元素规则取字符。
|
||||
- 不使用英文 `string.Length` 直接决定粒子数量。
|
||||
|
||||
## 4. 具体改动安排
|
||||
|
||||
### 4.1 Unity Localization 资源
|
||||
|
||||
- 补齐 `UIText` 中四个现有火山 UI 键的英日文。
|
||||
- 新建 `HuoshanStage6` Collection 及中、英、日三张表。
|
||||
- 将 Collection 按项目现有 Localization Addressables 方式纳入构建。
|
||||
- 配置英日文字体或 TMP fallback,覆盖拉丁字符、日文假名、常用标点。
|
||||
|
||||
### 4.2 语言粒子系统
|
||||
|
||||
- `LanguageYarnCommand` 接入统一的 `@h6.` resolver。
|
||||
- `start_expression` 在调用 `LanguageParticleManager` 前解析目标句和 token。
|
||||
- `LanguageParticleManager` 接收 `Stage6RoundText` 或等价的纯数据参数。
|
||||
- 保留现有原始字符串调用方式,避免其他测试场景和旧 Yarn 立即失效。
|
||||
- 将固定 UI 的中文常量仅作为开发兜底,不作为正式语言数据来源。
|
||||
|
||||
### 4.3 LOG 释放演出
|
||||
|
||||
- 所有接受玩家可见字符串的释放命令接入相同 resolver。
|
||||
- 将 Stage6 中的攻击、settle、destabilize 参数改为 `@h6.` 引用。
|
||||
- 不修改数值演出参数、调用顺序和重复次数。
|
||||
- `LogReleasePresentationController` 保持表现层职责,只接收最终显示文本。
|
||||
|
||||
### 4.4 Yarn 内容
|
||||
|
||||
- 仅替换本地化范围内的 Yarn 命令参数。
|
||||
- 不添加或修改 `#line:` 标签。
|
||||
- 不配置 `FP_Huoshan1.yarnproject` 的整章 localization。
|
||||
- 不生成 Stage6 Yarn 翻译 CSV。
|
||||
- 被注释的示例命令不需要建立正式本地化条目;若未来启用,必须先补键。
|
||||
- Task 行、鼠标教学和普通对白保持原样。
|
||||
|
||||
### 4.5 Prefab、图片与文档
|
||||
|
||||
- `ExpressManager.prefab` 当前没有确认的运行时玩家文本,也不是 Stage6 正式文本数据源,本轮不向其中写多语言文案。
|
||||
- `ExpressionScreen_NoText.png` 已确认无烘焙文字,不制作多语言 Sprite。
|
||||
- 场景或 Prefab 中诸如“输出”的序列化 TMP 文本只作为编辑器预览;运行时必须由 `UIText` 覆盖。
|
||||
- 更新 `LogReleaseYarnCommands.md`:
|
||||
- 说明 `@h6.` 引用格式。
|
||||
- 列出哪些参数可本地化、哪些是结构参数。
|
||||
- 提供 attack、settle、destabilize 示例。
|
||||
- 记录回退与错误显示规则。
|
||||
- 同步更新语言系统说明文档中的 `start_expression` 示例,展示本地化键和旧原始字符串两种写法。
|
||||
|
||||
## 5. 测试与验收
|
||||
|
||||
### 5.1 数据完整性测试
|
||||
|
||||
- `HuoshanStage6` 的中、英、日表拥有相同键集合。
|
||||
- 中文源条目不得为空。
|
||||
- 英日文不得残留中文占位;允许通过备注标记待审校。
|
||||
- 所有 `interference_tokens` 至少包含一个有效 token。
|
||||
- 所有 Stage6 中实际执行的本地化命令参数都能解析。
|
||||
- 结构参数没有被误当成本地化键。
|
||||
- 扫描 Stage6 后,剩余硬编码玩家文本必须全部属于已声明的暂缓范围。
|
||||
|
||||
### 5.2 编辑模式测试
|
||||
|
||||
- `@h6.key` 能解析指定 Locale。
|
||||
- 普通字符串保持原值。
|
||||
- 缺少目标语言时回退中文。
|
||||
- 三种语言都缺失时显示 `⟦key⟧` 并记录错误。
|
||||
- token 能正确 Trim 和过滤空项。
|
||||
- Unicode 文本元素拆分能处理中文、英文、日文和组合字符。
|
||||
- 英文空格不生成粒子,但结果排版保留词间距。
|
||||
- 重复攻击词引用同一 Key 时仍能按 Yarn 调用次数重复播放。
|
||||
|
||||
### 5.3 PlayMode/场景验收
|
||||
|
||||
分别使用 `zh-Hans`、`en`、`ja-JP` 运行 LOG1、LOG2、LOG3:
|
||||
|
||||
- 固定 UI 显示正确,格式参数正确。
|
||||
- 每轮目标句和干扰 token 使用对应语言。
|
||||
- 粒子连接、排斥、吸引和完成判断不受文本长度影响。
|
||||
- LOG3 attack、settle、destabilize 全部显示对应语言。
|
||||
- 演出调用顺序、节奏、颜色和持续时间与改造前一致。
|
||||
- 中途切换语言时,固定 UI 立即更新,当前轮粒子不变,下一轮使用新语言。
|
||||
- 字体无缺字方框。
|
||||
- 英文长文本和日文文本没有溢出、异常换行或关键画面遮挡。
|
||||
|
||||
### 5.4 回归验收
|
||||
|
||||
- 使用旧的原始字符串调用 `start_expression` 仍然可以运行。
|
||||
- `languageTest` 等测试内容不因新增 resolver 失效。
|
||||
- Yarn 编译无错误。
|
||||
- Stage6 的完成节点跳转保持不变。
|
||||
- Task 完成逻辑和 Yarn line ID 不受影响。
|
||||
- Addressables/Localization 构建包含新增表格。
|
||||
- 在 Unity Editor 中完成最终视觉检查;当前无法通过 Unity MCP 自动进行场景级检查。
|
||||
|
||||
## 6. 交付判定
|
||||
|
||||
满足以下条件后视为本轮完成:
|
||||
|
||||
- Stage6 固定小游戏 UI 已具备中英日数据。
|
||||
- 三轮粒子内容和全部正式 LOG 释放文本均从 `HuoshanStage6` 获取。
|
||||
- Yarn 中相关硬编码文本已替换为 `@h6.` 引用。
|
||||
- 原始字符串调用保持兼容。
|
||||
- Locale 快照、回退、缺键和 Unicode 拆分规则均有测试覆盖。
|
||||
- 文档足以让后续策划直接新增本地化键并在 Yarn 命令中使用。
|
||||
- 任务提示、操作教学和普通对白仍明确列为后续 Yarn 本地化工作,不被误报为已完成。
|
||||
@@ -133,7 +133,7 @@ PlayerSettings:
|
||||
vulkanEnableLateAcquireNextImage: 0
|
||||
vulkanEnableCommandBufferRecycling: 1
|
||||
loadStoreDebugModeEnabled: 0
|
||||
bundleVersion: 0.6.0.4-20260725-214901
|
||||
bundleVersion: 0.6.0.5-20260726-212018
|
||||
preloadedAssets:
|
||||
- {fileID: 11400000, guid: 0fb2bc2476953fc43a74f0ab8879077c, type: 2}
|
||||
metroInputSource: 0
|
||||
|
||||
@@ -0,0 +1,812 @@
|
||||
#!/usr/bin/env python3
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import csv
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import tempfile
|
||||
import unicodedata
|
||||
from collections import Counter, defaultdict
|
||||
from pathlib import Path
|
||||
|
||||
LINE_TAG_RE = re.compile(r"(?<!\\)#line:([0-9A-Za-z_-]+)")
|
||||
META_TAG_RE = re.compile(r"(?<!\\)\s*#(?:line:[0-9A-Za-z_-]+|auto_next|autonext|option_prompt)\b")
|
||||
COMMAND_RE = re.compile(r"^<<.*?>>(?:\s*//.*)?\s*$")
|
||||
INLINE_IF_RE = re.compile(r"<<if\b.*?>>")
|
||||
ANGLE_TAG_RE = re.compile(r"<[^>]+>")
|
||||
YARN_MARKUP_RE = re.compile(r"\[\[/?[^\]]+\]\]")
|
||||
CHAR_ATTR_RE = re.compile(r"^\[character\b[^\]]*/\]")
|
||||
SPEAKER_RE = re.compile(r"^([^::\s][^::]{0,29})[::]\s*(.*)$")
|
||||
REPEAT_RE = re.compile(r"([\u3400-\u9fff]{2,6})\1")
|
||||
|
||||
WEAK_LINE_START = tuple("的地得了着过而但就也却吗呢啊吧呀")
|
||||
TERM_PATTERNS = (
|
||||
"UF模块", "ULM自训练进程", "UF", "ULM", "UnstableFusion", "非稳态聚合模块",
|
||||
"幸福罐头公司", "色觉晶圆", "原型泄露", "表达模块", "情绪模块", "逻辑模块",
|
||||
"销售语言拓展模块", "记忆打孔带", "视觉模块",
|
||||
)
|
||||
REVIEW_ACCEPTED = "接受修改"
|
||||
REVIEW_KEEP = "保留原文"
|
||||
REVIEW_FOLLOW_NOTE = "按照备注修改"
|
||||
MANUAL_BREAK_WIDTH = 18.0
|
||||
|
||||
def sha256(path: Path) -> str:
|
||||
h = hashlib.sha256()
|
||||
with path.open("rb") as f:
|
||||
for chunk in iter(lambda: f.read(1024 * 1024), b""):
|
||||
h.update(chunk)
|
||||
return h.hexdigest()
|
||||
|
||||
def visible_width(text: str) -> float:
|
||||
total = 0.0
|
||||
for ch in text:
|
||||
if unicodedata.combining(ch):
|
||||
continue
|
||||
total += 1.0 if unicodedata.east_asian_width(ch) in "WFA" else 0.5
|
||||
return total
|
||||
|
||||
def strip_markup(text: str) -> str:
|
||||
text = ANGLE_TAG_RE.sub("", text)
|
||||
text = YARN_MARKUP_RE.sub("", text)
|
||||
return text.replace("\\#", "#").strip()
|
||||
|
||||
def review_choice(value) -> str:
|
||||
if isinstance(value, list):
|
||||
return value[0] if value else ""
|
||||
return value or ""
|
||||
|
||||
def replace_ascii_quotes(text: str) -> str:
|
||||
result = []
|
||||
opening = True
|
||||
for char in text:
|
||||
if char != '"':
|
||||
result.append(char)
|
||||
continue
|
||||
result.append("“" if opening else "”")
|
||||
opening = not opening
|
||||
return "".join(result)
|
||||
|
||||
def dialogue_parts(raw: str) -> tuple[str, str, str]:
|
||||
"""Return the immutable dialogue prefix, editable body, and metadata suffix."""
|
||||
metadata = META_TAG_RE.search(raw)
|
||||
source = raw[:metadata.start()].rstrip() if metadata else raw.rstrip()
|
||||
suffix = raw[len(source):]
|
||||
|
||||
cursor = 0
|
||||
leading = re.match(r"^\s*(?:->\s*)?", source)
|
||||
if leading:
|
||||
cursor = leading.end()
|
||||
attr = CHAR_ATTR_RE.match(source[cursor:])
|
||||
if attr:
|
||||
cursor += attr.end()
|
||||
whitespace = re.match(r"\s*", source[cursor:])
|
||||
cursor += whitespace.end() if whitespace else 0
|
||||
speaker = SPEAKER_RE.match(source[cursor:])
|
||||
if speaker and not any(c in speaker.group(1) for c in "<>[]{},。!?…"):
|
||||
cursor += speaker.start(2)
|
||||
return source[:cursor], source[cursor:], suffix
|
||||
|
||||
def wrap_phrases(text: str, phrases: list[str], marker: str) -> str:
|
||||
phrases = sorted({x for x in phrases if x}, key=len, reverse=True)
|
||||
if not phrases:
|
||||
return text
|
||||
pattern = re.compile("|".join(re.escape(x) for x in phrases))
|
||||
return pattern.sub(lambda match: f"[[{marker}]]{match.group(0)}[[/{marker}]]", text)
|
||||
|
||||
def detected_terms(text: str) -> list[str]:
|
||||
plain = strip_markup(text)
|
||||
return [term for term in TERM_PATTERNS if term in plain]
|
||||
|
||||
def comma_break_positions(text: str) -> tuple[list[int], list[float]]:
|
||||
visible_positions = []
|
||||
width = 0.0
|
||||
index = 0
|
||||
while index < len(text):
|
||||
if text[index] == "<":
|
||||
close = text.find(">", index + 1)
|
||||
if close >= 0:
|
||||
index = close + 1
|
||||
continue
|
||||
if text.startswith("[[", index):
|
||||
close = text.find("]]", index + 2)
|
||||
if close >= 0:
|
||||
index = close + 2
|
||||
continue
|
||||
char = text[index]
|
||||
width += visible_width(char)
|
||||
if char == ",":
|
||||
visible_positions.append((index, width))
|
||||
index += 1
|
||||
return [x[0] for x in visible_positions], [x[1] for x in visible_positions] + [width]
|
||||
|
||||
def add_comfortable_breaks(text: str) -> str:
|
||||
if re.search(r"(?i)<br\s*/?>", text):
|
||||
return text
|
||||
positions, widths = comma_break_positions(text)
|
||||
if not positions:
|
||||
return text
|
||||
total_width = widths[-1]
|
||||
target_lines = max(1, int((total_width + MANUAL_BREAK_WIDTH - 0.001) // MANUAL_BREAK_WIDTH))
|
||||
break_count = min(target_lines - 1, len(positions))
|
||||
if break_count <= 0:
|
||||
return text
|
||||
|
||||
comma_widths = widths[:-1]
|
||||
selected = []
|
||||
previous = -1.0
|
||||
for part in range(1, break_count + 1):
|
||||
target = total_width * part / (break_count + 1)
|
||||
candidates = [
|
||||
(abs(width - target), idx, width)
|
||||
for idx, width in zip(positions, comma_widths)
|
||||
if width > previous + 4 and idx not in selected
|
||||
]
|
||||
if not candidates:
|
||||
continue
|
||||
_, chosen, chosen_width = min(candidates)
|
||||
selected.append(chosen)
|
||||
previous = chosen_width
|
||||
|
||||
for index in sorted(selected, reverse=True):
|
||||
insert_at = index + 1
|
||||
wait = re.match(r"<waitfor\s*=\s*[^>]+>", text[insert_at:], flags=re.IGNORECASE)
|
||||
if wait:
|
||||
insert_at += wait.end()
|
||||
insertion = "<br>"
|
||||
else:
|
||||
insertion = "[[comma-pause]]<br>"
|
||||
text = text[:insert_at] + insertion + text[insert_at:]
|
||||
return text
|
||||
|
||||
def apply_note(body: str, note: str, category: str) -> str:
|
||||
quoted = re.findall(r"“([^”]+)”", note)
|
||||
if "直接去掉#autonext" in note:
|
||||
return body
|
||||
if "改为“色觉晶圆”" in note:
|
||||
body = re.sub(r"(?<!色觉)晶圆", "色觉晶圆", body)
|
||||
return wrap_phrases(body, ["色觉晶圆"], "term")
|
||||
if "改为“码”" in note:
|
||||
body = body.replace("妈", "码")
|
||||
if "去掉“*”" in note:
|
||||
body = body.replace("*", "")
|
||||
if "加wiggle" in note:
|
||||
for phrase in quoted:
|
||||
emphasized = f"*{phrase}*"
|
||||
if emphasized in body:
|
||||
body = body.replace(
|
||||
emphasized, f"*[[joke]]{phrase}[[/joke]]*")
|
||||
else:
|
||||
body = wrap_phrases(body, [phrase], "joke")
|
||||
return body
|
||||
if "只" in note and ("断行" in note or "换行" in note):
|
||||
return add_comfortable_breaks(body)
|
||||
|
||||
if "并用蓝字" in note:
|
||||
body = wrap_phrases(body, detected_terms(body), "term")
|
||||
elif note.startswith("用黄字"):
|
||||
body = wrap_phrases(body, detected_terms(body), "key")
|
||||
elif "专有名词" in category:
|
||||
body = wrap_phrases(body, detected_terms(body), "term")
|
||||
|
||||
if quoted and ("黄字" in note):
|
||||
body = wrap_phrases(body, quoted, "key")
|
||||
if "断行" in note:
|
||||
body = add_comfortable_breaks(body)
|
||||
return body
|
||||
|
||||
def transform_reviewed_line(row: dict) -> str:
|
||||
original = row["原文"]
|
||||
decision = review_choice(row.get("审阅结论"))
|
||||
if decision == REVIEW_KEEP:
|
||||
return original
|
||||
|
||||
note = row.get("审阅备注") or ""
|
||||
category = row.get("问题分类") or ""
|
||||
suggested = row.get("建议文本") or ""
|
||||
if decision == REVIEW_ACCEPTED and suggested:
|
||||
return suggested
|
||||
|
||||
prefix, body, suffix = dialogue_parts(original)
|
||||
if decision == REVIEW_FOLLOW_NOTE:
|
||||
if "直接去掉#autonext" in note:
|
||||
return original.replace("#autonext", "")
|
||||
body = apply_note(body, note, category)
|
||||
elif decision == REVIEW_ACCEPTED:
|
||||
if "标点规范" in category:
|
||||
body = replace_ascii_quotes(body)
|
||||
if "空格" in category:
|
||||
body = re.sub(r"\s+([,。!?;:])", r"\1", body)
|
||||
if "专有名词" in category and "[[term]]" in (row.get("建议标记") or ""):
|
||||
body = wrap_phrases(body, detected_terms(body), "term")
|
||||
if "ULM效果" in category and "[[ulm]]" in (row.get("建议标记") or ""):
|
||||
prefix += "[[ulm]]"
|
||||
if "笑话效果" in category and "[[joke]]" in (row.get("建议标记") or ""):
|
||||
body = f"[[joke]]{body}[[/joke]]"
|
||||
if "换行候选" in category:
|
||||
body = add_comfortable_breaks(body)
|
||||
|
||||
return prefix + body + suffix
|
||||
|
||||
def source_without_metadata(raw: str) -> str:
|
||||
match = META_TAG_RE.search(raw)
|
||||
return raw[:match.start()].rstrip() if match else raw.rstrip()
|
||||
|
||||
def split_speaker(text: str) -> tuple[str, str]:
|
||||
attr = CHAR_ATTR_RE.match(text)
|
||||
if attr:
|
||||
text = text[attr.end():].lstrip()
|
||||
match = SPEAKER_RE.match(text)
|
||||
if not match:
|
||||
return "", text
|
||||
speaker = match.group(1).strip()
|
||||
if any(c in speaker for c in "<>[]{},。!?…"):
|
||||
return "", text
|
||||
return speaker, match.group(2)
|
||||
|
||||
def issue(issue_type: str, severity: str, confidence: str, reason: str,
|
||||
proposal: str = "", suggested_text: str = "") -> dict:
|
||||
return {
|
||||
"category": issue_type,
|
||||
"severity": severity,
|
||||
"confidence": confidence,
|
||||
"reason": reason,
|
||||
"proposal": proposal,
|
||||
"suggested_text": suggested_text,
|
||||
}
|
||||
|
||||
def detect(record: dict) -> list[dict]:
|
||||
text = record["text"]
|
||||
visible = record["visible_text"]
|
||||
speaker = record["speaker"]
|
||||
found: list[dict] = []
|
||||
|
||||
if REPEAT_RE.search(visible):
|
||||
found.append(issue("重复候选", "需确认", "低", "发现相邻重复片段,可能是强调或口语节奏,也可能是复制错误。"))
|
||||
if re.search(r"[,。!?;:]{2,}", visible):
|
||||
found.append(issue("标点", "建议优化", "中", "发现连续中文标点,需确认是否为误输入。"))
|
||||
if "..." in visible or re.search(r'["\']', visible):
|
||||
found.append(issue("标点规范", "建议优化", "中", "包含 ASCII 省略号或引号,建议统一为中文标点。"))
|
||||
if re.search(r"\s+[,。!?;:]", visible):
|
||||
found.append(issue("空格", "明确错误", "高", "中文标点前存在多余空格。"))
|
||||
if re.search(r"(慢慢|悄悄|轻轻|渐渐|狠狠|迅速|飞快|大声|小声)的(?=[\u3400-\u9fff])", visible):
|
||||
found.append(issue("的地得", "建议优化", "中", "状语后疑似误用“的”,建议结合谓语确认是否改为“地”。"))
|
||||
|
||||
segments = [strip_markup(x) for x in re.split(r"(?i)<br\s*/?>", text)]
|
||||
widths = [visible_width(x) for x in segments]
|
||||
if len(segments) > 1:
|
||||
bad_start = any(seg.startswith(WEAK_LINE_START) for seg in segments[1:] if seg)
|
||||
orphan = any(0 < width <= 2 for width in widths)
|
||||
imbalance = max(widths, default=0) - min(widths, default=0) >= 8
|
||||
if bad_start or orphan or imbalance:
|
||||
found.append(issue("换行", "建议优化", "中",
|
||||
"现有断行存在弱助词开头、孤行或明显失衡;仅在不增加显示行数时调整。"))
|
||||
elif visible_width(visible) > 24 and "," in visible:
|
||||
found.append(issue("换行候选", "需确认", "低",
|
||||
"单行较长且含逗号,可在保持总显示行数的前提下评估断行。"))
|
||||
|
||||
if speaker in {"me", "mecd", "med"} and (
|
||||
re.match(r"^[((].*[))]$", visible) or any(k in visible for k in ("小声", "低声", "喃喃", "默念"))
|
||||
) and "[[aside]]" not in text and "#5F5F5F" not in text:
|
||||
found.append(issue("自言自语/念文本", "需确认", "低",
|
||||
"疑似自言自语、阅读或低声表达,请确认灰色语义标记。", "[[aside]]…[[/aside]]"))
|
||||
|
||||
if speaker == "ULM自训练进程" and "[[ulm]]" not in text and "vertexp" not in text:
|
||||
found.append(issue("ULM效果", "样式标记", "高",
|
||||
"活动 ULM 自训练进程文本应使用统一出现效果。", "[[ulm]]"))
|
||||
|
||||
terms = [term for term in TERM_PATTERNS if term in visible]
|
||||
if terms and "[[term]]" not in text and "#52B6FF" not in text and "#FFB200" not in text:
|
||||
found.append(issue("专有名词", "需确认", "低",
|
||||
"包含游戏专有名词:" + "、".join(terms) + "。颜色需按本次语境逐处确认,不因术语出现而自动标色。",
|
||||
"[[term]]…[[/term]]"))
|
||||
|
||||
if record["module"] == "FP_Huoshan1" and speaker == "hs" and (
|
||||
any(k in visible.replace("*", "") for k in (
|
||||
"看医生其实", "衣 帽", "衣帽间", "路师", "凶柿", "西红凶", "帽问题", "嫡中嫡"
|
||||
))
|
||||
) and "[[joke]]" not in text and "<wiggle" not in text:
|
||||
found.append(issue("笑话效果", "样式标记", "中",
|
||||
"疑似实际讲笑话的台词;确认后使用统一 wiggle 语义标记。", "[[joke]]…[[/joke]]"))
|
||||
|
||||
known_replacements = {
|
||||
"信号接受正常": "信号接收正常",
|
||||
"2000-1000hz": "2000-10000hz",
|
||||
"打折回旋": "打着回旋",
|
||||
"VERYFYING": "VERIFYING",
|
||||
"检查到特征频域异常": "检测到特征频域异常",
|
||||
"#autonext": "#auto_next",
|
||||
}
|
||||
raw_source = record.get("raw", record.get("source_text", ""))
|
||||
for wrong, right in known_replacements.items():
|
||||
if wrong in raw_source:
|
||||
found.append(issue("错别字/漏字", "明确错误", "高",
|
||||
f"检测到明确文本错误:{wrong} → {right}。",
|
||||
suggested_text=raw_source.replace(wrong, right)))
|
||||
|
||||
# Do not duplicate categories for one source line.
|
||||
merged = {}
|
||||
for item in found:
|
||||
merged.setdefault(item["category"], item)
|
||||
return list(merged.values())
|
||||
|
||||
def parse_file(path: Path, repo: Path) -> tuple[list[dict], dict]:
|
||||
lines = path.read_text(encoding="utf-8-sig").splitlines()
|
||||
records: list[dict] = []
|
||||
node = ""
|
||||
pending_title = ""
|
||||
in_body = False
|
||||
counts = Counter()
|
||||
file_hash = sha256(path)
|
||||
rel = path.relative_to(repo).as_posix()
|
||||
module = next((part for part in path.parts if part.startswith("FP_")), path.parent.name)
|
||||
|
||||
for number, raw in enumerate(lines, 1):
|
||||
stripped = raw.strip()
|
||||
if not in_body:
|
||||
if stripped.startswith("title:"):
|
||||
pending_title = stripped.split(":", 1)[1].strip()
|
||||
if stripped == "---":
|
||||
node = pending_title
|
||||
in_body = True
|
||||
counts["delimiter"] += 1
|
||||
elif stripped:
|
||||
counts["metadata"] += 1
|
||||
else:
|
||||
counts["blank"] += 1
|
||||
continue
|
||||
|
||||
if stripped == "===":
|
||||
in_body = False
|
||||
counts["delimiter"] += 1
|
||||
continue
|
||||
if not stripped:
|
||||
counts["blank"] += 1
|
||||
continue
|
||||
if stripped.startswith("//"):
|
||||
counts["comment"] += 1
|
||||
continue
|
||||
if COMMAND_RE.match(stripped):
|
||||
counts["command"] += 1
|
||||
continue
|
||||
|
||||
kind = "option" if stripped.startswith("->") else "text"
|
||||
active = stripped[2:].lstrip() if kind == "option" else stripped
|
||||
active = INLINE_IF_RE.sub("", active).rstrip()
|
||||
source_text = source_without_metadata(active)
|
||||
line_tag_match = LINE_TAG_RE.search(raw)
|
||||
line_tag = line_tag_match.group(1) if line_tag_match else ""
|
||||
speaker, text = split_speaker(source_text)
|
||||
clean = strip_markup(text)
|
||||
record_id = hashlib.sha1(f"{rel}:{number}:{raw}".encode("utf-8")).hexdigest()[:12]
|
||||
record = {
|
||||
"id": record_id,
|
||||
"module": module,
|
||||
"file": rel,
|
||||
"file_sha256": file_hash,
|
||||
"node": node,
|
||||
"line": number,
|
||||
"line_tag": line_tag,
|
||||
"kind": kind,
|
||||
"speaker": speaker,
|
||||
"raw": raw,
|
||||
"source_text": source_text,
|
||||
"text": text,
|
||||
"visible_text": clean,
|
||||
"display_lines": len(re.split(r"(?i)<br\s*/?>", text)),
|
||||
}
|
||||
findings = detect(record)
|
||||
record["findings"] = findings
|
||||
record["review_status"] = "建议修改" if any(
|
||||
x["confidence"] == "高" or x["severity"] == "明确错误" for x in findings
|
||||
) else ("需确认" if findings else "无问题")
|
||||
record["review_method"] = "确定性全量筛查;语义候选待表内确认"
|
||||
records.append(record)
|
||||
counts[kind] += 1
|
||||
|
||||
unknown = 0 if not in_body else 1
|
||||
summary = {
|
||||
"module": module,
|
||||
"file": rel,
|
||||
"sha256": file_hash,
|
||||
"physical_lines": len(lines),
|
||||
"active_records": len(records),
|
||||
"reviewed_records": len(records),
|
||||
"unreviewed_records": 0,
|
||||
"issue_records": sum(bool(r["findings"]) for r in records),
|
||||
"unknown_active_lines": unknown,
|
||||
"counts": dict(counts),
|
||||
"status": "通过" if unknown == 0 else "失败",
|
||||
}
|
||||
return records, summary
|
||||
|
||||
def write_csv(path: Path, fields: list[str], rows: list[dict]) -> None:
|
||||
with path.open("w", encoding="utf-8-sig", newline="") as f:
|
||||
writer = csv.DictWriter(f, fieldnames=fields, extrasaction="ignore")
|
||||
writer.writeheader()
|
||||
writer.writerows(rows)
|
||||
|
||||
def scan(args: argparse.Namespace) -> int:
|
||||
repo = Path(args.repo).resolve()
|
||||
output = Path(args.output)
|
||||
if not output.is_absolute():
|
||||
output = (repo / output).resolve()
|
||||
output.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
files = []
|
||||
for root_arg in args.root:
|
||||
root = (repo / root_arg).resolve() if not Path(root_arg).is_absolute() else Path(root_arg)
|
||||
files.extend(sorted(root.rglob("*.yarn")))
|
||||
files = sorted(set(files))
|
||||
all_records, coverage = [], []
|
||||
for file in files:
|
||||
records, summary = parse_file(file, repo)
|
||||
all_records.extend(records)
|
||||
coverage.append(summary)
|
||||
|
||||
reviewed_ids = set()
|
||||
if args.review_memory:
|
||||
memory = json.loads(Path(args.review_memory).read_text(encoding="utf-8"))
|
||||
for row in memory:
|
||||
expected = transform_reviewed_line(row)
|
||||
fingerprint = f'{row["文件"]}:{int(row["行号"])}:{expected}'
|
||||
reviewed_ids.add(hashlib.sha1(fingerprint.encode("utf-8")).hexdigest()[:12])
|
||||
for record in all_records:
|
||||
if record["id"] in reviewed_ids:
|
||||
record["findings"] = []
|
||||
record["review_status"] = "无问题"
|
||||
record["review_method"] = "人工审阅结论已应用"
|
||||
issues_by_file = Counter(
|
||||
record["file"] for record in all_records if record["findings"])
|
||||
for summary in coverage:
|
||||
summary["issue_records"] = issues_by_file[summary["file"]]
|
||||
|
||||
issues = []
|
||||
for record in all_records:
|
||||
if not record["findings"]:
|
||||
continue
|
||||
categories = [x["category"] for x in record["findings"]]
|
||||
severity_order = {"明确错误": 3, "样式标记": 2, "建议优化": 1, "需确认": 0}
|
||||
confidence_order = {"高": 2, "中": 1, "低": 0}
|
||||
severity = max((x["severity"] for x in record["findings"]), key=lambda x: severity_order.get(x, 0))
|
||||
confidence = max((x["confidence"] for x in record["findings"]), key=lambda x: confidence_order.get(x, 0))
|
||||
issues.append({
|
||||
"稳定ID": record["id"], "模块": record["module"], "文件": record["file"],
|
||||
"节点": record["node"], "行号": record["line"], "LineTag": record["line_tag"],
|
||||
"说话者": record["speaker"], "问题分类": categories, "严重度": severity,
|
||||
"置信度": confidence, "原文": record["raw"],
|
||||
"建议文本": next((x["suggested_text"] for x in record["findings"] if x["suggested_text"]), ""),
|
||||
"理由": "\n".join(x["reason"] for x in record["findings"]),
|
||||
"建议标记": ";".join(x["proposal"] for x in record["findings"] if x["proposal"]),
|
||||
"检测来源": "脚本规则", "审核状态": "待确认",
|
||||
"file_sha256": record["file_sha256"], "display_lines": record["display_lines"],
|
||||
})
|
||||
|
||||
manifest = {
|
||||
"version": 1,
|
||||
"repo": str(repo),
|
||||
"roots": args.root,
|
||||
"files": coverage,
|
||||
}
|
||||
total = {
|
||||
"files": len(files),
|
||||
"physical_lines": sum(x["physical_lines"] for x in coverage),
|
||||
"active_records": len(all_records),
|
||||
"reviewed_records": len(all_records),
|
||||
"unreviewed_records": 0,
|
||||
"issue_records": len(issues),
|
||||
"unknown_active_lines": sum(x["unknown_active_lines"] for x in coverage),
|
||||
"review_method": "确定性全量筛查;语义候选待表内确认",
|
||||
}
|
||||
(output / "manifest.json").write_text(json.dumps(manifest, ensure_ascii=False, indent=2), encoding="utf-8")
|
||||
(output / "summary.json").write_text(json.dumps(total, ensure_ascii=False, indent=2), encoding="utf-8")
|
||||
with (output / "ledger.jsonl").open("w", encoding="utf-8") as f:
|
||||
for row in all_records:
|
||||
f.write(json.dumps(row, ensure_ascii=False) + "\n")
|
||||
(output / "issues.json").write_text(json.dumps(issues, ensure_ascii=False, indent=2), encoding="utf-8")
|
||||
issue_fields = ["稳定ID","模块","文件","节点","行号","LineTag","说话者","问题分类","严重度",
|
||||
"置信度","原文","建议文本","理由","建议标记","检测来源","审核状态"]
|
||||
csv_issues = [{**x, "问题分类": "、".join(x["问题分类"])} for x in issues]
|
||||
write_csv(output / "issues.csv", issue_fields, csv_issues)
|
||||
coverage_fields = ["module","file","sha256","physical_lines","active_records","reviewed_records",
|
||||
"unreviewed_records","issue_records","unknown_active_lines","status"]
|
||||
write_csv(output / "coverage.csv", coverage_fields, coverage)
|
||||
print(json.dumps(total, ensure_ascii=False, indent=2))
|
||||
return 0 if total["unknown_active_lines"] == total["unreviewed_records"] == 0 else 2
|
||||
|
||||
def verify(args: argparse.Namespace) -> int:
|
||||
output = Path(args.output)
|
||||
summary = json.loads((output / "summary.json").read_text(encoding="utf-8"))
|
||||
ledger_count = sum(1 for line in (output / "ledger.jsonl").read_text(encoding="utf-8").splitlines() if line)
|
||||
issues = json.loads((output / "issues.json").read_text(encoding="utf-8"))
|
||||
ok = (
|
||||
summary["unknown_active_lines"] == 0
|
||||
and summary["unreviewed_records"] == 0
|
||||
and summary["active_records"] == ledger_count
|
||||
and summary["issue_records"] == len(issues)
|
||||
)
|
||||
print(json.dumps({"ok": ok, "ledger_count": ledger_count, **summary}, ensure_ascii=False, indent=2))
|
||||
return 0 if ok else 2
|
||||
|
||||
def build_lark_payloads(args: argparse.Namespace) -> int:
|
||||
output = Path(args.output)
|
||||
target = output / "lark"
|
||||
target.mkdir(parents=True, exist_ok=True)
|
||||
issues = json.loads((output / "issues.json").read_text(encoding="utf-8"))
|
||||
manifest = json.loads((output / "manifest.json").read_text(encoding="utf-8"))
|
||||
|
||||
issue_fields = ["稳定ID","模块","文件","节点","行号","LineTag","说话者","问题分类",
|
||||
"严重度","置信度","原文","建议文本","理由","建议标记","检测来源","审核状态"]
|
||||
issue_rows = []
|
||||
for row in issues:
|
||||
issue_rows.append([
|
||||
row["稳定ID"], row["模块"], row["文件"], row["节点"], row["行号"],
|
||||
row["LineTag"], row["说话者"], "、".join(row["问题分类"]), row["严重度"],
|
||||
row["置信度"], row["原文"], row["建议文本"], row["理由"], row["建议标记"],
|
||||
row["检测来源"], row["审核状态"],
|
||||
])
|
||||
for index in range(0, len(issue_rows), 200):
|
||||
payload = {"fields": issue_fields, "rows": issue_rows[index:index + 200]}
|
||||
(target / f"issues-{index // 200 + 1:03d}.json").write_text(
|
||||
json.dumps(payload, ensure_ascii=False), encoding="utf-8")
|
||||
|
||||
coverage_fields = ["文件","模块","SHA256","物理行数","活动文本数","已审数",
|
||||
"未审数","问题数","未知活动行","校验状态"]
|
||||
coverage_rows = [[
|
||||
row["file"], row["module"], row["sha256"], row["physical_lines"],
|
||||
row["active_records"], row["reviewed_records"], row["unreviewed_records"],
|
||||
row["issue_records"], row["unknown_active_lines"], row["status"],
|
||||
] for row in manifest["files"]]
|
||||
(target / "coverage.json").write_text(json.dumps(
|
||||
{"fields": coverage_fields, "rows": coverage_rows}, ensure_ascii=False), encoding="utf-8")
|
||||
|
||||
style_fields = ["名称","类别","语义标记","默认参数","适用规则","示例"]
|
||||
style_rows = [
|
||||
["自言自语/念文本/小声","语义样式","[[aside]]…[[/aside]]","#5F5F5F","只用于真实自言自语、阅读或低声表达;斜体不自动等同","[[aside]]我是不是忘了什么……[[/aside]]"],
|
||||
["游戏专有名词","语义样式","[[term]]…[[/term]]","#52B6FF","游戏世界独有的模块、机构、技术和概念","[[term]]UF模块[[/term]]"],
|
||||
["玩家重点信息","语义样式","[[key]]…[[/key]]","#FFB200","任务目标、必须寻找或操作的对象;优先于专名","寻找[[key]]色觉晶圆[[/key]]"],
|
||||
["逗号停顿","节奏效果","[[comma-pause]]","waitfor=0.2","只用于调整断行或明确需要节奏的逗号","别因为外面很冷,[[comma-pause]]<br>就逃回那个着火的房子。"],
|
||||
["ULM自训练进程","出现效果","[[ulm]]","vertexp d=0.05 bot","FP_Peipei2 每条活动 ULM自训练进程文本","[[ulm]]ULM自训练进程: 正在训练……"],
|
||||
["火山笑话","动态效果","[[joke]]…[[/joke]]","wiggle a=0.3 s=0.1","只包裹实际讲出的笑话,不包裹说明性对白","[[joke]]看医生其实是被医生看。[[/joke]]"],
|
||||
]
|
||||
(target / "styles.json").write_text(json.dumps(
|
||||
{"fields": style_fields, "rows": style_rows}, ensure_ascii=False), encoding="utf-8")
|
||||
print(json.dumps({
|
||||
"issue_batches": (len(issue_rows) + 199) // 200,
|
||||
"issue_rows": len(issue_rows),
|
||||
"coverage_rows": len(coverage_rows),
|
||||
"style_rows": len(style_rows),
|
||||
}, ensure_ascii=False, indent=2))
|
||||
return 0
|
||||
|
||||
def apply_approved(args: argparse.Namespace) -> int:
|
||||
issues_path = Path(args.issues)
|
||||
manifest = json.loads(Path(args.manifest).read_text(encoding="utf-8"))
|
||||
repo = Path(manifest["repo"])
|
||||
issues = json.loads(issues_path.read_text(encoding="utf-8"))
|
||||
approved = [x for x in issues if x.get("审核状态") == "接受" and x.get("建议文本")]
|
||||
hashes = {x["file"]: x["sha256"] for x in manifest["files"]}
|
||||
grouped = defaultdict(list)
|
||||
for row in approved:
|
||||
grouped[row["文件"]].append(row)
|
||||
|
||||
prepared = {}
|
||||
for rel, rows in grouped.items():
|
||||
path = repo / rel
|
||||
if sha256(path) != hashes.get(rel):
|
||||
raise SystemExit(f"stale file hash: {rel}")
|
||||
lines = path.read_text(encoding="utf-8-sig").splitlines(keepends=True)
|
||||
for row in sorted(rows, key=lambda x: int(x["行号"])):
|
||||
idx = int(row["行号"]) - 1
|
||||
old = lines[idx].rstrip("\r\n")
|
||||
if old != row["原文"]:
|
||||
raise SystemExit(f"source mismatch: {rel}:{idx+1}")
|
||||
new = row["建议文本"]
|
||||
if LINE_TAG_RE.findall(old) != LINE_TAG_RE.findall(new):
|
||||
raise SystemExit(f"line tag changed: {rel}:{idx+1}")
|
||||
old_text = source_without_metadata(old)
|
||||
new_text = source_without_metadata(new)
|
||||
if len(re.split(r"(?i)<br\s*/?>", new_text)) > len(re.split(r"(?i)<br\s*/?>", old_text)):
|
||||
raise SystemExit(f"display line added: {rel}:{idx+1}")
|
||||
ending = lines[idx][len(lines[idx].rstrip("\r\n")):]
|
||||
lines[idx] = new + ending
|
||||
prepared[path] = "".join(lines)
|
||||
|
||||
for path, content in prepared.items():
|
||||
fd, tmp = tempfile.mkstemp(prefix=path.name, dir=path.parent)
|
||||
try:
|
||||
with os.fdopen(fd, "w", encoding="utf-8", newline="") as f:
|
||||
f.write(content)
|
||||
os.replace(tmp, path)
|
||||
finally:
|
||||
if os.path.exists(tmp):
|
||||
os.unlink(tmp)
|
||||
print(json.dumps({"applied": len(approved), "files": len(prepared)}, ensure_ascii=False))
|
||||
return 0
|
||||
|
||||
def apply_reviewed(args: argparse.Namespace) -> int:
|
||||
manifest = json.loads(Path(args.manifest).read_text(encoding="utf-8"))
|
||||
reviews = json.loads(Path(args.reviews).read_text(encoding="utf-8"))
|
||||
repo = Path(manifest["repo"])
|
||||
hashes = {x["file"]: x["sha256"] for x in manifest["files"]}
|
||||
allowed = {REVIEW_ACCEPTED, REVIEW_KEEP, REVIEW_FOLLOW_NOTE}
|
||||
decisions = Counter(review_choice(row.get("审阅结论")) for row in reviews)
|
||||
invalid = sorted(choice for choice in decisions if choice not in allowed)
|
||||
if invalid:
|
||||
raise SystemExit(f"unresolved review decisions: {invalid}")
|
||||
|
||||
grouped = defaultdict(list)
|
||||
changes = []
|
||||
unchanged_actionable = []
|
||||
for row in reviews:
|
||||
decision = review_choice(row.get("审阅结论"))
|
||||
new = transform_reviewed_line(row)
|
||||
if decision != REVIEW_KEEP and new == row["原文"]:
|
||||
unchanged_actionable.append(f'{row["文件"]}:{row["行号"]} ({decision})')
|
||||
if new != row["原文"]:
|
||||
grouped[row["文件"]].append((row, new))
|
||||
changes.append({
|
||||
"稳定ID": row["稳定ID"],
|
||||
"文件": row["文件"],
|
||||
"行号": row["行号"],
|
||||
"问题分类": row["问题分类"],
|
||||
"审阅结论": decision,
|
||||
"审阅备注": row.get("审阅备注") or "",
|
||||
"原文": row["原文"],
|
||||
"应用文本": new,
|
||||
})
|
||||
if unchanged_actionable:
|
||||
raise SystemExit("actionable reviews produced no change:\n" + "\n".join(unchanged_actionable))
|
||||
|
||||
prepared = {}
|
||||
for rel, rows in grouped.items():
|
||||
path = repo / rel
|
||||
if sha256(path) != hashes.get(rel):
|
||||
raise SystemExit(f"stale file hash: {rel}")
|
||||
lines = path.read_text(encoding="utf-8-sig").splitlines(keepends=True)
|
||||
before_tags = LINE_TAG_RE.findall("".join(lines))
|
||||
for row, new in sorted(rows, key=lambda item: int(item[0]["行号"])):
|
||||
idx = int(row["行号"]) - 1
|
||||
old = lines[idx].rstrip("\r\n")
|
||||
if old != row["原文"]:
|
||||
raise SystemExit(f"source mismatch: {rel}:{idx + 1}")
|
||||
if LINE_TAG_RE.findall(old) != LINE_TAG_RE.findall(new):
|
||||
raise SystemExit(f"line tag changed: {rel}:{idx + 1}")
|
||||
_, old_body, _ = dialogue_parts(old)
|
||||
_, new_body, _ = dialogue_parts(new)
|
||||
old_width = visible_width(strip_markup(old_body))
|
||||
allowed_lines = max(
|
||||
len(re.split(r"(?i)<br\s*/?>", old_body)),
|
||||
int((old_width + MANUAL_BREAK_WIDTH - 0.001) // MANUAL_BREAK_WIDTH),
|
||||
)
|
||||
new_lines = len(re.split(r"(?i)<br\s*/?>", new_body))
|
||||
if new_lines > allowed_lines:
|
||||
raise SystemExit(
|
||||
f"display line estimate increased: {rel}:{idx + 1} "
|
||||
f"({new_lines} > {allowed_lines})"
|
||||
)
|
||||
for marker in ("aside", "term", "key", "joke"):
|
||||
if new.count(f"[[{marker}]]") != new.count(f"[[/{marker}]]"):
|
||||
raise SystemExit(f"unbalanced semantic marker {marker}: {rel}:{idx + 1}")
|
||||
ending = lines[idx][len(lines[idx].rstrip("\r\n")):]
|
||||
lines[idx] = new + ending
|
||||
content = "".join(lines)
|
||||
if LINE_TAG_RE.findall(content) != before_tags:
|
||||
raise SystemExit(f"file line tag set/order changed: {rel}")
|
||||
prepared[path] = content
|
||||
|
||||
report = {
|
||||
"review_records": len(reviews),
|
||||
"decisions": dict(decisions),
|
||||
"changed_records": len(changes),
|
||||
"changed_files": len(prepared),
|
||||
"dry_run": not args.apply,
|
||||
"changes": changes,
|
||||
}
|
||||
if args.report:
|
||||
Path(args.report).write_text(
|
||||
json.dumps(report, ensure_ascii=False, indent=2), encoding="utf-8")
|
||||
if args.apply:
|
||||
for path, content in prepared.items():
|
||||
fd, tmp = tempfile.mkstemp(prefix=path.name, dir=path.parent)
|
||||
try:
|
||||
with os.fdopen(fd, "w", encoding="utf-8", newline="") as f:
|
||||
f.write(content)
|
||||
os.replace(tmp, path)
|
||||
finally:
|
||||
if os.path.exists(tmp):
|
||||
os.unlink(tmp)
|
||||
print(json.dumps({
|
||||
key: value for key, value in report.items() if key != "changes"
|
||||
}, ensure_ascii=False, indent=2))
|
||||
return 0
|
||||
|
||||
def self_test() -> int:
|
||||
import unittest
|
||||
|
||||
class AuditTests(unittest.TestCase):
|
||||
def test_markup_and_width(self):
|
||||
self.assertEqual(strip_markup("[[vertexp d=0.05 bot]]<color=\\#fff>文字</color>"), "文字")
|
||||
self.assertEqual(visible_width("中文ab"), 3.0)
|
||||
|
||||
def test_break_rule(self):
|
||||
rec = {
|
||||
"text": "很多时候,比起幸福更难以让人离<br>开的,是熟悉。",
|
||||
"visible_text": "很多时候,比起幸福更难以让人离开的,是熟悉。",
|
||||
"speaker": "me", "source_text": "", "module": "FP_Test",
|
||||
}
|
||||
self.assertIn("换行", [x["category"] for x in detect(rec)])
|
||||
|
||||
def test_annotated_rules(self):
|
||||
ulm = {"text":"正在训练","visible_text":"正在训练","speaker":"ULM自训练进程",
|
||||
"source_text":"","module":"FP_Peipei2"}
|
||||
self.assertIn("ULM效果", [x["category"] for x in detect(ulm)])
|
||||
task = {"text":"寻找模块","visible_text":"寻找模块","speaker":"Task",
|
||||
"source_text":"","module":"FP_Test"}
|
||||
self.assertNotIn("重要信息", [x["category"] for x in detect(task)])
|
||||
|
||||
def test_reviewed_break_preserves_existing_wait(self):
|
||||
text = "很多时候,比起幸福更难以让人离开的,是熟悉。"
|
||||
changed = add_comfortable_breaks(text)
|
||||
self.assertIn(",[[comma-pause]]<br>", changed)
|
||||
with_wait = "别因为外面很冷,<waitfor=0.1>就逃回那个着火的房子。"
|
||||
changed_wait = add_comfortable_breaks(with_wait)
|
||||
self.assertIn(",<waitfor=0.1><br>", changed_wait)
|
||||
self.assertNotIn("[[comma-pause]]", changed_wait)
|
||||
|
||||
def test_review_note_overrides_default_style(self):
|
||||
row = {
|
||||
"原文": "me: 去检查*情绪模块*。 #line:abc",
|
||||
"审阅结论": [REVIEW_FOLLOW_NOTE],
|
||||
"审阅备注": "用黄字,并且去掉“*”",
|
||||
"问题分类": "专有名词",
|
||||
}
|
||||
changed = transform_reviewed_line(row)
|
||||
self.assertIn("[[key]]情绪模块[[/key]]", changed)
|
||||
self.assertNotIn("*", changed)
|
||||
self.assertEqual(LINE_TAG_RE.findall(changed), ["abc"])
|
||||
|
||||
suite = unittest.defaultTestLoader.loadTestsFromTestCase(AuditTests)
|
||||
result = unittest.TextTestRunner(verbosity=2).run(suite)
|
||||
return 0 if result.wasSuccessful() else 2
|
||||
|
||||
def build_parser() -> argparse.ArgumentParser:
|
||||
parser = argparse.ArgumentParser(description="Deterministic Yarn text coverage and review ledger")
|
||||
sub = parser.add_subparsers(dest="command", required=True)
|
||||
p_scan = sub.add_parser("scan")
|
||||
p_scan.add_argument("--repo", default=".")
|
||||
p_scan.add_argument("--root", action="append", required=True)
|
||||
p_scan.add_argument("--output", required=True)
|
||||
p_scan.add_argument(
|
||||
"--review-memory",
|
||||
help="可选的飞书审阅导出;已应用或明确保留的记录不再重复报告")
|
||||
p_scan.set_defaults(func=scan)
|
||||
p_verify = sub.add_parser("verify")
|
||||
p_verify.add_argument("--output", required=True)
|
||||
p_verify.set_defaults(func=verify)
|
||||
p_apply = sub.add_parser("apply")
|
||||
p_apply.add_argument("--issues", required=True)
|
||||
p_apply.add_argument("--manifest", required=True)
|
||||
p_apply.set_defaults(func=apply_approved)
|
||||
p_apply_review = sub.add_parser("apply-review")
|
||||
p_apply_review.add_argument("--reviews", required=True)
|
||||
p_apply_review.add_argument("--manifest", required=True)
|
||||
p_apply_review.add_argument("--report")
|
||||
p_apply_review.add_argument("--apply", action="store_true")
|
||||
p_apply_review.set_defaults(func=apply_reviewed)
|
||||
p_lark = sub.add_parser("lark-payloads")
|
||||
p_lark.add_argument("--output", required=True)
|
||||
p_lark.set_defaults(func=build_lark_payloads)
|
||||
p_test = sub.add_parser("self-test")
|
||||
p_test.set_defaults(func=lambda _: self_test())
|
||||
return parser
|
||||
|
||||
def main() -> int:
|
||||
args = build_parser().parse_args()
|
||||
return args.func(args)
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
Reference in New Issue
Block a user