@shipload/sdk 2.0.0-rc3 → 2.0.0-rc5
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 +81 -15
- package/lib/shipload.js +2091 -945
- package/lib/shipload.js.map +1 -1
- package/lib/shipload.m.js +2082 -940
- package/lib/shipload.m.js.map +1 -1
- package/package.json +1 -1
- package/src/contracts/server.ts +71 -1
- package/src/data/items.json +15 -14
- package/src/data/nebula-adjectives.json +211 -0
- package/src/data/nebula-nouns.json +151 -0
- package/src/data/syllables.json +1386 -780
- package/src/derivation/index.ts +8 -6
- package/src/derivation/resources.ts +54 -53
- package/src/derivation/stats.ts +70 -0
- package/src/derivation/stratum.ts +20 -18
- package/src/index-module.ts +10 -7
- package/src/market/items.ts +1 -1
- package/src/market/market.ts +4 -17
- package/src/types.ts +3 -3
- package/src/utils/system.ts +44 -10
package/src/derivation/index.ts
CHANGED
|
@@ -6,13 +6,13 @@ export {
|
|
|
6
6
|
getResourceWeight,
|
|
7
7
|
getLocationCandidates,
|
|
8
8
|
getDepthThreshold,
|
|
9
|
-
|
|
9
|
+
getResourceTier,
|
|
10
10
|
depthScaleFactor,
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
11
|
+
DEPTH_THRESHOLD_T1,
|
|
12
|
+
DEPTH_THRESHOLD_T2,
|
|
13
|
+
DEPTH_THRESHOLD_T3,
|
|
14
|
+
DEPTH_THRESHOLD_T4,
|
|
15
|
+
DEPTH_THRESHOLD_T5,
|
|
16
16
|
LOCATION_MIN_DEPTH,
|
|
17
17
|
LOCATION_MAX_DEPTH,
|
|
18
18
|
YIELD_THRESHOLD,
|
|
@@ -23,3 +23,5 @@ export {
|
|
|
23
23
|
PLANET_SUBTYPE_OCEAN,
|
|
24
24
|
PLANET_SUBTYPE_INDUSTRIAL,
|
|
25
25
|
} from './resources'
|
|
26
|
+
|
|
27
|
+
export * from './stats'
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {ResourceTier} from '../types'
|
|
2
2
|
|
|
3
|
-
export const
|
|
4
|
-
export const
|
|
5
|
-
export const
|
|
6
|
-
export const
|
|
7
|
-
export const
|
|
3
|
+
export const DEPTH_THRESHOLD_T1 = 0
|
|
4
|
+
export const DEPTH_THRESHOLD_T2 = 2000
|
|
5
|
+
export const DEPTH_THRESHOLD_T3 = 10000
|
|
6
|
+
export const DEPTH_THRESHOLD_T4 = 30000
|
|
7
|
+
export const DEPTH_THRESHOLD_T5 = 55000
|
|
8
8
|
|
|
9
9
|
export const LOCATION_MIN_DEPTH = 500
|
|
10
10
|
export const LOCATION_MAX_DEPTH = 65535
|
|
@@ -20,84 +20,85 @@ export const PLANET_SUBTYPE_INDUSTRIAL = 5
|
|
|
20
20
|
|
|
21
21
|
interface ResourceEntry {
|
|
22
22
|
id: number
|
|
23
|
-
|
|
23
|
+
tier: ResourceTier
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
const RESOURCE_CATALOG: ResourceEntry[] = [
|
|
27
|
-
{id: 26,
|
|
28
|
-
{id:
|
|
29
|
-
{id:
|
|
30
|
-
{id:
|
|
31
|
-
{id:
|
|
32
|
-
{id:
|
|
33
|
-
{id:
|
|
34
|
-
{id:
|
|
35
|
-
{id:
|
|
36
|
-
{id:
|
|
37
|
-
{id:
|
|
38
|
-
{id:
|
|
39
|
-
{id:
|
|
40
|
-
{id:
|
|
27
|
+
{id: 26, tier: 't1'},
|
|
28
|
+
{id: 13, tier: 't2'},
|
|
29
|
+
{id: 24, tier: 't3'},
|
|
30
|
+
{id: 29, tier: 't1'},
|
|
31
|
+
{id: 47, tier: 't2'},
|
|
32
|
+
{id: 79, tier: 't3'},
|
|
33
|
+
{id: 1, tier: 't1'},
|
|
34
|
+
{id: 2, tier: 't2'},
|
|
35
|
+
{id: 18, tier: 't3'},
|
|
36
|
+
{id: 14, tier: 't1'},
|
|
37
|
+
{id: 1000, tier: 't2'},
|
|
38
|
+
{id: 1001, tier: 't3'},
|
|
39
|
+
{id: 6, tier: 't1'},
|
|
40
|
+
{id: 1003, tier: 't2'},
|
|
41
|
+
{id: 1002, tier: 't3'},
|
|
41
42
|
]
|
|
42
43
|
|
|
43
|
-
export function getDepthThreshold(
|
|
44
|
-
switch (
|
|
45
|
-
case '
|
|
46
|
-
return
|
|
47
|
-
case '
|
|
48
|
-
return
|
|
49
|
-
case '
|
|
50
|
-
return
|
|
51
|
-
case '
|
|
52
|
-
return
|
|
53
|
-
case '
|
|
54
|
-
return
|
|
44
|
+
export function getDepthThreshold(tier: ResourceTier): number {
|
|
45
|
+
switch (tier) {
|
|
46
|
+
case 't1':
|
|
47
|
+
return DEPTH_THRESHOLD_T1
|
|
48
|
+
case 't2':
|
|
49
|
+
return DEPTH_THRESHOLD_T2
|
|
50
|
+
case 't3':
|
|
51
|
+
return DEPTH_THRESHOLD_T3
|
|
52
|
+
case 't4':
|
|
53
|
+
return DEPTH_THRESHOLD_T4
|
|
54
|
+
case 't5':
|
|
55
|
+
return DEPTH_THRESHOLD_T5
|
|
55
56
|
}
|
|
56
57
|
}
|
|
57
58
|
|
|
58
|
-
export function
|
|
59
|
+
export function getResourceTier(itemId: number): ResourceTier {
|
|
59
60
|
const entry = RESOURCE_CATALOG.find((r) => r.id === itemId)
|
|
60
|
-
return entry ? entry.
|
|
61
|
+
return entry ? entry.tier : 't5'
|
|
61
62
|
}
|
|
62
63
|
|
|
63
64
|
export function getResourceWeight(itemId: number, stratum: number): number {
|
|
64
|
-
const
|
|
65
|
-
const threshold = getDepthThreshold(
|
|
65
|
+
const tier = getResourceTier(itemId)
|
|
66
|
+
const threshold = getDepthThreshold(tier)
|
|
66
67
|
if (stratum < threshold) return 0
|
|
67
68
|
|
|
68
69
|
const depthAbove = stratum - threshold
|
|
69
70
|
|
|
70
|
-
switch (
|
|
71
|
-
case '
|
|
71
|
+
switch (tier) {
|
|
72
|
+
case 't1':
|
|
72
73
|
if (stratum < 2000) return 100
|
|
73
74
|
if (stratum < 10000) return 80
|
|
74
75
|
if (stratum < 30000) return 50
|
|
75
76
|
return 30
|
|
76
|
-
case '
|
|
77
|
+
case 't2':
|
|
77
78
|
if (depthAbove < 3000) return 40
|
|
78
79
|
if (depthAbove < 8000) return 60
|
|
79
80
|
return 50
|
|
80
|
-
case '
|
|
81
|
+
case 't3':
|
|
81
82
|
if (depthAbove < 5000) return 20
|
|
82
83
|
if (depthAbove < 15000) return 35
|
|
83
84
|
return 40
|
|
84
|
-
case '
|
|
85
|
+
case 't4':
|
|
85
86
|
if (depthAbove < 10000) return 10
|
|
86
87
|
if (depthAbove < 25000) return 20
|
|
87
88
|
return 30
|
|
88
|
-
case '
|
|
89
|
+
case 't5':
|
|
89
90
|
return 10
|
|
90
91
|
}
|
|
91
92
|
}
|
|
92
93
|
|
|
93
|
-
const ASTEROID_RESOURCES = [26,
|
|
94
|
-
const NEBULA_RESOURCES = [1, 2, 18
|
|
95
|
-
const GAS_GIANT_RESOURCES = [1, 2, 18,
|
|
96
|
-
const ROCKY_RESOURCES = [26,
|
|
97
|
-
const TERRESTRIAL_RESOURCES = [6, 1003, 1002
|
|
98
|
-
const ICY_RESOURCES = [
|
|
99
|
-
const OCEAN_RESOURCES = [1,
|
|
100
|
-
const INDUSTRIAL_RESOURCES = [26,
|
|
94
|
+
const ASTEROID_RESOURCES = [26, 13, 24, 29, 47]
|
|
95
|
+
const NEBULA_RESOURCES = [47, 79, 1, 2, 18]
|
|
96
|
+
const GAS_GIANT_RESOURCES = [1, 2, 18, 14, 6]
|
|
97
|
+
const ROCKY_RESOURCES = [26, 13, 24, 14, 1000, 1001, 1002]
|
|
98
|
+
const TERRESTRIAL_RESOURCES = [29, 47, 14, 1000, 6, 1003, 1002]
|
|
99
|
+
const ICY_RESOURCES = [26, 1, 2, 14, 1001, 6, 1003]
|
|
100
|
+
const OCEAN_RESOURCES = [29, 79, 1, 18, 6, 1003, 1002]
|
|
101
|
+
const INDUSTRIAL_RESOURCES = [26, 13, 24, 29, 79, 1000, 1001]
|
|
101
102
|
|
|
102
103
|
export function getLocationCandidates(locationType: number, subtype: number): number[] {
|
|
103
104
|
if (locationType === 2) return ASTEROID_RESOURCES
|
|
@@ -128,8 +129,8 @@ export function getEligibleResources(
|
|
|
128
129
|
): number[] {
|
|
129
130
|
const candidates = getLocationCandidates(locationType, subtype)
|
|
130
131
|
return candidates.filter((itemId) => {
|
|
131
|
-
const
|
|
132
|
-
const threshold = getDepthThreshold(
|
|
132
|
+
const tier = getResourceTier(itemId)
|
|
133
|
+
const threshold = getDepthThreshold(tier)
|
|
133
134
|
return stratum >= threshold
|
|
134
135
|
})
|
|
135
136
|
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import type {ResourceCategory} from '../types'
|
|
2
|
+
|
|
3
|
+
export interface StatDefinition {
|
|
4
|
+
key: string
|
|
5
|
+
label: string
|
|
6
|
+
abbreviation: string
|
|
7
|
+
purpose: string
|
|
8
|
+
inverted?: boolean
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const METAL_STATS: StatDefinition[] = [
|
|
12
|
+
{key: 'strength', label: 'Strength', abbreviation: 'STR', purpose: 'Raw structural/mechanical force'},
|
|
13
|
+
{key: 'tolerance', label: 'Tolerance', abbreviation: 'TOL', purpose: 'Ability to withstand heat, pressure, and stress extremes'},
|
|
14
|
+
{key: 'density', label: 'Density', abbreviation: 'DEN', purpose: 'Mass per unit', inverted: true},
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
const PRECIOUS_STATS: StatDefinition[] = [
|
|
18
|
+
{key: 'conductivity', label: 'Conductivity', abbreviation: 'CON', purpose: 'Efficiency of energy/signal transfer'},
|
|
19
|
+
{key: 'ductility', label: 'Ductility', abbreviation: 'DUC', purpose: 'Ability to be worked into fine, precise shapes'},
|
|
20
|
+
{key: 'reflectivity', label: 'Reflectivity', abbreviation: 'REF', purpose: 'Surface quality for heat management and precision optics'},
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
const GAS_STATS: StatDefinition[] = [
|
|
24
|
+
{key: 'volatility', label: 'Volatility', abbreviation: 'VOL', purpose: 'Energy release potential for propulsion and force'},
|
|
25
|
+
{key: 'reactivity', label: 'Reactivity', abbreviation: 'REA', purpose: 'Chemical interaction speed for processing and penetration'},
|
|
26
|
+
{key: 'thermal', label: 'Thermal', abbreviation: 'THM', purpose: 'Heat capacity for thermal management'},
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
const MINERAL_STATS: StatDefinition[] = [
|
|
30
|
+
{key: 'resonance', label: 'Resonance', abbreviation: 'RES', purpose: 'Energy field interaction — storage, focusing, projection'},
|
|
31
|
+
{key: 'hardness', label: 'Hardness', abbreviation: 'HRD', purpose: 'Resistance to wear — cutting surfaces, penetration'},
|
|
32
|
+
{key: 'clarity', label: 'Clarity', abbreviation: 'CLR', purpose: 'Crystalline perfection — precision optics'},
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
const ORGANIC_STATS: StatDefinition[] = [
|
|
36
|
+
{key: 'plasticity', label: 'Plasticity', abbreviation: 'PLA', purpose: 'Ease of reshaping — speeds processing'},
|
|
37
|
+
{key: 'insulation', label: 'Insulation', abbreviation: 'INS', purpose: 'Energy containment — reduces energy loss'},
|
|
38
|
+
{key: 'purity', label: 'Purity', abbreviation: 'PUR', purpose: 'Biological cleanliness — better composites and lubricants'},
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
const STAT_MAP: Record<ResourceCategory, StatDefinition[]> = {
|
|
42
|
+
metal: METAL_STATS,
|
|
43
|
+
precious: PRECIOUS_STATS,
|
|
44
|
+
gas: GAS_STATS,
|
|
45
|
+
mineral: MINERAL_STATS,
|
|
46
|
+
organic: ORGANIC_STATS,
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function getStatDefinitions(category: ResourceCategory): StatDefinition[] {
|
|
50
|
+
return STAT_MAP[category]
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function getStatName(category: ResourceCategory, index: 0 | 1 | 2): StatDefinition {
|
|
54
|
+
return STAT_MAP[category][index]
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface NamedStats {
|
|
58
|
+
definitions: StatDefinition[]
|
|
59
|
+
values: [number, number, number]
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function resolveStats(
|
|
63
|
+
category: ResourceCategory,
|
|
64
|
+
stats: {stat1: number; stat2: number; stat3: number}
|
|
65
|
+
): NamedStats {
|
|
66
|
+
return {
|
|
67
|
+
definitions: STAT_MAP[category],
|
|
68
|
+
values: [stats.stat1, stats.stat2, stats.stat3],
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -16,10 +16,9 @@ export interface StratumInfo {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
export interface ResourceStats {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
resonance: number
|
|
19
|
+
stat1: number
|
|
20
|
+
stat2: number
|
|
21
|
+
stat3: number
|
|
23
22
|
}
|
|
24
23
|
|
|
25
24
|
export function deriveStratum(
|
|
@@ -94,23 +93,26 @@ export function deriveStratum(
|
|
|
94
93
|
}
|
|
95
94
|
|
|
96
95
|
export function deriveResourceStats(seed: bigint): ResourceStats {
|
|
97
|
-
const
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
96
|
+
const seedBytes = new Uint8Array(8)
|
|
97
|
+
for (let i = 7; i >= 0; i--) {
|
|
98
|
+
seedBytes[i] = Number(seed & 0xFFn)
|
|
99
|
+
seed >>= 8n
|
|
100
|
+
}
|
|
101
|
+
const hashResult = Checksum256.hash(Bytes.from(seedBytes))
|
|
101
102
|
const hashBytes = hashResult.array
|
|
102
103
|
|
|
103
|
-
const
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
104
|
+
const extractU16 = (offset: number): number => (hashBytes[offset] << 8) | hashBytes[offset + 1]
|
|
105
|
+
|
|
106
|
+
const weibull = (raw: number): number => {
|
|
107
|
+
const u = raw / 65536
|
|
108
|
+
let x = 0.27 * Math.sqrt(-Math.log(1 - u))
|
|
109
|
+
if (x > 1) x = 1
|
|
110
|
+
return Math.floor(x * 999) + 1
|
|
111
|
+
}
|
|
109
112
|
|
|
110
113
|
return {
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
resonance: (extractU32(12) % 1000) + 1,
|
|
114
|
+
stat1: weibull(extractU16(0)),
|
|
115
|
+
stat2: weibull(extractU16(2)),
|
|
116
|
+
stat3: weibull(extractU16(4)),
|
|
115
117
|
}
|
|
116
118
|
}
|
package/src/index-module.ts
CHANGED
|
@@ -47,7 +47,7 @@ export type {EntityRefInput} from './managers/actions'
|
|
|
47
47
|
export {getItem, getItems, itemIds} from './market/items'
|
|
48
48
|
export {getCurrentEpoch, getEpochInfo} from './scheduling/epoch'
|
|
49
49
|
export type {EpochInfo} from './scheduling/epoch'
|
|
50
|
-
export {marketPrice, marketPrices, getRarity, Rarities} from './market/market'
|
|
50
|
+
export {marketPrice, marketPrices, getRarity, getRarityMultiplier, Rarities} from './market/market'
|
|
51
51
|
export type {Rarity} from './market/market'
|
|
52
52
|
export {
|
|
53
53
|
getSystemName,
|
|
@@ -67,13 +67,13 @@ export {
|
|
|
67
67
|
getResourceWeight,
|
|
68
68
|
getLocationCandidates,
|
|
69
69
|
getDepthThreshold,
|
|
70
|
-
|
|
70
|
+
getResourceTier,
|
|
71
71
|
depthScaleFactor,
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
72
|
+
DEPTH_THRESHOLD_T1,
|
|
73
|
+
DEPTH_THRESHOLD_T2,
|
|
74
|
+
DEPTH_THRESHOLD_T3,
|
|
75
|
+
DEPTH_THRESHOLD_T4,
|
|
76
|
+
DEPTH_THRESHOLD_T5,
|
|
77
77
|
LOCATION_MIN_DEPTH,
|
|
78
78
|
LOCATION_MAX_DEPTH,
|
|
79
79
|
PLANET_SUBTYPE_GAS_GIANT,
|
|
@@ -86,6 +86,9 @@ export {
|
|
|
86
86
|
|
|
87
87
|
export type {StratumInfo, ResourceStats} from './derivation'
|
|
88
88
|
|
|
89
|
+
export {getStatDefinitions, getStatName, resolveStats} from './derivation'
|
|
90
|
+
export type {StatDefinition, NamedStats} from './derivation'
|
|
91
|
+
|
|
89
92
|
export {hash, hash512} from './utils/hash'
|
|
90
93
|
|
|
91
94
|
export type {Deal, FindDealsOptions} from './trading/deal'
|
package/src/market/items.ts
CHANGED
package/src/market/market.ts
CHANGED
|
@@ -14,9 +14,9 @@ export enum Rarities {
|
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
export interface Rarity {
|
|
17
|
-
rarity: Rarities
|
|
18
|
-
minMultiplier: number
|
|
19
|
-
maxMultiplier: number
|
|
17
|
+
rarity: Rarities
|
|
18
|
+
minMultiplier: number
|
|
19
|
+
maxMultiplier: number
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
export function getRarity(
|
|
@@ -29,77 +29,66 @@ export function getRarity(
|
|
|
29
29
|
const rarityRoll = roll(gameSeed, seed)
|
|
30
30
|
|
|
31
31
|
if (rarityRoll < 13) {
|
|
32
|
-
// (Orange) ~0.02% chance = incredibly high value
|
|
33
32
|
return {
|
|
34
33
|
rarity: Rarities.legendary,
|
|
35
34
|
minMultiplier: 2.25,
|
|
36
35
|
maxMultiplier: 3.0,
|
|
37
36
|
}
|
|
38
37
|
} else if (rarityRoll < 176) {
|
|
39
|
-
// (Purple) ~0.25% chance = super high value
|
|
40
38
|
return {
|
|
41
39
|
rarity: Rarities.epic,
|
|
42
40
|
minMultiplier: 1.75,
|
|
43
41
|
maxMultiplier: 2.25,
|
|
44
42
|
}
|
|
45
43
|
} else if (rarityRoll < 996) {
|
|
46
|
-
// (Blue) ~1.25% chance = very high value
|
|
47
44
|
return {
|
|
48
45
|
rarity: Rarities.rare,
|
|
49
46
|
minMultiplier: 1.4,
|
|
50
47
|
maxMultiplier: 1.75,
|
|
51
48
|
}
|
|
52
49
|
} else if (rarityRoll < 2966) {
|
|
53
|
-
// (Green) ~3.00% chance = high value
|
|
54
50
|
return {
|
|
55
51
|
rarity: Rarities.uncommon,
|
|
56
52
|
minMultiplier: 1.225,
|
|
57
53
|
maxMultiplier: 1.4,
|
|
58
54
|
}
|
|
59
55
|
} else if (rarityRoll < 19568) {
|
|
60
|
-
// (White) ~25.33% chance = slightly higher value
|
|
61
56
|
return {
|
|
62
57
|
rarity: Rarities.common,
|
|
63
58
|
minMultiplier: 1.07,
|
|
64
59
|
maxMultiplier: 1.225,
|
|
65
60
|
}
|
|
66
61
|
} else if (rarityRoll < 45988) {
|
|
67
|
-
// ~40.30% chance = no value change
|
|
68
62
|
return {
|
|
69
63
|
rarity: Rarities.trash,
|
|
70
64
|
minMultiplier: 1,
|
|
71
65
|
maxMultiplier: 1.07,
|
|
72
|
-
}
|
|
66
|
+
}
|
|
73
67
|
} else if (rarityRoll < 62508) {
|
|
74
|
-
// (White) ~25.33% chance = slightly lower value
|
|
75
68
|
return {
|
|
76
69
|
rarity: Rarities.common,
|
|
77
70
|
minMultiplier: 0.925,
|
|
78
71
|
maxMultiplier: 1,
|
|
79
72
|
}
|
|
80
73
|
} else if (rarityRoll < 64518) {
|
|
81
|
-
// (Green) ~3.00% chance = low value
|
|
82
74
|
return {
|
|
83
75
|
rarity: Rarities.uncommon,
|
|
84
76
|
minMultiplier: 0.77,
|
|
85
77
|
maxMultiplier: 0.925,
|
|
86
78
|
}
|
|
87
79
|
} else if (rarityRoll < 65437) {
|
|
88
|
-
// (Blue) ~1.25% chance = very low value
|
|
89
80
|
return {
|
|
90
81
|
rarity: Rarities.rare,
|
|
91
82
|
minMultiplier: 0.595,
|
|
92
83
|
maxMultiplier: 0.77,
|
|
93
84
|
}
|
|
94
85
|
} else if (rarityRoll < 65523) {
|
|
95
|
-
// (Purple) ~0.25% chance = super low value
|
|
96
86
|
return {
|
|
97
87
|
rarity: Rarities.epic,
|
|
98
88
|
minMultiplier: 0.41,
|
|
99
89
|
maxMultiplier: 0.595,
|
|
100
90
|
}
|
|
101
91
|
} else {
|
|
102
|
-
// (Orange) ~0.02% chance = incredibly low value
|
|
103
92
|
return {
|
|
104
93
|
rarity: Rarities.legendary,
|
|
105
94
|
minMultiplier: 0.285,
|
|
@@ -178,8 +167,6 @@ export function marketPrice(
|
|
|
178
167
|
const item = getItem(goodId)
|
|
179
168
|
let price = Number(item.base_price)
|
|
180
169
|
|
|
181
|
-
// Rarity multiplier of the deal (changes with epoch)
|
|
182
|
-
// Large impact range on price, from 0.285x to 3.0x
|
|
183
170
|
const rarityMultiplier = getRarityMultiplier(gameSeed, state.seed, location, goodId)
|
|
184
171
|
price *= rarityMultiplier
|
|
185
172
|
|
package/src/types.ts
CHANGED
|
@@ -132,8 +132,8 @@ export interface Distance {
|
|
|
132
132
|
distance: UInt16
|
|
133
133
|
}
|
|
134
134
|
|
|
135
|
-
export type ResourceCategory = 'metal' | 'gas' | 'mineral' | 'organic'
|
|
136
|
-
export type
|
|
135
|
+
export type ResourceCategory = 'metal' | 'precious' | 'gas' | 'mineral' | 'organic'
|
|
136
|
+
export type ResourceTier = 't1' | 't2' | 't3' | 't4' | 't5'
|
|
137
137
|
|
|
138
138
|
@Struct.type('item')
|
|
139
139
|
export class Item extends Struct {
|
|
@@ -150,7 +150,7 @@ export class Item extends Struct {
|
|
|
150
150
|
@Struct.field('string')
|
|
151
151
|
category!: ResourceCategory
|
|
152
152
|
@Struct.field('string')
|
|
153
|
-
|
|
153
|
+
tier!: ResourceTier
|
|
154
154
|
@Struct.field('string')
|
|
155
155
|
color!: string
|
|
156
156
|
}
|
package/src/utils/system.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import {Checksum256, Checksum256Type, UInt8} from '@wharfkit/antelope'
|
|
1
|
+
import {Checksum256, Checksum256Type, Checksum512, UInt8} from '@wharfkit/antelope'
|
|
2
2
|
import {hash512} from './hash'
|
|
3
3
|
import {Coordinates, CoordinatesType, LocationType} from '../types'
|
|
4
4
|
import {ServerContract} from '../contracts'
|
|
5
5
|
import syllables from '../data/syllables.json'
|
|
6
|
+
import nebulaAdjectives from '../data/nebula-adjectives.json'
|
|
7
|
+
import nebulaNouns from '../data/nebula-nouns.json'
|
|
6
8
|
|
|
7
9
|
const LOCATION_EXISTS_THRESHOLD = 0x10
|
|
8
10
|
const LOCATION_ACTIVE_THRESHOLD = 0x80
|
|
@@ -31,23 +33,55 @@ export function isExtractableLocation(locationType: LocationType): boolean {
|
|
|
31
33
|
return locationType !== LocationType.EMPTY
|
|
32
34
|
}
|
|
33
35
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
const
|
|
40
|
-
const hashResult = hash512(seed, seedStr)
|
|
41
|
-
const syllableCount = 1 + (hashResult.array[0] % 3)
|
|
36
|
+
function uint16(hash: Checksum512, offset: number): number {
|
|
37
|
+
return (hash.array[offset] << 8) | hash.array[offset + 1]
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function generatePlanetName(hashResult: Checksum512): string {
|
|
41
|
+
const syllableCount = 2 + (hashResult.array[0] % 2)
|
|
42
42
|
const name: string[] = []
|
|
43
43
|
for (let i = 0; i < syllableCount; i++) {
|
|
44
|
-
const index = hashResult
|
|
44
|
+
const index = uint16(hashResult, 1 + i * 2) % syllables.length
|
|
45
45
|
const syllable = syllables[index]
|
|
46
46
|
name.push(i > 0 ? syllable.toLowerCase() : syllable)
|
|
47
47
|
}
|
|
48
48
|
return name.join('')
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
+
function generateAsteroidName(hashResult: Checksum512): string {
|
|
52
|
+
const A = 65
|
|
53
|
+
const letter1 = String.fromCharCode(A + (hashResult.array[0] % 26))
|
|
54
|
+
const letter2 = String.fromCharCode(A + (hashResult.array[1] % 26))
|
|
55
|
+
const num = (uint16(hashResult, 2) % 9000) + 1000
|
|
56
|
+
return `${letter1}${letter2}-${num}`
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function generateNebulaName(hashResult: Checksum512): string {
|
|
60
|
+
const adjIdx = uint16(hashResult, 0) % nebulaAdjectives.length
|
|
61
|
+
const nounIdx = uint16(hashResult, 2) % nebulaNouns.length
|
|
62
|
+
return `${nebulaAdjectives[adjIdx]} ${nebulaNouns[nounIdx]}`
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function getSystemName(gameSeed: Checksum256Type, location: CoordinatesType): string {
|
|
66
|
+
const seed = Checksum256.from(gameSeed)
|
|
67
|
+
const locationType = getLocationType(seed, location)
|
|
68
|
+
if (locationType === LocationType.EMPTY) {
|
|
69
|
+
throw new Error("System doesn't exist at location")
|
|
70
|
+
}
|
|
71
|
+
const seedStr = `${location.x}-${location.y}-${locationType}-name`
|
|
72
|
+
const hashResult = hash512(seed, seedStr)
|
|
73
|
+
switch (locationType) {
|
|
74
|
+
case LocationType.PLANET:
|
|
75
|
+
return generatePlanetName(hashResult)
|
|
76
|
+
case LocationType.ASTEROID:
|
|
77
|
+
return generateAsteroidName(hashResult)
|
|
78
|
+
case LocationType.NEBULA:
|
|
79
|
+
return generateNebulaName(hashResult)
|
|
80
|
+
default:
|
|
81
|
+
return generatePlanetName(hashResult)
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
51
85
|
export function hasSystem(gameSeed: Checksum256Type, coordinates: CoordinatesType): boolean {
|
|
52
86
|
return getLocationType(gameSeed, coordinates) !== LocationType.EMPTY
|
|
53
87
|
}
|