1
mirror of https://github.com/thepeacockproject/Peacock synced 2025-02-23 03:35:25 +01:00

Added service for mastery data ()

Added simplified mastery data for all locations
Added runtime generation of the full mastery data
Added initial support for profile progression
Reworked code around loading of resources to be more generic
This commit is contained in:
Lennard Fonteijn 2023-01-20 22:00:20 +01:00 committed by GitHub
parent e238ecf720
commit 85a55d4b48
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
33 changed files with 3035 additions and 66 deletions

1
.gitignore vendored

@ -37,6 +37,7 @@ offlineassets.zip
resources/contracts.br
resources/challenges
resources/mastery
/*.plugin.*
/*Plugin.*

@ -0,0 +1,182 @@
import { getSubLocationByName } from "components/contracts/dataGen"
import { log, LogLevel } from "components/loggingInterop"
import {
getConfig,
getVersionedConfig,
} from "../../components/configSwizzleManager"
import { getUserData } from "../../components/databaseHandler"
import {
MasteryData,
MasteryDataTemplate,
MasteryDrop,
MasteryPackage,
} from "../../components/types/mastery"
import {
CompletionData,
GameVersion,
Unlockable,
} from "../../components/types/types"
import { xpRequiredForLevel } from "../../components/utils"
export class MasteryService {
private masteryData: Map<string, MasteryPackage> = new Map()
registerMasteryData(masteryPackage: MasteryPackage) {
this.masteryData.set(masteryPackage.Id, masteryPackage)
}
getMasteryDataForDestination(
locationParentId: string,
gameVersion: GameVersion,
userId: string,
): MasteryData[] {
return this.getMasteryData(locationParentId, gameVersion, userId)
}
getMasteryDataForLocation(
locationId: string,
gameVersion: GameVersion,
userId: string,
): MasteryDataTemplate {
const subLocation: Unlockable = getSubLocationByName(
locationId,
gameVersion,
)
const masteryDataTemplate: MasteryDataTemplate =
getConfig<MasteryDataTemplate>(
"MasteryDataForLocationTemplate",
true,
)
const masteryData = this.getMasteryData(
subLocation.Properties.ParentLocation,
gameVersion,
userId,
)
return {
template: masteryDataTemplate,
data: {
Location: subLocation,
MasteryData: masteryData,
},
}
}
getCompletionData(
locationParentId: string,
gameVersion: GameVersion,
userId: string,
): CompletionData {
if (!this.masteryData.has(locationParentId)) {
return undefined
}
//Get the mastery data
const masteryData: MasteryPackage =
this.masteryData.get(locationParentId)
//Get the user profile
const userProfile = getUserData(userId, gameVersion)
//Gather all required data
const lowerCaseLocationParentId = locationParentId.toLowerCase()
userProfile.Extensions.progression.Locations[
lowerCaseLocationParentId
] ??= {
Xp: 0,
Level: 1,
}
const locationData =
userProfile.Extensions.progression.Locations[
lowerCaseLocationParentId
]
const maxLevel = masteryData.MaxLevel || 20
const nextLevel: number = Math.max(
0,
Math.min(locationData.Level + 1, maxLevel),
)
const nextLevelXp: number = xpRequiredForLevel(nextLevel)
return {
Level: locationData.Level,
MaxLevel: maxLevel,
XP: locationData.Xp,
Completion: locationData.Xp / nextLevelXp,
XpLeft: nextLevelXp - locationData.Xp,
Id: masteryData.Id,
SubLocationId: masteryData.Id,
HideProgression: false,
IsLocationProgression: true,
Name: undefined,
}
}
private getMasteryData(
locationParentId: string,
gameVersion: GameVersion,
userId: string,
): MasteryData[] {
if (!this.masteryData.has(locationParentId)) {
return []
}
//Get the mastery data
const masteryData: MasteryPackage =
this.masteryData.get(locationParentId)
//Put all Ids into a set for quick lookup
const dropIdSet = new Set(masteryData.Drops.map((drop) => drop.Id))
//Get all unlockables with matching Ids
const unlockableData: Unlockable[] = getVersionedConfig<Unlockable[]>(
"allunlockables",
gameVersion,
true,
).filter((unlockable) => dropIdSet.has(unlockable.Id))
//Put all unlockabkes in a map for quick lookup
const unlockableMap = new Map(
unlockableData.map((unlockable) => [unlockable.Id, unlockable]),
)
//Map all the data into a new structure
const completionData = this.getCompletionData(
locationParentId,
gameVersion,
userId,
)
const drops: MasteryDrop[] = masteryData.Drops.filter((drop) => {
if (!unlockableMap.has(drop.Id)) {
log(LogLevel.DEBUG, `No unlockable found for ${drop.Id}`)
return false
}
return true
}).map((drop) => {
const unlockable: Unlockable = unlockableMap.get(drop.Id)
return {
IsLevelMarker: false,
Unlockable: unlockable,
Level: drop.Level,
IsLocked: drop.Level > completionData.Level,
TypeLocaKey: `UI_MENU_PAGE_MASTERY_UNLOCKABLE_NAME_${unlockable.Type}`,
}
})
return [
{
CompletionData: completionData,
Drops: drops,
},
]
}
}

@ -105,6 +105,7 @@ import scoreoverviewtemplate from "../static/scoreoverviewtemplate.json"
import PeacockGameChangerProperties from "../static/PeacockGameChangerProperties.json"
import MultiplayerPresets from "../static/MultiplayerPresets.json"
import LobbySlimTemplate from "../static/LobbySlimTemplate.json"
import MasteryDataForLocationTemplate from "../static/MasteryDataForLocationTemplate.json"
import type { GameVersion } from "./types/types"
import { fastClone } from "./utils"
@ -196,6 +197,7 @@ const configs: Record<string, unknown> = {
PeacockGameChangerProperties,
MultiplayerPresets,
LobbySlimTemplate,
MasteryDataForLocationTemplate,
}
Object.keys(configs).forEach((cfg) => {

@ -97,24 +97,39 @@ export function generateCompletionData(
gameVersion: GameVersion,
isParentLocation = false,
): CompletionData {
// TODO(v6/v7): fetch actual statistics from the user's profile.
const subLocation = getSubLocationByName(subLocationId, gameVersion)
return {
Level: 20,
MaxLevel: 20,
XP: 0,
Completion: 1,
XpLeft: 6000,
Id: isParentLocation
? subLocationId
: subLocation?.Properties?.ParentLocation,
SubLocationId: subLocation?.Id,
HideProgression: false,
IsLocationProgression: true,
Name: null,
const locationId = subLocation
? subLocation.Properties?.ParentLocation
: subLocationId
const completionData = controller.masteryService.getCompletionData(
locationId,
gameVersion,
userId,
)
if (!completionData) {
log(
LogLevel.DEBUG,
`Could not get CompletionData for location ${locationId}`,
)
return {
Level: 20,
MaxLevel: 20,
XP: 0,
Completion: 1,
XpLeft: 0,
Id: locationId,
SubLocationId: subLocation?.Id,
HideProgression: false,
IsLocationProgression: true,
Name: null,
}
}
return completionData
}
/**

@ -83,6 +83,8 @@ import assert from "assert"
import { Response } from "express"
import { MissionEndRequestQuery } from "./types/gameSchemas"
import { ChallengeFilterType } from "./candle/challengeHelpers"
import { MasteryService } from "./candle/masteryService"
import { MasteryPackage } from "./types/mastery"
/**
* An array of string arrays that contains the IDs of the featured contracts.
@ -328,6 +330,7 @@ export class Controller {
public hooks: {
serverStart: SyncHook<[]>
challengesLoaded: SyncHook<[]>
masteryDataLoaded: SyncHook<[]>
newEvent: SyncHook<
[
/** event */ ClientToServerEvent,
@ -391,6 +394,7 @@ export class Controller {
*/
public contracts: Map<string, MissionManifest> = new Map()
public challengeService: ChallengeService
public masteryService: MasteryService
/**
* A list of Simple Mod Framework mods installed.
*/
@ -407,6 +411,7 @@ export class Controller {
this.hooks = {
serverStart: new SyncHook(),
challengesLoaded: new SyncHook(),
masteryDataLoaded: new SyncHook(),
newEvent: new SyncHook(),
newMetricsEvent: new SyncHook(),
getContractManifest: new SyncBailHook(),
@ -477,6 +482,7 @@ export class Controller {
await this._loadInternalContracts()
this.challengeService = new ChallengeService(this)
this.masteryService = new MasteryService()
this._addElusiveTargets()
this.index()
@ -543,8 +549,10 @@ export class Controller {
this.hooks.serverStart.call()
try {
await this._loadChallenges()
await this._loadResources()
this.hooks.challengesLoaded.call()
this.hooks.masteryDataLoaded.call()
} catch (e) {
log(LogLevel.ERROR, `Fatal error with challenge bootstrap: ${e}`)
log(LogLevel.ERROR, e.stack)
@ -884,45 +892,81 @@ export class Controller {
return fetchedData!.contract!.Contract
}
private async _loadChallenges(): Promise<void> {
const dir = join(
private async _loadResources(): Promise<void> {
// Load challenge resources
const challengeDirectory = join(
PEACOCK_DEV ? process.cwd() : __dirname,
"resources",
"challenges",
)
const files = await readdir(dir)
for (const challengeFile of files) {
await this._handleResources(
challengeDirectory,
(data: ChallengePackage) => {
this._handleChallengeResources(data)
},
)
// Load mastery resources
const masteryDirectory = join(
PEACOCK_DEV ? process.cwd() : __dirname,
"resources",
"mastery",
)
await this._handleResources(
masteryDirectory,
(data: MasteryPackage) => {
this._handleMasteryResources(data)
},
)
}
private async _handleResources<T>(
directory: string,
handleDataCallback: (data: T) => void | Promise<void>,
): Promise<void> {
const files = await readdir(directory)
for (const file of files) {
try {
const fileBuffer = await readFile(join(dir, challengeFile))
const data: ChallengePackage = unpack(fileBuffer)
const fileBuffer = await readFile(join(directory, file))
const data: T = unpack(fileBuffer)
for (const group of data.groups) {
if (
[
"UI_MENU_PAGE_PROFILE_CHALLENGES_CATEGORY_ARCADE",
"UI_MENU_PAGE_PROFILE_CHALLENGES_CATEGORY_ESCALATION_HM1",
"UI_MENU_PAGE_PROFILE_CHALLENGES_CATEGORY_ESCALATION_HM2",
].includes(group.Name)
) {
continue
}
this.challengeService.registerGroup(group)
for (const challenge of group.Challenges) {
this.challengeService.registerChallenge(
challenge,
group.CategoryId,
)
}
}
await handleDataCallback(data)
} catch (e) {
log(LogLevel.ERROR, `Aborting challenge parsing.`)
log(LogLevel.ERROR, `Aborting resource parsing. ${e}`)
}
}
}
private _handleChallengeResources(data: ChallengePackage): void {
for (const group of data.groups) {
if (
[
"UI_MENU_PAGE_PROFILE_CHALLENGES_CATEGORY_ARCADE",
"UI_MENU_PAGE_PROFILE_CHALLENGES_CATEGORY_ESCALATION_HM1",
"UI_MENU_PAGE_PROFILE_CHALLENGES_CATEGORY_ESCALATION_HM2",
].includes(group.Name)
) {
continue
}
this.challengeService.registerGroup(group)
for (const challenge of group.Challenges) {
this.challengeService.registerChallenge(
challenge,
group.CategoryId,
)
}
}
}
private _handleMasteryResources(data: MasteryPackage): void {
this.masteryService.registerMasteryData(data)
}
/**
* Fetch a contract from the official servers.
*

@ -44,6 +44,7 @@ import type {
IHit,
MissionManifest,
PeacockLocationsData,
PlayerProfileView,
RequestWithJwt,
SafehouseCategory,
SceneConfig,
@ -929,7 +930,12 @@ menuDataRouter.get(
req.jwt.unique_name,
),
},
MasteryData: [],
MasteryData:
controller.masteryService.getMasteryDataForDestination(
req.query.locationId,
req.gameVersion,
req.jwt.unique_name,
),
DifficultyData: undefined,
},
}
@ -1704,8 +1710,17 @@ menuDataRouter.post(
createLoadSaveMiddleware("SaveMenuTemplate"),
)
menuDataRouter.get("/PlayerProfile", (req, res) => {
const playerProfilePage = getConfig("PlayerProfilePage", true)
menuDataRouter.get("/PlayerProfile", (req: RequestWithJwt, res) => {
const playerProfilePage = getConfig<PlayerProfileView>(
"PlayerProfilePage",
true,
)
const userProfile = getUserData(req.jwt.unique_name, req.gameVersion)
playerProfilePage.data.PlayerProfileXp.Total =
userProfile.Extensions.progression.PlayerProfileXP.Total
playerProfilePage.data.PlayerProfileXp.Level =
userProfile.Extensions.progression.PlayerProfileXP.ProfileLevel
res.json(playerProfilePage)
})
@ -1816,4 +1831,17 @@ menuDataRouter.get(
},
)
menuDataRouter.get(
"/MasteryDataForLocation",
(req: RequestWithJwt<{ locationId: string }>, res) => {
res.json(
controller.masteryService.getMasteryDataForLocation(
req.query.locationId,
req.gameVersion,
req.jwt.unique_name,
),
)
},
)
export { menuDataRouter }

@ -0,0 +1,31 @@
import { CompletionData, Unlockable } from "./types"
export interface MasteryDataTemplate {
template: unknown
data: {
Location: Unlockable
MasteryData: MasteryData[]
}
}
export interface MasteryPackage {
Id: string
MaxLevel?: number
Drops: {
Id: string
Level: number
}[]
}
export interface MasteryData {
CompletionData: CompletionData
Drops: MasteryDrop[]
}
export interface MasteryDrop {
IsLevelMarker: boolean
Unlockable: Unlockable
Level: number
IsLocked: boolean
TypeLocaKey: string
}

@ -347,6 +347,16 @@ export interface MissionStory {
Image: string
}
export interface PlayerProfileView {
template: unknown
data: {
PlayerProfileXp: {
Total: number
Level: number
}
}
}
export interface UserProfile {
Id: string
LinkedAccounts: {
@ -390,6 +400,12 @@ export interface UserProfile {
*/
Total: number
}
Locations: {
[location: string]: {
Xp: number
Level: number
}
}
}
defaultloadout?: {
[location: string]: {

@ -0,0 +1,85 @@
{
"Id": "LOCATION_PARENT_ROCKY",
"Drops": [
{
"Id": "AGENCYPICKUP_ROCKY_SMALL_BIGCENTRALTREE",
"Level": 2
},
{
"Id": "PROP_MELEE_MACHETE_JUNGLE",
"Level": 3
},
{
"Id": "STARTING_LOCATION_ROCKY_WATERVILLAGE",
"Level": 4
},
{
"Id": "AGENCYPICKUP_ROCKY_SMALL_TRASHCAN_SOCIALHUB",
"Level": 5
},
{
"Id": "FIREARMS_SMG_DAK_X2_RUSTY",
"Level": 6
},
{
"Id": "STARTING_LOCATION_ROCKY_SOCIALHUB",
"Level": 7
},
{
"Id": "AGENCYPICKUP_ROCKY_LARGE_BOATNEARWORKSHOP",
"Level": 8
},
{
"Id": "AGENCYPICKUP_ROCKY_LARGE_FOODSTORAGE_SOCIALHUB",
"Level": 9
},
{
"Id": "PROP_MELEE_DUGONG_GRIPHOOK",
"Level": 10
},
{
"Id": "STARTING_LOCATION_ROCKY_SHRINE",
"Level": 11
},
{
"Id": "AGENCYPICKUP_ROCKY_SMALL_SHRINE",
"Level": 12
},
{
"Id": "FIREARMS_SMG_HX10_MILITIA",
"Level": 13
},
{
"Id": "PROP_TOOL_LOCK_PICK_BONE",
"Level": 14
},
{
"Id": "STARTING_LOCATION_ROCKY_PIRATECAMP",
"Level": 15
},
{
"Id": "AGENCYPICKUP_ROCKY_LARGE_RADARTOWER",
"Level": 16
},
{
"Id": "PROP_GAS_GRENADE_EMETIC_FROG",
"Level": 17
},
{
"Id": "STARTING_LOCATION_ROCKY_MILITIACAMP",
"Level": 18
},
{
"Id": "AGENCYPICKUP_ROCKY_LARGE_RUINS",
"Level": 19
},
{
"Id": "TOKEN_OUTFIT_HERO_DUGONG_SUIT",
"Level": 20
},
{
"Id": "PROP_EXPLOSIVE_GRENADE_MOLOTOV",
"Level": 20
}
]
}

@ -0,0 +1,101 @@
{
"Id": "LOCATION_PARENT_BANGKOK",
"Drops": [
{
"Id": "STARTING_LOCATION_BANGKOK_SECURITY_HUT",
"Level": 2
},
{
"Id": "PROP_MELEE_MACHETE_BLOODY",
"Level": 2
},
{
"Id": "AGENCYPICKUP_BANGKOK_GARDEN_SHED",
"Level": 3
},
{
"Id": "STARTING_LOCATION_BANGKOK_TIGER_47_SUITE",
"Level": 4
},
{
"Id": "FIREARMS_HERO_SHOTGUN_SEMIAUTO_ENRAM_HV_COVERT",
"Level": 5
},
{
"Id": "AGENCYPICKUP_BANGKOK_TIGER_PENTHOUSE",
"Level": 6
},
{
"Id": "STARTING_LOCATION_BANGKOK_BAR",
"Level": 7
},
{
"Id": "FIREARMS_HERO_SMG_TACTICAL_TAC_SMG_S",
"Level": 7
},
{
"Id": "AGENCYPICKUP_BANGKOK_TIGER_RESTAURANT_TOILET",
"Level": 8
},
{
"Id": "STARTING_LOCATION_BANGKOK_TIGER_RESTAURANT_KITCHEN",
"Level": 9
},
{
"Id": "PROP_MELEE_SYRINGE_EMETIC",
"Level": 10
},
{
"Id": "AGENCYPICKUP_BANGKOK_TIGER_BALCONY_PLANTER",
"Level": 11
},
{
"Id": "STARTING_LOCATION_BANGKOK_GARDEN",
"Level": 12
},
{
"Id": "PROP_MELEE_ANTIQUE_SYRINGE_LETHAL",
"Level": 12
},
{
"Id": "AGENCYPICKUP_BANGKOK_STORAGE_ROOM",
"Level": 13
},
{
"Id": "AGENCYPICKUP_BANGKOK_TIGER_BASEMENT_SOUTHWING_B",
"Level": 14
},
{
"Id": "FIREARMS_HERO_SNIPER_HEAVY_JAEGER_TIGER",
"Level": 15
},
{
"Id": "STARTING_LOCATION_BANGKOK_TIGER_LINEN_ROOM",
"Level": 16
},
{
"Id": "AGENCYPICKUP_BANGKOK_TIGER_BATHROOM_TOWELS",
"Level": 17
},
{
"Id": "AGENCYPICKUP_BANGKOK_TIGER_STUDIO",
"Level": 18
},
{
"Id": "PROP_DEVICE_ICA_PHONE_EXPLOSIVE",
"Level": 18
},
{
"Id": "STARTING_LOCATION_BANGKOK_TIGER_CREW_ROOM",
"Level": 19
},
{
"Id": "FIREARMS_HERO_PISTOL_KRUGERMEIER",
"Level": 20
},
{
"Id": "PROP_DEVICE_ICA_MODULAR_REMOTE_MUSICDISTRACTION",
"Level": 20
}
]
}

@ -0,0 +1,93 @@
{
"Id": "LOCATION_PARENT_EDGY",
"Drops": [
{
"Id": "AGENCYPICKUP_EDGY_LARGE_ENTRANCE",
"Level": 2
},
{
"Id": "PROP_DEVICE_ICA_REMOTE_MICROTASER_S3",
"Level": 2
},
{
"Id": "STARTING_LOCATION_EDGY_FOX_CLUB_ENTRANCE",
"Level": 3
},
{
"Id": "AGENCYPICKUP_EDGY_SMALL_B1_BAR",
"Level": 4
},
{
"Id": "PROP_DEVICE_ICA_MODULAR_REMOTE_EXPLOSIVE_S3",
"Level": 5
},
{
"Id": "STARTING_LOCATION_EDGY_FOX_B1_BAR",
"Level": 6
},
{
"Id": "AGENCYPICKUP_EDGY_SMALL_B2_TOILET",
"Level": 7
},
{
"Id": "FIREARMS_PISTOL_CUSTOM_5MM_DTI",
"Level": 7
},
{
"Id": "STARTING_LOCATION_EDGY_FOX_FOREST_TOWER",
"Level": 8
},
{
"Id": "AGENCYPICKUP_EDGY_SMALL_BIKER_GARAGE",
"Level": 9
},
{
"Id": "PROP_POISON_VIAL_LETHAL_S3",
"Level": 10
},
{
"Id": "STARTING_LOCATION_EDGY_FOX_CHILLOUT_AREA",
"Level": 11
},
{
"Id": "AGENCYPICKUP_EDGY_LARGE_CHILLOUT_SHED",
"Level": 12
},
{
"Id": "PROP_EXPLOSIVE_GRENADE_FLASH_S3",
"Level": 13
},
{
"Id": "AGENCYPICKUP_EDGY_LARGE_F0_TRASH_ROOM",
"Level": 14
},
{
"Id": "PROP_MELEE_SYRINGE_LETHAL_S3",
"Level": 15
},
{
"Id": "STARTING_LOCATION_EDGY_FOX_DJ_BOOTH",
"Level": 16
},
{
"Id": "AGENCYPICKUP_EDGY_LARGE_ABANDONED_TOWER_ROOM",
"Level": 17
},
{
"Id": "STARTING_LOCATION_EDGY_FOX_BIKER_LOUNGE",
"Level": 18
},
{
"Id": "AGENCYPICKUP_EDGY_LARGE_B2_ABANDONED_ROOM",
"Level": 19
},
{
"Id": "TOKEN_OUTFIT_REWARD_HERO_FOX_SUIT",
"Level": 20
},
{
"Id": "PROP_DEVICE_DEVIL_RUBBERDUCK_REMOTE_EXPLOSIVE",
"Level": 20
}
]
}

@ -0,0 +1,26 @@
{
"Id": "LOCATION_PARENT_TRAPPED",
"MaxLevel": 5,
"Drops": [
{
"Id": "STARTING_LOCATION_TRAPPED_WOLVERINE_TRAIN_LAB",
"Level": 2
},
{
"Id": "FIREARMS_HERO_PISTOL_SILENCED_HOMEMADE",
"Level": 2
},
{
"Id": "STARTING_LOCATION_TRAPPED_WOLVERINE_TRAIN_FLATBED",
"Level": 3
},
{
"Id": "PROP_DEVICE_ICA_SEMTEX_PROXIMITY_EXPLOSIVE_S3",
"Level": 4
},
{
"Id": "FIREARMS_HERO_SHOTGUN_SILENCED_WOLVERINE",
"Level": 5
}
]
}

@ -0,0 +1,97 @@
{
"Id": "LOCATION_PARENT_WET",
"Drops": [
{
"Id": "AGENCYPICKUP_WET_SMALL_ARCADE",
"Level": 2
},
{
"Id": "PROP_DEVICE_KEYCARD_HACKER_S3",
"Level": 2
},
{
"Id": "AGENCYPICKUP_WET_SMALL_RESTAURANT",
"Level": 3
},
{
"Id": "STARTING_LOCATION_WET_RAT_STREET",
"Level": 4
},
{
"Id": "PROP_EMETIC_POISON_PEN_SYRINGE",
"Level": 5
},
{
"Id": "AGENCYPICKUP_WET_LARGE_BLOCKF3",
"Level": 6
},
{
"Id": "STARTING_LOCATION_WET_RAT_RESTURANT",
"Level": 7
},
{
"Id": "PROP_DEVICE_PROXIMITY_CONCUSSION_S3",
"Level": 7
},
{
"Id": "AGENCYPICKUP_WET_LARGE_BLOCKROOF",
"Level": 8
},
{
"Id": "STARTING_LOCATION_WET_RAT_ROOF",
"Level": 9
},
{
"Id": "AGENCYPICKUP_WET_SMALL_FACILITYROOF",
"Level": 10
},
{
"Id": "FIREARMS_SHOTGUN_SEMIAUTO_ICA_12G_SHORT",
"Level": 10
},
{
"Id": "AGENCYPICKUP_WET_LARGE_COURTYARD",
"Level": 11
},
{
"Id": "AGENCYPICKUP_WET_LARGE_ALLEY",
"Level": 12
},
{
"Id": "STARTING_LOCATION_WET_RAT_BLOCK_SECURITY",
"Level": 13
},
{
"Id": "AGENCYPICKUP_WET_SMALL_FACILITYVENT",
"Level": 14
},
{
"Id": "FIREARMS_SMG_ICA_RAPTOR_COVERT",
"Level": 15
},
{
"Id": "STARTING_LOCATION_WET_RAT_SIGN",
"Level": 16
},
{
"Id": "AGENCYPICKUP_WET_SMALL_LAUNDRY",
"Level": 17
},
{
"Id": "AGENCYPICKUP_WET_LARGE_APARTMENT",
"Level": 18
},
{
"Id": "STARTING_LOCATION_WET_RAT_FACILITY_WORKER",
"Level": 19
},
{
"Id": "TOKEN_OUTFIT_REWARD_HERO_RAT_SUIT",
"Level": 20
},
{
"Id": "FIREARMS_SNIPER_ICA_HACKL_LEVIATHAN_COVERT",
"Level": 20
}
]
}

@ -0,0 +1,93 @@
{
"Id": "LOCATION_PARENT_COLORADO",
"Drops": [
{
"Id": "AGENCYPICKUP_COLORADO_WATERTOWER",
"Level": 2
},
{
"Id": "FIREARMS_HERO_RIFLE_FULLAUTO_RS_15",
"Level": 2
},
{
"Id": "STARTING_LOCATION_COLORADO_ORCHARD",
"Level": 3
},
{
"Id": "AGENCYPICKUP_COLORADO_BULL_ORCHARD_BOX",
"Level": 4
},
{
"Id": "FIREARMS_HERO_RIFLE_SEMIAUTO_TAC_4_SA_STEALTH",
"Level": 5
},
{
"Id": "STARTING_LOCATION_COLORADO_BULL_COURTYARD_GARAGE",
"Level": 6
},
{
"Id": "AGENCYPICKUP_COLORADO_HAYBARN",
"Level": 7
},
{
"Id": "PROP_MELEE_EXPANDABLE_BATON",
"Level": 7
},
{
"Id": "STARTING_LOCATION_COLORADO_BULL_DEMOLITION_AREA",
"Level": 8
},
{
"Id": "AGENCYPICKUP_COLORADO_BULL_RED_BARN",
"Level": 9
},
{
"Id": "FIREARMS_HERO_PISTOL_TACTICAL_ICA_19_FA_STEALTH",
"Level": 10
},
{
"Id": "PROP_TOOL_ELECTRICAL_KIT",
"Level": 10
},
{
"Id": "STARTING_LOCATION_COLORADO_BULL_GREENHOUSE",
"Level": 11
},
{
"Id": "AGENCYPICKUP_COLORADO_COURTYARD_OUTHOUSE",
"Level": 12
},
{
"Id": "AGENCYPICKUP_COLORADO_WESTBRIDGE",
"Level": 13
},
{
"Id": "STARTING_LOCATION_COLORADO_WEST_BRIDGE",
"Level": 14
},
{
"Id": "FIREARMS_HERO_SNIPER_MEDIUM_SIEGER_300",
"Level": 15
},
{
"Id": "STARTING_LOCATION_COLORADO_WATER_TOWER",
"Level": 16
},
{
"Id": "AGENCYPICKUP_COLORADO_BULL_ORCHARD_PARKINGAREA",
"Level": 17
},
{
"Id": "STARTING_LOCATION_COLORADO_BULL_HACKER_ROOM",
"Level": 18
},
{
"Id": "AGENCYPICKUP_COLORADO_BULL_HOUSE_LAUNDRYROOM",
"Level": 19
},
{
"Id": "PROP_DEVICE_ICA_C4_REMOTE_EXPLOSIVE",
"Level": 20
}
]
}

@ -0,0 +1,101 @@
{
"Id": "LOCATION_PARENT_ANCESTRAL",
"Drops": [
{
"Id": "AGENCYPICKUP_ANCESTRAL_SMALL_DELIVERIES",
"Level": 2
},
{
"Id": "PROP_TOOL_LOCK_PICK_S3",
"Level": 2
},
{
"Id": "AGENCYPICKUP_ANCESTRAL_LARGE_RESTROOM",
"Level": 3
},
{
"Id": "STARTING_LOCATION_ANCESTRAL_BULLDOG_GARDEN_GARDENER",
"Level": 4
},
{
"Id": "AGENCYPICKUP_ANCESTRAL_SMALL_GREENHOUSE",
"Level": 5
},
{
"Id": "FIREARMS_HERO_PISTOL_SHORT_BALLER",
"Level": 5
},
{
"Id": "STARTING_LOCATION_ANCESTRAL_BULLDOG_STAFFROOM_MANSIONGUARD",
"Level": 6
},
{
"Id": "AGENCYPICKUP_ANCESTRAL_LARGE_CHANGINGROOM",
"Level": 7
},
{
"Id": "PROP_POISON_SEDATIVE_VIAL_S3",
"Level": 7
},
{
"Id": "STARTING_LOCATION_ANCESTRAL_BULLDOG_BEHINDMANSION_SUIT",
"Level": 8
},
{
"Id": "AGENCYPICKUP_ANCESTRAL_LARGE_GRAVEYARD",
"Level": 9
},
{
"Id": "PROP_DEVICE_ICA_REMOTE_AUDIO_DISTRACTION_S3",
"Level": 10
},
{
"Id": "STARTING_LOCATION_ANCESTRAL_BULLDOG_LIBRARY_MANSIONSTAFF",
"Level": 11
},
{
"Id": "AGENCYPICKUP_ANCESTRAL_SMALL_LIBRARY",
"Level": 12
},
{
"Id": "PROP_MELEE_KUKRI_KNIFE",
"Level": 13
},
{
"Id": "AGENCYPICKUP_ANCESTRAL_LARGE_HALLWAY",
"Level": 14
},
{
"Id": "PROP_DEVICE_ICA_RUBBERDUCK_PROXIMITY_EXPLOSIVE_S3",
"Level": 15
},
{
"Id": "STARTING_LOCATION_ANCESTRAL_BULLDOG_ZACHARYSROOM_INVESTIGATOR",
"Level": 16
},
{
"Id": "AGENCYPICKUP_ANCESTRAL_SMALL_LAUNDRYROOM",
"Level": 17
},
{
"Id": "STARTING_LOCATION_ANCESTRAL_BULLDOG_DEFAULT_SUIT_B",
"Level": 18
},
{
"Id": "PROP_MELEE_CANE",
"Level": 18
},
{
"Id": "STARTING_LOCATION_ANCESTRAL_BULLDOG_BEHINDMANSION_SUIT_B",
"Level": 19
},
{
"Id": "TOKEN_OUTFIT_REWARD_HERO_BULLDOG_SUIT",
"Level": 20
},
{
"Id": "FIREARMS_HERO_SNIPER_WOODSMAN",
"Level": 20
}
]
}

@ -0,0 +1,85 @@
{
"Id": "LOCATION_PARENT_GOLDEN",
"Drops": [
{
"Id": "PROP_MELEE_SHOWGLOBE",
"Level": 2
},
{
"Id": "STARTING_LOCATION_GOLDEN_GECKO_INSIDE_DEFAULT",
"Level": 2
},
{
"Id": "AGENCYPICKUP_GOLDEN_SMALL_KITCHEN",
"Level": 3
},
{
"Id": "STARTING_LOCATION_GOLDEN_GECKO_MEETING_ROOM_STAFF",
"Level": 4
},
{
"Id": "PROP_POISON_EMETIC_VIAL_S3",
"Level": 5
},
{
"Id": "AGENCYPICKUP_GOLDEN_LARGE_PENTHOUSESUPPLYROOM",
"Level": 6
},
{
"Id": "STARTING_LOCATION_GOLDEN_GECKO_ART_INSTALLATION_TECHNICIAN",
"Level": 7
},
{
"Id": "PROP_CONTAINER_SUITCASE_ICA_S3",
"Level": 7
},
{
"Id": "AGENCYPICKUP_GOLDEN_SMALL_ATRIUMTOILET",
"Level": 8
},
{
"Id": "AGENCYPICKUP_GOLDEN_LARGE_JANITORROOM",
"Level": 9
},
{
"Id": "PROP_EXPLOSIVE_GOLFBALL",
"Level": 10
},
{
"Id": "STARTING_LOCATION_GOLDEN_GECKO_GUARD_ROOM_GUARD",
"Level": 11
},
{
"Id": "AGENCYPICKUP_GOLDEN_SMALL_LAUNDRYROOM",
"Level": 12
},
{
"Id": "PROP_MELEE_SCIMITAR",
"Level": 13
},
{
"Id": "AGENCYPICKUP_GOLDEN_LARGE_BACKSTAGEBALCONY",
"Level": 14
},
{
"Id": "FIREARMS_SNIPER_DRUZHINA_34_DTI",
"Level": 15
},
{
"Id": "AGENCYPICKUP_GOLDEN_LARGE_PENTHOUSEMAINTENANCE",
"Level": 17
},
{
"Id": "STARTING_LOCATION_GOLDEN_GECKO_PENTHOUSE_STAFF",
"Level": 19
},
{
"Id": "TOKEN_OUTFIT_REWARD_HERO_GECKO_SUIT",
"Level": 20
},
{
"Id": "PROP_DEVICE_ICA_PROXIMITY_EXPLOSIVE_S3",
"Level": 20
}
]
}

@ -0,0 +1,85 @@
{
"Id": "LOCATION_PARENT_OPULENT",
"Drops": [
{
"Id": "PROP_MELEE_PIRATE_SABRE",
"Level": 2
},
{
"Id": "STARTING_LOCATION_OPULENT_STINGRAY_47HUT",
"Level": 3
},
{
"Id": "AGENCYPICKUP_STINGRAY_SMALL_LAUNDRYROOM",
"Level": 4
},
{
"Id": "PROP_DEVICE_ICA_REMOTE_GAS_EMETIC",
"Level": 5
},
{
"Id": "AGENCYPICKUP_STINGRAY_SMALL_STAFFROOM",
"Level": 6
},
{
"Id": "STARTING_LOCATION_OPULENT_STINGRAY_POOL",
"Level": 7
},
{
"Id": "AGENCYPICKUP_STINGRAY_LARGE_47HUT",
"Level": 8
},
{
"Id": "AGENCYPICKUP_STINGRAY_SMALL_SPACHANGINGROOM",
"Level": 9
},
{
"Id": "FIREARMS_PISTOL_DARTGUN_SICK",
"Level": 10
},
{
"Id": "STARTING_LOCATION_OPULENT_STINGRAY_GYM",
"Level": 11
},
{
"Id": "AGENCYPICKUP_STINGRAY_LARGE_SECURITYHUT",
"Level": 12
},
{
"Id": "AGENCYPICKUP_STINGRAY_SMALL_HIDDENINSAND",
"Level": 13
},
{
"Id": "STARTING_LOCATION_OPULENT_STINGRAY_KITCHEN",
"Level": 14
},
{
"Id": "PROP_MELEE_TREASURE_KNIFE",
"Level": 15
},
{
"Id": "AGENCYPICKUP_STINGRAY_SMALL_VILLA_BATHROOM",
"Level": 16
},
{
"Id": "AGENCYPICKUP_STINGRAY_LARGE_VILLABEACH",
"Level": 17
},
{
"Id": "STARTING_LOCATION_OPULENT_STINGRAY_VILLA_PIER",
"Level": 18
},
{
"Id": "AGENCYPICKUP_STINGRAY_SMALL_UNDERGROUND_STORAGE",
"Level": 19
},
{
"Id": "FIREARMS_SNIPER_JAEGER_7_TUATARA",
"Level": 20
},
{
"Id": "TOKEN_OUTFIT_STINGRAY_MASTERY_REWARD_SUIT",
"Level": 20
}
]
}

@ -0,0 +1,38 @@
{
"Id": "LOCATION_PARENT_NEWZEALAND",
"MaxLevel": 5,
"Drops": [
{
"Id": "STARTING_LOCATION_NEWZEALAND_BOAT",
"Level": 1
},
{
"Id": "AGENCYPICKUP_NEWZEALAND_SMALL",
"Level": 2
},
{
"Id": "PROP_DEVICE_ICA_MODULAR_PROXIMITY_EXPLOSIVE_S2",
"Level": 2
},
{
"Id": "STARTING_LOCATION_NEWZEALAND_BEACH",
"Level": 3
},
{
"Id": "AGENCYPICKUP_NEWZEALAND_LARGE",
"Level": 4
},
{
"Id": "STARTING_LOCATION_NEWZEALAND_OFFICE",
"Level": 5
},
{
"Id": "PROP_EXPLOSIVE_GRENADE_FLASH",
"Level": 5
},
{
"Id": "PROP_MELEE_TANTO",
"Level": 5
}
]
}

@ -0,0 +1,101 @@
{
"Id": "LOCATION_PARENT_HOKKAIDO",
"Drops": [
{
"Id": "PROP_MELEE_SHURIKEN",
"Level": 2
},
{
"Id": "AGENCYPICKUP_HOKKAIDO_SNOWCRANE_MOUNTAINPATH",
"Level": 3
},
{
"Id": "AGENCYPICKUP_HOKKAIDO_SNOWCRANE_SLEEPINGQUARTERS",
"Level": 4
},
{
"Id": "FIREARMS_HERO_PISTOL_CUSTOM5MM",
"Level": 5
},
{
"Id": "STARTING_LOCATION_HOKKAIDO_SNOWCRANE_SPA",
"Level": 6
},
{
"Id": "STARTING_LOCATION_HOKKAIDO_SNOWCRANE_NINJA",
"Level": 7
},
{
"Id": "PROP_MELEE_NINJATONFA",
"Level": 7
},
{
"Id": "PROP_MELEE_KATANA_ENGRAVED",
"Level": 7
},
{
"Id": "STARTING_LOCATION_HOKKAIDO_SNOWCRANE_RESTAURANT",
"Level": 8
},
{
"Id": "AGENCYPICKUP_HOKKAIDO_SNOWCRANE_OPERATIONTOILET",
"Level": 9
},
{
"Id": "STARTING_LOCATION_HOKKAIDO_SNOWCRANE_SLEEPINGQUARTERS",
"Level": 10
},
{
"Id": "AGENCYPICKUP_HOKKAIDO_SNOWCRANE_KITCHEN",
"Level": 11
},
{
"Id": "STARTING_LOCATION_HOKKAIDO_SNOWCRANE_KITCHEN",
"Level": 12
},
{
"Id": "PROP_MELEE_HIDDEN_BLADE",
"Level": 12
},
{
"Id": "AGENCYPICKUP_HOKKAIDO_SNOWCRANE_GARAGE",
"Level": 13
},
{
"Id": "STARTING_LOCATION_HOKKAIDO_SNOWCRANE_GARDEN",
"Level": 14
},
{
"Id": "PROP_EXPLOSIVE_EXPLOSIVE_COMPOUND",
"Level": 15
},
{
"Id": "AGENCYPICKUP_HOKKAIDO_SNOWCRANE_MORGUE",
"Level": 16
},
{
"Id": "STARTING_LOCATION_HOKKAIDO_SNOWCRANE_MORGUE",
"Level": 17
},
{
"Id": "AGENCYPICKUP_HOKKAIDO_SNOWCRANE_RESTAURANTRESTROOM",
"Level": 18
},
{
"Id": "STARTING_LOCATION_HOKKAIDO_SNOWCRANE_OPERATINGTHEATER",
"Level": 19
},
{
"Id": "FIREARMS_HERO_SNIPER_MEDIUM_SIEGER_300_ADVANCED",
"Level": 20
},
{
"Id": "PROP_MELEE_JAPANESE_BASEBALLBAT",
"Level": 20
},
{
"Id": "LOADOUT_UNLOCK_HOKKAIDO",
"Level": 20
}
]
}

@ -0,0 +1,101 @@
{
"Id": "LOCATION_PARENT_MARRAKECH",
"Drops": [
{
"Id": "AGENCYPICKUP_MARRAKESH_SPIDER_CONSULATE_BASEMENT",
"Level": 2
},
{
"Id": "PROP_DEVICE_ICA_MODULAR_PROXIMITY_EXPLOSIVE",
"Level": 2
},
{
"Id": "STARTING_LOCATION_MARRAKESH_SHISHA_CAFE",
"Level": 3
},
{
"Id": "AGENCYPICKUP_MARRAKESH_MECHANIC_SHOP",
"Level": 4
},
{
"Id": "FIREARMS_HERO_PISTOL_TACTICAL_ICA_19_FA",
"Level": 5
},
{
"Id": "STARTING_LOCATION_MARRAKESH_SNAIL_VENDOR",
"Level": 6
},
{
"Id": "AGENCYPICKUP_MARRAKESH_SNIPER_ROOF",
"Level": 7
},
{
"Id": "PROP_POISON_VIAL_SICK",
"Level": 7
},
{
"Id": "STARTING_LOCATION_MARRAKESH_SPIDER_SCHOOL_DORMITORY",
"Level": 8
},
{
"Id": "AGENCYPICKUP_MARRAKESH_CAFE_RESTROOM",
"Level": 9
},
{
"Id": "PROP_DEVICE_ICA_RUBBERDUCK_REMOTE_EXPLOSIVE",
"Level": 10
},
{
"Id": "PROP_MELEE_CEREMONIAL_DAGGER",
"Level": 10
},
{
"Id": "STARTING_LOCATION_MARRAKESH_SNIPER_ROOF",
"Level": 11
},
{
"Id": "AGENCYPICKUP_MARRAKESH_HEADMASTER",
"Level": 12
},
{
"Id": "FIREARMS_HERO_SHOTGUN_SEMIAUTO_ENRAM_HV_CM",
"Level": 12
},
{
"Id": "STARTING_LOCATION_MARRAKESH_LAMPSTORE_ROOF",
"Level": 13
},
{
"Id": "AGENCYPICKUP_MARRAKESH_SPIDER_CONSULATE_TROLLEY",
"Level": 14
},
{
"Id": "PROP_DEVICE_ICA_C4_PROXIMITY_EXPLOSIVE",
"Level": 15
},
{
"Id": "STARTING_LOCATION_MARRAKESH_SPIDER_CONSULATE_CLEANING_TROLLEY",
"Level": 16
},
{
"Id": "AGENCYPICKUP_MARRAKESH_BAZAAR_CARPETSHOP",
"Level": 17
},
{
"Id": "STARTING_LOCATION_MARRAKESH_SPIDER_SCHOOL_ALLEY",
"Level": 18
},
{
"Id": "AGENCYPICKUP_MARRAKESH_SPIDER_SCHOOL_BACKENTRANCE",
"Level": 19
},
{
"Id": "FIREARMS_HERO_RIFLE_FULLAUTO_TAC_4_AR_STEALTH",
"Level": 20
},
{
"Id": "PROP_MELEE_CRYSTALBALL",
"Level": 20
}
]
}

@ -0,0 +1,97 @@
{
"Id": "LOCATION_PARENT_ELEGANT",
"Drops": [
{
"Id": "STARTING_LOCATION_ELEGANT_LLAMA_PARKINGLOT_SUIT",
"Level": 2
},
{
"Id": "FIREARMS_PISTOL_ICA_STEALTH_DTI",
"Level": 2
},
{
"Id": "AGENCYPICKUP_ELEGANT_SMALL_BOATHOUSE",
"Level": 3
},
{
"Id": "STARTING_LOCATION_ELEGANT_GRAPEFIELD_WORKER",
"Level": 4
},
{
"Id": "FIREARMS_PISTOL_DARTGUN_SEDATIVE_KALMER_2",
"Level": 5
},
{
"Id": "AGENCYPICKUP_ELEGANT_SMALL_WORKERSTOILET",
"Level": 6
},
{
"Id": "STARTING_LOCATION_ELEGANT_LLAMA_TASTINGROOM_WAITER",
"Level": 7
},
{
"Id": "PROP_MELEE_AXE_ICA",
"Level": 7
},
{
"Id": "AGENCYPICKUP_ELEGANT_LARGE_BARRELROOM",
"Level": 8
},
{
"Id": "STARTING_LOCATION_ELEGANT_LLAMA_SHRINE",
"Level": 9
},
{
"Id": "AGENCYPICKUP_ELEGANT_SMALL_CINEMA",
"Level": 10
},
{
"Id": "FIREARMS_HERO_PISTOL_KRUGERMEIER_SILVER",
"Level": 10
},
{
"Id": "AGENCYPICKUP_ELEGANT_SMALL_SHRINEPOT",
"Level": 11
},
{
"Id": "AGENCYPICKUP_ELEGANT_LARGE_STEELTANKS",
"Level": 12
},
{
"Id": "STARTING_LOCATION_ELEGANT_LLAMA_STEELTANKS",
"Level": 13
},
{
"Id": "AGENCYPICKUP_ELEGANT_LARGE_VILLAATTIC",
"Level": 14
},
{
"Id": "FIREARMS_SMG_TACTICAL_DAK_DTI_BLACK_COVERT",
"Level": 15
},
{
"Id": "AGENCYPICKUP_ELEGANT_LARGE_GRAPESHED",
"Level": 16
},
{
"Id": "STARTING_LOCATION_ELEGANT_ASADO_CHEF",
"Level": 17
},
{
"Id": "AGENCYPICKUP_ELEGANT_SMALL_VILLABASEMENT",
"Level": 18
},
{
"Id": "AGENCYPICKUP_ELEGANT_SMALL_DANCEFLOOR",
"Level": 19
},
{
"Id": "TOKEN_OUTFIT_REWARD_HERO_LLAMA_SUIT",
"Level": 20
},
{
"Id": "FIREARMS_SNIPER_MEDIUM_SIEGER_300_VIPER",
"Level": 20
}
]
}

@ -0,0 +1,129 @@
{
"Id": "LOCATION_PARENT_MIAMI",
"Drops": [
{
"Id": "STARTING_LOCATION_MIAMI_FLAMINGO_EXPO_ENTRANCE",
"Level": 2
},
{
"Id": "PROP_TOOL_LOCK_PICK_S2",
"Level": 2
},
{
"Id": "LOADOUT_UNLOCK_MIAMI",
"Level": 2
},
{
"Id": "AGENCYPICKUP_MIAMI_SMALL_EXPO_RECEPTION",
"Level": 3
},
{
"Id": "STARTING_LOCATION_MIAMI_FLAMINGO_MARINA",
"Level": 4
},
{
"Id": "PROP_MELEE_FISH",
"Level": 4
},
{
"Id": "AGENCYPICKUP_MIAMI_SMALL_STANDS_TOILET",
"Level": 5
},
{
"Id": "FIREARMS_HERO_SNIPER_JAEGER_S2",
"Level": 5
},
{
"Id": "STARTING_LOCATION_MIAMI_FLAMINGO_STANDS",
"Level": 6
},
{
"Id": "AGENCYPICKUP_MIAMI_LARGE_BOAT_RENTAL",
"Level": 7
},
{
"Id": "FIREARMS_PISTOL_HWK_21_S2",
"Level": 7
},
{
"Id": "STARTING_LOCATION_MIAMI_FLAMINGO_FOOD_TRUCK",
"Level": 8
},
{
"Id": "AGENCYPICKUP_MIAMI_SMALL_PODIUM",
"Level": 8
},
{
"Id": "STARTING_LOCATION_MIAMI_FLAMINGO_HOTEL",
"Level": 9
},
{
"Id": "PROP_DEVICE_ICA_PROXIMITY_TASER",
"Level": 10
},
{
"Id": "PROP_CONTAINER_SUITCASE_ICA",
"Level": 10
},
{
"Id": "AGENCYPICKUP_MIAMI_LARGE_TRUCK",
"Level": 11
},
{
"Id": "STARTING_LOCATION_MIAMI_FLAMINGO_VIPLOUNGE",
"Level": 12
},
{
"Id": "AGENCYPICKUP_MIAMI_LARGE_FOOD_AREA",
"Level": 13
},
{
"Id": "PROP_DEVICE_ICA_RUBBER_DUCK_PROXIMITY_EXPLOSIVE_S2",
"Level": 13
},
{
"Id": "STARTING_LOCATION_MIAMI_FLAMINGO_PODIUM",
"Level": 14
},
{
"Id": "AGENCYPICKUP_MIAMI_LARGE_STORAGE_CONTAINER",
"Level": 15
},
{
"Id": "FIREARMS_PISTOL_CONCEPT_5",
"Level": 15
},
{
"Id": "STARTING_LOCATION_MIAMI_FLAMINGO_MEDICAL_AREA",
"Level": 16
},
{
"Id": "PROP_MELEE_FISHING_LINE",
"Level": 16
},
{
"Id": "AGENCYPICKUP_MIAMI_LARGE_STORAGE_PADDOCK",
"Level": 17
},
{
"Id": "STARTING_LOCATION_MIAMI_FLAMINGO_EXPO",
"Level": 18
},
{
"Id": "PROP_DEVICE_ICA_REMOTE_AUDIO_DISTRACTION_S2",
"Level": 18
},
{
"Id": "AGENCYPICKUP_MIAMI_LARGE_PITBUILDING_BASEMENT",
"Level": 19
},
{
"Id": "STARTING_LOCATION_MIAMI_FLAMINGO_GARAGEPIT",
"Level": 20
},
{
"Id": "PROP_EXPLOSIVE_GRENADE_CONCUSSION",
"Level": 20
}
]
}

@ -0,0 +1,169 @@
{
"Id": "LOCATION_PARENT_MUMBAI",
"Drops": [
{
"Id": "STARTING_LOCATION_MUMBAI_MONGOOSE_TRAIN",
"Level": 2
},
{
"Id": "AGENCYPICKUP_MUMBAI_SMALL_SHOESHOP",
"Level": 2
},
{
"Id": "FIREARMS_PISTOL_SILVERBALLER_S2",
"Level": 2
},
{
"Id": "STARTING_LOCATION_MUMBAI_MONGOOSE_LAUNDRY",
"Level": 3
},
{
"Id": "AGENCYPICKUP_MUMBAI_SMALL_NEST",
"Level": 3
},
{
"Id": "STARTING_LOCATION_MUMBAI_MONGOOSE_BOAT",
"Level": 4
},
{
"Id": "STARTING_LOCATION_MUMBAI_MONGOOSE_BARGE",
"Level": 5
},
{
"Id": "AGENCYPICKUP_MUMBAI_SMALL_FLOWER",
"Level": 5
},
{
"Id": "AGENCYPICKUP_MUMBAI_SMALL_MEAT",
"Level": 5
},
{
"Id": "FIREARMS_HERO_SHOTGUN_BARTOLI_12G_HEROVERSION",
"Level": 5
},
{
"Id": "STARTING_LOCATION_MUMBAI_MONGOOSE_SKYWALK",
"Level": 6
},
{
"Id": "AGENCYPICKUP_MUMBAI_SMALL_CLOTH",
"Level": 6
},
{
"Id": "AGENCYPICKUP_MUMBAI_SMALL_POT",
"Level": 6
},
{
"Id": "AGENCYPICKUP_MUMBAI_LARGE_BARGE",
"Level": 7
},
{
"Id": "PROP_DEVICE_ICA_MODULAR_REMOTE_EXPLOSIVE_S2",
"Level": 7
},
{
"Id": "STARTING_LOCATION_MUMBAI_MONGOOSE_TAXI",
"Level": 8
},
{
"Id": "AGENCYPICKUP_MUMBAI_SMALL_TYRE",
"Level": 8
},
{
"Id": "AGENCYPICKUP_MUMBAI_SMALL_BOAT",
"Level": 8
},
{
"Id": "STARTING_LOCATION_MUMBAI_MONGOOSE_KASHMERIAN",
"Level": 9
},
{
"Id": "AGENCYPICKUP_MUMBAI_LARGE_FORGE",
"Level": 9
},
{
"Id": "AGENCYPICKUP_MUMBAI_LARGE_ROOFTOP",
"Level": 10
},
{
"Id": "PROP_DEVICE_ICA_MICRO_PROXIMITY_EXPLOSIVE",
"Level": 10
},
{
"Id": "PROP_DEVICE_ICA_MODULAR_REMOTE_EMP",
"Level": 10
},
{
"Id": "STARTING_LOCATION_MUMBAI_MONGOOSE_SLUMS",
"Level": 11
},
{
"Id": "AGENCYPICKUP_MUMBAI_SMALL_SEWER",
"Level": 11
},
{
"Id": "AGENCYPICKUP_MUMBAI_LARGE_TRAIN",
"Level": 12
},
{
"Id": "STARTING_LOCATION_MUMBAI_MONGOOSE_FORGE",
"Level": 13
},
{
"Id": "AGENCYPICKUP_MUMBAI_SMALL_BAG",
"Level": 13
},
{
"Id": "PROP_MELEE_SYRINGE_EMETIC_S2",
"Level": 13
},
{
"Id": "AGENCYPICKUP_MUMBAI_LARGE_LAUNDRY",
"Level": 14
},
{
"Id": "AGENCYPICKUP_MUMBAI_LARGE_HILL",
"Level": 15
},
{
"Id": "FIREARMS_HERO_SMG_MAC10_COVERT",
"Level": 15
},
{
"Id": "STARTING_LOCATION_MUMBAI_MONGOOSE_APARTMENT",
"Level": 16
},
{
"Id": "AGENCYPICKUP_MUMBAI_SMALL_KASHMERIAN",
"Level": 16
},
{
"Id": "STARTING_LOCATION_MUMBAI_MONGOOSE_HILL",
"Level": 17
},
{
"Id": "AGENCYPICKUP_MUMBAI_SMALL_APARTMENT",
"Level": 17
},
{
"Id": "AGENCYPICKUP_MUMBAI_LARGE_GARAGE",
"Level": 18
},
{
"Id": "PROP_MELEE_ANTIQUE_KNIFE_CURVED",
"Level": 18
},
{
"Id": "STARTING_LOCATION_MUMBAI_MONGOOSE_TRAINYARD",
"Level": 19
},
{
"Id": "AGENCYPICKUP_MUMBAI_LARGE_TRAINYARD",
"Level": 20
},
{
"Id": "FIREARMS_SNIPER_DRUZHINA_34",
"Level": 20
}
]
}

@ -0,0 +1,65 @@
{
"Id": "LOCATION_PARENT_GREEDY",
"Drops": [
{
"Id": "PROP_TOOL_GOLD_BAR_SMALL",
"Level": 2
},
{
"Id": "STARTING_LOCATION_GREEDY_RACCOON_MAINTENANCE_ENTRANCE",
"Level": 3
},
{
"Id": "AGENCYPICKUP_GREEDY_SMALL_1STFLOORTOILET",
"Level": 4
},
{
"Id": "PROP_DEVICE_ICA_REMOTE_FLASH",
"Level": 5
},
{
"Id": "AGENCYPICKUP_GREEDY_LARGE_FIRSTFLOORJANITOR",
"Level": 6
},
{
"Id": "STARTING_LOCATION_GREEDY_RACCOON_AUDITHALL_ENTRANCE",
"Level": 7
},
{
"Id": "AGENCYPICKUP_GREEDY_SMALL_2NDFLOORTOILET",
"Level": 8
},
{
"Id": "AGENCYPICKUP_GREEDY_SMALL_DEPOSITBOX",
"Level": 10
},
{
"Id": "STARTING_LOCATION_GREEDY_RACCOON_DEPOSITBOXROOM_ENTRANCE",
"Level": 12
},
{
"Id": "FIREARMS_HERO_SHOTGUN_BARTOLI_12G_SAWED_OFF",
"Level": 13
},
{
"Id": "STARTING_LOCATION_GREEDY_RACCOON_INVESTMENTFLOOR_ENTRANCE",
"Level": 14
},
{
"Id": "AGENCYPICKUP_GREEDY_LARGE_ASSISTANTSROOM",
"Level": 16
},
{
"Id": "STARTING_LOCATION_GREEDY_RACCOON_GARAGE_ENTRANCE",
"Level": 17
},
{
"Id": "AGENCYPICKUP_GREEDY_LARGE_GARAGE",
"Level": 18
},
{
"Id": "TOKEN_OUTFIT_BANK_STARTING_SUIT_REWARD",
"Level": 20
}
]
}

@ -0,0 +1,101 @@
{
"Id": "LOCATION_PARENT_PARIS",
"Drops": [
{
"Id": "STARTING_LOCATION_PARIS_PEACOCK_BASEMENT_KITCHEN",
"Level": 2
},
{
"Id": "PROP_POISON_VIAL_SEDATIVE",
"Level": 2
},
{
"Id": "AGENCYPICKUP_PARIS_BARGE",
"Level": 3
},
{
"Id": "STARTING_LOCATION_PARIS_PEACOCK_DRESSINGROOM",
"Level": 4
},
{
"Id": "FIREARMS_HERO_SNIPER_JAEGER",
"Level": 5
},
{
"Id": "AGENCYPICKUP_PARIS_PEACOCK_PANTRY",
"Level": 6
},
{
"Id": "STARTING_LOCATION_PARIS_PEACOCK_AVTECH",
"Level": 7
},
{
"Id": "FIREARMS_HERO_PISTOL_HWK_21",
"Level": 7
},
{
"Id": "AGENCYPICKUP_PARIS_PEACOCK_LOGISTICS_TRAILER",
"Level": 8
},
{
"Id": "STARTING_LOCATION_PARIS_PEACOCK_LOCKERROOM",
"Level": 9
},
{
"Id": "PROP_DEVICE_NAPOLEON_FIGURE_REMOTE_EXPLOSIVE",
"Level": 10
},
{
"Id": "FIREARMS_HERO_PISTOL_TACTICAL_SILVERBALLER",
"Level": 11
},
{
"Id": "STARTING_LOCATION_PARIS_PALACEGARDEN",
"Level": 12
},
{
"Id": "FIREARMS_HERO_SMG_TAC_SMG",
"Level": 12
},
{
"Id": "AGENCYPICKUP_PARIS_TOILET",
"Level": 13
},
{
"Id": "STARTING_LOCATION_PARIS_PEACOCK_ATTIC",
"Level": 14
},
{
"Id": "PROP_POISON_VIAL_FAST",
"Level": 15
},
{
"Id": "PROP_MELEE_SYRINGE_SEDATIVE",
"Level": 15
},
{
"Id": "AGENCYPICKUP_PARIS_PEACOCK_NEWSPAPERS",
"Level": 16
},
{
"Id": "STARTING_LOCATION_PARIS_SNIPERBARGE",
"Level": 17
},
{
"Id": "AGENCYPICKUP_PARIS_ATTIC_ROOM",
"Level": 18
},
{
"Id": "STARTING_LOCATION_PARIS_PEACOCK_AUCTION",
"Level": 19
},
{
"Id": "FIREARMS_HERO_PISTOL_LIGHT_HWK_21_COVERT",
"Level": 20
},
{
"Id": "PROP_DEVICE_ICA_MODULAR_REMOTE_EXPLOSIVE",
"Level": 20
}
]
}

@ -0,0 +1,117 @@
{
"Id": "LOCATION_PARENT_COLOMBIA",
"Drops": [
{
"Id": "AGENCYPICKUP_COLOMBIA_LARGE_VILLAGE_CONSTRUCTIONBUILDING",
"Level": 2
},
{
"Id": "PROP_POISON_PILLS_SEDATIVE",
"Level": 2
},
{
"Id": "STARTING_LOCATION_COLOMBIA_HIPPO_HOSTEL",
"Level": 3
},
{
"Id": "AGENCYPICKUP_COLOMBIA_SMALL_HOSTEL",
"Level": 4
},
{
"Id": "PROP_MELEE_MEAT_ITEM",
"Level": 4
},
{
"Id": "PROP_EXPLOSIVE_GRENADE_FRAG",
"Level": 5
},
{
"Id": "STARTING_LOCATION_COLOMBIA_HIPPO_VILLAGEBAR",
"Level": 6
},
{
"Id": "AGENCYPICKUP_COLOMBIA_SMALL_FISHINGVILLAGE",
"Level": 7
},
{
"Id": "PROP_POISON_PILLS_EMETIC",
"Level": 7
},
{
"Id": "STARTING_LOCATION_COLOMBIA_HIPPO_JUNGLE",
"Level": 8
},
{
"Id": "PROP_MELEE_VIOLIN_SMALL",
"Level": 8
},
{
"Id": "AGENCYPICKUP_COLOMBIA_SMALL_JUNGLE",
"Level": 9
},
{
"Id": "FIREARMS_HERO_RIFLE_AK47_HEROVERSION",
"Level": 10
},
{
"Id": "STARTING_LOCATION_COLOMBIA_HIPPO_CONSTRUCTIONSITE",
"Level": 11
},
{
"Id": "AGENCYPICKUP_COLOMBIA_LARGE_CONSTRUCTIONSITE",
"Level": 12
},
{
"Id": "STARTING_LOCATION_COLOMBIA_HIPPO_COCAFIELD",
"Level": 13
},
{
"Id": "FIREARMS_HERO_SMG_TAC_SMG_S2",
"Level": 13
},
{
"Id": "AGENCYPICKUP_COLOMBIA_LARGE_COCAFIELD",
"Level": 14
},
{
"Id": "PROP_DEVICE_ICA_RFID_COIN_EXPLOSIVE",
"Level": 15
},
{
"Id": "STARTING_LOCATION_COLOMBIA_HIPPO_SUBMARINECAVE",
"Level": 16
},
{
"Id": "PROP_MELEE_SACRIFICIAL_KNIFE",
"Level": 16
},
{
"Id": "AGENCYPICKUP_COLOMBIA_SMALL_CAVES",
"Level": 17
},
{
"Id": "PROP_DEVICE_ICA_REMOTE_TASER",
"Level": 17
},
{
"Id": "STARTING_LOCATION_COLOMBIA_HIPPO_MANSION",
"Level": 18
},
{
"Id": "PROP_DEVICE_ICA_PROXIMITY_SEMTEX_BLOCK",
"Level": 18
},
{
"Id": "AGENCYPICKUP_COLOMBIA_LARGE_MANSION_WINECELLAR",
"Level": 19
},
{
"Id": "PROP_DEVICE_ICA_MICRO_AUDIO_DISTRACTION",
"Level": 20
},
{
"Id": "PROP_EXPLOSIVE_SHAMAN_POWDER",
"Level": 20
}
]
}

@ -0,0 +1,101 @@
{
"Id": "LOCATION_PARENT_COASTALTOWN",
"Drops": [
{
"Id": "STARTING_LOCATION_SAPIENZA_APARTMENT",
"Level": 2
},
{
"Id": "PROP_MELEE_SYRINGE_LETHAL",
"Level": 2
},
{
"Id": "AGENCYPICKUP_SAPIENZA_CAFEBASEMENT",
"Level": 3
},
{
"Id": "STARTING_LOCATION_SAPIENZA_OCTOPUS_MANSIONGARDEN",
"Level": 4
},
{
"Id": "FIREARMS_HERO_RIFLE_FULLAUTO_TAC_4_AUTO",
"Level": 5
},
{
"Id": "AGENCYPICKUP_SAPIENZA_OCTOPUS_MANSIONGARAGE",
"Level": 6
},
{
"Id": "STARTING_LOCATION_SAPIENZA_OCTOPUS_MANSIONKITCHEN",
"Level": 7
},
{
"Id": "PROP_MELEE_COMBAT_KNIFE",
"Level": 7
},
{
"Id": "AGENCYPICKUP_SAPIENZA_RUINSTOWER",
"Level": 8
},
{
"Id": "STARTING_LOCATION_SAPIENZA_OCTOPUS_LEMONGARDEN",
"Level": 9
},
{
"Id": "PROP_DEVICE_ICA_MODULAR_REMOTE_AUDIODISTRACTION",
"Level": 10
},
{
"Id": "PROP_DISTRACTION_FIRECRACKER",
"Level": 10
},
{
"Id": "STARTING_LOCATION_SAPIENZA_OCTOPUS_BIOLAB",
"Level": 11
},
{
"Id": "AGENCYPICKUP_SAPIENZA_OCTOPUS_KITCHENPANTRY",
"Level": 12
},
{
"Id": "FIREARMS_HERO_SHOTGUN_SEMIAUTO_ENRAM_HV",
"Level": 12
},
{
"Id": "STARTING_LOCATION_SAPIENZA_HARBOUR",
"Level": 13
},
{
"Id": "AGENCYPICKUP_SAPIENZA_CHURCHCONFESSIONAL",
"Level": 14
},
{
"Id": "PROP_DEVICE_ICA_MODULAR_REMOTE_BREACHCHARGE",
"Level": 15
},
{
"Id": "STARTING_LOCATION_SAPIENZA_CAFETOWER",
"Level": 16
},
{
"Id": "AGENCYPICKUP_SAPIENZA_SEWERS",
"Level": 17
},
{
"Id": "STARTING_LOCATION_SAPIENZA_RUINS",
"Level": 18
},
{
"Id": "AGENCYPICKUP_SAPIENZA_OCTOPUS_BIOLAB",
"Level": 19
},
{
"Id": "FIREARMS_HERO_SNIPER_HEAVY_JAEAGER_LANCER",
"Level": 20
},
{
"Id": "PROP_MELEE_ANTIQUE_SYRINGE_EMETIC",
"Level": 20
}
]
}

@ -0,0 +1,101 @@
{
"Id": "LOCATION_PARENT_NORTHSEA",
"Drops": [
{
"Id": "PROP_MELEE_MACE",
"Level": 2
},
{
"Id": "AGENCYPICKUP_THEISLAND_LARGE_CHAPEL",
"Level": 2
},
{
"Id": "STARTING_LOCATION_THE_ISLAND_MAGPIE_EFFIGY",
"Level": 3
},
{
"Id": "AGENCYPICKUP_THEISLAND_SMALL_GATEHOUSE",
"Level": 4
},
{
"Id": "PROP_MELEE_SYRINGE_LETHAL_S2",
"Level": 5
},
{
"Id": "STARTING_LOCATION_THE_ISLAND_MAGPIE_WORKER_WAITER",
"Level": 6
},
{
"Id": "PROP_MELEE_FEATHER_DUSTER",
"Level": 6
},
{
"Id": "PROP_DEVICE_KEYCARD_HACKER_S2",
"Level": 7
},
{
"Id": "AGENCYPICKUP_THEISLAND_SMALL_BASEMENT",
"Level": 7
},
{
"Id": "STARTING_LOCATION_THE_ISLAND_MAGPIE_WORKER_CHEF",
"Level": 8
},
{
"Id": "AGENCYPICKUP_THEISLAND_SMALL_ARK",
"Level": 9
},
{
"Id": "FIREARMS_SNIPER_SIEGER_300_TACTICAL",
"Level": 10
},
{
"Id": "STARTING_LOCATION_THE_ISLAND_MAGPIE_WORKER_CUSTODIAN",
"Level": 11
},
{
"Id": "AGENCYPICKUP_THEISLAND_LARGE_KEEP",
"Level": 12
},
{
"Id": "STARTING_LOCATION_THE_ISLAND_MAGPIE_KEEP",
"Level": 13
},
{
"Id": "PROP_CONTAINER_SUITCASE_SLOW_MK_II",
"Level": 13
},
{
"Id": "AGENCYPICKUP_THEISLAND_LARGE_CISTERN",
"Level": 14
},
{
"Id": "PROP_MELEE_LONG_SWORD",
"Level": 15
},
{
"Id": "STARTING_LOCATION_THE_ISLAND_MAGPIE_ARKIAN_TIER2",
"Level": 15
},
{
"Id": "AGENCYPICKUP_THEISLAND_LARGE_CONSTANTS_BASEMENT",
"Level": 16
},
{
"Id": "FIREARMS_HERO_SHOTGUN_ENRAM_HV_COVERT_S2",
"Level": 18
},
{
"Id": "STARTING_LOCATION_THE_ISLAND_MAGPIE_ARKIAN_TIER3",
"Level": 18
},
{
"Id": "AGENCYPICKUP_THEISLAND_SMALL_CONFERENCE_ROOM",
"Level": 19
},
{
"Id": "PROP_DEVICE_REMOTE_RUBBERDUCK_CONCUSSION",
"Level": 20
}
]
}

@ -0,0 +1,113 @@
{
"Id": "LOCATION_PARENT_NORTHAMERICA",
"Drops": [
{
"Id": "FIREARMS_HERO_RIFLE_TAC_4_AR_AUTO_S2",
"Level": 2
},
{
"Id": "AGENCYPICKUP_NORTHAMERICA_SMALL_CREEK_SHED",
"Level": 2
},
{
"Id": "AGENCYPICKUP_NORTHAMERICA_SMALL_GARROS_DRIVEWAY",
"Level": 3
},
{
"Id": "STARTING_LOCATION_NORTHAMERICA_SKUNK_CONSTRUCTION",
"Level": 4
},
{
"Id": "PROP_DEVICE_PROXIMITY_CONCUSSION",
"Level": 5
},
{
"Id": "AGENCYPICKUP_NORTHAMERICA_LARGE_BENCH",
"Level": 5
},
{
"Id": "AGENCYPICKUP_NORTHAMERICA_SMALL_RENOVATION_HOUSE",
"Level": 6
},
{
"Id": "PROP_MELEE_MUFFIN_BLUEBERRY",
"Level": 6
},
{
"Id": "STARTING_LOCATION_NORTHAMERICA_SKUNK_FUMIGATION",
"Level": 7
},
{
"Id": "PROP_POISON_PILLS_LETHAL",
"Level": 7
},
{
"Id": "AGENCYPICKUP_NORTHAMERICA_LARGE_PARK_SHED",
"Level": 8
},
{
"Id": "STARTING_LOCATION_NORTHAMERICA_SKUNK_GARBAGE",
"Level": 9
},
{
"Id": "AGENCYPICKUP_NORTHAMERICA_SMALL_HELENS_GARAGE",
"Level": 9
},
{
"Id": "PROP_EXPLOSIVE_BASEBALL",
"Level": 10
},
{
"Id": "AGENCYPICKUP_NORTHAMERICA_SMALL_BATTYS_GARDEN",
"Level": 10
},
{
"Id": "STARTING_LOCATION_NORTHAMERICA_SKUNK_GARDENER",
"Level": 11
},
{
"Id": "AGENCYPICKUP_NORTHAMERICA_SMALL_HOUSE_FOR_SALE",
"Level": 12
},
{
"Id": "PROP_DEVICE_ICA_REMOTE_SEMTEX_BLOCK",
"Level": 13
},
{
"Id": "AGENCYPICKUP_NORTHAMERICA_LARGE_TREEHOUSE",
"Level": 13
},
{
"Id": "AGENCYPICKUP_NORTHAMERICA_SMALL_JANUS_KITCHEN",
"Level": 14
},
{
"Id": "FIREARMS_PISTOL_RUDE_RUBY",
"Level": 15
},
{
"Id": "AGENCYPICKUP_NORTHAMERICA_SMALL_PARK",
"Level": 16
},
{
"Id": "AGENCYPICKUP_NORTHAMERICA_LARGE_CASSIDYS_ATTIC",
"Level": 17
},
{
"Id": "STARTING_LOCATION_NORTHAMERICA_SKUNK_BBQ",
"Level": 18
},
{
"Id": "PROP_TOOL_BURGLARCROWBAR",
"Level": 18
},
{
"Id": "AGENCYPICKUP_NORTHAMERICA_LARGE_VACATIONHOUSE",
"Level": 19
},
{
"Id": "PROP_DEVICE_ICA_RUBBER_DUCK_REMOTE_EXPLOSIVE_S2",
"Level": 20
}
]
}

@ -19,11 +19,11 @@
import * as e from "esbuild"
import { createRequire } from "module"
import { esbuildPluginLicense } from "./esbuild-plugin-license.mjs"
import { packContractsAndChallenges } from "./buildTasks.mjs"
import { packResources } from "./buildTasks.mjs"
const require = createRequire(import.meta.url)
await packContractsAndChallenges()
await packResources()
const { version, revisionIdent } = require("../package.json")

@ -34,16 +34,28 @@ async function readJson(filePath) {
return JSON.parse((await readFile(filePath)).toString())
}
export async function packContractsAndChallenges() {
const resources = join("resources", "challenges")
async function createResourcesFolder(resources) {
if (!existsSync(resources)) {
await mkdir(resources)
} else {
for (const crp of await readdir(resources)) {
await unlink(join(resources, crp))
for (const prp of await readdir(resources)) {
await unlink(join(resources, prp))
}
}
}
async function handleFile(resources, name, contents) {
const targetName = createHash("md5").update(name).digest("hex")
await writeFile(join(resources, `${targetName}.prp`), packer.pack(contents))
}
export async function packResources() {
const challengesResources = join("resources", "challenges")
await createResourcesFolder(challengesResources)
const masteryResources = join("resources", "mastery")
await createResourcesFolder(masteryResources)
const start = Date.now()
@ -51,15 +63,6 @@ export async function packContractsAndChallenges() {
const b = []
const el = []
const handleChallengeFile = async (name, contents) => {
const targetName = createHash("md5").update(name).digest("hex")
await writeFile(
join(resources, `${targetName}.crp`),
packer.pack(contents),
)
}
for (const path of contracts) {
const filename = basename(path)
@ -78,9 +81,15 @@ export async function packContractsAndChallenges() {
const json = await readJson(path)
if (filename.startsWith("_")) {
if (filename.endsWith("_CHALLENGES.json")) {
// _LOCATION_CHALLENGES.json
await handleChallengeFile(filename + "#packed", json)
await handleFile(challengesResources, filename + "#packed", json)
continue
}
if (filename.endsWith("_MASTERY.json")) {
// _LOCATION_MASTERY.json
await handleFile(masteryResources, filename + "#packed", json)
continue
}

@ -17,7 +17,7 @@
*/
import picocolors from "picocolors"
import { packContractsAndChallenges } from "./buildTasks.mjs"
import { packResources } from "./buildTasks.mjs"
import { createRequire, Module } from "module"
import { readFileSync } from "fs"
@ -25,7 +25,7 @@ import { readFileSync } from "fs"
// TS files as if they were JS in a CommonJS environment
const require = createRequire(import.meta.url)
await packContractsAndChallenges()
await packResources()
const { version, revisionIdent } = require("../package.json")

@ -0,0 +1,642 @@
{
"buttons": [
{
"actiontype": "accept",
"actionlabel": "$loc UI_BUTTON_PROMPTS_ACTION_SELECT"
},
{
"actiontype": "cancel",
"actionlabel": "$loc UI_BUTTON_PROMPTS_ACTION_BACK"
}
],
"background": {
"url": "$res $.Location.Properties.Icon"
},
"onpageclosed": {
"set-mastery-data": {}
},
"body": {
"id": "root_list",
"controller": "list",
"data": {
"direction": "vertical"
},
"children": [
{
"controller": "group",
"id": "headline_container",
"row": 4.25,
"col": 0,
"selectable": false,
"pressable": false,
"_comment": "the container that will hold the HeadlineElement. It will show info on whatever item is selected",
"children": {
"id": "headline_element",
"view": "menu3.basic.HeadlineElement"
}
},
{
"controller": "list",
"id": "mastery_category_container"
},
{
"id": "mastery_category_controller",
"controller": "category",
"container": "mastery_category_container",
"view": "menu3.containers.ScrollingTabsContainer",
"direction": "horizontal",
"ncols": 10,
"data": {
"direction": "horizontal",
"overflowscrolling": "0.45",
"buttonprompts": [
{
"actiontype": ["lb", "rb"],
"actionlabel": "$loc UI_BUTTON_PROMPTS_BROWSE_CATEGORIES"
}
],
"topnavigation": {
"title": "$loc UI_MENU_PAGE_MASTERY_TITLE",
"icon": "unlocked"
}
},
"actions": {
"select": {
"set-selected": {
"target": "mastery-tile-unlocked",
"last-found": true
}
}
},
"children": {
"id": "$formatstring mastery_category_{$.Location.Id}",
"view": "menu3.basic.CategoryElement",
"data": {
"title": "$loc $formatstring UI_{$.Location.Id}_CITY",
"icon": "unlocked"
},
"children": {
"$if $eq (0,0)": {
"$then": [
{
"controller": "list",
"id": "sub_category_container",
"row": 0.1,
"col": 0,
"_comment": "enable analog handling to allow the submenu to handle LT/RT",
"handleanalog": true,
"actions": {
"$if $not $arg _isingame": {
"$then": {
"on-add-child": {
"show-background-layers": {
"showMenuBackgroundFullOverlay": true
}
},
"on-remove-child": {
"show-background-layers": {
"showMenuBackgroundFullOverlay": false
}
},
"on-page-closed": {
"show-background-layers": {
"showMenuBackgroundFullOverlay": false
}
}
}
}
}
},
{
"$setpageargs": {
"ShowPrevNextButtonPrompt": "$gt ($arraysize $.MasteryData,1)"
},
"controller": "category",
"id": "sub_category_controller",
"container": "sub_category_container",
"view": "menu3.containers.ScrollingTabsContainer",
"direction": "horizontal",
"submenu-navigation": true,
"prevnextnav": true,
"ncols": 10,
"data": {
"direction": "horizontal",
"submenu": true
},
"children": {
"$each $.MasteryData": {
"$if": {
"$condition": {
"$or": [
{
"$if $eqs ($arg _platform,stadia)": {
"$then": true,
"$else": true
}
},
"$eq ($._index,0)"
]
},
"$then": {
"$setpageargs": {
"IsUpgradeMastery": {
"$if $not $isnull $.Unlockable": {
"$then": true,
"$else": false
}
},
"OverrideUnlockableTileImage": {
"$if $not $isnull $.Unlockable": {
"$then": true,
"$else": false
}
}
},
"id": "$formatstring challenge_category_{$.Name}",
"view": "menu3.basic.SubCategoryElement",
"data": {
"title": {
"$if $not $isnull $.Unlockable": {
"$then": "$($item $.Unlockable).name",
"$else": "$loc UI_MENU_PAGE_PROFILE_LOCATION_MASTERY"
}
}
},
"buttons": [
{
"$if $arg ShowPrevNextButtonPrompt": {
"$then": {
"actiontype": "lt_rt",
"actionlabel": "$loc UI_BUTTON_PROMPTS_ACTION_PREVNEXT_CATEGORY",
"customplatform": {
"platform": "key",
"hide": true,
"actiontype": "mouse_lmb"
}
}
}
}
],
"actions": {
"select": {
"set-selected": {
"target": "mastery-tile-unlocked",
"last-found": true
}
}
},
"children": {
"controller": "list",
"id": "mastery_scrolling_group",
"view": "menu3.containers.ScrollingListContainer",
"col": 0.0,
"row": 1.0,
"ncols": 10,
"nrows": 3,
"direction": "horizontal",
"data": {
"direction": "horizontal",
"reversestartpos": true
},
"actions": {
"select": {
"set-mastery-data": {
"$setup": {
"$set ValidContractType": {
"$if $isnull $.Contract": {
"$then": true,
"$else": {
"$switch $.Contract.Metadata.Type": [
{
"case": "usercreated",
"return": false
},
{
"case": "featured",
"return": false
},
{
"default": true
}
]
}
}
},
"$set HideProgression": {
"$if $isnull $.CompletionData": {
"$then": "$.Data.LocationHideProgression",
"$else": "$.CompletionData.HideProgression"
}
},
"$set MasteryTitle": {
"$if $isnull $.CompletionData": {
"$then": "$formatstring {$.Data.LocationLevel,.0f}/{$.Data.LocationMaxLevel,.0f}",
"$else": "$formatstring {$.CompletionData.Level,.0f}/{$.CompletionData.MaxLevel,.0f}"
}
},
"$set MasteryCompletion": {
"$if $isnull $.CompletionData": {
"$then": "$.Data.LocationCompletion",
"$else": "$.CompletionData.Completion"
}
},
"$set MasteryXpLeft": {
"$if $isnull $.CompletionData": {
"$then": "$.Data.LocationXpLeft",
"$else": "$.CompletionData.XpLeft"
}
},
"$set NameLocalized": {
"$if $isnull $.CompletionData.Name": {
"$then": "$loc UI_MENU_PAGE_MASTERY_TITLE",
"$else": "$loc $.CompletionData.Name"
}
},
"$set IsLocationProgression": {
"$if": {
"$condition": {
"$or": [
"$isnull $.CompletionData",
"$.CompletionData.IsLocationProgression"
]
},
"$then": true,
"$else": false
}
},
"$set ShowUnit": {
"$if $.IsLocationProgression": {
"$then": true,
"$else": false
}
},
"$in": {
"$if": {
"$condition": {
"$and": [
"$arg _isonline",
"$not $.HideProgression",
"$.ValidContractType"
]
},
"$then": {
"masteryheader": "$.NameLocalized",
"masterytitle": "$.MasteryTitle",
"masterycompletion": "$.MasteryCompletion",
"masteryxpleft": "$.MasteryXpLeft",
"showUnit": "$.ShowUnit"
},
"$else": {}
}
}
}
}
},
"deselect": {
"set-mastery-data": {}
}
},
"children": {
"$merge": [
{
"$if $not $isnull $.Unlockable": {
"$then": {
"$setup": {
"$set Item": "$.Unlockable",
"$set LocalizedReproItem": "$item $.Unlockable",
"$set IsUpgradeMastery": false,
"$in": {
"id": "mastery-tile-unlocked",
"view": "menu3.basic.CategoryTile",
"nrows": 3,
"ncols": 2,
"pressable": true,
"data": {
"image": {
"$if $arg OverrideUnlockableTileImage": {
"$then": "$res $formatstring images/unlockables_override/{$.Unlockable.Id}_Tile.jpg",
"$else": "$.LocalizedReproItem.image"
}
},
"islocked": "$.IsLocked",
"header": "$.LocalizedReproItem.type",
"title": "$.LocalizedReproItem.name",
"icon": {
"$switch $.Unlockable.Type": [
{
"case": "access",
"return": "starting"
},
{
"case": "agencypickup",
"return": "stashpointempty"
},
{
"case": "loadoutunlock",
"return": "pistol"
},
{
"case": "difficultyunlock",
"return": "difficultylevel"
},
{
"default": "$.Unlockable.Subtype"
}
]
}
},
"actions": {
"accept": {
"show-modal": {
"config": {
"priority": "low",
"view": "menu3.modal.ModalDialogItemDetails",
"buttons": [
{
"label": "$loc UI_BUTTON_PROMPTS_ACTION_BACK",
"type": "cancel"
}
],
"data": {
"description": "$.LocalizedReproItem.desc",
"name": "$.LocalizedReproItem.name",
"type": {
"$if $.IsUpgradeMastery": {
"$then": "$loc UI_MENU_PAGE_MASTERY_UPGRADE_TITLE",
"$else": "$.Item.Type"
}
},
"subtype": {
"$if $.IsUpgradeMastery": {
"$then": null,
"$else": "$.Item.Subtype"
}
},
"image": "$.LocalizedReproItem.image",
"rarity": "$.LocalizedReproItem.rarity",
"perks": "$.LocalizedReproItem.perks",
"item": "$($repository $.LocalizedReproItem.repositoryid)",
"displaybuttons": [
{
"actiontype": "cancel",
"actionlabel": "$loc UI_BUTTON_PROMPTS_ACTION_BACK",
"hideIndicator": true
}
],
"actionAndKillTypes": {
"$setup": {
"$set ItemRepositoryId": "$repository $.LocalizedReproItem.repositoryid",
"$in": {
"$convertarray": {
"discardElementsWithoutConversion": true,
"sourceArray": "$.ItemRepositoryId.OnlineTraits",
"conversionRules": {
"melee_nonlethal": "$loc UI_ITEM_ONLINETRAITS_MELEE_NONLETHAL",
"melee_lethal": "$loc UI_ITEM_ONLINETRAITS_MELEE_LETHAL",
"throw_nonlethal": "$loc UI_ITEM_ONLINETRAITS_THROW_NONLETHAL",
"throw_lethal": "$loc UI_ITEM_ONLINETRAITS_THROW_LETHAL",
"fiberwire": "$loc UI_ITEM_ONLINETRAITS_FIBERWIRE",
"syringe_poison": "$loc UI_ITEM_ONLINETRAITS_SYRINGE_POISON",
"consumable_poison": "$loc UI_ITEM_ONLINETRAITS_CONSUMABLE_POISON",
"accident_explosion": "$loc UI_KILL_METHOD_ACCIDENT_EXPLOSION",
"detonator_explosive_device": "$loc UI_KILL_METHOD_EXPLOSIVE",
"explosive_device": "$loc UI_KILL_METHOD_EXPLOSIVE"
}
}
}
}
}
}
}
}
},
"select": {
"update-content": {
"target": "headline_element"
}
}
}
}
}
},
"$else": null
}
},
{
"$each $.Drops": {
"$setup": {
"$set Item": "$.Unlockable",
"$set LocalizedReproItem": "$item $.Unlockable",
"$set IsUpgradeMastery": "$arg IsUpgradeMastery",
"$in": {
"id": {
"$if $.IsLocked": {
"$then": "mastery-tile-locked",
"$else": "mastery-tile-unlocked"
}
},
"view": "menu3.basic.ObjectiveTile",
"nrows": 3,
"ncols": 2,
"pressable": true,
"data": {
"image": "$.LocalizedReproItem.image",
"islocked": "$.IsLocked",
"header": {
"$if $isnull $.Level": {
"$then": "$loc UI_OBJECTIVES_UNLOCKS_HEADER",
"$else": {
"$if $.IsLocked": {
"$then": "$loc UI_MENU_PAGE_MASTERY_UNLOCKS_AT_HEADER",
"$else": "$loc UI_MENU_PAGE_MASTERY_UNLOCKED_HEADER"
}
}
}
},
"title": "$formatstring {$loc UI_MENU_PAGE_MASTERY_LEVEL_SHORT} {$.Level,.0f}",
"icon": {
"$switch $.IsLocked": [
{
"case": false,
"return": "masteryunlocked"
},
{
"case": true,
"return": "locked"
},
{
"default": "locked"
}
]
},
"description": "$.LocalizedReproItem.desc",
"descriptionAlignment": "top",
"perks": "$.LocalizedReproItem.perks",
"rarity": "$.LocalizedReproItem.rarity",
"masteryLevel": "$formatstring {$loc UI_MENU_PAGE_MASTERY_LEVEL} {$.Level,.0f}",
"conditions": [
{
"header": {
"$if $arg IsUpgradeMastery": {
"$then": "$loc UI_MENU_PAGE_MASTERY_UPGRADE_TITLE",
"$else": "$.LocalizedReproItem.type"
}
},
"title": "$.LocalizedReproItem.name",
"icon": {
"$switch $.Unlockable.Type": [
{
"case": "access",
"return": "starting"
},
{
"case": "agencypickup",
"return": "stashpointempty"
},
{
"case": "loadoutunlock",
"return": "pistol"
},
{
"case": "difficultyunlock",
"return": "difficultylevel"
},
{
"default": "$.Unlockable.Subtype"
}
]
}
}
]
},
"actions": {
"accept": {
"show-modal": {
"config": {
"priority": "low",
"view": "menu3.modal.ModalDialogItemDetails",
"buttons": [
{
"label": "$loc UI_BUTTON_PROMPTS_ACTION_BACK",
"type": "cancel"
}
],
"data": {
"description": "$.LocalizedReproItem.desc",
"name": "$.LocalizedReproItem.name",
"type": {
"$if $.IsUpgradeMastery": {
"$then": "$loc UI_MENU_PAGE_MASTERY_UPGRADE_TITLE",
"$else": "$.Item.Type"
}
},
"subtype": {
"$if $.IsUpgradeMastery": {
"$then": null,
"$else": "$.Item.Subtype"
}
},
"image": "$.LocalizedReproItem.image",
"rarity": "$.LocalizedReproItem.rarity",
"perks": "$.LocalizedReproItem.perks",
"item": "$($repository $.LocalizedReproItem.repositoryid)",
"displaybuttons": [
{
"actiontype": "cancel",
"actionlabel": "$loc UI_BUTTON_PROMPTS_ACTION_BACK",
"hideIndicator": true
}
],
"actionAndKillTypes": {
"$setup": {
"$set ItemRepositoryId": "$repository $.LocalizedReproItem.repositoryid",
"$in": {
"$convertarray": {
"discardElementsWithoutConversion": true,
"sourceArray": "$.ItemRepositoryId.OnlineTraits",
"conversionRules": {
"melee_nonlethal": "$loc UI_ITEM_ONLINETRAITS_MELEE_NONLETHAL",
"melee_lethal": "$loc UI_ITEM_ONLINETRAITS_MELEE_LETHAL",
"throw_nonlethal": "$loc UI_ITEM_ONLINETRAITS_THROW_NONLETHAL",
"throw_lethal": "$loc UI_ITEM_ONLINETRAITS_THROW_LETHAL",
"fiberwire": "$loc UI_ITEM_ONLINETRAITS_FIBERWIRE",
"syringe_poison": "$loc UI_ITEM_ONLINETRAITS_SYRINGE_POISON",
"consumable_poison": "$loc UI_ITEM_ONLINETRAITS_CONSUMABLE_POISON",
"accident_explosion": "$loc UI_KILL_METHOD_ACCIDENT_EXPLOSION",
"detonator_explosive_device": "$loc UI_KILL_METHOD_EXPLOSIVE",
"explosive_device": "$loc UI_KILL_METHOD_EXPLOSIVE"
}
}
}
}
}
}
}
}
},
"select": {
"replace-children": {
"target": "headline_container",
"children": {
"id": "headline_element",
"view": "menu3.basic.HeadlineElement",
"selectable": false,
"pressable": false,
"data": {
"header": {
"$if $.IsUpgradeMastery": {
"$then": "$loc UI_MENU_PAGE_MASTERY_UPGRADE_TITLE",
"$else": "$loc $.TypeLocaKey"
}
},
"title": "$($item $.Item).name",
"typeicon": {
"$switch $.Unlockable.Type": [
{
"case": "access",
"return": "starting"
},
{
"case": "agencypickup",
"return": "stashpointempty"
},
{
"case": "loadoutunlock",
"return": "pistol"
},
{
"case": "difficultyunlock",
"return": "difficultylevel"
},
{
"default": "$.Unlockable.Subtype"
}
]
}
}
}
}
}
}
}
}
}
}
]
}
}
},
"$else": null
}
}
}
}
],
"$else": null
}
}
}
}
]
}
}