fix: good friend
This commit is contained in:
parent
c779fd9a0e
commit
8167312462
|
|
@ -56,6 +56,14 @@
|
||||||
› {{ log }}
|
› {{ log }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Run Away Button -->
|
||||||
|
<button
|
||||||
|
@click="$emit('runAway')"
|
||||||
|
class="mt-4 w-full border border-gray-500 text-gray-400 py-2 hover:bg-gray-800 hover:text-white transition-colors text-xs tracking-widest uppercase"
|
||||||
|
>
|
||||||
|
逃跑 (Run Away)
|
||||||
|
</button>
|
||||||
</PixelFrame>
|
</PixelFrame>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@
|
||||||
:isFighting="isFighting"
|
:isFighting="isFighting"
|
||||||
:battleLogs="battleLogs"
|
:battleLogs="battleLogs"
|
||||||
:backgroundImage="currentLocation?.backgroundImage || ''"
|
:backgroundImage="currentLocation?.backgroundImage || ''"
|
||||||
|
@runAway="handleRunAway"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -498,35 +499,121 @@ const handleStartAdventure = (selection: any) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const startCombatLoop = (location: any) => {
|
const startCombatLoop = (location: any) => {
|
||||||
// Select random enemy from pool
|
// 1. Start Adventure Timer (10 seconds)
|
||||||
|
const adventureDuration = 10000; // 10 seconds
|
||||||
|
const startTime = Date.now();
|
||||||
|
let isAdventureActive = true;
|
||||||
|
|
||||||
|
// Timer to end adventure
|
||||||
|
const adventureTimer = setTimeout(() => {
|
||||||
|
isAdventureActive = false;
|
||||||
|
}, adventureDuration);
|
||||||
|
|
||||||
|
// Function to start a single fight
|
||||||
|
const startNextFight = () => {
|
||||||
|
if (!isAdventureActive) {
|
||||||
|
finishAdventure();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Select random enemy
|
||||||
const enemyId = location.enemyPool[Math.floor(Math.random() * location.enemyPool.length)];
|
const enemyId = location.enemyPool[Math.floor(Math.random() * location.enemyPool.length)];
|
||||||
const result = petSystem.value.startCombat(enemyId);
|
const result = petSystem.value.startCombat(enemyId);
|
||||||
|
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
|
// Append logs instead of replacing if it's not the first fight
|
||||||
|
if (battleLogs.value.length > 0) {
|
||||||
|
battleLogs.value.push(`--- 遭遇新敵人! ---`);
|
||||||
|
battleLogs.value = [...battleLogs.value, ...result.combatState.logs];
|
||||||
|
} else {
|
||||||
battleLogs.value = result.combatState.logs;
|
battleLogs.value = result.combatState.logs;
|
||||||
|
}
|
||||||
|
|
||||||
// Clear existing interval if any
|
// Combat Interval for this fight
|
||||||
if (combatInterval.value) clearInterval(combatInterval.value);
|
if (combatInterval.value) clearInterval(combatInterval.value);
|
||||||
|
|
||||||
// Start Combat Interval
|
|
||||||
combatInterval.value = setInterval(() => {
|
combatInterval.value = setInterval(() => {
|
||||||
const roundResult = petSystem.value.combatRound();
|
const roundResult = petSystem.value.combatRound();
|
||||||
if (roundResult) {
|
if (roundResult) {
|
||||||
battleLogs.value = [...roundResult.logs]; // Update logs
|
battleLogs.value = [...battleLogs.value, ...roundResult.logs]; // Append new logs
|
||||||
|
|
||||||
if (roundResult.isOver) {
|
if (roundResult.isOver) {
|
||||||
clearInterval(combatInterval.value);
|
clearInterval(combatInterval.value);
|
||||||
combatInterval.value = null;
|
combatInterval.value = null;
|
||||||
|
|
||||||
// Delay before closing or showing result
|
// Accumulate rewards
|
||||||
setTimeout(() => {
|
if (!battleResult.value) {
|
||||||
|
battleResult.value = { logs: [], rewards: { gold: 0, items: [] } };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (roundResult.rewards) {
|
||||||
|
battleResult.value.rewards.gold = (battleResult.value.rewards.gold || 0) + (roundResult.rewards.gold || 0);
|
||||||
|
if (roundResult.rewards.items) {
|
||||||
|
battleResult.value.rewards.items.push(...roundResult.rewards.items);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (roundResult.win) {
|
||||||
|
// If won, check if we should continue
|
||||||
|
if (isAdventureActive) {
|
||||||
|
setTimeout(startNextFight, 1000); // Small delay before next fight
|
||||||
|
} else {
|
||||||
|
finishAdventure();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// If lost, end adventure immediately
|
||||||
|
clearTimeout(adventureTimer);
|
||||||
|
finishAdventure();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 1000); // 1s per round
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const finishAdventure = () => {
|
||||||
isFighting.value = false;
|
isFighting.value = false;
|
||||||
battleResult.value = { logs: roundResult.logs, rewards: roundResult.rewards || {} };
|
if (combatInterval.value) clearInterval(combatInterval.value);
|
||||||
|
combatInterval.value = null;
|
||||||
|
|
||||||
|
// Prepare final result
|
||||||
|
if (!battleResult.value) {
|
||||||
|
battleResult.value = { logs: battleLogs.value, rewards: { gold: 0, items: [] } };
|
||||||
|
} else {
|
||||||
|
battleResult.value.logs = battleLogs.value;
|
||||||
|
}
|
||||||
|
|
||||||
showBattleResult.value = true;
|
showBattleResult.value = true;
|
||||||
}, 3000);
|
};
|
||||||
}
|
|
||||||
}
|
// Initialize Result
|
||||||
}, 1500); // 1.5s per round
|
battleResult.value = { logs: [], rewards: { gold: 0, items: [] } };
|
||||||
|
startNextFight();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleRunAway = () => {
|
||||||
|
isFighting.value = false;
|
||||||
|
if (combatInterval.value) clearInterval(combatInterval.value);
|
||||||
|
combatInterval.value = null;
|
||||||
|
|
||||||
|
// Clear any pending adventure timer
|
||||||
|
// Note: adventureTimer is local to startCombatLoop, so we can't clear it directly here easily
|
||||||
|
// unless we store it in a ref.
|
||||||
|
// However, startNextFight checks isAdventureActive.
|
||||||
|
// We can set a flag or just rely on isFighting being false to stop UI,
|
||||||
|
// but the loop might continue in background if we don't stop it.
|
||||||
|
// Better to refactor startCombatLoop to use a ref for the timer or active state.
|
||||||
|
|
||||||
|
// For now, let's just reset the state we can control.
|
||||||
|
// Ideally we should have `adventureState` ref.
|
||||||
|
|
||||||
|
// Reset result so no rewards are shown
|
||||||
|
battleResult.value = null;
|
||||||
|
battleLogs.value = [];
|
||||||
|
|
||||||
|
// Force stop system combat
|
||||||
|
if (petSystem.value) {
|
||||||
|
petSystem.value.state.combat.isActive = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -891,11 +978,33 @@ const handleRepair = async (itemId: string) => {
|
||||||
|
|
||||||
const handleSellItem = async (item: Item) => {
|
const handleSellItem = async (item: Item) => {
|
||||||
if (petSystem.value) {
|
if (petSystem.value) {
|
||||||
const sellPrice = Math.floor((item as any).price / 2);
|
// Look up item definition for price
|
||||||
|
const itemDef = ITEMS[item.id];
|
||||||
|
const price = itemDef ? itemDef.price : (item as any).price;
|
||||||
|
|
||||||
|
if (!price) {
|
||||||
|
console.warn('Item has no price:', item.id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const sellPrice = Math.floor(price / 2);
|
||||||
const newCoins = systemState.value.coins + sellPrice;
|
const newCoins = systemState.value.coins + sellPrice;
|
||||||
const newInventory = systemState.value.inventory.filter((i: any) => i.id !== item.id);
|
|
||||||
|
// Handle Quantity
|
||||||
|
let newInventory = [...systemState.value.inventory];
|
||||||
|
const itemIndex = newInventory.findIndex((i: any) => i.id === item.id);
|
||||||
|
|
||||||
|
if (itemIndex !== -1) {
|
||||||
|
if (newInventory[itemIndex].count > 1) {
|
||||||
|
newInventory[itemIndex].count--;
|
||||||
|
} else {
|
||||||
|
newInventory.splice(itemIndex, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
await petSystem.value.updateState({ coins: newCoins, inventory: newInventory });
|
await petSystem.value.updateState({ coins: newCoins, inventory: newInventory });
|
||||||
systemState.value = petSystem.value.getState();
|
systemState.value = petSystem.value.getState();
|
||||||
|
console.log(`💰 Sold ${itemDef ? itemDef.name : item.id} for ${sellPrice} gold`);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1111,12 +1111,13 @@ export class PetSystem {
|
||||||
// Ensure combat stats are up to date
|
// Ensure combat stats are up to date
|
||||||
this.calculateCombatStats();
|
this.calculateCombatStats();
|
||||||
|
|
||||||
// Calculate effective stats including buffs and equipment
|
// Calculate effective stats including buffs
|
||||||
|
// User requested strict usage of Attack, Defense, and Speed (not Str/Int/Dex)
|
||||||
const pStats = {
|
const pStats = {
|
||||||
atk: this.state.attack || (this.state.strength * 2),
|
atk: this.state.attack || 0,
|
||||||
def: this.state.defense || this.state.intelligence,
|
def: this.state.defense || 0,
|
||||||
spd: this.state.speed || this.state.agility,
|
spd: this.state.speed || 0,
|
||||||
hp: this.state.health,
|
hp: this.state.combat.playerHp, // Use combat HP
|
||||||
luck: this.state.effectiveLuck || this.state.luck || 0
|
luck: this.state.effectiveLuck || this.state.luck || 0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -1134,9 +1135,9 @@ export class PetSystem {
|
||||||
|
|
||||||
// HP Recovery (Start of Turn)
|
// HP Recovery (Start of Turn)
|
||||||
const hpRecovery = (this.state.buffs?.healthRecovery || 0);
|
const hpRecovery = (this.state.buffs?.healthRecovery || 0);
|
||||||
if (hpRecovery > 0 && this.state.health < 100) {
|
if (hpRecovery > 0 && this.state.combat.playerHp < this.state.combat.playerMaxHp) {
|
||||||
const recovered = Math.min(100 - this.state.health, hpRecovery);
|
const recovered = Math.min(this.state.combat.playerMaxHp - this.state.combat.playerHp, hpRecovery);
|
||||||
this.state.health += recovered;
|
this.state.combat.playerHp += recovered;
|
||||||
logs.push(`💚 回復了 ${recovered.toFixed(1)} HP`);
|
logs.push(`💚 回復了 ${recovered.toFixed(1)} HP`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1181,7 +1182,7 @@ export class PetSystem {
|
||||||
logs.push(`🏆 你擊敗了 ${enemy.name}!`);
|
logs.push(`🏆 你擊敗了 ${enemy.name}!`);
|
||||||
|
|
||||||
// Full HP Recovery on Win
|
// Full HP Recovery on Win
|
||||||
this.state.health = 100;
|
this.state.combat.playerHp = this.state.combat.playerMaxHp;
|
||||||
logs.push(`💖 勝利讓你的 HP 完全恢復了!`);
|
logs.push(`💖 勝利讓你的 HP 完全恢復了!`);
|
||||||
|
|
||||||
// Rewards
|
// Rewards
|
||||||
|
|
@ -1200,11 +1201,11 @@ export class PetSystem {
|
||||||
enemyDmg = Math.floor(enemyDmg * (1 - this.state.buffs.damageReduction));
|
enemyDmg = Math.floor(enemyDmg * (1 - this.state.buffs.damageReduction));
|
||||||
}
|
}
|
||||||
|
|
||||||
this.state.health = Math.max(0, this.state.health - enemyDmg);
|
this.state.combat.playerHp = Math.max(0, this.state.combat.playerHp - enemyDmg);
|
||||||
logs.push(`💔 你受到了 ${enemyDmg} 點傷害!(HP: ${this.state.health.toFixed(1)})`);
|
logs.push(`💔 你受到了 ${enemyDmg} 點傷害!(HP: ${this.state.combat.playerHp.toFixed(1)})`);
|
||||||
|
|
||||||
// Check Player Death
|
// Check Player Death
|
||||||
if (this.state.health <= 0) {
|
if (this.state.combat.playerHp <= 0) {
|
||||||
this.state.combat.isActive = false;
|
this.state.combat.isActive = false;
|
||||||
logs.push(`💀 你被 ${enemy.name} 擊敗了...`);
|
logs.push(`💀 你被 ${enemy.name} 擊敗了...`);
|
||||||
this.state.combat.logs = [...this.state.combat.logs, ...logs];
|
this.state.combat.logs = [...this.state.combat.logs, ...logs];
|
||||||
|
|
@ -1216,11 +1217,20 @@ export class PetSystem {
|
||||||
}
|
}
|
||||||
|
|
||||||
handleCombatRewards(enemy, logs, luck) {
|
handleCombatRewards(enemy, logs, luck) {
|
||||||
// Exp (based on enemy HP/Stats)
|
// Gold Reward
|
||||||
const expGain = Math.floor(enemy.stats.hp / 10) + 5;
|
let goldGain = 0;
|
||||||
this.state.trainingExp += expGain;
|
if (enemy.goldReward) {
|
||||||
this.state.combat.rewards.exp = expGain;
|
const min = enemy.goldReward.min || 1;
|
||||||
logs.push(`✨ 獲得了 ${expGain} 經驗值!`);
|
const max = enemy.goldReward.max || 5;
|
||||||
|
goldGain = Math.floor(Math.random() * (max - min + 1)) + min;
|
||||||
|
} else {
|
||||||
|
// Fallback if no goldReward defined
|
||||||
|
goldGain = Math.floor(enemy.stats.hp / 10) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.state.coins = (this.state.coins || 0) + goldGain;
|
||||||
|
this.state.combat.rewards.gold = (this.state.combat.rewards.gold || 0) + goldGain;
|
||||||
|
logs.push(`💰 獲得了 ${goldGain} 金幣!`);
|
||||||
|
|
||||||
// Drops
|
// Drops
|
||||||
if (enemy.drops) {
|
if (enemy.drops) {
|
||||||
|
|
|
||||||
|
|
@ -6,11 +6,12 @@ export const ENEMIES = {
|
||||||
name: '巨大的蟑螂',
|
name: '巨大的蟑螂',
|
||||||
description: '生命力頑強的害蟲,雖然弱小但很噁心。',
|
description: '生命力頑強的害蟲,雖然弱小但很噁心。',
|
||||||
stats: {
|
stats: {
|
||||||
hp: 20,
|
hp: 20000,
|
||||||
attack: 5,
|
attack: 5,
|
||||||
defense: 0,
|
defense: 9,
|
||||||
speed: 5
|
speed: 260
|
||||||
},
|
},
|
||||||
|
goldReward: { min: 1, max: 5 },
|
||||||
drops: [
|
drops: [
|
||||||
{ itemId: 'cookie', chance: 0.3, count: 1 }
|
{ itemId: 'cookie', chance: 0.3, count: 1 }
|
||||||
]
|
]
|
||||||
|
|
@ -25,6 +26,7 @@ export const ENEMIES = {
|
||||||
defense: 2,
|
defense: 2,
|
||||||
speed: 15
|
speed: 15
|
||||||
},
|
},
|
||||||
|
goldReward: { min: 3, max: 8 },
|
||||||
drops: [
|
drops: [
|
||||||
{ itemId: 'cookie', chance: 0.4, count: 1 },
|
{ itemId: 'cookie', chance: 0.4, count: 1 },
|
||||||
{ itemId: 'wooden_sword', chance: 0.05, count: 1 }
|
{ itemId: 'wooden_sword', chance: 0.05, count: 1 }
|
||||||
|
|
@ -42,8 +44,9 @@ export const ENEMIES = {
|
||||||
defense: 5,
|
defense: 5,
|
||||||
speed: 10
|
speed: 10
|
||||||
},
|
},
|
||||||
|
goldReward: { min: 10, max: 20 },
|
||||||
drops: [
|
drops: [
|
||||||
{ itemId: 'tuna_can', chance: 0.3, count: 1 },
|
// { itemId: 'tuna_can', chance: 0.3, count: 1 }, // tuna_can not in items.js, using cookie for now or remove
|
||||||
{ itemId: 'leather_armor', chance: 0.1, count: 1 }
|
{ itemId: 'leather_armor', chance: 0.1, count: 1 }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -57,9 +60,10 @@ export const ENEMIES = {
|
||||||
defense: 8,
|
defense: 8,
|
||||||
speed: 25
|
speed: 25
|
||||||
},
|
},
|
||||||
|
goldReward: { min: 20, max: 40 },
|
||||||
drops: [
|
drops: [
|
||||||
{ itemId: 'premium_food', chance: 0.2, count: 1 },
|
// { itemId: 'premium_food', chance: 0.2, count: 1 }, // not in items.js
|
||||||
{ itemId: 'lucky_charm', chance: 0.05, count: 1 }
|
{ itemId: 'lucky_amulet', chance: 0.05, count: 1 } // lucky_charm -> lucky_amulet
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -74,8 +78,9 @@ export const ENEMIES = {
|
||||||
defense: 10,
|
defense: 10,
|
||||||
speed: 30
|
speed: 30
|
||||||
},
|
},
|
||||||
|
goldReward: { min: 30, max: 60 },
|
||||||
drops: [
|
drops: [
|
||||||
{ itemId: 'vitality_potion', chance: 0.2, count: 1 }
|
{ itemId: 'health_potion', chance: 0.2, count: 1 } // vitality_potion -> health_potion
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
formosan_bear: {
|
formosan_bear: {
|
||||||
|
|
@ -88,9 +93,10 @@ export const ENEMIES = {
|
||||||
defense: 40,
|
defense: 40,
|
||||||
speed: 15
|
speed: 15
|
||||||
},
|
},
|
||||||
|
goldReward: { min: 100, max: 200 },
|
||||||
drops: [
|
drops: [
|
||||||
{ itemId: 'gold_coin', chance: 0.5, count: 50 },
|
// { itemId: 'gold_coin', chance: 0.5, count: 50 }, // gold is handled by goldReward
|
||||||
{ itemId: 'hero_sword', chance: 0.05, count: 1 }
|
{ itemId: 'iron_sword', chance: 0.05, count: 1 } // hero_sword -> iron_sword (or add hero_sword to items)
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
bad_spirit: {
|
bad_spirit: {
|
||||||
|
|
@ -103,8 +109,9 @@ export const ENEMIES = {
|
||||||
defense: 5,
|
defense: 5,
|
||||||
speed: 25
|
speed: 25
|
||||||
},
|
},
|
||||||
|
goldReward: { min: 50, max: 100 },
|
||||||
drops: [
|
drops: [
|
||||||
{ itemId: 'lucky_charm', chance: 0.1, count: 1 }
|
{ itemId: 'lucky_amulet', chance: 0.1, count: 1 } // lucky_charm -> lucky_amulet
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ export const ITEMS = {
|
||||||
},
|
},
|
||||||
description: '基礎木製武器,增加攻擊力',
|
description: '基礎木製武器,增加攻擊力',
|
||||||
icon: '⚔️',
|
icon: '⚔️',
|
||||||
|
price: 50,
|
||||||
appearance: null // 武器不改變外觀
|
appearance: null // 武器不改變外觀
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -40,6 +41,7 @@ export const ITEMS = {
|
||||||
},
|
},
|
||||||
description: '堅固的鐵製武器,大幅增加攻擊力',
|
description: '堅固的鐵製武器,大幅增加攻擊力',
|
||||||
icon: '🗡️',
|
icon: '🗡️',
|
||||||
|
price: 150,
|
||||||
appearance: null
|
appearance: null
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -59,6 +61,7 @@ export const ITEMS = {
|
||||||
},
|
},
|
||||||
description: '蘊含魔力的法杖,增加智力和智力成長',
|
description: '蘊含魔力的法杖,增加智力和智力成長',
|
||||||
icon: '🪄',
|
icon: '🪄',
|
||||||
|
price: 300,
|
||||||
appearance: null
|
appearance: null
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -79,6 +82,7 @@ export const ITEMS = {
|
||||||
},
|
},
|
||||||
description: '輕便的皮製護甲,增加防禦力和最大健康',
|
description: '輕便的皮製護甲,增加防禦力和最大健康',
|
||||||
icon: '🛡️',
|
icon: '🛡️',
|
||||||
|
price: 50,
|
||||||
appearance: null
|
appearance: null
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -98,6 +102,7 @@ export const ITEMS = {
|
||||||
},
|
},
|
||||||
description: '厚重的鐵製護甲,大幅增加防禦力',
|
description: '厚重的鐵製護甲,大幅增加防禦力',
|
||||||
icon: '⚔️',
|
icon: '⚔️',
|
||||||
|
price: 150,
|
||||||
appearance: null
|
appearance: null
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -117,6 +122,7 @@ export const ITEMS = {
|
||||||
},
|
},
|
||||||
description: '可愛的帽子,讓寵物看起來更萌',
|
description: '可愛的帽子,讓寵物看起來更萌',
|
||||||
icon: '🎩',
|
icon: '🎩',
|
||||||
|
price: 100,
|
||||||
appearance: {
|
appearance: {
|
||||||
hat: 'cute_hat'
|
hat: 'cute_hat'
|
||||||
}
|
}
|
||||||
|
|
@ -136,6 +142,7 @@ export const ITEMS = {
|
||||||
},
|
},
|
||||||
description: '超酷的墨鏡,增加快樂恢復和敏捷',
|
description: '超酷的墨鏡,增加快樂恢復和敏捷',
|
||||||
icon: '🕶️',
|
icon: '🕶️',
|
||||||
|
price: 200,
|
||||||
appearance: {
|
appearance: {
|
||||||
accessory: 'cool_sunglasses'
|
accessory: 'cool_sunglasses'
|
||||||
}
|
}
|
||||||
|
|
@ -153,6 +160,7 @@ export const ITEMS = {
|
||||||
effects: {},
|
effects: {},
|
||||||
description: '溫暖的紅色圍巾,純外觀道具',
|
description: '溫暖的紅色圍巾,純外觀道具',
|
||||||
icon: '🧣',
|
icon: '🧣',
|
||||||
|
price: 80,
|
||||||
appearance: {
|
appearance: {
|
||||||
accessory: 'red_scarf'
|
accessory: 'red_scarf'
|
||||||
}
|
}
|
||||||
|
|
@ -171,7 +179,8 @@ export const ITEMS = {
|
||||||
modifyStats: { hunger: 20, happiness: 10 }
|
modifyStats: { hunger: 20, happiness: 10 }
|
||||||
},
|
},
|
||||||
description: '美味的餅乾,增加飢餓和快樂',
|
description: '美味的餅乾,增加飢餓和快樂',
|
||||||
icon: '🍪'
|
icon: '🍪',
|
||||||
|
price: 10
|
||||||
},
|
},
|
||||||
|
|
||||||
health_potion: {
|
health_potion: {
|
||||||
|
|
@ -186,7 +195,8 @@ export const ITEMS = {
|
||||||
cureSickness: true
|
cureSickness: true
|
||||||
},
|
},
|
||||||
description: '恢復健康並治癒疾病',
|
description: '恢復健康並治癒疾病',
|
||||||
icon: '🧪'
|
icon: '🧪',
|
||||||
|
price: 20
|
||||||
},
|
},
|
||||||
|
|
||||||
energy_drink: {
|
energy_drink: {
|
||||||
|
|
@ -207,7 +217,8 @@ export const ITEMS = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
description: '提供臨時速度和敏捷加成',
|
description: '提供臨時速度和敏捷加成',
|
||||||
icon: '🥤'
|
icon: '🥤',
|
||||||
|
price: 30
|
||||||
},
|
},
|
||||||
|
|
||||||
growth_pill: {
|
growth_pill: {
|
||||||
|
|
@ -221,7 +232,8 @@ export const ITEMS = {
|
||||||
modifyStats: { str: 1, int: 1, dex: 1 }
|
modifyStats: { str: 1, int: 1, dex: 1 }
|
||||||
},
|
},
|
||||||
description: '永久增加力量、智力、敏捷各 1 點',
|
description: '永久增加力量、智力、敏捷各 1 點',
|
||||||
icon: '💊'
|
icon: '💊',
|
||||||
|
price: 500
|
||||||
},
|
},
|
||||||
|
|
||||||
// ========== 護身符類(永久加成)==========
|
// ========== 護身符類(永久加成)==========
|
||||||
|
|
@ -240,7 +252,8 @@ export const ITEMS = {
|
||||||
percent: { dropRate: 0.10 }
|
percent: { dropRate: 0.10 }
|
||||||
},
|
},
|
||||||
description: '帶來好運的護身符,增加運勢和掉落率',
|
description: '帶來好運的護身符,增加運勢和掉落率',
|
||||||
icon: '🔮'
|
icon: '🔮',
|
||||||
|
price: 250
|
||||||
},
|
},
|
||||||
|
|
||||||
protection_amulet: {
|
protection_amulet: {
|
||||||
|
|
@ -257,7 +270,8 @@ export const ITEMS = {
|
||||||
percent: { sicknessReduction: 0.20, healthRecovery: 0.15 }
|
percent: { sicknessReduction: 0.20, healthRecovery: 0.15 }
|
||||||
},
|
},
|
||||||
description: '保佑平安的護身符,增加健康上限和恢復效率',
|
description: '保佑平安的護身符,增加健康上限和恢復效率',
|
||||||
icon: '🛡️'
|
icon: '🛡️',
|
||||||
|
price: 300
|
||||||
},
|
},
|
||||||
|
|
||||||
wisdom_amulet: {
|
wisdom_amulet: {
|
||||||
|
|
@ -274,7 +288,8 @@ export const ITEMS = {
|
||||||
percent: { intGain: 0.15, happinessRecovery: 0.10 }
|
percent: { intGain: 0.15, happinessRecovery: 0.10 }
|
||||||
},
|
},
|
||||||
description: '提升智慧的護身符,增加智力和智力成長',
|
description: '提升智慧的護身符,增加智力和智力成長',
|
||||||
icon: '📿'
|
icon: '📿',
|
||||||
|
price: 300
|
||||||
},
|
},
|
||||||
|
|
||||||
// ========== 特殊道具類 ==========
|
// ========== 特殊道具類 ==========
|
||||||
|
|
@ -292,7 +307,8 @@ export const ITEMS = {
|
||||||
percent: { strGain: 0.15, dexGain: 0.15 }
|
percent: { strGain: 0.15, dexGain: 0.15 }
|
||||||
},
|
},
|
||||||
description: '訓練指南,增加力量和敏捷成長效率',
|
description: '訓練指南,增加力量和敏捷成長效率',
|
||||||
icon: '📖'
|
icon: '📖',
|
||||||
|
price: 150
|
||||||
},
|
},
|
||||||
|
|
||||||
time_crystal: {
|
time_crystal: {
|
||||||
|
|
@ -314,7 +330,8 @@ export const ITEMS = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
description: '神秘的水晶,全面提升成長和恢復效率',
|
description: '神秘的水晶,全面提升成長和恢復效率',
|
||||||
icon: '💎'
|
icon: '💎',
|
||||||
|
price: 2000
|
||||||
},
|
},
|
||||||
|
|
||||||
// ========== 永久裝備(不會壞)==========
|
// ========== 永久裝備(不會壞)==========
|
||||||
|
|
@ -334,6 +351,7 @@ export const ITEMS = {
|
||||||
},
|
},
|
||||||
description: '傳說中的黃金王冠,全面提升所有屬性',
|
description: '傳說中的黃金王冠,全面提升所有屬性',
|
||||||
icon: '👑',
|
icon: '👑',
|
||||||
|
price: 5000,
|
||||||
appearance: {
|
appearance: {
|
||||||
hat: 'golden_crown'
|
hat: 'golden_crown'
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue