1.6.0更新

This commit is contained in:
谦君
2026-01-06 03:00:02 +08:00
parent 1ad051cd6d
commit 9e7560cc4b
50 changed files with 2374 additions and 468 deletions

View File

@@ -4,25 +4,15 @@ const config: CapacitorConfig = {
appId: 'games.wenzi.ogame',
appName: 'OGame Vue Ts',
webDir: 'docs',
server: {
androidScheme: 'https',
cacheControl: 'max-age=31536000'
},
server: { androidScheme: 'https', cacheControl: 'max-age=31536000' },
android: {
buildOptions: {
keystorePath: undefined,
keystoreAlias: undefined
},
buildOptions: { keystorePath: undefined, keystoreAlias: undefined },
webContentsDebuggingEnabled: false,
allowMixedContent: false,
hardwareAcceleration: true
},
plugins: {
// 禁用键盘自动调整视口
Keyboard: {
resize: 'none'
}
}
// 禁用键盘自动调整视口
plugins: { Keyboard: { resize: 'none' } }
}
export default config

75
main.go
View File

@@ -1,6 +1,7 @@
package main
import (
"bufio"
"embed"
"flag"
"fmt"
@@ -10,6 +11,7 @@ import (
"os"
"os/exec"
"runtime"
"strconv"
"strings"
"time"
)
@@ -20,10 +22,16 @@ var content embed.FS
func main() {
// --- 1. 命令行参数配置 ---
// 定义 -port 参数,默认为 0自动分配
portPtr := flag.Int("port", 0, "指定运行端口 (例如: 8080),不指定则自动分配可用端口")
// 定义 -port 参数,默认为 -1表示未指定需要交互选择
portPtr := flag.Int("port", -1, "指定运行端口 (例如: 8080),不指定则显示交互菜单")
flag.Parse()
// 如果没有通过命令行指定端口,显示交互式菜单
port := *portPtr
if port == -1 {
port = showPortMenu()
}
// --- 2. 静态资源处理 ---
// 获取 docs 子目录的文件系统句柄
distFS, err := fs.Sub(content, "docs")
@@ -60,10 +68,10 @@ func main() {
})
// --- 3. 端口监听逻辑 ---
addr := fmt.Sprintf("0.0.0.0:%d", *portPtr)
addr := fmt.Sprintf("0.0.0.0:%d", port)
listener, err := net.Listen("tcp", addr)
if err != nil {
fmt.Printf("错误: 端口 %d 已被占用或监听失败: %v\n", *portPtr, err)
fmt.Printf("错误: 端口 %d 已被占用或监听失败: %v\n", port, err)
// 停留 5 秒让用户看到错误信息
time.Sleep(5 * time.Second)
os.Exit(1)
@@ -79,8 +87,8 @@ func main() {
fmt.Printf("启动时间: %s\n", time.Now().Format("2006-01-02 15:04:05"))
fmt.Printf("本地访问: %s\n", localUrl)
fmt.Printf("局域网访问: %s\n", lanUrl)
if *portPtr != 0 {
fmt.Printf("运行模式: 固定端口 (%d)\n", *portPtr)
if port != 0 {
fmt.Printf("运行模式: 固定端口 (%d)\n", port)
} else {
fmt.Printf("运行模式: 自动分配端口\n")
}
@@ -131,4 +139,59 @@ func openBrowser(url string) {
}
_ = exec.Command(cmd, args...).Start()
}
// 显示端口选择菜单
func showPortMenu() int {
reader := bufio.NewReader(os.Stdin)
fmt.Println("=======================================")
fmt.Println(" OGame Vue Ts 服务器启动")
fmt.Println("=======================================")
fmt.Println()
fmt.Println("请选择端口模式:")
fmt.Println(" [1] 随机端口 (自动分配可用端口)")
fmt.Println(" [2] 自定义端口 (指定固定端口)")
fmt.Println()
fmt.Print("请输入选项 (1/2): ")
for {
input, _ := reader.ReadString('\n')
input = strings.TrimSpace(input)
switch input {
case "1", "":
fmt.Println("\n已选择: 随机端口模式")
return 0
case "2":
return inputCustomPort(reader)
default:
fmt.Print("无效输入,请输入 1 或 2: ")
}
}
}
// 输入自定义端口
func inputCustomPort(reader *bufio.Reader) int {
fmt.Print("请输入端口号 (1-65535推荐: 8080): ")
for {
input, _ := reader.ReadString('\n')
input = strings.TrimSpace(input)
// 如果直接回车,使用默认端口 8080
if input == "" {
fmt.Println("\n已选择: 固定端口 8080")
return 8080
}
port, err := strconv.Atoi(input)
if err != nil || port < 1 || port > 65535 {
fmt.Print("无效端口号,请输入 1-65535 之间的数字: ")
continue
}
fmt.Printf("\n已选择: 固定端口 %d\n", port)
return port
}
}

View File

@@ -8,8 +8,8 @@
"email": "1962257451@qq.com"
},
"private": true,
"version": "1.5.6",
"buildDate": "2025/12/27 03:58:44",
"version": "1.6.0",
"buildDate": "2026/1/6 02:54:44",
"main": "dist-electron/main.js",
"type": "module",
"scripts": {
@@ -34,6 +34,7 @@
"crypto-js": "^4.2.0",
"file-saver": "^2.0.5",
"finalhandler": "^2.1.1",
"lightningcss": "^1.30.2",
"lucide-vue-next": "^0.556.0",
"marked": "^17.0.1",
"motion-v": "^1.7.4",
@@ -44,10 +45,10 @@
"tailwindcss": "^4.1.17",
"vue": "^3.5.24",
"vue-router": "4",
"vue-sonner": "^2.0.9",
"lightningcss": "^1.30.2"
"vue-sonner": "^2.0.9"
},
"devDependencies": {
"@csstools/postcss-cascade-layers": "^5.0.2",
"@types/crypto-js": "^4.2.2",
"@types/file-saver": "^2.0.7",
"@types/node": "^24.10.2",

41
pnpm-lock.yaml generated
View File

@@ -81,6 +81,9 @@ importers:
specifier: ^2.0.9
version: 2.0.9
devDependencies:
'@csstools/postcss-cascade-layers':
specifier: ^5.0.2
version: 5.0.2(postcss@8.5.6)
'@types/crypto-js':
specifier: ^4.2.2
version: 4.2.2
@@ -674,6 +677,18 @@ packages:
'@capacitor/synapse@1.0.4':
resolution: {integrity: sha512-/C1FUo8/OkKuAT4nCIu/34ny9siNHr9qtFezu4kxm6GY1wNFxrCFWjfYx5C1tUhVGz3fxBABegupkpjXvjCHrw==}
'@csstools/postcss-cascade-layers@5.0.2':
resolution: {integrity: sha512-nWBE08nhO8uWl6kSAeCx4im7QfVko3zLrtgWZY4/bP87zrSPpSyN/3W3TDqz1jJuH+kbKOHXg5rJnK+ZVYcFFg==}
engines: {node: '>=18'}
peerDependencies:
postcss: ^8.4
'@csstools/selector-specificity@5.0.0':
resolution: {integrity: sha512-PCqQV3c4CoVm3kdPhyeZ07VmBRdH2EpMFA/pd9OASpOEC3aXNGoqPDAZ80D0cLpMBxnmk0+yNhGsEx31hq7Gtw==}
engines: {node: '>=18'}
peerDependencies:
postcss-selector-parser: ^7.0.0
'@develar/schema-utils@2.6.5':
resolution: {integrity: sha512-0cp4PsWQ/9avqTVMCtZ+GirikIA36ikvjtHweU4/j8yLtgObI0+JUPhYFScgwlteveGB1rt3Cm8UhN04XayDig==}
engines: {node: '>= 8.9.0'}
@@ -1915,6 +1930,11 @@ packages:
resolution: {integrity: sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==}
engines: {node: '>=8'}
cssesc@3.0.0:
resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
engines: {node: '>=4'}
hasBin: true
csstype@3.2.3:
resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==}
@@ -3104,6 +3124,10 @@ packages:
resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==}
engines: {node: '>= 0.4'}
postcss-selector-parser@7.1.1:
resolution: {integrity: sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==}
engines: {node: '>=4'}
postcss@8.5.6:
resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==}
engines: {node: ^10 || ^12 || >=14}
@@ -4646,6 +4670,16 @@ snapshots:
'@capacitor/synapse@1.0.4': {}
'@csstools/postcss-cascade-layers@5.0.2(postcss@8.5.6)':
dependencies:
'@csstools/selector-specificity': 5.0.0(postcss-selector-parser@7.1.1)
postcss: 8.5.6
postcss-selector-parser: 7.1.1
'@csstools/selector-specificity@5.0.0(postcss-selector-parser@7.1.1)':
dependencies:
postcss-selector-parser: 7.1.1
'@develar/schema-utils@2.6.5':
dependencies:
ajv: 6.12.6
@@ -5955,6 +5989,8 @@ snapshots:
crypto-random-string@2.0.0: {}
cssesc@3.0.0: {}
csstype@3.2.3: {}
data-view-buffer@1.0.2:
@@ -7243,6 +7279,11 @@ snapshots:
possible-typed-array-names@1.1.0: {}
postcss-selector-parser@7.1.1:
dependencies:
cssesc: 3.0.0
util-deprecate: 1.0.2
postcss@8.5.6:
dependencies:
nanoid: 3.3.11

View File

@@ -45,7 +45,7 @@
<ChevronsUpDown class="h-4 w-4 shrink-0 text-muted-foreground ml-2" />
</Button>
</PopoverTrigger>
<PopoverContent class="w-72 p-0" side="bottom" align="start">
<PopoverContent class="w-70 p-0" side="bottom" align="start">
<div class="p-2">
<div class="px-2 py-1.5 mb-1 text-xs font-semibold text-muted-foreground">
{{ t('planet.switchPlanet') }}
@@ -378,7 +378,7 @@
</SidebarInset>
<!-- 右下角固定通知按钮 -->
<div class="fixed bottom-4 right-4 z-50 flex flex-col gap-2">
<div class="fixed bottom-4 right-4 z-50 flex flex-col gap-2" :class="{ 'bottom-15': Capacitor.isNativePlatform() }">
<!-- 返回顶部 -->
<BackToTop />
<!-- 队列通知 -->
@@ -518,7 +518,7 @@
import HintToast from '@/components/notifications/HintToast.vue'
import BackToTop from '@/components/common/BackToTop.vue'
import Sonner from '@/components/ui/sonner/Sonner.vue'
import { MissionType, BuildingType, TechnologyType, DiplomaticEventType } from '@/types/game'
import { MissionType, BuildingType, TechnologyType, DiplomaticEventType, ShipType } from '@/types/game'
import type { FleetMission, NPC, MissileAttack } from '@/types/game'
import { DIPLOMATIC_CONFIG } from '@/config/gameConfig'
import type { VersionInfo } from '@/utils/versionCheck'
@@ -838,8 +838,14 @@
// 计算离线收益(直接同步计算,应用游戏速度)
const bonuses = officerLogic.calculateActiveBonuses(gameStore.player.officers, now)
const miningTechLevel = gameStore.player.technologies[TechnologyType.MiningTechnology] || 0
const techBonuses = {
mineralResearchLevel: gameStore.player.technologies[TechnologyType.MineralResearch] || 0,
crystalResearchLevel: gameStore.player.technologies[TechnologyType.CrystalResearch] || 0,
fuelResearchLevel: gameStore.player.technologies[TechnologyType.FuelResearch] || 0
}
gameStore.player.planets.forEach(planet => {
resourceLogic.updatePlanetResources(planet, now, bonuses, gameStore.gameSpeed)
resourceLogic.updatePlanetResources(planet, now, bonuses, gameStore.gameSpeed, miningTechLevel, techBonuses)
})
// 只在没有NPC星球时才生成首次加载已有玩家数据时
@@ -1065,6 +1071,19 @@
const targetNpc = npcStore.npcs.find(npc => npc.planets.some(p => p.id === targetPlanet.id))
if (targetNpc) {
diplomaticLogic.handleAttackReputation(gameStore.player, targetNpc, attackResult.battleResult, npcStore.npcs, gameStore.locale)
// 同步战斗损失到NPC的实际星球数据
const npcPlanet = targetNpc.planets.find(p => p.id === targetPlanet.id)
if (npcPlanet) {
// 同步舰队损失
Object.entries(attackResult.battleResult.defenderLosses.fleet).forEach(([shipType, lost]) => {
npcPlanet.fleet[shipType as ShipType] = Math.max(0, (npcPlanet.fleet[shipType as ShipType] || 0) - lost)
})
// 同步防御损失修复后的数据已在targetPlanet中
npcPlanet.defense = { ...targetPlanet.defense }
// 同步资源(被掠夺后的)
npcPlanet.resources = { ...targetPlanet.resources }
}
}
}
@@ -1262,8 +1281,41 @@
}
}
} else if (mission.missionType === MissionType.Destroy) {
// 处理行星毁灭任务
const destroyResult = fleetLogic.processDestroyArrival(mission, targetPlanet, gameStore.player)
// 处理行星毁灭任务(需要先战斗,再计算毁灭概率)
const destroyResult = await fleetLogic.processDestroyArrival(mission, targetPlanet, gameStore.player, null, gameStore.player.planets)
// 处理战斗报告(如果发生了战斗)
if (destroyResult.battleResult) {
gameStore.player.battleReports.push(destroyResult.battleResult)
// 处理战斗对NPC的影响
if (targetPlanet) {
const targetNpc = npcStore.npcs.find(npc => npc.planets.some(p => p.id === targetPlanet.id))
if (targetNpc) {
diplomaticLogic.handleAttackReputation(gameStore.player, targetNpc, destroyResult.battleResult, npcStore.npcs, gameStore.locale)
// 同步战斗损失到NPC的实际星球数据
const npcPlanet = targetNpc.planets.find(p => p.id === targetPlanet.id)
if (npcPlanet) {
Object.entries(destroyResult.battleResult.defenderLosses.fleet).forEach(([shipType, lost]) => {
npcPlanet.fleet[shipType as ShipType] = Math.max(0, (npcPlanet.fleet[shipType as ShipType] || 0) - lost)
})
npcPlanet.defense = { ...targetPlanet.defense }
npcPlanet.resources = { ...targetPlanet.resources }
}
}
}
}
// 处理新生成的月球
if (destroyResult.moon) {
gameStore.player.planets.push(destroyResult.moon)
}
// 处理残骸场
if (destroyResult.debrisField) {
universeStore.debrisFields[destroyResult.debrisField.id] = destroyResult.debrisField
}
// 更新成就统计 - 行星毁灭
if (destroyResult.success) {
@@ -1303,12 +1355,14 @@
? {
destroyedPlanetName:
targetPlanet?.name ||
`[${mission.targetPosition.galaxy}:${mission.targetPosition.system}:${mission.targetPosition.position}]`
`[${mission.targetPosition.galaxy}:${mission.targetPosition.system}:${mission.targetPosition.position}]`,
hadBattle: !!destroyResult.battleResult
}
: {
failReason: destroyResult.failReason,
destructionChance: destroyResult.destructionChance,
deathstarsLost: destroyResult.deathstarsLost
deathstarsLost: destroyResult.deathstarsLost,
hadBattle: !!destroyResult.battleResult
},
read: false
})
@@ -1387,7 +1441,7 @@
delete universeStore.debrisFields[destroyedDebrisId]
}
} else if (mission.missionType === MissionType.Expedition) {
// 处理远征任务
// 处理探险任务
const expeditionResult = fleetLogic.processExpeditionArrival(mission)
// 确保返回时间正确设置(兼容旧版本任务数据)
@@ -1399,12 +1453,12 @@
mission.returnTime = now + flightDuration
}
// 更新成就统计 - 远征
// 更新成就统计 - 探险
const isSuccessful =
expeditionResult.eventType === 'resources' || expeditionResult.eventType === 'darkMatter' || expeditionResult.eventType === 'fleet'
gameLogic.trackMissionStats(gameStore.player, 'expedition', { successful: isSuccessful })
// 生成远征任务报告
// 生成探险任务报告
if (!gameStore.player.missionReports) {
gameStore.player.missionReports = []
}
@@ -1676,10 +1730,16 @@
// 应用损失到目标星球
missileLogic.applyMissileAttackResult(targetPlanet, impactResult.defenseLosses)
// 如果目标是NPC的星球扣除外交好感度
// 如果目标是NPC的星球同步损失到NPC实际数据并扣除外交好感度
if (targetPlanet.ownerId && targetPlanet.ownerId !== gameStore.player.id) {
const targetNpc = npcStore.npcs.find(npc => npc.id === targetPlanet.ownerId)
if (targetNpc) {
// 同步防御损失到NPC的实际星球数据
const npcPlanet = targetNpc.planets.find(p => p.id === targetPlanet.id)
if (npcPlanet) {
missileLogic.applyMissileAttackResult(npcPlanet, impactResult.defenseLosses)
}
// 导弹攻击扣除好感度
const { REPUTATION_CHANGES } = DIPLOMATIC_CONFIG
const reputationLoss = REPUTATION_CHANGES.ATTACK / 2 // 导弹攻击的好感度惩罚是普通攻击的一半
@@ -2220,6 +2280,7 @@
const switchToMoon = () => {
if (moon.value) {
gameStore.currentPlanetId = moon.value.id
router.push('/')
}
}
@@ -2227,12 +2288,14 @@
const switchToParentPlanet = () => {
if (planet.value?.parentPlanetId) {
gameStore.currentPlanetId = planet.value.parentPlanetId
router.push('/')
}
}
// 切换到指定星球
const switchToPlanet = (planetId: string) => {
gameStore.currentPlanetId = planetId
router.push('/')
}
// 切换侧边栏

View File

@@ -72,15 +72,15 @@ html.light {
/* 队列添加动画 - 脉冲效果 */
@keyframes queue-pulse-animation {
0% {
transform: scale(1);
transform: scale3d(1, 1, 1);
box-shadow: 0 0 0 0 rgba(34, 197, 94, 0.7);
}
50% {
transform: scale(1.1);
transform: scale3d(1.1, 1.1, 1);
box-shadow: 0 0 0 8px rgba(34, 197, 94, 0);
}
100% {
transform: scale(1);
transform: scale3d(1, 1, 1);
box-shadow: 0 0 0 0 rgba(34, 197, 94, 0);
}
}

View File

@@ -9,7 +9,7 @@
<!-- 可缩放内容包装器 -->
<div
class="map-content origin-top-left transition-transform duration-200"
:style="{ transform: `scale(${zoomLevel})`, minWidth: calculatedMapWidth + 'px', minHeight: calculatedMapHeight + 'px' }"
:style="{ transform: `scale3d(${zoomLevel}, ${zoomLevel}, 1)`, minWidth: calculatedMapWidth + 'px', minHeight: calculatedMapHeight + 'px' }"
>
<!-- SVG连接线 - 位置与节点容器对齐 -->
<svg

View File

@@ -176,7 +176,7 @@
}
.quest-available .quest-node:hover {
transform: scale(1.05);
transform: scale3d(1.05, 1.05, 1);
}
@keyframes pulse-glow {

View File

@@ -491,9 +491,20 @@
return currentPlanet.value.buildings['naniteFactory'] || 0
})
// 获取研究所等级(用于研究时间计算
// 获取有效研究所等级(考虑星际研究网络
const researchLabLevel = computed(() => {
if (!currentPlanet.value) return 0
const intergalacticResearchNetworkLevel = gameStore.player.technologies[TechnologyType.IntergalacticResearchNetwork] || 0
// 如果有星际研究网络,计算有效实验室等级
if (intergalacticResearchNetworkLevel > 0) {
return researchLogic.calculateEffectiveLabLevel(
gameStore.player.planets,
currentPlanet.value.id,
intergalacticResearchNetworkLevel
)
}
return currentPlanet.value.buildings['researchLab'] || 0
})
@@ -502,6 +513,12 @@
return gameStore.player.technologies['energyTechnology'] || 0
})
// 获取大学等级(用于研究时间计算)
const universityLevel = computed(() => {
if (!currentPlanet.value) return 0
return currentPlanet.value.buildings['university'] || 0
})
// 翻译键(转换为复数形式)
const typeKey = computed(() => {
const typeMap = {
@@ -931,7 +948,9 @@
level - 1,
activeBonuses.value.researchSpeedBonus,
researchLabLevel.value,
energyTechLevel.value
energyTechLevel.value,
1,
universityLevel.value
)
let researchSpeedBonus = 0

View File

@@ -178,6 +178,16 @@
type: 'attacker-loss' | 'defender-loss' | 'info'
}
const battleLogs = ref<BattleLog[]>([])
const MAX_LOGS = 100 // 限制日志数量防止100回合战斗导致性能问题
// 添加日志的辅助函数,自动限制数量
const addBattleLog = (log: BattleLog) => {
battleLogs.value.push(log)
// 如果超过最大数量,删除最旧的日志
if (battleLogs.value.length > MAX_LOGS) {
battleLogs.value = battleLogs.value.slice(-MAX_LOGS)
}
}
// 计算属性
const totalRounds = computed(() => props.report.roundDetails?.length || props.report.rounds || 1)
@@ -367,97 +377,101 @@
if (currentRoundIndex.value >= totalRounds.value) return
isPlayingRound = true
const speed = parseFloat(speedMultiplier.value)
const roundIndex = currentRoundIndex.value
const roundData = props.report.roundDetails?.[roundIndex]
try {
const speed = parseFloat(speedMultiplier.value) || 1
const roundIndex = currentRoundIndex.value
const roundData = props.report.roundDetails?.[roundIndex]
// 攻击动画阶段
attackAnimationPhase.value = 'attack'
// 攻击动画阶段
attackAnimationPhase.value = 'attack'
// 添加日志
battleLogs.value.push({
round: roundIndex + 1,
message: t('messagesView.roundStarted').replace('{round}', String(roundIndex + 1)),
type: 'info'
})
// 添加日志
addBattleLog({
round: roundIndex + 1,
message: t('messagesView.roundStarted').replace('{round}', String(roundIndex + 1)),
type: 'info'
})
// 等待攻击动画
await sleep(400 / speed)
// 等待攻击动画
await sleep(400 / speed)
// 伤害阶段
attackAnimationPhase.value = 'damage'
// 伤害阶段
attackAnimationPhase.value = 'damage'
// 计算当前回合的损失数字
if (roundData) {
const attackerLoss = Object.values(roundData.attackerLosses).reduce((sum, count) => sum + count, 0)
const defenderLoss =
Object.values(roundData.defenderLosses.fleet || {}).reduce((sum, count) => sum + count, 0) +
Object.values(roundData.defenderLosses.defense || {}).reduce((sum, count) => sum + count, 0)
displayedLosses.value = { attacker: attackerLoss, defender: defenderLoss }
} else {
displayedLosses.value = { attacker: 0, defender: 0 }
// 计算当前回合的损失数字
if (roundData) {
const attackerLoss = Object.values(roundData.attackerLosses || {}).reduce((sum, count) => sum + count, 0)
const defenderLoss =
Object.values(roundData.defenderLosses?.fleet || {}).reduce((sum, count) => sum + count, 0) +
Object.values(roundData.defenderLosses?.defense || {}).reduce((sum, count) => sum + count, 0)
displayedLosses.value = { attacker: attackerLoss, defender: defenderLoss }
} else {
displayedLosses.value = { attacker: 0, defender: 0 }
}
showDamageNumbers.value = true
if (roundData) {
// 记录攻击方损失
for (const [shipType, count] of Object.entries(roundData.attackerLosses || {})) {
if (count > 0) {
explodingShips.value.push({ side: 'attacker', type: shipType })
addBattleLog({
round: roundIndex + 1,
message: t('messagesView.shipDestroyed')
.replace('{count}', String(count))
.replace('{ship}', SHIPS.value[shipType as ShipType]?.name || shipType),
type: 'attacker-loss'
})
}
}
// 记录防守方损失
for (const [shipType, count] of Object.entries(roundData.defenderLosses?.fleet || {})) {
if (count > 0) {
explodingShips.value.push({ side: 'defender', type: shipType })
addBattleLog({
round: roundIndex + 1,
message: t('messagesView.shipDestroyed')
.replace('{count}', String(count))
.replace('{ship}', SHIPS.value[shipType as ShipType]?.name || shipType),
type: 'defender-loss'
})
}
}
for (const [defType, count] of Object.entries(roundData.defenderLosses?.defense || {})) {
if (count > 0) {
explodingShips.value.push({ side: 'defender', type: defType })
addBattleLog({
round: roundIndex + 1,
message: t('messagesView.defenseDestroyed')
.replace('{count}', String(count))
.replace('{defense}', DEFENSES.value[defType as DefenseType]?.name || defType),
type: 'defender-loss'
})
}
}
}
// 等待伤害显示
await sleep(600 / speed)
// 清理状态
attackAnimationPhase.value = 'idle'
showDamageNumbers.value = false
explodingShips.value = []
currentRoundIndex.value++
} finally {
// 确保锁始终被释放,即使发生错误
isPlayingRound = false
}
showDamageNumbers.value = true
if (roundData) {
// 记录攻击方损失
for (const [shipType, count] of Object.entries(roundData.attackerLosses)) {
if (count > 0) {
explodingShips.value.push({ side: 'attacker', type: shipType })
battleLogs.value.push({
round: roundIndex + 1,
message: t('messagesView.shipDestroyed')
.replace('{count}', String(count))
.replace('{ship}', SHIPS.value[shipType as ShipType]?.name || shipType),
type: 'attacker-loss'
})
}
}
// 记录防守方损失
for (const [shipType, count] of Object.entries(roundData.defenderLosses.fleet || {})) {
if (count > 0) {
explodingShips.value.push({ side: 'defender', type: shipType })
battleLogs.value.push({
round: roundIndex + 1,
message: t('messagesView.shipDestroyed')
.replace('{count}', String(count))
.replace('{ship}', SHIPS.value[shipType as ShipType]?.name || shipType),
type: 'defender-loss'
})
}
}
for (const [defType, count] of Object.entries(roundData.defenderLosses.defense || {})) {
if (count > 0) {
explodingShips.value.push({ side: 'defender', type: defType })
battleLogs.value.push({
round: roundIndex + 1,
message: t('messagesView.defenseDestroyed')
.replace('{count}', String(count))
.replace('{defense}', DEFENSES.value[defType as DefenseType]?.name || defType),
type: 'defender-loss'
})
}
}
}
// 等待伤害显示
await sleep(600 / speed)
// 清理状态
attackAnimationPhase.value = 'idle'
showDamageNumbers.value = false
explodingShips.value = []
currentRoundIndex.value++
isPlayingRound = false
}
const nextRound = () => {
const nextRound = async () => {
if (currentRoundIndex.value < totalRounds.value) {
pause()
playRound()
await playRound()
}
}

View File

@@ -7,7 +7,7 @@
<ProgressIndicator
data-slot="progress-indicator"
class="bg-primary h-full w-full flex-1 transition-all"
:style="`transform: translateX(-${100 - (props.modelValue ?? 0)}%);`"
:style="`transform: translate3d(-${100 - (props.modelValue ?? 0)}%, 0, 0);`"
/>
</ProgressRoot>
</template>

View File

@@ -43,7 +43,8 @@ export const useGameConfig = () => {
[BuildingType.JumpGate]: 'jumpGate',
[BuildingType.PlanetDestroyerFactory]: 'planetDestroyerFactory',
[BuildingType.GeoResearchStation]: 'geoResearchStation',
[BuildingType.DeepDrillingFacility]: 'deepDrillingFacility'
[BuildingType.DeepDrillingFacility]: 'deepDrillingFacility',
[BuildingType.University]: 'university'
}
// 舰船类型枚举值到翻译键的映射
@@ -100,7 +101,11 @@ export const useGameConfig = () => {
[TechnologyType.DarkMatterTechnology]: 'darkMatterTechnology',
[TechnologyType.TerraformingTechnology]: 'terraformingTechnology',
[TechnologyType.PlanetDestructionTech]: 'planetDestructionTech',
[TechnologyType.MiningTechnology]: 'miningTechnology'
[TechnologyType.MiningTechnology]: 'miningTechnology',
[TechnologyType.IntergalacticResearchNetwork]: 'intergalacticResearchNetwork',
[TechnologyType.MineralResearch]: 'mineralResearch',
[TechnologyType.CrystalResearch]: 'crystalResearch',
[TechnologyType.FuelResearch]: 'fuelResearch'
}
// 军官类型枚举值到翻译键的映射

View File

@@ -110,7 +110,7 @@ export const triggerQueueAnimation = (event: MouseEvent, type: 'building' | 'tec
el.style.left = `${x}px`
el.style.top = `${y}px`
el.style.transform = `translate(-50%, -50%) scale(${scale})`
el.style.transform = `translate3d(-50%, -50%, 0) scale3d(${scale}, ${scale}, 1)`
el.style.opacity = `${opacity}`
if (progress < 1) {

View File

@@ -284,7 +284,7 @@ export const BUILDINGS: Record<BuildingType, BuildingConfig> = {
id: BuildingType.LunarBase,
name: '月球基地',
description: '增加月球可用空间',
baseCost: { metal: 20000, crystal: 40000, deuterium: 20000, darkMatter: 0, energy: 0 },
baseCost: { metal: 8000, crystal: 8000, deuterium: 4000, darkMatter: 0, energy: 0 },
baseTime: 45, // 减少建造时间60→45秒
costMultiplier: 2,
spaceUsage: 0, // 月球基地本身不占用空间,反而增加空间
@@ -357,7 +357,7 @@ export const BUILDINGS: Record<BuildingType, BuildingConfig> = {
[BuildingType.GeoResearchStation]: {
id: BuildingType.GeoResearchStation,
name: '地质研究站',
description: '研究地质结构,提高矿脉自然恢复速度。每级增加50%恢复速率',
description: '研究地质结构,提高矿脉自然恢复速度。每级增加10%恢复速率',
baseCost: { metal: 50000, crystal: 30000, deuterium: 20000, darkMatter: 0, energy: 0 },
baseTime: 60,
costMultiplier: 1.8,
@@ -416,6 +416,34 @@ export const BUILDINGS: Record<BuildingType, BuildingConfig> = {
[TechnologyType.PlasmaTechnology]: 5
}
}
},
// 2moons新增建筑
[BuildingType.University]: {
id: BuildingType.University,
name: '大学',
description: '培养科研人员加快研究速度。每级减少研究时间8%(与星际研究网络叠加)',
baseCost: { metal: 200000, crystal: 100000, deuterium: 50000, darkMatter: 0, energy: 0 },
baseTime: 120,
costMultiplier: 2,
spaceUsage: 8,
planetOnly: true,
maxLevel: 10, // 最多10级最高约57%研究时间减少)
requirements: {
[BuildingType.ResearchLab]: 8,
[BuildingType.RoboticsFactory]: 6
},
levelRequirements: {
5: {
[BuildingType.ResearchLab]: 10,
[BuildingType.RoboticsFactory]: 8,
[TechnologyType.EnergyTechnology]: 8
},
8: {
[BuildingType.ResearchLab]: 12,
[BuildingType.NaniteFactory]: 2,
[TechnologyType.ComputerTechnology]: 8
}
}
}
}
@@ -726,6 +754,111 @@ export const TECHNOLOGIES: Record<TechnologyType, TechnologyConfig> = {
[TechnologyType.PlasmaTechnology]: 3
}
}
},
// 2moons新增科技
[TechnologyType.IntergalacticResearchNetwork]: {
id: TechnologyType.IntergalacticResearchNetwork,
name: '星际研究网络',
description: '连接多个星球的研究实验室共享研究资源。每级可连接1个额外的研究实验室取等级最高的N个实验室',
baseCost: { metal: 240000, crystal: 400000, deuterium: 160000, darkMatter: 0, energy: 0 },
baseTime: 180,
costMultiplier: 2,
maxLevel: 10,
requirements: {
[BuildingType.ResearchLab]: 10,
[TechnologyType.ComputerTechnology]: 8,
[TechnologyType.HyperspaceTechnology]: 8
},
levelRequirements: {
5: {
[BuildingType.ResearchLab]: 12,
[TechnologyType.ComputerTechnology]: 10,
[TechnologyType.HyperspaceTechnology]: 10
},
8: {
[BuildingType.ResearchLab]: 14,
[TechnologyType.ComputerTechnology]: 12,
[BuildingType.NaniteFactory]: 5
}
}
},
[TechnologyType.MineralResearch]: {
id: TechnologyType.MineralResearch,
name: '矿物研究',
description: '研究更高效的金属提取技术提升金属矿产量。每级增加金属产量2%',
baseCost: { metal: 60000, crystal: 30000, deuterium: 0, darkMatter: 0, energy: 0 },
baseTime: 60,
costMultiplier: 1.75,
maxLevel: 20,
requirements: {
[BuildingType.ResearchLab]: 5,
[BuildingType.MetalMine]: 10,
[TechnologyType.EnergyTechnology]: 3
},
levelRequirements: {
10: {
[BuildingType.ResearchLab]: 8,
[BuildingType.MetalMine]: 20,
[TechnologyType.EnergyTechnology]: 8
},
15: {
[BuildingType.ResearchLab]: 12,
[BuildingType.NaniteFactory]: 2,
[TechnologyType.PlasmaTechnology]: 5
}
}
},
[TechnologyType.CrystalResearch]: {
id: TechnologyType.CrystalResearch,
name: '晶体研究',
description: '研究更高效的晶体提炼技术提升晶体矿产量。每级增加晶体产量2%',
baseCost: { metal: 40000, crystal: 60000, deuterium: 0, darkMatter: 0, energy: 0 },
baseTime: 60,
costMultiplier: 1.75,
maxLevel: 20,
requirements: {
[BuildingType.ResearchLab]: 5,
[BuildingType.CrystalMine]: 10,
[TechnologyType.EnergyTechnology]: 3
},
levelRequirements: {
10: {
[BuildingType.ResearchLab]: 8,
[BuildingType.CrystalMine]: 20,
[TechnologyType.EnergyTechnology]: 8
},
15: {
[BuildingType.ResearchLab]: 12,
[BuildingType.NaniteFactory]: 2,
[TechnologyType.PlasmaTechnology]: 5
}
}
},
[TechnologyType.FuelResearch]: {
id: TechnologyType.FuelResearch,
name: '燃料研究',
description: '研究更高效的重氢合成技术提升重氢产量。每级增加重氢产量2%',
baseCost: { metal: 0, crystal: 50000, deuterium: 50000, darkMatter: 0, energy: 0 },
baseTime: 60,
costMultiplier: 1.75,
maxLevel: 20,
requirements: {
[BuildingType.ResearchLab]: 5,
[BuildingType.DeuteriumSynthesizer]: 10,
[TechnologyType.EnergyTechnology]: 3
},
levelRequirements: {
10: {
[BuildingType.ResearchLab]: 8,
[BuildingType.DeuteriumSynthesizer]: 20,
[TechnologyType.EnergyTechnology]: 8
},
15: {
[BuildingType.ResearchLab]: 12,
[BuildingType.NaniteFactory]: 2,
[TechnologyType.PlasmaTechnology]: 5
}
}
}
}
@@ -1007,7 +1140,7 @@ export const SHIPS: Record<ShipType, ShipConfig> = {
id: ShipType.Deathstar,
name: '死星',
description: '终极武器,能够摧毁整个行星',
cost: { metal: 5000000, crystal: 4000000, deuterium: 1000000, darkMatter: 20000, energy: 0 },
cost: { metal: 50000000, crystal: 40000000, deuterium: 10000000, darkMatter: 20000, energy: 0 },
buildTime: 600,
cargoCapacity: 1000000,
attack: 200000,
@@ -1467,9 +1600,9 @@ export const DIPLOMATIC_CONFIG = {
// 贸易检查间隔(秒)
CHECK_INTERVAL: 1800, // 30分钟
// 贸易概率
PROBABILITY: 0.1,
PROBABILITY: 0.05,
// 玩家最多同时保留的贸易提议数量
MAX_PENDING_OFFERS: 30,
MAX_PENDING_OFFERS: 5,
// 汇率配置NPC出售资源的汇率
EXCHANGE_RATES: {
// 金属:晶体:重氢 基准比例 3:2:1
@@ -1658,9 +1791,9 @@ export const ORE_DEPOSIT_CONFIG = {
// 矿脉恢复配置
REGENERATION: {
ENABLED: true,
// 每小时恢复初始储量的百分比(0.1% = 每小时恢复0.1%约42天完全恢复
RATE_PER_HOUR: 0.001,
// 最大恢复到初始储量的百分比100%表示可以完全恢复)
// 每小时恢复初始储量的百分比1% = 每小时恢复1%约4.2天完全恢复
RATE_PER_HOUR: 0.01,
// 最大恢复到初始储量的百分比100表示可以完全恢复%
MAX_PERCENTAGE: 1.0
}
}

View File

@@ -153,6 +153,7 @@ export default {
planetDestroyerFactory: 'Planetenzerstörer-Fabrik',
geoResearchStation: 'Geologische Forschungsstation',
deepDrillingFacility: 'Tiefbohranlage',
university: 'Universität',
buildTime: 'Bauzeit',
build: 'Bauen',
production: 'Produktion',
@@ -204,8 +205,9 @@ export default {
jumpGate: 'Überträgt Flotten sofort zu anderen Monden',
planetDestroyerFactory: 'Konstruiert ultimative Waffen zur Zerstörung von Planeten',
geoResearchStation:
'Erforscht geologische Strukturen und erhöht die natürliche Erzvorkommen-Regenerationsrate. +50% Regeneration pro Stufe',
deepDrillingFacility: ''
'Erforscht geologische Strukturen und erhöht die natürliche Erzvorkommen-Regenerationsrate. +10% Regeneration pro Stufe',
deepDrillingFacility: '',
university: 'Bildet Forscher aus, um die Forschungsgeschwindigkeit zu beschleunigen. -8% Forschungszeit pro Stufe'
},
ships: {
lightFighter: 'Leichter Jäger',
@@ -287,7 +289,11 @@ export default {
researchQueueBonus: 'Forschungswarteschlange',
colonySlots: 'Kolonieplätze',
forAllPlanets: '(Global)',
speedBonus: 'Geschwindigkeitsbonus'
speedBonus: 'Geschwindigkeitsbonus',
// Ressourcenproduktionsbonus-Anzeige
mineralResearch: 'Mineralforschung',
crystalResearch: 'Kristallforschung',
fuelResearch: 'Brennstoffforschung'
},
technologies: {
energyTechnology: 'Energietechnik',
@@ -308,7 +314,11 @@ export default {
darkMatterTechnology: 'Dunkle-Materie-Technologie',
terraformingTechnology: 'Terraforming-Technologie',
planetDestructionTech: 'Planetenzerstörungstechnologie',
miningTechnology: ''
miningTechnology: '',
intergalacticResearchNetwork: 'Intergalaktisches Forschungsnetzwerk',
mineralResearch: 'Mineralforschung',
crystalResearch: 'Kristallforschung',
fuelResearch: 'Treibstoffforschung'
},
technologyDescriptions: {
energyTechnology: 'Verbessert Energieeffizienz',
@@ -330,7 +340,11 @@ export default {
darkMatterTechnology: 'Forschung zu Eigenschaften und Anwendungen von Dunkler Materie',
terraformingTechnology: 'Forschung zur Planeten-Terraforming-Technologie, erhöht verfügbaren Platz aller Planeten um 30 pro Stufe',
planetDestructionTech: 'Schreckliche Technologie zur Zerstörung ganzer Planeten',
miningTechnology: ''
miningTechnology: '',
intergalacticResearchNetwork: 'Verbindet mehrere Forschungslabore über Planeten hinweg. Jede Stufe verbindet 1 zusätzliches Labor',
mineralResearch: 'Erforscht effizientere Metallextraktionstechniken. +2% Metallproduktion pro Stufe',
crystalResearch: 'Erforscht effizientere Kristallveredelungstechniken. +2% Kristallproduktion pro Stufe',
fuelResearch: 'Erforscht effizientere Deuterium-Synthesetechniken. +2% Deuteriumproduktion pro Stufe'
},
officers: {
commander: 'Kommandant',
@@ -932,7 +946,10 @@ export default {
hideRoundDetails: 'Rundendetails ausblenden',
round: 'Runde {round}',
attackerRemainingPower: 'Verbleibende Angreiferkraft',
defenderRemainingPower: 'Verbleibende Verteidigerkraft'
defenderRemainingPower: 'Verbleibende Verteidigerkraft',
importFromSpyReport: 'Aus Spionagebericht importieren',
selectSpyReport: 'Spionagebericht auswählen',
noSpyReports: 'Keine Spionageberichte verfügbar'
},
settings: {
dataManagement: 'Datenverwaltung',
@@ -943,6 +960,7 @@ export default {
exporting: 'Exportieren...',
exportSuccess: 'Export erfolgreich',
exportSuccessWithPath: 'Export erfolgreich, Datei gespeichert unter: {path}',
storagePermissionDenied: 'Speicherberechtigung verweigert, Datei kann nicht exportiert werden',
exportFailed: 'Export fehlgeschlagen, bitte erneut versuchen',
importData: 'Daten importieren',
importDataDesc: 'Spielfortschritt aus JSON-Datei wiederherstellen',
@@ -962,6 +980,8 @@ export default {
gameSettingsDesc: 'Spielparameter und Einstellungen anpassen',
gamePause: 'Spielpause',
gamePauseDesc: 'Spielzeit und Ressourcenproduktion pausieren oder fortsetzen',
battleMode: 'Bis zum Ende kämpfen',
battleModeDesc: 'Wenn aktiviert, dauern Kämpfe bis zu 100 Runden bis ein Sieger feststeht. Wenn deaktiviert, wird der klassische 6-Runden-Modus verwendet',
pause: 'Pausieren',
resume: 'Fortsetzen',
gamePaused: 'Spiel pausiert',
@@ -1400,19 +1420,23 @@ export default {
skip: 'Anleitung überspringen',
welcome: {
title: 'Willkommen bei OGame',
content: 'Willkommen, Kommandant! Diese Anleitung führt Sie durch die Grundlagen des Imperiumsaufbaus. Klicken Sie auf "Weiter", um Ihre Reise zu beginnen.'
content:
'Willkommen, Kommandant! Diese Anleitung führt Sie durch die Grundlagen des Imperiumsaufbaus. Klicken Sie auf "Weiter", um Ihre Reise zu beginnen.'
},
resources: {
title: 'Ressourcenübersicht',
content: 'Dies sind Ihre Ressourcen: Metall, Kristall und Deuterium. Sie sind für den Bau von Gebäuden und die Erforschung von Technologien unerlässlich. Energie ist ebenfalls wichtig, um Ihre Infrastruktur zu betreiben.'
content:
'Dies sind Ihre Ressourcen: Metall, Kristall und Deuterium. Sie sind für den Bau von Gebäuden und die Erforschung von Technologien unerlässlich. Energie ist ebenfalls wichtig, um Ihre Infrastruktur zu betreiben.'
},
planet: {
title: 'Ihr Planet',
content: 'Dies ist Ihr Heimatplanet. Hier sehen Sie den Planetennamen, die Koordinaten und können zwischen Planeten wechseln, wenn Sie Ihr Imperium erweitern.'
content:
'Dies ist Ihr Heimatplanet. Hier sehen Sie den Planetennamen, die Koordinaten und können zwischen Planeten wechseln, wenn Sie Ihr Imperium erweitern.'
},
navigation: {
title: 'Navigationsmenü',
content: 'Verwenden Sie dieses Menü, um zwischen verschiedenen Bereichen zu navigieren: Gebäude, Forschung, Flotte, Galaxie usw. Jeder Bereich bietet einzigartige Spielfunktionen.'
content:
'Verwenden Sie dieses Menü, um zwischen verschiedenen Bereichen zu navigieren: Gebäude, Forschung, Flotte, Galaxie usw. Jeder Bereich bietet einzigartige Spielfunktionen.'
},
gotoBuildings: {
title: 'Zu Gebäuden gehen',
@@ -1420,39 +1444,48 @@ export default {
},
buildSolarPlant: {
title: 'Solarkraftwerk bauen',
content: 'Bauen Sie zuerst ein Solarkraftwerk! Es versorgt Ihren Planeten mit Energie. Ohne Energie können andere Ressourcengebäude nicht funktionieren. Dies ist der wichtigste erste Schritt.'
content:
'Bauen Sie zuerst ein Solarkraftwerk! Es versorgt Ihren Planeten mit Energie. Ohne Energie können andere Ressourcengebäude nicht funktionieren. Dies ist der wichtigste erste Schritt.'
},
waitBuild: {
title: 'Bauauftrag',
content: 'Ihr Gebäude befindet sich jetzt im Bauauftrag. Klicken Sie auf das Warteschlangensymbol oben rechts, um alle laufenden Bau- und Forschungsaufgaben anzuzeigen. Gebäude brauchen Zeit zur Fertigstellung, aber Sie können während des Wartens weitermachen.'
content:
'Ihr Gebäude befindet sich jetzt im Bauauftrag. Klicken Sie auf das Warteschlangensymbol oben rechts, um alle laufenden Bau- und Forschungsaufgaben anzuzeigen. Gebäude brauchen Zeit zur Fertigstellung, aber Sie können während des Wartens weitermachen.'
},
buildMetalMine: {
title: 'Metallmine bauen',
content: 'Jetzt, da Sie Energie haben, bauen Sie eine Metallmine. Die Metallmine ist Ihre Hauptmetallquelle, und Metall wird für fast jedes Gebäude und Schiff benötigt.'
content:
'Jetzt, da Sie Energie haben, bauen Sie eine Metallmine. Die Metallmine ist Ihre Hauptmetallquelle, und Metall wird für fast jedes Gebäude und Schiff benötigt.'
},
buildCrystalMine: {
title: 'Kristallmine bauen',
content: 'Kristall ist seltener, aber für fortgeschrittene Technologien entscheidend. Bauen Sie eine Kristallmine, um diese wertvolle Ressource zu sammeln.'
content:
'Kristall ist seltener, aber für fortgeschrittene Technologien entscheidend. Bauen Sie eine Kristallmine, um diese wertvolle Ressource zu sammeln.'
},
buildDeuterium: {
title: 'Deuteriumsynthesizer bauen',
content: 'Deuterium ist für Schiffstreibstoff und fortgeschrittene Forschung unerlässlich. Bauen Sie einen Deuteriumsynthesizer, um diese wichtige Ressource zu produzieren.'
content:
'Deuterium ist für Schiffstreibstoff und fortgeschrittene Forschung unerlässlich. Bauen Sie einen Deuteriumsynthesizer, um diese wichtige Ressource zu produzieren.'
},
upgradeMines: {
title: 'Ressourcenminen upgraden',
content: 'Als Nächstes müssen Sie die drei Ressourcenminen (Metall, Kristall, Deuterium) auf Level 2 upgraden, um die Anforderungen für den Bau der Roboterfabrik zu erfüllen. Upgraden Sie sie weiter, wenn Sie genügend Ressourcen haben.'
content:
'Als Nächstes müssen Sie die drei Ressourcenminen (Metall, Kristall, Deuterium) auf Level 2 upgraden, um die Anforderungen für den Bau der Roboterfabrik zu erfüllen. Upgraden Sie sie weiter, wenn Sie genügend Ressourcen haben.'
},
buildRobotics: {
title: 'Roboterfabrik bauen',
content: 'Die Roboterfabrik kann die Baugeschwindigkeit erheblich erhöhen. Sie benötigt Metallmine, Kristallmine und Deuteriumsynthesizer jeweils auf Level 2. Bauen Sie sie, um die Baueffizienz zu steigern!'
content:
'Die Roboterfabrik kann die Baugeschwindigkeit erheblich erhöhen. Sie benötigt Metallmine, Kristallmine und Deuteriumsynthesizer jeweils auf Level 2. Bauen Sie sie, um die Baueffizienz zu steigern!'
},
upgradeMinesForLab: {
title: 'Ressourcenminen weiter upgraden',
content: 'Jetzt müssen Sie die drei Ressourcenminen auf Level 3 upgraden, um die Bauanforderungen des Forschungslabors zu erfüllen. Entwickeln Sie Ihre Ressourcenproduktion weiter.'
content:
'Jetzt müssen Sie die drei Ressourcenminen auf Level 3 upgraden, um die Bauanforderungen des Forschungslabors zu erfüllen. Entwickeln Sie Ihre Ressourcenproduktion weiter.'
},
buildResearchLab: {
title: 'Forschungslabor bauen',
content: 'Das Forschungslabor ist die Grundlage für technologischen Fortschritt. Es benötigt alle drei Ressourcenminen auf Level 3. Bauen Sie es, um Technologieforschung freizuschalten!'
content:
'Das Forschungslabor ist die Grundlage für technologischen Fortschritt. Es benötigt alle drei Ressourcenminen auf Level 3. Bauen Sie es, um Technologieforschung freizuschalten!'
},
gotoResearch: {
title: 'Zur Forschung gehen',
@@ -1460,11 +1493,13 @@ export default {
},
researchEnergy: {
title: 'Energietechnik erforschen',
content: 'Die Energietechnik kann Ihre Energieproduktion verbessern und fortgeschrittene Gebäude freischalten. Dies ist eine der grundlegendsten und wichtigsten Technologien.'
content:
'Die Energietechnik kann Ihre Energieproduktion verbessern und fortgeschrittene Gebäude freischalten. Dies ist eine der grundlegendsten und wichtigsten Technologien.'
},
shipyardIntro: {
title: 'Flotte & Werft',
content: 'Schiffe ermöglichen es Ihnen, die Galaxie zu erkunden, Ressourcen zu transportieren und Ihr Imperium zu verteidigen. Um Schiffe zu bauen, benötigen Sie eine Raumschiffwerft (benötigt Roboterfabrik Level 2).'
content:
'Schiffe ermöglichen es Ihnen, die Galaxie zu erkunden, Ressourcen zu transportieren und Ihr Imperium zu verteidigen. Um Schiffe zu bauen, benötigen Sie eine Raumschiffwerft (benötigt Roboterfabrik Level 2).'
},
gotoBuildingsForShipyard: {
title: 'Zurück zur Gebäudeseite',
@@ -1472,32 +1507,39 @@ export default {
},
buildShipyard: {
title: 'Raumschiffwerft bauen',
content: 'Die Raumschiffwerft ermöglicht es Ihnen, Schiffe und Verteidigungssysteme zu bauen. Dies ist für Flottenoperationen unerlässlich.'
content:
'Die Raumschiffwerft ermöglicht es Ihnen, Schiffe und Verteidigungssysteme zu bauen. Dies ist für Flottenoperationen unerlässlich.'
},
fleetIntro: {
title: 'Flottenoperationen',
content: 'Sobald Sie Schiffe haben, können Sie sie auf Missionen schicken: Ressourcen transportieren, Planeten kolonisieren, Feinde angreifen oder Trümmerfelder erkunden.'
content:
'Sobald Sie Schiffe haben, können Sie sie auf Missionen schicken: Ressourcen transportieren, Planeten kolonisieren, Feinde angreifen oder Trümmerfelder erkunden.'
},
galaxyIntro: {
title: 'Galaxie erkunden',
content: 'Die Galaxieansicht zeigt andere Planeten, Trümmerfelder und Expansionsmöglichkeiten. Verwenden Sie sie, um Ziele auszukundschaften und Ihre Strategie zu planen.'
content:
'Die Galaxieansicht zeigt andere Planeten, Trümmerfelder und Expansionsmöglichkeiten. Verwenden Sie sie, um Ziele auszukundschaften und Ihre Strategie zu planen.'
},
complete: {
title: 'Anleitung abgeschlossen!',
content: 'Glückwunsch, Kommandant! Sie kennen jetzt die Grundlagen. Bauen Sie Ihr Imperium weiter auf, erforschen Sie Technologien und erkunden Sie die Galaxie. Denken Sie daran: Zuerst Energie entwickeln, dann Ressourcen, dann Fabriken und Forschung! Viel Glück!'
content:
'Glückwunsch, Kommandant! Sie kennen jetzt die Grundlagen. Bauen Sie Ihr Imperium weiter auf, erforschen Sie Technologien und erkunden Sie die Galaxie. Denken Sie daran: Zuerst Energie entwickeln, dann Ressourcen, dann Fabriken und Forschung! Viel Glück!'
},
mobile: {
welcome: {
title: 'Willkommen bei OGame (Mobil)',
content: 'Willkommen, Kommandant! Dies ist eine vereinfachte Anleitung für Touchscreens. Wir werden schnell die Kernfunktionen durchgehen, damit Sie mit dem Aufbau Ihres Imperiums beginnen können.'
content:
'Willkommen, Kommandant! Dies ist eine vereinfachte Anleitung für Touchscreens. Wir werden schnell die Kernfunktionen durchgehen, damit Sie mit dem Aufbau Ihres Imperiums beginnen können.'
},
resources: {
title: 'Obere Ressourcenleiste',
content: 'Oben werden Ihre Ressourcen angezeigt: Metall, Kristall und Deuterium. Tippen Sie, um detaillierte Produktionsinformationen anzuzeigen.'
content:
'Oben werden Ihre Ressourcen angezeigt: Metall, Kristall und Deuterium. Tippen Sie, um detaillierte Produktionsinformationen anzuzeigen.'
},
menu: {
title: 'Navigationsmenü öffnen',
content: 'Tippen Sie auf dieses Menüsymbol, um die Navigationsleiste zu öffnen. Sie können auf alle Funktionen zugreifen: Gebäude, Forschung, Flotte usw.'
content:
'Tippen Sie auf dieses Menüsymbol, um die Navigationsleiste zu öffnen. Sie können auf alle Funktionen zugreifen: Gebäude, Forschung, Flotte usw.'
},
gotoBuildings: {
title: 'Zur Gebäudeseite gehen',
@@ -1505,19 +1547,23 @@ export default {
},
buildSolarPlant: {
title: 'Solarkraftwerk bauen',
content: 'Bauen Sie zuerst ein Solarkraftwerk! Scrollen Sie nach unten, um es zu finden, und tippen Sie auf die Karte zum Bauen. Energie ist die Grundlage für alles.'
content:
'Bauen Sie zuerst ein Solarkraftwerk! Scrollen Sie nach unten, um es zu finden, und tippen Sie auf die Karte zum Bauen. Energie ist die Grundlage für alles.'
},
waitBuild: {
title: 'Bauauftrag',
content: 'Tippen Sie auf das Warteschlangensymbol oben rechts, um den Baufortschritt anzuzeigen. Sie können weiter andere Seiten durchsuchen - der Bau läuft im Hintergrund.'
content:
'Tippen Sie auf das Warteschlangensymbol oben rechts, um den Baufortschritt anzuzeigen. Sie können weiter andere Seiten durchsuchen - der Bau läuft im Hintergrund.'
},
buildMetalMine: {
title: 'Metallmine bauen',
content: 'Nachdem Sie Energie haben, bauen Sie eine Metallmine. Scrollen Sie nach unten, um die Metallmine zu finden, und tippen Sie zum Bauen.'
content:
'Nachdem Sie Energie haben, bauen Sie eine Metallmine. Scrollen Sie nach unten, um die Metallmine zu finden, und tippen Sie zum Bauen.'
},
complete: {
title: 'Schnellanleitung abgeschlossen!',
content: 'Sehr gut! Sie haben die Grundlagen gemeistert. Bauen Sie weiter die Kristallmine und den Deuteriumsynthesizer und erkunden Sie andere Funktionen. Denken Sie daran: Zuerst Energie, dann Ressourcen!'
content:
'Sehr gut! Sie haben die Grundlagen gemeistert. Bauen Sie weiter die Kristallmine und den Deuteriumsynthesizer und erkunden Sie andere Funktionen. Denken Sie daran: Zuerst Energie, dann Ressourcen!'
}
}
},
@@ -1586,7 +1632,8 @@ export default {
},
campaign: {
title: 'Kampagnenmodus',
message: 'Erkunden Sie die Galaxie-Story-Kampagne! Schließen Sie Missionen ab, um Ressourcenbelohnungen zu erhalten und neue Herausforderungen freizuschalten. Jeder Knoten hat einzigartige Ziele und Feinde.'
message:
'Erkunden Sie die Galaxie-Story-Kampagne! Schließen Sie Missionen ab, um Ressourcenbelohnungen zu erhalten und neue Herausforderungen freizuschalten. Jeder Knoten hat einzigartige Ziele und Feinde.'
},
achievements: {
title: 'Erfolgssystem',
@@ -1964,13 +2011,19 @@ export default {
questNotActive: 'Quest nicht aktiv',
questNotCompleted: 'Quest nicht abgeschlossen',
rewardsAlreadyClaimed: 'Belohnungen bereits erhalten',
prerequisiteNotMet: 'Voraussetzungs-Quest nicht abgeschlossen'
prerequisiteNotMet: 'Voraussetzungs-Quest nicht abgeschlossen',
questLocked: 'Quest ist gesperrt',
notInitialized: 'Kampagne nicht initialisiert',
questAlreadyCompleted: 'Quest bereits abgeschlossen'
},
speakers: {
ancientVoice: 'Antike Stimme',
neighborNPC: 'Nachbar-Fraktion',
mysteriousSignal: 'Mysteriöses Signal',
enemyCommander: 'Feindlicher Kommandant'
enemyCommander: 'Feindlicher Kommandant',
shadowVoice: 'Schattenstimme',
allyNPC: 'Verbündete Fraktion',
ancientGuardian: 'Antiker Wächter'
},
objectiveDescriptions: {
buildMetalMine: 'Baue Metallmine auf Stufe 2',
@@ -2060,13 +2113,19 @@ export default {
'2_3': {
prologue_1:
'Deine Expedition entdeckte anomale Signale. Diese Signale scheinen von einer antiken Zivilisation zu stammen... Untersuche ihre Quelle.',
prologue_2:
'Diese Signale... Sie tragen Echos einer längst verlorenen Zivilisation. Ihre Geheimnisse warten darauf, entdeckt zu werden...',
epilogue_1: 'Diese Symbole... Sie sind Ruinen einer antiken Zivilisation! Untersuche weiter, um ihre Geheimnisse zu enthüllen.'
},
'2_4': {
prologue_1: 'Du hast den Standort antiker Ruinen gefunden. Sende deine Flotte zur Erkundung und sieh, was du entdecken kannst.'
prologue_1: 'Du hast den Standort antiker Ruinen gefunden. Sende deine Flotte zur Erkundung und sieh, was du entdecken kannst.',
prologue_2: 'Die Ruinen bergen viele Geheimnisse... Wähle deinen Weg weise...',
choice_1: 'Vorsichtig erkunden - Sicherheit priorisieren',
choice_2: 'Aggressiv erkunden - Entdeckung priorisieren'
},
'2_5': {
prologue_1: 'Datenarchive wurden in den Ruinen gefunden. Studiere diese Daten, vielleicht kannst du neue Technologie freischalten.'
prologue_1: 'Datenarchive wurden in den Ruinen gefunden. Studiere diese Daten, vielleicht kannst du neue Technologie freischalten.',
epilogue_1: 'Die antiken Daten wurden entschlüsselt! Neue technologische Erkenntnisse wurden gewonnen.'
},
'3_1': { prologue_1: 'Beim Erkunden vergiss nicht die Diplomatie. Gute Beziehungen zu umliegenden Fraktionen zu pflegen nützt dir.' },
'3_2': {
@@ -2075,14 +2134,19 @@ export default {
},
'3_3': {
prologue_1:
'Geheimdienstberichte deuten darauf hin, dass feindliche Kräfte dich aus den Schatten beobachten. Bleibe wachsam und erkunde ihre Bewegungen.'
'Geheimdienstberichte deuten darauf hin, dass feindliche Kräfte dich aus den Schatten beobachten. Bleibe wachsam und erkunde ihre Bewegungen.',
prologue_2: 'Dunkle Mächte regen sich in der Leere... Sie haben deine wachsende Macht bemerkt...'
},
'3_4': {
prologue_1: 'Schließe eine formelle Allianz mit freundlichen Fraktionen, um euch gegenseitig gegen Bedrohungen zu unterstützen.'
},
'3_5': { prologue_1: 'Bedrohungen nähern sich. Baue Verteidigungsanlagen und bereite dich auf mögliche Konflikte vor.' },
'3_5': {
prologue_1: 'Bedrohungen nähern sich. Baue Verteidigungsanlagen und bereite dich auf mögliche Konflikte vor.',
epilogue_1: 'Deine Verteidigung ist bereit. Der Sturm naht, aber du bist vorbereitet.'
},
'4_1': {
prologue_1: 'Der Feind hat einen Angriff gestartet! Verteidige deinen Planeten!',
prologue_2: 'Die Schattenflotte nähert sich... Deine Stunde der Prüfung ist gekommen...',
epilogue_1: 'Du hast die erste Welle des Feindes erfolgreich abgewehrt. Aber das ist erst der Anfang...'
},
'4_2': {
@@ -2092,20 +2156,28 @@ export default {
'4_4': {
prologue_1: 'Viele Trümmer bleiben auf dem Schlachtfeld. Recycel diese Ressourcen, um dich auf die nächste Schlacht vorzubereiten.'
},
'4_5': { prologue_1: 'Die letzte Schlacht naht. Baue eine mächtige Flotte und bereite dich auf die ultimative Herausforderung vor.' },
'4_5': {
prologue_1: 'Die letzte Schlacht naht. Baue eine mächtige Flotte und bereite dich auf die ultimative Herausforderung vor.',
epilogue_1: 'Deine Flotte ist versammelt. Der entscheidende Moment naht...'
},
'5_1': {
prologue_1: 'Alle Hinweise deuten auf den tiefsten Teil der Ruinen. Die Kerngeheimnisse der antiken Zivilisation liegen dort.',
prologue_2: 'Du bist endlich angekommen... Die Wahrheit wird bald enthüllt...'
},
'5_2': { prologue_1: 'In den Tiefen der Ruinen entdecktest du verlorene antike Technologie. Erforsche und schalte ihre Macht frei.' },
'5_2': {
prologue_1: 'In den Tiefen der Ruinen entdecktest du verlorene antike Technologie. Erforsche und schalte ihre Macht frei.',
prologue_2: 'Diese Technologie... Sie ist älter als alle bekannten Zivilisationen. Gehe vorsichtig damit um...'
},
'5_3': {
prologue_1: 'Ein mysteriöser Feind ist aufgetaucht. Dies ist die letzte Herausforderung. Besiege ihn!',
prologue_2: 'Ich bin der Wächter dieser Geheimnisse. Beweise deinen Wert oder werde vernichtet!',
epilogue_1: 'Du hast es geschafft! Der antike Wächter wurde besiegt. Die Geheimnisse der Galaxie stehen dir nun offen.'
},
'5_4': { prologue_1: 'Frieden ist endlich eingekehrt. In dieser neuen Ära gründe neue Kolonien und erweitere dein Imperium.' },
'5_5': {
prologue_1: 'Deine Legende hat gerade erst begonnen. Erkunde weiter und erobere mehr Sternensysteme!',
epilogue_1: 'Die Galaxie ist weit und grenzenlos, mit zahllosen Geheimnissen, die auf dich warten...'
epilogue_1: 'Die Galaxie ist weit und grenzenlos, mit zahllosen Geheimnissen, die auf dich warten...',
epilogue_2: 'Deine Reise geht weiter... Neue Abenteuer warten jenseits der Sterne...'
}
}
}

View File

@@ -46,6 +46,8 @@ export default {
cannotAttackOwnPlanet: 'Cannot attack your own planet',
fleetMissionsFull: 'Fleet mission slots full',
insufficientFleet: 'Insufficient fleet',
insufficientShips: 'Insufficient ships',
invalidQuantity: 'Invalid quantity',
insufficientFuel: 'Insufficient fuel',
planetOnly: 'This building can only be built on planets',
moonOnly: 'This building can only be built on moons',
@@ -55,7 +57,12 @@ export default {
researchQueueFull: 'Research queue full',
moonExists: 'Moon already exists',
insufficientDebris: 'Insufficient debris field',
launchFailed: 'Launch failed'
launchFailed: 'Launch failed',
planetNotFound: 'Planet not found',
cannotAbandonHomePlanet: 'Cannot abandon home planet',
hasBuildQueue: 'Please wait for build queue to complete',
hasFleetOnPlanet: 'Please transfer or scrap all fleet first',
hasDefenseOnPlanet: 'Please demolish all defense first'
},
nav: {
overview: 'Overview',
@@ -123,7 +130,12 @@ export default {
renamePlanet: 'Rename Planet',
renamePlanetTitle: 'Rename Planet',
planetNamePlaceholder: 'Enter new planet name',
rename: 'Rename'
rename: 'Rename',
abandonColony: 'Abandon Colony',
confirmAbandon: 'Confirm Abandon Colony',
abandonWarning: 'Are you sure you want to abandon "{name}"?\n\nThis action cannot be undone!\nAll buildings, resources and the moon (if any) will be lost.',
confirmAbandonButton: 'Abandon',
abandonFailed: 'Abandon Failed'
},
player: {
points: 'Total Points'
@@ -152,6 +164,7 @@ export default {
planetDestroyerFactory: 'Planet Destroyer Factory',
geoResearchStation: 'Geological Research Station',
deepDrillingFacility: 'Deep Drilling Facility',
university: 'University',
buildTime: 'Build Time',
production: 'Production',
consumption: 'Consumption',
@@ -199,8 +212,9 @@ export default {
sensorPhalanx: 'Detects fleet activities in surrounding systems',
jumpGate: 'Instantly transfers fleets to other moons',
planetDestroyerFactory: 'Constructs ultimate weapons capable of destroying planets',
geoResearchStation: 'Researches geological structures and increases ore deposit regeneration rate. +50% regeneration per level',
deepDrillingFacility: 'Drills deep into the crust to access deeper ore veins. +20% ore deposit capacity per level'
geoResearchStation: 'Researches geological structures and increases ore deposit regeneration rate. +10% regeneration per level',
deepDrillingFacility: 'Drills deep into the crust to access deeper ore veins. +20% ore deposit capacity per level',
university: 'Trains researchers to accelerate research speed. -8% research time per level (stacks with Intergalactic Research Network)'
},
ships: {
lightFighter: 'Light Fighter',
@@ -275,7 +289,11 @@ export default {
researchQueueBonus: 'Research Queue',
colonySlots: 'Colony Slots',
forAllPlanets: '(Global)',
speedBonus: 'Speed Bonus'
speedBonus: 'Speed Bonus',
// 资源产量加成显示
mineralResearch: 'Mineral Research',
crystalResearch: 'Crystal Research',
fuelResearch: 'Fuel Research'
},
technologies: {
energyTechnology: 'Energy Technology',
@@ -296,7 +314,11 @@ export default {
darkMatterTechnology: 'Dark Matter Technology',
terraformingTechnology: 'Terraforming Technology',
planetDestructionTech: 'Planet Destruction Technology',
miningTechnology: 'Mining Technology'
miningTechnology: 'Mining Technology',
intergalacticResearchNetwork: 'Intergalactic Research Network',
mineralResearch: 'Mineral Research',
crystalResearch: 'Crystal Research',
fuelResearch: 'Fuel Research'
},
technologyDescriptions: {
energyTechnology: 'Improves energy efficiency',
@@ -318,7 +340,11 @@ export default {
darkMatterTechnology: 'Research into dark matter properties and applications',
terraformingTechnology: 'Research planet terraforming technology, adds 30 available space to all planets per level',
planetDestructionTech: 'Terrifying technology for destroying entire planets',
miningTechnology: 'Improves mining methods and equipment, increases ore deposit capacity on all planets. +15% capacity per level'
miningTechnology: 'Improves mining methods and equipment, increases ore deposit capacity on all planets. +15% capacity per level',
intergalacticResearchNetwork: 'Links multiple research labs across planets. Each level connects 1 additional lab (highest level labs are used)',
mineralResearch: 'Research more efficient metal extraction techniques. +2% metal production per level',
crystalResearch: 'Research more efficient crystal refinement techniques. +2% crystal production per level',
fuelResearch: 'Research more efficient deuterium synthesis techniques. +2% deuterium production per level'
},
officers: {
commander: 'Commander',
@@ -440,7 +466,12 @@ export default {
inputError: 'Input Error',
inputErrorMessage: 'Please enter build quantity!',
buildFailed: 'Build Failed',
buildFailedMessage: 'Please check if you have enough resources or if prerequisites are met.'
buildFailedMessage: 'Please check if you have enough resources or if prerequisites are met.',
scrapQuantity: 'Scrap Quantity',
scrapRefund: 'Scrap Refund (50%)',
scrap: 'Scrap',
scrapFailed: 'Scrap Failed',
scrapFailedMessage: 'Please check if you have enough ships.'
},
defense: {
attack: 'Attack',
@@ -917,6 +948,9 @@ export default {
round: 'Round {round}',
attackerRemainingPower: 'Attacker remaining power',
defenderRemainingPower: 'Defender remaining power',
importFromSpyReport: 'Import from Spy Report',
selectSpyReport: 'Select Spy Report',
noSpyReports: 'No spy reports available',
// Battle animation
playAnimation: 'Play Animation',
showDetails: 'Show Details',
@@ -944,6 +978,7 @@ export default {
exporting: 'Exporting...',
exportSuccess: 'Export successful',
exportSuccessWithPath: 'Export successful, file saved to: {path}',
storagePermissionDenied: 'Storage permission denied, cannot export file',
exportFailed: 'Export failed, please try again',
importData: 'Import Data',
importDataDesc: 'Restore game progress from JSON file',
@@ -961,6 +996,8 @@ export default {
gameSettingsDesc: 'Adjust game parameters and preferences',
gamePause: 'Game Pause',
gamePauseDesc: 'Pause or resume game time and resource production',
battleMode: 'Fight to Finish Mode',
battleModeDesc: 'When enabled, battles last up to 100 rounds until a winner is decided. When disabled, uses classic 6-round mode',
pause: 'Pause',
resume: 'Resume',
gamePaused: 'Game paused',
@@ -1950,13 +1987,19 @@ export default {
questNotActive: 'Quest not active',
questNotCompleted: 'Quest not completed',
rewardsAlreadyClaimed: 'Rewards already claimed',
prerequisiteNotMet: 'Prerequisite quest not completed'
prerequisiteNotMet: 'Prerequisite quest not completed',
questLocked: 'Quest is locked',
notInitialized: 'Campaign not initialized',
questAlreadyCompleted: 'Quest already completed'
},
speakers: {
ancientVoice: 'Ancient Voice',
neighborNPC: 'Neighbor Faction',
mysteriousSignal: 'Mysterious Signal',
enemyCommander: 'Enemy Commander'
enemyCommander: 'Enemy Commander',
shadowVoice: 'Shadow Voice',
allyNPC: 'Allied Faction',
ancientGuardian: 'Ancient Guardian'
},
objectiveDescriptions: {
buildMetalMine: 'Build Metal Mine to level 2',
@@ -2044,13 +2087,18 @@ export default {
'2_3': {
prologue_1:
'Your expedition discovered anomalous signals. These signals seem to come from an ancient civilization... Investigate their source.',
prologue_2: 'These signals... they carry echoes of a long-lost civilization. Their secrets await discovery...',
epilogue_1: 'These symbols... They are ruins of an ancient civilization! Continue investigating to uncover their secrets.'
},
'2_4': {
prologue_1: 'You have found the location of ancient ruins. Send your fleet to explore and see what you can discover.'
prologue_1: 'You have found the location of ancient ruins. Send your fleet to explore and see what you can discover.',
prologue_2: 'The ruins hold many secrets... Choose your path wisely...',
choice_1: 'Explore cautiously - prioritize safety',
choice_2: 'Explore aggressively - prioritize discovery'
},
'2_5': {
prologue_1: 'Data archives were found in the ruins. Study this data, perhaps you can unlock new technology.'
prologue_1: 'Data archives were found in the ruins. Study this data, perhaps you can unlock new technology.',
epilogue_1: 'The ancient data has been decrypted! New technological insights have been gained.'
},
'3_1': {
prologue_1: 'While exploring, do not forget about diplomacy. Maintaining good relations with surrounding factions benefits you.'
@@ -2059,16 +2107,19 @@ export default {
prologue_1: 'Some factions have shown friendliness. Continue deepening relations, perhaps you can gain more support.'
},
'3_3': {
prologue_1: 'Intelligence indicates hostile forces are watching you from the shadows. Stay vigilant and scout their movements.'
prologue_1: 'Intelligence indicates hostile forces are watching you from the shadows. Stay vigilant and scout their movements.',
prologue_2: 'Dark forces stir in the void... They have noticed your growing power...'
},
'3_4': {
prologue_1: 'Establish a formal alliance with friendly factions to support each other against threats.'
},
'3_5': {
prologue_1: 'Threats are approaching. Build defense facilities and prepare for possible conflict.'
prologue_1: 'Threats are approaching. Build defense facilities and prepare for possible conflict.',
epilogue_1: 'Your defenses are ready. The storm is coming, but you are prepared.'
},
'4_1': {
prologue_1: 'The enemy has launched an attack! Defend your planet!',
prologue_2: 'The shadow fleet approaches... Your moment of trial has come...',
epilogue_1: "You successfully repelled the enemy's first wave. But this is just the beginning..."
},
'4_2': {
@@ -2081,17 +2132,20 @@ export default {
prologue_1: 'Much debris remains on the battlefield. Recycle these resources to prepare for the next battle.'
},
'4_5': {
prologue_1: 'The final battle approaches. Build a powerful fleet and prepare for the ultimate challenge.'
prologue_1: 'The final battle approaches. Build a powerful fleet and prepare for the ultimate challenge.',
epilogue_1: 'Your fleet is assembled. The decisive moment draws near...'
},
'5_1': {
prologue_1: 'All clues point to the deepest part of the ruins. The core secrets of the ancient civilization lie there.',
prologue_2: 'You have finally arrived... The truth will soon be revealed...'
},
'5_2': {
prologue_1: 'In the depths of the ruins, you discovered lost ancient technology. Research and unlock their power.'
prologue_1: 'In the depths of the ruins, you discovered lost ancient technology. Research and unlock their power.',
prologue_2: 'This technology... it predates all known civilizations. Handle it with care...'
},
'5_3': {
prologue_1: 'A mysterious enemy has appeared. This is the final challenge. Defeat it!',
prologue_2: 'I am the guardian of these secrets. Prove your worth, or be destroyed!',
epilogue_1: 'You did it! The ancient guardian has been defeated. The secrets of the galaxy are now open to you.'
},
'5_4': {
@@ -2099,7 +2153,8 @@ export default {
},
'5_5': {
prologue_1: 'Your legend has just begun. Continue exploring and conquering more star systems!',
epilogue_1: 'The galaxy is vast and boundless, with countless secrets waiting for you to discover...'
epilogue_1: 'The galaxy is vast and boundless, with countless secrets waiting for you to discover...',
epilogue_2: 'Your journey continues... New adventures await beyond the stars...'
}
}
},

View File

@@ -152,6 +152,7 @@ export default {
planetDestroyerFactory: 'Fábrica de Destructores de Planetas',
geoResearchStation: 'Estación de Investigación Geológica',
deepDrillingFacility: 'Instalación de Perforación Profunda',
university: 'Universidad',
buildTime: 'Tiempo de Construcción',
production: 'Producción',
consumption: 'Consumo',
@@ -200,9 +201,10 @@ export default {
jumpGate: 'Transfiere flotas instantáneamente a otras lunas',
planetDestroyerFactory: 'Construye armas definitivas capaces de destruir planetas',
geoResearchStation:
'Investiga estructuras geológicas y aumenta la tasa de regeneración de depósitos de mineral. +50% de regeneración por nivel',
'Investiga estructuras geológicas y aumenta la tasa de regeneración de depósitos de mineral. +10% de regeneración por nivel',
deepDrillingFacility:
'Perfora profundamente en la corteza para acceder a vetas de mineral más profundas. +20% de capacidad de depósito de mineral por nivel'
'Perfora profundamente en la corteza para acceder a vetas de mineral más profundas. +20% de capacidad de depósito de mineral por nivel',
university: 'Entrena investigadores para acelerar la velocidad de investigación. -8% de tiempo de investigación por nivel'
},
ships: {
lightFighter: 'Caza Ligero',
@@ -278,7 +280,11 @@ export default {
colonySlots: 'Espacios de Colonia',
forAllPlanets: '(Global)',
speedBonus: 'Bono de Velocidad',
researchSpeedBonus: 'Bono de Velocidad de Investigación'
researchSpeedBonus: 'Bono de Velocidad de Investigación',
// Visualización de bono de producción de recursos
mineralResearch: 'Investigación Mineral',
crystalResearch: 'Investigación de Cristal',
fuelResearch: 'Investigación de Combustible'
},
technologies: {
energyTechnology: 'Tecnología de Energía',
@@ -299,7 +305,11 @@ export default {
darkMatterTechnology: 'Tecnología de Materia Oscura',
terraformingTechnology: 'Tecnología de Terraformación',
planetDestructionTech: 'Tecnología de Destrucción Planetaria',
miningTechnology: 'Tecnología de Minería'
miningTechnology: 'Tecnología de Minería',
intergalacticResearchNetwork: 'Red de Investigación Intergaláctica',
mineralResearch: 'Investigación Mineral',
crystalResearch: 'Investigación de Cristal',
fuelResearch: 'Investigación de Combustible'
},
technologyDescriptions: {
energyTechnology: 'Mejora la eficiencia energética',
@@ -323,7 +333,11 @@ export default {
'Investigación de tecnología de terraformación planetaria, añade 30 espacios disponibles a todos los planetas por nivel',
planetDestructionTech: 'Tecnología aterradora para destruir planetas enteros',
miningTechnology:
'Mejora los métodos y equipos de minería, aumenta la capacidad de depósito de mineral en todos los planetas. +15% de capacidad por nivel'
'Mejora los métodos y equipos de minería, aumenta la capacidad de depósito de mineral en todos los planetas. +15% de capacidad por nivel',
intergalacticResearchNetwork: 'Conecta múltiples laboratorios de investigación entre planetas. Cada nivel conecta 1 laboratorio adicional',
mineralResearch: 'Investiga técnicas más eficientes de extracción de metal. +2% de producción de metal por nivel',
crystalResearch: 'Investiga técnicas más eficientes de refinamiento de cristal. +2% de producción de cristal por nivel',
fuelResearch: 'Investiga técnicas más eficientes de síntesis de deuterio. +2% de producción de deuterio por nivel'
},
officers: {
commander: 'Comandante',
@@ -925,6 +939,9 @@ export default {
round: 'Ronda {round}',
attackerRemainingPower: 'Poder restante del atacante',
defenderRemainingPower: 'Poder restante del defensor',
importFromSpyReport: 'Importar desde informe de espionaje',
selectSpyReport: 'Seleccionar informe de espionaje',
noSpyReports: 'No hay informes de espionaje disponibles',
// Battle animation
playAnimation: 'Reproducir Animación',
showDetails: 'Mostrar Detalles',
@@ -952,6 +969,7 @@ export default {
exporting: 'Exportando...',
exportSuccess: 'Exportación exitosa',
exportSuccessWithPath: 'Exportación exitosa, archivo guardado en: {path}',
storagePermissionDenied: 'Permiso de almacenamiento denegado, no se puede exportar el archivo',
exportFailed: 'Exportación fallida, por favor intenta de nuevo',
importData: 'Importar Datos',
importDataDesc: 'Restaurar progreso del juego desde archivo JSON',
@@ -969,6 +987,8 @@ export default {
gameSettingsDesc: 'Ajustar parámetros y preferencias del juego',
gamePause: 'Pausa del Juego',
gamePauseDesc: 'Pausar o reanudar el tiempo del juego y la producción de recursos',
battleMode: 'Modo de combate hasta el final',
battleModeDesc: 'Cuando está activado, las batallas duran hasta 100 rondas hasta que se decide un ganador. Cuando está desactivado, se usa el modo clásico de 6 rondas',
pause: 'Pausar',
resume: 'Reanudar',
gamePaused: 'Juego pausado',
@@ -1954,13 +1974,19 @@ export default {
questNotActive: 'Misión no activa',
questNotCompleted: 'Misión no completada',
rewardsAlreadyClaimed: 'Recompensas ya reclamadas',
prerequisiteNotMet: 'Misión prerequisito no completada'
prerequisiteNotMet: 'Misión prerequisito no completada',
questLocked: 'Misión bloqueada',
notInitialized: 'Campaña no inicializada',
questAlreadyCompleted: 'Misión ya completada'
},
speakers: {
ancientVoice: 'Voz Antigua',
neighborNPC: 'Facción Vecina',
mysteriousSignal: 'Señal Misteriosa',
enemyCommander: 'Comandante Enemigo'
enemyCommander: 'Comandante Enemigo',
shadowVoice: 'Voz de la Sombra',
allyNPC: 'Facción Aliada',
ancientGuardian: 'Guardián Antiguo'
},
objectiveDescriptions: {
buildMetalMine: 'Construir Mina de Metal al nivel 2',
@@ -2050,13 +2076,18 @@ export default {
'2_3': {
prologue_1:
'Tu expedición descubrió señales anómalas. Estas señales parecen venir de una civilización antigua... Investiga su origen.',
prologue_2: 'Estas señales... llevan ecos de una civilización perdida hace tiempo. Sus secretos esperan ser descubiertos...',
epilogue_1: 'Estos símbolos... ¡Son ruinas de una civilización antigua! Continúa investigando para descubrir sus secretos.'
},
'2_4': {
prologue_1: 'Has encontrado la ubicación de ruinas antiguas. Envía tu flota a explorar y ver qué puedes descubrir.'
prologue_1: 'Has encontrado la ubicación de ruinas antiguas. Envía tu flota a explorar y ver qué puedes descubrir.',
prologue_2: 'Las ruinas guardan muchos secretos... Elige tu camino sabiamente...',
choice_1: 'Explorar con cautela - priorizar seguridad',
choice_2: 'Explorar agresivamente - priorizar descubrimiento'
},
'2_5': {
prologue_1: 'Se encontraron archivos de datos en las ruinas. Estudia estos datos, quizás puedas desbloquear nueva tecnología.'
prologue_1: 'Se encontraron archivos de datos en las ruinas. Estudia estos datos, quizás puedas desbloquear nueva tecnología.',
epilogue_1: '¡Los datos antiguos han sido descifrados! Se han obtenido nuevos conocimientos tecnológicos.'
},
'3_1': {
prologue_1: 'Mientras exploras, no olvides la diplomacia. Mantener buenas relaciones con las facciones circundantes te beneficia.'
@@ -2066,16 +2097,19 @@ export default {
},
'3_3': {
prologue_1:
'La inteligencia indica que fuerzas hostiles te están vigilando desde las sombras. Mantente alerta y explora sus movimientos.'
'La inteligencia indica que fuerzas hostiles te están vigilando desde las sombras. Mantente alerta y explora sus movimientos.',
prologue_2: 'Fuerzas oscuras se agitan en el vacío... Han notado tu poder creciente...'
},
'3_4': {
prologue_1: 'Establece una alianza formal con facciones amigables para apoyarse mutuamente contra las amenazas.'
},
'3_5': {
prologue_1: 'Las amenazas se acercan. Construye instalaciones de defensa y prepárate para posibles conflictos.'
prologue_1: 'Las amenazas se acercan. Construye instalaciones de defensa y prepárate para posibles conflictos.',
epilogue_1: 'Tus defensas están listas. La tormenta se acerca, pero estás preparado.'
},
'4_1': {
prologue_1: '¡El enemigo ha lanzado un ataque! ¡Defiende tu planeta!',
prologue_2: 'La flota de las sombras se acerca... Ha llegado tu momento de prueba...',
epilogue_1: 'Repeliste exitosamente la primera ola del enemigo. Pero esto es solo el comienzo...'
},
'4_2': {
@@ -2088,7 +2122,8 @@ export default {
prologue_1: 'Muchos escombros permanecen en el campo de batalla. Recicla estos recursos para prepararte para la próxima batalla.'
},
'4_5': {
prologue_1: 'La batalla final se acerca. Construye una flota poderosa y prepárate para el desafío definitivo.'
prologue_1: 'La batalla final se acerca. Construye una flota poderosa y prepárate para el desafío definitivo.',
epilogue_1: 'Tu flota está reunida. El momento decisivo se acerca...'
},
'5_1': {
prologue_1:
@@ -2096,10 +2131,12 @@ export default {
prologue_2: 'Finalmente has llegado... La verdad pronto será revelada...'
},
'5_2': {
prologue_1: 'En las profundidades de las ruinas, descubriste tecnología antigua perdida. Investiga y desbloquea su poder.'
prologue_1: 'En las profundidades de las ruinas, descubriste tecnología antigua perdida. Investiga y desbloquea su poder.',
prologue_2: 'Esta tecnología... es más antigua que todas las civilizaciones conocidas. Manéjala con cuidado...'
},
'5_3': {
prologue_1: 'Ha aparecido un enemigo misterioso. Este es el desafío final. ¡Derrótalo!',
prologue_2: '¡Soy el guardián de estos secretos. Demuestra tu valor o serás destruido!',
epilogue_1: '¡Lo lograste! El guardián antiguo ha sido derrotado. Los secretos de la galaxia ahora están abiertos para ti.'
},
'5_4': {
@@ -2107,7 +2144,8 @@ export default {
},
'5_5': {
prologue_1: 'Tu leyenda acaba de comenzar. ¡Continúa explorando y conquistando más sistemas estelares!',
epilogue_1: 'La galaxia es vasta e infinita, con innumerables secretos esperando que los descubras...'
epilogue_1: 'La galaxia es vasta e infinita, con innumerables secretos esperando que los descubras...',
epilogue_2: 'Tu viaje continúa... Nuevas aventuras esperan más allá de las estrellas...'
}
}
},

View File

@@ -165,6 +165,7 @@ export default {
planetDestroyerFactory: '惑星破壊工場',
geoResearchStation: '地質研究所',
deepDrillingFacility: '深部掘削施設',
university: '大学',
buildTime: '建設時間',
build: '建設',
production: '生産量',
@@ -215,8 +216,9 @@ export default {
sensorPhalanx: '周辺星系の艦隊活動を探知',
jumpGate: '他の月へ艦隊を瞬間移動',
planetDestroyerFactory: '惑星を破壊できる究極兵器を建造',
geoResearchStation: '地質構造を研究し、鉱脈の自然回復速度を向上。レベル毎に回復速度50%増加',
deepDrillingFacility: ''
geoResearchStation: '地質構造を研究し、鉱脈の自然回復速度を向上。レベル毎に回復速度10%増加',
deepDrillingFacility: '',
university: '研究者を育成し、研究速度を加速。レベル毎に研究時間-8%'
},
ships: {
lightFighter: '軽戦闘機',
@@ -299,7 +301,11 @@ export default {
colonySlots: '植民地スロット',
forAllPlanets: '(全惑星)',
speedBonus: '速度ボーナス',
researchSpeedBonus: '研究速度ボーナス'
researchSpeedBonus: '研究速度ボーナス',
// 資源生産ボーナス表示
mineralResearch: '鉱物研究',
crystalResearch: 'クリスタル研究',
fuelResearch: '燃料研究'
},
technologies: {
energyTechnology: 'エネルギー技術',
@@ -320,7 +326,11 @@ export default {
darkMatterTechnology: 'ダークマター技術',
terraformingTechnology: 'テラフォーミング技術',
planetDestructionTech: '惑星破壊技術',
miningTechnology: ''
miningTechnology: '',
intergalacticResearchNetwork: '銀河間研究ネットワーク',
mineralResearch: '鉱物研究',
crystalResearch: 'クリスタル研究',
fuelResearch: '燃料研究'
},
technologyDescriptions: {
energyTechnology: 'エネルギー利用効率を向上',
@@ -342,7 +352,11 @@ export default {
darkMatterTechnology: 'ダークマターの性質と応用を研究',
terraformingTechnology: '惑星地形改造技術を研究、レベル毎に全惑星の利用可能スペース30増加',
planetDestructionTech: '惑星全体を破壊する恐怖の技術を研究',
miningTechnology: ''
miningTechnology: '',
intergalacticResearchNetwork: '複数の惑星の研究所を連結。レベル毎に追加1研究所を接続',
mineralResearch: 'より効率的な金属抽出技術を研究。レベル毎に金属生産+2%',
crystalResearch: 'より効率的なクリスタル精製技術を研究。レベル毎にクリスタル生産+2%',
fuelResearch: 'より効率的な重水素合成技術を研究。レベル毎に重水素生産+2%'
},
officers: {
commander: '司令官',
@@ -955,7 +969,10 @@ export default {
hideRoundDetails: 'ラウンド詳細非表示',
round: '第{round}ラウンド',
attackerRemainingPower: '攻撃側残存火力',
defenderRemainingPower: '防御側残存火力'
defenderRemainingPower: '防御側残存火力',
importFromSpyReport: 'スパイレポートからインポート',
selectSpyReport: 'スパイレポートを選択',
noSpyReports: 'スパイレポートがありません'
},
settings: {
dataManagement: 'データ管理',
@@ -966,6 +983,7 @@ export default {
exporting: 'エクスポート中...',
exportSuccess: 'エクスポート成功',
exportSuccessWithPath: 'エクスポート成功、ファイルの保存先:{path}',
storagePermissionDenied: 'ストレージ権限が拒否されました。ファイルをエクスポートできません',
exportFailed: 'エクスポートに失敗しました。もう一度お試しください',
importData: 'データインポート',
importDataDesc: 'JSONファイルからゲームの進行状況を復元',
@@ -983,6 +1001,8 @@ export default {
gameSettingsDesc: 'ゲームパラメータと設定を調整',
gamePause: 'ゲーム一時停止',
gamePauseDesc: 'ゲーム時間と資源生産を一時停止または再開',
battleMode: '最後まで戦うモード',
battleModeDesc: '有効にすると、勝者が決まるまで最大100ラウンドの戦闘が行われます。無効の場合は、クラシックな6ラウンドモードが使用されます',
pause: '一時停止',
resume: '再開',
gamePaused: 'ゲームを一時停止しました',
@@ -1996,13 +2016,19 @@ export default {
questNotActive: 'クエストはアクティブではありません',
questNotCompleted: 'クエスト未完了',
rewardsAlreadyClaimed: '報酬は既に受け取り済み',
prerequisiteNotMet: '前提クエスト未完了'
prerequisiteNotMet: '前提クエスト未完了',
questLocked: 'クエストはロックされています',
notInitialized: 'キャンペーンが初期化されていません',
questAlreadyCompleted: 'クエストは既に完了しています'
},
speakers: {
ancientVoice: '古代の声',
neighborNPC: '隣接勢力',
mysteriousSignal: '謎の信号',
enemyCommander: '敵司令官'
enemyCommander: '敵司令官',
shadowVoice: '影の声',
allyNPC: '同盟勢力',
ancientGuardian: '古代の守護者'
},
objectiveDescriptions: {
buildMetalMine: '金属鉱山をレベル2に建設',
@@ -2082,36 +2108,60 @@ export default {
},
'2_3': {
prologue_1: '遠征で異常な信号を発見しました。これらの信号は古代文明からのようです...発信源を調査してください。',
prologue_2: 'これらの信号...失われた文明の残響を運んでいる。その秘密が発見を待っている...',
epilogue_1: 'これらの記号は...古代文明の遺跡だ!さらに調査して秘密を解き明かそう。'
},
'2_4': { prologue_1: '古代遺跡の場所を発見しました。艦隊を送り、何が見つかるか探索してください。' },
'2_5': { prologue_1: '遺跡でデータアーカイブが見つかりました。このデータを研究すれば、新しい技術が解放できるかもしれません。' },
'2_4': {
prologue_1: '古代遺跡の場所を発見しました。艦隊を送り、何が見つかるか探索してください。',
prologue_2: '遺跡には多くの秘密がある...賢く道を選べ...',
choice_1: '慎重に探索する - 安全を優先',
choice_2: '積極的に探索する - 発見を優先'
},
'2_5': {
prologue_1: '遺跡でデータアーカイブが見つかりました。このデータを研究すれば、新しい技術が解放できるかもしれません。',
epilogue_1: '古代のデータが解読されました!新しい技術的洞察を得ました。'
},
'3_1': { prologue_1: '探索中も外交を忘れないでください。周囲の勢力と良好な関係を維持することは有益です。' },
'3_2': { prologue_1: 'いくつかの勢力が友好を示しています。関係を深め続ければ、より多くのサポートを得られるかもしれません。' },
'3_3': { prologue_1: '情報によると敵対勢力が影からあなたを監視しています。警戒を怠らず、彼らの動きを偵察してください。' },
'3_3': {
prologue_1: '情報によると敵対勢力が影からあなたを監視しています。警戒を怠らず、彼らの動きを偵察してください。',
prologue_2: '闇の力が虚空で蠢いている...彼らはあなたの成長する力に気づいた...'
},
'3_4': { prologue_1: '友好勢力と正式な同盟を結び、脅威に対してお互いをサポートしましょう。' },
'3_5': { prologue_1: '脅威が迫っています。防衛施設を建設し、可能な紛争に備えてください。' },
'3_5': {
prologue_1: '脅威が迫っています。防衛施設を建設し、可能な紛争に備えてください。',
epilogue_1: '防衛準備が整いました。嵐が来るが、あなたは準備ができている。'
},
'4_1': {
prologue_1: '敵が攻撃を開始しました!惑星を守ってください!',
prologue_2: '影の艦隊が迫っている...あなたの試練の時が来た...',
epilogue_1: '敵の第一波を撃退しました。しかしこれは始まりに過ぎません...'
},
'4_2': { prologue_1: '敵は撤退しましたが、戻ってくるでしょう。彼らの惑星を偵察して戦力を把握してください。' },
'4_3': { prologue_1: '反撃の時です。敵の惑星を攻撃し、彼らの戦力を弱めてください。' },
'4_4': { prologue_1: '戦場に多くのデブリが残っています。これらの資源をリサイクルして次の戦闘に備えてください。' },
'4_5': { prologue_1: '最終決戦が近づいています。強力な艦隊を建造し、究極の挑戦に備えてください。' },
'4_5': {
prologue_1: '最終決戦が近づいています。強力な艦隊を建造し、究極の挑戦に備えてください。',
epilogue_1: '艦隊が集結しました。決戦の時が近づいている...'
},
'5_1': {
prologue_1: 'すべての手がかりは遺跡の最深部を指しています。古代文明の核心的な秘密がそこにあります。',
prologue_2: 'ついに到着した...真実がまもなく明かされる...'
},
'5_2': { prologue_1: '遺跡の深部で失われた古代技術を発見しました。研究してその力を解放してください。' },
'5_2': {
prologue_1: '遺跡の深部で失われた古代技術を発見しました。研究してその力を解放してください。',
prologue_2: 'この技術は...既知のすべての文明より古い。慎重に扱え...'
},
'5_3': {
prologue_1: '謎の敵が現れました。これが最後の挑戦です。撃破してください!',
prologue_2: '私はこれらの秘密の守護者だ。お前の価値を証明せよ、さもなくば滅びよ!',
epilogue_1: 'やりました!古代の守護者は倒されました。銀河の秘密は今やあなたに開かれています。'
},
'5_4': { prologue_1: 'ついに平和が訪れました。この新時代に新しい植民地を築き、帝国を拡大してください。' },
'5_5': {
prologue_1: 'あなたの伝説は始まったばかりです。さらに探索を続け、より多くの星系を征服してください!',
epilogue_1: '銀河は広大で果てしなく、数え切れない秘密があなたを待っています...'
epilogue_1: '銀河は広大で果てしなく、数え切れない秘密があなたを待っています...',
epilogue_2: 'あなたの旅は続く...新たな冒険が星の彼方で待っている...'
}
}
}

View File

@@ -153,6 +153,7 @@ export default {
planetDestroyerFactory: '행성 파괴 공장',
geoResearchStation: '지질 연구소',
deepDrillingFacility: '심층 시추 시설',
university: '대학',
buildTime: '건설 시간',
build: '건설',
production: '생산량',
@@ -199,8 +200,9 @@ export default {
sensorPhalanx: '주변 행성계의 함대 활동 감지',
jumpGate: '다른 위성으로 함대 순간 이동',
planetDestroyerFactory: '행성을 파괴할 수 있는 궁극 병기 건조',
geoResearchStation: '지질 구조를 연구하여 광맥 자연 회복 속도를 높입니다. 레벨당 회복 속도 50% 증가',
deepDrillingFacility: ''
geoResearchStation: '지질 구조를 연구하여 광맥 자연 회복 속도를 높입니다. 레벨당 회복 속도 10% 증가',
deepDrillingFacility: '',
university: '연구원을 양성하여 연구 속도를 가속합니다. 레벨당 연구 시간 -8%'
},
ships: {
lightFighter: '경전투기',
@@ -276,7 +278,11 @@ export default {
colonySlots: '식민지 슬롯',
forAllPlanets: '(전역)',
speedBonus: '속도 보너스',
researchSpeedBonus: '연구 속도 보너스'
researchSpeedBonus: '연구 속도 보너스',
// 자원 생산 보너스 표시
mineralResearch: '광물 연구',
crystalResearch: '크리스탈 연구',
fuelResearch: '연료 연구'
},
technologies: {
energyTechnology: '에너지 기술',
@@ -297,7 +303,11 @@ export default {
darkMatterTechnology: '암흑 물질 기술',
terraformingTechnology: '지형 변환 기술',
planetDestructionTech: '행성 파괴 기술',
miningTechnology: ''
miningTechnology: '',
intergalacticResearchNetwork: '은하간 연구 네트워크',
mineralResearch: '광물 연구',
crystalResearch: '크리스탈 연구',
fuelResearch: '연료 연구'
},
technologyDescriptions: {
energyTechnology: '에너지 이용 효율 향상',
@@ -319,7 +329,11 @@ export default {
darkMatterTechnology: '암흑 물질의 성질과 응용 연구',
terraformingTechnology: '행성 지형 개조 기술 연구, 레벨당 모든 행성의 가용 공간 30 증가',
planetDestructionTech: '행성 전체를 파괴하는 공포의 기술 연구',
miningTechnology: ''
miningTechnology: '',
intergalacticResearchNetwork: '여러 행성의 연구소를 연결합니다. 레벨당 1개 추가 연구소 연결',
mineralResearch: '더 효율적인 금속 추출 기술 연구. 레벨당 금속 생산 +2%',
crystalResearch: '더 효율적인 크리스탈 정제 기술 연구. 레벨당 크리스탈 생산 +2%',
fuelResearch: '더 효율적인 중수소 합성 기술 연구. 레벨당 중수소 생산 +2%'
},
officers: {
commander: '사령관',
@@ -910,7 +924,10 @@ export default {
hideRoundDetails: '라운드 상세 숨기기',
round: '제 {round} 라운드',
attackerRemainingPower: '공격자 잔여 화력',
defenderRemainingPower: '방어자 잔여 화력'
defenderRemainingPower: '방어자 잔여 화력',
importFromSpyReport: '정찰 보고서에서 가져오기',
selectSpyReport: '정찰 보고서 선택',
noSpyReports: '정찰 보고서가 없습니다'
},
settings: {
dataManagement: '데이터 관리',
@@ -921,6 +938,7 @@ export default {
exporting: '내보내는 중...',
exportSuccess: '내보내기 성공',
exportSuccessWithPath: '내보내기 성공, 파일 저장 위치: {path}',
storagePermissionDenied: '저장소 권한이 거부되어 파일을 내보낼 수 없습니다',
exportFailed: '내보내기 실패, 다시 시도해주세요',
importData: '데이터 가져오기',
importDataDesc: 'JSON 파일에서 게임 진행 상황 복원',
@@ -938,6 +956,8 @@ export default {
gameSettingsDesc: '게임 매개변수 및 설정 조정',
gamePause: '게임 일시정지',
gamePauseDesc: '게임 시간 및 자원 생산 일시정지 또는 재개',
battleMode: '끝까지 싸우기 모드',
battleModeDesc: '활성화하면 승자가 결정될 때까지 최대 100라운드까지 전투가 진행됩니다. 비활성화하면 클래식 6라운드 모드가 사용됩니다',
pause: '일시정지',
resume: '재개',
gamePaused: '게임이 일시정지되었습니다',
@@ -1936,13 +1956,19 @@ export default {
questNotActive: '퀘스트가 활성화되지 않았습니다',
questNotCompleted: '퀘스트 미완료',
rewardsAlreadyClaimed: '이미 보상을 받았습니다',
prerequisiteNotMet: '선행 퀘스트 미완료'
prerequisiteNotMet: '선행 퀘스트 미완료',
questLocked: '퀘스트가 잠겨 있습니다',
notInitialized: '캠페인이 초기화되지 않았습니다',
questAlreadyCompleted: '퀘스트가 이미 완료되었습니다'
},
speakers: {
ancientVoice: '고대의 목소리',
neighborNPC: '인접 세력',
mysteriousSignal: '신비한 신호',
enemyCommander: '적 사령관'
enemyCommander: '적 사령관',
shadowVoice: '그림자의 목소리',
allyNPC: '동맹 세력',
ancientGuardian: '고대의 수호자'
},
objectiveDescriptions: {
buildMetalMine: '금속 광산을 레벨 2로 건설',
@@ -2023,38 +2049,60 @@ export default {
},
'2_3': {
prologue_1: '탐험에서 이상한 신호를 발견했습니다. 이 신호들은 고대 문명에서 온 것 같습니다... 출처를 조사하세요.',
prologue_2: '이 신호들... 잃어버린 문명의 메아리를 담고 있다. 그들의 비밀이 발견을 기다리고 있다...',
epilogue_1: '이 기호들은... 고대 문명의 유적이다! 계속 조사하여 비밀을 밝히세요.'
},
'2_4': { prologue_1: '고대 유적의 위치를 발견했습니다. 함대를 보내 무엇을 발견할 수 있는지 탐험하세요.' },
'2_5': { prologue_1: '유적에서 데이터 아카이브가 발견되었습니다. 이 데이터를 연구하면 새 기술을 해금할 수 있을지도 모릅니다.' },
'2_4': {
prologue_1: '고대 유적의 위치를 발견습니다. 함대를 보내 무엇을 발견할 수 있는지 탐험하세요.',
prologue_2: '유적에는 많은 비밀이 있다... 현명하게 길을 선택하라...',
choice_1: '신중하게 탐험 - 안전 우선',
choice_2: '적극적으로 탐험 - 발견 우선'
},
'2_5': {
prologue_1: '유적에서 데이터 아카이브가 발견되었습니다. 이 데이터를 연구하면 새 기술을 해금할 수 있을지도 모릅니다.',
epilogue_1: '고대 데이터가 해독되었습니다! 새로운 기술적 통찰을 얻었습니다.'
},
'3_1': { prologue_1: '탐험 중에도 외교를 잊지 마세요. 주변 세력과 좋은 관계를 유지하는 것이 유익합니다.' },
'3_2': { prologue_1: '일부 세력이 우호를 보이고 있습니다. 관계를 계속 깊게 하면 더 많은 지원을 받을 수 있을지도 모릅니다.' },
'3_3': {
prologue_1: '정보에 따르면 적대 세력이 그림자에서 당신을 감시하고 있습니다. 경계를 늦추지 말고 그들의 움직임을 정찰하세요.'
prologue_1: '정보에 따르면 적대 세력이 그림자에서 당신을 감시하고 있습니다. 경계를 늦추지 말고 그들의 움직임을 정찰하세요.',
prologue_2: '어둠의 힘이 허공에서 움직이고 있다... 그들은 당신의 성장하는 힘을 알아챘다...'
},
'3_4': { prologue_1: '우호 세력과 공식 동맹을 맺어 위협에 대해 서로를 지원하세요.' },
'3_5': { prologue_1: '위협이 다가오고 있습니다. 방어 시설을 건설하고 가능한 충돌에 대비하세요.' },
'3_5': {
prologue_1: '위협이 다가오고 있습니다. 방어 시설을 건설하고 가능한 충돌에 대비하세요.',
epilogue_1: '방어 준비가 완료되었습니다. 폭풍이 오지만, 당신은 준비가 되어 있습니다.'
},
'4_1': {
prologue_1: '적이 공격을 시작했습니다! 행성을 방어하세요!',
prologue_2: '그림자 함대가 다가온다... 당신의 시련의 시간이 왔다...',
epilogue_1: '적의 첫 번째 파도를 성공적으로 격퇴했습니다. 하지만 이것은 시작에 불과합니다...'
},
'4_2': { prologue_1: '적이 후퇴했지만 돌아올 것입니다. 그들의 행성을 정찰하여 전력을 파악하세요.' },
'4_3': { prologue_1: '반격할 시간입니다. 적 행성을 공격하여 그들의 전력을 약화시키세요.' },
'4_4': { prologue_1: '전장에 많은 잔해가 남아 있습니다. 이 자원을 재활용하여 다음 전투에 대비하세요.' },
'4_5': { prologue_1: '최종 전투가 다가오고 있습니다. 강력한 함대를 건조하고 궁극의 도전에 대비하세요.' },
'4_5': {
prologue_1: '최종 전투가 다가오고 있습니다. 강력한 함대를 건조하고 궁극의 도전에 대비하세요.',
epilogue_1: '함대가 집결했습니다. 결전의 시간이 다가온다...'
},
'5_1': {
prologue_1: '모든 단서가 유적의 가장 깊은 곳을 가리킵니다. 고대 문명의 핵심 비밀이 그곳에 있습니다.',
prologue_2: '드디어 도착했다... 진실이 곧 밝혀질 것이다...'
},
'5_2': { prologue_1: '유적 깊은 곳에서 잃어버린 고대 기술을 발견했습니다. 연구하여 그 힘을 해방하세요.' },
'5_2': {
prologue_1: '유적 깊은 곳에서 잃어버린 고대 기술을 발견했습니다. 연구하여 그 힘을 해방하세요.',
prologue_2: '이 기술은... 알려진 모든 문명보다 오래되었다. 신중하게 다루어라...'
},
'5_3': {
prologue_1: '신비한 적이 나타났습니다. 이것이 마지막 도전입니다. 격파하세요!',
prologue_2: '나는 이 비밀들의 수호자다. 네 가치를 증명하라, 그렇지 않으면 멸망하라!',
epilogue_1: '해냈습니다! 고대의 수호자가 쓰러졌습니다. 은하의 비밀이 이제 당신에게 열려 있습니다.'
},
'5_4': { prologue_1: '마침내 평화가 찾아왔습니다. 이 새 시대에 새 식민지를 세우고 제국을 확장하세요.' },
'5_5': {
prologue_1: '당신의 전설은 이제 막 시작되었습니다. 계속 탐험하고 더 많은 성계를 정복하세요!',
epilogue_1: '은하는 광대하고 끝이 없으며, 셀 수 없는 비밀이 당신을 기다리고 있습니다...'
epilogue_1: '은하는 광대하고 끝이 없으며, 셀 수 없는 비밀이 당신을 기다리고 있습니다...',
epilogue_2: '당신의 여정은 계속된다... 새로운 모험이 별 너머에서 기다리고 있다...'
}
}
}

View File

@@ -154,6 +154,7 @@ export default {
planetDestroyerFactory: 'Фабрика разрушителей планет',
geoResearchStation: 'Геологическая станция',
deepDrillingFacility: 'Глубинная буровая установка',
university: 'Университет',
buildTime: 'Время строительства',
build: 'Построить',
production: 'Производство',
@@ -205,8 +206,9 @@ export default {
jumpGate: 'Мгновенно переносит флоты на другие луны',
planetDestroyerFactory: 'Производит абсолютное оружие, способное уничтожать планеты',
geoResearchStation:
'Исследует геологическую структуру и повышает скорость восстановления рудных месторождений. +50% скорости восстановления за уровень',
deepDrillingFacility: ''
'Исследует геологическую структуру и повышает скорость восстановления рудных месторождений. +10% скорости восстановления за уровень',
deepDrillingFacility: '',
university: 'Обучает исследователей для ускорения исследований. -8% времени исследования за уровень'
},
ships: {
lightFighter: 'Лёгкий истребитель',
@@ -288,7 +290,11 @@ export default {
researchQueueBonus: 'Очередь исследований',
colonySlots: 'Слоты колоний',
forAllPlanets: '(Глобально)',
speedBonus: 'Бонус скорости'
speedBonus: 'Бонус скорости',
// Отображение бонуса производства ресурсов
mineralResearch: 'Минеральные исследования',
crystalResearch: 'Кристаллические исследования',
fuelResearch: 'Топливные исследования'
},
technologies: {
energyTechnology: 'Энергетическая технология',
@@ -309,7 +315,11 @@ export default {
darkMatterTechnology: 'Технология тёмной материи',
terraformingTechnology: 'Технология терраформирования',
planetDestructionTech: 'Технология уничтожения планет',
miningTechnology: ''
miningTechnology: '',
intergalacticResearchNetwork: 'Межгалактическая исследовательская сеть',
mineralResearch: 'Исследование минералов',
crystalResearch: 'Исследование кристаллов',
fuelResearch: 'Исследование топлива'
},
technologyDescriptions: {
energyTechnology: 'Улучшает энергоэффективность',
@@ -332,7 +342,11 @@ export default {
terraformingTechnology:
'Исследование технологии терраформирования планет, увеличивает доступное пространство всех планет на 30 за уровень',
planetDestructionTech: 'Исследование ужасающей технологии уничтожения целых планет',
miningTechnology: ''
miningTechnology: '',
intergalacticResearchNetwork: 'Связывает несколько исследовательских лабораторий на разных планетах. Каждый уровень подключает 1 дополнительную лабораторию',
mineralResearch: 'Исследование более эффективных методов добычи металла. +2% производства металла за уровень',
crystalResearch: 'Исследование более эффективных методов обработки кристаллов. +2% производства кристаллов за уровень',
fuelResearch: 'Исследование более эффективных методов синтеза дейтерия. +2% производства дейтерия за уровень'
},
officers: {
commander: 'Командир',
@@ -933,7 +947,10 @@ export default {
hideRoundDetails: 'Скрыть детали раундов',
round: 'Раунд {round}',
attackerRemainingPower: 'Оставшаяся мощь нападающего',
defenderRemainingPower: 'Оставшаяся мощь защитника'
defenderRemainingPower: 'Оставшаяся мощь защитника',
importFromSpyReport: 'Импорт из шпионского отчета',
selectSpyReport: 'Выбрать шпионский отчет',
noSpyReports: 'Нет шпионских отчетов'
},
settings: {
dataManagement: 'Управление данными',
@@ -944,6 +961,7 @@ export default {
exporting: 'Экспорт...',
exportSuccess: 'Экспорт успешен',
exportSuccessWithPath: 'Экспорт успешен, файл сохранен в: {path}',
storagePermissionDenied: 'Разрешение на хранение отклонено, невозможно экспортировать файл',
exportFailed: 'Экспорт не удался, попробуйте еще раз',
importData: 'Импорт данных',
importDataDesc: 'Восстановить прогресс игры из JSON файла',
@@ -961,6 +979,8 @@ export default {
gameSettingsDesc: 'Настроить параметры и предпочтения игры',
gamePause: 'Пауза игры',
gamePauseDesc: 'Приостановить или возобновить игровое время и производство ресурсов',
battleMode: 'Режим боя до конца',
battleModeDesc: 'При включении бои длятся до 100 раундов до определения победителя. При выключении используется классический режим 6 раундов',
pause: 'Пауза',
resume: 'Возобновить',
gamePaused: 'Игра приостановлена',
@@ -1993,13 +2013,19 @@ export default {
questNotActive: 'Квест не активен',
questNotCompleted: 'Квест не завершён',
rewardsAlreadyClaimed: 'Награды уже получены',
prerequisiteNotMet: 'Предварительный квест не завершён'
prerequisiteNotMet: 'Предварительный квест не завершён',
questLocked: 'Квест заблокирован',
notInitialized: 'Кампания не инициализирована',
questAlreadyCompleted: 'Квест уже завершён'
},
speakers: {
ancientVoice: 'Древний голос',
neighborNPC: 'Соседняя фракция',
mysteriousSignal: 'Загадочный сигнал',
enemyCommander: 'Вражеский командир'
enemyCommander: 'Вражеский командир',
shadowVoice: 'Голос тени',
allyNPC: 'Союзная фракция',
ancientGuardian: 'Древний страж'
},
objectiveDescriptions: {
buildMetalMine: 'Построить Металлургический завод до уровня 2',
@@ -2089,12 +2115,19 @@ export default {
'2_3': {
prologue_1:
'Ваша экспедиция обнаружила аномальные сигналы. Эти сигналы, похоже, исходят от древней цивилизации... Исследуйте их источник.',
prologue_2: 'Эти сигналы... Они несут отголоски исчезнувшей цивилизации. Их тайны ждут открытия...',
epilogue_1: 'Эти символы... Это руины древней цивилизации! Продолжайте исследование, чтобы раскрыть их тайны.'
},
'2_4': {
prologue_1: 'Вы нашли местоположение древних руин. Отправьте свой флот на исследование и посмотрите, что вы можете обнаружить.'
prologue_1: 'Вы нашли местоположение древних руин. Отправьте свой флот на исследование и посмотрите, что вы можете обнаружить.',
prologue_2: 'В руинах скрыто много тайн... Выбирайте путь мудро...',
choice_1: 'Исследовать осторожно - приоритет безопасности',
choice_2: 'Исследовать агрессивно - приоритет открытий'
},
'2_5': {
prologue_1: 'В руинах найдены архивы данных. Изучите эти данные, возможно, вы сможете разблокировать новую технологию.',
epilogue_1: 'Древние данные расшифрованы! Получены новые технологические знания.'
},
'2_5': { prologue_1: 'В руинах найдены архивы данных. Изучите эти данные, возможно, вы сможете разблокировать новую технологию.' },
'3_1': {
prologue_1: 'Во время исследований не забывайте о дипломатии. Поддержание хороших отношений с окружающими фракциями выгодно.'
},
@@ -2103,31 +2136,44 @@ export default {
},
'3_3': {
prologue_1:
'Разведка показывает, что враждебные силы наблюдают за вами из тени. Оставайтесь бдительными и разведайте их перемещения.'
'Разведка показывает, что враждебные силы наблюдают за вами из тени. Оставайтесь бдительными и разведайте их перемещения.',
prologue_2: 'Тёмные силы шевелятся в пустоте... Они заметили вашу растущую мощь...'
},
'3_4': { prologue_1: 'Заключите официальный альянс с дружественными фракциями для взаимной поддержки против угроз.' },
'3_5': { prologue_1: 'Угрозы приближаются. Постройте оборонительные сооружения и подготовьтесь к возможному конфликту.' },
'3_5': {
prologue_1: 'Угрозы приближаются. Постройте оборонительные сооружения и подготовьтесь к возможному конфликту.',
epilogue_1: 'Ваша оборона готова. Буря надвигается, но вы подготовлены.'
},
'4_1': {
prologue_1: 'Враг начал атаку! Защитите свою планету!',
prologue_2: 'Теневой флот приближается... Час твоего испытания настал...',
epilogue_1: 'Вы успешно отбили первую волну врага. Но это только начало...'
},
'4_2': { prologue_1: 'Враг отступил, но он вернётся. Разведайте их планеты, чтобы понять их силу.' },
'4_3': { prologue_1: 'Пора контратаковать. Атакуйте вражеские планеты и ослабьте их силы.' },
'4_4': { prologue_1: 'На поле боя осталось много обломков. Переработайте эти ресурсы для подготовки к следующей битве.' },
'4_5': { prologue_1: 'Финальная битва приближается. Постройте мощный флот и приготовьтесь к конечному испытанию.' },
'4_5': {
prologue_1: 'Финальная битва приближается. Постройте мощный флот и приготовьтесь к конечному испытанию.',
epilogue_1: 'Ваш флот собран. Решающий момент приближается...'
},
'5_1': {
prologue_1: 'Все улики указывают на самую глубокую часть руин. Ключевые тайны древней цивилизации находятся там.',
prologue_2: 'Ты наконец прибыл... Истина скоро откроется...'
},
'5_2': { prologue_1: 'В глубинах руин вы обнаружили утерянные древние технологии. Исследуйте и разблокируйте их мощь.' },
'5_2': {
prologue_1: 'В глубинах руин вы обнаружили утерянные древние технологии. Исследуйте и разблокируйте их мощь.',
prologue_2: 'Эта технология... Она древнее всех известных цивилизаций. Обращайтесь с ней осторожно...'
},
'5_3': {
prologue_1: 'Появился загадочный враг. Это финальное испытание. Победите его!',
prologue_2: 'Я — страж этих тайн. Докажи свою ценность или будешь уничтожен!',
epilogue_1: 'Вы справились! Древний страж повержен. Тайны галактики теперь открыты для вас.'
},
'5_4': { prologue_1: 'Мир наконец наступил. В эту новую эру основывайте новые колонии и расширяйте свою империю.' },
'5_5': {
prologue_1: 'Ваша легенда только началась. Продолжайте исследовать и завоёвывать больше звёздных систем!',
epilogue_1: 'Галактика необъятна и бесконечна, бесчисленные тайны ждут вас...'
epilogue_1: 'Галактика необъятна и бесконечна, бесчисленные тайны ждут вас...',
epilogue_2: 'Ваше путешествие продолжается... Новые приключения ждут за звёздами...'
}
}
}

View File

@@ -48,6 +48,8 @@ export default {
launchFailed: '发射失败',
fleetMissionsFull: '舰队任务槽位已满',
insufficientFleet: '舰队数量不足',
insufficientShips: '舰船数量不足',
invalidQuantity: '无效数量',
insufficientFuel: '燃料不足',
planetOnly: '该建筑只能在行星上建造',
moonOnly: '该建筑只能在月球上建造',
@@ -56,7 +58,12 @@ export default {
buildingLevelZero: '建筑等级为0无法拆除',
researchQueueFull: '研究队列已满',
moonExists: '已存在月球',
insufficientDebris: '残骸场不足'
insufficientDebris: '残骸场不足',
planetNotFound: '找不到星球',
cannotAbandonHomePlanet: '不能放弃母星',
hasBuildQueue: '请等待建造队列完成',
hasFleetOnPlanet: '请先转移或拆除所有舰船',
hasDefenseOnPlanet: '请先拆除所有防御设施'
},
nav: {
overview: '总览',
@@ -124,7 +131,12 @@ export default {
renamePlanet: '重命名星球',
renamePlanetTitle: '重命名星球',
planetNamePlaceholder: '输入新的星球名称',
rename: '重命名'
rename: '重命名',
abandonColony: '放弃殖民地',
confirmAbandon: '确认放弃殖民地',
abandonWarning: '确定要放弃 "{name}" 吗?\n\n此操作无法撤销\n所有建筑、资源和月球如有都将丢失。',
confirmAbandonButton: '放弃',
abandonFailed: '放弃失败'
},
player: {
points: '总积分'
@@ -153,6 +165,7 @@ export default {
planetDestroyerFactory: '行星毁灭者工厂',
geoResearchStation: '地质研究站',
deepDrillingFacility: '深层钻探设施',
university: '大学',
buildTime: '建造时间',
production: '产量',
consumption: '消耗',
@@ -200,8 +213,9 @@ export default {
sensorPhalanx: '侦测周围星系的舰队活动',
jumpGate: '瞬间传送舰队到其他月球',
planetDestroyerFactory: '建造能够摧毁行星的终极武器',
geoResearchStation: '研究地质结构,提高矿脉自然恢复速度。每级增加50%恢复速率',
deepDrillingFacility: '深入地壳钻探解锁更深层的矿脉储量。每级增加20%矿脉上限'
geoResearchStation: '研究地质结构,提高矿脉自然恢复速度。每级增加10%恢复速率',
deepDrillingFacility: '深入地壳钻探解锁更深层的矿脉储量。每级增加20%矿脉上限',
university: '培养科研人员加快研究速度。每级减少研究时间8%(与星际研究网络叠加)'
},
ships: {
lightFighter: '轻型战斗机',
@@ -276,7 +290,11 @@ export default {
researchQueueBonus: '研究队列',
colonySlots: '殖民地槽位',
forAllPlanets: '(全局)',
speedBonus: '速度加成'
speedBonus: '速度加成',
// 资源产量加成显示
mineralResearch: '矿物研究',
crystalResearch: '晶体研究',
fuelResearch: '燃料研究'
},
technologies: {
energyTechnology: '能源技术',
@@ -297,7 +315,11 @@ export default {
darkMatterTechnology: '暗物质技术',
terraformingTechnology: '地形改造技术',
planetDestructionTech: '行星毁灭技术',
miningTechnology: '采矿技术'
miningTechnology: '采矿技术',
intergalacticResearchNetwork: '星际研究网络',
mineralResearch: '矿物研究',
crystalResearch: '晶体研究',
fuelResearch: '燃料研究'
},
technologyDescriptions: {
energyTechnology: '提高能源利用效率',
@@ -319,7 +341,11 @@ export default {
darkMatterTechnology: '研究暗物质的性质和应用',
terraformingTechnology: '研究行星地形改造技术每级为所有行星增加30个可用空间',
planetDestructionTech: '研究如何摧毁整个行星的恐怖技术',
miningTechnology: '改进采矿方法和设备提升所有星球矿脉储量上限。每级增加15%矿脉上限'
miningTechnology: '改进采矿方法和设备提升所有星球矿脉储量上限。每级增加15%矿脉上限',
intergalacticResearchNetwork: '连接多个星球的研究实验室共享研究资源。每级可连接1个额外的研究实验室取等级最高的N个实验室',
mineralResearch: '研究更高效的金属提取技术提升金属矿产量。每级增加金属产量2%',
crystalResearch: '研究更高效的晶体提炼技术提升晶体矿产量。每级增加晶体产量2%',
fuelResearch: '研究更高效的重氢合成技术提升重氢产量。每级增加重氢产量2%'
},
officers: {
commander: '指挥官',
@@ -437,7 +463,12 @@ export default {
inputError: '输入错误',
inputErrorMessage: '请输入建造数量!',
buildFailed: '建造失败',
buildFailedMessage: '请检查资源是否足够或前置条件是否满足。'
buildFailedMessage: '请检查资源是否足够或前置条件是否满足。',
scrapQuantity: '拆除数量',
scrapRefund: '拆除返还 (50%)',
scrap: '拆除',
scrapFailed: '拆除失败',
scrapFailedMessage: '请检查舰船数量是否足够。'
},
defense: {
attack: '攻击力',
@@ -859,14 +890,14 @@ export default {
missileAttackFailed: '导弹攻击失败,目标星球不存在',
missileAttackIntercepted: '所有导弹被拦截',
hits: '枚命中',
expeditionResources: '远征队发现了资源!',
expeditionDarkMatter: '远征队发现了暗物质!',
expeditionFleet: '远征队发现了废弃的舰船!',
expeditionPiratesAttack: '远征队遭遇海盗袭击,损失了部分舰船',
expeditionPiratesEscaped: '远征队遭遇海盗,但成功逃脱',
expeditionAliensAttack: '远征队遭遇外星人袭击,损失了部分舰船',
expeditionAliensEscaped: '远征队遭遇外星人,但成功逃脱',
expeditionNothing: '远征队什么也没有发现'
expeditionResources: '探险队发现了资源!',
expeditionDarkMatter: '探险队发现了暗物质!',
expeditionFleet: '探险队发现了废弃的舰船!',
expeditionPiratesAttack: '探险队遭遇海盗袭击,损失了部分舰船',
expeditionPiratesEscaped: '探险队遭遇海盗,但成功逃脱',
expeditionAliensAttack: '探险队遭遇外星人袭击,损失了部分舰船',
expeditionAliensEscaped: '探险队遭遇外星人,但成功逃脱',
expeditionNothing: '探险队什么也没有发现'
},
simulatorView: {
title: '战斗模拟器',
@@ -903,7 +934,10 @@ export default {
hideRoundDetails: '隐藏回合详情',
round: '第 {round} 回合',
attackerRemainingPower: '攻击方剩余火力',
defenderRemainingPower: '防守方剩余火力'
defenderRemainingPower: '防守方剩余火力',
importFromSpyReport: '从侦查报告导入',
selectSpyReport: '选择侦查报告',
noSpyReports: '没有侦查报告'
},
settings: {
dataManagement: '数据管理',
@@ -914,6 +948,7 @@ export default {
exporting: '导出中...',
exportSuccess: '导出成功',
exportSuccessWithPath: '导出成功,文件已保存到:{path}',
storagePermissionDenied: '存储权限被拒绝,无法导出文件',
exportFailed: '导出失败,请重试',
importData: '导入数据',
importDataDesc: '从JSON文件恢复游戏进度',
@@ -931,6 +966,8 @@ export default {
gameSettingsDesc: '调整游戏参数和偏好设置',
gamePause: '游戏暂停',
gamePauseDesc: '暂停或恢复游戏时间和资源生产',
battleMode: '战斗到底模式',
battleModeDesc: '启用后战斗最多进行100回合直到分出胜负关闭则使用经典6回合模式',
pause: '暂停',
resume: '恢复',
gamePaused: '游戏已暂停',
@@ -1738,8 +1775,8 @@ export default {
colonizer: '成功殖民星球次数',
spy: '执行侦查任务次数',
deployer: '执行部署任务次数',
explorer: '远征总次数',
luckyExplorer: '远征成功次数',
explorer: '探险总次数',
luckyExplorer: '探险成功次数',
recycler: '回收任务次数',
scavenger: '回收资源总量',
destroyer: '摧毁星球次数',
@@ -1867,7 +1904,7 @@ export default {
},
'2_2': {
title: '深空探险',
description: '派遣舰队进行远征探险'
description: '派遣舰队进行探险探险'
},
'2_3': {
title: '神秘信号',
@@ -1963,13 +2000,19 @@ export default {
questNotActive: '任务未激活',
questNotCompleted: '任务未完成',
rewardsAlreadyClaimed: '奖励已领取',
prerequisiteNotMet: '前置任务未完成'
prerequisiteNotMet: '前置任务未完成',
questLocked: '任务已锁定',
notInitialized: '战役未初始化',
questAlreadyCompleted: '任务已完成'
},
speakers: {
ancientVoice: '古代之声',
neighborNPC: '邻近势力',
mysteriousSignal: '神秘信号',
enemyCommander: '敌方指挥官'
enemyCommander: '敌方指挥官',
shadowVoice: '暗影之声',
allyNPC: '盟友势力',
ancientGuardian: '远古守护者'
},
objectiveDescriptions: {
buildMetalMine: '建造金属矿到2级',
@@ -1989,10 +2032,10 @@ export default {
buildColonyShip: '建造殖民船',
colonizeNewPlanet: '殖民新星球',
colonizeMultiple: '殖民5个星球',
completeExpedition: '完成3次远征任务',
expeditionDeepSpace: '完成2次深空远征',
completeExpedition: '完成3次探险任务',
expeditionDeepSpace: '完成2次深空探险',
expeditionUncharted: '探索1次未知区域',
expeditionDangerous: '完成3次危险星云远征',
expeditionDangerous: '完成3次危险星云探险',
discoverRuins: '发现古代遗迹',
researchComputer: '研究电脑技术到4级',
researchImpulse: '研究脉冲驱动到3级',
@@ -2048,18 +2091,23 @@ export default {
prologue_2: '宇宙是无限的...更多的星球意味着更多的可能性...'
},
'2_2': {
prologue_1: '殖民成功!但宇宙深处还有更多秘密等待发现。派遣舰队进行远征探险吧。',
prologue_1: '殖民成功!但宇宙深处还有更多秘密等待发现。派遣舰队进行探险探险吧。',
prologue_2: '远方传来微弱的信号...那里有什么在等待着你...'
},
'2_3': {
prologue_1: '你的探险队发现了异常信号。这些信号似乎来自一个古老的文明...调查它们的来源。',
prologue_2: '这些信号...承载着一个早已消逝的文明的回响。它们的秘密等待被发现...',
epilogue_1: '这些符号...是古代文明的遗迹!继续调查,揭开它们的秘密。'
},
'2_4': {
prologue_1: '你发现了古代遗迹的位置。派遣舰队前去探索,看看能发现什么。'
prologue_1: '你发现了古代遗迹的位置。派遣舰队前去探索,看看能发现什么。',
prologue_2: '遗迹中隐藏着许多秘密...明智地选择你的道路...',
choice_1: '谨慎探索 - 优先安全',
choice_2: '激进探索 - 优先发现'
},
'2_5': {
prologue_1: '遗迹中发现了大量数据档案。研究这些数据,也许能解锁新的科技。'
prologue_1: '遗迹中发现了大量数据档案。研究这些数据,也许能解锁新的科技。',
epilogue_1: '古代数据已被解密!获得了新的科技洞见。'
},
'3_1': {
prologue_1: '在探索的同时,也不要忘记外交。与周围的势力保持良好关系对你有益。'
@@ -2068,16 +2116,19 @@ export default {
prologue_1: '有些势力对你表示了友好。继续加深关系,也许能获得更多支持。'
},
'3_3': {
prologue_1: '情报显示,有敌对势力正在暗中观察你。保持警惕,侦查他们的动向。'
prologue_1: '情报显示,有敌对势力正在暗中观察你。保持警惕,侦查他们的动向。',
prologue_2: '黑暗势力在虚空中蠢蠢欲动...他们已经注意到你日益增长的力量...'
},
'3_4': {
prologue_1: '与友好势力建立正式同盟,在面对威胁时互相支持。'
},
'3_5': {
prologue_1: '威胁正在逼近。建设防御设施,准备迎接可能的冲突。'
prologue_1: '威胁正在逼近。建设防御设施,准备迎接可能的冲突。',
epilogue_1: '你的防线已经准备就绪。风暴即将来临,但你已经做好了准备。'
},
'4_1': {
prologue_1: '敌人发动了进攻!保卫你的星球!',
prologue_2: '暗影舰队正在逼近...你的考验时刻已经到来...',
epilogue_1: '你成功击退了敌人的第一波进攻。但这只是开始...'
},
'4_2': {
@@ -2090,17 +2141,20 @@ export default {
prologue_1: '战场上留下了大量残骸。回收这些资源,为下一场战斗做准备。'
},
'4_5': {
prologue_1: '最终决战即将来临。建造强大的舰队,准备迎接最后的挑战。'
prologue_1: '最终决战即将来临。建造强大的舰队,准备迎接最后的挑战。',
epilogue_1: '你的舰队已经集结完毕。决定性的时刻即将到来...'
},
'5_1': {
prologue_1: '所有线索都指向遗迹的最深处。那里隐藏着古代文明最核心的秘密。',
prologue_2: '你终于来到了这里...真相即将揭晓...'
},
'5_2': {
prologue_1: '在遗迹深处,你发现了失落的古代科技。研究并解锁它们的力量。'
prologue_1: '在遗迹深处,你发现了失落的古代科技。研究并解锁它们的力量。',
prologue_2: '这项科技...比所有已知文明都要古老。小心处理...'
},
'5_3': {
prologue_1: '一个神秘的敌人出现了。这是最后的挑战,击败它!',
prologue_2: '我是这些秘密的守护者。证明你的价值,否则将被毁灭!',
epilogue_1: '你做到了!古代的守护者已被击败。银河系的秘密向你敞开。'
},
'5_4': {
@@ -2108,7 +2162,8 @@ export default {
},
'5_5': {
prologue_1: '你的传奇才刚刚开始。继续探索,征服更多的星系!',
epilogue_1: '银河系广阔无垠,还有无数秘密等待你去发现...'
epilogue_1: '银河系广阔无垠,还有无数秘密等待你去发现...',
epilogue_2: '你的旅程仍在继续...新的冒险在群星之外等待着你...'
}
}
},

View File

@@ -155,6 +155,7 @@ export default {
planetDestroyerFactory: '行星毀滅者工廠',
geoResearchStation: '地質研究站',
deepDrillingFacility: '深層鑽探設施',
university: '大學',
buildTime: '建造時間',
build: '建造',
production: '產量',
@@ -206,7 +207,8 @@ export default {
jumpGate: '瞬間傳送艦隊到其他月球',
planetDestroyerFactory: '建造能夠摧毀行星的終極武器',
geoResearchStation: '研究地質結構提高礦脈自然恢復速度。每級增加50%恢復速率',
deepDrillingFacility: ''
deepDrillingFacility: '',
university: '培養科研人員加快研究速度。每級減少研究時間8%'
},
ships: {
lightFighter: '輕型戰鬥機',
@@ -281,7 +283,11 @@ export default {
researchQueueBonus: '研究隊列',
colonySlots: '殖民地槽位',
forAllPlanets: '(全局)',
speedBonus: '速度加成'
speedBonus: '速度加成',
// 資源產量加成顯示
mineralResearch: '礦物研究',
crystalResearch: '晶體研究',
fuelResearch: '燃料研究'
},
technologies: {
energyTechnology: '能源技術',
@@ -302,7 +308,11 @@ export default {
darkMatterTechnology: '暗物質技術',
terraformingTechnology: '地形改造技術',
planetDestructionTech: '行星毀滅技術',
miningTechnology: ''
miningTechnology: '',
intergalacticResearchNetwork: '星際研究網絡',
mineralResearch: '礦物研究',
crystalResearch: '晶體研究',
fuelResearch: '燃料研究'
},
technologyDescriptions: {
energyTechnology: '提高能源利用效率',
@@ -324,7 +334,11 @@ export default {
darkMatterTechnology: '研究暗物質的性質和應用',
terraformingTechnology: '研究行星地形改造技術每級為所有行星增加30個可用空間',
planetDestructionTech: '研究如何摧毀整個行星的恐怖技術',
miningTechnology: ''
miningTechnology: '',
intergalacticResearchNetwork: '連接多個星球的研究實驗室共享研究資源。每級可連接1個額外的研究實驗室',
mineralResearch: '研究更高效的金屬提取技術提升金屬礦產量。每級增加金屬產量2%',
crystalResearch: '研究更高效的晶體提煉技術提升晶體礦產量。每級增加晶體產量2%',
fuelResearch: '研究更高效的重氫合成技術提升重氫產量。每級增加重氫產量2%'
},
officers: {
commander: '指揮官',
@@ -924,7 +938,10 @@ export default {
hideRoundDetails: '隱藏回合詳情',
round: '第 {round} 回合',
attackerRemainingPower: '攻擊方剩餘火力',
defenderRemainingPower: '防守方剩餘火力'
defenderRemainingPower: '防守方剩餘火力',
importFromSpyReport: '從偵查報告匯入',
selectSpyReport: '選擇偵查報告',
noSpyReports: '沒有偵查報告'
},
settings: {
dataManagement: '資料管理',
@@ -935,6 +952,7 @@ export default {
exporting: '匯出中...',
exportSuccess: '匯出成功',
exportSuccessWithPath: '匯出成功,檔案已儲存到:{path}',
storagePermissionDenied: '儲存權限被拒絕,無法匯出檔案',
exportFailed: '匯出失敗,請重試',
importData: '匯入資料',
importDataDesc: '從JSON檔案恢復遊戲進度',
@@ -952,6 +970,8 @@ export default {
gameSettingsDesc: '調整遊戲參數和偏好設定',
gamePause: '遊戲暫停',
gamePauseDesc: '暫停或恢復遊戲時間和資源生產',
battleMode: '戰鬥到底模式',
battleModeDesc: '啟用後戰鬥最多進行100回合直到分出勝負關閉則使用經典6回合模式',
pause: '暫停',
resume: '恢復',
gamePaused: '遊戲已暫停',
@@ -2159,13 +2179,19 @@ export default {
questNotActive: '任務未激活',
questNotCompleted: '任務未完成',
rewardsAlreadyClaimed: '獎勵已領取',
prerequisiteNotMet: '前置任務未完成'
prerequisiteNotMet: '前置任務未完成',
questLocked: '任務已鎖定',
notInitialized: '戰役未初始化',
questAlreadyCompleted: '任務已完成'
},
speakers: {
ancientVoice: '古代之聲',
neighborNPC: '鄰近勢力',
mysteriousSignal: '神秘信號',
enemyCommander: '敵方指揮官'
enemyCommander: '敵方指揮官',
shadowVoice: '暗影之聲',
allyNPC: '盟友勢力',
ancientGuardian: '遠古守護者'
},
objectiveDescriptions: {
buildMetalMine: '建造金屬礦到2級',
@@ -2249,13 +2275,18 @@ export default {
},
'2_3': {
prologue_1: '你的探險隊發現了異常信號。這些信號似乎來自一個古老的文明...調查它們的來源。',
prologue_2: '這些信號...承載著失落文明的回響。它們的秘密等待被發現...',
epilogue_1: '這些符號...是古代文明的遺跡!繼續調查,揭開它們的秘密。'
},
'2_4': {
prologue_1: '你發現了古代遺跡的位置。派遣艦隊前去探索,看看能發現什麼。'
prologue_1: '你發現了古代遺跡的位置。派遣艦隊前去探索,看看能發現什麼。',
prologue_2: '遺跡中藏有許多秘密...明智地選擇你的道路...',
choice_1: '謹慎探索 - 優先安全',
choice_2: '積極探索 - 優先發現'
},
'2_5': {
prologue_1: '遺跡中發現了大量數據檔案。研究這些數據,也許能解鎖新的科技。'
prologue_1: '遺跡中發現了大量數據檔案。研究這些數據,也許能解鎖新的科技。',
epilogue_1: '古代數據已被解密!獲得了新的技術見解。'
},
'3_1': {
prologue_1: '在探索的同時,也不要忘記外交。與周圍的勢力保持良好關係對你有益。'
@@ -2264,16 +2295,19 @@ export default {
prologue_1: '有些勢力對你表示了友好。繼續加深關係,也許能獲得更多支持。'
},
'3_3': {
prologue_1: '情報顯示,有敵對勢力正在暗中觀察你。保持警惕,偵查他們的動向。'
prologue_1: '情報顯示,有敵對勢力正在暗中觀察你。保持警惕,偵查他們的動向。',
prologue_2: '黑暗勢力在虛空中蠢蠢欲動...他們已經注意到你日益增長的力量...'
},
'3_4': {
prologue_1: '與友好勢力建立正式同盟,在面對威脅時互相支持。'
},
'3_5': {
prologue_1: '威脅正在逼近。建設防禦設施,準備迎接可能的衝突。'
prologue_1: '威脅正在逼近。建設防禦設施,準備迎接可能的衝突。',
epilogue_1: '你的防禦已經就緒。風暴即將來臨,但你已準備好了。'
},
'4_1': {
prologue_1: '敵人發動了進攻!保衛你的星球!',
prologue_2: '暗影艦隊正在逼近...你的考驗時刻已經到來...',
epilogue_1: '你成功擊退了敵人的第一波進攻。但這只是開始...'
},
'4_2': {
@@ -2286,17 +2320,20 @@ export default {
prologue_1: '戰場上留下了大量殘骸。回收這些資源,為下一場戰鬥做準備。'
},
'4_5': {
prologue_1: '最終決戰即將來臨。建造強大的艦隊,準備迎接最後的挑戰。'
prologue_1: '最終決戰即將來臨。建造強大的艦隊,準備迎接最後的挑戰。',
epilogue_1: '你的艦隊已經集結完畢。決戰時刻即將來臨...'
},
'5_1': {
prologue_1: '所有線索都指向遺跡的最深處。那裡隱藏著古代文明最核心的秘密。',
prologue_2: '你終於來到了這裡...真相即將揭曉...'
},
'5_2': {
prologue_1: '在遺跡深處,你發現了失落的古代科技。研究並解鎖它們的力量。'
prologue_1: '在遺跡深處,你發現了失落的古代科技。研究並解鎖它們的力量。',
prologue_2: '這項科技...比所有已知文明都要古老。小心處理它...'
},
'5_3': {
prologue_1: '一個神秘的敵人出現了。這是最後的挑戰,擊敗它!',
prologue_2: '我是這些秘密的守護者。證明你的價值,否則將被毀滅!',
epilogue_1: '你做到了!古代的守護者已被擊敗。銀河系的秘密向你敞開。'
},
'5_4': {
@@ -2304,7 +2341,8 @@ export default {
},
'5_5': {
prologue_1: '你的傳奇才剛剛開始。繼續探索,征服更多的星系!',
epilogue_1: '銀河系廣闘無垠,還有無數秘密等待你去發現...'
epilogue_1: '銀河系廣闘無垠,還有無數秘密等待你去發現...',
epilogue_2: '你的旅程還在繼續...新的冒險在星海彼岸等待著你...'
}
}
}

View File

@@ -15,7 +15,8 @@ export const simulateBattle = async (
_attackerOfficers: Record<OfficerType, Officer>,
_defenderOfficers: Record<OfficerType, Officer>,
attackerTechnologies: Record<TechnologyType, number>,
defenderTechnologies: Record<TechnologyType, number>
defenderTechnologies: Record<TechnologyType, number>,
battleToFinish: boolean = false // 战斗到底模式
): Promise<BattleResult> => {
// 从科技系统读取实际科技等级
const attackerWeaponTech = attackerTechnologies['weaponsTechnology'] || 0
@@ -41,7 +42,7 @@ export const simulateBattle = async (
shieldTech: defenderShieldTech,
armorTech: defenderArmorTech
},
maxRounds: 6 // 最多6回合
maxRounds: battleToFinish ? 100 : 6 // 战斗到底模式最多100回合经典模式6回合
})
// 计算掠夺(仅攻击方胜利时)

View File

@@ -23,30 +23,44 @@ export const calculateBuildingCost = (buildingType: BuildingType, targetLevel: n
/**
* 计算建筑升级时间
* 使用 2moons 公式(调整版):
* 1. 成本系数 = Σ (资源^0.3 / 0.003)
* 2. 时间(秒) = 成本系数 / ((1 + 机器人工厂) × 2^纳米工厂 × 游戏速度)
* @param buildingType 建筑类型
* @param targetLevel 目标等级
* @param buildingSpeedBonus 指挥官等提供的速度加成百分比
* @param roboticsFactoryLevel 机器人工厂等级
* @param naniteFactoryLevel 纳米工厂等级
* @param gameSpeed 游戏速度默认1
*/
export const calculateBuildingTime = (
buildingType: BuildingType,
targetLevel: number,
buildingSpeedBonus: number = 0,
roboticsFactoryLevel: number = 0,
naniteFactoryLevel: number = 0
naniteFactoryLevel: number = 0,
gameSpeed: number = 1
): number => {
const config = BUILDINGS[buildingType]
const multiplier = Math.pow(config.costMultiplier, targetLevel - 1)
const baseTime = config.baseTime * multiplier
// 计算该等级的成本
const cost = calculateBuildingCost(buildingType, targetLevel)
// 机器人工厂和纳米工厂的加速:建造时间 / (1 + 机器人工厂等级 + 纳米工厂等级 × 2)
const factorySpeedDivisor = 1 + roboticsFactoryLevel + naniteFactoryLevel * 2
// 2moons 公式:成本系数 = Σ (资源^0.3 / 0.003)
let elementCost = 0
if (cost.metal > 0) elementCost += Math.pow(cost.metal, 0.3) / 0.003
if (cost.crystal > 0) elementCost += Math.pow(cost.crystal, 0.3) / 0.003
if (cost.deuterium > 0) elementCost += Math.pow(cost.deuterium, 0.3) / 0.003
// 机器人工厂和纳米工厂的加速
const factoryBonus = (1 + roboticsFactoryLevel) * Math.pow(2, naniteFactoryLevel)
// 简化公式:时间(秒) = 成本系数 / (工厂加成 × 游戏速度)
const timeInSeconds = elementCost / (factoryBonus * gameSpeed)
// 指挥官等的百分比加成
const speedMultiplier = 1 - buildingSpeedBonus / 100
return Math.floor((baseTime / factorySpeedDivisor) * speedMultiplier)
// 确保最小时间为5秒
return Math.max(5, Math.floor(timeInSeconds * speedMultiplier))
}
/**
@@ -78,7 +92,16 @@ export const checkBuildingRequirements = (
for (const [key, level] of Object.entries(requirements)) {
const requiredLevel = level as number
if (Object.values(BuildingType).includes(key as BuildingType)) {
if ((planet.buildings[key as BuildingType] || 0) < requiredLevel) {
const requiredBuildingType = key as BuildingType
const requiredBuildingConfig = BUILDINGS[requiredBuildingType]
// 如果当前是月球且所需建筑是星球专属建筑planetOnly则跳过此前置条件
// 这允许在月球上建造机器人工厂等建筑,即使它们的前置条件是无法在月球建造的矿场
if (planet.isMoon && requiredBuildingConfig?.planetOnly) {
continue
}
if ((planet.buildings[requiredBuildingType] || 0) < requiredLevel) {
return false
}
} else if (Object.values(TechnologyType).includes(key as TechnologyType)) {
@@ -168,6 +191,12 @@ export const completeBuildQueue = (
const buildingType = item.itemType as BuildingType
const currentLevel = planet.buildings[buildingType] || 0
planet.buildings[buildingType] = Math.max(0, currentLevel - 1)
} else if (item.type === 'scrap_ship') {
// 舰船拆除完成,减少舰船数量(舰船已在开始拆除时扣除)
// 资源返还也在开始拆除时完成,这里不需要额外操作
if (onCompleted) {
onCompleted('ship', item.itemType, undefined, item.quantity)
}
}
return false
}

View File

@@ -2,6 +2,7 @@ import type { FleetMission, Planet, Resources, Fleet, BattleResult, SpyReport, P
import type { Locale } from '@/locales'
import { ShipType, DefenseType, MissionType, BuildingType, OfficerType, TechnologyType, ExpeditionZone } from '@/types/game'
import { FLEET_STORAGE_CONFIG, EXPEDITION_ZONES } from '@/config/gameConfig'
import { useGameStore } from '@/stores/gameStore'
import * as battleLogic from './battleLogic'
import * as moonLogic from './moonLogic'
import * as moonValidation from './moonValidation'
@@ -156,6 +157,7 @@ export const processAttackArrival = async (
}
// 执行战斗(使用 Worker 进行异步计算)
const gameStore = useGameStore()
const battleResult = await battleLogic.simulateBattle(
mission.fleet,
targetPlanet.fleet,
@@ -164,7 +166,8 @@ export const processAttackArrival = async (
attacker.officers,
defender?.officers || ({} as Record<OfficerType, Officer>),
attacker.technologies,
defender?.technologies || ({} as Record<TechnologyType, number>)
defender?.technologies || ({} as Record<TechnologyType, number>),
gameStore.battleToFinish
)
// 更新战斗报告ID
@@ -250,6 +253,7 @@ export const processNPCAttackArrival = async (
allPlanets: Planet[]
): Promise<{ battleResult: BattleResult; moon: Planet | null; debrisField: DebrisField | null } | null> => {
// 执行战斗(使用 Worker 进行异步计算)
const gameStore = useGameStore()
const battleResult = await battleLogic.simulateBattle(
mission.fleet, // NPC舰队
targetPlanet.fleet, // 玩家舰队
@@ -258,7 +262,8 @@ export const processNPCAttackArrival = async (
{} as Record<OfficerType, Officer>, // NPC没有军官系统
defender.officers || ({} as Record<OfficerType, Officer>), // 玩家军官
npc.technologies, // NPC科技等级
defender.technologies // 玩家科技等级
defender.technologies, // 玩家科技等级
gameStore.battleToFinish
)
// 更新战斗报告ID和参与者信息
@@ -721,12 +726,12 @@ export const processRecycleArrival = (
}
/**
* 远征事件类型
* 探险事件类型
*/
export type ExpeditionEventType = 'resources' | 'darkMatter' | 'fleet' | 'nothing' | 'pirates' | 'aliens'
/**
* 远征结果
* 探险结果
*/
export interface ExpeditionResult {
eventType: ExpeditionEventType
@@ -737,8 +742,8 @@ export interface ExpeditionResult {
}
/**
* 处理远征任务到达
* 远征任务会随机触发各种事件,基于探险区域配置
* 处理探险任务到达
* 探险任务会随机触发各种事件,基于探险区域配置
*/
export const processExpeditionArrival = (mission: FleetMission): ExpeditionResult => {
// 获取探险区域配置,默认为近空区域
@@ -968,9 +973,18 @@ export interface DestroyResult {
deathstarDestructionChance: number // 死星反向销毁概率
isMoon: boolean // 目标是否为月球
failReason?: DestroyFailReason // 失败原因
battleResult?: BattleResult // 战斗结果(如果发生了战斗)
debrisField?: DebrisField // 战斗产生的残骸场
moon?: Planet // 战斗产生的月球
}
export const processDestroyArrival = (mission: FleetMission, targetPlanet: Planet | undefined, attacker: Player): DestroyResult => {
export const processDestroyArrival = async (
mission: FleetMission,
targetPlanet: Planet | undefined,
attacker: Player,
defender: Player | null,
allPlanets: Planet[]
): Promise<DestroyResult> => {
if (!targetPlanet) {
mission.status = 'returning'
return {
@@ -995,8 +1009,8 @@ export const processDestroyArrival = (mission: FleetMission, targetPlanet: Plane
}
// 检查是否有死星
const deathstarCount = mission.fleet[ShipType.Deathstar] || 0
if (deathstarCount === 0) {
const initialDeathstarCount = mission.fleet[ShipType.Deathstar] || 0
if (initialDeathstarCount === 0) {
mission.status = 'returning'
return {
success: false,
@@ -1008,10 +1022,113 @@ export const processDestroyArrival = (mission: FleetMission, targetPlanet: Plane
}
}
// 检查目标是否有防御力量(舰队或防御设施)
const hasDefenderFleet = Object.values(targetPlanet.fleet || {}).some(count => count > 0)
const hasDefense = Object.values(targetPlanet.defense || {}).some(count => count > 0)
const needsBattle = hasDefenderFleet || hasDefense
let battleResult: BattleResult | undefined
let debrisField: DebrisField | undefined
let newMoon: Planet | undefined
let survivingDeathstars = initialDeathstarCount
// 如果目标有防御力量,先进行战斗
if (needsBattle) {
const gameStore = useGameStore()
// 执行战斗
battleResult = await battleLogic.simulateBattle(
mission.fleet,
targetPlanet.fleet,
targetPlanet.defense,
targetPlanet.resources,
attacker.officers,
defender?.officers || ({} as Record<OfficerType, Officer>),
attacker.technologies,
defender?.technologies || ({} as Record<TechnologyType, number>),
gameStore.battleToFinish
)
// 更新战斗报告
battleResult.id = `battle_${Date.now()}`
battleResult.attackerId = attacker.id
battleResult.defenderId = targetPlanet.ownerId || 'unknown'
battleResult.attackerPlanetId = mission.originPlanetId
battleResult.defenderPlanetId = targetPlanet.id
// 更新舰队 - 计算幸存舰船
const survivingFleet: Partial<Fleet> = {}
Object.entries(mission.fleet).forEach(([shipType, initialCount]) => {
const lost = battleResult!.attackerLosses[shipType as ShipType] || 0
const surviving = initialCount - lost
if (surviving > 0) {
survivingFleet[shipType as ShipType] = surviving
}
})
mission.fleet = survivingFleet
// 计算存活的死星数量
survivingDeathstars = survivingFleet[ShipType.Deathstar] || 0
// 更新目标星球舰队和防御
Object.entries(battleResult.defenderLosses.fleet).forEach(([shipType, lost]) => {
const current = targetPlanet.fleet[shipType as ShipType] || 0
targetPlanet.fleet[shipType as ShipType] = Math.max(0, current - lost)
})
Object.entries(battleResult.defenderLosses.defense).forEach(([defenseType, lost]) => {
const current = targetPlanet.defense[defenseType as DefenseType] || 0
targetPlanet.defense[defenseType as DefenseType] = Math.max(0, current - lost)
})
// 计算残骸场
const debrisResources = battleResult.debrisField
if (debrisResources.metal > 0 || debrisResources.crystal > 0) {
debrisField = {
id: `debris_${targetPlanet.position.galaxy}_${targetPlanet.position.system}_${targetPlanet.position.position}`,
position: { ...targetPlanet.position },
resources: {
metal: debrisResources.metal,
crystal: debrisResources.crystal
},
createdAt: Date.now()
}
}
// 检查是否生成月球(只有非月球位置才能生成月球)
if (!targetPlanet.isMoon && debrisField) {
const moonExists = moonLogic.hasMoonAtPosition(allPlanets, targetPlanet.position)
if (!moonExists) {
newMoon =
moonLogic.tryGenerateMoon(
{ ...debrisResources, deuterium: 0, darkMatter: 0, energy: 0 },
targetPlanet.position,
targetPlanet.id,
targetPlanet.ownerId || attacker.id
) || undefined
}
}
// 如果攻击方失败或没有存活的死星,直接返回
if (battleResult.winner === 'defender' || survivingDeathstars === 0) {
mission.status = 'returning'
return {
success: false,
destructionChance: 0,
deathstarsLost: initialDeathstarCount > 0 && survivingDeathstars === 0,
deathstarDestructionChance: 0,
isMoon: targetPlanet.isMoon || false,
failReason: survivingDeathstars === 0 ? 'noDeathstar' : 'chanceFailed',
battleResult,
debrisField,
moon: newMoon
}
}
}
// 根据目标类型使用不同的销毁逻辑
if (targetPlanet.isMoon) {
// 月球销毁使用 OGame 公式
const result = moonLogic.tryDestroyMoon(targetPlanet, deathstarCount)
const result = moonLogic.tryDestroyMoon(targetPlanet, survivingDeathstars)
// 如果死星被反向销毁,从任务舰队中移除
if (result.deathstarsDestroyed) {
@@ -1027,13 +1144,16 @@ export const processDestroyArrival = (mission: FleetMission, targetPlanet: Plane
deathstarsLost: result.deathstarsDestroyed,
deathstarDestructionChance: result.deathstarDestructionChance,
isMoon: true,
failReason: result.moonDestroyed ? undefined : 'chanceFailed'
failReason: result.moonDestroyed ? undefined : 'chanceFailed',
battleResult,
debrisField,
moon: newMoon
}
} else {
// 行星销毁使用原有逻辑
// 行星销毁使用原有逻辑(基于存活的死星数量)
const planetaryShieldCount = targetPlanet.defense[DefenseType.PlanetaryShield] || 0
const defensePower = calculatePlanetDefensePower(targetPlanet.fleet, targetPlanet.defense)
const destructionChance = calculateDestructionChance(deathstarCount, planetaryShieldCount, defensePower)
const destructionChance = calculateDestructionChance(survivingDeathstars, planetaryShieldCount, defensePower)
const randomValue = Math.random() * 100
const success = randomValue < destructionChance
@@ -1047,7 +1167,10 @@ export const processDestroyArrival = (mission: FleetMission, targetPlanet: Plane
deathstarsLost: false,
deathstarDestructionChance: 0,
isMoon: false,
failReason: success ? undefined : 'chanceFailed'
failReason: success ? undefined : 'chanceFailed',
battleResult,
debrisField,
moon: newMoon
}
}
}
@@ -1200,8 +1323,40 @@ export const updateFleetMissions = async (
}
break
case MissionType.Destroy:
const destroyResult = processDestroyArrival(mission, targetPlanet, attacker)
case MissionType.Destroy: {
const destroyResult = await processDestroyArrival(mission, targetPlanet, attacker, defender, allPlanets)
// 处理战斗报告
if (destroyResult.battleResult) {
battleReports.push(destroyResult.battleResult)
}
// 处理新生成的月球
if (destroyResult.moon) {
newMoons.push(destroyResult.moon)
const moonKey = `${destroyResult.moon.position.galaxy}:${destroyResult.moon.position.system}:${destroyResult.moon.position.position}`
planets.set(moonKey, destroyResult.moon)
}
// 处理残骸场
if (destroyResult.debrisField) {
const existingDebris = debrisFields.get(destroyResult.debrisField.id)
if (existingDebris) {
const updatedDebris: DebrisField = {
...existingDebris,
resources: {
metal: existingDebris.resources.metal + destroyResult.debrisField.resources.metal,
crystal: existingDebris.resources.crystal + destroyResult.debrisField.resources.crystal
}
}
debrisFields.set(destroyResult.debrisField.id, updatedDebris)
updatedDebrisFields.push(updatedDebris)
} else {
debrisFields.set(destroyResult.debrisField.id, destroyResult.debrisField)
newDebrisFields.push(destroyResult.debrisField)
}
}
if (destroyResult.success && destroyResult.planetId) {
// 星球被摧毁
destroyedPlanetIds.push(destroyResult.planetId)
@@ -1217,6 +1372,7 @@ export const updateFleetMissions = async (
planets.delete(targetKey)
}
break
}
}
}

View File

@@ -150,11 +150,20 @@ export const processGameUpdate = (
}
// 更新所有星球资源(直接同步计算,避免 Worker 通信开销)
// 获取采矿技术等级(用于矿脉恢复上限计算)
const miningTechLevel = player.technologies[TechnologyType.MiningTechnology] || 0
// 获取资源研究科技等级
const techBonuses = {
mineralResearchLevel: player.technologies[TechnologyType.MineralResearch] || 0,
crystalResearchLevel: player.technologies[TechnologyType.CrystalResearch] || 0,
fuelResearchLevel: player.technologies[TechnologyType.FuelResearch] || 0
}
player.planets.forEach(planet => {
// 计算更新前的资源(用于计算生产量)
const resourcesBefore = { ...planet.resources }
resourceLogic.updatePlanetResources(planet, now, bonuses, gameSpeed)
resourceLogic.updatePlanetResources(planet, now, bonuses, gameSpeed, miningTechLevel, techBonuses)
// 追踪资源生产统计
if (player.achievementStats) {
@@ -209,6 +218,10 @@ export const processGameUpdate = (
onCompleted
)
// 重要:先更新 player.researchQueue再处理等待队列
// 这样等待队列处理时可以正确 push 新项目到队列中
player.researchQueue = updatedResearchQueue
// 处理等待队列自动执行
const waitingResult = waitingQueueLogic.processAllWaitingQueues(player, now)
// 如果有等待队列项被执行,可以在这里添加通知(可选)
@@ -244,8 +257,9 @@ export const processGameUpdate = (
onUnlock(allUnlockedItems)
}
// 返回当前的研究队列(包含等待队列处理后添加的新项)
return {
updatedResearchQueue
updatedResearchQueue: player.researchQueue
}
}

View File

@@ -17,14 +17,14 @@ import type {
AllyDefenseNotification,
AttitudeChangeNotification
} from '@/types/game'
import { MissionType, ShipType, TechnologyType, RelationStatus, NPCAIType } from '@/types/game'
import { MissionType, ShipType, DefenseType, TechnologyType, RelationStatus, NPCAIType } from '@/types/game'
// 重新导出类型供外部使用
export type { TradeOffer, IntelReport, JointAttackInvite, IntelType, AidNotification, AllyDefenseNotification, AttitudeChangeNotification }
import * as fleetLogic from './fleetLogic'
import * as diplomaticLogic from './diplomaticLogic'
import * as resourceLogic from './resourceLogic'
import { DIPLOMATIC_CONFIG, SHIPS } from '@/config/gameConfig'
import { DIPLOMATIC_CONFIG, SHIPS, DEFENSES } from '@/config/gameConfig'
// ========== 敌对NPC增强行为类型定义 ==========
@@ -908,11 +908,69 @@ export const processNPCSpyArrival = (
}
/**
* 决定NPC攻击舰队组成
* 基于侦查报告和NPC实
* 计算舰队的战斗力
* 使用 attack + shield + armor 作为单位战斗
*/
const decideAttackFleet = (_npc: NPC, npcPlanet: Planet, _spyReport: SpyReport, config: DynamicBehaviorConfig): Partial<Fleet> | null => {
// 简单策略:派出一定比例的可用舰队
const calculateFleetCombatPower = (fleet: Partial<Fleet> | undefined): number => {
if (!fleet) return 0
let power = 0
for (const [shipType, count] of Object.entries(fleet)) {
if (count && count > 0) {
const config = SHIPS[shipType as ShipType]
if (config) {
// 战斗力 = (攻击力 + 护盾 + 装甲) * 数量
power += (config.attack + config.shield + config.armor) * count
}
}
}
return power
}
/**
* 计算防御设施的战斗力
*/
const calculateDefenseCombatPower = (defense: Partial<Record<DefenseType, number>> | undefined): number => {
if (!defense) return 0
let power = 0
for (const [defenseType, count] of Object.entries(defense)) {
if (count && count > 0) {
const config = DEFENSES[defenseType as DefenseType]
if (config) {
// 战斗力 = (攻击力 + 护盾 + 装甲) * 数量
power += (config.attack + config.shield + config.armor) * count
}
}
}
return power
}
/**
* 评估NPC是否能赢得战斗
* 返回NPC战斗力与敌方战斗力的比值
*/
export const evaluateWinProbability = (npcFleet: Partial<Fleet>, spyReport: SpyReport): number => {
const npcPower = calculateFleetCombatPower(npcFleet)
const enemyFleetPower = calculateFleetCombatPower(spyReport.fleet)
const enemyDefensePower = calculateDefenseCombatPower(spyReport.defense)
const totalEnemyPower = enemyFleetPower + enemyDefensePower
// 如果敌方没有防御力,返回无限大(可以攻击)
if (totalEnemyPower === 0) return Infinity
return npcPower / totalEnemyPower
}
/**
* 决定NPC攻击舰队组成
* 基于侦查报告和NPC实力只有当有合理胜算时才攻击
*/
const decideAttackFleet = (_npc: NPC, npcPlanet: Planet, spyReport: SpyReport, config: DynamicBehaviorConfig): Partial<Fleet> | null => {
// 计算敌方总战斗力
const enemyFleetPower = calculateFleetCombatPower(spyReport.fleet)
const enemyDefensePower = calculateDefenseCombatPower(spyReport.defense)
const totalEnemyPower = enemyFleetPower + enemyDefensePower
// 先计算可用的攻击舰队
const attackFleet: Partial<Fleet> = {}
let hasShips = false
@@ -939,7 +997,22 @@ const decideAttackFleet = (_npc: NPC, npcPlanet: Planet, _spyReport: SpyReport,
}
}
return hasShips ? attackFleet : null
if (!hasShips) {
return null
}
// 计算NPC舰队战斗力
const npcPower = calculateFleetCombatPower(attackFleet)
// 如果敌方有防御力,检查是否有足够的胜算
// 要求NPC战斗力至少是敌方的1.2倍才会发动攻击(确保有较大胜算)
const MIN_WIN_RATIO = 1.2
if (totalEnemyPower > 0 && npcPower < totalEnemyPower * MIN_WIN_RATIO) {
// NPC战斗力不足不发动攻击
return null
}
return attackFleet
}
/**
@@ -1520,6 +1593,25 @@ export const createNPCRecycleMission = (npc: NPC, debris: DebrisField, player: P
return null
}
// 检查残骸位置是否有玩家星球
const playerPlanetAtDebris = allPlanets.find(
p =>
p.ownerId === player.id &&
p.position.galaxy === debris.position.galaxy &&
p.position.system === debris.position.system &&
p.position.position === debris.position.position
)
// 如果残骸在玩家星球位置,检查玩家是否有防御
// 如果玩家有防御NPC不应该只派回收船去送死会被击毁产生更多残骸形成恶性循环
if (playerPlanetAtDebris) {
// 计算玩家星球的总防御数量
const totalDefense = Object.values(playerPlanetAtDebris.defense || {}).reduce((sum, count) => sum + (count || 0), 0)
if (totalDefense > 0) {
return null // 玩家有防御,不派纯回收船去送死
}
}
// 检查NPC是否有回收船
const recyclers = closestPlanet.fleet[ShipType.Recycler] || 0
if (recyclers === 0) {
@@ -1566,15 +1658,7 @@ export const createNPCRecycleMission = (npc: NPC, debris: DebrisField, player: P
}
npc.fleetMissions.push(mission)
// 检查残骸位置是否有玩家星球,如果有则发送警告
const playerPlanetAtDebris = allPlanets.find(
p =>
p.ownerId === player.id &&
p.position.galaxy === debris.position.galaxy &&
p.position.system === debris.position.system &&
p.position.position === debris.position.position
)
// 如果残骸在玩家星球位置发送警告非敌对NPC才会执行到这里
if (playerPlanetAtDebris) {
// 创建即将到来的舰队警告(非敌对)
const alert = createIncomingFleetAlert(mission, npc, playerPlanetAtDebris)

View File

@@ -266,12 +266,12 @@ export const formatDepletionTime = (hours: number): string => {
/**
* 计算地质研究站带来的恢复速率加成
* @param geoStationLevel 地质研究站等级
* @returns 恢复速率倍数1 + 等级 * 0.5
* @returns 恢复速率倍数1 + 等级 * 0.1
*/
export const calculateGeoStationBonus = (geoStationLevel: number): number => {
// 每级地质研究站增加50%恢复速度
// 0级 = 1倍, 1级 = 1.5倍, 2级 = 2倍, ..., 10级 = 6倍
return 1 + geoStationLevel * 0.5
return 1 + geoStationLevel * 0.1
}
/**
@@ -280,8 +280,16 @@ export const calculateGeoStationBonus = (geoStationLevel: number): number => {
* @param deposits 矿脉储量对象
* @param hoursElapsed 经过的小时数
* @param geoStationLevel 地质研究站等级(可选,影响恢复速度)
* @param deepDrillingLevel 深层钻探设施等级(可选,影响恢复上限)
* @param miningTechLevel 采矿技术等级(可选,影响恢复上限)
*/
export const regenerateDeposits = (deposits: OreDeposits, hoursElapsed: number, geoStationLevel: number = 0): void => {
export const regenerateDeposits = (
deposits: OreDeposits,
hoursElapsed: number,
geoStationLevel: number = 0,
deepDrillingLevel: number = 0,
miningTechLevel: number = 0
): void => {
const { REGENERATION } = ORE_DEPOSIT_CONFIG
if (!REGENERATION.ENABLED || hoursElapsed <= 0) return
@@ -289,32 +297,36 @@ export const regenerateDeposits = (deposits: OreDeposits, hoursElapsed: number,
// 计算地质研究站加成
const geoBonus = calculateGeoStationBonus(geoStationLevel)
// 动态计算初始储量上限
const initialDeposits = calculateInitialDeposits(deposits.position)
// 计算带有建筑和科技加成的储量上限
const enhancedDeposits = calculateEnhancedDeposits(deposits.position, deepDrillingLevel, miningTechLevel)
// 计算恢复量(基于初始储量的百分比,乘以地质研究站加成)
// 计算恢复量(基于增强后储量的百分比,乘以地质研究站加成)
const regenRate = REGENERATION.RATE_PER_HOUR * hoursElapsed * geoBonus
const maxPercentage = REGENERATION.MAX_PERCENTAGE
// 恢复每种资源
const metalRegen = initialDeposits.metal * regenRate
const crystalRegen = initialDeposits.crystal * regenRate
const deuteriumRegen = initialDeposits.deuterium * regenRate
const metalRegen = enhancedDeposits.metal * regenRate
const crystalRegen = enhancedDeposits.crystal * regenRate
const deuteriumRegen = enhancedDeposits.deuterium * regenRate
// 添加恢复量,但不超过初始储量的最大百分比
deposits.metal = Math.min(initialDeposits.metal * maxPercentage, deposits.metal + metalRegen)
deposits.crystal = Math.min(initialDeposits.crystal * maxPercentage, deposits.crystal + crystalRegen)
deposits.deuterium = Math.min(initialDeposits.deuterium * maxPercentage, deposits.deuterium + deuteriumRegen)
// 添加恢复量,但不超过增强后储量的最大百分比
deposits.metal = Math.min(enhancedDeposits.metal * maxPercentage, deposits.metal + metalRegen)
deposits.crystal = Math.min(enhancedDeposits.crystal * maxPercentage, deposits.crystal + crystalRegen)
deposits.deuterium = Math.min(enhancedDeposits.deuterium * maxPercentage, deposits.deuterium + deuteriumRegen)
}
/**
* 获取矿脉恢复状态信息
* @param deposits 矿脉储量
* @param geoStationLevel 地质研究站等级(可选,影响恢复时间计算)
* @param deepDrillingLevel 深层钻探设施等级(可选,影响恢复上限)
* @param miningTechLevel 采矿技术等级(可选,影响恢复上限)
*/
export const getRegenerationInfo = (
deposits: OreDeposits | undefined,
geoStationLevel: number = 0
geoStationLevel: number = 0,
deepDrillingLevel: number = 0,
miningTechLevel: number = 0
): {
metalRecovering: boolean
crystalRecovering: boolean
@@ -338,26 +350,26 @@ export const getRegenerationInfo = (
}
}
// 动态计算初始储量上限
const initialDeposits = calculateInitialDeposits(deposits.position)
// 计算带有建筑和科技加成的储量上限
const enhancedDeposits = calculateEnhancedDeposits(deposits.position, deepDrillingLevel, miningTechLevel)
const { REGENERATION } = ORE_DEPOSIT_CONFIG
const maxPercentage = REGENERATION.MAX_PERCENTAGE
// 实际恢复速率 = 基础速率 * 地质研究站加成
const ratePerHour = REGENERATION.RATE_PER_HOUR * geoBonus
const metalMax = initialDeposits.metal * maxPercentage
const crystalMax = initialDeposits.crystal * maxPercentage
const deuteriumMax = initialDeposits.deuterium * maxPercentage
const metalMax = enhancedDeposits.metal * maxPercentage
const crystalMax = enhancedDeposits.crystal * maxPercentage
const deuteriumMax = enhancedDeposits.deuterium * maxPercentage
const metalRecovering = deposits.metal < metalMax
const crystalRecovering = deposits.crystal < crystalMax
const deuteriumRecovering = deposits.deuterium < deuteriumMax
// 计算恢复到满需要的小时数(考虑地质研究站加成)
const hoursToFullMetal = metalRecovering ? (metalMax - deposits.metal) / (initialDeposits.metal * ratePerHour) : 0
const hoursToFullCrystal = crystalRecovering ? (crystalMax - deposits.crystal) / (initialDeposits.crystal * ratePerHour) : 0
const hoursToFullDeuterium = deuteriumRecovering ? (deuteriumMax - deposits.deuterium) / (initialDeposits.deuterium * ratePerHour) : 0
const hoursToFullMetal = metalRecovering ? (metalMax - deposits.metal) / (enhancedDeposits.metal * ratePerHour) : 0
const hoursToFullCrystal = crystalRecovering ? (crystalMax - deposits.crystal) / (enhancedDeposits.crystal * ratePerHour) : 0
const hoursToFullDeuterium = deuteriumRecovering ? (deuteriumMax - deposits.deuterium) / (enhancedDeposits.deuterium * ratePerHour) : 0
return {
metalRecovering,

View File

@@ -320,3 +320,63 @@ export const calculateDeuteriumTemperatureBonus = (maxTemperature: number): numb
// 返回乘数,例如:-40°C时返回1.52+100°C时返回0.96
return 1.36 - 0.004 * maxTemperature
}
/**
* 检查是否可以放弃殖民地
* @param planets 玩家所有星球
* @param planetId 要放弃的星球ID
* @returns 是否可以放弃及原因
*/
export const canAbandonColony = (
planets: Planet[],
planetId: string
): { canAbandon: boolean; reason?: string } => {
const planet = planets.find(p => p.id === planetId)
if (!planet) {
return { canAbandon: false, reason: 'errors.planetNotFound' }
}
// 主星(第一个非月球星球)不能放弃
const mainPlanet = planets.find(p => !p.isMoon)
if (mainPlanet && mainPlanet.id === planetId) {
return { canAbandon: false, reason: 'errors.cannotAbandonHomePlanet' }
}
// 检查是否有正在进行的建造队列
if (planet.buildQueue.length > 0) {
return { canAbandon: false, reason: 'errors.hasBuildQueue' }
}
// 检查是否有舰队在该星球
const hasFleet = Object.values(planet.fleet).some(count => count > 0)
if (hasFleet) {
return { canAbandon: false, reason: 'errors.hasFleetOnPlanet' }
}
// 检查是否有防御在该星球
const hasDefense = Object.values(planet.defense).some(count => count > 0)
if (hasDefense) {
return { canAbandon: false, reason: 'errors.hasDefenseOnPlanet' }
}
return { canAbandon: true }
}
/**
* 放弃殖民地
* @param planets 玩家所有星球
* @param planetId 要放弃的星球ID
* @returns 放弃后的星球列表
*/
export const abandonColony = (planets: Planet[], planetId: string): Planet[] => {
const planet = planets.find(p => p.id === planetId)
if (!planet) return planets
// 如果放弃的是行星,同时删除其月球
if (!planet.isMoon) {
return planets.filter(p => p.id !== planetId && p.parentPlanetId !== planetId)
}
// 如果放弃的是月球,只删除月球
return planets.filter(p => p.id !== planetId)
}

View File

@@ -90,16 +90,27 @@ export const checkRequirements = (
}
/**
* 计算星球的资源产量(包含军官加成)
* 计算星球的资源产量(包含军官加成和科技加成
* @param planet 星球对象
* @param officers 玩家的军官对象
* @param resourceSpeed 游戏速度
* @param techBonuses 科技加成(可选,矿物研究/晶体研究/燃料研究)
* @returns 每小时各类资源的产量
*/
export const getResourceProduction = (planet: Planet, officers: Record<OfficerType, Officer>, resourceSpeed: number = 1): Resources => {
export const getResourceProduction = (
planet: Planet,
officers: Record<OfficerType, Officer>,
resourceSpeed: number = 1,
techBonuses?: {
mineralResearchLevel?: number
crystalResearchLevel?: number
fuelResearchLevel?: number
}
): Resources => {
// 计算当前激活的军官加成
const bonuses = officerLogic.calculateActiveBonuses(officers, Date.now())
// 根据建筑等级和军官加成计算资源产量
const base = resourceLogic.calculateResourceProduction(planet, bonuses)
const base = resourceLogic.calculateResourceProduction(planet, bonuses, techBonuses)
return scaleResources(base, resourceSpeed)
}

View File

@@ -1,8 +1,57 @@
import type { Resources, BuildQueueItem } from '@/types/game'
import type { Resources, BuildQueueItem, Planet } from '@/types/game'
import { TechnologyType, BuildingType } from '@/types/game'
import { TECHNOLOGIES } from '@/config/gameConfig'
import * as pointsLogic from './pointsLogic'
/**
* 计算有效研究实验室等级(考虑星际研究网络)
* 星际研究网络允许连接多个星球的研究实验室取等级最高的N个实验室等级之和
* @param planets 玩家的所有星球
* @param currentPlanetId 当前星球ID研究所在的星球
* @param intergalacticResearchNetworkLevel 星际研究网络等级
* @returns 有效的研究实验室等级总和
*/
export const calculateEffectiveLabLevel = (
planets: Planet[],
currentPlanetId: string,
intergalacticResearchNetworkLevel: number
): number => {
// 收集所有星球的研究实验室等级
const labLevels: { planetId: string; level: number }[] = []
for (const planet of planets) {
const labLevel = planet.buildings[BuildingType.ResearchLab] || 0
if (labLevel > 0) {
labLevels.push({ planetId: planet.id, level: labLevel })
}
}
// 如果没有星际研究网络,只返回当前星球的实验室等级
if (intergalacticResearchNetworkLevel === 0) {
const currentPlanet = planets.find(p => p.id === currentPlanetId)
return currentPlanet?.buildings[BuildingType.ResearchLab] || 0
}
// 按等级降序排序
labLevels.sort((a, b) => b.level - a.level)
// 可连接的实验室数量 = 1 + 星际研究网络等级
// 等级1可连接2个实验室等级2可连接3个以此类推
const maxLabs = 1 + intergalacticResearchNetworkLevel
// 取前N个实验室的等级之和
let totalLevel = 0
const count = Math.min(maxLabs, labLevels.length)
for (let i = 0; i < count; i++) {
const lab = labLevels[i]
if (lab) {
totalLevel += lab.level
}
}
return totalLevel
}
// 用于生成唯一ID的计数器
let researchQueueIdCounter = 0
@@ -23,31 +72,56 @@ export const calculateTechnologyCost = (techType: TechnologyType, targetLevel: n
/**
* 计算科技研究时间
* 使用 2moons 公式(调整版):
* 1. 成本系数 = Σ (资源^0.3 / 0.003)
* 2. 时间(秒) = 成本系数 / ((1 + 研究实验室等级) × 能源加成 × 游戏速度)
* @param techType 科技类型
* @param currentLevel 当前等级
* @param currentLevel 当前等级(要研究的目标等级 = currentLevel + 1
* @param researchSpeedBonus 军官等提供的研究速度加成百分比
* @param researchLabLevel 研究实验室等级
* @param energyTechLevel 能源技术等级
* @param energyTechLevel 能源技术等级(提供额外加速)
* @param gameSpeed 游戏速度默认1
* @param universityLevel 大学等级每级减少研究时间8%
*/
export const calculateTechnologyTime = (
techType: TechnologyType,
currentLevel: number,
researchSpeedBonus: number = 0,
researchLabLevel: number = 1,
energyTechLevel: number = 0
energyTechLevel: number = 0,
gameSpeed: number = 1,
universityLevel: number = 0
): number => {
const config = TECHNOLOGIES[techType]
const baseTime = config.baseTime * Math.pow(config.costMultiplier, currentLevel)
// 目标等级 = 当前等级 + 1
const targetLevel = currentLevel + 1
// 计算该等级的成本
const cost = calculateTechnologyCost(techType, targetLevel)
// 2moons 公式:成本系数 = Σ (资源^0.3 / 0.003)
let elementCost = 0
if (cost.metal > 0) elementCost += Math.pow(cost.metal, 0.3) / 0.003
if (cost.crystal > 0) elementCost += Math.pow(cost.crystal, 0.3) / 0.003
if (cost.deuterium > 0) elementCost += Math.pow(cost.deuterium, 0.3) / 0.003
// 研究实验室和能源技术的加速:研究时间 / (研究实验室等级 × (1 + 能源技术等级))
// 研究实验室等级至少为1防止除以0
const labLevel = Math.max(1, researchLabLevel)
const techSpeedDivisor = labLevel * (1 + energyTechLevel)
// 能源技术提供额外加速每级5%
const energyBonus = 1 + energyTechLevel * 0.05
// 简化公式:时间(秒) = 成本系数 / (实验室加成 × 能源加成 × 游戏速度)
const timeInSeconds = elementCost / ((1 + labLevel) * energyBonus * gameSpeed)
// 军官等的百分比加成
const speedMultiplier = 1 - researchSpeedBonus / 100
return Math.floor((baseTime / techSpeedDivisor) * speedMultiplier)
// 大学加成每级减少研究时间8%最高10级=57%减少,因为是乘法叠加)
// 使用乘法叠加:(1 - 0.08)^level
const universityMultiplier = Math.pow(0.92, universityLevel)
// 确保最小时间为5秒
return Math.max(5, Math.floor(timeInSeconds * speedMultiplier * universityMultiplier))
}
/**

View File

@@ -54,7 +54,8 @@ export const executeTechnologyResearch = (
techType: TechnologyType,
currentLevel: number,
officers: Record<OfficerType, Officer>,
technologies: Partial<Record<TechnologyType, number>>
technologies: Partial<Record<TechnologyType, number>>,
allPlanets?: Planet[]
): { queueItem: BuildQueueItem } => {
const targetLevel = currentLevel + 1
const cost = researchLogic.calculateTechnologyCost(techType, targetLevel)
@@ -62,11 +63,30 @@ export const executeTechnologyResearch = (
// 计算军官加成
const bonuses = officerLogic.calculateActiveBonuses(officers, Date.now())
// 获取研究实验室等级和能源技术等级
const researchLabLevel = planet.buildings[BuildingType.ResearchLab] || 1
const energyTechLevel = technologies[TechnologyType.EnergyTechnology] || 0
// 获取星际研究网络等级
const intergalacticResearchNetworkLevel = technologies[TechnologyType.IntergalacticResearchNetwork] || 0
const time = researchLogic.calculateTechnologyTime(techType, currentLevel, bonuses.researchSpeedBonus, researchLabLevel, energyTechLevel)
// 计算有效研究实验室等级(考虑星际研究网络)
let researchLabLevel: number
if (allPlanets && intergalacticResearchNetworkLevel > 0) {
researchLabLevel = researchLogic.calculateEffectiveLabLevel(allPlanets, planet.id, intergalacticResearchNetworkLevel)
} else {
researchLabLevel = planet.buildings[BuildingType.ResearchLab] || 1
}
const energyTechLevel = technologies[TechnologyType.EnergyTechnology] || 0
// 获取大学等级(加速研究)
const universityLevel = planet.buildings[BuildingType.University] || 0
const time = researchLogic.calculateTechnologyTime(
techType,
currentLevel,
bonuses.researchSpeedBonus,
researchLabLevel,
energyTechLevel,
1,
universityLevel
)
// 扣除资源
resourceLogic.deductResources(planet.resources, cost)

View File

@@ -5,6 +5,24 @@ import { OFFICERS } from '@/config/gameConfig'
import * as oreDepositLogic from './oreDepositLogic'
import * as planetLogic from './planetLogic'
/**
* 计算资源研究科技加成
* @param mineralResearchLevel 矿物研究等级(每级+2%金属产量)
* @param crystalResearchLevel 晶体研究等级(每级+2%晶体产量)
* @param fuelResearchLevel 燃料研究等级(每级+2%重氢产量)
*/
export const calculateResearchProductionBonus = (
mineralResearchLevel: number = 0,
crystalResearchLevel: number = 0,
fuelResearchLevel: number = 0
): { metalBonus: number; crystalBonus: number; deuteriumBonus: number } => {
return {
metalBonus: mineralResearchLevel * 2, // 每级2%
crystalBonus: crystalResearchLevel * 2,
deuteriumBonus: fuelResearchLevel * 2
}
}
/**
* 计算电量产出
*/
@@ -93,6 +111,9 @@ export const calculateEnergyConsumption = (planet: Planet): number => {
/**
* 计算资源产量(每小时)
* @param planet 星球
* @param bonuses 军官等加成
* @param techBonuses 科技加成(可选,矿物研究/晶体研究/燃料研究)
*/
export const calculateResourceProduction = (
planet: Planet,
@@ -100,6 +121,11 @@ export const calculateResourceProduction = (
resourceProductionBonus: number
darkMatterProductionBonus: number
energyProductionBonus: number
},
techBonuses?: {
mineralResearchLevel?: number
crystalResearchLevel?: number
fuelResearchLevel?: number
}
): Resources => {
const metalMineLevel = planet.buildings[BuildingType.MetalMine] || 0
@@ -110,6 +136,16 @@ export const calculateResourceProduction = (
const resourceBonus = 1 + (bonuses.resourceProductionBonus || 0) / 100
const darkMatterBonus = 1 + (bonuses.darkMatterProductionBonus || 0) / 100
// 计算科技加成
const researchBonus = calculateResearchProductionBonus(
techBonuses?.mineralResearchLevel || 0,
techBonuses?.crystalResearchLevel || 0,
techBonuses?.fuelResearchLevel || 0
)
const metalTechBonus = 1 + researchBonus.metalBonus / 100
const crystalTechBonus = 1 + researchBonus.crystalBonus / 100
const deuteriumTechBonus = 1 + researchBonus.deuteriumBonus / 100
// 计算能量产出(每小时)
const energyProduction = calculateEnergyProduction(planet, { energyProductionBonus: bonuses.energyProductionBonus })
@@ -131,13 +167,28 @@ export const calculateResourceProduction = (
const deuteriumTempBonus = planetLogic.calculateDeuteriumTemperatureBonus(planet.temperature?.max ?? 0)
return {
metal: metalMineLevel * 1500 * Math.pow(1.5, metalMineLevel) * resourceBonus * productionEfficiency * metalDepositEfficiency,
crystal: crystalMineLevel * 1000 * Math.pow(1.5, crystalMineLevel) * resourceBonus * productionEfficiency * crystalDepositEfficiency,
metal:
metalMineLevel *
1500 *
Math.pow(1.5, metalMineLevel) *
resourceBonus *
metalTechBonus *
productionEfficiency *
metalDepositEfficiency,
crystal:
crystalMineLevel *
1000 *
Math.pow(1.5, crystalMineLevel) *
resourceBonus *
crystalTechBonus *
productionEfficiency *
crystalDepositEfficiency,
deuterium:
deuteriumSynthesizerLevel *
500 *
Math.pow(1.5, deuteriumSynthesizerLevel) *
resourceBonus *
deuteriumTechBonus *
productionEfficiency *
deuteriumDepositEfficiency *
deuteriumTempBonus,
@@ -183,7 +234,13 @@ export const updatePlanetResources = (
energyProductionBonus: number
storageCapacityBonus: number
},
gameSpeed: number = 1
gameSpeed: number = 1,
miningTechLevel: number = 0,
techBonuses?: {
mineralResearchLevel?: number
crystalResearchLevel?: number
fuelResearchLevel?: number
}
): void => {
const timeDiff = (now - planet.lastUpdate) / 1000 // 转换为秒
@@ -214,11 +271,15 @@ export const updatePlanetResources = (
planet.resources.energy = Math.max(0, planet.resources.energy)
// 计算资源产量(会检查能量是否充足,以及矿脉储量效率)
const production = calculateResourceProduction(planet, {
resourceProductionBonus: bonuses.resourceProductionBonus,
darkMatterProductionBonus: bonuses.darkMatterProductionBonus,
energyProductionBonus: bonuses.energyProductionBonus
})
const production = calculateResourceProduction(
planet,
{
resourceProductionBonus: bonuses.resourceProductionBonus,
darkMatterProductionBonus: bonuses.darkMatterProductionBonus,
energyProductionBonus: bonuses.energyProductionBonus
},
techBonuses
)
// 计算实际产出量(用于消耗矿脉储量)
const metalProduced = (production.metal * effectiveTimeDiff) / 3600
@@ -232,10 +293,11 @@ export const updatePlanetResources = (
oreDepositLogic.consumeDeposit(planet.oreDeposits, 'deuterium', deuteriumProduced)
// 矿脉缓慢恢复(每次更新时恢复一小部分)
// 地质研究站等级影响恢复速度
// 地质研究站等级影响恢复速度,深层钻探设施和采矿技术影响恢复上限
const hoursElapsed = effectiveTimeDiff / 3600
const geoStationLevel = planet.buildings[BuildingType.GeoResearchStation] || 0
oreDepositLogic.regenerateDeposits(planet.oreDeposits, hoursElapsed, geoStationLevel)
const deepDrillingLevel = planet.buildings[BuildingType.DeepDrillingFacility] || 0
oreDepositLogic.regenerateDeposits(planet.oreDeposits, hoursElapsed, geoStationLevel, deepDrillingLevel, miningTechLevel)
}
// 更新资源(转换为每秒产量,应用游戏速度)
@@ -386,12 +448,22 @@ export interface ConsumptionDetail {
/**
* 计算资源产量详细breakdown
* @param planet 星球
* @param officers 军官
* @param currentTime 当前时间
* @param resourceSpeed 游戏速度
* @param techBonuses 科技加成(可选,矿物研究/晶体研究/燃料研究)
*/
export const calculateProductionBreakdown = (
planet: Planet,
officers: Record<OfficerType, Officer>,
currentTime: number,
resourceSpeed: number = 1
resourceSpeed: number = 1,
techBonuses?: {
mineralResearchLevel?: number
crystalResearchLevel?: number
fuelResearchLevel?: number
}
): ProductionBreakdown => {
const metalMineLevel = planet.buildings[BuildingType.MetalMine] || 0
const crystalMineLevel = planet.buildings[BuildingType.CrystalMine] || 0
@@ -432,6 +504,13 @@ export const calculateProductionBreakdown = (
const totalDarkMatterBonus = activeOfficerBonuses.reduce((sum, officer) => sum + officer.darkMatterBonus, 0)
const totalEnergyBonus = activeOfficerBonuses.reduce((sum, officer) => sum + officer.energyBonus, 0)
// 计算科技加成
const researchBonus = calculateResearchProductionBonus(
techBonuses?.mineralResearchLevel || 0,
techBonuses?.crystalResearchLevel || 0,
techBonuses?.fuelResearchLevel || 0
)
// 金属矿产量
const metalBase = metalMineLevel * 1500 * Math.pow(1.5, metalMineLevel)
const metalBonuses: ProductionBonus[] = []
@@ -449,16 +528,27 @@ export const calculateProductionBreakdown = (
}
})
// 添加矿物研究科技加成
if (researchBonus.metalBonus > 0) {
const techBonusValue = metalBase * (1 + totalResourceBonus / 100) * (researchBonus.metalBonus / 100)
metalBonuses.push({
name: 'research.mineralResearch',
percentage: researchBonus.metalBonus,
value: techBonusValue,
source: 'technology'
})
}
if (!hasPositiveEnergyBalance) {
metalBonuses.push({
name: 'resources.noEnergy',
percentage: -100,
value: -metalBase * (1 + totalResourceBonus / 100),
value: -metalBase * (1 + totalResourceBonus / 100) * (1 + researchBonus.metalBonus / 100),
source: 'other'
})
}
const metalFinal = metalBase * (1 + totalResourceBonus / 100) * productionEfficiency
const metalFinal = metalBase * (1 + totalResourceBonus / 100) * (1 + researchBonus.metalBonus / 100) * productionEfficiency
// 晶体矿产量
const crystalBase = crystalMineLevel * 1000 * Math.pow(1.5, crystalMineLevel)
@@ -476,16 +566,27 @@ export const calculateProductionBreakdown = (
}
})
// 添加晶体研究科技加成
if (researchBonus.crystalBonus > 0) {
const techBonusValue = crystalBase * (1 + totalResourceBonus / 100) * (researchBonus.crystalBonus / 100)
crystalBonuses.push({
name: 'research.crystalResearch',
percentage: researchBonus.crystalBonus,
value: techBonusValue,
source: 'technology'
})
}
if (!hasPositiveEnergyBalance) {
crystalBonuses.push({
name: 'resources.noEnergy',
percentage: -100,
value: -crystalBase * (1 + totalResourceBonus / 100),
value: -crystalBase * (1 + totalResourceBonus / 100) * (1 + researchBonus.crystalBonus / 100),
source: 'other'
})
}
const crystalFinal = crystalBase * (1 + totalResourceBonus / 100) * productionEfficiency
const crystalFinal = crystalBase * (1 + totalResourceBonus / 100) * (1 + researchBonus.crystalBonus / 100) * productionEfficiency
// 重氢合成器产量(受温度影响)
// OGame 原版规则:温度越低,重氢产量越高
@@ -518,16 +619,27 @@ export const calculateProductionBreakdown = (
}
})
// 添加燃料研究科技加成
if (researchBonus.deuteriumBonus > 0) {
const techBonusValue = deuteriumBase * (1 + totalResourceBonus / 100) * (researchBonus.deuteriumBonus / 100)
deuteriumBonuses.push({
name: 'research.fuelResearch',
percentage: researchBonus.deuteriumBonus,
value: techBonusValue,
source: 'technology'
})
}
if (!hasPositiveEnergyBalance) {
deuteriumBonuses.push({
name: 'resources.noEnergy',
percentage: -100,
value: -deuteriumBase * (1 + totalResourceBonus / 100),
value: -deuteriumBase * (1 + totalResourceBonus / 100) * (1 + researchBonus.deuteriumBonus / 100),
source: 'other'
})
}
const deuteriumFinal = deuteriumBase * (1 + totalResourceBonus / 100) * productionEfficiency
const deuteriumFinal = deuteriumBase * (1 + totalResourceBonus / 100) * (1 + researchBonus.deuteriumBonus / 100) * productionEfficiency
// 暗物质收集器产量
const darkMatterBase = darkMatterCollectorLevel * 25 * Math.pow(1.5, darkMatterCollectorLevel)

View File

@@ -322,3 +322,49 @@ export const addFleet = (currentFleet: Fleet, fleet: Partial<Fleet>): void => {
}
}
}
/**
* 计算舰船拆除返还资源
* 返还50%的建造成本
*/
export const calculateShipScrapRefund = (shipType: ShipType, quantity: number): Resources => {
const cost = calculateShipCost(shipType, quantity)
return {
metal: Math.floor(cost.metal * 0.5),
crystal: Math.floor(cost.crystal * 0.5),
deuterium: Math.floor(cost.deuterium * 0.5),
darkMatter: Math.floor(cost.darkMatter * 0.5),
energy: 0
}
}
/**
* 计算舰船拆除时间
* 拆除时间为建造时间的50%
*/
export const calculateShipScrapTime = (
shipType: ShipType,
quantity: number,
buildingSpeedBonus: number = 0,
roboticsFactoryLevel: number = 0,
naniteFactoryLevel: number = 0
): number => {
const buildTime = calculateShipBuildTime(shipType, quantity, buildingSpeedBonus, roboticsFactoryLevel, naniteFactoryLevel)
return Math.floor(buildTime * 0.5)
}
/**
* 创建舰船拆除队列项
*/
export const createShipScrapQueueItem = (shipType: ShipType, quantity: number, scrapTime: number): BuildQueueItem => {
const now = Date.now()
shipQueueIdCounter++
return {
id: `scrap_ship_${now}_${shipQueueIdCounter}`,
type: 'scrap_ship',
itemType: shipType,
quantity,
startTime: now,
endTime: now + scrapTime * 1000
}
}

View File

@@ -201,3 +201,66 @@ export const executeFleetDispatch = (
resourceLogic.deductResources(planet.resources, cargo)
}
}
/**
* 验证舰船拆除的所有条件
*/
export const validateShipScrap = (
planet: Planet,
shipType: ShipType,
quantity: number
): {
valid: boolean
reason?: string
} => {
// 检查数量是否有效
if (quantity <= 0) {
return { valid: false, reason: 'errors.invalidQuantity' }
}
// 检查舰船数量是否足够
const available = planet.fleet[shipType] || 0
if (available < quantity) {
return { valid: false, reason: 'errors.insufficientShips' }
}
return { valid: true }
}
/**
* 执行舰船拆除
*/
export const executeShipScrap = (
planet: Planet,
shipType: ShipType,
quantity: number,
officers: Record<OfficerType, Officer>
): BuildQueueItem => {
// 计算军官加成
const bonuses = officerLogic.calculateActiveBonuses(officers, Date.now())
// 获取机器人工厂和纳米工厂等级
const roboticsFactoryLevel = planet.buildings[BuildingType.RoboticsFactory] || 0
const naniteFactoryLevel = planet.buildings[BuildingType.NaniteFactory] || 0
// 计算拆除时间
const scrapTime = shipLogic.calculateShipScrapTime(
shipType,
quantity,
bonuses.buildingSpeedBonus,
roboticsFactoryLevel,
naniteFactoryLevel
)
// 计算返还资源
const refund = shipLogic.calculateShipScrapRefund(shipType, quantity)
// 扣除舰船(立即扣除,避免拆除过程中派遣)
planet.fleet[shipType] = (planet.fleet[shipType] || 0) - quantity
// 返还资源
resourceLogic.addResources(planet.resources, refund)
// 创建队列项
return shipLogic.createShipScrapQueueItem(shipType, quantity, scrapTime)
}

View File

@@ -26,6 +26,7 @@ export const useGameStore = defineStore('game', {
gameTime: Date.now(),
isPaused: false,
gameSpeed: 1,
battleToFinish: true, // 战斗到底模式false=经典模式(6回合平局)true=战斗到底(最多100回合)
player: {
id: 'player1',
name: '',

View File

@@ -160,12 +160,12 @@
@keyframes fade-in {
from {
opacity: 0;
transform: translateY(10px);
transform: translate3d(0, 10px, 0);
}
to {
opacity: 1;
transform: translateY(0);
transform: translate3d(0, 0, 0);
}
}
@@ -179,7 +179,7 @@ aside nav a {
}
aside nav a:hover button {
transform: translateX(4px);
transform: translate3d(4px, 0, 0);
}
/* 资源数字更新动画 */

View File

@@ -50,7 +50,9 @@ export const BuildingType = {
// 特殊建筑
PlanetDestroyerFactory: 'planetDestroyerFactory', // 行星毁灭者工厂
GeoResearchStation: 'geoResearchStation', // 地质研究站(影响矿脉恢复速度)
DeepDrillingFacility: 'deepDrillingFacility' // 深层钻探设施(提升矿脉上限)
DeepDrillingFacility: 'deepDrillingFacility', // 深层钻探设施(提升矿脉上限)
// 2moons新增建筑
University: 'university' // 大学(加速研究)
} as const
export type BuildingType = (typeof BuildingType)[keyof typeof BuildingType]
@@ -98,7 +100,12 @@ export const TechnologyType = {
DarkMatterTechnology: 'darkMatterTechnology', // 暗物质技术
TerraformingTechnology: 'terraformingTechnology', // 地形改造技术
PlanetDestructionTech: 'planetDestructionTech', // 行星毁灭技术
MiningTechnology: 'miningTechnology' // 采矿技术(提升矿脉上限)
MiningTechnology: 'miningTechnology', // 采矿技术(提升矿脉上限)
// 2moons新增科技
IntergalacticResearchNetwork: 'intergalacticResearchNetwork', // 星际研究网络(连接多个研究实验室)
MineralResearch: 'mineralResearch', // 矿物研究(提升金属产量)
CrystalResearch: 'crystalResearch', // 晶体研究(提升晶体产量)
FuelResearch: 'fuelResearch' // 燃料研究(提升重氢产量)
} as const
export type TechnologyType = (typeof TechnologyType)[keyof typeof TechnologyType]
@@ -496,6 +503,8 @@ export interface MissionReport {
// 毁灭任务:概率和死星损失
destructionChance?: number
deathstarsLost?: boolean
// 毁灭任务:是否发生了战斗
hadBattle?: boolean
// 部署任务:部署的舰队
deployedFleet?: Partial<Fleet>
// 导弹攻击任务:导弹信息
@@ -656,7 +665,7 @@ export interface DebrisField {
// 建造队列项
export interface BuildQueueItem {
id: string
type: 'building' | 'technology' | 'ship' | 'defense' | 'demolish'
type: 'building' | 'technology' | 'ship' | 'defense' | 'demolish' | 'scrap_ship'
itemType: BuildingType | TechnologyType | ShipType | DefenseType
targetLevel?: number // 用于建筑和科技
quantity?: number // 用于舰船和防御
@@ -667,7 +676,7 @@ export interface BuildQueueItem {
// 等待队列项(尚未开始执行,不需要 startTime/endTime
export interface WaitingQueueItem {
id: string
type: 'building' | 'technology' | 'ship' | 'defense' | 'demolish'
type: 'building' | 'technology' | 'ship' | 'defense' | 'demolish' | 'scrap_ship'
itemType: BuildingType | TechnologyType | ShipType | DefenseType
targetLevel?: number // 用于建筑和科技
quantity?: number // 用于舰船和防御

View File

@@ -109,7 +109,10 @@ const COMBAT_EFFECTS = {
* 计算一个单位对另一个单位造成的伤害
* 增强版:包含护盾弹回、重型武器穿透、装甲损坏累积
*/
const calculateDamage = (attacker: CombatUnit, defender: CombatUnit): { destroyed: number; damagedShield: number; armorDamageDealt: number } => {
const calculateDamage = (
attacker: CombatUnit,
defender: CombatUnit
): { destroyed: number; damagedShield: number; armorDamageDealt: number } => {
const attackPower = attacker.attack
// 使用当前护盾值(如果有),否则使用最大护盾
const defenderCurrentShield = defender.currentShield ?? defender.shield
@@ -157,14 +160,8 @@ const calculateDamage = (attacker: CombatUnit, defender: CombatUnit): { destroye
// 穿透护盾后对装甲造成损坏累积
if (remainingDamage > 0) {
armorDamageDealt = Math.min(
COMBAT_EFFECTS.ARMOR_DAMAGE_RATE,
COMBAT_EFFECTS.MAX_ARMOR_DAMAGE - (defender.armorDamage ?? 0)
)
defender.armorDamage = Math.min(
COMBAT_EFFECTS.MAX_ARMOR_DAMAGE,
(defender.armorDamage ?? 0) + armorDamageDealt
)
armorDamageDealt = Math.min(COMBAT_EFFECTS.ARMOR_DAMAGE_RATE, COMBAT_EFFECTS.MAX_ARMOR_DAMAGE - (defender.armorDamage ?? 0))
defender.armorDamage = Math.min(COMBAT_EFFECTS.MAX_ARMOR_DAMAGE, (defender.armorDamage ?? 0) + armorDamageDealt)
}
// 再消耗装甲
@@ -453,8 +450,24 @@ export const simulateBattle = (
} else if (defenderUnits.length === 0) {
winner = 'attacker'
} else {
// OGame原版规则6回合后双方都有剩余单位时判定为平局
winner = 'draw'
// 达到最大回合后双方都有剩余单位
// 如果是战斗到底模式(maxRounds > 6),根据剩余战力判定胜负
if (maxRounds > 6) {
// 计算剩余战力
const attackerPower = attackerUnits.reduce((sum, u) => sum + u.count * u.armor, 0)
const defenderPower = defenderUnits.reduce((sum, u) => sum + u.count * u.armor, 0)
// 战力差距超过20%判定胜负,否则平局
if (attackerPower > defenderPower * 1.2) {
winner = 'attacker'
} else if (defenderPower > attackerPower * 1.2) {
winner = 'defender'
} else {
winner = 'draw'
}
} else {
// OGame原版规则6回合后双方都有剩余单位时判定为平局
winner = 'draw'
}
}
return {

View File

@@ -57,9 +57,15 @@
<!-- 防守方配置 -->
<TabsContent value="defender" class="mt-4">
<Card>
<CardHeader>
<CardTitle>{{ t('simulatorView.defenderConfig') }}</CardTitle>
<CardDescription>{{ t('simulatorView.defenderConfigDesc') }}</CardDescription>
<CardHeader class="flex flex-row items-center justify-between space-y-0 pb-2">
<div class="space-y-1">
<CardTitle>{{ t('simulatorView.defenderConfig') }}</CardTitle>
<CardDescription>{{ t('simulatorView.defenderConfigDesc') }}</CardDescription>
</div>
<Button variant="outline" size="sm" @click="showSpyReportSelector = true" :disabled="!gameStore.player?.spyReports?.length">
<FileDown class="h-4 w-4 mr-2" />
{{ t('simulatorView.importFromSpyReport') }}
</Button>
</CardHeader>
<CardContent class="space-y-4">
<!-- 舰队配置 -->
@@ -147,28 +153,80 @@
<!-- 战斗结果对话框 -->
<BattleReportDialog v-model:open="showResultDialog" :report="simulationResult" />
<!-- 侦查报告选择对话框 -->
<Dialog v-model:open="showSpyReportSelector">
<DialogContent class="max-w-2xl max-h-[80vh] overflow-y-auto">
<DialogHeader>
<DialogTitle>{{ t('simulatorView.selectSpyReport') }}</DialogTitle>
</DialogHeader>
<div class="space-y-2">
<div v-if="!sortedSpyReports.length" class="text-center py-8 text-muted-foreground">
{{ t('simulatorView.noSpyReports') }}
</div>
<div
v-for="report in sortedSpyReports"
:key="report.id"
@click="importFromSpyReport(report)"
class="p-3 border rounded-lg cursor-pointer hover:bg-accent transition-colors"
>
<div class="flex justify-between items-start">
<div>
<div class="font-medium">{{ report.targetPlanetName }}</div>
<div class="text-sm text-muted-foreground">
[{{ report.targetPosition.galaxy }}:{{ report.targetPosition.system }}:{{ report.targetPosition.position }}]
</div>
</div>
<div class="text-sm text-muted-foreground">
{{ formatTime(report.timestamp) }}
</div>
</div>
<div class="mt-2 flex gap-4 text-xs">
<span class="flex items-center gap-1">
<ResourceIcon type="metal" size="sm" />
{{ formatNumber(report.resources.metal) }}
</span>
<span class="flex items-center gap-1">
<ResourceIcon type="crystal" size="sm" />
{{ formatNumber(report.resources.crystal) }}
</span>
<span class="flex items-center gap-1">
<ResourceIcon type="deuterium" size="sm" />
{{ formatNumber(report.resources.deuterium) }}
</span>
</div>
</div>
</div>
</DialogContent>
</Dialog>
</div>
</template>
<script setup lang="ts">
import { ref, toRaw } from 'vue'
import { ref, toRaw, computed } from 'vue'
import { useI18n } from '@/composables/useI18n'
import { useGameConfig } from '@/composables/useGameConfig'
import { useGameStore } from '@/stores/gameStore'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import { ShipType, DefenseType } from '@/types/game'
import type { Fleet, BattleResult } from '@/types/game'
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog'
import { ShipType, DefenseType, TechnologyType } from '@/types/game'
import type { Fleet, BattleResult, SpyReport } from '@/types/game'
import { workerManager } from '@/workers/workerManager'
import ResourceIcon from '@/components/common/ResourceIcon.vue'
import BattleReportDialog from '@/components/dialogs/BattleReportDialog.vue'
import { Sword, Shield, Zap, RotateCcw } from 'lucide-vue-next'
import { Sword, Shield, Zap, RotateCcw, FileDown } from 'lucide-vue-next'
import * as planetLogic from '@/logic/planetLogic'
const { t } = useI18n()
const { SHIPS, DEFENSES } = useGameConfig()
const gameStore = useGameStore()
// 侦查报告选择对话框状态
const showSpyReportSelector = ref(false)
// 科技类型配置
const techTypes = ['weapon', 'shield', 'armor'] as const
@@ -249,7 +307,8 @@
// 使用 Worker 执行战斗模拟
const result = await workerManager.simulateBattle({
attacker: attackerSide,
defender: defenderSide
defender: defenderSide,
maxRounds: gameStore.battleToFinish ? 100 : 6
})
// 计算掠夺和残骸场
@@ -302,4 +361,65 @@
simulationResult.value = null
showResultDialog.value = false
}
// 按时间排序的侦查报告
const sortedSpyReports = computed(() => {
return [...(gameStore.player?.spyReports || [])].sort((a, b) => b.timestamp - a.timestamp)
})
// 格式化时间
const formatTime = (timestamp: number) => {
return new Date(timestamp).toLocaleString()
}
// 格式化数字
const formatNumber = (num: number) => {
if (num >= 1e9) return (num / 1e9).toFixed(1) + 'B'
if (num >= 1e6) return (num / 1e6).toFixed(1) + 'M'
if (num >= 1e3) return (num / 1e3).toFixed(1) + 'K'
return num.toString()
}
// 从侦查报告导入数据
const importFromSpyReport = (report: SpyReport) => {
// 先重置防守方数据
defenderFleet.value = initializeFleet()
defenderDefense.value = initializeDefense()
// 填入资源
if (report.resources) {
defenderResources.value = {
metal: report.resources.metal || 0,
crystal: report.resources.crystal || 0,
deuterium: report.resources.deuterium || 0,
darkMatter: report.resources.darkMatter || 0,
energy: 0
}
}
// 填入舰队
if (report.fleet) {
Object.entries(report.fleet).forEach(([key, value]) => {
defenderFleet.value[key as keyof Fleet] = value || 0
})
}
// 填入防御
if (report.defense) {
Object.entries(report.defense).forEach(([key, value]) => {
defenderDefense.value[key as DefenseType] = value || 0
})
}
// 填入科技
if (report.technologies) {
defenderTech.value.weapon = report.technologies[TechnologyType.WeaponsTechnology] || 0
defenderTech.value.shield = report.technologies[TechnologyType.ShieldingTechnology] || 0
defenderTech.value.armor = report.technologies[TechnologyType.ArmourTechnology] || 0
}
// 关闭对话框并切换到防守方标签
showSpyReportSelector.value = false
activeTab.value = 'defender'
}
</script>

View File

@@ -10,8 +10,8 @@
<TabsList :class="['grid', 'w-full', showJumpGateTab ? 'grid-cols-3' : 'grid-cols-2']">
<TabsTrigger v-for="tab in visibleTabs" :key="tab.value" :value="tab.value">
{{ t(`fleetView.${tab.labelKey}`) }}
<Badge v-if="tab.value === 'missions' && gameStore.player.fleetMissions.length > 0" variant="destructive" class="ml-1">
{{ gameStore.player.fleetMissions.length }}
<Badge v-if="tab.value === 'missions' && totalMissionsCount > 0" variant="destructive" class="ml-1">
{{ totalMissionsCount }}
</Badge>
<Badge v-if="tab.value === 'jumpGate' && jumpGateReady" variant="default" class="ml-1"></Badge>
</TabsTrigger>
@@ -294,13 +294,14 @@
<!-- 飞行任务 -->
<TabsContent value="missions" class="mt-4 space-y-4">
<Empty v-if="gameStore.player.fleetMissions.length === 0" class="border rounded-lg">
<Empty v-if="totalMissionsCount === 0" class="border rounded-lg">
<EmptyContent>
<RocketIcon class="h-10 w-10 text-muted-foreground" />
<EmptyDescription>{{ t('fleetView.noFlightMissions') }}</EmptyDescription>
</EmptyContent>
</Empty>
<!-- 舰队任务 -->
<Card v-for="mission in gameStore.player.fleetMissions" :key="mission.id">
<CardHeader>
<div class="flex justify-between items-start">
@@ -378,6 +379,44 @@
</div>
</CardContent>
</Card>
<!-- 导弹攻击任务 -->
<Card v-for="missileAttack in flyingMissileAttacks" :key="missileAttack.id">
<CardHeader>
<div class="flex justify-between items-start">
<div>
<CardTitle class="text-base sm:text-lg flex items-center gap-2">
<Crosshair class="h-4 w-4 text-destructive" />
{{ t('galaxyView.missileAttackTitle') }}
</CardTitle>
<CardDescription class="text-xs sm:text-sm">
{{ getPlanetName(missileAttack.originPlanetId) }} [{{ missileAttack.targetPosition.galaxy }}:{{ missileAttack.targetPosition.system }}:{{
missileAttack.targetPosition.position
}}]
</CardDescription>
</div>
<Badge variant="destructive">
{{ t('fleetView.outbound') }}
</Badge>
</div>
</CardHeader>
<CardContent class="space-y-3">
<!-- 导弹数量 -->
<div>
<p class="text-xs sm:text-sm font-medium mb-2">{{ t('galaxyView.missileCount') }}:</p>
<Badge variant="outline">{{ missileAttack.missileCount }}</Badge>
</div>
<!-- 进度条 -->
<div class="space-y-2">
<div class="flex justify-between text-xs sm:text-sm">
<span>{{ t('fleetView.arrivalTime') }}:</span>
<span>{{ formatTime(getMissileRemainingTime(missileAttack)) }}</span>
</div>
<Progress :model-value="getMissileProgress(missileAttack)" />
</div>
</CardContent>
</Card>
</TabsContent>
<!-- 跳跃门 -->
@@ -591,7 +630,8 @@
Clock,
Check,
Globe,
Moon
Moon,
Crosshair
} from 'lucide-vue-next'
import { formatNumber, formatTime } from '@/utils/format'
import * as shipValidation from '@/logic/shipValidation'
@@ -628,6 +668,16 @@
return publicLogic.getMaxFleetMissions(bonuses.additionalFleetSlots, computerTechLevel)
})
// 飞行中的导弹攻击
const flyingMissileAttacks = computed(() => {
return gameStore.player.missileAttacks?.filter(m => m.status === 'flying') || []
})
// 总任务数量(舰队任务 + 导弹攻击)
const totalMissionsCount = computed(() => {
return gameStore.player.fleetMissions.length + flyingMissileAttacks.value.length
})
const activeTab = ref<'send' | 'missions' | 'jumpGate'>('send')
// Tab 配置
@@ -837,6 +887,8 @@
selectedMission.value = MissionType.Attack
} else if (mission === 'colonize') {
selectedMission.value = MissionType.Colonize
} else if (mission === 'recycle') {
selectedMission.value = MissionType.Recycle
} else if (gift === '1') {
// 如果有gift参数设置为运输任务并启用赠送模式
selectedMission.value = MissionType.Transport
@@ -1413,4 +1465,18 @@
return Math.max(0, Math.min(100, (elapsed / total) * 100))
}
}
// 获取导弹任务剩余时间
const getMissileRemainingTime = (missileAttack: any): number => {
const now = currentTime.value
return Math.max(0, (missileAttack.arrivalTime - now) / 1000)
}
// 获取导弹任务进度
const getMissileProgress = (missileAttack: any): number => {
const now = currentTime.value
const total = missileAttack.arrivalTime - missileAttack.launchTime
const elapsed = now - missileAttack.launchTime
return Math.max(0, Math.min(100, (elapsed / total) * 100))
}
</script>

View File

@@ -66,7 +66,7 @@
{{ t('galaxyView.myPlanets') }}
</Button>
</PopoverTrigger>
<PopoverContent class="w-72 p-2" align="start">
<PopoverContent class="w-87 p-2 max-h-80 overflow-y-auto" align="start">
<div class="space-y-1">
<div class="px-2 py-1.5 text-xs font-semibold text-muted-foreground">
{{ t('galaxyView.selectPlanetToView') }}
@@ -114,7 +114,7 @@
{{ highlightedNpc.name }} ({{ highlightedNpc.planets.length }})
</Button>
</PopoverTrigger>
<PopoverContent class="w-72 p-2" align="start">
<PopoverContent class="w-72 p-2 max-h-96 overflow-y-auto" align="start">
<div class="space-y-1">
<div class="px-2 py-1.5 text-xs font-semibold text-muted-foreground">
{{ t('galaxyView.selectPlanetToView') }}

View File

@@ -149,11 +149,11 @@
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(-10px);
transform: translate3d(0, -10px, 0);
}
to {
opacity: 1;
transform: translateY(0);
transform: translate3d(0, 0, 0);
}
}
</style>

View File

@@ -22,8 +22,47 @@
<div v-if="planet.isMoon" class="mt-2">
<Button @click="switchToParentPlanet" variant="outline" size="sm">{{ t('planet.backToPlanet') }}</Button>
</div>
<!-- 放弃殖民地按钮 -->
<div v-if="canShowAbandonButton" class="mt-4">
<Button @click="showAbandonDialog = true" variant="destructive" size="sm">
{{ t('planet.abandonColony') }}
</Button>
</div>
</div>
<!-- 放弃殖民地确认对话框 -->
<AlertDialog :open="showAbandonDialog" @update:open="showAbandonDialog = $event">
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>{{ t('planet.confirmAbandon') }}</AlertDialogTitle>
<AlertDialogDescription class="whitespace-pre-line">
{{ t('planet.abandonWarning', { name: planet.name }) }}
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>{{ t('common.cancel') }}</AlertDialogCancel>
<AlertDialogAction @click="handleAbandonColony" class="bg-destructive text-destructive-foreground hover:bg-destructive/90">
{{ t('planet.confirmAbandonButton') }}
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
<!-- 错误提示对话框 -->
<AlertDialog :open="showErrorDialog" @update:open="showErrorDialog = $event">
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>{{ t('planet.abandonFailed') }}</AlertDialogTitle>
<AlertDialogDescription>
{{ errorMessage }}
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogAction>{{ t('common.confirm') }}</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
<!-- 资源管理 -->
<Card>
<CardHeader>
@@ -195,25 +234,45 @@
import { useGameStore } from '@/stores/gameStore'
import { useI18n } from '@/composables/useI18n'
import { useGameConfig } from '@/composables/useGameConfig'
import { computed } from 'vue'
import { computed, ref } from 'vue'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'
import { Button } from '@/components/ui/button'
import { Badge } from '@/components/ui/badge'
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle
} from '@/components/ui/alert-dialog'
import ResourceIcon from '@/components/common/ResourceIcon.vue'
import { formatNumber, getResourceColor } from '@/utils/format'
import { scaleNumber } from '@/utils/speed'
import type { Planet } from '@/types/game'
import { TechnologyType } from '@/types/game'
import * as publicLogic from '@/logic/publicLogic'
import * as resourceLogic from '@/logic/resourceLogic'
import * as planetLogic from '@/logic/planetLogic'
const gameStore = useGameStore()
const { t } = useI18n()
const { SHIPS } = useGameConfig()
const planet = computed(() => gameStore.currentPlanet)
// 获取科技加成
const techBonuses = computed(() => ({
mineralResearchLevel: gameStore.player.technologies[TechnologyType.MineralResearch] || 0,
crystalResearchLevel: gameStore.player.technologies[TechnologyType.CrystalResearch] || 0,
fuelResearchLevel: gameStore.player.technologies[TechnologyType.FuelResearch] || 0
}))
const production = computed(() =>
planet.value ? publicLogic.getResourceProduction(planet.value, gameStore.player.officers, gameStore.gameSpeed) : null
planet.value ? publicLogic.getResourceProduction(planet.value, gameStore.player.officers, gameStore.gameSpeed, techBonuses.value) : null
)
const capacity = computed(() => (planet.value ? publicLogic.getResourceCapacity(planet.value, gameStore.player.officers) : null))
@@ -226,7 +285,7 @@
// 资源产量详细breakdown
const productionBreakdown = computed(() => {
if (!planet.value) return null
return resourceLogic.calculateProductionBreakdown(planet.value, gameStore.player.officers, Date.now(), gameStore.gameSpeed)
return resourceLogic.calculateProductionBreakdown(planet.value, gameStore.player.officers, Date.now(), gameStore.gameSpeed, techBonuses.value)
})
// 资源消耗详细breakdown
@@ -286,4 +345,45 @@
gameStore.currentPlanetId = planet.value.parentPlanetId
}
}
// 放弃殖民地相关
const showAbandonDialog = ref(false)
const showErrorDialog = ref(false)
const errorMessage = ref('')
// 是否显示放弃按钮(非主星才显示)
const canShowAbandonButton = computed(() => {
if (!planet.value) return false
// 找到主星(第一个非月球星球)
const mainPlanet = gameStore.player.planets.find(p => !p.isMoon)
// 当前星球不是主星时才显示放弃按钮
return mainPlanet && mainPlanet.id !== planet.value.id
})
// 处理放弃殖民地
const handleAbandonColony = () => {
if (!planet.value) return
const check = planetLogic.canAbandonColony(gameStore.player.planets, planet.value.id)
if (!check.canAbandon) {
showAbandonDialog.value = false
errorMessage.value = check.reason ? t(check.reason) : t('planet.abandonFailed')
showErrorDialog.value = true
return
}
// 记录当前星球ID用于后续切换
const abandonedPlanetId = planet.value.id
// 执行放弃
gameStore.player.planets = planetLogic.abandonColony(gameStore.player.planets, abandonedPlanetId)
// 切换到主星
const mainPlanet = gameStore.player.planets.find(p => !p.isMoon)
if (mainPlanet) {
gameStore.currentPlanetId = mainPlanet.id
}
showAbandonDialog.value = false
}
</script>

View File

@@ -175,7 +175,8 @@
techType,
currentLevel,
gameStore.player.officers,
gameStore.player.technologies
gameStore.player.technologies,
gameStore.player.planets
)
gameStore.player.researchQueue.push(queueItem)
return true
@@ -333,11 +334,33 @@
const getResearchTime = (techType: TechnologyType): number => {
if (!planet.value) return 0
const currentLevel = getTechLevel(techType)
const researchLabLevel = planet.value.buildings['researchLab'] || 0
const intergalacticResearchNetworkLevel = player.value.technologies[TechnologyType.IntergalacticResearchNetwork] || 0
// 计算有效研究实验室等级(考虑星际研究网络)
let researchLabLevel: number
if (intergalacticResearchNetworkLevel > 0) {
researchLabLevel = researchLogic.calculateEffectiveLabLevel(
gameStore.player.planets,
planet.value.id,
intergalacticResearchNetworkLevel
)
} else {
researchLabLevel = planet.value.buildings['researchLab'] || 0
}
const energyTechLevel = player.value.technologies['energyTechnology'] || 0
const universityLevel = planet.value.buildings['university'] || 0
const bonuses = officerLogic.calculateActiveBonuses(player.value.officers, gameStore.gameTime)
return researchLogic.calculateTechnologyTime(techType, currentLevel, bonuses.researchSpeedBonus, researchLabLevel, energyTechLevel)
return researchLogic.calculateTechnologyTime(
techType,
currentLevel,
bonuses.researchSpeedBonus,
researchLabLevel,
energyTechLevel,
1,
universityLevel
)
}
// 检查是否可以添加到等待队列

View File

@@ -114,6 +114,15 @@
{{ gameStore.isPaused ? t('settings.resume') : t('settings.pause') }}
</Button>
</div>
<!-- 战斗模式 -->
<div class="flex items-center justify-between p-4 border rounded-lg">
<div class="space-y-1">
<h3 class="font-medium">{{ t('settings.battleMode') }}</h3>
<p class="text-sm text-muted-foreground">{{ t('settings.battleModeDesc') }}</p>
</div>
<Switch :checked="gameStore.battleToFinish" @update:checked="(val: boolean) => (gameStore.battleToFinish = val)" />
</div>
</CardContent>
</Card>
@@ -581,12 +590,22 @@
const fileName = `${pkg.name}-${new Date().toISOString().slice(0, 10)}-${Date.now()}.json`
const jsonString = JSON.stringify(exportData, null, 2)
// Android 保存到 Documents 目录
// Android 保存到公共 Downloads 目录
if (Capacitor.isNativePlatform()) {
// 检查并请求存储权限
const permStatus = await Filesystem.checkPermissions()
if (permStatus.publicStorage !== 'granted') {
const reqResult = await Filesystem.requestPermissions()
if (reqResult.publicStorage !== 'granted') {
toast.error(t('settings.storagePermissionDenied'))
return
}
}
const result = await Filesystem.writeFile({
path: fileName,
path: `Download/${fileName}`,
data: jsonString,
directory: Directory.Documents,
directory: Directory.ExternalStorage,
encoding: Encoding.UTF8
})
toast.success(t('settings.exportSuccessWithPath', { path: result.uri }))

View File

@@ -101,6 +101,20 @@
/>
</div>
<!-- 拆除数量输入 -->
<div v-if="(planet.fleet[shipType] || 0) > 0" class="space-y-2">
<Label :for="`scrap-quantity-${shipType}`" class="text-xs sm:text-sm text-destructive">{{ t('shipyardView.scrapQuantity') }}</Label>
<Input
:id="`scrap-quantity-${shipType}`"
v-model.number="scrapQuantities[shipType]"
type="number"
min="0"
:max="planet.fleet[shipType] || 0"
placeholder="0"
class="text-sm"
/>
</div>
<div v-if="quantities[shipType] > 0" class="text-xs sm:text-sm space-y-1.5 sm:space-y-2 p-2.5 sm:p-3 bg-muted rounded-lg">
<p class="font-medium text-muted-foreground">{{ t('shipyardView.totalCost') }}:</p>
<div class="space-y-1 sm:space-y-1.5">
@@ -133,6 +147,36 @@
>
{{ t('queue.addToWaiting') }}
</Button>
<!-- 拆除返还资源显示 -->
<div v-if="scrapQuantities[shipType] > 0" class="text-xs sm:text-sm space-y-1.5 sm:space-y-2 p-2.5 sm:p-3 bg-destructive/10 rounded-lg border border-destructive/30">
<p class="font-medium text-destructive">{{ t('shipyardView.scrapRefund') }}:</p>
<div class="space-y-1 sm:space-y-1.5">
<div
v-for="resourceType in costResourceTypes"
:key="resourceType.key"
v-show="resourceType.key !== 'darkMatter' || getScrapRefund(shipType).darkMatter > 0"
class="flex items-center gap-1.5 sm:gap-2"
>
<ResourceIcon :type="resourceType.key" size="sm" />
<span class="text-xs">{{ t(`resources.${resourceType.key}`) }}:</span>
<span class="font-medium text-xs sm:text-sm text-green-500">
+{{ formatNumber(getScrapRefund(shipType)[resourceType.key]) }}
</span>
</div>
</div>
</div>
<!-- 拆除按钮 -->
<Button
v-if="(planet.fleet[shipType] || 0) > 0"
@click="handleScrap(shipType, $event)"
:disabled="!canScrap(shipType)"
variant="destructive"
class="w-full"
>
{{ t('shipyardView.scrap') }}
</Button>
</div>
</CardContent>
</Card>
@@ -243,6 +287,25 @@
[ShipType.Deathstar]: 0
})
// 每种舰船的拆除数量
const scrapQuantities = ref<Record<ShipType, number>>({
[ShipType.LightFighter]: 0,
[ShipType.HeavyFighter]: 0,
[ShipType.Cruiser]: 0,
[ShipType.Battleship]: 0,
[ShipType.Battlecruiser]: 0,
[ShipType.Bomber]: 0,
[ShipType.Destroyer]: 0,
[ShipType.SmallCargo]: 0,
[ShipType.LargeCargo]: 0,
[ShipType.ColonyShip]: 0,
[ShipType.Recycler]: 0,
[ShipType.EspionageProbe]: 0,
[ShipType.SolarSatellite]: 0,
[ShipType.DarkMatterHarvester]: 0,
[ShipType.Deathstar]: 0
})
const buildShip = (shipType: ShipType, quantity: number): { success: boolean; reason?: string } => {
if (!gameStore.currentPlanet) return { success: false }
const validation = shipValidation.validateShipBuild(gameStore.currentPlanet, shipType, quantity, gameStore.player.technologies)
@@ -380,4 +443,54 @@
waitingQueueLogic.addToBuildWaitingQueue(planet.value, item)
quantities.value[shipType] = 0
}
// 计算拆除返还资源
const getScrapRefund = (shipType: ShipType) => {
const quantity = scrapQuantities.value[shipType]
return shipLogic.calculateShipScrapRefund(shipType, quantity)
}
// 检查是否可以拆除
const canScrap = (shipType: ShipType): boolean => {
if (!planet.value) return false
const quantity = scrapQuantities.value[shipType]
if (quantity <= 0) return false
const available = planet.value.fleet[shipType] || 0
return available >= quantity
}
// 拆除舰船
const handleScrap = (shipType: ShipType, _event: MouseEvent) => {
// 防抖:防止快速点击
if (isProcessing.value) return
isProcessing.value = true
setTimeout(() => {
isProcessing.value = false
}, DEBOUNCE_DELAY)
const quantity = scrapQuantities.value[shipType]
if (quantity <= 0) {
alertDialogTitle.value = t('shipyardView.inputError')
alertDialogMessage.value = t('shipyardView.inputErrorMessage')
alertDialogOpen.value = true
return
}
if (!gameStore.currentPlanet) return
const validation = shipValidation.validateShipScrap(gameStore.currentPlanet, shipType, quantity)
if (!validation.valid) {
alertDialogTitle.value = t('shipyardView.scrapFailed')
alertDialogMessage.value = validation.reason ? t(validation.reason) : t('shipyardView.scrapFailedMessage')
alertDialogOpen.value = true
return
}
// 执行拆除
const queueItem = shipValidation.executeShipScrap(gameStore.currentPlanet, shipType, quantity, gameStore.player.officers)
gameStore.currentPlanet.buildQueue.push(queueItem)
scrapQuantities.value[shipType] = 0
}
</script>

View File

@@ -304,8 +304,24 @@ const simulateBattle = (attacker: BattleSideData, defender: BattleSideData, maxR
} else if (defenderUnits.length === 0) {
winner = 'attacker'
} else {
// OGame原版规则6回合后双方都有剩余单位时判定为平局
winner = 'draw'
// 达到最大回合后双方都有剩余单位
// 如果是战斗到底模式(maxRounds > 6),根据剩余战力判定胜负
if (maxRounds > 6) {
// 计算剩余战力
const attackerPower = attackerUnits.reduce((sum, u) => sum + u.count * u.armor, 0)
const defenderPower = defenderUnits.reduce((sum, u) => sum + u.count * u.armor, 0)
// 战力差距超过20%判定胜负,否则平局
if (attackerPower > defenderPower * 1.2) {
winner = 'attacker'
} else if (defenderPower > attackerPower * 1.2) {
winner = 'defender'
} else {
winner = 'draw'
}
} else {
// OGame原版规则6回合后双方都有剩余单位时判定为平局
winner = 'draw'
}
}
return {

View File

@@ -23,14 +23,7 @@ export default defineConfig(async () => {
background_color: '#000000',
display: 'fullscreen',
orientation: 'any',
icons: [
{
src: 'logo.svg',
sizes: 'any',
type: 'image/svg+xml',
purpose: 'any'
}
]
icons: [{ src: 'logo.svg', sizes: 'any', type: 'image/svg+xml', purpose: 'any' }]
},
workbox: {
globPatterns: ['**/*.{js,css,html,ico,png,svg,mp3,wav,json}'],
@@ -39,13 +32,7 @@ export default defineConfig(async () => {
{
urlPattern: ({ request }) => request.destination === 'image' || request.destination === 'audio',
handler: 'CacheFirst', // 优先使用缓存
options: {
cacheName: 'game-assets',
expiration: {
maxEntries: 100,
maxAgeSeconds: 30 * 24 * 60 * 60 // 缓存 30 天
}
}
options: { cacheName: 'game-assets', expiration: { maxEntries: 100, maxAgeSeconds: 30 * 24 * 60 * 60 } }
}
]
}
@@ -113,16 +100,14 @@ export default defineConfig(async () => {
// 使用 lightningcss 处理 CSS自动转换 oklch 等新语法为兼容格式
transformer: 'lightningcss',
lightningcss: {
// 目标浏览器:Android 5+, iOS 10+, Chrome 60+
// 目标浏览器:降低到更保守的版本以支持华为等国产手机 WebView
targets: {
android: 5 << 16, // Android 5.0
chrome: 60 << 16, // Chrome 60
ios_saf: 10 << 16 // iOS Safari 10
android: (4 << 16) | (4 << 8), // Android 4.4
chrome: 49 << 16, // Chrome 49 (Android 4.4 WebView)
ios_saf: (9 << 16) | (3 << 8) // iOS Safari 9.3
},
// 禁用现代 CSS 特性,确保兼容旧版浏览器
drafts: {
customMedia: false
}
drafts: { customMedia: false }
}
},
// 优化依赖预构建

View File

@@ -0,0 +1,28 @@
OGame-Vue-Ts v1.6.0 更新说明
调整基础矿脉恢复速度
调整地质研究站每级恢复速率
调整建造死星所需资源
修复研究等待队列资源扣除但等级不增加的问题
修复攻击NPC后NPC拥有资源不减少的问题
修复导弹攻击后反弹道导弹不减少的问题
修复矿脉上限加成计算错误问题
为战斗模拟器新增加从侦查报告一键填入的功能
调整建筑与研究升级时间
修复文本丢失问题
调整月球基地初始建造成本
修复无法派遣舰队到自己星球位置的问题
修复敌对NPC会无脑派遣舰队回收残骸导致产生更多残骸的恶性循环问题
修复敌对NPC反复派回收船到玩家星球的问题
修复NPC无脑进攻问题
修复贸易邮件大量生成导致淹没其他邮件问题
添加舰船拆除功能
添加放弃殖民地功能
修复从月球切换回母星会触发白屏问题
修复死星毁灭任务跳过战斗的问题
修复对战动画偶现卡顿导致弹窗无响应问题
增加战斗到底模式, 开启后支持最多战斗100回合
添加建筑: 大学
添加科技: 星际研究网络, 矿物研究, 晶体研究, 燃料研究