![]()
🎭 角色简介
在庆应大学,提起神崎晃司这个名字,知道的人不少。大家都晓得他是经济学部的中国留学生,本名叫周之霖。人长得好看,一头浅金色的狼尾发,眼睛看人时总是微微眯着,带着点笑意,像是天生就高兴。
他的人缘好,在日本人学生和留学生里都吃得开。谁组织派对,只要他在,场子就不会冷下来。他三两句话就能让刚认识的人觉得…
💬 开场白
“`html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Chapter Z</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@300;400;700&display=swap" rel="stylesheet">
<style>
:root {
–bg-color: rgba(20, 20, 22, 0.7);
–blur-bg: rgba(20, 20, 22, 0.5);
–primary-text: #e0e0e0;
–secondary-text: #a0a0a0;
–accent-color: #d4af37; /* A subtle gold */
–border-color: rgba(255, 255, 255, 0.1);
–hover-bg: rgba(255, 255, 255, 0.05);
}* {
margin: 0;
padding: 0;
box-sizing: border-box;
}body {
font-family: 'Noto Sans SC', sans-serif;
background-color: #000;
color: var(–primary-text);
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
padding: 20px;
overflow: hidden;
}#video-bg {
position: fixed;
top: 50%;
left: 50%;
min-width: 100%;
min-height: 100%;
width: auto;
height: auto;
transform: translateX(-50%) translateY(-50%);
z-index: -2;
object-fit: cover;
}.overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0,0,0,0.4);
z-index: -1;
}.container {
width: 100%;
max-width: 450px;
background: var(–bg-color);
backdrop-filter: blur(15px);
-webkit-backdrop-filter: blur(15px);
border: 1px solid var(–border-color);
border-radius: 20px;
padding: 25px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
opacity: 0;
transform: translateY(20px);
animation: fadeIn 1s ease-out forwards;
max-height: 90vh;
overflow-y: auto;
}/* Custom scrollbar for webkit browsers */
.container::-webkit-scrollbar {
width: 5px;
}
.container::-webkit-scrollbar-track {
background: transparent;
}
.container::-webkit-scrollbar-thumb {
background-color: var(–accent-color);
border-radius: 20px;
border: 3px solid transparent;
}@keyframes fadeIn {
to {
opacity: 1;
transform: translateY(0);
}
}.music-player {
background: var(–blur-bg);
border-radius: 15px;
padding: 15px;
margin-bottom: 25px;
border: 1px solid var(–border-color);
}.player-row {
display: flex;
align-items: center;
}.album-icon {
font-size: 24px;
margin-right: 15px;
color: var(–accent-color);
text-shadow: 0 0 10px var(–accent-color);
animation: pulse 2s infinite;
}@keyframes pulse {
0% { transform: scale(1); opacity: 0.8; }
50% { transform: scale(1.1); opacity: 1; }
100% { transform: scale(1); opacity: 0.8; }
}.song-details {
flex-grow: 1;
}.song-title {
font-weight: 700;
font-size: 1rem;
}.song-artist {
font-size: 0.8rem;
color: var(–secondary-text);
}.player-controls button {
background: none;
border: none;
color: var(–primary-text);
font-size: 1.2rem;
cursor: pointer;
margin-left: 15px;
transition: color 0.3s, transform 0.3s;
}.player-controls button:hover {
color: var(–accent-color);
transform: scale(1.1);
}#playlist {
max-height: 0;
overflow: hidden;
transition: max-height 0.5s ease-in-out;
margin-top: 0;
}#playlist.show {
max-height: 200px; /* Adjust as needed */
margin-top: 15px;
}#playlist ul {
list-style: none;
background: rgba(0,0,0,0.3);
border-radius: 10px;
padding: 8px;
}#playlist li {
padding: 8px 12px;
cursor: pointer;
border-radius: 6px;
transition: background-color 0.2s;
font-size: 0.9rem;
display: flex;
align-items: center;
}#playlist li:hover {
background-color: var(–hover-bg);
}#playlist li.playing {
font-weight: bold;
color: var(–accent-color);
}#playlist li:not(.playing) {
color: var(–secondary-text);
}#playlist li::before {
content: '♦';
margin-right: 10px;
font-size: 0.7rem;
transition: color 0.3s;
}#playlist li.playing::before {
color: var(–accent-color);
animation: spin 3s linear infinite;
}@keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
.author-notes {
margin-bottom: 25px;
}#toggle-notes {
width: 100%;
background: none;
border: 1px solid var(–border-color);
color: var(–primary-text);
padding: 10px;
border-radius: 10px;
cursor: pointer;
font-family: inherit;
font-size: 0.9rem;
display: flex;
justify-content: space-between;
align-items: center;
transition: background-color 0.3s;
}#toggle-notes:hover {
background-color: var(–hover-bg);
}#toggle-notes .arrow {
transition: transform 0.3s ease-in-out;
}#notes-content {
max-height: 0;
overflow: hidden;
transition: max-height 0.5s ease-in-out, padding 0.5s ease-in-out;
background: var(–blur-bg);
border-radius: 0 0 10px 10px;
padding: 0 15px;
font-size: 0.85rem;
color: var(–secondary-text);
line-height: 1.6;
}#notes-content.expanded {
max-height: 500px; /* Adjust as needed */
padding: 15px;
border: 1px solid var(–border-color);
border-top: none;
}#toggle-notes.expanded .arrow {
transform: rotate(180deg);
}.section-title {
text-align: center;
font-weight: 300;
font-size: 1.2rem;
letter-spacing: 3px;
margin-bottom: 20px;
color: var(–accent-color);
text-transform: uppercase;
}.scene-list {
display: flex;
flex-direction: column;
gap: 12px;
}.scene-btn {
background: none;
border: 1px solid var(–border-color);
color: var(–primary-text);
padding: 15px 20px;
width: 100%;
border-radius: 10px;
text-align: left;
font-family: inherit;
font-size: 1rem;
cursor: pointer;
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}.scene-btn:hover {
background-color: var(–hover-bg);
border-color: var(–accent-color);
color: var(–accent-color);
transform: translateX(5px);
}
</style>
</head>
<body>
<div id="video-bg">
<video src="https://files.catbox.moe/f6l818.mov" autoplay loop muted playsinline></video>
</div>
<div class="overlay"></div><div class="container">
<div class="music-player">
<div class="player-row">
<div class="album-icon">♫</div>
<div class="song-details">
<div id="song-title-display" class="song-title">Loading…</div>
<div id="song-artist-display" class="song-artist"></div>
</div>
<div class="player-controls">
<button id="play-pause-btn">▶</button>
<button id="playlist-toggle-btn">☰</button>
</div>
</div>
<div id="playlist">
<ul></ul>
</div>
<audio id="audio-player"></audio>
</div><div class="author-notes">
<button id="toggle-notes">
<span>游玩说明(玩前请看)</span>
<span class="arrow">▼</span>
</button>
<div id="notes-content">
<p>作者oi,请不要二传二改,有需要请问我,🚫商用</p>
<p>玩之前请填写世界书中的“我也不太了解她”</p>
<p>玩小手机需要开启blmx世界书,以及换轻量预设</p>
<p>感谢游玩,repo大欢迎!</p>
</div>
</div><div class="scene-selection">
<div class="section-title">开场白</div>
<div class="scene-list">
<button class="scene-btn" onclick="switchToOpening(2)">1. 前男友问你在不在</button>
<button class="scene-btn" onclick="switchToOpening(3)">2. 大概是不想暧昧关系</button>
<button class="scene-btn" onclick="switchToOpening(4)">3. 前男友在街上见到你</button>
<button class="scene-btn" onclick="switchToOpening(5)">4. 前男友假装改变了,其实想__了</button>
<button class="scene-btn" onclick="switchToOpening(6)">5. 前男友在街上遇到你和现任</button>
<button class="scene-btn" onclick="switchToOpening(7)">6. 暧昧时期水煎</button>
<button class="scene-btn" onclick="switchToOpening(8)">7. 暧昧到床上了</button>
<button class="scene-btn" onclick="switchToOpening(9)">8. 我周之霖就是死,也不会复合</button>
<button class="scene-btn" onclick="switchToOpening(10)">9. 用尽伤人的话去说</button>
<button class="scene-btn" onclick="switchToOpening(11)">10. 炮友,大做特做</button>
<button class="scene-btn" onclick="switchToOpening(12)">10. 小手机</button>
</div>
</div>
</div><script>
document.addEventListener('DOMContentLoaded', () => {
// — Music Player Logic —
const audioPlayer = document.getElementById('audio-player');
const playPauseBtn = document.getElementById('play-pause-btn');
const playlistToggleBtn = document.getElementById('playlist-toggle-btn');
const playlistEl = document.getElementById('playlist');
const playlistUl = playlistEl.querySelector('ul');
const songTitleDisplay = document.getElementById('song-title-display');
const songArtistDisplay = document.getElementById('song-artist-display');const playlistData = [
{ title: "舍得", artist: "王唯漪", url: "https://files.catbox.moe/jrxsnk.mp3" },
{ title: "優しい雨", artist: "Ms.OOJA", url: "https://files.catbox.moe/lisqxy.mp3" },
{ title: "坠落", artist: "蔡健雅", url: "https://files.catbox.moe/rjpuiq.mp3" }
];
let currentSongIndex = 0;function loadSong(index) {
if (index < 0 || index >= playlistData.length) return;
const song = playlistData[index];
audioPlayer.src = song.url;
songTitleDisplay.textContent = song.title;
songArtistDisplay.textContent = song.artist;
updatePlaylistUI();
audioPlayer.play().catch(e => console.log("Autoplay was prevented. User must interact first."));
}function updatePlaylistUI() {
playlistUl.innerHTML = '';
playlistData.forEach((song, index) => {
const li = document.createElement('li');
li.innerHTML = `<span>${song.title} – ${song.artist}</span>`;
if (index === currentSongIndex) {
li.classList.add('playing');
}
li.addEventListener('click', () => {
currentSongIndex = index;
loadSong(currentSongIndex);
});
playlistUl.appendChild(li);
});
}function playNextSong() {
currentSongIndex = (currentSongIndex + 1) % playlistData.length;
loadSong(currentSongIndex);
}playPauseBtn.addEventListener('click', () => {
if (audioPlayer.paused) {
audioPlayer.play();
} else {
audioPlayer.pause();
}
});audioPlayer.addEventListener('play', () => { playPauseBtn.textContent = '❚❚'; });
audioPlayer.addEventListener('pause', () => { playPauseBtn.textContent = '▶'; });
audioPlayer.addEventListener('ended', playNextSong);playlistToggleBtn.addEventListener('click', () => {
playlistEl.classList.toggle('show');});
// — Author's Notes Logic —
const toggleNotesBtn = document.getElementById('toggle-notes');
const notesContent = document.getElementById('notes-content');toggleNotesBtn.addEventListener('click', () => {
notesContent.classList.toggle('expanded');
toggleNotesBtn.classList.toggle('expanded');
});// — Initial Load —
loadSong(currentSongIndex);
});// — SillyTavern Integration —
async function switchToOpening(openingId) {
// Function to switch character card swipes in SillyTavern
try {
if (typeof getChatMessages === 'function' && typeof setChatMessage === 'function') {
const messages = await getChatMessages(0, { include_swipe: true });
// Swipes are 0-indexed, openingId is 1-indexed
const swipeIndex = openingId – 1;
if (messages && messages.length > 0 && messages[0].swipes && messages[0].swipes.length > swipeIndex) {
const content = messages[0].swipes[swipeIndex];
setChatMessage(content, 0, { swipe_id: swipeIndex, refresh: 'display_and_render_current' });
console.log(`Successfully switched to opening ${openingId}`);
} else {
console.error(`Error: Opening with ID ${openingId} (index ${swipeIndex}) not found.`);
}
} else {
// Fallback for when not in SillyTavern
console.log(`Simulating switch to opening ${openingId}. (SillyTavern API not found)`);
alert(`Switched to opening: ${openingId}`);
}
} catch (error) {
console.error('Error switching opening:', error);
}
}
</script>
</body>
</html>
“`