@shipload/sdk 1.0.0-next.2 → 1.0.0-next.21
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 +1731 -1044
- package/lib/shipload.js +6758 -4523
- package/lib/shipload.js.map +1 -1
- package/lib/shipload.m.js +6649 -4479
- package/lib/shipload.m.js.map +1 -1
- package/lib/testing.d.ts +833 -0
- package/lib/testing.js +3647 -0
- package/lib/testing.js.map +1 -0
- package/lib/testing.m.js +3641 -0
- package/lib/testing.m.js.map +1 -0
- package/package.json +15 -2
- package/src/capabilities/gathering.ts +17 -7
- package/src/capabilities/modules.ts +9 -0
- package/src/capabilities/storage.ts +1 -1
- package/src/contracts/platform.ts +211 -3
- package/src/contracts/server.ts +723 -438
- package/src/data/capabilities.ts +9 -329
- package/src/data/capability-formulas.ts +76 -0
- package/src/data/catalog.ts +0 -5
- package/src/data/colors.ts +14 -28
- package/src/data/entities.json +46 -10
- package/src/data/item-ids.ts +17 -13
- package/src/data/items.json +308 -37
- package/src/data/kind-registry.json +85 -0
- package/src/data/kind-registry.ts +150 -0
- package/src/data/metadata.ts +99 -24
- package/src/data/recipes-runtime.ts +3 -23
- package/src/data/recipes.json +265 -96
- package/src/derivation/build-methods.ts +45 -0
- package/src/derivation/capabilities.ts +414 -0
- package/src/derivation/capability-mappings.ts +117 -0
- package/src/derivation/crafting.ts +23 -24
- package/src/derivation/index.ts +8 -2
- package/src/derivation/reserve-regen.ts +34 -0
- package/src/derivation/resources.ts +125 -38
- package/src/derivation/stats.ts +1 -2
- package/src/derivation/stratum.ts +15 -19
- package/src/derivation/tiers.ts +28 -7
- package/src/entities/entity.ts +98 -0
- package/src/entities/gamestate.ts +3 -28
- package/src/entities/makers.ts +75 -129
- package/src/entities/slot-multiplier.ts +37 -0
- package/src/errors.ts +10 -15
- package/src/format.ts +26 -4
- package/src/index-module.ts +151 -40
- package/src/managers/actions.ts +184 -82
- package/src/managers/base.ts +2 -2
- package/src/managers/construction-types.ts +68 -0
- package/src/managers/construction.ts +292 -0
- package/src/managers/context.ts +9 -0
- package/src/managers/entities.ts +18 -66
- package/src/managers/epochs.ts +40 -0
- package/src/managers/index.ts +16 -1
- package/src/managers/locations.ts +2 -20
- package/src/managers/nft.ts +28 -0
- package/src/managers/plot.ts +123 -0
- package/src/nft/atomicassets.ts +231 -0
- package/src/nft/atomicdata.ts +130 -0
- package/src/nft/buildImmutableData.ts +319 -0
- package/src/nft/description.ts +45 -13
- package/src/nft/index.ts +3 -0
- package/src/resolution/describe-module.ts +5 -8
- package/src/resolution/display-name.ts +38 -10
- package/src/resolution/resolve-item.ts +20 -12
- package/src/scheduling/accessor.ts +4 -0
- package/src/scheduling/projection.ts +79 -27
- package/src/scheduling/schedule.ts +15 -1
- package/src/scheduling/task-cargo.ts +46 -0
- package/src/shipload.ts +5 -0
- package/src/subscriptions/manager.ts +40 -6
- package/src/subscriptions/mappers.ts +3 -8
- package/src/subscriptions/types.ts +3 -2
- 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/travel/travel.ts +61 -2
- package/src/types/index.ts +0 -1
- package/src/types.ts +17 -12
- package/src/utils/cargo.ts +27 -0
- package/src/utils/system.ts +25 -24
- package/src/entities/container.ts +0 -108
- package/src/entities/ship-deploy.ts +0 -258
- package/src/entities/ship.ts +0 -204
- package/src/entities/warehouse.ts +0 -119
- package/src/types/entity-traits.ts +0 -69
package/src/types.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
2
|
type Int64Type,
|
|
3
|
-
Name,
|
|
4
3
|
type UInt16,
|
|
5
4
|
type UInt16Type,
|
|
6
5
|
type UInt32,
|
|
@@ -12,7 +11,7 @@ import {ServerContract} from './contracts'
|
|
|
12
11
|
export const PRECISION = 10000
|
|
13
12
|
export const CRAFT_ENERGY_DIVISOR = 150000
|
|
14
13
|
|
|
15
|
-
export const
|
|
14
|
+
export const PLANETARY_STRUCTURE_Z = 0
|
|
16
15
|
|
|
17
16
|
export const CONTAINER_Z = 300
|
|
18
17
|
|
|
@@ -23,6 +22,8 @@ export const MAX_ORBITAL_ALTITUDE = 3000
|
|
|
23
22
|
|
|
24
23
|
export const BASE_ORBITAL_MASS = 100000
|
|
25
24
|
|
|
25
|
+
export const MIN_TRANSFER_DISTANCE = 100
|
|
26
|
+
|
|
26
27
|
export interface ShipLike {
|
|
27
28
|
coordinates: ServerContract.Types.coordinates
|
|
28
29
|
hullmass?: UInt32
|
|
@@ -49,8 +50,11 @@ export enum TaskType {
|
|
|
49
50
|
WARP = 6,
|
|
50
51
|
CRAFT = 7,
|
|
51
52
|
DEPLOY = 8,
|
|
52
|
-
WRAP = 9,
|
|
53
53
|
UNWRAP = 10,
|
|
54
|
+
UNDEPLOY = 11,
|
|
55
|
+
DEMOLISH = 13,
|
|
56
|
+
CLAIMPLOT = 14,
|
|
57
|
+
BUILDPLOT = 15,
|
|
54
58
|
}
|
|
55
59
|
|
|
56
60
|
export enum LocationType {
|
|
@@ -58,6 +62,7 @@ export enum LocationType {
|
|
|
58
62
|
PLANET = 1,
|
|
59
63
|
ASTEROID = 2,
|
|
60
64
|
NEBULA = 3,
|
|
65
|
+
ICE_FIELD = 4,
|
|
61
66
|
}
|
|
62
67
|
|
|
63
68
|
export enum TaskCancelable {
|
|
@@ -66,14 +71,6 @@ export enum TaskCancelable {
|
|
|
66
71
|
ALWAYS = 2,
|
|
67
72
|
}
|
|
68
73
|
|
|
69
|
-
export const EntityType = {
|
|
70
|
-
SHIP: Name.from('ship'),
|
|
71
|
-
WAREHOUSE: Name.from('warehouse'),
|
|
72
|
-
CONTAINER: Name.from('container'),
|
|
73
|
-
} as const
|
|
74
|
-
|
|
75
|
-
export type EntityTypeName = (typeof EntityType)[keyof typeof EntityType]
|
|
76
|
-
|
|
77
74
|
export type CoordinatesType =
|
|
78
75
|
| Coordinates
|
|
79
76
|
| ServerContract.Types.coordinates
|
|
@@ -122,8 +119,9 @@ export type ModuleType =
|
|
|
122
119
|
| 'launcher'
|
|
123
120
|
| 'storage'
|
|
124
121
|
| 'hauler'
|
|
122
|
+
| 'battery'
|
|
125
123
|
|
|
126
|
-
export const
|
|
124
|
+
export const RESOURCE_TIER_ADJECTIVES: Record<number, string> = {
|
|
127
125
|
1: 'Crude',
|
|
128
126
|
2: 'Dense',
|
|
129
127
|
3: 'Pure',
|
|
@@ -136,6 +134,9 @@ export const TIER_ADJECTIVES: Record<number, string> = {
|
|
|
136
134
|
10: 'Ascendant',
|
|
137
135
|
}
|
|
138
136
|
|
|
137
|
+
export const COMPONENT_TIER_PREFIXES: Record<number, string> = {}
|
|
138
|
+
export const MODULE_TIER_PREFIXES: Record<number, string> = {}
|
|
139
|
+
|
|
139
140
|
export const CATEGORY_LABELS: Record<ResourceCategory, string> = {
|
|
140
141
|
ore: 'Ore',
|
|
141
142
|
crystal: 'Crystal',
|
|
@@ -159,3 +160,7 @@ export interface Item {
|
|
|
159
160
|
export function formatTier(tier: number): string {
|
|
160
161
|
return 'T' + tier
|
|
161
162
|
}
|
|
163
|
+
|
|
164
|
+
export function tierAdjective(tier: number): string {
|
|
165
|
+
return RESOURCE_TIER_ADJECTIVES[tier] ?? `T${tier}`
|
|
166
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type {ServerContract} from '../contracts'
|
|
2
|
+
|
|
3
|
+
export function cargoRef(src: {
|
|
4
|
+
item_id: number
|
|
5
|
+
stats: bigint | number
|
|
6
|
+
modules?: ServerContract.Types.module_entry[]
|
|
7
|
+
}): ServerContract.ActionParams.Type.cargo_ref {
|
|
8
|
+
return {
|
|
9
|
+
item_id: src.item_id,
|
|
10
|
+
stats: src.stats,
|
|
11
|
+
modules: src.modules ?? [],
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function cargoItem(
|
|
16
|
+
src: {
|
|
17
|
+
item_id: number
|
|
18
|
+
stats: bigint | number
|
|
19
|
+
modules?: ServerContract.Types.module_entry[]
|
|
20
|
+
},
|
|
21
|
+
quantity: bigint | number
|
|
22
|
+
): ServerContract.ActionParams.Type.cargo_item {
|
|
23
|
+
return {
|
|
24
|
+
...cargoRef(src),
|
|
25
|
+
quantity,
|
|
26
|
+
}
|
|
27
|
+
}
|
package/src/utils/system.ts
CHANGED
|
@@ -8,7 +8,6 @@ import nebulaAdjectives from '../data/nebula-adjectives.json'
|
|
|
8
8
|
import nebulaNouns from '../data/nebula-nouns.json'
|
|
9
9
|
|
|
10
10
|
const LOCATION_EXISTS_THRESHOLD = 0x10
|
|
11
|
-
const LOCATION_ACTIVE_THRESHOLD = 0x80
|
|
12
11
|
|
|
13
12
|
export function getLocationType(
|
|
14
13
|
gameSeed: Checksum256Type,
|
|
@@ -22,12 +21,10 @@ export function getLocationType(
|
|
|
22
21
|
return LocationType.EMPTY
|
|
23
22
|
}
|
|
24
23
|
|
|
25
|
-
if (hashResult.array[1] < 96)
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
30
|
-
return LocationType.NEBULA
|
|
24
|
+
if (hashResult.array[1] < 96) return LocationType.PLANET
|
|
25
|
+
if (hashResult.array[1] < 149) return LocationType.ASTEROID
|
|
26
|
+
if (hashResult.array[1] < 202) return LocationType.NEBULA
|
|
27
|
+
return LocationType.ICE_FIELD
|
|
31
28
|
}
|
|
32
29
|
|
|
33
30
|
export function isGatherableLocation(locationType: LocationType): boolean {
|
|
@@ -44,6 +41,8 @@ export function getLocationTypeName(type: LocationType): string {
|
|
|
44
41
|
return 'Asteroid'
|
|
45
42
|
case LocationType.NEBULA:
|
|
46
43
|
return 'Nebula'
|
|
44
|
+
case LocationType.ICE_FIELD:
|
|
45
|
+
return 'Ice Field'
|
|
47
46
|
}
|
|
48
47
|
}
|
|
49
48
|
|
|
@@ -76,6 +75,15 @@ function generateNebulaName(hashResult: Checksum512): string {
|
|
|
76
75
|
return `${nebulaAdjectives[adjIdx]} ${nebulaNouns[nounIdx]}`
|
|
77
76
|
}
|
|
78
77
|
|
|
78
|
+
function generateIceFieldName(hashResult: Checksum512): string {
|
|
79
|
+
const A = 65
|
|
80
|
+
const letter1 = String.fromCharCode(A + (hashResult.array[0] % 26))
|
|
81
|
+
const letter2 = String.fromCharCode(A + (hashResult.array[1] % 26))
|
|
82
|
+
const subId = (hashResult.array[2] % 9) + 1
|
|
83
|
+
const num = (uint16(hashResult, 3) % 9000) + 1000
|
|
84
|
+
return `${letter1}${letter2}-${subId}/${num}`
|
|
85
|
+
}
|
|
86
|
+
|
|
79
87
|
export function getSystemName(gameSeed: Checksum256Type, location: CoordinatesType): string {
|
|
80
88
|
const seed = Checksum256.from(gameSeed)
|
|
81
89
|
const locationType = getLocationType(seed, location)
|
|
@@ -91,6 +99,8 @@ export function getSystemName(gameSeed: Checksum256Type, location: CoordinatesTy
|
|
|
91
99
|
return generateAsteroidName(hashResult)
|
|
92
100
|
case LocationType.NEBULA:
|
|
93
101
|
return generateNebulaName(hashResult)
|
|
102
|
+
case LocationType.ICE_FIELD:
|
|
103
|
+
return generateIceFieldName(hashResult)
|
|
94
104
|
default:
|
|
95
105
|
return generatePlanetName(hashResult)
|
|
96
106
|
}
|
|
@@ -123,10 +133,12 @@ export function deriveLocationStatic(
|
|
|
123
133
|
|
|
124
134
|
if (hashResult.array[1] < 96) {
|
|
125
135
|
loc.type = UInt8.from(LocationType.PLANET)
|
|
126
|
-
} else if (hashResult.array[1] <
|
|
136
|
+
} else if (hashResult.array[1] < 149) {
|
|
127
137
|
loc.type = UInt8.from(LocationType.ASTEROID)
|
|
128
|
-
} else {
|
|
138
|
+
} else if (hashResult.array[1] < 202) {
|
|
129
139
|
loc.type = UInt8.from(LocationType.NEBULA)
|
|
140
|
+
} else {
|
|
141
|
+
loc.type = UInt8.from(LocationType.ICE_FIELD)
|
|
130
142
|
}
|
|
131
143
|
|
|
132
144
|
loc.subtype = UInt8.from(
|
|
@@ -138,31 +150,20 @@ export function deriveLocationStatic(
|
|
|
138
150
|
return loc
|
|
139
151
|
}
|
|
140
152
|
|
|
141
|
-
export function
|
|
142
|
-
|
|
153
|
+
export function isLocationBuildable(
|
|
154
|
+
gameSeed: Checksum256Type,
|
|
143
155
|
coordinates: CoordinatesType
|
|
144
|
-
):
|
|
145
|
-
|
|
146
|
-
const coords = Coordinates.from(coordinates)
|
|
147
|
-
const str = `system-epoch-${coords.x}-${coords.y}`
|
|
148
|
-
const hashResult = hash512(seed, str)
|
|
149
|
-
|
|
150
|
-
return ServerContract.Types.location_epoch.from({
|
|
151
|
-
active: hashResult.array[0] < LOCATION_ACTIVE_THRESHOLD,
|
|
152
|
-
seed0: hashResult.array[1],
|
|
153
|
-
seed1: hashResult.array[2],
|
|
154
|
-
})
|
|
156
|
+
): boolean {
|
|
157
|
+
return getLocationType(gameSeed, coordinates) === LocationType.PLANET
|
|
155
158
|
}
|
|
156
159
|
|
|
157
160
|
export function deriveLocation(
|
|
158
161
|
gameSeed: Checksum256Type,
|
|
159
|
-
epochSeed: Checksum256Type,
|
|
160
162
|
coordinates: CoordinatesType
|
|
161
163
|
): ServerContract.Types.location_derived {
|
|
162
164
|
const staticProps = deriveLocationStatic(gameSeed, coordinates)
|
|
163
165
|
return ServerContract.Types.location_derived.from({
|
|
164
166
|
static_props: staticProps,
|
|
165
|
-
epoch_props: deriveLocationEpoch(epochSeed, coordinates),
|
|
166
167
|
size: deriveLocationSize(staticProps),
|
|
167
168
|
})
|
|
168
169
|
}
|
|
@@ -1,108 +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 * as schedule from '../scheduling/schedule'
|
|
7
|
-
|
|
8
|
-
export interface ContainerStateInput {
|
|
9
|
-
id: UInt64Type
|
|
10
|
-
owner: string
|
|
11
|
-
name: string
|
|
12
|
-
coordinates: CoordinatesType | {x: number; y: number; z?: number}
|
|
13
|
-
hullmass: number
|
|
14
|
-
capacity: number
|
|
15
|
-
cargomass?: number
|
|
16
|
-
cargo?: ServerContract.Types.cargo_item[]
|
|
17
|
-
schedule?: ServerContract.Types.schedule
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export class Container extends ServerContract.Types.entity_info {
|
|
21
|
-
private _sched?: ScheduleAccessor
|
|
22
|
-
|
|
23
|
-
get name(): string {
|
|
24
|
-
return this.entity_name
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
get sched(): ScheduleAccessor {
|
|
28
|
-
this._sched ??= new ScheduleAccessor(this)
|
|
29
|
-
return this._sched
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
get isIdle(): boolean {
|
|
33
|
-
return this.is_idle
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
isLoading(now: Date): boolean {
|
|
37
|
-
return schedule.isLoading(this, now)
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
isUnloading(now: Date): boolean {
|
|
41
|
-
return schedule.isUnloading(this, now)
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
get location(): Location {
|
|
45
|
-
return Location.from(this.coordinates)
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
get totalMass(): UInt64 {
|
|
49
|
-
return UInt64.from(this.hullmass ?? 0).adding(this.cargomass)
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
get maxCapacity(): UInt64 {
|
|
53
|
-
return UInt64.from(this.capacity)
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
get availableCapacity(): UInt64 {
|
|
57
|
-
const cargo = UInt64.from(this.cargomass)
|
|
58
|
-
return cargo.gte(this.maxCapacity) ? UInt64.from(0) : this.maxCapacity.subtracting(cargo)
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
hasSpace(additionalMass: UInt64): boolean {
|
|
62
|
-
return UInt64.from(this.cargomass).adding(additionalMass).lte(this.maxCapacity)
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
get isFull(): boolean {
|
|
66
|
-
return UInt64.from(this.cargomass).gte(this.maxCapacity)
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
get orbitalAltitude(): number {
|
|
70
|
-
return this.coordinates.z?.toNumber() || 0
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
export function computeContainerCapabilities(stats: Record<string, number>): {
|
|
75
|
-
hullmass: number
|
|
76
|
-
capacity: number
|
|
77
|
-
} {
|
|
78
|
-
const density = stats['density'] ?? 500
|
|
79
|
-
const strength = stats['strength'] ?? 500
|
|
80
|
-
const hardness = stats['hardness'] ?? 500
|
|
81
|
-
const saturation = stats['saturation'] ?? 500
|
|
82
|
-
|
|
83
|
-
const hullmass = 25000 + 75 * density
|
|
84
|
-
|
|
85
|
-
const statSum = strength + hardness + saturation
|
|
86
|
-
const exponent = statSum / 2997
|
|
87
|
-
const capacity = Math.floor(1000000 * 10 ** exponent)
|
|
88
|
-
|
|
89
|
-
return {hullmass, capacity}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
export function computeContainerT2Capabilities(stats: Record<string, number>): {
|
|
93
|
-
hullmass: number
|
|
94
|
-
capacity: number
|
|
95
|
-
} {
|
|
96
|
-
const strength = stats['strength'] ?? 0
|
|
97
|
-
const density = stats['density'] ?? 0
|
|
98
|
-
const hardness = stats['hardness'] ?? 0
|
|
99
|
-
const saturation = stats['saturation'] ?? 0
|
|
100
|
-
|
|
101
|
-
const hullmass = 20000 + 50 * density
|
|
102
|
-
|
|
103
|
-
const statSum = strength + hardness + saturation
|
|
104
|
-
const exponent = statSum / 2500
|
|
105
|
-
const capacity = Math.floor(1500000 * 10 ** exponent)
|
|
106
|
-
|
|
107
|
-
return {hullmass, capacity}
|
|
108
|
-
}
|
|
@@ -1,258 +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
|
-
|
|
12
|
-
export function computeShipHullCapabilities(stats: Record<string, number>): {
|
|
13
|
-
hullmass: number
|
|
14
|
-
capacity: number
|
|
15
|
-
} {
|
|
16
|
-
const density = stats.density ?? 500
|
|
17
|
-
const strength = stats.strength ?? 500
|
|
18
|
-
const hardness = stats.hardness ?? 500
|
|
19
|
-
const saturation = stats.saturation ?? 500
|
|
20
|
-
|
|
21
|
-
const hullmass = 25000 + 75 * density
|
|
22
|
-
const statSum = strength + hardness + saturation
|
|
23
|
-
const exponent = statSum / 2997.0
|
|
24
|
-
const capacity = Math.floor(1000000 * 10 ** exponent)
|
|
25
|
-
|
|
26
|
-
return {hullmass, capacity}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export function computeEngineCapabilities(stats: Record<string, number>): {
|
|
30
|
-
thrust: number
|
|
31
|
-
drain: number
|
|
32
|
-
} {
|
|
33
|
-
const vol = stats.volatility ?? 500
|
|
34
|
-
const thm = stats.thermal ?? 500
|
|
35
|
-
|
|
36
|
-
return {
|
|
37
|
-
thrust: 400 + Math.floor((vol * 3) / 4),
|
|
38
|
-
drain: Math.max(30, 50 - Math.floor(thm / 70)),
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export function computeGeneratorCapabilities(stats: Record<string, number>): {
|
|
43
|
-
capacity: number
|
|
44
|
-
recharge: number
|
|
45
|
-
} {
|
|
46
|
-
const res = stats.resonance ?? 500
|
|
47
|
-
const ref = stats.reflectivity ?? 500
|
|
48
|
-
|
|
49
|
-
return {
|
|
50
|
-
capacity: 300 + Math.floor(res / 6),
|
|
51
|
-
recharge: 1 + Math.floor((ref * 3) / 1000),
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
export function computeGathererCapabilities(stats: Record<string, number>): {
|
|
56
|
-
yield: number
|
|
57
|
-
drain: number
|
|
58
|
-
depth: number
|
|
59
|
-
speed: number
|
|
60
|
-
} {
|
|
61
|
-
const str = stats.strength ?? 500
|
|
62
|
-
const con = stats.conductivity ?? 500
|
|
63
|
-
const ref = stats.reflectivity ?? 500
|
|
64
|
-
const tol = stats.tolerance ?? 500
|
|
65
|
-
|
|
66
|
-
return {
|
|
67
|
-
yield: 200 + str,
|
|
68
|
-
drain: Math.max(250, 1250 - Math.floor((con * 25) / 20)),
|
|
69
|
-
depth: 200 + Math.floor((tol * 3) / 2),
|
|
70
|
-
speed: 100 + Math.floor((ref * 4) / 5),
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
export function computeLoaderCapabilities(stats: Record<string, number>): {
|
|
75
|
-
mass: number
|
|
76
|
-
thrust: number
|
|
77
|
-
quantity: number
|
|
78
|
-
} {
|
|
79
|
-
const hrd = stats.hardness ?? 500
|
|
80
|
-
const pla = stats.plasticity ?? 500
|
|
81
|
-
|
|
82
|
-
return {
|
|
83
|
-
mass: Math.max(200, 2000 - Math.floor(hrd * 2)),
|
|
84
|
-
thrust: 1 + Math.floor(pla / 500),
|
|
85
|
-
quantity: 1,
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
export function computeCrafterCapabilities(stats: Record<string, number>): {
|
|
90
|
-
speed: number
|
|
91
|
-
drain: number
|
|
92
|
-
} {
|
|
93
|
-
const rea = stats.reactivity ?? 500
|
|
94
|
-
const com = stats.composition ?? 500
|
|
95
|
-
|
|
96
|
-
return {
|
|
97
|
-
speed: 100 + Math.floor((rea * 4) / 5),
|
|
98
|
-
drain: Math.max(5, 30 - Math.floor(com / 33)),
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
export function computeHaulerCapabilities(stats: Record<string, number>): {
|
|
103
|
-
capacity: number
|
|
104
|
-
efficiency: number
|
|
105
|
-
drain: number
|
|
106
|
-
} {
|
|
107
|
-
const res = stats.resonance ?? 500
|
|
108
|
-
const con = stats.conductivity ?? 500
|
|
109
|
-
const ref = stats.reflectivity ?? 500
|
|
110
|
-
|
|
111
|
-
return {
|
|
112
|
-
capacity: Math.max(1, 1 + Math.floor(res / 400)),
|
|
113
|
-
efficiency: 2000 + con * 6,
|
|
114
|
-
drain: Math.max(3, 15 - Math.floor(ref / 80)),
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
export function computeStorageCapabilities(
|
|
119
|
-
stats: Record<string, number>,
|
|
120
|
-
baseCapacity: number
|
|
121
|
-
): {
|
|
122
|
-
capacityBonus: number
|
|
123
|
-
} {
|
|
124
|
-
const strength = stats.strength ?? 500
|
|
125
|
-
const hardness = stats.hardness ?? 500
|
|
126
|
-
const saturation = stats.saturation ?? 500
|
|
127
|
-
|
|
128
|
-
const statSum = strength + hardness + saturation
|
|
129
|
-
const capacityBonus = Math.floor(
|
|
130
|
-
(baseCapacity * (10 + Math.floor((statSum * 10) / 2997))) / 100
|
|
131
|
-
)
|
|
132
|
-
|
|
133
|
-
return {capacityBonus}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
export function computeWarehouseHullCapabilities(stats: Record<string, number>): {
|
|
137
|
-
hullmass: number
|
|
138
|
-
capacity: number
|
|
139
|
-
} {
|
|
140
|
-
const density = stats.density ?? 500
|
|
141
|
-
const strength = stats.strength ?? 500
|
|
142
|
-
const hardness = stats.hardness ?? 500
|
|
143
|
-
const saturation = stats.saturation ?? 500
|
|
144
|
-
|
|
145
|
-
const hullmass = 25000 + 75 * density
|
|
146
|
-
const statSum = strength + hardness + saturation
|
|
147
|
-
const exponent = statSum / 2997.0
|
|
148
|
-
const capacity = Math.floor(20000000 * 10 ** exponent)
|
|
149
|
-
|
|
150
|
-
return {hullmass, capacity}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
export interface ShipCapabilities {
|
|
154
|
-
engines?: {thrust: number; drain: number}
|
|
155
|
-
generator?: {capacity: number; recharge: number}
|
|
156
|
-
gatherer?: {yield: number; drain: number; depth: number; speed: number}
|
|
157
|
-
hauler?: {capacity: number; efficiency: number; drain: number}
|
|
158
|
-
loaders?: {mass: number; thrust: number; quantity: number}
|
|
159
|
-
crafter?: {speed: number; drain: number}
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
export function computeShipCapabilities(
|
|
163
|
-
modules: {itemId: number; stats: bigint}[]
|
|
164
|
-
): ShipCapabilities {
|
|
165
|
-
const ship: ShipCapabilities = {}
|
|
166
|
-
|
|
167
|
-
const engineModules = modules.filter((m) => getModuleCapabilityType(m.itemId) === MODULE_ENGINE)
|
|
168
|
-
if (engineModules.length > 0) {
|
|
169
|
-
let totalThrust = 0
|
|
170
|
-
let totalDrain = 0
|
|
171
|
-
for (const m of engineModules) {
|
|
172
|
-
const caps = computeEngineCapabilities(decodeCraftedItemStats(m.itemId, m.stats))
|
|
173
|
-
totalThrust += caps.thrust
|
|
174
|
-
totalDrain += caps.drain
|
|
175
|
-
}
|
|
176
|
-
ship.engines = {thrust: totalThrust, drain: totalDrain}
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
const generatorModules = modules.filter(
|
|
180
|
-
(m) => getModuleCapabilityType(m.itemId) === MODULE_GENERATOR
|
|
181
|
-
)
|
|
182
|
-
if (generatorModules.length > 0) {
|
|
183
|
-
let totalCapacity = 0
|
|
184
|
-
let totalRecharge = 0
|
|
185
|
-
for (const m of generatorModules) {
|
|
186
|
-
const caps = computeGeneratorCapabilities(decodeCraftedItemStats(m.itemId, m.stats))
|
|
187
|
-
totalCapacity += caps.capacity
|
|
188
|
-
totalRecharge += caps.recharge
|
|
189
|
-
}
|
|
190
|
-
ship.generator = {capacity: totalCapacity, recharge: totalRecharge}
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
const gathererModules = modules.filter(
|
|
194
|
-
(m) => getModuleCapabilityType(m.itemId) === MODULE_GATHERER
|
|
195
|
-
)
|
|
196
|
-
if (gathererModules.length > 0) {
|
|
197
|
-
let totalYield = 0
|
|
198
|
-
let totalDrain = 0
|
|
199
|
-
let totalDepth = 0
|
|
200
|
-
let totalSpeed = 0
|
|
201
|
-
for (const m of gathererModules) {
|
|
202
|
-
const caps = computeGathererCapabilities(decodeCraftedItemStats(m.itemId, m.stats))
|
|
203
|
-
totalYield += caps.yield
|
|
204
|
-
totalDrain += caps.drain
|
|
205
|
-
totalDepth += caps.depth
|
|
206
|
-
totalSpeed += caps.speed
|
|
207
|
-
}
|
|
208
|
-
ship.gatherer = {yield: totalYield, drain: totalDrain, depth: totalDepth, speed: totalSpeed}
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
const haulerModules = modules.filter((m) => getModuleCapabilityType(m.itemId) === MODULE_HAULER)
|
|
212
|
-
if (haulerModules.length > 0) {
|
|
213
|
-
let totalCapacity = 0
|
|
214
|
-
let weightedEffNum = 0
|
|
215
|
-
let totalDrain = 0
|
|
216
|
-
for (const m of haulerModules) {
|
|
217
|
-
const caps = computeHaulerCapabilities(decodeCraftedItemStats(m.itemId, m.stats))
|
|
218
|
-
totalCapacity += caps.capacity
|
|
219
|
-
weightedEffNum += caps.efficiency * caps.capacity
|
|
220
|
-
totalDrain += caps.drain
|
|
221
|
-
}
|
|
222
|
-
ship.hauler = {
|
|
223
|
-
capacity: totalCapacity,
|
|
224
|
-
efficiency: totalCapacity > 0 ? Math.floor(weightedEffNum / totalCapacity) : 0,
|
|
225
|
-
drain: totalDrain,
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
const loaderModules = modules.filter((m) => getModuleCapabilityType(m.itemId) === MODULE_LOADER)
|
|
230
|
-
if (loaderModules.length > 0) {
|
|
231
|
-
let totalMass = 0
|
|
232
|
-
let totalThrust = 0
|
|
233
|
-
let totalQuantity = 0
|
|
234
|
-
for (const m of loaderModules) {
|
|
235
|
-
const caps = computeLoaderCapabilities(decodeCraftedItemStats(m.itemId, m.stats))
|
|
236
|
-
totalMass += caps.mass
|
|
237
|
-
totalThrust += caps.thrust
|
|
238
|
-
totalQuantity += caps.quantity
|
|
239
|
-
}
|
|
240
|
-
ship.loaders = {mass: totalMass, thrust: totalThrust, quantity: totalQuantity}
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
const crafterModules = modules.filter(
|
|
244
|
-
(m) => getModuleCapabilityType(m.itemId) === MODULE_CRAFTER
|
|
245
|
-
)
|
|
246
|
-
if (crafterModules.length > 0) {
|
|
247
|
-
let totalSpeed = 0
|
|
248
|
-
let totalDrain = 0
|
|
249
|
-
for (const m of crafterModules) {
|
|
250
|
-
const caps = computeCrafterCapabilities(decodeCraftedItemStats(m.itemId, m.stats))
|
|
251
|
-
totalSpeed += caps.speed
|
|
252
|
-
totalDrain += caps.drain
|
|
253
|
-
}
|
|
254
|
-
ship.crafter = {speed: totalSpeed, drain: totalDrain}
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
return ship
|
|
258
|
-
}
|