@shipload/sdk 1.0.0-next.11 → 1.0.0-next.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/shipload.d.ts +744 -926
- package/lib/shipload.js +2336 -2752
- package/lib/shipload.js.map +1 -1
- package/lib/shipload.m.js +2316 -2726
- package/lib/shipload.m.js.map +1 -1
- package/package.json +1 -1
- package/src/data/kind-registry.json +78 -0
- package/src/data/kind-registry.ts +133 -0
- package/src/derivation/capabilities.ts +397 -0
- package/src/derivation/crafting.ts +1 -1
- package/src/entities/entity.ts +98 -0
- package/src/entities/makers.ts +75 -228
- package/src/index-module.ts +37 -34
- package/src/managers/entities.ts +18 -114
- package/src/managers/index.ts +1 -1
- package/src/nft/atomicdata.ts +2 -0
- package/src/nft/description.ts +1 -1
- package/src/resolution/resolve-item.ts +3 -2
- package/src/subscriptions/manager.ts +2 -5
- package/src/subscriptions/mappers.ts +3 -12
- package/src/testing/catalog-hash.ts +19 -0
- package/src/testing/index.ts +2 -0
- package/src/testing/projection-parity.ts +143 -0
- package/src/types/index.ts +0 -1
- package/src/types.ts +0 -9
- package/src/entities/container.ts +0 -123
- package/src/entities/extractor.ts +0 -144
- package/src/entities/factory.ts +0 -135
- package/src/entities/nexus.ts +0 -29
- package/src/entities/ship-deploy.ts +0 -316
- package/src/entities/ship.ts +0 -221
- package/src/entities/warehouse.ts +0 -136
- package/src/types/entity-traits.ts +0 -171
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
import {UInt64, type UInt64Type} from '@wharfkit/antelope'
|
|
2
|
-
import {ServerContract} from '../contracts'
|
|
3
|
-
import type {CoordinatesType} from '../types'
|
|
4
|
-
import {Location} from './location'
|
|
5
|
-
import {ScheduleAccessor} from '../scheduling/accessor'
|
|
6
|
-
import {InventoryAccessor} from './inventory-accessor'
|
|
7
|
-
import type {EntityInventory} from './entity-inventory'
|
|
8
|
-
import type {PackedModuleInput} from './ship'
|
|
9
|
-
import {decodeCraftedItemStats} from '../derivation/crafting'
|
|
10
|
-
import {getModuleCapabilityType, MODULE_GATHERER, MODULE_GENERATOR} from '../capabilities/modules'
|
|
11
|
-
import {computeGathererCapabilities, computeGeneratorCapabilities} from './ship-deploy'
|
|
12
|
-
import {applySlotMultiplier, clampUint16, getSlotAmp, type InstalledModule} from './slot-multiplier'
|
|
13
|
-
import type {EntitySlot} from '../data/recipes-runtime'
|
|
14
|
-
import {getItem} from '../data/catalog'
|
|
15
|
-
|
|
16
|
-
export interface ExtractorStateInput {
|
|
17
|
-
id: UInt64Type
|
|
18
|
-
owner: string
|
|
19
|
-
name: string
|
|
20
|
-
coordinates: CoordinatesType | {x: number; y: number; z?: number}
|
|
21
|
-
hullmass?: number
|
|
22
|
-
capacity?: number
|
|
23
|
-
energy?: number
|
|
24
|
-
modules?: PackedModuleInput[]
|
|
25
|
-
schedule?: ServerContract.Types.schedule
|
|
26
|
-
cargo?: ServerContract.Types.cargo_item[]
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export class Extractor extends ServerContract.Types.entity_info {
|
|
30
|
-
private _sched?: ScheduleAccessor
|
|
31
|
-
private _inv?: InventoryAccessor
|
|
32
|
-
|
|
33
|
-
get name(): string {
|
|
34
|
-
return this.entity_name
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
get entityClass(): 'planetary' {
|
|
38
|
-
return 'planetary'
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
get canDemolish(): boolean {
|
|
42
|
-
return true
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
get inv(): InventoryAccessor {
|
|
46
|
-
this._inv ??= new InventoryAccessor(this)
|
|
47
|
-
return this._inv
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
get inventory(): EntityInventory[] {
|
|
51
|
-
return this.inv.items
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
get sched(): ScheduleAccessor {
|
|
55
|
-
this._sched ??= new ScheduleAccessor(this)
|
|
56
|
-
return this._sched
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
get isIdle(): boolean {
|
|
60
|
-
return this.is_idle
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
get location(): Location {
|
|
64
|
-
return Location.from(this.coordinates)
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
get totalCargoMass(): UInt64 {
|
|
68
|
-
return this.inv.totalMass
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
get maxCapacity(): UInt64 {
|
|
72
|
-
return UInt64.from(this.capacity)
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
get availableCapacity(): UInt64 {
|
|
76
|
-
const cargo = this.totalCargoMass
|
|
77
|
-
return cargo.gte(this.maxCapacity) ? UInt64.from(0) : this.maxCapacity.subtracting(cargo)
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
get isFull(): boolean {
|
|
81
|
-
return this.totalCargoMass.gte(this.maxCapacity)
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
get totalMass(): UInt64 {
|
|
85
|
-
const hull = this.hullmass ? UInt64.from(this.hullmass) : UInt64.from(0)
|
|
86
|
-
return hull.adding(this.totalCargoMass)
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
export interface ExtractorCapabilities {
|
|
91
|
-
generator?: {capacity: number; recharge: number}
|
|
92
|
-
gatherer?: {yield: number; drain: number; depth: number; speed: number}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
export function computeExtractorCapabilities(
|
|
96
|
-
modules: InstalledModule[],
|
|
97
|
-
layout: EntitySlot[]
|
|
98
|
-
): ExtractorCapabilities {
|
|
99
|
-
const out: ExtractorCapabilities = {}
|
|
100
|
-
|
|
101
|
-
const genModules = modules.filter((m) => getModuleCapabilityType(m.itemId) === MODULE_GENERATOR)
|
|
102
|
-
if (genModules.length > 0) {
|
|
103
|
-
let totalCapacity = 0
|
|
104
|
-
let totalRecharge = 0
|
|
105
|
-
for (const m of genModules) {
|
|
106
|
-
const caps = computeGeneratorCapabilities(decodeCraftedItemStats(m.itemId, m.stats))
|
|
107
|
-
const amp = getSlotAmp(layout, m.slotIndex)
|
|
108
|
-
totalCapacity += applySlotMultiplier(caps.capacity, amp)
|
|
109
|
-
totalRecharge += applySlotMultiplier(caps.recharge, amp)
|
|
110
|
-
}
|
|
111
|
-
out.generator = {
|
|
112
|
-
capacity: clampUint16(totalCapacity),
|
|
113
|
-
recharge: clampUint16(totalRecharge),
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
const gathModules = modules.filter((m) => getModuleCapabilityType(m.itemId) === MODULE_GATHERER)
|
|
118
|
-
if (gathModules.length > 0) {
|
|
119
|
-
let totalYield = 0
|
|
120
|
-
let totalDrain = 0
|
|
121
|
-
let maxDepth = 0
|
|
122
|
-
let totalSpeed = 0
|
|
123
|
-
for (const m of gathModules) {
|
|
124
|
-
const tier = getItem(m.itemId).tier
|
|
125
|
-
const caps = computeGathererCapabilities(
|
|
126
|
-
decodeCraftedItemStats(m.itemId, m.stats),
|
|
127
|
-
tier
|
|
128
|
-
)
|
|
129
|
-
const amp = getSlotAmp(layout, m.slotIndex)
|
|
130
|
-
totalYield += applySlotMultiplier(caps.yield, amp)
|
|
131
|
-
totalDrain += caps.drain
|
|
132
|
-
if (caps.depth > maxDepth) maxDepth = caps.depth
|
|
133
|
-
totalSpeed += applySlotMultiplier(caps.speed, amp)
|
|
134
|
-
}
|
|
135
|
-
out.gatherer = {
|
|
136
|
-
yield: clampUint16(totalYield),
|
|
137
|
-
drain: totalDrain,
|
|
138
|
-
depth: maxDepth,
|
|
139
|
-
speed: clampUint16(totalSpeed),
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
return out
|
|
144
|
-
}
|
package/src/entities/factory.ts
DELETED
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
import {UInt64, type UInt64Type} from '@wharfkit/antelope'
|
|
2
|
-
import {ServerContract} from '../contracts'
|
|
3
|
-
import type {CoordinatesType} from '../types'
|
|
4
|
-
import {Location} from './location'
|
|
5
|
-
import {ScheduleAccessor} from '../scheduling/accessor'
|
|
6
|
-
import {InventoryAccessor} from './inventory-accessor'
|
|
7
|
-
import type {EntityInventory} from './entity-inventory'
|
|
8
|
-
import type {PackedModuleInput} from './ship'
|
|
9
|
-
import {decodeCraftedItemStats} from '../derivation/crafting'
|
|
10
|
-
import {getModuleCapabilityType, MODULE_CRAFTER, MODULE_GENERATOR} from '../capabilities/modules'
|
|
11
|
-
import {computeCrafterCapabilities, computeGeneratorCapabilities} from './ship-deploy'
|
|
12
|
-
import {applySlotMultiplier, clampUint16, getSlotAmp, type InstalledModule} from './slot-multiplier'
|
|
13
|
-
import type {EntitySlot} from '../data/recipes-runtime'
|
|
14
|
-
|
|
15
|
-
export interface FactoryStateInput {
|
|
16
|
-
id: UInt64Type
|
|
17
|
-
owner: string
|
|
18
|
-
name: string
|
|
19
|
-
coordinates: CoordinatesType | {x: number; y: number; z?: number}
|
|
20
|
-
hullmass?: number
|
|
21
|
-
capacity?: number
|
|
22
|
-
energy?: number
|
|
23
|
-
modules?: PackedModuleInput[]
|
|
24
|
-
schedule?: ServerContract.Types.schedule
|
|
25
|
-
cargo?: ServerContract.Types.cargo_item[]
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export class Factory extends ServerContract.Types.entity_info {
|
|
29
|
-
private _sched?: ScheduleAccessor
|
|
30
|
-
private _inv?: InventoryAccessor
|
|
31
|
-
|
|
32
|
-
get name(): string {
|
|
33
|
-
return this.entity_name
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
get entityClass(): 'planetary' {
|
|
37
|
-
return 'planetary'
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
get canDemolish(): boolean {
|
|
41
|
-
return true
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
get inv(): InventoryAccessor {
|
|
45
|
-
this._inv ??= new InventoryAccessor(this)
|
|
46
|
-
return this._inv
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
get inventory(): EntityInventory[] {
|
|
50
|
-
return this.inv.items
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
get sched(): ScheduleAccessor {
|
|
54
|
-
this._sched ??= new ScheduleAccessor(this)
|
|
55
|
-
return this._sched
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
get isIdle(): boolean {
|
|
59
|
-
return this.is_idle
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
get location(): Location {
|
|
63
|
-
return Location.from(this.coordinates)
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
get totalCargoMass(): UInt64 {
|
|
67
|
-
return this.inv.totalMass
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
get maxCapacity(): UInt64 {
|
|
71
|
-
return UInt64.from(this.capacity)
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
get availableCapacity(): UInt64 {
|
|
75
|
-
const cargo = this.totalCargoMass
|
|
76
|
-
return cargo.gte(this.maxCapacity) ? UInt64.from(0) : this.maxCapacity.subtracting(cargo)
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
get isFull(): boolean {
|
|
80
|
-
return this.totalCargoMass.gte(this.maxCapacity)
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
get totalMass(): UInt64 {
|
|
84
|
-
const hull = this.hullmass ? UInt64.from(this.hullmass) : UInt64.from(0)
|
|
85
|
-
return hull.adding(this.totalCargoMass)
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
export interface FactoryCapabilities {
|
|
90
|
-
generator?: {capacity: number; recharge: number}
|
|
91
|
-
crafter?: {speed: number; drain: number}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
export function computeFactoryCapabilities(
|
|
95
|
-
modules: InstalledModule[],
|
|
96
|
-
layout: EntitySlot[]
|
|
97
|
-
): FactoryCapabilities {
|
|
98
|
-
const out: FactoryCapabilities = {}
|
|
99
|
-
|
|
100
|
-
const genModules = modules.filter((m) => getModuleCapabilityType(m.itemId) === MODULE_GENERATOR)
|
|
101
|
-
if (genModules.length > 0) {
|
|
102
|
-
let totalCapacity = 0
|
|
103
|
-
let totalRecharge = 0
|
|
104
|
-
for (const m of genModules) {
|
|
105
|
-
const caps = computeGeneratorCapabilities(decodeCraftedItemStats(m.itemId, m.stats))
|
|
106
|
-
const amp = getSlotAmp(layout, m.slotIndex)
|
|
107
|
-
totalCapacity += applySlotMultiplier(caps.capacity, amp)
|
|
108
|
-
totalRecharge += applySlotMultiplier(caps.recharge, amp)
|
|
109
|
-
}
|
|
110
|
-
out.generator = {
|
|
111
|
-
capacity: clampUint16(totalCapacity),
|
|
112
|
-
recharge: clampUint16(totalRecharge),
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
const crafterModules = modules.filter(
|
|
117
|
-
(m) => getModuleCapabilityType(m.itemId) === MODULE_CRAFTER
|
|
118
|
-
)
|
|
119
|
-
if (crafterModules.length > 0) {
|
|
120
|
-
let totalSpeed = 0
|
|
121
|
-
let totalDrain = 0
|
|
122
|
-
for (const m of crafterModules) {
|
|
123
|
-
const caps = computeCrafterCapabilities(decodeCraftedItemStats(m.itemId, m.stats))
|
|
124
|
-
const amp = getSlotAmp(layout, m.slotIndex)
|
|
125
|
-
totalSpeed += applySlotMultiplier(caps.speed, amp)
|
|
126
|
-
totalDrain += caps.drain
|
|
127
|
-
}
|
|
128
|
-
out.crafter = {
|
|
129
|
-
speed: clampUint16(totalSpeed),
|
|
130
|
-
drain: totalDrain,
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
return out
|
|
135
|
-
}
|
package/src/entities/nexus.ts
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import type {UInt64Type} from '@wharfkit/antelope'
|
|
2
|
-
import {ServerContract} from '../contracts'
|
|
3
|
-
import type {CoordinatesType} from '../types'
|
|
4
|
-
import {Location} from './location'
|
|
5
|
-
|
|
6
|
-
export interface NexusStateInput {
|
|
7
|
-
id: UInt64Type
|
|
8
|
-
owner: string
|
|
9
|
-
name: string
|
|
10
|
-
coordinates: CoordinatesType | {x: number; y: number; z?: number}
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export class Nexus extends ServerContract.Types.entity_info {
|
|
14
|
-
get name(): string {
|
|
15
|
-
return this.entity_name
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
get entityClass(): 'orbital' {
|
|
19
|
-
return 'orbital'
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
get location(): Location {
|
|
23
|
-
return Location.from(this.coordinates)
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
get orbitalAltitude(): number {
|
|
27
|
-
return this.coordinates.z?.toNumber() || 0
|
|
28
|
-
}
|
|
29
|
-
}
|
|
@@ -1,316 +0,0 @@
|
|
|
1
|
-
import {decodeCraftedItemStats} from '../derivation/crafting'
|
|
2
|
-
import {
|
|
3
|
-
getModuleCapabilityType,
|
|
4
|
-
MODULE_CRAFTER,
|
|
5
|
-
MODULE_ENGINE,
|
|
6
|
-
MODULE_GATHERER,
|
|
7
|
-
MODULE_GENERATOR,
|
|
8
|
-
MODULE_HAULER,
|
|
9
|
-
MODULE_LOADER,
|
|
10
|
-
} from '../capabilities/modules'
|
|
11
|
-
import {getItem} from '../data/catalog'
|
|
12
|
-
import type {EntitySlot} from '../data/recipes-runtime'
|
|
13
|
-
import {applySlotMultiplier, clampUint16, getSlotAmp, type InstalledModule} from './slot-multiplier'
|
|
14
|
-
|
|
15
|
-
export type {InstalledModule}
|
|
16
|
-
|
|
17
|
-
export function computeShipHullCapabilities(stats: Record<string, number>): {
|
|
18
|
-
hullmass: number
|
|
19
|
-
capacity: number
|
|
20
|
-
} {
|
|
21
|
-
const density = stats.density
|
|
22
|
-
const strength = stats.strength
|
|
23
|
-
const hardness = stats.hardness
|
|
24
|
-
const saturation = stats.saturation
|
|
25
|
-
|
|
26
|
-
const hullmass = 100000 - 75 * density
|
|
27
|
-
const statSum = strength + hardness + saturation
|
|
28
|
-
const exponent = statSum / 2997.0
|
|
29
|
-
const capacity = Math.floor(1000000 * 10 ** exponent)
|
|
30
|
-
|
|
31
|
-
return {hullmass, capacity}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export function computeEngineCapabilities(stats: Record<string, number>): {
|
|
35
|
-
thrust: number
|
|
36
|
-
drain: number
|
|
37
|
-
} {
|
|
38
|
-
const vol = stats.volatility
|
|
39
|
-
const thm = stats.thermal
|
|
40
|
-
|
|
41
|
-
return {
|
|
42
|
-
thrust: 400 + Math.floor((vol * 3) / 4),
|
|
43
|
-
drain: Math.max(30, 50 - Math.floor(thm / 70)),
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export function computeGeneratorCapabilities(stats: Record<string, number>): {
|
|
48
|
-
capacity: number
|
|
49
|
-
recharge: number
|
|
50
|
-
} {
|
|
51
|
-
const com = stats.composition
|
|
52
|
-
const fin = stats.fineness
|
|
53
|
-
|
|
54
|
-
return {
|
|
55
|
-
capacity: 300 + Math.floor(com / 6),
|
|
56
|
-
recharge: 1 + Math.floor((fin * 3) / 1000),
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
export interface GathererDepthParams {
|
|
61
|
-
readonly floor: number
|
|
62
|
-
readonly slope: number
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export const GATHERER_DEPTH_TABLE: readonly GathererDepthParams[] = [
|
|
66
|
-
{floor: 500, slope: 5},
|
|
67
|
-
{floor: 2000, slope: 11},
|
|
68
|
-
{floor: 7000, slope: 16},
|
|
69
|
-
{floor: 15000, slope: 18},
|
|
70
|
-
{floor: 25000, slope: 19},
|
|
71
|
-
{floor: 35000, slope: 16},
|
|
72
|
-
{floor: 46000, slope: 12},
|
|
73
|
-
{floor: 53500, slope: 10},
|
|
74
|
-
{floor: 60000, slope: 5},
|
|
75
|
-
{floor: 63500, slope: 2},
|
|
76
|
-
]
|
|
77
|
-
|
|
78
|
-
export const GATHERER_DEPTH_MAX_TIER = 10
|
|
79
|
-
|
|
80
|
-
export function gathererDepthForTier(tol: number, tier: number): number {
|
|
81
|
-
if (tier < 1 || tier > GATHERER_DEPTH_MAX_TIER) {
|
|
82
|
-
throw new Error(`gatherer tier out of range: ${tier}`)
|
|
83
|
-
}
|
|
84
|
-
const p = GATHERER_DEPTH_TABLE[tier - 1]
|
|
85
|
-
return p.floor + tol * p.slope
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
export function computeGathererCapabilities(
|
|
89
|
-
stats: Record<string, number>,
|
|
90
|
-
tier: number
|
|
91
|
-
): {
|
|
92
|
-
yield: number
|
|
93
|
-
drain: number
|
|
94
|
-
depth: number
|
|
95
|
-
speed: number
|
|
96
|
-
} {
|
|
97
|
-
const str = stats.strength
|
|
98
|
-
const con = stats.conductivity
|
|
99
|
-
const ref = stats.reflectivity
|
|
100
|
-
const tol = stats.tolerance
|
|
101
|
-
|
|
102
|
-
return {
|
|
103
|
-
yield: 200 + str,
|
|
104
|
-
drain: Math.max(250, 1250 - Math.floor((con * 25) / 20)),
|
|
105
|
-
depth: gathererDepthForTier(tol, tier),
|
|
106
|
-
speed: 100 + Math.floor((ref * 4) / 5),
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
export function computeLoaderCapabilities(stats: Record<string, number>): {
|
|
111
|
-
mass: number
|
|
112
|
-
thrust: number
|
|
113
|
-
quantity: number
|
|
114
|
-
} {
|
|
115
|
-
const insulation = stats.insulation
|
|
116
|
-
const plasticity = stats.plasticity
|
|
117
|
-
|
|
118
|
-
return {
|
|
119
|
-
mass: Math.max(200, 2000 - Math.floor(insulation * 2)),
|
|
120
|
-
thrust: 1 + Math.floor(plasticity / 500),
|
|
121
|
-
quantity: 1,
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
export function computeCrafterCapabilities(stats: Record<string, number>): {
|
|
126
|
-
speed: number
|
|
127
|
-
drain: number
|
|
128
|
-
} {
|
|
129
|
-
const rea = stats.reactivity
|
|
130
|
-
const fin = stats.fineness
|
|
131
|
-
|
|
132
|
-
return {
|
|
133
|
-
speed: 100 + Math.floor((rea * 4) / 5),
|
|
134
|
-
drain: Math.max(5, 30 - Math.floor(fin / 33)),
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
export function computeHaulerCapabilities(stats: Record<string, number>): {
|
|
139
|
-
capacity: number
|
|
140
|
-
efficiency: number
|
|
141
|
-
drain: number
|
|
142
|
-
} {
|
|
143
|
-
const fineness = stats.fineness
|
|
144
|
-
const conductivity = stats.conductivity
|
|
145
|
-
const composition = stats.composition
|
|
146
|
-
|
|
147
|
-
return {
|
|
148
|
-
capacity: Math.max(1, 1 + Math.floor(fineness / 400)),
|
|
149
|
-
efficiency: 2000 + conductivity * 6,
|
|
150
|
-
drain: Math.max(3, 15 - Math.floor(composition / 80)),
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
export function computeStorageCapabilities(
|
|
155
|
-
stats: Record<string, number>,
|
|
156
|
-
baseCapacity: number
|
|
157
|
-
): {
|
|
158
|
-
capacityBonus: number
|
|
159
|
-
} {
|
|
160
|
-
const strength = stats.strength
|
|
161
|
-
const density = stats.density
|
|
162
|
-
const hardness = stats.hardness
|
|
163
|
-
const saturation = stats.saturation
|
|
164
|
-
|
|
165
|
-
const statSum = strength + density + hardness + saturation
|
|
166
|
-
const capacityBonus = Math.floor(
|
|
167
|
-
(baseCapacity * (10 + Math.floor((statSum * 10) / 2997))) / 100
|
|
168
|
-
)
|
|
169
|
-
|
|
170
|
-
return {capacityBonus}
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
export function computeWarehouseHullCapabilities(stats: Record<string, number>): {
|
|
174
|
-
hullmass: number
|
|
175
|
-
capacity: number
|
|
176
|
-
} {
|
|
177
|
-
const density = stats.density
|
|
178
|
-
const strength = stats.strength
|
|
179
|
-
const hardness = stats.hardness
|
|
180
|
-
const saturation = stats.saturation
|
|
181
|
-
|
|
182
|
-
const hullmass = 100000 - 75 * density
|
|
183
|
-
const statSum = strength + hardness + saturation
|
|
184
|
-
const exponent = statSum / 2997.0
|
|
185
|
-
const capacity = Math.floor(20000000 * 10 ** exponent)
|
|
186
|
-
|
|
187
|
-
return {hullmass, capacity}
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
export interface ShipCapabilities {
|
|
191
|
-
engines?: {thrust: number; drain: number}
|
|
192
|
-
generator?: {capacity: number; recharge: number}
|
|
193
|
-
gatherer?: {yield: number; drain: number; depth: number; speed: number}
|
|
194
|
-
hauler?: {capacity: number; efficiency: number; drain: number}
|
|
195
|
-
loaders?: {mass: number; thrust: number; quantity: number}
|
|
196
|
-
crafter?: {speed: number; drain: number}
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
export function computeShipCapabilities(
|
|
200
|
-
modules: InstalledModule[],
|
|
201
|
-
layout: EntitySlot[]
|
|
202
|
-
): ShipCapabilities {
|
|
203
|
-
const ship: ShipCapabilities = {}
|
|
204
|
-
|
|
205
|
-
const engineModules = modules.filter((m) => getModuleCapabilityType(m.itemId) === MODULE_ENGINE)
|
|
206
|
-
if (engineModules.length > 0) {
|
|
207
|
-
let totalThrust = 0
|
|
208
|
-
let totalDrain = 0
|
|
209
|
-
for (const m of engineModules) {
|
|
210
|
-
const caps = computeEngineCapabilities(decodeCraftedItemStats(m.itemId, m.stats))
|
|
211
|
-
totalThrust += applySlotMultiplier(caps.thrust, getSlotAmp(layout, m.slotIndex))
|
|
212
|
-
totalDrain += caps.drain
|
|
213
|
-
}
|
|
214
|
-
ship.engines = {thrust: totalThrust, drain: totalDrain}
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
const generatorModules = modules.filter(
|
|
218
|
-
(m) => getModuleCapabilityType(m.itemId) === MODULE_GENERATOR
|
|
219
|
-
)
|
|
220
|
-
if (generatorModules.length > 0) {
|
|
221
|
-
let totalCapacity = 0
|
|
222
|
-
let totalRecharge = 0
|
|
223
|
-
for (const m of generatorModules) {
|
|
224
|
-
const caps = computeGeneratorCapabilities(decodeCraftedItemStats(m.itemId, m.stats))
|
|
225
|
-
const amp = getSlotAmp(layout, m.slotIndex)
|
|
226
|
-
totalCapacity += applySlotMultiplier(caps.capacity, amp)
|
|
227
|
-
totalRecharge += applySlotMultiplier(caps.recharge, amp)
|
|
228
|
-
}
|
|
229
|
-
ship.generator = {
|
|
230
|
-
capacity: clampUint16(totalCapacity),
|
|
231
|
-
recharge: clampUint16(totalRecharge),
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
const gathererModules = modules.filter(
|
|
236
|
-
(m) => getModuleCapabilityType(m.itemId) === MODULE_GATHERER
|
|
237
|
-
)
|
|
238
|
-
if (gathererModules.length > 0) {
|
|
239
|
-
let totalYield = 0
|
|
240
|
-
let totalDrain = 0
|
|
241
|
-
let maxDepth = 0
|
|
242
|
-
let totalSpeed = 0
|
|
243
|
-
for (const m of gathererModules) {
|
|
244
|
-
const tier = getItem(m.itemId).tier
|
|
245
|
-
const caps = computeGathererCapabilities(
|
|
246
|
-
decodeCraftedItemStats(m.itemId, m.stats),
|
|
247
|
-
tier
|
|
248
|
-
)
|
|
249
|
-
const amp = getSlotAmp(layout, m.slotIndex)
|
|
250
|
-
totalYield += applySlotMultiplier(caps.yield, amp)
|
|
251
|
-
totalDrain += caps.drain
|
|
252
|
-
if (caps.depth > maxDepth) maxDepth = caps.depth
|
|
253
|
-
totalSpeed += applySlotMultiplier(caps.speed, amp)
|
|
254
|
-
}
|
|
255
|
-
ship.gatherer = {
|
|
256
|
-
yield: clampUint16(totalYield),
|
|
257
|
-
drain: totalDrain,
|
|
258
|
-
depth: maxDepth,
|
|
259
|
-
speed: clampUint16(totalSpeed),
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
const haulerModules = modules.filter((m) => getModuleCapabilityType(m.itemId) === MODULE_HAULER)
|
|
264
|
-
if (haulerModules.length > 0) {
|
|
265
|
-
let totalCapacity = 0
|
|
266
|
-
let weightedEffNum = 0
|
|
267
|
-
let totalDrain = 0
|
|
268
|
-
for (const m of haulerModules) {
|
|
269
|
-
const caps = computeHaulerCapabilities(decodeCraftedItemStats(m.itemId, m.stats))
|
|
270
|
-
const eff = applySlotMultiplier(caps.efficiency, getSlotAmp(layout, m.slotIndex))
|
|
271
|
-
totalCapacity += caps.capacity
|
|
272
|
-
weightedEffNum += eff * caps.capacity
|
|
273
|
-
totalDrain += caps.drain
|
|
274
|
-
}
|
|
275
|
-
const efficiency = totalCapacity > 0 ? Math.floor(weightedEffNum / totalCapacity) : 0
|
|
276
|
-
ship.hauler = {
|
|
277
|
-
capacity: totalCapacity,
|
|
278
|
-
efficiency: clampUint16(efficiency),
|
|
279
|
-
drain: totalDrain,
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
const loaderModules = modules.filter((m) => getModuleCapabilityType(m.itemId) === MODULE_LOADER)
|
|
284
|
-
if (loaderModules.length > 0) {
|
|
285
|
-
let totalMass = 0
|
|
286
|
-
let totalThrust = 0
|
|
287
|
-
let totalQuantity = 0
|
|
288
|
-
for (const m of loaderModules) {
|
|
289
|
-
const caps = computeLoaderCapabilities(decodeCraftedItemStats(m.itemId, m.stats))
|
|
290
|
-
totalMass += caps.mass
|
|
291
|
-
totalThrust += applySlotMultiplier(caps.thrust, getSlotAmp(layout, m.slotIndex))
|
|
292
|
-
totalQuantity += caps.quantity
|
|
293
|
-
}
|
|
294
|
-
ship.loaders = {
|
|
295
|
-
mass: totalMass,
|
|
296
|
-
thrust: clampUint16(totalThrust),
|
|
297
|
-
quantity: totalQuantity,
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
const crafterModules = modules.filter(
|
|
302
|
-
(m) => getModuleCapabilityType(m.itemId) === MODULE_CRAFTER
|
|
303
|
-
)
|
|
304
|
-
if (crafterModules.length > 0) {
|
|
305
|
-
let totalSpeed = 0
|
|
306
|
-
let totalDrain = 0
|
|
307
|
-
for (const m of crafterModules) {
|
|
308
|
-
const caps = computeCrafterCapabilities(decodeCraftedItemStats(m.itemId, m.stats))
|
|
309
|
-
totalSpeed += applySlotMultiplier(caps.speed, getSlotAmp(layout, m.slotIndex))
|
|
310
|
-
totalDrain += caps.drain
|
|
311
|
-
}
|
|
312
|
-
ship.crafter = {speed: clampUint16(totalSpeed), drain: totalDrain}
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
return ship
|
|
316
|
-
}
|