mirror of
https://github.com/setube/ogame-vue-ts.git
synced 2026-05-12 16:05:12 +08:00
新增 BattleReportDialog、SpyReportDialog、NumberWithTooltip 等组件,完善舰队模拟器功能。重构并引入 Sheet、Sidebar、Tooltip、Skeleton 等 UI 组件,优化界面结构。实现 battle.worker 支持战斗计算,增加 universeStore、fleetStorageLogic 等核心逻辑,完善多语言与类型定义。
392 lines
13 KiB
TypeScript
392 lines
13 KiB
TypeScript
import type { Planet, Resources } from '@/types/game'
|
||
import { BuildingType } from '@/types/game'
|
||
|
||
/**
|
||
* 计算电量产出
|
||
*/
|
||
export const calculateEnergyProduction = (
|
||
planet: Planet,
|
||
bonuses: {
|
||
energyProductionBonus: number
|
||
}
|
||
): number => {
|
||
const solarPlantLevel = planet.buildings[BuildingType.SolarPlant] || 0
|
||
const energyBonus = 1 + (bonuses.energyProductionBonus || 0) / 100
|
||
|
||
// 太阳能电站每级产出:50 * 1.1^等级
|
||
return solarPlantLevel * 50 * Math.pow(1.1, solarPlantLevel) * energyBonus
|
||
}
|
||
|
||
/**
|
||
* 计算电量消耗
|
||
*/
|
||
export const calculateEnergyConsumption = (planet: Planet): number => {
|
||
const metalMineLevel = planet.buildings[BuildingType.MetalMine] || 0
|
||
const crystalMineLevel = planet.buildings[BuildingType.CrystalMine] || 0
|
||
const deuteriumSynthesizerLevel = planet.buildings[BuildingType.DeuteriumSynthesizer] || 0
|
||
|
||
// 矿场每级消耗:10 * 1.1^等级
|
||
const metalConsumption = metalMineLevel * 10 * Math.pow(1.1, metalMineLevel)
|
||
const crystalConsumption = crystalMineLevel * 10 * Math.pow(1.1, crystalMineLevel)
|
||
const deuteriumConsumption = deuteriumSynthesizerLevel * 15 * Math.pow(1.1, deuteriumSynthesizerLevel)
|
||
|
||
return metalConsumption + crystalConsumption + deuteriumConsumption
|
||
}
|
||
|
||
/**
|
||
* 计算资源产量(每小时)
|
||
*/
|
||
export const calculateResourceProduction = (
|
||
planet: Planet,
|
||
bonuses: {
|
||
resourceProductionBonus: number
|
||
darkMatterProductionBonus: number
|
||
energyProductionBonus: number
|
||
}
|
||
): Resources => {
|
||
const metalMineLevel = planet.buildings[BuildingType.MetalMine] || 0
|
||
const crystalMineLevel = planet.buildings[BuildingType.CrystalMine] || 0
|
||
const deuteriumSynthesizerLevel = planet.buildings[BuildingType.DeuteriumSynthesizer] || 0
|
||
const darkMatterCollectorLevel = planet.buildings[BuildingType.DarkMatterCollector] || 0
|
||
|
||
const resourceBonus = 1 + (bonuses.resourceProductionBonus || 0) / 100
|
||
const darkMatterBonus = 1 + (bonuses.darkMatterProductionBonus || 0) / 100
|
||
|
||
// 计算能量产出(每小时)
|
||
const energyProduction = calculateEnergyProduction(planet, { energyProductionBonus: bonuses.energyProductionBonus })
|
||
|
||
// 检查当前能量是否充足
|
||
// 如果当前能量 <= 0,矿场停止生产
|
||
const hasEnergy = planet.resources.energy > 0
|
||
const productionEfficiency = hasEnergy ? 1 : 0
|
||
|
||
return {
|
||
metal: metalMineLevel * 1500 * Math.pow(1.5, metalMineLevel) * resourceBonus * productionEfficiency,
|
||
crystal: crystalMineLevel * 1000 * Math.pow(1.5, crystalMineLevel) * resourceBonus * productionEfficiency,
|
||
deuterium: deuteriumSynthesizerLevel * 500 * Math.pow(1.5, deuteriumSynthesizerLevel) * resourceBonus * productionEfficiency,
|
||
darkMatter: darkMatterCollectorLevel * 25 * Math.pow(1.5, darkMatterCollectorLevel) * darkMatterBonus,
|
||
energy: energyProduction
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 计算资源容量
|
||
*/
|
||
export const calculateResourceCapacity = (planet: Planet, storageCapacityBonus: number): Resources => {
|
||
const metalStorageLevel = planet.buildings[BuildingType.MetalStorage] || 0
|
||
const crystalStorageLevel = planet.buildings[BuildingType.CrystalStorage] || 0
|
||
const deuteriumTankLevel = planet.buildings[BuildingType.DeuteriumTank] || 0
|
||
const darkMatterCollectorLevel = planet.buildings[BuildingType.DarkMatterCollector] || 0
|
||
const solarPlantLevel = planet.buildings[BuildingType.SolarPlant] || 0
|
||
|
||
const bonus = 1 + (storageCapacityBonus || 0) / 100
|
||
|
||
const baseCapacity = 10000
|
||
return {
|
||
metal: baseCapacity * Math.pow(2, metalStorageLevel) * bonus,
|
||
crystal: baseCapacity * Math.pow(2, crystalStorageLevel) * bonus,
|
||
deuterium: baseCapacity * Math.pow(2, deuteriumTankLevel) * bonus,
|
||
darkMatter: 1000 + darkMatterCollectorLevel * 100, // 暗物质容量较小
|
||
energy: 1000 + solarPlantLevel * 500 // 能量容量基于太阳能电站等级
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 更新星球资源
|
||
*/
|
||
export const updatePlanetResources = (
|
||
planet: Planet,
|
||
now: number,
|
||
bonuses: {
|
||
resourceProductionBonus: number
|
||
darkMatterProductionBonus: number
|
||
energyProductionBonus: number
|
||
storageCapacityBonus: number
|
||
}
|
||
): void => {
|
||
const timeDiff = (now - planet.lastUpdate) / 1000 // 转换为秒
|
||
|
||
// 计算能量消耗(每小时)
|
||
const energyConsumption = calculateEnergyConsumption(planet)
|
||
|
||
// 先增加能量产出
|
||
const energyProduction = calculateEnergyProduction(planet, { energyProductionBonus: bonuses.energyProductionBonus })
|
||
planet.resources.energy += (energyProduction * timeDiff) / 3600
|
||
|
||
// 限制能量上限
|
||
const capacity = calculateResourceCapacity(planet, bonuses.storageCapacityBonus)
|
||
planet.resources.energy = Math.min(planet.resources.energy, capacity.energy)
|
||
|
||
// 扣除能量消耗
|
||
planet.resources.energy -= (energyConsumption * timeDiff) / 3600
|
||
|
||
// 能量不能为负数,最低为0
|
||
planet.resources.energy = Math.max(0, planet.resources.energy)
|
||
|
||
// 计算资源产量(会检查能量是否充足)
|
||
const production = calculateResourceProduction(planet, {
|
||
resourceProductionBonus: bonuses.resourceProductionBonus,
|
||
darkMatterProductionBonus: bonuses.darkMatterProductionBonus,
|
||
energyProductionBonus: bonuses.energyProductionBonus
|
||
})
|
||
|
||
// 更新资源(转换为每秒产量)
|
||
planet.resources.metal += (production.metal * timeDiff) / 3600
|
||
planet.resources.crystal += (production.crystal * timeDiff) / 3600
|
||
planet.resources.deuterium += (production.deuterium * timeDiff) / 3600
|
||
planet.resources.darkMatter += (production.darkMatter * timeDiff) / 3600
|
||
|
||
// 限制资源上限
|
||
planet.resources.metal = Math.min(planet.resources.metal, capacity.metal)
|
||
planet.resources.crystal = Math.min(planet.resources.crystal, capacity.crystal)
|
||
planet.resources.deuterium = Math.min(planet.resources.deuterium, capacity.deuterium)
|
||
planet.resources.darkMatter = Math.min(planet.resources.darkMatter, capacity.darkMatter)
|
||
|
||
planet.lastUpdate = now
|
||
}
|
||
|
||
/**
|
||
* 检查资源是否足够
|
||
*/
|
||
export const checkResourcesAvailable = (currentResources: Resources, cost: Resources): boolean => {
|
||
return (
|
||
currentResources.metal >= cost.metal &&
|
||
currentResources.crystal >= cost.crystal &&
|
||
currentResources.deuterium >= cost.deuterium &&
|
||
currentResources.darkMatter >= cost.darkMatter
|
||
)
|
||
}
|
||
|
||
/**
|
||
* 扣除资源
|
||
*/
|
||
export const deductResources = (currentResources: Resources, cost: Resources): void => {
|
||
currentResources.metal -= cost.metal
|
||
currentResources.crystal -= cost.crystal
|
||
currentResources.deuterium -= cost.deuterium
|
||
currentResources.darkMatter -= cost.darkMatter
|
||
}
|
||
|
||
/**
|
||
* 添加资源
|
||
*/
|
||
export const addResources = (currentResources: Resources, amount: Resources): void => {
|
||
currentResources.metal += amount.metal
|
||
currentResources.crystal += amount.crystal
|
||
currentResources.deuterium += amount.deuterium
|
||
currentResources.darkMatter += amount.darkMatter
|
||
}
|
||
|
||
/**
|
||
* 资源产量详细信息(用于UI展示)
|
||
*/
|
||
export interface ProductionBreakdown {
|
||
metal: ProductionDetail
|
||
crystal: ProductionDetail
|
||
deuterium: ProductionDetail
|
||
darkMatter: ProductionDetail
|
||
energy: ProductionDetail
|
||
}
|
||
|
||
export interface ProductionDetail {
|
||
baseProduction: number // 建筑基础产量
|
||
buildingLevel: number // 建筑等级
|
||
buildingName: string // 建筑名称(用于显示)
|
||
bonuses: ProductionBonus[] // 加成列表
|
||
finalProduction: number // 最终产量
|
||
}
|
||
|
||
export interface ProductionBonus {
|
||
name: string // 加成名称
|
||
value: number // 加成百分比或固定值
|
||
type: 'percentage' | 'multiplier' // 百分比加成或倍率
|
||
}
|
||
|
||
/**
|
||
* 能量消耗详细信息
|
||
*/
|
||
export interface ConsumptionBreakdown {
|
||
metalMine: ConsumptionDetail
|
||
crystalMine: ConsumptionDetail
|
||
deuteriumSynthesizer: ConsumptionDetail
|
||
total: number
|
||
}
|
||
|
||
export interface ConsumptionDetail {
|
||
buildingLevel: number
|
||
buildingName: string
|
||
consumption: number
|
||
}
|
||
|
||
/**
|
||
* 计算资源产量详细breakdown
|
||
*/
|
||
export const calculateProductionBreakdown = (
|
||
planet: Planet,
|
||
bonuses: {
|
||
resourceProductionBonus: number
|
||
darkMatterProductionBonus: number
|
||
energyProductionBonus: number
|
||
}
|
||
): ProductionBreakdown => {
|
||
const metalMineLevel = planet.buildings[BuildingType.MetalMine] || 0
|
||
const crystalMineLevel = planet.buildings[BuildingType.CrystalMine] || 0
|
||
const deuteriumSynthesizerLevel = planet.buildings[BuildingType.DeuteriumSynthesizer] || 0
|
||
const darkMatterCollectorLevel = planet.buildings[BuildingType.DarkMatterCollector] || 0
|
||
const solarPlantLevel = planet.buildings[BuildingType.SolarPlant] || 0
|
||
|
||
const hasEnergy = planet.resources.energy > 0
|
||
const productionEfficiency = hasEnergy ? 1 : 0
|
||
|
||
// 金属矿产量
|
||
const metalBase = metalMineLevel * 1500 * Math.pow(1.5, metalMineLevel)
|
||
const metalBonuses: ProductionBonus[] = []
|
||
if (bonuses.resourceProductionBonus > 0) {
|
||
metalBonuses.push({
|
||
name: 'officers.resourceBonus',
|
||
value: bonuses.resourceProductionBonus,
|
||
type: 'percentage'
|
||
})
|
||
}
|
||
if (!hasEnergy) {
|
||
metalBonuses.push({
|
||
name: 'resources.noEnergy',
|
||
value: -100,
|
||
type: 'percentage'
|
||
})
|
||
}
|
||
const metalFinal = metalBase * (1 + bonuses.resourceProductionBonus / 100) * productionEfficiency
|
||
|
||
// 晶体矿产量
|
||
const crystalBase = crystalMineLevel * 1000 * Math.pow(1.5, crystalMineLevel)
|
||
const crystalBonuses: ProductionBonus[] = []
|
||
if (bonuses.resourceProductionBonus > 0) {
|
||
crystalBonuses.push({
|
||
name: 'officers.resourceBonus',
|
||
value: bonuses.resourceProductionBonus,
|
||
type: 'percentage'
|
||
})
|
||
}
|
||
if (!hasEnergy) {
|
||
crystalBonuses.push({
|
||
name: 'resources.noEnergy',
|
||
value: -100,
|
||
type: 'percentage'
|
||
})
|
||
}
|
||
const crystalFinal = crystalBase * (1 + bonuses.resourceProductionBonus / 100) * productionEfficiency
|
||
|
||
// 重氢合成器产量
|
||
const deuteriumBase = deuteriumSynthesizerLevel * 500 * Math.pow(1.5, deuteriumSynthesizerLevel)
|
||
const deuteriumBonuses: ProductionBonus[] = []
|
||
if (bonuses.resourceProductionBonus > 0) {
|
||
deuteriumBonuses.push({
|
||
name: 'officers.resourceBonus',
|
||
value: bonuses.resourceProductionBonus,
|
||
type: 'percentage'
|
||
})
|
||
}
|
||
if (!hasEnergy) {
|
||
deuteriumBonuses.push({
|
||
name: 'resources.noEnergy',
|
||
value: -100,
|
||
type: 'percentage'
|
||
})
|
||
}
|
||
const deuteriumFinal = deuteriumBase * (1 + bonuses.resourceProductionBonus / 100) * productionEfficiency
|
||
|
||
// 暗物质收集器产量
|
||
const darkMatterBase = darkMatterCollectorLevel * 25 * Math.pow(1.5, darkMatterCollectorLevel)
|
||
const darkMatterBonuses: ProductionBonus[] = []
|
||
if (bonuses.darkMatterProductionBonus > 0) {
|
||
darkMatterBonuses.push({
|
||
name: 'officers.darkMatterBonus',
|
||
value: bonuses.darkMatterProductionBonus,
|
||
type: 'percentage'
|
||
})
|
||
}
|
||
const darkMatterFinal = darkMatterBase * (1 + bonuses.darkMatterProductionBonus / 100)
|
||
|
||
// 太阳能电站产量
|
||
const energyBase = solarPlantLevel * 50 * Math.pow(1.1, solarPlantLevel)
|
||
const energyBonuses: ProductionBonus[] = []
|
||
if (bonuses.energyProductionBonus > 0) {
|
||
energyBonuses.push({
|
||
name: 'officers.energyBonus',
|
||
value: bonuses.energyProductionBonus,
|
||
type: 'percentage'
|
||
})
|
||
}
|
||
const energyFinal = energyBase * (1 + bonuses.energyProductionBonus / 100)
|
||
|
||
return {
|
||
metal: {
|
||
baseProduction: metalBase,
|
||
buildingLevel: metalMineLevel,
|
||
buildingName: 'buildings.metalMine',
|
||
bonuses: metalBonuses,
|
||
finalProduction: metalFinal
|
||
},
|
||
crystal: {
|
||
baseProduction: crystalBase,
|
||
buildingLevel: crystalMineLevel,
|
||
buildingName: 'buildings.crystalMine',
|
||
bonuses: crystalBonuses,
|
||
finalProduction: crystalFinal
|
||
},
|
||
deuterium: {
|
||
baseProduction: deuteriumBase,
|
||
buildingLevel: deuteriumSynthesizerLevel,
|
||
buildingName: 'buildings.deuteriumSynthesizer',
|
||
bonuses: deuteriumBonuses,
|
||
finalProduction: deuteriumFinal
|
||
},
|
||
darkMatter: {
|
||
baseProduction: darkMatterBase,
|
||
buildingLevel: darkMatterCollectorLevel,
|
||
buildingName: 'buildings.darkMatterCollector',
|
||
bonuses: darkMatterBonuses,
|
||
finalProduction: darkMatterFinal
|
||
},
|
||
energy: {
|
||
baseProduction: energyBase,
|
||
buildingLevel: solarPlantLevel,
|
||
buildingName: 'buildings.solarPlant',
|
||
bonuses: energyBonuses,
|
||
finalProduction: energyFinal
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 计算能量消耗详细breakdown
|
||
*/
|
||
export const calculateConsumptionBreakdown = (planet: Planet): ConsumptionBreakdown => {
|
||
const metalMineLevel = planet.buildings[BuildingType.MetalMine] || 0
|
||
const crystalMineLevel = planet.buildings[BuildingType.CrystalMine] || 0
|
||
const deuteriumSynthesizerLevel = planet.buildings[BuildingType.DeuteriumSynthesizer] || 0
|
||
|
||
const metalConsumption = metalMineLevel * 10 * Math.pow(1.1, metalMineLevel)
|
||
const crystalConsumption = crystalMineLevel * 10 * Math.pow(1.1, crystalMineLevel)
|
||
const deuteriumConsumption = deuteriumSynthesizerLevel * 15 * Math.pow(1.1, deuteriumSynthesizerLevel)
|
||
|
||
return {
|
||
metalMine: {
|
||
buildingLevel: metalMineLevel,
|
||
buildingName: 'buildings.metalMine',
|
||
consumption: metalConsumption
|
||
},
|
||
crystalMine: {
|
||
buildingLevel: crystalMineLevel,
|
||
buildingName: 'buildings.crystalMine',
|
||
consumption: crystalConsumption
|
||
},
|
||
deuteriumSynthesizer: {
|
||
buildingLevel: deuteriumSynthesizerLevel,
|
||
buildingName: 'buildings.deuteriumSynthesizer',
|
||
consumption: deuteriumConsumption
|
||
},
|
||
total: metalConsumption + crystalConsumption + deuteriumConsumption
|
||
}
|
||
}
|