mirror of
https://github.com/setube/ogame-vue-ts.git
synced 2026-05-11 23:45:11 +08:00
feat: 实现远征任务事件与报告展示
新增远征任务事件逻辑,支持资源、暗物质、舰船发现及遭遇海盗/外星人等多种结果,并生成对应任务报告。MessagesView支持远征任务详情展示,包括获得资源、舰船及损失舰船。补充多语言包相关远征事件提示。
This commit is contained in:
@@ -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": {
|
||||
|
||||
54
src/App.vue
54
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<string, unknown> = {}
|
||||
|
||||
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
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,17 +11,15 @@
|
||||
</button>
|
||||
|
||||
<!-- 页码 - 椭圆形胶囊 -->
|
||||
<div class="bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60 border rounded-full py-2 px-3 shadow-lg flex items-center gap-1">
|
||||
<div
|
||||
class="bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60 border rounded-full py-2 px-3 shadow-lg flex items-center gap-1"
|
||||
>
|
||||
<button
|
||||
v-for="pageNum in pageNumbers"
|
||||
:key="pageNum"
|
||||
@click="emit('update:page', pageNum)"
|
||||
class="h-8 min-w-8 px-2 rounded-full text-sm font-medium transition-colors"
|
||||
:class="
|
||||
pageNum === currentPage
|
||||
? 'bg-primary text-primary-foreground'
|
||||
: 'hover:bg-accent'
|
||||
"
|
||||
:class="pageNum === currentPage ? 'bg-primary text-primary-foreground' : 'hover:bg-accent'"
|
||||
>
|
||||
{{ pageNum }}
|
||||
</button>
|
||||
@@ -40,54 +38,54 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { ChevronLeft, ChevronRight } from 'lucide-vue-next'
|
||||
import { computed } from 'vue'
|
||||
import { ChevronLeft, ChevronRight } from 'lucide-vue-next'
|
||||
|
||||
interface Props {
|
||||
page: number
|
||||
totalPages: number
|
||||
maxVisible?: number
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
maxVisible: 3
|
||||
})
|
||||
|
||||
const emit = defineEmits<{
|
||||
'update:page': [page: number]
|
||||
}>()
|
||||
|
||||
const currentPage = computed(() => props.page)
|
||||
|
||||
// 生成页码列表 - 最多显示指定数量页码,不含省略号
|
||||
const pageNumbers = computed(() => {
|
||||
const pages: number[] = []
|
||||
const { totalPages, maxVisible } = props
|
||||
const current = currentPage.value
|
||||
|
||||
if (totalPages <= maxVisible) {
|
||||
for (let i = 1; i <= totalPages; i++) {
|
||||
pages.push(i)
|
||||
}
|
||||
} else {
|
||||
let start = current - Math.floor(maxVisible / 2)
|
||||
let end = current + Math.floor(maxVisible / 2)
|
||||
|
||||
// 边界调整
|
||||
if (start < 1) {
|
||||
start = 1
|
||||
end = maxVisible
|
||||
}
|
||||
if (end > totalPages) {
|
||||
end = totalPages
|
||||
start = totalPages - maxVisible + 1
|
||||
}
|
||||
|
||||
for (let i = start; i <= end; i++) {
|
||||
pages.push(i)
|
||||
}
|
||||
interface Props {
|
||||
page: number
|
||||
totalPages: number
|
||||
maxVisible?: number
|
||||
}
|
||||
|
||||
return pages
|
||||
})
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
maxVisible: 3
|
||||
})
|
||||
|
||||
const emit = defineEmits<{
|
||||
'update:page': [page: number]
|
||||
}>()
|
||||
|
||||
const currentPage = computed(() => props.page)
|
||||
|
||||
// 生成页码列表 - 最多显示指定数量页码,不含省略号
|
||||
const pageNumbers = computed(() => {
|
||||
const pages: number[] = []
|
||||
const { totalPages, maxVisible } = props
|
||||
const current = currentPage.value
|
||||
|
||||
if (totalPages <= maxVisible) {
|
||||
for (let i = 1; i <= totalPages; i++) {
|
||||
pages.push(i)
|
||||
}
|
||||
} else {
|
||||
let start = current - Math.floor(maxVisible / 2)
|
||||
let end = current + Math.floor(maxVisible / 2)
|
||||
|
||||
// 边界调整
|
||||
if (start < 1) {
|
||||
start = 1
|
||||
end = maxVisible
|
||||
}
|
||||
if (end > totalPages) {
|
||||
end = totalPages
|
||||
start = totalPages - maxVisible + 1
|
||||
}
|
||||
|
||||
for (let i = start; i <= end; i++) {
|
||||
pages.push(i)
|
||||
}
|
||||
}
|
||||
|
||||
return pages
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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: '戦闘シミュレーター',
|
||||
|
||||
@@ -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: '전투 시뮬레이터',
|
||||
|
||||
@@ -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: 'Симулятор боя',
|
||||
|
||||
@@ -729,7 +729,15 @@ export default {
|
||||
missileAttackSuccess: '导弹攻击成功',
|
||||
missileAttackFailed: '导弹攻击失败,目标星球不存在',
|
||||
missileAttackIntercepted: '所有导弹被拦截',
|
||||
hits: '枚命中'
|
||||
hits: '枚命中',
|
||||
expeditionResources: '远征队发现了资源!',
|
||||
expeditionDarkMatter: '远征队发现了暗物质!',
|
||||
expeditionFleet: '远征队发现了废弃的舰船!',
|
||||
expeditionPiratesAttack: '远征队遭遇海盗袭击,损失了部分舰船',
|
||||
expeditionPiratesEscaped: '远征队遭遇海盗,但成功逃脱',
|
||||
expeditionAliensAttack: '远征队遭遇外星人袭击,损失了部分舰船',
|
||||
expeditionAliensEscaped: '远征队遭遇外星人,但成功逃脱',
|
||||
expeditionNothing: '远征队什么也没有发现'
|
||||
},
|
||||
simulatorView: {
|
||||
title: '战斗模拟器',
|
||||
|
||||
@@ -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: '戰鬥模擬器',
|
||||
|
||||
@@ -639,6 +639,162 @@ export const processRecycleArrival = (
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 远征事件类型
|
||||
*/
|
||||
export type ExpeditionEventType = 'resources' | 'darkMatter' | 'fleet' | 'nothing' | 'pirates' | 'aliens'
|
||||
|
||||
/**
|
||||
* 远征结果
|
||||
*/
|
||||
export interface ExpeditionResult {
|
||||
eventType: ExpeditionEventType
|
||||
resources?: Partial<Resources>
|
||||
fleet?: Partial<Fleet>
|
||||
fleetLost?: Partial<Fleet>
|
||||
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<Fleet> = {}
|
||||
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<Fleet> = {}
|
||||
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<Fleet> = {}
|
||||
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, number> = {
|
||||
[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
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算行星毁灭概率
|
||||
*/
|
||||
|
||||
@@ -430,6 +430,12 @@ export interface MissionReport {
|
||||
missileHits?: number
|
||||
missileIntercepted?: number
|
||||
defenseLosses?: Partial<Record<DefenseType, number>>
|
||||
// 探险任务:发现的资源
|
||||
foundResources?: Partial<Resources>
|
||||
// 探险任务:发现的舰船
|
||||
foundFleet?: Partial<Fleet>
|
||||
// 探险任务:损失的舰船
|
||||
fleetLost?: Partial<Fleet>
|
||||
}
|
||||
read?: boolean
|
||||
}
|
||||
|
||||
@@ -525,6 +525,43 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 探险任务详情 - 发现资源 -->
|
||||
<div v-if="selectedMissionReport.details?.foundResources" class="mt-3 space-y-1">
|
||||
<p class="text-xs font-semibold text-muted-foreground">{{ t('messagesView.resources') }}:</p>
|
||||
<div class="grid grid-cols-2 gap-2 text-sm p-2 bg-green-50 dark:bg-green-950/30 rounded">
|
||||
<div v-for="res in allResourceFields" :key="res.key">
|
||||
<template v-if="(selectedMissionReport.details?.foundResources?.[res.key] ?? 0) > 0">
|
||||
<span class="text-muted-foreground">{{ t(`resources.${res.key}`) }}:</span>
|
||||
<span class="ml-1 font-medium text-green-600 dark:text-green-400">
|
||||
+{{ (selectedMissionReport.details?.foundResources?.[res.key] ?? 0).toLocaleString() }}
|
||||
</span>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 探险任务详情 - 发现舰船 -->
|
||||
<div v-if="selectedMissionReport.details?.foundFleet" class="mt-3 space-y-1">
|
||||
<p class="text-xs font-semibold text-muted-foreground">{{ t('messagesView.fleet') }}:</p>
|
||||
<div class="grid grid-cols-2 gap-2 text-sm p-2 bg-blue-50 dark:bg-blue-950/30 rounded">
|
||||
<div v-for="(count, shipType) in selectedMissionReport.details.foundFleet" :key="shipType">
|
||||
<span class="text-muted-foreground">{{ t('ships.' + shipType) }}:</span>
|
||||
<span class="ml-1 font-medium text-blue-600 dark:text-blue-400">+{{ count }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 探险任务详情 - 损失舰船 -->
|
||||
<div v-if="selectedMissionReport.details?.fleetLost" class="mt-3 space-y-1">
|
||||
<p class="text-xs font-semibold text-muted-foreground">{{ t('messagesView.attackerLosses') }}:</p>
|
||||
<div class="grid grid-cols-2 gap-2 text-sm p-2 bg-red-50 dark:bg-red-950/30 rounded">
|
||||
<div v-for="(count, shipType) in selectedMissionReport.details.fleetLost" :key="shipType">
|
||||
<span class="text-muted-foreground">{{ t('ships.' + shipType) }}:</span>
|
||||
<span class="ml-1 font-medium text-red-600 dark:text-red-400">-{{ count }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -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)
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user