good version
This commit is contained in:
parent
53bdcb8a9d
commit
34adb9c15c
|
|
@ -175,6 +175,9 @@ function triggerDebugAction(action, payload = null) {
|
|||
<div class="btn-group">
|
||||
<button @click="unlockAllAchievements()">🏆 Unlock All Achievements</button>
|
||||
</div>
|
||||
<div class="btn-group">
|
||||
<button @click="stats.dailyPrayerCount = 0">🙏 Reset Prayer Count</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
<div class="action-menu">
|
||||
<button class="icon-btn icon-clean" @click="$emit('clean')" :disabled="disabled || poopCount === 0" title="清理"></button>
|
||||
<button class="icon-btn icon-medicine" @click="$emit('medicine')" :disabled="disabled || !isSick" title="治療"></button>
|
||||
<button class="icon-btn icon-training" @click="$emit('training')" :disabled="disabled" title="祈禱"></button>
|
||||
<button class="icon-btn icon-sleep" @click="$emit('sleep')" :disabled="disabled" title="關燈"></button>
|
||||
<button class="icon-btn icon-backpack" @click="$emit('inventory')" :disabled="disabled" title="背包"></button>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -27,7 +27,7 @@ const props = defineProps({
|
|||
}
|
||||
});
|
||||
|
||||
defineEmits(['clean', 'medicine', 'training', 'inventory']);
|
||||
defineEmits(['clean', 'medicine', 'sleep', 'inventory']);
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
|
@ -90,30 +90,27 @@ defineEmits(['clean', 'medicine', 'training', 'inventory']);
|
|||
0px 4px 0 #ff4444, 0px 6px 0 #ff4444;
|
||||
}
|
||||
|
||||
/* Training Icon (Praying Hands) */
|
||||
.icon-training::before {
|
||||
/* Sleep Icon (Light Bulb/燈泡) */
|
||||
.icon-sleep::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 2px;
|
||||
height: 2px;
|
||||
background: #d4a574; /* 手的膚色 */
|
||||
background: #ffd700; /* 燈泡顏色 */
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
box-shadow:
|
||||
/* 光芒 - 頂部 */
|
||||
0px -8px 0 #ffcc00,
|
||||
-2px -6px 0 #ffcc00, 2px -6px 0 #ffcc00,
|
||||
|
||||
/* 合掌的手 - 簡化版 */
|
||||
-2px -4px 0 #d4a574, 0px -4px 0 #d4a574, 2px -4px 0 #d4a574,
|
||||
-2px -2px 0 #d4a574, 0px -2px 0 #d4a574, 2px -2px 0 #d4a574,
|
||||
-2px 0px 0 #d4a574, 0px 0px 0 #d4a574, 2px 0px 0 #d4a574,
|
||||
0px 2px 0 #d4a574, 0px 4px 0 #d4a574,
|
||||
|
||||
/* 光芒 - 左右 */
|
||||
-6px -2px 0 #ffcc00, 6px -2px 0 #ffcc00,
|
||||
-6px 0px 0 #ffcc00, 6px 0px 0 #ffcc00;
|
||||
/* 燈泡主體 (圓形) */
|
||||
-2px -6px 0 #ffd700, 0px -6px 0 #ffd700, 2px -6px 0 #ffd700,
|
||||
-4px -4px 0 #ffd700, -2px -4px 0 #ffd700, 0px -4px 0 #ffd700, 2px -4px 0 #ffd700, 4px -4px 0 #ffd700,
|
||||
-4px -2px 0 #ffd700, -2px -2px 0 #ffd700, 0px -2px 0 #ffd700, 2px -2px 0 #ffd700, 4px -2px 0 #ffd700,
|
||||
-4px 0px 0 #ffd700, -2px 0px 0 #ffd700, 0px 0px 0 #ffd700, 2px 0px 0 #ffd700, 4px 0px 0 #ffd700,
|
||||
-2px 2px 0 #ffd700, 0px 2px 0 #ffd700, 2px 2px 0 #ffd700,
|
||||
/* 燈泡底部 (螺旋) */
|
||||
-1px 4px 0 #8B4513, 0px 4px 0 #8B4513, 1px 4px 0 #8B4513,
|
||||
/* 光線 (向下) */
|
||||
0px 6px 0 #ffd700, 0px 8px 0 #ffd700;
|
||||
}
|
||||
|
||||
/* Backpack Icon */
|
||||
|
|
|
|||
|
|
@ -0,0 +1,637 @@
|
|||
<template>
|
||||
<div class="deity-temple-overlay">
|
||||
<div class="temple-container" @click.stop>
|
||||
<!-- Header -->
|
||||
<div class="temple-header">
|
||||
<button class="close-btn" @click="$emit('close')">×</button>
|
||||
<h2 class="temple-title">神廟</h2>
|
||||
</div>
|
||||
|
||||
<!-- Scrollable Content -->
|
||||
<div class="temple-content">
|
||||
<!-- Deity Display -->
|
||||
<div class="deity-display">
|
||||
<div class="deity-icon" :class="currentDeity.icon"></div>
|
||||
<div class="deity-name">{{ currentDeity.name }}</div>
|
||||
<div class="deity-subtitle">{{ currentDeity.personality }}</div>
|
||||
</div>
|
||||
|
||||
<!-- Dialogue Bubble -->
|
||||
<div class="dialogue-bubble">
|
||||
<p>{{ currentDialogue }}</p>
|
||||
</div>
|
||||
|
||||
<!-- Favor Progress -->
|
||||
<div class="favor-section">
|
||||
<div class="favor-label">
|
||||
好感度: {{ favorStars }} ({{ currentFavor }}/100)
|
||||
</div>
|
||||
<div class="favor-bar">
|
||||
<div class="favor-fill" :style="{ width: currentFavor + '%' }"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Active Buffs -->
|
||||
<div class="buffs-section" v-if="activeBuffs.length > 0">
|
||||
<div class="buff-title">當前加成:</div>
|
||||
<div class="buff-list">
|
||||
<div v-for="buff in activeBuffs" :key="buff.type" class="buff-item">
|
||||
• {{ buff.description }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Prayer Options -->
|
||||
<div class="prayer-section">
|
||||
<!-- 祈福按鈕 -->
|
||||
<button
|
||||
class="prayer-btn"
|
||||
:disabled="dailyPrayerCount >= 3"
|
||||
@click="handlePrayer"
|
||||
>
|
||||
🙏 祈福 (今日 {{ dailyPrayerCount }}/3)
|
||||
</button>
|
||||
|
||||
<div class="prayer-divider">或</div>
|
||||
|
||||
<div class="prayer-options">
|
||||
<!-- 擲筊選項 -->
|
||||
<button
|
||||
class="prayer-option"
|
||||
@click="handlePrayerSelect('jiaobei')"
|
||||
>
|
||||
<div class="option-icon icon-jiaobei"></div>
|
||||
<span class="option-label">擲筊</span>
|
||||
</button>
|
||||
|
||||
<!-- 求籤選項 -->
|
||||
<button
|
||||
class="prayer-option"
|
||||
@click="handlePrayerSelect('fortune')"
|
||||
>
|
||||
<div class="option-icon icon-fortune"></div>
|
||||
<span class="option-label">求籤</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Bottom Actions -->
|
||||
<div class="bottom-actions">
|
||||
<button class="action-btn" @click="showDeitySelector = !showDeitySelector">
|
||||
切換神明
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Deity Selector (Overlay on top of content) -->
|
||||
<div v-if="showDeitySelector" class="deity-selector-overlay" @click="showDeitySelector = false">
|
||||
<div class="deity-selector-menu" @click.stop>
|
||||
<div class="selector-header">選擇神明</div>
|
||||
<div
|
||||
v-for="deity in DEITIES"
|
||||
:key="deity.id"
|
||||
class="deity-option"
|
||||
:class="{ active: deity.id === currentDeity.id }"
|
||||
@click="selectDeity(deity.id)"
|
||||
>
|
||||
<div class="deity-icon-small" :class="deity.icon"></div>
|
||||
<span>{{ deity.name }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, onMounted } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
deityFavors: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
currentDeityId: {
|
||||
type: String,
|
||||
default: 'mazu'
|
||||
},
|
||||
dailyPrayerCount: {
|
||||
type: Number,
|
||||
default: 0
|
||||
}
|
||||
});
|
||||
|
||||
const emit = defineEmits(['close', 'prayer', 'change-deity', 'prayer-select']);
|
||||
|
||||
// Deity Data
|
||||
const DEITIES = [
|
||||
{
|
||||
id: 'mazu',
|
||||
name: '媽祖',
|
||||
personality: '溫柔守護',
|
||||
buffs: {
|
||||
gameSuccessRate: 0.1,
|
||||
sicknessReduction: 0.15
|
||||
},
|
||||
buffDescriptions: [
|
||||
'小遊戲成功率 +10%',
|
||||
'生病機率 -15%'
|
||||
],
|
||||
dialogues: [
|
||||
"好孩子,媽祖保佑你平安喔",
|
||||
"海上無風浪,心中有媽祖",
|
||||
"要好好照顧寵物啊"
|
||||
],
|
||||
icon: 'deity-mazu'
|
||||
},
|
||||
{
|
||||
id: 'earthgod',
|
||||
name: '土地公',
|
||||
personality: '碎念管家',
|
||||
buffs: {
|
||||
itemDropRate: 0.2,
|
||||
resourceGain: 0.15
|
||||
},
|
||||
buffDescriptions: [
|
||||
'掉落物品機率 +20%',
|
||||
'資源獲得 +15%'
|
||||
],
|
||||
dialogues: [
|
||||
"又來啦?今天有好好餵寵物嗎?",
|
||||
"欸,地上那個便便怎麼不清一清",
|
||||
"拜我就對了,土地公最靈驗"
|
||||
],
|
||||
icon: 'deity-earthgod'
|
||||
},
|
||||
{
|
||||
id: 'matchmaker',
|
||||
name: '月老',
|
||||
personality: '八卦熱情',
|
||||
buffs: {
|
||||
happinessRecovery: 0.25,
|
||||
goodEventRate: 0.1
|
||||
},
|
||||
buffDescriptions: [
|
||||
'Happiness 回復 +25%',
|
||||
'好事件機率 +10%'
|
||||
],
|
||||
dialogues: [
|
||||
"哎呀~你的寵物今天心情不錯喔",
|
||||
"要不要幫你牽條紅線?咦,寵物也需要嗎",
|
||||
"姻緣天注定,開心最重要!"
|
||||
],
|
||||
icon: 'deity-matchmaker'
|
||||
},
|
||||
{
|
||||
id: 'wenchang',
|
||||
name: '文昌帝君',
|
||||
personality: '嚴肅學者',
|
||||
buffs: {
|
||||
intGrowth: 0.3,
|
||||
guessingReward: 0.2
|
||||
},
|
||||
buffDescriptions: [
|
||||
'INT 成長 +30%',
|
||||
'猜拳獎勵 +20%'
|
||||
],
|
||||
dialogues: [
|
||||
"學海無涯,勤能補拙",
|
||||
"多動腦,少偷懶",
|
||||
"智慧是一切的根本"
|
||||
],
|
||||
icon: 'deity-wenchang'
|
||||
},
|
||||
{
|
||||
id: 'guanyin',
|
||||
name: '觀音菩薩',
|
||||
personality: '慈悲救苦',
|
||||
buffs: {
|
||||
healthRecovery: 0.2,
|
||||
autoHeal: true
|
||||
},
|
||||
buffDescriptions: [
|
||||
'Health 回復 +20%',
|
||||
'自動治療 (1次/天)'
|
||||
],
|
||||
dialogues: [
|
||||
"阿彌陀佛,施主請安心",
|
||||
"救苦救難,觀音保佑",
|
||||
"..."
|
||||
],
|
||||
icon: 'deity-guanyin'
|
||||
}
|
||||
];
|
||||
|
||||
const showDeitySelector = ref(false);
|
||||
const currentDialogue = ref('');
|
||||
const activeBuffs = ref([]);
|
||||
|
||||
const currentDeity = computed(() => {
|
||||
return DEITIES.find(d => d.id === props.currentDeityId) || DEITIES[0];
|
||||
});
|
||||
|
||||
const currentFavor = computed(() => {
|
||||
return props.deityFavors[props.currentDeityId] || 0;
|
||||
});
|
||||
|
||||
const favorStars = computed(() => {
|
||||
const level = Math.floor(currentFavor.value / 20);
|
||||
return '★'.repeat(level) + '☆'.repeat(5 - level);
|
||||
});
|
||||
|
||||
function selectDeity(deityId) {
|
||||
emit('change-deity', deityId);
|
||||
showDeitySelector.value = false;
|
||||
updateDialogue();
|
||||
}
|
||||
|
||||
function updateDialogue() {
|
||||
const dialogues = currentDeity.value.dialogues;
|
||||
currentDialogue.value = dialogues[Math.floor(Math.random() * dialogues.length)];
|
||||
}
|
||||
|
||||
function handlePrayer() {
|
||||
if (props.dailyPrayerCount >= 3) return;
|
||||
|
||||
emit('prayer', currentDeity.value.id);
|
||||
updateDialogue();
|
||||
|
||||
// Update active buffs display
|
||||
activeBuffs.value = currentDeity.value.buffDescriptions.map(desc => ({
|
||||
type: currentDeity.value.id,
|
||||
description: desc
|
||||
}));
|
||||
}
|
||||
|
||||
function handlePrayerSelect(mode) {
|
||||
emit('prayer-select', mode);
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
updateDialogue();
|
||||
|
||||
// Load active buffs if favor > 0
|
||||
if (currentFavor.value > 0) {
|
||||
activeBuffs.value = currentDeity.value.buffDescriptions.map(desc => ({
|
||||
type: currentDeity.value.id,
|
||||
description: desc
|
||||
}));
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.deity-temple-overlay {
|
||||
position: absolute; /* Absolute to parent (DeviceScreen) */
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0, 0, 0, 0.85);
|
||||
z-index: 50; /* Same as PetInfoScreen */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.temple-container {
|
||||
background: linear-gradient(to bottom, #8B4513 0%, #A0522D 100%);
|
||||
border: 3px solid #654321;
|
||||
border-radius: 6px;
|
||||
width: calc(100% - 8px);
|
||||
max-width: 198px; /* Fit within 210px screen with padding */
|
||||
height: calc(100% - 8px);
|
||||
max-height: 152px; /* Fit within 160px screen with padding */
|
||||
box-shadow: 0 4px 8px rgba(0,0,0,0.5);
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden; /* Contain children */
|
||||
pointer-events: auto; /* Ensure container can receive clicks */
|
||||
}
|
||||
|
||||
.temple-container::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
}
|
||||
|
||||
.temple-container::-webkit-scrollbar-track {
|
||||
background: rgba(0,0,0,0.2);
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.temple-container::-webkit-scrollbar-thumb {
|
||||
background: #FFD700;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.temple-header {
|
||||
background: #654321;
|
||||
padding: 6px;
|
||||
text-align: center;
|
||||
border-bottom: 2px solid #4a3216;
|
||||
flex-shrink: 0; /* Don't shrink header */
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.temple-content {
|
||||
flex: 1;
|
||||
overflow-y: auto; /* Scrollable content area */
|
||||
overflow-x: hidden;
|
||||
padding-bottom: 8px;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
.close-btn {
|
||||
position: absolute;
|
||||
right: 4px;
|
||||
top: 4px;
|
||||
background: #8B0000;
|
||||
border: 2px solid #fff;
|
||||
color: #fff;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
border-radius: 3px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
line-height: 1;
|
||||
z-index: 10;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.temple-title {
|
||||
font-family: 'DotGothic16', monospace;
|
||||
color: #FFD700;
|
||||
margin: 0;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.deity-display { padding: 6px; text-align: center; }
|
||||
.deity-icon { width: 32px; height: 32px; margin: 0 auto 4px; background: #FFD700; border: 2px solid #FFA500; border-radius: 50%; }
|
||||
.deity-name { font-family: 'DotGothic16', monospace; font-size: 11px; color: #FFD700; font-weight: bold; margin-bottom: 2px; }
|
||||
.deity-subtitle { font-family: 'DotGothic16', monospace; font-size: 9px; color: #DEB887; }
|
||||
|
||||
.dialogue-bubble {
|
||||
margin: 0 6px 6px;
|
||||
background: #FFF8DC;
|
||||
border: 2px solid #654321;
|
||||
border-radius: 4px;
|
||||
padding: 6px;
|
||||
position: relative;
|
||||
min-height: 30px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.dialogue-bubble::before {
|
||||
content: ''; position: absolute; top: -6px; left: 50%; transform: translateX(-50%);
|
||||
border-width: 0 6px 6px 6px; border-style: solid; border-color: transparent transparent #654321 transparent;
|
||||
}
|
||||
.dialogue-bubble p { font-family: 'DotGothic16', monospace; font-size: 9px; color: #333; margin: 0; text-align: center; line-height: 1.3; }
|
||||
|
||||
.favor-section, .buffs-section { padding: 0 6px 6px; }
|
||||
.prayer-section {
|
||||
padding: 0 6px 6px;
|
||||
position: relative;
|
||||
z-index: 5;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.prayer-btn {
|
||||
width: 100%;
|
||||
padding: 6px;
|
||||
background: #FFD700;
|
||||
border: 2px solid #FFA500;
|
||||
border-radius: 4px;
|
||||
font-family: 'DotGothic16', monospace;
|
||||
font-size: 10px;
|
||||
font-weight: bold;
|
||||
color: #8B4513;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
.prayer-btn:hover:not(:disabled) {
|
||||
background: #FFA500;
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
.prayer-btn:active:not(:disabled) {
|
||||
transform: translateY(0);
|
||||
}
|
||||
.prayer-btn:disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
background: #ccc;
|
||||
border-color: #999;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.prayer-divider {
|
||||
font-family: 'DotGothic16', monospace;
|
||||
font-size: 8px;
|
||||
color: #DEB887;
|
||||
text-align: center;
|
||||
margin: 2px 0;
|
||||
}
|
||||
.bottom-actions {
|
||||
padding: 4px 6px;
|
||||
flex-shrink: 0;
|
||||
border-top: 2px solid #4a3216;
|
||||
background: rgba(101, 67, 33, 0.5);
|
||||
position: relative;
|
||||
z-index: 5;
|
||||
}
|
||||
.favor-label { font-family: 'DotGothic16', monospace; font-size: 9px; color: #FFD700; margin-bottom: 2px; }
|
||||
.favor-bar { height: 8px; background: rgba(0,0,0,0.3); border: 1px solid #654321; border-radius: 4px; overflow: hidden; }
|
||||
.favor-fill { height: 100%; background: linear-gradient(to right, #FFD700, #FFA500); transition: width 0.3s ease; }
|
||||
|
||||
.buffs-section { background: rgba(255,255,255,0.1); border-radius: 3px; padding: 4px; }
|
||||
.buff-title { font-family: 'DotGothic16', monospace; font-size: 9px; color: #FFD700; margin-bottom: 2px; }
|
||||
.buff-list { font-family: 'DotGothic16', monospace; font-size: 8px; color: #FFF8DC; }
|
||||
|
||||
.prayer-options {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.prayer-option {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 2px;
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
border: 2px solid #654321;
|
||||
border-radius: 4px;
|
||||
padding: 4px 6px;
|
||||
cursor: pointer;
|
||||
transition: transform 0.2s, box-shadow 0.2s;
|
||||
min-width: 50px;
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
|
||||
.prayer-option:hover {
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
|
||||
background: #FFD700;
|
||||
border-color: #FFA500;
|
||||
}
|
||||
|
||||
.prayer-option:active {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.option-icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
position: relative;
|
||||
transform: scale(0.6);
|
||||
}
|
||||
|
||||
.option-label {
|
||||
font-family: 'DotGothic16', monospace;
|
||||
font-size: 8px;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.prayer-count-info {
|
||||
font-family: 'DotGothic16', monospace;
|
||||
font-size: 8px;
|
||||
color: #FFD700;
|
||||
text-align: center;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
width: 100%; padding: 6px; background: #654321; border: 2px solid #4a3216; border-radius: 3px;
|
||||
font-family: 'DotGothic16', monospace; font-size: 9px; color: #FFD700; cursor: pointer;
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
.action-btn:active {
|
||||
transform: translateY(1px);
|
||||
background: #4a3216;
|
||||
}
|
||||
|
||||
/* Deity Selector Overlay */
|
||||
.deity-selector-overlay {
|
||||
position: absolute;
|
||||
top: 0; left: 0; width: 100%; height: 100%;
|
||||
background: rgba(0,0,0,0.7);
|
||||
z-index: 20;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.deity-selector-menu {
|
||||
background: #4a3216;
|
||||
border: 2px solid #FFD700;
|
||||
border-radius: 4px;
|
||||
padding: 6px;
|
||||
width: 85%;
|
||||
max-height: 75%;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.selector-header {
|
||||
text-align: center; color: #FFD700; font-family: 'DotGothic16', monospace; margin-bottom: 6px; font-weight: bold; font-size: 10px;
|
||||
}
|
||||
|
||||
.deity-option {
|
||||
display: flex; align-items: center; gap: 6px; padding: 4px; margin: 3px 0;
|
||||
background: #654321; border: 1px solid transparent; border-radius: 3px; cursor: pointer;
|
||||
position: relative;
|
||||
z-index: 25;
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
.deity-option:hover {
|
||||
border-color: #FFD700;
|
||||
background: #7a5238;
|
||||
}
|
||||
.deity-option:active {
|
||||
transform: scale(0.98);
|
||||
}
|
||||
.deity-option.active { background: #8B4513; border-color: #FFD700; }
|
||||
.deity-option span { font-family: 'DotGothic16', monospace; font-size: 9px; color: #FFD700; }
|
||||
.deity-icon-small { width: 16px; height: 16px; background: #FFD700; border: 1px solid #FFA500; border-radius: 50%; }
|
||||
|
||||
/* Deity Icons - Pixel Art Placeholders */
|
||||
.deity-mazu,
|
||||
.deity-earthgod,
|
||||
.deity-matchmaker,
|
||||
.deity-wenchang,
|
||||
.deity-guanyin {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.deity-mazu::after { content: '媽'; }
|
||||
.deity-earthgod::after { content: '土'; }
|
||||
.deity-matchmaker::after { content: '月'; }
|
||||
.deity-wenchang::after { content: '文'; }
|
||||
.deity-guanyin::after { content: '觀'; }
|
||||
|
||||
/* Prayer Option Icons */
|
||||
.icon-jiaobei::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 2px;
|
||||
height: 2px;
|
||||
background: transparent;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
box-shadow:
|
||||
/* 左邊筊杯 */
|
||||
-7px -4px 0 #ff5252, -5px -4px 0 #ff5252, -3px -4px 0 #ff5252,
|
||||
-9px -2px 0 #ff5252, -7px -2px 0 #ff8a80, -5px -2px 0 #ff5252, -3px -2px 0 #ff5252, -1px -2px 0 #ff5252,
|
||||
-9px 0px 0 #ff5252, -7px 0px 0 #ff5252, -5px 0px 0 #ff5252, -3px 0px 0 #ff5252, -1px 0px 0 #ff5252,
|
||||
-7px 2px 0 #ff5252, -5px 2px 0 #ff5252, -3px 2px 0 #ff5252,
|
||||
-5px 4px 0 #d32f2f,
|
||||
/* 右邊筊杯 */
|
||||
3px -4px 0 #ff5252, 5px -4px 0 #ff5252, 7px -4px 0 #ff5252,
|
||||
1px -2px 0 #ff5252, 3px -2px 0 #ff5252, 5px -2px 0 #ff5252, 7px -2px 0 #ff8a80, 9px -2px 0 #ff5252,
|
||||
1px 0px 0 #ff5252, 3px 0px 0 #ff5252, 5px 0px 0 #ff5252, 7px 0px 0 #ff5252, 9px 0px 0 #ff5252,
|
||||
3px 2px 0 #ff5252, 5px 2px 0 #ff5252, 7px 2px 0 #ff5252,
|
||||
5px 4px 0 #d32f2f;
|
||||
}
|
||||
|
||||
.icon-fortune::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 2px;
|
||||
height: 2px;
|
||||
background: #8B4513;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
box-shadow:
|
||||
/* 籤筒本體 */
|
||||
-4px -4px 0 #8B4513, -2px -4px 0 #8B4513, 0px -4px 0 #8B4513, 2px -4px 0 #8B4513, 4px -4px 0 #8B4513,
|
||||
-4px -2px 0 #8B4513, -2px -2px 0 #8B4513, 0px -2px 0 #8B4513, 2px -2px 0 #8B4513, 4px -2px 0 #8B4513,
|
||||
-4px 0px 0 #8B4513, -2px 0px 0 #8B4513, 0px 0px 0 #8B4513, 2px 0px 0 #8B4513, 4px 0px 0 #8B4513,
|
||||
-4px 2px 0 #8B4513, -2px 2px 0 #8B4513, 0px 2px 0 #8B4513, 2px 2px 0 #8B4513, 4px 2px 0 #8B4513,
|
||||
-4px 4px 0 #8B4513, -2px 4px 0 #8B4513, 0px 4px 0 #8B4513, 2px 4px 0 #8B4513, 4px 4px 0 #8B4513,
|
||||
/* 突出的籤條 */
|
||||
-2px -8px 0 #d4522e, 0px -8px 0 #d4522e,
|
||||
-2px -6px 0 #d4522e, 0px -6px 0 #d4522e,
|
||||
2px -6px 0 #d4522e;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -6,7 +6,7 @@
|
|||
@info="showPetInfo = !showPetInfo"
|
||||
@feed="$emit('action', 'feed')"
|
||||
@playMenu="showPlayMenu = true"
|
||||
@sleep="$emit('action', 'sleep')"
|
||||
@temple="showTemple = true"
|
||||
/>
|
||||
|
||||
<!-- Stats Dashboard (Toggelable) -->
|
||||
|
|
@ -177,12 +177,11 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Prayer Menu (覆蓋整個遊戲區域) -->
|
||||
<PrayerMenu
|
||||
v-if="showPrayerMenu"
|
||||
@select="handlePrayerSelect"
|
||||
@close="showPrayerMenu = false"
|
||||
/>
|
||||
<!-- 關燈黑色遮罩 (原本 PrayerMenu 的位置) -->
|
||||
<div
|
||||
v-if="state === 'sleep'"
|
||||
class="dark-overlay-fullscreen"
|
||||
></div>
|
||||
|
||||
<!-- Jiaobei Animation (覆蓋遊戲區域) -->
|
||||
<JiaobeiAnimation
|
||||
|
|
@ -268,6 +267,18 @@
|
|||
@update:inventory="handleInventoryUpdate"
|
||||
/>
|
||||
|
||||
<!-- Deity Temple -->
|
||||
<DeityTemple
|
||||
v-if="showTemple"
|
||||
:deityFavors="stats?.deityFavors || {}"
|
||||
:currentDeityId="stats?.currentDeity || 'mazu'"
|
||||
:dailyPrayerCount="stats?.dailyPrayerCount || 0"
|
||||
@close="showTemple = false"
|
||||
@prayer="handlePrayer"
|
||||
@change-deity="handleChangeDeity"
|
||||
@prayer-select="handlePrayerSelect"
|
||||
/>
|
||||
|
||||
<!-- Action Menu (Bottom) -->
|
||||
<ActionMenu
|
||||
:disabled="stage === 'egg'"
|
||||
|
|
@ -276,7 +287,7 @@
|
|||
:isSick="state === 'sick'"
|
||||
@clean="$emit('action', 'clean')"
|
||||
@medicine="$emit('action', 'medicine')"
|
||||
@training="showPrayerMenu = true"
|
||||
@sleep="$emit('action', 'sleep')"
|
||||
@inventory="showInventory = !showInventory"
|
||||
/>
|
||||
|
||||
|
|
@ -286,17 +297,17 @@
|
|||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, onMounted, onUnmounted, watch, nextTick } from 'vue';
|
||||
import { ref, computed, onMounted, onUnmounted, watch, nextTick, toRef } from 'vue';
|
||||
import { SPRITE_PRESETS_FLAT as SPRITE_PRESETS, SPRITE_PRESETS as FULL_PRESETS } from '../data/petPresets.js';
|
||||
import { FOOD_OPTIONS } from '../data/foodOptions.js';
|
||||
import StatsBar from './StatsBar.vue';
|
||||
import ActionMenu from './ActionMenu.vue';
|
||||
import TopMenu from './TopMenu.vue';
|
||||
import PrayerMenu from './PrayerMenu.vue';
|
||||
import JiaobeiAnimation from './JiaobeiAnimation.vue';
|
||||
import FortuneStickAnimation from './FortuneStickAnimation.vue';
|
||||
import FortuneResult from './FortuneResult.vue';
|
||||
import PetInfoScreen from './PetInfoScreen.vue';
|
||||
import DeityTemple from './DeityTemple.vue';
|
||||
import InventoryScreen from './InventoryScreen.vue';
|
||||
import PlayMenu from './PlayMenu.vue';
|
||||
import GuessingGame from './GuessingGame.vue';
|
||||
|
|
@ -341,8 +352,26 @@ const props = defineProps({
|
|||
|
||||
const emit = defineEmits(['update:state', 'action']);
|
||||
|
||||
// Prayer Menu State
|
||||
const showPrayerMenu = ref(false);
|
||||
// Create local ref for stats to match usage pattern in component
|
||||
const stats = toRef(props, 'stats');
|
||||
|
||||
// Helper function to temporarily change pet state
|
||||
function triggerState(tempState, duration) {
|
||||
const previousState = props.state;
|
||||
emit('update:state', tempState);
|
||||
|
||||
// Store timeout ID to potentially clear it if needed
|
||||
const timeoutId = setTimeout(() => {
|
||||
// Revert to previous state (or idle if previous was sleep)
|
||||
const revertState = previousState === 'sleep' ? 'idle' : (previousState === 'dead' ? 'dead' : 'idle');
|
||||
emit('update:state', revertState);
|
||||
}, duration);
|
||||
|
||||
// Return timeout ID in case we need to clear it
|
||||
return timeoutId;
|
||||
}
|
||||
|
||||
// Prayer State
|
||||
const fortuneMode = ref('jiaobei');
|
||||
const showJiaobeiAnimation = ref(false);
|
||||
const showFortuneStick = ref(false);
|
||||
|
|
@ -354,6 +383,7 @@ const lastJiaobeiResult = ref(null); // 記錄最後的擲筊結果用於招魂
|
|||
|
||||
const showPetInfo = ref(false);
|
||||
const showInventory = ref(false);
|
||||
const showTemple = ref(false);
|
||||
const showPlayMenu = ref(false);
|
||||
const currentGame = ref(''); // '', 'training', 'guessing', 'ball'
|
||||
const inventory = ref(new Array(16).fill(null));
|
||||
|
|
@ -395,7 +425,8 @@ watch(() => props.debugAction, (action) => {
|
|||
});
|
||||
|
||||
const handlePrayerSelect = (mode) => {
|
||||
showPrayerMenu.value = false;
|
||||
// Close temple when selecting prayer mode
|
||||
showTemple.value = false;
|
||||
|
||||
if (mode === 'jiaobei') {
|
||||
fortuneMode.value = 'normal';
|
||||
|
|
@ -482,9 +513,13 @@ function handleGameComplete(won) {
|
|||
|
||||
if (gameType === 'training') {
|
||||
stats.value.str = (stats.value.str || 0) + statGain;
|
||||
// Training also gives Deity Favor slightly? Maybe not.
|
||||
} else if (gameType === 'guessing') {
|
||||
stats.value.int = (stats.value.int || 0) + statGain;
|
||||
let intGain = statGain;
|
||||
// Deity Buff: 文昌 - INT 成長 +30%
|
||||
if (stats.value.currentDeity === 'wenchang' && stats.value.deityFavors?.wenchang > 0) {
|
||||
intGain = Math.ceil(intGain * 1.3);
|
||||
}
|
||||
stats.value.int = (stats.value.int || 0) + intGain;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -530,6 +565,7 @@ function handleStickComplete(number) {
|
|||
|
||||
// 進入擲筊確認階段
|
||||
consecutiveSaintCount.value = 0;
|
||||
fortuneMode.value = 'fortune'; // 確保模式正確
|
||||
showJiaobeiAnimation.value = true;
|
||||
}
|
||||
|
||||
|
|
@ -602,6 +638,7 @@ function handleRetryFortune() {
|
|||
// 重新開始搖籤
|
||||
showJiaobeiAnimation.value = false;
|
||||
consecutiveSaintCount.value = 0;
|
||||
fortuneMode.value = 'fortune'; // 確保模式正確
|
||||
showFortuneStick.value = true;
|
||||
}
|
||||
|
||||
|
|
@ -659,6 +696,56 @@ function handleCloseResult() {
|
|||
fortuneMode.value = 'normal';
|
||||
}
|
||||
|
||||
function handlePrayer(deityId) {
|
||||
// Initialize deityFavors if it doesn't exist
|
||||
if (!stats.value.deityFavors) {
|
||||
stats.value.deityFavors = {
|
||||
mazu: 0,
|
||||
earthgod: 0,
|
||||
matchmaker: 0,
|
||||
wenchang: 0,
|
||||
guanyin: 0
|
||||
};
|
||||
}
|
||||
|
||||
// Initialize the specific deity favor if it doesn't exist
|
||||
if (stats.value.deityFavors[deityId] === undefined) {
|
||||
stats.value.deityFavors[deityId] = 0;
|
||||
}
|
||||
|
||||
// Increase favor for the deity
|
||||
stats.value.deityFavors[deityId] = Math.min(100, (stats.value.deityFavors[deityId] || 0) + 5);
|
||||
|
||||
// Increase daily prayer count
|
||||
stats.value.dailyPrayerCount = (stats.value.dailyPrayerCount || 0) + 1;
|
||||
|
||||
// Apply temporary buff based on deity
|
||||
// (Buffs would be applied in the game loop or stat calculations)
|
||||
|
||||
console.log(`Prayed to ${deityId}, favor: ${stats.value.deityFavors[deityId]}, count: ${stats.value.dailyPrayerCount}`);
|
||||
}
|
||||
|
||||
function handleChangeDeity(deityId) {
|
||||
// Initialize deityFavors if it doesn't exist
|
||||
if (!stats.value.deityFavors) {
|
||||
stats.value.deityFavors = {
|
||||
mazu: 0,
|
||||
earthgod: 0,
|
||||
matchmaker: 0,
|
||||
wenchang: 0,
|
||||
guanyin: 0
|
||||
};
|
||||
}
|
||||
|
||||
// Initialize the specific deity favor if it doesn't exist
|
||||
if (stats.value.deityFavors[deityId] === undefined) {
|
||||
stats.value.deityFavors[deityId] = 0;
|
||||
}
|
||||
|
||||
stats.value.currentDeity = deityId;
|
||||
console.log(`Changed deity to ${deityId}`);
|
||||
}
|
||||
|
||||
function handleUseItem(item) {
|
||||
console.log('Used item:', item.name);
|
||||
|
||||
|
|
@ -1549,7 +1636,7 @@ defineExpose({
|
|||
50% { opacity: 1; }
|
||||
}
|
||||
|
||||
/* Dark Overlay (關燈效果) */
|
||||
/* Dark Overlay (關燈效果 - 覆蓋整個遊戲容器) */
|
||||
.dark-overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
|
|
@ -1559,6 +1646,19 @@ defineExpose({
|
|||
background: #000;
|
||||
z-index: 7; /* Above poop (5), Below ZZZ (10) */
|
||||
pointer-events: none;
|
||||
border-radius: 10px; /* 與螢幕邊框一致 */
|
||||
}
|
||||
|
||||
/* Fullscreen Dark Overlay (原本 PrayerMenu 的位置) */
|
||||
.dark-overlay-fullscreen {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: #000;
|
||||
z-index: 100; /* Same as PrayerMenu was */
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* Sleep ZZZ */
|
||||
|
|
@ -1570,7 +1670,7 @@ defineExpose({
|
|||
z-index: 10; /* Above dark overlay */
|
||||
}
|
||||
.sleep-zzz.dark-mode {
|
||||
color: #fff; /* 顏色顛倒:在黑色背景下變白色 */
|
||||
color: #fff !important; /* 強制白色:在黑色背景下變白色 */
|
||||
text-shadow: 0 0 4px rgba(255, 255, 255, 0.8); /* 添加發光效果讓它更明顯 */
|
||||
}
|
||||
.sleep-zzz span {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
<button class="icon-btn icon-stats" @click="$emit('info')" title="Status"></button>
|
||||
<button class="icon-btn icon-feed" @click="$emit('feed')" :disabled="disabled" title="Feed"></button>
|
||||
<button class="icon-btn icon-play" @click="$emit('playMenu')" :disabled="disabled" title="Play"></button>
|
||||
<button class="icon-btn icon-sleep" @click="$emit('sleep')" :disabled="disabled" title="Sleep"></button>
|
||||
<button class="icon-btn icon-temple" @click="$emit('temple')" :disabled="disabled" title="Temple"></button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -15,7 +15,7 @@ const props = defineProps({
|
|||
}
|
||||
});
|
||||
|
||||
defineEmits(['info', 'feed', 'playMenu', 'sleep']);
|
||||
defineEmits(['info', 'feed', 'playMenu', 'temple']);
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
|
@ -96,23 +96,26 @@ defineEmits(['info', 'feed', 'playMenu', 'sleep']);
|
|||
-2px 4px 0 #4444ff, 0px 4px 0 #4444ff, 2px 4px 0 #4444ff;
|
||||
}
|
||||
|
||||
/* Sleep Icon (Moon) */
|
||||
.icon-sleep::before {
|
||||
/* Temple Icon (廟宇) */
|
||||
.icon-temple::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 2px;
|
||||
height: 2px;
|
||||
background: #ffcc00;
|
||||
background: #D2691E;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
box-shadow:
|
||||
0px -6px 0 #ffcc00, 2px -6px 0 #ffcc00,
|
||||
-2px -4px 0 #ffcc00, 0px -4px 0 #ffcc00, 2px -4px 0 #ffcc00, 4px -4px 0 #ffcc00,
|
||||
-2px -2px 0 #ffcc00, 0px -2px 0 #ffcc00, 4px -2px 0 #ffcc00,
|
||||
-2px 0px 0 #ffcc00, 0px 0px 0 #ffcc00, 4px 0px 0 #ffcc00,
|
||||
-2px 2px 0 #ffcc00, 0px 2px 0 #ffcc00, 4px 2px 0 #ffcc00,
|
||||
-2px 4px 0 #ffcc00, 0px 4px 0 #ffcc00, 2px 4px 0 #ffcc00, 4px 4px 0 #ffcc00,
|
||||
0px 6px 0 #ffcc00, 2px 6px 0 #ffcc00;
|
||||
/* 屋頂 */
|
||||
-4px -6px 0 #8B4513, -2px -6px 0 #8B4513, 0px -6px 0 #8B4513, 2px -6px 0 #8B4513, 4px -6px 0 #8B4513,
|
||||
/* 屋簷 */
|
||||
-6px -4px 0 #D2691E, -4px -4px 0 #D2691E, -2px -4px 0 #D2691E, 0px -4px 0 #D2691E, 2px -4px 0 #D2691E, 4px -4px 0 #D2691E, 6px -4px 0 #D2691E,
|
||||
/* 柱子與牆 */
|
||||
-4px -2px 0 #8B4513, 4px -2px 0 #8B4513,
|
||||
-4px 0px 0 #8B4513, -2px 0px 0 #FFD700, 0px 0px 0 #FFD700, 2px 0px 0 #FFD700, 4px 0px 0 #8B4513,
|
||||
-4px 2px 0 #8B4513, 4px 2px 0 #8B4513,
|
||||
/* 底座 */
|
||||
-4px 4px 0 #654321, -2px 4px 0 #654321, 0px 4px 0 #654321, 2px 4px 0 #654321, 4px 4px 0 #654321;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -30,7 +30,17 @@ export function usePetSystem() {
|
|||
dex: 0, // 敏捷 (Catch Ball)
|
||||
generation: 1, // 輪迴世代
|
||||
deityFavor: 0, // 神明好感度
|
||||
destiny: null // 天生命格 (Object)
|
||||
destiny: null, // 天生命格 (Object)
|
||||
// Deity System
|
||||
currentDeity: 'mazu',
|
||||
deityFavors: {
|
||||
mazu: 0,
|
||||
earthgod: 0,
|
||||
matchmaker: 0,
|
||||
wenchang: 0,
|
||||
guanyin: 0
|
||||
},
|
||||
dailyPrayerCount: 0
|
||||
});
|
||||
|
||||
const achievements = ref([
|
||||
|
|
@ -189,10 +199,14 @@ export function usePetSystem() {
|
|||
|
||||
// Sickness Check (更低的生病機率)
|
||||
// Destiny Effect: Purification (淨化) - Sickness chance -20%
|
||||
// Deity Buff: 媽祖 - Sickness chance -15%
|
||||
let sickChance = 0.1;
|
||||
if (stats.value.destiny?.id === 'purification') {
|
||||
sickChance *= 0.8;
|
||||
}
|
||||
if (stats.value.currentDeity === 'mazu' && stats.value.deityFavors?.mazu > 0) {
|
||||
sickChance *= 0.85;
|
||||
}
|
||||
|
||||
if (stats.value.health < 30 && state.value !== 'sick') {
|
||||
if (Math.random() < sickChance) {
|
||||
|
|
@ -202,8 +216,21 @@ export function usePetSystem() {
|
|||
|
||||
// Health Recovery (健康值可以緩慢恢復)
|
||||
// 如果沒有便便、飢餓值和快樂值都高,健康值會緩慢恢復
|
||||
let healthRecovery = 0.05;
|
||||
|
||||
// Deity Buff: 觀音 - Health 回復 +20%
|
||||
if (stats.value.currentDeity === 'guanyin' && stats.value.deityFavors?.guanyin > 0) {
|
||||
healthRecovery *= 1.2;
|
||||
}
|
||||
|
||||
// Deity Buff: 月老 - Happiness 回復 +25%
|
||||
if (stats.value.currentDeity === 'matchmaker' && stats.value.deityFavors?.matchmaker > 0) {
|
||||
// Apply to happiness decay reduction (slower decay = faster recovery)
|
||||
happinessDecay *= 0.75;
|
||||
}
|
||||
|
||||
if (stats.value.poopCount === 0 && stats.value.hunger > 50 && stats.value.happiness > 50 && stats.value.health < 100 && state.value !== 'sick') {
|
||||
stats.value.health = Math.min(100, stats.value.health + 0.05);
|
||||
stats.value.health = Math.min(100, stats.value.health + healthRecovery);
|
||||
}
|
||||
|
||||
// Death Check (移除死亡機制,依照之前的討論)
|
||||
|
|
|
|||
Loading…
Reference in New Issue