新版本
This commit is contained in:
@@ -260,6 +260,20 @@ const SFX_UI = {
|
||||
setTimeout(() => Snd.synth({ freq: 523, dur: 100, vol: 0.13 }), 120);
|
||||
},
|
||||
|
||||
// 打字/录音音效(~800ms)
|
||||
typing() {
|
||||
for (let i = 0; i < 6; i++) {
|
||||
setTimeout(() => {
|
||||
Snd.synth({ freq: 600 + Math.random() * 200, dur: 30, type: 'sine', vol: 0.1 });
|
||||
}, i * 120);
|
||||
}
|
||||
},
|
||||
|
||||
// 发送音效
|
||||
send() {
|
||||
Snd.synth({ freq: 400, freq2: 900, dur: 120, type: 'sine', vol: 0.18 });
|
||||
},
|
||||
|
||||
// 结局音效
|
||||
ending() {
|
||||
Snd.synth({ freq: 523, dur: 400, vol: 0.25 });
|
||||
|
||||
+224
-93
@@ -1,32 +1,40 @@
|
||||
// engine.js — 游戏引擎(玩家驱动,无时间依赖)
|
||||
// engine.js — 游戏引擎 v2(多轮对话 + 林夏语音 + NPC反应)
|
||||
//
|
||||
// 状态流:idle → notification/ringing → playing → choosing → idle → …… → ending
|
||||
// 所有 UI 反馈使用合成短音效(SFX_UI),不使用 TTS 语音播报
|
||||
// 状态流:idle → notification/ringing → playing → choosing
|
||||
// → responding → reacting → [choosing | idle] → …… → ending
|
||||
//
|
||||
// 新增状态:
|
||||
// responding — 林夏说话中(打字音效 + 语音播放)
|
||||
// reacting — NPC反应播放中
|
||||
|
||||
class GameEngine {
|
||||
constructor() {
|
||||
// 状态(通过 setter 自动更新提示栏)
|
||||
this._state = 'idle';
|
||||
|
||||
// 剧情变量
|
||||
this.vars = {
|
||||
MOM_LINK: false,
|
||||
HE_BACK: null, // null=未定, true=来了, false=拒了
|
||||
HE_BACK: null,
|
||||
GROUP_REPLY: false,
|
||||
ZHOUNAN_DEPTH: 0, // 0-3
|
||||
ZHOUNAN_DEPTH: 0,
|
||||
ZHOUNAN_SHARE: false,
|
||||
SELF_RECORD: false,
|
||||
UNREAD: 0,
|
||||
};
|
||||
|
||||
this.profile = new ProfileTracker();
|
||||
this.msgState = {}; // msgId → 'unread'|'read'|'replied'|'missed'
|
||||
this.msgState = {};
|
||||
this.currentMsg = null;
|
||||
|
||||
this._queue = []; // 消息队列
|
||||
this._queue = [];
|
||||
this._endingTriggered = false;
|
||||
this._reminderTimer = null;
|
||||
|
||||
// v2: 对话系统
|
||||
this._currentChoices = null; // 当前可用的选项集
|
||||
this._pendingResolve = null; // 用于中断语音播放的 resolve
|
||||
this._skipRequested = false; // 跳过标志
|
||||
|
||||
this.gest = null;
|
||||
}
|
||||
|
||||
@@ -43,6 +51,8 @@ class GameEngine {
|
||||
ringing: '单击 接听 · 左滑 拒接',
|
||||
playing: '双击 跳过',
|
||||
choosing: '→温暖 ←冷淡 ↑追问 ↓沉默',
|
||||
responding: '双击 跳过',
|
||||
reacting: '双击 跳过',
|
||||
ending: '',
|
||||
};
|
||||
el.textContent = H[s] || '';
|
||||
@@ -66,16 +76,48 @@ class GameEngine {
|
||||
async start() {
|
||||
this._queue = [...MESSAGES];
|
||||
|
||||
// 环境音 + BGM
|
||||
await Snd.startAmbience(AMBIENCE_DEFAULT, { vol: 0.15 });
|
||||
await sleep(1500);
|
||||
Snd.startBGM(`${MUS}/lv11_bgm_m1_main_loop_v1.mp3`, { vol: 0.2 });
|
||||
await sleep(1500);
|
||||
|
||||
// 开始第一条消息
|
||||
this._next();
|
||||
}
|
||||
|
||||
// ══════════════════════════════════════════
|
||||
// 语音播放(异步 + 可中断)
|
||||
// ══════════════════════════════════════════
|
||||
|
||||
_playVoiceAsync(urls) {
|
||||
return new Promise(resolve => {
|
||||
this._pendingResolve = resolve;
|
||||
Snd.playVoice(urls, {
|
||||
onEnd: () => {
|
||||
this._pendingResolve = null;
|
||||
resolve();
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
_interruptVoice() {
|
||||
Snd.stopVoice();
|
||||
TTS.stop();
|
||||
if (this._pendingResolve) {
|
||||
this._pendingResolve();
|
||||
this._pendingResolve = null;
|
||||
}
|
||||
}
|
||||
|
||||
// 打字 + 发送音效
|
||||
async _playTypingSend() {
|
||||
SFX_UI.typing();
|
||||
await sleep(800);
|
||||
if (this._skipRequested) return;
|
||||
SFX_UI.send();
|
||||
await sleep(300);
|
||||
}
|
||||
|
||||
// ══════════════════════════════════════════
|
||||
// 消息队列推进
|
||||
// ══════════════════════════════════════════
|
||||
@@ -89,13 +131,13 @@ class GameEngine {
|
||||
return;
|
||||
}
|
||||
|
||||
// 消息16需要 MOM_LINK
|
||||
if (msg.requiresMomLink && !this.vars.MOM_LINK) {
|
||||
this.triggerFinalEnding();
|
||||
return;
|
||||
}
|
||||
|
||||
this.currentMsg = msg;
|
||||
this._currentChoices = msg.choices || null;
|
||||
this.msgState[msg.id] = 'unread';
|
||||
this.vars.UNREAD++;
|
||||
|
||||
@@ -106,7 +148,6 @@ class GameEngine {
|
||||
}
|
||||
}
|
||||
|
||||
// ── 非通话消息通知 ──
|
||||
_notifyMessage(msg) {
|
||||
this.state = 'notification';
|
||||
Haptic.message();
|
||||
@@ -114,7 +155,6 @@ class GameEngine {
|
||||
this._startReminder();
|
||||
}
|
||||
|
||||
// ── 来电铃声 ──
|
||||
async _startRinging(msg) {
|
||||
this.state = 'ringing';
|
||||
Haptic.ring();
|
||||
@@ -123,10 +163,10 @@ class GameEngine {
|
||||
}
|
||||
|
||||
// ══════════════════════════════════════════
|
||||
// 通话流程
|
||||
// 通话流程(异步)
|
||||
// ══════════════════════════════════════════
|
||||
|
||||
_answerCall(msg) {
|
||||
async _answerCall(msg) {
|
||||
Snd.stopRingtone();
|
||||
Haptic.stop();
|
||||
Haptic.confirm();
|
||||
@@ -140,22 +180,57 @@ class GameEngine {
|
||||
if (msg.stateOnAnswer) this._applyState(msg.stateOnAnswer);
|
||||
if (msg.profileOnAnswer) this.profile.add(msg.profileOnAnswer);
|
||||
|
||||
Snd.playVoice(msg.audio, {
|
||||
onEnd: () => {
|
||||
if (this.state !== 'playing') return; // 已被跳过
|
||||
if (msg.autoHangup && msg.sfxAfter) {
|
||||
const sfx = Array.isArray(msg.sfxAfter) ? msg.sfxAfter[0] : msg.sfxAfter;
|
||||
Snd.playVoice([sfx], { onEnd: () => this._proceedToNext() });
|
||||
} else if (msg.choices) {
|
||||
this.state = 'choosing';
|
||||
SFX_UI.choiceReady();
|
||||
Haptic.confirm();
|
||||
this._startReminder();
|
||||
} else {
|
||||
this._proceedToNext();
|
||||
this._skipRequested = false;
|
||||
|
||||
// 播放通话内容
|
||||
await this._playVoiceAsync(msg.audio);
|
||||
|
||||
// _onDoubleTap 在 'playing' 状态下会直接处理状态转换
|
||||
// 所以如果状态已不是 'playing',说明跳过已被处理,直接返回
|
||||
if (this.state !== 'playing') return;
|
||||
|
||||
// 自动挂断(MSG-08 未知号码)
|
||||
if (msg.autoHangup) {
|
||||
if (msg.sfxAfter) {
|
||||
const sfx = Array.isArray(msg.sfxAfter) ? msg.sfxAfter[0] : msg.sfxAfter;
|
||||
await this._playVoiceAsync([sfx]);
|
||||
if (this.state !== 'playing') return;
|
||||
}
|
||||
this._proceedToNext();
|
||||
return;
|
||||
}
|
||||
|
||||
// 自动回复(MSG-01/03/14 妈妈电话、外卖、妈妈第二次电话)
|
||||
if (msg.autoReply) {
|
||||
await this._playTypingSend();
|
||||
if (this.state !== 'playing') return;
|
||||
|
||||
this.state = 'responding';
|
||||
await this._playVoiceAsync([msg.autoReply]);
|
||||
|
||||
// 条件反应(MSG-14:根据 MOM_LINK 播放不同反应)
|
||||
if (!this._skipRequested && msg.autoReact) {
|
||||
const val = this.vars[msg.autoReact.condition];
|
||||
const reactUrl = val ? msg.autoReact['true'] : msg.autoReact['false'];
|
||||
if (reactUrl) {
|
||||
this.state = 'reacting';
|
||||
await sleep(500);
|
||||
if (!this._skipRequested) {
|
||||
await this._playVoiceAsync([reactUrl]);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
this._proceedToNext();
|
||||
return;
|
||||
}
|
||||
|
||||
// 通话后有选择(MSG-11 阿哲)
|
||||
if (msg.choices) {
|
||||
this._enterChoosing(msg.choices);
|
||||
return;
|
||||
}
|
||||
|
||||
this._proceedToNext();
|
||||
}
|
||||
|
||||
_rejectCall(msg) {
|
||||
@@ -169,7 +244,7 @@ class GameEngine {
|
||||
}
|
||||
|
||||
// ══════════════════════════════════════════
|
||||
// 消息播放
|
||||
// 消息播放(异步)
|
||||
// ══════════════════════════════════════════
|
||||
|
||||
async _playMessage(msg) {
|
||||
@@ -186,32 +261,27 @@ class GameEngine {
|
||||
return;
|
||||
}
|
||||
|
||||
// 文字消息(用 TTS 朗读内容)
|
||||
if (msg.type === 'wechat_text' && msg.text && (!msg.audio || msg.audio.length === 0)) {
|
||||
TTS.speak(msg.text).then(() => {
|
||||
if (this.state === 'playing') this._afterPlayed(msg);
|
||||
});
|
||||
return;
|
||||
this._skipRequested = false;
|
||||
|
||||
// 文字消息(TTS 朗读)
|
||||
if (msg.type === 'wechat_text' && msg.text) {
|
||||
await TTS.speak(msg.text);
|
||||
}
|
||||
// 语音消息
|
||||
else if (msg.audio?.length > 0) {
|
||||
await this._playVoiceAsync(msg.audio);
|
||||
}
|
||||
|
||||
// 语音消息
|
||||
if (msg.audio && msg.audio.length > 0) {
|
||||
Snd.playVoice(msg.audio, {
|
||||
onEnd: () => {
|
||||
if (this.state === 'playing') this._afterPlayed(msg);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this._afterPlayed(msg);
|
||||
}
|
||||
if (this._skipRequested) return;
|
||||
if (this.state !== 'playing') return;
|
||||
|
||||
this._afterPlayed(msg);
|
||||
}
|
||||
|
||||
// ── 系统通知特殊处理 ──
|
||||
_playSystemNotification(msg) {
|
||||
Snd.playVoice([msg.systemAudio], {
|
||||
onEnd: () => {
|
||||
if (this.state !== 'playing') return;
|
||||
// 根据画像播放对应版本
|
||||
const audio = msg.audioByProfile?.[this.profile.label];
|
||||
if (audio) {
|
||||
if (msg.stateOnPlay) this._applyState(msg.stateOnPlay);
|
||||
@@ -219,19 +289,18 @@ class GameEngine {
|
||||
setTimeout(() => {
|
||||
if (this.state !== 'playing') return;
|
||||
Snd.playVoice([audio], {
|
||||
onEnd: () => this._proceedToNext()
|
||||
onEnd: () => this._proceedToNext(),
|
||||
});
|
||||
}, 800);
|
||||
} else {
|
||||
this._proceedToNext();
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// ── 消息播放完成 ──
|
||||
_afterPlayed(msg) {
|
||||
if (this.state !== 'playing') return; // 防止重复调用
|
||||
if (this.state !== 'playing') return;
|
||||
|
||||
if (msg.isEnding) {
|
||||
this.triggerFinalEnding();
|
||||
@@ -239,28 +308,34 @@ class GameEngine {
|
||||
}
|
||||
|
||||
if (msg.choices) {
|
||||
this.state = 'choosing';
|
||||
SFX_UI.choiceReady();
|
||||
Haptic.confirm();
|
||||
this._startReminder();
|
||||
} else {
|
||||
this._proceedToNext();
|
||||
this._enterChoosing(msg.choices);
|
||||
return;
|
||||
}
|
||||
|
||||
this._proceedToNext();
|
||||
}
|
||||
|
||||
// ══════════════════════════════════════════
|
||||
// 选择回复
|
||||
// 选择系统(v2 多轮对话核心)
|
||||
// ══════════════════════════════════════════
|
||||
|
||||
_choose(dir) {
|
||||
const msg = this.currentMsg;
|
||||
if (!msg?.choices) {
|
||||
_enterChoosing(choices) {
|
||||
this._currentChoices = choices;
|
||||
this.state = 'choosing';
|
||||
SFX_UI.choiceReady();
|
||||
Haptic.confirm();
|
||||
this._startReminder();
|
||||
}
|
||||
|
||||
async _handleChoice(dir) {
|
||||
const choices = this._currentChoices;
|
||||
if (!choices) {
|
||||
SFX_UI.error();
|
||||
Haptic.error();
|
||||
return;
|
||||
}
|
||||
|
||||
const choice = msg.choices[dir];
|
||||
const choice = choices[dir];
|
||||
if (!choice) {
|
||||
SFX_UI.error();
|
||||
Haptic.error();
|
||||
@@ -268,8 +343,9 @@ class GameEngine {
|
||||
}
|
||||
|
||||
this._clearReminder();
|
||||
this._skipRequested = false;
|
||||
|
||||
// 播放方向对应的情感音效
|
||||
// 1. 播放方向对应的情感音效
|
||||
const sfxMap = {
|
||||
tap: 'tap',
|
||||
right: 'choiceWarm',
|
||||
@@ -280,13 +356,63 @@ class GameEngine {
|
||||
if (sfxMap[dir]) SFX_UI[sfxMap[dir]]();
|
||||
Haptic.select();
|
||||
|
||||
// 2. 应用状态和画像
|
||||
if (!choice.isSilence) {
|
||||
this.msgState[msg.id] = 'replied';
|
||||
this.msgState[this.currentMsg.id] = 'replied';
|
||||
}
|
||||
|
||||
if (choice.state) this._applyState(choice.state);
|
||||
if (choice.profile) this.profile.add(choice.profile);
|
||||
|
||||
// 3. 林夏回应
|
||||
this.state = 'responding';
|
||||
|
||||
if (choice.isSilence) {
|
||||
// 沉默:短暂停顿
|
||||
await sleep(1500);
|
||||
} else if (choice.linxia) {
|
||||
// 打字 → 发送 → 林夏语音
|
||||
await this._playTypingSend();
|
||||
if (!this._skipRequested) {
|
||||
await this._playVoiceAsync([choice.linxia]);
|
||||
}
|
||||
}
|
||||
|
||||
if (this._skipRequested) {
|
||||
// 跳过了林夏回应 → 如有 followUp 进入选择,否则跳到下一条
|
||||
if (choice.followUp?.choices) {
|
||||
this._enterChoosing(choice.followUp.choices);
|
||||
return;
|
||||
}
|
||||
this._proceedToNext();
|
||||
return;
|
||||
}
|
||||
|
||||
// 4. NPC 反应
|
||||
if (choice.npcReact?.length > 0) {
|
||||
this.state = 'reacting';
|
||||
await sleep(400);
|
||||
if (!this._skipRequested) {
|
||||
await this._playVoiceAsync(choice.npcReact);
|
||||
}
|
||||
}
|
||||
|
||||
if (this._skipRequested) {
|
||||
if (choice.followUp?.choices) {
|
||||
this._enterChoosing(choice.followUp.choices);
|
||||
return;
|
||||
}
|
||||
this._proceedToNext();
|
||||
return;
|
||||
}
|
||||
|
||||
// 5. 如有后续对话 → 再次进入选择
|
||||
if (choice.followUp?.choices) {
|
||||
await sleep(300);
|
||||
this._enterChoosing(choice.followUp.choices);
|
||||
return;
|
||||
}
|
||||
|
||||
// 6. 推进到下一条
|
||||
this._proceedToNext();
|
||||
}
|
||||
|
||||
@@ -305,6 +431,7 @@ class GameEngine {
|
||||
async _proceedToNext() {
|
||||
const prev = this.currentMsg;
|
||||
this.currentMsg = null;
|
||||
this._currentChoices = null;
|
||||
this.state = 'idle';
|
||||
this._clearReminder();
|
||||
|
||||
@@ -318,7 +445,7 @@ class GameEngine {
|
||||
await sleep(3000);
|
||||
}
|
||||
|
||||
// 检查结局D:未读过多(14条消息处理后检查)
|
||||
// 检查结局D:未读过多
|
||||
const triggered = MESSAGES.length - this._queue.length;
|
||||
if (this.vars.UNREAD >= 8 && triggered >= 14) {
|
||||
this._triggerEnding('D');
|
||||
@@ -332,7 +459,7 @@ class GameEngine {
|
||||
}
|
||||
|
||||
// ══════════════════════════════════════════
|
||||
// 提醒定时器(玩家不操作时重复提示音)
|
||||
// 提醒定时器
|
||||
// ══════════════════════════════════════════
|
||||
|
||||
_startReminder() {
|
||||
@@ -379,23 +506,26 @@ class GameEngine {
|
||||
|
||||
_onTap() {
|
||||
const s = this.state;
|
||||
if (s === 'ringing') this._answerCall(this.currentMsg);
|
||||
else if (s === 'notification') {
|
||||
if (s === 'ringing') {
|
||||
this._answerCall(this.currentMsg);
|
||||
} else if (s === 'notification') {
|
||||
SFX_UI.tap();
|
||||
Haptic.confirm();
|
||||
this._playMessage(this.currentMsg);
|
||||
} else if (s === 'choosing') {
|
||||
this._handleChoice('tap');
|
||||
}
|
||||
else if (s === 'choosing') this._choose('tap');
|
||||
}
|
||||
|
||||
_onDoubleTap() {
|
||||
const s = this.state;
|
||||
|
||||
if (s === 'ringing') {
|
||||
// 双击来电 = 拒接
|
||||
this._rejectCall(this.currentMsg);
|
||||
return;
|
||||
}
|
||||
else if (s === 'notification') {
|
||||
// 跳过消息
|
||||
|
||||
if (s === 'notification') {
|
||||
this._clearReminder();
|
||||
SFX_UI.skip();
|
||||
Haptic.confirm();
|
||||
@@ -403,28 +533,36 @@ class GameEngine {
|
||||
if (msg?.profileOnSkip) this.profile.add(msg.profileOnSkip);
|
||||
else this.profile.add({ avoidance: 1 });
|
||||
this._proceedToNext();
|
||||
return;
|
||||
}
|
||||
else if (s === 'playing') {
|
||||
// 跳过当前播放
|
||||
Snd.stopVoice();
|
||||
TTS.stop();
|
||||
|
||||
if (s === 'playing') {
|
||||
this._skipRequested = true;
|
||||
this._interruptVoice();
|
||||
SFX_UI.skip();
|
||||
Haptic.confirm();
|
||||
const msg = this.currentMsg;
|
||||
// 直接进入后续流程
|
||||
if (msg?.isEnding) {
|
||||
this.triggerFinalEnding();
|
||||
} else if (msg?.choices) {
|
||||
this.state = 'choosing';
|
||||
SFX_UI.choiceReady();
|
||||
Haptic.confirm();
|
||||
this._startReminder();
|
||||
this._enterChoosing(msg.choices);
|
||||
} else {
|
||||
this._proceedToNext();
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (s === 'choosing') {
|
||||
|
||||
if (s === 'responding' || s === 'reacting') {
|
||||
this._skipRequested = true;
|
||||
this._interruptVoice();
|
||||
SFX_UI.skip();
|
||||
Haptic.confirm();
|
||||
return;
|
||||
}
|
||||
|
||||
if (s === 'choosing') {
|
||||
this._skipChoice();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -439,7 +577,6 @@ class GameEngine {
|
||||
|
||||
if (s === 'notification') {
|
||||
if (dir === 'left') {
|
||||
// 左滑忽略消息
|
||||
this._clearReminder();
|
||||
SFX_UI.skip();
|
||||
Haptic.confirm();
|
||||
@@ -450,7 +587,7 @@ class GameEngine {
|
||||
}
|
||||
|
||||
if (s === 'choosing') {
|
||||
this._choose(dir);
|
||||
this._handleChoice(dir);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -497,9 +634,8 @@ class GameEngine {
|
||||
|
||||
this.state = 'ending';
|
||||
this._clearReminder();
|
||||
Snd.stopVoice();
|
||||
this._interruptVoice();
|
||||
Snd.stopRingtone();
|
||||
TTS.stop();
|
||||
Snd.stopBGM(3000);
|
||||
await sleep(2000);
|
||||
|
||||
@@ -515,7 +651,6 @@ class GameEngine {
|
||||
if (fn) await fn();
|
||||
}
|
||||
|
||||
// ── 结局A:明天再说 ──
|
||||
async _endingA() {
|
||||
Snd.startAmbience(`${AMB}/amb_kitchen_morning_v1.mp3`, { vol: 0.3 });
|
||||
await sleep(2000);
|
||||
@@ -525,7 +660,6 @@ class GameEngine {
|
||||
this._showCaption('明天再说。');
|
||||
}
|
||||
|
||||
// ── 结局B:寄出 ──
|
||||
async _endingB() {
|
||||
await sleep(2000);
|
||||
SFX_UI.ending();
|
||||
@@ -533,7 +667,6 @@ class GameEngine {
|
||||
this._showCaption('寄出。');
|
||||
}
|
||||
|
||||
// ── 结局C:今晚就这样 ──
|
||||
async _endingC() {
|
||||
await sleep(3000);
|
||||
SFX_UI.ending();
|
||||
@@ -541,7 +674,6 @@ class GameEngine {
|
||||
this._showCaption('今晚就这样。');
|
||||
}
|
||||
|
||||
// ── 结局D:早上好 ──
|
||||
async _endingD() {
|
||||
Haptic.system();
|
||||
await sleep(2000);
|
||||
@@ -552,7 +684,6 @@ class GameEngine {
|
||||
this._showCaption('早上好。');
|
||||
}
|
||||
|
||||
// ── 结局E(隐藏):好 ──
|
||||
async _endingE() {
|
||||
Haptic.message();
|
||||
SFX_UI.notify();
|
||||
|
||||
+448
-77
@@ -1,33 +1,48 @@
|
||||
// story.js — 消息数据(玩家驱动,无时间依赖)
|
||||
// story.js — 消息数据 v2(多轮对话 + 林夏语音 + NPC反应)
|
||||
//
|
||||
// 选择方向的情感含义(全局一致):
|
||||
// 单击 → 简单回应("嗯")
|
||||
// 双击 → 不回复 / 跳过
|
||||
// 右滑 → 温暖 / 接受 / 开放
|
||||
// 左滑 → 冷淡 / 拒绝 / 疏远
|
||||
// 上滑 → 好奇 / 主动 / 追问
|
||||
// 下滑 → 沉默 / 退缩
|
||||
// 单击(tap) → 简单回应
|
||||
// 双击 → 不回复 / 跳过
|
||||
// 右滑(right) → 温暖 / 接受 / 开放
|
||||
// 左滑(left) → 冷淡 / 拒绝 / 疏远
|
||||
// 上滑(up) → 好奇 / 主动 / 追问
|
||||
// 下滑(down) → 沉默 / 退缩
|
||||
//
|
||||
// 每个 choice 结构:
|
||||
// linxia: 林夏回应的音频路径(null/缺省 = 沉默)
|
||||
// npcReact: NPC反应音频数组(缺省 = 无反应)
|
||||
// isSilence: 沉默选项标记
|
||||
// state: 剧情状态变更
|
||||
// profile: 画像分数变更
|
||||
// followUp: 可选的下一轮对话 { choices: { ... } }
|
||||
|
||||
const A = '../audio/mp3';
|
||||
const TDIR = `${A}/tts`;
|
||||
const MUS = `${A}/music`;
|
||||
const SFX = `${A}/sfx`;
|
||||
const AMB = `${A}/ambience`;
|
||||
const A = '../audio/mp3';
|
||||
const TDIR = `${A}/tts`;
|
||||
const LINXIA = `${A}/linxia`;
|
||||
const REACT = `${A}/react`;
|
||||
const MUS = `${A}/music`;
|
||||
const SFX = `${A}/sfx`;
|
||||
const AMB = `${A}/ambience`;
|
||||
|
||||
const MESSAGES = [
|
||||
|
||||
// ── 01 · 妈妈 · 电话 ──
|
||||
// ══════════════════════════════════════════
|
||||
// 01 · 妈妈 · 电话(教学:接/拒电话)
|
||||
// ══════════════════════════════════════════
|
||||
{
|
||||
id: 1, type: 'call',
|
||||
sender: 'mom', senderName: '妈妈',
|
||||
ringtone: `${MUS}/lv11_ring_mom_v1.mp3`,
|
||||
audio: [`${TDIR}/lv11_2103_mom_call_01_wav_v1.mp3`],
|
||||
autoReply: `${LINXIA}/msg01_auto.mp3`,
|
||||
stateOnAnswer: { MOM_LINK: true },
|
||||
profileOnMiss: { avoidance: 2 },
|
||||
profileOnAnswer: { engagement: 1 },
|
||||
},
|
||||
|
||||
// ── 02 · 小美 · 微信语音×3 ──
|
||||
// ══════════════════════════════════════════
|
||||
// 02 · 小美 · 微信语音 ×3(教学:选择系统)
|
||||
// ══════════════════════════════════════════
|
||||
{
|
||||
id: 2, type: 'wechat_voice',
|
||||
sender: 'xiaomei', senderName: '小美',
|
||||
@@ -37,67 +52,190 @@ const MESSAGES = [
|
||||
`${TDIR}/lv11_2115_xiaomei_voice_03_wav_v1.mp3`,
|
||||
],
|
||||
choices: {
|
||||
tap: { label: '好啊。', profile: { engagement: 1 } },
|
||||
right: { label: '好啊,明天不见不散。', profile: { engagement: 2 } },
|
||||
up: { label: '我不太想出门……', profile: { nostalgia: 1 } },
|
||||
left: { label: '你先去,我再说。', profile: { avoidance: 1 } },
|
||||
down: { label: '(沉默)', isSilence: true, profile: { avoidance: 2 } },
|
||||
right: {
|
||||
linxia: `${LINXIA}/msg02_warm.mp3`,
|
||||
npcReact: [`${REACT}/msg02_react_warm.mp3`],
|
||||
profile: { engagement: 2 },
|
||||
},
|
||||
left: {
|
||||
linxia: `${LINXIA}/msg02_cold.mp3`,
|
||||
npcReact: [`${REACT}/msg02_react_cold.mp3`],
|
||||
profile: { avoidance: 1 },
|
||||
},
|
||||
up: {
|
||||
linxia: `${LINXIA}/msg02_curious.mp3`,
|
||||
npcReact: [`${REACT}/msg02_react_curious.mp3`],
|
||||
profile: { engagement: 1 },
|
||||
followUp: {
|
||||
choices: {
|
||||
right: {
|
||||
linxia: `${LINXIA}/msg02_r3_curious.mp3`,
|
||||
npcReact: [`${REACT}/msg02_r3_curious.mp3`],
|
||||
profile: { nostalgia: 1 },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
down: {
|
||||
isSilence: true,
|
||||
npcReact: [`${REACT}/msg02_react_silent.mp3`],
|
||||
profile: { avoidance: 2 },
|
||||
},
|
||||
tap: {
|
||||
linxia: `${LINXIA}/generic_hmm.mp3`,
|
||||
npcReact: [`${REACT}/msg02_react_tap.mp3`],
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// ── 03 · 外卖小哥 · 电话 ──
|
||||
// ══════════════════════════════════════════
|
||||
// 03 · 外卖小哥 · 电话(日常感)
|
||||
// ══════════════════════════════════════════
|
||||
{
|
||||
id: 3, type: 'call',
|
||||
sender: 'delivery', senderName: '外卖小哥',
|
||||
ringtone: `${MUS}/lv11_ring_delivery_v1.mp3`,
|
||||
audio: [`${TDIR}/lv11_2120_delivery_call_01_wav_v1.mp3`],
|
||||
autoReply: `${LINXIA}/msg03_auto.mp3`,
|
||||
profileOnMiss: { avoidance: 1 },
|
||||
profileOnAnswer: { engagement: 1 },
|
||||
},
|
||||
|
||||
// ── 04 · 阿哲 · 微信语音 ──
|
||||
// ══════════════════════════════════════════
|
||||
// 04 · 阿哲 · 微信语音(前男友要东西)
|
||||
// ══════════════════════════════════════════
|
||||
{
|
||||
id: 4, type: 'wechat_voice',
|
||||
sender: 'azhe', senderName: '阿哲',
|
||||
audio: [`${TDIR}/lv11_2130_azhe_voice_01_wav_v1.mp3`],
|
||||
choices: {
|
||||
tap: { label: '好,明天寄。', state: { HE_BACK: false }, profile: { engagement: 1 } },
|
||||
right: { label: '你那边……都好吗。', profile: { engagement: 2 } },
|
||||
up: { label: '你怎么不自己来拿。', profile: { engagement: 2 } },
|
||||
left: { label: '(不想理)', profile: { avoidance: 1 } },
|
||||
down: { label: '(什么都不说)', isSilence: true, state: { HE_BACK: null }, profile: { avoidance: 2 } },
|
||||
right: {
|
||||
linxia: `${LINXIA}/msg04_warm.mp3`,
|
||||
npcReact: [`${REACT}/msg04_react_warm.mp3`],
|
||||
profile: { engagement: 2 },
|
||||
followUp: {
|
||||
choices: {
|
||||
right: {
|
||||
linxia: `${LINXIA}/msg04_r3w_warm.mp3`,
|
||||
npcReact: [`${REACT}/msg04_r3w_sorry.mp3`],
|
||||
},
|
||||
left: {
|
||||
linxia: `${LINXIA}/msg04_r3w_cold.mp3`,
|
||||
npcReact: [`${REACT}/msg04_r3w_good.mp3`],
|
||||
},
|
||||
down: {
|
||||
isSilence: true,
|
||||
npcReact: [`${REACT}/msg04_r3w_night.mp3`],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
left: {
|
||||
linxia: `${LINXIA}/msg04_cold.mp3`,
|
||||
npcReact: [`${REACT}/msg04_react_cold.mp3`],
|
||||
state: { HE_BACK: false },
|
||||
profile: { avoidance: 1 },
|
||||
},
|
||||
up: {
|
||||
linxia: `${LINXIA}/msg04_curious.mp3`,
|
||||
npcReact: [`${REACT}/msg04_react_curious.mp3`],
|
||||
profile: { engagement: 2 },
|
||||
followUp: {
|
||||
choices: {
|
||||
up: {
|
||||
linxia: `${LINXIA}/msg04_r3c_curious.mp3`,
|
||||
npcReact: [`${REACT}/msg04_r3c_nevermind.mp3`],
|
||||
state: { HE_BACK: false },
|
||||
},
|
||||
right: {
|
||||
linxia: `${LINXIA}/msg04_r3c_warm.mp3`,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
down: {
|
||||
isSilence: true,
|
||||
npcReact: [`${REACT}/msg04_react_silent.mp3`],
|
||||
state: { HE_BACK: null },
|
||||
profile: { avoidance: 2 },
|
||||
},
|
||||
tap: {
|
||||
linxia: `${LINXIA}/generic_ok.mp3`,
|
||||
npcReact: [`${REACT}/msg04_react_tap.mp3`],
|
||||
state: { HE_BACK: false },
|
||||
profile: { engagement: 1 },
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// ── 05 · HR王姐 · 微信语音 ──
|
||||
// ══════════════════════════════════════════
|
||||
// 05 · HR王姐 · 微信语音
|
||||
// ══════════════════════════════════════════
|
||||
{
|
||||
id: 5, type: 'wechat_voice',
|
||||
sender: 'hr', senderName: 'HR王姐',
|
||||
audio: [`${TDIR}/lv11_2145_hr_voice_01_wav_v1.mp3`],
|
||||
choices: {
|
||||
tap: { label: '好的,我知道了。', profile: { engagement: 1 } },
|
||||
right: { label: '谢谢王姐。', profile: { engagement: 1 } },
|
||||
up: { label: '王姐,有什么建议吗?', profile: { engagement: 2 } },
|
||||
left: { label: '……谢谢你。', profile: { nostalgia: 1 } },
|
||||
down: { label: '(不回复)', isSilence: true, profile: { avoidance: 1 } },
|
||||
right: {
|
||||
linxia: `${LINXIA}/msg05_warm.mp3`,
|
||||
npcReact: [`${REACT}/msg05_react_warm.mp3`],
|
||||
profile: { engagement: 1 },
|
||||
},
|
||||
left: {
|
||||
linxia: `${LINXIA}/msg05_cold.mp3`,
|
||||
},
|
||||
up: {
|
||||
linxia: `${LINXIA}/msg05_curious.mp3`,
|
||||
npcReact: [`${REACT}/msg05_react_curious.mp3`],
|
||||
profile: { engagement: 2 },
|
||||
},
|
||||
down: {
|
||||
isSilence: true,
|
||||
profile: { avoidance: 1 },
|
||||
},
|
||||
tap: {
|
||||
linxia: `${LINXIA}/generic_ok.mp3`,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// ── 06 · 安安 · 微信语音 ──
|
||||
// ══════════════════════════════════════════
|
||||
// 06 · 安安 · 微信语音(酒吧邀约)
|
||||
// ══════════════════════════════════════════
|
||||
{
|
||||
id: 6, type: 'wechat_voice',
|
||||
sender: 'anan', senderName: '安安',
|
||||
audio: [`${TDIR}/lv11_2200_anan_voice_01_wav_v1.mp3`],
|
||||
choices: {
|
||||
tap: { label: '不了,你们玩好~', profile: {} },
|
||||
right: { label: '在哪儿啊?我……看看吧。', profile: { engagement: 1 } },
|
||||
up: { label: '你喝了多少了哈哈。', profile: { engagement: 1 } },
|
||||
left: { label: '我今晚不方便。', profile: { avoidance: 1 } },
|
||||
down: { label: '(不回复)', isSilence: true, profile: { avoidance: 2 } },
|
||||
right: {
|
||||
linxia: `${LINXIA}/msg06_warm.mp3`,
|
||||
npcReact: [`${REACT}/msg06_react_warm.mp3`],
|
||||
profile: { engagement: 2 },
|
||||
},
|
||||
left: {
|
||||
linxia: `${LINXIA}/msg06_cold.mp3`,
|
||||
npcReact: [`${REACT}/msg06_react_cold.mp3`],
|
||||
},
|
||||
up: {
|
||||
linxia: `${LINXIA}/msg06_curious.mp3`,
|
||||
npcReact: [`${REACT}/msg06_react_curious.mp3`],
|
||||
profile: { engagement: 1 },
|
||||
},
|
||||
down: {
|
||||
isSilence: true,
|
||||
npcReact: [`${REACT}/msg06_react_silent.mp3`],
|
||||
profile: { avoidance: 1 },
|
||||
},
|
||||
tap: {
|
||||
linxia: `${LINXIA}/generic_hmm.mp3`,
|
||||
npcReact: [`${REACT}/msg06_react_tap.mp3`],
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// ── 07 · 大学寝室群 · 5条语音 ──
|
||||
// ══════════════════════════════════════════
|
||||
// 07 · 大学寝室群 · 5条语音
|
||||
// ══════════════════════════════════════════
|
||||
{
|
||||
id: 7, type: 'wechat_voice',
|
||||
sender: 'dorm', senderName: '寝室群',
|
||||
@@ -109,15 +247,49 @@ const MESSAGES = [
|
||||
`${TDIR}/lv11_2215_dorm_c_voice_01_wav_v1.mp3`,
|
||||
],
|
||||
choices: {
|
||||
tap: { label: '恭喜!', state: { GROUP_REPLY: true }, profile: { engagement: 1 } },
|
||||
right: { label: '哇,快讲讲!', state: { GROUP_REPLY: true }, profile: { engagement: 2 } },
|
||||
up: { label: '最近有点忙,你们聊~', profile: { avoidance: 1 } },
|
||||
left: { label: '(不想参与)', profile: { avoidance: 1 } },
|
||||
down: { label: '(沉默)', isSilence: true, profile: { avoidance: 2 } },
|
||||
right: {
|
||||
linxia: `${LINXIA}/msg07_warm.mp3`,
|
||||
npcReact: [`${REACT}/msg07_react_warm.mp3`],
|
||||
state: { GROUP_REPLY: true },
|
||||
profile: { engagement: 2 },
|
||||
followUp: {
|
||||
choices: {
|
||||
right: {
|
||||
linxia: `${LINXIA}/msg07_r3_warm.mp3`,
|
||||
profile: { engagement: 1 },
|
||||
},
|
||||
left: {
|
||||
linxia: `${LINXIA}/msg07_r3_cold.mp3`,
|
||||
npcReact: [`${REACT}/msg07_r3_cold.mp3`],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
left: {
|
||||
linxia: `${LINXIA}/msg07_cold.mp3`,
|
||||
profile: { avoidance: 1 },
|
||||
},
|
||||
up: {
|
||||
linxia: `${LINXIA}/msg07_curious.mp3`,
|
||||
npcReact: [`${REACT}/msg07_react_curious.mp3`],
|
||||
state: { GROUP_REPLY: true },
|
||||
profile: { engagement: 2 },
|
||||
},
|
||||
down: {
|
||||
isSilence: true,
|
||||
profile: { avoidance: 2 },
|
||||
},
|
||||
tap: {
|
||||
linxia: `${LINXIA}/generic_hmm.mp3`,
|
||||
npcReact: [`${REACT}/msg07_react_tap.mp3`],
|
||||
state: { GROUP_REPLY: true },
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// ── 08 · 未知号码 · 电话(悬疑)──
|
||||
// ══════════════════════════════════════════
|
||||
// 08 · 未知号码 · 电话(悬疑钩子)
|
||||
// ══════════════════════════════════════════
|
||||
{
|
||||
id: 8, type: 'call',
|
||||
sender: 'unknown', senderName: '未知号码',
|
||||
@@ -129,7 +301,9 @@ const MESSAGES = [
|
||||
profileOnAnswer: { nostalgia: 1 },
|
||||
},
|
||||
|
||||
// ── 09 · 小美(醉)· 4段语音 ──
|
||||
// ══════════════════════════════════════════
|
||||
// 09 · 小美(醉)· 4段语音(秘密揭露)
|
||||
// ══════════════════════════════════════════
|
||||
{
|
||||
id: 9, type: 'wechat_voice',
|
||||
sender: 'xiaomei', senderName: '小美',
|
||||
@@ -141,29 +315,114 @@ const MESSAGES = [
|
||||
],
|
||||
bgm: `${MUS}/lv11_bgm_m2_suspense_v1.mp3`,
|
||||
choices: {
|
||||
tap: { label: '我知道了。', profile: { avoidance: 1 } },
|
||||
right: { label: '小美,你还好吗。', profile: { engagement: 2 } },
|
||||
up: { label: '你……为什么现在才说。', profile: { engagement: 2 } },
|
||||
left: { label: '(不想理她)', profile: { avoidance: 1 } },
|
||||
down: { label: '(什么都不说)', isSilence: true, profile: { avoidance: 2, nostalgia: 1 } },
|
||||
right: {
|
||||
linxia: `${LINXIA}/msg09_warm.mp3`,
|
||||
npcReact: [`${REACT}/msg09_react_warm.mp3`],
|
||||
profile: { engagement: 2 },
|
||||
},
|
||||
left: {
|
||||
linxia: `${LINXIA}/msg09_cold.mp3`,
|
||||
profile: { avoidance: 1 },
|
||||
},
|
||||
up: {
|
||||
linxia: `${LINXIA}/msg09_curious.mp3`,
|
||||
npcReact: [`${REACT}/msg09_react_curious.mp3`],
|
||||
profile: { engagement: 2 },
|
||||
followUp: {
|
||||
choices: {
|
||||
right: {
|
||||
linxia: `${LINXIA}/msg09_r3_warm.mp3`,
|
||||
npcReact: [`${REACT}/msg09_r3_warm.mp3`],
|
||||
},
|
||||
left: {
|
||||
linxia: `${LINXIA}/msg09_r3_cold.mp3`,
|
||||
npcReact: [`${REACT}/msg09_r3_cold.mp3`],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
down: {
|
||||
isSilence: true,
|
||||
profile: { avoidance: 2, nostalgia: 1 },
|
||||
},
|
||||
tap: {
|
||||
linxia: `${LINXIA}/generic_hmm.mp3`,
|
||||
npcReact: [`${REACT}/msg09_react_tap.mp3`],
|
||||
profile: { nostalgia: 1 },
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// ── 10 · 妈妈 · 文字消息 ──
|
||||
// ══════════════════════════════════════════
|
||||
// 10 · 妈妈 · 文字消息(多层嵌套对话)
|
||||
// ══════════════════════════════════════════
|
||||
{
|
||||
id: 10, type: 'wechat_text',
|
||||
sender: 'mom', senderName: '妈妈',
|
||||
text: '睡了吗?',
|
||||
choices: {
|
||||
tap: { label: '嗯。', state: { MOM_LINK: true } },
|
||||
right: { label: '没有,怎么了。', state: { MOM_LINK: true }, profile: { engagement: 1 } },
|
||||
up: { label: '妈,我想打电话。', state: { MOM_LINK: true }, profile: { engagement: 2 } },
|
||||
left: { label: '嗯,要睡了。', state: { MOM_LINK: true }, profile: { avoidance: 1 } },
|
||||
down: { label: '(不回复)', isSilence: true, profile: { avoidance: 2 } },
|
||||
right: {
|
||||
linxia: `${LINXIA}/msg10_warm.mp3`,
|
||||
npcReact: [`${REACT}/msg10_react_warm.mp3`],
|
||||
state: { MOM_LINK: true },
|
||||
profile: { engagement: 2 },
|
||||
followUp: {
|
||||
choices: {
|
||||
right: {
|
||||
linxia: `${LINXIA}/msg10_rw_warm.mp3`,
|
||||
npcReact: [`${REACT}/msg10_rw_warm.mp3`],
|
||||
},
|
||||
up: {
|
||||
linxia: `${LINXIA}/msg10_rw_curious.mp3`,
|
||||
npcReact: [`${REACT}/msg10_rw_curious.mp3`],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
left: {
|
||||
linxia: `${LINXIA}/msg10_cold.mp3`,
|
||||
npcReact: [`${REACT}/msg10_react_cold.mp3`],
|
||||
state: { MOM_LINK: true },
|
||||
profile: { avoidance: 1 },
|
||||
},
|
||||
up: {
|
||||
linxia: `${LINXIA}/msg10_curious.mp3`,
|
||||
npcReact: [`${REACT}/msg10_react_curious.mp3`],
|
||||
state: { MOM_LINK: true },
|
||||
profile: { engagement: 3 },
|
||||
followUp: {
|
||||
choices: {
|
||||
right: {
|
||||
linxia: `${LINXIA}/msg10_call_warm.mp3`,
|
||||
npcReact: [`${REACT}/msg10_call_warm.mp3`],
|
||||
},
|
||||
up: {
|
||||
linxia: `${LINXIA}/msg10_call_curious.mp3`,
|
||||
npcReact: [`${REACT}/msg10_call_curious.mp3`],
|
||||
},
|
||||
down: {
|
||||
isSilence: true,
|
||||
npcReact: [`${REACT}/msg10_call_silent.mp3`],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
down: {
|
||||
isSilence: true,
|
||||
npcReact: [`${REACT}/msg10_react_silent.mp3`],
|
||||
profile: { avoidance: 2 },
|
||||
},
|
||||
tap: {
|
||||
linxia: `${LINXIA}/generic_hmm.mp3`,
|
||||
npcReact: [`${REACT}/msg10_react_tap.mp3`],
|
||||
state: { MOM_LINK: true },
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// ── 11 · 阿哲 · 电话(关键分支)──
|
||||
// ══════════════════════════════════════════
|
||||
// 11 · 阿哲 · 电话(关键分支:来不来)
|
||||
// ══════════════════════════════════════════
|
||||
{
|
||||
id: 11, type: 'call',
|
||||
sender: 'azhe', senderName: '阿哲',
|
||||
@@ -172,28 +431,88 @@ const MESSAGES = [
|
||||
profileOnMiss: { avoidance: 2 },
|
||||
profileOnAnswer: { engagement: 1 },
|
||||
choices: {
|
||||
tap: { label: '不方便,明天吧。', state: { HE_BACK: false } },
|
||||
right: { label: '可以,但只有5分钟。', state: { HE_BACK: true } },
|
||||
left: { label: '(挂断)', state: { HE_BACK: false } },
|
||||
down: { label: '(沉默挂断)', isSilence: true, state: { HE_BACK: false } },
|
||||
right: {
|
||||
linxia: `${LINXIA}/msg11_warm.mp3`,
|
||||
npcReact: [`${REACT}/msg11_react_warm.mp3`],
|
||||
state: { HE_BACK: true },
|
||||
},
|
||||
left: {
|
||||
linxia: `${LINXIA}/msg11_cold.mp3`,
|
||||
npcReact: [`${REACT}/msg11_react_cold.mp3`],
|
||||
state: { HE_BACK: false },
|
||||
},
|
||||
up: {
|
||||
linxia: `${LINXIA}/msg11_curious.mp3`,
|
||||
npcReact: [`${REACT}/msg11_react_curious.mp3`],
|
||||
followUp: {
|
||||
choices: {
|
||||
right: {
|
||||
linxia: `${LINXIA}/msg11_warm.mp3`,
|
||||
npcReact: [`${REACT}/msg11_react_warm.mp3`],
|
||||
state: { HE_BACK: true },
|
||||
},
|
||||
left: {
|
||||
linxia: `${LINXIA}/msg11_cold.mp3`,
|
||||
npcReact: [`${REACT}/msg11_react_cold.mp3`],
|
||||
state: { HE_BACK: false },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
down: {
|
||||
isSilence: true,
|
||||
state: { HE_BACK: false },
|
||||
},
|
||||
tap: {
|
||||
linxia: `${LINXIA}/msg11_tap.mp3`,
|
||||
npcReact: [`${REACT}/msg11_react_tap.mp3`],
|
||||
state: { HE_BACK: false },
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// ── 12 · 周南 · 微信语音 ──
|
||||
// ══════════════════════════════════════════
|
||||
// 12 · 周南 · 微信语音(老同学)
|
||||
// ══════════════════════════════════════════
|
||||
{
|
||||
id: 12, type: 'wechat_voice',
|
||||
sender: 'zhounan', senderName: '周南',
|
||||
audio: [`${TDIR}/lv11_2330_zhounan_voice_01_wav_v1.mp3`],
|
||||
choices: {
|
||||
tap: { label: '嗯……你好。', state: { ZHOUNAN_DEPTH: 1 }, profile: { nostalgia: 1 } },
|
||||
right: { label: '周南!你还记得我啊!', state: { ZHOUNAN_DEPTH: 1 }, profile: { engagement: 2, nostalgia: 1 } },
|
||||
up: { label: '你是……初三那个……?', state: { ZHOUNAN_DEPTH: 1 }, profile: { nostalgia: 2 } },
|
||||
left: { label: '(冷淡)', profile: { avoidance: 1 } },
|
||||
down: { label: '(不回复)', isSilence: true },
|
||||
right: {
|
||||
linxia: `${LINXIA}/msg12_warm.mp3`,
|
||||
npcReact: [`${REACT}/msg12_react_warm.mp3`],
|
||||
state: { ZHOUNAN_DEPTH: 1 },
|
||||
profile: { engagement: 2, nostalgia: 1 },
|
||||
},
|
||||
left: {
|
||||
linxia: `${LINXIA}/msg12_cold.mp3`,
|
||||
npcReact: [`${REACT}/msg12_react_cold.mp3`],
|
||||
state: { ZHOUNAN_DEPTH: 1 },
|
||||
profile: { nostalgia: 1 },
|
||||
},
|
||||
up: {
|
||||
linxia: `${LINXIA}/msg12_curious.mp3`,
|
||||
npcReact: [`${REACT}/msg12_react_curious.mp3`],
|
||||
state: { ZHOUNAN_DEPTH: 1 },
|
||||
profile: { nostalgia: 2 },
|
||||
},
|
||||
down: {
|
||||
isSilence: true,
|
||||
npcReact: [`${REACT}/msg12_react_silent.mp3`],
|
||||
profile: { nostalgia: 1 },
|
||||
},
|
||||
tap: {
|
||||
linxia: `${LINXIA}/msg12_tap.mp3`,
|
||||
npcReact: [`${REACT}/msg12_react_tap.mp3`],
|
||||
state: { ZHOUNAN_DEPTH: 1 },
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// ── 13 · 周南 · 4条长语音 ──
|
||||
// ══════════════════════════════════════════
|
||||
// 13 · 周南 · 4条长语音(他的十年)
|
||||
// ══════════════════════════════════════════
|
||||
{
|
||||
id: 13, type: 'wechat_voice',
|
||||
sender: 'zhounan', senderName: '周南',
|
||||
@@ -205,26 +524,76 @@ const MESSAGES = [
|
||||
],
|
||||
bgm: `${MUS}/lv11_bgm_m3_zhounan_v1.mp3`,
|
||||
choices: {
|
||||
tap: { label: '谢谢你告诉我。', state: { ZHOUNAN_DEPTH_ADD: 1 } },
|
||||
right: { label: '你在北京还好吗?', state: { ZHOUNAN_DEPTH_ADD: 1 }, profile: { engagement: 2 } },
|
||||
up: { label: '……生日快乐。', state: { ZHOUNAN_DEPTH_ADD: 1, ZHOUNAN_SHARE: true }, profile: { nostalgia: 2, engagement: 1 } },
|
||||
left: { label: '你讲了好多。', state: { ZHOUNAN_DEPTH_ADD: 1 }, profile: { engagement: 2, nostalgia: 1 } },
|
||||
down: { label: '(沉默)', isSilence: true, profile: { nostalgia: 1, avoidance: 1 } },
|
||||
right: {
|
||||
linxia: `${LINXIA}/msg13_warm.mp3`,
|
||||
npcReact: [`${REACT}/msg13_react_warm.mp3`],
|
||||
state: { ZHOUNAN_DEPTH_ADD: 1 },
|
||||
profile: { engagement: 2 },
|
||||
followUp: {
|
||||
choices: {
|
||||
right: {
|
||||
linxia: `${LINXIA}/msg13_r3_warm.mp3`,
|
||||
npcReact: [`${REACT}/msg13_r3_warm.mp3`],
|
||||
state: { ZHOUNAN_SHARE: true },
|
||||
},
|
||||
left: {
|
||||
linxia: `${LINXIA}/msg13_r3_cold.mp3`,
|
||||
npcReact: [`${REACT}/msg13_r3_cold.mp3`],
|
||||
},
|
||||
up: {
|
||||
linxia: `${LINXIA}/msg13_r3_curious.mp3`,
|
||||
npcReact: [`${REACT}/msg13_r3_curious.mp3`],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
left: {
|
||||
linxia: `${LINXIA}/msg13_cold.mp3`,
|
||||
npcReact: [`${REACT}/msg13_react_cold.mp3`],
|
||||
state: { ZHOUNAN_DEPTH_ADD: 1 },
|
||||
profile: { nostalgia: 1 },
|
||||
},
|
||||
up: {
|
||||
linxia: `${LINXIA}/msg13_curious.mp3`,
|
||||
npcReact: [`${REACT}/msg13_react_curious.mp3`],
|
||||
state: { ZHOUNAN_DEPTH_ADD: 1, ZHOUNAN_SHARE: true },
|
||||
profile: { nostalgia: 2, engagement: 1 },
|
||||
},
|
||||
down: {
|
||||
isSilence: true,
|
||||
npcReact: [`${REACT}/msg13_react_silent.mp3`],
|
||||
profile: { avoidance: 1 },
|
||||
},
|
||||
tap: {
|
||||
linxia: `${LINXIA}/msg13_tap.mp3`,
|
||||
npcReact: [`${REACT}/msg13_react_tap.mp3`],
|
||||
state: { ZHOUNAN_DEPTH_ADD: 1 },
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// ── 14 · 妈妈 · 第二次电话 ──
|
||||
// ══════════════════════════════════════════
|
||||
// 14 · 妈妈 · 第二次电话(自动回应 + 条件反应)
|
||||
// ══════════════════════════════════════════
|
||||
{
|
||||
id: 14, type: 'call',
|
||||
sender: 'mom', senderName: '妈妈',
|
||||
ringtone: `${MUS}/lv11_ring_mom_v1.mp3`,
|
||||
audio: [`${TDIR}/lv11_0015_mom_call_01_wav_v1.mp3`],
|
||||
autoReply: `${LINXIA}/msg14_auto.mp3`,
|
||||
autoReact: {
|
||||
condition: 'MOM_LINK',
|
||||
true: `${REACT}/msg14_react_linked.mp3`,
|
||||
false: `${REACT}/msg14_react_unlinked.mp3`,
|
||||
},
|
||||
stateOnAnswer: { MOM_LINK: true },
|
||||
profileOnMiss: { avoidance: 2 },
|
||||
profileOnAnswer: { engagement: 2 },
|
||||
},
|
||||
|
||||
// ── 15 · 时光胶囊 · 系统通知 ──
|
||||
// ══════════════════════════════════════════
|
||||
// 15 · 时光胶囊 · 系统通知
|
||||
// ══════════════════════════════════════════
|
||||
{
|
||||
id: 15, type: 'system_notification',
|
||||
sender: 'self', senderName: '时光胶囊',
|
||||
@@ -239,7 +608,9 @@ const MESSAGES = [
|
||||
profileOnSkip: { avoidance: 2 },
|
||||
},
|
||||
|
||||
// ── 16 · 妈妈 · 长语音(结局前奏)──
|
||||
// ══════════════════════════════════════════
|
||||
// 16 · 妈妈 · 长语音(结局前奏)
|
||||
// ══════════════════════════════════════════
|
||||
{
|
||||
id: 16, type: 'wechat_voice',
|
||||
sender: 'mom', senderName: '妈妈',
|
||||
|
||||
Reference in New Issue
Block a user