diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index bbd8172..de82fcc 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -35,6 +35,7 @@ jobs: - uses: actions/setup-go@v5 with: go-version: '1.23' + cache: true - name: Build Frontend & Server run: | @@ -71,6 +72,17 @@ jobs: - name: Setup Android SDK uses: android-actions/setup-android@v3 + # 缓存 Gradle 依赖 (可节省 3-5 分钟) + - name: Cache Gradle + uses: actions/cache@v4 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: gradle-${{ runner.os }}-${{ hashFiles('android/**/*.gradle*', 'android/**/gradle-wrapper.properties') }} + restore-keys: | + gradle-${{ runner.os }}- + - name: Build Frontend run: | pnpm install @@ -78,9 +90,7 @@ jobs: - name: Generate Android Icons run: | - # 安装 ImageMagick - sudo apt-get update && sudo apt-get install -y imagemagick - # 使用 ImageMagick 生成各尺寸图标 + # 使用 ImageMagick 生成各尺寸图标 (Ubuntu runner 已预装) convert logo.png -resize 48x48 android/app/src/main/res/mipmap-mdpi/ic_launcher.png convert logo.png -resize 48x48 android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png convert logo.png -resize 72x72 android/app/src/main/res/mipmap-hdpi/ic_launcher.png @@ -105,7 +115,7 @@ jobs: working-directory: android run: | chmod +x ./gradlew - ./gradlew assembleRelease + ./gradlew assembleRelease --no-daemon - name: Upload APK Artifacts uses: actions/upload-artifact@v4 @@ -138,6 +148,16 @@ jobs: node-version: 20 cache: 'pnpm' + - name: Cache Electron Builder + uses: actions/cache@v4 + with: + path: | + ~/.cache/electron + ~/.cache/electron-builder + key: electron-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }} + restore-keys: | + electron-${{ runner.os }}- + - name: Build Electron run: | pnpm install @@ -180,7 +200,6 @@ jobs: mkdir -p ./final-release # 移动 Server 文件并确保名字唯一 - # 注意:根据你之前的附件,Artifact 名字是 server-windows-amd64 cp ./raw-assets/server-windows-amd64/OGame-Vue-Ts-server-win.exe ./final-release/OGame-Vue-Ts-server-win.exe || cp ./raw-assets/server-windows-amd64/server-windows-amd64.exe ./final-release/OGame-Vue-Ts-server-win.exe || true cp ./raw-assets/server-linux-amd64/OGame-Vue-Ts-server-linux ./final-release/OGame-Vue-Ts-server-linux || true cp ./raw-assets/server-linux-arm64/OGame-Vue-Ts-server-linux-arm64 ./final-release/OGame-Vue-Ts-server-linux-arm64 || true diff --git a/.github/workflows/github-pages.yml b/.github/workflows/github-pages.yml index 1d8b418..2dd4a9e 100644 --- a/.github/workflows/github-pages.yml +++ b/.github/workflows/github-pages.yml @@ -19,15 +19,17 @@ jobs: - name: 检出代码 uses: actions/checkout@v6 + - name: 安装 pnpm + uses: pnpm/action-setup@v4 + - name: 安装 Nodejs uses: actions/setup-node@v6 with: - node-version: 20 # 建议使用 LTS 版本 + node-version: 20 + cache: 'pnpm' - - name: 安装 pnpm 并构建前端 - uses: pnpm/action-setup@v4 - with: - run_install: true + - name: 安装依赖 + run: pnpm install - name: 构建前端项目 run: pnpm run build diff --git a/README-DE.md b/README-DE.md index 8a91dd0..972d97a 100644 --- a/README-DE.md +++ b/README-DE.md @@ -6,13 +6,10 @@ Ein modernes Weltraum-Strategiespiel basierend auf dem klassischen OGame, entwickelt mit Vue 3 und TypeScript. [![GitHub Release](https://img.shields.io/github/v/release/setube/ogame-vue-ts?style=flat&logo=github&label=Release)](https://github.com/setube/ogame-vue-ts/releases/latest) - [![License: CC BY-NC 4.0](https://img.shields.io/badge/License-CC%20BY--NC%204.0-lightgrey.svg)](https://creativecommons.org/licenses/by-nc/4.0/) - [![Vue 3](https://img.shields.io/badge/Vue-3.5-brightgreen.svg)](https://vuejs.org/) - [![TypeScript](https://img.shields.io/badge/TypeScript-5.9-blue.svg)](https://www.typescriptlang.org/) - [![Vite](https://img.shields.io/badge/Vite-7.2-646CFF.svg)](https://vitejs.dev/) - [![Go](https://img.shields.io/badge/Go-1.23-79D4FD.svg)](https://golang.org/) + [![License: CC BY-NC 4.0](https://img.shields.io/badge/License-CC%20BY--NC%204.0-lightgrey.svg)](https://creativecommons.org/licenses/by-nc/4.0) + [![Tap Tap](https://img.shields.io/badge/TapTap-OGame%20Vue%20Ts-18d6e0)](https://www.taptap.cn/app/801190) - [简体中文](README.md) | [English](README-EN.md) | [繁體中文](README-zh-TW.md) | Deutsch | [Русский](README-RU.md) | [한국어](README-KO.md) + [简体中文](README.md)| [繁體中文](README-zh-TW.md) | [English](README-EN.md) | Deutsch | [Русский](README-RU.md) | [Español](README-ES.md) | [한국어](README-KO.md) | [日本語](README-JA.md) @@ -22,7 +19,6 @@ OGame Vue TS ist ein Einzelspieler-Weltraum-Strategiespiel im Browser, inspirier ## Hauptfunktionen -- **Mehrsprachige Unterstützung** - Verfügbar in 6 Sprachen: Englisch, Chinesisch (vereinfacht & traditionell), Deutsch, Russisch und Koreanisch - **Gebäudeverwaltung** - Baue und verbessere verschiedene Gebäude auf Planeten und Monden - **Technologieforschung** - Schalte fortschrittliche Technologien frei, um dein Imperium zu stärken - **Flottenverwaltung** - Baue Schiffe, sende Missionen und nimm an taktischen Weltraumkämpfen teil @@ -37,14 +33,14 @@ OGame Vue TS ist ein Einzelspieler-Weltraum-Strategiespiel im Browser, inspirier ## Technologie-Stack -- **Frontend-Framework:** [Vue 3](https://vuejs.org/) + Composition API (` diff --git a/src/components/notifications/QueueNotifications.vue b/src/components/notifications/QueueNotifications.vue index 4e4a1d4..0e6df95 100644 --- a/src/components/notifications/QueueNotifications.vue +++ b/src/components/notifications/QueueNotifications.vue @@ -308,10 +308,10 @@ import * as resourceLogic from '@/logic/resourceLogic' const getStatusDotClass = (item: BuildQueueItem | WaitingQueueItem): string => { // 等待队列项根据资源是否足够显示不同颜色 if (isWaitingItem(item)) { - return isWaitingItemResourcesReady(item) ? 'bg-green-500' : 'bg-yellow-500' + return isWaitingItemResourcesReady(item) ? 'bg-green-500 dark:bg-green-400' : 'bg-yellow-500 dark:bg-yellow-400' } if (item.type === 'demolish') return 'bg-destructive' - if (item.type === 'technology') return 'bg-blue-500' - return 'bg-green-500' + if (item.type === 'technology') return 'bg-blue-500 dark:bg-blue-400' + return 'bg-green-500 dark:bg-green-400' } diff --git a/src/components/npc/NpcRelationRow.vue b/src/components/npc/NpcRelationRow.vue index 1b4dfec..d8aa893 100644 --- a/src/components/npc/NpcRelationRow.vue +++ b/src/components/npc/NpcRelationRow.vue @@ -7,9 +7,9 @@
@@ -37,8 +37,8 @@
-
-
+
+
{{ reputation > 0 ? '+' : '' }}{{ reputation }} @@ -72,9 +72,9 @@
diff --git a/src/components/settings/WebDAVConfigDialog.vue b/src/components/settings/WebDAVConfigDialog.vue new file mode 100644 index 0000000..e334515 --- /dev/null +++ b/src/components/settings/WebDAVConfigDialog.vue @@ -0,0 +1,180 @@ + + + diff --git a/src/components/settings/WebDAVFileListDialog.vue b/src/components/settings/WebDAVFileListDialog.vue new file mode 100644 index 0000000..c747177 --- /dev/null +++ b/src/components/settings/WebDAVFileListDialog.vue @@ -0,0 +1,180 @@ + + + diff --git a/src/components/ui/bg-stars/StarsBackground.vue b/src/components/ui/bg-stars/StarsBackground.vue index fd5c6b0..4647ea0 100644 --- a/src/components/ui/bg-stars/StarsBackground.vue +++ b/src/components/ui/bg-stars/StarsBackground.vue @@ -94,7 +94,7 @@ // For slot content defineSlots() - function generateStars(count: number, starColor: string) { + const generateStars = (count: number, starColor: string) => { const shadows: string[] = [] for (let i = 0; i < count; i++) { const x = Math.floor(Math.random() * 4000) - 2000 @@ -110,7 +110,7 @@ const springX = useSpring(offsetX, props.transition) const springY = useSpring(offsetY, props.transition) - function handleMouseMove(e: MouseEvent) { + const handleMouseMove = (e: MouseEvent) => { const centerX = window.innerWidth / 2 const centerY = window.innerHeight / 2 const newOffsetX = -(e.clientX - centerX) * props.factor diff --git a/src/components/ui/collapsible/Collapsible.vue b/src/components/ui/collapsible/Collapsible.vue new file mode 100644 index 0000000..05a898f --- /dev/null +++ b/src/components/ui/collapsible/Collapsible.vue @@ -0,0 +1,15 @@ + + + diff --git a/src/components/ui/collapsible/CollapsibleContent.vue b/src/components/ui/collapsible/CollapsibleContent.vue new file mode 100644 index 0000000..d4b7140 --- /dev/null +++ b/src/components/ui/collapsible/CollapsibleContent.vue @@ -0,0 +1,12 @@ + + + diff --git a/src/components/ui/collapsible/CollapsibleTrigger.vue b/src/components/ui/collapsible/CollapsibleTrigger.vue new file mode 100644 index 0000000..95321a3 --- /dev/null +++ b/src/components/ui/collapsible/CollapsibleTrigger.vue @@ -0,0 +1,12 @@ + + + diff --git a/src/components/ui/collapsible/index.ts b/src/components/ui/collapsible/index.ts new file mode 100644 index 0000000..abab956 --- /dev/null +++ b/src/components/ui/collapsible/index.ts @@ -0,0 +1,3 @@ +export { default as Collapsible } from './Collapsible.vue' +export { default as CollapsibleContent } from './CollapsibleContent.vue' +export { default as CollapsibleTrigger } from './CollapsibleTrigger.vue' diff --git a/src/components/ui/particles-bg/ParticlesBg.vue b/src/components/ui/particles-bg/ParticlesBg.vue index 3d9181a..b3d4268 100644 --- a/src/components/ui/particles-bg/ParticlesBg.vue +++ b/src/components/ui/particles-bg/ParticlesBg.vue @@ -68,45 +68,7 @@ return `${r} ${g} ${b}` }) - onMounted(() => { - if (canvasRef.value) { - context.value = canvasRef.value.getContext('2d') - } - - initCanvas() - animate() - window.addEventListener('resize', initCanvas) - }) - - onBeforeUnmount(() => { - window.removeEventListener('resize', initCanvas) - }) - - watch([mouseX, mouseY], () => { - onMouseMove() - }) - - function initCanvas() { - resizeCanvas() - drawParticles() - } - - function onMouseMove() { - if (canvasRef.value) { - const rect = canvasRef.value.getBoundingClientRect() - const { w, h } = canvasSize - const x = mouseX.value - rect.left - w / 2 - const y = mouseY.value - rect.top - h / 2 - - const inside = x < w / 2 && x > -w / 2 && y < h / 2 && y > -h / 2 - if (inside) { - mouse.x = x - mouse.y = y - } - } - } - - function resizeCanvas() { + const resizeCanvas = () => { if (canvasContainerRef.value && canvasRef.value && context.value) { circles.value.length = 0 canvasSize.w = canvasContainerRef.value.offsetWidth @@ -119,7 +81,7 @@ } } - function circleParams(): Circle { + const circleParams = (): Circle => { const x = Math.floor(Math.random() * canvasSize.w) const y = Math.floor(Math.random() * canvasSize.h) const translateX = 0 @@ -144,7 +106,7 @@ } } - function drawCircle(circle: Circle, update = false) { + const drawCircle = (circle: Circle, update = false) => { if (context.value) { const { x, y, translateX, translateY, size, alpha } = circle context.value.translate(translateX, translateY) @@ -160,13 +122,13 @@ } } - function clearContext() { + const clearContext = () => { if (context.value) { context.value.clearRect(0, 0, canvasSize.w, canvasSize.h) } } - function drawParticles() { + const drawParticles = () => { clearContext() const particleCount = props.quantity for (let i = 0; i < particleCount; i++) { @@ -175,12 +137,32 @@ } } - function remapValue(value: number, start1: number, end1: number, start2: number, end2: number): number { + const initCanvas = () => { + resizeCanvas() + drawParticles() + } + + const onMouseMove = () => { + if (canvasRef.value) { + const rect = canvasRef.value.getBoundingClientRect() + const { w, h } = canvasSize + const x = mouseX.value - rect.left - w / 2 + const y = mouseY.value - rect.top - h / 2 + + const inside = x < w / 2 && x > -w / 2 && y < h / 2 && y > -h / 2 + if (inside) { + mouse.x = x + mouse.y = y + } + } + } + + const remapValue = (value: number, start1: number, end1: number, start2: number, end2: number): number => { const remapped = ((value - start1) * (end2 - start2)) / (end1 - start1) + start2 return remapped > 0 ? remapped : 0 } - function animate() { + const animate = () => { clearContext() circles.value.forEach((circle, i) => { // Handle the alpha value @@ -235,4 +217,22 @@ }) window.requestAnimationFrame(animate) } + + onMounted(() => { + if (canvasRef.value) { + context.value = canvasRef.value.getContext('2d') + } + + initCanvas() + animate() + window.addEventListener('resize', initCanvas) + }) + + onBeforeUnmount(() => { + window.removeEventListener('resize', initCanvas) + }) + + watch([mouseX, mouseY], () => { + onMouseMove() + }) diff --git a/src/composables/useGameConfig.ts b/src/composables/useGameConfig.ts index dca3328..e6fcb6c 100644 --- a/src/composables/useGameConfig.ts +++ b/src/composables/useGameConfig.ts @@ -41,7 +41,9 @@ export const useGameConfig = () => { [BuildingType.LunarBase]: 'lunarBase', [BuildingType.SensorPhalanx]: 'sensorPhalanx', [BuildingType.JumpGate]: 'jumpGate', - [BuildingType.PlanetDestroyerFactory]: 'planetDestroyerFactory' + [BuildingType.PlanetDestroyerFactory]: 'planetDestroyerFactory', + [BuildingType.GeoResearchStation]: 'geoResearchStation', + [BuildingType.DeepDrillingFacility]: 'deepDrillingFacility' } // 舰船类型枚举值到翻译键的映射 @@ -97,7 +99,8 @@ export const useGameConfig = () => { [TechnologyType.HyperspaceDrive]: 'hyperspaceDrive', [TechnologyType.DarkMatterTechnology]: 'darkMatterTechnology', [TechnologyType.TerraformingTechnology]: 'terraformingTechnology', - [TechnologyType.PlanetDestructionTech]: 'planetDestructionTech' + [TechnologyType.PlanetDestructionTech]: 'planetDestructionTech', + [TechnologyType.MiningTechnology]: 'miningTechnology' } // 军官类型枚举值到翻译键的映射 diff --git a/src/composables/useHints.ts b/src/composables/useHints.ts index f159038..58793e1 100644 --- a/src/composables/useHints.ts +++ b/src/composables/useHints.ts @@ -106,6 +106,14 @@ const hints: Hint[] = [ icon: 'swords', delay: 500 }, + { + id: 'campaign_intro', + route: '/campaign', + titleKey: 'hints.campaign.title', + messageKey: 'hints.campaign.message', + icon: 'map', + delay: 500 + }, { id: 'achievements_intro', route: '/achievements', @@ -114,6 +122,14 @@ const hints: Hint[] = [ icon: 'trophy', delay: 500 }, + { + id: 'ranking_intro', + route: '/ranking', + titleKey: 'hints.ranking.title', + messageKey: 'hints.ranking.message', + icon: 'medal', + delay: 500 + }, { id: 'settings_intro', route: '/settings', @@ -138,7 +154,7 @@ const isHintVisible = ref(false) let hintTimeout: ReturnType | null = null -export function useHints() { +export const useHints = () => { const router = useRouter() const gameStore = useGameStore() diff --git a/src/composables/useI18n.ts b/src/composables/useI18n.ts index 3441763..a1f45a6 100644 --- a/src/composables/useI18n.ts +++ b/src/composables/useI18n.ts @@ -1,22 +1,51 @@ -import { computed } from 'vue' +import { ref, computed, watch } from 'vue' import { useGameStore } from '@/stores/gameStore' -import { locales, type Locale } from '@/locales' +import { loadLocale, getLocale, isLocaleLoaded, type Locale, type TranslationSchema } from '@/locales' + +// 全局加载状态 +const isLoading = ref(false) +const currentMessages = ref(null) export const useI18n = () => { const gameStore = useGameStore() const currentLocale = computed(() => gameStore.locale) - const messages = computed(() => locales[currentLocale.value]) + // 初始化或切换语言时加载 + const ensureLocaleLoaded = async (locale: Locale) => { + if (isLocaleLoaded(locale)) { + currentMessages.value = getLocale(locale) + return + } + + isLoading.value = true + try { + currentMessages.value = await loadLocale(locale) + } finally { + isLoading.value = false + } + } + + // 监听语言变化 + watch( + currentLocale, + async newLocale => { + await ensureLocaleLoaded(newLocale) + }, + { immediate: true } + ) + + // 获取当前消息(同步,使用缓存或默认语言) + const messages = computed(() => currentMessages.value || getLocale(currentLocale.value)) // 获取翻译文本的辅助函数 const t = (key: string, params?: Record): string => { const keys = key.split('.') - let value: any = messages.value + let value: unknown = messages.value for (const k of keys) { if (value && typeof value === 'object' && k in value) { - value = value[k] + value = (value as Record)[k] } else { return key // 如果找不到翻译,返回原始 key } @@ -34,7 +63,10 @@ export const useI18n = () => { return result } - const setLocale = (locale: Locale) => { + const setLocale = async (locale: Locale) => { + // 预加载语言文件 + await ensureLocaleLoaded(locale) + // 然后切换 gameStore.locale = locale } @@ -42,6 +74,7 @@ export const useI18n = () => { t, locale: currentLocale, setLocale, - messages + messages, + isLoading: computed(() => isLoading.value) } } diff --git a/src/config/achievementConfig.ts b/src/config/achievementConfig.ts index 7f64b23..5c8a625 100644 --- a/src/config/achievementConfig.ts +++ b/src/config/achievementConfig.ts @@ -542,12 +542,12 @@ export const TIER_ORDER: AchievementTier[] = [ ] // 获取等级索引 -export function getTierIndex(tier: AchievementTier): number { +export const getTierIndex = (tier: AchievementTier): number => { return TIER_ORDER.indexOf(tier) } // 获取下一个等级 -export function getNextTier(tier: AchievementTier | null): AchievementTier | null { +export const getNextTier = (tier: AchievementTier | null): AchievementTier | null => { if (tier === null) return AchievementTier.Bronze const index = getTierIndex(tier) if (index >= TIER_ORDER.length - 1) return null diff --git a/src/config/gameConfig.ts b/src/config/gameConfig.ts index 2e7d9be..6226cbd 100644 --- a/src/config/gameConfig.ts +++ b/src/config/gameConfig.ts @@ -352,6 +352,70 @@ export const BUILDINGS: Record = { [TechnologyType.HyperspaceTechnology]: 10 } } + }, + // 资源管理建筑 + [BuildingType.GeoResearchStation]: { + id: BuildingType.GeoResearchStation, + name: '地质研究站', + description: '研究地质结构,提高矿脉自然恢复速度。每级增加50%恢复速率', + baseCost: { metal: 50000, crystal: 30000, deuterium: 20000, darkMatter: 0, energy: 0 }, + baseTime: 60, + costMultiplier: 1.8, + spaceUsage: 4, + planetOnly: true, // 只能在行星上建造 + maxLevel: 10, // 最多10级(最高6倍恢复速度) + requirements: { + [BuildingType.ResearchLab]: 5, + [BuildingType.MetalMine]: 10, + [BuildingType.CrystalMine]: 10, + [BuildingType.DeuteriumSynthesizer]: 8 + }, + levelRequirements: { + 5: { + [BuildingType.ResearchLab]: 8, + [BuildingType.RoboticsFactory]: 5, + [TechnologyType.EnergyTechnology]: 5 + }, + 8: { + [BuildingType.ResearchLab]: 10, + [BuildingType.RoboticsFactory]: 8, + [TechnologyType.EnergyTechnology]: 8, + [BuildingType.NaniteFactory]: 1 + } + } + }, + // 深层钻探设施 - 提升矿脉上限 + [BuildingType.DeepDrillingFacility]: { + id: BuildingType.DeepDrillingFacility, + name: '深层钻探设施', + description: '深入地壳钻探,解锁更深层的矿脉储量。每级增加20%矿脉上限', + baseCost: { metal: 100000, crystal: 80000, deuterium: 50000, darkMatter: 0, energy: 0 }, + baseTime: 120, + costMultiplier: 2.0, + spaceUsage: 6, + planetOnly: true, // 只能在行星上建造 + maxLevel: 10, // 最多10级(最高3倍矿脉上限) + requirements: { + [BuildingType.ResearchLab]: 8, + [BuildingType.MetalMine]: 15, + [BuildingType.CrystalMine]: 15, + [BuildingType.DeuteriumSynthesizer]: 12, + [BuildingType.GeoResearchStation]: 3 + }, + levelRequirements: { + 5: { + [BuildingType.ResearchLab]: 10, + [BuildingType.RoboticsFactory]: 8, + [BuildingType.NaniteFactory]: 2, + [TechnologyType.EnergyTechnology]: 10 + }, + 8: { + [BuildingType.ResearchLab]: 12, + [BuildingType.NaniteFactory]: 5, + [TechnologyType.EnergyTechnology]: 12, + [TechnologyType.PlasmaTechnology]: 5 + } + } } } @@ -582,7 +646,7 @@ export const TECHNOLOGIES: Record = { baseCost: { metal: 100000, crystal: 200000, deuterium: 100000, darkMatter: 0, energy: 0 }, baseTime: 180, costMultiplier: 2, - requirements: { [BuildingType.ResearchLab]: 8, [TechnologyType.HyperspaceTechnology]: 5 }, + requirements: { [BuildingType.ResearchLab]: 10, [TechnologyType.HyperspaceTechnology]: 5 }, levelRequirements: { 3: { [BuildingType.ResearchLab]: 10, @@ -634,6 +698,34 @@ export const TECHNOLOGIES: Record = { [BuildingType.NaniteFactory]: 5 } } + }, + [TechnologyType.MiningTechnology]: { + id: TechnologyType.MiningTechnology, + name: '采矿技术', + description: '改进采矿方法和设备,提升所有星球矿脉储量上限。每级增加15%矿脉上限', + baseCost: { metal: 50000, crystal: 30000, deuterium: 20000, darkMatter: 0, energy: 0 }, + baseTime: 90, + costMultiplier: 1.8, + maxLevel: 15, // 最多15级(最高约2.25倍上限加成) + requirements: { + [BuildingType.ResearchLab]: 5, + [TechnologyType.EnergyTechnology]: 4, + [BuildingType.MetalMine]: 12, + [BuildingType.CrystalMine]: 12 + }, + levelRequirements: { + 5: { + [BuildingType.ResearchLab]: 8, + [TechnologyType.EnergyTechnology]: 8, + [BuildingType.RoboticsFactory]: 5 + }, + 10: { + [BuildingType.ResearchLab]: 12, + [TechnologyType.EnergyTechnology]: 12, + [BuildingType.NaniteFactory]: 3, + [TechnologyType.PlasmaTechnology]: 3 + } + } } } @@ -652,7 +744,11 @@ export const SHIPS: Record = { speed: 12500, fuelConsumption: 20, storageUsage: 5, - requirements: { [BuildingType.Shipyard]: 1, [TechnologyType.CombustionDrive]: 1 } + requirements: { [BuildingType.Shipyard]: 1, [TechnologyType.CombustionDrive]: 1 }, + rapidFire: { + [ShipType.EspionageProbe]: 5, + [ShipType.SolarSatellite]: 5 + } }, [ShipType.HeavyFighter]: { id: ShipType.HeavyFighter, @@ -667,12 +763,17 @@ export const SHIPS: Record = { speed: 10000, fuelConsumption: 75, storageUsage: 10, - requirements: { [BuildingType.Shipyard]: 3, [TechnologyType.ImpulseDrive]: 2 } + requirements: { [BuildingType.Shipyard]: 3, [TechnologyType.ImpulseDrive]: 2 }, + rapidFire: { + [ShipType.SmallCargo]: 3, + [ShipType.EspionageProbe]: 5, + [ShipType.SolarSatellite]: 5 + } }, [ShipType.Cruiser]: { id: ShipType.Cruiser, name: '巡洋舰', - description: '中型战舰', + description: '中型战舰,克制轻型战斗机', cost: { metal: 20000, crystal: 7000, deuterium: 2000, darkMatter: 0, energy: 0 }, buildTime: 60, cargoCapacity: 800, @@ -682,7 +783,13 @@ export const SHIPS: Record = { speed: 15000, fuelConsumption: 300, storageUsage: 15, - requirements: { [BuildingType.Shipyard]: 5, [TechnologyType.ImpulseDrive]: 4, [TechnologyType.IonTechnology]: 2 } + requirements: { [BuildingType.Shipyard]: 5, [TechnologyType.ImpulseDrive]: 4, [TechnologyType.IonTechnology]: 2 }, + rapidFire: { + [ShipType.LightFighter]: 6, + [ShipType.EspionageProbe]: 5, + [ShipType.SolarSatellite]: 5, + [DefenseType.RocketLauncher]: 10 + } }, [ShipType.Battleship]: { id: ShipType.Battleship, @@ -697,12 +804,16 @@ export const SHIPS: Record = { speed: 10000, fuelConsumption: 500, storageUsage: 25, - requirements: { [BuildingType.Shipyard]: 7, [TechnologyType.HyperspaceDrive]: 4 } + requirements: { [BuildingType.Shipyard]: 7, [TechnologyType.HyperspaceDrive]: 4 }, + rapidFire: { + [ShipType.EspionageProbe]: 5, + [ShipType.SolarSatellite]: 5 + } }, [ShipType.Battlecruiser]: { id: ShipType.Battlecruiser, name: '战列巡洋舰', - description: '快速强大的战斗舰船,擅长攻击战列舰', + description: '快速强大的战斗舰船,克制战列舰和巡洋舰', cost: { metal: 30000, crystal: 40000, deuterium: 15000, darkMatter: 0, energy: 0 }, buildTime: 70, cargoCapacity: 750, @@ -717,12 +828,21 @@ export const SHIPS: Record = { [TechnologyType.HyperspaceDrive]: 5, [TechnologyType.HyperspaceTechnology]: 5, [TechnologyType.LaserTechnology]: 12 + }, + rapidFire: { + [ShipType.SmallCargo]: 3, + [ShipType.LargeCargo]: 3, + [ShipType.HeavyFighter]: 4, + [ShipType.Cruiser]: 4, + [ShipType.Battleship]: 7, + [ShipType.EspionageProbe]: 5, + [ShipType.SolarSatellite]: 5 } }, [ShipType.Bomber]: { id: ShipType.Bomber, name: '轰炸机', - description: '专门对付防御设施的轰炸舰', + description: '专门对付防御设施的轰炸舰,高效摧毁炮台', cost: { metal: 50000, crystal: 25000, deuterium: 15000, darkMatter: 0, energy: 0 }, buildTime: 100, cargoCapacity: 500, @@ -736,25 +856,42 @@ export const SHIPS: Record = { [BuildingType.Shipyard]: 8, [TechnologyType.ImpulseDrive]: 6, [TechnologyType.PlasmaTechnology]: 5 + }, + rapidFire: { + [ShipType.EspionageProbe]: 5, + [ShipType.SolarSatellite]: 5, + [DefenseType.RocketLauncher]: 20, + [DefenseType.LightLaser]: 20, + [DefenseType.HeavyLaser]: 10, + [DefenseType.IonCannon]: 10, + [DefenseType.GaussCannon]: 5, + [DefenseType.PlasmaTurret]: 5 } }, [ShipType.Destroyer]: { id: ShipType.Destroyer, name: '驱逐舰', - description: '专业反大型舰船战舰,高火力低防护', - cost: { metal: 60000, crystal: 50000, deuterium: 15000, darkMatter: 0, energy: 0 }, - buildTime: 120, - cargoCapacity: 2000, - attack: 2500, - shield: 250, - armor: 8000, - speed: 5000, - fuelConsumption: 1000, - storageUsage: 40, + description: '轻型快速战舰,擅长护航和反侦察,克制轻型单位和探测器', + cost: { metal: 15000, crystal: 5000, deuterium: 1500, darkMatter: 0, energy: 0 }, + buildTime: 45, + cargoCapacity: 500, + attack: 250, + shield: 40, + armor: 2000, + speed: 18000, + fuelConsumption: 200, + storageUsage: 12, requirements: { - [BuildingType.Shipyard]: 9, - [TechnologyType.HyperspaceDrive]: 6, - [TechnologyType.HyperspaceTechnology]: 5 + [BuildingType.Shipyard]: 4, + [TechnologyType.ImpulseDrive]: 3, + [TechnologyType.ComputerTechnology]: 3 + }, + rapidFire: { + [ShipType.LightFighter]: 4, + [ShipType.EspionageProbe]: 10, + [ShipType.SolarSatellite]: 10, + [ShipType.SmallCargo]: 2, + [DefenseType.RocketLauncher]: 5 } }, [ShipType.SmallCargo]: { @@ -883,6 +1020,32 @@ export const SHIPS: Record = { [BuildingType.PlanetDestroyerFactory]: 3, [TechnologyType.PlanetDestructionTech]: 7, [TechnologyType.HyperspaceDrive]: 7 + }, + rapidFire: { + // 对所有舰船的快速射击 + [ShipType.SmallCargo]: 250, + [ShipType.LargeCargo]: 250, + [ShipType.LightFighter]: 200, + [ShipType.HeavyFighter]: 100, + [ShipType.Cruiser]: 33, + [ShipType.Battleship]: 30, + [ShipType.Battlecruiser]: 15, + [ShipType.Bomber]: 25, + [ShipType.Destroyer]: 5, + [ShipType.ColonyShip]: 250, + [ShipType.Recycler]: 250, + [ShipType.EspionageProbe]: 1250, + [ShipType.SolarSatellite]: 1250, + [ShipType.DarkMatterHarvester]: 50, + // 对所有防御设施的快速射击 + [DefenseType.RocketLauncher]: 200, + [DefenseType.LightLaser]: 200, + [DefenseType.HeavyLaser]: 100, + [DefenseType.GaussCannon]: 50, + [DefenseType.IonCannon]: 100, + [DefenseType.PlasmaTurret]: 10, + [DefenseType.SmallShieldDome]: 1250, + [DefenseType.LargeShieldDome]: 1250 } } } @@ -1180,12 +1343,31 @@ export const DIPLOMATIC_CONFIG = { NPC_GIFT_CONFIG: { ENABLED: true, MIN_REPUTATION: 60, // NPC对玩家好感度≥60才会赠送 - CHECK_INTERVAL: 24 * 3600, // 每天检查一次(秒) - GIFT_PROBABILITY: 0.05, // 5%概率赠送 - GIFT_AMOUNT: { - METAL: { min: 1000, max: 5000 }, - CRYSTAL: { min: 500, max: 2500 }, - DEUTERIUM: { min: 200, max: 1000 } + CHECK_INTERVAL: 4 * 3600, // 每4小时检查一次(秒) + GIFT_PROBABILITY: 0.3, // 30%概率赠送(提高频率) + // 基础赠送量(会根据玩家经济规模动态调整) + BASE_GIFT_AMOUNT: { + METAL: { min: 100000, max: 500000 }, + CRYSTAL: { min: 50000, max: 250000 }, + DEUTERIUM: { min: 20000, max: 100000 } + }, + // 动态赠送配置:根据玩家总产量比例赠送 + DYNAMIC_GIFT: { + ENABLED: true, + // 赠送玩家每小时产量的倍数(4-8小时产量) + PRODUCTION_MULTIPLIER: { min: 4, max: 8 }, + // 最小赠送量(保底) + MIN_AMOUNT: { + METAL: 100000, + CRYSTAL: 50000, + DEUTERIUM: 20000 + }, + // 最大赠送量(封顶,防止过于夸张) + MAX_AMOUNT: { + METAL: 100000000, // 1亿 + CRYSTAL: 50000000, // 5千万 + DEUTERIUM: 20000000 // 2千万 + } } }, @@ -1197,16 +1379,264 @@ export const DIPLOMATIC_CONFIG = { MAX_REJECTION_PROBABILITY: 0.8, // 最大拒绝概率(80%,即使关系很差) GIFT_EXPIRATION_DAYS: 7, // 礼物通知过期天数 REJECTION_REPUTATION_PENALTY: -5 // 拒绝礼物导致的好感度降低 + }, + + // 盟友协防配置 + ALLY_DEFENSE_CONFIG: { + ENABLED: true, + // 触发协防的最低好感度 + MIN_REPUTATION: 70, + // 检查间隔(秒) + CHECK_INTERVAL: 30, + // 派遣舰队比例(派出多少比例的可用舰队) + FLEET_RATIO: { min: 0.3, max: 0.6 }, + // 协防持续时间(毫秒)- 舰队在玩家星球驻守多久 + STATION_DURATION: 2 * 60 * 60 * 1000, // 2小时 + // 每个NPC最多同时协防几个星球 + MAX_CONCURRENT_DEFENSES: 2, + // 协防触发条件:来袭舰队规模最小值 + MIN_INCOMING_FLEET_SIZE: 50, + // 协防触发概率(根据好感度调整) + BASE_DEFENSE_PROBABILITY: 0.7 + }, + + // 敌对NPC增强行为配置 + HOSTILE_BEHAVIOR_CONFIG: { + // 围攻机制:多个敌对NPC协同攻击 + SIEGE: { + ENABLED: true, + // 触发围攻的条件 + MIN_HOSTILE_NPCS: 2, // 至少2个敌对NPC才能触发围攻 + TRIGGER_REPUTATION: -50, // 好感度低于此值的NPC可能参与围攻 + // 围攻窗口时间(毫秒)- NPC在此时间内协调攻击 + COORDINATION_WINDOW: 60 * 1000, // 1分钟内到达 + // 围攻概率(基础概率,会根据玩家实力调整) + BASE_PROBABILITY: 0.3, + // 围攻冷却时间(毫秒) + COOLDOWN: 30 * 60 * 1000, // 30分钟 + // 围攻舰队比例(每个参与NPC派出的舰队比例) + FLEET_RATIO: { min: 0.5, max: 0.8 } + }, + + // 骚扰战术:小规模持续袭击 + HARASSMENT: { + ENABLED: true, + // 触发条件:好感度低于此值 + TRIGGER_REPUTATION: -30, + // 骚扰间隔(秒)- 比正常攻击更频繁 + INTERVAL: 120, // 2分钟 + // 骚扰舰队规模(小规模) + FLEET_SIZE_RATIO: { min: 0.1, max: 0.2 }, + // 骚扰概率 + PROBABILITY: 0.4, + // 骚扰类型权重 + TYPES: { + spy: 0.4, // 40%概率侦查骚扰 + raid: 0.4, // 40%概率小规模袭击 + intimidate: 0.2 // 20%概率威慑(派舰队但不攻击,消耗玩家注意力) + } + }, + + // 报复升级:被攻击次数越多,反击越猛烈 + REVENGE_ESCALATION: { + ENABLED: true, + // 报复等级配置(基于被攻击次数) + LEVELS: [ + { attackCount: 1, fleetMultiplier: 1.0, attackInterval: 600, name: 'mild' }, // 轻微:正常反击 + { attackCount: 3, fleetMultiplier: 1.5, attackInterval: 300, name: 'moderate' }, // 中等:1.5倍舰队,5分钟间隔 + { attackCount: 5, fleetMultiplier: 2.0, attackInterval: 180, name: 'severe' }, // 严重:2倍舰队,3分钟间隔 + { attackCount: 10, fleetMultiplier: 3.0, attackInterval: 60, name: 'extreme' } // 极端:3倍舰队,1分钟间隔 + ], + // 报复记忆时间(毫秒)- 超过此时间后报复等级重置 + MEMORY_DURATION: 7 * 24 * 60 * 60 * 1000, // 7天 + // 报复期间是否呼叫盟友NPC助战 + CALL_ALLIES: true, + // 呼叫盟友的概率(报复等级越高概率越大) + ALLY_CALL_BASE_PROBABILITY: 0.2 + } + }, + + // 中立NPC行为配置 + NEUTRAL_BEHAVIOR_CONFIG: { + // 有条件贸易:中立NPC可以与玩家进行资源交换 + TRADE: { + ENABLED: true, + // 贸易前提:好感度在此区间内的中立NPC才会贸易 + MIN_REPUTATION: -10, // 好感度不能太低 + MAX_REPUTATION: 19, // 好感度不能太高(太高就是友好了) + // 贸易检查间隔(秒) + CHECK_INTERVAL: 1800, // 30分钟 + // 贸易概率 + PROBABILITY: 0.1, + // 玩家最多同时保留的贸易提议数量 + MAX_PENDING_OFFERS: 30, + // 汇率配置:NPC出售资源的汇率 + EXCHANGE_RATES: { + // 金属:晶体:重氢 基准比例 3:2:1 + metalToCrystal: 1.5, // 1.5金属换1晶体 + metalToDeuterium: 3.0, // 3金属换1重氢 + crystalToDeuterium: 2.0 // 2晶体换1重氢 + }, + // 贸易量配置(基于玩家每小时产量的倍数) + TRADE_AMOUNT: { + min: 2, // 最少2小时产量 + max: 6 // 最多6小时产量 + }, + // 贸易手续费(NPC抽取的百分比) + FEE_PERCENTAGE: 10, + // 成功贸易增加好感度 + REPUTATION_GAIN: 3 + }, + + // 外交摇摆:中立NPC会根据玩家行为倾向友好或敌对 + SWING: { + ENABLED: true, + // 摇摆检查间隔(秒) + CHECK_INTERVAL: 1800, // 30分钟 + // 摇摆触发阈值 + SWING_THRESHOLD: { + toFriendly: 15, // 好感度达到15时有概率变友好 + toHostile: -15 // 好感度达到-15时有概率变敌对 + }, + // 摇摆概率(基础概率,根据好感度调整) + BASE_PROBABILITY: 0.2, + // 摇摆时的通知(给玩家提示NPC态度变化) + NOTIFY_PLAYER: true + }, + + // 观望行为:中立NPC会观察玩家与其他NPC的互动 + OBSERVE: { + ENABLED: true, + // 观察范围(同一星系内的NPC) + SAME_GALAXY_ONLY: true, + // 玩家攻击附近NPC时,中立NPC好感度变化 + ATTACK_NEARBY_PENALTY: -3, + // 玩家帮助附近NPC时,中立NPC好感度变化 + HELP_NEARBY_BONUS: 2 + } + }, + + // 友好NPC增强行为配置 + FRIENDLY_BEHAVIOR_CONFIG: { + // 情报共享:友好NPC会分享其他NPC的情报 + INTEL_SHARING: { + ENABLED: true, + // 触发条件:好感度达到此值 + MIN_REPUTATION: 50, + // 分享间隔(秒) + INTERVAL: 3600, // 1小时 + // 分享概率 + PROBABILITY: 0.4, + // 情报类型 + INTEL_TYPES: { + enemyFleet: 0.4, // 40%概率分享敌对NPC舰队信息 + enemyResources: 0.3, // 30%概率分享敌对NPC资源信息 + enemyMovement: 0.3 // 30%概率分享敌对NPC舰队动向 + } + }, + + // 联合攻击邀请:友好NPC可能邀请玩家一起攻击敌对NPC + JOINT_ATTACK: { + ENABLED: true, + // 触发条件:好感度达到此值 + MIN_REPUTATION: 70, + // 邀请间隔(秒) + INTERVAL: 7200, // 2小时 + // 邀请概率 + PROBABILITY: 0.25, + // 目标选择:共同敌人优先 + PREFER_COMMON_ENEMY: true, + // NPC提供的舰队比例 + NPC_FLEET_RATIO: { min: 0.3, max: 0.5 }, + // 战利品分配:玩家获得的比例 + PLAYER_LOOT_RATIO: 0.7, + // 联合攻击成功增加好感度 + SUCCESS_REPUTATION_GAIN: 10, + // 拒绝邀请减少好感度 + DECLINE_REPUTATION_PENALTY: -5 + }, + + // 资源援助:友好NPC在玩家困难时提供援助 + RESOURCE_AID: { + ENABLED: true, + // 触发条件:好感度达到此值 + MIN_REPUTATION: 60, + // 检查间隔(秒) + CHECK_INTERVAL: 1800, // 30分钟 + // 触发条件:玩家资源低于产量的N小时 + TRIGGER_LOW_RESOURCES_HOURS: 2, + // 援助量(玩家N小时产量) + AID_AMOUNT_HOURS: 4, + // 援助概率 + PROBABILITY: 0.5 + } + }, + + // NPC联盟系统配置 + NPC_ALLIANCE_CONFIG: { + ENABLED: true, + + // NPC之间关系初始化 + INTER_NPC_RELATIONS: { + // 初始化方式:random(随机)、distance(基于距离)、type(基于AI类型) + INIT_MODE: 'mixed', + // 同一星系内NPC更容易成为盟友 + SAME_GALAXY_ALLY_BONUS: 0.3, + // AI类型兼容性(决定NPC之间关系) + TYPE_COMPATIBILITY: { + // 侵略型与防守型互为敌人 + aggressive_defensive: -0.8, + // 商人型与任何类型都友好 + trader_any: 0.5, + // 扩张型互相竞争 + expansionist_expansionist: -0.3, + // 平衡型保持中立 + balanced_any: 0 + } + }, + + // 连坐效应配置 + GUILT_BY_ASSOCIATION: { + ENABLED: true, + // 攻击NPC时,其盟友好感度降低 + ALLY_REPUTATION_PENALTY: -10, + // 帮助NPC时,其盟友好感度增加 + ALLY_REPUTATION_BONUS: 5, + // 盟友关系强度影响(越紧密影响越大) + STRENGTH_MULTIPLIER: true, + // 最大传播深度(防止无限传播) + MAX_PROPAGATION_DEPTH: 2 + }, + + // NPC盟友互助 + MUTUAL_DEFENSE: { + ENABLED: true, + // 盟友被攻击时的响应概率 + RESPONSE_PROBABILITY: 0.5, + // 响应舰队比例 + FLEET_RATIO: { min: 0.2, max: 0.4 }, + // 响应冷却时间(秒) + COOLDOWN: 1800 // 30分钟 + }, + + // NPC之间的资源共享 + RESOURCE_SHARING: { + ENABLED: true, + // 共享间隔(秒) + INTERVAL: 7200, // 2小时 + // 共享比例 + SHARE_RATIO: 0.1 // 共享10%资源 + } } } // 矿脉储量配置 export const ORE_DEPOSIT_CONFIG = { - // 基础储量(单位:资源量) + // 基础储量(单位:资源量)- 大幅提升以支持后期发展 BASE_DEPOSITS: { - metal: 50_000_000, // 5000万金属 - crystal: 30_000_000, // 3000万晶体 - deuterium: 15_000_000 // 1500万重氢 + metal: 500_000_000_0, // 50亿金属 + crystal: 300_000_000_0, // 30亿晶体 + deuterium: 150_000_000_0 // 15亿重氢 }, // 位置系数(位置1-15),影响资源分布 // 内圈(1-4)晶体多,中圈(5-10)均衡,外圈(11-15)重氢多 @@ -1222,77 +1652,87 @@ export const ORE_DEPOSIT_CONFIG = { // 警告阈值(低于10%时显示警告) WARNING_THRESHOLD: 0.1, // 产量衰减开始阈值(低于5%时产量开始衰减) - DECAY_START_THRESHOLD: 0.05 + DECAY_START_THRESHOLD: 0.05, + // 矿脉耗尽后的基础产量保底(20%产量,确保游戏可继续) + MIN_PRODUCTION_EFFICIENCY: 0.2, + // 矿脉恢复配置 + REGENERATION: { + ENABLED: true, + // 每小时恢复初始储量的百分比(0.1% = 每小时恢复0.1%,约42天完全恢复) + RATE_PER_HOUR: 0.001, + // 最大恢复到初始储量的百分比(100%表示可以完全恢复) + MAX_PERCENTAGE: 1.0 + } } -// 探险区域配置 +// 探险区域配置 - 大幅提升奖励,降低空手而归概率 export const EXPEDITION_ZONES: Record = { [ExpeditionZone.NearSpace]: { id: ExpeditionZone.NearSpace, requiredTechLevel: 0, // 无需求 flightTimeMultiplier: 1.0, - resourceMultiplier: 1.0, - darkMatterMultiplier: 1.0, - fleetFindMultiplier: 1.0, + resourceMultiplier: 1.5, // 1.0 -> 1.5 + darkMatterMultiplier: 1.5, // 1.0 -> 1.5 + fleetFindMultiplier: 1.5, // 1.0 -> 1.5 dangerMultiplier: 0.5, // 低危险 probabilities: { - resources: 35, // 高概率发现资源 - darkMatter: 8, - fleet: 10, - pirates: 7, // 低海盗 - aliens: 5, // 低外星人 - nothing: 35 // 高概率什么都没发现 + resources: 40, // 35 -> 40 高概率发现资源 + darkMatter: 12, // 8 -> 12 + fleet: 15, // 10 -> 15 + pirates: 5, // 7 -> 5 低海盗 + aliens: 3, // 5 -> 3 低外星人 + nothing: 25 // 35 -> 25 降低空手而归 } }, [ExpeditionZone.DeepSpace]: { id: ExpeditionZone.DeepSpace, requiredTechLevel: 4, // 需要天体物理学4级 flightTimeMultiplier: 1.5, - resourceMultiplier: 1.5, - darkMatterMultiplier: 1.5, - fleetFindMultiplier: 1.5, + resourceMultiplier: 2.5, // 1.5 -> 2.5 + darkMatterMultiplier: 2.5, // 1.5 -> 2.5 + fleetFindMultiplier: 2.0, // 1.5 -> 2.0 dangerMultiplier: 1.0, // 标准危险 probabilities: { - resources: 30, - darkMatter: 10, - fleet: 15, - pirates: 15, - aliens: 10, - nothing: 20 + resources: 35, // 30 -> 35 + darkMatter: 15, // 10 -> 15 + fleet: 18, // 15 -> 18 + pirates: 12, // 15 -> 12 + aliens: 8, // 10 -> 8 + nothing: 12 // 20 -> 12 } }, [ExpeditionZone.UnchartedSpace]: { id: ExpeditionZone.UnchartedSpace, requiredTechLevel: 8, // 需要天体物理学8级 flightTimeMultiplier: 2.0, - resourceMultiplier: 2.5, - darkMatterMultiplier: 2.0, - fleetFindMultiplier: 2.0, + resourceMultiplier: 4.0, // 2.5 -> 4.0 + darkMatterMultiplier: 3.5, // 2.0 -> 3.5 + fleetFindMultiplier: 3.0, // 2.0 -> 3.0 dangerMultiplier: 1.5, // 高危险 probabilities: { - resources: 25, - darkMatter: 12, - fleet: 18, - pirates: 18, - aliens: 15, - nothing: 12 + resources: 32, // 25 -> 32 + darkMatter: 18, // 12 -> 18 + fleet: 22, // 18 -> 22 + pirates: 12, // 18 -> 12 + aliens: 10, // 15 -> 10 + nothing: 6 // 12 -> 6 } }, [ExpeditionZone.DangerousNebula]: { id: ExpeditionZone.DangerousNebula, requiredTechLevel: 12, // 需要天体物理学12级 flightTimeMultiplier: 3.0, - resourceMultiplier: 4.0, - darkMatterMultiplier: 3.0, - fleetFindMultiplier: 3.0, + resourceMultiplier: 6.0, // 4.0 -> 6.0 + darkMatterMultiplier: 5.0, // 3.0 -> 5.0 + fleetFindMultiplier: 5.0, // 3.0 -> 5.0 dangerMultiplier: 2.5, // 极高危险 probabilities: { - resources: 20, - darkMatter: 15, - fleet: 20, - pirates: 20, - aliens: 20, - nothing: 5 // 很少什么都没发现 + resources: 30, // 20 -> 30 + darkMatter: 20, // 15 -> 20 + fleet: 25, // 20 -> 25 + pirates: 12, // 20 -> 12 + aliens: 10, // 20 -> 10 + nothing: 3 // 5 -> 3 极少空手而归 } } } diff --git a/src/lib/utils.ts b/src/lib/utils.ts index abba253..2aec90c 100644 --- a/src/lib/utils.ts +++ b/src/lib/utils.ts @@ -2,6 +2,6 @@ import type { ClassValue } from 'clsx' import { clsx } from 'clsx' import { twMerge } from 'tailwind-merge' -export function cn(...inputs: ClassValue[]) { +export const cn = (...inputs: ClassValue[]) => { return twMerge(clsx(inputs)) } diff --git a/src/locales/de.ts b/src/locales/de.ts index 80770c6..b58c3d1 100644 --- a/src/locales/de.ts +++ b/src/locales/de.ts @@ -11,29 +11,11 @@ export default { common: { confirm: 'Bestätigen', cancel: 'Abbrechen', - delete: 'Löschen', - edit: 'Bearbeiten', save: 'Speichern', close: 'Schließen', - back: 'Zurück', - next: 'Weiter', - gotIt: '', - previous: 'Vorherige', - submit: 'Absenden', - reset: 'Zurücksetzen', - search: 'Suchen', - filter: 'Filtern', - loading: 'Laden...', - noData: 'Keine Daten', - error: 'Fehler', - success: 'Erfolg', - warning: 'Warnung', - info: 'Info', + gotIt: 'Verstanden', resourceType: 'Ressourcentyp', playerName: 'Kommandant', - timeHour: 'Std', - timeMinute: 'Min', - timeSecond: 'Sek', featureLocked: 'Funktion gesperrt', unlockRequired: 'Gebäude erforderlich', requiredBuilding: 'Erforderliches Gebäude', @@ -41,7 +23,6 @@ export default { goToBuildings: 'Zu Gebäuden', locked: 'Gesperrt', viewRequirements: 'Anforderungen anzeigen', - requirements: 'Anforderungen', requirementsNotMet: 'Anforderungen nicht erfüllt', current: 'Aktuell', level: 'Stufe', @@ -51,7 +32,8 @@ export default { viewDetails: 'Details anzeigen', exitConfirmTitle: 'Spiel beenden', exitConfirmMessage: 'Möchten Sie das Spiel wirklich beenden? Ihr Fortschritt wird automatisch gespeichert.', - points: 'Punkte' + points: 'Punkte', + retry: 'Wiederholen' }, errors: { requirementsNotMet: 'Anforderungen nicht erfüllt', @@ -88,13 +70,13 @@ export default { galaxy: 'Galaxie', diplomacy: 'Diplomatie', achievements: 'Erfolge', + campaign: 'Kampagne', ranking: 'Rangliste', messages: 'Nachrichten', settings: 'Einstellungen', gm: 'GM' }, sidebar: { - language: 'Sprache', lightMode: 'Heller Modus', darkMode: 'Dunkler Modus', collapse: 'Einklappen', @@ -119,9 +101,6 @@ export default { }, energy: { lowWarning: 'Energiedefizit! Ressourcenproduktion gestoppt!', - severeWarning: 'Energiedefizit! Ressourcenproduktion gestoppt!', - criticalWarning: 'Energiedefizit! Ressourcenproduktion gestoppt!', - noProduction: 'Energiedefizit! Ressourcenproduktion gestoppt!', deficitDetail: 'Energiedefizit: {deficit}, bauen Sie mehr Kraftwerke', buildSolarPlant: 'Kraftwerk bauen' }, @@ -132,27 +111,20 @@ export default { lowResources: 'Fast erschöpft: {resources}' }, planet: { - planet: 'Planet', moon: 'Mond', - colony: 'Kolonie', position: 'Position', - coordinates: 'Koordinaten', switchToMoon: 'Zum Mond', backToPlanet: 'Zurück zum Planeten', switchPlanet: 'Planet wechseln', currentPlanet: 'Aktueller Planet', - fields: 'Felder', temperature: 'Temperatur', homePlanet: 'Heimatplanet', planetPrefix: 'Planet', - moonSuffix: 's Mond', colonyPrefix: 'Kolonie', renamePlanet: 'Planet umbenennen', renamePlanetTitle: 'Planet umbenennen', - newPlanetName: 'Neuer Name', planetNamePlaceholder: 'Neuen Planetennamen eingeben', - rename: 'Umbenennen', - renameSuccess: 'Planet wurde in {name} umbenannt' + rename: 'Umbenennen' }, player: { points: 'Gesamtpunkte' @@ -179,13 +151,12 @@ export default { sensorPhalanx: 'Sensorphalanx', jumpGate: 'Sprungtor', planetDestroyerFactory: 'Planetenzerstörer-Fabrik', + geoResearchStation: 'Geologische Forschungsstation', + deepDrillingFacility: 'Tiefbohranlage', buildTime: 'Bauzeit', - build: '', + build: 'Bauen', production: 'Produktion', consumption: 'Verbrauch', - totalCost: 'Gesamtkosten', - totalPoints: 'Gesamtpunkte', - levelRange: 'Stufenbereich', capacity: 'Capacity/Effect', storageCapacity: 'Capacity', energyProduction: 'Energy Production', @@ -194,7 +165,6 @@ export default { buildQueueBonus: 'Bauauftrag', spaceBonus: 'Raumbonus', buildSpeedBonus: 'Baugeschwindigkeitsbonus', - researchSpeedBonus: 'Forschungsgeschwindigkeitsbonus', planetSpace: 'Planet Space', moonSpace: 'Moon Space', missileCapacity: 'Missile Capacity', @@ -228,7 +198,10 @@ export default { lunarBase: 'Erhöht verfügbaren Platz auf dem Mond, +30 Platz pro Stufe', sensorPhalanx: 'Erkennt Flottenaktivitäten in umliegenden Systemen', jumpGate: 'Überträgt Flotten sofort zu anderen Monden', - planetDestroyerFactory: 'Konstruiert ultimative Waffen zur Zerstörung von Planeten' + 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: '' }, ships: { lightFighter: 'Leichter Jäger', @@ -292,9 +265,6 @@ export default { }, research: { researchTime: 'Forschungszeit', - totalCost: 'Gesamtkosten', - totalPoints: 'Gesamtpunkte', - levelRange: 'Stufenbereich', capacity: 'Capacity/Effect', storageCapacity: 'Capacity', energyProduction: 'Energy Production', @@ -302,7 +272,15 @@ export default { buildQueue: 'Build Queue', planetSpace: 'Planet Space', moonSpace: 'Moon Space', - missileCapacity: 'Missile Capacity' + missileCapacity: 'Missile Capacity', + attackBonus: 'Angriffsbonus', + shieldBonus: 'Schildbonus', + armorBonus: 'Panzerungsbonus', + spyLevel: 'Spionagestufe', + researchQueueBonus: 'Forschungswarteschlange', + colonySlots: 'Kolonieplätze', + forAllPlanets: '(Global)', + speedBonus: 'Geschwindigkeitsbonus' }, technologies: { energyTechnology: 'Energietechnik', @@ -322,7 +300,8 @@ export default { hyperspaceDrive: 'Hyperraumantrieb', darkMatterTechnology: 'Dunkle-Materie-Technologie', terraformingTechnology: 'Terraforming-Technologie', - planetDestructionTech: 'Planetenzerstörungstechnologie' + planetDestructionTech: 'Planetenzerstörungstechnologie', + miningTechnology: '' }, technologyDescriptions: { energyTechnology: 'Verbessert Energieeffizienz', @@ -343,7 +322,8 @@ export default { hyperspaceDrive: 'Fortgeschrittene Antriebstechnologie', 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' + planetDestructionTech: 'Schreckliche Technologie zur Zerstörung ganzer Planeten', + miningTechnology: '' }, officers: { commander: 'Kommandant', @@ -378,8 +358,12 @@ export default { cancelResearch: 'Forschung abbrechen', confirmCancel: 'Möchten Sie wirklich abbrechen? 50% der Ressourcen werden zurückerstattet.', level: 'Stufe', - gmModeActivated: '', + gmModeActivated: 'GM-Modus aktiviert! Überprüfen Sie das Navigationsmenü.', upgradeToLevel: 'Auf Stufe aufrüsten', + buildQueueBonus: 'Bauauftrag', + spaceBonus: 'Raumbonus', + researchQueueBonus: 'Forschungswarteschlange', + quantity: 'Anzahl', tabs: { all: 'Alle', buildings: 'Gebäude', @@ -397,14 +381,9 @@ export default { movedToQueue: 'Aufgabe in Warteschlange verschoben' }, overview: { - title: 'Planetenübersicht', resourceOverview: 'Ressourcen', fleetInfo: 'Flotte', currentShips: 'Schiffe auf diesem Planeten', - productionSources: 'Produktionsquellen', - productionSourcesDesc: 'Detaillierte Ressourcenproduktion und Bonusinformationen', - consumptionSources: 'Verbrauchsquellen', - consumptionSourcesDesc: 'Energieverbrauchsdetails für Gebäude', totalProduction: 'Gesamtproduktion', totalConsumption: 'Gesamtverbrauch', noConsumption: 'Kein Energieverbrauch', @@ -413,14 +392,8 @@ export default { tabConsumption: 'Verbrauchsdetails' }, buildingsView: { - title: 'Gebäude', - usedSpace: 'Verwendeter Platz', spaceUsage: 'Platzbedarf', - level: 'Stufe', - gmModeActivated: '', upgradeCost: 'Ausbaukosten', - buildTime: 'Bauzeit', - build: 'Bauen', upgrade: 'Ausbauen', maxLevelReached: 'Maximale Stufe erreicht', requirementsNotMet: 'Anforderungen nicht erfüllt', @@ -430,8 +403,7 @@ export default { demolishRefund: 'Abriss-Rückerstattung', demolishFailed: 'Abriss fehlgeschlagen', demolishFailedMessage: 'Abriss nicht möglich. Bitte überprüfen Sie, ob die Bauqueue voll ist oder die Gebäudestufe 0 ist.', - confirmDemolish: '', - confirmDemolishMessage: '' + confirmDemolish: 'Abriss bestätigen' }, researchView: { title: 'Forschung', @@ -443,26 +415,14 @@ export default { 'Bitte überprüfen Sie, ob Sie genügend Ressourcen haben, die Voraussetzungen erfüllt sind oder keine anderen Forschungsaufträge vorhanden sind.' }, shipyard: { - attack: 'Angriff', missileAttack: 'Raketenangriff', - shield: 'Schild', - armor: 'Panzerung', speed: 'Geschwindigkeit', cargoCapacity: 'Ladekapazität', - fuelConsumption: 'Treibstoffverbrauch', - buildCost: 'Baukosten', - buildTime: 'Bauzeit', - build: '', - perUnit: 'Pro Einheit', - batchCalculator: 'Batch-Rechner', - quantity: 'Menge', - totalCost: 'Gesamtkosten', - totalTime: 'Gesamtzeit' + fuelConsumption: 'Treibstoffverbrauch' }, shipyardView: { title: 'Raumschiffwerft', fleetStorage: 'Flottenspeicher', - owned: 'Besitz', attack: 'Angriff', missileAttack: 'Raketenangriff', shield: 'Schild', @@ -484,7 +444,7 @@ export default { armor: 'Panzerung', buildCost: 'Baukosten', buildTime: 'Bauzeit', - build: '', + build: 'Bauen', perUnit: 'Pro Einheit', batchCalculator: 'Batch-Rechner', quantity: 'Menge', @@ -538,6 +498,7 @@ export default { missionInfo: 'Missionsinfo', fuelConsumption: 'Treibstoffverbrauch', flightTime: 'Flugzeit', + outOfRange: 'Außer Reichweite', attackMission: 'Angriff', transport: 'Transport', colonize: 'Kolonisieren', @@ -549,6 +510,7 @@ export default { requiresAstro: 'Benötigt Astrophysik Stufe {level}', reward: 'Belohnung', danger: 'Gefahr', + destroy: 'Vernichten', zones: { nearSpace: { name: 'Naher Weltraum', @@ -579,11 +541,12 @@ export default { arrivalTime: 'Ankunftszeit', returnTime: 'Rückkehrzeit', recallFleet: 'Flotte zurückrufen', - abortMission: '', - abortMissionTitle: '', - abortMissionWarning: '', - abortMissionSuccess: '', - abortMissionSuccessMessage: '', + abortMission: 'Mission abbrechen', + abortMissionTitle: 'Mission abbrechen bestätigen', + abortMissionWarning: + 'WARNUNG: Das Abbrechen dieser Mission führt zum permanenten Verlust von {ships} Schiffen und {resources} Ressourcen!\n\nDiese Aktion ist unwiderruflich und die Flotte und Ressourcen werden nicht zurückkehren.', + abortMissionSuccess: 'Mission abgebrochen', + abortMissionSuccessMessage: 'Mission wurde abgebrochen, Flotte und Ressourcen sind verloren.', sendFailed: 'Senden fehlgeschlagen', sendFailedMessage: 'Bitte überprüfen Sie Flottenanzahl, Treibstoffverfügbarkeit oder Ladekapazitätsgrenzen.', recallFailed: 'Zurückrufen fehlgeschlagen', @@ -652,7 +615,6 @@ export default { benefitsBonus: 'Vorteile', resourceProduction: 'Ressourcenproduktion', darkMatterProduction: 'Dunkle-Materie-Produktion', - energyProduction: 'Energieproduktion', buildingSpeed: 'Baugeschwindigkeit', researchSpeed: 'Forschungsgeschwindigkeit', fleetSpeed: 'Flottengeschwindigkeit', @@ -681,14 +643,11 @@ export default { selectGalaxy: 'Galaxie auswählen', system: 'System', selectSystem: 'System auswählen', - view: 'Anzeigen', - myPlanet: 'Mein Planet', myPlanets: 'Meine Systeme ansehen', npcPlanets: 'NPC-Planeten', selectPlanetToView: 'Planet auswählen, um sein System anzuzeigen', totalPositions: 'Insgesamt 10 Planetenpositionen', mine: 'Mein', - hostile: 'Feindlich', emptySlot: 'Leer - Kolonisierbar', scout: 'Spähen', attack: 'Angriff', @@ -715,7 +674,9 @@ export default { systems: 'Systeme', distance: 'Entfernung', flightTime: 'Flugzeit', + outOfRange: 'Außer Reichweite', launchMissile: 'Starten', + missileLaunched: 'Rakete abgefeuert', cancel: 'Abbrechen', colonizePlanetMessage: 'Möchten Sie wirklich Position [{coordinates}] kolonisieren?\n\nBitte gehen Sie zur Flottenseite, um ein Kolonieschiff zu senden.', @@ -728,20 +689,34 @@ export default { 'Möchten Sie wirklich Ressourcen als Geschenk an Planet [{coordinates}] senden?\n\nBitte gehen Sie zur Flottenseite, um Transporter auszuwählen und Ressourcen zu laden.', npcPlanetName: '{name}s Planet', intercepted: 'Abgefangen', - defenseLosses: 'Verteidigungsverluste' + defenseLosses: 'Verteidigungsverluste', + phalanxScan: 'Sensorabtastung', + phalanxScanTitle: 'Sensorarray-Scan', + phalanxScanDescription: 'Flottenaktivität von Planet [{coordinates}] scannen', + phalanxNoMoon: 'Benötigt Mond mit Sensorarray zum Scannen', + phalanxCost: 'Scan-Kosten', + phalanxNoFleets: 'Keine Flottenaktivität erkannt', + phalanxFleetDetected: '{count} Flotte(n) erkannt', + phalanxOrigin: 'Ausgangsort', + phalanxDestination: 'Zielort', + phalanxArrival: 'Ankunftszeit', + phalanxReturn: 'Rückkehrzeit', + phalanxStatusOutbound: 'Unterwegs', + phalanxStatusReturning: 'Rückkehr', + phalanxInsufficientDeuterium: 'Unzureichend Deuterium' }, messagesView: { title: 'Nachrichten', battles: 'Kämpfe', spy: 'Spionage', npc: 'NPC', - diplomacy: '', + diplomacy: 'Diplomatie', spied: 'Ausspioniert', battleReports: 'Kampfberichte', spyReports: 'Spionageberichte', noBattleReports: 'Keine Kampfberichte', noSpyReports: 'Keine Spionageberichte', - noDiplomaticReports: '', + noDiplomaticReports: 'Keine diplomatischen Berichte', noSpiedNotifications: 'Keine Ausspionierungs-Benachrichtigungen', battleReport: 'Kampfbericht', spyReport: 'Spionagebericht', @@ -766,6 +741,8 @@ export default { defense: 'Verteidigung', buildings: 'Gebäude', unread: 'Ungelesen', + pending: 'Ausstehend', + invalidData: 'Ungültige Daten', targetPlanet: 'Zielplanet', attackerRemaining: 'Angreifer verblieben', defenderRemaining: 'Verteidiger verblieben', @@ -813,36 +790,37 @@ export default { polite_decline: 'Sie lehnten höflich ab' }, // Spied notification dialog - spiedNotificationDetails: '', - spyDetected: '', - detectionResult: '', - detectionSuccess: '', - spiedNotificationMessage: '', - spiedNotificationTip: '', - viewInGalaxy: '', + spiedNotificationDetails: 'Ausspionierung Details', + spyDetected: 'Spion entdeckt', + detectionResult: 'Erkennungsergebnis', + detectionSuccess: 'Du hast den feindlichen Spion entdeckt!', + spiedNotificationMessage: '{npc} hat versucht, deinen Planeten {planet} auszuspionieren', + spiedNotificationTip: 'Erwäge, deine Verteidigung zu erhöhen oder einen Gegenangriff zu starten, wenn dieser NPC feindlich ist', + viewInGalaxy: 'In Galaxie anzeigen', // Mission report dialog - missionReportDetails: '', - missionSuccess: '', - missionFailed: '', - origin: '', - destination: '', - missionDetails: '', - transportedResources: '', - recycledResources: '', - remainingDebris: '', - newPlanet: '', + missionReportDetails: 'Missionsbericht Details', + missionSuccess: 'Erfolg', + missionFailed: 'Fehlgeschlagen', + origin: 'Herkunft', + destination: 'Ziel', + missionDetails: 'Missionsdetails', + transportedResources: 'Transportierte Ressourcen', + recycledResources: 'Recycelte Ressourcen', + remainingDebris: 'Verbleibende Trümmer', + newPlanet: 'Neuer Planet', // NPC activity dialog - npcActivityDetails: '', + npcActivityDetails: 'NPC-Aktivität Details', activityType: { - recycle: '' + recycle: 'Trümmer recyceln' }, - activityLocation: '', - position: '', - nearPlanet: '', - activityDescription: '', - npcActivityMessage: '', - arrivalTime: '', - npcActivityTip: '', + activityLocation: 'Aktivitätsort', + position: 'Position', + nearPlanet: 'In der Nähe von Planet', + activityDescription: 'Aktivitätsbeschreibung', + npcActivityMessage: '{npc} {activity} bei {position}', + arrivalTime: 'Ankunftszeit', + npcActivityTip: + 'NPCs können Trümmer aus Kämpfen sammeln. Du kannst versuchen, den Ort zuerst zu erreichen, wenn du um Ressourcen konkurrieren möchtest', clearMessages: 'Nachrichten löschen', clearMessageTypes: 'Nachrichtentypen zum Löschen auswählen', clearBattleReports: 'Kampfberichte', @@ -852,7 +830,11 @@ export default { clearNPCActivity: 'NPC-Aktivität', clearGiftNotifications: 'Geschenkbenachrichtigungen', clearGiftRejected: 'Abgelehnte Geschenke', - clearNow: 'Jetzt löschen' + clearTradeOffers: 'Handelsangebote', + clearIntelReports: 'Geheimdienstberichte', + clearJointAttackInvites: 'Gemeinsame Angriffseinladungen', + clearNow: 'Jetzt löschen', + clearSuccess: 'Nachrichten gelöscht' }, missionReports: { transportSuccess: 'Transportmission erfolgreich abgeschlossen', @@ -963,7 +945,6 @@ export default { resume: 'Fortsetzen', gamePaused: 'Spiel pausiert', gameResumed: 'Spiel fortgesetzt', - playerName: 'Spielername', gameSpeed: 'Ressourcenproduktionsgeschwindigkeit', gameSpeedDesc: 'Aktueller Ressourcenproduktionsgeschwindigkeitsmultiplikator', speedChanged: 'Ressourcenproduktionsgeschwindigkeit auf {speed}x geändert', @@ -971,17 +952,18 @@ export default { reset: 'Zurücksetzen', about: 'Über', version: 'Version', - latestVersion: 'Neueste Version', checkUpdate: 'Update prüfen', checking: 'Prüfen...', newVersionAvailable: 'Neue Version {version} verfügbar', upToDate: 'Bereits auf dem neuesten Stand', - checkUpdateCooldown: 'Bitte versuchen Sie es später erneut (5 Minuten Abklingzeit)', checkUpdateFailed: 'Update-Prüfung fehlgeschlagen, bitte überprüfen Sie Ihre Netzwerkverbindung', viewUpdate: 'Update ansehen', updateAvailable: 'Eine neue Version ist verfügbar. Klicken Sie, um die Versionshinweise anzuzeigen.', download: 'Herunterladen', - goToDownload: 'Zum Download', + displaySettings: 'Anzeigeeinstellungen', + displaySettingsDesc: 'Visuelle Effekte des Spiels anpassen', + backgroundAnimation: 'Hintergrundanimation', + backgroundAnimationDesc: 'Sternenhimmel-/Partikel-Hintergrundanimation anzeigen (kann die Leistung beeinträchtigen)', buildDate: 'Build-Datum', community: 'Community', github: 'GitHub-Repository', @@ -1004,13 +986,53 @@ export default { expandTypes: 'Details anzeigen', collapseTypes: 'Details ausblenden', // NPC-Namen-Update - npcNameUpdate: 'NPC-Namen-Update', npcNameUpdateTitle: 'Alte NPC-Namen erkannt', npcNameUpdateMessage: '{count} NPCs mit altem Namensformat gefunden. Möchten Sie auf neue lokalisierte Namen aktualisieren?', npcNameUpdateConfirm: 'Namen aktualisieren', npcNameUpdateCancel: 'Beibehalten', npcNameUpdateSuccess: '{count} NPC-Namen erfolgreich aktualisiert', - npcNameUpdateSkipped: 'NPC-Namen-Update übersprungen' + npcNameUpdateSkipped: 'NPC-Namen-Update übersprungen', + // WebDAV + webdav: { + title: 'Cloud-Sync', + desc: 'Spielstände über WebDAV synchronisieren', + config: 'Konfigurieren', + configTitle: 'WebDAV-Konfiguration', + configDesc: 'WebDAV-Server für Cloud-Sync konfigurieren', + notConfigured: 'Bitte zuerst WebDAV-Server konfigurieren', + serverUrl: 'Server-URL', + serverUrlPlaceholder: 'z.B. https://dav.example.com', + serverUrlHint: 'Gib deine WebDAV-Server-Adresse ein', + username: 'Benutzername', + usernamePlaceholder: 'Benutzername eingeben', + password: 'Passwort', + passwordPlaceholder: 'Passwort eingeben', + passwordHint: 'Passwort wird nur lokal gespeichert', + basePath: 'Speicherpfad', + basePathPlaceholder: 'z.B. /ogame-saves/', + testConnection: 'Verbindung testen', + testing: 'Teste...', + testSuccess: 'Verbindung erfolgreich', + testFailed: 'Verbindung fehlgeschlagen', + save: 'Speichern', + clearConfig: 'Löschen', + configSaved: 'Konfiguration gespeichert', + configCleared: 'Konfiguration gelöscht', + upload: 'Hochladen', + uploading: 'Lädt hoch...', + uploadSuccess: 'Upload erfolgreich', + uploadFailed: 'Upload fehlgeschlagen', + download: 'Herunterladen', + downloadSuccess: 'Download erfolgreich', + downloadFailed: 'Download fehlgeschlagen', + selectFile: 'Spielstand wählen', + selectFileDesc: 'Wähle eine Spielstand-Datei zum Wiederherstellen', + noFiles: 'Keine Spielstände gefunden', + loadFailed: 'Dateiliste konnte nicht geladen werden', + confirmDelete: 'Möchtest du "{name}" wirklich löschen?', + deleteSuccess: 'Datei gelöscht', + deleteFailed: 'Löschen fehlgeschlagen' + } }, notifications: { constructionComplete: 'Bau abgeschlossen', @@ -1032,8 +1054,8 @@ export default { officers: 'Offiziere', modifyResources: 'Ressourcen ändern', resourcesDesc: 'Planetenressourcen schnell ändern', - maxAllResources: '', - maxAllResourcesSuccess: '', + maxAllResources: 'Alle maximieren', + maxAllResourcesSuccess: 'Alle Ressourcen wurden maximiert', modifyBuildings: 'Gebäude ändern', buildingsDesc: 'Gebäudelevel schnell festlegen', modifyResearch: 'Forschung ändern', @@ -1075,10 +1097,11 @@ export default { dangerZoneDesc: 'Die folgenden Vorgänge sind irreversibel', resetGame: 'Spiel zurücksetzen', resetGameConfirm: 'Möchten Sie das Spiel wirklich zurücksetzen? Alle Daten werden gelöscht!', - completeAllQueues: '', - completeAllQueuesDesc: '', - completeQueues: '', - completeQueuesSuccess: '' + completeAllQueues: 'Alle Warteschlangen abschließen', + completeAllQueuesDesc: 'Alle Bau-, Forschungs-, Schiffs- und Verteidigungswarteschlangen sowie Flottenmissionen sofort abschließen', + completeQueues: 'Warteschlangen abschließen', + completeQueuesSuccess: + '{buildingCount} Bauwarteschlangen, {researchCount} Forschungswarteschlangen, {missionCount} Flottenmissionen, {missileCount} Raketenangriffe abgeschlossen' }, alerts: { incomingFleets: '{count} feindliche Flotten im Anmarsch', @@ -1109,11 +1132,13 @@ export default { missionType: { spy: 'Spionage', attack: 'Angriff', + recycle: 'Recyceln', unknown: 'Unbekannt' }, warning: { spy: 'Feindliche Spionage im Anmarsch!', attack: 'Feindlicher Angriff im Anmarsch!', + recycle: 'Feind recycelt Trümmer in deiner Nähe!', unknown: 'Feindliche Flotte im Anmarsch!' } }, @@ -1130,13 +1155,11 @@ export default { noFriendlyNpcs: 'Keine freundlichen NPCs', noNeutralNpcs: 'Keine neutralen NPCs', noHostileNpcs: 'Keine feindlichen NPCs', - recentEvents: 'Aktuelle Ereignisse', - recentEventsDescription: 'Protokoll der jüngsten diplomatischen Aktivitäten', ago: 'vor', - notifications: '', - markAllRead: '', - noReports: '', - viewAll: '', + notifications: 'Diplomatische Benachrichtigungen', + markAllRead: 'Alle als gelesen markieren', + noReports: 'Keine diplomatischen Ereignisse', + viewAll: 'Alle anzeigen', status: { friendly: 'Freundlich', neutral: 'Neutral', @@ -1155,7 +1178,6 @@ export default { }, note: 'Notiz', notePlaceholder: 'Notiz eingeben...', - noteEmpty: 'Keine Notiz', lastEvent: 'Letztes Ereignis', reportDetails: 'Diplomatischer Bericht Details', eventDescription: 'Ereignisbeschreibung', @@ -1211,6 +1233,19 @@ export default { npcEliminatedMessage: 'Sie haben alle Planeten von {npcName} zerstört! Diese Fraktion wurde vollständig ausgelöscht.' }, searchPlaceholder: 'NPC-Name suchen...', + notificationType: { + tradeOffer: 'Handelsangebot', + intelReport: 'Geheimdienstbericht', + jointAttack: 'Gemeinsame Angriffseinladung' + }, + notificationBadge: { + trade: 'Handel', + intel: 'Intel', + jointAttack: 'Einladung' + }, + notificationExtra: { + pending: 'Ausstehend' + }, viewMode: { card: 'Karte', list: 'Liste' @@ -1227,6 +1262,21 @@ export default { medium: 'Mittel', hard: 'Schwer' }, + aiType: 'KI-Typ', + aiTypes: { + aggressive: 'Aggressiv', + defensive: 'Defensiv', + trader: 'Händler', + expansionist: 'Expansionist', + balanced: 'Ausgewogen' + }, + aiTypeDescriptions: { + aggressive: 'Spioniert und greift aktiv an, starke Vergeltung', + defensive: 'Greift selten an, starke Vergeltung bei Angriff', + trader: 'Greift fast nie an, bevorzugt Handel und Geschenke', + expansionist: 'Konzentriert auf Entwicklung, weniger aggressiv', + balanced: 'Passt Strategie dynamisch an die Situation an' + }, reputation: 'Ansehen', spyProbes: 'Spionagesonden', fleetPower: 'Flottenstärke', @@ -1253,27 +1303,11 @@ export default { attackCooldown: 'Angriff auf Abklingzeit ({min}m {sec}s)', notSpiedYet: 'Noch nicht spioniert, zuerst Spionage nötig' } - }, - aiType: 'KI-Typ', - aiTypes: { - aggressive: 'Aggressiv', - defensive: 'Defensiv', - trader: 'Händler', - expansionist: 'Expansionist', - balanced: 'Ausgewogen' - }, - aiTypeDescriptions: { - aggressive: 'Spioniert und greift aktiv an, starke Vergeltung', - defensive: 'Greift selten an, starke Vergeltung bei Angriff', - trader: 'Greift fast nie an, bevorzugt Handel und Geschenke', - expansionist: 'Konzentriert auf Entwicklung, weniger aggressiv', - balanced: 'Passt Strategie dynamisch an die Situation an' } }, pagination: { previous: 'Vorherige', next: 'Nächste', - gotIt: '', first: 'Erste', last: 'Letzte', page: 'Seite {page}' @@ -1337,30 +1371,132 @@ export default { seconds: 'Sekunden' }, tutorial: { + progress: 'Fortschritt', + previous: 'Zurück', + next: 'Weiter', + gotIt: 'Verstanden', + completeButton: 'Fertig', + skip: 'Anleitung überspringen', welcome: { title: 'Willkommen bei OGame', - content: 'Willkommen, Kommandant! Beginnen wir mit den Grundlagen und bauen Sie Ihr Weltraum-Imperium auf.' + 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.' + }, + 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.' + }, + 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.' + }, + gotoBuildings: { + title: 'Zu Gebäuden gehen', + content: 'Beginnen wir mit dem Bau einiger Gebäude. Klicken Sie auf den Menüpunkt "Gebäude", um verfügbare Gebäude anzuzeigen.' }, buildSolarPlant: { title: 'Solarkraftwerk bauen', - content: - 'Bauen Sie zuerst ein Solarkraftwerk! Es liefert Energie für Ihren Planeten. 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 in der Bauauftragsliste. Klicken Sie auf das Warteschlangensymbol oben rechts, um alle laufenden Bau- und Forschungsaufträge anzuzeigen. Gebäude brauchen Zeit zum Fertigstellen, 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.' + }, + buildCrystalMine: { + title: 'Kristallmine bauen', + 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.' + }, + 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.' + }, + 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!' + }, + 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.' + }, + 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!' + }, + gotoResearch: { + title: 'Zur Forschung gehen', + content: 'Da Sie nun ein Forschungslabor haben, klicken Sie auf das Menü "Forschung", um verfügbare Technologien anzuzeigen.' + }, + researchEnergy: { + title: 'Energietechnik erforschen', + 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).' + }, + gotoBuildingsForShipyard: { + title: 'Zurück zur Gebäudeseite', + content: 'Kehren Sie zur Gebäudeseite zurück, um Ihre Raumschiffwerft zu bauen.' + }, + buildShipyard: { + title: 'Raumschiffwerft bauen', + 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.' + }, + 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.' + }, + 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!' }, mobile: { welcome: { title: 'Willkommen bei OGame (Mobil)', - content: - 'Willkommen, Kommandant! Dies ist ein optimiertes Tutorial 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.' + }, + 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.' + }, + gotoBuildings: { + title: 'Zur Gebäudeseite gehen', + content: 'Das Menü ist jetzt geöffnet! Tippen Sie nun auf die Option "Gebäude", um mit dem Bau der Infrastruktur zu beginnen.' + }, + 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.' }, waitBuild: { title: 'Bauauftrag', - content: - 'Klicken 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.' + }, + 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!' } } }, @@ -1427,11 +1563,20 @@ export default { message: 'Simulieren Sie Kampfergebnisse vor dem Angriff. Geben Sie Flotten und Technologiestufen ein, um Sieg, Verluste und Beute vorherzusagen.' }, + 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.' + }, achievements: { title: 'Erfolgssystem', message: 'Schließen Sie Spielziele ab, um Erfolge freizuschalten und Dunkle Materie-Belohnungen zu erhalten! Erfolge haben mehrere Stufen - streben Sie höhere Herausforderungen an, um bessere Belohnungen zu erhalten.' }, + ranking: { + title: 'Rangliste', + message: + 'Vergleichen Sie Ihren Fortschritt mit anderen Spielern und NPCs. Sehen Sie Rankings basierend auf Punkten aus Gebäuden, Forschung, Flotte und Verteidigung. Streben Sie nach höheren Platzierungen!' + }, settings: { title: 'Einstellungen', message: 'Verwalten Sie hier Spieldaten, Benachrichtigungen und Import/Export. Sichern Sie regelmäßig Ihren Fortschritt!' @@ -1557,5 +1702,350 @@ export default { you: 'Du', scoreBreakdown: 'Punkteübersicht', noData: 'Keine Ranglistendaten' + }, + // NPC Enhanced Behavior Notifications + npcBehavior: { + tradeOfferReceived: 'Handelsangebot erhalten', + tradeOfferDesc: '{npcName} hat dir ein Handelsangebot gesendet', + attitudeChanged: 'NPC-Haltung geändert', + becameFriendly: '{npcName} ist dir gegenüber freundlich geworden', + becameHostile: '{npcName} ist dir gegenüber feindlich geworden', + intelReceived: 'Informationen erhalten', + intelReceivedDesc: '{npcName} hat Feindinformationen mit dir geteilt', + jointAttackInvite: 'Gemeinsamer Angriffseinladung', + jointAttackInviteDesc: '{npcName} lädt dich ein, gemeinsam einen Feind anzugreifen', + aidReceived: 'Hilfe erhalten', + aidReceivedDesc: '{npcName} hat dir {amount} Ressourcen gesendet', + allyDefense: 'Verbündete Verteidigung', + allyDefenseDesc: '{npcName} sendet eine Flotte, um deinen Planeten zu verteidigen', + trade: { + title: 'Handelsangebote', + from: 'Von', + offers: 'Bietet', + requests: 'Fordert', + expiresIn: 'Läuft ab in', + expired: 'Abgelaufen', + accept: 'Annehmen', + decline: 'Ablehnen', + noOffers: 'Keine Handelsangebote', + acceptSuccess: 'Handel abgeschlossen!', + acceptFailed: 'Nicht genug Ressourcen für den Handel', + declined: 'Handel abgelehnt', + ratio: 'Tauschverhältnis' + }, + intel: { + title: 'Geheimdienstberichte', + from: 'Quelle', + target: 'Ziel-NPC', + type: 'Informationstyp', + types: { + enemyFleet: 'Flotteninformation', + enemyResources: 'Ressourceninformation', + enemyMovement: 'Bewegungsinformation' + }, + fleetInfo: 'Flotteninformation', + resourceInfo: 'Ressourceninformation', + movementInfo: 'Bewegungsinformation', + noReports: 'Keine Geheimdienstberichte', + markAsRead: 'Als gelesen markieren', + content: 'Informationsinhalt', + noFleet: 'Keine Flotte erkannt', + noData: 'Keine Daten verfügbar', + targetPosition: 'Zielposition', + missionType: 'Missionstyp' + }, + jointAttack: { + title: 'Gemeinsame Angriffseinladungen', + from: 'Initiator', + target: 'Ziel-NPC', + targetPlanet: 'Zielplanet', + npcFleet: 'NPC-Flotte', + lootShare: 'Beuteanteil', + expiresIn: 'Läuft ab in', + expired: 'Abgelaufen', + accept: 'Am Angriff teilnehmen', + decline: 'Ablehnen', + noInvites: 'Keine gemeinsamen Angriffseinladungen', + acceptSuccess: 'Dem gemeinsamen Angriff beigetreten!', + declined: 'Einladung abgelehnt', + targetInfo: 'Angriffsziel', + expectedShare: 'Erwarteter Anteil', + remaining: 'Verbleibende Zeit' + }, + aid: { + title: 'Ressourcenhilfe', + from: 'Quelle', + resources: 'Hilfsressourcen', + noAid: 'Keine Hilfsaufzeichnungen' + }, + attitudeChange: { + title: 'Haltungsänderungen', + npc: 'NPC', + previous: 'Vorher', + current: 'Jetzt', + reason: 'Grund', + reasons: { + naturalSwing: 'Natürliche Veränderung', + giftReceived: 'Geschenk erhalten', + attacked: 'Wurde angegriffen', + reputationThreshold: 'Reputationsschwelle', + attitude_swing: 'Haltungsschwankung', + gift: 'Geschenk erhalten', + attack: 'Angriff erlitten' + } + }, + allyAction: { + title: 'Verbündete Aktionen', + defense: 'Verteidigungsunterstützung', + defenseDesc: '{npcName} sendet Flotte zur Verteidigung von {targetPlanet}', + jointAttackStarted: 'Gemeinsamer Angriff gestartet', + jointAttackStartedDesc: 'Gemeinsamer Angriff auf {targetNpc} hat begonnen', + reputationBonus: 'Reputationsbonus', + reputationBonusDesc: 'Dein Verbündeter {npcName} spricht gut von dir zu {targetNpc}' + } + }, + campaign: { + name: 'Kampagne', + description: 'Erkunde die mysteriöse Galaxie und entdecke antike Geheimnisse', + totalProgress: 'Gesamtfortschritt', + questsCompleted: 'Quests abgeschlossen', + chapter: 'Kapitel', + branch: 'Zweig', + startQuest: 'Quest starten', + claimRewards: 'Belohnungen abholen', + objectives: 'Ziele', + rewards: 'Belohnungen', + completed: 'Abgeschlossen', + inProgress: 'In Bearbeitung', + available: 'Verfügbar', + locked: 'Gesperrt', + notifications: { + questStarted: 'Quest gestartet', + questCompleted: 'Quest abgeschlossen!', + rewardsClaimed: 'Belohnungen erhalten', + objectiveCompleted: 'Ziel erreicht', + chapterUnlocked: 'Neues Kapitel freigeschaltet', + reputationUp: 'Reputation bei {npcName} um {value} erhöht', + reputationDown: 'Reputation bei {npcName} um {value} verringert', + branchUnlocked: 'Neuer Storyzweig freigeschaltet!' + }, + dialogue: { + skip: 'Überspringen', + continue: 'Weiter', + finish: 'Beenden', + player: 'Kommandant', + npc: 'NPC', + narrator: 'Erzähler', + mysterious: 'Mysteriöses Signal', + unknownSource: 'Unbekannte Quelle', + choiceEffect: 'Dialogauswahl-Effekt' + }, + chapters: { + '1': { + title: 'Ursprung', + description: 'Baue deine Heimat auf und mache den ersten Schritt ins All', + backgroundStory: + 'Du bist ein junger Weltraumkommandant, der gerade seinen ersten Planeten erworben hat. In diesem weiten Universum wirst du deine Heimat aufbauen, Technologie entwickeln und die Tiefen der Galaxie erkunden...' + }, + '2': { + title: 'Erkundung', + description: 'Erkunde das Universum und entdecke antike Ruinen', + backgroundStory: + 'Während deine Macht wächst, erregen mysteriöse Signale aus dem tiefen Weltraum deine Aufmerksamkeit. Diese Signale scheinen auf ein antikes Geheimnis hinzuweisen, das mutige Entdecker erwartet...' + }, + '3': { + title: 'Diplomatie', + description: 'Knüpfe Verbindungen mit anderen Fraktionen', + backgroundStory: + 'Du bist nicht allein in der Galaxie. Andere Zivilisationen erheben sich. Du musst entscheiden, ob du ihr Feind oder Verbündeter sein willst. Diplomatische Weisheit wird bestimmen, wie weit dein Imperium gehen kann...' + }, + '4': { + title: 'Aufziehende Schatten', + description: 'Stelle dich mächtigen Feinden und verteidige dein Territorium', + backgroundStory: + 'Gefahr lauert in den Schatten. Eine mächtige feindliche Macht hat dein Territorium ins Visier genommen. Krieg ist unvermeidlich. Du musst dich auf den kommenden Sturm vorbereiten...' + }, + '5': { + title: 'Antike Geheimnisse', + description: 'Enthülle die tiefsten Geheimnisse der Galaxie', + backgroundStory: + 'Alle Hinweise deuten auf die mysteriöseste Region der Galaxie. Dort warten die ultimativen Geheimnisse antiker Zivilisationen. Bist du bereit, alles zu enthüllen?' + } + }, + quests: { + '1_1': { title: 'Heimataufbau', description: 'Baue Infrastruktur auf, um die Grundlage für deinen Planeten zu legen' }, + '1_2': { title: 'Technische Erleuchtung', description: 'Erforsche Basistechnologie, um deine technische Reise zu beginnen' }, + '1_3': { title: 'Erstes Schiff', description: 'Baue dein erstes Kriegsschiff' }, + '1_4': { title: 'Seltsame Nachbarn', description: 'Erkunde andere Fraktionen in nahen Systemen' }, + '1_5': { title: 'Erster Kontakt', description: 'Stelle ersten Kontakt mit nahen NPC-Fraktionen her' }, + '2_1': { title: 'Pionierkolonie', description: 'Kolonisiere deinen ersten neuen Planeten' }, + '2_2': { title: 'Tiefraum-Expedition', description: 'Sende Flotte auf Expeditionsmissionen' }, + '2_3': { title: 'Mysteriöses Signal', description: 'Untersuche mysteriöse Signale aus dem tiefen Weltraum' }, + '2_4': { title: 'Ruinenuntersuchung', description: 'Erkunde entdeckte antike Ruinen' }, + '2_5': { title: 'Archive entschlüsseln', description: 'Erforsche Daten aus den Ruinen' }, + '3_1': { title: 'Friedensstifter', description: 'Verbessere Beziehungen zu NPCs durch Diplomatie' }, + '3_2': { title: 'Handelsbeziehungen', description: 'Baue stabile Beziehungen zu freundlichen Fraktionen auf' }, + '3_3': { title: 'Gemeinsame Bedrohung', description: 'Entdecke potenzielle feindliche Kräfte' }, + '3_4': { title: 'Allianzverhandlungen', description: 'Schließe eine formelle Allianz mit freundlichen NPCs' }, + '3_5': { title: 'Sturmvorbereitung', description: 'Baue Verteidigungen zur Vorbereitung auf Herausforderungen' }, + '4_1': { title: 'Außenpostenangriff', description: 'Wehre den ersten Angriff feindlicher Kräfte ab' }, + '4_2': { title: 'Informationsbeschaffung', description: 'Erkunde feindliche Militäraufstellungen' }, + '4_3': { title: 'Gegenangriff', description: 'Starte einen Gegenangriff gegen den Feind' }, + '4_4': { title: 'Ressourcenkampf', description: 'Recycel Schlachtfeldtrümmer für Ressourcen' }, + '4_5': { title: 'Vorabend der Schlacht', description: 'Baue eine mächtige Flotte für die letzte Schlacht' }, + '5_1': { title: 'Tiefen der Ruinen', description: 'Erkunde die tiefsten Teile der Ruinen' }, + '5_2': { title: 'Antike Technologie', description: 'Schalte Technologie antiker Zivilisationen frei' }, + '5_3': { title: 'Letzte Konfrontation', description: 'Stelle dich dem letzten Kampf gegen den mysteriösen Feind' }, + '5_4': { title: 'Neue Ära', description: 'Gründe neue Kolonien und beginne ein neues Zeitalter' }, + '5_5': { title: 'Vermächtnis', description: 'Entwickle weiter und erobere mehr Systeme' } + }, + objectiveTypes: { + buildBuilding: 'Baue {building} auf Stufe {level}', + researchTech: 'Erforsche {tech} auf Stufe {level}', + produceShips: 'Produziere {count} {ship}', + accumulateResources: 'Sammle {amount} {resource}', + defeatNPC: 'Besiege {npc}', + winBattles: 'Gewinne {count} Kämpfe', + recycleDebris: 'Recycel {amount} Trümmer', + reachRelation: 'Erreiche {level} Beziehung mit {npc}', + sendGift: 'Sende {count} Geschenke an {npc}', + formAlliance: 'Schließe Allianz mit {npc}', + colonize: 'Kolonisiere {count} Planeten', + expedition: 'Schließe {count} Expeditionen ab', + spyTarget: 'Spioniere {target} aus' + }, + errors: { + questNotFound: 'Quest nicht gefunden', + questNotAvailable: 'Quest nicht verfügbar', + questNotActive: 'Quest nicht aktiv', + questNotCompleted: 'Quest nicht abgeschlossen', + rewardsAlreadyClaimed: 'Belohnungen bereits erhalten', + prerequisiteNotMet: 'Voraussetzungs-Quest nicht abgeschlossen' + }, + speakers: { + ancientVoice: 'Antike Stimme', + neighborNPC: 'Nachbar-Fraktion', + mysteriousSignal: 'Mysteriöses Signal', + enemyCommander: 'Feindlicher Kommandant' + }, + objectiveDescriptions: { + buildMetalMine: 'Baue Metallmine auf Stufe 2', + buildCrystalMine: 'Baue Kristallmine auf Stufe 2', + buildSolarPlant: 'Baue Solarkraftwerk auf Stufe 2', + buildResearchLab: 'Baue Forschungslabor auf Stufe 1', + researchEnergy: 'Erforsche Energietechnik auf Stufe 1', + buildShipyard: 'Baue Raumschiffwerft auf Stufe 2', + researchCombustion: 'Erforsche Verbrennungstriebwerk auf Stufe 1', + buildLightFighters: 'Baue 5 Leichte Jäger', + researchEspionage: 'Erforsche Spionagetechnik auf Stufe 2', + buildSpyProbes: 'Baue 3 Spionagesonden', + spyAnyNPC: 'Spioniere einen NPC-Planeten aus', + sendGiftToNPC: 'Sende ein Geschenk an einen NPC', + researchAstrophysics: 'Erforsche Astrophysik auf Stufe 1', + buildColonyShip: 'Baue ein Kolonieschiff', + colonizeNewPlanet: 'Kolonisiere einen neuen Planeten', + completeExpedition: 'Schließe eine Expeditionsmission ab', + discoverRuins: 'Entdecke antike Ruinen', + researchComputer: 'Erforsche Computertechnik auf Stufe 4', + improveRelation: 'Verbessere Beziehungen zu einem NPC', + reachFriendly: 'Erreiche freundlichen Status mit einem NPC', + spyHostileNPC: 'Spioniere einen feindlichen NPC aus', + formAlliance: 'Schließe Allianz mit einem freundlichen NPC', + buildDefenses: 'Baue Verteidigungsanlagen', + winDefenseBattle: 'Gewinne eine Verteidigungsschlacht', + spyEnemyPlanet: 'Spioniere Feindplaneten aus', + attackEnemy: 'Greife den Feind an', + recycleDebris: 'Recycel Trümmer', + buildBattleships: 'Baue 10 Schlachtschiffe', + exploreDeepRuins: 'Erkunde tiefe Ruinen', + researchHyperspace: 'Erforsche Hyperraumtechnologie', + defeatBoss: 'Besiege den mysteriösen Feind', + colonizeSpecial: 'Kolonisiere besonderen Standort', + continueDevelopment: 'Setze Entwicklung fort' + }, + dialogues: { + '1_1': { + prologue_1: + 'Willkommen in der Galaxie, junger Kommandant. Dieses weite Universum wartet auf deine Erkundung. Zuerst bauen wir deinen Heimatplaneten auf.', + prologue_2: 'Ich spüre ein neues Bewusstsein erwachen... Interessant... Mal sehen, wie weit du kommst...' + }, + '1_2': { + prologue_1: + 'Grundlegende Infrastruktur ist fertig. Jetzt ist es Zeit, Technologie zu entwickeln. Baue ein Forschungslabor und beginne deine technische Reise.' + }, + '1_3': { + prologue_1: + 'Mit technologischer Unterstützung kannst du beginnen, deine Flotte aufzubauen. Baue eine Werft und produziere dein erstes Kriegsschiff.' + }, + '1_4': { + prologue_1: + 'Deine Flotte nimmt Form an. Jetzt lass uns deine Umgebung kennenlernen. Sende Spionagesonden aus, um nahe Fraktionen zu erkunden.', + prologue_2: 'Du bist nicht allein... Andere Zivilisationen existieren in dieser Galaxie...' + }, + '1_5': { + prologue_1: 'Du hast nahe Fraktionen entdeckt. Diplomatie ist eine Kunst. Versuche, Kontakt mit ihnen aufzunehmen.', + epilogue_1: 'Danke für dein Geschenk, Kommandant. Ich hoffe, wir können Freunde werden.', + epilogue_2: 'Gut... Verbindungen aufzubauen ist der erste Schritt, tiefere Geheimnisse zu enthüllen...' + }, + '2_1': { + prologue_1: + 'Deine Macht ist etabliert. Es ist Zeit, dein Territorium zu erweitern. Erforsche Astrophysik, baue ein Kolonieschiff und erkunde neue Planeten.', + prologue_2: 'Das Universum ist unendlich... Mehr Planeten bedeuten mehr Möglichkeiten...' + }, + '2_2': { + prologue_1: 'Kolonisierung erfolgreich! Aber tiefere Geheimnisse warten im Universum. Sende deine Flotte auf Expeditionsmissionen.', + prologue_2: 'Schwache Signale aus der Ferne... Etwas erwartet dich dort...' + }, + '2_3': { + prologue_1: + 'Deine Expedition entdeckte anomale Signale. Diese Signale scheinen von einer antiken Zivilisation zu stammen... Untersuche ihre Quelle.', + 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.' + }, + '2_5': { + prologue_1: 'Datenarchive wurden in den Ruinen gefunden. Studiere diese Daten, vielleicht kannst du neue Technologie freischalten.' + }, + '3_1': { prologue_1: 'Beim Erkunden vergiss nicht die Diplomatie. Gute Beziehungen zu umliegenden Fraktionen zu pflegen nützt dir.' }, + '3_2': { + prologue_1: + 'Einige Fraktionen haben Freundlichkeit gezeigt. Vertiefe die Beziehungen weiter, vielleicht erhältst du mehr Unterstützung.' + }, + '3_3': { + prologue_1: + 'Geheimdienstberichte deuten darauf hin, dass feindliche Kräfte dich aus den Schatten beobachten. Bleibe wachsam und erkunde ihre Bewegungen.' + }, + '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.' }, + '4_1': { + prologue_1: 'Der Feind hat einen Angriff gestartet! Verteidige deinen Planeten!', + epilogue_1: 'Du hast die erste Welle des Feindes erfolgreich abgewehrt. Aber das ist erst der Anfang...' + }, + '4_2': { + prologue_1: 'Der Feind hat sich zurückgezogen, aber er wird zurückkehren. Erkunde ihre Planeten, um ihre Stärke zu verstehen.' + }, + '4_3': { prologue_1: 'Es ist Zeit zurückzuschlagen. Greife die feindlichen Planeten an und schwäche ihre Kräfte.' }, + '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.' }, + '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_3': { + prologue_1: 'Ein mysteriöser Feind ist aufgetaucht. Dies ist die letzte Herausforderung. Besiege ihn!', + 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...' + } + } } } diff --git a/src/locales/en.ts b/src/locales/en.ts index 9de42b3..f7dc47f 100644 --- a/src/locales/en.ts +++ b/src/locales/en.ts @@ -11,28 +11,10 @@ export default { common: { confirm: 'Confirm', cancel: 'Cancel', - delete: 'Delete', - edit: 'Edit', save: 'Save', close: 'Close', - back: 'Back', - next: 'Next', - previous: 'Previous', - submit: 'Submit', - reset: 'Reset', - search: 'Search', - filter: 'Filter', - loading: 'Loading...', - noData: 'No Data', - error: 'Error', - success: 'Success', - warning: 'Warning', - info: 'Info', resourceType: 'Resource Type', playerName: 'Commander', - timeHour: 'h', - timeMinute: 'm', - timeSecond: 's', featureLocked: 'Feature Locked', unlockRequired: 'Building Required', requiredBuilding: 'Required Building', @@ -40,7 +22,6 @@ export default { goToBuildings: 'Go to Buildings', locked: 'Locked', viewRequirements: 'View Requirements', - requirements: 'Requirements', requirementsNotMet: 'Requirements Not Met', current: 'Current', level: 'Level', @@ -50,7 +31,8 @@ export default { viewDetails: 'View Details', exitConfirmTitle: 'Exit Game', exitConfirmMessage: 'Are you sure you want to exit? Your progress is saved automatically.', - points: 'Points' + points: 'Points', + retry: 'Retry' }, errors: { requirementsNotMet: 'Requirements not met', @@ -94,7 +76,6 @@ export default { gm: 'GM' }, sidebar: { - language: 'Language', lightMode: 'Light Mode', darkMode: 'Dark Mode', collapse: 'Collapse', @@ -119,9 +100,6 @@ export default { }, energy: { lowWarning: 'Energy deficit! Resource production stopped!', - severeWarning: 'Energy deficit! Resource production stopped!', - criticalWarning: 'Energy deficit! Resource production stopped!', - noProduction: 'Energy deficit! Resource production stopped!', deficitDetail: 'Energy deficit: {deficit}, build more power plants', buildSolarPlant: 'Build Power Plant' }, @@ -132,27 +110,20 @@ export default { lowResources: 'Running low: {resources}' }, planet: { - planet: 'Planet', moon: 'Moon', - colony: 'Colony', position: 'Position', - coordinates: 'Coordinates', switchToMoon: 'View Moon', backToPlanet: 'Back to Planet', switchPlanet: 'Switch Planet', currentPlanet: 'Current Planet', - fields: 'Fields', temperature: 'Temperature', homePlanet: 'Home Planet', planetPrefix: 'Planet', - moonSuffix: "'s Moon", colonyPrefix: 'Colony', renamePlanet: 'Rename Planet', renamePlanetTitle: 'Rename Planet', - newPlanetName: 'New Name', planetNamePlaceholder: 'Enter new planet name', - rename: 'Rename', - renameSuccess: 'Planet renamed to {name}' + rename: 'Rename' }, player: { points: 'Total Points' @@ -179,12 +150,11 @@ export default { sensorPhalanx: 'Sensor Phalanx', jumpGate: 'Jump Gate', planetDestroyerFactory: 'Planet Destroyer Factory', + geoResearchStation: 'Geological Research Station', + deepDrillingFacility: 'Deep Drilling Facility', buildTime: 'Build Time', production: 'Production', consumption: 'Consumption', - totalCost: 'Total Cost', - totalPoints: 'Total Points', - levelRange: 'Level Range', storageCapacity: 'Capacity', energyProduction: 'Energy Production', @@ -192,7 +162,6 @@ export default { buildQueueBonus: 'Build Queue', spaceBonus: 'Space Bonus', buildSpeedBonus: 'Build Speed Bonus', - researchSpeedBonus: 'Research Speed Bonus', missileCapacity: 'Missile Capacity', @@ -225,7 +194,9 @@ export default { lunarBase: 'Increases available space on the moon, +30 space per level', sensorPhalanx: 'Detects fleet activities in surrounding systems', jumpGate: 'Instantly transfers fleets to other moons', - planetDestroyerFactory: 'Constructs ultimate weapons capable of destroying planets' + 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' }, ships: { lightFighter: 'Light Fighter', @@ -289,9 +260,6 @@ export default { }, research: { researchTime: 'Research Time', - totalCost: 'Total Cost', - totalPoints: 'Total Points', - levelRange: 'Level Range', attackBonus: 'Attack Bonus', shieldBonus: 'Shield Bonus', @@ -300,8 +268,7 @@ export default { researchQueueBonus: 'Research Queue', colonySlots: 'Colony Slots', forAllPlanets: '(Global)', - speedBonus: 'Speed Bonus', - researchSpeedBonus: 'Research Speed Bonus' + speedBonus: 'Speed Bonus' }, technologies: { energyTechnology: 'Energy Technology', @@ -321,7 +288,8 @@ export default { hyperspaceDrive: 'Hyperspace Drive', darkMatterTechnology: 'Dark Matter Technology', terraformingTechnology: 'Terraforming Technology', - planetDestructionTech: 'Planet Destruction Technology' + planetDestructionTech: 'Planet Destruction Technology', + miningTechnology: 'Mining Technology' }, technologyDescriptions: { energyTechnology: 'Improves energy efficiency', @@ -342,7 +310,8 @@ export default { hyperspaceDrive: 'Advanced propulsion technology', 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' + planetDestructionTech: 'Terrifying technology for destroying entire planets', + miningTechnology: 'Improves mining methods and equipment, increases ore deposit capacity on all planets. +15% capacity per level' }, officers: { commander: 'Commander', @@ -399,14 +368,9 @@ export default { movedToQueue: 'Task moved to queue' }, overview: { - title: 'Planet Overview', resourceOverview: 'Resources', fleetInfo: 'Fleet', currentShips: 'Ships on this planet', - productionSources: 'Production Sources', - productionSourcesDesc: 'Detailed resource production and bonus information', - consumptionSources: 'Consumption Sources', - consumptionSourcesDesc: 'Energy consumption details for buildings', totalProduction: 'Total Production', totalConsumption: 'Total Consumption', noConsumption: 'No energy consumption', @@ -416,12 +380,8 @@ export default { }, buildingsView: { title: 'Buildings', - usedSpace: 'Used Space', spaceUsage: 'Space Usage', - level: 'Level', upgradeCost: 'Upgrade Cost', - buildTime: 'Build Time', - build: 'Build', upgrade: 'Upgrade', maxLevelReached: 'Max Level Reached', requirementsNotMet: 'Requirements Not Met', @@ -431,8 +391,7 @@ export default { demolishRefund: 'Demolish Refund', demolishFailed: 'Demolish Failed', demolishFailedMessage: 'Unable to demolish this building. Please check if the build queue is full or the building level is 0.', - confirmDemolish: 'Confirm Demolish', - confirmDemolishMessage: 'Are you sure you want to demolish' + confirmDemolish: 'Confirm Demolish' }, researchView: { title: 'Research', @@ -443,25 +402,14 @@ export default { researchFailedMessage: 'Please check if you have enough resources, prerequisites are met, or if there are other research tasks.' }, shipyard: { - attack: 'Attack', missileAttack: 'Missile Attack', - shield: 'Shield', - armor: 'Armor', speed: 'Speed', cargoCapacity: 'Cargo Capacity', - fuelConsumption: 'Fuel Consumption', - buildCost: 'Build Cost', - buildTime: 'Build Time', - perUnit: 'Per Unit', - batchCalculator: 'Batch Calculator', - quantity: 'Quantity', - totalCost: 'Total Cost', - totalTime: 'Total Time' + fuelConsumption: 'Fuel Consumption' }, shipyardView: { title: 'Shipyard', fleetStorage: 'Fleet Storage', - owned: 'Owned', attack: 'Attack', missileAttack: 'Missile Attack', shield: 'Shield', @@ -477,17 +425,7 @@ export default { buildFailedMessage: 'Please check if you have enough resources or if prerequisites are met.' }, defense: { - attack: 'Attack', - missileAttack: 'Missile Attack', - shield: 'Shield', - armor: 'Armor', - buildCost: 'Build Cost', - buildTime: 'Build Time', - perUnit: 'Per Unit', - batchCalculator: 'Batch Calculator', - quantity: 'Quantity', - totalCost: 'Total Cost', - totalTime: 'Total Time' + missileAttack: 'Missile Attack' }, defenseView: { title: 'Defense', @@ -651,14 +589,13 @@ export default { benefitsBonus: 'Benefits Bonus', resourceProduction: 'Resource Production', darkMatterProduction: 'Dark Matter Production', - energyProduction: 'Energy Production', buildingSpeed: 'Building Speed', researchSpeed: 'Research Speed', fleetSpeed: 'Fleet Speed', fuelConsumption: 'Fuel Consumption', defense: 'Defense', storageCapacity: 'Storage Capacity', - buildQueueBonus: 'Build Queue', + buildQueue: 'Build Queue', spaceBonus: 'Space Bonus', buildSpeedBonus: 'Build Speed Bonus', researchSpeedBonus: 'Research Speed Bonus', @@ -683,14 +620,11 @@ export default { selectGalaxy: 'Select Galaxy', system: 'System', selectSystem: 'Select System', - view: 'View', - myPlanet: 'My Planet', myPlanets: 'View My Systems', npcPlanets: 'NPC Planets', selectPlanetToView: 'Select planet to view its system', totalPositions: '10 planet positions total', mine: 'Mine', - hostile: 'Hostile', emptySlot: 'Empty - Colonizable', scout: 'Scout', attack: 'Attack', @@ -716,7 +650,9 @@ export default { systems: 'systems', distance: 'Distance', flightTime: 'Flight Time', + outOfRange: 'Out of Range', launchMissile: 'Launch', + missileLaunched: 'Missile Launched', cancel: 'Cancel', colonizePlanetMessage: 'Are you sure you want to colonize position [{coordinates}]?\n\nPlease go to the fleet page to send a colony ship.', @@ -733,17 +669,13 @@ export default { phalanxScanTitle: 'Sensor Phalanx Scan', phalanxScanDescription: 'Scanning fleet activity at planet [{coordinates}]', phalanxNoMoon: 'Requires a moon with Sensor Phalanx to scan', - phalanxOutOfRange: 'Target is out of scan range', - phalanxRange: 'Scan Range', phalanxCost: 'Scan Cost', phalanxNoFleets: 'No fleet activity detected', phalanxFleetDetected: '{count} fleet(s) detected', - phalanxMission: 'Mission', phalanxOrigin: 'Origin', phalanxDestination: 'Destination', phalanxArrival: 'Arrival', phalanxReturn: 'Return', - phalanxStatus: 'Status', phalanxStatusOutbound: 'Outbound', phalanxStatusReturning: 'Returning', phalanxInsufficientDeuterium: 'Insufficient Deuterium', @@ -781,10 +713,29 @@ export default { defense: 'Defense', buildings: 'Buildings', unread: 'Unread', + pending: 'Pending', + invalidData: 'Invalid Data', targetPlanet: 'Target Planet', attackerRemaining: 'Attacker Remaining', defenderRemaining: 'Defender Remaining', allDestroyed: 'All destroyed', + moonChance: 'Moon Chance', + showRoundDetails: 'Show Round Details', + hideRoundDetails: 'Hide Round Details', + round: 'Round {round}', + attackerRemainingPower: 'Attacker Remaining Power', + defenderRemainingPower: 'Defender Remaining Power', + playAnimation: 'Play Animation', + showDetails: 'Show Details', + speed: 'Speed', + power: 'Power', + battleLogEmpty: 'Battle log is empty', + roundStarted: 'Round {round} started', + shipDestroyed: '{count} {ship} destroyed', + defenseDestroyed: '{count} {defense} destroyed', + attackerWins: 'Attacker Wins', + defenderWins: 'Defender Wins', + roundsPlayed: 'rounds played', spied: 'Spied', spiedNotification: 'Spied Notification', noSpiedNotifications: 'No spied notifications', @@ -855,7 +806,11 @@ export default { clearNPCActivity: 'NPC Activity', clearGiftNotifications: 'Gift Notifications', clearGiftRejected: 'Rejected Gifts', - clearNow: 'Clear Now' + clearTradeOffers: 'Trade Offers', + clearIntelReports: 'Intel Reports', + clearJointAttackInvites: 'Joint Attack Invitations', + clearNow: 'Clear Now', + clearSuccess: 'Messages cleared' }, missionReports: { transportSuccess: 'Transport mission completed successfully', @@ -980,7 +935,6 @@ export default { resume: 'Resume', gamePaused: 'Game paused', gameResumed: 'Game resumed', - playerName: 'Player Name', gameSpeed: 'Resource Production Speed', gameSpeedDesc: 'Current resource production speed multiplier', speedChanged: 'Resource production speed changed to {speed}x', @@ -988,17 +942,14 @@ export default { reset: 'Reset', about: 'About', version: 'Version', - latestVersion: 'Latest Version', checkUpdate: 'Check Update', checking: 'Checking...', newVersionAvailable: 'New version {version} available', upToDate: 'Already up to date', - checkUpdateCooldown: 'Please try again later (5 minute cooldown)', checkUpdateFailed: 'Failed to check for updates, please check your network connection', viewUpdate: 'View Update', updateAvailable: 'A new version is available. Click to view release notes.', download: 'Download', - goToDownload: 'Go to Download', buildDate: 'Build Date', community: 'Community', github: 'GitHub Repository', @@ -1025,13 +976,53 @@ export default { expandTypes: 'Expand Details', collapseTypes: 'Collapse Details', // NPC name update - npcNameUpdate: 'NPC Name Update', npcNameUpdateTitle: 'Old NPC Names Detected', npcNameUpdateMessage: 'Found {count} NPCs using old name format. Would you like to update them to new localized names?', npcNameUpdateConfirm: 'Update Names', npcNameUpdateCancel: 'Keep Current', npcNameUpdateSuccess: 'Successfully updated {count} NPC names', - npcNameUpdateSkipped: 'NPC name update skipped' + npcNameUpdateSkipped: 'NPC name update skipped', + // WebDAV + webdav: { + title: 'Cloud Sync', + desc: 'Sync game saves via WebDAV', + config: 'Configure', + configTitle: 'WebDAV Configuration', + configDesc: 'Configure your WebDAV server for cloud sync', + notConfigured: 'Please configure WebDAV server first', + serverUrl: 'Server URL', + serverUrlPlaceholder: 'e.g. https://dav.example.com', + serverUrlHint: 'Enter your WebDAV server address', + username: 'Username', + usernamePlaceholder: 'Enter username', + password: 'Password', + passwordPlaceholder: 'Enter password', + passwordHint: 'Password is stored locally only', + basePath: 'Save Path', + basePathPlaceholder: 'e.g. /ogame-saves/', + testConnection: 'Test Connection', + testing: 'Testing...', + testSuccess: 'Connection successful', + testFailed: 'Connection failed', + save: 'Save', + clearConfig: 'Clear', + configSaved: 'Configuration saved', + configCleared: 'Configuration cleared', + upload: 'Upload', + uploading: 'Uploading...', + uploadSuccess: 'Upload successful', + uploadFailed: 'Upload failed', + download: 'Download', + downloadSuccess: 'Download successful', + downloadFailed: 'Download failed', + selectFile: 'Select Save File', + selectFileDesc: 'Choose a save file to restore', + noFiles: 'No save files found', + loadFailed: 'Failed to load file list', + confirmDelete: 'Are you sure you want to delete "{name}"?', + deleteSuccess: 'File deleted', + deleteFailed: 'Delete failed' + } }, notifications: { constructionComplete: 'Construction Complete', @@ -1154,8 +1145,6 @@ export default { noFriendlyNpcs: 'No friendly NPCs', noNeutralNpcs: 'No neutral NPCs', noHostileNpcs: 'No hostile NPCs', - recentEvents: 'Recent Events', - recentEventsDescription: 'Recent diplomatic activity log', ago: 'ago', notifications: 'Diplomatic Notifications', markAllRead: 'Mark All Read', @@ -1179,7 +1168,6 @@ export default { }, note: 'Note', notePlaceholder: 'Enter note...', - noteEmpty: 'No note', lastEvent: 'Last Event', reportDetails: 'Diplomatic Report Details', eventDescription: 'Event Description', @@ -1235,6 +1223,22 @@ export default { npcEliminatedMessage: "You destroyed all of {npcName}'s planets! This faction has been completely wiped out." }, searchPlaceholder: 'Search NPC name...', + // Notification types + notificationType: { + tradeOffer: 'Trade Offer', + intelReport: 'Intel Report', + jointAttack: 'Joint Attack Invitation' + }, + // Notification badges + notificationBadge: { + trade: 'Trade', + intel: 'Intel', + jointAttack: 'Invite' + }, + // Notification extra info + notificationExtra: { + pending: 'Pending' + }, viewMode: { card: 'Card', list: 'List' @@ -1251,6 +1255,21 @@ export default { medium: 'Medium', hard: 'Hard' }, + aiType: 'AI Type', + aiTypes: { + aggressive: 'Aggressive', + defensive: 'Defensive', + trader: 'Trader', + expansionist: 'Expansionist', + balanced: 'Balanced' + }, + aiTypeDescriptions: { + aggressive: 'Actively scouts and attacks, retaliates fiercely', + defensive: 'Rarely attacks first, retaliates strongly when attacked', + trader: 'Rarely attacks, prefers trading and gifting', + expansionist: 'Focuses on development, attacks less', + balanced: 'Dynamically adjusts strategy based on situation' + }, reputation: 'Reputation', spyProbes: 'Spy Probes', fleetPower: 'Fleet Power', @@ -1567,11 +1586,21 @@ export default { title: 'Battle Simulator', message: 'Simulate battle outcomes before attacking. Enter both fleets and tech levels to predict victory, losses, and loot.' }, + campaign: { + title: 'Campaign Mode', + message: + 'Explore the galaxy story campaign! Complete missions to earn resource rewards and unlock new challenges. Each node has unique objectives and enemies.' + }, achievements: { title: 'Achievement System', message: 'Complete game objectives to unlock achievements and earn Dark Matter rewards! Achievements have multiple tiers - aim for higher challenges to get better rewards.' }, + ranking: { + title: 'Ranking', + message: + 'Compare your progress with other players and NPCs. See rankings based on points from buildings, research, fleet and defense. Strive to climb the leaderboard!' + }, settings: { title: 'Settings', message: 'Manage game data, adjust notifications, export/import saves here. Remember to backup your progress regularly!' @@ -1708,7 +1737,6 @@ export default { startQuest: 'Start Quest', claimRewards: 'Claim Rewards', objectives: 'Objectives', - objectivesLabel: 'Goals', rewards: 'Rewards', completed: 'Completed', inProgress: 'In Progress', @@ -1719,7 +1747,10 @@ export default { questCompleted: 'Quest completed!', rewardsClaimed: 'Rewards claimed', objectiveCompleted: 'Objective completed', - chapterUnlocked: 'New chapter unlocked' + chapterUnlocked: 'New chapter unlocked', + reputationUp: 'Reputation with {npcName} increased by {value}', + reputationDown: 'Reputation with {npcName} decreased by {value}', + branchUnlocked: 'New story branch unlocked!' }, dialogue: { skip: 'Skip', @@ -1729,33 +1760,39 @@ export default { npc: 'NPC', narrator: 'Narrator', mysterious: 'Mysterious Signal', - unknownSource: 'Unknown source' + unknownSource: 'Unknown source', + choiceEffect: 'Dialogue choice effect' }, chapters: { '1': { title: 'Origin', description: 'Build your home and take the first step into space', - backgroundStory: 'You are a young space commander who has just acquired your first planet. In this vast universe, you will build your home, develop technology, and explore the depths of the galaxy...' + backgroundStory: + 'You are a young space commander who has just acquired your first planet. In this vast universe, you will build your home, develop technology, and explore the depths of the galaxy...' }, '2': { title: 'Exploration', description: 'Explore the universe and discover ancient ruins', - backgroundStory: 'As your power grows, mysterious signals from deep space catch your attention. These signals seem to point to an ancient secret, waiting for brave explorers to uncover...' + backgroundStory: + 'As your power grows, mysterious signals from deep space catch your attention. These signals seem to point to an ancient secret, waiting for brave explorers to uncover...' }, '3': { title: 'Diplomacy', description: 'Establish connections with other factions', - backgroundStory: 'You are not alone in the galaxy. Other civilizations are rising. You must decide whether to be their enemy or ally. Diplomatic wisdom will determine how far your empire can go...' + backgroundStory: + 'You are not alone in the galaxy. Other civilizations are rising. You must decide whether to be their enemy or ally. Diplomatic wisdom will determine how far your empire can go...' }, '4': { title: 'Shadow Rising', description: 'Face powerful enemies and defend your territory', - backgroundStory: 'Danger lurks in the shadows. A powerful hostile force has targeted your territory. War is inevitable. You must prepare to face the coming storm...' + backgroundStory: + 'Danger lurks in the shadows. A powerful hostile force has targeted your territory. War is inevitable. You must prepare to face the coming storm...' }, '5': { title: 'Ancient Secrets', description: 'Uncover the deepest secrets of the galaxy', - backgroundStory: 'All clues point to the most mysterious region of the galaxy. There, the ultimate secrets left by ancient civilizations await. Are you ready to uncover everything?' + backgroundStory: + 'All clues point to the most mysterious region of the galaxy. There, the ultimate secrets left by ancient civilizations await. Are you ready to uncover everything?' } }, quests: { @@ -1926,11 +1963,13 @@ export default { }, dialogues: { '1_1': { - prologue_1: 'Welcome to the galaxy, young commander. This vast universe awaits your exploration. First, let us build up your home planet.', + prologue_1: + 'Welcome to the galaxy, young commander. This vast universe awaits your exploration. First, let us build up your home planet.', prologue_2: 'I sense a new consciousness awakening... Interesting... Let us see how far you can go...' }, '1_2': { - prologue_1: 'Basic infrastructure is complete. Now it is time to develop technology. Build a Research Lab and begin your tech journey.' + prologue_1: + 'Basic infrastructure is complete. Now it is time to develop technology. Build a Research Lab and begin your tech journey.' }, '1_3': { prologue_1: 'With technology support, you can start building your fleet. Build a Shipyard and produce your first warship.' @@ -1945,7 +1984,8 @@ export default { epilogue_2: 'Good... Establishing connections is the first step to uncovering deeper secrets...' }, '2_1': { - prologue_1: 'Your power is established. It is time to expand your territory. Research Astrophysics, build a colony ship, and explore new planets.', + prologue_1: + 'Your power is established. It is time to expand your territory. Research Astrophysics, build a colony ship, and explore new planets.', prologue_2: 'The universe is infinite... More planets mean more possibilities...' }, '2_2': { @@ -1953,7 +1993,8 @@ export default { prologue_2: 'Faint signals from afar... Something awaits you there...' }, '2_3': { - prologue_1: 'Your expedition discovered anomalous signals. These signals seem to come from an ancient civilization... Investigate their source.', + prologue_1: + 'Your expedition discovered anomalous signals. These signals seem to come from an ancient civilization... Investigate their source.', epilogue_1: 'These symbols... They are ruins of an ancient civilization! Continue investigating to uncover their secrets.' }, '2_4': { @@ -1979,7 +2020,7 @@ export default { }, '4_1': { prologue_1: 'The enemy has launched an attack! Defend your planet!', - epilogue_1: 'You successfully repelled the enemy\'s first wave. But this is just the beginning...' + epilogue_1: "You successfully repelled the enemy's first wave. But this is just the beginning..." }, '4_2': { prologue_1: 'The enemy has retreated, but they will return. Scout their planets to understand their strength.' @@ -2012,5 +2053,114 @@ export default { epilogue_1: 'The galaxy is vast and boundless, with countless secrets waiting for you to discover...' } } + }, + // NPC Enhanced Behavior Notifications + npcBehavior: { + // Neutral NPC behavior + tradeOfferReceived: 'Trade Offer Received', + tradeOfferDesc: '{npcName} has sent you a trade offer', + attitudeChanged: 'NPC Attitude Changed', + becameFriendly: '{npcName} has become friendly towards you', + becameHostile: '{npcName} has become hostile towards you', + // Friendly NPC behavior + intelReceived: 'Intel Received', + intelReceivedDesc: '{npcName} has shared enemy intelligence with you', + jointAttackInvite: 'Joint Attack Invitation', + jointAttackInviteDesc: '{npcName} invites you to attack an enemy together', + aidReceived: 'Aid Received', + aidReceivedDesc: '{npcName} has sent you {amount} resources', + allyDefense: 'Ally Defense', + allyDefenseDesc: '{npcName} is sending a fleet to help defend your planet', + // Trade related + trade: { + title: 'Trade Offers', + from: 'From', + offers: 'Offers', + requests: 'Requests', + expiresIn: 'Expires In', + expired: 'Expired', + accept: 'Accept', + decline: 'Decline', + noOffers: 'No trade offers', + acceptSuccess: 'Trade completed!', + acceptFailed: 'Insufficient resources to complete trade', + declined: 'Trade declined', + ratio: 'Exchange Ratio' + }, + // Intel related + intel: { + title: 'Intel Reports', + from: 'Source', + target: 'Target NPC', + type: 'Intel Type', + types: { + enemyFleet: 'Fleet Intel', + enemyResources: 'Resource Intel', + enemyMovement: 'Movement Intel' + }, + fleetInfo: 'Fleet Information', + resourceInfo: 'Resource Information', + movementInfo: 'Movement Information', + noReports: 'No intel reports', + markAsRead: 'Mark as Read', + content: 'Intel Content', + noFleet: 'No fleet detected', + noData: 'No data available', + targetPosition: 'Target Position', + missionType: 'Mission Type' + }, + // Joint attack related + jointAttack: { + title: 'Joint Attack Invitations', + from: 'Initiator', + target: 'Target NPC', + targetPlanet: 'Target Planet', + npcFleet: 'NPC Fleet', + lootShare: 'Loot Share', + expiresIn: 'Expires In', + expired: 'Expired', + accept: 'Join Attack', + decline: 'Decline', + noInvites: 'No joint attack invitations', + acceptSuccess: 'Joined joint attack!', + declined: 'Invitation declined', + targetInfo: 'Attack Target', + expectedShare: 'Expected Share', + remaining: 'Time Remaining' + }, + // Aid related + aid: { + title: 'Resource Aid', + from: 'Source', + resources: 'Aid Resources', + noAid: 'No aid records' + }, + // Attitude change related + attitudeChange: { + title: 'Attitude Changes', + npc: 'NPC', + previous: 'Previous', + current: 'Current', + reason: 'Reason', + reasons: { + attitude_swing: 'Attitude swing', + gift: 'Received gift', + attack: 'Attacked', + naturalSwing: 'Natural shift', + giftReceived: 'Received gift', + attacked: 'Was attacked', + reputationThreshold: 'Reputation threshold' + } + }, + // Ally actions related + allyAction: { + title: 'Ally Actions', + defense: 'Defensive Support', + defenseDesc: '{npcName} is sending fleet to help defend {targetPlanet}', + jointAttackStarted: 'Joint Attack Started', + jointAttackStartedDesc: 'Joint attack on {targetNpc} has begun', + reputationBonus: 'Reputation Bonus', + reputationBonusDesc: 'Your ally {npcName} speaks well of you to {targetNpc}' + } } } diff --git a/src/locales/es-LA.ts b/src/locales/es-LA.ts new file mode 100644 index 0000000..c21f46b --- /dev/null +++ b/src/locales/es-LA.ts @@ -0,0 +1,2188 @@ +export default { + home: { + subtitle: 'Conquista las Estrellas', + startGame: 'Iniciar Juego', + privacyAgreement: 'Acuerdo de Privacidad', + privacyAgreementDesc: 'Por favor, lee y acepta nuestra política de privacidad antes de iniciar el juego.', + agreeToPrivacy: 'He leído y acepto', + viewFullPolicy: 'Ver Política Completa', + agreeAndStart: 'Aceptar e Iniciar' + }, + common: { + confirm: 'Confirmar', + cancel: 'Cancelar', + save: 'Guardar', + close: 'Cerrar', + success: 'Éxito', + resourceType: 'Tipo de Recurso', + featureLocked: 'Característica Bloqueada', + unlockRequired: 'Edificio Requerido', + requiredBuilding: 'Edificio Requerido', + currentLevel: 'Nivel Actual', + goToBuildings: 'Ir a Edificios', + locked: 'Bloqueado', + viewRequirements: 'Ver Requisitos', + requirementsNotMet: 'Requisitos No Cumplidos', + current: 'Actual', + level: 'Nivel', + to: 'a', + gmModeActivated: '¡Modo GM Activado! Revisa el menú de navegación.', + view: 'Ver', + viewDetails: 'Ver Detalles', + exitConfirmTitle: 'Salir del Juego', + exitConfirmMessage: '¿Estás seguro de que quieres salir? Tu progreso se guarda automáticamente.', + points: 'Puntos', + retry: 'Reintentar' + }, + errors: { + requirementsNotMet: 'Requisitos no cumplidos', + insufficientResources: 'Recursos insuficientes', + insufficientFleetStorage: 'Almacenamiento de flota insuficiente', + shieldDomeLimit: 'Límite de cúpula de escudo alcanzado', + missileSiloLimit: 'Capacidad del silo de misiles excedida', + insufficientMissiles: 'Misiles interplanetarios insuficientes', + invalidMissileCount: 'Cantidad de misiles inválida', + targetOutOfRange: 'Objetivo fuera de alcance', + cannotAttackOwnPlanet: 'No puedes atacar tu propio planeta', + fleetMissionsFull: 'Espacios de misión de flota llenos', + insufficientFleet: 'Flota insuficiente', + insufficientFuel: 'Combustible insuficiente', + planetOnly: 'Este edificio solo puede construirse en planetas', + moonOnly: 'Este edificio solo puede construirse en lunas', + buildQueueFull: 'Cola de construcción llena', + insufficientSpace: 'Espacio insuficiente', + buildingLevelZero: 'El nivel del edificio es 0, no se puede demoler', + researchQueueFull: 'Cola de investigación llena', + moonExists: 'La luna ya existe', + insufficientDebris: 'Campo de escombros insuficiente', + launchFailed: 'Lanzamiento fallido' + }, + nav: { + overview: 'Resumen', + buildings: 'Edificios', + research: 'Investigación', + shipyard: 'Astillero', + defense: 'Defensa', + fleet: 'Flota', + officers: 'Oficiales', + simulator: 'Simulador', + galaxy: 'Galaxia', + diplomacy: 'Diplomacia', + achievements: 'Logros', + campaign: 'Campaña', + ranking: 'Clasificación', + messages: 'Mensajes', + settings: 'Configuración', + gm: 'GM' + }, + sidebar: { + lightMode: 'Modo Claro', + darkMode: 'Modo Oscuro', + collapse: 'Contraer', + expand: 'Expandir' + }, + resources: { + metal: 'Metal', + crystal: 'Cristal', + deuterium: 'Deuterio', + darkMatter: 'Materia Oscura', + energy: 'Energía', + production: 'Producción', + consumption: 'Consumo', + capacity: 'Capacidad', + current: 'Actual', + max: 'Capacidad Máxima', + perHour: 'hora', + perMinute: 'min', + hour: 'hora', + noEnergy: 'Sin Energía', + temperatureBonus: 'Bono de Temperatura' + }, + energy: { + lowWarning: '¡Déficit de energía! ¡Producción de recursos detenida!', + deficitDetail: 'Déficit de energía: {deficit}, construye más plantas de energía', + buildSolarPlant: 'Construir Planta de Energía' + }, + oreDeposit: { + lowWarning: '¡Los depósitos de mineral se están agotando!', + depletedWarning: '¡Depósitos de mineral agotados!', + depletedResources: 'Agotados: {resources}', + lowResources: 'Agotándose: {resources}' + }, + planet: { + moon: 'Luna', + position: 'Posición', + switchToMoon: 'Ver Luna', + backToPlanet: 'Volver al Planeta', + switchPlanet: 'Cambiar Planeta', + currentPlanet: 'Planeta Actual', + temperature: 'Temperatura', + homePlanet: 'Planeta Principal', + planetPrefix: 'Planeta', + colonyPrefix: 'Colonia', + renamePlanet: 'Renombrar Planeta', + renamePlanetTitle: 'Renombrar Planeta', + planetNamePlaceholder: 'Ingresa el nuevo nombre del planeta', + rename: 'Renombrar' + }, + player: { + points: 'Puntos Totales' + }, + buildings: { + metalMine: 'Mina de Metal', + crystalMine: 'Mina de Cristal', + deuteriumSynthesizer: 'Sintetizador de Deuterio', + solarPlant: 'Planta Solar', + fusionReactor: 'Reactor de Fusión', + roboticsFactory: 'Fábrica de Robótica', + naniteFactory: 'Fábrica de Nanites', + shipyard: 'Astillero', + hangar: 'Hangar', + researchLab: 'Laboratorio de Investigación', + metalStorage: 'Almacén de Metal', + crystalStorage: 'Almacén de Cristal', + deuteriumTank: 'Tanque de Deuterio', + darkMatterCollector: 'Colector de Materia Oscura', + darkMatterTank: 'Tanque de Materia Oscura', + missileSilo: 'Silo de Misiles', + terraformer: 'Terraformador', + lunarBase: 'Base Lunar', + sensorPhalanx: 'Falange de Sensores', + jumpGate: 'Portal de Salto', + planetDestroyerFactory: 'Fábrica de Destructores de Planetas', + geoResearchStation: 'Estación de Investigación Geológica', + deepDrillingFacility: 'Instalación de Perforación Profunda', + buildTime: 'Tiempo de Construcción', + production: 'Producción', + consumption: 'Consumo', + + storageCapacity: 'Capacidad', + energyProduction: 'Producción de Energía', + fleetStorage: 'Almacenamiento de Flota', + buildQueueBonus: 'Cola de Construcción', + spaceBonus: 'Bono de Espacio', + buildSpeedBonus: 'Bono de Velocidad de Construcción', + + missileCapacity: 'Capacidad de Misiles', + + // Ore deposits + oreDeposit: 'Depósito de Mineral', + remainingDeposit: 'Restante', + depletionTime: 'Agotamiento Est.', + depositDepleted: 'Agotado', + depositWarning: '¡Advertencia: Los depósitos de mineral se están agotando (por debajo del 10%)!', + depositDepletedMessage: 'Los depósitos de mineral se han agotado. La producción se ha detenido.' + }, + buildingDescriptions: { + metalMine: 'Extrae recursos de metal', + crystalMine: 'Extrae recursos de cristal', + deuteriumSynthesizer: 'Sintetiza deuterio (mayor producción en temperaturas frías)', + solarPlant: 'Proporciona energía', + fusionReactor: 'Usa deuterio para generar grandes cantidades de energía', + roboticsFactory: 'Acelera la velocidad de construcción', + naniteFactory: 'Aumenta la capacidad de la cola de construcción, +1 por nivel (máximo 10 niveles)', + shipyard: 'Construye naves', + hangar: 'Instalación especializada para expandir la capacidad de almacenamiento de flota, apoya la especialización planetaria', + researchLab: 'Investiga tecnologías', + metalStorage: 'Aumenta la capacidad de almacenamiento de metal', + crystalStorage: 'Aumenta la capacidad de almacenamiento de cristal', + deuteriumTank: 'Aumenta la capacidad de almacenamiento de deuterio', + darkMatterCollector: 'Recolecta recursos raros de materia oscura', + darkMatterTank: 'Aumenta la capacidad de almacenamiento de materia oscura', + missileSilo: 'Almacena y lanza misiles, 10 misiles por nivel', + terraformer: 'Terraforma la superficie del planeta, añade 30 espacios disponibles por nivel', + lunarBase: 'Aumenta el espacio disponible en la luna, +30 espacios por nivel', + sensorPhalanx: 'Detecta actividades de flotas en sistemas circundantes', + 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', + 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' + }, + ships: { + lightFighter: 'Caza Ligero', + heavyFighter: 'Caza Pesado', + cruiser: 'Crucero', + battleship: 'Nave de Batalla', + battlecruiser: 'Crucero de Batalla', + bomber: 'Bombardero', + destroyer: 'Destructor', + smallCargo: 'Nave de Carga Pequeña', + largeCargo: 'Nave de Carga Grande', + colonyShip: 'Nave Colonizadora', + recycler: 'Reciclador', + espionageProbe: 'Sonda de Espionaje', + solarSatellite: 'Satélite Solar', + darkMatterHarvester: 'Recolector de Materia Oscura', + deathstar: 'Estrella de la Muerte' + }, + shipDescriptions: { + lightFighter: 'Unidad de combate básica', + heavyFighter: 'Caza fuertemente blindado', + cruiser: 'Nave de guerra mediana, ofensiva y defensa equilibradas', + battleship: 'Principal nave de guerra pesada con potente poder de fuego y defensa fuerte', + battlecruiser: 'Nave de guerra rápida y poderosa, sobresale atacando naves de batalla', + bomber: 'Nave especializada para atacar estructuras de defensa', + destroyer: 'Nave anti-capital especializada con alto poder de fuego pero baja defensa', + smallCargo: 'Transporta pequeñas cantidades de recursos', + largeCargo: 'Transporta grandes cantidades de recursos', + colonyShip: 'Usada para colonizar nuevos planetas', + recycler: 'Recolecta recursos del campo de escombros', + espionageProbe: 'Explora planetas enemigos', + solarSatellite: 'Proporciona energía extra, producción basada en la temperatura del planeta (mayor en climas cálidos)', + darkMatterHarvester: 'Nave especial para cosechar materia oscura', + deathstar: 'Arma definitiva capaz de destruir planetas enteros' + }, + defenses: { + rocketLauncher: 'Lanzacohetes', + lightLaser: 'Láser Ligero', + heavyLaser: 'Láser Pesado', + gaussCannon: 'Cañón Gauss', + ionCannon: 'Cañón de Iones', + plasmaTurret: 'Torreta de Plasma', + smallShieldDome: 'Cúpula de Escudo Pequeña', + largeShieldDome: 'Cúpula de Escudo Grande', + antiBallisticMissile: 'Misil Anti-Balístico', + interplanetaryMissile: 'Misil Interplanetario', + planetaryShield: 'Escudo Planetario' + }, + defenseDescriptions: { + rocketLauncher: 'Instalación de defensa básica', + lightLaser: 'Arma de energía ligera', + heavyLaser: 'Arma de energía pesada', + gaussCannon: 'Arma cinética de alta velocidad', + ionCannon: 'Efectivo contra escudos', + plasmaTurret: 'Instalación de defensa poderosa', + smallShieldDome: 'Escudo pequeño que protege todo el planeta', + largeShieldDome: 'Escudo grande que protege todo el planeta', + antiBallisticMissile: 'Intercepta misiles enemigos, puede interceptar 1 misil interplanetario cada uno', + interplanetaryMissile: 'Puede atacar estructuras de defensa en otros planetas', + planetaryShield: 'Súper escudo que protege el planeta de ataques de destrucción' + }, + research: { + researchTime: 'Tiempo de Investigación', + totalCost: 'Costo Total', + totalPoints: 'Puntos Totales', + levelRange: 'Rango de Nivel', + + attackBonus: 'Bono de Ataque', + shieldBonus: 'Bono de Escudo', + armorBonus: 'Bono de Blindaje', + spyLevel: 'Nivel de Espionaje', + researchQueueBonus: 'Cola de Investigación', + colonySlots: 'Espacios de Colonia', + forAllPlanets: '(Global)', + speedBonus: 'Bono de Velocidad', + researchSpeedBonus: 'Bono de Velocidad de Investigación' + }, + technologies: { + energyTechnology: 'Tecnología de Energía', + laserTechnology: 'Tecnología Láser', + ionTechnology: 'Tecnología de Iones', + hyperspaceTechnology: 'Tecnología de Hiperespacio', + plasmaTechnology: 'Tecnología de Plasma', + computerTechnology: 'Tecnología Computacional', + espionageTechnology: 'Tecnología de Espionaje', + weaponsTechnology: 'Tecnología de Armas', + shieldingTechnology: 'Tecnología de Escudos', + armourTechnology: 'Tecnología de Blindaje', + astrophysics: 'Astrofísica', + gravitonTechnology: 'Tecnología de Gravitones', + combustionDrive: 'Motor de Combustión', + impulseDrive: 'Motor de Impulso', + hyperspaceDrive: 'Motor de Hiperespacio', + 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' + }, + technologyDescriptions: { + energyTechnology: 'Mejora la eficiencia energética', + laserTechnology: 'Fundamento de armas y defensa láser', + ionTechnology: 'Tecnología de armas de iones', + hyperspaceTechnology: 'Tecnología de salto hiperespacial', + plasmaTechnology: 'Tecnología de armas de plasma', + computerTechnology: 'Aumenta la cola de investigación y espacios de misión de flota, +1 cola +1 espacio por nivel (máximo 10 niveles)', + espionageTechnology: + 'Mejora la efectividad de la sonda de espionaje, +1 nivel de espionaje por nivel. Nivel de espionaje = tu nivel - nivel enemigo + sondas/5. ≥-1 muestra flota, ≥1 muestra defensa, ≥3 muestra edificios, ≥5 muestra tecnologías', + weaponsTechnology: 'Aumenta el poder de ataque de naves y defensas en un 10% por nivel', + shieldingTechnology: 'Aumenta los escudos de naves y defensas en un 10% por nivel', + armourTechnology: 'Aumenta el blindaje de naves y defensas en un 10% por nivel', + astrophysics: 'Cada nivel añade 1 espacio de colonia y aumenta la tasa de éxito de expediciones', + gravitonTechnology: 'Estudia la manipulación de gravitones, requerido para la Estrella de la Muerte', + combustionDrive: 'Tecnología de propulsión básica', + impulseDrive: 'Tecnología de propulsión intermedia', + hyperspaceDrive: 'Tecnología de propulsión avanzada', + darkMatterTechnology: 'Investigación de las propiedades y aplicaciones de la materia oscura', + terraformingTechnology: + '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' + }, + officers: { + commander: 'Comandante', + admiral: 'Almirante', + engineer: 'Ingeniero', + geologist: 'Geólogo', + technocrat: 'Tecnócrata', + darkMatterSpecialist: 'Especialista en Materia Oscura', + resourceBonus: 'Bono de Producción de Recursos', + darkMatterBonus: 'Bono de Producción de Materia Oscura', + energyBonus: 'Bono de Producción de Energía' + }, + officerDescriptions: { + commander: 'Mejora la velocidad de construcción y gestión', + admiral: 'Mejora el combate y la velocidad de la flota', + engineer: 'Mejora la energía y defensa', + geologist: 'Mejora la producción de recursos', + technocrat: 'Mejora la velocidad de investigación y espionaje', + darkMatterSpecialist: 'Mejora la eficiencia de recolección de materia oscura' + }, + queue: { + title: 'Tareas Activas', + empty: 'No hay colas activas', + buildQueueBonus: 'Cola de Construcción', + spaceBonus: 'Bono de Espacio', + buildSpeedBonus: 'Bono de Velocidad de Construcción', + researchSpeedBonus: 'Bono de Velocidad de Investigación', + researchQueueBonus: 'Cola de Investigación', + building: 'Construyendo', + researching: 'Investigando', + demolishing: 'Demoliendo', + remaining: 'Restante', + cancel: 'Cancelar', + cancelBuild: 'Cancelar Construcción', + cancelResearch: 'Cancelar Investigación', + confirmCancel: '¿Estás seguro de que quieres cancelar? Se reembolsará el 50% de los recursos.', + level: 'Nivel', + quantity: 'Cantidad', + upgradeToLevel: 'Mejorar a Nivel', + tabs: { + all: 'Todo', + buildings: 'Edificios', + research: 'Investigación', + ships: 'Naves', + defense: 'Defensa', + waiting: 'Esperando' + }, + waitingEmpty: 'No hay tareas en espera', + addToWaiting: 'Añadir a Cola de Espera', + remove: 'Remover', + resourcesReady: 'Listo', + waitingResources: 'Esperando', + waitingQueueFull: 'La cola de espera está llena', + movedToQueue: 'Tarea movida a la cola' + }, + overview: { + resourceOverview: 'Recursos', + fleetInfo: 'Flota', + currentShips: 'Naves en este planeta', + totalProduction: 'Producción Total', + totalConsumption: 'Consumo Total', + noConsumption: 'Sin consumo de energía', + tabOverview: 'Resumen', + tabProduction: 'Detalles de Producción', + tabConsumption: 'Detalles de Consumo' + }, + buildingsView: { + spaceUsage: 'Uso de Espacio', + upgradeCost: 'Costo de Mejora', + upgrade: 'Mejorar', + maxLevelReached: 'Nivel Máximo Alcanzado', + requirementsNotMet: 'Requisitos No Cumplidos', + upgradeFailed: 'Mejora Fallida', + upgradeFailedMessage: 'Por favor verifica si tienes suficientes recursos, espacio, o si hay otras tareas de construcción.', + demolish: 'Demoler', + demolishRefund: 'Reembolso de Demolición', + demolishFailed: 'Demolición Fallida', + demolishFailedMessage: + 'No se puede demoler este edificio. Por favor verifica si la cola de construcción está llena o si el nivel del edificio es 0.', + confirmDemolish: 'Confirmar Demolición' + }, + researchView: { + title: 'Investigación', + researchCost: 'Costo de Investigación', + research: 'Investigar', + maxLevelReached: 'Nivel Máximo Alcanzado', + researchFailed: 'Investigación Fallida', + researchFailedMessage: + 'Por favor verifica si tienes suficientes recursos, si se cumplen los prerrequisitos, o si hay otras tareas de investigación.' + }, + shipyard: { + missileAttack: 'Ataque de Misil', + speed: 'Velocidad', + cargoCapacity: 'Capacidad de Carga', + fuelConsumption: 'Consumo de Combustible' + }, + shipyardView: { + title: 'Astillero', + fleetStorage: 'Almacenamiento de Flota', + attack: 'Ataque', + missileAttack: 'Ataque de Misil', + shield: 'Escudo', + speed: 'Velocidad', + cargoCapacity: 'Capacidad de Carga', + unitCost: 'Costo por Unidad', + buildQuantity: 'Cantidad a Construir', + totalCost: 'Costo Total', + build: 'Construir', + inputError: 'Error de Entrada', + inputErrorMessage: '¡Por favor ingresa la cantidad a construir!', + buildFailed: 'Construcción Fallida', + buildFailedMessage: 'Por favor verifica si tienes suficientes recursos o si se cumplen los prerrequisitos.' + }, + defense: { + attack: 'Ataque', + missileAttack: 'Ataque de Misil', + shield: 'Escudo', + armor: 'Blindaje', + buildCost: 'Costo de Construcción', + buildTime: 'Tiempo de Construcción', + perUnit: 'Por Unidad', + batchCalculator: 'Calculadora de Lotes', + quantity: 'Cantidad', + totalCost: 'Costo Total', + totalTime: 'Tiempo Total' + }, + defenseView: { + title: 'Defensa', + attack: 'Ataque', + missileAttack: 'Ataque de Misil', + shield: 'Escudo', + armor: 'Blindaje', + buildTime: 'Tiempo de Construcción', + seconds: 's', + unitCost: 'Costo por Unidad', + buildQuantity: 'Cantidad a Construir', + totalCost: 'Costo Total', + build: 'Construir', + shieldDomeBuilt: 'Cúpula de escudo ya construida', + missileCapacity: 'Capacidad de Misiles', + inputError: 'Error de Entrada', + inputErrorMessage: '¡Por favor ingresa la cantidad a construir!', + buildFailed: 'Construcción Fallida', + buildFailedMessage: + 'Por favor verifica si tienes suficientes recursos o si se cumplen los prerrequisitos. Las cúpulas de escudo solo se pueden construir una vez.' + }, + fleetView: { + title: 'Gestión de Flota', + fleetOverview: 'Resumen de Flota', + sendFleet: 'Enviar Flota', + flightMissions: 'Misiones de Vuelo', + currentPlanetFleet: 'Flota del Planeta Actual', + attack: 'Ataque', + missileAttack: 'Ataque de Misil', + shield: 'Escudo', + armor: 'Blindaje', + speed: 'Velocidad', + cargo: 'Carga', + selectFleet: 'Seleccionar Flota', + selectFleetDescription: 'Selecciona el número de naves a enviar', + available: 'Disponible', + all: 'Todas', + targetCoordinates: 'Coordenadas de Destino', + targetType: 'Tipo de Destino', + planet: 'Planeta', + moon: 'Luna', + galaxy: 'Galaxia', + system: 'Sistema', + position: 'Posición', + missionType: 'Tipo de Misión', + missionInfo: 'Información de Misión', + fuelConsumption: 'Consumo de Combustible', + flightTime: 'Tiempo de Vuelo', + attackMission: 'Atacar', + transport: 'Transportar', + colonize: 'Colonizar', + spy: 'Espiar', + deploy: 'Desplegar', + expedition: 'Expedición', + expeditionZone: 'Zona de Expedición', + expeditionZoneDesc: 'Selecciona la zona de destino. Diferentes zonas tienen diferentes riesgos y recompensas', + requiresAstro: 'Requiere nivel de Astrofísica {level}', + reward: 'Recompensa', + danger: 'Peligro', + zones: { + nearSpace: { + name: 'Espacio Cercano', + desc: 'Área de espacio cercano segura, bajo riesgo pero menos recompensas' + }, + deepSpace: { + name: 'Espacio Profundo', + desc: 'Lejos de las estrellas, se pueden encontrar más recursos' + }, + unchartedSpace: { + name: 'Espacio Inexplorado', + desc: 'Área no explorada, alto riesgo alta recompensa' + }, + dangerousNebula: { + name: 'Nebulosa Peligrosa', + desc: 'Nebulosa llena de peligros desconocidos, pero contiene tesoros extremadamente ricos' + } + }, + recycle: 'Reciclar', + destroy: 'Destrucción Planetaria', + transportResources: 'Transportar Recursos', + totalCargoCapacity: 'Capacidad de Carga Total', + used: 'Usado', + noFlightMissions: 'No hay misiones de vuelo', + outbound: 'En Ruta', + returning: 'Regresando', + fleetComposition: 'Composición de Flota', + carryingResources: 'Transportando Recursos', + arrivalTime: 'Hora de Llegada', + returnTime: 'Hora de Regreso', + recallFleet: 'Recuperar Flota', + abortMission: 'Abortar Misión', + abortMissionTitle: 'Confirmar Abortar Misión', + abortMissionWarning: + 'ADVERTENCIA: ¡Abortar esta misión perderá permanentemente {ships} naves y {resources} recursos!\n\nEsta acción es irreversible y la flota y los recursos no regresarán.', + abortMissionSuccess: 'Misión Abortada', + abortMissionSuccessMessage: 'La misión ha sido abortada, la flota y los recursos se han perdido.', + sendFailed: 'Envío Fallido', + sendFailedMessage: 'Por favor verifica el número de naves, disponibilidad de combustible, o límites de capacidad de carga.', + recallFailed: 'Recuperación Fallida', + recallFailedMessage: 'Esta misión no puede ser recuperada.', + unknownPlanet: 'Planeta Desconocido', + fleetMissionSlots: 'Espacios de Misión de Flota', + noShipsSelected: 'No se han seleccionado naves', + cannotSendToOwnPlanet: 'No puedes enviar flota a tu propio planeta', + cargoExceedsCapacity: 'La carga excede la capacidad', + noColonyShip: 'Se requiere nave colonizadora para misión de colonización', + noDebrisAtTarget: 'No hay campo de escombros en las coordenadas de destino o el campo de escombros está vacío', + noDeathstar: 'Se requiere Estrella de la Muerte para misión de destrucción', + giftMode: 'Modo Regalo', + giftModeDescription: 'Enviar recursos como regalo a', + estimatedReputationGain: 'Ganancia de reputación estimada', + // Fleet presets + fleetPresets: 'Presets de Flota', + fleetPresetsDescription: 'Guarda configuraciones comunes de flota para envío rápido (máximo 3)', + savePreset: 'Guardar Preset', + noPresets: 'No hay presets aún, selecciona flota y haz clic en "Guardar Preset" para crear', + shipTypes: 'tipos de nave', + editPreset: 'Editar contenido del preset', + renamePreset: 'Renombrar', + deletePreset: 'Eliminar preset', + editingPresetHint: 'Editando preset, modifica la configuración de flota y haz clic en "Guardar" para actualizar', + presetLimitReached: 'Límite de presets alcanzado', + presetLimitReachedMessage: 'Se permiten máximo {max} presets', + presetError: 'Guardado fallido', + presetNoShips: 'Por favor selecciona al menos una nave primero', + presetDefaultName: 'Preset {number}', + savePresetTitle: 'Guardar Preset de Flota', + savePresetDescription: 'Nombra esta configuración de flota', + renamePresetTitle: 'Renombrar Preset', + renamePresetDescription: 'Ingresa un nuevo nombre de preset', + presetName: 'Nombre del Preset', + presetNamePlaceholder: 'Ingresa nombre del preset', + deletePresetTitle: 'Eliminar Preset', + deletePresetMessage: '¿Estás seguro de que quieres eliminar el preset "{name}"? Esta acción no se puede deshacer.', + // Jump Gate + jumpGate: 'Portal de Salto', + jumpGateDescription: 'Usa el Portal de Salto para transferir instantáneamente la flota a otra luna con Portal de Salto', + jumpGateNotAvailable: 'Portal de Salto No Disponible', + jumpGateRequiresMoon: 'El Portal de Salto solo se puede usar en lunas', + jumpGateNotBuilt: 'La luna actual no tiene un Portal de Salto', + jumpGateCooldown: 'Portal de Salto en Enfriamiento', + jumpGateCooldownRemaining: 'Enfriamiento Restante', + jumpGateReady: 'Portal de Salto Listo', + jumpGateSelectTarget: 'Seleccionar Luna de Destino', + jumpGateNoTargetMoons: 'No hay lunas de destino disponibles (requiere Portal de Salto y enfriamiento completo)', + jumpGateSelectFleet: 'Seleccionar Flota para Transferir', + jumpGateTransfer: 'Transferir Flota', + jumpGateSuccess: 'Transferencia de Portal de Salto Exitosa', + jumpGateSuccessMessage: 'La flota ha sido transferida instantáneamente a {target}', + jumpGateFailed: 'Transferencia de Portal de Salto Fallida', + jumpGateFailedMessage: 'Por favor verifica el estado del Portal de Salto y la configuración de flota' + }, + officersView: { + title: 'Oficiales', + activated: 'Activado', + inactive: 'Inactivo', + activeStatus: 'Estado Activo', + expirationTime: 'Tiempo de Expiración', + remainingTime: 'Tiempo Restante', + recruitCost: 'Costo de Reclutamiento', + days: 'días', + benefitsBonus: 'Bono de Beneficios', + resourceProduction: 'Producción de Recursos', + darkMatterProduction: 'Producción de Materia Oscura', + buildingSpeed: 'Velocidad de Construcción', + researchSpeed: 'Velocidad de Investigación', + fleetSpeed: 'Velocidad de Flota', + fuelConsumption: 'Consumo de Combustible', + defense: 'Defensa', + storageCapacity: 'Capacidad de Almacenamiento', + buildQueueBonus: 'Cola de Construcción', + spaceBonus: 'Bono de Espacio', + buildSpeedBonus: 'Bono de Velocidad de Construcción', + researchSpeedBonus: 'Bono de Velocidad de Investigación', + fleetSlots: 'Espacios de Flota', + buildQueue: 'Cola de Edificios', + hire: 'Contratar', + renew: 'Renovar', + dismiss: 'Despedir', + hireTitle: 'Contratar Oficial', + hireMessage: '¿Estás seguro de que quieres contratar a {name}? Válido por 7 días.', + renewTitle: 'Renovar Oficial', + renewMessage: '¿Estás seguro de que quieres renovar a {name} por 7 días?', + dismissTitle: 'Despedir Oficial', + dismissMessage: '¿Estás seguro de que quieres despedir a {name}? No se darán reembolsos.', + hireFailed: 'Contratación Fallida', + renewFailed: 'Renovación Fallida', + insufficientResources: '¡Recursos insuficientes!' + }, + galaxyView: { + selectCoordinates: 'Seleccionar Coordenadas', + galaxy: 'Galaxia', + selectGalaxy: 'Seleccionar Galaxia', + system: 'Sistema', + selectSystem: 'Seleccionar Sistema', + myPlanets: 'Ver Mis Sistemas', + npcPlanets: 'Planetas NPC', + selectPlanetToView: 'Selecciona planeta para ver su sistema', + totalPositions: '10 posiciones de planeta en total', + mine: 'Mío', + emptySlot: 'Vacío - Colonizable', + scout: 'Explorar', + attack: 'Atacar', + missileAttack: 'Ataque de Misil', + colonize: 'Colonizar', + switch: 'Cambiar', + recycle: 'Reciclar', + debrisField: 'Campo de Escombros', + oreDeposits: 'Depósitos de Mineral', + deposits: 'Depósitos', + scoutPlanetTitle: 'Explorar Planeta', + attackPlanetTitle: 'Atacar Planeta', + missileAttackTitle: 'Ataque de Misil', + colonizePlanetTitle: 'Colonizar Planeta', + recyclePlanetTitle: 'Reciclar Escombros', + scoutPlanetMessage: + '¿Estás seguro de que quieres enviar sondas de espionaje para explorar el planeta [{coordinates}]?\n\nPor favor ve a la página de flota para seleccionar naves y enviar.', + attackPlanetMessage: + '¿Estás seguro de que quieres atacar el planeta [{coordinates}]?\n\nPor favor ve a la página de flota para seleccionar naves y enviar.', + missileAttackMessage: 'Lanzar misiles interplanetarios para atacar el planeta [{coordinates}]', + missileCount: 'Cantidad de Misiles', + availableMissiles: 'Misiles Disponibles', + missileRange: 'Alcance de Misil', + systems: 'sistemas', + distance: 'Distancia', + flightTime: 'Tiempo de Vuelo', + outOfRange: 'Fuera de Alcance', + launchMissile: 'Lanzar', + cancel: 'Cancelar', + colonizePlanetMessage: + '¿Estás seguro de que quieres colonizar la posición [{coordinates}]?\n\nPor favor ve a la página de flota para enviar una nave colonizadora.', + recyclePlanetMessage: + '¿Estás seguro de que quieres reciclar escombros en la posición [{coordinates}]?\n\nPor favor ve a la página de flota para enviar naves recicladoras.', + sendGift: 'Enviar Regalo', + debris: 'Escombros', + giftPlanetTitle: 'Enviar Regalo', + giftPlanetMessage: + '¿Estás seguro de que quieres enviar recursos como regalo al planeta [{coordinates}]?\n\nPor favor ve a la página de flota para seleccionar naves de transporte y cargar recursos.', + npcPlanetName: 'Planeta de {name}', + // Sensor Phalanx Scan + phalanxScan: 'Escaneo de Falange', + phalanxScanTitle: 'Escaneo de Falange de Sensores', + phalanxScanDescription: 'Escaneando actividad de flota en el planeta [{coordinates}]', + phalanxNoMoon: 'Requiere una luna con Falange de Sensores para escanear', + phalanxCost: 'Costo de Escaneo', + phalanxNoFleets: 'No se detectó actividad de flota', + phalanxFleetDetected: '{count} flota(s) detectada(s)', + phalanxOrigin: 'Origen', + phalanxDestination: 'Destino', + phalanxArrival: 'Llegada', + phalanxReturn: 'Regreso', + phalanxStatusOutbound: 'En Ruta', + phalanxStatusReturning: 'Regresando', + phalanxInsufficientDeuterium: 'Deuterio Insuficiente', + intercepted: 'Interceptado', + defenseLosses: 'Pérdidas de Defensa', + missileLaunched: 'Misil lanzado' + }, + messagesView: { + title: 'Mensajes', + battles: 'Batallas', + spy: 'Espionaje', + npc: 'NPC', + diplomacy: 'Diplomacia', + battleReports: 'Reportes de Batalla', + spyReports: 'Reportes de Espionaje', + noBattleReports: 'No hay reportes de batalla', + noSpyReports: 'No hay reportes de espionaje', + noDiplomaticReports: 'No hay reportes diplomáticos', + battleReport: 'Reporte de Batalla', + spyReport: 'Reporte de Espionaje', + victory: 'Victoria', + defeat: 'Derrota', + draw: 'Empate', + attackerFleet: 'Flota Atacante', + defenderFleet: 'Flota Defensora', + defenderDefense: 'Defensa del Defensor', + attackerLosses: 'Pérdidas del Atacante', + defenderLosses: 'Pérdidas del Defensor', + noLosses: 'Sin pérdidas', + losses: 'Pérdidas', + remainingUnits: 'Unidades Restantes', + plunder: 'Botín', + debrisField: 'Campo de Escombros', + resources: 'Recursos', + fleet: 'Flota', + defense: 'Defensa', + buildings: 'Edificios', + unread: 'No leído', + pending: 'Pendiente', + invalidData: 'Datos Inválidos', + targetPlanet: 'Planeta Objetivo', + attackerRemaining: 'Atacante Restante', + defenderRemaining: 'Defensor Restante', + allDestroyed: 'Todo destruido', + moonChance: 'Probabilidad de generación de luna', + showRoundDetails: 'Mostrar detalles de ronda', + hideRoundDetails: 'Ocultar detalles de ronda', + round: 'Ronda {round}', + attackerRemainingPower: 'Potencia de fuego restante del atacante', + defenderRemainingPower: 'Potencia de fuego restante del defensor', + playAnimation: 'Reproducir animación', + showDetails: 'Mostrar detalles', + speed: 'Velocidad', + power: 'Poder de combate', + battleLogEmpty: 'Registro de batalla vacío', + roundStarted: 'Ronda {round} iniciada', + shipDestroyed: '{count} {ship} destruidos', + defenseDestroyed: '{count} {defense} destruidos', + attackerWins: 'El atacante gana', + defenderWins: 'El defensor gana', + roundsPlayed: 'Rondas reproducidas', + spied: 'Espiado', + spiedNotification: 'Notificación de Espionaje', + noSpiedNotifications: 'No hay notificaciones de espionaje', + detected: 'Detectado', + undetected: 'No detectado', + missions: 'Misiones', + noMissionReports: 'No hay reportes de misión', + success: 'Éxito', + failed: 'Fallido', + npcActivity: 'Actividad NPC', + noNPCActivity: 'No hay notificaciones de actividad NPC', + npcRecycleActivity: 'NPC Reciclando Escombros', + gifts: 'Regalos', + giftRejected: 'Rechazado', + noGiftNotifications: 'No hay notificaciones de regalos', + noGiftRejected: 'No hay regalos rechazados', + giftFrom: 'Regalo de {npcName}', + giftRejectedBy: '{npcName} rechazó el regalo', + giftResources: 'Recursos de regalo', + rejectedResources: 'Recursos rechazados', + expectedReputation: 'Reputación esperada', + currentReputation: 'Reputación actual', + acceptGift: 'Aceptar', + rejectGift: 'Rechazar', + rejectionReason: { + hostile: 'Son hostiles hacia ti y no aceptan regalos', + neutral_distrust: 'Les falta confianza en ti', + polite_decline: 'Declinaron cortésmente' + }, + // Spied notification dialog + spiedNotificationDetails: 'Detalles de Notificación de Espionaje', + spyDetected: 'Espía Detectado', + detectionResult: 'Resultado de Detección', + detectionSuccess: '¡Detectaste al espía enemigo!', + spiedNotificationMessage: '{npc} intentó espiar tu planeta {planet}', + spiedNotificationTip: 'Considera aumentar tu defensa o contraatacar si este NPC es hostil', + viewInGalaxy: 'Ver en Galaxia', + // Mission report dialog + missionReportDetails: 'Detalles del Reporte de Misión', + missionSuccess: 'Éxito', + missionFailed: 'Fallido', + origin: 'Origen', + destination: 'Destino', + missionDetails: 'Detalles de Misión', + transportedResources: 'Recursos Transportados', + recycledResources: 'Recursos Reciclados', + remainingDebris: 'Escombros Restantes', + newPlanet: 'Nuevo Planeta', + // NPC activity dialog + npcActivityDetails: 'Detalles de Actividad NPC', + activityType: { + recycle: 'Reciclando Escombros' + }, + activityLocation: 'Ubicación de Actividad', + position: 'Posición', + nearPlanet: 'Cerca del Planeta', + activityDescription: 'Descripción de Actividad', + npcActivityMessage: '{npc} está {activity} en {position}', + arrivalTime: 'Hora de Llegada', + npcActivityTip: + 'Los NPCs pueden recolectar escombros de batallas. Puedes intentar llegar primero a la ubicación si quieres competir por los recursos', + // Clear messages + clearMessages: 'Limpiar Mensajes', + clearMessageTypes: 'Selecciona tipos de mensaje a limpiar', + clearBattleReports: 'Reportes de Batalla', + clearSpyReports: 'Reportes de Espionaje', + clearSpiedNotifications: 'Notificaciones de Espionaje', + clearMissionReports: 'Reportes de Misión', + clearNPCActivity: 'Actividad NPC', + clearGiftNotifications: 'Notificaciones de Regalos', + clearGiftRejected: 'Regalos Rechazados', + clearTradeOffers: 'Ofertas de Comercio', + clearIntelReports: 'Reportes de Inteligencia', + clearJointAttackInvites: 'Invitaciones de Ataque Conjunto', + clearNow: 'Limpiar Ahora', + clearSuccess: 'Mensajes limpiados' + }, + missionReports: { + transportSuccess: 'Misión de transporte completada exitosamente', + transportFailed: 'Misión de transporte fallida', + transportFailedTargetNotFound: 'Transporte fallido: El planeta objetivo no existe', + transportFailedGiftRejected: 'Transporte fallido: El regalo fue rechazado', + colonizeSuccess: 'Misión de colonización exitosa, nuevo planeta establecido', + colonizeFailed: 'Misión de colonización fallida', + colonizeFailedOccupied: 'Colonización fallida: La posición objetivo ya está ocupada por otro planeta', + colonizeFailedMaxColonies: 'Colonización fallida: Número máximo de colonias alcanzado. Investiga Astrofísica para aumentar el límite.', + spySuccess: 'Misión de espionaje completada exitosamente', + spyFailed: 'Misión de espionaje fallida', + spyFailedTargetNotFound: 'Espionaje fallido: El planeta objetivo no existe', + deploySuccess: 'Misión de despliegue completada exitosamente', + deployFailed: 'Misión de despliegue fallida', + deployFailedTargetNotFound: 'Despliegue fallido: El planeta objetivo no existe', + deployFailedNotOwnPlanet: 'Despliegue fallido: El planeta objetivo no te pertenece', + recycleSuccess: 'Misión de reciclaje completada exitosamente', + recycleFailed: 'Misión de reciclaje fallida, no hay escombros en la ubicación objetivo', + recycleFailedNoDebris: 'Reciclaje fallido: No hay campo de escombros en la ubicación objetivo', + recycleFailedDebrisEmpty: 'Reciclaje fallido: El campo de escombros ha sido limpiado', + destroySuccess: 'Misión de destrucción planetaria ejecutada exitosamente', + destroyFailed: 'Misión de destrucción planetaria fallida', + destroyFailedTargetNotFound: 'Destrucción fallida: El planeta objetivo no existe', + destroyFailedOwnPlanet: 'Destrucción fallida: No puedes destruir tu propio planeta', + destroyFailedNoDeathstar: 'Destrucción fallida: No hay Estrella de la Muerte para ejecutar la misión', + destroyFailedChance: 'Destrucción fallida: Verificación de probabilidad fallida (Tasa de éxito: {chance}%)', + missileAttackSuccess: 'Ataque de misil exitoso', + missileAttackFailed: 'Ataque de misil fallido, el planeta objetivo no existe', + missileAttackIntercepted: 'Todos los misiles interceptados', + hits: 'impactos', + expeditionResources: '¡La expedición encontró recursos!', + expeditionDarkMatter: '¡La expedición encontró materia oscura!', + expeditionFleet: '¡La expedición encontró naves abandonadas!', + expeditionPiratesAttack: 'La expedición fue atacada por piratas y perdió algunas naves', + expeditionPiratesEscaped: 'La expedición se encontró con piratas pero escapó exitosamente', + expeditionAliensAttack: 'La expedición fue atacada por alienígenas y perdió algunas naves', + expeditionAliensEscaped: 'La expedición se encontró con alienígenas pero escapó exitosamente', + expeditionNothing: 'La expedición no encontró nada' + }, + simulatorView: { + title: 'Simulador de Batalla', + attacker: 'Atacante', + defender: 'Defensor', + attackerConfig: 'Configuración del Atacante', + attackerConfigDesc: 'Configura flota del atacante y niveles de tecnología', + defenderConfig: 'Configuración del Defensor', + defenderConfigDesc: 'Configura flota del defensor, defensa, y niveles de tecnología', + fleet: 'Flota', + defenseStructures: 'Estructuras de Defensa', + techLevels: 'Niveles de Tecnología', + weapon: 'Arma', + shield: 'Escudo', + armor: 'Blindaje', + defenderResources: 'Recursos del Defensor (para cálculo de botín)', + startSimulation: 'Iniciar Simulación', + reset: 'Reiniciar', + battleResult: 'Resultado de Batalla', + attackerVictory: 'Victoria del Atacante', + defenderVictory: 'Victoria del Defensor', + draw: 'Empate', + afterRounds: 'Después de {rounds} rondas', + attackerLosses: 'Pérdidas del Atacante', + defenderLosses: 'Pérdidas del Defensor', + noLosses: 'Sin pérdidas', + attackerRemaining: 'Atacante Restante', + defenderRemaining: 'Defensor Restante', + allDestroyed: 'Todo destruido', + plunderableResources: 'Recursos Saqueables', + debrisField: 'Campo de Escombros', + moonChance: 'Probabilidad de luna', + showRoundDetails: 'Mostrar detalles de rondas', + hideRoundDetails: 'Ocultar detalles de rondas', + round: 'Ronda {round}', + attackerRemainingPower: 'Poder restante del atacante', + defenderRemainingPower: 'Poder restante del defensor', + // Battle animation + playAnimation: 'Reproducir Animación', + showDetails: 'Mostrar Detalles', + speed: 'Velocidad', + power: 'Poder', + battleLogEmpty: 'El registro de batalla está vacío', + roundStarted: 'Ronda {round} iniciada', + shipDestroyed: '{count} {ship} destruido(s)', + defenseDestroyed: '{count} {defense} destruido(s)', + attackerWins: 'El Atacante Gana', + defenderWins: 'El Defensor Gana', + roundsPlayed: 'rondas jugadas', + spied: 'Espiado', + spiedNotification: 'Notificación de Espionaje', + noSpiedNotifications: 'No hay notificaciones de espionaje', + detected: 'Detectado', + undetected: 'No detectado' + }, + settings: { + dataManagement: 'Gestión de Datos', + dataManagementDesc: 'Exportar, importar o limpiar datos del juego', + exportData: 'Exportar Datos', + exportDataDesc: 'Exportar progreso del juego como archivo JSON', + export: 'Exportar', + exporting: 'Exportando...', + exportSuccess: 'Exportación exitosa', + exportSuccessWithPath: 'Exportación exitosa, archivo guardado en: {path}', + exportFailed: 'Exportación fallida, por favor intenta de nuevo', + importData: 'Importar Datos', + importDataDesc: 'Restaurar progreso del juego desde archivo JSON', + selectFile: 'Seleccionar Archivo', + importSuccess: 'Importación exitosa', + importConfirmTitle: 'Confirmar Importación', + importConfirmMessage: 'Importar sobrescribirá el progreso actual del juego. Esta acción no se puede deshacer. ¿Continuar?', + importFailed: 'Importación fallida, por favor verifica el formato del archivo', + clearData: 'Limpiar Datos', + clearDataDesc: 'Eliminar todos los datos del juego y reiniciar', + clear: 'Limpiar', + clearConfirmTitle: 'Confirmar Limpiar Datos', + clearConfirmMessage: 'Esto eliminará todos los datos del juego y empezará de nuevo. Esta acción no se puede deshacer. ¿Continuar?', + gameSettings: 'Configuración del Juego', + 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', + pause: 'Pausar', + resume: 'Reanudar', + gamePaused: 'Juego pausado', + gameResumed: 'Juego reanudado', + gameSpeed: 'Velocidad de Producción de Recursos', + gameSpeedDesc: 'Multiplicador actual de velocidad de producción de recursos', + speedChanged: 'Velocidad de producción de recursos cambiada a {speed}x', + speedReset: 'Velocidad de producción de recursos reiniciada a 1x', + reset: 'Reiniciar', + about: 'Acerca de', + version: 'Versión', + checkUpdate: 'Verificar Actualización', + checking: 'Verificando...', + newVersionAvailable: 'Nueva versión {version} disponible', + upToDate: 'Ya está actualizado', + checkUpdateFailed: 'Falló la verificación de actualizaciones, por favor verifica tu conexión de red', + viewUpdate: 'Ver Actualización', + updateAvailable: 'Una nueva versión está disponible. Haz clic para ver las notas de la versión.', + download: 'Descargar', + buildDate: 'Fecha de Compilación', + community: 'Comunidad', + github: 'Repositorio GitHub', + qqGroup: 'Grupo QQ', + privacyPolicy: 'Política de Privacidad', + displaySettings: 'Configuración de Pantalla', + displaySettingsDesc: 'Ajustar efectos visuales', + backgroundAnimation: 'Animación de Fondo', + backgroundAnimationDesc: 'Mostrar animación de fondo de campo estelar/partículas (puede afectar el rendimiento)', + notifications: 'Configuración de Notificaciones', + notificationsDesc: 'Gestionar alertas de notificación en el juego', + notificationTypes: 'Tipos de Notificación', + browserNotifications: 'Notificaciones del Navegador', + inAppNotifications: 'Notificaciones en la Aplicación', + constructionComplete: 'Construcción Completa', + researchComplete: 'Investigación Completa', + unlockNotification: 'Notificación de Desbloqueo', + browserPermission: 'Habilitar Notificaciones del Navegador', + permissionGranted: 'Permiso Concedido', + permissionDenied: 'Permiso Denegado/No Concedido', + inAppNotificationsDesc: 'Mostrar mediante ventanas emergentes en la página', + notificationsDisabled: 'Habilita cualquier interruptor arriba para configurar notificaciones específicas', + suppressInFocus: 'Suprimir notificaciones del navegador cuando la página está enfocada', + expandTypes: 'Expandir Detalles', + collapseTypes: 'Contraer Detalles', + // NPC name update + npcNameUpdateTitle: 'Nombres NPC Antiguos Detectados', + npcNameUpdateMessage: + 'Se encontraron {count} NPCs usando formato de nombre antiguo. ¿Te gustaría actualizarlos a nuevos nombres localizados?', + npcNameUpdateConfirm: 'Actualizar Nombres', + npcNameUpdateCancel: 'Mantener Actual', + npcNameUpdateSuccess: 'Se actualizaron exitosamente {count} nombres NPC', + npcNameUpdateSkipped: 'Actualización de nombres NPC omitida', + // WebDAV + webdav: { + title: 'Sincronización en la Nube', + desc: 'Sincronizar guardados mediante WebDAV', + config: 'Configurar', + configTitle: 'Configuración WebDAV', + configDesc: 'Configure su servidor WebDAV para sincronización en la nube', + notConfigured: 'Por favor configure primero el servidor WebDAV', + serverUrl: 'URL del Servidor', + serverUrlPlaceholder: 'ej. https://dav.example.com', + serverUrlHint: 'Ingrese la dirección de su servidor WebDAV', + username: 'Usuario', + usernamePlaceholder: 'Ingrese usuario', + password: 'Contraseña', + passwordPlaceholder: 'Ingrese contraseña', + passwordHint: 'La contraseña solo se almacena localmente', + basePath: 'Ruta de Guardados', + basePathPlaceholder: 'ej. /ogame-saves/', + testConnection: 'Probar Conexión', + testing: 'Probando...', + testSuccess: 'Conexión exitosa', + testFailed: 'Conexión fallida', + save: 'Guardar', + clearConfig: 'Limpiar', + configSaved: 'Configuración guardada', + configCleared: 'Configuración eliminada', + upload: 'Subir', + uploading: 'Subiendo...', + uploadSuccess: 'Subida exitosa', + uploadFailed: 'Subida fallida', + download: 'Descargar', + downloadSuccess: 'Descarga exitosa', + downloadFailed: 'Descarga fallida', + selectFile: 'Seleccionar Guardado', + selectFileDesc: 'Elige un archivo de guardado para restaurar', + noFiles: 'No se encontraron archivos de guardado', + loadFailed: 'Error al cargar lista de archivos', + confirmDelete: '¿Estás seguro de eliminar "{name}"?', + deleteSuccess: 'Archivo eliminado', + deleteFailed: 'Error al eliminar' + } + }, + notifications: { + constructionComplete: 'Construcción Completa', + researchComplete: 'Investigación Completa', + newUnlock: 'Nuevo Contenido Desbloqueado', + building: 'Edificio', + technology: 'Tecnología' + }, + gmView: { + title: 'Panel de Control GM', + adminOnly: 'Solo Administrador', + selectPlanet: 'Seleccionar Planeta', + choosePlanet: 'Elige un planeta', + resources: 'Recursos', + buildings: 'Edificios', + research: 'Investigación', + ships: 'Naves', + defense: 'Defensa', + officers: 'Oficiales', + modifyResources: 'Modificar Recursos', + resourcesDesc: 'Modificar rápidamente los recursos del planeta', + maxAllResources: 'Maximizar Todos', + maxAllResourcesSuccess: 'Todos los recursos maximizados', + modifyBuildings: 'Modificar Edificios', + buildingsDesc: 'Establecer rápidamente niveles de edificios', + modifyResearch: 'Modificar Investigación', + researchDesc: 'Establecer rápidamente niveles de investigación', + modifyShips: 'Modificar Naves', + shipsDesc: 'Establecer rápidamente cantidades de naves', + modifyDefense: 'Modificar Defensa', + defenseDesc: 'Establecer rápidamente cantidades de defensa', + modifyOfficers: 'Modificar Oficiales', + officersDesc: 'Establecer rápidamente tiempo de expiración de oficiales', + days: 'd', + npcTesting: 'Pruebas NPC', + npcTestingDesc: 'Probar comportamiento de espionaje y ataque NPC', + selectNPC: 'Seleccionar NPC', + chooseNPC: 'Elige un NPC', + targetPlanet: 'Planeta Objetivo', + chooseTarget: 'Elige planeta objetivo', + testSpy: 'Probar Espionaje', + testAttack: 'Probar Ataque', + testSpyAndAttack: 'Probar Espionaje y Ataque', + testSpyMessage: 'Haz clic en confirmar para acelerar la misión de espionaje', + testAttackMessage: 'Haz clic en confirmar para acelerar la misión de ataque', + testSpyAndAttackMessage: 'Haz clic en confirmar para acelerar las misiones', + initializeFleet: 'Inicializar Flota NPC', + accelerateMissions: 'Acelerar Todas las Misiones (5s)', + selectNPCFirst: 'Por favor selecciona un NPC primero', + npcNoProbes: 'El NPC no tiene sondas de espionaje', + npcNoSpyReport: 'El NPC necesita espiar primero', + npcMissionFailed: 'Falló la creación de la misión', + npcNoPlanets: 'El NPC no tiene planetas', + npcWillSpyIn5s: '{npcName} espiará en 5 segundos', + npcWillAttackIn5s: '{npcName} atacará en 5 segundos', + npcWillSpyAndAttack: '{npcName} espiará en 5s y atacará en 10s', + acceleratedMissions: '{count} misiones aceleradas a 5 segundos', + npcFleetInitialized: 'Flota de {npcName} inicializada', + npcFleetDetails: + '100 Sondas de Espionaje\n500 Cazas Ligeros\n300 Cazas Pesados\n200 Cruceros\n100 Naves de Batalla\n50 Bombarderos\n30 Destructores\n20 Cruceros de Batalla', + dangerZone: 'Zona de Peligro', + dangerZoneDesc: 'Las siguientes operaciones son irreversibles', + resetGame: 'Reiniciar Juego', + resetGameConfirm: '¿Estás seguro de que quieres reiniciar el juego? ¡Esto eliminará todos los datos!', + completeAllQueues: 'Completar Todas las Colas', + completeAllQueuesDesc: 'Completar instantáneamente todas las colas de edificios, investigación, naves, defensa y misiones de flota', + completeQueues: 'Completar Colas', + completeQueuesSuccess: + 'Completadas {buildingCount} colas de edificios, {researchCount} colas de investigación, {missionCount} misiones de flota, {missileCount} ataques de misiles' + }, + alerts: { + incomingFleets: '{count} Flotas Enemigas Entrantes', + npcSpyIncoming: 'Sonda de Espionaje NPC Entrante', + npcAttackIncoming: '¡Ataque de Flota NPC Entrante!', + npcFleetIncoming: 'Flota NPC Acercándose', + ships: 'naves', + spiedBy: 'Espiado Por', + attackedBy: 'Atacado Por', + detectionSuccess: 'Espía detectado', + detectionFailed: 'Espía no detectado', + npcSpiedYourPlanet: 'NPC espió tu planeta', + npcAttackedYourPlanet: 'NPC atacó tu planeta' + }, + enemyAlert: { + title: 'Alerta de Enemigo', + markAllRead: 'Marcar Todos como Leídos', + noAlerts: 'No hay alertas', + fleetSize: 'Tamaño de Flota', + ships: 'naves', + viewFleet: 'Ver Flota', + alertDetails: 'Detalles de Alerta', + targetInfo: 'Información del Objetivo', + arrivalTime: 'Hora de Llegada', + countdown: 'Cuenta Regresiva', + viewMessages: 'Ver Mensajes', + arrived: 'Llegó', + missionType: { + spy: 'Espionaje', + attack: 'Ataque', + recycle: 'Reciclaje', + unknown: 'Desconocido' + }, + warning: { + spy: '¡Espía enemigo entrante!', + attack: '¡Ataque enemigo entrante!', + recycle: '¡El enemigo está reciclando escombros cerca de ti!', + unknown: '¡Flota enemiga entrante!' + } + }, + diplomacy: { + title: 'Diplomacia', + description: 'Gestionar relaciones diplomáticas con NPCs', + tabs: { + all: 'Todos', + friendly: 'Amigables', + neutral: 'Neutrales', + hostile: 'Hostiles' + }, + noNpcs: 'Sin NPCs', + noFriendlyNpcs: 'Sin NPCs amigables', + noNeutralNpcs: 'Sin NPCs neutrales', + noHostileNpcs: 'Sin NPCs hostiles', + ago: 'hace', + notifications: 'Notificaciones Diplomáticas', + markAllRead: 'Marcar Todas como Leídas', + noReports: 'Sin eventos diplomáticos', + viewAll: 'Ver Todas', + status: { + friendly: 'Amigable', + neutral: 'Neutral', + hostile: 'Hostil' + }, + planets: 'planetas', + allies: 'aliados', + reputation: 'Reputación', + alliedWith: 'Aliado con', + more: 'más', + actions: { + gift: 'Enviar Regalo', + viewPlanets: 'Ver Planetas', + addNote: 'Agregar Nota', + editNote: 'Editar Nota' + }, + note: 'Nota', + notePlaceholder: 'Ingresar nota...', + lastEvent: 'Último Evento', + reportDetails: 'Detalles del Reporte Diplomático', + eventDescription: 'Descripción del Evento', + reputationChange: 'Cambio de Reputación', + before: 'Antes', + after: 'Después', + statusChange: 'Cambio de Estado', + viewDiplomacy: 'Ver Página de Diplomacia', + eventType: { + gift: 'Envió recursos', + attack: 'Lanzó un ataque', + allyAttacked: 'Atacó a un aliado', + spy: 'Realizó espionaje', + stealDebris: 'Robó escombros', + destroyPlanet: 'Destruyó un planeta', + unknown: 'Evento desconocido' + }, + events: { + gift: 'Regalo Enviado', + attack: 'Ataque', + missileAttack: 'Ataque de Misil', + allyAttacked: 'Aliado Atacado', + spy: 'Espionaje', + stealDebris: 'Escombros Robados' + }, + reports: { + giftedResources: 'Regaló {metal}M {crystal}C {deuterium}D', + receivedGiftFromPlayer: 'Recibió regalo del jugador', + giftedToNpc: 'Regalaste recursos a {npcName}. Reputación +{reputation}', + rejectedPlayerGift: 'Rechazó el regalo del jugador', + npcRejectedGift: '{npcName} rechazó tu regalo. Reputación {reputation}', + attackedNpc: 'Atacó a {npcName}', + wasAttackedByPlayer: 'Fue atacado por el jugador', + youAttackedNpc: 'Atacaste a {npcName}', + playerAttackedAlly: 'El jugador atacó al aliado {allyName}', + allyDispleased: '{allyName} está disgustado de que atacaras a su aliado {targetName}', + wasSpiedByPlayer: 'Fue espiado por el jugador (detectado: {detected})', + spyDetected: 'Tu espionaje fue detectado por {npcName}', + stoleDebrisFromTerritory: 'Robó escombros del territorio de {npcName}', + playerStoleDebris: 'El jugador robó escombros del territorio', + recycledDebrisNearNpc: 'Reciclaste escombros cerca del planeta de {npcName}. Están disgustados.', + giftedResourcesToPlayer: 'Regaló recursos al jugador', + receivedGiftFromNpc: 'Recibiste un regalo de {npcName}', + acceptedGiftFromNpc: 'Aceptaste un regalo de {npcName}: {metal}M {crystal}C {deuterium}D', + playerRejectedGift: 'El jugador rechazó el regalo', + rejectedGiftFromNpc: 'Rechazaste un regalo de {npcName}. Reputación {reputation}', + destroyedNpcPlanet: 'Destruyó {planetName} de {npcName}', + playerDestroyedPlanet: 'El jugador destruyó {planetName}', + youDestroyedNpcPlanet: 'Destruiste {planetName} de {npcName}. Reputación {reputation}', + playerDestroyedAllyPlanet: 'El jugador destruyó {planetName} del aliado {allyName}', + allyOutraged: '{allyName} está indignado de que destruyeras {planetName} de su aliado {targetName}', + npcEliminated: 'NPC {npcName} ha sido completamente eliminado', + npcEliminatedMessage: '¡Destruiste todos los planetas de {npcName}! Esta facción ha sido completamente eliminada.' + }, + searchPlaceholder: 'Buscar nombre de NPC...', + // Notification types + notificationType: { + tradeOffer: 'Oferta Comercial', + intelReport: 'Reporte de Inteligencia', + jointAttack: 'Invitación de Ataque Conjunto' + }, + // Notification badges + notificationBadge: { + trade: 'Comercio', + intel: 'Inteligencia', + jointAttack: 'Invitación' + }, + // Notification extra info + notificationExtra: { + pending: 'Pendiente' + }, + viewMode: { + card: 'Tarjeta', + list: 'Lista' + }, + diagnostic: { + button: 'Diagnóstico de NPC', + title: 'Diagnóstico de Estado de NPC', + description: + 'Puntos del jugador: {points}, Intervalo de espionaje: {spyInterval}min, Intervalo de ataque: {attackInterval}min, Probabilidad de ataque: {attackProb}%', + noData: 'Sin datos de NPC', + difficulty: 'Dificultad', + difficultyLevels: { + easy: 'Fácil', + medium: 'Medio', + hard: 'Difícil' + }, + reputation: 'Reputación', + spyProbes: 'Sondas de Espionaje', + fleetPower: 'Poder de Flota', + canSpy: 'Puede Espiar', + canAttack: 'Puede Atacar', + attackProbability: 'Probabilidad de Ataque', + nextSpy: 'Próximo Espionaje', + nextAttack: 'Próximo Ataque', + yes: 'Sí', + no: 'No', + timeFormat: '{min}m {sec}s', + anytime: 'En cualquier momento', + statusExplanation: 'Explicación de Estado', + noRelation: 'Sin Relación', + noRelationNeutral: 'Sin Relación (Neutral)', + reasons: { + friendlyNoAction: 'Relación amigable, no actuará', + neutralNoAction: 'Relación neutral, no actuará', + hostileWillAct: 'Relación hostil, puede tomar acción', + noRelationNeutral: 'Sin relación diplomática, tratado como neutral', + insufficientProbes: 'Sondas insuficientes (Actual: {current}, Requerido: {required})', + noFleet: 'Sin flota de combate', + spyCooldown: 'Espionaje en espera ({min}m {sec}s)', + attackCooldown: 'Ataque en espera ({min}m {sec}s)', + notSpiedYet: 'Aún no espiado, necesita espiar primero' + }, + aiType: 'Tipo de IA', + aiTypes: { + aggressive: 'Agresivo', + defensive: 'Defensivo', + trader: 'Comerciante', + expansionist: 'Expansionista', + balanced: 'Equilibrado' + }, + aiTypeDescriptions: { + aggressive: 'Espía y ataca activamente, fuerte represalia', + defensive: 'Rara vez ataca, fuerte represalia cuando es atacado', + trader: 'Casi nunca ataca, prefiere comerciar y dar regalos', + expansionist: 'Se enfoca en el desarrollo, menos agresivo', + balanced: 'Ajusta dinámicamente la estrategia según la situación' + } + } + }, + pagination: { + previous: 'Previous', + next: 'Next', + first: 'First', + last: 'Last', + page: 'Page {page}' + }, + notFound: { + title: 'Page Not Found', + description: 'Sorry, the page you are looking for does not exist', + goHome: 'Go Home' + }, + privacy: { + title: 'Privacy Policy', + sections: { + introduction: { + title: 'Introduction', + content: + 'This privacy policy explains how OGame-Vue-Ts handles your data. We are committed to protecting your privacy, and this game is designed with complete respect for user privacy.' + }, + dataCollection: { + title: 'Data Collection', + content: 'This game only collects and stores the following data locally in your browser:', + items: { + gameProgress: 'Game progress (building levels, fleets, resources, etc.)', + settings: 'Game settings (notification preferences, display options, etc.)', + language: 'Language preference' + } + }, + dataStorage: { + title: 'Data Storage', + content: + "All data is stored in your browser's local storage (localStorage). This means your data always remains on your own device, and we cannot access, view, or collect any of your game data." + }, + noServer: { + title: 'No Server Communication', + content: + 'This game is a completely offline single-player game. Except for the update check feature (which fetches version information from GitHub), the game does not communicate with any server. Your game data never leaves your device.' + }, + thirdParty: { + title: 'Third-Party Services', + content: + 'This game uses third-party analytics services to track visitor statistics and traffic sources, helping us understand usage patterns and improve the gaming experience. This analytics data is anonymous and does not contain any personally identifiable information. We do not use any advertising services or other commercial tracking tools.' + }, + dataControl: { + title: 'Data Control', + content: 'You have complete control over your data:', + items: { + export: 'You can export your game data at any time', + import: 'You can import data from backup files', + delete: 'You can delete all data by clearing browser data or using the in-game "Clear Data" feature' + } + }, + contact: { + title: 'Contact Us', + content: 'If you have any questions about this privacy policy, please contact us via:' + } + } + }, + time: { + days: 'días', + hours: 'horas', + minutes: 'minutos', + seconds: 'segundos' + }, + tutorial: { + progress: 'Progreso', + previous: 'Anterior', + next: 'Siguiente', + gotIt: 'Entendido', + completeButton: 'Completar', + skip: 'Saltar Tutorial', + welcome: { + title: 'Bienvenido a OGame', + content: + '¡Bienvenido, Comandante! Este tutorial te guiará a través de los conceptos básicos para construir tu imperio. Haz clic en "Siguiente" para comenzar tu aventura.' + }, + resources: { + title: 'Resumen de Recursos', + content: + 'Estos son tus recursos: Metal, Cristal y Deuterio. Son esenciales para construir estructuras e investigar tecnologías. La energía también es importante para alimentar tu infraestructura.' + }, + planet: { + title: 'Tu Planeta', + content: 'Este es tu planeta natal. Aquí puedes ver su nombre, coordenadas y cambiar entre planetas a medida que expandes tu imperio.' + }, + navigation: { + title: 'Menú de Navegación', + content: + 'Usa este menú para navegar entre diferentes secciones: Edificios, Investigación, Flota, Galaxia y más. Cada sección ofrece características de juego únicas.' + }, + gotoBuildings: { + title: 'Ir a Edificios', + content: + 'Comencemos construyendo algunas estructuras. Haz clic en el elemento de menú "Edificios" para ver las estructuras disponibles.' + }, + buildSolarPlant: { + title: 'Construir Planta Solar', + content: + '¡Primero, construye una Planta Solar! Genera energía para tu planeta. Sin energía, otros edificios de recursos no pueden funcionar. Este es el primer paso más importante.' + }, + waitBuild: { + title: 'Cola de Construcción', + content: + 'Tu edificio está ahora en la cola de construcción. Haz clic en el ícono de la cola en la esquina superior derecha para ver todas las tareas de construcción e investigación en curso. Los edificios tardan tiempo en completarse, pero puedes seguir trabajando mientras esperas.' + }, + buildMetalMine: { + title: 'Construir Mina de Metal', + content: + 'Ahora que tienes energía, puedes construir la Mina de Metal. Es tu fuente principal de metal, que se usa en casi todas las estructuras y naves.' + }, + buildCrystalMine: { + title: 'Construir Mina de Cristal', + content: + 'El cristal es más escaso pero esencial para tecnologías avanzadas. Construye una Mina de Cristal para comenzar a recolectar este valioso recurso.' + }, + buildDeuterium: { + title: 'Construir Sintetizador de Deuterio', + content: + 'El deuterio es esencial para el combustible de las naves y la investigación avanzada. Construye un Sintetizador de Deuterio para comenzar a producir este recurso crítico.' + }, + upgradeMines: { + title: 'Mejorar Minas de Recursos', + content: + 'A continuación, necesitas mejorar las tres minas de recursos (Metal, Cristal, Deuterio) al nivel 2 para cumplir los requisitos de construcción de una Fábrica de Robots. Mejóralas cuando tengas suficientes recursos.' + }, + buildRobotics: { + title: 'Construir Fábrica de Robots', + content: + 'La Fábrica de Robots acelera significativamente la construcción. Requiere Mina de Metal, Mina de Cristal y Sintetizador de Deuterio en nivel 2 cada uno. ¡Constrúyela para mejorar la eficiencia de construcción!' + }, + upgradeMinesForLab: { + title: 'Continuar Mejorando Minas', + content: + 'Ahora necesitas mejorar las tres minas de recursos al nivel 3 para cumplir los requisitos del Laboratorio de Investigación. Continúa desarrollando tu producción de recursos.' + }, + buildResearchLab: { + title: 'Construir Laboratorio de Investigación', + content: + 'El Laboratorio de Investigación es la base del avance tecnológico. Requiere todas las tres minas de recursos en nivel 3. ¡Constrúyelo para desbloquear la investigación tecnológica!' + }, + gotoResearch: { + title: 'Ir a Investigación', + content: 'Ahora que tienes un Laboratorio de Investigación, haz clic en el menú "Investigación" para ver las tecnologías disponibles.' + }, + researchEnergy: { + title: 'Investigar Tecnología de Energía', + content: + 'La Tecnología de Energía mejora tu producción de energía y desbloquea estructuras avanzadas. Es una de las tecnologías más fundamentales e importantes.' + }, + shipyardIntro: { + title: 'Flota y Astillero', + content: + 'Las naves te permiten explorar la galaxia, transportar recursos y defender tu imperio. Para construir naves, necesitas un Astillero (requiere Fábrica de Robots nivel 2).' + }, + gotoBuildingsForShipyard: { + title: 'Volver a Edificios', + content: 'Regresa a la página de Edificios para construir tu Astillero.' + }, + buildShipyard: { + title: 'Construir Astillero', + content: 'El Astillero te permite construir naves y sistemas de defensa. Esto es crucial para las operaciones de flota.' + }, + fleetIntro: { + title: 'Operaciones de Flota', + content: + 'Una vez que tengas naves, puedes enviarlas en misiones: transportar recursos, colonizar planetas, atacar enemigos o explorar campos de escombros.' + }, + galaxyIntro: { + title: 'Explorar la Galaxia', + content: + 'La vista de Galaxia muestra otros planetas, campos de escombros y oportunidades de expansión. Úsala para explorar objetivos y planificar tu estrategia.' + }, + complete: { + title: '¡Tutorial Completo!', + content: + '¡Felicitaciones, Comandante! Ahora conoces los conceptos básicos. Continúa construyendo tu imperio, investigando tecnologías y explorando la galaxia. ¡Recuerda: desarrolla la energía primero, luego recursos, luego fábricas e investigación! ¡Buena suerte!' + }, + // Mobile tutorial + mobile: { + welcome: { + title: 'Bienvenido a OGame (Móvil)', + content: + '¡Bienvenido, Comandante! Este es un tutorial simplificado diseñado para pantallas táctiles. Cubriremos rápidamente las características principales para que comiences a construir tu imperio.' + }, + resources: { + title: 'Barra de Recursos Superior', + content: 'En la parte superior, ves tus recursos: Metal, Cristal y Deuterio. Toca para ver información detallada de producción.' + }, + menu: { + title: 'Abrir Menú de Navegación', + content: + 'Toca este ícono de menú para abrir la barra de navegación. Puedes acceder a Edificios, Investigación, Flota y todas las demás características desde aquí.' + }, + gotoBuildings: { + title: 'Ir a Página de Edificios', + content: '¡El menú está ahora abierto! Ahora toca "Edificios" para comenzar a construir tu infraestructura.' + }, + buildSolarPlant: { + title: 'Construir Planta Solar', + content: + '¡Primero, construye una Planta Solar! Desplázate hacia abajo para encontrarla y toca la tarjeta para construir. La energía es la base de todo.' + }, + waitBuild: { + title: 'Cola de Construcción', + content: + 'Haz clic en el ícono de la cola en la esquina superior derecha para ver el progreso de construcción. Puedes seguir navegando por otras páginas: la construcción ocurre en segundo plano.' + }, + buildMetalMine: { + title: 'Construir Mina de Metal', + content: 'Ahora que tienes energía, construye una Mina de Metal. Desplázate hacia abajo para encontrarla y toca para construir.' + }, + complete: { + title: '¡Tutorial Rápido Completo!', + content: + '¡Genial! Has dominado los conceptos básicos. Continúa construyendo instalaciones de Cristal y Deuterio, luego explora otras características. ¡Recuerda: energía primero, luego recursos!' + } + } + }, + hints: { + close: 'Cerrar', + gotIt: 'Entendido', + dontShowAgain: 'No mostrar de nuevo', + resetHints: 'Reiniciar Consejos', + resetHintsDesc: 'Mostrar todos los consejos nuevamente', + hintsEnabled: 'Habilitar Consejos', + hintsEnabledDesc: 'Mostrar consejos útiles al visitar páginas', + overview: { + title: 'Resumen del Planeta', + message: + 'Aquí puedes ver los recursos de tu planeta, estado de flota y detalles de producción. ¡Revisa con frecuencia para monitorear tu progreso!' + }, + buildings: { + title: 'Edificios', + message: + 'Construye y mejora estructuras aquí. Comienza con la Planta Solar para energía, luego minas de recursos. Consejo: ¡La Fábrica de Robots acelera la construcción!' + }, + research: { + title: 'Laboratorio de Investigación', + message: + 'Investiga tecnologías para desbloquear nuevas naves, mejorar el combate y avanzar tu civilización. ¡La Tecnología de Energía es un gran comienzo!' + }, + shipyard: { + title: 'Astillero', + message: + 'Construye naves para explorar, transportar recursos y defender tu imperio. Las naves de carga ayudan a mover recursos entre planetas.' + }, + fleet: { + title: 'Comando de Flota', + message: + 'Envía tus naves en misiones: atacar enemigos, transportar recursos, colonizar nuevos planetas o explorar campos de escombros.' + }, + galaxy: { + title: 'Mapa de la Galaxia', + message: + 'Explora la galaxia para encontrar planetas vacíos que colonizar, campos de escombros que recolectar y enemigos que atacar. ¡Usa sondas espía primero!' + }, + diplomacy: { + title: 'Diplomacia', + message: + 'Gestiona relaciones con NPCs. Envía regalos para mejorar la reputación, o enfrenta ataques hostiles. ¡Los aliados de tus enemigos también pueden volverse hostiles!' + }, + messages: { + title: 'Mensajes', + message: + 'Ve reportes de batalla, reportes de espionaje y notificaciones diplomáticas aquí. Mantén un registro de tus actividades y encuentros con enemigos.' + }, + defense: { + title: 'Defensa Planetaria', + message: + 'Construye estructuras de defensa para proteger tu planeta de ataques. ¡Las cúpulas de escudo y torretas pueden disuadir a los asaltantes!' + }, + officers: { + title: 'Oficiales', + message: + '¡Recluta oficiales para obtener varios bonos! El Comandante acelera la construcción, el Geólogo aumenta la producción de recursos, el Almirante mejora las capacidades de flota.' + }, + simulator: { + title: 'Simulador de Batalla', + message: + 'Simula resultados de batalla antes de atacar. Ingresa ambas flotas y niveles tecnológicos para predecir victoria, pérdidas y botín.' + }, + campaign: { + title: 'Modo Campaña', + message: + '¡Explora la campaña de historia galáctica! Completa misiones para obtener recompensas de recursos y desbloquear nuevos desafíos. Cada nodo tiene objetivos y enemigos únicos.' + }, + achievements: { + title: 'Sistema de Logros', + message: + '¡Completa objetivos del juego para desbloquear logros y ganar recompensas de Materia Oscura! Los logros tienen múltiples niveles: apunta a desafíos más altos para obtener mejores recompensas.' + }, + ranking: { + title: 'Ranking', + message: + 'Compara tu progreso con otros jugadores y NPCs. Consulta rankings basados en puntos de edificios, investigación, flota y defensa. ¡Esfuérzate por escalar en la tabla de clasificación!' + }, + settings: { + title: 'Configuración', + message: + 'Gestiona datos del juego, ajusta notificaciones, exporta/importa guardados aquí. ¡Recuerda respaldar tu progreso regularmente!' + }, + gm: { + title: 'Panel GM', + message: + 'El modo GM permite la modificación rápida de recursos, edificios y niveles tecnológicos. Úsalo para pruebas o para experimentar el contenido completo del juego.' + } + }, + achievements: { + title: 'Logros', + unlocked: 'Logro Desbloqueado', + progress: 'Progreso', + nextTier: 'Siguiente Nivel', + maxTierReached: 'Nivel Máximo Alcanzado', + tiers: { + bronze: 'Bronce', + silver: 'Plata', + gold: 'Oro', + platinum: 'Platino', + diamond: 'Diamante' + }, + categories: { + resource: 'Recurso', + building: 'Edificio', + combat: 'Combate', + mission: 'Misión', + diplomacy: 'Diplomacia' + }, + names: { + metalCollector: 'Colector de Metal', + crystalCollector: 'Colector de Cristal', + deuteriumCollector: 'Colector de Deuterio', + darkMatterCollector: 'Colector de Materia Oscura', + resourceConsumer: 'Consumidor de Recursos', + masterBuilder: 'Maestro Constructor', + researcher: 'Investigador', + shipwright: 'Constructor de Naves', + fortifier: 'Fortificador', + warmonger: 'Belicista', + conqueror: 'Conquistador', + defender: 'Defensor', + fleetDestroyer: 'Destructor de Flotas', + debrisCreator: 'Creador de Escombros', + fleetSacrifice: 'Sacrificio de Flota', + defenseSacrifice: 'Sacrificio de Defensa', + pilot: 'Piloto', + transporter: 'Transportista', + cargoMaster: 'Maestro de Carga', + colonizer: 'Colonizador', + spy: 'Maestro Espía', + deployer: 'Desplegador', + explorer: 'Explorador', + luckyExplorer: 'Explorador Afortunado', + recycler: 'Reciclador', + scavenger: 'Recolector', + destroyer: 'Destructor', + fuelBurner: 'Quemador de Combustible', + diplomat: 'Diplomático', + nemesis: 'Némesis', + generous: 'Generoso', + philanthropist: 'Filántropo', + target: 'Objetivo', + watched: 'Vigilado', + robbed: 'Robado', + lostToNPC: 'Perdido ante NPC' + }, + descriptions: { + metalCollector: 'Total de metal producido', + crystalCollector: 'Total de cristal producido', + deuteriumCollector: 'Total de deuterio producido', + darkMatterCollector: 'Total de materia oscura producida', + resourceConsumer: 'Total de recursos consumidos', + masterBuilder: 'Total de edificios mejorados', + researcher: 'Total de investigaciones completadas', + shipwright: 'Total de naves producidas', + fortifier: 'Total de defensas construidas', + warmonger: 'Total de ataques lanzados', + conqueror: 'Total de ataques ganados', + defender: 'Total de defensas exitosas', + fleetDestroyer: 'Flota enemiga destruida en defensa', + debrisCreator: 'Total de escombros creados en batallas', + fleetSacrifice: 'Total de flota perdida', + defenseSacrifice: 'Total de defensas perdidas en defensa', + pilot: 'Total de misiones de vuelo', + transporter: 'Total de misiones de transporte', + cargoMaster: 'Total de recursos transportados', + colonizer: 'Planetas colonizados', + spy: 'Misiones de espionaje completadas', + deployer: 'Misiones de despliegue completadas', + explorer: 'Total de expediciones', + luckyExplorer: 'Expediciones exitosas', + recycler: 'Total de misiones de reciclaje', + scavenger: 'Total de recursos reciclados', + destroyer: 'Planetas destruidos', + fuelBurner: 'Total de combustible consumido', + diplomat: 'Número de NPCs amigables', + nemesis: 'Número de NPCs hostiles', + generous: 'Total de regalos enviados', + philanthropist: 'Total de recursos regalados', + target: 'Veces atacado por NPC', + watched: 'Veces espiado por NPC', + robbed: 'Veces que escombros fueron reciclados por NPC', + lostToNPC: 'Total de recursos de escombros perdidos ante NPC' + } + }, + ranking: { + title: 'Clasificación', + totalPlayers: '{count} Jugadores', + yourRanking: 'Tu Clasificación', + categories: { + total: 'Total', + building: 'Edificio', + research: 'Investigación', + fleet: 'Flota', + defense: 'Defensa' + }, + points: 'pts', + name: 'Nombre', + planets: 'Planetas', + details: 'Detalles', + you: 'Tú', + scoreBreakdown: 'Desglose de Puntuación', + noData: 'Sin datos de clasificación' + }, + campaign: { + name: 'Campaña', + description: 'Explora la misteriosa galaxia y descubre secretos antiguos', + totalProgress: 'Progreso Total', + questsCompleted: 'Misiones Completadas', + chapter: 'Capítulo', + branch: 'Rama', + startQuest: 'Iniciar Misión', + claimRewards: 'Reclamar Recompensas', + objectives: 'Objetivos', + rewards: 'Recompensas', + completed: 'Completado', + inProgress: 'En Progreso', + available: 'Disponible', + locked: 'Bloqueado', + notifications: { + questStarted: 'Misión iniciada', + questCompleted: '¡Misión completada!', + rewardsClaimed: 'Recompensas reclamadas', + objectiveCompleted: 'Objetivo completado', + chapterUnlocked: 'Nuevo capítulo desbloqueado', + reputationUp: 'Reputación con {npcName} aumentada en {value}', + reputationDown: 'Reputación con {npcName} disminuida en {value}', + branchUnlocked: '¡Nueva rama de historia desbloqueada!' + }, + dialogue: { + skip: 'Saltar', + continue: 'Continuar', + finish: 'Finalizar', + player: 'Comandante', + npc: 'NPC', + narrator: 'Narrador', + mysterious: 'Señal Misteriosa', + unknownSource: 'Fuente desconocida', + choiceEffect: 'Efecto de elección de diálogo' + }, + chapters: { + '1': { + title: 'Origen', + description: 'Construye tu hogar y da el primer paso al espacio', + backgroundStory: + 'Eres un joven comandante espacial que acaba de adquirir tu primer planeta. En este vasto universo, construirás tu hogar, desarrollarás tecnología y explorarás las profundidades de la galaxia...' + }, + '2': { + title: 'Exploración', + description: 'Explora el universo y descubre ruinas antiguas', + backgroundStory: + 'A medida que tu poder crece, señales misteriosas del espacio profundo captan tu atención. Estas señales parecen apuntar a un secreto antiguo, esperando que exploradores valientes lo descubran...' + }, + '3': { + title: 'Diplomacia', + description: 'Establece conexiones con otras facciones', + backgroundStory: + 'No estás solo en la galaxia. Otras civilizaciones están surgiendo. Debes decidir si ser su enemigo o aliado. La sabiduría diplomática determinará hasta dónde puede llegar tu imperio...' + }, + '4': { + title: 'Ascenso de las Sombras', + description: 'Enfrenta enemigos poderosos y defiende tu territorio', + backgroundStory: + 'El peligro acecha en las sombras. Una poderosa fuerza hostil ha puesto los ojos en tu territorio. La guerra es inevitable. Debes prepararte para enfrentar la tormenta que se avecina...' + }, + '5': { + title: 'Secretos Antiguos', + description: 'Descubre los secretos más profundos de la galaxia', + backgroundStory: + 'Todas las pistas apuntan a la región más misteriosa de la galaxia. Allí, los secretos últimos dejados por civilizaciones antiguas esperan. ¿Estás listo para descubrir todo?' + } + }, + quests: { + '1_1': { + title: 'Construcción del Hogar', + description: 'Construye infraestructura para sentar las bases de tu planeta' + }, + '1_2': { + title: 'Iluminación Tecnológica', + description: 'Investiga tecnología básica para comenzar tu viaje tecnológico' + }, + '1_3': { + title: 'Primera Nave', + description: 'Construye tu primera nave de guerra' + }, + '1_4': { + title: 'Vecinos Extraños', + description: 'Explora otras facciones en sistemas cercanos' + }, + '1_5': { + title: 'Primer Contacto', + description: 'Establece contacto inicial con facciones NPC cercanas' + }, + '2_1': { + title: 'Colonia Pionera', + description: 'Coloniza tu primer planeta nuevo' + }, + '2_2': { + title: 'Expedición al Espacio Profundo', + description: 'Envía flota en misiones de expedición' + }, + '2_3': { + title: 'Señal Misteriosa', + description: 'Investiga señales misteriosas del espacio profundo' + }, + '2_4': { + title: 'Investigación de Ruinas', + description: 'Explora las ruinas antiguas descubiertas' + }, + '2_5': { + title: 'Descifrar Archivos', + description: 'Investiga datos obtenidos de las ruinas' + }, + '3_1': { + title: 'Pacificador', + description: 'Mejora relaciones con NPCs a través de la diplomacia' + }, + '3_2': { + title: 'Relaciones Comerciales', + description: 'Establece relaciones estables con facciones amigables' + }, + '3_3': { + title: 'Amenaza Común', + description: 'Descubre fuerzas hostiles potenciales' + }, + '3_4': { + title: 'Negociaciones de Alianza', + description: 'Forma una alianza formal con NPCs amigables' + }, + '3_5': { + title: 'Preparación para la Tormenta', + description: 'Construye defensas para prepararte para los desafíos' + }, + '4_1': { + title: 'Ataque al Puesto', + description: 'Repele el primer ataque de fuerzas hostiles' + }, + '4_2': { + title: 'Recopilación de Inteligencia', + description: 'Explora despliegues militares enemigos' + }, + '4_3': { + title: 'Contraataque', + description: 'Lanza un contraataque contra el enemigo' + }, + '4_4': { + title: 'Disputa de Recursos', + description: 'Recicla escombros del campo de batalla para obtener recursos' + }, + '4_5': { + title: 'Víspera de Batalla', + description: 'Construye una flota poderosa para la batalla final' + }, + '5_1': { + title: 'Profundidades de las Ruinas', + description: 'Explora las partes más profundas de las ruinas' + }, + '5_2': { + title: 'Tecnología Antigua', + description: 'Desbloquea tecnología de civilización antigua' + }, + '5_3': { + title: 'Confrontación Final', + description: 'Enfrenta la batalla final contra el enemigo misterioso' + }, + '5_4': { + title: 'Nueva Era', + description: 'Establece nuevas colonias y comienza una nueva era' + }, + '5_5': { + title: 'El Legado Continúa', + description: 'Continúa desarrollando y conquistando más sistemas' + } + }, + objectiveTypes: { + buildBuilding: 'Construir {building} al nivel {level}', + researchTech: 'Investigar {tech} al nivel {level}', + produceShips: 'Producir {count} {ship}', + accumulateResources: 'Acumular {amount} {resource}', + defeatNPC: 'Derrotar {npc}', + winBattles: 'Ganar {count} batallas', + recycleDebris: 'Reciclar {amount} de escombros', + reachRelation: 'Alcanzar relación {level} con {npc}', + sendGift: 'Enviar {count} regalos a {npc}', + formAlliance: 'Formar alianza con {npc}', + colonize: 'Colonizar {count} planetas', + expedition: 'Completar {count} expediciones', + spyTarget: 'Espiar {target}' + }, + errors: { + questNotFound: 'Misión no encontrada', + questNotAvailable: 'Misión no disponible', + questNotActive: 'Misión no activa', + questNotCompleted: 'Misión no completada', + rewardsAlreadyClaimed: 'Recompensas ya reclamadas', + prerequisiteNotMet: 'Misión prerequisito no completada' + }, + speakers: { + ancientVoice: 'Voz Antigua', + neighborNPC: 'Facción Vecina', + mysteriousSignal: 'Señal Misteriosa', + enemyCommander: 'Comandante Enemigo' + }, + objectiveDescriptions: { + buildMetalMine: 'Construir Mina de Metal al nivel 2', + buildCrystalMine: 'Construir Mina de Cristal al nivel 2', + buildSolarPlant: 'Construir Planta Solar al nivel 2', + buildResearchLab: 'Construir Laboratorio de Investigación al nivel 1', + researchEnergy: 'Investigar Tecnología de Energía al nivel 1', + buildShipyard: 'Construir Astillero al nivel 2', + researchCombustion: 'Investigar Motor de Combustión al nivel 1', + buildLightFighters: 'Construir 5 Cazadores Ligeros', + researchEspionage: 'Investigar Tecnología de Espionaje al nivel 2', + buildSpyProbes: 'Construir 3 Sondas de Espionaje', + spyAnyNPC: 'Espiar cualquier planeta NPC', + sendGiftToNPC: 'Enviar un regalo a cualquier NPC', + researchAstrophysics: 'Investigar Astrofísica al nivel 1', + buildColonyShip: 'Construir una Nave Colonial', + colonizeNewPlanet: 'Colonizar un nuevo planeta', + completeExpedition: 'Completar una misión de expedición', + discoverRuins: 'Descubrir ruinas antiguas', + researchComputer: 'Investigar Tecnología de Computación al nivel 4', + improveRelation: 'Mejorar relaciones con un NPC', + reachFriendly: 'Alcanzar estatus amigable con un NPC', + spyHostileNPC: 'Espiar un NPC hostil', + formAlliance: 'Formar alianza con un NPC amigable', + buildDefenses: 'Construir instalaciones de defensa', + winDefenseBattle: 'Ganar una batalla defensiva', + spyEnemyPlanet: 'Espiar planeta enemigo', + attackEnemy: 'Atacar al enemigo', + recycleDebris: 'Reciclar escombros', + buildBattleships: 'Construir 10 Naves de Batalla', + exploreDeepRuins: 'Explorar ruinas profundas', + researchHyperspace: 'Investigar Tecnología de Hiperespacio', + defeatBoss: 'Derrotar al enemigo misterioso', + colonizeSpecial: 'Colonizar ubicación especial', + continueDevelopment: 'Continuar desarrollo' + }, + dialogues: { + '1_1': { + prologue_1: + 'Bienvenido a la galaxia, joven comandante. Este vasto universo espera tu exploración. Primero, construyamos tu planeta natal.', + prologue_2: 'Siento una nueva consciencia despertando... Interesante... Veamos hasta dónde puedes llegar...' + }, + '1_2': { + prologue_1: + 'La infraestructura básica está completa. Ahora es momento de desarrollar tecnología. Construye un Laboratorio de Investigación y comienza tu viaje tecnológico.' + }, + '1_3': { + prologue_1: + 'Con apoyo tecnológico, puedes comenzar a construir tu flota. Construye un Astillero y produce tu primera nave de guerra.' + }, + '1_4': { + prologue_1: + 'Tu flota está tomando forma. Ahora aprendamos sobre tus alrededores. Envía sondas espía para explorar facciones cercanas.', + prologue_2: 'No estás solo... Otras civilizaciones existen en esta galaxia...' + }, + '1_5': { + prologue_1: 'Has descubierto facciones cercanas. La diplomacia es un arte. Intenta establecer contacto con ellos.', + epilogue_1: 'Gracias por tu regalo, comandante. Espero que podamos ser amigos.', + epilogue_2: 'Bien... Establecer conexiones es el primer paso para descubrir secretos más profundos...' + }, + '2_1': { + prologue_1: + 'Tu poder está establecido. Es momento de expandir tu territorio. Investiga Astrofísica, construye una nave colonial y explora nuevos planetas.', + prologue_2: 'El universo es infinito... Más planetas significan más posibilidades...' + }, + '2_2': { + prologue_1: '¡Colonización exitosa! Pero secretos más profundos esperan en el universo. Envía tu flota en misiones de expedición.', + prologue_2: 'Señales débiles desde lejos... Algo te espera allí...' + }, + '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.', + 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.' + }, + '2_5': { + prologue_1: 'Se encontraron archivos de datos en las ruinas. Estudia estos datos, quizás puedas desbloquear nueva tecnología.' + }, + '3_1': { + prologue_1: 'Mientras exploras, no olvides la diplomacia. Mantener buenas relaciones con las facciones circundantes te beneficia.' + }, + '3_2': { + prologue_1: 'Algunas facciones han mostrado amabilidad. Continúa profundizando las relaciones, quizás puedas obtener más apoyo.' + }, + '3_3': { + prologue_1: + 'La inteligencia indica que fuerzas hostiles te están vigilando desde las sombras. Mantente alerta y explora sus movimientos.' + }, + '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.' + }, + '4_1': { + prologue_1: '¡El enemigo ha lanzado un ataque! ¡Defiende tu planeta!', + epilogue_1: 'Repeliste exitosamente la primera ola del enemigo. Pero esto es solo el comienzo...' + }, + '4_2': { + prologue_1: 'El enemigo se ha retirado, pero regresarán. Explora sus planetas para entender su fuerza.' + }, + '4_3': { + prologue_1: 'Es momento de contraatacar. Ataca los planetas enemigos y debilita sus fuerzas.' + }, + '4_4': { + 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.' + }, + '5_1': { + prologue_1: + 'Todas las pistas apuntan a la parte más profunda de las ruinas. Los secretos centrales de la civilización antigua yacen allí.', + 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.' + }, + '5_3': { + prologue_1: 'Ha aparecido un enemigo misterioso. Este es el desafío final. ¡Derrótalo!', + epilogue_1: '¡Lo lograste! El guardián antiguo ha sido derrotado. Los secretos de la galaxia ahora están abiertos para ti.' + }, + '5_4': { + prologue_1: 'La paz ha llegado finalmente. En esta nueva era, establece nuevas colonias y expande tu imperio.' + }, + '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...' + } + } + }, + // NPC Enhanced Behavior Notifications + npcBehavior: { + // Neutral NPC behavior + tradeOfferReceived: 'Oferta Comercial Recibida', + tradeOfferDesc: '{npcName} te ha enviado una oferta comercial', + attitudeChanged: 'Actitud de NPC Cambiada', + becameFriendly: '{npcName} se ha vuelto amigable hacia ti', + becameHostile: '{npcName} se ha vuelto hostil hacia ti', + // Friendly NPC behavior + intelReceived: 'Inteligencia Recibida', + intelReceivedDesc: '{npcName} ha compartido inteligencia enemiga contigo', + jointAttackInvite: 'Invitación de Ataque Conjunto', + jointAttackInviteDesc: '{npcName} te invita a atacar a un enemigo juntos', + aidReceived: 'Ayuda Recibida', + aidReceivedDesc: '{npcName} te ha enviado {amount} recursos', + allyDefense: 'Defensa de Aliado', + allyDefenseDesc: '{npcName} está enviando una flota para ayudar a defender tu planeta', + // Trade related + trade: { + title: 'Ofertas Comerciales', + from: 'De', + offers: 'Ofrece', + requests: 'Solicita', + expiresIn: 'Expira En', + expired: 'Expirado', + accept: 'Aceptar', + decline: 'Rechazar', + noOffers: 'Sin ofertas comerciales', + acceptSuccess: '¡Comercio completado!', + acceptFailed: 'Recursos insuficientes para completar el comercio', + declined: 'Comercio rechazado', + ratio: 'Tasa de Cambio' + }, + // Intel related + intel: { + title: 'Reportes de Inteligencia', + from: 'Fuente', + target: 'NPC Objetivo', + type: 'Tipo de Inteligencia', + types: { + enemyFleet: 'Inteligencia de Flota', + enemyResources: 'Inteligencia de Recursos', + enemyMovement: 'Inteligencia de Movimiento' + }, + fleetInfo: 'Información de Flota', + resourceInfo: 'Información de Recursos', + movementInfo: 'Información de Movimiento', + noReports: 'Sin reportes de inteligencia', + markAsRead: 'Marcar como Leído', + content: 'Contenido de Inteligencia', + noFleet: 'No se detectó flota', + noData: 'Sin datos disponibles', + targetPosition: 'Posición Objetivo', + missionType: 'Tipo de Misión' + }, + // Joint attack related + jointAttack: { + title: 'Invitaciones de Ataque Conjunto', + from: 'Iniciador', + target: 'NPC Objetivo', + targetPlanet: 'Planeta Objetivo', + npcFleet: 'Flota NPC', + lootShare: 'Reparto de Botín', + expiresIn: 'Expira En', + expired: 'Expirado', + accept: 'Unirse al Ataque', + decline: 'Rechazar', + noInvites: 'Sin invitaciones de ataque conjunto', + acceptSuccess: '¡Te has unido al ataque conjunto!', + declined: 'Invitación rechazada', + targetInfo: 'Objetivo del Ataque', + expectedShare: 'Parte Esperada', + remaining: 'Tiempo Restante' + }, + // Aid related + aid: { + title: 'Ayuda de Recursos', + from: 'Fuente', + resources: 'Recursos de Ayuda', + noAid: 'Sin registros de ayuda' + }, + // Attitude change related + attitudeChange: { + title: 'Cambios de Actitud', + npc: 'NPC', + previous: 'Anterior', + current: 'Actual', + reason: 'Razón', + reasons: { + naturalSwing: 'Cambio natural', + giftReceived: 'Regalo recibido', + attacked: 'Fue atacado', + reputationThreshold: 'Umbral de reputación', + attitude_swing: 'Oscilación de actitud', + gift: 'Recibió regalo', + attack: 'Sufrió ataque' + } + }, + // Ally actions related + allyAction: { + title: 'Acciones de Aliado', + defense: 'Apoyo Defensivo', + defenseDesc: '{npcName} está enviando flota para ayudar a defender {targetPlanet}', + jointAttackStarted: 'Ataque Conjunto Iniciado', + jointAttackStartedDesc: 'El ataque conjunto contra {targetNpc} ha comenzado', + reputationBonus: 'Bonificación de Reputación', + reputationBonusDesc: 'Tu aliado {npcName} habla bien de ti ante {targetNpc}' + } + } +} diff --git a/src/locales/index.ts b/src/locales/index.ts index 95b5f7c..6fa7ebd 100644 --- a/src/locales/index.ts +++ b/src/locales/index.ts @@ -1,14 +1,73 @@ +// 默认语言(打包在主包中) import zhCN from './zh-CN' -import zhTW from './zh-TW' -import en from './en' -import de from './de' -import ru from './ru' -import ko from './ko' -import ja from './ja' -export type Locale = 'zh-CN' | 'zh-TW' | 'en' | 'de' | 'ru' | 'ko' | 'ja' +export type Locale = 'zh-CN' | 'zh-TW' | 'en' | 'de' | 'ru' | 'ko' | 'ja' | 'es-LA' -export const locales = { 'zh-CN': zhCN, 'zh-TW': zhTW, en, de, ru, ko, ja } +export type TranslationSchema = typeof zhCN + +// 语言加载器 - 使用动态导入实现按需加载 +// 注意: 各语言文件可能有细微差异,缺失的键会在运行时回退到 key 本身 +type LocaleModule = { default: TranslationSchema } +const localeLoaders: Record Promise> = { + 'zh-CN': () => Promise.resolve({ default: zhCN }), + 'zh-TW': () => import('./zh-TW') as unknown as Promise, + en: () => import('./en') as unknown as Promise, + de: () => import('./de') as unknown as Promise, + ru: () => import('./ru') as unknown as Promise, + ko: () => import('./ko') as unknown as Promise, + ja: () => import('./ja') as unknown as Promise, + 'es-LA': () => import('./es-LA') as unknown as Promise +} + +// 已加载的语言缓存 +const loadedLocales: Partial> = { + 'zh-CN': zhCN // 默认语言预加载 +} + +/** + * 异步加载指定语言 + * @param locale 语言代码 + * @returns 语言翻译对象 + */ +export const loadLocale = async (locale: Locale): Promise => { + // 如果已经加载过,直接返回缓存 + if (loadedLocales[locale]) { + return loadedLocales[locale]! + } + + // 动态加载语言文件 + const loader = localeLoaders[locale] + if (!loader) { + console.warn(`Locale "${locale}" not found, falling back to zh-CN`) + return zhCN + } + + try { + const module = await loader() + loadedLocales[locale] = module.default + return module.default + } catch (error) { + console.error(`Failed to load locale "${locale}":`, error) + return zhCN + } +} + +/** + * 同步获取已加载的语言(如果未加载则返回默认语言) + * @param locale 语言代码 + * @returns 语言翻译对象 + */ +export const getLocale = (locale: Locale): TranslationSchema => { + return loadedLocales[locale] || zhCN +} + +/** + * 检查语言是否已加载 + * @param locale 语言代码 + */ +export const isLocaleLoaded = (locale: Locale): boolean => { + return locale in loadedLocales +} export const localeNames: Record = { 'zh-CN': '简体中文', @@ -17,7 +76,8 @@ export const localeNames: Record = { de: 'Deutsch', ru: 'Русский', ko: '한국어', - ja: '日本語' + ja: '日本語', + 'es-LA': 'Español (LA)' } /** @@ -44,10 +104,9 @@ export const detectBrowserLocale = (): Locale => { return 'de' } else if (lang.startsWith('ru')) { return 'ru' + } else if (lang.startsWith('es')) { + return 'es-LA' } - // 默认返回简体中文 return 'zh-CN' } - -export type TranslationSchema = typeof zhCN diff --git a/src/locales/ja.ts b/src/locales/ja.ts index d070730..86a3778 100644 --- a/src/locales/ja.ts +++ b/src/locales/ja.ts @@ -11,29 +11,11 @@ export default { common: { confirm: '確認', cancel: 'キャンセル', - delete: '削除', - edit: '編集', save: '保存', close: '閉じる', - back: '戻る', - next: '次へ', - gotIt: '', - previous: '前へ', - submit: '送信', - reset: 'リセット', - search: '検索', - filter: 'フィルター', - loading: '読み込み中...', - noData: 'データなし', - error: 'エラー', - success: '成功', - warning: '警告', - info: '情報', + gotIt: '了解', resourceType: '資源タイプ', playerName: '司令官', - timeHour: '時間', - timeMinute: '分', - timeSecond: '秒', featureLocked: '機能がロックされています', unlockRequired: '建物が必要です', requiredBuilding: '必要な建物', @@ -41,7 +23,6 @@ export default { goToBuildings: '建物へ移動', locked: 'ロック済み', viewRequirements: '必要条件を表示', - requirements: '必要条件', requirementsNotMet: '必要条件が満たされていません', current: '現在', level: 'レベル', @@ -51,7 +32,8 @@ export default { viewDetails: '詳細を見る', exitConfirmTitle: 'ゲーム終了', exitConfirmMessage: 'ゲームを終了しますか?進行状況は自動的に保存されます。', - points: 'ポイント' + points: 'ポイント', + retry: '再試行' }, errors: { requirementsNotMet: '前提条件を満たしていません', @@ -87,6 +69,7 @@ export default { simulator: 'シミュレーター', galaxy: '銀河', diplomacy: '外交', + campaign: 'キャンペーン', achievements: '実績', ranking: 'ランキング', messages: 'メッセージ', @@ -180,8 +163,10 @@ export default { sensorPhalanx: 'センサーファランクス', jumpGate: 'ジャンプゲート', planetDestroyerFactory: '惑星破壊工場', + geoResearchStation: '地質研究所', + deepDrillingFacility: '深部掘削施設', buildTime: '建設時間', - build: '', + build: '建設', production: '生産量', consumption: '消費', totalCost: '総コスト', @@ -229,7 +214,9 @@ export default { lunarBase: '月の利用可能スペースを増加、レベル毎に+30スペース', sensorPhalanx: '周辺星系の艦隊活動を探知', jumpGate: '他の月へ艦隊を瞬間移動', - planetDestroyerFactory: '惑星を破壊できる究極兵器を建造' + planetDestroyerFactory: '惑星を破壊できる究極兵器を建造', + geoResearchStation: '地質構造を研究し、鉱脈の自然回復速度を向上。レベル毎に回復速度50%増加', + deepDrillingFacility: '' }, ships: { lightFighter: '軽戦闘機', @@ -303,7 +290,16 @@ export default { buildQueue: 'Build Queue', planetSpace: 'Planet Space', moonSpace: 'Moon Space', - missileCapacity: 'Missile Capacity' + missileCapacity: 'Missile Capacity', + attackBonus: '攻撃ボーナス', + shieldBonus: 'シールドボーナス', + armorBonus: '装甲ボーナス', + spyLevel: '偵察レベル', + researchQueueBonus: '研究キュー', + colonySlots: '植民地スロット', + forAllPlanets: '(全惑星)', + speedBonus: '速度ボーナス', + researchSpeedBonus: '研究速度ボーナス' }, technologies: { energyTechnology: 'エネルギー技術', @@ -323,7 +319,8 @@ export default { hyperspaceDrive: 'ハイパースペースドライブ', darkMatterTechnology: 'ダークマター技術', terraformingTechnology: 'テラフォーミング技術', - planetDestructionTech: '惑星破壊技術' + planetDestructionTech: '惑星破壊技術', + miningTechnology: '' }, technologyDescriptions: { energyTechnology: 'エネルギー利用効率を向上', @@ -344,7 +341,8 @@ export default { hyperspaceDrive: '高級推進技術', darkMatterTechnology: 'ダークマターの性質と応用を研究', terraformingTechnology: '惑星地形改造技術を研究、レベル毎に全惑星の利用可能スペース30増加', - planetDestructionTech: '惑星全体を破壊する恐怖の技術を研究' + planetDestructionTech: '惑星全体を破壊する恐怖の技術を研究', + miningTechnology: '' }, officers: { commander: '司令官', @@ -379,8 +377,12 @@ export default { cancelResearch: '研究キャンセル', confirmCancel: 'キャンセルしますか?資源の50%が返還されます。', level: 'レベル', - gmModeActivated: '', + gmModeActivated: 'GMモードが有効になりました!ナビゲーションメニューを確認してください。', upgradeToLevel: 'レベルにアップグレード', + buildQueueBonus: '建設キュー', + spaceBonus: '空間ボーナス', + researchQueueBonus: '研究キュー', + quantity: '数量', tabs: { all: 'すべて', buildings: '建物', @@ -407,7 +409,7 @@ export default { fuelConsumption: '燃料消費', buildCost: '建設コスト', buildTime: '建設時間', - build: '', + build: '建設', perUnit: 'ユニットあたり', batchCalculator: '一括計算機', quantity: '数量', @@ -435,7 +437,6 @@ export default { usedSpace: '使用済みスペース', spaceUsage: 'スペース使用量', level: 'レベル', - gmModeActivated: '', upgradeCost: 'アップグレードコスト', buildTime: '建設時間', build: '建設', @@ -466,7 +467,7 @@ export default { armor: '装甲', buildCost: '建設コスト', buildTime: '建設時間', - build: '', + build: '建設', perUnit: 'ユニットあたり', batchCalculator: '一括計算機', quantity: '数量', @@ -537,6 +538,7 @@ export default { missionInfo: 'ミッション情報', fuelConsumption: '燃料消費', flightTime: '飛行時間', + outOfRange: '射程外', attackMission: '攻撃', transport: '輸送', colonize: '植民', @@ -578,11 +580,12 @@ export default { arrivalTime: '到着時刻', returnTime: '帰還時刻', recallFleet: '艦隊召還', - abortMission: '', - abortMissionTitle: '', - abortMissionWarning: '', - abortMissionSuccess: '', - abortMissionSuccessMessage: '', + abortMission: 'ミッション中止', + abortMissionTitle: 'ミッション中止の確認', + abortMissionWarning: + '警告: このミッションを中止すると、{ships}隻の艦船と{resources}の資源が永久に失われます!\n\nこの操作は取り消すことができず、艦隊と資源は戻ってきません。', + abortMissionSuccess: 'ミッション中止', + abortMissionSuccessMessage: 'ミッションが中止され、艦隊と資源は失われました。', sendFailed: '派遣失敗', sendFailedMessage: '艦隊数、燃料の充足、または積載量の制限を確認してください。', recallFailed: '召還失敗', @@ -637,7 +640,8 @@ export default { jumpGateSuccess: 'ジャンプゲート転送成功', jumpGateSuccessMessage: '艦隊は{target}へ瞬時に転送されました', jumpGateFailed: 'ジャンプゲート転送失敗', - jumpGateFailedMessage: 'ジャンプゲートの状態と艦隊構成を確認してください' + jumpGateFailedMessage: 'ジャンプゲートの状態と艦隊構成を確認してください', + destroy: '破壊' }, officersView: { title: '士官', @@ -709,10 +713,12 @@ export default { missileCount: 'ミサイル数', availableMissiles: '利用可能なミサイル', missileRange: 'ミサイル射程', - systems: 'システム', + systems: '星系', distance: '距離', flightTime: '飛行時間', + outOfRange: '射程外', launchMissile: '発射', + missileLaunched: 'ミサイル発射完了', cancel: 'キャンセル', colonizePlanetMessage: '位置[{coordinates}]を植民しますか?\n\n艦隊ページに移動してコロニーシップを派遣してください。', recyclePlanetMessage: '位置[{coordinates}]のデブリを回収しますか?\n\n艦隊ページに移動してリサイクラーを派遣してください。', @@ -721,6 +727,25 @@ export default { giftPlanetTitle: 'ギフト送信', giftPlanetMessage: '惑星[{coordinates}]にリソースを贈りますか?\n\n艦隊ページに移動して輸送船を選択し、リソースを積載してください。', npcPlanetName: '{name}の惑星', + // センサーアレイスキャン + phalanxScan: 'センサースキャン', + phalanxScanTitle: 'センサーアレイスキャン', + phalanxScanDescription: '惑星 [{coordinates}] の艦隊活動をスキャン', + phalanxNoMoon: 'センサーアレイを持つ月が必要です', + phalanxOutOfRange: 'ターゲットがスキャン範囲外です', + phalanxRange: 'スキャン範囲', + phalanxCost: 'スキャンコスト', + phalanxNoFleets: '艦隊活動が検出されませんでした', + phalanxFleetDetected: '{count}隻の艦隊を検出', + phalanxMission: 'ミッション', + phalanxOrigin: '出発地', + phalanxDestination: '目的地', + phalanxArrival: '到着時刻', + phalanxReturn: '帰還時刻', + phalanxStatus: 'ステータス', + phalanxStatusOutbound: '往路中', + phalanxStatusReturning: '帰還中', + phalanxInsufficientDeuterium: '重氢不足', intercepted: '迎撃済み', defenseLosses: '防衛損失' }, @@ -729,12 +754,12 @@ export default { battles: '戦闘', spy: 'スパイ', npc: 'NPC', - diplomacy: '', + diplomacy: '外交', battleReports: '戦闘レポート', spyReports: 'スパイレポート', noBattleReports: '戦闘レポートなし', noSpyReports: 'スパイレポートなし', - noDiplomaticReports: '', + noDiplomaticReports: '外交レポートなし', battleReport: '戦闘レポート', spyReport: 'スパイレポート', victory: '勝利', @@ -755,6 +780,8 @@ export default { defense: '防衛', buildings: '建物', unread: '未読', + pending: '保留中', + invalidData: '無効なデータ', targetPlanet: '目標惑星', attackerRemaining: '攻撃側残存', defenderRemaining: '防御側残存', @@ -807,36 +834,36 @@ export default { polite_decline: '丁重に断りました' }, // Spied notification dialog - spiedNotificationDetails: '', - spyDetected: '', - detectionResult: '', - detectionSuccess: '', - spiedNotificationMessage: '', - spiedNotificationTip: '', - viewInGalaxy: '', + spiedNotificationDetails: '偵察通知の詳細', + spyDetected: 'スパイを検出', + detectionResult: '検出結果', + detectionSuccess: '敵のスパイを検出しました!', + spiedNotificationMessage: '{npc}があなたの惑星{planet}を偵察しようとしました', + spiedNotificationTip: 'このNPCが敵対的な場合は、防衛を強化するか反撃を検討してください', + viewInGalaxy: '銀河で表示', // Mission report dialog - missionReportDetails: '', - missionSuccess: '', - missionFailed: '', - origin: '', - destination: '', - missionDetails: '', - transportedResources: '', - recycledResources: '', - remainingDebris: '', - newPlanet: '', + missionReportDetails: 'ミッションレポートの詳細', + missionSuccess: '成功', + missionFailed: '失敗', + origin: '出発地', + destination: '目的地', + missionDetails: 'ミッション詳細', + transportedResources: '輸送資源', + recycledResources: 'リサイクル資源', + remainingDebris: '残りの破片', + newPlanet: '新惑星', // NPC activity dialog - npcActivityDetails: '', + npcActivityDetails: 'NPCアクティビティの詳細', activityType: { - recycle: '' + recycle: '破片をリサイクル中' }, - activityLocation: '', - position: '', - nearPlanet: '', - activityDescription: '', - npcActivityMessage: '', - arrivalTime: '', - npcActivityTip: '', + activityLocation: 'アクティビティの場所', + position: '位置', + nearPlanet: '近くの惑星', + activityDescription: 'アクティビティの説明', + npcActivityMessage: '{npc}が{position}で{activity}', + arrivalTime: '到着時刻', + npcActivityTip: 'NPCは戦闘の破片を収集することがあります。資源を競いたい場合は、先に現地に到着することを試みてください', clearMessages: 'メッセージをクリア', clearMessageTypes: 'クリアするメッセージタイプを選択', clearBattleReports: '戦闘レポート', @@ -846,7 +873,11 @@ export default { clearNPCActivity: 'NPCアクティビティ', clearGiftNotifications: 'ギフト通知', clearGiftRejected: '拒否されたギフト', - clearNow: '今すぐクリア' + clearTradeOffers: '貿易提案', + clearIntelReports: '諜報報告', + clearJointAttackInvites: '共同攻撃の招待', + clearNow: '今すぐクリア', + clearSuccess: 'メッセージがクリアされました' }, missionReports: { transportSuccess: '輸送ミッションが正常に完了しました', @@ -978,6 +1009,10 @@ export default { github: 'GitHubリポジトリ', qqGroup: 'QQグループ', privacyPolicy: 'プライバシーポリシー', + displaySettings: '表示設定', + displaySettingsDesc: 'ゲームの視覚効果を調整', + backgroundAnimation: '背景アニメーション', + backgroundAnimationDesc: '有効にすると星空/パーティクル背景アニメーションを表示(パフォーマンスに影響する可能性があります)', notifications: '通知設定', notificationsDesc: 'ゲーム内の通知アラートを管理', notificationTypes: '通知タイプ', @@ -1001,7 +1036,48 @@ export default { npcNameUpdateConfirm: '名前を更新', npcNameUpdateCancel: '現状維持', npcNameUpdateSuccess: '{count}件のNPC名を更新しました', - npcNameUpdateSkipped: 'NPC名の更新をスキップしました' + npcNameUpdateSkipped: 'NPC名の更新をスキップしました', + // WebDAV + webdav: { + title: 'クラウド同期', + desc: 'WebDAVでセーブデータを同期', + config: '設定', + configTitle: 'WebDAV設定', + configDesc: 'クラウド同期のためのWebDAVサーバーを設定', + notConfigured: '先にWebDAVサーバーを設定してください', + serverUrl: 'サーバーURL', + serverUrlPlaceholder: '例: https://dav.example.com', + serverUrlHint: 'WebDAVサーバーのアドレスを入力', + username: 'ユーザー名', + usernamePlaceholder: 'ユーザー名を入力', + password: 'パスワード', + passwordPlaceholder: 'パスワードを入力', + passwordHint: 'パスワードはローカルにのみ保存されます', + basePath: '保存パス', + basePathPlaceholder: '例: /ogame-saves/', + testConnection: '接続テスト', + testing: 'テスト中...', + testSuccess: '接続成功', + testFailed: '接続失敗', + save: '保存', + clearConfig: 'クリア', + configSaved: '設定を保存しました', + configCleared: '設定をクリアしました', + upload: 'アップロード', + uploading: 'アップロード中...', + uploadSuccess: 'アップロード成功', + uploadFailed: 'アップロード失敗', + download: 'ダウンロード', + downloadSuccess: 'ダウンロード成功', + downloadFailed: 'ダウンロード失敗', + selectFile: 'セーブファイルを選択', + selectFileDesc: '復元するセーブファイルを選択してください', + noFiles: 'セーブファイルが見つかりません', + loadFailed: 'ファイル一覧の読み込みに失敗しました', + confirmDelete: '"{name}" を削除してもよろしいですか?', + deleteSuccess: 'ファイルを削除しました', + deleteFailed: '削除に失敗しました' + } }, notifications: { constructionComplete: '建設完了', @@ -1023,8 +1099,8 @@ export default { officers: '士官', modifyResources: '資源を変更', resourcesDesc: '惑星の資源を素早く変更', - maxAllResources: '', - maxAllResourcesSuccess: '', + maxAllResources: 'すべて最大化', + maxAllResourcesSuccess: 'すべての資源が最大化されました', modifyBuildings: '建物を変更', buildingsDesc: '建物レベルを素早く設定', modifyResearch: '研究を変更', @@ -1065,10 +1141,11 @@ export default { dangerZoneDesc: '以下の操作は元に戻せません', resetGame: 'ゲームをリセット', resetGameConfirm: 'ゲームをリセットしてもよろしいですか?すべてのデータが削除されます!', - completeAllQueues: '', - completeAllQueuesDesc: '', - completeQueues: '', - completeQueuesSuccess: '' + completeAllQueues: 'すべてのキューを完了', + completeAllQueuesDesc: 'すべての建設、研究、艦船、防衛キューおよび艦隊ミッションを即座に完了', + completeQueues: 'キューを完了', + completeQueuesSuccess: + '{buildingCount}件の建設キュー、{researchCount}件の研究キュー、{missionCount}件の艦隊ミッション、{missileCount}件のミサイル攻撃を完了しました' }, alerts: { incomingFleets: '{count}機の敵艦隊が接近中', @@ -1125,10 +1202,10 @@ export default { recentEvents: '最近のイベント', recentEventsDescription: '最近の外交活動ログ', ago: '前', - notifications: '', - markAllRead: '', - noReports: '', - viewAll: '', + notifications: '外交通知', + markAllRead: 'すべて既読にする', + noReports: '外交イベントなし', + viewAll: 'すべて表示', status: { friendly: '友好的', neutral: '中立', @@ -1203,6 +1280,19 @@ export default { npcEliminatedMessage: 'あなたは{npcName}のすべての惑星を破壊しました!この勢力は完全に壊滅しました。' }, searchPlaceholder: 'NPC名で検索...', + notificationType: { + tradeOffer: '貿易提案', + intelReport: '諜報報告', + jointAttack: '共同攻撃の招待' + }, + notificationBadge: { + trade: '貿易', + intel: '諜報', + jointAttack: '招待' + }, + notificationExtra: { + pending: '保留中' + }, viewMode: { card: 'カード', list: 'リスト' @@ -1218,6 +1308,21 @@ export default { medium: '普通', hard: '難しい' }, + aiType: 'AIタイプ', + aiTypes: { + aggressive: '侵略型', + defensive: '防御型', + trader: '商人型', + expansionist: '拡張型', + balanced: 'バランス型' + }, + aiTypeDescriptions: { + aggressive: '積極的に偵察と攻撃、強烈な反撃', + defensive: 'めったに攻撃しない、攻撃されると強く反撃', + trader: 'ほとんど攻撃せず、取引と贈り物を好む', + expansionist: '発展に注力、攻撃は少ない', + balanced: '状況に応じて戦略を動的に調整' + }, reputation: '評判', spyProbes: '偵察機数', fleetPower: '艦隊戦力', @@ -1244,27 +1349,11 @@ export default { attackCooldown: '攻撃クールダウン中({min}分{sec}秒)', notSpiedYet: '未偵察、先に偵察が必要' } - }, - aiType: 'AIタイプ', - aiTypes: { - aggressive: '攻撃型', - defensive: '防御型', - trader: '商人型', - expansionist: '拡張型', - balanced: 'バランス型' - }, - aiTypeDescriptions: { - aggressive: '積極的に偵察・攻撃、強い報復', - defensive: '滅多に攻撃しない、攻撃されると強く報復', - trader: 'ほとんど攻撃しない、取引と贈り物を好む', - expansionist: '発展に集中、攻撃性が低い', - balanced: '状況に応じて戦略を動的に調整' } }, pagination: { previous: '前へ', next: '次へ', - gotIt: '', first: '最初', last: '最後', page: '{page}ページ' @@ -1328,9 +1417,33 @@ export default { seconds: '秒' }, tutorial: { + progress: '進捗', + previous: '前へ', + next: '次へ', + gotIt: '了解', + completeButton: '完了', + skip: 'ガイドをスキップ', welcome: { - title: 'OGame-Vue-Ts へようこそ', - content: 'ようこそ、司令官!基礎から始めて、宇宙帝国を築きましょう。' + title: 'OGameへようこそ', + content: 'ようこそ、司令官!このチュートリアルでは帝国建設の基礎を学びます。「次へ」をクリックして征服の旅を始めましょう。' + }, + resources: { + title: '資源概要', + content: + 'これらがあなたの資源です:金属、クリスタル、デューテリウム。建物の建設と科学技術の研究に不可欠です。エネルギーも重要で、インフラに電力を供給します。' + }, + planet: { + title: 'あなたの惑星', + content: 'これがあなたの母星です。ここで惑星名、座標を確認でき、帝国を拡張する際に惑星を切り替えることができます。' + }, + navigation: { + title: 'ナビゲーションメニュー', + content: + 'このメニューを使用して、建物、研究、艦隊、銀河などの異なるセクション間を移動します。各セクションには独自のゲーム機能があります。' + }, + gotoBuildings: { + title: '建物ページへ移動', + content: 'まず建物の建設から始めましょう。「建物」メニューをクリックして利用可能な建物を表示します。' }, buildSolarPlant: { title: '太陽光発電所を建設', @@ -1342,16 +1455,108 @@ export default { content: '建物は建設キューに追加されました。右上のキューアイコンをクリックすると、進行中のすべての建設と研究タスクを確認できます。建設には時間がかかりますが、待機中も作業を続けられます。' }, + buildMetalMine: { + title: '金属鉱山を建設', + content: 'エネルギーがあれば、金属鉱山を建設できます。金属鉱山は主要な金属源であり、金属はほぼすべての建物と艦船に使用されます。' + }, + buildCrystalMine: { + title: 'クリスタル鉱山を建設', + content: 'クリスタルはより希少ですが、高度な技術には不可欠です。クリスタル鉱山を建設してこの貴重な資源の収集を開始します。' + }, + buildDeuterium: { + title: 'デューテリウム合成器を建設', + content: 'デューテリウムは艦船の燃料と高度な研究に必要です。デューテリウム合成器を建設してこの重要な資源の生産を開始します。' + }, + upgradeMines: { + title: '資源鉱山をアップグレード', + content: + '次に、3つの資源鉱山(金属、クリスタル、デューテリウム)をレベル2にアップグレードして、ロボット工場の建設要件を満たす必要があります。資源が十分になったら、アップグレードを続けてください。' + }, + buildRobotics: { + title: 'ロボット工場を建設', + content: + 'ロボット工場は建設速度を大幅に向上させます。金属鉱山、クリスタル鉱山、デューテリウム合成器がそれぞれレベル2に達している必要があります。建設して建設効率を向上させましょう!' + }, + upgradeMinesForLab: { + title: '資源鉱山のアップグレードを続ける', + content: + '今度は3つの資源鉱山をレベル3にアップグレードして、研究ラボの建設要件を満たす必要があります。資源生産能力の発展を続けてください。' + }, + buildResearchLab: { + title: '研究ラボを建設', + content: + '研究ラボは技術進歩の基礎です。3つの資源鉱山がそれぞれレベル3に達している必要があります。建設して科学技術研究をアンロックしましょう!' + }, + gotoResearch: { + title: '研究ページへ移動', + content: '研究ラボができたので、「研究」メニューをクリックして利用可能な技術を表示します。' + }, + researchEnergy: { + title: 'エネルギー技術を研究', + content: 'エネルギー技術はエネルギー出力を向上させ、高度な建物をアンロックします。これは最も基本的で重要な技術の1つです。' + }, + shipyardIntro: { + title: '艦隊と造船所', + content: + '艦船により銀河を探索し、資源を輸送し、帝国を守ることができます。艦船を建造するには、造船所が必要です(ロボット工場レベル2が必要)。' + }, + gotoBuildingsForShipyard: { + title: '建物ページに戻る', + content: '建物ページに戻って造船所を建設します。' + }, + buildShipyard: { + title: '造船所を建設', + content: '造船所では艦船と防御システムを建造できます。これは艦隊作戦に不可欠です。' + }, + fleetIntro: { + title: '艦隊作戦', + content: '艦船を所有したら、ミッションに派遣できます:資源を輸送、惑星を植民、敵を攻撃、または廃墟場を探索します。' + }, + galaxyIntro: { + title: '銀河を探索', + content: '銀河ビューには他の惑星、廃墟場、拡張の機会が表示されます。これを使用してターゲットを偵察し、戦略を計画します。' + }, + complete: { + title: 'チュートリアル完了!', + content: + 'おめでとうございます、司令官!基礎知識を習得しました。帝国の建設を続け、技術を研究し、銀河を探索してください。覚えておいてください:まずエネルギーを発展させ、次に資源を建設し、その後に工場と研究を!幸運を祈ります!' + }, + // モバイルチュートリアル mobile: { welcome: { - title: 'OGame-Vue-Ts へようこそ(モバイル版)', + title: 'OGameへようこそ(モバイル版)', content: 'ようこそ、司令官!これはタッチスクリーン向けに最適化された簡易チュートリアルです。帝国建設を始めるために、コア機能を素早くご紹介します。' }, + resources: { + title: '上部リソースバー', + content: '上部にあなたの資源が表示されます:金属、クリスタル、デューテリウム。タップすると詳細な生産情報を表示できます。' + }, + menu: { + title: 'ナビゲーションメニューを開く', + content: 'このメニューアイコンをタップしてナビゲーションバーを開き、建物、研究、艦隊などのすべての機能にアクセスできます。' + }, + gotoBuildings: { + title: '建物ページへ移動', + content: 'メニューが開きました!「建物」オプションをタップして、インフラの建設を開始します。' + }, + buildSolarPlant: { + title: '太陽光発電所を建設', + content: 'まず太陽光発電所を建設しましょう!下にスクロールして見つけ、カードをタップして建設します。エネルギーはすべての基礎です。' + }, waitBuild: { title: '建設キュー', content: - '右上のキューアイコンをクリックして建設進度を確認できます。他のページを閲覧し続けることができます。建設はバックグラウンドで進行します。' + '右上のキューアイコンをタップして建設進度を確認できます。他のページを閲覧し続けることができます。建設はバックグラウンドで進行します。' + }, + buildMetalMine: { + title: '金属鉱山を建設', + content: 'エネルギーがあれば、金属鉱山を建設します。下にスクロールして金属鉱山を見つけ、建設をタップします。' + }, + complete: { + title: 'クイックチュートリアル完了!', + content: + '素晴らしい!基本操作をマスターしました。クリスタル鉱山とデューテリウム合成器の建設を続け、他の機能を探索してください。覚えておいてください:まずエネルギー、次に資源!' } } }, @@ -1408,11 +1613,21 @@ export default { title: '戦闘シミュレーター', message: '攻撃前に戦闘結果をシミュレート。双方の艦隊と技術レベルを入力して、勝敗と損失を予測。' }, + campaign: { + title: 'キャンペーンモード', + message: + '銀河のストーリーキャンペーンを探索!ミッションを完了してリソース報酬を獲得し、新しい挑戦をアンロック。各ノードにはユニークな目標と敵がいます。' + }, achievements: { title: '実績システム', message: 'ゲーム目標を達成して実績をアンロックし、ダークマター報酬を獲得!実績には複数のティアがあり、高い目標に挑戦してより良い報酬を手に入れましょう。' }, + ranking: { + title: 'ランキング', + message: + '他のプレイヤーやNPCと進捗を比較。建物、研究、艦隊、防御のポイントに基づくランキングを確認。ランキング上位を目指しましょう!' + }, settings: { title: '設定', message: 'ここでゲームデータの管理、通知設定、セーブのエクスポート/インポートができます。定期的にバックアップを!' @@ -1537,5 +1752,325 @@ export default { you: 'あなた', scoreBreakdown: 'スコア内訳', noData: 'ランキングデータがありません' + }, + // NPC強化行動通知 + npcBehavior: { + tradeOfferReceived: '取引提案を受信', + tradeOfferDesc: '{npcName}から取引提案が届きました', + attitudeChanged: 'NPC態度変化', + becameFriendly: '{npcName}があなたに友好的になりました', + becameHostile: '{npcName}があなたに敵対的になりました', + intelReceived: '情報を受信', + intelReceivedDesc: '{npcName}が敵の情報を共有しました', + jointAttackInvite: '共同攻撃への招待', + jointAttackInviteDesc: '{npcName}が敵への共同攻撃に招待しています', + aidReceived: '援助を受信', + aidReceivedDesc: '{npcName}が{amount}の資源を送りました', + allyDefense: '同盟防衛', + allyDefenseDesc: '{npcName}があなたの惑星を防衛するために艦隊を派遣しています', + trade: { + title: '取引提案', + from: '送信者', + offers: '提供', + requests: '要求', + expiresIn: '有効期限', + expired: '期限切れ', + accept: '承諾', + decline: '拒否', + noOffers: '取引提案なし', + acceptSuccess: '取引完了!', + acceptFailed: '資源不足で取引できません', + declined: '取引を拒否しました', + ratio: '交換レート' + }, + intel: { + title: '情報レポート', + from: '情報源', + target: '対象NPC', + type: '情報タイプ', + types: { + enemyFleet: '艦隊情報', + enemyResources: '資源情報', + enemyMovement: '動向情報' + }, + fleetInfo: '艦隊情報', + resourceInfo: '資源情報', + movementInfo: '動向情報', + noReports: '情報レポートなし', + markAsRead: '既読にする', + content: '情報内容', + noFleet: '艦隊は検出されませんでした', + noData: 'データなし', + targetPosition: '目標座標', + missionType: 'ミッションタイプ' + }, + jointAttack: { + title: '共同攻撃招待', + from: '発起者', + target: '対象NPC', + targetPlanet: '対象惑星', + npcFleet: 'NPC艦隊', + lootShare: '戦利品分配', + expiresIn: '有効期限', + expired: '期限切れ', + accept: '攻撃に参加', + decline: '拒否', + noInvites: '共同攻撃招待なし', + acceptSuccess: '共同攻撃に参加しました!', + declined: '招待を拒否しました', + targetInfo: '攻撃目標', + expectedShare: '予想分配', + remaining: '残り時間' + }, + aid: { + title: '資源援助', + from: '送信者', + resources: '援助資源', + noAid: '援助記録なし' + }, + attitudeChange: { + title: '態度変化', + npc: 'NPC', + previous: '以前', + current: '現在', + reason: '理由', + reasons: { + attitude_swing: '態度の変動', + gift: '贈り物を受け取った', + attack: '攻撃された', + naturalSwing: '自然変動', + giftReceived: '贈り物を受け取った', + attacked: '攻撃された', + reputationThreshold: '評判閾値' + } + }, + allyAction: { + title: '同盟行動', + defense: '防衛支援', + defenseDesc: '{npcName}が{targetPlanet}の防衛に艦隊を派遣', + jointAttackStarted: '共同攻撃開始', + jointAttackStartedDesc: '{targetNpc}への共同攻撃が開始されました', + reputationBonus: '評判ボーナス', + reputationBonusDesc: '同盟の{npcName}が{targetNpc}にあなたのことを良く言っています' + } + }, + campaign: { + name: 'キャンペーン', + description: '神秘的な銀河を探索し、古代の秘密を解き明かす', + totalProgress: '総進捗', + questsCompleted: 'クエスト完了', + chapter: '章', + branch: '分岐', + startQuest: 'クエスト開始', + claimRewards: '報酬を受け取る', + objectives: '目標', + objectivesLabel: '目標', + rewards: '報酬', + completed: '完了', + inProgress: '進行中', + available: '受注可能', + locked: 'ロック中', + notifications: { + questStarted: 'クエスト開始', + questCompleted: 'クエスト完了!', + rewardsClaimed: '報酬を獲得しました', + objectiveCompleted: '目標達成', + chapterUnlocked: '新章が解放されました', + reputationUp: '{npcName}との評判が{value}上昇しました', + reputationDown: '{npcName}との評判が{value}低下しました', + branchUnlocked: '新しいストーリー分岐が解放されました!' + }, + dialogue: { + skip: 'スキップ', + continue: '続ける', + finish: '完了', + player: '司令官', + npc: 'NPC', + narrator: 'ナレーター', + mysterious: '謎の信号', + unknownSource: '不明な発信源', + choiceEffect: '選択肢の効果' + }, + chapters: { + '1': { + title: '起源', + description: '故郷を築き、宇宙への第一歩を踏み出す', + backgroundStory: + 'あなたは初めての惑星を手に入れた若き宇宙司令官です。この広大な宇宙で、故郷を築き、技術を発展させ、銀河の深淵を探索していきます...' + }, + '2': { + title: '探索', + description: '宇宙を探索し、古代遺跡を発見する', + backgroundStory: + '勢力が拡大するにつれ、深宇宙からの謎の信号があなたの注意を引きます。これらの信号は古代の秘密を指し示し、勇敢な探検者を待っているようです...' + }, + '3': { + title: '外交', + description: '他の勢力との関係を構築する', + backgroundStory: + '銀河にはあなただけではありません。他の文明が台頭しています。敵となるか同盟を結ぶか決めなければなりません。外交的知恵があなたの帝国の行く末を決めるでしょう...' + }, + '4': { + title: '暗影の台頭', + description: '強大な敵に立ち向かい、領土を守る', + backgroundStory: + '影に危険が潜んでいます。強大な敵対勢力があなたの領土を狙っています。戦争は避けられません。来たる嵐に備えなければなりません...' + }, + '5': { + title: '古代の秘密', + description: '銀河最深部の秘密を解き明かす', + backgroundStory: + 'すべての手がかりは銀河で最も神秘的な領域を指しています。そこには古代文明が残した究極の秘密が眠っています。すべてを明らかにする準備はできていますか?' + } + }, + quests: { + '1_1': { title: '故郷建設', description: 'インフラを整備し、惑星の基盤を築く' }, + '1_2': { title: '技術啓蒙', description: '基礎技術を研究し、技術の旅を始める' }, + '1_3': { title: '最初の船', description: '最初の戦艦を建造する' }, + '1_4': { title: '奇妙な隣人', description: '近隣システムの他の勢力を偵察する' }, + '1_5': { title: 'ファーストコンタクト', description: '近隣のNPC勢力と初期接触を確立する' }, + '2_1': { title: '開拓植民地', description: '最初の新惑星を植民地化する' }, + '2_2': { title: '深宇宙遠征', description: '艦隊を遠征ミッションに派遣する' }, + '2_3': { title: '謎の信号', description: '深宇宙からの謎の信号を調査する' }, + '2_4': { title: '遺跡調査', description: '発見した古代遺跡を探索する' }, + '2_5': { title: 'アーカイブ解読', description: '遺跡から得たデータを研究する' }, + '3_1': { title: '平和の使者', description: '外交でNPCとの関係を改善する' }, + '3_2': { title: '通商関係', description: '友好勢力と安定した関係を築く' }, + '3_3': { title: '共通の脅威', description: '潜在的な敵対勢力を発見する' }, + '3_4': { title: '同盟交渉', description: '友好NPCと正式な同盟を結ぶ' }, + '3_5': { title: '嵐への備え', description: '防衛施設を建設し、課題に備える' }, + '4_1': { title: '前哨攻撃', description: '敵対勢力の最初の攻撃を撃退する' }, + '4_2': { title: '情報収集', description: '敵の軍事配置を偵察する' }, + '4_3': { title: '反撃', description: '敵への反撃を開始する' }, + '4_4': { title: '資源争奪', description: '戦場のデブリをリサイクルして資源を得る' }, + '4_5': { title: '決戦前夜', description: '最終決戦に向けて強力な艦隊を建造する' }, + '5_1': { title: '遺跡の深部', description: '遺跡の最深部を探索する' }, + '5_2': { title: '古代技術', description: '古代文明の技術を解放する' }, + '5_3': { title: '最終対決', description: '謎の敵との最終決戦に臨む' }, + '5_4': { title: '新時代', description: '新たな植民地を築き、新時代を開く' }, + '5_5': { title: '遺産継承', description: '発展を続け、より多くのシステムを征服する' } + }, + objectiveTypes: { + buildBuilding: '{building}をレベル{level}に建設', + researchTech: '{tech}をレベル{level}まで研究', + produceShips: '{ship}を{count}隻生産', + accumulateResources: '{resource}を{amount}蓄積', + defeatNPC: '{npc}を撃破', + winBattles: '{count}回戦闘に勝利', + recycleDebris: 'デブリを{amount}リサイクル', + reachRelation: '{npc}と{level}の関係に到達', + sendGift: '{npc}に{count}回贈り物を送る', + formAlliance: '{npc}と同盟を結ぶ', + colonize: '{count}個の惑星を植民地化', + expedition: '{count}回の遠征を完了', + spyTarget: '{target}をスパイ' + }, + errors: { + questNotFound: 'クエストが見つかりません', + questNotAvailable: 'クエストは利用できません', + questNotActive: 'クエストはアクティブではありません', + questNotCompleted: 'クエスト未完了', + rewardsAlreadyClaimed: '報酬は既に受け取り済み', + prerequisiteNotMet: '前提クエスト未完了' + }, + speakers: { + ancientVoice: '古代の声', + neighborNPC: '隣接勢力', + mysteriousSignal: '謎の信号', + enemyCommander: '敵司令官' + }, + objectiveDescriptions: { + buildMetalMine: '金属鉱山をレベル2に建設', + buildCrystalMine: 'クリスタル鉱山をレベル2に建設', + buildSolarPlant: 'ソーラープラントをレベル2に建設', + buildResearchLab: '研究所をレベル1に建設', + researchEnergy: 'エネルギー技術をレベル1まで研究', + buildShipyard: '造船所をレベル2に建設', + researchCombustion: '燃焼ドライブをレベル1まで研究', + buildLightFighters: 'ライトファイター5機を建造', + researchEspionage: 'スパイ技術をレベル2まで研究', + buildSpyProbes: 'スパイプローブ3機を建造', + spyAnyNPC: 'NPC惑星をスパイ', + sendGiftToNPC: 'NPCに贈り物を送る', + researchAstrophysics: '宇宙物理学をレベル1まで研究', + buildColonyShip: 'コロニーシップを建造', + colonizeNewPlanet: '新惑星を植民地化', + completeExpedition: '遠征ミッションを完了', + discoverRuins: '古代遺跡を発見', + researchComputer: 'コンピュータ技術をレベル4まで研究', + improveRelation: 'NPCとの関係を改善', + reachFriendly: 'NPCと友好ステータスに到達', + spyHostileNPC: '敵対NPCをスパイ', + formAlliance: '友好NPCと同盟を結ぶ', + buildDefenses: '防衛施設を建設', + winDefenseBattle: '防衛戦に勝利', + spyEnemyPlanet: '敵惑星をスパイ', + attackEnemy: '敵を攻撃', + recycleDebris: 'デブリをリサイクル', + buildBattleships: 'バトルシップ10隻を建造', + exploreDeepRuins: '深部遺跡を探索', + researchHyperspace: 'ハイパースペース技術を研究', + defeatBoss: '謎の敵を撃破', + colonizeSpecial: '特別な場所を植民地化', + continueDevelopment: '発展を継続' + }, + dialogues: { + '1_1': { + prologue_1: '銀河へようこそ、若き司令官。この広大な宇宙があなたの探索を待っています。まずは故郷の惑星を建設しましょう。', + prologue_2: '新しい意識が目覚めるのを感じる...興味深い...どこまで行けるか見てみよう...' + }, + '1_2': { prologue_1: '基本インフラが完成しました。次は技術を発展させる時です。研究所を建設し、技術の旅を始めましょう。' }, + '1_3': { prologue_1: '技術のサポートで艦隊の建造が可能になりました。造船所を建設し、最初の戦艦を生産しましょう。' }, + '1_4': { + prologue_1: '艦隊が形になってきました。周囲の状況を把握しましょう。スパイプローブを送り出し、近隣の勢力を偵察してください。', + prologue_2: 'あなたは一人ではない...この銀河には他の文明が存在する...' + }, + '1_5': { + prologue_1: '近隣の勢力を発見しました。外交は芸術です。彼らとの接触を試みてください。', + epilogue_1: '贈り物をありがとう、司令官。友人になれることを願っています。', + epilogue_2: 'よい...繋がりを築くことは、より深い秘密を解き明かす第一歩だ...' + }, + '2_1': { + prologue_1: '勢力が確立しました。領土を拡大する時です。宇宙物理学を研究し、コロニーシップを建造して新しい惑星を探索しましょう。', + prologue_2: '宇宙は無限...より多くの惑星はより多くの可能性を意味する...' + }, + '2_2': { + prologue_1: '植民地化成功!しかし宇宙にはより深い秘密が待っています。艦隊を遠征ミッションに派遣しましょう。', + prologue_2: '遠くから微かな信号が...何かがそこであなたを待っている...' + }, + '2_3': { + prologue_1: '遠征で異常な信号を発見しました。これらの信号は古代文明からのようです...発信源を調査してください。', + epilogue_1: 'これらの記号は...古代文明の遺跡だ!さらに調査して秘密を解き明かそう。' + }, + '2_4': { prologue_1: '古代遺跡の場所を発見しました。艦隊を送り、何が見つかるか探索してください。' }, + '2_5': { prologue_1: '遺跡でデータアーカイブが見つかりました。このデータを研究すれば、新しい技術が解放できるかもしれません。' }, + '3_1': { prologue_1: '探索中も外交を忘れないでください。周囲の勢力と良好な関係を維持することは有益です。' }, + '3_2': { prologue_1: 'いくつかの勢力が友好を示しています。関係を深め続ければ、より多くのサポートを得られるかもしれません。' }, + '3_3': { prologue_1: '情報によると敵対勢力が影からあなたを監視しています。警戒を怠らず、彼らの動きを偵察してください。' }, + '3_4': { prologue_1: '友好勢力と正式な同盟を結び、脅威に対してお互いをサポートしましょう。' }, + '3_5': { prologue_1: '脅威が迫っています。防衛施設を建設し、可能な紛争に備えてください。' }, + '4_1': { + prologue_1: '敵が攻撃を開始しました!惑星を守ってください!', + epilogue_1: '敵の第一波を撃退しました。しかしこれは始まりに過ぎません...' + }, + '4_2': { prologue_1: '敵は撤退しましたが、戻ってくるでしょう。彼らの惑星を偵察して戦力を把握してください。' }, + '4_3': { prologue_1: '反撃の時です。敵の惑星を攻撃し、彼らの戦力を弱めてください。' }, + '4_4': { prologue_1: '戦場に多くのデブリが残っています。これらの資源をリサイクルして次の戦闘に備えてください。' }, + '4_5': { prologue_1: '最終決戦が近づいています。強力な艦隊を建造し、究極の挑戦に備えてください。' }, + '5_1': { + prologue_1: 'すべての手がかりは遺跡の最深部を指しています。古代文明の核心的な秘密がそこにあります。', + prologue_2: 'ついに到着した...真実がまもなく明かされる...' + }, + '5_2': { prologue_1: '遺跡の深部で失われた古代技術を発見しました。研究してその力を解放してください。' }, + '5_3': { + prologue_1: '謎の敵が現れました。これが最後の挑戦です。撃破してください!', + epilogue_1: 'やりました!古代の守護者は倒されました。銀河の秘密は今やあなたに開かれています。' + }, + '5_4': { prologue_1: 'ついに平和が訪れました。この新時代に新しい植民地を築き、帝国を拡大してください。' }, + '5_5': { + prologue_1: 'あなたの伝説は始まったばかりです。さらに探索を続け、より多くの星系を征服してください!', + epilogue_1: '銀河は広大で果てしなく、数え切れない秘密があなたを待っています...' + } + } } } diff --git a/src/locales/ko.ts b/src/locales/ko.ts index f002b1b..b7bb512 100644 --- a/src/locales/ko.ts +++ b/src/locales/ko.ts @@ -11,29 +11,11 @@ export default { common: { confirm: '확인', cancel: '취소', - delete: '삭제', - edit: '편집', save: '저장', close: '닫기', - back: '돌아가기', - next: '다음', - gotIt: '', - previous: '이전', - submit: '제출', - reset: '초기화', - search: '검색', - filter: '필터', - loading: '로딩 중...', - noData: '데이터 없음', - error: '오류', + gotIt: '알겠습니다', success: '성공', - warning: '경고', - info: '정보', resourceType: '자원 유형', - playerName: '사령관', - timeHour: '시간', - timeMinute: '분', - timeSecond: '초', featureLocked: '기능 잠김', unlockRequired: '건물 필요', requiredBuilding: '필요한 건물', @@ -41,7 +23,6 @@ export default { goToBuildings: '건물로 이동', locked: '잠김', viewRequirements: '요구사항 보기', - requirements: '요구사항', requirementsNotMet: '요구사항 미충족', current: '현재', level: '레벨', @@ -51,7 +32,8 @@ export default { viewDetails: '상세 보기', exitConfirmTitle: '게임 종료', exitConfirmMessage: '게임을 종료하시겠습니까? 진행 상황은 자동으로 저장됩니다.', - points: '포인트' + points: '포인트', + retry: '재시도' }, errors: { requirementsNotMet: '전제 조건 미충족', @@ -88,13 +70,13 @@ export default { galaxy: '은하계', diplomacy: '외교', achievements: '업적', + campaign: '캠페인', ranking: '랭킹', messages: '메시지', settings: '설정', gm: 'GM' }, sidebar: { - language: '언어', lightMode: '라이트 모드', darkMode: '다크 모드', collapse: '메뉴 접기', @@ -119,9 +101,6 @@ export default { }, energy: { lowWarning: '에너지 부족! 자원 생산 중단!', - severeWarning: '에너지 부족! 자원 생산 중단!', - criticalWarning: '에너지 부족! 자원 생산 중단!', - noProduction: '에너지 부족! 자원 생산 중단!', deficitDetail: '에너지 부족: {deficit}, 발전소를 더 건설하세요', buildSolarPlant: '발전소 건설' }, @@ -132,27 +111,20 @@ export default { lowResources: '곧 고갈: {resources}' }, planet: { - planet: '행성', moon: '위성', - colony: '식민지', position: '위치', - coordinates: '좌표', switchToMoon: '위성 보기', backToPlanet: '모행성으로 돌아가기', switchPlanet: '행성 전환', currentPlanet: '현재 행성', - fields: '필드', temperature: '온도', homePlanet: '모행성', planetPrefix: '행성', - moonSuffix: '의 위성', colonyPrefix: '식민지', renamePlanet: '행성 이름 변경', renamePlanetTitle: '행성 이름 변경', - newPlanetName: '새 이름', planetNamePlaceholder: '새 행성 이름 입력', - rename: '이름 변경', - renameSuccess: '행성 이름이 {name}(으)로 변경되었습니다' + rename: '이름 변경' }, player: { points: '총 점수' @@ -179,13 +151,12 @@ export default { sensorPhalanx: '센서 팔랑크스', jumpGate: '점프 게이트', planetDestroyerFactory: '행성 파괴 공장', + geoResearchStation: '지질 연구소', + deepDrillingFacility: '심층 시추 시설', buildTime: '건설 시간', - build: '', + build: '건설', production: '생산량', consumption: '소비', - totalCost: '총 비용', - totalPoints: '총 점수', - levelRange: '레벨 범위', capacity: 'Capacity/Effect', storageCapacity: 'Capacity', energyProduction: 'Energy Production', @@ -194,7 +165,6 @@ export default { buildQueueBonus: '건설 대기열', spaceBonus: '공간 보너스', buildSpeedBonus: '건설 속도 보너스', - researchSpeedBonus: '연구 속도 보너스', planetSpace: 'Planet Space', moonSpace: 'Moon Space', missileCapacity: 'Missile Capacity', @@ -228,7 +198,9 @@ export default { lunarBase: '달 가용 공간 증가, 레벨당 +30 공간', sensorPhalanx: '주변 행성계의 함대 활동 감지', jumpGate: '다른 위성으로 함대 순간 이동', - planetDestroyerFactory: '행성을 파괴할 수 있는 궁극 병기 건조' + planetDestroyerFactory: '행성을 파괴할 수 있는 궁극 병기 건조', + geoResearchStation: '지질 구조를 연구하여 광맥 자연 회복 속도를 높입니다. 레벨당 회복 속도 50% 증가', + deepDrillingFacility: '' }, ships: { lightFighter: '경전투기', @@ -295,14 +267,16 @@ export default { totalCost: '총 비용', totalPoints: '총 점수', levelRange: '레벨 범위', - capacity: 'Capacity/Effect', - storageCapacity: 'Capacity', - energyProduction: 'Energy Production', - fleetStorage: 'Fleet Storage', - buildQueue: 'Build Queue', - planetSpace: 'Planet Space', - moonSpace: 'Moon Space', - missileCapacity: 'Missile Capacity' + + attackBonus: '공격 보너스', + shieldBonus: '실드 보너스', + armorBonus: '장갑 보너스', + spyLevel: '정찰 레벨', + researchQueueBonus: '연구 대기열', + colonySlots: '식민지 슬롯', + forAllPlanets: '(전역)', + speedBonus: '속도 보너스', + researchSpeedBonus: '연구 속도 보너스' }, technologies: { energyTechnology: '에너지 기술', @@ -322,7 +296,8 @@ export default { hyperspaceDrive: '초공간 엔진', darkMatterTechnology: '암흑 물질 기술', terraformingTechnology: '지형 변환 기술', - planetDestructionTech: '행성 파괴 기술' + planetDestructionTech: '행성 파괴 기술', + miningTechnology: '' }, technologyDescriptions: { energyTechnology: '에너지 이용 효율 향상', @@ -343,7 +318,8 @@ export default { hyperspaceDrive: '고급 추진 기술', darkMatterTechnology: '암흑 물질의 성질과 응용 연구', terraformingTechnology: '행성 지형 개조 기술 연구, 레벨당 모든 행성의 가용 공간 30 증가', - planetDestructionTech: '행성 전체를 파괴하는 공포의 기술 연구' + planetDestructionTech: '행성 전체를 파괴하는 공포의 기술 연구', + miningTechnology: '' }, officers: { commander: '사령관', @@ -367,8 +343,9 @@ export default { queue: { title: '진행 중인 작업', empty: '활성 대기열 없음', - buildQueue: '건설 대기열', - researchQueue: '연구 대기열', + buildQueueBonus: '건설 대기열', + spaceBonus: '공간 보너스', + researchQueueBonus: '연구 대기열', building: '건설 중', researching: '연구 중', demolishing: '철거 중', @@ -378,7 +355,7 @@ export default { cancelResearch: '연구 취소', confirmCancel: '취소하시겠습니까? 자원의 50%가 환불됩니다.', level: '레벨', - gmModeActivated: '', + quantity: '수량', upgradeToLevel: '레벨로 업그레이드', tabs: { all: '전체', @@ -397,14 +374,9 @@ export default { movedToQueue: '작업이 대기열로 이동되었습니다' }, overview: { - title: '행성 개요', resourceOverview: '자원 개요', fleetInfo: '함대', currentShips: '현재 행성의 함선 수', - productionSources: '생산 소스', - productionSourcesDesc: '상세 자원 생산 및 보너스 정보', - consumptionSources: '소비 소스', - consumptionSourcesDesc: '건물 에너지 소비 세부 정보', totalProduction: '총 생산량', totalConsumption: '총 소비량', noConsumption: '에너지 소비 없음', @@ -414,13 +386,8 @@ export default { }, buildingsView: { title: '건물', - usedSpace: '사용된 공간', spaceUsage: '공간 사용', - level: '레벨', - gmModeActivated: '', upgradeCost: '업그레이드 비용', - buildTime: '건설 시간', - build: '건설', upgrade: '업그레이드', maxLevelReached: '최대 레벨 도달', requirementsNotMet: '요구 사항 미충족', @@ -430,8 +397,7 @@ export default { demolishRefund: '철거 환불', demolishFailed: '철거 실패', demolishFailedMessage: '이 건물을 철거할 수 없습니다. 건설 대기열이 가득 찼거나 건물 레벨이 0인지 확인하세요.', - confirmDemolish: '철거 확인', - confirmDemolishMessage: '다음 건물을 철거하시겠습니까?' + confirmDemolish: '철거 확인' }, researchView: { title: '연구', @@ -442,26 +408,13 @@ export default { researchFailedMessage: '자원이 충분한지, 전제 조건이 충족되었는지, 또는 다른 연구 작업이 있는지 확인하세요.' }, shipyard: { - attack: '공격력', - missileAttack: '미사일 공격', - shield: '쉴드', - armor: '장갑', speed: '속도', cargoCapacity: '화물 용량', - fuelConsumption: '연료 소비', - buildCost: '건설 비용', - buildTime: '건설 시간', - build: '', - perUnit: '단위당', - batchCalculator: '일괄 계산기', - quantity: '수량', - totalCost: '총 비용', - totalTime: '총 시간' + fuelConsumption: '연료 소비' }, shipyardView: { title: '조선소', fleetStorage: '함대 저장소', - owned: '보유', attack: '공격력', missileAttack: '미사일 공격', shield: '실드', @@ -483,7 +436,7 @@ export default { armor: '장갑', buildCost: '건설 비용', buildTime: '건설 시간', - build: '', + build: '건설', perUnit: '단위당', batchCalculator: '일괄 계산기', quantity: '수량', @@ -536,6 +489,7 @@ export default { missionInfo: '임무 정보', fuelConsumption: '연료 소비', flightTime: '비행 시간', + outOfRange: '사정거리 밖', attackMission: '공격', transport: '수송', colonize: '식민', @@ -566,6 +520,7 @@ export default { } }, recycle: '회수', + destroy: '행성 파괴', transportResources: '자원 수송', totalCargoCapacity: '총 적재량', used: '사용됨', @@ -577,11 +532,12 @@ export default { arrivalTime: '도착 시간', returnTime: '귀환 시간', recallFleet: '함대 소환', - abortMission: '', - abortMissionTitle: '', - abortMissionWarning: '', - abortMissionSuccess: '', - abortMissionSuccessMessage: '', + abortMission: '임무 중단', + abortMissionTitle: '임무 중단 확인', + abortMissionWarning: + '경고: 이 임무를 중단하면 {ships}척의 함선과 {resources}의 자원이 영구적으로 손실됩니다!\n\n이 작업은 되돌릴 수 없으며 함대와 자원은 돌아오지 않습니다.', + abortMissionSuccess: '임무 중단됨', + abortMissionSuccessMessage: '임무가 중단되었으며, 함대와 자원이 손실되었습니다.', sendFailed: '파견 실패', sendFailedMessage: '함대 수, 연료 충분 여부 또는 적재량 한계를 확인하세요.', recallFailed: '소환 실패', @@ -650,7 +606,6 @@ export default { benefitsBonus: '효과 보너스', resourceProduction: '자원 생산량', darkMatterProduction: '암흑 물질 생산량', - energyProduction: '에너지 생산량', buildingSpeed: '건설 속도', researchSpeed: '연구 속도', fleetSpeed: '함대 속도', @@ -679,14 +634,11 @@ export default { selectGalaxy: '은하계 선택', system: '행성계', selectSystem: '행성계 선택', - view: '보기', - myPlanet: '내 행성', myPlanets: '내 행성계 보기', npcPlanets: 'NPC 행성들', selectPlanetToView: '행성을 선택하여 행성계 보기', totalPositions: '총 10개 행성 위치', mine: '내 것', - hostile: '적대', emptySlot: '빈 자리 - 식민 가능', scout: '정찰', attack: '공격', @@ -709,10 +661,12 @@ export default { missileCount: '미사일 수량', availableMissiles: '사용 가능한 미사일', missileRange: '미사일 사정거리', - systems: '시스템', + systems: '성계', distance: '거리', flightTime: '비행 시간', + outOfRange: '사정거리 밖', launchMissile: '발사', + missileLaunched: '미사일이 발사되었습니다', cancel: '취소', colonizePlanetMessage: '위치 [{coordinates}]을(를) 식민하시겠습니까?\n\n함대 페이지로 이동하여 식민선을 파견하세요.', recyclePlanetMessage: '위치 [{coordinates}]의 잔해를 회수하시겠습니까?\n\n함대 페이지로 이동하여 회수선을 파견하세요.', @@ -722,6 +676,20 @@ export default { giftPlanetMessage: '행성 [{coordinates}]에 자원을 선물로 보내시겠습니까?\n\n함대 페이지로 이동하여 수송선을 선택하고 자원을 적재하세요.', npcPlanetName: '{name}의 행성', + phalanxScan: '센서 스캔', + phalanxScanTitle: '센서 팔랑크스 스캔', + phalanxScanDescription: '행성 [{coordinates}]의 함대 활동 스캔', + phalanxNoMoon: '스캔하려면 센서 팔랑크스가 있는 위성이 필요합니다', + phalanxCost: '스캔 비용', + phalanxNoFleets: '함대 활동 감지되지 않음', + phalanxFleetDetected: '{count}개의 함대 감지됨', + phalanxOrigin: '출발지', + phalanxDestination: '목적지', + phalanxArrival: '도착 시간', + phalanxReturn: '귀환 시간', + phalanxStatusOutbound: '이동 중', + phalanxStatusReturning: '귀환 중', + phalanxInsufficientDeuterium: '중수소 부족', intercepted: '요격됨', defenseLosses: '방어 손실' }, @@ -730,12 +698,12 @@ export default { battles: '전투', spy: '정찰', npc: 'NPC', - diplomacy: '', + diplomacy: '외교', battleReports: '전투 보고서', spyReports: '정찰 보고서', noBattleReports: '전투 보고서 없음', noSpyReports: '정찰 보고서 없음', - noDiplomaticReports: '', + noDiplomaticReports: '외교 보고서 없음', battleReport: '전투 보고서', spyReport: '정찰 보고서', victory: '승리', @@ -756,6 +724,8 @@ export default { defense: '방어', buildings: '건물', unread: '읽지 않음', + pending: '대기 중', + invalidData: '잘못된 데이터', targetPlanet: '목표 행성', attackerRemaining: '공격자 잔여', defenderRemaining: '방어자 잔여', @@ -808,36 +778,36 @@ export default { polite_decline: '정중하게 거절했습니다' }, // Spied notification dialog - spiedNotificationDetails: '', - spyDetected: '', - detectionResult: '', - detectionSuccess: '', - spiedNotificationMessage: '', - spiedNotificationTip: '', - viewInGalaxy: '', + spiedNotificationDetails: '정찰 알림 상세', + spyDetected: '스파이 탐지됨', + detectionResult: '탐지 결과', + detectionSuccess: '적의 스파이를 탐지했습니다!', + spiedNotificationMessage: '{npc}가 당신의 행성 {planet}을 정찰하려 했습니다', + spiedNotificationTip: '이 NPC가 적대적이라면 방어를 강화하거나 반격을 고려하세요', + viewInGalaxy: '은하에서 보기', // Mission report dialog - missionReportDetails: '', - missionSuccess: '', - missionFailed: '', - origin: '', - destination: '', - missionDetails: '', - transportedResources: '', - recycledResources: '', - remainingDebris: '', - newPlanet: '', + missionReportDetails: '임무 보고서 상세', + missionSuccess: '성공', + missionFailed: '실패', + origin: '출발지', + destination: '목적지', + missionDetails: '임무 상세', + transportedResources: '운송된 자원', + recycledResources: '재활용된 자원', + remainingDebris: '남은 잔해', + newPlanet: '새 행성', // NPC activity dialog - npcActivityDetails: '', + npcActivityDetails: 'NPC 활동 상세', activityType: { - recycle: '' + recycle: '잔해 재활용 중' }, - activityLocation: '', - position: '', - nearPlanet: '', - activityDescription: '', - npcActivityMessage: '', - arrivalTime: '', - npcActivityTip: '', + activityLocation: '활동 위치', + position: '위치', + nearPlanet: '근처 행성', + activityDescription: '활동 설명', + npcActivityMessage: '{npc}가 {position}에서 {activity}', + arrivalTime: '도착 시간', + npcActivityTip: 'NPC가 전투 잔해를 수집할 수 있습니다. 자원을 경쟁하려면 먼저 현장에 도착하세요', clearMessages: '메시지 삭제', clearMessageTypes: '삭제할 메시지 유형 선택', clearBattleReports: '전투 보고서', @@ -847,7 +817,11 @@ export default { clearNPCActivity: 'NPC 활동', clearGiftNotifications: '선물 알림', clearGiftRejected: '거절된 선물', - clearNow: '지금 삭제' + clearTradeOffers: '무역 제안', + clearIntelReports: '정보 보고서', + clearJointAttackInvites: '공동 공격 초대', + clearNow: '지금 삭제', + clearSuccess: '메시지가 삭제되었습니다' }, missionReports: { transportSuccess: '수송 임무가 성공적으로 완료되었습니다', @@ -955,7 +929,6 @@ export default { resume: '재개', gamePaused: '게임이 일시정지되었습니다', gameResumed: '게임이 재개되었습니다', - playerName: '플레이어 이름', gameSpeed: '자원 생산 속도', gameSpeedDesc: '현재 자원 생산 속도 배율', speedChanged: '자원 생산 속도가 {speed}x로 변경되었습니다', @@ -963,22 +936,23 @@ export default { reset: '재설정', about: '정보', version: '버전', - latestVersion: '최신 버전', checkUpdate: '업데이트 확인', checking: '확인 중...', newVersionAvailable: '새 버전 {version} 사용 가능', upToDate: '이미 최신 버전입니다', - checkUpdateCooldown: '나중에 다시 시도해주세요 (5분 쿨다운)', checkUpdateFailed: '업데이트 확인 실패, 네트워크 연결을 확인하세요', viewUpdate: '업데이트 보기', updateAvailable: '새 버전이 사용 가능합니다. 릴리스 노트를 보려면 클릭하세요.', download: '다운로드', - goToDownload: '다운로드로 이동', buildDate: '빌드 날짜', community: '커뮤니티', github: 'GitHub 저장소', qqGroup: 'QQ 그룹', privacyPolicy: '개인정보처리방침', + displaySettings: '디스플레이 설정', + displaySettingsDesc: '게임 시각 효과 조정', + backgroundAnimation: '배경 애니메이션', + backgroundAnimationDesc: '별하늘/입자 배경 애니메이션 표시 (성능에 영향을 줄 수 있음)', notifications: '알림 설정', notificationsDesc: '게임 내 알림 관리', notificationTypes: '알림 유형', @@ -996,13 +970,53 @@ export default { expandTypes: '세부 정보 펼치기', collapseTypes: '세부 정보 접기', // NPC 이름 업데이트 - npcNameUpdate: 'NPC 이름 업데이트', - npcNameUpdateTitle: '이전 형식 NPC 이름 감지됨', - npcNameUpdateMessage: '{count}개의 NPC가 이전 형식의 이름을 사용 중입니다. 새로운 현지화된 이름으로 업데이트하시겠습니까?', + npcNameUpdateTitle: '이전 NPC 이름 감지됨', + npcNameUpdateMessage: '이전 이름 형식을 사용하는 {count}개의 NPC가 발견되었습니다. 새로운 현지화 이름으로 업데이트하시겠습니까?', npcNameUpdateConfirm: '이름 업데이트', npcNameUpdateCancel: '현재 유지', - npcNameUpdateSuccess: '{count}개의 NPC 이름이 업데이트되었습니다', - npcNameUpdateSkipped: 'NPC 이름 업데이트 건너뜀' + npcNameUpdateSuccess: '{count}개의 NPC 이름이 성공적으로 업데이트되었습니다', + npcNameUpdateSkipped: 'NPC 이름 업데이트 건너뜀', + // WebDAV + webdav: { + title: '클라우드 동기화', + desc: 'WebDAV를 통해 세이브 파일 동기화', + config: '설정', + configTitle: 'WebDAV 설정', + configDesc: '클라우드 동기화를 위한 WebDAV 서버 설정', + notConfigured: '먼저 WebDAV 서버를 설정하세요', + serverUrl: '서버 URL', + serverUrlPlaceholder: '예: https://dav.example.com', + serverUrlHint: 'WebDAV 서버 주소를 입력하세요', + username: '사용자 이름', + usernamePlaceholder: '사용자 이름 입력', + password: '비밀번호', + passwordPlaceholder: '비밀번호 입력', + passwordHint: '비밀번호는 로컬에만 저장됩니다', + basePath: '저장 경로', + basePathPlaceholder: '예: /ogame-saves/', + testConnection: '연결 테스트', + testing: '테스트 중...', + testSuccess: '연결 성공', + testFailed: '연결 실패', + save: '저장', + clearConfig: '지우기', + configSaved: '설정이 저장되었습니다', + configCleared: '설정이 삭제되었습니다', + upload: '업로드', + uploading: '업로드 중...', + uploadSuccess: '업로드 성공', + uploadFailed: '업로드 실패', + download: '다운로드', + downloadSuccess: '다운로드 성공', + downloadFailed: '다운로드 실패', + selectFile: '세이브 파일 선택', + selectFileDesc: '복원할 세이브 파일을 선택하세요', + noFiles: '세이브 파일을 찾을 수 없습니다', + loadFailed: '파일 목록 로드 실패', + confirmDelete: '"{name}"을(를) 삭제하시겠습니까?', + deleteSuccess: '파일이 삭제되었습니다', + deleteFailed: '삭제 실패' + } }, notifications: { constructionComplete: '건설 완료', @@ -1024,8 +1038,8 @@ export default { officers: '장교', modifyResources: '자원 수정', resourcesDesc: '행성 자원을 빠르게 수정', - maxAllResources: '', - maxAllResourcesSuccess: '', + maxAllResources: '모두 최대화', + maxAllResourcesSuccess: '모든 자원이 최대화되었습니다', modifyBuildings: '건물 수정', buildingsDesc: '건물 레벨을 빠르게 설정', modifyResearch: '연구 수정', @@ -1066,10 +1080,11 @@ export default { dangerZoneDesc: '다음 작업은 되돌릴 수 없습니다', resetGame: '게임 초기화', resetGameConfirm: '게임을 초기화하시겠습니까? 모든 데이터가 삭제됩니다!', - completeAllQueues: '', - completeAllQueuesDesc: '', - completeQueues: '', - completeQueuesSuccess: '' + completeAllQueues: '모든 대기열 완료', + completeAllQueuesDesc: '모든 건설, 연구, 함선, 방어 대기열 및 함대 임무를 즉시 완료', + completeQueues: '대기열 완료', + completeQueuesSuccess: + '{buildingCount}개의 건설 대기열, {researchCount}개의 연구 대기열, {missionCount}개의 함대 임무, {missileCount}개의 미사일 공격을 완료했습니다' }, alerts: { incomingFleets: '{count}개의 적 함대 접근 중', @@ -1123,13 +1138,11 @@ export default { noFriendlyNpcs: '우호적인 NPC 없음', noNeutralNpcs: '중립적인 NPC 없음', noHostileNpcs: '적대적인 NPC 없음', - recentEvents: '최근 이벤트', - recentEventsDescription: '최근 외교 활동 로그', ago: '전', - notifications: '', - markAllRead: '', - noReports: '', - viewAll: '', + notifications: '외교 알림', + markAllRead: '모두 읽음으로 표시', + noReports: '외교 이벤트 없음', + viewAll: '모두 보기', status: { friendly: '우호적', neutral: '중립', @@ -1148,7 +1161,6 @@ export default { }, note: '메모', notePlaceholder: '메모 입력...', - noteEmpty: '메모 없음', lastEvent: '최근 이벤트', reportDetails: '외교 보고서 상세', eventDescription: '이벤트 설명', @@ -1204,6 +1216,19 @@ export default { npcEliminatedMessage: '당신은 {npcName}의 모든 행성을 파괴했습니다! 이 세력은 완전히 소멸되었습니다.' }, searchPlaceholder: 'NPC 이름 검색...', + notificationType: { + tradeOffer: '무역 제안', + intelReport: '정보 보고서', + jointAttack: '공동 공격 초대' + }, + notificationBadge: { + trade: '무역', + intel: '정보', + jointAttack: '초대' + }, + notificationExtra: { + pending: '대기 중' + }, viewMode: { card: '카드', list: '목록' @@ -1219,6 +1244,21 @@ export default { medium: '보통', hard: '어려움' }, + aiType: 'AI 유형', + aiTypes: { + aggressive: '공격형', + defensive: '방어형', + trader: '상인형', + expansionist: '확장형', + balanced: '균형형' + }, + aiTypeDescriptions: { + aggressive: '적극적으로 정찰하고 공격하며, 반격이 격렬함', + defensive: '거의 공격하지 않지만, 공격받으면 강력하게 반격함', + trader: '거의 공격하지 않으며, 무역과 선물을 선호함', + expansionist: '발전에 집중하며, 공격은 적음', + balanced: '상황에 따라 전략을 동적으로 조정함' + }, reputation: '평판', spyProbes: '정찰기 수', fleetPower: '함대 전력', @@ -1245,27 +1285,11 @@ export default { attackCooldown: '공격 쿨다운 중 ({min}분 {sec}초)', notSpiedYet: '아직 정찰하지 않음, 먼저 정찰 필요' } - }, - aiType: 'AI 유형', - aiTypes: { - aggressive: '공격형', - defensive: '방어형', - trader: '상인형', - expansionist: '확장형', - balanced: '균형형' - }, - aiTypeDescriptions: { - aggressive: '적극적으로 정찰 및 공격, 강한 보복', - defensive: '거의 공격하지 않음, 공격받으면 강하게 보복', - trader: '거의 공격하지 않음, 거래와 선물 선호', - expansionist: '발전에 집중, 공격성 낮음', - balanced: '상황에 따라 전략을 동적으로 조정' } }, pagination: { previous: '이전', next: '다음', - gotIt: '', first: '처음', last: '마지막', page: '{page}페이지' @@ -1329,30 +1353,144 @@ export default { seconds: '초' }, tutorial: { + progress: '진행률', + previous: '이전', + next: '다음', + gotIt: '알겠습니다', + completeButton: '완료', + skip: '튜토리얼 건너뛰기', welcome: { title: 'OGame에 오신 것을 환영합니다', - content: '환영합니다, 사령관! 기초부터 시작하여 우주 제국을 건설해 봅시다.' + content: '환영합니다, 사령관! 이 튜토리얼은 제국 건설의 기초를 안내합니다. "다음"을 클릭하여 여정을 시작하세요.' + }, + resources: { + title: '자원 개요', + content: + '이것은 당신의 자원입니다: 금속, 크리스탈, 중수소. 건물 건설과 기술 연구에 필수적입니다. 에너지도 중요하며, 인프라에 전력을 공급합니다.' + }, + planet: { + title: '당신의 행성', + content: '이것은 당신의 모행성입니다. 여기서 행성 이름, 좌표를 확인하고, 제국이 확장되면 행성을 전환할 수 있습니다.' + }, + navigation: { + title: '탐색 메뉴', + content: '이 메뉴를 사용하여 다양한 섹션을 탐색하세요: 건물, 연구, 함대, 은하계 등. 각 섹션은 고유한 게임 기능을 제공합니다.' + }, + gotoBuildings: { + title: '건물 페이지로 이동', + content: '몇 가지 건물을 건설해 봅시다. "건물" 메뉴 항목을 클릭하여 사용 가능한 건물을 확인하세요.' }, buildSolarPlant: { title: '태양광 발전소 건설', content: - '먼저 태양광 발전소를 건설하세요! 행성에 에너지를 공급합니다. 에너지가 없으면 다른 자원 건물이 작동할 수 없습니다. 가장 중요한 첫 단계입니다.' + '먼저 태양광 발전소를 건설하세요! 행성에 에너지를 제공합니다. 에너지가 없으면 다른 자원 건물이 작동할 수 없습니다. 가장 중요한 첫 단계입니다.' }, waitBuild: { title: '건설 대기열', content: - '건물이 건설 대기열에 추가되었습니다. 오른쪽 상단의 대기열 아이콘을 클릭하면 진행 중인 모든 건설 및 연구 작업을 확인할 수 있습니다. 건설에는 시간이 걸리지만 대기하는 동안 계속 작업할 수 있습니다.' + '건물이 이제 건설 대기열에 있습니다. 오른쪽 상단의 대기열 아이콘을 클릭하여 진행 중인 모든 건설 및 연구 작업을 확인할 수 있습니다. 건설에는 시간이 걸리지만 대기하는 동안 계속 작업할 수 있습니다.' + }, + buildMetalMine: { + title: '금속 광산 건설', + content: + '이제 에너지가 있으니 금속 광산을 건설할 수 있습니다. 금속 광산은 주요 금속 공급원이며, 금속은 거의 모든 건물과 함선에 사용됩니다.' + }, + buildCrystalMine: { + title: '크리스탈 광산 건설', + content: '크리스탈은 더 희귀하지만 고급 기술에 필수적입니다. 크리스탈 광산을 건설하여 이 귀중한 자원을 수집하기 시작하세요.' + }, + buildDeuterium: { + title: '중수소 합성기 건설', + content: '중수소는 함선 연료와 고급 연구에 필수적입니다. 중수소 합성기를 건설하여 이 핵심 자원을 생산하기 시작하세요.' + }, + upgradeMines: { + title: '자원 광산 업그레이드', + content: + '다음으로, 로봇 공장 건설 요구 사항을 충족하기 위해 세 가지 자원 광산(금속, 크리스탈, 중수소)을 2레벨로 업그레이드해야 합니다. 자원이 충분하면 계속 업그레이드하세요.' + }, + buildRobotics: { + title: '로봇 공장 건설', + content: + '로봇 공장은 건설 속도를 크게 높일 수 있습니다. 금속 광산, 크리스탈 광산, 중수소 합성기가 각각 2레벨이어야 합니다. 건설 효율을 높이기 위해 건설하세요!' + }, + upgradeMinesForLab: { + title: '자원 광산 계속 업그레이드', + content: + '이제 연구 실험실 건설 요구 사항을 충족하기 위해 세 가지 자원 광산을 3레벨로 업그레이드해야 합니다. 자원 생산 능력을 계속 발전시키세요.' + }, + buildResearchLab: { + title: '연구 실험실 건설', + content: '연구 실험실은 기술 발전의 기초입니다. 세 가지 자원 광산이 각각 3레벨이어야 합니다. 기술 연구를 해제하기 위해 건설하세요!' + }, + gotoResearch: { + title: '연구 페이지로 이동', + content: '이제 연구 실험실이 있으니 "연구" 메뉴를 클릭하여 사용 가능한 기술을 확인하세요.' + }, + researchEnergy: { + title: '에너지 기술 연구', + content: '에너지 기술은 에너지 생산을 높이고 고급 건물을 해제합니다. 가장 기본적이고 중요한 기술 중 하나입니다.' + }, + shipyardIntro: { + title: '함대와 조선소', + content: + '함선을 통해 은하계를 탐험하고, 자원을 운송하고, 제국을 방어할 수 있습니다. 함선을 건조하려면 조선소(로봇 공장 2레벨 필요)가 필요합니다.' + }, + gotoBuildingsForShipyard: { + title: '건물 페이지로 돌아가기', + content: '조선소를 건설하기 위해 건물 페이지로 돌아가세요.' + }, + buildShipyard: { + title: '조선소 건설', + content: '조선소를 통해 함선과 방어 시스템을 건조할 수 있습니다. 함대 작전에 필수적입니다.' + }, + fleetIntro: { + title: '함대 작전', + content: '함선을 보유하면 임무를 수행할 수 있습니다: 자원 운송, 행성 식민, 적 공격 또는 잔해장 탐험.' + }, + galaxyIntro: { + title: '은하계 탐험', + content: '은하계 뷰는 다른 행성, 잔해장, 확장 기회를 보여줍니다. 목표를 정찰하고 전략을 계획하는 데 사용하세요.' + }, + complete: { + title: '튜토리얼 완료!', + content: + '축하합니다, 사령관! 이제 기본 사항을 이해했습니다. 계속해서 제국을 건설하고, 기술을 연구하고, 은하계를 탐험하세요. 기억하세요: 먼저 에너지를 개발하고, 그다음 자원, 그다음 공장과 연구입니다! 행운을 빕니다!' }, mobile: { welcome: { title: 'OGame에 오신 것을 환영합니다 (모바일)', content: - '환영합니다, 사령관! 터치스크린용으로 설계된 간소화된 튜토리얼입니다. 제국 건설을 시작할 수 있도록 핵심 기능을 빠르게 소개하겠습니다.' + '환영합니다, 사령관! 터치스크린을 위해 설계된 간소화된 튜토리얼입니다. 핵심 기능을 빠르게 소개하여 제국 건설을 시작하겠습니다.' + }, + resources: { + title: '상단 자원 바', + content: '상단에 자원이 표시됩니다: 금속, 크리스탈, 중수소. 클릭하여 자세한 생산 정보를 확인하세요.' + }, + menu: { + title: '탐색 메뉴 열기', + content: '이 메뉴 아이콘을 클릭하여 탐색 바를 열면 건물, 연구, 함대 등 모든 기능에 액세스할 수 있습니다.' + }, + gotoBuildings: { + title: '건물 페이지로 이동', + content: '메뉴가 열렸습니다! 이제 "건물" 옵션을 클릭하여 인프라 건설을 시작하세요.' + }, + buildSolarPlant: { + title: '태양광 발전소 건설', + content: '먼저 태양광 발전소를 건설하세요! 아래로 스크롤하여 찾아 카드를 클릭하여 건설하세요. 에너지는 모든 것의 기초입니다.' }, waitBuild: { title: '건설 대기열', content: - '오른쪽 상단의 대기열 아이콘을 클릭하여 건설 진행 상황을 확인하세요. 다른 페이지를 계속 탐색할 수 있으며, 건설은 백그라운드에서 진행됩니다.' + '오른쪽 상단의 대기열 아이콘을 클릭하여 건설 진행 상황을 확인하세요. 다른 페이지를 계속 탐색할 수 있으며 건설은 백그라운드에서 진행됩니다.' + }, + buildMetalMine: { + title: '금속 광산 건설', + content: '에너지가 있으면 금속 광산을 건설하세요. 아래로 스크롤하여 금속 광산을 찾아 건설을 클릭하세요.' + }, + complete: { + title: '빠른 튜토리얼 완료!', + content: + '잘하셨습니다! 이제 기본 작업을 익혔습니다. 계속해서 크리스탈 광산과 중수소 합성기를 건설한 다음 다른 기능을 탐험하세요. 기억하세요: 먼저 에너지, 그다음 자원!' } } }, @@ -1409,11 +1547,21 @@ export default { title: '전투 시뮬레이터', message: '공격 전에 전투 결과를 시뮬레이션하세요. 양측 함대와 기술 레벨을 입력하여 승패와 손실을 예측.' }, + campaign: { + title: '캠페인 모드', + message: + '은하계 스토리 캠페인을 탐험하세요! 미션을 완료하여 자원 보상을 획득하고 새로운 도전을 해제하세요. 각 노드에는 고유한 목표와 적이 있습니다.' + }, achievements: { title: '업적 시스템', message: '게임 목표를 완료하여 업적을 해제하고 암흑 물질 보상을 획득하세요! 업적은 여러 등급이 있으며, 더 높은 도전으로 더 좋은 보상을 받으세요.' }, + ranking: { + title: '랭킹', + message: + '다른 플레이어 및 NPC와 진행도를 비교하세요. 건물, 연구, 함대, 방어 점수에 따른 순위를 확인하세요. 리더보드 상위권을 목표로 하세요!' + }, settings: { title: '설정', message: '여기서 게임 데이터 관리, 알림 설정, 저장 내보내기/가져오기가 가능합니다. 정기적으로 백업하세요!' @@ -1538,5 +1686,323 @@ export default { you: '나', scoreBreakdown: '점수 상세', noData: '랭킹 데이터 없음' + }, + // NPC 강화 행동 알림 + npcBehavior: { + tradeOfferReceived: '거래 제안 수신', + tradeOfferDesc: '{npcName}이(가) 거래 제안을 보냈습니다', + attitudeChanged: 'NPC 태도 변화', + becameFriendly: '{npcName}이(가) 당신에게 우호적으로 변했습니다', + becameHostile: '{npcName}이(가) 당신에게 적대적으로 변했습니다', + intelReceived: '정보 수신', + intelReceivedDesc: '{npcName}이(가) 적 정보를 공유했습니다', + jointAttackInvite: '공동 공격 초대', + jointAttackInviteDesc: '{npcName}이(가) 적에 대한 공동 공격에 초대합니다', + aidReceived: '지원 수신', + aidReceivedDesc: '{npcName}이(가) {amount} 자원을 보냈습니다', + allyDefense: '동맹 방어', + allyDefenseDesc: '{npcName}이(가) 당신의 행성 방어를 위해 함대를 보내고 있습니다', + trade: { + title: '거래 제안', + from: '발신자', + offers: '제공', + requests: '요청', + expiresIn: '만료까지', + expired: '만료됨', + accept: '수락', + decline: '거절', + noOffers: '거래 제안 없음', + acceptSuccess: '거래 완료!', + acceptFailed: '자원 부족으로 거래할 수 없습니다', + declined: '거래를 거절했습니다', + ratio: '교환 비율' + }, + intel: { + title: '정보 보고서', + from: '정보원', + target: '대상 NPC', + type: '정보 유형', + types: { + enemyFleet: '함대 정보', + enemyResources: '자원 정보', + enemyMovement: '동향 정보' + }, + fleetInfo: '함대 정보', + resourceInfo: '자원 정보', + movementInfo: '동향 정보', + noReports: '정보 보고서 없음', + markAsRead: '읽음으로 표시', + content: '정보 내용', + noFleet: '함대가 감지되지 않음', + noData: '데이터 없음', + targetPosition: '목표 좌표', + missionType: '임무 유형' + }, + jointAttack: { + title: '공동 공격 초대', + from: '발기자', + target: '대상 NPC', + targetPlanet: '대상 행성', + npcFleet: 'NPC 함대', + lootShare: '전리품 분배', + expiresIn: '만료까지', + expired: '만료됨', + accept: '공격 참여', + decline: '거절', + noInvites: '공동 공격 초대 없음', + acceptSuccess: '공동 공격에 참여했습니다!', + declined: '초대를 거절했습니다', + targetInfo: '공격 대상', + expectedShare: '예상 분배', + remaining: '남은 시간' + }, + aid: { + title: '자원 지원', + from: '발신자', + resources: '지원 자원', + noAid: '지원 기록 없음' + }, + attitudeChange: { + title: '태도 변화', + npc: 'NPC', + previous: '이전', + current: '현재', + reason: '이유', + reasons: { + attitude_swing: '태도 변동', + gift: '선물 수령', + attack: '공격 받음' + } + }, + allyAction: { + title: '동맹 행동', + defense: '방어 지원', + defenseDesc: '{npcName}이(가) {targetPlanet} 방어를 위해 함대 파견', + jointAttackStarted: '공동 공격 시작', + jointAttackStartedDesc: '{targetNpc}에 대한 공동 공격이 시작되었습니다', + reputationBonus: '평판 보너스', + reputationBonusDesc: '동맹 {npcName}이(가) {targetNpc}에게 당신을 좋게 말하고 있습니다' + } + }, + campaign: { + name: '캠페인', + description: '신비로운 은하를 탐험하고 고대의 비밀을 밝혀내세요', + totalProgress: '총 진행률', + questsCompleted: '퀘스트 완료', + chapter: '챕터', + branch: '분기', + startQuest: '퀘스트 시작', + claimRewards: '보상 받기', + objectives: '목표', + rewards: '보상', + completed: '완료', + inProgress: '진행 중', + available: '수락 가능', + locked: '잠김', + notifications: { + questStarted: '퀘스트 시작', + questCompleted: '퀘스트 완료!', + rewardsClaimed: '보상을 받았습니다', + objectiveCompleted: '목표 달성', + chapterUnlocked: '새 챕터가 해금되었습니다', + reputationUp: '{npcName}와(과)의 평판이 {value} 상승했습니다', + reputationDown: '{npcName}와(과)의 평판이 {value} 하락했습니다', + branchUnlocked: '새로운 스토리 분기가 해금되었습니다!' + }, + dialogue: { + skip: '건너뛰기', + continue: '계속', + finish: '완료', + player: '사령관', + npc: 'NPC', + narrator: '내레이터', + mysterious: '신비한 신호', + unknownSource: '알 수 없는 출처', + choiceEffect: '선택지 효과' + }, + chapters: { + '1': { + title: '기원', + description: '고향을 건설하고 우주로 첫 발을 내딛으세요', + backgroundStory: + '당신은 첫 행성을 얻은 젊은 우주 사령관입니다. 이 광활한 우주에서 고향을 건설하고, 기술을 발전시키며, 은하의 깊은 곳을 탐험하게 됩니다...' + }, + '2': { + title: '탐험', + description: '우주를 탐험하고 고대 유적을 발견하세요', + backgroundStory: + '세력이 커짐에 따라 심우주에서 오는 신비한 신호가 당신의 주의를 끕니다. 이 신호들은 고대의 비밀을 가리키며, 용감한 탐험가를 기다리고 있는 것 같습니다...' + }, + '3': { + title: '외교', + description: '다른 세력과 관계를 구축하세요', + backgroundStory: + '은하에 당신만 있는 것은 아닙니다. 다른 문명들이 부상하고 있습니다. 그들의 적이 될지 동맹을 맺을지 결정해야 합니다. 외교적 지혜가 제국의 운명을 결정할 것입니다...' + }, + '4': { + title: '그림자의 부상', + description: '강력한 적에 맞서고 영토를 방어하세요', + backgroundStory: + '그림자 속에 위험이 도사리고 있습니다. 강력한 적대 세력이 당신의 영토를 노리고 있습니다. 전쟁은 불가피합니다. 다가오는 폭풍에 대비해야 합니다...' + }, + '5': { + title: '고대의 비밀', + description: '은하 깊은 곳의 비밀을 밝혀내세요', + backgroundStory: + '모든 단서가 은하에서 가장 신비로운 지역을 가리킵니다. 그곳에는 고대 문명이 남긴 궁극의 비밀이 잠들어 있습니다. 모든 것을 밝힐 준비가 되었습니까?' + } + }, + quests: { + '1_1': { title: '고향 건설', description: '기반 시설을 구축하여 행성의 토대를 마련하세요' }, + '1_2': { title: '기술 계몽', description: '기초 기술을 연구하여 기술 여정을 시작하세요' }, + '1_3': { title: '첫 번째 함선', description: '첫 전함을 건조하세요' }, + '1_4': { title: '낯선 이웃', description: '인근 시스템의 다른 세력을 정찰하세요' }, + '1_5': { title: '첫 접촉', description: '인근 NPC 세력과 초기 접촉을 확립하세요' }, + '2_1': { title: '개척 식민지', description: '첫 번째 새 행성을 식민지화하세요' }, + '2_2': { title: '심우주 탐험', description: '함대를 탐험 임무에 보내세요' }, + '2_3': { title: '신비한 신호', description: '심우주에서 오는 신비한 신호를 조사하세요' }, + '2_4': { title: '유적 조사', description: '발견한 고대 유적을 탐험하세요' }, + '2_5': { title: '아카이브 해독', description: '유적에서 얻은 데이터를 연구하세요' }, + '3_1': { title: '평화의 사절', description: '외교로 NPC와의 관계를 개선하세요' }, + '3_2': { title: '무역 관계', description: '우호 세력과 안정적인 관계를 구축하세요' }, + '3_3': { title: '공통의 위협', description: '잠재적인 적대 세력을 발견하세요' }, + '3_4': { title: '동맹 협상', description: '우호 NPC와 공식 동맹을 맺으세요' }, + '3_5': { title: '폭풍 대비', description: '방어 시설을 건설하여 도전에 대비하세요' }, + '4_1': { title: '전초 기지 공격', description: '적대 세력의 첫 공격을 격퇴하세요' }, + '4_2': { title: '정보 수집', description: '적의 군사 배치를 정찰하세요' }, + '4_3': { title: '반격', description: '적에게 반격을 시작하세요' }, + '4_4': { title: '자원 쟁탈', description: '전장 잔해를 재활용하여 자원을 얻으세요' }, + '4_5': { title: '결전 전야', description: '최종 전투를 위한 강력한 함대를 건조하세요' }, + '5_1': { title: '유적의 깊은 곳', description: '유적의 가장 깊은 곳을 탐험하세요' }, + '5_2': { title: '고대 기술', description: '고대 문명의 기술을 해금하세요' }, + '5_3': { title: '최종 대결', description: '신비한 적과의 최종 전투에 임하세요' }, + '5_4': { title: '새 시대', description: '새 식민지를 세우고 새 시대를 열으세요' }, + '5_5': { title: '유산 계승', description: '계속 발전하고 더 많은 시스템을 정복하세요' } + }, + objectiveTypes: { + buildBuilding: '{building}을(를) 레벨 {level}로 건설', + researchTech: '{tech}을(를) 레벨 {level}까지 연구', + produceShips: '{ship} {count}대 생산', + accumulateResources: '{resource}을(를) {amount} 축적', + defeatNPC: '{npc} 격파', + winBattles: '{count}회 전투 승리', + recycleDebris: '잔해 {amount} 재활용', + reachRelation: '{npc}와 {level} 관계 도달', + sendGift: '{npc}에게 {count}회 선물 보내기', + formAlliance: '{npc}와 동맹 체결', + colonize: '행성 {count}개 식민지화', + expedition: '탐험 {count}회 완료', + spyTarget: '{target} 정찰' + }, + errors: { + questNotFound: '퀘스트를 찾을 수 없습니다', + questNotAvailable: '퀘스트를 이용할 수 없습니다', + questNotActive: '퀘스트가 활성화되지 않았습니다', + questNotCompleted: '퀘스트 미완료', + rewardsAlreadyClaimed: '이미 보상을 받았습니다', + prerequisiteNotMet: '선행 퀘스트 미완료' + }, + speakers: { + ancientVoice: '고대의 목소리', + neighborNPC: '인접 세력', + mysteriousSignal: '신비한 신호', + enemyCommander: '적 사령관' + }, + objectiveDescriptions: { + buildMetalMine: '금속 광산을 레벨 2로 건설', + buildCrystalMine: '크리스탈 광산을 레벨 2로 건설', + buildSolarPlant: '태양열 발전소를 레벨 2로 건설', + buildResearchLab: '연구소를 레벨 1로 건설', + researchEnergy: '에너지 기술을 레벨 1까지 연구', + buildShipyard: '조선소를 레벨 2로 건설', + researchCombustion: '연소 드라이브를 레벨 1까지 연구', + buildLightFighters: '경전투기 5대 건조', + researchEspionage: '스파이 기술을 레벨 2까지 연구', + buildSpyProbes: '스파이 탐사선 3대 건조', + spyAnyNPC: 'NPC 행성 정찰', + sendGiftToNPC: 'NPC에게 선물 보내기', + researchAstrophysics: '천체물리학을 레벨 1까지 연구', + buildColonyShip: '식민선 건조', + colonizeNewPlanet: '새 행성 식민지화', + completeExpedition: '탐험 임무 완료', + discoverRuins: '고대 유적 발견', + researchComputer: '컴퓨터 기술을 레벨 4까지 연구', + improveRelation: 'NPC와의 관계 개선', + reachFriendly: 'NPC와 우호 상태 도달', + spyHostileNPC: '적대 NPC 정찰', + formAlliance: '우호 NPC와 동맹 체결', + buildDefenses: '방어 시설 건설', + winDefenseBattle: '방어전 승리', + spyEnemyPlanet: '적 행성 정찰', + attackEnemy: '적 공격', + recycleDebris: '잔해 재활용', + buildBattleships: '전함 10대 건조', + exploreDeepRuins: '깊은 유적 탐험', + researchHyperspace: '하이퍼스페이스 기술 연구', + defeatBoss: '신비한 적 격파', + colonizeSpecial: '특별한 장소 식민지화', + continueDevelopment: '개발 계속' + }, + dialogues: { + '1_1': { + prologue_1: + '은하에 오신 것을 환영합니다, 젊은 사령관. 이 광활한 우주가 당신의 탐험을 기다리고 있습니다. 먼저 고향 행성을 건설합시다.', + prologue_2: '새로운 의식이 깨어나는 것을 느낀다... 흥미롭군... 어디까지 갈 수 있는지 보자...' + }, + '1_2': { prologue_1: '기본 인프라가 완성되었습니다. 이제 기술을 발전시킬 시간입니다. 연구소를 건설하고 기술 여정을 시작하세요.' }, + '1_3': { prologue_1: '기술 지원으로 함대 건조가 가능해졌습니다. 조선소를 건설하고 첫 전함을 생산하세요.' }, + '1_4': { + prologue_1: '함대가 형태를 갖추고 있습니다. 주변 상황을 파악합시다. 스파이 탐사선을 보내 인근 세력을 정찰하세요.', + prologue_2: '당신은 혼자가 아니다... 이 은하에는 다른 문명이 존재한다...' + }, + '1_5': { + prologue_1: '인근 세력을 발견했습니다. 외교는 예술입니다. 그들과의 접촉을 시도하세요.', + epilogue_1: '선물에 감사합니다, 사령관. 친구가 될 수 있기를 바랍니다.', + epilogue_2: '좋아... 연결을 구축하는 것은 더 깊은 비밀을 밝히는 첫 단계다...' + }, + '2_1': { + prologue_1: '세력이 확립되었습니다. 영토를 확장할 시간입니다. 천체물리학을 연구하고, 식민선을 건조하여 새 행성을 탐험하세요.', + prologue_2: '우주는 무한하다... 더 많은 행성은 더 많은 가능성을 의미한다...' + }, + '2_2': { + prologue_1: '식민지화 성공! 하지만 우주에는 더 깊은 비밀이 기다리고 있습니다. 함대를 탐험 임무에 보내세요.', + prologue_2: '저 멀리서 희미한 신호가... 무언가 그곳에서 당신을 기다리고 있다...' + }, + '2_3': { + prologue_1: '탐험에서 이상한 신호를 발견했습니다. 이 신호들은 고대 문명에서 온 것 같습니다... 출처를 조사하세요.', + epilogue_1: '이 기호들은... 고대 문명의 유적이다! 계속 조사하여 비밀을 밝히세요.' + }, + '2_4': { prologue_1: '고대 유적의 위치를 발견했습니다. 함대를 보내 무엇을 발견할 수 있는지 탐험하세요.' }, + '2_5': { prologue_1: '유적에서 데이터 아카이브가 발견되었습니다. 이 데이터를 연구하면 새 기술을 해금할 수 있을지도 모릅니다.' }, + '3_1': { prologue_1: '탐험 중에도 외교를 잊지 마세요. 주변 세력과 좋은 관계를 유지하는 것이 유익합니다.' }, + '3_2': { prologue_1: '일부 세력이 우호를 보이고 있습니다. 관계를 계속 깊게 하면 더 많은 지원을 받을 수 있을지도 모릅니다.' }, + '3_3': { + prologue_1: '정보에 따르면 적대 세력이 그림자에서 당신을 감시하고 있습니다. 경계를 늦추지 말고 그들의 움직임을 정찰하세요.' + }, + '3_4': { prologue_1: '우호 세력과 공식 동맹을 맺어 위협에 대해 서로를 지원하세요.' }, + '3_5': { prologue_1: '위협이 다가오고 있습니다. 방어 시설을 건설하고 가능한 충돌에 대비하세요.' }, + '4_1': { + prologue_1: '적이 공격을 시작했습니다! 행성을 방어하세요!', + epilogue_1: '적의 첫 번째 파도를 성공적으로 격퇴했습니다. 하지만 이것은 시작에 불과합니다...' + }, + '4_2': { prologue_1: '적이 후퇴했지만 돌아올 것입니다. 그들의 행성을 정찰하여 전력을 파악하세요.' }, + '4_3': { prologue_1: '반격할 시간입니다. 적 행성을 공격하여 그들의 전력을 약화시키세요.' }, + '4_4': { prologue_1: '전장에 많은 잔해가 남아 있습니다. 이 자원을 재활용하여 다음 전투에 대비하세요.' }, + '4_5': { prologue_1: '최종 전투가 다가오고 있습니다. 강력한 함대를 건조하고 궁극의 도전에 대비하세요.' }, + '5_1': { + prologue_1: '모든 단서가 유적의 가장 깊은 곳을 가리킵니다. 고대 문명의 핵심 비밀이 그곳에 있습니다.', + prologue_2: '드디어 도착했다... 진실이 곧 밝혀질 것이다...' + }, + '5_2': { prologue_1: '유적 깊은 곳에서 잃어버린 고대 기술을 발견했습니다. 연구하여 그 힘을 해방하세요.' }, + '5_3': { + prologue_1: '신비한 적이 나타났습니다. 이것이 마지막 도전입니다. 격파하세요!', + epilogue_1: '해냈습니다! 고대의 수호자가 쓰러졌습니다. 은하의 비밀이 이제 당신에게 열려 있습니다.' + }, + '5_4': { prologue_1: '마침내 평화가 찾아왔습니다. 이 새 시대에 새 식민지를 세우고 제국을 확장하세요.' }, + '5_5': { + prologue_1: '당신의 전설은 이제 막 시작되었습니다. 계속 탐험하고 더 많은 성계를 정복하세요!', + epilogue_1: '은하는 광대하고 끝이 없으며, 셀 수 없는 비밀이 당신을 기다리고 있습니다...' + } + } } } diff --git a/src/locales/ru.ts b/src/locales/ru.ts index c251d3b..4bbd3ce 100644 --- a/src/locales/ru.ts +++ b/src/locales/ru.ts @@ -11,29 +11,12 @@ export default { common: { confirm: 'Подтвердить', cancel: 'Отмена', - delete: 'Удалить', - edit: 'Редактировать', save: 'Сохранить', close: 'Закрыть', - back: 'Назад', - next: 'Далее', - gotIt: '', - previous: 'Предыдущий', - submit: 'Отправить', - reset: 'Сбросить', - search: 'Поиск', - filter: 'Фильтр', - loading: 'Загрузка...', - noData: 'Нет данных', - error: 'Ошибка', + gotIt: 'Понятно', success: 'Успешно', - warning: 'Предупреждение', - info: 'Информация', resourceType: 'Тип ресурса', playerName: 'Командир', - timeHour: 'ч', - timeMinute: 'мин', - timeSecond: 'сек', featureLocked: 'Функция заблокирована', unlockRequired: 'Требуется здание', requiredBuilding: 'Необходимое здание', @@ -41,7 +24,6 @@ export default { goToBuildings: 'К зданиям', locked: 'Заблокировано', viewRequirements: 'Просмотр требований', - requirements: 'Требования', requirementsNotMet: 'Требования не выполнены', current: 'Текущий', level: 'Уровень', @@ -51,7 +33,8 @@ export default { viewDetails: 'Подробнее', exitConfirmTitle: 'Выйти из игры', exitConfirmMessage: 'Вы уверены, что хотите выйти? Прогресс сохраняется автоматически.', - points: 'Очки' + points: 'Очки', + retry: 'Повторить' }, errors: { requirementsNotMet: 'Требования не выполнены', @@ -88,13 +71,13 @@ export default { galaxy: 'Галактика', diplomacy: 'Дипломатия', achievements: 'Достижения', + campaign: 'Кампания', ranking: 'Рейтинг', messages: 'Сообщения', settings: 'Настройки', gm: 'GM' }, sidebar: { - language: 'Язык', lightMode: 'Светлая тема', darkMode: 'Тёмная тема', collapse: 'Свернуть', @@ -119,9 +102,6 @@ export default { }, energy: { lowWarning: 'Дефицит энергии! Производство ресурсов остановлено!', - severeWarning: 'Дефицит энергии! Производство ресурсов остановлено!', - criticalWarning: 'Дефицит энергии! Производство ресурсов остановлено!', - noProduction: 'Дефицит энергии! Производство ресурсов остановлено!', deficitDetail: 'Дефицит энергии: {deficit}, постройте больше электростанций', buildSolarPlant: 'Построить электростанцию' }, @@ -132,27 +112,20 @@ export default { lowResources: 'Почти истощено: {resources}' }, planet: { - planet: 'Планета', moon: 'Луна', - colony: 'Колония', position: 'Позиция', - coordinates: 'Координаты', switchToMoon: 'На луну', backToPlanet: 'Вернуться на планету', switchPlanet: 'Переключить планету', currentPlanet: 'Текущая планета', - fields: 'Поля', temperature: 'Температура', homePlanet: 'Родная планета', planetPrefix: 'Планета', - moonSuffix: 'я луна', colonyPrefix: 'Колония', renamePlanet: 'Переименовать планету', renamePlanetTitle: 'Переименовать планету', - newPlanetName: 'Новое название', planetNamePlaceholder: 'Введите новое название планеты', - rename: 'Переименовать', - renameSuccess: 'Планета переименована в {name}' + rename: 'Переименовать' }, player: { points: 'Всего очков' @@ -179,8 +152,10 @@ export default { sensorPhalanx: 'Сенсорная фаланга', jumpGate: 'Прыжковые ворота', planetDestroyerFactory: 'Фабрика разрушителей планет', + geoResearchStation: 'Геологическая станция', + deepDrillingFacility: 'Глубинная буровая установка', buildTime: 'Время строительства', - build: '', + build: 'Построить', production: 'Производство', consumption: 'Потребление', totalCost: 'Общая стоимость', @@ -194,7 +169,6 @@ export default { buildQueueBonus: 'Очередь строительства', spaceBonus: 'Бонус пространства', buildSpeedBonus: 'Бонус скорости строительства', - researchSpeedBonus: 'Бонус скорости исследования', planetSpace: 'Planet Space', moonSpace: 'Moon Space', missileCapacity: 'Missile Capacity', @@ -228,7 +202,10 @@ export default { lunarBase: 'Увеличивает доступное пространство на луне, +30 пространства за уровень', sensorPhalanx: 'Обнаруживает активность флота в окружающих системах', jumpGate: 'Мгновенно переносит флоты на другие луны', - planetDestroyerFactory: 'Производит абсолютное оружие, способное уничтожать планеты' + planetDestroyerFactory: 'Производит абсолютное оружие, способное уничтожать планеты', + geoResearchStation: + 'Исследует геологическую структуру и повышает скорость восстановления рудных месторождений. +50% скорости восстановления за уровень', + deepDrillingFacility: '' }, ships: { lightFighter: 'Лёгкий истребитель', @@ -292,9 +269,6 @@ export default { }, research: { researchTime: 'Время исследования', - totalCost: 'Общая стоимость', - totalPoints: 'Общие очки', - levelRange: 'Диапазон уровней', capacity: 'Capacity/Effect', storageCapacity: 'Capacity', energyProduction: 'Energy Production', @@ -302,7 +276,15 @@ export default { buildQueue: 'Build Queue', planetSpace: 'Planet Space', moonSpace: 'Moon Space', - missileCapacity: 'Missile Capacity' + missileCapacity: 'Missile Capacity', + attackBonus: 'Бонус атаки', + shieldBonus: 'Бонус щита', + armorBonus: 'Бонус брони', + spyLevel: 'Уровень шпионажа', + researchQueueBonus: 'Очередь исследований', + colonySlots: 'Слоты колоний', + forAllPlanets: '(Глобально)', + speedBonus: 'Бонус скорости' }, technologies: { energyTechnology: 'Энергетическая технология', @@ -322,7 +304,8 @@ export default { hyperspaceDrive: 'Гиперпространственный двигатель', darkMatterTechnology: 'Технология тёмной материи', terraformingTechnology: 'Технология терраформирования', - planetDestructionTech: 'Технология уничтожения планет' + planetDestructionTech: 'Технология уничтожения планет', + miningTechnology: '' }, technologyDescriptions: { energyTechnology: 'Улучшает энергоэффективность', @@ -344,7 +327,8 @@ export default { darkMatterTechnology: 'Исследование свойств и применения тёмной материи', terraformingTechnology: 'Исследование технологии терраформирования планет, увеличивает доступное пространство всех планет на 30 за уровень', - planetDestructionTech: 'Исследование ужасающей технологии уничтожения целых планет' + planetDestructionTech: 'Исследование ужасающей технологии уничтожения целых планет', + miningTechnology: '' }, officers: { commander: 'Командир', @@ -379,7 +363,7 @@ export default { cancelResearch: 'Отменить исследование', confirmCancel: 'Вы уверены, что хотите отменить? 50% ресурсов будет возвращено.', level: 'Уровень', - gmModeActivated: '', + gmModeActivated: 'Режим GM активирован! Проверьте меню навигации.', upgradeToLevel: 'Улучшить до уровня', tabs: { all: 'Все', @@ -395,17 +379,17 @@ export default { resourcesReady: 'Готово', waitingResources: 'Ожидание', waitingQueueFull: 'Очередь ожидания заполнена', - movedToQueue: 'Задача перемещена в очередь' + movedToQueue: 'Задача перемещена в очередь', + buildQueueBonus: 'Очередь строительства', + spaceBonus: 'Бонус пространства', + researchQueueBonus: 'Очередь исследований', + quantity: 'Количество' }, overview: { title: 'Обзор планеты', resourceOverview: 'Ресурсы', fleetInfo: 'Флот', currentShips: 'Корабли на этой планете', - productionSources: 'Источники производства', - productionSourcesDesc: 'Подробная информация о производстве ресурсов и бонусах', - consumptionSources: 'Источники потребления', - consumptionSourcesDesc: 'Детали потребления энергии зданиями', totalProduction: 'Общее производство', totalConsumption: 'Общее потребление', noConsumption: 'Нет потребления энергии', @@ -415,13 +399,9 @@ export default { }, buildingsView: { title: 'Здания', - usedSpace: 'Использовано полей', spaceUsage: 'Использование полей', level: 'Уровень', - gmModeActivated: '', upgradeCost: 'Стоимость улучшения', - buildTime: 'Время строительства', - build: 'Построить', upgrade: 'Улучшить', maxLevelReached: 'Достигнут максимальный уровень', requirementsNotMet: 'Требования не выполнены', @@ -431,8 +411,7 @@ export default { demolishRefund: 'Возврат от сноса', demolishFailed: 'Снос не удался', demolishFailedMessage: 'Невозможно снести это здание. Проверьте, не заполнена ли очередь строительства или уровень здания не равен 0.', - confirmDemolish: 'Подтвердить снос', - confirmDemolishMessage: 'Вы уверены, что хотите снести следующее здание?' + confirmDemolish: 'Подтвердить снос' }, researchView: { title: 'Исследования', @@ -444,27 +423,13 @@ export default { 'Пожалуйста, проверьте, достаточно ли у вас ресурсов, выполнены ли предварительные условия или нет других исследовательских задач.' }, shipyard: { - attack: 'Атака', - missileAttack: 'Ракетная атака', - shield: 'Щит', - armor: 'Броня', speed: 'Скорость', cargoCapacity: 'Грузоподъёмность', - fuelConsumption: 'Расход топлива', - buildCost: 'Стоимость постройки', - buildTime: 'Время строительства', - build: '', - perUnit: 'За единицу', - batchCalculator: 'Калькулятор партий', - quantity: 'Количество', - totalCost: 'Общая стоимость', - totalTime: 'Общее время' + fuelConsumption: 'Расход топлива' }, shipyardView: { title: 'Верфь', fleetStorage: 'Хранилище флота', - owned: 'В наличии', - attack: 'Атака', missileAttack: 'Ракетная атака', shield: 'Щит', speed: 'Скорость', @@ -485,7 +450,7 @@ export default { armor: 'Броня', buildCost: 'Стоимость постройки', buildTime: 'Время строительства', - build: '', + build: 'Построить', perUnit: 'За единицу', batchCalculator: 'Калькулятор партий', quantity: 'Количество', @@ -539,6 +504,7 @@ export default { missionInfo: 'Информация о миссии', fuelConsumption: 'Расход топлива', flightTime: 'Время полета', + outOfRange: 'Вне зоны досягаемости', attackMission: 'Атака', transport: 'Транспорт', colonize: 'Колонизация', @@ -580,11 +546,12 @@ export default { arrivalTime: 'Время прибытия', returnTime: 'Время возврата', recallFleet: 'Отозвать флот', - abortMission: '', - abortMissionTitle: '', - abortMissionWarning: '', - abortMissionSuccess: '', - abortMissionSuccessMessage: '', + abortMission: 'Прервать миссию', + abortMissionTitle: 'Подтверждение прерывания миссии', + abortMissionWarning: + 'ВНИМАНИЕ: Прерывание этой миссии приведёт к необратимой потере {ships} кораблей и {resources} ресурсов!\n\nЭто действие необратимо, флот и ресурсы не вернутся.', + abortMissionSuccess: 'Миссия прервана', + abortMissionSuccessMessage: 'Миссия была прервана, флот и ресурсы потеряны.', sendFailed: 'Отправка не удалась', sendFailedMessage: 'Пожалуйста, проверьте количество флота, наличие топлива или ограничения грузоподъёмности.', recallFailed: 'Отзыв не удался', @@ -639,7 +606,8 @@ export default { jumpGateSuccess: 'Переброска через ворота успешна', jumpGateSuccessMessage: 'Флот мгновенно переброшен к {target}', jumpGateFailed: 'Переброска через ворота не удалась', - jumpGateFailedMessage: 'Проверьте состояние ворот и конфигурацию флота' + jumpGateFailedMessage: 'Проверьте состояние ворот и конфигурацию флота', + destroy: 'Уничтожение' }, officersView: { title: 'Офицеры', @@ -653,7 +621,6 @@ export default { benefitsBonus: 'Бонусы', resourceProduction: 'Производство ресурсов', darkMatterProduction: 'Производство тёмной материи', - energyProduction: 'Производство энергии', buildingSpeed: 'Скорость строительства', researchSpeed: 'Скорость исследований', fleetSpeed: 'Скорость флота', @@ -682,14 +649,11 @@ export default { selectGalaxy: 'Выбрать галактику', system: 'Система', selectSystem: 'Выбрать систему', - view: 'Показать', - myPlanet: 'Моя планета', myPlanets: 'Просмотр моих систем', npcPlanets: 'Планеты NPC', selectPlanetToView: 'Выберите планету для просмотра её системы', totalPositions: 'Всего 10 позиций планет', mine: 'Моя', - hostile: 'Враждебная', emptySlot: 'Пусто - можно колонизировать', scout: 'Разведка', attack: 'Атака', @@ -716,7 +680,9 @@ export default { systems: 'систем', distance: 'Расстояние', flightTime: 'Время полета', + outOfRange: 'Вне зоны досягаемости', launchMissile: 'Запустить', + missileLaunched: 'Ракета запущена', cancel: 'Отмена', colonizePlanetMessage: 'Вы уверены, что хотите колонизировать позицию [{coordinates}]?\n\nПерейдите на страницу флота, чтобы отправить колонизационный корабль.', @@ -729,19 +695,33 @@ export default { 'Вы уверены, что хотите отправить ресурсы в подарок планете [{coordinates}]?\n\nПерейдите на страницу флота, чтобы выбрать транспортные корабли и загрузить ресурсы.', npcPlanetName: 'Планета {name}', intercepted: 'Перехвачено', - defenseLosses: 'Потери обороны' + defenseLosses: 'Потери обороны', + phalanxScan: 'Сканирование сенсором', + phalanxScanTitle: 'Сканирование сенсорной решёткой', + phalanxScanDescription: 'Сканировать активность флота планеты [{coordinates}]', + phalanxNoMoon: 'Требуется луна с сенсорной решёткой для сканирования', + phalanxCost: 'Стоимость сканирования', + phalanxNoFleets: 'Активность флота не обнаружена', + phalanxFleetDetected: 'Обнаружено флотов: {count}', + phalanxOrigin: 'Отправление', + phalanxDestination: 'Назначение', + phalanxArrival: 'Время прибытия', + phalanxReturn: 'Время возвращения', + phalanxStatusOutbound: 'В пути', + phalanxStatusReturning: 'Возвращается', + phalanxInsufficientDeuterium: 'Недостаточно дейтерия' }, messagesView: { title: 'Сообщения', battles: 'Битвы', spy: 'Разведка', npc: 'NPC', - diplomacy: '', + diplomacy: 'Дипломатия', battleReports: 'Отчёты о боях', spyReports: 'Отчёты разведки', noBattleReports: 'Нет отчётов о боях', noSpyReports: 'Нет отчётов разведки', - noDiplomaticReports: '', + noDiplomaticReports: 'Нет дипломатических отчётов', battleReport: 'Отчёт о бое', spyReport: 'Отчёт разведки', victory: 'Победа', @@ -762,6 +742,8 @@ export default { defense: 'Оборона', buildings: 'Здания', unread: 'Непрочитано', + pending: 'Ожидает', + invalidData: 'Недействительные данные', targetPlanet: 'Целевая планета', attackerRemaining: 'Осталось у нападающего', defenderRemaining: 'Осталось у защитника', @@ -814,36 +796,36 @@ export default { polite_decline: 'Вежливо отказались' }, // Spied notification dialog - spiedNotificationDetails: '', - spyDetected: '', - detectionResult: '', - detectionSuccess: '', - spiedNotificationMessage: '', - spiedNotificationTip: '', - viewInGalaxy: '', + spiedNotificationDetails: 'Детали уведомления о шпионаже', + spyDetected: 'Шпион обнаружен', + detectionResult: 'Результат обнаружения', + detectionSuccess: 'Вы обнаружили вражеского шпиона!', + spiedNotificationMessage: '{npc} попытался шпионить за вашей планетой {planet}', + spiedNotificationTip: 'Рассмотрите возможность усиления обороны или контратаки, если этот NPC враждебен', + viewInGalaxy: 'Показать в галактике', // Mission report dialog - missionReportDetails: '', - missionSuccess: '', - missionFailed: '', - origin: '', - destination: '', - missionDetails: '', - transportedResources: '', - recycledResources: '', - remainingDebris: '', - newPlanet: '', + missionReportDetails: 'Детали отчёта о миссии', + missionSuccess: 'Успех', + missionFailed: 'Неудача', + origin: 'Происхождение', + destination: 'Назначение', + missionDetails: 'Детали миссии', + transportedResources: 'Перевезённые ресурсы', + recycledResources: 'Переработанные ресурсы', + remainingDebris: 'Оставшиеся обломки', + newPlanet: 'Новая планета', // NPC activity dialog - npcActivityDetails: '', + npcActivityDetails: 'Детали активности NPC', activityType: { - recycle: '' + recycle: 'Переработка обломков' }, - activityLocation: '', - position: '', - nearPlanet: '', - activityDescription: '', - npcActivityMessage: '', - arrivalTime: '', - npcActivityTip: '', + activityLocation: 'Местоположение активности', + position: 'Позиция', + nearPlanet: 'Возле планеты', + activityDescription: 'Описание активности', + npcActivityMessage: '{npc} {activity} в {position}', + arrivalTime: 'Время прибытия', + npcActivityTip: 'NPC могут собирать обломки после боёв. Вы можете попытаться прибыть на место первым, чтобы конкурировать за ресурсы', clearMessages: 'Очистить сообщения', clearMessageTypes: 'Выберите типы сообщений для очистки', clearBattleReports: 'Боевые отчёты', @@ -853,7 +835,11 @@ export default { clearNPCActivity: 'Активность NPC', clearGiftNotifications: 'Уведомления о подарках', clearGiftRejected: 'Отклонённые подарки', - clearNow: 'Очистить сейчас' + clearTradeOffers: 'Торговые предложения', + clearIntelReports: 'Разведывательные отчёты', + clearJointAttackInvites: 'Приглашения на совместную атаку', + clearNow: 'Очистить сейчас', + clearSuccess: 'Сообщения очищены' }, missionReports: { transportSuccess: 'Миссия транспортировки успешно завершена', @@ -980,7 +966,6 @@ export default { viewUpdate: 'Просмотреть обновление', updateAvailable: 'Доступна новая версия. Нажмите, чтобы просмотреть примечания к выпуску.', download: 'Скачать', - goToDownload: 'Перейти к загрузке', buildDate: 'Дата сборки', community: 'Сообщество', github: 'Репозиторий GitHub', @@ -1002,14 +987,58 @@ export default { suppressInFocus: 'Не отправлять уведомления браузера, когда страница в фокусе', expandTypes: 'Развернуть детали', collapseTypes: 'Свернуть детали', + displaySettings: 'Настройки отображения', + displaySettingsDesc: 'Настройка визуальных эффектов игры', + backgroundAnimation: 'Фоновая анимация', + backgroundAnimationDesc: 'Показывать анимацию звёздного неба/частиц на фоне (может влиять на производительность)', // Обновление имен NPC - npcNameUpdate: 'Обновление имен NPC', npcNameUpdateTitle: 'Обнаружены устаревшие имена NPC', npcNameUpdateMessage: 'Найдено {count} NPC с устаревшим форматом имен. Хотите обновить их до новых локализованных имен?', npcNameUpdateConfirm: 'Обновить имена', npcNameUpdateCancel: 'Оставить как есть', npcNameUpdateSuccess: 'Успешно обновлено {count} имен NPC', - npcNameUpdateSkipped: 'Обновление имен NPC пропущено' + npcNameUpdateSkipped: 'Обновление имен NPC пропущено', + // WebDAV + webdav: { + title: 'Облачная синхронизация', + desc: 'Синхронизация сохранений через WebDAV', + config: 'Настроить', + configTitle: 'Настройка WebDAV', + configDesc: 'Настройте сервер WebDAV для облачной синхронизации', + notConfigured: 'Сначала настройте сервер WebDAV', + serverUrl: 'URL сервера', + serverUrlPlaceholder: 'напр. https://dav.example.com', + serverUrlHint: 'Введите адрес вашего WebDAV сервера', + username: 'Имя пользователя', + usernamePlaceholder: 'Введите имя пользователя', + password: 'Пароль', + passwordPlaceholder: 'Введите пароль', + passwordHint: 'Пароль хранится только локально', + basePath: 'Путь сохранений', + basePathPlaceholder: 'напр. /ogame-saves/', + testConnection: 'Проверить соединение', + testing: 'Проверка...', + testSuccess: 'Соединение успешно', + testFailed: 'Соединение не удалось', + save: 'Сохранить', + clearConfig: 'Очистить', + configSaved: 'Настройки сохранены', + configCleared: 'Настройки очищены', + upload: 'Загрузить', + uploading: 'Загрузка...', + uploadSuccess: 'Загрузка успешна', + uploadFailed: 'Загрузка не удалась', + download: 'Скачать', + downloadSuccess: 'Скачивание успешно', + downloadFailed: 'Скачивание не удалось', + selectFile: 'Выбрать сохранение', + selectFileDesc: 'Выберите файл сохранения для восстановления', + noFiles: 'Файлы сохранений не найдены', + loadFailed: 'Не удалось загрузить список файлов', + confirmDelete: 'Вы уверены, что хотите удалить "{name}"?', + deleteSuccess: 'Файл удален', + deleteFailed: 'Удаление не удалось' + } }, notifications: { constructionComplete: 'Строительство завершено', @@ -1031,8 +1060,8 @@ export default { officers: 'Офицеры', modifyResources: 'Изменить ресурсы', resourcesDesc: 'Быстрое изменение ресурсов планеты', - maxAllResources: '', - maxAllResourcesSuccess: '', + maxAllResources: 'Максимизировать все', + maxAllResourcesSuccess: 'Все ресурсы максимизированы', modifyBuildings: 'Изменить здания', buildingsDesc: 'Быстрая установка уровней зданий', modifyResearch: 'Изменить исследования', @@ -1074,10 +1103,10 @@ export default { dangerZoneDesc: 'Следующие операции необратимы', resetGame: 'Сбросить игру', resetGameConfirm: 'Вы уверены, что хотите сбросить игру? Все данные будут удалены!', - completeAllQueues: '', - completeAllQueuesDesc: '', - completeQueues: '', - completeQueuesSuccess: '' + completeAllQueues: 'Завершить все очереди', + completeAllQueuesDesc: 'Мгновенно завершить все очереди строительства, исследований, верфи, обороны и миссии флота', + completeQueues: 'Завершить очереди', + completeQueuesSuccess: 'Все очереди успешно завершены' }, alerts: { incomingFleets: '{count} вражеских флотов приближается', @@ -1108,11 +1137,13 @@ export default { missionType: { spy: 'Разведка', attack: 'Атака', + recycle: 'Переработка', unknown: 'Неизвестно' }, warning: { spy: 'Вражеская разведка приближается!', attack: 'Вражеская атака приближается!', + recycle: 'Враг перерабатывает обломки поблизости!', unknown: 'Вражеский флот приближается!' } }, @@ -1129,13 +1160,11 @@ export default { noFriendlyNpcs: 'Нет дружественных NPC', noNeutralNpcs: 'Нет нейтральных NPC', noHostileNpcs: 'Нет враждебных NPC', - recentEvents: 'Недавние события', - recentEventsDescription: 'Журнал последних дипломатических действий', ago: 'назад', - notifications: '', - markAllRead: '', - noReports: '', - viewAll: '', + notifications: 'Дипломатические уведомления', + markAllRead: 'Отметить всё прочитанным', + noReports: 'Нет дипломатических событий', + viewAll: 'Показать все', status: { friendly: 'Дружественный', neutral: 'Нейтральный', @@ -1154,7 +1183,6 @@ export default { }, note: 'Заметка', notePlaceholder: 'Введите заметку...', - noteEmpty: 'Нет заметки', lastEvent: 'Последнее событие', reportDetails: 'Детали дипломатического отчёта', eventDescription: 'Описание события', @@ -1210,6 +1238,19 @@ export default { npcEliminatedMessage: 'Вы уничтожили все планеты {npcName}! Эта фракция полностью уничтожена.' }, searchPlaceholder: 'Поиск NPC по имени...', + notificationType: { + tradeOffer: 'Торговое предложение', + intelReport: 'Разведывательный отчёт', + jointAttack: 'Приглашение на совместную атаку' + }, + notificationBadge: { + trade: 'Торговля', + intel: 'Разведка', + jointAttack: 'Приглашение' + }, + notificationExtra: { + pending: 'Ожидание' + }, viewMode: { card: 'Карточки', list: 'Список' @@ -1226,6 +1267,21 @@ export default { medium: 'Средняя', hard: 'Сложная' }, + aiType: 'Тип ИИ', + aiTypes: { + aggressive: 'Агрессивный', + defensive: 'Оборонительный', + trader: 'Торговец', + expansionist: 'Экспансионист', + balanced: 'Сбалансированный' + }, + aiTypeDescriptions: { + aggressive: 'Активно шпионит и атакует, сильная месть', + defensive: 'Редко атакует, сильная месть при нападении', + trader: 'Почти не атакует, предпочитает торговлю и подарки', + expansionist: 'Фокус на развитии, менее агрессивен', + balanced: 'Динамически адаптирует стратегию к ситуации' + }, reputation: 'Репутация', spyProbes: 'Шпионские зонды', fleetPower: 'Мощь флота', @@ -1252,27 +1308,12 @@ export default { attackCooldown: 'Атака на перезарядке ({min}м {sec}с)', notSpiedYet: 'Ещё не разведан, сначала нужна разведка' } - }, - aiType: 'Тип ИИ', - aiTypes: { - aggressive: 'Агрессивный', - defensive: 'Оборонительный', - trader: 'Торговец', - expansionist: 'Экспансионист', - balanced: 'Сбалансированный' - }, - aiTypeDescriptions: { - aggressive: 'Активно шпионит и атакует, сильная месть', - defensive: 'Редко атакует, сильная месть при нападении', - trader: 'Почти не атакует, предпочитает торговлю и подарки', - expansionist: 'Фокус на развитии, менее агрессивен', - balanced: 'Динамически адаптирует стратегию к ситуации' } }, pagination: { previous: 'Предыдущая', next: 'Следующая', - gotIt: '', + gotIt: 'Понятно', first: 'Первая', last: 'Последняя', page: 'Страница {page}' @@ -1336,9 +1377,35 @@ export default { seconds: 'секунд' }, tutorial: { + progress: 'Прогресс', + previous: 'Назад', + next: 'Далее', + gotIt: 'Понятно', + completeButton: 'Завершить', + skip: 'Пропустить руководство', welcome: { title: 'Добро пожаловать в OGame', - content: 'Добро пожаловать, Командир! Давайте начнём с основ и построим вашу космическую империю.' + content: + 'Добро пожаловать, Командир! Это руководство познакомит вас с основами построения империи. Нажмите "Далее", чтобы начать своё путешествие.' + }, + resources: { + title: 'Обзор ресурсов', + content: + 'Это ваши ресурсы: металл, кристалл и дейтерий. Они необходимы для строительства зданий и исследований. Энергия также важна для питания инфраструктуры.' + }, + planet: { + title: 'Ваша планета', + content: + 'Это ваша родная планета. Здесь вы можете увидеть название планеты, координаты и переключаться между планетами при расширении империи.' + }, + navigation: { + title: 'Меню навигации', + content: + 'Используйте это меню для перехода между разделами: здания, исследования, флот, галактика и другие. Каждый раздел предоставляет уникальные игровые функции.' + }, + gotoBuildings: { + title: 'Перейти к зданиям', + content: 'Давайте начнём с постройки зданий. Нажмите на пункт меню "Здания", чтобы увидеть доступные здания.' }, buildSolarPlant: { title: 'Постройте солнечную электростанцию', @@ -1350,16 +1417,119 @@ export default { content: 'Ваше здание теперь в очереди строительства. Нажмите на значок очереди в правом верхнем углу, чтобы увидеть все текущие задачи строительства и исследований. Строительство занимает время, но вы можете продолжать работать во время ожидания.' }, + buildMetalMine: { + title: 'Постройте рудник металла', + content: + 'Теперь, когда есть энергия, постройте рудник металла. Рудник металла — ваш основной источник металла, который используется почти в каждом здании и корабле.' + }, + buildCrystalMine: { + title: 'Постройте рудник кристалла', + content: + 'Кристалл более редкий, но важен для продвинутых технологий. Постройте рудник кристалла, чтобы начать сбор этого ценного ресурса.' + }, + buildDeuterium: { + title: 'Постройте синтезатор дейтерия', + content: + 'Дейтерий необходим для топлива кораблей и продвинутых исследований. Постройте синтезатор дейтерия, чтобы начать производство этого ключевого ресурса.' + }, + upgradeMines: { + title: 'Улучшите ресурсные рудники', + content: + 'Далее вам нужно улучшить все три ресурсных рудника (металл, кристалл, дейтерий) до уровня 2, чтобы соответствовать требованиям для фабрики роботов. Продолжайте улучшать их, когда накопите достаточно ресурсов.' + }, + buildRobotics: { + title: 'Постройте фабрику роботов', + content: + 'Фабрика роботов значительно ускоряет строительство. Она требует, чтобы рудники металла, кристалла и дейтерия были на уровне 2. Постройте её для повышения эффективности строительства!' + }, + upgradeMinesForLab: { + title: 'Продолжайте улучшать рудники', + content: + 'Теперь вам нужно улучшить все три ресурсных рудника до уровня 3, чтобы соответствовать требованиям исследовательской лаборатории. Продолжайте развивать производство ресурсов.' + }, + buildResearchLab: { + title: 'Постройте исследовательскую лабораторию', + content: + 'Исследовательская лаборатория — основа технологического прогресса. Она требует, чтобы все три ресурсных рудника были на уровне 3. Постройте её, чтобы разблокировать исследования!' + }, + gotoResearch: { + title: 'Перейти к исследованиям', + content: + 'Теперь, когда у вас есть исследовательская лаборатория, нажмите на пункт меню "Исследования", чтобы увидеть доступные технологии.' + }, + researchEnergy: { + title: 'Исследуйте энергетическую технологию', + content: + 'Энергетическая технология увеличивает производство энергии и открывает продвинутые здания. Это одна из самых базовых и важных технологий.' + }, + shipyardIntro: { + title: 'Флот и верфь', + content: + 'Корабли позволяют исследовать галактику, транспортировать ресурсы и защищать вашу империю. Для строительства кораблей вам нужна верфь (требуется фабрика роботов уровня 2).' + }, + gotoBuildingsForShipyard: { + title: 'Вернитесь к зданиям', + content: 'Вернитесь на страницу зданий, чтобы построить верфь.' + }, + buildShipyard: { + title: 'Постройте верфь', + content: 'Верфь позволяет строить корабли и оборонительные системы. Это критично для флотских операций.' + }, + fleetIntro: { + title: 'Флотские операции', + content: + 'Когда у вас появятся корабли, вы сможете отправлять их на миссии: транспортировать ресурсы, колонизировать планеты, атаковать врагов или исследовать поля обломков.' + }, + galaxyIntro: { + title: 'Исследование галактики', + content: + 'Вид галактики показывает другие планеты, поля обломков и возможности для расширения. Используйте его для разведки целей и планирования стратегии.' + }, + complete: { + title: 'Руководство завершено!', + content: + 'Поздравляем, Командир! Теперь вы знаете основы. Продолжайте строить империю, исследовать технологии и изучать галактику. Помните: сначала развивайте энергию, затем ресурсы, потом фабрики и исследования! Удачи!' + }, + // Мобильное руководство mobile: { welcome: { title: 'Добро пожаловать в OGame (Мобильная версия)', content: 'Добро пожаловать, Командир! Это упрощённое руководство, разработанное для сенсорных экранов. Мы быстро рассмотрим основные функции, чтобы вы могли начать строить свою империю.' }, + resources: { + title: 'Верхняя панель ресурсов', + content: + 'Вверху отображаются ваши ресурсы: металл, кристалл и дейтерий. Нажмите, чтобы увидеть подробную информацию о производстве.' + }, + menu: { + title: 'Открыть меню навигации', + content: + 'Нажмите на этот значок меню, чтобы открыть панель навигации, где можно получить доступ к зданиям, исследованиям, флоту и всем функциям.' + }, + gotoBuildings: { + title: 'Перейти к зданиям', + content: 'Меню открыто! Теперь нажмите на опцию "Здания", чтобы начать строительство инфраструктуры.' + }, + buildSolarPlant: { + title: 'Постройте солнечную электростанцию', + content: + 'Сначала постройте солнечную электростанцию! Прокрутите вниз, чтобы найти её, и нажмите на карточку для строительства. Энергия — основа всего.' + }, waitBuild: { title: 'Очередь строительства', content: 'Нажмите на значок очереди в правом верхнем углу, чтобы увидеть прогресс строительства. Вы можете продолжать просматривать другие страницы - строительство происходит в фоновом режиме.' + }, + buildMetalMine: { + title: 'Постройте рудник металла', + content: + 'После получения энергии постройте рудник металла. Прокрутите вниз, чтобы найти рудник металла, и нажмите для строительства.' + }, + complete: { + title: 'Быстрое руководство завершено!', + content: + 'Отлично! Вы освоили базовые операции. Продолжайте строить рудники кристалла и синтезатор дейтерия, затем исследуйте другие функции. Помните: сначала энергия, затем ресурсы!' } } }, @@ -1424,11 +1594,21 @@ export default { title: 'Симулятор боя', message: 'Симулируйте результаты боя перед атакой. Введите флоты и уровни технологий для прогноза победы, потерь и добычи.' }, + campaign: { + title: 'Режим кампании', + message: + 'Исследуйте сюжетную кампанию галактики! Выполняйте миссии, чтобы получить ресурсные награды и открыть новые испытания. Каждый узел имеет уникальные цели и врагов.' + }, achievements: { title: 'Система достижений', message: 'Выполняйте игровые цели для разблокировки достижений и получения наград в виде тёмной материи! Достижения имеют несколько уровней - стремитесь к более высоким целям для лучших наград.' }, + ranking: { + title: 'Рейтинг', + message: + 'Сравнивайте свой прогресс с другими игроками и NPC. Смотрите рейтинги по очкам за здания, исследования, флот и оборону. Стремитесь к вершине таблицы лидеров!' + }, settings: { title: 'Настройки', message: 'Управляйте игровыми данными, уведомлениями, импортом/экспортом сохранений. Регулярно создавайте резервные копии!' @@ -1554,5 +1734,344 @@ export default { you: 'Вы', scoreBreakdown: 'Детали очков', noData: 'Нет данных рейтинга' + }, + // Уведомления о расширенном поведении НПС + npcBehavior: { + tradeOfferReceived: 'Торговое предложение получено', + tradeOfferDesc: '{npcName} отправил вам торговое предложение', + attitudeChanged: 'Изменение отношения НПС', + becameFriendly: '{npcName} стал к вам дружелюбным', + becameHostile: '{npcName} стал к вам враждебным', + intelReceived: 'Разведданные получены', + intelReceivedDesc: '{npcName} поделился информацией о враге', + jointAttackInvite: 'Приглашение к совместной атаке', + jointAttackInviteDesc: '{npcName} приглашает вас совместно атаковать врага', + aidReceived: 'Помощь получена', + aidReceivedDesc: '{npcName} отправил вам {amount} ресурсов', + allyDefense: 'Союзная оборона', + allyDefenseDesc: '{npcName} отправляет флот для защиты вашей планеты', + trade: { + title: 'Торговые предложения', + from: 'От', + offers: 'Предлагает', + requests: 'Запрашивает', + expiresIn: 'Истекает через', + expired: 'Истекло', + accept: 'Принять', + decline: 'Отклонить', + noOffers: 'Нет торговых предложений', + acceptSuccess: 'Сделка завершена!', + acceptFailed: 'Недостаточно ресурсов для сделки', + declined: 'Сделка отклонена', + ratio: 'Курс обмена' + }, + intel: { + title: 'Разведывательные отчёты', + from: 'Источник', + target: 'Цель НПС', + type: 'Тип разведки', + types: { + enemyFleet: 'Данные о флоте', + enemyResources: 'Данные о ресурсах', + enemyMovement: 'Данные о передвижениях' + }, + fleetInfo: 'Информация о флоте', + resourceInfo: 'Информация о ресурсах', + movementInfo: 'Информация о передвижениях', + noReports: 'Нет разведывательных отчётов', + markAsRead: 'Отметить как прочитанное', + content: 'Содержание разведки', + noFleet: 'Флот не обнаружен', + noData: 'Нет данных', + targetPosition: 'Целевые координаты', + missionType: 'Тип миссии' + }, + jointAttack: { + title: 'Приглашения к совместной атаке', + from: 'Инициатор', + target: 'Цель НПС', + targetPlanet: 'Целевая планета', + npcFleet: 'Флот НПС', + lootShare: 'Доля добычи', + expiresIn: 'Истекает через', + expired: 'Истекло', + accept: 'Присоединиться к атаке', + decline: 'Отклонить', + noInvites: 'Нет приглашений к совместной атаке', + acceptSuccess: 'Вы присоединились к совместной атаке!', + declined: 'Приглашение отклонено', + targetInfo: 'Цель атаки', + expectedShare: 'Ожидаемая доля', + remaining: 'Оставшееся время' + }, + aid: { + title: 'Ресурсная помощь', + from: 'Источник', + resources: 'Ресурсы помощи', + noAid: 'Нет записей о помощи' + }, + attitudeChange: { + title: 'Изменения отношения', + npc: 'НПС', + previous: 'Было', + current: 'Сейчас', + reason: 'Причина', + reasons: { + naturalSwing: 'Естественное изменение', + giftReceived: 'Получен подарок', + attacked: 'Был атакован', + reputationThreshold: 'Порог репутации', + attitude_swing: 'Смена отношения', + gift: 'Получен подарок', + attack: 'Был атакован' + } + }, + allyAction: { + title: 'Действия союзников', + defense: 'Оборонная поддержка', + defenseDesc: '{npcName} отправляет флот для защиты {targetPlanet}', + jointAttackStarted: 'Совместная атака началась', + jointAttackStartedDesc: 'Совместная атака на {targetNpc} началась', + reputationBonus: 'Бонус репутации', + reputationBonusDesc: 'Ваш союзник {npcName} хорошо отзывается о вас {targetNpc}' + } + }, + campaign: { + name: 'Кампания', + description: 'Исследуйте загадочную галактику и раскройте древние тайны', + totalProgress: 'Общий прогресс', + questsCompleted: 'Квестов выполнено', + chapter: 'Глава', + branch: 'Ветвь', + startQuest: 'Начать квест', + claimRewards: 'Получить награды', + objectives: 'Цели', + objectivesLabel: 'Цели', + rewards: 'Награды', + completed: 'Завершено', + inProgress: 'В процессе', + available: 'Доступно', + locked: 'Заблокировано', + notifications: { + questStarted: 'Квест начат', + questCompleted: 'Квест завершён!', + rewardsClaimed: 'Награды получены', + objectiveCompleted: 'Цель достигнута', + chapterUnlocked: 'Новая глава разблокирована', + reputationUp: 'Репутация с {npcName} повысилась на {value}', + reputationDown: 'Репутация с {npcName} понизилась на {value}', + branchUnlocked: 'Новая сюжетная ветка разблокирована!' + }, + dialogue: { + skip: 'Пропустить', + continue: 'Продолжить', + finish: 'Завершить', + player: 'Командир', + npc: 'NPC', + narrator: 'Рассказчик', + mysterious: 'Загадочный сигнал', + unknownSource: 'Неизвестный источник', + choiceEffect: 'Эффект выбора диалога' + }, + chapters: { + '1': { + title: 'Начало', + description: 'Постройте свой дом и сделайте первый шаг в космос', + backgroundStory: + 'Вы молодой космический командир, только что получивший свою первую планету. В этой необъятной вселенной вы будете строить свой дом, развивать технологии и исследовать глубины галактики...' + }, + '2': { + title: 'Исследование', + description: 'Исследуйте вселенную и откройте древние руины', + backgroundStory: + 'По мере роста вашей мощи загадочные сигналы из глубокого космоса привлекают ваше внимание. Эти сигналы, кажется, указывают на древнюю тайну, ожидающую смелых исследователей...' + }, + '3': { + title: 'Дипломатия', + description: 'Установите связи с другими фракциями', + backgroundStory: + 'Вы не одиноки в галактике. Другие цивилизации поднимаются. Вы должны решить, быть ли им врагом или союзником. Дипломатическая мудрость определит, как далеко зайдёт ваша империя...' + }, + '4': { + title: 'Восходящая тень', + description: 'Противостойте могущественным врагам и защитите свою территорию', + backgroundStory: + 'Опасность таится в тени. Могущественная враждебная сила нацелилась на вашу территорию. Война неизбежна. Вы должны подготовиться к надвигающейся буре...' + }, + '5': { + title: 'Древние тайны', + description: 'Раскройте глубочайшие секреты галактики', + backgroundStory: + 'Все улики указывают на самый загадочный регион галактики. Там скрыты конечные тайны, оставленные древними цивилизациями. Готовы ли вы раскрыть всё?' + } + }, + quests: { + '1_1': { title: 'Строительство дома', description: 'Постройте инфраструктуру, чтобы заложить основу для вашей планеты' }, + '1_2': { title: 'Техническое просвещение', description: 'Исследуйте базовые технологии, чтобы начать свой технологический путь' }, + '1_3': { title: 'Первый корабль', description: 'Постройте свой первый боевой корабль' }, + '1_4': { title: 'Странные соседи', description: 'Разведайте другие фракции в ближайших системах' }, + '1_5': { title: 'Первый контакт', description: 'Установите начальный контакт с ближайшими NPC-фракциями' }, + '2_1': { title: 'Пионерская колония', description: 'Колонизируйте свою первую новую планету' }, + '2_2': { title: 'Экспедиция в глубокий космос', description: 'Отправьте флот в экспедиционные миссии' }, + '2_3': { title: 'Загадочный сигнал', description: 'Исследуйте загадочные сигналы из глубокого космоса' }, + '2_4': { title: 'Исследование руин', description: 'Исследуйте обнаруженные древние руины' }, + '2_5': { title: 'Расшифровка архивов', description: 'Изучите данные, полученные из руин' }, + '3_1': { title: 'Миротворец', description: 'Улучшите отношения с NPC через дипломатию' }, + '3_2': { title: 'Торговые отношения', description: 'Установите стабильные отношения с дружественными фракциями' }, + '3_3': { title: 'Общая угроза', description: 'Обнаружьте потенциальные враждебные силы' }, + '3_4': { title: 'Переговоры об альянсе', description: 'Заключите официальный альянс с дружественными NPC' }, + '3_5': { title: 'Подготовка к буре', description: 'Постройте оборону для подготовки к вызовам' }, + '4_1': { title: 'Атака на форпост', description: 'Отразите первую атаку враждебных сил' }, + '4_2': { title: 'Сбор разведданных', description: 'Разведайте военные позиции врага' }, + '4_3': { title: 'Контратака', description: 'Начните контратаку против врага' }, + '4_4': { title: 'Борьба за ресурсы', description: 'Переработайте обломки поля боя для ресурсов' }, + '4_5': { title: 'Канун битвы', description: 'Постройте мощный флот для финальной битвы' }, + '5_1': { title: 'Глубины руин', description: 'Исследуйте самые глубокие части руин' }, + '5_2': { title: 'Древние технологии', description: 'Разблокируйте технологии древних цивилизаций' }, + '5_3': { title: 'Финальное противостояние', description: 'Примите участие в финальной битве с загадочным врагом' }, + '5_4': { title: 'Новая эра', description: 'Основывайте новые колонии и начните новую эпоху' }, + '5_5': { title: 'Продолжение наследия', description: 'Продолжайте развитие и завоёвывайте больше систем' } + }, + objectiveTypes: { + buildBuilding: 'Построить {building} до уровня {level}', + researchTech: 'Исследовать {tech} до уровня {level}', + produceShips: 'Произвести {count} {ship}', + accumulateResources: 'Накопить {amount} {resource}', + defeatNPC: 'Победить {npc}', + winBattles: 'Выиграть {count} сражений', + recycleDebris: 'Переработать {amount} обломков', + reachRelation: 'Достичь отношений {level} с {npc}', + sendGift: 'Отправить {count} подарков {npc}', + formAlliance: 'Заключить альянс с {npc}', + colonize: 'Колонизировать {count} планет', + expedition: 'Завершить {count} экспедиций', + spyTarget: 'Разведать {target}' + }, + errors: { + questNotFound: 'Квест не найден', + questNotAvailable: 'Квест недоступен', + questNotActive: 'Квест не активен', + questNotCompleted: 'Квест не завершён', + rewardsAlreadyClaimed: 'Награды уже получены', + prerequisiteNotMet: 'Предварительный квест не завершён' + }, + speakers: { + ancientVoice: 'Древний голос', + neighborNPC: 'Соседняя фракция', + mysteriousSignal: 'Загадочный сигнал', + enemyCommander: 'Вражеский командир' + }, + objectiveDescriptions: { + buildMetalMine: 'Построить Металлургический завод до уровня 2', + buildCrystalMine: 'Построить Кристаллический завод до уровня 2', + buildSolarPlant: 'Построить Солнечную электростанцию до уровня 2', + buildResearchLab: 'Построить Исследовательскую лабораторию до уровня 1', + researchEnergy: 'Исследовать Энергетическую технологию до уровня 1', + buildShipyard: 'Построить Верфь до уровня 2', + researchCombustion: 'Исследовать Реактивный двигатель до уровня 1', + buildLightFighters: 'Построить 5 Лёгких истребителей', + researchEspionage: 'Исследовать Шпионаж до уровня 2', + buildSpyProbes: 'Построить 3 Шпионских зонда', + spyAnyNPC: 'Разведать планету NPC', + sendGiftToNPC: 'Отправить подарок NPC', + researchAstrophysics: 'Исследовать Астрофизику до уровня 1', + buildColonyShip: 'Построить Колониальный корабль', + colonizeNewPlanet: 'Колонизировать новую планету', + completeExpedition: 'Завершить экспедиционную миссию', + discoverRuins: 'Обнаружить древние руины', + researchComputer: 'Исследовать Компьютерную технологию до уровня 4', + improveRelation: 'Улучшить отношения с NPC', + reachFriendly: 'Достичь дружеского статуса с NPC', + spyHostileNPC: 'Разведать враждебного NPC', + formAlliance: 'Заключить альянс с дружественным NPC', + buildDefenses: 'Построить оборонительные сооружения', + winDefenseBattle: 'Выиграть оборонительное сражение', + spyEnemyPlanet: 'Разведать вражескую планету', + attackEnemy: 'Атаковать врага', + recycleDebris: 'Переработать обломки', + buildBattleships: 'Построить 10 Линкоров', + exploreDeepRuins: 'Исследовать глубокие руины', + researchHyperspace: 'Исследовать Гиперпространственную технологию', + defeatBoss: 'Победить загадочного врага', + colonizeSpecial: 'Колонизировать особое место', + continueDevelopment: 'Продолжить развитие' + }, + dialogues: { + '1_1': { + prologue_1: + 'Добро пожаловать в галактику, молодой командир. Эта необъятная вселенная ждёт вашего исследования. Сначала построим вашу родную планету.', + prologue_2: 'Я чувствую пробуждение нового сознания... Интересно... Посмотрим, как далеко ты зайдёшь...' + }, + '1_2': { + prologue_1: + 'Базовая инфраструктура завершена. Теперь время развивать технологии. Постройте Исследовательскую лабораторию и начните свой технологический путь.' + }, + '1_3': { + prologue_1: + 'С технологической поддержкой вы можете начать строить свой флот. Постройте Верфь и произведите свой первый боевой корабль.' + }, + '1_4': { + prologue_1: + 'Ваш флот обретает форму. Теперь давайте узнаем о вашем окружении. Отправьте шпионские зонды для разведки ближайших фракций.', + prologue_2: 'Ты не один... В этой галактике существуют другие цивилизации...' + }, + '1_5': { + prologue_1: 'Вы обнаружили ближайшие фракции. Дипломатия — это искусство. Попробуйте установить с ними контакт.', + epilogue_1: 'Спасибо за ваш подарок, командир. Надеюсь, мы станем друзьями.', + epilogue_2: 'Хорошо... Установление связей — первый шаг к раскрытию более глубоких тайн...' + }, + '2_1': { + prologue_1: + 'Ваша сила установлена. Пора расширять территорию. Исследуйте Астрофизику, постройте колониальный корабль и исследуйте новые планеты.', + prologue_2: 'Вселенная бесконечна... Больше планет означает больше возможностей...' + }, + '2_2': { + prologue_1: 'Колонизация успешна! Но в космосе ждут более глубокие тайны. Отправьте свой флот в экспедиционные миссии.', + prologue_2: 'Слабые сигналы издалека... Что-то ждёт тебя там...' + }, + '2_3': { + prologue_1: + 'Ваша экспедиция обнаружила аномальные сигналы. Эти сигналы, похоже, исходят от древней цивилизации... Исследуйте их источник.', + epilogue_1: 'Эти символы... Это руины древней цивилизации! Продолжайте исследование, чтобы раскрыть их тайны.' + }, + '2_4': { + prologue_1: 'Вы нашли местоположение древних руин. Отправьте свой флот на исследование и посмотрите, что вы можете обнаружить.' + }, + '2_5': { prologue_1: 'В руинах найдены архивы данных. Изучите эти данные, возможно, вы сможете разблокировать новую технологию.' }, + '3_1': { + prologue_1: 'Во время исследований не забывайте о дипломатии. Поддержание хороших отношений с окружающими фракциями выгодно.' + }, + '3_2': { + prologue_1: 'Некоторые фракции проявили дружелюбие. Продолжайте углублять отношения, возможно, вы получите больше поддержки.' + }, + '3_3': { + prologue_1: + 'Разведка показывает, что враждебные силы наблюдают за вами из тени. Оставайтесь бдительными и разведайте их перемещения.' + }, + '3_4': { prologue_1: 'Заключите официальный альянс с дружественными фракциями для взаимной поддержки против угроз.' }, + '3_5': { prologue_1: 'Угрозы приближаются. Постройте оборонительные сооружения и подготовьтесь к возможному конфликту.' }, + '4_1': { + prologue_1: 'Враг начал атаку! Защитите свою планету!', + epilogue_1: 'Вы успешно отбили первую волну врага. Но это только начало...' + }, + '4_2': { prologue_1: 'Враг отступил, но он вернётся. Разведайте их планеты, чтобы понять их силу.' }, + '4_3': { prologue_1: 'Пора контратаковать. Атакуйте вражеские планеты и ослабьте их силы.' }, + '4_4': { prologue_1: 'На поле боя осталось много обломков. Переработайте эти ресурсы для подготовки к следующей битве.' }, + '4_5': { prologue_1: 'Финальная битва приближается. Постройте мощный флот и приготовьтесь к конечному испытанию.' }, + '5_1': { + prologue_1: 'Все улики указывают на самую глубокую часть руин. Ключевые тайны древней цивилизации находятся там.', + prologue_2: 'Ты наконец прибыл... Истина скоро откроется...' + }, + '5_2': { prologue_1: 'В глубинах руин вы обнаружили утерянные древние технологии. Исследуйте и разблокируйте их мощь.' }, + '5_3': { + prologue_1: 'Появился загадочный враг. Это финальное испытание. Победите его!', + epilogue_1: 'Вы справились! Древний страж повержен. Тайны галактики теперь открыты для вас.' + }, + '5_4': { prologue_1: 'Мир наконец наступил. В эту новую эру основывайте новые колонии и расширяйте свою империю.' }, + '5_5': { + prologue_1: 'Ваша легенда только началась. Продолжайте исследовать и завоёвывать больше звёздных систем!', + epilogue_1: 'Галактика необъятна и бесконечна, бесчисленные тайны ждут вас...' + } + } } } diff --git a/src/locales/zh-CN.ts b/src/locales/zh-CN.ts index 20053b7..1f5c76c 100644 --- a/src/locales/zh-CN.ts +++ b/src/locales/zh-CN.ts @@ -11,28 +11,10 @@ export default { common: { confirm: '确认', cancel: '取消', - delete: '删除', - edit: '编辑', save: '保存', close: '关闭', - back: '返回', - next: '下一步', - previous: '上一步', - submit: '提交', - reset: '重置', - search: '搜索', - filter: '筛选', - loading: '加载中...', - noData: '暂无数据', - error: '错误', success: '成功', - warning: '警告', - info: '信息', resourceType: '资源类型', - playerName: '指挥官', - timeHour: '时', - timeMinute: '分', - timeSecond: '秒', featureLocked: '功能已锁定', unlockRequired: '需要解锁前置建筑', requiredBuilding: '所需建筑', @@ -40,7 +22,6 @@ export default { goToBuildings: '前往建筑页面', locked: '已锁定', viewRequirements: '查看前置条件', - requirements: '前置条件', requirementsNotMet: '前置条件未满足', current: '当前', level: '等级', @@ -50,7 +31,8 @@ export default { viewDetails: '查看详情', exitConfirmTitle: '退出游戏', exitConfirmMessage: '确定要退出游戏吗?游戏进度会自动保存。', - points: '积分' + points: '积分', + retry: '重试' }, errors: { requirementsNotMet: '不满足前置条件', @@ -94,7 +76,6 @@ export default { gm: 'GM' }, sidebar: { - language: '语言', lightMode: '日间模式', darkMode: '夜间模式', collapse: '收起菜单', @@ -119,9 +100,6 @@ export default { }, energy: { lowWarning: '电力不足,资源生产已停止!', - severeWarning: '电力不足,资源生产已停止!', - criticalWarning: '电力不足,资源生产已停止!', - noProduction: '电力不足,资源生产已停止!', deficitDetail: '电力缺口: {deficit},请建造更多电站', buildSolarPlant: '建造电站' }, @@ -132,27 +110,20 @@ export default { lowResources: '即将耗尽: {resources}' }, planet: { - planet: '星球', moon: '月球', - colony: '殖民地', position: '位置', - coordinates: '坐标', switchToMoon: '查看月球', backToPlanet: '返回母星', switchPlanet: '切换星球', currentPlanet: '当前星球', - fields: '场地', temperature: '温度', homePlanet: '母星', planetPrefix: '星球', - moonSuffix: '的月球', colonyPrefix: '殖民地', renamePlanet: '重命名星球', renamePlanetTitle: '重命名星球', - newPlanetName: '新名称', planetNamePlaceholder: '输入新的星球名称', - rename: '重命名', - renameSuccess: '星球已重命名为 {name}' + rename: '重命名' }, player: { points: '总积分' @@ -179,6 +150,8 @@ export default { sensorPhalanx: '传感器阵列', jumpGate: '跳跃门', planetDestroyerFactory: '行星毁灭者工厂', + geoResearchStation: '地质研究站', + deepDrillingFacility: '深层钻探设施', buildTime: '建造时间', production: '产量', consumption: '消耗', @@ -225,7 +198,9 @@ export default { lunarBase: '增加月球可用空间,每级+30空间', sensorPhalanx: '侦测周围星系的舰队活动', jumpGate: '瞬间传送舰队到其他月球', - planetDestroyerFactory: '建造能够摧毁行星的终极武器' + planetDestroyerFactory: '建造能够摧毁行星的终极武器', + geoResearchStation: '研究地质结构,提高矿脉自然恢复速度。每级增加50%恢复速率', + deepDrillingFacility: '深入地壳钻探,解锁更深层的矿脉储量。每级增加20%矿脉上限' }, ships: { lightFighter: '轻型战斗机', @@ -289,9 +264,6 @@ export default { }, research: { researchTime: '研究时间', - totalCost: '累积成本', - totalPoints: '累积积分', - levelRange: '等级范围', attackBonus: '攻击加成', shieldBonus: '护盾加成', @@ -300,8 +272,7 @@ export default { researchQueueBonus: '研究队列', colonySlots: '殖民地槽位', forAllPlanets: '(全局)', - speedBonus: '速度加成', - researchSpeedBonus: '研究速度加成' + speedBonus: '速度加成' }, technologies: { energyTechnology: '能源技术', @@ -321,7 +292,8 @@ export default { hyperspaceDrive: '超空间引擎', darkMatterTechnology: '暗物质技术', terraformingTechnology: '地形改造技术', - planetDestructionTech: '行星毁灭技术' + planetDestructionTech: '行星毁灭技术', + miningTechnology: '采矿技术' }, technologyDescriptions: { energyTechnology: '提高能源利用效率', @@ -342,7 +314,8 @@ export default { hyperspaceDrive: '高级推进技术', darkMatterTechnology: '研究暗物质的性质和应用', terraformingTechnology: '研究行星地形改造技术,每级为所有行星增加30个可用空间', - planetDestructionTech: '研究如何摧毁整个行星的恐怖技术' + planetDestructionTech: '研究如何摧毁整个行星的恐怖技术', + miningTechnology: '改进采矿方法和设备,提升所有星球矿脉储量上限。每级增加15%矿脉上限' }, officers: { commander: '指挥官', @@ -397,14 +370,9 @@ export default { movedToQueue: '任务已移至正式队列' }, overview: { - title: '星球总览', resourceOverview: '资源概览', fleetInfo: '舰队', currentShips: '当前星球的舰船数量', - productionSources: '资源获取来源', - productionSourcesDesc: '详细的资源产量及加成信息', - consumptionSources: '电力消耗来源', - consumptionSourcesDesc: '各建筑的电力消耗详情', totalProduction: '总产量', totalConsumption: '总消耗', noConsumption: '当前无电力消耗', @@ -414,12 +382,8 @@ export default { }, buildingsView: { title: '建筑', - usedSpace: '已用空间', spaceUsage: '占用空间', - level: '等级', upgradeCost: '升级消耗', - buildTime: '建造时间', - build: '建造', upgrade: '升级', maxLevelReached: '等级已满', requirementsNotMet: '条件不足', @@ -429,8 +393,7 @@ export default { demolishRefund: '拆除返还', demolishFailed: '拆除失败', demolishFailedMessage: '无法拆除该建筑,请检查建造队列是否已满或建筑等级是否为0。', - confirmDemolish: '确认拆除', - confirmDemolishMessage: '确定要拆除' + confirmDemolish: '确认拆除' }, researchView: { title: '研究', @@ -441,24 +404,13 @@ export default { researchFailedMessage: '请检查资源是否足够、前置条件是否满足,或是否有其他研究任务。' }, shipyard: { - attack: '攻击力', - shield: '护盾', - armor: '装甲', speed: '速度', cargoCapacity: '载货量', - fuelConsumption: '燃料消耗', - buildCost: '建造成本', - buildTime: '建造时间', - perUnit: '每个单位', - batchCalculator: '批量建造计算器', - quantity: '数量', - totalCost: '总成本', - totalTime: '总时间' + fuelConsumption: '燃料消耗' }, shipyardView: { title: '船坞', fleetStorage: '舰队仓储', - owned: '拥有', attack: '攻击力', shield: '护盾', speed: '速度', @@ -643,7 +595,6 @@ export default { benefitsBonus: '效果加成', resourceProduction: '资源产量', darkMatterProduction: '暗物质产量', - energyProduction: '电量产出', buildingSpeed: '建筑速度', researchSpeed: '研究速度', fleetSpeed: '舰队速度', @@ -672,14 +623,11 @@ export default { selectGalaxy: '选择银河系', system: '星系', selectSystem: '选择星系', - view: '查看', - myPlanet: '我的星球', myPlanets: '查看我的星系', npcPlanets: 'NPC星球', selectPlanetToView: '选择星球以查看其所在星系', totalPositions: '共10个星球位置', mine: '我的', - hostile: '敌对', emptySlot: '空位 - 可殖民', scout: '侦察', attack: '攻击', @@ -704,9 +652,10 @@ export default { missileCount: '导弹数量', availableMissiles: '可用导弹', missileRange: '射程', - systems: '系统', + systems: '星系', distance: '距离', flightTime: '飞行时间', + outOfRange: '超出射程', launchMissile: '发射', missileLaunched: '导弹已发射', cancel: '取消', @@ -719,17 +668,13 @@ export default { phalanxScanTitle: '传感器阵列扫描', phalanxScanDescription: '扫描星球 [{coordinates}] 的舰队活动', phalanxNoMoon: '需要有传感器阵列的月球才能扫描', - phalanxOutOfRange: '目标超出扫描范围', - phalanxRange: '扫描范围', phalanxCost: '扫描消耗', phalanxNoFleets: '未检测到舰队活动', phalanxFleetDetected: '检测到 {count} 支舰队', - phalanxMission: '任务', phalanxOrigin: '出发地', phalanxDestination: '目的地', phalanxArrival: '到达时间', phalanxReturn: '返回时间', - phalanxStatus: '状态', phalanxStatusOutbound: '前往中', phalanxStatusReturning: '返回中', phalanxInsufficientDeuterium: '氘不足', @@ -767,6 +712,8 @@ export default { defense: '防御', buildings: '建筑', unread: '未读', + pending: '待处理', + invalidData: '无效数据', targetPlanet: '目标星球', attackerRemaining: '攻击方剩余', defenderRemaining: '防守方剩余', @@ -859,7 +806,11 @@ export default { clearNPCActivity: 'NPC活动', clearGiftNotifications: '礼物通知', clearGiftRejected: '拒绝记录', - clearNow: '立即清空' + clearTradeOffers: '贸易提议', + clearIntelReports: '情报报告', + clearJointAttackInvites: '联合攻击邀请', + clearNow: '立即清空', + clearSuccess: '消息已清空' }, missionReports: { transportSuccess: '运输任务成功完成', @@ -967,7 +918,6 @@ export default { resume: '恢复', gamePaused: '游戏已暂停', gameResumed: '游戏已恢复', - playerName: '玩家名称', gameSpeed: '资源产出速度', gameSpeedDesc: '当前资源产出速度倍率', speedChanged: '资源产出速度已更改为 {speed}x', @@ -975,17 +925,14 @@ export default { reset: '重置', about: '关于', version: '版本', - latestVersion: '最新版本', checkUpdate: '检查更新', checking: '检查中...', newVersionAvailable: '发现新版本 {version}', upToDate: '已是最新版本', - checkUpdateCooldown: '请稍后再试(5分钟冷却时间)', checkUpdateFailed: '检查更新失败,请检查网络连接', viewUpdate: '查看更新', updateAvailable: '有新版本可用。点击查看更新内容。', download: '下载', - goToDownload: '前往下载', buildDate: '构建日期', community: '社区', github: 'GitHub 仓库', @@ -1012,13 +959,53 @@ export default { expandTypes: '展开详细设置', collapseTypes: '收起详细设置', // NPC名称更新 - npcNameUpdate: 'NPC名称更新', npcNameUpdateTitle: '检测到旧版NPC名称', npcNameUpdateMessage: '发现 {count} 个NPC使用旧版名称格式。是否更新为新的本地化名称?', npcNameUpdateConfirm: '更新名称', npcNameUpdateCancel: '保持原样', npcNameUpdateSuccess: '已成功更新 {count} 个NPC名称', - npcNameUpdateSkipped: '已跳过NPC名称更新' + npcNameUpdateSkipped: '已跳过NPC名称更新', + // WebDAV + webdav: { + title: '云同步', + desc: '通过WebDAV同步游戏存档', + config: '配置', + configTitle: 'WebDAV 配置', + configDesc: '配置WebDAV服务器以启用云同步', + notConfigured: '请先配置WebDAV服务器', + serverUrl: '服务器地址', + serverUrlPlaceholder: '例如 https://dav.example.com', + serverUrlHint: '输入您的WebDAV服务器地址', + username: '用户名', + usernamePlaceholder: '输入用户名', + password: '密码', + passwordPlaceholder: '输入密码', + passwordHint: '密码仅存储在本地', + basePath: '存档路径', + basePathPlaceholder: '例如 /ogame-saves/', + testConnection: '测试连接', + testing: '测试中...', + testSuccess: '连接成功', + testFailed: '连接失败', + save: '保存', + clearConfig: '清除', + configSaved: '配置已保存', + configCleared: '配置已清除', + upload: '上传', + uploading: '上传中...', + uploadSuccess: '上传成功', + uploadFailed: '上传失败', + download: '下载', + downloadSuccess: '下载成功', + downloadFailed: '下载失败', + selectFile: '选择存档', + selectFileDesc: '选择要恢复的存档文件', + noFiles: '没有找到存档文件', + loadFailed: '加载文件列表失败', + confirmDelete: '确定要删除 "{name}" 吗?', + deleteSuccess: '文件已删除', + deleteFailed: '删除失败' + } }, notifications: { constructionComplete: '建造完成', @@ -1140,8 +1127,6 @@ export default { noFriendlyNpcs: '暂无友好NPC', noNeutralNpcs: '暂无中立NPC', noHostileNpcs: '暂无敌对NPC', - recentEvents: '最近事件', - recentEventsDescription: '最近的外交活动记录', ago: '前', notifications: '外交通知', markAllRead: '全部已读', @@ -1165,7 +1150,6 @@ export default { }, note: '备注', notePlaceholder: '输入备注...', - noteEmpty: '无备注', lastEvent: '最近活动', reportDetails: '外交报告详情', eventDescription: '事件描述', @@ -1220,10 +1204,23 @@ export default { npcEliminatedMessage: '你消灭了{npcName}的所有星球!该势力已被彻底摧毁。' }, searchPlaceholder: '搜索NPC名称...', - viewMode: { - card: '卡片', - list: '列表' + // 通知类型 + notificationType: { + tradeOffer: '贸易提议', + intelReport: '情报报告', + jointAttack: '联合攻击邀请' }, + // 通知徽章 + notificationBadge: { + trade: '贸易', + intel: '情报', + jointAttack: '邀请' + }, + // 通知额外信息 + notificationExtra: { + pending: '待处理' + }, + diagnostic: { button: 'NPC状态诊断', title: 'NPC状态诊断', @@ -1278,6 +1275,101 @@ export default { } } }, + // NPC增强行为通知 + npcBehavior: { + // 中立NPC行为 + tradeOfferReceived: '收到贸易提议', + tradeOfferDesc: '{npcName}向你发来了贸易提议', + attitudeChanged: 'NPC态度变化', + becameFriendly: '{npcName}对你的态度变得友好了', + becameHostile: '{npcName}对你的态度变得敌对了', + // 友好NPC行为 + intelReceived: '收到情报', + intelReceivedDesc: '{npcName}向你分享了敌方情报', + jointAttackInvite: '联合攻击邀请', + jointAttackInviteDesc: '{npcName}邀请你一起攻击敌人', + aidReceived: '收到援助', + aidReceivedDesc: '{npcName}向你赠送了 {amount} 资源', + allyDefense: '盟友协防', + allyDefenseDesc: '{npcName}派遣舰队协助防御你的星球', + // 贸易相关 + trade: { + title: '贸易提议', + from: '来自', + offers: '提供', + requests: '请求', + expiresIn: '剩余时间', + expired: '已过期', + accept: '接受', + decline: '拒绝', + noOffers: '暂无贸易提议', + acceptSuccess: '贸易完成!', + acceptFailed: '资源不足,无法完成贸易', + declined: '已拒绝贸易', + ratio: '交换比率' + }, + // 情报相关 + intel: { + title: '情报报告', + from: '情报来源', + target: '目标NPC', + type: '情报类型', + types: { + enemyFleet: '舰队情报', + enemyResources: '资源情报', + enemyMovement: '动向情报' + }, + fleetInfo: '舰队信息', + resourceInfo: '资源信息', + movementInfo: '动向信息', + noReports: '暂无情报报告', + markAsRead: '标记已读', + content: '情报内容', + noFleet: '未探测到舰队', + noData: '暂无数据', + targetPosition: '目标坐标', + missionType: '任务类型' + }, + // 联合攻击相关 + jointAttack: { + title: '联合攻击邀请', + from: '发起者', + target: '目标NPC', + targetPlanet: '目标星球', + npcFleet: 'NPC出动舰队', + lootShare: '战利品分成', + expiresIn: '剩余时间', + expired: '已过期', + accept: '参与攻击', + decline: '婉拒', + noInvites: '暂无联合攻击邀请', + acceptSuccess: '已加入联合攻击!', + declined: '已婉拒邀请', + targetInfo: '攻击目标', + expectedShare: '预期分成', + remaining: '剩余时间' + }, + // 援助相关 + aid: { + title: '资源援助', + from: '援助来源', + resources: '援助资源', + noAid: '暂无援助记录' + }, + // 态度变化相关 + attitudeChange: { + title: '态度变化', + npc: 'NPC', + previous: '之前', + current: '现在', + reason: '原因', + reasons: { + attitude_swing: '态度摇摆', + gift: '收到礼物', + attack: '遭受攻击' + } + } + }, pagination: { previous: '上一页', next: '下一页', @@ -1527,10 +1619,18 @@ export default { title: '战斗模拟器', message: '在发动攻击前模拟战斗结果。输入双方舰队和科技等级,预测胜负和损失。' }, + campaign: { + title: '战役模式', + message: '探索银河系的故事战役!完成任务获得资源奖励,解锁新的挑战。每个节点都有独特的目标和敌人。' + }, achievements: { title: '成就系统', message: '完成各类游戏目标解锁成就,获得暗物质奖励!成就分为多个等级,挑战更高难度获得更丰厚的奖励。' }, + ranking: { + title: '排行榜', + message: '与其他玩家和NPC比较进度。查看基于建筑、研究、舰队和防御积分的排名。努力攀登排行榜!' + }, settings: { title: '设置', message: '在这里管理游戏数据、调整通知设置、导出/导入存档。记得定期备份你的进度!' @@ -1666,7 +1766,6 @@ export default { startQuest: '开始任务', claimRewards: '领取奖励', objectives: '任务目标', - objectivesLabel: '目标', rewards: '任务奖励', completed: '已完成', inProgress: '进行中', @@ -1677,7 +1776,10 @@ export default { questCompleted: '任务完成!', rewardsClaimed: '奖励已领取', objectiveCompleted: '目标完成', - chapterUnlocked: '新章节已解锁' + chapterUnlocked: '新章节已解锁', + reputationUp: '与 {npcName} 的声望提升了 {value}', + reputationDown: '与 {npcName} 的声望降低了 {value}', + branchUnlocked: '新的故事分支已解锁!' }, dialogue: { skip: '跳过', @@ -1687,18 +1789,21 @@ export default { npc: 'NPC', narrator: '旁白', mysterious: '神秘信号', - unknownSource: '信号来源不明' + unknownSource: '信号来源不明', + choiceEffect: '对话选择效果' }, chapters: { '1': { title: '起源之地', description: '建设你的家园,迈出星际征途的第一步', - backgroundStory: '你是一位年轻的星际指挥官,刚刚获得了属于自己的第一颗星球。在这片陌生的宇宙中,你将建设家园,发展科技,探索未知的银河系深处...' + backgroundStory: + '你是一位年轻的星际指挥官,刚刚获得了属于自己的第一颗星球。在这片陌生的宇宙中,你将建设家园,发展科技,探索未知的银河系深处...' }, '2': { title: '星际探索', description: '探索宇宙,发现神秘的古代遗迹', - backgroundStory: '随着你的势力不断壮大,来自深空的神秘信号引起了你的注意。这些信号似乎指向一个古老的秘密,等待着勇敢的探索者去揭开...' + backgroundStory: + '随着你的势力不断壮大,来自深空的神秘信号引起了你的注意。这些信号似乎指向一个古老的秘密,等待着勇敢的探索者去揭开...' }, '3': { title: '银河外交', diff --git a/src/locales/zh-TW.ts b/src/locales/zh-TW.ts index eae5b9d..21b18a1 100644 --- a/src/locales/zh-TW.ts +++ b/src/locales/zh-TW.ts @@ -11,29 +11,12 @@ export default { common: { confirm: '確認', cancel: '取消', - delete: '刪除', - edit: '編輯', save: '儲存', close: '關閉', - back: '返回', - next: '下一步', - gotIt: '', - previous: '上一步', - submit: '提交', - reset: '重置', - search: '搜尋', - filter: '篩選', - loading: '載入中...', - noData: '暫無資料', - error: '錯誤', + gotIt: '知道了', success: '成功', - warning: '警告', - info: '資訊', resourceType: '資源類型', playerName: '指揮官', - timeHour: '時', - timeMinute: '分', - timeSecond: '秒', featureLocked: '功能已鎖定', unlockRequired: '需要解鎖前置建築', requiredBuilding: '所需建築', @@ -41,7 +24,6 @@ export default { goToBuildings: '前往建築頁面', locked: '已鎖定', viewRequirements: '查看前置條件', - requirements: '前置條件', requirementsNotMet: '前置條件未滿足', current: '當前', level: '等級', @@ -51,7 +33,8 @@ export default { viewDetails: '查看詳情', exitConfirmTitle: '退出遊戲', exitConfirmMessage: '確定要退出遊戲嗎?遊戲進度會自動儲存。', - points: '積分' + points: '積分', + retry: '重試' }, errors: { requirementsNotMet: '不滿足前置條件', @@ -88,6 +71,7 @@ export default { galaxy: '星系', diplomacy: '外交', achievements: '成就', + campaign: '戰役', ranking: '排行', messages: '訊息', settings: '設定', @@ -95,7 +79,6 @@ export default { gm: 'GM' }, sidebar: { - language: '語言', lightMode: '日間模式', darkMode: '夜間模式', collapse: '收起選單', @@ -120,9 +103,6 @@ export default { }, energy: { lowWarning: '電力不足,資源生產已停止!', - severeWarning: '電力不足,資源生產已停止!', - criticalWarning: '電力不足,資源生產已停止!', - noProduction: '電力不足,資源生產已停止!', deficitDetail: '電力缺口: {deficit},請建造更多電站', buildSolarPlant: '建造電站' }, @@ -133,27 +113,20 @@ export default { lowResources: '即將耗盡: {resources}' }, planet: { - planet: '星球', moon: '月球', - colony: '殖民地', position: '位置', - coordinates: '座標', switchToMoon: '查看月球', backToPlanet: '返回母星', switchPlanet: '切換星球', currentPlanet: '當前星球', - fields: '場地', temperature: '溫度', homePlanet: '母星', planetPrefix: '星球', - moonSuffix: '的月球', colonyPrefix: '殖民地', renamePlanet: '重命名星球', renamePlanetTitle: '重命名星球', - newPlanetName: '新名稱', planetNamePlaceholder: '輸入新的星球名稱', - rename: '重命名', - renameSuccess: '星球已重命名為 {name}' + rename: '重命名' }, player: { points: '總積分' @@ -180,8 +153,10 @@ export default { sensorPhalanx: '傳感器陣列', jumpGate: '跳躍門', planetDestroyerFactory: '行星毀滅者工廠', + geoResearchStation: '地質研究站', + deepDrillingFacility: '深層鑽探設施', buildTime: '建造時間', - build: '', + build: '建造', production: '產量', consumption: '消耗', totalCost: '累積成本', @@ -229,7 +204,9 @@ export default { lunarBase: '增加月球可用空間,每級+30空間', sensorPhalanx: '偵測周圍星系的艦隊活動', jumpGate: '瞬間傳送艦隊到其他月球', - planetDestroyerFactory: '建造能夠摧毀行星的終極武器' + planetDestroyerFactory: '建造能夠摧毀行星的終極武器', + geoResearchStation: '研究地質結構,提高礦脈自然恢復速度。每級增加50%恢復速率', + deepDrillingFacility: '' }, ships: { lightFighter: '輕型戰鬥機', @@ -293,9 +270,6 @@ export default { }, research: { researchTime: '研究時間', - totalCost: '累積成本', - totalPoints: '累積積分', - levelRange: '等級範圍', capacity: '容量/效果', attackBonus: '攻擊加成', shieldBonus: '護盾加成', @@ -304,8 +278,7 @@ export default { researchQueueBonus: '研究隊列', colonySlots: '殖民地槽位', forAllPlanets: '(全局)', - speedBonus: '速度加成', - researchSpeedBonus: '研究速度加成' + speedBonus: '速度加成' }, technologies: { energyTechnology: '能源技術', @@ -325,7 +298,8 @@ export default { hyperspaceDrive: '超空間引擎', darkMatterTechnology: '暗物質技術', terraformingTechnology: '地形改造技術', - planetDestructionTech: '行星毀滅技術' + planetDestructionTech: '行星毀滅技術', + miningTechnology: '' }, technologyDescriptions: { energyTechnology: '提高能源利用效率', @@ -346,7 +320,8 @@ export default { hyperspaceDrive: '高級推進技術', darkMatterTechnology: '研究暗物質的性質和應用', terraformingTechnology: '研究行星地形改造技術,每級為所有行星增加30個可用空間', - planetDestructionTech: '研究如何摧毀整個行星的恐怖技術' + planetDestructionTech: '研究如何摧毀整個行星的恐怖技術', + miningTechnology: '' }, officers: { commander: '指揮官', @@ -370,6 +345,9 @@ export default { queue: { title: '進行中的任務', empty: '當前沒有進行中的隊列', + buildQueueBonus: '建造佇列', + spaceBonus: '空間加成', + researchQueueBonus: '研究佇列', buildQueue: '建造佇列', researchQueue: '研究佇列', building: '建造中', @@ -381,7 +359,8 @@ export default { cancelResearch: '取消研究', confirmCancel: '確定要取消嗎?將返還50%的資源。', level: '等級', - gmModeActivated: '', + quantity: '數量', + gmModeActivated: 'GM 模式已啟動!請查看導航選單。', upgradeToLevel: '升級到等級', tabs: { all: '全部', @@ -400,14 +379,9 @@ export default { movedToQueue: '任務已移至正式佇列' }, overview: { - title: '星球總覽', resourceOverview: '資源概覽', fleetInfo: '艦隊資訊', currentShips: '當前星球的艦船數量', - productionSources: '生產來源', - productionSourcesDesc: '詳細資源生產和加成資訊', - consumptionSources: '電力消耗來源', - consumptionSourcesDesc: '各建築的電力消耗詳情', totalProduction: '總產量', totalConsumption: '總消耗', noConsumption: '當前無電力消耗', @@ -417,12 +391,8 @@ export default { }, buildingsView: { title: '建築', - usedSpace: '已用空間', spaceUsage: '佔用空間', - level: '等級', - gmModeActivated: '', upgradeCost: '升級消耗', - buildTime: '建造時間', build: '建造', upgrade: '升級', maxLevelReached: '等級已滿', @@ -433,8 +403,7 @@ export default { demolishRefund: '拆除返還', demolishFailed: '拆除失敗', demolishFailedMessage: '無法拆除該建築,請檢查建造隊列是否已滿或建築等級是否為0。', - confirmDemolish: '確認拆除', - confirmDemolishMessage: '確定要拆除以下建築嗎?' + confirmDemolish: '確認拆除' }, researchView: { title: '研究', @@ -445,26 +414,16 @@ export default { researchFailedMessage: '請檢查資源是否足夠、前置條件是否滿足,或是否有其他研究任務。' }, shipyard: { - attack: '攻擊力', missileAttack: '導彈攻擊', - shield: '護盾', armor: '裝甲', speed: '速度', cargoCapacity: '載貨量', fuelConsumption: '燃料消耗', - buildCost: '建造成本', - buildTime: '建造時間', - build: '', - perUnit: '每個單位', - batchCalculator: '批量建造計算器', - quantity: '數量', - totalCost: '總成本', - totalTime: '總時間' + build: '建造' }, shipyardView: { title: '船塢', fleetStorage: '艦隊倉儲', - owned: '擁有', attack: '攻擊力', missileAttack: '導彈攻擊', shield: '護盾', @@ -486,7 +445,7 @@ export default { armor: '裝甲', buildCost: '建造成本', buildTime: '建造時間', - build: '', + build: '建造', perUnit: '每個單位', batchCalculator: '批量建造計算器', quantity: '數量', @@ -539,6 +498,7 @@ export default { missionInfo: '任務資訊', fuelConsumption: '燃料消耗', flightTime: '飛行時間', + outOfRange: '超出射程', attackMission: '攻擊', transport: '運輸', colonize: '殖民', @@ -569,6 +529,7 @@ export default { } }, recycle: '回收', + destroy: '行星毀滅', transportResources: '運輸資源', totalCargoCapacity: '總載貨量', used: '已用', @@ -580,11 +541,11 @@ export default { arrivalTime: '到達時間', returnTime: '返回時間', recallFleet: '召回艦隊', - abortMission: '', - abortMissionTitle: '', - abortMissionWarning: '', - abortMissionSuccess: '', - abortMissionSuccessMessage: '', + abortMission: '終止任務', + abortMissionTitle: '確認終止任務', + abortMissionWarning: '警告:終止任務將永久損失 {ships} 艘艦船和 {resources} 資源!\n\n此操作不可撤銷,艦隊和資源將不會返回。', + abortMissionSuccess: '任務已終止', + abortMissionSuccessMessage: '任務已終止,艦隊和資源已損失。', sendFailed: '派遣失敗', sendFailedMessage: '請檢查艦隊數量、燃料是否充足,或載貨量是否超出限制。', recallFailed: '召回失敗', @@ -682,14 +643,12 @@ export default { selectGalaxy: '選擇銀河系', system: '星系', selectSystem: '選擇星系', - view: '查看', myPlanet: '我的星球', myPlanets: '查看我的星系', npcPlanets: 'NPC星球', selectPlanetToView: '選擇星球以查看其所在星系', totalPositions: '共10個星球位置', mine: '我的', - hostile: '敵對', emptySlot: '空位 - 可殖民', scout: '偵察', attack: '攻擊', @@ -714,7 +673,9 @@ export default { systems: '星系', distance: '距離', flightTime: '飛行時間', + outOfRange: '超出射程', launchMissile: '發射', + missileLaunched: '導彈已發射', cancel: '取消', colonizePlanetMessage: '確定要殖民位置 [{coordinates}] 嗎?\n\n請前往艦隊頁面派遣殖民船。', recyclePlanetMessage: '確定要回收位置 [{coordinates}] 的殘骸嗎?\n\n請前往艦隊頁面派遣回收船。', @@ -723,6 +684,25 @@ export default { giftPlanetTitle: '贈送禮物', giftPlanetMessage: '確定要向星球 [{coordinates}] 贈送資源嗎?\n\n請前往艦隊頁面選擇運輸船並裝載資源。', npcPlanetName: '{name}的星球', + // 傳感器陣列掃描 + phalanxScan: '傳感器掃描', + phalanxScanTitle: '傳感器陣列掃描', + phalanxScanDescription: '掃描星球 [{coordinates}] 的艦隊活動', + phalanxNoMoon: '需要有傳感器陣列的月球才能掃描', + phalanxOutOfRange: '目標超出掃描範圍', + phalanxRange: '掃描範圍', + phalanxCost: '掃描消耗', + phalanxNoFleets: '未檢測到艦隊活動', + phalanxFleetDetected: '檢測到 {count} 支艦隊', + phalanxMission: '任務', + phalanxOrigin: '出發地', + phalanxDestination: '目的地', + phalanxArrival: '到達時間', + phalanxReturn: '返回時間', + phalanxStatus: '狀態', + phalanxStatusOutbound: '前往中', + phalanxStatusReturning: '返回中', + phalanxInsufficientDeuterium: '氘不足', intercepted: '被攔截', defenseLosses: '防禦損失' }, @@ -731,12 +711,12 @@ export default { battles: '戰鬥', spy: '偵查', npc: 'NPC', - diplomacy: '', + diplomacy: '外交', battleReports: '戰鬥報告', spyReports: '間諜報告', noBattleReports: '暫無戰鬥報告', noSpyReports: '暫無間諜報告', - noDiplomaticReports: '', + noDiplomaticReports: '暫無外交事件', battleReport: '戰鬥報告', spyReport: '間諜報告', victory: '勝利', @@ -757,6 +737,8 @@ export default { defense: '防禦', buildings: '建築', unread: '未讀', + pending: '待處理', + invalidData: '無效數據', targetPlanet: '目標星球', attackerRemaining: '攻擊方剩餘', defenderRemaining: '防守方剩餘', @@ -809,36 +791,36 @@ export default { polite_decline: '對方禮貌地拒絕了' }, // Spied notification dialog - spiedNotificationDetails: '', - spyDetected: '', - detectionResult: '', - detectionSuccess: '', - spiedNotificationMessage: '', - spiedNotificationTip: '', - viewInGalaxy: '', + spiedNotificationDetails: '被偵查通知詳情', + spyDetected: '偵查被發現', + detectionResult: '檢測結果', + detectionSuccess: '你發現了敵方偵查!', + spiedNotificationMessage: '{npc}試圖偵查你的星球{planet}', + spiedNotificationTip: '若該NPC對你有敵意,請考慮增強防禦或反擊', + viewInGalaxy: '在星系中查看', // Mission report dialog - missionReportDetails: '', - missionSuccess: '', - missionFailed: '', - origin: '', - destination: '', - missionDetails: '', - transportedResources: '', - recycledResources: '', - remainingDebris: '', - newPlanet: '', + missionReportDetails: '任務報告詳情', + missionSuccess: '成功', + missionFailed: '失敗', + origin: '起點', + destination: '終點', + missionDetails: '任務詳情', + transportedResources: '運輸資源', + recycledResources: '回收資源', + remainingDebris: '剩餘殘骸', + newPlanet: '新星球', // NPC activity dialog - npcActivityDetails: '', + npcActivityDetails: 'NPC活動詳情', activityType: { - recycle: '' + recycle: '回收殘骸' }, - activityLocation: '', - position: '', - nearPlanet: '', - activityDescription: '', - npcActivityMessage: '', - arrivalTime: '', - npcActivityTip: '', + activityLocation: '活動位置', + position: '位置', + nearPlanet: '附近星球', + activityDescription: '活動描述', + npcActivityMessage: '{npc}正在{position}{activity}', + arrivalTime: '到達時間', + npcActivityTip: 'NPC可能會收集戰鬥產生的殘骸。若想競爭資源,可嘗試先到達該位置', clearMessages: '清空訊息', clearMessageTypes: '選擇要清空的訊息類型', clearBattleReports: '戰鬥報告', @@ -848,7 +830,11 @@ export default { clearNPCActivity: 'NPC活動', clearGiftNotifications: '禮物通知', clearGiftRejected: '拒絕記錄', - clearNow: '立即清空' + clearTradeOffers: '貿易提議', + clearIntelReports: '情報報告', + clearJointAttackInvites: '聯合攻擊邀請', + clearNow: '立即清空', + clearSuccess: '訊息已清空' }, missionReports: { transportSuccess: '運輸任務成功完成', @@ -980,6 +966,10 @@ export default { github: 'GitHub 儲存庫', qqGroup: 'QQ 交流群', privacyPolicy: '隱私協議', + displaySettings: '顯示設定', + displaySettingsDesc: '調整遊戲的視覺效果', + backgroundAnimation: '背景動畫', + backgroundAnimationDesc: '開啟後顯示星空/粒子背景動畫(可能影響效能)', notifications: '通知設定', notificationsDesc: '管理遊戲內的通知提醒', notificationTypes: '通知類型', @@ -1003,7 +993,48 @@ export default { npcNameUpdateConfirm: '更新名稱', npcNameUpdateCancel: '保持原樣', npcNameUpdateSuccess: '已成功更新 {count} 個NPC名稱', - npcNameUpdateSkipped: '已跳過NPC名稱更新' + npcNameUpdateSkipped: '已跳過NPC名稱更新', + // WebDAV + webdav: { + title: '雲端同步', + desc: '透過WebDAV同步遊戲存檔', + config: '設定', + configTitle: 'WebDAV 設定', + configDesc: '設定WebDAV伺服器以啟用雲端同步', + notConfigured: '請先設定WebDAV伺服器', + serverUrl: '伺服器位址', + serverUrlPlaceholder: '例如 https://dav.example.com', + serverUrlHint: '輸入您的WebDAV伺服器位址', + username: '使用者名稱', + usernamePlaceholder: '輸入使用者名稱', + password: '密碼', + passwordPlaceholder: '輸入密碼', + passwordHint: '密碼僅儲存在本機', + basePath: '存檔路徑', + basePathPlaceholder: '例如 /ogame-saves/', + testConnection: '測試連線', + testing: '測試中...', + testSuccess: '連線成功', + testFailed: '連線失敗', + save: '儲存', + clearConfig: '清除', + configSaved: '設定已儲存', + configCleared: '設定已清除', + upload: '上傳', + uploading: '上傳中...', + uploadSuccess: '上傳成功', + uploadFailed: '上傳失敗', + download: '下載', + downloadSuccess: '下載成功', + downloadFailed: '下載失敗', + selectFile: '選擇存檔', + selectFileDesc: '選擇要還原的存檔檔案', + noFiles: '沒有找到存檔檔案', + loadFailed: '載入檔案清單失敗', + confirmDelete: '確定要刪除 "{name}" 嗎?', + deleteSuccess: '檔案已刪除', + deleteFailed: '刪除失敗' + } }, notifications: { constructionComplete: '建造完成', @@ -1025,8 +1056,8 @@ export default { officers: '軍官', modifyResources: '修改資源', resourcesDesc: '快速修改星球資源數量', - maxAllResources: '', - maxAllResourcesSuccess: '', + maxAllResources: '一鍵拉滿', + maxAllResourcesSuccess: '所有資源已拉滿', modifyBuildings: '修改建築', buildingsDesc: '快速設定建築等級', modifyResearch: '修改科技', @@ -1067,10 +1098,11 @@ export default { dangerZoneDesc: '以下操作不可撤銷,請謹慎操作', resetGame: '重置遊戲', resetGameConfirm: '確定要重置遊戲嗎?這將刪除所有資料!', - completeAllQueues: '', - completeAllQueuesDesc: '', - completeQueues: '', - completeQueuesSuccess: '' + completeAllQueues: '一鍵完成所有佇列', + completeAllQueuesDesc: '立即完成所有建築、科技、艦船、防禦佇列和飛行任務', + completeQueues: '完成佇列', + completeQueuesSuccess: + '已完成 {buildingCount} 個建築佇列、{researchCount} 個科技佇列、{missionCount} 個飛行任務、{missileCount} 個導彈任務' }, alerts: { incomingFleets: '{count}支敵方艦隊來襲', @@ -1127,10 +1159,10 @@ export default { recentEvents: '最近事件', recentEventsDescription: '最近的外交活動記錄', ago: '前', - notifications: '', - markAllRead: '', - noReports: '', - viewAll: '', + notifications: '外交通知', + markAllRead: '全部已讀', + noReports: '暫無外交事件', + viewAll: '查看全部', status: { friendly: '友好', neutral: '中立', @@ -1205,6 +1237,19 @@ export default { npcEliminatedMessage: '你消滅了{npcName}的所有星球!該勢力已被徹底摧毀。' }, searchPlaceholder: '搜索NPC名稱...', + notificationType: { + tradeOffer: '貿易提議', + intelReport: '情報報告', + jointAttack: '聯合攻擊邀請' + }, + notificationBadge: { + trade: '貿易', + intel: '情報', + jointAttack: '邀請' + }, + notificationExtra: { + pending: '待處理' + }, viewMode: { card: '卡片', list: '列表' @@ -1220,6 +1265,21 @@ export default { medium: '普通', hard: '困難' }, + aiType: 'AI類型', + aiTypes: { + aggressive: '侵略型', + defensive: '防守型', + trader: '商人型', + expansionist: '擴張型', + balanced: '平衡型' + }, + aiTypeDescriptions: { + aggressive: '積極偵查和攻擊,反擊猛烈', + defensive: '很少主動攻擊,被攻擊後強烈反擊', + trader: '幾乎不攻擊,更願意交易和送禮', + expansionist: '專注發展,較少攻擊', + balanced: '根據情況動態調整策略' + }, reputation: '好感度', spyProbes: '偵察機數量', fleetPower: '艦隊戰力', @@ -1246,27 +1306,12 @@ export default { attackCooldown: '攻擊冷卻中({min}分{sec}秒)', notSpiedYet: '尚未偵查過,需要先進行偵查' } - }, - aiType: 'AI類型', - aiTypes: { - aggressive: '侵略型', - defensive: '防守型', - trader: '商人型', - expansionist: '擴張型', - balanced: '平衡型' - }, - aiTypeDescriptions: { - aggressive: '積極偵查和攻擊,反擊猛烈', - defensive: '很少主動攻擊,被攻擊後強烈反擊', - trader: '幾乎不攻擊,更願意交易和送禮', - expansionist: '專注發展,較少攻擊', - balanced: '根據情況動態調整策略' } }, pagination: { previous: '上一頁', next: '下一頁', - gotIt: '', + gotIt: '知道了', first: '首頁', last: '末頁', page: '第 {page} 頁' @@ -1329,9 +1374,31 @@ export default { seconds: '秒' }, tutorial: { + progress: '進度', + previous: '上一步', + next: '下一步', + gotIt: '我知道了', + completeButton: '完成', + skip: '跳過引導', welcome: { title: '歡迎來到 OGame', - content: '歡迎,指揮官!讓我們從基礎開始,建立您的宇宙帝國。' + content: '歡迎,指揮官!本教學將引導您了解建立帝國的基礎知識。點擊「下一步」開始您的征程。' + }, + resources: { + title: '資源概覽', + content: '這些是您的資源:金屬、晶體和重氫。它們是建造建築和研究科技的必需品。能量也很重要,用於為您的基礎設施供電。' + }, + planet: { + title: '您的星球', + content: '這是您的母星。您可以在這裡查看星球名稱、座標,並在擴張帝國時切換星球。' + }, + navigation: { + title: '導航選單', + content: '使用此選單在不同部分之間導航:建築、研究、艦隊、星系等。每個部分都提供獨特的遊戲功能。' + }, + gotoBuildings: { + title: '前往建築頁面', + content: '讓我們從建造一些建築開始。點擊「建築」選單項查看可用建築。' }, buildSolarPlant: { title: '建造太陽能電站', @@ -1342,14 +1409,100 @@ export default { content: '您的建築現在在建造佇列中。點擊右上角的佇列圖示可以查看所有正在進行的建造和研究任務。建築需要時間完成,但您可以在等待時繼續操作。' }, + buildMetalMine: { + title: '建造金屬礦', + content: '現在有了能量,可以建造金屬礦了。金屬礦是您的主要金屬來源,金屬幾乎用於每個建築和艦船。' + }, + buildCrystalMine: { + title: '建造晶體礦', + content: '晶體更稀有但對高級科技至關重要。建造晶體礦開始收集這種寶貴的資源。' + }, + buildDeuterium: { + title: '建造重氫合成器', + content: '重氫是艦船燃料和高級研究的必需品。建造重氫合成器開始生產這種關鍵資源。' + }, + upgradeMines: { + title: '升級資源礦', + content: '接下來,您需要升級三種資源礦(金屬、晶體、重氫)到2級,以滿足建造機器人工廠的要求。資源充足後,繼續升級它們。' + }, + buildRobotics: { + title: '建造機器人工廠', + content: '機器人工廠可以大幅加快建造速度。它需要金屬礦、晶體礦和重氫合成器各達到2級。建造它來提升建造效率!' + }, + upgradeMinesForLab: { + title: '繼續升級資源礦', + content: '現在需要將三種資源礦升級到3級,以滿足研究實驗室的建造要求。繼續發展您的資源產能。' + }, + buildResearchLab: { + title: '建造研究實驗室', + content: '研究實驗室是技術進步的基礎。它需要三種資源礦各達到3級。建造它以解鎖科技研究!' + }, + gotoResearch: { + title: '前往研究頁面', + content: '既然您有了研究實驗室,點擊「研究」選單查看可用的科技。' + }, + researchEnergy: { + title: '研究能量科技', + content: '能量科技可以提高您的能量產出並解鎖高級建築。這是最基礎也是最重要的科技之一。' + }, + shipyardIntro: { + title: '艦隊與船塢', + content: '艦船讓您能夠探索星系、運輸資源並保衛您的帝國。要建造艦船,您需要船塢(需要機器人工廠2級)。' + }, + gotoBuildingsForShipyard: { + title: '返回建築頁面', + content: '返回建築頁面來建造您的船塢。' + }, + buildShipyard: { + title: '建造船塢', + content: '船塢允許您建造艦船和防禦系統。這對艦隊行動至關重要。' + }, + fleetIntro: { + title: '艦隊行動', + content: '一旦您擁有艦船,就可以派遣它們執行任務:運輸資源、殖民星球、攻擊敵人或探索廢墟場。' + }, + galaxyIntro: { + title: '探索星系', + content: '星系視圖顯示其他星球、廢墟場和擴張機會。使用它來偵察目標並規劃您的戰略。' + }, + complete: { + title: '教學完成!', + content: + '恭喜,指揮官!您現在了解了基礎知識。繼續建設您的帝國,研究科技,探索星系。記住:先發展能量,再建資源,然後是工廠和研究!祝您好運!' + }, + // 移動端教學 mobile: { welcome: { title: '歡迎來到 OGame(移動版)', - content: '歡迎,指揮官!這是專為觸控螢幕設計的簡化教程。我們將快速介紹核心功能,讓您開始建設帝國。' + content: '歡迎,指揮官!這是專為觸控螢幕設計的簡化教學。我們將快速介紹核心功能,讓您開始建設帝國。' + }, + resources: { + title: '頂部資源欄', + content: '頂部顯示您的資源:金屬、晶體和重氫。點擊可查看詳細生產資訊。' + }, + menu: { + title: '打開導航選單', + content: '點擊這個選單圖示打開導航欄,您可以存取建築、研究、艦隊等所有功能。' + }, + gotoBuildings: { + title: '前往建築頁面', + content: '選單已打開!現在點擊「建築」選項,開始建造基礎設施。' + }, + buildSolarPlant: { + title: '建造太陽能電站', + content: '首先建造太陽能電站!向下捲動找到它,點擊卡片進行建造。能量是一切的基礎。' }, waitBuild: { title: '建造佇列', content: '點擊右上角的佇列圖示可以查看建造進度。您可以繼續瀏覽其他頁面,建造會在背景進行。' + }, + buildMetalMine: { + title: '建造金屬礦', + content: '有了能量後,建造金屬礦。向下捲動找到金屬礦,點擊建造。' + }, + complete: { + title: '快速教學完成!', + content: '很好!您已經掌握了基礎操作。繼續建造晶體礦和重氫合成器,然後探索其他功能。記住:先能量,再資源!' } } }, @@ -1405,10 +1558,18 @@ export default { title: '戰鬥模擬器', message: '在發動攻擊前模擬戰鬥結果。輸入雙方艦隊和科技等級,預測勝負和損失。' }, + campaign: { + title: '戰役模式', + message: '探索銀河系的故事戰役!完成任務獲得資源獎勵,解鎖新的挑戰。每個節點都有獨特的目標和敵人。' + }, achievements: { title: '成就系統', message: '完成各類遊戲目標解鎖成就,獲得暗物質獎勵!成就分為多個等級,挑戰更高難度獲得更豐厚的獎勵。' }, + ranking: { + title: '排行榜', + message: '與其他玩家和NPC比較進度。查看基於建築、研究、艦隊和防禦積分的排名。努力攀登排行榜!' + }, settings: { title: '設置', message: '在這裡管理遊戲數據、調整通知設置、導出/導入存檔。記得定期備份你的進度!' @@ -1670,5 +1831,427 @@ export default { you: '你', scoreBreakdown: '積分詳情', noData: '暫無排行數據' + }, + // NPC增強行為通知 + npcBehavior: { + tradeOfferReceived: '收到貿易提議', + tradeOfferDesc: '{npcName}向你發來了貿易提議', + attitudeChanged: 'NPC態度變化', + becameFriendly: '{npcName}對你的態度變得友好了', + becameHostile: '{npcName}對你的態度變得敵對了', + intelReceived: '收到情報', + intelReceivedDesc: '{npcName}向你分享了敵方情報', + jointAttackInvite: '聯合攻擊邀請', + jointAttackInviteDesc: '{npcName}邀請你一起攻擊敵人', + aidReceived: '收到援助', + aidReceivedDesc: '{npcName}向你贈送了 {amount} 資源', + allyDefense: '盟友協防', + allyDefenseDesc: '{npcName}派遣艦隊協助防禦你的星球', + trade: { + title: '貿易提議', + from: '來自', + offers: '提供', + requests: '請求', + expiresIn: '剩餘時間', + expired: '已過期', + accept: '接受', + decline: '拒絕', + noOffers: '暫無貿易提議', + acceptSuccess: '貿易完成!', + acceptFailed: '資源不足,無法完成貿易', + declined: '已拒絕貿易', + ratio: '交換比率' + }, + intel: { + title: '情報報告', + from: '情報來源', + target: '目標NPC', + type: '情報類型', + types: { + enemyFleet: '艦隊情報', + enemyResources: '資源情報', + enemyMovement: '動向情報' + }, + fleetInfo: '艦隊資訊', + resourceInfo: '資源資訊', + movementInfo: '動向資訊', + noReports: '暫無情報報告', + markAsRead: '標記已讀', + content: '情報內容', + noFleet: '未偵測到艦隊', + noData: '暫無資料', + targetPosition: '目標座標', + missionType: '任務類型' + }, + jointAttack: { + title: '聯合攻擊邀請', + from: '發起者', + target: '目標NPC', + targetPlanet: '目標星球', + npcFleet: 'NPC出動艦隊', + lootShare: '戰利品分成', + expiresIn: '剩餘時間', + expired: '已過期', + accept: '參與攻擊', + decline: '婉拒', + noInvites: '暫無聯合攻擊邀請', + acceptSuccess: '已加入聯合攻擊!', + declined: '已婉拒邀請', + targetInfo: '攻擊目標', + expectedShare: '預期分成', + remaining: '剩餘時間' + }, + aid: { + title: '資源援助', + from: '援助來源', + resources: '援助資源', + noAid: '暫無援助記錄' + }, + attitudeChange: { + title: '態度變化', + npc: 'NPC', + previous: '之前', + current: '現在', + reason: '原因', + reasons: { + attitude_swing: '態度搖擺', + gift: '收到禮物', + attack: '遭受攻擊', + naturalSwing: '自然變動', + giftReceived: '收到禮物', + attacked: '被攻擊', + reputationThreshold: '聲望閾值' + } + }, + allyAction: { + title: '盟友行動', + defense: '防禦支援', + defenseDesc: '{npcName}派遣艦隊協助防禦{targetPlanet}', + jointAttackStarted: '聯合攻擊開始', + jointAttackStartedDesc: '對{targetNpc}的聯合攻擊已開始', + reputationBonus: '聲望加成', + reputationBonusDesc: '你的盟友{npcName}向{targetNpc}說了你的好話' + } + }, + campaign: { + name: '戰役', + description: '探索神秘的銀河系,揭開古代文明的秘密', + totalProgress: '總進度', + questsCompleted: '任務完成', + chapter: '章節', + branch: '分支', + startQuest: '開始任務', + claimRewards: '領取獎勵', + objectives: '任務目標', + objectivesLabel: '目標', + rewards: '任務獎勵', + completed: '已完成', + inProgress: '進行中', + available: '可接取', + locked: '未解鎖', + notifications: { + questStarted: '任務已開始', + questCompleted: '任務完成!', + rewardsClaimed: '獎勵已領取', + objectiveCompleted: '目標完成', + chapterUnlocked: '新章節已解鎖', + reputationUp: '與 {npcName} 的聲望提升了 {value}', + reputationDown: '與 {npcName} 的聲望降低了 {value}', + branchUnlocked: '新的故事分支已解鎖!' + }, + dialogue: { + skip: '跳過', + continue: '繼續', + finish: '完成', + player: '指揮官', + npc: 'NPC', + narrator: '旁白', + mysterious: '神秘信號', + unknownSource: '信號來源不明', + choiceEffect: '對話選擇效果' + }, + chapters: { + '1': { + title: '起源之地', + description: '建設你的家園,邁出星際征途的第一步', + backgroundStory: + '你是一位年輕的星際指揮官,剛剛獲得了屬於自己的第一顆星球。在這片陌生的宇宙中,你將建設家園,發展科技,探索未知的銀河系深處...' + }, + '2': { + title: '星際探索', + description: '探索宇宙,發現神秘的古代遺跡', + backgroundStory: + '隨著你的勢力不斷壯大,來自深空的神秘信號引起了你的注意。這些信號似乎指向一個古老的秘密,等待著勇敢的探索者去揭開...' + }, + '3': { + title: '銀河外交', + description: '與其他勢力建立聯繫,在星際政治中立足', + backgroundStory: '銀河系中並不只有你一方勢力。其他文明正在崛起,你需要決定是與他們為敵還是結盟。外交的智慧將決定你的帝國能走多遠...' + }, + '4': { + title: '暗影降臨', + description: '面對強大的敵人,保衛你的領地', + backgroundStory: '暗影中潛伏著危險。一個強大的敵對勢力已經盯上了你的領地。戰爭不可避免,你必須做好準備,迎接即將到來的風暴...' + }, + '5': { + title: '古代秘密', + description: '揭開銀河系最深處的秘密', + backgroundStory: '所有的線索都指向銀河系最神秘的區域。在那裡,隱藏著古代文明留下的終極秘密。你準備好揭開這一切了嗎?' + } + }, + quests: { + '1_1': { + title: '家園建設', + description: '建造基礎設施,為你的星球奠定發展基礎' + }, + '1_2': { + title: '科技啟蒙', + description: '研究基礎科技,開啟科技發展之路' + }, + '1_3': { + title: '第一艘船', + description: '建造你的第一艘戰艦' + }, + '1_4': { + title: '陌生鄰居', + description: '偵查附近星系中的其他勢力' + }, + '1_5': { + title: '初次接觸', + description: '與附近的NPC勢力建立初步聯繫' + }, + '2_1': { + title: '殖民先驅', + description: '殖民你的第一顆新星球' + }, + '2_2': { + title: '深空探險', + description: '派遣艦隊進行遠征探險' + }, + '2_3': { + title: '神秘信號', + description: '調查來自深空的神秘信號' + }, + '2_4': { + title: '遺跡調查', + description: '探索發現的古代遺跡' + }, + '2_5': { + title: '解密檔案', + description: '研究從遺跡中獲得的數據' + }, + '3_1': { + title: '和平使者', + description: '通過外交手段提升與NPC的關係' + }, + '3_2': { + title: '利益交換', + description: '與友好勢力建立穩定的關係' + }, + '3_3': { + title: '共同威脅', + description: '發現潛在的敵對勢力' + }, + '3_4': { + title: '聯盟談判', + description: '與友好NPC建立正式同盟' + }, + '3_5': { + title: '備戰風暴', + description: '建設防禦設施,準備迎接挑戰' + }, + '4_1': { + title: '前哨遭襲', + description: '抵禦敵對勢力的首次進攻' + }, + '4_2': { + title: '情報收集', + description: '偵查敵方的軍事部署' + }, + '4_3': { + title: '反擊行動', + description: '對敵方發起反擊' + }, + '4_4': { + title: '資源爭奪', + description: '回收戰場殘骸,獲取資源' + }, + '4_5': { + title: '決戰前夕', + description: '建造強大的艦隊,準備最終決戰' + }, + '5_1': { + title: '遺跡深處', + description: '探索遺跡的最深處' + }, + '5_2': { + title: '古代科技', + description: '解鎖古代文明的科技' + }, + '5_3': { + title: '最終對決', + description: '與神秘敵人進行最終決戰' + }, + '5_4': { + title: '新紀元', + description: '建立新的殖民地,開啟新時代' + }, + '5_5': { + title: '傳承延續', + description: '繼續發展,征服更多的星系' + } + }, + objectiveTypes: { + buildBuilding: '建造 {building} 到 {level} 級', + researchTech: '研究 {tech} 到 {level} 級', + produceShips: '生產 {count} 艘 {ship}', + accumulateResources: '積累 {amount} {resource}', + defeatNPC: '擊敗 {npc}', + winBattles: '贏得 {count} 場戰鬥', + recycleDebris: '回收 {amount} 殘骸', + reachRelation: '與 {npc} 達到 {level} 關係', + sendGift: '向 {npc} 送禮 {count} 次', + formAlliance: '與 {npc} 結盟', + colonize: '殖民 {count} 顆星球', + expedition: '完成 {count} 次探險', + spyTarget: '偵查 {target}' + }, + errors: { + questNotFound: '任務不存在', + questNotAvailable: '任務不可接取', + questNotActive: '任務未激活', + questNotCompleted: '任務未完成', + rewardsAlreadyClaimed: '獎勵已領取', + prerequisiteNotMet: '前置任務未完成' + }, + speakers: { + ancientVoice: '古代之聲', + neighborNPC: '鄰近勢力', + mysteriousSignal: '神秘信號', + enemyCommander: '敵方指揮官' + }, + objectiveDescriptions: { + buildMetalMine: '建造金屬礦到2級', + buildCrystalMine: '建造晶體礦到2級', + buildSolarPlant: '建造太陽能電站到2級', + buildResearchLab: '建造研究實驗室到1級', + researchEnergy: '研究能量技術到1級', + buildShipyard: '建造船塢到2級', + researchCombustion: '研究燃燒驅動到1級', + buildLightFighters: '建造5艘輕型戰鬥機', + researchEspionage: '研究間諜技術到2級', + buildSpyProbes: '建造3艘間諜探測器', + spyAnyNPC: '偵查任意NPC星球', + sendGiftToNPC: '向任意NPC送禮', + researchAstrophysics: '研究天體物理學到1級', + buildColonyShip: '建造殖民船', + colonizeNewPlanet: '殖民新星球', + completeExpedition: '完成遠征任務', + discoverRuins: '發現古代遺跡', + researchComputer: '研究電腦技術到4級', + improveRelation: '提升與NPC的關係', + reachFriendly: '與NPC達到友好關係', + spyHostileNPC: '偵查敵對NPC', + formAlliance: '與友好NPC結盟', + buildDefenses: '建造防禦設施', + winDefenseBattle: '贏得防禦戰鬥', + spyEnemyPlanet: '偵查敵方星球', + attackEnemy: '攻擊敵方', + recycleDebris: '回收殘骸', + buildBattleships: '建造10艘戰列艦', + exploreDeepRuins: '探索遺跡深處', + researchHyperspace: '研究超空間技術', + defeatBoss: '擊敗神秘敵人', + colonizeSpecial: '殖民特殊位置', + continueDevelopment: '繼續發展' + }, + dialogues: { + '1_1': { + prologue_1: '歡迎來到銀河系,年輕的指揮官。這片廣袤的宇宙等待著你的探索。首先,讓我們建設好你的家園星球。', + prologue_2: '我感應到了新的意識覺醒...有趣...讓我們看看你能走多遠...' + }, + '1_2': { + prologue_1: '基礎設施已經建設完成。現在,是時候發展科技了。建造研究實驗室,開啟你的科技之路。' + }, + '1_3': { + prologue_1: '有了科技的支持,你可以開始建造艦隊了。建造船塢,生產你的第一艘戰艦。' + }, + '1_4': { + prologue_1: '你的艦隊已經成型。現在,讓我們了解一下周圍的環境。派出間諜探測器,偵查附近的勢力。', + prologue_2: '你並不孤單...銀河系中還有其他文明存在...' + }, + '1_5': { + prologue_1: '你已經發現了鄰近的勢力。外交是一門藝術,嘗試與他們建立聯繫。', + epilogue_1: '感謝你的禮物,指揮官。希望我們能成為朋友。', + epilogue_2: '很好...建立聯繫是探索更深秘密的第一步...' + }, + '2_1': { + prologue_1: '你的勢力已經穩固。是時候擴張領地了。研究天體物理學,建造殖民船,探索新的星球。', + prologue_2: '宇宙是無限的...更多的星球意味著更多的可能性...' + }, + '2_2': { + prologue_1: '殖民成功!但宇宙深處還有更多秘密等待發現。派遣艦隊進行遠征探險吧。', + prologue_2: '遠方傳來微弱的信號...那裡有什麼在等待著你...' + }, + '2_3': { + prologue_1: '你的探險隊發現了異常信號。這些信號似乎來自一個古老的文明...調查它們的來源。', + epilogue_1: '這些符號...是古代文明的遺跡!繼續調查,揭開它們的秘密。' + }, + '2_4': { + prologue_1: '你發現了古代遺跡的位置。派遣艦隊前去探索,看看能發現什麼。' + }, + '2_5': { + prologue_1: '遺跡中發現了大量數據檔案。研究這些數據,也許能解鎖新的科技。' + }, + '3_1': { + prologue_1: '在探索的同時,也不要忘記外交。與周圍的勢力保持良好關係對你有益。' + }, + '3_2': { + prologue_1: '有些勢力對你表示了友好。繼續加深關係,也許能獲得更多支持。' + }, + '3_3': { + prologue_1: '情報顯示,有敵對勢力正在暗中觀察你。保持警惕,偵查他們的動向。' + }, + '3_4': { + prologue_1: '與友好勢力建立正式同盟,在面對威脅時互相支持。' + }, + '3_5': { + prologue_1: '威脅正在逼近。建設防禦設施,準備迎接可能的衝突。' + }, + '4_1': { + prologue_1: '敵人發動了進攻!保衛你的星球!', + epilogue_1: '你成功擊退了敵人的第一波進攻。但這只是開始...' + }, + '4_2': { + prologue_1: '敵人退卻了,但他們還會回來。偵查他們的星球,了解他們的實力。' + }, + '4_3': { + prologue_1: '是時候反擊了。進攻敵人的星球,削弱他們的力量。' + }, + '4_4': { + prologue_1: '戰場上留下了大量殘骸。回收這些資源,為下一場戰鬥做準備。' + }, + '4_5': { + prologue_1: '最終決戰即將來臨。建造強大的艦隊,準備迎接最後的挑戰。' + }, + '5_1': { + prologue_1: '所有線索都指向遺跡的最深處。那裡隱藏著古代文明最核心的秘密。', + prologue_2: '你終於來到了這裡...真相即將揭曉...' + }, + '5_2': { + prologue_1: '在遺跡深處,你發現了失落的古代科技。研究並解鎖它們的力量。' + }, + '5_3': { + prologue_1: '一個神秘的敵人出現了。這是最後的挑戰,擊敗它!', + epilogue_1: '你做到了!古代的守護者已被擊敗。銀河系的秘密向你敞開。' + }, + '5_4': { + prologue_1: '和平終於來臨。在這個新紀元中,建立新的殖民地,擴展你的帝國。' + }, + '5_5': { + prologue_1: '你的傳奇才剛剛開始。繼續探索,征服更多的星系!', + epilogue_1: '銀河系廣闘無垠,還有無數秘密等待你去發現...' + } + } } } diff --git a/src/logic/achievementLogic.ts b/src/logic/achievementLogic.ts index 29c03e5..d2bec30 100644 --- a/src/logic/achievementLogic.ts +++ b/src/logic/achievementLogic.ts @@ -14,7 +14,7 @@ import { import { ACHIEVEMENTS, ACHIEVEMENT_MAP, getNextTier, getTierIndex } from '@/config/achievementConfig' // 初始化空的成就统计数据 -export function initializeAchievementStats(): AchievementStats { +export const initializeAchievementStats = (): AchievementStats => { const emptyShipRecord = Object.values(ShipType).reduce((acc, type) => { acc[type] = 0 return acc @@ -100,7 +100,7 @@ export function initializeAchievementStats(): AchievementStats { } // 初始化所有成就进度 -export function initializeAchievements(): Record { +export const initializeAchievements = (): Record => { const achievements: Record = {} for (const config of ACHIEVEMENTS) { @@ -122,7 +122,7 @@ export function initializeAchievements(): Record { } // 获取成就的当前值 -function getAchievementValue(stats: AchievementStats, statKey: string, checkType: string): number { +const getAchievementValue = (stats: AchievementStats, statKey: string, checkType: string): number => { // 处理特殊的组合统计键 if (statKey === 'totalResourcesConsumed') { return stats.totalMetalConsumed + stats.totalCrystalConsumed + stats.totalDeuteriumConsumed + stats.totalDarkMatterConsumed @@ -157,7 +157,7 @@ export interface AchievementUnlock { reward: AchievementReward } -export function checkAchievements(player: Player): AchievementUnlock[] { +export const checkAchievements = (player: Player): AchievementUnlock[] => { if (!player.achievementStats || !player.achievements) { return [] } @@ -213,7 +213,7 @@ export function checkAchievements(player: Player): AchievementUnlock[] { } // 应用成就奖励 -export function applyAchievementReward(player: Player, reward: AchievementReward): void { +export const applyAchievementReward = (player: Player, reward: AchievementReward): void => { const firstPlanet = player.planets[0] if (reward.darkMatter && firstPlanet) { // 奖励添加到第一个星球的资源中 @@ -228,10 +228,10 @@ export function applyAchievementReward(player: Player, reward: AchievementReward // ==================== 统计更新函数 ==================== // 更新资源生产统计 -export function updateResourceProductionStats( +export const updateResourceProductionStats = ( stats: AchievementStats, produced: { metal?: number; crystal?: number; deuterium?: number; darkMatter?: number } -): void { +): void => { if (produced.metal) stats.totalMetalProduced += produced.metal if (produced.crystal) stats.totalCrystalProduced += produced.crystal if (produced.deuterium) stats.totalDeuteriumProduced += produced.deuterium @@ -239,7 +239,7 @@ export function updateResourceProductionStats( } // 更新资源消耗统计 -export function updateResourceConsumptionStats(stats: AchievementStats, consumed: Partial): void { +export const updateResourceConsumptionStats = (stats: AchievementStats, consumed: Partial): void => { if (consumed.metal) stats.totalMetalConsumed += consumed.metal if (consumed.crystal) stats.totalCrystalConsumed += consumed.crystal if (consumed.deuterium) stats.totalDeuteriumConsumed += consumed.deuterium @@ -247,7 +247,7 @@ export function updateResourceConsumptionStats(stats: AchievementStats, consumed } // 更新建筑升级统计 -export function updateBuildingStats(stats: AchievementStats, buildingType: BuildingType, level: number): void { +export const updateBuildingStats = (stats: AchievementStats, buildingType: BuildingType, level: number): void => { stats.buildingsUpgraded += 1 // 更新最高等级记录 @@ -257,7 +257,7 @@ export function updateBuildingStats(stats: AchievementStats, buildingType: Build } // 更新科技研究统计 -export function updateResearchStats(stats: AchievementStats, techType: TechnologyType, level: number): void { +export const updateResearchStats = (stats: AchievementStats, techType: TechnologyType, level: number): void => { stats.researchCompleted += 1 // 更新最高等级记录 @@ -267,19 +267,19 @@ export function updateResearchStats(stats: AchievementStats, techType: Technolog } // 更新舰船生产统计 -export function updateShipProductionStats(stats: AchievementStats, shipType: ShipType, quantity: number): void { +export const updateShipProductionStats = (stats: AchievementStats, shipType: ShipType, quantity: number): void => { stats.shipsProduced[shipType] = (stats.shipsProduced[shipType] || 0) + quantity stats.totalShipsProduced += quantity } // 更新防御建造统计 -export function updateDefenseProductionStats(stats: AchievementStats, defenseType: DefenseType, quantity: number): void { +export const updateDefenseProductionStats = (stats: AchievementStats, defenseType: DefenseType, quantity: number): void => { stats.defensesBuilt[defenseType] = (stats.defensesBuilt[defenseType] || 0) + quantity stats.totalDefensesBuilt += quantity } // 更新攻击统计(玩家作为攻击者) -export function updateAttackStats(stats: AchievementStats, battleResult: BattleResult, won: boolean, debrisValue: number): void { +export const updateAttackStats = (stats: AchievementStats, battleResult: BattleResult, won: boolean, debrisValue: number): void => { // 攻击也算飞行任务 stats.totalFlightMissions += 1 stats.attacksLaunched += 1 @@ -305,7 +305,7 @@ export function updateAttackStats(stats: AchievementStats, battleResult: BattleR } // 更新防御统计(玩家作为防御者) -export function updateDefenseStats(stats: AchievementStats, battleResult: BattleResult, won: boolean, debrisValue: number): void { +export const updateDefenseStats = (stats: AchievementStats, battleResult: BattleResult, won: boolean, debrisValue: number): void => { if (won) { stats.defensesSuccessful += 1 } else { @@ -347,33 +347,33 @@ export function updateDefenseStats(stats: AchievementStats, battleResult: Battle } // 更新飞行任务统计 -export function updateFlightMissionStats(stats: AchievementStats): void { +export const updateFlightMissionStats = (stats: AchievementStats): void => { stats.totalFlightMissions += 1 } // 更新运输任务统计 -export function updateTransportStats(stats: AchievementStats, resourcesAmount: number): void { +export const updateTransportStats = (stats: AchievementStats, resourcesAmount: number): void => { stats.transportMissions += 1 stats.transportedResources += resourcesAmount } // 更新殖民统计 -export function updateColonizationStats(stats: AchievementStats): void { +export const updateColonizationStats = (stats: AchievementStats): void => { stats.colonizations += 1 } // 更新侦查统计 -export function updateSpyStats(stats: AchievementStats): void { +export const updateSpyStats = (stats: AchievementStats): void => { stats.spyMissions += 1 } // 更新部署统计 -export function updateDeploymentStats(stats: AchievementStats): void { +export const updateDeploymentStats = (stats: AchievementStats): void => { stats.deployments += 1 } // 更新探险统计 -export function updateExpeditionStats(stats: AchievementStats, successful: boolean): void { +export const updateExpeditionStats = (stats: AchievementStats, successful: boolean): void => { stats.expeditionsTotal += 1 if (successful) { stats.expeditionsSuccessful += 1 @@ -381,55 +381,55 @@ export function updateExpeditionStats(stats: AchievementStats, successful: boole } // 更新回收统计 -export function updateRecyclingStats(stats: AchievementStats, resourcesAmount: number): void { +export const updateRecyclingStats = (stats: AchievementStats, resourcesAmount: number): void => { stats.recyclingMissions += 1 stats.recycledResources += resourcesAmount } // 更新行星毁灭统计 -export function updatePlanetDestructionStats(stats: AchievementStats): void { +export const updatePlanetDestructionStats = (stats: AchievementStats): void => { stats.planetDestructions += 1 } // 更新燃料消耗统计 -export function updateFuelConsumptionStats(stats: AchievementStats, fuelAmount: number): void { +export const updateFuelConsumptionStats = (stats: AchievementStats, fuelAmount: number): void => { stats.fuelConsumed += fuelAmount } // 更新友好NPC数量 -export function updateFriendlyNPCStats(stats: AchievementStats, count: number): void { +export const updateFriendlyNPCStats = (stats: AchievementStats, count: number): void => { stats.friendlyNPCCount = count } // 更新敌对NPC数量 -export function updateHostileNPCStats(stats: AchievementStats, count: number): void { +export const updateHostileNPCStats = (stats: AchievementStats, count: number): void => { stats.hostileNPCCount = count } // 更新送礼统计 -export function updateGiftStats(stats: AchievementStats, resourcesAmount: number): void { +export const updateGiftStats = (stats: AchievementStats, resourcesAmount: number): void => { stats.giftsSent += 1 stats.giftResourcesTotal += resourcesAmount } // 更新被NPC攻击统计 -export function updateAttackedByNPCStats(stats: AchievementStats): void { +export const updateAttackedByNPCStats = (stats: AchievementStats): void => { stats.attackedByNPC += 1 } // 更新被NPC侦查统计 -export function updateSpiedByNPCStats(stats: AchievementStats): void { +export const updateSpiedByNPCStats = (stats: AchievementStats): void => { stats.spiedByNPC += 1 } // 更新被NPC回收残骸统计 -export function updateDebrisRecycledByNPCStats(stats: AchievementStats, resourcesAmount: number): void { +export const updateDebrisRecycledByNPCStats = (stats: AchievementStats, resourcesAmount: number): void => { stats.debrisRecycledByNPC += 1 stats.debrisResourcesLostToNPC += resourcesAmount } // 获取成就的下一个目标 -export function getNextTarget(achievementId: string, currentTier: AchievementTier | null): number | null { +export const getNextTarget = (achievementId: string, currentTier: AchievementTier | null): number | null => { const config = ACHIEVEMENT_MAP[achievementId] if (!config) return null @@ -441,7 +441,7 @@ export function getNextTarget(achievementId: string, currentTier: AchievementTie } // 获取成就进度百分比 -export function getAchievementProgress(achievementId: string, currentValue: number, currentTier: AchievementTier | null): number { +export const getAchievementProgress = (achievementId: string, currentValue: number, currentTier: AchievementTier | null): number => { const config = ACHIEVEMENT_MAP[achievementId] if (!config) return 0 diff --git a/src/logic/buildingLogic.ts b/src/logic/buildingLogic.ts index 9f079f8..7c4fa48 100644 --- a/src/logic/buildingLogic.ts +++ b/src/logic/buildingLogic.ts @@ -130,7 +130,8 @@ export const completeBuildQueue = ( // 建造完成 if (item.type === 'building') { const oldLevel = planet.buildings[item.itemType as BuildingType] || 0 - const newLevel = item.targetLevel || 0 + // 升级完成时,等级+1(而不是直接使用targetLevel,避免在升级过程中被拆除后跳级) + const newLevel = oldLevel + 1 planet.buildings[item.itemType as BuildingType] = newLevel // 计算并累积积分 @@ -164,7 +165,6 @@ export const completeBuildQueue = ( } } else if (item.type === 'demolish') { // 拆除完成,降低建筑等级 - // 注意:拆除不会扣除积分,积分只增不减 const buildingType = item.itemType as BuildingType const currentLevel = planet.buildings[buildingType] || 0 planet.buildings[buildingType] = Math.max(0, currentLevel - 1) diff --git a/src/logic/diplomaticLogic.ts b/src/logic/diplomaticLogic.ts index 8ffca07..c5792ec 100644 --- a/src/logic/diplomaticLogic.ts +++ b/src/logic/diplomaticLogic.ts @@ -5,7 +5,7 @@ */ import { DIPLOMATIC_CONFIG } from '@/config/gameConfig' -import { locales, type Locale } from '@/locales' +import { getLocale, type Locale } from '@/locales' import * as resourceLogic from './resourceLogic' import * as officerLogic from './officerLogic' import type { @@ -34,7 +34,7 @@ import { RelationStatus as RS, DiplomaticEventType as DET } from '@/types/game' */ const t = (key: string, locale: Locale, params?: Record): string => { const keys = key.split('.') - let value: any = locales[locale] + let value: any = getLocale(locale) for (const k of keys) { if (value && typeof value === 'object' && k in value) { @@ -372,7 +372,7 @@ export const handleAttackReputation = ( attacker, defender, DET.Attack, - -reputationLoss, + reputationLoss, t('diplomacy.reports.youAttackedNpc', locale, { npcName: defender.name }) ) } @@ -876,3 +876,48 @@ export const checkAndHandleEliminatedNPCs = (allNpcs: NPC[], player: Player, loc return eliminatedNpcIds } + +/** + * 通知玩家盟友正在协防 + * @param npc 派遣协防舰队的NPC + * @param player 玩家 + * @param targetPlanet 被协防的星球 + * @param mission 协防任务 + */ +export const notifyPlayerOfAllyDefense = ( + npc: NPC, + player: Player, + targetPlanet: Planet, + mission: FleetMission +): void => { + // 计算舰队规模 + const fleetSize = Object.values(mission.fleet).reduce((sum, count) => sum + (count || 0), 0) + + // 创建外交报告 + const report: DiplomaticReport = { + id: `ally_defense_${Date.now()}_${npc.id}`, + npcId: npc.id, + npcName: npc.name, + eventType: 'ally_defend' as DiplomaticEventType, + timestamp: Date.now(), + details: { + targetPlanetName: targetPlanet.name, + targetPosition: targetPlanet.position, + fleetSize, + arrivalTime: mission.arrivalTime, + stationDuration: mission.returnTime ? mission.returnTime - mission.arrivalTime : 0 + }, + read: false + } + + // 添加到玩家的外交报告列表 + if (!player.diplomaticReports) { + player.diplomaticReports = [] + } + player.diplomaticReports.unshift(report) + + // 限制报告数量 + if (player.diplomaticReports.length > 100) { + player.diplomaticReports = player.diplomaticReports.slice(0, 100) + } +} diff --git a/src/logic/fleetLogic.ts b/src/logic/fleetLogic.ts index fc217a7..1867a0b 100644 --- a/src/logic/fleetLogic.ts +++ b/src/logic/fleetLogic.ts @@ -63,7 +63,8 @@ export const createFleetMission = ( id: `mission_${now}`, playerId, originPlanetId, - targetPosition, + // 深拷贝targetPosition,避免多个任务共享同一个引用 + targetPosition: { ...targetPosition }, missionType, fleet, cargo, @@ -766,8 +767,8 @@ export const processExpeditionArrival = (mission: FleetMission): ExpeditionResul const aliensThreshold = piratesThreshold + probs.aliens if (random < resourceThreshold) { - // 发现资源 - const baseMultiplier = 0.1 + Math.random() * 0.3 // 10%-40% 的货舱容量 + // 发现资源 - 大幅提升奖励 + const baseMultiplier = 0.3 + Math.random() * 0.5 // 30%-80% 的货舱容量 const resourceMultiplier = baseMultiplier * zoneConfig.resourceMultiplier const resourceAmount = Math.floor(totalCargoCapacity * resourceMultiplier) const metalAmount = Math.floor(resourceAmount * 0.5) @@ -784,8 +785,8 @@ export const processExpeditionArrival = (mission: FleetMission): ExpeditionResul message: 'expedition.foundResources' } } else if (random < darkMatterThreshold) { - // 发现暗物质 - const baseDarkMatter = 50 + Math.random() * 150 // 50-200 暗物质 + // 发现暗物质 - 大幅提升奖励 + const baseDarkMatter = 200 + Math.random() * 500 // 200-700 暗物质 const darkMatterAmount = Math.floor(baseDarkMatter * zoneConfig.darkMatterMultiplier) mission.cargo.darkMatter += darkMatterAmount @@ -807,7 +808,7 @@ export const processExpeditionArrival = (mission: FleetMission): ExpeditionResul const shipTypeIndex = Math.floor(Math.random() * possibleShips.length) const shipType = possibleShips[shipTypeIndex] ?? ShipType.LightFighter - const baseCount = 1 + Math.random() * 5 // 1-5 艘 + const baseCount = 3 + Math.random() * 12 // 3-15 艘 const count = Math.floor(baseCount * zoneConfig.fleetFindMultiplier) foundFleet[shipType] = count @@ -1062,11 +1063,11 @@ export const processFleetReturn = ( ): void => { // 舰船返回 - 使用安全添加函数 fleetStorageLogic.addFleetSafely(originPlanet, mission.fleet, technologies) - // 注意:如果舰队仓储溢出,超出部分会丢失(这是合理的惩罚) + // 如果舰队仓储溢出,超出部分会丢失(这是合理的惩罚) // 资源返回(掠夺物或运输货物)- 使用安全添加函数 resourceLogic.addResourcesSafely(originPlanet, mission.cargo, storageCapacityBonus) - // 注意:如果资源仓储溢出,超出部分会丢失(这是合理的惩罚) + // 如果资源仓储溢出,超出部分会丢失(这是合理的惩罚) } /** diff --git a/src/logic/gameLogic.ts b/src/logic/gameLogic.ts index ee04972..d9bec39 100644 --- a/src/logic/gameLogic.ts +++ b/src/logic/gameLogic.ts @@ -223,7 +223,7 @@ export const processGameUpdate = ( if (onUnlock && player.technologies !== previousTechnologies) { const mainPlanet = player.planets.find(p => !p.isMoon) if (mainPlanet) { - // 注意:这里使用完成后的建筑状态,因为我们只关心科技完成带来的解锁 + // 这里使用完成后的建筑状态,因为我们只关心科技完成带来的解锁 const techUnlockedItems = unlockLogic.checkAllNewlyUnlocked( mainPlanet, player.technologies, diff --git a/src/logic/npcBehaviorLogic.ts b/src/logic/npcBehaviorLogic.ts index e5fbf08..35178f6 100644 --- a/src/logic/npcBehaviorLogic.ts +++ b/src/logic/npcBehaviorLogic.ts @@ -1,9 +1,102 @@ -import type { NPC, Planet, Player, FleetMission, SpyReport, SpiedNotification, IncomingFleetAlert, Fleet, DebrisField } from '@/types/game' +import type { + NPC, + Planet, + Player, + FleetMission, + SpyReport, + SpiedNotification, + IncomingFleetAlert, + Fleet, + DebrisField, + Resources, + TradeOffer, + IntelReport, + JointAttackInvite, + IntelType, + AidNotification, + AllyDefenseNotification, + AttitudeChangeNotification +} from '@/types/game' import { MissionType, ShipType, 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' +// ========== 敌对NPC增强行为类型定义 ========== + +/** + * 骚扰任务类型 + */ +export type HarassmentType = 'spy' | 'raid' | 'intimidate' + +/** + * 报复等级 + */ +export interface RevengeLevel { + attackCount: number + fleetMultiplier: number + attackInterval: number + name: string +} + +/** + * 围攻协调信息 + */ +export interface SiegeCoordination { + targetPlanetId: string + targetPosition: { galaxy: number; system: number; position: number } + coordinatorNpcId: string + participantNpcIds: string[] + arrivalTime: number + startedAt: number +} + +// TradeOffer, IntelReport, JointAttackInvite, IntelType 类型已移至 @/types/game.ts + +/** + * NPC之间的关系 + */ +export interface NPCRelation { + npcId: string + targetNpcId: string + status: 'ally' | 'neutral' | 'enemy' + strength: number // 关系强度 0-100 + lastUpdated: number +} + +/** + * NPC联盟 + */ +export interface NPCAlliance { + id: string + name: string + leaderNpcId: string + memberNpcIds: string[] + enemyNpcIds: string[] + createdAt: number +} + +/** + * 辅助函数:获取舰队中最慢船只的速度 + * 用于计算飞行时间 + */ +const getFleetMinSpeed = (fleet: Partial): number => { + let minSpeed = Infinity + for (const [shipType, count] of Object.entries(fleet)) { + if ((count || 0) > 0) { + const shipConfig = SHIPS[shipType as ShipType] + if (shipConfig) { + minSpeed = Math.min(minSpeed, shipConfig.speed) + } + } + } + return minSpeed === Infinity ? 10000 : minSpeed // 默认使用基础速度 +} + /** * AI 类型行为修改器 * 根据 NPC 的 AI 类型调整其行为参数 @@ -342,27 +435,133 @@ export const shouldNPCGiftPlayer = (npc: NPC, player: Player, currentTime: numbe return Math.random() < giftProbability } +/** + * 计算玩家的总资源产量(每小时) + */ +const calculatePlayerTotalProduction = (player: Player): { metal: number; crystal: number; deuterium: number } => { + let totalMetal = 0 + let totalCrystal = 0 + let totalDeuterium = 0 + + // 计算当前激活的军官加成 + const bonuses = player.officers + ? { + resourceProductionBonus: Object.values(player.officers).reduce((sum, officer) => { + if (officer.active && officer.expiresAt && officer.expiresAt > Date.now()) { + return sum + (officer.bonuses?.resourceProductionBonus || 0) + } + return sum + }, 0), + darkMatterProductionBonus: Object.values(player.officers).reduce((sum, officer) => { + if (officer.active && officer.expiresAt && officer.expiresAt > Date.now()) { + return sum + (officer.bonuses?.darkMatterProductionBonus || 0) + } + return sum + }, 0), + energyProductionBonus: Object.values(player.officers).reduce((sum, officer) => { + if (officer.active && officer.expiresAt && officer.expiresAt > Date.now()) { + return sum + (officer.bonuses?.energyProductionBonus || 0) + } + return sum + }, 0) + } + : { resourceProductionBonus: 0, darkMatterProductionBonus: 0, energyProductionBonus: 0 } + + // 遍历所有星球计算总产量 + for (const planet of player.planets) { + if (planet.isMoon) continue // 月球没有矿场 + + const production = resourceLogic.calculateResourceProduction(planet, bonuses) + + totalMetal += production.metal || 0 + totalCrystal += production.crystal || 0 + totalDeuterium += production.deuterium || 0 + } + + return { metal: totalMetal, crystal: totalCrystal, deuterium: totalDeuterium } +} + /** * NPC向玩家赠送资源 + * 动态计算赠送量:基于玩家每小时产量的4-8倍 + * 赠送的资源会从NPC主星球扣除 */ export const giftResourcesToPlayer = (npc: NPC, player: Player): void => { const { NPC_GIFT_CONFIG } = DIPLOMATIC_CONFIG + const dynamicConfig = NPC_GIFT_CONFIG.DYNAMIC_GIFT + const baseConfig = NPC_GIFT_CONFIG.BASE_GIFT_AMOUNT - // 随机生成赠送资源量 - const giftResources = { - metal: - Math.floor(Math.random() * (NPC_GIFT_CONFIG.GIFT_AMOUNT.METAL.max - NPC_GIFT_CONFIG.GIFT_AMOUNT.METAL.min + 1)) + - NPC_GIFT_CONFIG.GIFT_AMOUNT.METAL.min, - crystal: - Math.floor(Math.random() * (NPC_GIFT_CONFIG.GIFT_AMOUNT.CRYSTAL.max - NPC_GIFT_CONFIG.GIFT_AMOUNT.CRYSTAL.min + 1)) + - NPC_GIFT_CONFIG.GIFT_AMOUNT.CRYSTAL.min, - deuterium: - Math.floor(Math.random() * (NPC_GIFT_CONFIG.GIFT_AMOUNT.DEUTERIUM.max - NPC_GIFT_CONFIG.GIFT_AMOUNT.DEUTERIUM.min + 1)) + - NPC_GIFT_CONFIG.GIFT_AMOUNT.DEUTERIUM.min, + // 获取NPC主星球 + const npcPlanet = npc.planets[0] + if (!npcPlanet) return + + let giftResources = { + metal: 0, + crystal: 0, + deuterium: 0, darkMatter: 0, energy: 0 } + if (dynamicConfig?.ENABLED) { + // 动态计算:根据玩家产量 + const playerProduction = calculatePlayerTotalProduction(player) + + // 随机生成产量倍数(4-8倍) + const multiplierRange = dynamicConfig.PRODUCTION_MULTIPLIER + const multiplier = multiplierRange.min + Math.random() * (multiplierRange.max - multiplierRange.min) + + // 计算赠送量(产量 × 倍数) + let metalGift = Math.floor(playerProduction.metal * multiplier) + let crystalGift = Math.floor(playerProduction.crystal * multiplier) + let deuteriumGift = Math.floor(playerProduction.deuterium * multiplier) + + // 应用最小值保底 + metalGift = Math.max(metalGift, dynamicConfig.MIN_AMOUNT.METAL) + crystalGift = Math.max(crystalGift, dynamicConfig.MIN_AMOUNT.CRYSTAL) + deuteriumGift = Math.max(deuteriumGift, dynamicConfig.MIN_AMOUNT.DEUTERIUM) + + // 应用最大值封顶 + metalGift = Math.min(metalGift, dynamicConfig.MAX_AMOUNT.METAL) + crystalGift = Math.min(crystalGift, dynamicConfig.MAX_AMOUNT.CRYSTAL) + deuteriumGift = Math.min(deuteriumGift, dynamicConfig.MAX_AMOUNT.DEUTERIUM) + + giftResources.metal = metalGift + giftResources.crystal = crystalGift + giftResources.deuterium = deuteriumGift + } else { + // 使用基础配置(后备方案) + giftResources.metal = Math.floor(Math.random() * (baseConfig.METAL.max - baseConfig.METAL.min + 1)) + baseConfig.METAL.min + giftResources.crystal = Math.floor(Math.random() * (baseConfig.CRYSTAL.max - baseConfig.CRYSTAL.min + 1)) + baseConfig.CRYSTAL.min + giftResources.deuterium = + Math.floor(Math.random() * (baseConfig.DEUTERIUM.max - baseConfig.DEUTERIUM.min + 1)) + baseConfig.DEUTERIUM.min + } + + // 根据好感度额外加成:好感度越高,赠送越多 + const relation = npc.relations?.[player.id] + if (relation && relation.reputation > 60) { + // 好感度60-100区间,额外增加0-40% + const reputationBonus = 1 + (relation.reputation - 60) / 100 + giftResources.metal = Math.floor(giftResources.metal * reputationBonus) + giftResources.crystal = Math.floor(giftResources.crystal * reputationBonus) + giftResources.deuterium = Math.floor(giftResources.deuterium * reputationBonus) + } + + // 限制赠送量不超过NPC拥有的资源(只赠送NPC实际拥有的部分) + giftResources.metal = Math.min(giftResources.metal, Math.floor(npcPlanet.resources.metal)) + giftResources.crystal = Math.min(giftResources.crystal, Math.floor(npcPlanet.resources.crystal)) + giftResources.deuterium = Math.min(giftResources.deuterium, Math.floor(npcPlanet.resources.deuterium)) + + // 如果NPC资源不足(所有资源都为0),则不赠送 + if (giftResources.metal <= 0 && giftResources.crystal <= 0 && giftResources.deuterium <= 0) { + return + } + + // 从NPC星球扣除资源 + npcPlanet.resources.metal -= giftResources.metal + npcPlanet.resources.crystal -= giftResources.crystal + npcPlanet.resources.deuterium -= giftResources.deuterium + // 处理赠送 diplomaticLogic.handleNPCGiftToPlayer(npc, player, giftResources) @@ -370,6 +569,161 @@ export const giftResourcesToPlayer = (npc: NPC, player: Player): void => { ;(npc as any).lastGiftTime = Date.now() } +/** + * 检查NPC是否应该协防玩家 + * 当玩家受到攻击且NPC是友好状态时触发 + */ +export const shouldNPCDefendPlayer = (npc: NPC, player: Player, currentTime: number): boolean => { + const { ALLY_DEFENSE_CONFIG } = DIPLOMATIC_CONFIG + + // 检查功能是否启用 + if (!ALLY_DEFENSE_CONFIG?.ENABLED) { + return false + } + + // 检查好感度 + const relation = npc.relations?.[player.id] + if (!relation || relation.reputation < ALLY_DEFENSE_CONFIG.MIN_REPUTATION) { + return false + } + + // 检查上次协防时间 + const lastDefendTime = (npc as any).lastDefendTime || 0 + if (currentTime - lastDefendTime < ALLY_DEFENSE_CONFIG.CHECK_INTERVAL * 1000) { + return false + } + + // 检查当前协防任务数量 + const activeDefenseMissions = npc.fleetMissions?.filter(m => m.missionType === MissionType.Station && m.status === 'outbound').length || 0 + if (activeDefenseMissions >= ALLY_DEFENSE_CONFIG.MAX_CONCURRENT_DEFENSES) { + return false + } + + // 检查玩家是否有来袭攻击舰队 + const incomingAttacks = + player.incomingFleetAlerts?.filter( + alert => alert.missionType === MissionType.Attack && alert.fleetSize >= ALLY_DEFENSE_CONFIG.MIN_INCOMING_FLEET_SIZE + ) || [] + if (incomingAttacks.length === 0) { + return false + } + + // 根据好感度计算协防概率 + const reputationBonus = (relation.reputation - ALLY_DEFENSE_CONFIG.MIN_REPUTATION) / 30 // 70-100区间 + const defenseProbability = ALLY_DEFENSE_CONFIG.BASE_DEFENSE_PROBABILITY + reputationBonus * 0.3 + return Math.random() < defenseProbability +} + +/** + * NPC派舰队协防玩家 + */ +export const sendDefenseFleet = (npc: NPC, _player: Player, targetPlanet: Planet): FleetMission | null => { + const { ALLY_DEFENSE_CONFIG } = DIPLOMATIC_CONFIG + + // 选择最近且有舰队的NPC星球 + const sourcePlanet = selectBestNPCPlanet(npc, targetPlanet.position) + if (!sourcePlanet) return null + + // 计算派遣舰队(战斗舰船的30%-60%) + const fleetRatio = + ALLY_DEFENSE_CONFIG.FLEET_RATIO.min + Math.random() * (ALLY_DEFENSE_CONFIG.FLEET_RATIO.max - ALLY_DEFENSE_CONFIG.FLEET_RATIO.min) + + const combatShipTypes = [ + ShipType.LightFighter, + ShipType.HeavyFighter, + ShipType.Cruiser, + ShipType.Battleship, + ShipType.Battlecruiser, + ShipType.Bomber, + ShipType.Destroyer + ] + + const defenseFleet: Partial = {} + let hasShips = false + + for (const shipType of combatShipTypes) { + const available = sourcePlanet.fleet[shipType] || 0 + if (available > 0) { + const toSend = Math.floor(available * fleetRatio) + if (toSend > 0) { + defenseFleet[shipType] = toSend + sourcePlanet.fleet[shipType] = available - toSend + hasShips = true + } + } + } + + if (!hasShips) return null + + // 计算飞行时间 + const distance = fleetLogic.calculateDistance(sourcePlanet.position, targetPlanet.position) + const minSpeed = getFleetMinSpeed(defenseFleet) + const flightTime = fleetLogic.calculateFlightTime(distance, minSpeed) + + const currentTime = Date.now() + const arrivalTime = currentTime + flightTime + + // 创建协防任务 + const mission: FleetMission = { + id: `ally_defend_${currentTime}_${npc.id}`, + playerId: npc.id, + npcId: npc.id, + originPlanetId: sourcePlanet.id, + targetPosition: targetPlanet.position, + targetPlanetId: targetPlanet.id, + fleet: defenseFleet as Fleet, + missionType: MissionType.Station, + departureTime: currentTime, + arrivalTime: arrivalTime, + returnTime: arrivalTime + ALLY_DEFENSE_CONFIG.STATION_DURATION, + status: 'outbound', + cargo: { metal: 0, crystal: 0, deuterium: 0, darkMatter: 0, energy: 0 }, + isGift: false, + isHostile: false // 盟友协防不是敌对任务 + } + + // 添加到NPC任务列表 + if (!npc.fleetMissions) { + npc.fleetMissions = [] + } + npc.fleetMissions.push(mission) + + // 更新上次协防时间 + ;(npc as any).lastDefendTime = currentTime + + return mission +} + +/** + * 检查并执行NPC协防行为 + */ +export const checkAndExecuteAllyDefense = (npc: NPC, player: Player, currentTime: number): void => { + if (!shouldNPCDefendPlayer(npc, player, currentTime)) { + return + } + + // 找到受攻击的玩家星球 + const incomingAttacks = player.incomingFleetAlerts?.filter(alert => alert.missionType === MissionType.Attack) || [] + + if (incomingAttacks.length === 0) return + + // 选择一个受攻击的星球进行协防 + const targetAlert = incomingAttacks[Math.floor(Math.random() * incomingAttacks.length)] + if (!targetAlert) return + + const targetPlanet = player.planets.find(p => p.id === targetAlert.targetPlanetId) + + if (!targetPlanet) return + + // 派遣协防舰队 + const mission = sendDefenseFleet(npc, player, targetPlanet) + + if (mission) { + // 可以在这里添加通知玩家的逻辑 + diplomaticLogic.notifyPlayerOfAllyDefense(npc, player, targetPlanet, mission) + } +} + /** * 选择NPC的最佳攻击来源星球 */ @@ -795,7 +1149,10 @@ export const updateNPCBehavior = ( giftResourcesToPlayer(npc, player) } - // 6. 更新即将到来的舰队警告(删除过期的) + // 6. 检查是否应该协防玩家(仅友好NPC,玩家被攻击时) + checkAndExecuteAllyDefense(npc, player, currentTime) + + // 7. 更新即将到来的舰队警告(删除过期的) updateIncomingFleetAlerts(player, currentTime) } @@ -898,7 +1255,10 @@ export const updateNPCBehaviorWithLimit = ( giftResourcesToPlayer(npc, player) } - // 6. 更新即将到来的舰队警告(删除过期的) + // 6. 检查是否应该协防玩家(仅友好NPC,玩家被攻击时,不受并发限制) + checkAndExecuteAllyDefense(npc, player, currentTime) + + // 7. 更新即将到来的舰队警告(删除过期的) updateIncomingFleetAlerts(player, currentTime) return { spyCreated, attackCreated } @@ -1552,3 +1912,1875 @@ export const diagnoseNPCBehavior = (npcs: NPC[], player: Player, currentTime: nu } }) } + +// ========== 敌对NPC增强行为系统 ========== + +/** + * 获取NPC的报复等级 + * 基于被攻击次数确定报复强度 + */ +export const getRevengeLevel = (npc: NPC, playerId: string): RevengeLevel => { + const { HOSTILE_BEHAVIOR_CONFIG } = DIPLOMATIC_CONFIG + const levels = HOSTILE_BEHAVIOR_CONFIG.REVENGE_ESCALATION.LEVELS + const memoryDuration = HOSTILE_BEHAVIOR_CONFIG.REVENGE_ESCALATION.MEMORY_DURATION + + // 默认等级(用于数组为空或未找到时) + const defaultLevel: RevengeLevel = levels[0] || { attackCount: 1, fleetMultiplier: 1.0, attackInterval: 600, name: 'mild' } + + const attackRecord = npc.attackedBy?.[playerId] + if (!attackRecord) { + return defaultLevel // 默认最低等级 + } + + // 检查记忆是否过期 + const now = Date.now() + if (now - attackRecord.lastAttackTime > memoryDuration) { + return defaultLevel // 记忆过期,重置为最低等级 + } + + // 根据被攻击次数确定报复等级 + const attackCount = attackRecord.count + let currentLevel = defaultLevel + + for (const level of levels) { + if (attackCount >= level.attackCount) { + currentLevel = level + } + } + + return currentLevel +} + +/** + * 检查NPC是否应该执行骚扰战术 + */ +export const shouldNPCHarass = (npc: NPC, player: Player, currentTime: number): boolean => { + const { HOSTILE_BEHAVIOR_CONFIG } = DIPLOMATIC_CONFIG + const harassConfig = HOSTILE_BEHAVIOR_CONFIG.HARASSMENT + + if (!harassConfig.ENABLED) { + return false + } + + // 检查外交关系 + const relation = npc.relations?.[player.id] + if (!relation || relation.status !== RelationStatus.Hostile) { + return false + } + + // 检查好感度是否足够低 + if (relation.reputation > harassConfig.TRIGGER_REPUTATION) { + return false + } + + // 检查骚扰冷却时间 + const lastHarassTime = (npc as any).lastHarassTime || 0 + if (currentTime - lastHarassTime < harassConfig.INTERVAL * 1000) { + return false + } + + // 概率判断 + return Math.random() < harassConfig.PROBABILITY +} + +/** + * 选择骚扰类型 + */ +export const selectHarassmentType = (): HarassmentType => { + const { HOSTILE_BEHAVIOR_CONFIG } = DIPLOMATIC_CONFIG + const types = HOSTILE_BEHAVIOR_CONFIG.HARASSMENT.TYPES + + const rand = Math.random() + if (rand < types.spy) { + return 'spy' + } else if (rand < types.spy + types.raid) { + return 'raid' + } else { + return 'intimidate' + } +} + +/** + * 创建骚扰任务 + */ +export const createHarassmentMission = ( + npc: NPC, + player: Player, + allPlanets: Planet[], + harassmentType: HarassmentType +): FleetMission | null => { + const { HOSTILE_BEHAVIOR_CONFIG } = DIPLOMATIC_CONFIG + const harassConfig = HOSTILE_BEHAVIOR_CONFIG.HARASSMENT + + // 选择随机玩家星球作为目标 + const playerPlanets = allPlanets.filter(p => p.ownerId === player.id) + if (playerPlanets.length === 0) return null + + const targetPlanet = playerPlanets[Math.floor(Math.random() * playerPlanets.length)] + if (!targetPlanet) return null + + // 选择NPC最佳星球 + const npcPlanet = selectBestNPCPlanet(npc, targetPlanet.position) + if (!npcPlanet) return null + + let fleet: Partial = {} + let missionType: MissionType = MissionType.Attack + + if (harassmentType === 'spy') { + // 侦查骚扰:派出间谍探测器 + const probes = npcPlanet.fleet[ShipType.EspionageProbe] || 0 + if (probes < 1) return null + fleet = { [ShipType.EspionageProbe]: Math.min(probes, 3) } + missionType = MissionType.Spy + } else { + // 袭击或威慑:派出小规模战斗舰队 + const fleetRatio = + harassConfig.FLEET_SIZE_RATIO.min + Math.random() * (harassConfig.FLEET_SIZE_RATIO.max - harassConfig.FLEET_SIZE_RATIO.min) + + const combatShips = [ShipType.LightFighter, ShipType.HeavyFighter, ShipType.Cruiser] + + let hasShips = false + for (const shipType of combatShips) { + const available = npcPlanet.fleet[shipType] || 0 + if (available > 0) { + const sendCount = Math.max(1, Math.floor(available * fleetRatio)) + fleet[shipType] = sendCount + hasShips = true + } + } + + if (!hasShips) return null + + // 威慑任务使用部署类型(不攻击,只是展示武力) + if (harassmentType === 'intimidate') { + missionType = MissionType.Deploy + } + } + + // 从NPC星球扣除舰队 + for (const [shipType, count] of Object.entries(fleet)) { + npcPlanet.fleet[shipType as ShipType] = (npcPlanet.fleet[shipType as ShipType] || 0) - (count as number) + } + + // 计算飞行时间 + const distance = fleetLogic.calculateDistance(npcPlanet.position, targetPlanet.position) + const fleetMinSpeed = getFleetMinSpeed(fleet) + const flightTime = fleetLogic.calculateFlightTime(distance, fleetMinSpeed) + + const now = Date.now() + const mission: FleetMission = { + id: `npc-harass-${harassmentType}-${npc.id}-${now}`, + playerId: npc.id, + npcId: npc.id, + isHostile: harassmentType !== 'intimidate', // 威慑不是敌对行动 + originPlanetId: npcPlanet.id, + targetPosition: targetPlanet.position, + targetPlanetId: targetPlanet.id, + missionType, + fleet, + cargo: { metal: 0, crystal: 0, deuterium: 0, darkMatter: 0, energy: 0 }, + departureTime: now, + arrivalTime: now + flightTime * 1000, + status: 'outbound' + } + + // 更新骚扰时间 + ;(npc as any).lastHarassTime = now + + // 添加到NPC任务列表 + if (!npc.fleetMissions) { + npc.fleetMissions = [] + } + npc.fleetMissions.push(mission) + + return mission +} + +/** + * 检查是否可以发起围攻 + * 需要多个敌对NPC协调 + */ +export const canInitiateSiege = (npcs: NPC[], player: Player, currentTime: number): { canSiege: boolean; eligibleNpcs: NPC[] } => { + const { HOSTILE_BEHAVIOR_CONFIG } = DIPLOMATIC_CONFIG + const siegeConfig = HOSTILE_BEHAVIOR_CONFIG.SIEGE + + if (!siegeConfig.ENABLED) { + return { canSiege: false, eligibleNpcs: [] } + } + + // 找出所有符合围攻条件的敌对NPC + const eligibleNpcs = npcs.filter(npc => { + const relation = npc.relations?.[player.id] + if (!relation || relation.status !== RelationStatus.Hostile) { + return false + } + + // 检查好感度是否足够低 + if (relation.reputation > siegeConfig.TRIGGER_REPUTATION) { + return false + } + + // 检查围攻冷却 + const lastSiegeTime = (npc as any).lastSiegeTime || 0 + if (currentTime - lastSiegeTime < siegeConfig.COOLDOWN) { + return false + } + + // 检查是否有足够的舰队 + const npcPlanet = npc.planets[0] + if (!npcPlanet) return false + + const combatPower = calculateNPCCombatPower(npcPlanet) + return combatPower >= MIN_COMBAT_POWER_FOR_SPY * 10 // 围攻需要较大战力 + }) + + // 检查是否有足够的NPC参与围攻 + const canSiege = eligibleNpcs.length >= siegeConfig.MIN_HOSTILE_NPCS + + return { canSiege, eligibleNpcs } +} + +/** + * 发起围攻 + * 协调多个NPC同时攻击玩家 + */ +export const initiateSiege = ( + eligibleNpcs: NPC[], + player: Player, + allPlanets: Planet[] +): { missions: FleetMission[]; coordination: SiegeCoordination } | null => { + const { HOSTILE_BEHAVIOR_CONFIG } = DIPLOMATIC_CONFIG + const siegeConfig = HOSTILE_BEHAVIOR_CONFIG.SIEGE + + if (eligibleNpcs.length < siegeConfig.MIN_HOSTILE_NPCS) { + return null + } + + // 选择目标星球(选择资源最多的) + const playerPlanets = allPlanets.filter(p => p.ownerId === player.id) + if (playerPlanets.length === 0) return null + + let targetPlanet = playerPlanets[0] + let maxResources = 0 + for (const planet of playerPlanets) { + const totalResources = planet.resources.metal + planet.resources.crystal + planet.resources.deuterium + if (totalResources > maxResources) { + maxResources = totalResources + targetPlanet = planet + } + } + + if (!targetPlanet) return null + + // 计算统一到达时间(以最远NPC的飞行时间为基准) + let maxFlightTime = 0 + for (const npc of eligibleNpcs) { + const npcPlanet = selectBestNPCPlanet(npc, targetPlanet.position) + if (npcPlanet) { + const distance = fleetLogic.calculateDistance(npcPlanet.position, targetPlanet.position) + const flightTime = fleetLogic.calculateFlightTime(distance, 10000) // 使用基准速度 + maxFlightTime = Math.max(maxFlightTime, flightTime) + } + } + + const now = Date.now() + const coordWindow = siegeConfig.COORDINATION_WINDOW + const baseArrivalTime = now + maxFlightTime * 1000 + coordWindow + + const missions: FleetMission[] = [] + const participantNpcIds: string[] = [] + + // 为每个NPC创建攻击任务 + for (const npc of eligibleNpcs) { + const npcPlanet = selectBestNPCPlanet(npc, targetPlanet.position) + if (!npcPlanet) continue + + // 计算围攻舰队 + const fleetRatio = siegeConfig.FLEET_RATIO.min + Math.random() * (siegeConfig.FLEET_RATIO.max - siegeConfig.FLEET_RATIO.min) + + const combatShips = [ + ShipType.LightFighter, + ShipType.HeavyFighter, + ShipType.Cruiser, + ShipType.Battleship, + ShipType.Bomber, + ShipType.Destroyer, + ShipType.Battlecruiser + ] + + const siegeFleet: Partial = {} + let hasShips = false + + for (const shipType of combatShips) { + const available = npcPlanet.fleet[shipType] || 0 + if (available > 0) { + const sendCount = Math.max(1, Math.floor(available * fleetRatio)) + siegeFleet[shipType] = sendCount + hasShips = true + } + } + + if (!hasShips) continue + + // 从NPC星球扣除舰队 + for (const [shipType, count] of Object.entries(siegeFleet)) { + npcPlanet.fleet[shipType as ShipType] = (npcPlanet.fleet[shipType as ShipType] || 0) - (count as number) + } + + // 计算随机偏移的到达时间(在协调窗口内) + const arrivalOffset = Math.random() * coordWindow + const arrivalTime = baseArrivalTime + arrivalOffset + + // 反推出发时间 + const distance = fleetLogic.calculateDistance(npcPlanet.position, targetPlanet.position) + const siegeMinSpeed = getFleetMinSpeed(siegeFleet) + const actualFlightTime = fleetLogic.calculateFlightTime(distance, siegeMinSpeed) + const departureTime = arrivalTime - actualFlightTime * 1000 + + const mission: FleetMission = { + id: `npc-siege-${npc.id}-${now}`, + playerId: npc.id, + npcId: npc.id, + isHostile: true, + originPlanetId: npcPlanet.id, + targetPosition: targetPlanet.position, + targetPlanetId: targetPlanet.id, + missionType: MissionType.Attack, + fleet: siegeFleet, + cargo: { metal: 0, crystal: 0, deuterium: 0, darkMatter: 0, energy: 0 }, + departureTime: Math.max(now, departureTime), + arrivalTime, + status: 'outbound' + } + + // 更新NPC的围攻时间 + ;(npc as any).lastSiegeTime = now + + // 添加到NPC任务列表 + if (!npc.fleetMissions) { + npc.fleetMissions = [] + } + npc.fleetMissions.push(mission) + + missions.push(mission) + participantNpcIds.push(npc.id) + } + + if (missions.length < siegeConfig.MIN_HOSTILE_NPCS) { + return null // 没有足够的NPC成功发起围攻 + } + + const coordination: SiegeCoordination = { + targetPlanetId: targetPlanet.id, + targetPosition: targetPlanet.position, + coordinatorNpcId: eligibleNpcs[0]?.id || '', + participantNpcIds, + arrivalTime: baseArrivalTime, + startedAt: now + } + + return { missions, coordination } +} + +/** + * 执行报复升级攻击 + * 根据报复等级派出不同强度的攻击 + */ +export const executeEscalatedRevenge = ( + npc: NPC, + player: Player, + allPlanets: Planet[], + config: DynamicBehaviorConfig +): FleetMission | null => { + const { HOSTILE_BEHAVIOR_CONFIG } = DIPLOMATIC_CONFIG + const escalationConfig = HOSTILE_BEHAVIOR_CONFIG.REVENGE_ESCALATION + + if (!escalationConfig.ENABLED) { + return null + } + + // 获取报复等级 + const revengeLevel = getRevengeLevel(npc, player.id) + + // 检查攻击间隔 + const lastRevengeTime = npc.lastAttackTime || 0 + const now = Date.now() + if (now - lastRevengeTime < revengeLevel.attackInterval * 1000) { + return null + } + + // 找到攻击者的星球 + const attackRecord = npc.attackedBy?.[player.id] + if (!attackRecord?.planetId) { + return null + } + + const targetPlanet = allPlanets.find(p => p.id === attackRecord.planetId) + if (!targetPlanet) { + return null + } + + // 选择NPC最佳星球 + const npcPlanet = selectBestNPCPlanet(npc, targetPlanet.position) + if (!npcPlanet) { + return null + } + + // 根据报复等级计算舰队规模 + const baseFleetRatio = config.attackFleetSizeRatio + const escalatedRatio = Math.min(1.0, baseFleetRatio * revengeLevel.fleetMultiplier) + + const combatShips = [ + ShipType.LightFighter, + ShipType.HeavyFighter, + ShipType.Cruiser, + ShipType.Battleship, + ShipType.Bomber, + ShipType.Destroyer, + ShipType.Battlecruiser, + ShipType.Deathstar + ] + + const revengeFleet: Partial = {} + let hasShips = false + + for (const shipType of combatShips) { + const available = npcPlanet.fleet[shipType] || 0 + if (available > 0) { + const sendCount = Math.max(1, Math.floor(available * escalatedRatio)) + revengeFleet[shipType] = sendCount + hasShips = true + } + } + + if (!hasShips) { + return null + } + + // 从NPC星球扣除舰队 + for (const [shipType, count] of Object.entries(revengeFleet)) { + npcPlanet.fleet[shipType as ShipType] = (npcPlanet.fleet[shipType as ShipType] || 0) - (count as number) + } + + // 计算飞行时间 + const distance = fleetLogic.calculateDistance(npcPlanet.position, targetPlanet.position) + const revengeMinSpeed = getFleetMinSpeed(revengeFleet) + const flightTime = fleetLogic.calculateFlightTime(distance, revengeMinSpeed) + + const mission: FleetMission = { + id: `npc-revenge-escalated-${revengeLevel.name}-${npc.id}-${now}`, + playerId: npc.id, + npcId: npc.id, + isHostile: true, + originPlanetId: npcPlanet.id, + targetPosition: targetPlanet.position, + targetPlanetId: targetPlanet.id, + missionType: MissionType.Attack, + fleet: revengeFleet, + cargo: { metal: 0, crystal: 0, deuterium: 0, darkMatter: 0, energy: 0 }, + departureTime: now, + arrivalTime: now + flightTime * 1000, + status: 'outbound' + } + + // 更新攻击时间 + npc.lastAttackTime = now + + // 添加到NPC任务列表 + if (!npc.fleetMissions) { + npc.fleetMissions = [] + } + npc.fleetMissions.push(mission) + + return mission +} + +/** + * 呼叫盟友NPC助战 + * 在报复等级较高时,可能呼叫盟友一起攻击 + */ +export const callAlliesForRevenge = ( + npc: NPC, + allNpcs: NPC[], + player: Player, + allPlanets: Planet[], + _config: DynamicBehaviorConfig +): FleetMission[] => { + const { HOSTILE_BEHAVIOR_CONFIG } = DIPLOMATIC_CONFIG + const escalationConfig = HOSTILE_BEHAVIOR_CONFIG.REVENGE_ESCALATION + + if (!escalationConfig.CALL_ALLIES) { + return [] + } + + // 获取报复等级 + const revengeLevel = getRevengeLevel(npc, player.id) + + // 计算呼叫盟友概率(报复等级越高概率越大) + const levelIndex = HOSTILE_BEHAVIOR_CONFIG.REVENGE_ESCALATION.LEVELS.findIndex(l => l.name === revengeLevel.name) + const allyCallProbability = escalationConfig.ALLY_CALL_BASE_PROBABILITY * (levelIndex + 1) + + if (Math.random() > allyCallProbability) { + return [] + } + + // 找到NPC的盟友(同样敌对玩家的NPC) + const allyMissions: FleetMission[] = [] + const attackRecord = npc.attackedBy?.[player.id] + if (!attackRecord?.planetId) { + return [] + } + + const targetPlanet = allPlanets.find(p => p.id === attackRecord.planetId) + if (!targetPlanet) { + return [] + } + + for (const allyNpc of allNpcs) { + if (allyNpc.id === npc.id) continue // 跳过自己 + + // 检查是否是盟友(也敌对玩家) + const allyRelation = allyNpc.relations?.[player.id] + if (!allyRelation || allyRelation.status !== RelationStatus.Hostile) { + continue + } + + // 检查NPC之间是否有盟友关系 + const interNpcRelation = allyNpc.allies?.includes(npc.id) || npc.allies?.includes(allyNpc.id) + if (!interNpcRelation) { + // 即使不是正式盟友,敌对同一玩家的NPC也有概率响应 + if (Math.random() > 0.3) continue + } + + // 选择盟友NPC的最佳星球 + const allyPlanet = selectBestNPCPlanet(allyNpc, targetPlanet.position) + if (!allyPlanet) continue + + // 派出援军舰队(较小规模) + const combatShips = [ShipType.LightFighter, ShipType.HeavyFighter, ShipType.Cruiser, ShipType.Battleship] + + const allyFleet: Partial = {} + let hasShips = false + + for (const shipType of combatShips) { + const available = allyPlanet.fleet[shipType] || 0 + if (available > 0) { + const sendCount = Math.max(1, Math.floor(available * 0.3)) // 援军派30% + allyFleet[shipType] = sendCount + hasShips = true + } + } + + if (!hasShips) continue + + // 从盟友星球扣除舰队 + for (const [shipType, count] of Object.entries(allyFleet)) { + allyPlanet.fleet[shipType as ShipType] = (allyPlanet.fleet[shipType as ShipType] || 0) - (count as number) + } + + // 计算飞行时间 + const distance = fleetLogic.calculateDistance(allyPlanet.position, targetPlanet.position) + const allyMinSpeed = getFleetMinSpeed(allyFleet) + const flightTime = fleetLogic.calculateFlightTime(distance, allyMinSpeed) + + const now = Date.now() + const mission: FleetMission = { + id: `npc-ally-revenge-${allyNpc.id}-${now}`, + playerId: allyNpc.id, + npcId: allyNpc.id, + isHostile: true, + originPlanetId: allyPlanet.id, + targetPosition: targetPlanet.position, + targetPlanetId: targetPlanet.id, + missionType: MissionType.Attack, + fleet: allyFleet, + cargo: { metal: 0, crystal: 0, deuterium: 0, darkMatter: 0, energy: 0 }, + departureTime: now, + arrivalTime: now + flightTime * 1000, + status: 'outbound' + } + + // 添加到盟友NPC任务列表 + if (!allyNpc.fleetMissions) { + allyNpc.fleetMissions = [] + } + allyNpc.fleetMissions.push(mission) + + allyMissions.push(mission) + } + + return allyMissions +} + +/** + * 增强版NPC行为更新函数 + * 包含围攻、骚扰、报复升级等增强行为 + */ +export const updateHostileNPCBehavior = ( + npc: NPC, + allNpcs: NPC[], + player: Player, + allPlanets: Planet[], + _debrisFields: Record, + currentTime: number, + activeSiege?: SiegeCoordination +): { + harassMission?: FleetMission + siegeMissions?: FleetMission[] + revengeMission?: FleetMission + allyRevengeMissions?: FleetMission[] + newSiegeCoordination?: SiegeCoordination +} => { + const result: { + harassMission?: FleetMission + siegeMissions?: FleetMission[] + revengeMission?: FleetMission + allyRevengeMissions?: FleetMission[] + newSiegeCoordination?: SiegeCoordination + } = {} + + const config = calculateDynamicBehavior(player.points) + + // 检查是否是敌对NPC + const relation = npc.relations?.[player.id] + if (!relation || relation.status !== RelationStatus.Hostile) { + return result + } + + // 1. 检查报复升级(优先级最高) + if (npc.revengeTarget === player.id) { + const revengeMission = executeEscalatedRevenge(npc, player, allPlanets, config) + if (revengeMission) { + result.revengeMission = revengeMission + + // 创建警告 + const targetPlanet = allPlanets.find(p => p.id === revengeMission.targetPlanetId) + if (targetPlanet) { + const alert = createIncomingFleetAlert(revengeMission, npc, targetPlanet) + if (!player.incomingFleetAlerts) { + player.incomingFleetAlerts = [] + } + player.incomingFleetAlerts.push(alert) + } + + // 呼叫盟友助战 + const allyMissions = callAlliesForRevenge(npc, allNpcs, player, allPlanets, config) + if (allyMissions.length > 0) { + result.allyRevengeMissions = allyMissions + + // 为盟友任务创建警告 + for (const allyMission of allyMissions) { + const targetPlanet = allPlanets.find(p => p.id === allyMission.targetPlanetId) + const allyNpc = allNpcs.find(n => n.id === allyMission.npcId) + if (targetPlanet && allyNpc) { + const alert = createIncomingFleetAlert(allyMission, allyNpc, targetPlanet) + player.incomingFleetAlerts.push(alert) + } + } + } + + return result // 报复后不执行其他行为 + } + } + + // 2. 检查围攻(如果没有正在进行的围攻) + if (!activeSiege) { + const { canSiege, eligibleNpcs } = canInitiateSiege(allNpcs, player, currentTime) + if (canSiege && eligibleNpcs.includes(npc)) { + // 概率触发围攻 + const { HOSTILE_BEHAVIOR_CONFIG } = DIPLOMATIC_CONFIG + if (Math.random() < HOSTILE_BEHAVIOR_CONFIG.SIEGE.BASE_PROBABILITY) { + const siegeResult = initiateSiege(eligibleNpcs, player, allPlanets) + if (siegeResult) { + result.siegeMissions = siegeResult.missions + result.newSiegeCoordination = siegeResult.coordination + + // 为所有围攻任务创建警告 + for (const mission of siegeResult.missions) { + const targetPlanet = allPlanets.find(p => p.id === mission.targetPlanetId) + const attackerNpc = allNpcs.find(n => n.id === mission.npcId) + if (targetPlanet && attackerNpc) { + const alert = createIncomingFleetAlert(mission, attackerNpc, targetPlanet) + if (!player.incomingFleetAlerts) { + player.incomingFleetAlerts = [] + } + player.incomingFleetAlerts.push(alert) + } + } + + return result // 围攻后不执行其他行为 + } + } + } + } + + // 3. 检查骚扰战术 + if (shouldNPCHarass(npc, player, currentTime)) { + const harassmentType = selectHarassmentType() + const harassMission = createHarassmentMission(npc, player, allPlanets, harassmentType) + if (harassMission) { + result.harassMission = harassMission + + // 创建警告 + const targetPlanet = allPlanets.find(p => p.id === harassMission.targetPlanetId) + if (targetPlanet) { + const alert = createIncomingFleetAlert(harassMission, npc, targetPlanet) + if (!player.incomingFleetAlerts) { + player.incomingFleetAlerts = [] + } + player.incomingFleetAlerts.push(alert) + } + } + } + + return result +} + +// ========== 中立NPC行为系统 ========== + +/** + * 检查中立NPC是否应该提议贸易 + */ +export const shouldNPCOfferTrade = (npc: NPC, player: Player, currentTime: number): boolean => { + const { NEUTRAL_BEHAVIOR_CONFIG } = DIPLOMATIC_CONFIG + const tradeConfig = NEUTRAL_BEHAVIOR_CONFIG.TRADE + + if (!tradeConfig.ENABLED) { + return false + } + + // 检查玩家当前贸易提议数量是否已达上限 + const maxOffers = (tradeConfig as any).MAX_PENDING_OFFERS || 30 + if ((player.tradeOffers?.length || 0) >= maxOffers) { + return false + } + + // 检查外交关系 + const relation = npc.relations?.[player.id] + if (!relation || relation.status !== RelationStatus.Neutral) { + return false + } + + // 检查好感度范围 + if (relation.reputation < tradeConfig.MIN_REPUTATION || relation.reputation > tradeConfig.MAX_REPUTATION) { + return false + } + + // 检查贸易冷却 + const lastTradeTime = (npc as any).lastTradeOfferTime || 0 + if (currentTime - lastTradeTime < tradeConfig.CHECK_INTERVAL * 1000) { + return false + } + + // 概率判断 + return Math.random() < tradeConfig.PROBABILITY +} + +/** + * 创建贸易提议 + */ +export const createTradeOffer = (npc: NPC, player: Player): TradeOffer | null => { + const { NEUTRAL_BEHAVIOR_CONFIG } = DIPLOMATIC_CONFIG + const tradeConfig = NEUTRAL_BEHAVIOR_CONFIG.TRADE + + // 获取NPC主星球 + const npcPlanet = npc.planets[0] + if (!npcPlanet) return null + + // 计算玩家总产量 + const playerProduction = calculatePlayerTotalProduction(player) + + // 随机决定贸易量 + const tradeMultiplier = tradeConfig.TRADE_AMOUNT.min + Math.random() * (tradeConfig.TRADE_AMOUNT.max - tradeConfig.TRADE_AMOUNT.min) + + // 随机选择交易类型 + const tradeTypes: Array<{ offer: 'metal' | 'crystal' | 'deuterium'; request: 'metal' | 'crystal' | 'deuterium'; rate: number }> = [ + { offer: 'crystal', request: 'metal', rate: tradeConfig.EXCHANGE_RATES.metalToCrystal }, + { offer: 'deuterium', request: 'metal', rate: tradeConfig.EXCHANGE_RATES.metalToDeuterium }, + { offer: 'deuterium', request: 'crystal', rate: tradeConfig.EXCHANGE_RATES.crystalToDeuterium } + ] + + const selectedTrade = tradeTypes[Math.floor(Math.random() * tradeTypes.length)] + if (!selectedTrade) return null + + // 计算交易量(基于玩家产量和NPC资源) + const baseAmount = playerProduction[selectedTrade.request] * tradeMultiplier + const npcHas = Math.floor(npcPlanet.resources[selectedTrade.offer] || 0) + + // 验证基础数值有效性 + if (!isFinite(baseAmount) || baseAmount <= 0 || !isFinite(npcHas) || npcHas <= 0) { + return null + } + + // NPC提供的资源量 + const offerAmount = Math.min(Math.floor(baseAmount / selectedTrade.rate), npcHas) + if (!isFinite(offerAmount) || offerAmount <= 0) return null + + // 玩家需要支付的资源量(含手续费) + const requestAmount = Math.floor(offerAmount * selectedTrade.rate * (1 + tradeConfig.FEE_PERCENTAGE / 100)) + if (!isFinite(requestAmount) || requestAmount <= 0) return null + + const now = Date.now() + const offer: TradeOffer = { + id: `trade-${npc.id}-${now}`, + npcId: npc.id, + npcName: npc.name, + timestamp: now, + offeredResources: { + type: selectedTrade.offer, + amount: offerAmount + }, + requestedResources: { + type: selectedTrade.request, + amount: requestAmount + }, + expiresAt: now + 30 * 60 * 1000, // 30分钟后过期 + status: 'pending' + } + + // 更新NPC的贸易时间 + ;(npc as any).lastTradeOfferTime = now + + return offer +} + +/** + * 处理贸易接受 + */ +export const acceptTradeOffer = ( + offer: TradeOffer, + npc: NPC, + player: Player, + playerPlanet: Planet +): { success: boolean; reason?: string } => { + const { NEUTRAL_BEHAVIOR_CONFIG } = DIPLOMATIC_CONFIG + const tradeConfig = NEUTRAL_BEHAVIOR_CONFIG.TRADE + + // 检查贸易是否过期 + if (Date.now() > offer.expiresAt) { + offer.status = 'expired' + return { success: false, reason: 'errors.tradeExpired' } + } + + // 检查玩家是否有足够资源 + const playerHas = playerPlanet.resources[offer.requestedResources.type] + if (playerHas < offer.requestedResources.amount) { + return { success: false, reason: 'errors.insufficientResources' } + } + + // 获取NPC主星球 + const npcPlanet = npc.planets[0] + if (!npcPlanet) { + return { success: false, reason: 'errors.npcPlanetNotFound' } + } + + // 检查NPC是否还有足够资源 + const npcHas = npcPlanet.resources[offer.offeredResources.type] + if (npcHas < offer.offeredResources.amount) { + return { success: false, reason: 'errors.npcInsufficientResources' } + } + + // 执行交易 + // 从玩家扣除 + playerPlanet.resources[offer.requestedResources.type] -= offer.requestedResources.amount + + // 给玩家资源 + playerPlanet.resources[offer.offeredResources.type] += offer.offeredResources.amount + + // 从NPC扣除 + npcPlanet.resources[offer.offeredResources.type] -= offer.offeredResources.amount + + // 给NPC资源 + npcPlanet.resources[offer.requestedResources.type] += offer.requestedResources.amount + + // 增加好感度 + const relation = npc.relations?.[player.id] + if (relation) { + relation.reputation = Math.min(DIPLOMATIC_CONFIG.MAX_REPUTATION, relation.reputation + tradeConfig.REPUTATION_GAIN) + relation.lastUpdated = Date.now() + } + + offer.status = 'accepted' + return { success: true } +} + +/** + * 检查中立NPC是否应该摇摆态度 + */ +export const shouldNPCSwingAttitude = ( + npc: NPC, + player: Player, + currentTime: number +): { shouldSwing: boolean; direction?: 'friendly' | 'hostile' } => { + const { NEUTRAL_BEHAVIOR_CONFIG } = DIPLOMATIC_CONFIG + const swingConfig = NEUTRAL_BEHAVIOR_CONFIG.SWING + + if (!swingConfig.ENABLED) { + return { shouldSwing: false } + } + + // 检查外交关系 + const relation = npc.relations?.[player.id] + if (!relation || relation.status !== RelationStatus.Neutral) { + return { shouldSwing: false } + } + + // 检查摇摆冷却 + const lastSwingCheck = (npc as any).lastSwingCheck || 0 + if (currentTime - lastSwingCheck < swingConfig.CHECK_INTERVAL * 1000) { + return { shouldSwing: false } + } + + // 更新检查时间 + ;(npc as any).lastSwingCheck = currentTime + + // 检查是否达到摇摆阈值 + if (relation.reputation >= swingConfig.SWING_THRESHOLD.toFriendly) { + // 好感度足够高,可能变友好 + const probability = swingConfig.BASE_PROBABILITY * (relation.reputation / 20) + if (Math.random() < probability) { + return { shouldSwing: true, direction: 'friendly' } + } + } else if (relation.reputation <= swingConfig.SWING_THRESHOLD.toHostile) { + // 好感度足够低,可能变敌对 + const probability = swingConfig.BASE_PROBABILITY * (Math.abs(relation.reputation) / 20) + if (Math.random() < probability) { + return { shouldSwing: true, direction: 'hostile' } + } + } + + return { shouldSwing: false } +} + +/** + * 执行NPC态度摇摆 + */ +export const executeNPCSwing = (npc: NPC, player: Player, direction: 'friendly' | 'hostile'): void => { + const relation = npc.relations?.[player.id] + if (!relation) return + + if (direction === 'friendly') { + relation.status = RelationStatus.Friendly + relation.reputation = Math.max(relation.reputation, DIPLOMATIC_CONFIG.FRIENDLY_THRESHOLD + 5) + } else { + relation.status = RelationStatus.Hostile + relation.reputation = Math.min(relation.reputation, DIPLOMATIC_CONFIG.HOSTILE_THRESHOLD - 5) + } + + relation.lastUpdated = Date.now() +} + +/** + * 中立NPC观察附近事件并调整好感度 + */ +export const observeNearbyEvents = (neutralNpc: NPC, eventNpc: NPC, player: Player, eventType: 'attack' | 'help'): void => { + const { NEUTRAL_BEHAVIOR_CONFIG } = DIPLOMATIC_CONFIG + const observeConfig = NEUTRAL_BEHAVIOR_CONFIG.OBSERVE + + if (!observeConfig.ENABLED) return + + // 检查是否是中立NPC + const relation = neutralNpc.relations?.[player.id] + if (!relation || relation.status !== RelationStatus.Neutral) return + + // 检查是否在同一星系(如果配置要求) + if (observeConfig.SAME_GALAXY_ONLY) { + const neutralPlanet = neutralNpc.planets[0] + const eventPlanet = eventNpc.planets[0] + if (!neutralPlanet || !eventPlanet) return + if (neutralPlanet.position.galaxy !== eventPlanet.position.galaxy) return + } + + // 根据事件类型调整好感度 + if (eventType === 'attack') { + relation.reputation = Math.max(DIPLOMATIC_CONFIG.MIN_REPUTATION, relation.reputation + observeConfig.ATTACK_NEARBY_PENALTY) + } else if (eventType === 'help') { + relation.reputation = Math.min(DIPLOMATIC_CONFIG.MAX_REPUTATION, relation.reputation + observeConfig.HELP_NEARBY_BONUS) + } + + relation.lastUpdated = Date.now() +} + +// ========== 友好NPC增强行为系统 ========== + +/** + * 检查友好NPC是否应该分享情报 + */ +export const shouldNPCShareIntel = (npc: NPC, player: Player, currentTime: number): boolean => { + const { FRIENDLY_BEHAVIOR_CONFIG } = DIPLOMATIC_CONFIG + const intelConfig = FRIENDLY_BEHAVIOR_CONFIG.INTEL_SHARING + + if (!intelConfig.ENABLED) { + return false + } + + // 检查外交关系 + const relation = npc.relations?.[player.id] + if (!relation || relation.status !== RelationStatus.Friendly) { + return false + } + + // 检查好感度 + if (relation.reputation < intelConfig.MIN_REPUTATION) { + return false + } + + // 检查分享冷却 + const lastIntelTime = (npc as any).lastIntelShareTime || 0 + if (currentTime - lastIntelTime < intelConfig.INTERVAL * 1000) { + return false + } + + // 概率判断 + return Math.random() < intelConfig.PROBABILITY +} + +/** + * 选择情报类型 + */ +export const selectIntelType = (): IntelType => { + const { FRIENDLY_BEHAVIOR_CONFIG } = DIPLOMATIC_CONFIG + const types = FRIENDLY_BEHAVIOR_CONFIG.INTEL_SHARING.INTEL_TYPES + + const rand = Math.random() + if (rand < types.enemyFleet) { + return 'enemyFleet' + } else if (rand < types.enemyFleet + types.enemyResources) { + return 'enemyResources' + } else { + return 'enemyMovement' + } +} + +/** + * 创建情报报告 + */ +export const createIntelReport = (friendlyNpc: NPC, allNpcs: NPC[], player: Player): IntelReport | null => { + // 找到一个敌对NPC作为情报目标 + const hostileNpcs = allNpcs.filter(n => { + const relation = n.relations?.[player.id] + return relation && relation.status === RelationStatus.Hostile + }) + + if (hostileNpcs.length === 0) return null + + const targetNpc = hostileNpcs[Math.floor(Math.random() * hostileNpcs.length)] + if (!targetNpc) return null + + const targetPlanet = targetNpc.planets[0] + if (!targetPlanet) return null + + const intelType = selectIntelType() + const now = Date.now() + + const report: IntelReport = { + id: `intel-${friendlyNpc.id}-${now}`, + fromNpcId: friendlyNpc.id, + fromNpcName: friendlyNpc.name, + timestamp: now, + targetNpcId: targetNpc.id, + targetNpcName: targetNpc.name, + intelType, + data: {}, + read: false + } + + // 根据情报类型填充数据 + switch (intelType) { + case 'enemyFleet': + report.data.fleet = { ...targetPlanet.fleet } + break + case 'enemyResources': + report.data.resources = { ...targetPlanet.resources } + break + case 'enemyMovement': + // 检查NPC是否有正在进行的任务 + const activeMission = targetNpc.fleetMissions?.find(m => m.status === 'outbound') + if (activeMission) { + report.data.movement = { + targetPosition: activeMission.targetPosition, + arrivalTime: activeMission.arrivalTime, + missionType: activeMission.missionType + } + } else { + // 没有活动任务,改为分享舰队信息 + report.intelType = 'enemyFleet' + report.data.fleet = { ...targetPlanet.fleet } + } + break + } + + // 更新NPC的情报分享时间 + ;(friendlyNpc as any).lastIntelShareTime = now + + return report +} + +/** + * 检查友好NPC是否应该邀请联合攻击 + */ +export const shouldNPCInviteJointAttack = (npc: NPC, player: Player, currentTime: number): boolean => { + const { FRIENDLY_BEHAVIOR_CONFIG } = DIPLOMATIC_CONFIG + const jointConfig = FRIENDLY_BEHAVIOR_CONFIG.JOINT_ATTACK + + if (!jointConfig.ENABLED) { + return false + } + + // 检查外交关系 + const relation = npc.relations?.[player.id] + if (!relation || relation.status !== RelationStatus.Friendly) { + return false + } + + // 检查好感度 + if (relation.reputation < jointConfig.MIN_REPUTATION) { + return false + } + + // 检查邀请冷却 + const lastInviteTime = (npc as any).lastJointAttackInvite || 0 + if (currentTime - lastInviteTime < jointConfig.INTERVAL * 1000) { + return false + } + + // 概率判断 + return Math.random() < jointConfig.PROBABILITY +} + +/** + * 创建联合攻击邀请 + */ +export const createJointAttackInvite = (friendlyNpc: NPC, allNpcs: NPC[], player: Player): JointAttackInvite | null => { + const { FRIENDLY_BEHAVIOR_CONFIG } = DIPLOMATIC_CONFIG + const jointConfig = FRIENDLY_BEHAVIOR_CONFIG.JOINT_ATTACK + + // 找到合适的攻击目标 + let targetNpc: NPC | null = null + + if (jointConfig.PREFER_COMMON_ENEMY) { + // 优先选择共同敌人(对友好NPC也敌对的NPC) + const commonEnemies = allNpcs.filter(n => { + const playerRelation = n.relations?.[player.id] + const npcRelation = n.relations?.[friendlyNpc.id] + return playerRelation?.status === RelationStatus.Hostile && npcRelation?.status === RelationStatus.Hostile + }) + if (commonEnemies.length > 0) { + targetNpc = commonEnemies[Math.floor(Math.random() * commonEnemies.length)] || null + } + } + + // 如果没有共同敌人,选择任意敌对NPC + if (!targetNpc) { + const hostileNpcs = allNpcs.filter(n => { + const relation = n.relations?.[player.id] + return relation && relation.status === RelationStatus.Hostile + }) + if (hostileNpcs.length > 0) { + targetNpc = hostileNpcs[Math.floor(Math.random() * hostileNpcs.length)] || null + } + } + + if (!targetNpc) return null + + const targetPlanet = targetNpc.planets[0] + if (!targetPlanet) return null + + // 计算NPC承诺的舰队 + const npcPlanet = friendlyNpc.planets[0] + if (!npcPlanet) return null + + const fleetRatio = jointConfig.NPC_FLEET_RATIO.min + Math.random() * (jointConfig.NPC_FLEET_RATIO.max - jointConfig.NPC_FLEET_RATIO.min) + + const combatShips = [ + ShipType.LightFighter, + ShipType.HeavyFighter, + ShipType.Cruiser, + ShipType.Battleship, + ShipType.Bomber, + ShipType.Destroyer + ] + + const committedFleet: Partial = {} + let hasShips = false + + for (const shipType of combatShips) { + const available = npcPlanet.fleet[shipType] || 0 + if (available > 0) { + const commitCount = Math.floor(available * fleetRatio) + if (commitCount > 0) { + committedFleet[shipType] = commitCount + hasShips = true + } + } + } + + if (!hasShips) return null + + const now = Date.now() + const invite: JointAttackInvite = { + id: `joint-attack-${friendlyNpc.id}-${now}`, + fromNpcId: friendlyNpc.id, + fromNpcName: friendlyNpc.name, + timestamp: now, + targetNpcId: targetNpc.id, + targetNpcName: targetNpc.name, + targetPlanetId: targetPlanet.id, + targetPosition: targetPlanet.position, + npcFleetCommitment: committedFleet, + expectedLootRatio: jointConfig.PLAYER_LOOT_RATIO, + expiresAt: now + 2 * 60 * 60 * 1000, // 2小时后过期 + status: 'pending' + } + + // 更新NPC的邀请时间 + ;(friendlyNpc as any).lastJointAttackInvite = now + + return invite +} + +/** + * 检查友好NPC是否应该提供资源援助 + */ +export const shouldNPCProvideAid = (npc: NPC, player: Player, currentTime: number): boolean => { + const { FRIENDLY_BEHAVIOR_CONFIG } = DIPLOMATIC_CONFIG + const aidConfig = FRIENDLY_BEHAVIOR_CONFIG.RESOURCE_AID + + if (!aidConfig.ENABLED) { + return false + } + + // 检查外交关系 + const relation = npc.relations?.[player.id] + if (!relation || relation.status !== RelationStatus.Friendly) { + return false + } + + // 检查好感度 + if (relation.reputation < aidConfig.MIN_REPUTATION) { + return false + } + + // 检查援助冷却 + const lastAidTime = (npc as any).lastAidTime || 0 + if (currentTime - lastAidTime < aidConfig.CHECK_INTERVAL * 1000) { + return false + } + + // 检查玩家是否资源紧张 + const playerProduction = calculatePlayerTotalProduction(player) + const lowResourceThreshold = { + metal: playerProduction.metal * aidConfig.TRIGGER_LOW_RESOURCES_HOURS, + crystal: playerProduction.crystal * aidConfig.TRIGGER_LOW_RESOURCES_HOURS, + deuterium: playerProduction.deuterium * aidConfig.TRIGGER_LOW_RESOURCES_HOURS + } + + // 检查玩家总资源 + let totalPlayerResources = { metal: 0, crystal: 0, deuterium: 0 } + for (const planet of player.planets) { + totalPlayerResources.metal += planet.resources.metal + totalPlayerResources.crystal += planet.resources.crystal + totalPlayerResources.deuterium += planet.resources.deuterium + } + + // 如果玩家资源充足,不援助 + if ( + totalPlayerResources.metal > lowResourceThreshold.metal && + totalPlayerResources.crystal > lowResourceThreshold.crystal && + totalPlayerResources.deuterium > lowResourceThreshold.deuterium + ) { + return false + } + + // 概率判断 + return Math.random() < aidConfig.PROBABILITY +} + +/** + * 执行资源援助 + */ +export const executeResourceAid = (npc: NPC, player: Player): Resources | null => { + const { FRIENDLY_BEHAVIOR_CONFIG } = DIPLOMATIC_CONFIG + const aidConfig = FRIENDLY_BEHAVIOR_CONFIG.RESOURCE_AID + + // 获取NPC主星球 + const npcPlanet = npc.planets[0] + if (!npcPlanet) return null + + // 计算援助量 + const playerProduction = calculatePlayerTotalProduction(player) + const aidAmount = { + metal: Math.floor(playerProduction.metal * aidConfig.AID_AMOUNT_HOURS), + crystal: Math.floor(playerProduction.crystal * aidConfig.AID_AMOUNT_HOURS), + deuterium: Math.floor(playerProduction.deuterium * aidConfig.AID_AMOUNT_HOURS), + darkMatter: 0, + energy: 0 + } + + // 限制为NPC实际拥有的资源 + aidAmount.metal = Math.min(aidAmount.metal, Math.floor(npcPlanet.resources.metal * 0.5)) + aidAmount.crystal = Math.min(aidAmount.crystal, Math.floor(npcPlanet.resources.crystal * 0.5)) + aidAmount.deuterium = Math.min(aidAmount.deuterium, Math.floor(npcPlanet.resources.deuterium * 0.5)) + + // 如果援助量太少,不援助 + if (aidAmount.metal <= 0 && aidAmount.crystal <= 0 && aidAmount.deuterium <= 0) { + return null + } + + // 从NPC扣除 + npcPlanet.resources.metal -= aidAmount.metal + npcPlanet.resources.crystal -= aidAmount.crystal + npcPlanet.resources.deuterium -= aidAmount.deuterium + + // 给玩家主星球 + const playerMainPlanet = player.planets[0] + if (playerMainPlanet) { + playerMainPlanet.resources.metal += aidAmount.metal + playerMainPlanet.resources.crystal += aidAmount.crystal + playerMainPlanet.resources.deuterium += aidAmount.deuterium + } + + // 更新援助时间 + ;(npc as any).lastAidTime = Date.now() + + return aidAmount +} + +/** + * 更新中立NPC行为 + */ +export const updateNeutralNPCBehavior = ( + npc: NPC, + _allNpcs: NPC[], + player: Player, + currentTime: number +): { + tradeOffer?: TradeOffer + swingDirection?: 'friendly' | 'hostile' +} => { + const result: { + tradeOffer?: TradeOffer + swingDirection?: 'friendly' | 'hostile' + } = {} + + // 检查是否是中立NPC + const relation = npc.relations?.[player.id] + if (!relation || relation.status !== RelationStatus.Neutral) { + return result + } + + // 1. 检查贸易提议 + if (shouldNPCOfferTrade(npc, player, currentTime)) { + const offer = createTradeOffer(npc, player) + if (offer) { + result.tradeOffer = offer + } + } + + // 2. 检查态度摇摆 + const swingResult = shouldNPCSwingAttitude(npc, player, currentTime) + if (swingResult.shouldSwing && swingResult.direction) { + executeNPCSwing(npc, player, swingResult.direction) + result.swingDirection = swingResult.direction + } + + return result +} + +/** + * 更新友好NPC行为 + */ +export const updateFriendlyNPCBehavior = ( + npc: NPC, + allNpcs: NPC[], + player: Player, + currentTime: number +): { + intelReport?: IntelReport + jointAttackInvite?: JointAttackInvite + aidProvided?: Resources +} => { + const result: { + intelReport?: IntelReport + jointAttackInvite?: JointAttackInvite + aidProvided?: Resources + } = {} + + // 检查是否是友好NPC + const relation = npc.relations?.[player.id] + if (!relation || relation.status !== RelationStatus.Friendly) { + return result + } + + // 1. 检查情报分享 + if (shouldNPCShareIntel(npc, player, currentTime)) { + const report = createIntelReport(npc, allNpcs, player) + if (report) { + result.intelReport = report + } + } + + // 2. 检查联合攻击邀请 + if (shouldNPCInviteJointAttack(npc, player, currentTime)) { + const invite = createJointAttackInvite(npc, allNpcs, player) + if (invite) { + result.jointAttackInvite = invite + } + } + + // 3. 检查资源援助 + if (shouldNPCProvideAid(npc, player, currentTime)) { + const aid = executeResourceAid(npc, player) + if (aid) { + result.aidProvided = aid + } + } + + return result +} + +/** + * 综合NPC行为更新函数 + * 根据NPC与玩家的关系状态调用相应的行为更新 + */ +export const updateAllNPCBehaviors = ( + npcs: NPC[], + player: Player, + allPlanets: Planet[], + debrisFields: Record, + currentTime: number, + activeSiege?: SiegeCoordination +): { + hostileResults: Map> + neutralResults: Map> + friendlyResults: Map> + newSiegeCoordination?: SiegeCoordination +} => { + const hostileResults = new Map>() + const neutralResults = new Map>() + const friendlyResults = new Map>() + let newSiegeCoordination: SiegeCoordination | undefined + + for (const npc of npcs) { + const relation = npc.relations?.[player.id] + + if (relation?.status === RelationStatus.Hostile) { + // 敌对NPC + const result = updateHostileNPCBehavior(npc, npcs, player, allPlanets, debrisFields, currentTime, activeSiege) + hostileResults.set(npc.id, result) + if (result.newSiegeCoordination) { + newSiegeCoordination = result.newSiegeCoordination + } + } else if (relation?.status === RelationStatus.Neutral) { + // 中立NPC + const result = updateNeutralNPCBehavior(npc, npcs, player, currentTime) + neutralResults.set(npc.id, result) + } else if (relation?.status === RelationStatus.Friendly) { + // 友好NPC + const result = updateFriendlyNPCBehavior(npc, npcs, player, currentTime) + friendlyResults.set(npc.id, result) + } + } + + return { + hostileResults, + neutralResults, + friendlyResults, + newSiegeCoordination + } +} + +// ========== NPC联盟系统 ========== + +/** + * 获取NPC之间的AI类型兼容性分数 + */ +export const getAITypeCompatibility = (type1?: NPCAIType, type2?: NPCAIType): number => { + const { NPC_ALLIANCE_CONFIG } = DIPLOMATIC_CONFIG + const compatibility = NPC_ALLIANCE_CONFIG.INTER_NPC_RELATIONS.TYPE_COMPATIBILITY + + // 默认类型为平衡型 + const t1 = type1 || NPCAIType.Balanced + const t2 = type2 || NPCAIType.Balanced + + // 商人型与任何类型都友好 + if (t1 === NPCAIType.Trader || t2 === NPCAIType.Trader) { + return compatibility.trader_any + } + + // 侵略型与防守型互为敌人 + if ((t1 === NPCAIType.Aggressive && t2 === NPCAIType.Defensive) || (t1 === NPCAIType.Defensive && t2 === NPCAIType.Aggressive)) { + return compatibility.aggressive_defensive + } + + // 扩张型互相竞争 + if (t1 === NPCAIType.Expansionist && t2 === NPCAIType.Expansionist) { + return compatibility.expansionist_expansionist + } + + // 平衡型保持中立 + if (t1 === NPCAIType.Balanced || t2 === NPCAIType.Balanced) { + return compatibility.balanced_any + } + + // 默认中立 + return 0 +} + +/** + * 初始化NPC之间的关系 + */ +export const initializeInterNPCRelations = (npcs: NPC[]): void => { + const { NPC_ALLIANCE_CONFIG } = DIPLOMATIC_CONFIG + + if (!NPC_ALLIANCE_CONFIG.ENABLED) return + + const config = NPC_ALLIANCE_CONFIG.INTER_NPC_RELATIONS + + for (const npc of npcs) { + if (!npc.allies) npc.allies = [] + if (!npc.enemies) npc.enemies = [] + + const npcPlanet = npc.planets[0] + if (!npcPlanet) continue + + for (const otherNpc of npcs) { + if (npc.id === otherNpc.id) continue + + const otherPlanet = otherNpc.planets[0] + if (!otherPlanet) continue + + // 计算关系分数 + let relationScore = 0 + + // 1. AI类型兼容性 + const typeCompatibility = getAITypeCompatibility(npc.aiType, otherNpc.aiType) + relationScore += typeCompatibility * 50 // 将-1到1映射到-50到50 + + // 2. 同一星系加成 + if (npcPlanet.position.galaxy === otherPlanet.position.galaxy) { + relationScore += config.SAME_GALAXY_ALLY_BONUS * 100 // 30点加成 + } + + // 3. 随机因素(如果是mixed模式) + if (config.INIT_MODE === 'mixed' || config.INIT_MODE === 'random') { + relationScore += (Math.random() - 0.5) * 40 // -20到20的随机值 + } + + // 根据分数决定关系 + if (relationScore > 30) { + // 盟友 + if (!npc.allies.includes(otherNpc.id)) { + npc.allies.push(otherNpc.id) + } + } else if (relationScore < -30) { + // 敌人 + if (!npc.enemies.includes(otherNpc.id)) { + npc.enemies.push(otherNpc.id) + } + } + // 否则保持中立 + } + } +} + +/** + * 传播连坐效应 + * 当玩家攻击/帮助NPC时,影响其盟友的好感度 + */ +export const propagateGuiltByAssociation = ( + targetNpc: NPC, + allNpcs: NPC[], + player: Player, + eventType: 'attack' | 'help', + depth: number = 0 +): void => { + const { NPC_ALLIANCE_CONFIG } = DIPLOMATIC_CONFIG + const guiltConfig = NPC_ALLIANCE_CONFIG.GUILT_BY_ASSOCIATION + + if (!guiltConfig.ENABLED) return + if (depth >= guiltConfig.MAX_PROPAGATION_DEPTH) return + + // 获取目标NPC的盟友 + const allies = targetNpc.allies || [] + + for (const allyId of allies) { + const allyNpc = allNpcs.find(n => n.id === allyId) + if (!allyNpc) continue + + // 获取盟友与玩家的关系 + const relation = allyNpc.relations?.[player.id] + if (!relation) continue + + // 计算好感度变化 + let reputationChange = eventType === 'attack' ? guiltConfig.ALLY_REPUTATION_PENALTY : guiltConfig.ALLY_REPUTATION_BONUS + + // 如果启用强度乘数,根据传播深度减弱效果 + if (guiltConfig.STRENGTH_MULTIPLIER) { + reputationChange = Math.floor(reputationChange * Math.pow(0.5, depth)) + } + + // 应用好感度变化 + relation.reputation = Math.max( + DIPLOMATIC_CONFIG.MIN_REPUTATION, + Math.min(DIPLOMATIC_CONFIG.MAX_REPUTATION, relation.reputation + reputationChange) + ) + relation.lastUpdated = Date.now() + + // 更新关系状态 + if (relation.reputation < DIPLOMATIC_CONFIG.HOSTILE_THRESHOLD) { + relation.status = RelationStatus.Hostile + } else if (relation.reputation > DIPLOMATIC_CONFIG.FRIENDLY_THRESHOLD) { + relation.status = RelationStatus.Friendly + } else { + relation.status = RelationStatus.Neutral + } + + // 递归传播到盟友的盟友 + propagateGuiltByAssociation(allyNpc, allNpcs, player, eventType, depth + 1) + } +} + +/** + * NPC盟友互助:当NPC被攻击时,盟友可能响应 + */ +export const checkAllyMutualDefense = ( + attackedNpc: NPC, + attackerPlayerId: string, + allNpcs: NPC[], + allPlanets: Planet[], + currentTime: number +): FleetMission[] => { + const { NPC_ALLIANCE_CONFIG } = DIPLOMATIC_CONFIG + const defenseConfig = NPC_ALLIANCE_CONFIG.MUTUAL_DEFENSE + + if (!defenseConfig.ENABLED) return [] + + const defenseMissions: FleetMission[] = [] + const allies = attackedNpc.allies || [] + + // 找到攻击者的星球 + const attackerPlanet = allPlanets.find(p => p.ownerId === attackerPlayerId) + if (!attackerPlanet) return [] + + for (const allyId of allies) { + const allyNpc = allNpcs.find(n => n.id === allyId) + if (!allyNpc) continue + + // 检查响应冷却 + const lastDefenseTime = (allyNpc as any).lastMutualDefenseTime || 0 + if (currentTime - lastDefenseTime < defenseConfig.COOLDOWN * 1000) { + continue + } + + // 概率检查 + if (Math.random() > defenseConfig.RESPONSE_PROBABILITY) { + continue + } + + // 选择盟友最佳星球 + const allyPlanet = selectBestNPCPlanet(allyNpc, attackerPlanet.position) + if (!allyPlanet) continue + + // 计算响应舰队 + const fleetRatio = defenseConfig.FLEET_RATIO.min + Math.random() * (defenseConfig.FLEET_RATIO.max - defenseConfig.FLEET_RATIO.min) + + const combatShips = [ + ShipType.LightFighter, + ShipType.HeavyFighter, + ShipType.Cruiser, + ShipType.Battleship, + ShipType.Bomber, + ShipType.Destroyer + ] + + const defenseFleet: Partial = {} + let hasShips = false + + for (const shipType of combatShips) { + const available = allyPlanet.fleet[shipType] || 0 + if (available > 0) { + const sendCount = Math.max(1, Math.floor(available * fleetRatio)) + defenseFleet[shipType] = sendCount + hasShips = true + } + } + + if (!hasShips) continue + + // 从盟友星球扣除舰队 + for (const [shipType, count] of Object.entries(defenseFleet)) { + allyPlanet.fleet[shipType as ShipType] = (allyPlanet.fleet[shipType as ShipType] || 0) - (count as number) + } + + // 计算飞行时间 + const distance = fleetLogic.calculateDistance(allyPlanet.position, attackerPlanet.position) + const defenseMinSpeed = getFleetMinSpeed(defenseFleet) + const flightTime = fleetLogic.calculateFlightTime(distance, defenseMinSpeed) + + const now = Date.now() + const mission: FleetMission = { + id: `npc-mutual-defense-${allyNpc.id}-${now}`, + playerId: allyNpc.id, + npcId: allyNpc.id, + isHostile: true, + originPlanetId: allyPlanet.id, + targetPosition: attackerPlanet.position, + targetPlanetId: attackerPlanet.id, + missionType: MissionType.Attack, + fleet: defenseFleet, + cargo: { metal: 0, crystal: 0, deuterium: 0, darkMatter: 0, energy: 0 }, + departureTime: now, + arrivalTime: now + flightTime * 1000, + status: 'outbound' + } + + // 更新响应时间 + ;(allyNpc as any).lastMutualDefenseTime = now + + // 添加到盟友NPC任务列表 + if (!allyNpc.fleetMissions) { + allyNpc.fleetMissions = [] + } + allyNpc.fleetMissions.push(mission) + + defenseMissions.push(mission) + } + + return defenseMissions +} + +/** + * NPC之间的资源共享 + */ +export const executeNPCResourceSharing = (npcs: NPC[], currentTime: number): void => { + const { NPC_ALLIANCE_CONFIG } = DIPLOMATIC_CONFIG + const sharingConfig = NPC_ALLIANCE_CONFIG.RESOURCE_SHARING + + if (!sharingConfig.ENABLED) return + + for (const npc of npcs) { + // 检查共享冷却 + const lastShareTime = (npc as any).lastResourceShareTime || 0 + if (currentTime - lastShareTime < sharingConfig.INTERVAL * 1000) { + continue + } + + const npcPlanet = npc.planets[0] + if (!npcPlanet) continue + + const allies = npc.allies || [] + if (allies.length === 0) continue + + // 计算可共享资源 + const shareAmount = { + metal: Math.floor(npcPlanet.resources.metal * sharingConfig.SHARE_RATIO), + crystal: Math.floor(npcPlanet.resources.crystal * sharingConfig.SHARE_RATIO), + deuterium: Math.floor(npcPlanet.resources.deuterium * sharingConfig.SHARE_RATIO) + } + + // 平均分配给所有盟友 + const perAlly = { + metal: Math.floor(shareAmount.metal / allies.length), + crystal: Math.floor(shareAmount.crystal / allies.length), + deuterium: Math.floor(shareAmount.deuterium / allies.length) + } + + if (perAlly.metal <= 0 && perAlly.crystal <= 0 && perAlly.deuterium <= 0) { + continue + } + + // 从NPC扣除 + npcPlanet.resources.metal -= perAlly.metal * allies.length + npcPlanet.resources.crystal -= perAlly.crystal * allies.length + npcPlanet.resources.deuterium -= perAlly.deuterium * allies.length + + // 分配给盟友 + for (const allyId of allies) { + const allyNpc = npcs.find(n => n.id === allyId) + if (!allyNpc) continue + + const allyPlanet = allyNpc.planets[0] + if (!allyPlanet) continue + + allyPlanet.resources.metal += perAlly.metal + allyPlanet.resources.crystal += perAlly.crystal + allyPlanet.resources.deuterium += perAlly.deuterium + } + + // 更新共享时间 + ;(npc as any).lastResourceShareTime = currentTime + } +} + +/** + * 获取NPC的所有盟友信息 + */ +export const getNPCAllies = (npc: NPC, allNpcs: NPC[]): NPC[] => { + const allies: NPC[] = [] + const allyIds = npc.allies || [] + + for (const allyId of allyIds) { + const allyNpc = allNpcs.find(n => n.id === allyId) + if (allyNpc) { + allies.push(allyNpc) + } + } + + return allies +} + +/** + * 获取NPC的所有敌人信息 + */ +export const getNPCEnemies = (npc: NPC, allNpcs: NPC[]): NPC[] => { + const enemies: NPC[] = [] + const enemyIds = npc.enemies || [] + + for (const enemyId of enemyIds) { + const enemyNpc = allNpcs.find(n => n.id === enemyId) + if (enemyNpc) { + enemies.push(enemyNpc) + } + } + + return enemies +} + +/** + * 增强版NPC被攻击处理 + * 包含连坐效应和盟友互助 + */ +export const handleNPCAttackedWithAlliance = ( + npc: NPC, + attackerId: string, + attackerPlanetId: string | undefined, + allNpcs: NPC[], + player: Player, + allPlanets: Planet[], + currentTime: number +): FleetMission[] => { + // 基础被攻击处理 + handleNPCAttacked(npc, attackerId, attackerPlanetId) + + // 传播连坐效应 + propagateGuiltByAssociation(npc, allNpcs, player, 'attack') + + // 检查盟友互助 + const defenseMissions = checkAllyMutualDefense(npc, attackerId, allNpcs, allPlanets, currentTime) + + return defenseMissions +} + +/** + * 更新NPC联盟系统 + * 在游戏循环中调用 + */ +export const updateNPCAllianceSystem = (npcs: NPC[], currentTime: number): void => { + const { NPC_ALLIANCE_CONFIG } = DIPLOMATIC_CONFIG + + if (!NPC_ALLIANCE_CONFIG.ENABLED) return + + // 执行NPC之间的资源共享 + executeNPCResourceSharing(npcs, currentTime) +} diff --git a/src/logic/npcGrowthLogic.ts b/src/logic/npcGrowthLogic.ts index 90eab6f..ace56aa 100644 --- a/src/logic/npcGrowthLogic.ts +++ b/src/logic/npcGrowthLogic.ts @@ -427,11 +427,11 @@ export const generateNPCResources = (npc: NPC, deltaSeconds: number, config: Dyn const deuteriumLevel = planet.buildings[BuildingType.DeuteriumSynthesizer] || 0 const darkMatterLevel = planet.buildings[BuildingType.DarkMatterCollector] || 0 - // 简化的资源产量计算(每秒产量) - const metalProduction = 30 * metalMineLevel * Math.pow(1.1, metalMineLevel) * config.resourceGrowthRate - const crystalProduction = 20 * crystalMineLevel * Math.pow(1.1, crystalMineLevel) * config.resourceGrowthRate - const deuteriumProduction = 10 * deuteriumLevel * Math.pow(1.1, deuteriumLevel) * config.resourceGrowthRate - const darkMatterProduction = ((25 * darkMatterLevel * Math.pow(1.5, darkMatterLevel)) / 3600) * config.resourceGrowthRate + // 简化的资源产量计算(每秒产量) - 提升3倍让NPC更富有 + const metalProduction = 90 * metalMineLevel * Math.pow(1.1, metalMineLevel) * config.resourceGrowthRate + const crystalProduction = 60 * crystalMineLevel * Math.pow(1.1, crystalMineLevel) * config.resourceGrowthRate + const deuteriumProduction = 30 * deuteriumLevel * Math.pow(1.1, deuteriumLevel) * config.resourceGrowthRate + const darkMatterProduction = ((75 * darkMatterLevel * Math.pow(1.5, darkMatterLevel)) / 3600) * config.resourceGrowthRate // 应用游戏速度倍率到时间 const effectiveDeltaSeconds = deltaSeconds * gameSpeed @@ -541,11 +541,11 @@ export const initializeNPCStartingPower = ( npc.technologies[TechnologyType.ArmourTechnology] = Math.floor(targetTechLevel * 0.7) npc.technologies[TechnologyType.CombustionDrive] = Math.floor(targetTechLevel * 0.6) - // 给予起始资源 - planet.resources.metal = 100000 * config.powerRatio - planet.resources.crystal = 50000 * config.powerRatio - planet.resources.deuterium = 20000 * config.powerRatio - planet.resources.darkMatter = 1000 * config.powerRatio + // 给予起始资源 - 大幅提升以让NPC更富有 + planet.resources.metal = 500000 * config.powerRatio + planet.resources.crystal = 250000 * config.powerRatio + planet.resources.deuterium = 100000 * config.powerRatio + planet.resources.darkMatter = 5000 * config.powerRatio // 给予起始舰队(确保NPC能够立即侦查和攻击) // 使用平方根函数来平滑舰队数量增长,避免初期过于强大 @@ -586,8 +586,6 @@ export const ensureNPCSpyProbes = (npcs: NPC[]): void => { const config = NPC_GROWTH_CONFIG[npc.difficulty] const fleetRatio = Math.sqrt(config.powerRatio) planet.fleet[ShipType.EspionageProbe] = Math.max(5, Math.floor(10 * fleetRatio)) - - console.log(`[NPC Migration] Added ${planet.fleet[ShipType.EspionageProbe]} spy probes to NPC ${npc.name}`) } }) } @@ -761,17 +759,32 @@ export const ensureAllNPCsAIType = (npcs: NPC[]): void => { * 基于距离难度初始化NPC星球 * 替代旧的 initializeNPCStartingPower * - * 建筑等级上限:30 - * 科技等级上限:20 - * 资源上限:基于仓储建筑等级计算 (10000 * 2^level) - * 舰队数量:基于船坞等级和难度等级合理计算 + * 设计原则: + * 1. 只设置行星可建造的建筑(不设置月球专属建筑) + * 2. 建筑空间不超出 maxSpace 限制 + * 3. 舰队仓储不超出限制(基于船坞+机库+计算机技术计算) + * 4. 建筑和科技等级合理,不是随机的,与难度成正比 + * + * 空间占用(每级): + * - 金属矿/晶体矿: 1, 重氢合成器: 2, 太阳能电站: 2 + * - 聚变反应堆: 4, 金属/晶体/重氢仓库: 1 + * - 机器人工厂: 4, 造船厂: 5, 研究实验室: 3, 机库: 3 + * - 纳米工厂: 8, 导弹发射井: 6, 地形改造器: 5 + * - 暗物质收集器: 5, 暗物质储罐: 2, 地质研究站: 6, 深钻设施: 15 + * + * 舰队仓储容量 = 1000 + 船坞×1000 + 机库×1500 + 计算机技术×500 + * + * 舰船仓储占用: + * - 轻型战斗机: 5, 重型战斗机: 10, 巡洋舰: 15, 战列舰: 25 + * - 战列巡洋舰: 20, 轰炸机: 35, 驱逐舰: 12 + * - 小型运输: 10, 大型运输: 20, 殖民船: 40, 回收船: 30 + * - 间谍探测器: 2, 太阳能卫星: 1, 暗物质收集船: 50, 死星: 100 */ export const initializeNPCByDistance = (npc: NPC, homeworldPosition: { galaxy: number; system: number; position: number }): void => { const planet = npc.planets[0] if (!planet) return const distance = calculateDistanceToHomeworld(planet.position, homeworldPosition) - const multipliers = calculateDistanceDifficultyMultiplier(distance) // 保存距离和难度等级到NPC npc.distanceToHomeworld = distance @@ -780,88 +793,197 @@ export const initializeNPCByDistance = (npc: NPC, homeworldPosition: { galaxy: n // 分配随机 AI 类型(如果还没有) ensureNPCAIType(npc) - // 基础等级 * 倍率,并限制上限 - const baseLevel = 5 - const MAX_BUILDING_LEVEL = 30 - const MAX_TECH_LEVEL = 20 - - const targetBuildingLevel = Math.min(MAX_BUILDING_LEVEL, Math.max(1, Math.floor(baseLevel * multipliers.buildingMultiplier))) - const targetTechLevel = Math.min(MAX_TECH_LEVEL, Math.max(1, Math.floor(baseLevel * multipliers.techMultiplier))) - - // 设置资源建筑(上限30) - planet.buildings[BuildingType.MetalMine] = Math.min(MAX_BUILDING_LEVEL, targetBuildingLevel) - planet.buildings[BuildingType.CrystalMine] = Math.min(MAX_BUILDING_LEVEL, Math.max(1, Math.floor(targetBuildingLevel * 0.8))) - planet.buildings[BuildingType.DeuteriumSynthesizer] = Math.min(MAX_BUILDING_LEVEL, Math.max(1, Math.floor(targetBuildingLevel * 0.6))) - planet.buildings[BuildingType.SolarPlant] = Math.min(MAX_BUILDING_LEVEL, targetBuildingLevel + 2) - - // 设置设施建筑 - planet.buildings[BuildingType.RoboticsFactory] = Math.min(15, Math.max(1, Math.floor(targetBuildingLevel * 0.5))) - planet.buildings[BuildingType.Shipyard] = Math.min(12, Math.max(1, Math.floor(targetBuildingLevel * 0.4))) - planet.buildings[BuildingType.ResearchLab] = Math.min(12, Math.max(1, Math.floor(targetBuildingLevel * 0.4))) - - // 设置仓储(上限10级,对应10000*2^10=10,240,000容量) - const storageLevel = Math.min(10, Math.max(1, Math.floor(targetBuildingLevel * 0.3))) - planet.buildings[BuildingType.MetalStorage] = storageLevel - planet.buildings[BuildingType.CrystalStorage] = storageLevel - planet.buildings[BuildingType.DeuteriumTank] = storageLevel - - // 设置科技(上限20) - npc.technologies[TechnologyType.EnergyTechnology] = Math.min(MAX_TECH_LEVEL, targetTechLevel) - npc.technologies[TechnologyType.ComputerTechnology] = Math.min(MAX_TECH_LEVEL, Math.max(1, Math.floor(targetTechLevel * 0.8))) - npc.technologies[TechnologyType.WeaponsTechnology] = Math.min(MAX_TECH_LEVEL, Math.max(1, Math.floor(targetTechLevel * 0.7))) - npc.technologies[TechnologyType.ShieldingTechnology] = Math.min(MAX_TECH_LEVEL, Math.max(1, Math.floor(targetTechLevel * 0.7))) - npc.technologies[TechnologyType.ArmourTechnology] = Math.min(MAX_TECH_LEVEL, Math.max(1, Math.floor(targetTechLevel * 0.7))) - npc.technologies[TechnologyType.CombustionDrive] = Math.min(MAX_TECH_LEVEL, Math.max(1, Math.floor(targetTechLevel * 0.6))) - npc.technologies[TechnologyType.EspionageTechnology] = Math.min(MAX_TECH_LEVEL, Math.max(1, Math.floor(targetTechLevel * 0.5))) - - // 计算舰队仓储容量(船坞每级+1000) - const shipyardLevel = planet.buildings[BuildingType.Shipyard] || 1 - const fleetStorageCapacity = shipyardLevel * 1000 - - // 基于难度等级和船坞容量计算舰队数量 - // 难度等级1-7对应不同的舰队规模 + // 难度等级 1-7+,有效等级 = 难度等级 + 2 const difficultyLevel = npc.difficultyLevel || 1 - const fleetScale = Math.min(1, difficultyLevel / 7) // 0.14 ~ 1.0 + const effectiveLevel = difficultyLevel + 2 // 实力提升两档 - // 设置舰队(基于船坞容量和难度等级) - // 总舰队数量不超过船坞容量的80% - const maxTotalFleet = Math.floor(fleetStorageCapacity * 0.8) - const baseFleetCount = Math.floor(maxTotalFleet * fleetScale) + // ========== 第一步:设置建筑等级(确保不超出空间限制)========== + // maxSpace 默认为 200,需要合理分配 - // 分配舰队比例 - planet.fleet[ShipType.EspionageProbe] = Math.max(5, Math.floor(baseFleetCount * 0.05)) - planet.fleet[ShipType.LightFighter] = Math.floor(baseFleetCount * 0.35) - planet.fleet[ShipType.HeavyFighter] = Math.floor(baseFleetCount * 0.2) - planet.fleet[ShipType.Cruiser] = Math.floor(baseFleetCount * 0.15) - planet.fleet[ShipType.Battleship] = Math.floor(baseFleetCount * 0.05) - planet.fleet[ShipType.SmallCargo] = Math.floor(baseFleetCount * 0.1) - planet.fleet[ShipType.Recycler] = Math.floor(baseFleetCount * 0.1) + // 根据effectiveLevel计算建筑等级上限 + // effectiveLevel: 3,4,5,6,7,8,9 对应不同的建筑配置 - // 设置防御设施(基于难度等级,合理范围) - const defenseScale = difficultyLevel * 5 - planet.defense[DefenseType.RocketLauncher] = Math.floor(defenseScale * 2) - planet.defense[DefenseType.LightLaser] = Math.floor(defenseScale * 1.5) - planet.defense[DefenseType.HeavyLaser] = Math.floor(defenseScale * 0.8) - planet.defense[DefenseType.GaussCannon] = Math.floor(defenseScale * 0.3) - planet.defense[DefenseType.IonCannon] = Math.floor(defenseScale * 0.3) - // 高级防御设施只有高难度NPC才有 - if (difficultyLevel >= 4) { - planet.defense[DefenseType.PlasmaTurret] = Math.floor(defenseScale * 0.1) - planet.defense[DefenseType.SmallShieldDome] = 1 + // 资源建筑(空间占用较低,优先配置) + const metalMineLevel = Math.min(25, Math.floor(10 + effectiveLevel * 2)) // 16-28级 + const crystalMineLevel = Math.min(23, Math.floor(9 + effectiveLevel * 1.8)) // 14-25级 + const deutLevel = Math.min(20, Math.floor(8 + effectiveLevel * 1.5)) // 12-21级 + const solarPlantLevel = Math.min(28, Math.floor(12 + effectiveLevel * 2)) // 18-30级 + + planet.buildings[BuildingType.MetalMine] = metalMineLevel // 空间: 16-28 + planet.buildings[BuildingType.CrystalMine] = crystalMineLevel // 空间: 14-25 + planet.buildings[BuildingType.DeuteriumSynthesizer] = deutLevel // 空间: 24-42 + planet.buildings[BuildingType.SolarPlant] = solarPlantLevel // 空间: 36-60 + + // 仓储建筑(空间占用低,每级1) + const storageLevel = Math.min(10, Math.floor(4 + effectiveLevel * 0.8)) // 6-11级 + planet.buildings[BuildingType.MetalStorage] = storageLevel // 空间: 6-11 + planet.buildings[BuildingType.CrystalStorage] = storageLevel // 空间: 6-11 + planet.buildings[BuildingType.DeuteriumTank] = storageLevel // 空间: 6-11 + + // 关键设施建筑(决定舰队仓储容量) + const shipyardLevel = Math.min(16, Math.floor(6 + effectiveLevel * 1.2)) // 10-17级 + const hangarLevel = Math.min(20, Math.floor(8 + effectiveLevel * 1.5)) // 12-21级 + const roboticsLevel = Math.min(14, Math.floor(5 + effectiveLevel)) // 8-14级 + const researchLabLevel = Math.min(14, Math.floor(5 + effectiveLevel)) // 8-14级 + + planet.buildings[BuildingType.Shipyard] = shipyardLevel // 空间: 50-85 + planet.buildings[BuildingType.Hangar] = hangarLevel // 空间: 36-63 + planet.buildings[BuildingType.RoboticsFactory] = roboticsLevel // 空间: 32-56 + planet.buildings[BuildingType.ResearchLab] = researchLabLevel // 空间: 24-42 + + // 其他设施 + planet.buildings[BuildingType.MissileSilo] = Math.min(8, effectiveLevel) // 3-9级, 空间: 18-54 + planet.buildings[BuildingType.FusionReactor] = Math.min(10, effectiveLevel) // 3-9级, 空间: 12-36 + + // 高级设施(根据effectiveLevel逐步解锁) + if (effectiveLevel >= 4) { + planet.buildings[BuildingType.NaniteFactory] = Math.min(5, effectiveLevel - 3) // 1-6级, 空间: 8-48 } - if (difficultyLevel >= 6) { - planet.defense[DefenseType.LargeShieldDome] = 1 + if (effectiveLevel >= 5) { + planet.buildings[BuildingType.DarkMatterCollector] = Math.min(4, effectiveLevel - 4) // 1-5级, 空间: 5-25 + planet.buildings[BuildingType.DarkMatterTank] = Math.min(5, effectiveLevel - 4) // 1-5级, 空间: 2-10 + planet.buildings[BuildingType.GeoResearchStation] = Math.min(3, effectiveLevel - 4) // 1-5级, 空间: 6-30 + } + if (effectiveLevel >= 7) { + planet.buildings[BuildingType.Terraformer] = Math.min(3, effectiveLevel - 6) // 1-3级, 空间: 5-15 + planet.buildings[BuildingType.DeepDrillingFacility] = Math.min(2, effectiveLevel - 6) // 1-3级, 空间: 15-45 } - // 设置资源(基于仓储建筑等级计算容量上限) - // 容量公式:10000 * 2^level + // 计算并更新maxSpace(基于地形改造器) + const terraformerLevel = planet.buildings[BuildingType.Terraformer] || 0 + planet.maxSpace = 200 + terraformerLevel * 10 // 地形改造器每级+10空间 + + // ========== 第二步:设置科技等级(基于研究实验室等级)========== + // 科技等级与研究实验室等级相关,不应超过实验室等级太多 + const baseTechLevel = Math.min(20, researchLabLevel + effectiveLevel) // 实验室+难度 + + npc.technologies[TechnologyType.EnergyTechnology] = baseTechLevel + npc.technologies[TechnologyType.ComputerTechnology] = Math.min(10, Math.floor(baseTechLevel * 0.6)) // 计算机技术上限10 + npc.technologies[TechnologyType.WeaponsTechnology] = Math.floor(baseTechLevel * 0.9) + npc.technologies[TechnologyType.ShieldingTechnology] = Math.floor(baseTechLevel * 0.85) + npc.technologies[TechnologyType.ArmourTechnology] = Math.floor(baseTechLevel * 0.85) + npc.technologies[TechnologyType.CombustionDrive] = Math.floor(baseTechLevel * 0.8) + npc.technologies[TechnologyType.ImpulseDrive] = Math.floor(baseTechLevel * 0.7) + npc.technologies[TechnologyType.EspionageTechnology] = Math.floor(baseTechLevel * 0.7) + npc.technologies[TechnologyType.LaserTechnology] = Math.floor(baseTechLevel * 0.8) + npc.technologies[TechnologyType.Astrophysics] = Math.floor(baseTechLevel * 0.5) + npc.technologies[TechnologyType.IonTechnology] = Math.min(10, effectiveLevel) + npc.technologies[TechnologyType.HyperspaceTechnology] = Math.min(10, effectiveLevel) + npc.technologies[TechnologyType.HyperspaceDrive] = Math.min(8, Math.max(0, effectiveLevel - 1)) + + if (effectiveLevel >= 4) { + npc.technologies[TechnologyType.PlasmaTechnology] = Math.min(10, effectiveLevel - 2) + } + if (effectiveLevel >= 5) { + npc.technologies[TechnologyType.DarkMatterTechnology] = Math.min(6, effectiveLevel - 4) + npc.technologies[TechnologyType.TerraformingTechnology] = Math.min(4, effectiveLevel - 4) + } + if (effectiveLevel >= 8) { + npc.technologies[TechnologyType.GravitonTechnology] = 1 + } + + // ========== 第三步:计算舰队仓储容量 ========== + // 舰队仓储 = 基础1000 + 船坞×1000 + 机库×1500 + 计算机技术×500 + const computerTechLevel = npc.technologies[TechnologyType.ComputerTechnology] || 0 + const maxFleetStorage = 1000 + shipyardLevel * 1000 + hangarLevel * 1500 + computerTechLevel * 500 + // effectiveLevel 3: 1000 + 10×1000 + 12×1500 + 6×500 = 1000+10000+18000+3000 = 32000 + // effectiveLevel 9: 1000 + 17×1000 + 21×1500 + 10×500 = 1000+17000+31500+5000 = 54500 + + // ========== 第四步:设置舰队(确保不超出仓储限制)========== + // 先清空舰队 + Object.values(ShipType).forEach(shipType => { + planet.fleet[shipType] = 0 + }) + + // 计算每种舰船的仓储占用 + const shipStorage: Record = { + [ShipType.LightFighter]: 5, + [ShipType.HeavyFighter]: 10, + [ShipType.Cruiser]: 15, + [ShipType.Battleship]: 25, + [ShipType.Battlecruiser]: 20, + [ShipType.Bomber]: 35, + [ShipType.Destroyer]: 12, + [ShipType.SmallCargo]: 10, + [ShipType.LargeCargo]: 20, + [ShipType.ColonyShip]: 40, + [ShipType.Recycler]: 30, + [ShipType.EspionageProbe]: 2, + [ShipType.SolarSatellite]: 1, + [ShipType.DarkMatterHarvester]: 50, + [ShipType.Deathstar]: 100 + } + + // 根据 effectiveLevel 计算舰队基数 + // effectiveLevel 3: fleetMultiplier = 1, effectiveLevel 9: fleetMultiplier = 4 + const fleetMultiplier = Math.pow(effectiveLevel / 3, 2) // 1, 1.78, 2.78, 4, 5.44, 7.11, 9 + + // 按优先级分配舰队(战斗舰优先) + let usedStorage = 0 + + // 辅助函数:添加舰船并追踪仓储使用 + const addShips = (shipType: ShipType, baseCount: number) => { + const count = Math.floor(baseCount * fleetMultiplier) + const availableStorage = maxFleetStorage - usedStorage + const maxAffordable = Math.floor(availableStorage / shipStorage[shipType]) + const actualCount = Math.min(count, maxAffordable) + if (actualCount > 0) { + planet.fleet[shipType] = actualCount + usedStorage += actualCount * shipStorage[shipType] + } + } + + // 主力战斗舰队 + addShips(ShipType.LightFighter, 800) // 800-7200 + addShips(ShipType.HeavyFighter, 400) // 400-3600 + addShips(ShipType.Cruiser, 200) // 200-1800 + addShips(ShipType.Battleship, 100) // 100-900 + addShips(ShipType.Battlecruiser, 80) // 80-720 + addShips(ShipType.Destroyer, 60) // 60-540 + addShips(ShipType.Bomber, 40) // 40-360 + + // 辅助舰队 + addShips(ShipType.SmallCargo, 150) // 150-1350 + addShips(ShipType.LargeCargo, 60) // 60-540 + addShips(ShipType.Recycler, 50) // 50-450 + addShips(ShipType.EspionageProbe, 100) // 100-900 + addShips(ShipType.SolarSatellite, 200) // 200-1800 + + // 特殊舰船 + if (effectiveLevel >= 4) { + addShips(ShipType.ColonyShip, 3) // 3-27 + } + if (effectiveLevel >= 5) { + addShips(ShipType.DarkMatterHarvester, 10) // 10-90 + } + if (effectiveLevel >= 8) { + addShips(ShipType.Deathstar, 2) // 2-18 + } + + // ========== 第五步:设置防御设施 ========== + // 防御不受仓储限制,使用 effectiveLevel 的平方增长 + const defenseMultiplier = effectiveLevel * effectiveLevel // 9, 16, 25, 36, 49, 64, 81 + + planet.defense[DefenseType.RocketLauncher] = defenseMultiplier * 50 // 450-4050 + planet.defense[DefenseType.LightLaser] = defenseMultiplier * 40 // 360-3240 + planet.defense[DefenseType.HeavyLaser] = defenseMultiplier * 20 // 180-1620 + planet.defense[DefenseType.GaussCannon] = defenseMultiplier * 8 // 72-648 + planet.defense[DefenseType.IonCannon] = defenseMultiplier * 8 // 72-648 + planet.defense[DefenseType.PlasmaTurret] = defenseMultiplier * 4 // 36-324 + planet.defense[DefenseType.SmallShieldDome] = 1 + planet.defense[DefenseType.LargeShieldDome] = effectiveLevel >= 4 ? 1 : 0 + planet.defense[DefenseType.AntiBallisticMissile] = defenseMultiplier * 3 // 27-243 + planet.defense[DefenseType.InterplanetaryMissile] = effectiveLevel >= 4 ? defenseMultiplier : 0 // 0-81 + planet.defense[DefenseType.PlanetaryShield] = effectiveLevel >= 6 ? 1 : 0 + + // ========== 第六步:设置资源 ========== + // 基于仓储建筑等级计算容量上限,资源填充70-100% const metalCapacity = 10000 * Math.pow(2, planet.buildings[BuildingType.MetalStorage] || 0) const crystalCapacity = 10000 * Math.pow(2, planet.buildings[BuildingType.CrystalStorage] || 0) const deuteriumCapacity = 10000 * Math.pow(2, planet.buildings[BuildingType.DeuteriumTank] || 0) const darkMatterCapacity = 1000 * Math.pow(2, planet.buildings[BuildingType.DarkMatterTank] || 0) - // 资源设置为容量的50%-80%(基于难度等级) - const resourceFillRate = 0.5 + (difficultyLevel / 7) * 0.3 + const resourceFillRate = 0.7 + (difficultyLevel / 10) * 0.3 planet.resources.metal = Math.floor(metalCapacity * resourceFillRate) planet.resources.crystal = Math.floor(crystalCapacity * resourceFillRate) planet.resources.deuterium = Math.floor(deuteriumCapacity * resourceFillRate) @@ -984,11 +1106,11 @@ export const generateNPCResourcesByDistance = ( const deuteriumLevel = planet.buildings[BuildingType.DeuteriumSynthesizer] || 0 const darkMatterLevel = planet.buildings[BuildingType.DarkMatterCollector] || 0 - // 简化的资源产量计算(每秒产量) - const metalProduction = 30 * metalMineLevel * Math.pow(1.1, metalMineLevel) * config.resourceGrowthRate - const crystalProduction = 20 * crystalMineLevel * Math.pow(1.1, crystalMineLevel) * config.resourceGrowthRate - const deuteriumProduction = 10 * deuteriumLevel * Math.pow(1.1, deuteriumLevel) * config.resourceGrowthRate - const darkMatterProduction = ((25 * darkMatterLevel * Math.pow(1.5, darkMatterLevel)) / 3600) * config.resourceGrowthRate + // 简化的资源产量计算(每秒产量) - 提升3倍让NPC更富有 + const metalProduction = 90 * metalMineLevel * Math.pow(1.1, metalMineLevel) * config.resourceGrowthRate + const crystalProduction = 60 * crystalMineLevel * Math.pow(1.1, crystalMineLevel) * config.resourceGrowthRate + const deuteriumProduction = 30 * deuteriumLevel * Math.pow(1.1, deuteriumLevel) * config.resourceGrowthRate + const darkMatterProduction = ((75 * darkMatterLevel * Math.pow(1.5, darkMatterLevel)) / 3600) * config.resourceGrowthRate // 应用游戏速度倍率到时间 const effectiveDeltaSeconds = deltaSeconds * gameSpeed diff --git a/src/logic/oreDepositLogic.ts b/src/logic/oreDepositLogic.ts index 2384ed1..550c462 100644 --- a/src/logic/oreDepositLogic.ts +++ b/src/logic/oreDepositLogic.ts @@ -7,10 +7,57 @@ import type { Planet, OreDeposits } from '@/types/game' import { ORE_DEPOSIT_CONFIG } from '@/config/gameConfig' /** - * 根据星球位置生成初始矿脉储量 + * 矿脉上限加成配置 */ -export const generateOreDeposits = (position: { galaxy: number; system: number; position: number }): OreDeposits => { - const { BASE_DEPOSITS, POSITION_MULTIPLIERS, GALAXY_MULTIPLIER, RANDOM_VARIANCE } = ORE_DEPOSIT_CONFIG +export const ORE_CAPACITY_BONUS = { + // 深层钻探设施:每级增加20%矿脉上限 + DEEP_DRILLING_BONUS_PER_LEVEL: 0.2, + // 采矿技术:每级增加15%矿脉上限(全局) + MINING_TECH_BONUS_PER_LEVEL: 0.15 +} + +/** + * 计算深层钻探设施的矿脉上限加成 + * @param deepDrillingLevel 深层钻探设施等级 + * @returns 加成倍数(1 + 等级 * 0.2) + */ +export const calculateDeepDrillingBonus = (deepDrillingLevel: number): number => { + return 1 + deepDrillingLevel * ORE_CAPACITY_BONUS.DEEP_DRILLING_BONUS_PER_LEVEL +} + +/** + * 计算采矿技术的矿脉上限加成 + * @param miningTechLevel 采矿技术等级 + * @returns 加成倍数(1 + 等级 * 0.15) + */ +export const calculateMiningTechBonus = (miningTechLevel: number): number => { + return 1 + miningTechLevel * ORE_CAPACITY_BONUS.MINING_TECH_BONUS_PER_LEVEL +} + +/** + * 根据星球位置动态计算基础储量上限(不含建筑/科技加成) + * 这样修改配置后,所有星球的上限都会自动更新 + */ +export const calculateInitialDeposits = ( + position: + | { + galaxy: number + system: number + position: number + } + | undefined +): { metal: number; crystal: number; deuterium: number } => { + const { BASE_DEPOSITS, POSITION_MULTIPLIERS, GALAXY_MULTIPLIER } = ORE_DEPOSIT_CONFIG + + // 防御性检查:如果position无效,返回默认值(位置8,银河系1) + if (!position || typeof position.position !== 'number' || typeof position.galaxy !== 'number') { + console.warn('[OreDeposits] Invalid position, using defaults:', position) + return { + metal: BASE_DEPOSITS.metal, + crystal: BASE_DEPOSITS.crystal, + deuterium: BASE_DEPOSITS.deuterium + } + } // 位置索引 (0-14) const posIndex = Math.max(0, Math.min(14, position.position - 1)) @@ -18,59 +65,87 @@ export const generateOreDeposits = (position: { galaxy: number; system: number; // 银河系加成 (银河系1为基础,每增加1个银河系增加5%) const galaxyBonus = 1 + (position.galaxy - 1) * GALAXY_MULTIPLIER - // 计算每种资源的储量 - const calculateDeposit = (baseAmount: number, positionMultiplier: number): number => { - // 基础储量 × 位置系数 × 银河系加成 - const baseDeposit = baseAmount * positionMultiplier * galaxyBonus + // 计算每种资源的储量上限(不含随机浮动,确保一致性) + const metal = Math.floor(BASE_DEPOSITS.metal * (POSITION_MULTIPLIERS.metal[posIndex] ?? 1) * galaxyBonus) + const crystal = Math.floor(BASE_DEPOSITS.crystal * (POSITION_MULTIPLIERS.crystal[posIndex] ?? 1) * galaxyBonus) + const deuterium = Math.floor(BASE_DEPOSITS.deuterium * (POSITION_MULTIPLIERS.deuterium[posIndex] ?? 1) * galaxyBonus) - // 添加随机浮动 (±RANDOM_VARIANCE) - const variance = 1 + (Math.random() * 2 - 1) * RANDOM_VARIANCE - return Math.floor(baseDeposit * variance) - } + return { metal, crystal, deuterium } +} - const metalDeposit = calculateDeposit(BASE_DEPOSITS.metal, POSITION_MULTIPLIERS.metal[posIndex] ?? 1) - const crystalDeposit = calculateDeposit(BASE_DEPOSITS.crystal, POSITION_MULTIPLIERS.crystal[posIndex] ?? 1) - const deuteriumDeposit = calculateDeposit(BASE_DEPOSITS.deuterium, POSITION_MULTIPLIERS.deuterium[posIndex] ?? 1) +/** + * 计算带有建筑和科技加成的矿脉储量上限 + * @param position 星球位置 + * @param deepDrillingLevel 深层钻探设施等级(星球级) + * @param miningTechLevel 采矿技术等级(全局) + * @returns 包含加成的储量上限 + */ +export const calculateEnhancedDeposits = ( + position: { galaxy: number; system: number; position: number } | undefined, + deepDrillingLevel: number = 0, + miningTechLevel: number = 0 +): { metal: number; crystal: number; deuterium: number; bonusMultiplier: number } => { + const baseDeposits = calculateInitialDeposits(position) + + // 计算总加成倍数 + const deepDrillingBonus = calculateDeepDrillingBonus(deepDrillingLevel) + const miningTechBonus = calculateMiningTechBonus(miningTechLevel) + const totalBonus = deepDrillingBonus * miningTechBonus return { - metal: metalDeposit, - crystal: crystalDeposit, - deuterium: deuteriumDeposit, - initialMetal: metalDeposit, - initialCrystal: crystalDeposit, - initialDeuterium: deuteriumDeposit + metal: Math.floor(baseDeposits.metal * totalBonus), + crystal: Math.floor(baseDeposits.crystal * totalBonus), + deuterium: Math.floor(baseDeposits.deuterium * totalBonus), + bonusMultiplier: totalBonus + } +} + +/** + * 根据星球位置生成初始矿脉储量 + */ +export const generateOreDeposits = (position: { galaxy: number; system: number; position: number }): OreDeposits => { + const initialDeposits = calculateInitialDeposits(position) + + return { + metal: initialDeposits.metal, + crystal: initialDeposits.crystal, + deuterium: initialDeposits.deuterium, + position: { ...position } } } /** * 计算矿脉储量对产量的效率系数 * 当储量低于衰减阈值时,产量会线性下降 - * @returns 0-1 之间的效率系数 + * 但即使耗尽也保留最低产量(MIN_PRODUCTION_EFFICIENCY) + * @returns MIN_PRODUCTION_EFFICIENCY-1 之间的效率系数 */ export const calculateDepositEfficiency = (deposits: OreDeposits | undefined, resourceType: 'metal' | 'crystal' | 'deuterium'): number => { if (!deposits) return 1 // 没有储量数据时返回满效率(向后兼容) - const { DECAY_START_THRESHOLD } = ORE_DEPOSIT_CONFIG + const { DECAY_START_THRESHOLD, MIN_PRODUCTION_EFFICIENCY } = ORE_DEPOSIT_CONFIG const currentDeposit = deposits[resourceType] - const initialDeposit = - resourceType === 'metal' ? deposits.initialMetal : resourceType === 'crystal' ? deposits.initialCrystal : deposits.initialDeuterium + const initialDeposits = calculateInitialDeposits(deposits.position) + const initialDeposit = initialDeposits[resourceType] - // 如果初始储量为0,返回0(避免除以0) - if (initialDeposit <= 0) return 0 + // 如果初始储量为0,返回最低效率(避免除以0) + if (initialDeposit <= 0) return MIN_PRODUCTION_EFFICIENCY // 计算剩余百分比 const remainingPercentage = currentDeposit / initialDeposit - // 如果已耗尽,返回0 - if (currentDeposit <= 0) return 0 - // 如果高于衰减阈值,返回满效率 if (remainingPercentage >= DECAY_START_THRESHOLD) return 1 + // 如果已耗尽,返回最低效率(保底产量) + if (currentDeposit <= 0) return MIN_PRODUCTION_EFFICIENCY + // 在衰减阈值以下,线性衰减 - // 从 DECAY_START_THRESHOLD 到 0,效率从 1 降到 0 - return remainingPercentage / DECAY_START_THRESHOLD + // 从 DECAY_START_THRESHOLD 到 0,效率从 1 降到 MIN_PRODUCTION_EFFICIENCY + const decayRange = 1 - MIN_PRODUCTION_EFFICIENCY + const decayProgress = remainingPercentage / DECAY_START_THRESHOLD + return MIN_PRODUCTION_EFFICIENCY + decayRange * decayProgress } /** @@ -94,10 +169,12 @@ export const consumeDeposit = (deposits: OreDeposits, resourceType: 'metal' | 'c */ export const getDepositPercentage = (deposits: OreDeposits | undefined, resourceType: 'metal' | 'crystal' | 'deuterium'): number => { if (!deposits) return 100 + // 如果没有position信息,返回100%(向后兼容旧数据) + if (!deposits.position) return 100 const currentDeposit = deposits[resourceType] - const initialDeposit = - resourceType === 'metal' ? deposits.initialMetal : resourceType === 'crystal' ? deposits.initialCrystal : deposits.initialDeuterium + const initialDeposits = calculateInitialDeposits(deposits.position) + const initialDeposit = initialDeposits[resourceType] if (initialDeposit <= 0) return 0 @@ -125,6 +202,7 @@ export const isDepositDepleted = (deposits: OreDeposits | undefined, resourceTyp /** * 为现有星球迁移/初始化矿脉储量 * 如果星球没有矿脉数据,则生成新的储量 + * 如果有矿脉数据但缺少position,则补充position信息 */ export const migrateOreDeposits = (planet: Planet): void => { // 月球不需要矿脉(没有采矿建筑) @@ -132,6 +210,9 @@ export const migrateOreDeposits = (planet: Planet): void => { if (!planet.oreDeposits) { planet.oreDeposits = generateOreDeposits(planet.position) + } else if (!planet.oreDeposits.position) { + // 旧数据迁移:补充position信息 + planet.oreDeposits.position = { ...planet.position } } } @@ -181,3 +262,110 @@ export const formatDepletionTime = (hours: number): string => { return `${remainingHours}h` } + +/** + * 计算地质研究站带来的恢复速率加成 + * @param geoStationLevel 地质研究站等级 + * @returns 恢复速率倍数(1 + 等级 * 0.5) + */ +export const calculateGeoStationBonus = (geoStationLevel: number): number => { + // 每级地质研究站增加50%恢复速度 + // 0级 = 1倍, 1级 = 1.5倍, 2级 = 2倍, ..., 10级 = 6倍 + return 1 + geoStationLevel * 0.5 +} + +/** + * 恢复矿脉储量 + * 矿脉会随时间缓慢恢复,模拟地质活动 + * @param deposits 矿脉储量对象 + * @param hoursElapsed 经过的小时数 + * @param geoStationLevel 地质研究站等级(可选,影响恢复速度) + */ +export const regenerateDeposits = (deposits: OreDeposits, hoursElapsed: number, geoStationLevel: number = 0): void => { + const { REGENERATION } = ORE_DEPOSIT_CONFIG + + if (!REGENERATION.ENABLED || hoursElapsed <= 0) return + + // 计算地质研究站加成 + const geoBonus = calculateGeoStationBonus(geoStationLevel) + + // 动态计算初始储量上限 + const initialDeposits = calculateInitialDeposits(deposits.position) + + // 计算恢复量(基于初始储量的百分比,乘以地质研究站加成) + 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 + + // 添加恢复量,但不超过初始储量的最大百分比 + 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) +} + +/** + * 获取矿脉恢复状态信息 + * @param deposits 矿脉储量 + * @param geoStationLevel 地质研究站等级(可选,影响恢复时间计算) + */ +export const getRegenerationInfo = ( + deposits: OreDeposits | undefined, + geoStationLevel: number = 0 +): { + metalRecovering: boolean + crystalRecovering: boolean + deuteriumRecovering: boolean + hoursToFullMetal: number + hoursToFullCrystal: number + hoursToFullDeuterium: number + geoStationBonus: number // 地质研究站加成倍数 +} => { + const geoBonus = calculateGeoStationBonus(geoStationLevel) + + if (!deposits) { + return { + metalRecovering: false, + crystalRecovering: false, + deuteriumRecovering: false, + hoursToFullMetal: 0, + hoursToFullCrystal: 0, + hoursToFullDeuterium: 0, + geoStationBonus: geoBonus + } + } + + // 动态计算初始储量上限 + const initialDeposits = calculateInitialDeposits(deposits.position) + + 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 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 + + return { + metalRecovering, + crystalRecovering, + deuteriumRecovering, + hoursToFullMetal, + hoursToFullCrystal, + hoursToFullDeuterium, + geoStationBonus: geoBonus + } +} diff --git a/src/logic/planetLogic.ts b/src/logic/planetLogic.ts index 627237e..f48f3d3 100644 --- a/src/logic/planetLogic.ts +++ b/src/logic/planetLogic.ts @@ -131,9 +131,11 @@ export const createNPCPlanet = ( isMoon: false } - // 随机初始化建筑等级 + // 初始化所有建筑等级为0 + // 实际的建筑等级会在 initializeNPCByDistance 中根据距离难度系统设置 + // 这里只做基础初始化,避免随机设置不合理的等级(如月球专属建筑) Object.values(BuildingType).forEach(building => { - npcPlanet.buildings[building] = Math.floor(Math.random() * 10) + npcPlanet.buildings[building] = 0 }) // 初始化矿脉储量 diff --git a/src/logic/researchLogic.ts b/src/logic/researchLogic.ts index 8c35a23..243435d 100644 --- a/src/logic/researchLogic.ts +++ b/src/logic/researchLogic.ts @@ -105,7 +105,8 @@ export const completeResearchQueue = ( if (now >= item.endTime) { // 研究完成 const oldLevel = technologies[item.itemType as TechnologyType] || 0 - const newLevel = item.targetLevel || 0 + // 研究完成时,等级+1(而不是直接使用targetLevel,保持一致性) + const newLevel = oldLevel + 1 technologies[item.itemType as TechnologyType] = newLevel // 计算并累积积分 diff --git a/src/logic/resourceLogic.ts b/src/logic/resourceLogic.ts index 749a9be..4aea2ee 100644 --- a/src/logic/resourceLogic.ts +++ b/src/logic/resourceLogic.ts @@ -187,6 +187,12 @@ export const updatePlanetResources = ( ): void => { const timeDiff = (now - planet.lastUpdate) / 1000 // 转换为秒 + // 时间回拨保护:如果时间差为负或为零,跳过资源更新但重置时间戳 + if (timeDiff <= 0) { + planet.lastUpdate = now + return + } + // 应用游戏速度到时间差(游戏速度影响资源产出速率) const effectiveTimeDiff = timeDiff * gameSpeed @@ -224,6 +230,12 @@ export const updatePlanetResources = ( oreDepositLogic.consumeDeposit(planet.oreDeposits, 'metal', metalProduced) oreDepositLogic.consumeDeposit(planet.oreDeposits, 'crystal', crystalProduced) oreDepositLogic.consumeDeposit(planet.oreDeposits, 'deuterium', deuteriumProduced) + + // 矿脉缓慢恢复(每次更新时恢复一小部分) + // 地质研究站等级影响恢复速度 + const hoursElapsed = effectiveTimeDiff / 3600 + const geoStationLevel = planet.buildings[BuildingType.GeoResearchStation] || 0 + oreDepositLogic.regenerateDeposits(planet.oreDeposits, hoursElapsed, geoStationLevel) } // 更新资源(转换为每秒产量,应用游戏速度) diff --git a/src/logic/waitingQueueLogic.ts b/src/logic/waitingQueueLogic.ts index 73bf64d..3e0502a 100644 --- a/src/logic/waitingQueueLogic.ts +++ b/src/logic/waitingQueueLogic.ts @@ -340,21 +340,40 @@ const tryExecuteBuildingWaitingItem = ( ): { success: boolean; queueItem?: BuildQueueItem; message?: string } => { const buildingType = item.itemType as BuildingType const currentLevel = planet.buildings[buildingType] || 0 - const targetLevel = item.targetLevel || currentLevel + 1 + const waitingTargetLevel = item.targetLevel || currentLevel + 1 // 检查目标等级是否仍然正确(可能在等待期间已经升级了) - if (currentLevel >= targetLevel) { + if (currentLevel >= waitingTargetLevel) { return { success: false, message: 'errors.levelAlreadyReached' } } - // 验证升级条件(跳过队列已满检查,因为我们已经检查过了) + // 实际执行的目标等级是当前等级+1 + const actualTargetLevel = currentLevel + 1 + + // 验证升级条件 + // 跳过以下错误,因为它们不影响下一级升级: + // - buildQueueFull: 我们已经在外层检查了 + // - buildingAlreadyInQueue: 同一建筑可能在队列中(等待前一级完成) + // - insufficientResources: 我们会在下面单独检查实际需要的资源 const validation = buildingValidation.validateBuildingUpgrade(planet, buildingType, technologies, officers) - if (!validation.valid && validation.reason !== 'errors.buildQueueFull') { + if (!validation.valid && + validation.reason !== 'errors.buildQueueFull' && + validation.reason !== 'errors.buildingAlreadyInQueue' && + validation.reason !== 'errors.insufficientResources') { return { success: false, message: validation.reason } } - // 重新检查资源(因为validateBuildingUpgrade可能因资源不足失败) - const cost = buildingLogic.calculateBuildingCost(buildingType, targetLevel) + // 检查同一建筑是否已在正式队列中(等待前一级完成) + const existingInQueue = planet.buildQueue.find( + q => (q.type === 'building' || q.type === 'demolish') && q.itemType === buildingType + ) + if (existingInQueue) { + // 同一建筑已在队列中,暂时不执行,等待完成后再处理 + return { success: false, message: 'errors.buildingAlreadyInQueue' } + } + + // 检查实际需要的资源(下一级的成本,不是等待队列项的目标等级) + const cost = buildingLogic.calculateBuildingCost(buildingType, actualTargetLevel) if (!resourceLogic.checkResourcesAvailable(planet.resources, cost)) { return { success: false, message: 'errors.insufficientResources' } } @@ -374,10 +393,10 @@ const tryExecuteDemolishWaitingItem = ( ): { success: boolean; queueItem?: BuildQueueItem; message?: string } => { const buildingType = item.itemType as BuildingType const currentLevel = planet.buildings[buildingType] || 0 - const targetLevel = item.targetLevel || currentLevel - 1 + const waitingTargetLevel = item.targetLevel || currentLevel - 1 // 检查等级是否仍然可拆除 - if (currentLevel <= 0 || currentLevel <= targetLevel) { + if (currentLevel <= 0 || currentLevel <= waitingTargetLevel) { return { success: false, message: 'errors.buildingLevelZero' } } @@ -387,6 +406,15 @@ const tryExecuteDemolishWaitingItem = ( return { success: false, message: validation.reason } } + // 检查同一建筑是否已在正式队列中(等待前一次拆除完成) + const existingInQueue = planet.buildQueue.find( + q => (q.type === 'building' || q.type === 'demolish') && q.itemType === buildingType + ) + if (existingInQueue) { + // 同一建筑已在队列中,暂时不执行,等待完成后再处理 + return { success: false, message: 'errors.buildingAlreadyInQueue' } + } + // 执行拆除 const queueItem = buildingValidation.executeBuildingDemolish(planet, buildingType, officers) return { success: true, queueItem, message: 'queue.movedToQueue' } @@ -449,21 +477,38 @@ const tryExecuteResearchWaitingItem = ( ): { success: boolean; queueItem?: BuildQueueItem; message?: string } => { const techType = item.itemType as TechnologyType const currentLevel = player.technologies[techType] || 0 - const targetLevel = item.targetLevel || currentLevel + 1 + const waitingTargetLevel = item.targetLevel || currentLevel + 1 // 检查目标等级是否仍然正确 - if (currentLevel >= targetLevel) { + if (currentLevel >= waitingTargetLevel) { return { success: false, message: 'errors.levelAlreadyReached' } } + // 实际执行的目标等级是当前等级+1 + const actualTargetLevel = currentLevel + 1 + // 验证研究条件 + // 跳过以下错误: + // - researchQueueFull: 我们已经在外层检查了 + // - technologyAlreadyInQueue: 同一科技可能在队列中(等待前一级完成) + // - insufficientResources: 我们会在下面单独检查实际需要的资源 const validation = researchValidation.validateTechnologyResearch(planet, techType, player.technologies, player.researchQueue) - if (!validation.valid && validation.reason !== 'errors.researchQueueFull') { + if (!validation.valid && + validation.reason !== 'errors.researchQueueFull' && + validation.reason !== 'errors.technologyAlreadyInQueue' && + validation.reason !== 'errors.insufficientResources') { return { success: false, message: validation.reason } } - // 重新检查资源 - const cost = researchLogic.calculateTechnologyCost(techType, targetLevel) + // 检查同一科技是否已在研究队列中(等待前一级完成) + const existingInQueue = player.researchQueue.find(q => q.itemType === techType) + if (existingInQueue) { + // 同一科技已在队列中,暂时不执行,等待完成后再处理 + return { success: false, message: 'errors.technologyAlreadyInQueue' } + } + + // 检查实际需要的资源(下一级的成本,不是等待队列项的目标等级) + const cost = researchLogic.calculateTechnologyCost(techType, actualTargetLevel) if (!resourceLogic.checkResourcesAvailable(planet.resources, cost)) { return { success: false, message: 'errors.insufficientResources' } } diff --git a/src/services/webdavService.ts b/src/services/webdavService.ts new file mode 100644 index 0000000..028a453 --- /dev/null +++ b/src/services/webdavService.ts @@ -0,0 +1,313 @@ +/** + * WebDAV 同步服务 + * 支持将存档上传到 WebDAV 服务器(如坚果云、Nextcloud、NAS等) + */ + +export interface WebDAVConfig { + serverUrl: string // WebDAV 服务器地址,如 https://dav.jianguoyun.com/dav/ + username: string // 用户名 + password: string // 密码或应用专用密码 + basePath: string // 存档存放路径,如 /ogame-saves/ +} + +export interface WebDAVFile { + name: string + path: string + size: number + lastModified: Date + isDirectory: boolean +} + +const STORAGE_KEY = 'ogame-webdav-config' + +// 获取保存的 WebDAV 配置 +export const getWebDAVConfig = (): WebDAVConfig | null => { + try { + const saved = localStorage.getItem(STORAGE_KEY) + if (saved) { + return JSON.parse(saved) + } + } catch (e) { + console.error('Failed to load WebDAV config:', e) + } + return null +} + +// 保存 WebDAV 配置 +export const saveWebDAVConfig = (config: WebDAVConfig): void => { + localStorage.setItem(STORAGE_KEY, JSON.stringify(config)) +} + +// 清除 WebDAV 配置 +export const clearWebDAVConfig = (): void => { + localStorage.removeItem(STORAGE_KEY) +} + +// 构建 Authorization header +const buildAuthHeader = (config: WebDAVConfig): string => { + const credentials = btoa(`${config.username}:${config.password}`) + return `Basic ${credentials}` +} + +// 规范化 URL 路径 +const normalizePath = (serverUrl: string, basePath: string, fileName?: string): string => { + let url = serverUrl.replace(/\/+$/, '') + let path = basePath.replace(/^\/+/, '').replace(/\/+$/, '') + + if (path) { + url = `${url}/${path}` + } + + if (fileName) { + url = `${url}/${fileName}` + } + + return url +} + +// 测试 WebDAV 连接 +export const testWebDAVConnection = async (config: WebDAVConfig): Promise<{ success: boolean; message: string }> => { + try { + const url = normalizePath(config.serverUrl, config.basePath) + + const response = await fetch(url, { + method: 'PROPFIND', + headers: { + Authorization: buildAuthHeader(config), + Depth: '0', + 'Content-Type': 'application/xml' + } + }) + + if (response.ok || response.status === 207) { + return { success: true, message: 'WebDAV 连接成功' } + } + + if (response.status === 401) { + return { success: false, message: '认证失败,请检查用户名和密码' } + } + + if (response.status === 404) { + // 尝试创建目录 + const createResult = await createDirectory(config, config.basePath) + if (createResult) { + return { success: true, message: 'WebDAV 连接成功,已创建存档目录' } + } + return { success: false, message: '目录不存在且无法创建' } + } + + return { success: false, message: `连接失败: HTTP ${response.status}` } + } catch (error) { + const message = error instanceof Error ? error.message : String(error) + // CORS 错误的处理 + if (message.includes('Failed to fetch') || message.includes('NetworkError')) { + return { + success: false, + message: '网络错误,可能是 CORS 限制。建议使用支持 CORS 的 WebDAV 服务或通过代理访问。' + } + } + return { success: false, message: `连接错误: ${message}` } + } +} + +// 创建目录 +const createDirectory = async (config: WebDAVConfig, path: string): Promise => { + try { + const url = normalizePath(config.serverUrl, path) + + const response = await fetch(url, { + method: 'MKCOL', + headers: { + Authorization: buildAuthHeader(config) + } + }) + + return response.ok || response.status === 201 + } catch (error) { + console.error('Failed to create directory:', error) + return false + } +} + +// 上传存档到 WebDAV +export const uploadToWebDAV = async ( + config: WebDAVConfig, + data: string, + fileName?: string +): Promise<{ success: boolean; message: string; fileName?: string }> => { + try { + // 生成带时间戳的文件名 + const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19) + const actualFileName = fileName || `ogame-save-${timestamp}.json` + const url = normalizePath(config.serverUrl, config.basePath, actualFileName) + + const response = await fetch(url, { + method: 'PUT', + headers: { + Authorization: buildAuthHeader(config), + 'Content-Type': 'application/json' + }, + body: data + }) + + if (response.ok || response.status === 201 || response.status === 204) { + return { success: true, message: '上传成功', fileName: actualFileName } + } + + if (response.status === 401) { + return { success: false, message: '认证失败' } + } + + if (response.status === 403) { + return { success: false, message: '没有写入权限' } + } + + if (response.status === 507) { + return { success: false, message: '存储空间不足' } + } + + return { success: false, message: `上传失败: HTTP ${response.status}` } + } catch (error) { + const message = error instanceof Error ? error.message : String(error) + return { success: false, message: `上传错误: ${message}` } + } +} + +// 解析 PROPFIND XML 响应 +const parsePropfindResponse = (xml: string, _basePath: string): WebDAVFile[] => { + const parser = new DOMParser() + const doc = parser.parseFromString(xml, 'application/xml') + const responses = doc.getElementsByTagNameNS('DAV:', 'response') + const files: WebDAVFile[] = [] + + for (let i = 0; i < responses.length; i++) { + const response = responses[i] + if (!response) continue + const href = response.getElementsByTagNameNS('DAV:', 'href')[0]?.textContent || '' + const displayName = response.getElementsByTagNameNS('DAV:', 'displayname')[0]?.textContent + const contentLength = response.getElementsByTagNameNS('DAV:', 'getcontentlength')[0]?.textContent + const lastModified = response.getElementsByTagNameNS('DAV:', 'getlastmodified')[0]?.textContent + const resourceType = response.getElementsByTagNameNS('DAV:', 'resourcetype')[0] + const isCollection = resourceType ? resourceType.getElementsByTagNameNS('DAV:', 'collection').length > 0 : false + + // 解码 URL 编码的路径 + const decodedHref = decodeURIComponent(href) + const fileName = displayName || decodedHref.split('/').filter(Boolean).pop() || '' + + // 跳过目录本身和非 JSON 文件 + if (isCollection) continue + if (!fileName.endsWith('.json')) continue + + files.push({ + name: fileName, + path: decodedHref, + size: parseInt(contentLength || '0', 10), + lastModified: lastModified ? new Date(lastModified) : new Date(), + isDirectory: false + }) + } + + // 按修改时间降序排序(最新的在前) + return files.sort((a, b) => b.lastModified.getTime() - a.lastModified.getTime()) +} + +// 列出 WebDAV 目录中的存档文件 +export const listWebDAVFiles = async (config: WebDAVConfig): Promise<{ success: boolean; files?: WebDAVFile[]; message?: string }> => { + try { + const url = normalizePath(config.serverUrl, config.basePath) + + const response = await fetch(url, { + method: 'PROPFIND', + headers: { + Authorization: buildAuthHeader(config), + Depth: '1', + 'Content-Type': 'application/xml' + } + }) + + if (!response.ok && response.status !== 207) { + if (response.status === 401) { + return { success: false, message: '认证失败' } + } + if (response.status === 404) { + return { success: false, message: '目录不存在' } + } + return { success: false, message: `获取文件列表失败: HTTP ${response.status}` } + } + + const xml = await response.text() + const files = parsePropfindResponse(xml, config.basePath) + + return { success: true, files } + } catch (error) { + const message = error instanceof Error ? error.message : String(error) + return { success: false, message: `获取文件列表错误: ${message}` } + } +} + +// 从 WebDAV 下载存档 +export const downloadFromWebDAV = async ( + config: WebDAVConfig, + fileName: string +): Promise<{ success: boolean; data?: string; message?: string }> => { + try { + const url = normalizePath(config.serverUrl, config.basePath, fileName) + + const response = await fetch(url, { + method: 'GET', + headers: { + Authorization: buildAuthHeader(config) + } + }) + + if (!response.ok) { + if (response.status === 401) { + return { success: false, message: '认证失败' } + } + if (response.status === 404) { + return { success: false, message: '文件不存在' } + } + return { success: false, message: `下载失败: HTTP ${response.status}` } + } + + const data = await response.text() + return { success: true, data } + } catch (error) { + const message = error instanceof Error ? error.message : String(error) + return { success: false, message: `下载错误: ${message}` } + } +} + +// 删除 WebDAV 文件 +export const deleteFromWebDAV = async ( + config: WebDAVConfig, + fileName: string +): Promise<{ success: boolean; message?: string }> => { + try { + const url = normalizePath(config.serverUrl, config.basePath, fileName) + + const response = await fetch(url, { + method: 'DELETE', + headers: { + Authorization: buildAuthHeader(config) + } + }) + + if (response.ok || response.status === 204) { + return { success: true } + } + + if (response.status === 401) { + return { success: false, message: '认证失败' } + } + + if (response.status === 404) { + return { success: true } // 文件不存在也视为删除成功 + } + + return { success: false, message: `删除失败: HTTP ${response.status}` } + } catch (error) { + const message = error instanceof Error ? error.message : String(error) + return { success: false, message: `删除错误: ${message}` } + } +} diff --git a/src/types/game.ts b/src/types/game.ts index 18f1986..777e4cc 100644 --- a/src/types/game.ts +++ b/src/types/game.ts @@ -19,9 +19,9 @@ export interface OreDeposits { metal: number // 金属矿脉剩余储量 crystal: number // 晶体矿脉剩余储量 deuterium: number // 重氢储量 - initialMetal: number // 初始金属储量(用于计算百分比) - initialCrystal: number // 初始晶体储量 - initialDeuterium: number // 初始重氢储量 + // 存储星球位置,用于动态计算初始储量上限 + // 这样修改配置后,所有星球的上限都会自动更新 + position: { galaxy: number; system: number; position: number } } // 建筑类型 @@ -48,7 +48,9 @@ export const BuildingType = { SensorPhalanx: 'sensorPhalanx', // 传感器阵列 JumpGate: 'jumpGate', // 跳跃门 // 特殊建筑 - PlanetDestroyerFactory: 'planetDestroyerFactory' // 行星毁灭者工厂 + PlanetDestroyerFactory: 'planetDestroyerFactory', // 行星毁灭者工厂 + GeoResearchStation: 'geoResearchStation', // 地质研究站(影响矿脉恢复速度) + DeepDrillingFacility: 'deepDrillingFacility' // 深层钻探设施(提升矿脉上限) } as const export type BuildingType = (typeof BuildingType)[keyof typeof BuildingType] @@ -95,7 +97,8 @@ export const TechnologyType = { GravitonTechnology: 'gravitonTechnology', // 引力技术 DarkMatterTechnology: 'darkMatterTechnology', // 暗物质技术 TerraformingTechnology: 'terraformingTechnology', // 地形改造技术 - PlanetDestructionTech: 'planetDestructionTech' // 行星毁灭技术 + PlanetDestructionTech: 'planetDestructionTech', // 行星毁灭技术 + MiningTechnology: 'miningTechnology' // 采矿技术(提升矿脉上限) } as const export type TechnologyType = (typeof TechnologyType)[keyof typeof TechnologyType] @@ -186,6 +189,9 @@ export interface ShipConfig { fuelConsumption: number storageUsage: number // 占用舰队仓储 requirements?: Partial> + // 快速射击:对特定目标有额外攻击次数 + // 例如 { lightFighter: 6 } 表示对轻型战斗机有6倍快速射击 + rapidFire?: Partial> } // 舰船实例 @@ -218,7 +224,8 @@ export const MissionType = { HarvestDarkMatter: 'harvestDarkMatter', // 暗物质采集 Recycle: 'recycle', // 回收残骸 Destroy: 'destroy', // 行星毁灭 - MissileAttack: 'missileAttack' // 导弹攻击 + MissileAttack: 'missileAttack', // 导弹攻击 + Station: 'station' // 驻守协防 } as const export type MissionType = (typeof MissionType)[keyof typeof MissionType] @@ -268,7 +275,8 @@ export const DiplomaticEventType = { Spy: 'spy', // 侦查 StealDebris: 'stealDebris', // 抢夺残骸 AllyAttacked: 'allyAttacked', // 盟友被攻击 - DestroyPlanet: 'destroyPlanet' // 摧毁星球 + DestroyPlanet: 'destroyPlanet', // 摧毁星球 + CampaignChoice: 'campaignChoice' // 战役对话选择 } as const export type DiplomaticEventType = (typeof DiplomaticEventType)[keyof typeof DiplomaticEventType] @@ -296,14 +304,22 @@ export interface DiplomaticReport { npcId: string // NPC ID npcName: string // NPC名称 eventType: DiplomaticEventType // 事件类型 - reputationChange: number // 好感度变化值 - newReputation: number // 新的好感度值 - oldStatus: RelationStatus // 旧的关系状态 - newStatus: RelationStatus // 新的关系状态 - message: string // 消息内容(已弃用,保留用于兼容性) + reputationChange?: number // 好感度变化值(可选,ally_defend 事件没有) + newReputation?: number // 新的好感度值(可选) + oldStatus?: RelationStatus // 旧的关系状态(可选) + newStatus?: RelationStatus // 新的关系状态(可选) + message?: string // 消息内容(已弃用,保留用于兼容性) messageKey?: string // 翻译键(如 'diplomacy.reports.youDestroyedNpcPlanet') messageParams?: Record // 翻译参数(如 { npcName: 'NPC-1', planetName: '星球 1:1:8', reputation: -80 }) read?: boolean // 已读状态 + details?: { + // 协防任务详情 + targetPlanetName?: string + targetPosition?: Position + fleetSize?: number + arrivalTime?: number + stationDuration?: number + } } // 舰队预设 @@ -526,6 +542,108 @@ export interface GiftRejectedNotification { read?: boolean } +// NPC贸易提议 +export interface TradeOffer { + id: string + npcId: string + npcName: string + timestamp: number + offeredResources: { + type: 'metal' | 'crystal' | 'deuterium' + amount: number + } + requestedResources: { + type: 'metal' | 'crystal' | 'deuterium' + amount: number + } + expiresAt: number + status: 'pending' | 'accepted' | 'declined' | 'expired' + read?: boolean +} + +// NPC情报类型 +export type IntelType = 'enemyFleet' | 'enemyResources' | 'enemyMovement' + +// NPC情报报告 +export interface IntelReport { + id: string + fromNpcId: string + fromNpcName: string + timestamp: number + targetNpcId: string + targetNpcName: string + intelType: IntelType + data: { + fleet?: Partial + resources?: Partial + movement?: { + targetPosition: { galaxy: number; system: number; position: number } + arrivalTime: number + missionType: string + } + } + read: boolean +} + +// NPC联合攻击邀请 +export interface JointAttackInvite { + id: string + fromNpcId: string + fromNpcName: string + timestamp: number + targetNpcId: string + targetNpcName: string + targetPlanetId: string + targetPosition: { galaxy: number; system: number; position: number } + npcFleetCommitment: Partial + expectedLootRatio: number // 玩家预期分成比例 (0-1) + expiresAt: number + status: 'pending' | 'accepted' | 'declined' | 'expired' + read?: boolean +} + +// NPC资源援助通知 +export interface AidNotification { + id: string + timestamp: number + npcId: string + npcName: string + aidResources: Resources + read?: boolean +} + +// NPC报复等级 +export interface RevengeLevel { + attackCount: number + fleetMultiplier: number + attackInterval: number + name: string +} + +// NPC协防通知 +export interface AllyDefenseNotification { + id: string + timestamp: number + npcId: string + npcName: string + targetPlanetId: string + targetPlanetName: string + fleetSent: Partial + read?: boolean +} + +// NPC态度变化通知 +export interface AttitudeChangeNotification { + id: string + timestamp: number + npcId: string + npcName: string + previousStatus: 'hostile' | 'neutral' | 'friendly' + newStatus: 'hostile' | 'neutral' | 'friendly' + reason: string // 变化原因 + read?: boolean +} + // 残骸场 export interface DebrisField { id: string @@ -629,6 +747,20 @@ export interface Officer { active: boolean hiredAt?: number // 招募时间 expiresAt?: number // 到期时间 + // 动态加成(与 OfficerConfig.benefits 结构相同) + bonuses?: { + buildingSpeedBonus?: number + researchSpeedBonus?: number + resourceProductionBonus?: number + darkMatterProductionBonus?: number + energyProductionBonus?: number + fleetSpeedBonus?: number + fuelConsumptionReduction?: number + defenseBonus?: number + additionalBuildQueue?: number + additionalFleetSlots?: number + storageCapacityBonus?: number + } } // 玩家 @@ -650,6 +782,13 @@ export interface Player { incomingFleetAlerts: IncomingFleetAlert[] // 即将到来的敌对舰队警告 giftNotifications: GiftNotification[] // 礼物通知(等待接受/拒绝) giftRejectedNotifications: GiftRejectedNotification[] // 礼物被拒绝通知 + // NPC增强行为通知 + tradeOffers?: TradeOffer[] // 中立NPC贸易提议 + intelReports?: IntelReport[] // 友好NPC情报报告 + jointAttackInvites?: JointAttackInvite[] // 友好NPC联合攻击邀请 + aidNotifications?: AidNotification[] // 友好NPC资源援助通知 + allyDefenseNotifications?: AllyDefenseNotification[] // 友好NPC协防通知 + attitudeChangeNotifications?: AttitudeChangeNotification[] // NPC态度变化通知 points: number // 总积分(每1000资源=1分) isGMEnabled?: boolean // GM模式开关(默认false,通过秘籍激活) lastVersionCheckTime?: number // 最后一次自动检查版本的时间戳(被动检测) @@ -999,6 +1138,9 @@ export interface DialogueChoice { textKey: string // 翻译键 nextDialogueId?: string effect?: 'reputation_up' | 'reputation_down' | 'unlock_branch' + npcId?: string // 影响的NPC ID(用于声望变化) + value?: number // 效果数值(如声望变化量,默认为10) + branchId?: string // 解锁的分支ID(用于unlock_branch效果) } // 战役任务配置 @@ -1069,6 +1211,7 @@ export interface PlayerCampaignProgress { completedQuests: string[] unlockedQuests: string[] branchChoices?: Record // 分支选择记录 + unlockedBranches?: string[] // 已解锁的分支任务ID列表 } // 任务通知 diff --git a/src/utils/battleSimulator.ts b/src/utils/battleSimulator.ts index 4d14b4a..e504e5a 100644 --- a/src/utils/battleSimulator.ts +++ b/src/utils/battleSimulator.ts @@ -10,6 +10,9 @@ interface CombatUnit { shield: number armor: number rapidFire?: Record // 快速射击 + // 战斗状态追踪(用于护盾再生和装甲损坏效果) + currentShield?: number // 当前护盾值(每轮开始恢复) + armorDamage?: number // 累积装甲损坏(降低防御效果) } // 战斗方 @@ -55,7 +58,8 @@ const prepareCombatUnits = (side: BattleSide, isDefender: boolean = false): Comb count: count, attack: applyTechBonus(config.attack, side.weaponTech), shield: applyTechBonus(config.shield, side.shieldTech), - armor: applyTechBonus(config.armor, side.armorTech) + armor: applyTechBonus(config.armor, side.armorTech), + rapidFire: config.rapidFire as Record | undefined }) } } @@ -72,6 +76,7 @@ const prepareCombatUnits = (side: BattleSide, isDefender: boolean = false): Comb attack: applyTechBonus(config.attack, side.weaponTech), shield: applyTechBonus(config.shield, side.shieldTech), armor: applyTechBonus(config.armor, side.armorTech) + // 防御设施没有rapidFire }) } } @@ -81,20 +86,57 @@ const prepareCombatUnits = (side: BattleSide, isDefender: boolean = false): Comb } /** - * 计算一个单位对另一个单位造成的伤害 + * 战斗效果配置 */ -const calculateDamage = (attacker: CombatUnit, defender: CombatUnit): { destroyed: number; damagedShield: number } => { +const COMBAT_EFFECTS = { + // 护盾弹回阈值:攻击力低于护盾此比例时大概率弹回 + SHIELD_BOUNCE_THRESHOLD: 0.01, + // 护盾弹回时仍有此概率穿透 + SHIELD_BOUNCE_PENETRATION_CHANCE: 0.01, + // 每轮护盾再生比例(恢复最大护盾的百分比) + SHIELD_REGEN_RATE: 0.7, + // 装甲损坏累积效果:每次受到未被护盾完全吸收的伤害,累积装甲损坏 + ARMOR_DAMAGE_RATE: 0.05, + // 装甲损坏上限(最多降低防御效果的百分比) + MAX_ARMOR_DAMAGE: 0.3, + // 重型武器对护盾穿透概率(攻击力>5000的武器) + HEAVY_WEAPON_SHIELD_PENETRATION: 0.15, + // 重型武器阈值 + HEAVY_WEAPON_THRESHOLD: 5000 +} + +/** + * 计算一个单位对另一个单位造成的伤害 + * 增强版:包含护盾弹回、重型武器穿透、装甲损坏累积 + */ +const calculateDamage = (attacker: CombatUnit, defender: CombatUnit): { destroyed: number; damagedShield: number; armorDamageDealt: number } => { const attackPower = attacker.attack - const defenderShield = defender.shield - const defenderArmor = defender.armor + // 使用当前护盾值(如果有),否则使用最大护盾 + const defenderCurrentShield = defender.currentShield ?? defender.shield + // 考虑装甲损坏后的有效装甲 + const armorDamageMultiplier = 1 - (defender.armorDamage ?? 0) + const effectiveArmor = defender.armor * armorDamageMultiplier let destroyed = 0 let damagedShield = 0 + let armorDamageDealt = 0 - // 如果攻击力小于护盾的1%,有很大概率无法击穿护盾 - if (attackPower < defenderShield * 0.01) { - if (Math.random() > 0.01) { - return { destroyed: 0, damagedShield: 0 } + // 重型武器穿透:高攻击力武器有概率部分无视护盾 + let shieldPenetration = 0 + if (attackPower >= COMBAT_EFFECTS.HEAVY_WEAPON_THRESHOLD) { + if (Math.random() < COMBAT_EFFECTS.HEAVY_WEAPON_SHIELD_PENETRATION) { + // 穿透30%-50%的护盾 + shieldPenetration = 0.3 + Math.random() * 0.2 + } + } + + // 计算实际护盾值(考虑穿透) + const effectiveShield = defenderCurrentShield * (1 - shieldPenetration) + + // 如果攻击力小于护盾的1%,有很大概率无法击穿护盾(护盾弹回机制) + if (attackPower < effectiveShield * COMBAT_EFFECTS.SHIELD_BOUNCE_THRESHOLD) { + if (Math.random() > COMBAT_EFFECTS.SHIELD_BOUNCE_PENETRATION_CHANCE) { + return { destroyed: 0, damagedShield: 0, armorDamageDealt: 0 } } } @@ -102,26 +144,96 @@ const calculateDamage = (attacker: CombatUnit, defender: CombatUnit): { destroye let remainingDamage = attackPower // 先消耗护盾 - if (remainingDamage > defenderShield) { - remainingDamage -= defenderShield - damagedShield = defenderShield + if (remainingDamage > effectiveShield) { + remainingDamage -= effectiveShield + damagedShield = effectiveShield + // 更新单位的当前护盾 + defender.currentShield = Math.max(0, defenderCurrentShield - damagedShield) } else { damagedShield = remainingDamage - return { destroyed: 0, damagedShield } + defender.currentShield = Math.max(0, defenderCurrentShield - damagedShield) + return { destroyed: 0, damagedShield, armorDamageDealt: 0 } + } + + // 穿透护盾后对装甲造成损坏累积 + 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 + ) } // 再消耗装甲 - if (remainingDamage > defenderArmor) { + if (remainingDamage > effectiveArmor) { destroyed = 1 } else { - // 有概率摧毁 - const destroyChance = remainingDamage / defenderArmor + // 有概率摧毁(基于伤害与有效装甲的比例) + const destroyChance = remainingDamage / effectiveArmor if (Math.random() < destroyChance) { destroyed = 1 } } - return { destroyed, damagedShield } + return { destroyed, damagedShield, armorDamageDealt } +} + +/** + * 执行单个攻击单位的射击(包含快速射击机制) + * OGame规则:如果攻击者对目标有rapidFire值N,攻击后有(N-1)/N的概率再次攻击 + * @param attacker 攻击单位 + * @param targets 目标单位数组 + * @param losses 损失记录对象 + * @param isShipLoss 是否是舰船损失(用于区分舰船和防御) + */ +const executeAttack = ( + attacker: CombatUnit, + targets: CombatUnit[], + shipLosses: Partial, + defenseLosses: Partial> +): void => { + if (targets.length === 0) return + + // 随机选择一个目标 + const targetIndex = Math.floor(Math.random() * targets.length) + const target = targets[targetIndex] + if (!target) return + + const { destroyed } = calculateDamage(attacker, target) + + if (destroyed > 0) { + target.count -= destroyed + + // 记录损失 + if (Object.values(ShipType).includes(target.type as ShipType)) { + const shipType = target.type as ShipType + shipLosses[shipType] = (shipLosses[shipType] || 0) + destroyed + } else { + const defenseType = target.type as DefenseType + defenseLosses[defenseType] = (defenseLosses[defenseType] || 0) + destroyed + } + + // 如果目标被全部摧毁,从列表中移除 + if (target.count <= 0) { + targets.splice(targetIndex, 1) + } + } + + // 快速射击机制:如果攻击者对目标类型有rapidFire,有概率继续攻击 + if (attacker.rapidFire && targets.length > 0) { + const rapidFireValue = attacker.rapidFire[target.type] + if (rapidFireValue && rapidFireValue > 1) { + // 继续攻击的概率 = (N-1)/N + const continueChance = (rapidFireValue - 1) / rapidFireValue + if (Math.random() < continueChance) { + // 递归执行下一次攻击 + executeAttack(attacker, targets, shipLosses, defenseLosses) + } + } + } } /** @@ -132,43 +244,17 @@ const executeRound = (attackerUnits: CombatUnit[], defenderUnits: CombatUnit[]): const defenderShipLosses: Partial = {} const defenderDefenseLosses: Partial> = {} - // 攻击方向防守方射击 + // 攻击方向防守方射击(带快速射击) for (const attacker of attackerUnits) { for (let i = 0; i < attacker.count; i++) { - // 随机选择一个目标 if (defenderUnits.length === 0) break - - const targetIndex = Math.floor(Math.random() * defenderUnits.length) - const target = defenderUnits[targetIndex] - - if (!target) continue - - const { destroyed } = calculateDamage(attacker, target) - - if (destroyed > 0) { - target.count -= destroyed - - // 记录损失 - if (Object.values(ShipType).includes(target.type as ShipType)) { - const shipType = target.type as ShipType - defenderShipLosses[shipType] = (defenderShipLosses[shipType] || 0) + destroyed - } else { - const defenseType = target.type as DefenseType - defenderDefenseLosses[defenseType] = (defenderDefenseLosses[defenseType] || 0) + destroyed - } - - // 如果目标被全部摧毁,从列表中移除 - if (target.count <= 0) { - defenderUnits.splice(targetIndex, 1) - } - } + executeAttack(attacker, defenderUnits, defenderShipLosses, defenderDefenseLosses) } } - // 防守方向攻击方射击 + // 防守方向攻击方射击(防御设施没有rapidFire,使用简化逻辑) for (const defender of defenderUnits) { for (let i = 0; i < defender.count; i++) { - // 随机选择一个目标 if (attackerUnits.length === 0) break const targetIndex = Math.floor(Math.random() * attackerUnits.length) @@ -246,6 +332,27 @@ export const simulateBattle = ( let attackerUnits = prepareCombatUnits(attacker, false) let defenderUnits = prepareCombatUnits(defender, true) + // 初始化战斗状态 + const initializeCombatState = (units: CombatUnit[]) => { + for (const unit of units) { + unit.currentShield = unit.shield + unit.armorDamage = 0 + } + } + initializeCombatState(attackerUnits) + initializeCombatState(defenderUnits) + + // 护盾再生函数:每轮战斗后恢复部分护盾 + const regenerateShields = (units: CombatUnit[]) => { + for (const unit of units) { + if (unit.currentShield !== undefined && unit.currentShield < unit.shield) { + // 恢复最大护盾的70%(但不超过最大值) + const regenAmount = unit.shield * COMBAT_EFFECTS.SHIELD_REGEN_RATE + unit.currentShield = Math.min(unit.shield, unit.currentShield + regenAmount) + } + } + } + const totalAttackerLosses: Partial = {} const totalDefenderShipLosses: Partial = {} const totalDefenderDefenseLosses: Partial> = {} @@ -272,6 +379,10 @@ export const simulateBattle = ( const roundResult = executeRound(attackerUnits, defenderUnits) + // 每轮结束后护盾再生 + regenerateShields(attackerUnits) + regenerateShields(defenderUnits) + // 保存当前回合详情 roundDetails.push({ round: rounds, diff --git a/src/utils/migration.ts b/src/utils/migration.ts index f2b77e1..b6053a0 100644 --- a/src/utils/migration.ts +++ b/src/utils/migration.ts @@ -109,15 +109,27 @@ export const migrateGameData = (): void => { planet.temperature = generatePlanetTemperature(planet.position.position) needsSave = true } + // 迁移矿脉数据:确保所有矿脉都有 position 字段 + if (planet.oreDeposits && !planet.isMoon) { + const deposits = planet.oreDeposits as any + // 情况1:旧格式有 initialMetal,需要删除并添加 position + if (deposits.initialMetal !== undefined) { + delete deposits.initialMetal + delete deposits.initialCrystal + delete deposits.initialDeuterium + needsSave = true + } + // 情况2:没有 position 字段,需要添加 + if (!deposits.position) { + deposits.position = { ...planet.position } + needsSave = true + } + } }) - if (needsSave) { - console.log('[Migration] Added temperature to player planets') - } } // NPC星球 if (oldData.npcs && Array.isArray(oldData.npcs)) { - let npcPlanetMigrated = false oldData.npcs.forEach((npc: NPC) => { if (npc.planets && Array.isArray(npc.planets)) { npc.planets.forEach((planet: Planet) => { @@ -125,14 +137,26 @@ export const migrateGameData = (): void => { if (!planet.isMoon && !planet.temperature) { planet.temperature = generatePlanetTemperature(planet.position.position) needsSave = true - npcPlanetMigrated = true + } + // 迁移矿脉数据:确保所有矿脉都有 position 字段 + if (planet.oreDeposits && !planet.isMoon) { + const deposits = planet.oreDeposits as any + // 情况1:旧格式有 initialMetal,需要删除 + if (deposits.initialMetal !== undefined) { + delete deposits.initialMetal + delete deposits.initialCrystal + delete deposits.initialDeuterium + needsSave = true + } + // 情况2:没有 position 字段,需要添加 + if (!deposits.position) { + deposits.position = { ...planet.position } + needsSave = true + } } }) } }) - if (npcPlanetMigrated) { - console.log('[Migration] Added temperature to NPC planets') - } } // 迁移 player.diplomaticRelations 到 npc.relations @@ -172,7 +196,6 @@ export const migrateGameData = (): void => { // 删除旧的 diplomaticRelations 字段 delete oldData.player.diplomaticRelations needsSave = true - console.log('[Migration] Migrated player.diplomaticRelations to npc.relations') } // 检查是否需要迁移地图数据 @@ -241,7 +264,6 @@ export const migrateGameData = (): void => { if (universePlanetMigrated) { localStorage.setItem(universeStorageKey, encryptData(universeData)) - console.log('[Migration] Added temperature to universe planets') } } catch (error) { console.error('[Migration] Failed to migrate universe planets temperature:', error) @@ -251,7 +273,6 @@ export const migrateGameData = (): void => { // 如果有任何数据被修改,保存gameStore数据 if (needsSave) { localStorage.setItem(storageKey, encryptData(oldData)) - console.log('[Migration] Game data migrated successfully') } } catch (error) { console.error('[Migration] Failed to migrate game data:', error) diff --git a/src/views/BuildingsView.vue b/src/views/BuildingsView.vue index 6e4c83b..d06813a 100644 --- a/src/views/BuildingsView.vue +++ b/src/views/BuildingsView.vue @@ -52,7 +52,7 @@
-

{{ t('buildingsView.upgradeCost') }}:

+

{{ t('buildingsView.upgradeCost') }}

-

{{ t('buildingsView.demolishRefund') }}:

+

{{ t('buildingsView.demolishRefund') }}

- {{ formatNumber(getDemolishRefund(buildingType).metal) }} {{ t('resources.metal') }} - {{ formatNumber(getDemolishRefund(buildingType).crystal) }} {{ t('resources.crystal') }} - {{ formatNumber(getDemolishRefund(buildingType).deuterium) }} {{ t('resources.deuterium') }} - - {{ formatNumber(getDemolishRefund(buildingType).darkMatter) }} {{ t('resources.darkMatter') }} + + + {{ formatNumber(getDemolishRefund(buildingType).metal) }} + + + + {{ formatNumber(getDemolishRefund(buildingType).crystal) }} + + + + {{ formatNumber(getDemolishRefund(buildingType).deuterium) }} + + + + {{ formatNumber(getDemolishRefund(buildingType).darkMatter) }}
@@ -221,6 +231,10 @@ const alertDialogRequirements = ref>([]) const alertDialogShowRequirements = ref(false) + // 防抖状态:防止快速点击 + const isProcessing = ref(false) + const DEBOUNCE_DELAY = 300 // 防抖延迟(毫秒) + // 拆除确认对话框状态 const demolishConfirmOpen = ref(false) const demolishConfirmMessage = ref('') @@ -276,6 +290,13 @@ // 升级建筑 const handleUpgrade = (buildingType: BuildingType, event: MouseEvent) => { + // 防抖:防止快速点击 + if (isProcessing.value) return + isProcessing.value = true + setTimeout(() => { + isProcessing.value = false + }, DEBOUNCE_DELAY) + // 检查前置条件 if (!checkUpgradeRequirements(buildingType)) { alertDialogTitle.value = t('common.requirementsNotMet') @@ -448,12 +469,11 @@ const handleDemolish = (buildingType: BuildingType) => { const refund = getDemolishRefund(buildingType) - demolishConfirmMessage.value = `${t('buildingsView.demolishRefund')}: -${t('resources.metal')}: ${formatNumber(refund.metal)} -${t('resources.crystal')}: ${formatNumber(refund.crystal)} -${t('resources.deuterium')}: ${formatNumber(refund.deuterium)}${ - refund.darkMatter > 0 ? `\n${t('resources.darkMatter')}: ${formatNumber(refund.darkMatter)}` : '' - }` + demolishConfirmMessage.value = `${t('buildingsView.demolishRefund')} +${refund.metal ? `${t('resources.metal')}: ${formatNumber(refund.metal)}` : ''} +${refund.crystal ? `${t('resources.crystal')}: ${formatNumber(refund.crystal)}` : ''} +${refund.deuterium ? `${t('resources.deuterium')}: ${formatNumber(refund.deuterium)}` : ''} +${refund.darkMatter ? `${t('resources.darkMatter')}: ${formatNumber(refund.darkMatter)}` : ''}` pendingDemolishBuilding.value = buildingType demolishConfirmOpen.value = true diff --git a/src/views/CampaignView.vue b/src/views/CampaignView.vue index e773541..3ae64bd 100644 --- a/src/views/CampaignView.vue +++ b/src/views/CampaignView.vue @@ -58,11 +58,7 @@ - + @@ -71,12 +67,7 @@
-
+
@@ -88,18 +79,11 @@ {{ t(selectedQuest.descriptionKey) }}
- - @@ -113,16 +97,12 @@ {{ t('campaign.objectives') }}
-
+
@@ -170,12 +150,7 @@ +{{ formatNumber(selectedQuest.rewards.points) }} {{ t('common.points') }} - + {{ count }}x {{ getShipName(shipType) }} @@ -185,270 +160,315 @@ - +
diff --git a/src/views/DefenseView.vue b/src/views/DefenseView.vue index 4c2faa0..9555adf 100644 --- a/src/views/DefenseView.vue +++ b/src/views/DefenseView.vue @@ -217,6 +217,10 @@ const alertDialogTitle = ref('') const alertDialogMessage = ref('') + // 防抖状态:防止快速点击 + const isProcessing = ref(false) + const DEBOUNCE_DELAY = 300 // 防抖延迟(毫秒) + // 资源类型配置(用于成本显示) const costResourceTypes = [ { key: 'metal' as const }, @@ -262,6 +266,13 @@ // 建造防御设施 const handleBuild = (defenseType: DefenseType, event: MouseEvent) => { + // 防抖:防止快速点击 + if (isProcessing.value) return + isProcessing.value = true + setTimeout(() => { + isProcessing.value = false + }, DEBOUNCE_DELAY) + const quantity = quantities.value[defenseType] if (quantity <= 0) { alertDialogTitle.value = t('defenseView.inputError') diff --git a/src/views/DiplomacyView.vue b/src/views/DiplomacyView.vue index 897f312..6663120 100644 --- a/src/views/DiplomacyView.vue +++ b/src/views/DiplomacyView.vue @@ -81,7 +81,10 @@
{{ t('diplomacy.diagnostic.aiType') }}: - + {{ diagnostic.aiType ? t(`diplomacy.diagnostic.aiTypes.${diagnostic.aiType}`) : '-' }}
@@ -178,6 +181,133 @@ + +
+ + +
+ + {{ t('npcBehavior.trade.title') }} & {{ t('npcBehavior.intel.title') }} + {{ totalInteractionCount }} +
+ +
+ + +
+

+ + {{ t('npcBehavior.trade.title') }} ({{ activeTradeOffers.length }}) +

+
+ +
+
+
{{ getNpcName(offer.npcId) }}
+
+ {{ t('npcBehavior.trade.offers') }}: + {{ formatResources(offer.offeredResources) }} +
+
+ {{ t('npcBehavior.trade.requests') }}: + {{ formatResources(offer.requestedResources) }} +
+
+ {{ t('npcBehavior.trade.expiresIn') }}: {{ formatTimeRemaining(offer.expiresAt) }} +
+
+
+ + +
+
+
+
+
+ + +
+

+ + {{ t('npcBehavior.intel.title') }} ({{ unreadIntelReports.length }}) +

+
+ +
+
+
{{ t('npcBehavior.intel.from') }}: {{ getNpcName(intel.fromNpcId) }}
+
+ {{ t('npcBehavior.intel.target') }}: {{ getNpcName(intel.targetNpcId) }} +
+
+ {{ t(`npcBehavior.intel.types.${intel.intelType}`) }} +
+
+ {{ t('npcBehavior.intel.fleetInfo') }}: {{ formatFleetInfo(intel.data.fleet) }} +
+
+ {{ t('npcBehavior.intel.resourceInfo') }}: {{ formatResources(intel.data.resources as Resources) }} +
+
+ +
+
+
+
+ + +
+

+ + {{ t('npcBehavior.jointAttack.title') }} ({{ activeJointAttackInvites.length }}) +

+
+ +
+
+
{{ t('npcBehavior.jointAttack.from') }}: {{ getNpcName(invite.fromNpcId) }}
+
+ {{ t('npcBehavior.jointAttack.target') }}: {{ getNpcName(invite.targetNpcId) }} +
+
+ {{ t('npcBehavior.jointAttack.targetPlanet') }}: [{{ invite.targetPosition.galaxy }}:{{ + invite.targetPosition.system + }}:{{ invite.targetPosition.position }}] +
+
+ {{ t('npcBehavior.jointAttack.lootShare') }}: {{ (invite.expectedLootRatio * 100).toFixed(0) }}% +
+
+ {{ t('npcBehavior.jointAttack.expiresIn') }}: {{ formatTimeRemaining(invite.expiresAt) }} +
+
+
+ + +
+
+
+
+
+ + +
+ {{ t('npcBehavior.trade.noOffers') }} +
+
+
+
+
@@ -373,11 +503,14 @@ import { useGameStore } from '@/stores/gameStore' import { useNPCStore } from '@/stores/npcStore' import { useI18n } from '@/composables/useI18n' + import { toast } from 'vue-sonner' import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs' import { Badge } from '@/components/ui/badge' import { Button } from '@/components/ui/button' + import { Card } from '@/components/ui/card' import { Dialog, DialogDescription, DialogTitle } from '@/components/ui/dialog' import ScrollableDialogContent from '@/components/ui/dialog/ScrollableDialogContent.vue' + import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/components/ui/collapsible' import { FixedPagination, Pagination, @@ -390,9 +523,22 @@ import NpcRelationCard from '@/components/npc/NpcRelationCard.vue' import NpcRelationRow from '@/components/npc/NpcRelationRow.vue' import { RelationStatus } from '@/types/game' - import type { DiplomaticRelation } from '@/types/game' + import type { DiplomaticRelation, TradeOffer, IntelReport, JointAttackInvite, Resources } from '@/types/game' import * as npcBehaviorLogic from '@/logic/npcBehaviorLogic' - import { Search, Users, Heart, Minus, Swords, Activity, LayoutGrid, List } from 'lucide-vue-next' + import { + Search, + Users, + Heart, + Minus, + Swords, + Activity, + LayoutGrid, + List, + Handshake, + ChevronDown, + ArrowLeftRight, + Eye + } from 'lucide-vue-next' import { Empty, EmptyContent, EmptyDescription } from '@/components/ui/empty' const route = useRoute() @@ -402,6 +548,9 @@ const activeTab = ref('all') + // NPC互动面板状态 + const interactionPanelOpen = ref(true) + // 视图模式: 'card' | 'list' const viewMode = ref<'card' | 'list'>('list') @@ -715,6 +864,188 @@ currentPage.value[activeTab.value] = val } }) + + // ========== NPC互动面板相关 ========== + + // 获取当前时间戳 + const now = computed(() => Date.now()) + + // 有效的贸易提议(未过期) + const activeTradeOffers = computed(() => { + return (gameStore.player.tradeOffers || []).filter(offer => offer.expiresAt > now.value) + }) + + // 未读的情报报告 + const unreadIntelReports = computed(() => { + return (gameStore.player.intelReports || []).filter(report => !report.read) + }) + + // 有效的联合攻击邀请(未过期) + const activeJointAttackInvites = computed(() => { + return (gameStore.player.jointAttackInvites || []).filter(invite => invite.expiresAt > now.value) + }) + + // 是否有NPC互动数据 + const hasNpcInteractions = computed(() => { + return ( + (gameStore.player.tradeOffers?.length || 0) > 0 || + (gameStore.player.intelReports?.length || 0) > 0 || + (gameStore.player.jointAttackInvites?.length || 0) > 0 + ) + }) + + // 是否有有效的互动内容 + const hasActiveInteractions = computed(() => { + return activeTradeOffers.value.length > 0 || unreadIntelReports.value.length > 0 || activeJointAttackInvites.value.length > 0 + }) + + // 总互动数量(用于显示徽章) + const totalInteractionCount = computed(() => { + return activeTradeOffers.value.length + unreadIntelReports.value.length + activeJointAttackInvites.value.length + }) + + // 获取NPC名称 + const getNpcName = (npcId: string): string => { + const npc = npcStore.npcs.find(n => n.id === npcId) + return npc?.name || npcId + } + + // 格式化资源显示 + // 格式化资源(兼容新旧格式) + const formatResources = (resources: Resources | { type: string; amount: number }): string => { + // 新格式:{ type: 'metal', amount: 1000 } + if ('type' in resources && 'amount' in resources) { + const typeLabels: Record = { + metal: 'M', + crystal: 'C', + deuterium: 'D' + } + return `${Math.floor(resources.amount).toLocaleString()} ${typeLabels[resources.type] || resources.type}` + } + // 旧格式:{ metal: 1000, crystal: 0, deuterium: 0 } + const parts: string[] = [] + if ((resources as Resources).metal > 0) parts.push(`${Math.floor((resources as Resources).metal).toLocaleString()} M`) + if ((resources as Resources).crystal > 0) parts.push(`${Math.floor((resources as Resources).crystal).toLocaleString()} C`) + if ((resources as Resources).deuterium > 0) parts.push(`${Math.floor((resources as Resources).deuterium).toLocaleString()} D`) + return parts.join(' / ') || '-' + } + + // 格式化舰队信息 + const formatFleetInfo = (fleetInfo: Record): string => { + const parts: string[] = [] + for (const [shipType, count] of Object.entries(fleetInfo)) { + if (count > 0) { + parts.push(`${shipType}: ${count}`) + } + } + return parts.join(', ') || '-' + } + + // 格式化剩余时间 + const formatTimeRemaining = (expiresAt: number): string => { + const remaining = expiresAt - now.value + if (remaining <= 0) return t('npcBehavior.trade.expired') + + const minutes = Math.floor(remaining / 60000) + const hours = Math.floor(minutes / 60) + const mins = minutes % 60 + + if (hours > 0) { + return `${hours}h ${mins}m` + } + return `${mins}m` + } + + // 检查是否可以接受贸易(兼容新格式 { type, amount }) + const canAcceptTrade = (offer: TradeOffer): boolean => { + const planet = gameStore.player.planets[0] + if (!planet) return false + + // 新格式:{ type: 'metal', amount: 1000 } + const requestedType = offer.requestedResources.type + const requestedAmount = offer.requestedResources.amount + return planet.resources[requestedType] >= requestedAmount + } + + // 接受贸易提议 + const acceptTradeOffer = (offer: TradeOffer) => { + if (!canAcceptTrade(offer)) { + toast.error(t('npcBehavior.trade.acceptFailed')) + return + } + + const planet = gameStore.player.planets[0] + if (!planet) return + + // 新格式:{ type: 'metal', amount: 1000 } + const requestedType = offer.requestedResources.type + const requestedAmount = offer.requestedResources.amount + const offeredType = offer.offeredResources.type + const offeredAmount = offer.offeredResources.amount + + // 扣除请求的资源 + planet.resources[requestedType] -= requestedAmount + + // 添加获得的资源 + planet.resources[offeredType] += offeredAmount + + // 移除贸易提议 + const index = gameStore.player.tradeOffers?.indexOf(offer) + if (index !== undefined && index >= 0) { + gameStore.player.tradeOffers?.splice(index, 1) + } + + // 提高与该NPC的好感度(使用 npcId 而不是 fromNpcId) + const npcRelation = npcStore.npcs.find(n => n.id === offer.npcId)?.relations?.[gameStore.player.id] + if (npcRelation) { + npcRelation.reputation += 10 + } + + toast.success(t('npcBehavior.trade.acceptSuccess')) + } + + // 拒绝贸易提议 + const declineTradeOffer = (offer: TradeOffer) => { + const index = gameStore.player.tradeOffers?.indexOf(offer) + if (index !== undefined && index >= 0) { + gameStore.player.tradeOffers?.splice(index, 1) + } + + toast.info(t('npcBehavior.trade.declined')) + } + + // 标记情报为已读 + const markIntelAsRead = (intel: IntelReport) => { + intel.read = true + } + + // 接受联合攻击邀请 + const acceptJointAttack = (invite: JointAttackInvite) => { + // 这里可以添加联合攻击的逻辑 + // 目前只是简单地移除邀请并显示提示 + const index = gameStore.player.jointAttackInvites?.indexOf(invite) + if (index !== undefined && index >= 0) { + gameStore.player.jointAttackInvites?.splice(index, 1) + } + + // 提高与该NPC的好感度(使用 npcStore) + const npcRelation = npcStore.npcs.find(n => n.id === invite.fromNpcId)?.relations?.[gameStore.player.id] + if (npcRelation) { + npcRelation.reputation += 15 + } + + toast.success(t('npcBehavior.jointAttack.acceptSuccess')) + } + + // 拒绝联合攻击邀请 + const declineJointAttack = (invite: JointAttackInvite) => { + const index = gameStore.player.jointAttackInvites?.indexOf(invite) + if (index !== undefined && index >= 0) { + gameStore.player.jointAttackInvites?.splice(index, 1) + } + + toast.info(t('npcBehavior.jointAttack.declined')) + }