Files
ogame-vue-ts/src/logic/resourceLogic.ts
谦君 731d79673b feat: 新增战报弹窗与舰队模拟器,重构UI组件
新增 BattleReportDialog、SpyReportDialog、NumberWithTooltip 等组件,完善舰队模拟器功能。重构并引入 Sheet、Sidebar、Tooltip、Skeleton 等 UI 组件,优化界面结构。实现 battle.worker 支持战斗计算,增加 universeStore、fleetStorageLogic 等核心逻辑,完善多语言与类型定义。
2025-12-13 11:14:23 +08:00

392 lines
13 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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
}
}