feat(tongji): add hidden flow scoring mode
This commit is contained in:
@@ -117,12 +117,20 @@
|
||||
background: rgba(255,255,255,.92);
|
||||
box-shadow: 0 18rpx 44rpx rgba(29, 78, 59, .12);
|
||||
}
|
||||
.eg-board-shell.is-flowing {
|
||||
border-color: rgba(245, 158, 11, .72);
|
||||
box-shadow: 0 0 0 5rpx rgba(255, 221, 89, .2), 0 18rpx 46rpx rgba(234, 88, 12, .2);
|
||||
animation: egFlowShell 1.05s ease-in-out infinite alternate;
|
||||
}
|
||||
|
||||
.eg-board-top { display: flex; align-items: center; justify-content: space-between; margin: 0 4rpx 14rpx; }
|
||||
.eg-board-bonuses { display: flex; align-items: center; gap: 8rpx; }
|
||||
.eg-combo { padding: 8rpx 16rpx; border-radius: 999rpx; color: #45685d; background: #e8f3ee; font-size: 25rpx; font-weight: 700; }
|
||||
.eg-combo.is-hot { color: #fff; background: linear-gradient(135deg, #f59e0b, #ea580c); }
|
||||
.eg-double-state { padding: 8rpx 14rpx; border: 2rpx solid rgba(255,255,255,.9); border-radius: 999rpx; color: #fff; background: linear-gradient(135deg, #7c3aed, #d946ef); box-shadow: 0 4rpx 12rpx rgba(124,58,237,.24); font-size: 23rpx; font-weight: 900; white-space: nowrap; }
|
||||
.eg-flow-state { display: flex; align-items: center; gap: 8rpx; padding: 8rpx 14rpx; border: 3rpx solid #fff3a3; border-radius: 999rpx; color: #fff; background: linear-gradient(135deg, #f97316, #dc2626); box-shadow: 0 5rpx 16rpx rgba(220,38,38,.3); font-size: 25rpx; font-weight: 1000; white-space: nowrap; animation: egFlowBadge .62s ease-in-out infinite alternate; }
|
||||
.eg-flow-state > text:last-child { min-width: 62rpx; color: #fff7a8; text-align: right; }
|
||||
.eg-flow-state.is-paused { border-color: #d9f6ff; background: linear-gradient(135deg, #1687b4, #3155a6); box-shadow: 0 5rpx 16rpx rgba(34,109,166,.28); animation: none; }
|
||||
.eg-risk { display: flex; align-items: center; gap: 10rpx; color: #8d512c; font-size: 24rpx; }
|
||||
.eg-risk-dots { display: flex; gap: 5rpx; }
|
||||
.eg-risk-dot { width: 12rpx; height: 12rpx; border-radius: 50%; background: #ead8c9; }
|
||||
@@ -559,6 +567,16 @@
|
||||
100% { opacity: 1; transform: scale(1); }
|
||||
}
|
||||
|
||||
@keyframes egFlowShell {
|
||||
from { filter: saturate(1); }
|
||||
to { filter: saturate(1.08); }
|
||||
}
|
||||
|
||||
@keyframes egFlowBadge {
|
||||
from { transform: scale(.98); filter: brightness(.96); }
|
||||
to { transform: scale(1.035); filter: brightness(1.12); }
|
||||
}
|
||||
|
||||
@keyframes egStageIn {
|
||||
0% { opacity: 0; transform: scale(.7) translateY(34rpx); }
|
||||
18% { opacity: 1; transform: scale(1.06) translateY(0); }
|
||||
|
||||
@@ -70,11 +70,19 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="eg-board-shell">
|
||||
<view class="eg-board-shell" :class="{ 'is-flowing': flowActive }">
|
||||
<view class="eg-board-top">
|
||||
<view class="eg-board-bonuses">
|
||||
<view class="eg-combo" :class="{ 'is-hot': combo >= 3 }">连消 ×{{ Math.max(combo, 1) }}</view>
|
||||
<view v-if="feastMoves > 0" class="eg-double-state">双倍得分 ×{{ feastMoves }}</view>
|
||||
<view
|
||||
v-if="flowActive"
|
||||
class="eg-flow-state"
|
||||
:class="{ 'is-paused': flowPaused }"
|
||||
>
|
||||
<text>{{ flowPaused ? '选择暂停' : '心流 ×2' }}</text>
|
||||
<text>{{ flowCountdownLabel }}秒</text>
|
||||
</view>
|
||||
<view v-else-if="feastMoves > 0" class="eg-double-state">双倍得分 ×{{ feastMoves }}</view>
|
||||
</view>
|
||||
<view class="eg-risk">
|
||||
<text>高糖食物 {{ highCount }}/3</text>
|
||||
@@ -324,8 +332,16 @@ const COMBO_TASK_WAVE = 2
|
||||
const COMBO_TASK_TARGET = 2
|
||||
const COMBO_PITY_TURNS = 6
|
||||
const MEGA_COMBO_SCORE = 300
|
||||
const ACTIVE_GAME_KEY = 'tongji_endless_active_game_v1'
|
||||
const ACTIVE_GAME_VERSION = 1
|
||||
const FLOW_TRIGGER_GROUPS = 10
|
||||
const FLOW_WINDOW_MS = 3000
|
||||
const FLOW_DURATION_MS = 3000
|
||||
const FLOW_CAMEL_PAUSE_MS = 3000
|
||||
const FLOW_JACKPOT_DURATION_MS = 6000
|
||||
const FLOW_TICK_MS = 100
|
||||
const ACTIVE_GAME_KEY = 'tongji_endless_active_game_v2'
|
||||
const LEGACY_ACTIVE_GAME_KEY = 'tongji_endless_active_game_v1'
|
||||
const ENDED_GAME_KEY = 'tongji_endless_ended_game_v1'
|
||||
const ACTIVE_GAME_VERSION = 2
|
||||
const DANGER_DROP_CHANCE = 0.05 + GAME_DIFFICULTY * 0.01
|
||||
const COLUMN_GROUP_BIAS = 0.86 - GAME_DIFFICULTY * 0.028
|
||||
const CHEER_MESSAGES = [
|
||||
@@ -426,6 +442,10 @@ const bestScore = ref(0)
|
||||
const learned = ref(0)
|
||||
const combo = ref(0)
|
||||
const feastMoves = ref(0)
|
||||
const flowActive = ref(false)
|
||||
const flowPaused = ref(false)
|
||||
const flowRemainingMs = ref(0)
|
||||
const flowChainCount = ref(0)
|
||||
const camelCount = ref(3)
|
||||
const camelMode = ref(false)
|
||||
const busy = ref(false)
|
||||
@@ -478,6 +498,12 @@ let jackpotTimer = null
|
||||
let confettiTimer = null
|
||||
let stageTimer = null
|
||||
let taskRewardTimer = null
|
||||
let flowTimer = null
|
||||
let flowPauseTimer = null
|
||||
let flowPausedRemainingMs = 0
|
||||
let lastFlowGroupAt = 0
|
||||
let flowLastTickAt = 0
|
||||
let flowPageHidden = false
|
||||
let pendingThemeMatchCount = 0
|
||||
let taskRewardStatusUntil = 0
|
||||
let sfxGesturePrimed = false
|
||||
@@ -495,6 +521,7 @@ const currentTask = computed(() => {
|
||||
return templates[taskIndex.value % templates.length]
|
||||
})
|
||||
const taskPercent = computed(() => Math.min(100, taskProgress.value / currentTask.value.target * 100))
|
||||
const flowCountdownLabel = computed(() => Math.max(0, flowRemainingMs.value / 1000).toFixed(1))
|
||||
const highCount = computed(() => board.value.filter(tile => tile && foodOf(tile.key).high).length)
|
||||
const boardRows = computed(() => Array.from({ length: ROWS }, (_, row) => (
|
||||
board.value.slice(row * COLS, row * COLS + COLS).map((tile, col) => ({ ...tile, index: row * COLS + col }))
|
||||
@@ -634,12 +661,16 @@ onLoad((options = {}) => {
|
||||
})
|
||||
|
||||
onShow(() => {
|
||||
flowPageHidden = false
|
||||
syncFlowClock()
|
||||
connectPlatform(incomingInviteCode).then((ok) => {
|
||||
if (ok) flushPlatformProgress()
|
||||
})
|
||||
})
|
||||
|
||||
onHide(() => {
|
||||
flowPageHidden = true
|
||||
if (flowPaused.value) resumeFlowFromCamel()
|
||||
saveActiveGame()
|
||||
})
|
||||
|
||||
@@ -655,6 +686,7 @@ onUnload(() => {
|
||||
if (confettiTimer) clearTimeout(confettiTimer)
|
||||
if (stageTimer) clearTimeout(stageTimer)
|
||||
if (taskRewardTimer) clearTimeout(taskRewardTimer)
|
||||
clearFlowTimers()
|
||||
})
|
||||
|
||||
function makeTile(key, special = '') {
|
||||
@@ -742,6 +774,142 @@ function currentWeekStartKey(now = new Date()) {
|
||||
|
||||
function clearActiveGame() {
|
||||
try { uni.removeStorageSync(ACTIVE_GAME_KEY) } catch (_) {}
|
||||
try { uni.removeStorageSync(LEGACY_ACTIVE_GAME_KEY) } catch (_) {}
|
||||
}
|
||||
|
||||
function readEndedGame() {
|
||||
try { return uni.getStorageSync(ENDED_GAME_KEY) || null } catch (_) { return null }
|
||||
}
|
||||
|
||||
function markGameEnded() {
|
||||
try {
|
||||
uni.setStorageSync(ENDED_GAME_KEY, {
|
||||
session_key: getPlatformSessionKey(),
|
||||
ended_at: Date.now()
|
||||
})
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
function clearFlowTimers() {
|
||||
if (flowTimer) clearInterval(flowTimer)
|
||||
if (flowPauseTimer) clearTimeout(flowPauseTimer)
|
||||
flowTimer = null
|
||||
flowPauseTimer = null
|
||||
}
|
||||
|
||||
function resetFlowState() {
|
||||
clearFlowTimers()
|
||||
flowActive.value = false
|
||||
flowPaused.value = false
|
||||
flowRemainingMs.value = 0
|
||||
flowChainCount.value = 0
|
||||
flowPausedRemainingMs = 0
|
||||
lastFlowGroupAt = 0
|
||||
flowLastTickAt = 0
|
||||
}
|
||||
|
||||
function flowClockBlocked() {
|
||||
return flowPageHidden
|
||||
|| flowPaused.value
|
||||
|| busy.value
|
||||
|| reshuffling.value
|
||||
|| stageVisible.value
|
||||
|| camelJackpot.value.visible
|
||||
|| weeklyRankVisible.value
|
||||
|| gameOver.value
|
||||
}
|
||||
|
||||
function syncFlowClock() {
|
||||
if (!flowActive.value) return
|
||||
const now = Date.now()
|
||||
if (!flowLastTickAt) flowLastTickAt = now
|
||||
const elapsed = Math.max(0, now - flowLastTickAt)
|
||||
flowLastTickAt = now
|
||||
if (flowClockBlocked()) return
|
||||
flowRemainingMs.value = Math.max(0, flowRemainingMs.value - elapsed)
|
||||
if (flowRemainingMs.value <= 0) endFlow()
|
||||
}
|
||||
|
||||
function ensureFlowTimer() {
|
||||
if (flowTimer) clearInterval(flowTimer)
|
||||
flowLastTickAt = Date.now()
|
||||
flowTimer = setInterval(syncFlowClock, FLOW_TICK_MS)
|
||||
}
|
||||
|
||||
function activateFlow(duration = FLOW_DURATION_MS, source = 'streak') {
|
||||
const wasActive = flowActive.value
|
||||
flowActive.value = true
|
||||
flowPaused.value = false
|
||||
flowPausedRemainingMs = 0
|
||||
flowRemainingMs.value = Math.max(wasActive ? flowRemainingMs.value : 0, duration)
|
||||
flowChainCount.value = Math.max(flowChainCount.value, FLOW_TRIGGER_GROUPS)
|
||||
ensureFlowTimer()
|
||||
if (wasActive) return
|
||||
statusText.value = source === 'camel-five'
|
||||
? '五罐驼乳开启 6 秒心流,继续消除得分翻倍'
|
||||
: '手感来了!3 秒内继续消除,得分翻倍'
|
||||
playSfxLayer('comboMega', 'sparkle', 90, .72)
|
||||
vibrate('medium')
|
||||
uni.showToast({
|
||||
title: source === 'camel-five' ? '五连大奖:心流双倍 6 秒' : '隐藏心流已触发:得分 ×2',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
|
||||
function endFlow() {
|
||||
if (flowTimer) clearInterval(flowTimer)
|
||||
if (flowPauseTimer) clearTimeout(flowPauseTimer)
|
||||
flowTimer = null
|
||||
flowPauseTimer = null
|
||||
flowActive.value = false
|
||||
flowPaused.value = false
|
||||
flowRemainingMs.value = 0
|
||||
flowChainCount.value = 0
|
||||
flowPausedRemainingMs = 0
|
||||
lastFlowGroupAt = 0
|
||||
flowLastTickAt = 0
|
||||
if (!busy.value && !gameOver.value) statusText.value = '心流结束,继续寻找下一次手感'
|
||||
}
|
||||
|
||||
function pauseFlowForCamel() {
|
||||
if (!flowActive.value || flowPaused.value) return
|
||||
syncFlowClock()
|
||||
if (!flowActive.value) return
|
||||
flowPaused.value = true
|
||||
flowPausedRemainingMs = flowRemainingMs.value
|
||||
if (flowPauseTimer) clearTimeout(flowPauseTimer)
|
||||
flowPauseTimer = setTimeout(() => {
|
||||
resumeFlowFromCamel()
|
||||
if (camelMode.value && !busy.value) statusText.value = '3 秒选择暂停已结束,请尽快选择替换食物'
|
||||
}, FLOW_CAMEL_PAUSE_MS)
|
||||
}
|
||||
|
||||
function resumeFlowFromCamel() {
|
||||
if (!flowPaused.value) return
|
||||
if (flowPauseTimer) clearTimeout(flowPauseTimer)
|
||||
flowPauseTimer = null
|
||||
flowPaused.value = false
|
||||
flowRemainingMs.value = Math.max(0, flowPausedRemainingMs)
|
||||
flowPausedRemainingMs = 0
|
||||
flowLastTickAt = Date.now()
|
||||
if (flowRemainingMs.value <= 0) endFlow()
|
||||
}
|
||||
|
||||
function registerFlowGroups(groupCount, countsTowardTrigger = true) {
|
||||
const count = Math.max(0, Number(groupCount) || 0)
|
||||
if (!count) return
|
||||
const now = Date.now()
|
||||
if (flowActive.value) {
|
||||
flowRemainingMs.value = Math.max(flowRemainingMs.value, FLOW_DURATION_MS)
|
||||
flowLastTickAt = now
|
||||
return
|
||||
}
|
||||
if (!countsTowardTrigger) return
|
||||
flowChainCount.value = now - lastFlowGroupAt <= FLOW_WINDOW_MS
|
||||
? flowChainCount.value + count
|
||||
: count
|
||||
lastFlowGroupAt = now
|
||||
if (flowChainCount.value >= FLOW_TRIGGER_GROUPS) activateFlow(FLOW_DURATION_MS)
|
||||
}
|
||||
|
||||
function saveActiveGame() {
|
||||
@@ -755,6 +923,7 @@ function saveActiveGame() {
|
||||
try {
|
||||
uni.setStorageSync(ACTIVE_GAME_KEY, {
|
||||
version: ACTIVE_GAME_VERSION,
|
||||
status: 'active',
|
||||
week_start: currentWeekStartKey(),
|
||||
session_key: getPlatformSessionKey(),
|
||||
confirmed_session_learned: Math.max(0, Number(confirmedSessionLearned.value) || 0),
|
||||
@@ -782,7 +951,16 @@ function restoreActiveGame() {
|
||||
const validBoard = Array.isArray(saved?.board)
|
||||
&& saved.board.length === ROWS * COLS
|
||||
&& saved.board.every(tile => tile && FOODS[tile.key])
|
||||
if (saved?.version !== ACTIVE_GAME_VERSION || saved?.week_start !== currentWeekStartKey() || !validBoard) {
|
||||
const ended = readEndedGame()
|
||||
const savedSessionKey = String(saved?.session_key || '')
|
||||
const endedSessionKey = String(ended?.session_key || '')
|
||||
if (
|
||||
saved?.version !== ACTIVE_GAME_VERSION
|
||||
|| saved?.status !== 'active'
|
||||
|| saved?.week_start !== currentWeekStartKey()
|
||||
|| !validBoard
|
||||
|| (savedSessionKey && savedSessionKey === endedSessionKey)
|
||||
) {
|
||||
clearActiveGame()
|
||||
return false
|
||||
}
|
||||
@@ -798,6 +976,7 @@ function restoreActiveGame() {
|
||||
learned.value = Math.max(0, Number(saved.learned) || 0)
|
||||
combo.value = Math.max(0, Number(saved.combo) || 0)
|
||||
feastMoves.value = Math.max(0, Number(saved.feast_moves) || 0)
|
||||
resetFlowState()
|
||||
camelCount.value = Math.max(0, Math.min(MAX_CAMEL_COUNT, Number(saved.camel_count) || 0))
|
||||
taskIndex.value = Math.max(0, Number(saved.task_index) || 0) % 4
|
||||
taskProgress.value = Math.max(0, Number(saved.task_progress) || 0)
|
||||
@@ -839,6 +1018,7 @@ function startGame() {
|
||||
learned.value = 0
|
||||
combo.value = 0
|
||||
feastMoves.value = 0
|
||||
resetFlowState()
|
||||
camelCount.value = 3
|
||||
camelMode.value = false
|
||||
busy.value = false
|
||||
@@ -1003,6 +1183,7 @@ async function tapTile(index) {
|
||||
board.value = [...board.value]
|
||||
camelCount.value -= 1
|
||||
camelMode.value = false
|
||||
resumeFlowFromCamel()
|
||||
selected.value = -1
|
||||
playSfxLayer('insulin', 'sparkle', 55, .5)
|
||||
vibrate('light')
|
||||
@@ -1010,7 +1191,7 @@ async function tapTile(index) {
|
||||
if (groups.length) {
|
||||
busy.value = true
|
||||
statusText.value = '驼乳棋子连起来了!'
|
||||
await resolveMatches(groups, index)
|
||||
await resolveMatches(groups, index, { toolTriggered: true })
|
||||
busy.value = false
|
||||
finishTurn()
|
||||
} else {
|
||||
@@ -1046,7 +1227,15 @@ function toggleCamel() {
|
||||
if (busy.value || camelCount.value <= 0 || gameOver.value) return
|
||||
camelMode.value = !camelMode.value
|
||||
selected.value = -1
|
||||
statusText.value = camelMode.value ? `请选择橙色边框的${foodOf(currentTheme.value.danger).short}进行替换` : '已取消使用驼乳粉'
|
||||
if (camelMode.value) {
|
||||
pauseFlowForCamel()
|
||||
statusText.value = flowPaused.value
|
||||
? `心流暂停 3 秒,请选择橙色边框的${foodOf(currentTheme.value.danger).short}`
|
||||
: `请选择橙色边框的${foodOf(currentTheme.value.danger).short}进行替换`
|
||||
} else {
|
||||
resumeFlowFromCamel()
|
||||
statusText.value = '已取消使用驼乳粉'
|
||||
}
|
||||
}
|
||||
|
||||
function isAdjacent(a, b) {
|
||||
@@ -1081,6 +1270,8 @@ async function trySwap(a, b, soundPlayed = false) {
|
||||
endedFood.value = foodOf(highTile.key)
|
||||
saveBest()
|
||||
gameOver.value = true
|
||||
resetFlowState()
|
||||
markGameEnded()
|
||||
clearActiveGame()
|
||||
queuePlatformProgress(learned.value, score.value, true)
|
||||
busy.value = false
|
||||
@@ -1097,7 +1288,8 @@ function swap(a, b) {
|
||||
board.value = next
|
||||
}
|
||||
|
||||
async function resolveMatches(initialGroups, movedIndex) {
|
||||
async function resolveMatches(initialGroups, movedIndex, options = {}) {
|
||||
const toolTriggered = !!options.toolTriggered
|
||||
const comboTaskAtStart = currentTask.value.kind === 'combo'
|
||||
let groups = initialGroups
|
||||
let wave = 0
|
||||
@@ -1136,6 +1328,7 @@ async function resolveMatches(initialGroups, movedIndex) {
|
||||
? 5
|
||||
: 0
|
||||
const camelMatchCount = Math.max(bentCamelCount, camelGroup?.indices.length || 0)
|
||||
registerFlowGroups(groups.length, !toolTriggered)
|
||||
if (camelMatchCount >= 3) applyCamelJackpot(camelMatchCount, remove)
|
||||
const removedTiles = [...remove].map(i => board.value[i]).filter(Boolean)
|
||||
// 排名统计的是正确认识并消除的普通食物;驼乳是道具,不计入认糖数。
|
||||
@@ -1162,7 +1355,7 @@ async function resolveMatches(initialGroups, movedIndex) {
|
||||
turnConsumed += removedNormal.length
|
||||
learned.value += removedNormal.length
|
||||
updateFoodTask(removedNormal)
|
||||
const multiplier = feastMoves.value > 0 ? 2 : 1
|
||||
const multiplier = feastMoves.value > 0 || flowActive.value ? 2 : 1
|
||||
score.value += (removedNormal.length * 12 + Math.max(0, wave - 1) * 20 + madeSpecial * 35) * multiplier
|
||||
queuePlatformProgress(learned.value, score.value, false)
|
||||
await wait(specialEffects.hasFire ? 330 : 210)
|
||||
@@ -1262,29 +1455,31 @@ function camelRewardText(reward) {
|
||||
|
||||
function applyCamelJackpot(count, remove) {
|
||||
pendingThemeMatchCount = Math.max(pendingThemeMatchCount, count)
|
||||
const bonusMultiplier = flowActive.value ? 2 : 1
|
||||
if (count >= 5) {
|
||||
score.value += 1554
|
||||
const camelReward = grantCamelReward(4)
|
||||
feastMoves.value = Math.max(feastMoves.value, 6)
|
||||
const bonus = 1554 * bonusMultiplier
|
||||
score.value += bonus
|
||||
activateFlow(FLOW_JACKPOT_DURATION_MS, 'camel-five')
|
||||
board.value.forEach((tile, index) => { if (foodOf(tile?.key).high) remove.add(index) })
|
||||
showCamelJackpot(5, '驼乳五连双倍大奖', `+1554 分 · ${camelRewardText(camelReward)} · 双倍得分 ×6`)
|
||||
showCamelJackpot(5, '驼乳五连双倍大奖', `+${bonus} 分 · 移出全部高糖 · 心流双倍 6 秒`)
|
||||
startConfetti()
|
||||
playJackpotSequence()
|
||||
return
|
||||
}
|
||||
if (count === 4) {
|
||||
score.value += 288
|
||||
const camelReward = grantCamelReward(1)
|
||||
const bonus = 388 * bonusMultiplier
|
||||
score.value += bonus
|
||||
const highIndex = board.value.findIndex((tile, index) => foodOf(tile?.key).high && !remove.has(index))
|
||||
if (highIndex >= 0) remove.add(highIndex)
|
||||
showCamelJackpot(4, '驼乳超级四连', `+288 分 · ${camelRewardText(camelReward)} · 移出一份高糖食物`)
|
||||
showCamelJackpot(4, '驼乳超级四连', `+${bonus} 分 · 移出一份高糖食物 · 再来一罐冲击大奖`)
|
||||
playSfxLayer('match5', 'fanfare', 90, .7)
|
||||
setTimeout(() => playSfx('tap', 1.16, .58), 260)
|
||||
vibrate('medium')
|
||||
return
|
||||
}
|
||||
score.value += 77
|
||||
showCamelJackpot(3, '驼乳幸运三连', '+77 分 · 轻量连消奖励')
|
||||
const bonus = 77 * bonusMultiplier
|
||||
score.value += bonus
|
||||
showCamelJackpot(3, '驼乳幸运三连', `+${bonus} 分 · 轻量连消奖励`)
|
||||
playSfxLayer('match3', 'sparkle', 44, .38)
|
||||
vibrate('light')
|
||||
}
|
||||
@@ -1586,7 +1781,9 @@ function finishTurn() {
|
||||
scheduleHint()
|
||||
return
|
||||
}
|
||||
statusText.value = combo.value >= 2 ? `漂亮!完成 ${combo.value} 连消` : '食物已从上方补充,继续挑战'
|
||||
statusText.value = flowActive.value
|
||||
? '心流双倍进行中,3 秒内继续消除可续时'
|
||||
: (combo.value >= 2 ? `漂亮!完成 ${combo.value} 连消` : '食物已从上方补充,继续挑战')
|
||||
scheduleHint()
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user