diff --git a/README.md b/README.md index 3bb8314..9b51d8a 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ - Llama purchasing and opening with random loot - Every Hero, Weapon, Defender and Resource - All Founder's Packs rewards screen (togglable in the config) +- Refreshing, sending, collecting and aborting expeditions - Crafting items in Backpack - Transferring items to and from Storage - Modifying and upgrading Schematic perks diff --git a/responses/Campaign/expeditionData.json b/responses/Campaign/expeditionData.json new file mode 100644 index 0000000..d9fd142 --- /dev/null +++ b/responses/Campaign/expeditionData.json @@ -0,0 +1,1604 @@ +{ + "author": "This list was created by PRO100KatYT", + "note": "Half of the data here is from epic servers and cannot be found in the game files.", + "questsUnlockingSlots": [ + "quest:stonewoodquest_launchrocket_d5", + "quest:outpostquest_t2_l2", + "quest:outpostquest_t2_l3", + "quest:outpostquest_t2_l4", + "quest:outpostquest_t2_l6", + "quest:outpostquest_t3_l1", + "quest:outpostquest_t3_l4", + "quest:outpostquest_t3_l5", + "quest:outpostquest_t4_l2", + "quest:outpostquest_t4_l3", + "quest:outpostquest_t4_l4" + ], + "slotsFromQuests": { + "quest:stonewoodquest_launchrocket_d5": [ + "expedition.generation.miningore", + "expedition.generation.choppingwood", + "expedition.generation.land.t01_0", + "expedition.generation.land.t01_1" + ], + "quest:outpostquest_t2_l2": [ + "expedition.generation.sea.t01_0", + "expedition.generation.sea.t01_1" + ], + "quest:outpostquest_t2_l3": [ + "expedition.generation.air.t02_0", + "expedition.generation.air.t02_1" + ], + "quest:outpostquest_t2_l4": [ + "expedition.generation.land.t02_0", + "expedition.generation.land.t02_1" + ], + "quest:outpostquest_t2_l6": [ + "expedition.generation.sea.t02_0", + "expedition.generation.sea.t02_1" + ], + "quest:outpostquest_t3_l1": [ + "expedition.generation.sea.t03_0", + "expedition.generation.sea.t03_1" + ], + "quest:outpostquest_t3_l4": [ + "expedition.generation.air.t03_0", + "expedition.generation.air.t03_1" + ], + "quest:outpostquest_t3_l5": [ + "expedition.generation.land.t03_0", + "expedition.generation.land.t03_1" + ], + "quest:outpostquest_t4_l2": [ + "expedition.generation.land.t04_0", + "expedition.generation.land.t04_1" + ], + "quest:outpostquest_t4_l3": [ + "expedition.generation.sea.t04_0", + "expedition.generation.sea.t04_1" + ], + "quest:outpostquest_t4_l4": [ + "expedition.generation.air.t04_0", + "expedition.generation.air.t04_1" + ] + }, + "slots": { + "expedition.generation.land.t01_0": { + "normal": [ + "Expedition:expedition_resourcerun_wood_medium", + "Expedition:expedition_resourcerun_stone_short", + "Expedition:expedition_survivorscouting_short_t01", + "Expedition:expedition_supplyrun_short_t01", + "Expedition:expedition_craftingrun_short_t01", + "Expedition:expedition_resourcerun_stone_medium", + "Expedition:expedition_supplyrun_medium_t01", + "Expedition:expedition_craftingrun_medium_t01", + "Expedition:expedition_resourcerun_wood_short" + ] + }, + "expedition.generation.land.t01_1": { + "normal": [ + "Expedition:expedition_resourcerun_stone_short", + "Expedition:expedition_resourcerun_wood_medium", + "Expedition:expedition_survivorscouting_short_t01", + "Expedition:expedition_supplyrun_medium_t01", + "Expedition:expedition_resourcerun_stone_medium", + "Expedition:expedition_craftingrun_short_t01", + "Expedition:expedition_resourcerun_wood_short", + "Expedition:expedition_craftingrun_medium_t01", + "Expedition:expedition_supplyrun_short_t01" + ] + }, + "expedition.generation.land.t02_0": { + "normal": [ + "Expedition:expedition_resourcerun_woodstone_medium", + "Expedition:expedition_supplyrun_short_t02", + "Expedition:expedition_supplyrun_medium_t02", + "Expedition:expedition_supplyrun_long_t02", + "Expedition:expedition_survivorscouting_medium_t02", + "Expedition:expedition_resourcerun_metal_short", + "Expedition:expedition_resourcerun_metal_medium", + "Expedition:expedition_resourcerun_woodstone_short", + "Expedition:expedition_craftingrun_medium_t02", + "Expedition:expedition_craftingrun_short_t02", + "Expedition:expedition_resourcerun_stone_medium", + "Expedition:expedition_resourcerun_stone_short" + ], + "rare": [ + "Expedition:expedition_rare_weapons_t02" + ] + }, + "expedition.generation.land.t02_1": { + "normal": [ + "Expedition:expedition_resourcerun_stone_short", + "Expedition:expedition_resourcerun_woodstone_medium", + "Expedition:expedition_resourcerun_metal_short", + "Expedition:expedition_supplyrun_long_t02", + "Expedition:expedition_resourcerun_stone_medium", + "Expedition:expedition_resourcerun_woodstone_short", + "Expedition:expedition_craftingrun_short_t02", + "Expedition:expedition_supplyrun_medium_t02", + "Expedition:expedition_resourcerun_metal_medium", + "Expedition:expedition_supplyrun_short_t02", + "Expedition:expedition_survivorscouting_medium_t02", + "Expedition:expedition_craftingrun_medium_t02" + ], + "rare": [ + "Expedition:expedition_rare_traps_t02", + "Expedition:expedition_rare_weapons_t02" + ] + }, + "expedition.generation.land.t03_0": { + "normal": [ + "Expedition:expedition_supplyrun_short_t03", + "Expedition:expedition_survivorscouting_long_t03", + "Expedition:expedition_craftingrun_short_t03", + "Expedition:expedition_supplyrun_long_t03", + "Expedition:expedition_supplyrun_medium_t03", + "Expedition:expedition_craftingrun_long_t03", + "Expedition:expedition_craftingrun_medium_t03" + ], + "rare": [ + "Expedition:expedition_rare_managers_t03", + "Expedition:expedition_rare_heroes_t03", + "Expedition:expedition_rare_traps_t03", + "Expedition:expedition_rare_weapons_t03" + ] + }, + "expedition.generation.land.t03_1": { + "normal": [ + "Expedition:expedition_supplyrun_long_t03", + "Expedition:expedition_supplyrun_short_t03", + "Expedition:expedition_craftingrun_long_t03", + "Expedition:expedition_survivorscouting_long_t03", + "Expedition:expedition_craftingrun_short_t03", + "Expedition:expedition_supplyrun_medium_t03", + "Expedition:expedition_craftingrun_medium_t03" + ], + "rare": [ + "Expedition:expedition_rare_managers_t03", + "Expedition:expedition_rare_heroes_t03", + "Expedition:expedition_rare_traps_t03", + "Expedition:expedition_rare_weapons_t03" + ] + }, + "expedition.generation.land.t04_0": { + "normal": [ + "Expedition:expedition_survivorscouting_long_t04", + "Expedition:expedition_supplyrun_long_t04", + "Expedition:expedition_craftingrun_long_t04" + ], + "rare": [ + "Expedition:expedition_rare_weapons_t04", + "Expedition:expedition_rare_heroes_t04", + "Expedition:expedition_rare_managers_t04", + "Expedition:expedition_rare_traps_t04" + ] + }, + "expedition.generation.land.t04_1": { + "normal": [ + "Expedition:expedition_supplyrun_long_t04", + "Expedition:expedition_survivorscouting_long_t04", + "Expedition:expedition_craftingrun_long_t04" + ], + "rare": [ + "Expedition:expedition_rare_weapons_t04", + "Expedition:expedition_rare_heroes_t04", + "Expedition:expedition_rare_traps_t04", + "Expedition:expedition_rare_managers_t04" + ] + }, + "expedition.generation.sea.t03_0": { + "normal": [ + "Expedition:expedition_sea_supplyrun_long_t03", + "Expedition:expedition_sea_survivorscouting_medium_t03" + ] + }, + "expedition.generation.sea.t03_1": { + "normal": [ + "Expedition:expedition_sea_survivorscouting_medium_t03", + "Expedition:expedition_sea_supplyrun_long_t03" + ] + }, + "expedition.generation.sea.t04_0": { + "normal": [ + "Expedition:expedition_sea_supplyrun_long_t04", + "Expedition:expedition_sea_survivorscouting_long_t04" + ], + "rare": [ + "Expedition:expedition_rare_sea_traps_t04", + "Expedition:expedition_rare_sea_weapons_t04", + "Expedition:expedition_rare_sea_managers_t05", + "Expedition:expedition_rare_sea_managers_t04", + "Expedition:expedition_rare_sea_heroes_t04", + "Expedition:expedition_rare_sea_traps_t05", + "Expedition:expedition_rare_sea_weapons_t05", + "Expedition:expedition_rare_sea_heroes_t05" + ] + }, + "expedition.generation.sea.t04_1": { + "normal": [ + "Expedition:expedition_sea_supplyrun_long_t04", + "Expedition:expedition_sea_survivorscouting_long_t04" + ], + "rare": [ + "Expedition:expedition_rare_sea_traps_t04", + "Expedition:expedition_rare_sea_traps_t05", + "Expedition:expedition_rare_sea_managers_t04", + "Expedition:expedition_rare_sea_heroes_t04", + "Expedition:expedition_rare_sea_weapons_t04", + "Expedition:expedition_rare_sea_managers_t05", + "Expedition:expedition_rare_sea_heroes_t05" + ] + }, + "expedition.generation.air.t03_0": { + "normal": [ + "Expedition:expedition_air_survivorscouting_medium_t03", + "Expedition:expedition_air_supplyrun_long_t03" + ] + }, + "expedition.generation.air.t03_1": { + "normal": [ + "Expedition:expedition_air_survivorscouting_medium_t03", + "Expedition:expedition_air_supplyrun_long_t03" + ] + }, + "expedition.generation.air.t04_0": { + "normal": [ + "Expedition:expedition_air_supplyrun_long_t04", + "Expedition:expedition_air_survivorscouting_long_t04" + ], + "rare": [ + "Expedition:expedition_rare_air_heroes_t04", + "Expedition:expedition_rare_air_traps_t05", + "Expedition:expedition_rare_air_weapons_t04", + "Expedition:expedition_rare_air_managers_t04", + "Expedition:expedition_rare_air_traps_t04", + "Expedition:expedition_rare_air_heroes_t05", + "Expedition:expedition_rare_air_weapons_t05", + "Expedition:expedition_rare_air_managers_t05" + ] + }, + "expedition.generation.air.t04_1": { + "normal": [ + "Expedition:expedition_air_supplyrun_long_t04", + "Expedition:expedition_air_survivorscouting_long_t04" + ], + "rare": [ + "Expedition:expedition_rare_air_heroes_t04", + "Expedition:expedition_rare_air_traps_t04", + "Expedition:expedition_rare_air_weapons_t04", + "Expedition:expedition_rare_air_managers_t05", + "Expedition:expedition_rare_air_managers_t04", + "Expedition:expedition_rare_air_weapons_t05", + "Expedition:expedition_rare_air_traps_t05", + "Expedition:expedition_rare_air_heroes_t05" + ] + }, + "expedition.generation.choppingwood": { + "normal": [ + "Expedition:expedition_miningore_t00" + ] + }, + "expedition.generation.miningore": { + "normal": [ + "Expedition:expedition_choppingwood_t00" + ] + }, + "expedition.generation.sea.t01_0": { + "normal": [ + "Expedition:expedition_sea_supplyrun_short_t01", + "Expedition:expedition_sea_survivorscouting_short_t01" + ] + }, + "expedition.generation.sea.t01_1": { + "normal": [ + "Expedition:expedition_sea_survivorscouting_short_t01", + "Expedition:expedition_sea_supplyrun_short_t01" + ] + }, + "expedition.generation.sea.t02_0": { + "normal": [ + "Expedition:expedition_sea_supplyrun_medium_t02", + "Expedition:expedition_sea_survivorscouting_medium_t02" + ] + }, + "expedition.generation.sea.t02_1": { + "normal": [ + "Expedition:expedition_sea_supplyrun_medium_t02", + "Expedition:expedition_sea_survivorscouting_medium_t02" + ] + }, + "expedition.generation.air.t02_0": { + "normal": [ + "Expedition:expedition_air_supplyrun_long_t02", + "Expedition:expedition_air_supplyrun_medium_t02", + "Expedition:expedition_air_survivorscouting_long_t02" + ] + }, + "expedition.generation.air.t02_1": { + "normal": [ + "Expedition:expedition_air_survivorscouting_long_t02", + "Expedition:expedition_air_supplyrun_long_t02", + "Expedition:expedition_air_supplyrun_medium_t02" + ] + } + }, + "attributes": { + "Expedition:expedition_air_supplyrun_long_t02": { + "expedition_max_target_power": 330, + "expedition_min_target_power": 16, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 1200 + }, + "Expedition:expedition_air_supplyrun_long_t03": { + "expedition_max_target_power": 520, + "expedition_min_target_power": 26, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 1200 + }, + "Expedition:expedition_air_supplyrun_long_t04": { + "expedition_max_target_power": 735, + "expedition_min_target_power": 36, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 1320 + }, + "Expedition:expedition_air_supplyrun_medium_t02": { + "expedition_max_target_power": 230, + "expedition_min_target_power": 11, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 960 + }, + "Expedition:expedition_air_survivorscouting_long_t02": { + "expedition_max_target_power": 385, + "expedition_min_target_power": 19, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 1200 + }, + "Expedition:expedition_air_survivorscouting_long_t04": { + "expedition_max_target_power": 835, + "expedition_min_target_power": 41, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 1320 + }, + "Expedition:expedition_air_survivorscouting_medium_t03": { + "expedition_max_target_power": 390, + "expedition_min_target_power": 19, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 960 + }, + "Expedition:expedition_choppingwood_t00": { + "expedition_max_target_power": 20, + "expedition_min_target_power": 1, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 240 + }, + "Expedition:expedition_craftingrun_long_t03": { + "expedition_max_target_power": 475, + "expedition_min_target_power": 23, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 1200 + }, + "Expedition:expedition_craftingrun_long_t04": { + "expedition_max_target_power": 685, + "expedition_min_target_power": 34, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 1320 + }, + "Expedition:expedition_craftingrun_medium_t01": { + "expedition_max_target_power": 105, + "expedition_min_target_power": 5, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 960 + }, + "Expedition:expedition_craftingrun_medium_t02": { + "expedition_max_target_power": 195, + "expedition_min_target_power": 9, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 960 + }, + "Expedition:expedition_craftingrun_medium_t03": { + "expedition_max_target_power": 275, + "expedition_min_target_power": 13, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 960 + }, + "Expedition:expedition_craftingrun_short_t01": { + "expedition_max_target_power": 95, + "expedition_min_target_power": 4, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 480 + }, + "Expedition:expedition_craftingrun_short_t02": { + "expedition_max_target_power": 155, + "expedition_min_target_power": 7, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 480 + }, + "Expedition:expedition_craftingrun_short_t03": { + "expedition_max_target_power": 225, + "expedition_min_target_power": 11, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 480 + }, + "Expedition:expedition_miningore_t00": { + "expedition_max_target_power": 25, + "expedition_min_target_power": 1, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 240 + }, + "Expedition:expedition_rare_air_heroes_t04": { + "expedition_max_target_power": 1540, + "expedition_min_target_power": 77, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 1320 + }, + "Expedition:expedition_rare_air_heroes_t05": { + "expedition_max_target_power": 1840, + "expedition_min_target_power": 92, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 1440 + }, + "Expedition:expedition_rare_air_managers_t04": { + "expedition_max_target_power": 1240, + "expedition_min_target_power": 62, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 1320 + }, + "Expedition:expedition_rare_air_managers_t05": { + "expedition_max_target_power": 1540, + "expedition_min_target_power": 77, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 1440 + }, + "Expedition:expedition_rare_air_traps_t04": { + "expedition_max_target_power": 1240, + "expedition_min_target_power": 62, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 1320 + }, + "Expedition:expedition_rare_air_traps_t05": { + "expedition_max_target_power": 1540, + "expedition_min_target_power": 77, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 1440 + }, + "Expedition:expedition_rare_air_weapons_t04": { + "expedition_max_target_power": 1240, + "expedition_min_target_power": 62, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 1320 + }, + "Expedition:expedition_rare_air_weapons_t05": { + "expedition_max_target_power": 1540, + "expedition_min_target_power": 77, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 1440 + }, + "Expedition:expedition_rare_heroes_t03": { + "expedition_max_target_power": 740, + "expedition_min_target_power": 37, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 1320 + }, + "Expedition:expedition_rare_heroes_t04": { + "expedition_max_target_power": 1440, + "expedition_min_target_power": 72, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 1320 + }, + "Expedition:expedition_rare_managers_t03": { + "expedition_max_target_power": 740, + "expedition_min_target_power": 37, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 1320 + }, + "Expedition:expedition_rare_managers_t04": { + "expedition_max_target_power": 1440, + "expedition_min_target_power": 72, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 1320 + }, + "Expedition:expedition_rare_sea_heroes_t04": { + "expedition_max_target_power": 1640, + "expedition_min_target_power": 82, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 1320 + }, + "Expedition:expedition_rare_sea_heroes_t05": { + "expedition_max_target_power": 2040, + "expedition_min_target_power": 102, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 1440 + }, + "Expedition:expedition_rare_sea_managers_t04": { + "expedition_max_target_power": 1240, + "expedition_min_target_power": 62, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 1320 + }, + "Expedition:expedition_rare_sea_managers_t05": { + "expedition_max_target_power": 1540, + "expedition_min_target_power": 77, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 1440 + }, + "Expedition:expedition_rare_sea_traps_t04": { + "expedition_max_target_power": 1240, + "expedition_min_target_power": 62, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 1320 + }, + "Expedition:expedition_rare_sea_traps_t05": { + "expedition_max_target_power": 1540, + "expedition_min_target_power": 77, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 1440 + }, + "Expedition:expedition_rare_sea_weapons_t04": { + "expedition_max_target_power": 1240, + "expedition_min_target_power": 62, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 1320 + }, + "Expedition:expedition_rare_sea_weapons_t05": { + "expedition_max_target_power": 1540, + "expedition_min_target_power": 77, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 1440 + }, + "Expedition:expedition_rare_traps_t02": { + "expedition_max_target_power": 220, + "expedition_min_target_power": 11, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 1320 + }, + "Expedition:expedition_rare_traps_t03": { + "expedition_max_target_power": 490, + "expedition_min_target_power": 24, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 1320 + }, + "Expedition:expedition_rare_traps_t04": { + "expedition_max_target_power": 1240, + "expedition_min_target_power": 62, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 1320 + }, + "Expedition:expedition_rare_weapons_t02": { + "expedition_max_target_power": 220, + "expedition_min_target_power": 11, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 1320 + }, + "Expedition:expedition_rare_weapons_t03": { + "expedition_max_target_power": 490, + "expedition_min_target_power": 24, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 1320 + }, + "Expedition:expedition_rare_weapons_t04": { + "expedition_max_target_power": 1240, + "expedition_min_target_power": 62, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 1320 + }, + "Expedition:expedition_resourcerun_metal_medium": { + "expedition_max_target_power": 140, + "expedition_min_target_power": 7, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 960 + }, + "Expedition:expedition_resourcerun_metal_short": { + "expedition_max_target_power": 125, + "expedition_min_target_power": 6, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 480 + }, + "Expedition:expedition_resourcerun_stone_medium": { + "expedition_max_target_power": 120, + "expedition_min_target_power": 6, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 960 + }, + "Expedition:expedition_resourcerun_stone_short": { + "expedition_max_target_power": 110, + "expedition_min_target_power": 5, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 480 + }, + "Expedition:expedition_resourcerun_woodstone_medium": { + "expedition_max_target_power": 130, + "expedition_min_target_power": 6, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 960 + }, + "Expedition:expedition_resourcerun_woodstone_short": { + "expedition_max_target_power": 120, + "expedition_min_target_power": 6, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 480 + }, + "Expedition:expedition_resourcerun_wood_medium": { + "expedition_max_target_power": 100, + "expedition_min_target_power": 5, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 960 + }, + "Expedition:expedition_resourcerun_wood_short": { + "expedition_max_target_power": 95, + "expedition_min_target_power": 4, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 480 + }, + "Expedition:expedition_sea_supplyrun_long_t03": { + "expedition_max_target_power": 500, + "expedition_min_target_power": 25, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 1200 + }, + "Expedition:expedition_sea_supplyrun_long_t04": { + "expedition_max_target_power": 725, + "expedition_min_target_power": 36, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 1320 + }, + "Expedition:expedition_sea_supplyrun_medium_t02": { + "expedition_max_target_power": 215, + "expedition_min_target_power": 10, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 960 + }, + "Expedition:expedition_sea_supplyrun_short_t01": { + "expedition_max_target_power": 110, + "expedition_min_target_power": 5, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 480 + }, + "Expedition:expedition_sea_survivorscouting_long_t04": { + "expedition_max_target_power": 825, + "expedition_min_target_power": 41, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 1320 + }, + "Expedition:expedition_sea_survivorscouting_medium_t02": { + "expedition_max_target_power": 270, + "expedition_min_target_power": 13, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 960 + }, + "Expedition:expedition_sea_survivorscouting_medium_t03": { + "expedition_max_target_power": 370, + "expedition_min_target_power": 18, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 960 + }, + "Expedition:expedition_sea_survivorscouting_short_t01": { + "expedition_max_target_power": 120, + "expedition_min_target_power": 6, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 480 + }, + "Expedition:expedition_supplyrun_long_t02": { + "expedition_max_target_power": 295, + "expedition_min_target_power": 14, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 1200 + }, + "Expedition:expedition_supplyrun_long_t03": { + "expedition_max_target_power": 475, + "expedition_min_target_power": 23, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 1200 + }, + "Expedition:expedition_supplyrun_long_t04": { + "expedition_max_target_power": 685, + "expedition_min_target_power": 34, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 1320 + }, + "Expedition:expedition_supplyrun_medium_t01": { + "expedition_max_target_power": 105, + "expedition_min_target_power": 5, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 960 + }, + "Expedition:expedition_supplyrun_medium_t02": { + "expedition_max_target_power": 195, + "expedition_min_target_power": 9, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 960 + }, + "Expedition:expedition_supplyrun_medium_t03": { + "expedition_max_target_power": 275, + "expedition_min_target_power": 13, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 960 + }, + "Expedition:expedition_supplyrun_short_t01": { + "expedition_max_target_power": 95, + "expedition_min_target_power": 4, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 480 + }, + "Expedition:expedition_supplyrun_short_t02": { + "expedition_max_target_power": 155, + "expedition_min_target_power": 7, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 480 + }, + "Expedition:expedition_supplyrun_short_t03": { + "expedition_max_target_power": 225, + "expedition_min_target_power": 11, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 480 + }, + "Expedition:expedition_survivorscouting_long_t03": { + "expedition_max_target_power": 545, + "expedition_min_target_power": 27, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 1200 + }, + "Expedition:expedition_survivorscouting_long_t04": { + "expedition_max_target_power": 785, + "expedition_min_target_power": 39, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 1320 + }, + "Expedition:expedition_survivorscouting_medium_t02": { + "expedition_max_target_power": 250, + "expedition_min_target_power": 12, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 960 + }, + "Expedition:expedition_survivorscouting_short_t01": { + "expedition_max_target_power": 130, + "expedition_min_target_power": 6, + "expiration_duration_minutes": 90, + "expedition_duration_minutes": 480 + } + }, + "note2": "The rewards here are different from the ones on epic servers.", + "rewards": [ + [ + { + "templateId": "WorldItem:wooditemdata", + "itemProfile": "theater0", + "minQuantity": 50, + "maxQuantity": 250 + }, + { + "templateId": "WorldItem:stoneitemdata", + "itemProfile": "theater0", + "minQuantity": 50, + "maxQuantity": 250 + }, + { + "templateId": "WorldItem:metalitemdata", + "itemProfile": "theater0", + "minQuantity": 50, + "maxQuantity": 250 + } + ], + [ + { + "templateId": "Ingredient:ingredient_ore_obsidian", + "itemProfile": "theater0", + "minQuantity": 50, + "maxQuantity": 250 + }, + { + "templateId": "Ingredient:ingredient_ore_malachite", + "itemProfile": "theater0", + "minQuantity": 50, + "maxQuantity": 250 + }, + + { + "templateId": "Ingredient:ingredient_ore_silver", + "itemProfile": "theater0", + "minQuantity": 50, + "maxQuantity": 250 + }, + + { + "templateId": "Ingredient:ingredient_ore_copper", + "itemProfile": "theater0", + "minQuantity": 50, + "maxQuantity": 250 + } + ], + [ + { + "templateId": "Ingredient:ingredient_mechanical_parts_t04", + "itemProfile": "theater0", + "minQuantity": 50, + "maxQuantity": 250 + }, + { + "templateId": "Ingredient:ingredient_mechanical_parts_t03", + "itemProfile": "theater0", + "minQuantity": 50, + "maxQuantity": 250 + }, + { + "templateId": "Ingredient:ingredient_mechanical_parts_t02", + "itemProfile": "theater0", + "minQuantity": 50, + "maxQuantity": 250 + }, + { + "templateId": "Ingredient:ingredient_mechanical_parts_t01", + "itemProfile": "theater0", + "minQuantity": 50, + "maxQuantity": 250 + } + ], + [ + { + "templateId": "Ingredient:ingredient_rare_powercell", + "itemProfile": "theater0", + "minQuantity": 50, + "maxQuantity": 250 + }, + { + "templateId": "Ingredient:ingredient_batteries", + "itemProfile": "theater0", + "minQuantity": 50, + "maxQuantity": 250 + }, + { + "templateId": "Ingredient:ingredient_rare_mechanism", + "itemProfile": "theater0", + "minQuantity": 50, + "maxQuantity": 250 + } + ], + [ + { + "templateId": "Ingredient:ingredient_twine_t04", + "itemProfile": "theater0", + "minQuantity": 50, + "maxQuantity": 250 + }, + { + "templateId": "Ingredient:ingredient_twine_t03", + "itemProfile": "theater0", + "minQuantity": 50, + "maxQuantity": 250 + }, + { + "templateId": "Ingredient:ingredient_twine_t02", + "itemProfile": "theater0", + "minQuantity": 50, + "maxQuantity": 250 + }, + { + "templateId": "Ingredient:ingredient_twine_t01", + "itemProfile": "theater0", + "minQuantity": 50, + "maxQuantity": 250 + } + ], + [ + { + "templateId": "Ingredient:ingredient_duct_tape", + "itemProfile": "theater0", + "minQuantity": 50, + "maxQuantity": 250 + }, + { + "templateId": "Ingredient:ingredient_ore_coal", + "itemProfile": "theater0", + "minQuantity": 50, + "maxQuantity": 250 + }, + { + "templateId": "Ingredient:ingredient_crystal_quartz", + "itemProfile": "theater0", + "minQuantity": 50, + "maxQuantity": 250 + }, + { + "templateId": "Ingredient:ingredient_resin", + "itemProfile": "theater0", + "minQuantity": 50, + "maxQuantity": 250 + } + ], + [ + { + "templateId": "Ingredient:ingredient_powder_t04", + "itemProfile": "theater0", + "minQuantity": 50, + "maxQuantity": 250 + }, + { + "templateId": "Ingredient:ingredient_powder_t03", + "itemProfile": "theater0", + "minQuantity": 50, + "maxQuantity": 250 + }, + { + "templateId": "Ingredient:ingredient_powder_t02", + "itemProfile": "theater0", + "minQuantity": 50, + "maxQuantity": 250 + }, + { + "templateId": "Ingredient:ingredient_powder_t01", + "itemProfile": "theater0", + "minQuantity": 50, + "maxQuantity": 250 + } + ], + [ + { + "templateId": "Ingredient:ingredient_bacon", + "itemProfile": "theater0", + "minQuantity": 50, + "maxQuantity": 250 + }, + { + "templateId": "Ingredient:ingredient_planks", + "itemProfile": "theater0", + "minQuantity": 50, + "maxQuantity": 250 + }, + { + "templateId": "Ingredient:ingredient_flowers", + "itemProfile": "theater0", + "minQuantity": 50, + "maxQuantity": 250 + }, + { + "templateId": "Ingredient:ingredient_ore_alloy", + "itemProfile": "theater0", + "minQuantity": 50, + "maxQuantity": 250 + }, + { + "templateId": "Ingredient:ingredient_nuts_bolts", + "itemProfile": "theater0", + "minQuantity": 50, + "maxQuantity": 250 + }, + { + "templateId": "Ingredient:ingredient_herbs", + "itemProfile": "theater0", + "minQuantity": 50, + "maxQuantity": 250 + } + ] + ], + "criteria": [ + "RequiresNinja", + "RequiresCommando", + "RequiresConstructor", + "RequiresOutlander", + "RequiresRareNinja", + "RequiresRareCommando", + "RequiresRareConstructor", + "RequiresRareOutlander", + "RequiresEpicNinja", + "RequiresEpicCommando", + "RequiresEpicConstructor", + "RequiresEpicOutlander", + "RequiresLegendaryNinja", + "RequiresLegendaryCommando", + "RequiresLegendaryConstructor", + "RequiresLegendaryOutlander" + ], + "criteriaRequirements": { + "RequiresNinja": { + "ModValue": 1.5, + "requirements": { + "class": "ninja" + } + }, + "RequiresCommando": { + "ModValue": 1.5, + "requirements": { + "class": "commando" + } + }, + "RequiresConstructor": { + "ModValue": 1.5, + "requirements": { + "class": "constructor" + } + }, + "RequiresOutlander": { + "ModValue": 1.5, + "requirements": { + "class": "outlander" + } + }, + "RequiresRareNinja": { + "ModValue": 1.625, + "requirements": { + "class": "ninja", + "rarity": [ + "r", + "vr", + "sr" + ] + } + }, + "RequiresRareCommando": { + "ModValue": 1.625, + "requirements": { + "class": "commando", + "rarity": [ + "r", + "vr", + "sr" + ] + } + }, + "RequiresRareConstructor": { + "ModValue": 1.625, + "requirements": { + "class": "constructor", + "rarity": [ + "r", + "vr", + "sr" + ] + } + }, + "RequiresRareOutlander": { + "ModValue": 1.625, + "requirements": { + "class": "outlander", + "rarity": [ + "r", + "vr", + "sr" + ] + } + }, + "RequiresEpicNinja": { + "ModValue": 1.75, + "requirements": { + "class": "ninja", + "rarity": [ + "vr", + "sr" + ] + } + }, + "RequiresEpicCommando": { + "ModValue": 1.75, + "requirements": { + "class": "commando", + "rarity": [ + "vr", + "sr" + ] + } + }, + "RequiresEpicConstructor": { + "ModValue": 1.75, + "requirements": { + "class": "constructor", + "rarity": [ + "vr", + "sr" + ] + } + }, + "RequiresEpicOutlander": { + "ModValue": 1.75, + "requirements": { + "class": "outlander", + "rarity": [ + "vr", + "sr" + ] + } + }, + "RequiresLegendaryNinja": { + "ModValue": 2.0, + "requirements": { + "class": "ninja", + "rarity": [ + "sr" + ] + } + }, + "RequiresLegendaryCommando": { + "ModValue": 2.0, + "requirements": { + "class": "commando", + "rarity": [ + "sr" + ] + } + }, + "RequiresLegendaryConstructor": { + "ModValue": 2.0, + "requirements": { + "class": "constructor", + "rarity": [ + "sr" + ] + } + }, + "RequiresLegendaryOutlander": { + "ModValue": 2.0, + "requirements": { + "class": "outlander", + "rarity": [ + "sr" + ] + } + } + }, + "heroLevels": { + "old": { + "uc": { + "t01": { + "1": 5, + "2": 6, + "3": 7, + "4": 8, + "5": 9, + "6": 10, + "7": 11, + "8": 13, + "9": 14, + "10": 15 + }, + "t02": { + "10": 21, + "11": 22, + "12": 23, + "13": 24, + "14": 25, + "15": 26, + "16": 28, + "17": 29, + "18": 30, + "19": 31, + "20": 32 + }, + "t03": { + "20": 38, + "21": 39, + "22": 40, + "23": 41, + "24": 43, + "25": 44, + "26": 45, + "27": 46, + "28": 47, + "29": 48, + "30": 49 + } + }, + "r": { + "t01": { + "1": 10, + "2": 11, + "3": 12, + "4": 14, + "5": 15, + "6": 16, + "7": 17, + "8": 19, + "9": 20, + "10": 21 + }, + "t02": { + "10": 28, + "11": 29, + "12": 31, + "13": 32, + "14": 33, + "15": 34, + "16": 36, + "17": 37, + "18": 38, + "19": 39, + "20": 41 + }, + "t03": { + "20": 48, + "21": 49, + "22": 50, + "23": 51, + "24": 53, + "25": 54, + "26": 55, + "27": 56, + "28": 58, + "29": 59, + "30": 60 + }, + "t04": { + "30": 67, + "31": 68, + "32": 70, + "33": 71, + "34": 72, + "35": 73, + "36": 75, + "37": 76, + "38": 77, + "39": 78, + "40": 80 + } + }, + "vr": { + "t01": { + "1": 15, + "2": 16, + "3": 18, + "4": 19, + "5": 20, + "6": 22, + "7": 23, + "8": 25, + "9": 26, + "10": 27 + }, + "t02": { + "10": 35, + "11": 37, + "12": 38, + "13": 39, + "14": 41, + "15": 42, + "16": 44, + "17": 45, + "18": 46, + "19": 48, + "20": 49 + }, + "t03": { + "20": 57, + "21": 58, + "22": 60, + "23": 61, + "24": 63, + "25": 64, + "26": 65, + "27": 67, + "28": 68, + "29": 69, + "30": 71 + }, + "t04": { + "30": 79, + "31": 80, + "32": 82, + "33": 83, + "34": 84, + "35": 86, + "36": 87, + "37": 88, + "38": 90, + "39": 91, + "40": 93 + }, + "t05": { + "40": 101, + "41": 102, + "42": 103, + "43": 105, + "44": 106, + "45": 107, + "46": 109, + "47": 110, + "48": 112, + "49": 113, + "50": 114 + } + }, + "sr": { + "t01": { + "1": 20, + "2": 22, + "3": 23, + "4": 25, + "5": 26, + "6": 28, + "7": 29, + "8": 31, + "9": 32, + "10": 34 + }, + "t02": { + "10": 43, + "11": 44, + "12": 46, + "13": 47, + "14": 49, + "15": 50, + "16": 52, + "17": 53, + "18": 55, + "19": 56, + "20": 58 + }, + "t03": { + "20": 67, + "21": 68, + "22": 70, + "23": 71, + "24": 73, + "25": 74, + "26": 76, + "27": 77, + "28": 79, + "29": 80, + "30": 82 + }, + "t04": { + "30": 91, + "31": 92, + "32": 94, + "33": 95, + "34": 97, + "35": 98, + "36": 100, + "37": 101, + "38": 103, + "39": 104, + "40": 106 + }, + "t05": { + "40": 115, + "41": 116, + "42": 118, + "43": 119, + "44": 121, + "45": 122, + "46": 124, + "47": 125, + "48": 127, + "49": 128, + "50": 130 + } + } + }, + "new": { + "uc": { + "t01": { + "1": 4, + "2": 5, + "3": 6, + "4": 8, + "5": 9, + "6": 10, + "7": 11, + "8": 13, + "9": 14, + "10": 15 + }, + "t02": { + "10": 22, + "11": 23, + "12": 24, + "13": 26, + "14": 27, + "15": 28, + "16": 30, + "17": 31, + "18": 32, + "19": 34, + "20": 35 + }, + "t03": { + "20": 43, + "21": 45, + "22": 46, + "23": 47, + "24": 49, + "25": 50, + "26": 51, + "27": 53, + "28": 54, + "29": 55, + "30": 57 + } + }, + "r": { + "t01": { + "1": 7, + "2": 8, + "3": 9, + "4": 11, + "5": 12, + "6": 13, + "7": 15, + "8": 16, + "9": 17, + "10": 19 + }, + "t02": { + "10": 26, + "11": 27, + "12": 29, + "13": 30, + "14": 32, + "15": 33, + "16": 35, + "17": 36, + "18": 38, + "19": 39, + "20": 41 + }, + "t03": { + "20": 49, + "21": 51, + "22": 52, + "23": 54, + "24": 55, + "25": 56, + "26": 58, + "27": 59, + "28": 61, + "29": 62, + "30": 64 + }, + "t04": { + "30": 74, + "31": 75, + "32": 77, + "33": 78, + "34": 80, + "35": 81, + "36": 83, + "37": 84, + "38": 86, + "39": 87, + "40": 89 + } + }, + "vr": { + "t01": { + "1": 9, + "2": 11, + "3": 12, + "4": 14, + "5": 15, + "6": 17, + "7": 18, + "8": 20, + "9": 21, + "10": 22 + }, + "t02": { + "10": 30, + "11": 32, + "12": 34, + "13": 35, + "14": 37, + "15": 39, + "16": 40, + "17": 42, + "18": 43, + "19": 45, + "20": 46 + }, + "t03": { + "20": 55, + "21": 56, + "22": 58, + "23": 60, + "24": 61, + "25": 63, + "26": 65, + "27": 66, + "28": 68, + "29": 69, + "30": 71 + }, + "t04": { + "30": 81, + "31": 83, + "32": 84, + "33": 86, + "34": 87, + "35": 89, + "36": 91, + "37": 92, + "38": 94, + "39": 96, + "40": 97 + }, + "t05": { + "40": 108, + "41": 110, + "42": 111, + "43": 112, + "44": 114, + "45": 115, + "46": 116, + "47": 118, + "48": 119, + "49": 120, + "50": 122, + "52": 124, + "54": 127, + "56": 130, + "58": 132, + "60": 135 + } + }, + "sr": { + "t01": { + "1": 12, + "2": 14, + "3": 15, + "4": 17, + "5": 18, + "6": 20, + "7": 21, + "8": 23, + "9": 24, + "10": 26 + }, + "t02": { + "10": 35, + "11": 36, + "12": 38, + "13": 40, + "14": 42, + "15": 43, + "16": 45, + "17": 46, + "18": 48, + "19": 49, + "20": 51 + }, + "t03": { + "20": 61, + "21": 62, + "22": 64, + "23": 66, + "24": 68, + "25": 69, + "26": 71, + "27": 73, + "28": 74, + "29": 76, + "30": 77 + }, + "t04": { + "30": 88, + "31": 90, + "32": 92, + "33": 94, + "34": 95, + "35": 97, + "36": 99, + "37": 101, + "38": 102, + "39": 104, + "40": 106 + }, + "t05": { + "40": 116, + "41": 117, + "42": 118, + "43": 120, + "44": 121, + "45": 123, + "46": 124, + "47": 126, + "48": 127, + "49": 129, + "50": 130, + "52": 133, + "54": 136, + "56": 139, + "58": 142, + "60": 144 + } + } + } + } +} diff --git a/structure/mcp.js b/structure/mcp.js index 6b2f416..bdabae9 100644 --- a/structure/mcp.js +++ b/structure/mcp.js @@ -4543,6 +4543,659 @@ express.post("/fortnite/api/game/v2/profile/*/client/PurchaseOrUpgradeHomebaseNo res.end(); }); +// Refresh expeditions STW +express.post("/fortnite/api/game/v2/profile/*/client/RefreshExpeditions", async (req, res) => { + const profile = require(`./../profiles/${req.query.profileId || "campaign"}.json`); + var expeditionData = require("./../responses/Campaign/expeditionData.json"); + + // do not change any of these or you will end up breaking it + var ApplyProfileChanges = []; + var BaseRevision = profile.rvn || 0; + var QueryRevision = req.query.rvn || -1; + var StatChanged = false; + + var ExpeditionSlots = []; + var date = new Date().toISOString(); + + // Check which quests that grant expedition slots are completed and add these slots to the list of available ones. + for (var key in profile.items) { + var templateId = profile.items[key].templateId.toLowerCase(); + if (expeditionData.questsUnlockingSlots.includes(templateId)) { + if (profile.items[key].attributes.quest_state == "Claimed") { + ExpeditionSlots = ExpeditionSlots.concat(expeditionData.slotsFromQuests[templateId]); + } + } + } + + // Remove the expired expeditions. + for (var key in profile.items) { + if (profile.items[key].templateId.toLowerCase().startsWith("expedition:")) { + var expiration_end_time = new Date(profile.items[key].attributes.expedition_expiration_end_time).toISOString(); + if (date > expiration_end_time && !profile.items[key].attributes.hasOwnProperty("expedition_start_time")) { + delete profile.items[key]; + + ApplyProfileChanges.push({ + "changeType": "itemRemoved", + "itemId": key + }) + + StatChanged = true; + } else { // If the expedition is still active, remove its slot from ExpeditionSlots list so the server doesn't make a new one for it. + var index = ExpeditionSlots.indexOf(profile.items[key].attributes.expedition_slot_id); + if (index !== -1) { + ExpeditionSlots.splice(index, 1) + } + } + } + } + + // Make new expeditions + for (var i = 0; i < ExpeditionSlots.length; i++) { + var slot = ExpeditionSlots[i]; + + // 5% (could be different) chance of making a rare expedition + var ExpeditionsToChoose = expeditionData.slots[slot]; + if (ExpeditionsToChoose.hasOwnProperty("rare") && Math.random() < 0.05) { + ExpeditionsToChoose = ExpeditionsToChoose.rare; + } else { + ExpeditionsToChoose = ExpeditionsToChoose.normal; + } + + var randomNumber = Math.floor(Math.random() * ExpeditionsToChoose.length); + var ID = functions.MakeID(); + var templateId = ExpeditionsToChoose[randomNumber]; + + var endDate = new Date(date); + endDate.setMinutes(endDate.getMinutes() + expeditionData.attributes[templateId].expiration_duration_minutes); + endDate = endDate.toISOString(); + + var Item = { + "templateId": templateId, + "attributes": { + "expedition_expiration_end_time": endDate, + "expedition_criteria": [], + "level": 1, + "expedition_max_target_power": expeditionData.attributes[templateId].expedition_max_target_power, + "expedition_min_target_power": expeditionData.attributes[templateId].expedition_min_target_power, + "expedition_slot_id": slot, + "expedition_expiration_start_time": date + }, + "quantity": 1 + } + + for (var x = 0; x < 3; x++) { + if (Math.random() < 0.2) { // 20% (could be different) chance of the expedition having a bonus criteria up to 3 + randomNumber = Math.floor(Math.random() * expeditionData.criteria.length); + Item.attributes.expedition_criteria.push(expeditionData.criteria[randomNumber]) + } + } + + profile.items[ID] = Item; + + ApplyProfileChanges.push({ + "changeType": "itemAdded", + "itemId": ID, + "item": Item + }) + StatChanged = true; + } + + if (StatChanged == true) { + profile.rvn += 1; + profile.commandRevision += 1; + + fs.writeFileSync(`./profiles/${req.query.profileId || "campaign"}.json`, JSON.stringify(profile, null, 2)); + } + + // this doesn't work properly on version v12.20 and above but whatever + if (QueryRevision != BaseRevision) { + ApplyProfileChanges = [{ + "changeType": "fullProfileUpdate", + "profile": profile + }]; + } + + res.json({ + "profileRevision": profile.rvn || 0, + "profileId": req.query.profileId || "campaign", + "profileChangesBaseRevision": BaseRevision, + "profileChanges": ApplyProfileChanges, + "profileCommandRevision": profile.commandRevision || 0, + "serverTime": new Date().toISOString(), + "responseVersion": 1 + }) + res.end(); +}); + +// Start an expedition STW +express.post("/fortnite/api/game/v2/profile/*/client/StartExpedition", async (req, res) => { + const profile = require(`./../profiles/${req.query.profileId || "campaign"}.json`); + const memory = functions.GetVersionInfo(req); + var expeditionData = require("./../responses/Campaign/expeditionData.json"); + + // do not change any of these or you will end up breaking it + var ApplyProfileChanges = []; + var BaseRevision = profile.rvn || 0; + var QueryRevision = req.query.rvn || -1; + var StatChanged = false; + + var date = new Date().toISOString(); + + if (req.body.expeditionId && req.body.squadId && req.body.itemIds && req.body.slotIndices) { + var ExpeditionLevel = profile.items[req.body.expeditionId].attributes.expedition_max_target_power; + var HeroLevels = expeditionData.heroLevels; + if (memory.build < 13.20) { // The levels got changed a bit in v13.20+ + HeroLevels = HeroLevels.old; + } else { + HeroLevels = HeroLevels.new; + } + + // Make a list with expedition heroes sorted by their power level + var SortedHeroes = [] + for (var i = 0; i < req.body.itemIds.length; i++) { + var hero = req.body.itemIds[i]; + for (var item in profile.items) { + if (hero == item) { + var splitTemplateId = profile.items[item].templateId.split("_") + var rarity = splitTemplateId.slice(-2, -1)[0].toLowerCase(); + var tier = splitTemplateId.slice(-1)[0].toLowerCase(); + var level = profile.items[item].attributes.level; + var Hero = { + "itemGuid": hero, + "templateId": profile.items[item].templateId, + "class": splitTemplateId[1].toLowerCase(), + "rarity": rarity, + "tier": tier, + "level": level, + "powerLevel": HeroLevels[rarity][tier][level], + "bBoostedByCriteria": false + } + SortedHeroes.push(Hero) + } + } + } + SortedHeroes.sort((a, b) => b.powerLevel - a.powerLevel); + + // Check if any of the heroes meet any of the available criterias. If so, then boost their power level. + if (profile.items[req.body.expeditionId].attributes.hasOwnProperty("expedition_criteria")) { + var criteria = profile.items[req.body.expeditionId].attributes.expedition_criteria; + for (var i = 0; i < criteria.length; i++) { + criterion = criteria[i]; + + for (var x = 0; x < SortedHeroes.length; x++) { + var bIsMatchingHero = true; + var requirements = expeditionData.criteriaRequirements[criterion].requirements; + if (requirements.class != SortedHeroes[x].class) { + bIsMatchingHero = false; + } + if (requirements.hasOwnProperty("rarity")) { + if (!requirements.rarity.includes(SortedHeroes[x].rarity)) { + bIsMatchingHero = false; + } + } + + if (bIsMatchingHero == true && SortedHeroes[x].bBoostedByCriteria == false) { + SortedHeroes[x].powerLevel = SortedHeroes[x].powerLevel * expeditionData.criteriaRequirements[criterion].ModValue; + SortedHeroes[x].bBoostedByCriteria = true; + break; + } + } + } + } + + // Calculate the expedition success chance + var TotalPowerLevel = 0; + for (var i = 0; i < SortedHeroes.length; i++) { + TotalPowerLevel += SortedHeroes[i].powerLevel; + } + var ExpeditionSuccessChance = TotalPowerLevel / ExpeditionLevel; + if (ExpeditionSuccessChance > 1) { + ExpeditionSuccessChance = 1; + } + + // Assign Squad ids and slots to selected heroes + for (var i = 0; i < req.body.itemIds.length; i++) { + var hero = req.body.itemIds[i]; + profile.items[hero].attributes.squad_id = req.body.squadId.toLowerCase(); + profile.items[hero].attributes.squad_slot_idx = req.body.slotIndices[i]; + + ApplyProfileChanges.push({ + "changeType": "itemAttrChanged", + "itemId": hero, + "attributeName": "squad_id", + "attributeValue": profile.items[hero].attributes.squad_id + }) + ApplyProfileChanges.push({ + "changeType": "itemAttrChanged", + "itemId": hero, + "attributeName": "squad_slot_idx", + "attributeValue": profile.items[hero].attributes.squad_slot_idx + }) + } + + // Calculate the expedition end date + var endDate = new Date(date); + endDate.setMinutes(endDate.getMinutes() + expeditionData.attributes[profile.items[req.body.expeditionId].templateId].expedition_duration_minutes); + endDate = endDate.toISOString(); + + profile.items[req.body.expeditionId].attributes.expedition_squad_id = req.body.squadId.toLowerCase(); + profile.items[req.body.expeditionId].attributes.expedition_success_chance = ExpeditionSuccessChance; + profile.items[req.body.expeditionId].attributes.expedition_start_time = date; + profile.items[req.body.expeditionId].attributes.expedition_end_time = endDate; + + ApplyProfileChanges.push({ + "changeType": "itemAttrChanged", + "itemId": req.body.expeditionId, + "attributeName": "expedition_squad_id", + "attributeValue": profile.items[req.body.expeditionId].attributes.expedition_squad_id + }) + ApplyProfileChanges.push({ + "changeType": "itemAttrChanged", + "itemId": req.body.expeditionId, + "attributeName": "expedition_success_chance", + "attributeValue": profile.items[req.body.expeditionId].attributes.expedition_success_chance + }) + ApplyProfileChanges.push({ + "changeType": "itemAttrChanged", + "itemId": req.body.expeditionId, + "attributeName": "expedition_start_time", + "attributeValue": profile.items[req.body.expeditionId].attributes.expedition_start_time + }) + ApplyProfileChanges.push({ + "changeType": "itemAttrChanged", + "itemId": req.body.expeditionId, + "attributeName": "expedition_end_time", + "attributeValue": profile.items[req.body.expeditionId].attributes.expedition_end_time + }) + + StatChanged = true; + } + + if (StatChanged == true) { + profile.rvn += 1; + profile.commandRevision += 1; + + fs.writeFileSync(`./profiles/${req.query.profileId || "campaign"}.json`, JSON.stringify(profile, null, 2)); + } + + // this doesn't work properly on version v12.20 and above but whatever + if (QueryRevision != BaseRevision) { + ApplyProfileChanges = [{ + "changeType": "fullProfileUpdate", + "profile": profile + }]; + } + + res.json({ + "profileRevision": profile.rvn || 0, + "profileId": req.query.profileId || "campaign", + "profileChangesBaseRevision": BaseRevision, + "profileChanges": ApplyProfileChanges, + "profileCommandRevision": profile.commandRevision || 0, + "serverTime": new Date().toISOString(), + "responseVersion": 1 + }) + res.end(); +}); + +// Abandon an expedition STW +express.post("/fortnite/api/game/v2/profile/*/client/AbandonExpedition", async (req, res) => { + const profile = require(`./../profiles/${req.query.profileId || "campaign"}.json`); + var expeditionData = require("./../responses/Campaign/expeditionData.json"); + + // do not change any of these or you will end up breaking it + var ApplyProfileChanges = []; + var BaseRevision = profile.rvn || 0; + var QueryRevision = req.query.rvn || -1; + var StatChanged = false; + + var date = new Date().toISOString(); + + if (req.body.expeditionId) { + var squad_id = profile.items[req.body.expeditionId].attributes.expedition_squad_id; + for (var item2 in profile.items) { // Remove the squad ids and slots from heroes + if (profile.items[item2].attributes.hasOwnProperty("squad_id")) { + if (profile.items[item2].attributes.squad_id == squad_id) { + profile.items[item2].attributes.squad_id = ""; + profile.items[item2].attributes.squad_slot_idx = -1; + ApplyProfileChanges.push({ + "changeType": "itemAttrChanged", + "itemId": item2, + "attributeName": "squad_id", + "attributeValue": profile.items[item2].attributes.squad_id + }) + ApplyProfileChanges.push({ + "changeType": "itemAttrChanged", + "itemId": item2, + "attributeName": "squad_slot_idx", + "attributeValue": profile.items[item2].attributes.squad_slot_idx + }) + } + } + } + + // Set the expedition back as availale + delete profile.items[req.body.expeditionId].attributes.expedition_squad_id + delete profile.items[req.body.expeditionId].attributes.expedition_start_time + delete profile.items[req.body.expeditionId].attributes.expedition_end_time + ApplyProfileChanges.push({ + "changeType": "itemAttrChanged", + "itemId": req.body.expeditionId, + "attributeName": "expedition_squad_id", + "attributeValue": "" + }) + ApplyProfileChanges.push({ + "changeType": "itemAttrChanged", + "itemId": req.body.expeditionId, + "attributeName": "expedition_start_time", + "attributeValue": null + }) + ApplyProfileChanges.push({ + "changeType": "itemAttrChanged", + "itemId": req.body.expeditionId, + "attributeName": "expedition_end_time", + "attributeValue": null + }) + + var expiration_end_time = new Date(profile.items[req.body.expeditionId].attributes.expedition_expiration_end_time).toISOString(); + if (date > expiration_end_time) { + // Remove the abandoned expedition and make a new one to replace it + var slot = profile.items[req.body.expeditionId].attributes.expedition_slot_id; + delete profile.items[req.body.expeditionId] + ApplyProfileChanges.push({ + "changeType": "itemRemoved", + "itemId": req.body.expeditionId + }) + + // 5% (could be different) chance of making a rare expedition + var ExpeditionsToChoose = expeditionData.slots[slot]; + if (ExpeditionsToChoose.hasOwnProperty("rare") && Math.random() < 0.05) { + ExpeditionsToChoose = ExpeditionsToChoose.rare; + } else { + ExpeditionsToChoose = ExpeditionsToChoose.normal; + } + + var randomNumber = Math.floor(Math.random() * ExpeditionsToChoose.length); + var ID = functions.MakeID(); + var templateId = ExpeditionsToChoose[randomNumber]; + + var endDate = new Date(date); + endDate.setMinutes(endDate.getMinutes() + expeditionData.attributes[templateId].expiration_duration_minutes); + endDate = endDate.toISOString(); + + var Item = { + "templateId": templateId, + "attributes": { + "expedition_expiration_end_time": endDate, + "expedition_criteria": [], + "level": 1, + "expedition_max_target_power": expeditionData.attributes[templateId].expedition_max_target_power, + "expedition_min_target_power": expeditionData.attributes[templateId].expedition_min_target_power, + "expedition_slot_id": slot, + "expedition_expiration_start_time": date + }, + "quantity": 1 + } + + for (var x = 0; x < 3; x++) { + if (Math.random() < 0.2) { // 20% (could be different) chance of the expedition having a bonus criteria up to 3 + randomNumber = Math.floor(Math.random() * expeditionData.criteria.length); + Item.attributes.expedition_criteria.push(expeditionData.criteria[randomNumber]) + } + } + + profile.items[ID] = Item; + + ApplyProfileChanges.push({ + "changeType": "itemAdded", + "itemId": ID, + "item": Item + }) + } + + StatChanged = true; + } + + if (StatChanged == true) { + profile.rvn += 1; + profile.commandRevision += 1; + + fs.writeFileSync(`./profiles/${req.query.profileId || "campaign"}.json`, JSON.stringify(profile, null, 2)); + } + + // this doesn't work properly on version v12.20 and above but whatever + if (QueryRevision != BaseRevision) { + ApplyProfileChanges = [{ + "changeType": "fullProfileUpdate", + "profile": profile + }]; + } + + res.json({ + "profileRevision": profile.rvn || 0, + "profileId": req.query.profileId || "campaign", + "profileChangesBaseRevision": BaseRevision, + "profileChanges": ApplyProfileChanges, + "profileCommandRevision": profile.commandRevision || 0, + "serverTime": new Date().toISOString(), + "responseVersion": 1 + }) + res.end(); +}); + +// Collect a finished expedition STW +express.post("/fortnite/api/game/v2/profile/*/client/CollectExpedition", async (req, res) => { + const profile = require(`./../profiles/${req.query.profileId || "campaign"}.json`); + var expeditionData = require("./../responses/Campaign/expeditionData.json"); + + // do not change any of these or you will end up breaking it + var ApplyProfileChanges = []; + var MultiUpdate = []; + var Notifications = []; + var OtherProfiles = []; + var BaseRevision = profile.rvn || 0; + var QueryRevision = req.query.rvn || -1; + var StatChanged = false; + + var date = new Date().toISOString(); + + if (req.body.expeditionId) { + Notifications.push({ + "type": "expeditionResult", + "primary": true, + "client_request_id": "", + "bExpeditionSucceeded" : false + }) + + // Determine if the expedition was successful + if (Math.random() < profile.items[req.body.expeditionId].attributes.expedition_success_chance) { + Notifications[0].bExpeditionSucceeded = true; + Notifications[0].expeditionRewards = []; + + // If so, then grant the rewards + for (var i = 0; i < expeditionData.rewards.length; i++) { + var randomNumber = Math.floor(Math.random() * expeditionData.rewards[i].length); + var ID = functions.MakeID(); + var templateId = expeditionData.rewards[i][randomNumber].templateId; + var itemProfile = expeditionData.rewards[i][randomNumber].itemProfile; + + var minQ = expeditionData.rewards[i][randomNumber].minQuantity; + var maxQ = expeditionData.rewards[i][randomNumber].maxQuantity; + var quantity = Math.floor(Math.random() * (maxQ - minQ + 1)) + minQ; + + var Item = { + "templateId": templateId, + "attributes": { + "loadedAmmo": 0, + "inventory_overflow_date": false, + "level": 0, + "alterationDefinitions": [], + "durability": 1, + "itemSource": "" + }, + "quantity": quantity + } + + Notifications[0].expeditionRewards.push({ + "itemType": templateId, + "itemGuid": ID, + "itemProfile": itemProfile, + "quantity": quantity + }) + + if (itemProfile == req.query.profileId) { + profile.items[ID] = Item; + ApplyProfileChanges.push({ + "changeType": "itemAdded", + "itemId": ID, + "item": Item + }) + } else { + var k = -1; // index of item profile in MultiUpdate + for (var x = 0; x < MultiUpdate.length; x++) { + if (MultiUpdate[x].profileId == itemProfile) { + k = x; + } + } + if (k == -1) { + OtherProfiles.push(require(`./../profiles/${itemProfile}.json`)) + k = MultiUpdate.length; + MultiUpdate.push({ + "profileRevision": OtherProfiles[k].rvn || 0, + "profileId": OtherProfiles[k].profileId, + "profileChangesBaseRevision": OtherProfiles[k].rvn || 0, + "profileChanges": [], + "profileCommandRevision": OtherProfiles[k].commandRevision || 0, + }) + } + + OtherProfiles[k].items[ID] = Item; + MultiUpdate[k].profileChanges.push({ + "changeType": "itemAdded", + "itemId": ID, + "item": Item + }) + } + } + } + + var squad_id = profile.items[req.body.expeditionId].attributes.expedition_squad_id; + for (var item2 in profile.items) { // Remove the squad ids and slots from heroes + if (profile.items[item2].attributes.hasOwnProperty("squad_id")) { + if (profile.items[item2].attributes.squad_id == squad_id) { + profile.items[item2].attributes.squad_id = ""; + profile.items[item2].attributes.squad_slot_idx = -1; + ApplyProfileChanges.push({ + "changeType": "itemAttrChanged", + "itemId": item2, + "attributeName": "squad_id", + "attributeValue": profile.items[item2].attributes.squad_id + }) + ApplyProfileChanges.push({ + "changeType": "itemAttrChanged", + "itemId": item2, + "attributeName": "squad_slot_idx", + "attributeValue": profile.items[item2].attributes.squad_slot_idx + }) + } + } + } + + // Make a new expedition to replace the finished one + var slot = profile.items[req.body.expeditionId].attributes.expedition_slot_id; + delete profile.items[req.body.expeditionId] + ApplyProfileChanges.push({ + "changeType": "itemRemoved", + "itemId": req.body.expeditionId + }) + + // 5% (could be different) chance of making a rare expedition + var ExpeditionsToChoose = expeditionData.slots[slot]; + if (ExpeditionsToChoose.hasOwnProperty("rare") && Math.random() < 0.05) { + ExpeditionsToChoose = ExpeditionsToChoose.rare; + } else { + ExpeditionsToChoose = ExpeditionsToChoose.normal; + } + + var randomNumber = Math.floor(Math.random() * ExpeditionsToChoose.length); + var ID = functions.MakeID(); + var templateId = ExpeditionsToChoose[randomNumber]; + + var endDate = new Date(date); + endDate.setMinutes(endDate.getMinutes() + expeditionData.attributes[templateId].expiration_duration_minutes); + endDate = endDate.toISOString(); + + var Item = { + "templateId": templateId, + "attributes": { + "expedition_expiration_end_time": endDate, + "expedition_criteria": [], + "level": 1, + "expedition_max_target_power": expeditionData.attributes[templateId].expedition_max_target_power, + "expedition_min_target_power": expeditionData.attributes[templateId].expedition_min_target_power, + "expedition_slot_id": slot, + "expedition_expiration_start_time": date + }, + "quantity": 1 + } + + for (var x = 0; x < 3; x++) { + if (Math.random() < 0.2) { // 20% (could be different) chance of the expedition having a bonus criteria up to 3 + randomNumber = Math.floor(Math.random() * expeditionData.criteria.length); + Item.attributes.expedition_criteria.push(expeditionData.criteria[randomNumber]) + } + } + + profile.items[ID] = Item; + + ApplyProfileChanges.push({ + "changeType": "itemAdded", + "itemId": ID, + "item": Item + }) + + StatChanged = true; + } + + if (StatChanged == true) { + profile.rvn += 1; + profile.commandRevision += 1; + + fs.writeFileSync(`./profiles/${req.query.profileId || "campaign"}.json`, JSON.stringify(profile, null, 2)); + + for (var i = 0; i < OtherProfiles.length; i++) { + OtherProfiles[i].rvn += 1; + OtherProfiles[i].commandRevision += 1; + + MultiUpdate[i].profileRevision += 1; + MultiUpdate[i].profileCommandRevision += 1; + + fs.writeFileSync(`./profiles/${OtherProfiles[i].profileId || "campaign"}.json`, JSON.stringify(OtherProfiles[i], null, 2)); + } + } + + // this doesn't work properly on version v12.20 and above but whatever + if (QueryRevision != BaseRevision) { + ApplyProfileChanges = [{ + "changeType": "fullProfileUpdate", + "profile": profile + }]; + } + + res.json({ + "profileRevision": profile.rvn || 0, + "profileId": req.query.profileId || "campaign", + "profileChangesBaseRevision": BaseRevision, + "profileChanges": ApplyProfileChanges, + "notifications": Notifications, + "profileCommandRevision": profile.commandRevision || 0, + "serverTime": new Date().toISOString(), + "multiUpdate": MultiUpdate, + "responseVersion": 1 + }) + res.end(); +}); + // Set active hero loadout STW express.post("/fortnite/api/game/v2/profile/*/client/SetActiveHeroLoadout", async (req, res) => { const profile = require(`./../profiles/${req.query.profileId || "campaign"}.json`);