From 20fb2bb6a4aa27ddd28be629ed0daac3e4a6531e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B0=A6=E5=90=9B?= <73606411+setube@users.noreply.github.com> Date: Fri, 19 Dec 2025 12:37:34 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=9E=E7=8E=B0=E8=BF=9C=E5=BE=81?= =?UTF-8?q?=E4=BB=BB=E5=8A=A1=E4=BA=8B=E4=BB=B6=E4=B8=8E=E6=8A=A5=E5=91=8A?= =?UTF-8?q?=E5=B1=95=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增远征任务事件逻辑,支持资源、暗物质、舰船发现及遭遇海盗/外星人等多种结果,并生成对应任务报告。MessagesView支持远征任务详情展示,包括获得资源、舰船及损失舰船。补充多语言包相关远征事件提示。 --- package.json | 2 +- src/App.vue | 54 ++++++ .../ui/pagination/FixedPagination.vue | 104 ++++++------ src/locales/de.ts | 17 +- src/locales/en.ts | 17 +- src/locales/ja.ts | 17 +- src/locales/ko.ts | 17 +- src/locales/ru.ts | 17 +- src/locales/zh-CN.ts | 10 +- src/locales/zh-TW.ts | 17 +- src/logic/fleetLogic.ts | 156 ++++++++++++++++++ src/types/game.ts | 6 + src/views/MessagesView.vue | 41 +++++ 13 files changed, 408 insertions(+), 67 deletions(-) diff --git a/package.json b/package.json index be571aa..a81e6f0 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ }, "private": true, "version": "1.4.0", - "buildDate": "2025/12/19 12:01:23", + "buildDate": "2025/12/19 12:29:46", "main": "dist-electron/main.js", "type": "module", "scripts": { diff --git a/src/App.vue b/src/App.vue index 21c17c9..f81b5f0 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1048,6 +1048,60 @@ delete universeStore.planets[targetKey] } } + } else if (mission.missionType === MissionType.Expedition) { + // 处理远征任务 + const expeditionResult = fleetLogic.processExpeditionArrival(mission) + + // 生成远征任务报告 + if (!gameStore.player.missionReports) { + gameStore.player.missionReports = [] + } + + // 根据事件类型生成不同的报告消息 + let reportMessage = '' + let reportDetails: Record = {} + + switch (expeditionResult.eventType) { + case 'resources': + reportMessage = t('missionReports.expeditionResources') + reportDetails = { foundResources: expeditionResult.resources } + break + case 'darkMatter': + reportMessage = t('missionReports.expeditionDarkMatter') + reportDetails = { foundResources: expeditionResult.resources } + break + case 'fleet': + reportMessage = t('missionReports.expeditionFleet') + reportDetails = { foundFleet: expeditionResult.fleet } + break + case 'pirates': + reportMessage = expeditionResult.fleetLost + ? t('missionReports.expeditionPiratesAttack') + : t('missionReports.expeditionPiratesEscaped') + reportDetails = expeditionResult.fleetLost ? { fleetLost: expeditionResult.fleetLost } : {} + break + case 'aliens': + reportMessage = expeditionResult.fleetLost + ? t('missionReports.expeditionAliensAttack') + : t('missionReports.expeditionAliensEscaped') + reportDetails = expeditionResult.fleetLost ? { fleetLost: expeditionResult.fleetLost } : {} + break + default: + reportMessage = t('missionReports.expeditionNothing') + } + + gameStore.player.missionReports.push({ + id: `mission-report-${mission.id}`, + timestamp: Date.now(), + missionType: MissionType.Expedition, + originPlanetId: mission.originPlanetId, + originPlanetName, + targetPosition: mission.targetPosition, + success: expeditionResult.eventType !== 'nothing', + message: reportMessage, + details: reportDetails, + read: false + }) } } diff --git a/src/components/ui/pagination/FixedPagination.vue b/src/components/ui/pagination/FixedPagination.vue index 5ae060d..c94e1ae 100644 --- a/src/components/ui/pagination/FixedPagination.vue +++ b/src/components/ui/pagination/FixedPagination.vue @@ -11,17 +11,15 @@ -
+
@@ -40,54 +38,54 @@ diff --git a/src/locales/de.ts b/src/locales/de.ts index 5e26c7e..2c86d38 100644 --- a/src/locales/de.ts +++ b/src/locales/de.ts @@ -68,7 +68,8 @@ export default { buildingLevelZero: 'Gebäudelevel ist 0, kann nicht abgerissen werden', researchQueueFull: 'Forschungsauftrag voll', moonExists: 'Mond existiert bereits', - insufficientDebris: 'Unzureichendes Trümmerfeld' + insufficientDebris: 'Unzureichendes Trümmerfeld', + launchFailed: 'Start fehlgeschlagen' }, nav: { overview: 'Übersicht', @@ -739,7 +740,19 @@ export default { recycleSuccess: 'Recyclingmission erfolgreich abgeschlossen', recycleFailed: 'Recyclingmission fehlgeschlagen, keine Trümmer am Zielort', destroySuccess: 'Planetenzerstörungsmission erfolgreich ausgeführt', - destroyFailed: 'Planetenzerstörungsmission fehlgeschlagen' + destroyFailed: 'Planetenzerstörungsmission fehlgeschlagen', + missileAttackSuccess: 'Raketenangriff erfolgreich', + missileAttackFailed: 'Raketenangriff fehlgeschlagen, Zielplanet existiert nicht', + missileAttackIntercepted: 'Alle Raketen abgefangen', + hits: 'Treffer', + expeditionResources: 'Die Expedition hat Ressourcen gefunden!', + expeditionDarkMatter: 'Die Expedition hat Dunkle Materie gefunden!', + expeditionFleet: 'Die Expedition hat verlassene Schiffe gefunden!', + expeditionPiratesAttack: 'Die Expedition wurde von Piraten angegriffen und verlor einige Schiffe', + expeditionPiratesEscaped: 'Die Expedition traf auf Piraten, konnte aber entkommen', + expeditionAliensAttack: 'Die Expedition wurde von Aliens angegriffen und verlor einige Schiffe', + expeditionAliensEscaped: 'Die Expedition traf auf Aliens, konnte aber entkommen', + expeditionNothing: 'Die Expedition hat nichts gefunden' }, simulatorView: { title: 'Kampfsimulator', diff --git a/src/locales/en.ts b/src/locales/en.ts index 5be867d..360f6e8 100644 --- a/src/locales/en.ts +++ b/src/locales/en.ts @@ -67,7 +67,8 @@ export default { buildingLevelZero: 'Building level is 0, cannot demolish', researchQueueFull: 'Research queue full', moonExists: 'Moon already exists', - insufficientDebris: 'Insufficient debris field' + insufficientDebris: 'Insufficient debris field', + launchFailed: 'Launch failed' }, nav: { overview: 'Overview', @@ -732,7 +733,19 @@ export default { recycleSuccess: 'Recycling mission completed successfully', recycleFailed: 'Recycling mission failed, no debris at target location', destroySuccess: 'Planet destruction mission executed successfully', - destroyFailed: 'Planet destruction mission failed' + destroyFailed: 'Planet destruction mission failed', + missileAttackSuccess: 'Missile attack successful', + missileAttackFailed: 'Missile attack failed, target planet does not exist', + missileAttackIntercepted: 'All missiles intercepted', + hits: 'hits', + expeditionResources: 'The expedition found resources!', + expeditionDarkMatter: 'The expedition found dark matter!', + expeditionFleet: 'The expedition found abandoned ships!', + expeditionPiratesAttack: 'The expedition was attacked by pirates and lost some ships', + expeditionPiratesEscaped: 'The expedition encountered pirates but escaped successfully', + expeditionAliensAttack: 'The expedition was attacked by aliens and lost some ships', + expeditionAliensEscaped: 'The expedition encountered aliens but escaped successfully', + expeditionNothing: 'The expedition found nothing' }, simulatorView: { title: 'Battle Simulator', diff --git a/src/locales/ja.ts b/src/locales/ja.ts index b5c3db6..52a9543 100644 --- a/src/locales/ja.ts +++ b/src/locales/ja.ts @@ -68,7 +68,8 @@ export default { buildingLevelZero: '建物レベルが0のため、解体できません', researchQueueFull: '研究キューが満杯です', moonExists: '月は既に存在します', - insufficientDebris: '残骸フィールドが不足しています' + insufficientDebris: '残骸フィールドが不足しています', + launchFailed: '発射に失敗しました' }, nav: { overview: '概要', @@ -732,7 +733,19 @@ export default { recycleSuccess: '回収ミッションが正常に完了しました', recycleFailed: '回収ミッションが失敗しました。目標位置にデブリがありません', destroySuccess: '惑星破壊ミッションが正常に実行されました', - destroyFailed: '惑星破壊ミッションが失敗しました' + destroyFailed: '惑星破壊ミッションが失敗しました', + missileAttackSuccess: 'ミサイル攻撃成功', + missileAttackFailed: 'ミサイル攻撃失敗、目標惑星が存在しません', + missileAttackIntercepted: '全てのミサイルが迎撃されました', + hits: '命中', + expeditionResources: '探検隊が資源を発見しました!', + expeditionDarkMatter: '探検隊がダークマターを発見しました!', + expeditionFleet: '探検隊が廃棄された艦船を発見しました!', + expeditionPiratesAttack: '探検隊が海賊に襲撃され、一部の艦船を失いました', + expeditionPiratesEscaped: '探検隊が海賊に遭遇しましたが、無事に脱出しました', + expeditionAliensAttack: '探検隊がエイリアンに襲撃され、一部の艦船を失いました', + expeditionAliensEscaped: '探検隊がエイリアンに遭遇しましたが、無事に脱出しました', + expeditionNothing: '探検隊は何も発見できませんでした' }, simulatorView: { title: '戦闘シミュレーター', diff --git a/src/locales/ko.ts b/src/locales/ko.ts index 22ae565..6240082 100644 --- a/src/locales/ko.ts +++ b/src/locales/ko.ts @@ -68,7 +68,8 @@ export default { buildingLevelZero: '건물 레벨이 0이므로 철거할 수 없습니다', researchQueueFull: '연구 대기열 가득 참', moonExists: '위성이 이미 존재합니다', - insufficientDebris: '잔해장 부족' + insufficientDebris: '잔해장 부족', + launchFailed: '발사 실패' }, nav: { overview: '개요', @@ -734,7 +735,19 @@ export default { recycleSuccess: '회수 임무가 성공적으로 완료되었습니다', recycleFailed: '회수 임무 실패, 목표 위치에 잔해가 없습니다', destroySuccess: '행성 파괴 임무가 성공적으로 실행되었습니다', - destroyFailed: '행성 파괴 임무 실패' + destroyFailed: '행성 파괴 임무 실패', + missileAttackSuccess: '미사일 공격 성공', + missileAttackFailed: '미사일 공격 실패, 목표 행성이 존재하지 않습니다', + missileAttackIntercepted: '모든 미사일이 요격되었습니다', + hits: '명중', + expeditionResources: '탐험대가 자원을 발견했습니다!', + expeditionDarkMatter: '탐험대가 암흑 물질을 발견했습니다!', + expeditionFleet: '탐험대가 버려진 함선을 발견했습니다!', + expeditionPiratesAttack: '탐험대가 해적의 공격을 받아 일부 함선을 잃었습니다', + expeditionPiratesEscaped: '탐험대가 해적과 조우했지만 무사히 탈출했습니다', + expeditionAliensAttack: '탐험대가 외계인의 공격을 받아 일부 함선을 잃었습니다', + expeditionAliensEscaped: '탐험대가 외계인과 조우했지만 무사히 탈출했습니다', + expeditionNothing: '탐험대가 아무것도 발견하지 못했습니다' }, simulatorView: { title: '전투 시뮬레이터', diff --git a/src/locales/ru.ts b/src/locales/ru.ts index 59bacde..63c46df 100644 --- a/src/locales/ru.ts +++ b/src/locales/ru.ts @@ -68,7 +68,8 @@ export default { buildingLevelZero: 'Уровень здания 0, нельзя снести', researchQueueFull: 'Очередь исследований заполнена', moonExists: 'Луна уже существует', - insufficientDebris: 'Недостаточно обломков' + insufficientDebris: 'Недостаточно обломков', + launchFailed: 'Запуск не удался' }, nav: { overview: 'Обзор', @@ -740,7 +741,19 @@ export default { recycleSuccess: 'Миссия переработки успешно завершена', recycleFailed: 'Миссия переработки провалена, нет обломков в целевой позиции', destroySuccess: 'Миссия уничтожения планеты успешно выполнена', - destroyFailed: 'Миссия уничтожения планеты провалена' + destroyFailed: 'Миссия уничтожения планеты провалена', + expeditionResources: 'Экспедиция обнаружила ресурсы!', + expeditionDarkMatter: 'Экспедиция обнаружила тёмную материю!', + expeditionFleet: 'Экспедиция обнаружила заброшенные корабли!', + expeditionPiratesAttack: 'Экспедиция попала в засаду пиратов, часть кораблей потеряна', + expeditionPiratesEscaped: 'Экспедиция столкнулась с пиратами, но успела скрыться', + expeditionAliensAttack: 'Экспедиция подверглась атаке инопланетян, часть кораблей потеряна', + expeditionAliensEscaped: 'Экспедиция столкнулась с инопланетянами, но успела скрыться', + expeditionNothing: 'Экспедиция ничего не обнаружила', + missileAttackSuccess: 'Ракетная атака успешна!', + missileAttackFailed: 'Ракетная атака провалена', + missileAttackIntercepted: 'Ракеты перехвачены', + hits: 'попаданий' }, simulatorView: { title: 'Симулятор боя', diff --git a/src/locales/zh-CN.ts b/src/locales/zh-CN.ts index f2505ff..161890d 100644 --- a/src/locales/zh-CN.ts +++ b/src/locales/zh-CN.ts @@ -729,7 +729,15 @@ export default { missileAttackSuccess: '导弹攻击成功', missileAttackFailed: '导弹攻击失败,目标星球不存在', missileAttackIntercepted: '所有导弹被拦截', - hits: '枚命中' + hits: '枚命中', + expeditionResources: '远征队发现了资源!', + expeditionDarkMatter: '远征队发现了暗物质!', + expeditionFleet: '远征队发现了废弃的舰船!', + expeditionPiratesAttack: '远征队遭遇海盗袭击,损失了部分舰船', + expeditionPiratesEscaped: '远征队遭遇海盗,但成功逃脱', + expeditionAliensAttack: '远征队遭遇外星人袭击,损失了部分舰船', + expeditionAliensEscaped: '远征队遭遇外星人,但成功逃脱', + expeditionNothing: '远征队什么也没有发现' }, simulatorView: { title: '战斗模拟器', diff --git a/src/locales/zh-TW.ts b/src/locales/zh-TW.ts index e3f5063..6e79f65 100644 --- a/src/locales/zh-TW.ts +++ b/src/locales/zh-TW.ts @@ -68,7 +68,8 @@ export default { buildingLevelZero: '建築等級為0,無法拆除', researchQueueFull: '研究隊列已滿', moonExists: '已存在月球', - insufficientDebris: '殘骸場不足' + insufficientDebris: '殘骸場不足', + launchFailed: '發射失敗' }, nav: { overview: '總覽', @@ -734,7 +735,19 @@ export default { recycleSuccess: '回收任務成功完成', recycleFailed: '回收任務失敗,目標位置沒有殘骸', destroySuccess: '行星毀滅任務成功執行', - destroyFailed: '行星毀滅任務失敗' + destroyFailed: '行星毀滅任務失敗', + expeditionResources: '探險隊發現了資源!', + expeditionDarkMatter: '探險隊發現了暗物質!', + expeditionFleet: '探險隊發現了廢棄的艦船!', + expeditionPiratesAttack: '探險隊遭遇海盜襲擊,損失了部分艦船', + expeditionPiratesEscaped: '探險隊遭遇海盜,但成功逃脫', + expeditionAliensAttack: '探險隊遭遇外星人襲擊,損失了部分艦船', + expeditionAliensEscaped: '探險隊遭遇外星人,但成功逃脫', + expeditionNothing: '探險隊什麼也沒有發現', + missileAttackSuccess: '導彈攻擊成功!', + missileAttackFailed: '導彈攻擊失敗', + missileAttackIntercepted: '導彈被攔截', + hits: '命中' }, simulatorView: { title: '戰鬥模擬器', diff --git a/src/logic/fleetLogic.ts b/src/logic/fleetLogic.ts index 8ac6697..ccad46d 100644 --- a/src/logic/fleetLogic.ts +++ b/src/logic/fleetLogic.ts @@ -639,6 +639,162 @@ export const processRecycleArrival = ( } } +/** + * 远征事件类型 + */ +export type ExpeditionEventType = 'resources' | 'darkMatter' | 'fleet' | 'nothing' | 'pirates' | 'aliens' + +/** + * 远征结果 + */ +export interface ExpeditionResult { + eventType: ExpeditionEventType + resources?: Partial + fleet?: Partial + fleetLost?: Partial + message: string +} + +/** + * 处理远征任务到达 + * 远征任务会随机触发各种事件 + */ +export const processExpeditionArrival = (mission: FleetMission): ExpeditionResult => { + // 计算舰队总货舱容量 + let totalCargoCapacity = 0 + for (const [shipType, count] of Object.entries(mission.fleet)) { + if (count > 0) { + const shipConfig = getShipCargoCapacity(shipType as ShipType) + totalCargoCapacity += shipConfig * count + } + } + + // 随机事件概率 + const random = Math.random() * 100 + let result: ExpeditionResult + + if (random < 30) { + // 30% 概率发现资源 + const resourceMultiplier = 0.1 + Math.random() * 0.3 // 10%-40% 的货舱容量 + const resourceAmount = Math.floor(totalCargoCapacity * resourceMultiplier) + const metalAmount = Math.floor(resourceAmount * 0.5) + const crystalAmount = Math.floor(resourceAmount * 0.35) + const deuteriumAmount = Math.floor(resourceAmount * 0.15) + + mission.cargo.metal += metalAmount + mission.cargo.crystal += crystalAmount + mission.cargo.deuterium += deuteriumAmount + + result = { + eventType: 'resources', + resources: { metal: metalAmount, crystal: crystalAmount, deuterium: deuteriumAmount, darkMatter: 0, energy: 0 }, + message: 'expedition.foundResources' + } + } else if (random < 40) { + // 10% 概率发现暗物质 + const darkMatterAmount = Math.floor(50 + Math.random() * 150) // 50-200 暗物质 + mission.cargo.darkMatter += darkMatterAmount + + result = { + eventType: 'darkMatter', + resources: { metal: 0, crystal: 0, deuterium: 0, darkMatter: darkMatterAmount, energy: 0 }, + message: 'expedition.foundDarkMatter' + } + } else if (random < 55) { + // 15% 概率发现废弃舰船 + const foundFleet: Partial = {} + const possibleShips: ShipType[] = [ShipType.LightFighter, ShipType.HeavyFighter, ShipType.SmallCargo, ShipType.LargeCargo] + const shipTypeIndex = Math.floor(Math.random() * possibleShips.length) + const shipType = possibleShips[shipTypeIndex] ?? ShipType.LightFighter + const count = Math.floor(1 + Math.random() * 5) // 1-5 艘 + foundFleet[shipType] = count + + // 将发现的舰船添加到任务舰队中 + mission.fleet[shipType] = (mission.fleet[shipType] || 0) + count + + result = { + eventType: 'fleet', + fleet: foundFleet, + message: 'expedition.foundFleet' + } + } else if (random < 70) { + // 15% 概率遭遇海盗(损失部分舰队) + const fleetLost: Partial = {} + let hasLoss = false + + for (const [shipType, count] of Object.entries(mission.fleet)) { + if (count > 0 && Math.random() < 0.3) { + // 30% 概率损失该类型舰船 + const lossCount = Math.max(1, Math.floor(count * 0.1)) // 损失10%,最少1艘 + const actualLoss = Math.min(lossCount, count) + fleetLost[shipType as ShipType] = actualLoss + mission.fleet[shipType as ShipType] = count - actualLoss + hasLoss = true + } + } + + result = { + eventType: 'pirates', + fleetLost: hasLoss ? fleetLost : undefined, + message: hasLoss ? 'expedition.piratesAttack' : 'expedition.piratesEscaped' + } + } else if (random < 80) { + // 10% 概率遭遇外星人(损失更多舰队) + const fleetLost: Partial = {} + let hasLoss = false + + for (const [shipType, count] of Object.entries(mission.fleet)) { + if (count > 0 && Math.random() < 0.5) { + // 50% 概率损失该类型舰船 + const lossCount = Math.max(1, Math.floor(count * 0.2)) // 损失20%,最少1艘 + const actualLoss = Math.min(lossCount, count) + fleetLost[shipType as ShipType] = actualLoss + mission.fleet[shipType as ShipType] = count - actualLoss + hasLoss = true + } + } + + result = { + eventType: 'aliens', + fleetLost: hasLoss ? fleetLost : undefined, + message: hasLoss ? 'expedition.aliensAttack' : 'expedition.aliensEscaped' + } + } else { + // 20% 概率什么都没发现 + result = { + eventType: 'nothing', + message: 'expedition.nothing' + } + } + + mission.status = 'returning' + return result +} + +/** + * 获取舰船货舱容量 + */ +const getShipCargoCapacity = (shipType: ShipType): number => { + const cargoCapacities: Record = { + [ShipType.LightFighter]: 50, + [ShipType.HeavyFighter]: 100, + [ShipType.Cruiser]: 800, + [ShipType.Battleship]: 1500, + [ShipType.Battlecruiser]: 750, + [ShipType.Bomber]: 500, + [ShipType.Destroyer]: 2000, + [ShipType.SmallCargo]: 5000, + [ShipType.LargeCargo]: 25000, + [ShipType.ColonyShip]: 7500, + [ShipType.Recycler]: 20000, + [ShipType.EspionageProbe]: 5, + [ShipType.SolarSatellite]: 0, + [ShipType.DarkMatterHarvester]: 1000, + [ShipType.Deathstar]: 1000000 + } + return cargoCapacities[shipType] || 0 +} + /** * 计算行星毁灭概率 */ diff --git a/src/types/game.ts b/src/types/game.ts index 2e8511e..7468ec5 100644 --- a/src/types/game.ts +++ b/src/types/game.ts @@ -430,6 +430,12 @@ export interface MissionReport { missileHits?: number missileIntercepted?: number defenseLosses?: Partial> + // 探险任务:发现的资源 + foundResources?: Partial + // 探险任务:发现的舰船 + foundFleet?: Partial + // 探险任务:损失的舰船 + fleetLost?: Partial } read?: boolean } diff --git a/src/views/MessagesView.vue b/src/views/MessagesView.vue index 09a6083..1b96fc5 100644 --- a/src/views/MessagesView.vue +++ b/src/views/MessagesView.vue @@ -525,6 +525,43 @@
+ + +
+

{{ t('messagesView.resources') }}:

+
+
+ +
+
+
+ + +
+

{{ t('messagesView.fleet') }}:

+
+
+ {{ t('ships.' + shipType) }}: + +{{ count }} +
+
+
+ + +
+

{{ t('messagesView.attackerLosses') }}:

+
+
+ {{ t('ships.' + shipType) }}: + -{{ count }} +
+
+
@@ -706,6 +743,10 @@ type DebrisResourceKey = 'metal' | 'crystal' const debrisResourceFields: { key: DebrisResourceKey }[] = [{ key: 'metal' }, { key: 'crystal' }] + // 全部资源字段配置(包含暗物质,用于探险任务) + type AllResourceKey = 'metal' | 'crystal' | 'deuterium' | 'darkMatter' + const allResourceFields: { key: AllResourceKey }[] = [{ key: 'metal' }, { key: 'crystal' }, { key: 'deuterium' }, { key: 'darkMatter' }] + const hasSelectedAny = computed(() => { return Object.values(clearOptions.value).some(v => v) })