Add files via upload

This commit is contained in:
Cola-Echo
2025-12-30 15:08:26 +08:00
committed by GitHub
parent 49f3978d11
commit 713f2211d2
13 changed files with 773 additions and 119 deletions

View File

@@ -28,17 +28,41 @@ const TOY_ICONS = {
// 吮吸类玩具图标
gentle: `<svg viewBox="0 0 24 24" width="28" height="28"><circle cx="12" cy="12" r="8" stroke="currentColor" stroke-width="1.5" fill="none"/><circle cx="12" cy="12" r="4" stroke="currentColor" stroke-width="1.5" fill="none"/><circle cx="12" cy="12" r="1" fill="currentColor"/></svg>`,
strong: `<svg viewBox="0 0 24 24" width="28" height="28"><circle cx="12" cy="12" r="9" stroke="currentColor" stroke-width="2" fill="none"/><circle cx="12" cy="12" r="5" stroke="currentColor" stroke-width="2" fill="none"/><circle cx="12" cy="12" r="2" fill="currentColor"/></svg>`,
pulse: `<svg viewBox="0 0 24 24" width="28" height="28"><circle cx="6" cy="12" r="3" stroke="currentColor" stroke-width="1.5" fill="none"/><circle cx="12" cy="12" r="3" stroke="currentColor" stroke-width="1.5" fill="currentColor"/><circle cx="18" cy="12" r="3" stroke="currentColor" stroke-width="1.5" fill="none"/></svg>`
pulse: `<svg viewBox="0 0 24 24" width="28" height="28"><circle cx="6" cy="12" r="3" stroke="currentColor" stroke-width="1.5" fill="none"/><circle cx="12" cy="12" r="3" stroke="currentColor" stroke-width="1.5" fill="currentColor"/><circle cx="18" cy="12" r="3" stroke="currentColor" stroke-width="1.5" fill="none"/></svg>`,
// 炮机专用图标
slow: `<svg viewBox="0 0 24 24" width="28" height="28"><path d="M5 12h14" stroke="currentColor" stroke-width="2" stroke-linecap="round"/><path d="M12 5l7 7-7 7" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"/></svg>`,
fast: `<svg viewBox="0 0 24 24" width="28" height="28"><path d="M3 12h18" stroke="currentColor" stroke-width="2" stroke-linecap="round"/><path d="M13 5l7 7-7 7" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"/><path d="M8 8l4 4-4 4" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"/></svg>`,
deep: `<svg viewBox="0 0 24 24" width="28" height="28"><path d="M12 4v16" stroke="currentColor" stroke-width="2" stroke-linecap="round"/><path d="M5 13l7 7 7-7" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"/></svg>`,
// 飞机杯专用图标
tighten: `<svg viewBox="0 0 24 24" width="28" height="28"><path d="M9 4v16M15 4v16" stroke="currentColor" stroke-width="2" stroke-linecap="round"/><path d="M4 12h4M16 12h4" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg>`,
suck: `<svg viewBox="0 0 24 24" width="28" height="28"><circle cx="12" cy="12" r="8" stroke="currentColor" stroke-width="1.5" fill="none"/><path d="M8 12h8M12 8v8" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>`,
combo: `<svg viewBox="0 0 24 24" width="28" height="28"><path d="M12 3v18M3 12h18" stroke="currentColor" stroke-width="2" stroke-linecap="round"/><circle cx="12" cy="12" r="4" stroke="currentColor" stroke-width="1.5" fill="none"/></svg>`
};
// 吮吸类玩具ID列表
const SUCTION_TOY_IDS = ['breastPump', 'clitSucker'];
// 炮机ID
const MACHINE_TOY_IDS = ['fuckingMachine'];
// 飞机杯ID
const CUP_TOY_IDS = ['masturbatorCup'];
// 判断是否是吮吸类玩具
function isSuctionToy(giftId) {
return SUCTION_TOY_IDS.includes(giftId);
}
// 判断是否是炮机
function isMachineToy(giftId) {
return MACHINE_TOY_IDS.includes(giftId);
}
// 判断是否是飞机杯
function isCupToy(giftId) {
return CUP_TOY_IDS.includes(giftId);
}
// 震动类控制模式定义
const TOY_CONTROL_MODES = {
classic: {
@@ -107,6 +131,74 @@ const SUCTION_CONTROL_MODES = {
}
};
// 炮机控制模式定义
const MACHINE_CONTROL_MODES = {
slow: {
id: 'slow',
name: '慢速抽插',
icon: TOY_ICONS.slow,
desc: '缓慢温柔的节奏'
},
start: {
id: 'start',
name: '开始运作',
icon: TOY_ICONS.start,
desc: '开始/继续运作'
},
fast: {
id: 'fast',
name: '快速冲刺',
icon: TOY_ICONS.fast,
desc: '高速猛烈的节奏'
},
deep: {
id: 'deep',
name: '深入模式',
icon: TOY_ICONS.deep,
desc: '深度刺激'
},
pause: {
id: 'pause',
name: '暂停',
icon: TOY_ICONS.pause,
desc: '暂停运作'
}
};
// 飞机杯控制模式定义
const CUP_CONTROL_MODES = {
tighten: {
id: 'tighten',
name: '收紧夹吸',
icon: TOY_ICONS.tighten,
desc: '收紧通道增加摩擦'
},
start: {
id: 'start',
name: '开始享受',
icon: TOY_ICONS.start,
desc: '开始/继续运作'
},
suck: {
id: 'suck',
name: '吮吸模式',
icon: TOY_ICONS.suck,
desc: '模拟吮吸感'
},
combo: {
id: 'combo',
name: '组合模式',
icon: TOY_ICONS.combo,
desc: '震动+吮吸组合'
},
pause: {
id: 'pause',
name: '暂停',
icon: TOY_ICONS.pause,
desc: '暂停运作'
}
};
// 电击按钮(仅微电流乳链)
const SHOCK_BUTTON = {
id: 'shock',
@@ -220,13 +312,32 @@ function renderToyControlPage() {
const messagesEl = document.getElementById('wechat-toy-control-messages');
if (titleEl) {
const targetText = toyControlState.target === 'character' ? 'TA在用' : '你在用';
let targetText;
if (toyControlState.target === 'character') {
targetText = 'TA在用';
} else if (toyControlState.target === 'user') {
targetText = '你在用';
} else {
targetText = '一起用';
}
titleEl.textContent = `${toyControlState.gift.giftName} · ${targetText}`;
}
// 判断当前玩具类型
const isSuction = isSuctionToy(toyControlState.gift.giftId);
const modes = isSuction ? SUCTION_CONTROL_MODES : TOY_CONTROL_MODES;
const isMachine = isMachineToy(toyControlState.gift.giftId);
const isCup = isCupToy(toyControlState.gift.giftId);
let modes;
if (isSuction) {
modes = SUCTION_CONTROL_MODES;
} else if (isMachine) {
modes = MACHINE_CONTROL_MODES;
} else if (isCup) {
modes = CUP_CONTROL_MODES;
} else {
modes = TOY_CONTROL_MODES;
}
// 渲染按钮
if (buttonsEl) {
@@ -265,6 +376,74 @@ function renderToyControlPage() {
</button>
</div>
`;
} else if (isMachine) {
// 炮机按钮布局
buttonsHtml = `
<div class="wechat-toy-btn-row">
<button class="wechat-toy-btn" data-mode="slow">
${modes.slow.icon}
<span class="wechat-toy-btn-label">${modes.slow.name}</span>
</button>
<button class="wechat-toy-btn" data-mode="start">
${modes.start.icon}
<span class="wechat-toy-btn-label">${modes.start.name}</span>
</button>
<button class="wechat-toy-btn" data-mode="fast">
${modes.fast.icon}
<span class="wechat-toy-btn-label">${modes.fast.name}</span>
</button>
</div>
<div class="wechat-toy-btn-row">
<button class="wechat-toy-btn wechat-toy-btn-media" data-media="mic" title="麦克风">
${toyControlState.micEnabled ? TOY_ICONS.micOn : TOY_ICONS.micOff}
</button>
<button class="wechat-toy-btn" data-mode="deep">
${modes.deep.icon}
<span class="wechat-toy-btn-label">${modes.deep.name}</span>
</button>
<button class="wechat-toy-btn" data-mode="pause">
${modes.pause.icon}
<span class="wechat-toy-btn-label">${modes.pause.name}</span>
</button>
<button class="wechat-toy-btn wechat-toy-btn-media" data-media="camera" title="摄像头">
${toyControlState.cameraEnabled ? TOY_ICONS.cameraOn : TOY_ICONS.cameraOff}
</button>
</div>
`;
} else if (isCup) {
// 飞机杯按钮布局
buttonsHtml = `
<div class="wechat-toy-btn-row">
<button class="wechat-toy-btn" data-mode="tighten">
${modes.tighten.icon}
<span class="wechat-toy-btn-label">${modes.tighten.name}</span>
</button>
<button class="wechat-toy-btn" data-mode="start">
${modes.start.icon}
<span class="wechat-toy-btn-label">${modes.start.name}</span>
</button>
<button class="wechat-toy-btn" data-mode="suck">
${modes.suck.icon}
<span class="wechat-toy-btn-label">${modes.suck.name}</span>
</button>
</div>
<div class="wechat-toy-btn-row">
<button class="wechat-toy-btn wechat-toy-btn-media" data-media="mic" title="麦克风">
${toyControlState.micEnabled ? TOY_ICONS.micOn : TOY_ICONS.micOff}
</button>
<button class="wechat-toy-btn" data-mode="combo">
${modes.combo.icon}
<span class="wechat-toy-btn-label">${modes.combo.name}</span>
</button>
<button class="wechat-toy-btn" data-mode="pause">
${modes.pause.icon}
<span class="wechat-toy-btn-label">${modes.pause.name}</span>
</button>
<button class="wechat-toy-btn wechat-toy-btn-media" data-media="camera" title="摄像头">
${toyControlState.cameraEnabled ? TOY_ICONS.cameraOn : TOY_ICONS.cameraOff}
</button>
</div>
`;
} else {
// 震动类玩具按钮布局(原有)
buttonsHtml = `
@@ -321,6 +500,9 @@ function renderToyControlPage() {
// 多玩具轮盘选择器
renderToyWheelSelector();
// 更新麦克风/摄像头按钮的 active 状态
updateMediaButtonUI();
// 不清空消息(保留聊天内容)
// 只在首次进入时清空
if (messagesEl && messagesEl.children.length === 0 && toyControlState.messages.length === 0) {
@@ -729,7 +911,23 @@ function buildMediaTogglePrompt(mediaType, isEnabled) {
async function onButtonPress(buttonId, pressedBy = 'user') {
if (!toyControlState.isActive) return;
const button = TOY_CONTROL_MODES[buttonId] || (buttonId === 'shock' ? SHOCK_BUTTON : null);
// 根据玩具类型获取对应的模式定义
const isSuction = isSuctionToy(toyControlState.gift.giftId);
const isMachine = isMachineToy(toyControlState.gift.giftId);
const isCup = isCupToy(toyControlState.gift.giftId);
let modes;
if (isSuction) {
modes = SUCTION_CONTROL_MODES;
} else if (isMachine) {
modes = MACHINE_CONTROL_MODES;
} else if (isCup) {
modes = CUP_CONTROL_MODES;
} else {
modes = TOY_CONTROL_MODES;
}
const button = modes[buttonId] || (buttonId === 'shock' ? SHOCK_BUTTON : null);
if (!button) return;
// 更新按钮状态(变深色)
@@ -781,27 +979,49 @@ function updateButtonState(buttonId) {
// 构建按钮按下提示词
function buildButtonPressPrompt(buttonId, buttonName, pressedBy) {
const isCharacterUsing = toyControlState.target === 'character';
const isBothUsing = toyControlState.target === 'both';
const isAIPress = pressedBy === 'ai';
const isSuction = isSuctionToy(toyControlState.gift.giftId);
const isMachine = isMachineToy(toyControlState.gift.giftId);
const isCup = isCupToy(toyControlState.gift.giftId);
// 根据玩具类型选择效果描述
const modeEffects = isSuction ? {
// 吮吸类玩具效果
gentle: '轻柔的吮吸开始了,温柔地包裹着敏感部位',
start: '吮吸开始/继续了',
strong: '吮吸力度突然加大,强烈的吸力让人难以抗拒',
pulse: '有节奏的吸放开始了,一收一放的刺激',
pause: '吮吸停止了,可以喘息一下',
shock: '一阵微电流刺激瞬间传来,让人猛地一颤'
} : {
// 震动类玩具效果
classic: '稳定持续的震动开始了',
start: '震动开始/继续了',
rampage: '震动突然变到最大强度,非常强烈的刺激袭来',
wave: '震动开始由弱到强循环变化,一波一波的刺激',
pause: '震动停止了,可以喘息一下',
shock: '一阵微电流刺激瞬间传来,让人猛地一颤'
};
let modeEffects;
if (isSuction) {
modeEffects = {
gentle: '轻柔的吮吸开始了,温柔地包裹着敏感部位',
start: '吮吸开始/继续了',
strong: '吮吸力度突然加大,强烈的吸力让人难以抗拒',
pulse: '有节奏的吸放开始了,一收一放的刺激',
pause: '吮吸停止了,可以喘息一下',
shock: '一阵微电流刺激瞬间传来,让人猛地一颤'
};
} else if (isMachine) {
modeEffects = {
slow: '缓慢的抽插开始了,温柔而深情的节奏',
start: '炮机开始运作了',
fast: '炮机突然加速,快速猛烈的冲击让人招架不住',
deep: '炮机调整角度深入,每一下都直抵最深处',
pause: '炮机停止了,可以喘息一下'
};
} else if (isCup) {
modeEffects = {
tighten: '飞机杯收紧了通道,增加的摩擦感让人更加敏感',
start: '飞机杯开始运作了',
suck: '飞机杯开始模拟吮吸,一吸一放的快感',
combo: '震动和吮吸同时开启,双重刺激袭来',
pause: '飞机杯停止了,可以喘息一下'
};
} else {
modeEffects = {
classic: '稳定持续的震动开始了',
start: '震动开始/继续了',
rampage: '震动突然变到最大强度,非常强烈的刺激袭来',
wave: '震动开始由弱到强循环变化,一波一波的刺激',
pause: '震动停止了,可以喘息一下',
shock: '一阵微电流刺激瞬间传来,让人猛地一颤'
};
}
let prompt;
@@ -817,6 +1037,11 @@ function buildButtonPressPrompt(buttonId, buttonName, pressedBy) {
- 为什么要主动切换这个模式(想要更多刺激/受不了想暂停/想换个感觉等)
- 切换后的身体感受和情绪变化
- 回复要有情感细节,符合你的角色性格`;
} else if (isBothUsing) {
prompt += `你和用户都在使用玩具,你主动切换了模式,请描述:
- 两人同时使用时的互动感受
- 切换后你们双方的反应
- 可以和用户分享此刻的感受`;
} else {
prompt += `你主动控制了用户正在使用的${toyControlState.gift.giftName},请描述你主动操作后的感受:
- 为什么要主动给用户切换这个模式(想折磨对方/想看对方的反应/调侃等)
@@ -833,6 +1058,11 @@ function buildButtonPressPrompt(buttonId, buttonName, pressedBy) {
if (isCharacterUsing) {
prompt += `你正在使用${toyControlState.gift.giftName},请根据这个刺激变化做出反应。
描述你的身体感受、情绪变化。回复要有情感细节,符合你的角色性格。`;
} else if (isBothUsing) {
prompt += `你和用户都在使用玩具,用户切换了模式,请描述:
- 你自己感受到的变化
- 想象用户此刻的感受
- 可以和用户互动,分享彼此的感受`;
} else {
prompt += `用户正在使用${toyControlState.gift.giftName},你在观察。
请描述你观察到的用户可能的反应,可以调侃、鼓励或挑逗。回复要有趣,符合你的角色性格。`;