diff --git a/CHANGELOG.md b/CHANGELOG.md
index 34b598224a..3a6e2db950 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -18,6 +18,7 @@
- Feat: [mCaptcha](https://github.com/mCaptcha/mCaptcha)のサポートを追加
### Client
+- Feat: 新しいゲームを追加
- Enhance: ハッシュタグ入力時に、本文の末尾の行に何も書かれていない場合は新たにスペースを追加しないように
- Fix: v2023.12.0で追加された「モデレーターがユーザーのアイコンもしくはバナー画像を未設定状態にできる機能」が管理画面上で正しく表示されていない問題を修正
- Enhance: チャンネルノートのピン留めをノートのメニューからできるよ
diff --git a/packages/frontend/assets/drop-and-fusion/cold_face.png b/packages/frontend/assets/drop-and-fusion/cold_face.png
new file mode 100644
index 0000000000..f5f53e9efc
Binary files /dev/null and b/packages/frontend/assets/drop-and-fusion/cold_face.png differ
diff --git a/packages/frontend/assets/drop-and-fusion/drop-arrow.svg b/packages/frontend/assets/drop-and-fusion/drop-arrow.svg
new file mode 100644
index 0000000000..f98bb8a1ac
--- /dev/null
+++ b/packages/frontend/assets/drop-and-fusion/drop-arrow.svg
@@ -0,0 +1,6 @@
+
+
+
diff --git a/packages/frontend/assets/drop-and-fusion/exploding_head.png b/packages/frontend/assets/drop-and-fusion/exploding_head.png
new file mode 100644
index 0000000000..e8ec5182c8
Binary files /dev/null and b/packages/frontend/assets/drop-and-fusion/exploding_head.png differ
diff --git a/packages/frontend/assets/drop-and-fusion/face_with_open_mouth.png b/packages/frontend/assets/drop-and-fusion/face_with_open_mouth.png
new file mode 100644
index 0000000000..c523020f62
Binary files /dev/null and b/packages/frontend/assets/drop-and-fusion/face_with_open_mouth.png differ
diff --git a/packages/frontend/assets/drop-and-fusion/face_with_symbols_on_mouth.png b/packages/frontend/assets/drop-and-fusion/face_with_symbols_on_mouth.png
new file mode 100644
index 0000000000..db9e839c84
Binary files /dev/null and b/packages/frontend/assets/drop-and-fusion/face_with_symbols_on_mouth.png differ
diff --git a/packages/frontend/assets/drop-and-fusion/frame.svg b/packages/frontend/assets/drop-and-fusion/frame.svg
new file mode 100644
index 0000000000..4276dae833
--- /dev/null
+++ b/packages/frontend/assets/drop-and-fusion/frame.svg
@@ -0,0 +1,25 @@
+
+
+
diff --git a/packages/frontend/assets/drop-and-fusion/grinning_squinting_face.png b/packages/frontend/assets/drop-and-fusion/grinning_squinting_face.png
new file mode 100644
index 0000000000..fd72d749a1
Binary files /dev/null and b/packages/frontend/assets/drop-and-fusion/grinning_squinting_face.png differ
diff --git a/packages/frontend/assets/drop-and-fusion/heart_suit.png b/packages/frontend/assets/drop-and-fusion/heart_suit.png
new file mode 100644
index 0000000000..b0105f8582
Binary files /dev/null and b/packages/frontend/assets/drop-and-fusion/heart_suit.png differ
diff --git a/packages/frontend/assets/drop-and-fusion/pleading_face.png b/packages/frontend/assets/drop-and-fusion/pleading_face.png
new file mode 100644
index 0000000000..42f58d411c
Binary files /dev/null and b/packages/frontend/assets/drop-and-fusion/pleading_face.png differ
diff --git a/packages/frontend/assets/drop-and-fusion/smiling_face_with_hearts.png b/packages/frontend/assets/drop-and-fusion/smiling_face_with_hearts.png
new file mode 100644
index 0000000000..416ef0410a
Binary files /dev/null and b/packages/frontend/assets/drop-and-fusion/smiling_face_with_hearts.png differ
diff --git a/packages/frontend/assets/drop-and-fusion/smiling_face_with_sunglasses.png b/packages/frontend/assets/drop-and-fusion/smiling_face_with_sunglasses.png
new file mode 100644
index 0000000000..c0f72254c2
Binary files /dev/null and b/packages/frontend/assets/drop-and-fusion/smiling_face_with_sunglasses.png differ
diff --git a/packages/frontend/assets/drop-and-fusion/zany_face.png b/packages/frontend/assets/drop-and-fusion/zany_face.png
new file mode 100644
index 0000000000..f14f9db20b
Binary files /dev/null and b/packages/frontend/assets/drop-and-fusion/zany_face.png differ
diff --git a/packages/frontend/src/components/MkPlusOneEffect.vue b/packages/frontend/src/components/MkPlusOneEffect.vue
index a741a3f7a8..6feb85d8de 100644
--- a/packages/frontend/src/components/MkPlusOneEffect.vue
+++ b/packages/frontend/src/components/MkPlusOneEffect.vue
@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
- +1
+ +{{ value }}
@@ -16,7 +16,9 @@ import * as os from '@/os.js';
const props = withDefaults(defineProps<{
x: number;
y: number;
+ value?: number;
}>(), {
+ value: 1,
});
const emit = defineEmits<{
diff --git a/packages/frontend/src/pages/drop-and-fusion.vue b/packages/frontend/src/pages/drop-and-fusion.vue
new file mode 100644
index 0000000000..d0ca5157ef
--- /dev/null
+++ b/packages/frontend/src/pages/drop-and-fusion.vue
@@ -0,0 +1,761 @@
+
+
+
+
+
+
+
+
+
+
+
+ NEXT >>>
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ comboPrev }} Chain!
+
+
+
+
+
+
+
+
+
+
+
+
Restart
+
+
+
+
+
+
+
+
diff --git a/packages/frontend/src/router.ts b/packages/frontend/src/router.ts
index baee85866c..9cf4be778c 100644
--- a/packages/frontend/src/router.ts
+++ b/packages/frontend/src/router.ts
@@ -527,6 +527,10 @@ export const routes = [{
path: '/clicker',
component: page(() => import('./pages/clicker.vue')),
loginRequired: true,
+}, {
+ path: '/drop-and-fusion',
+ component: page(() => import('./pages/drop-and-fusion.vue')),
+ loginRequired: true,
}, {
path: '/timeline',
component: page(() => import('./pages/timeline.vue')),
diff --git a/packages/frontend/src/scripts/sound.ts b/packages/frontend/src/scripts/sound.ts
index 0b966ff199..acde78f5fd 100644
--- a/packages/frontend/src/scripts/sound.ts
+++ b/packages/frontend/src/scripts/sound.ts
@@ -92,7 +92,13 @@ export type OperationType = typeof operationTypes[number];
* @param soundStore サウンド設定
* @param options `useCache`: デフォルトは`true` 一度再生した音声はキャッシュする
*/
-export async function loadAudio(soundStore: SoundStore, options?: { useCache?: boolean; }) {
+export async function loadAudio(soundStore: {
+ type: Exclude;
+} | {
+ type: '_driveFile_';
+ fileId: string;
+ fileUrl: string;
+}, options?: { useCache?: boolean; }) {
if (_DEV_) console.log('loading audio. opts:', options);
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (soundStore.type === null || (soundStore.type === '_driveFile_' && !soundStore.fileUrl)) {
@@ -179,18 +185,31 @@ export async function playFile(soundStore: SoundStore) {
createSourceNode(buffer, soundStore.volume)?.start();
}
-export function createSourceNode(buffer: AudioBuffer, volume: number) : AudioBufferSourceNode | null {
+export async function playRaw(type: Exclude, volume = 1, pan = 0, playbackRate = 1) {
+ const buffer = await loadAudio({ type });
+ if (!buffer) return;
+ createSourceNode(buffer, volume, pan, playbackRate)?.start();
+}
+
+export function createSourceNode(buffer: AudioBuffer, volume: number, pan = 0, playbackRate = 1) : AudioBufferSourceNode | null {
const masterVolume = defaultStore.state.sound_masterVolume;
if (isMute() || masterVolume === 0 || volume === 0) {
return null;
}
+ const panNode = ctx.createStereoPanner();
+ panNode.pan.value = pan;
+
const gainNode = ctx.createGain();
gainNode.gain.value = masterVolume * volume;
const soundSource = ctx.createBufferSource();
soundSource.buffer = buffer;
- soundSource.connect(gainNode).connect(ctx.destination);
+ soundSource.playbackRate.value = playbackRate;
+ soundSource
+ .connect(panNode)
+ .connect(gainNode)
+ .connect(ctx.destination);
return soundSource;
}
diff --git a/packages/frontend/src/ui/_common_/common.ts b/packages/frontend/src/ui/_common_/common.ts
index b970ff1df4..e50002dc2c 100644
--- a/packages/frontend/src/ui/_common_/common.ts
+++ b/packages/frontend/src/ui/_common_/common.ts
@@ -27,6 +27,11 @@ function toolsMenuItems(): MenuItem[] {
to: '/clicker',
text: '🍪👈',
icon: 'ti ti-cookie',
+ }, {
+ type: 'link',
+ to: '/drop-and-fusion',
+ text: 'Drop & Fusion',
+ icon: 'ti ti-apple',
}, ($i && ($i.isAdmin || $i.policies.canManageCustomEmojis)) ? {
type: 'link',
to: '/custom-emojis-manager',