From 73fb1b80740f1e2a4691949ec5c6040d753d8b6c Mon Sep 17 00:00:00 2001 From: Fabian Dill Date: Fri, 15 Jul 2022 17:41:53 +0200 Subject: [PATCH] Subnautica: updates (#759) * Subnautica: add more goals * Subnautica: fix wrongly positioned Databox * Subnautica: allow techs to remain vanilla * Subnautica: make zipimport compatible * Subnautica: force two Seaglide fragments into local sphere 1 --- Main.py | 3 +- worlds/subnautica/Items.py | 360 ++++++++++++++++++- worlds/subnautica/Locations.py | 576 ++++++++++++++++++++++++++++++- worlds/subnautica/Options.py | 29 +- worlds/subnautica/Regions.py | 8 - worlds/subnautica/Rules.py | 71 ++-- worlds/subnautica/__init__.py | 123 ++++--- worlds/subnautica/items.json | 83 ----- worlds/subnautica/locations.json | 521 ---------------------------- 9 files changed, 1059 insertions(+), 715 deletions(-) delete mode 100644 worlds/subnautica/Regions.py delete mode 100644 worlds/subnautica/items.json delete mode 100644 worlds/subnautica/locations.json diff --git a/Main.py b/Main.py index 6daa16d9..3912e65c 100644 --- a/Main.py +++ b/Main.py @@ -363,7 +363,8 @@ def main(args, seed=None, baked_server_options: Optional[Dict[str, object]] = No for location in world.get_filled_locations(): if type(location.address) == int: assert location.item.code is not None, "item code None should be event, " \ - "location.address should then also be None" + "location.address should then also be None. Location: " \ + f" {location}" locations_data[location.player][location.address] = \ location.item.code, location.item.player, location.item.flags if location.name in world.start_location_hints[location.player]: diff --git a/worlds/subnautica/Items.py b/worlds/subnautica/Items.py index b9377b7a..b55efe24 100644 --- a/worlds/subnautica/Items.py +++ b/worlds/subnautica/Items.py @@ -1,23 +1,353 @@ -import json -import os +from BaseClasses import ItemClassification +from typing import TypedDict, Dict, Set -with open(os.path.join(os.path.dirname(__file__), 'items.json'), 'r') as file: - item_table = json.loads(file.read()) -lookup_id_to_name = {} -lookup_name_to_item = {} -advancement_item_names = set() -non_advancement_item_names = set() +class ItemDict(TypedDict): + classification: ItemClassification + count: int + name: str + tech_type: str -for item in item_table: - item_name = item["name"] - lookup_id_to_name[item["id"]] = item_name - lookup_name_to_item[item_name] = item - if item["progression"]: + +item_table: Dict[int, ItemDict] = { + 35000: {'classification': ItemClassification.useful, + 'count': 1, + 'name': 'Compass', + 'tech_type': 'Compass'}, + 35001: {'classification': ItemClassification.progression, + 'count': 1, + 'name': 'Lightweight High Capacity Tank', + 'tech_type': 'PlasteelTank'}, + 35002: {'classification': ItemClassification.progression, + 'count': 1, + 'name': 'Vehicle Upgrade Console', + 'tech_type': 'BaseUpgradeConsole'}, + 35003: {'classification': ItemClassification.progression, + 'count': 1, + 'name': 'Ultra Glide Fins', + 'tech_type': 'UltraGlideFins'}, + 35004: {'classification': ItemClassification.useful, + 'count': 1, + 'name': 'Cyclops Sonar Upgrade', + 'tech_type': 'CyclopsSonarModule'}, + 35005: {'classification': ItemClassification.useful, + 'count': 1, + 'name': 'Reinforced Dive Suit', + 'tech_type': 'ReinforcedDiveSuit'}, + 35006: {'classification': ItemClassification.useful, + 'count': 1, + 'name': 'Cyclops Thermal Reactor Module', + 'tech_type': 'CyclopsThermalReactorModule'}, + 35007: {'classification': ItemClassification.filler, + 'count': 1, + 'name': 'Stillsuit', + 'tech_type': 'Stillsuit'}, + 35008: {'classification': ItemClassification.filler, + 'count': 2, + 'name': 'Alien Containment Fragment', + 'tech_type': 'BaseWaterParkFragment'}, + 35009: {'classification': ItemClassification.useful, + 'count': 1, + 'name': 'Creature Decoy', + 'tech_type': 'CyclopsDecoy'}, + 35010: {'classification': ItemClassification.useful, + 'count': 1, + 'name': 'Cyclops Fire Suppression System', + 'tech_type': 'CyclopsFireSuppressionModule'}, + 35011: {'classification': ItemClassification.useful, + 'count': 1, + 'name': 'Swim Charge Fins', + 'tech_type': 'SwimChargeFins'}, + 35012: {'classification': ItemClassification.useful, + 'count': 1, + 'name': 'Repulsion Cannon', + 'tech_type': 'RepulsionCannon'}, + 35013: {'classification': ItemClassification.useful, + 'count': 1, + 'name': 'Cyclops Decoy Tube Upgrade', + 'tech_type': 'CyclopsDecoyModule'}, + 35014: {'classification': ItemClassification.progression, + 'count': 1, + 'name': 'Cyclops Shield Generator', + 'tech_type': 'CyclopsShieldModule'}, + 35015: {'classification': ItemClassification.progression, + 'count': 1, + 'name': 'Cyclops Depth Module MK1', + 'tech_type': 'CyclopsHullModule1'}, + 35016: {'classification': ItemClassification.useful, + 'count': 1, + 'name': 'Cyclops Docking Bay Repair Module', + 'tech_type': 'CyclopsSeamothRepairModule'}, + 35017: {'classification': ItemClassification.useful, + 'count': 2, + 'name': 'Battery Charger fragment', + 'tech_type': 'BatteryChargerFragment'}, + 35018: {'classification': ItemClassification.filler, + 'count': 2, + 'name': 'Beacon Fragment', + 'tech_type': 'BeaconFragment'}, + 35019: {'classification': ItemClassification.useful, + 'count': 2, + 'name': 'Bioreactor Fragment', + 'tech_type': 'BaseBioReactorFragment'}, + 35020: {'classification': ItemClassification.progression, + 'count': 3, + 'name': 'Cyclops Bridge Fragment', + 'tech_type': 'CyclopsBridgeFragment'}, + 35021: {'classification': ItemClassification.progression, + 'count': 3, + 'name': 'Cyclops Engine Fragment', + 'tech_type': 'CyclopsEngineFragment'}, + 35022: {'classification': ItemClassification.progression, + 'count': 3, + 'name': 'Cyclops Hull Fragment', + 'tech_type': 'CyclopsHullFragment'}, + 35023: {'classification': ItemClassification.filler, + 'count': 2, + 'name': 'Grav Trap Fragment', + 'tech_type': 'GravSphereFragment'}, + 35024: {'classification': ItemClassification.progression, + 'count': 3, + 'name': 'Laser Cutter Fragment', + 'tech_type': 'LaserCutterFragment'}, + 35025: {'classification': ItemClassification.filler, + 'count': 1, + 'name': 'Light Stick Fragment', + 'tech_type': 'TechlightFragment'}, + 35026: {'classification': ItemClassification.progression, + 'count': 3, + 'name': 'Mobile Vehicle Bay Fragment', + 'tech_type': 'ConstructorFragment'}, + 35027: {'classification': ItemClassification.progression, + 'count': 3, + 'name': 'Modification Station Fragment', + 'tech_type': 'WorkbenchFragment'}, + 35028: {'classification': ItemClassification.progression, + 'count': 2, + 'name': 'Moonpool Fragment', + 'tech_type': 'MoonpoolFragment'}, + 35029: {'classification': ItemClassification.useful, + 'count': 3, + 'name': 'Nuclear Reactor Fragment', + 'tech_type': 'BaseNuclearReactorFragment'}, + 35030: {'classification': ItemClassification.useful, + 'count': 2, + 'name': 'Power Cell Charger Fragment', + 'tech_type': 'PowerCellChargerFragment'}, + 35031: {'classification': ItemClassification.filler, + 'count': 1, + 'name': 'Power Transmitter Fragment', + 'tech_type': 'PowerTransmitterFragment'}, + 35032: {'classification': ItemClassification.progression, + 'count': 4, + 'name': 'Prawn Suit Fragment', + 'tech_type': 'ExosuitFragment'}, + 35033: {'classification': ItemClassification.useful, + 'count': 2, + 'name': 'Prawn Suit Drill Arm Fragment', + 'tech_type': 'ExosuitDrillArmFragment'}, + 35034: {'classification': ItemClassification.useful, + 'count': 2, + 'name': 'Prawn Suit Grappling Arm Fragment', + 'tech_type': 'ExosuitGrapplingArmFragment'}, + 35035: {'classification': ItemClassification.useful, + 'count': 2, + 'name': 'Prawn Suit Propulsion Cannon Fragment', + 'tech_type': 'ExosuitPropulsionArmFragment'}, + 35036: {'classification': ItemClassification.useful, + 'count': 2, + 'name': 'Prawn Suit Torpedo Arm Fragment', + 'tech_type': 'ExosuitTorpedoArmFragment'}, + 35037: {'classification': ItemClassification.useful, + 'count': 3, + 'name': 'Scanner Room Fragment', + 'tech_type': 'BaseMapRoomFragment'}, + 35038: {'classification': ItemClassification.progression, + 'count': 5, + 'name': 'Seamoth Fragment', + 'tech_type': 'SeamothFragment'}, + 35039: {'classification': ItemClassification.useful, + 'count': 2, + 'name': 'Stasis Rifle Fragment', + 'tech_type': 'StasisRifleFragment'}, + 35040: {'classification': ItemClassification.useful, + 'count': 2, + 'name': 'Thermal Plant Fragment', + 'tech_type': 'ThermalPlantFragment'}, + 35041: {'classification': ItemClassification.progression, + 'count': 2, + 'name': 'Seaglide Fragment', + 'tech_type': 'SeaglideFragment'}, + 35042: {'classification': ItemClassification.progression, + 'count': 1, + 'name': 'Radiation Suit', + 'tech_type': 'RadiationSuit'}, + 35043: {'classification': ItemClassification.progression, + 'count': 2, + 'name': 'Propulsion Cannon Fragment', + 'tech_type': 'PropulsionCannonFragment'}, + 35044: {'classification': ItemClassification.progression, + 'count': 1, + 'name': 'Neptune Launch Platform', + 'tech_type': 'RocketBase'}, + 35045: {'classification': ItemClassification.progression, + 'count': 1, + 'name': 'Ion Power Cell', + 'tech_type': 'PrecursorIonPowerCell'}, + 35046: {'classification': ItemClassification.filler, + 'count': 2, + 'name': 'Exterior Growbed Fragment', + 'tech_type': 'FarmingTrayFragment'}, + 35047: {'classification': ItemClassification.filler, + 'count': 1, + 'name': 'Picture Frame', + 'tech_type': 'PictureFrameFragment'}, + 35048: {'classification': ItemClassification.filler, + 'count': 2, + 'name': 'Bench Fragment', + 'tech_type': 'BenchFragment'}, + 35049: {'classification': ItemClassification.filler, + 'count': 1, + 'name': 'Basic Plant Pot', + 'tech_type': 'PlanterPotFragment'}, + 35050: {'classification': ItemClassification.filler, + 'count': 1, + 'name': 'Interior Growbed', + 'tech_type': 'PlanterBoxFragment'}, + 35051: {'classification': ItemClassification.filler, + 'count': 1, + 'name': 'Plant Shelf', + 'tech_type': 'PlanterShelfFragment'}, + 35052: {'classification': ItemClassification.filler, + 'count': 2, + 'name': 'Observatory Fragment', + 'tech_type': 'BaseObservatoryFragment'}, + 35053: {'classification': ItemClassification.filler, + 'count': 2, + 'name': 'Multipurpose Room Fragment', + 'tech_type': 'BaseRoomFragment'}, + 35054: {'classification': ItemClassification.useful, + 'count': 2, + 'name': 'Bulkhead Fragment', + 'tech_type': 'BaseBulkheadFragment'}, + 35055: {'classification': ItemClassification.filler, + 'count': 1, + 'name': 'Spotlight', + 'tech_type': 'Spotlight'}, + 35056: {'classification': ItemClassification.filler, + 'count': 2, + 'name': 'Desk', + 'tech_type': 'StarshipDesk'}, + 35057: {'classification': ItemClassification.filler, + 'count': 1, + 'name': 'Swivel Chair', + 'tech_type': 'StarshipChair'}, + 35058: {'classification': ItemClassification.filler, + 'count': 1, + 'name': 'Office Chair', + 'tech_type': 'StarshipChair2'}, + 35059: {'classification': ItemClassification.filler, + 'count': 1, + 'name': 'Command Chair', + 'tech_type': 'StarshipChair3'}, + 35060: {'classification': ItemClassification.filler, + 'count': 2, + 'name': 'Counter', + 'tech_type': 'LabCounter'}, + 35061: {'classification': ItemClassification.filler, + 'count': 1, + 'name': 'Single Bed', + 'tech_type': 'NarrowBed'}, + 35062: {'classification': ItemClassification.filler, + 'count': 1, + 'name': 'Basic Double Bed', + 'tech_type': 'Bed1'}, + 35063: {'classification': ItemClassification.filler, + 'count': 1, + 'name': 'Quilted Double Bed', + 'tech_type': 'Bed2'}, + 35064: {'classification': ItemClassification.filler, + 'count': 2, + 'name': 'Coffee Vending Machine', + 'tech_type': 'CoffeeVendingMachine'}, + 35065: {'classification': ItemClassification.filler, + 'count': 2, + 'name': 'Trash Can', + 'tech_type': 'Trashcans'}, + 35066: {'classification': ItemClassification.filler, + 'count': 1, + 'name': 'Floodlight', + 'tech_type': 'Techlight'}, + 35067: {'classification': ItemClassification.filler, + 'count': 1, + 'name': 'Bar Table', + 'tech_type': 'BarTable'}, + 35068: {'classification': ItemClassification.filler, + 'count': 1, + 'name': 'Vending Machine', + 'tech_type': 'VendingMachine'}, + 35069: {'classification': ItemClassification.filler, + 'count': 1, + 'name': 'Single Wall Shelf', + 'tech_type': 'SingleWallShelf'}, + 35070: {'classification': ItemClassification.filler, + 'count': 1, + 'name': 'Wall Shelves', + 'tech_type': 'WallShelves'}, + 35071: {'classification': ItemClassification.filler, + 'count': 1, + 'name': 'Round Plant Pot', + 'tech_type': 'PlanterPot2'}, + 35072: {'classification': ItemClassification.filler, + 'count': 1, + 'name': 'Chic Plant Pot', + 'tech_type': 'PlanterPot3'}, + 35073: {'classification': ItemClassification.filler, + 'count': 1, + 'name': 'Nuclear Waste Disposal', + 'tech_type': 'LabTrashcan'}, + 35074: {'classification': ItemClassification.filler, + 'count': 1, + 'name': 'Wall Planter', + 'tech_type': 'BasePlanter'}, + 35075: {'classification': ItemClassification.progression, + 'count': 1, + 'name': 'Ion Battery', + 'tech_type': 'PrecursorIonBattery'}, + 35076: {'classification': ItemClassification.progression, + 'count': 1, + 'name': 'Neptune Gantry', + 'tech_type': 'RocketBaseLadder'}, + 35077: {'classification': ItemClassification.progression, + 'count': 1, + 'name': 'Neptune Boosters', + 'tech_type': 'RocketStage1'}, + 35078: {'classification': ItemClassification.progression, + 'count': 1, + 'name': 'Neptune Fuel Reserve', + 'tech_type': 'RocketStage2'}, + 35079: {'classification': ItemClassification.progression, + 'count': 1, + 'name': 'Neptune Cockpit', + 'tech_type': 'RocketStage3'}, + 35080: {'classification': ItemClassification.filler, + 'count': 1, + 'name': 'Water Filtration Machine', + 'tech_type': 'BaseFiltrationMachine'}} + +advancement_item_names: Set[str] = set() +non_advancement_item_names: Set[str] = set() + +for item_id, item_data in item_table.items(): + item_name = item_data["name"] + if ItemClassification.progression in item_data["classification"]: advancement_item_names.add(item_name) else: non_advancement_item_names.add(item_name) -lookup_id_to_name[None] = "Victory" +if False: # turn to True to export for Subnautica mod + payload = {item_id: item_data["tech_type"] for item_id, item_data in item_table.items()} + import json -lookup_name_to_id = {name: id for id, name in lookup_id_to_name.items()} \ No newline at end of file + with open("items.json", "w") as f: + json.dump(payload, f) diff --git a/worlds/subnautica/Locations.py b/worlds/subnautica/Locations.py index 361a712b..c437fbc9 100644 --- a/worlds/subnautica/Locations.py +++ b/worlds/subnautica/Locations.py @@ -1,12 +1,570 @@ -import json -import os +from typing import Dict, TypedDict, List -with open(os.path.join(os.path.dirname(__file__), 'locations.json'), 'r') as file: - location_table = json.loads(file.read()) -lookup_id_to_name = {} -for item in location_table: - lookup_id_to_name[item["id"]] = item["name"] +class Vector(TypedDict): + x: float + y: float + z: float -lookup_id_to_name[None] = "Neptune Launch" -lookup_name_to_id = {name: id for id, name in lookup_id_to_name.items()} + +class LocationDict(TypedDict, total=False): + name: str + can_slip_through: bool + need_laser_cutter: bool + position: Vector + need_propulsion_cannon: bool + + +events: List[str] = ["Neptune Launch", "Disable Quarantine", "Full Infection", "Repair Aurora Drive"] + +location_table: Dict[int, LocationDict] = { + 33000: {'can_slip_through': False, + 'name': 'Blood Kelp Trench Wreck - Outside Databox', + 'need_laser_cutter': False, + 'position': {'x': -1234.3, 'y': -349.7, 'z': -396.0}}, + 33001: {'can_slip_through': False, + 'name': 'Blood Kelp Trench Wreck - Inside Databox', + 'need_laser_cutter': False, + 'position': {'x': -1208.0, 'y': -349.6, 'z': -383.0}}, + 33002: {'can_slip_through': False, + 'name': 'Blood Kelp Trench Wreck - PDA', + 'need_laser_cutter': False, + 'position': {'x': -1210.6, 'y': -340.7, 'z': -393.4}}, + 33003: {'can_slip_through': False, + 'name': 'Bulb Zone West Wreck - Outside Databox', + 'need_laser_cutter': False, + 'position': {'x': 903.8, 'y': -220.3, 'z': 590.9}}, + 33004: {'can_slip_through': False, + 'name': 'Bulb Zone West Wreck - Under Databox', + 'need_laser_cutter': False, + 'position': {'x': 910.9, 'y': -201.8, 'z': 623.5}}, + 33005: {'can_slip_through': False, + 'name': 'Bulb Zone West Wreck - Inside Databox', + 'need_laser_cutter': True, + 'position': {'x': 914.9, 'y': -202.1, 'z': 611.8}}, + 33006: {'can_slip_through': False, + 'name': 'Bulb Zone West Wreck - PDA', + 'need_laser_cutter': True, + 'position': {'x': 912.6, 'y': -202.0, 'z': 609.5}}, + 33007: {'can_slip_through': False, + 'name': 'Bulb Zone East Wreck - Databox', + 'need_laser_cutter': False, + 'position': {'x': 1327.1, 'y': -234.9, 'z': 575.8}}, + 33008: {'can_slip_through': False, + 'name': 'Dunes North Wreck - Outside Databox', + 'need_laser_cutter': False, + 'position': {'x': -1407.7, 'y': -344.2, 'z': 721.5}}, + 33009: {'can_slip_through': False, + 'name': 'Dunes North Wreck - Office Databox', + 'need_laser_cutter': False, + 'position': {'x': -1393.9, 'y': -329.7, 'z': 733.5}}, + 33010: {'can_slip_through': False, + 'name': 'Dunes North Wreck - PDA', + 'need_laser_cutter': False, + 'position': {'x': -1396.3, 'y': -330.8, 'z': 730.0}}, + 33011: {'can_slip_through': False, + 'name': 'Dunes North Wreck - Cargo Databox', + 'need_laser_cutter': True, + 'position': {'x': -1409.8, 'y': -332.4, 'z': 706.9}}, + 33012: {'can_slip_through': False, + 'name': 'Dunes West Wreck - Databox', + 'need_laser_cutter': False, + 'position': {'x': -1626.2, 'y': -357.5, 'z': 99.5}}, + 33013: {'can_slip_through': False, + 'name': 'Dunes East Wreck - Outside Databox', + 'need_laser_cutter': False, + 'position': {'x': -1196.3, 'y': -223.0, 'z': 12.5}}, + 33014: {'can_slip_through': False, + 'name': 'Dunes East Wreck - Inside Databox', + 'need_laser_cutter': False, + 'position': {'x': -1206.4, 'y': -225.6, 'z': 4.0}}, + 33015: {'can_slip_through': False, + 'name': 'Grand Reef North Wreck - Outside Databox', + 'need_laser_cutter': False, + 'position': {'x': -269.7, 'y': -262.8, 'z': -764.3}}, + 33016: {'can_slip_through': False, + 'name': 'Grand Reef North Wreck - Elevator Databox', + 'need_laser_cutter': True, + 'position': {'x': -285.8, 'y': -240.2, 'z': -786.5}}, + 33017: {'can_slip_through': False, + 'name': 'Grand Reef North Wreck - Bottom Databox', + 'need_laser_cutter': False, + 'position': {'x': -285.2, 'y': -262.4, 'z': -788.4}}, + 33018: {'can_slip_through': False, + 'name': 'Grand Reef North Wreck - Hangar PDA', + 'need_laser_cutter': False, + 'position': {'x': -272.5, 'y': -254.7, 'z': -788.5}}, + 33019: {'can_slip_through': False, + 'name': 'Grand Reef South Wreck - Trench Databox', + 'need_laser_cutter': False, + 'position': {'x': -850.9, 'y': -473.2, 'z': -1414.6}}, + 33020: {'can_slip_through': False, + 'name': 'Grand Reef South Wreck - Comms Databox', + 'need_laser_cutter': True, + 'position': {'x': -889.4, 'y': -433.8, 'z': -1424.8}}, + 33021: {'can_slip_through': False, + 'name': 'Grand Reef South Wreck - Outside Databox', + 'need_laser_cutter': False, + 'position': {'x': -862.4, 'y': -437.5, 'z': -1444.1}}, + 33022: {'can_slip_through': False, + 'name': 'Grand Reef South Wreck - PDA', + 'need_laser_cutter': False, + 'position': {'x': -887.9, 'y': -446.0, 'z': -1422.7}}, + 33023: {'can_slip_through': False, + 'name': 'Grassy Plateaus South Wreck - Databox', + 'need_laser_cutter': False, + 'position': {'x': -23.3, 'y': -105.8, 'z': -604.2}}, + 33024: {'can_slip_through': False, + 'name': 'Grassy Plateaus South Wreck - PDA', + 'need_laser_cutter': False, + 'position': {'x': -27.3, 'y': -106.8, 'z': -607.2}}, + 33025: {'can_slip_through': True, + 'name': 'Grassy Plateaus East Wreck - Breach Databox', + 'need_laser_cutter': True, + 'position': {'x': 313.9, 'y': -91.8, 'z': 432.6}}, + 33026: {'can_slip_through': True, + 'name': 'Grassy Plateaus East Wreck - Hangar Databox', + 'need_laser_cutter': True, + 'position': {'x': 319.4, 'y': -104.3, 'z': 441.5}}, + 33027: {'can_slip_through': False, + 'name': 'Grassy Plateaus West Wreck - Locker PDA', + 'need_laser_cutter': False, + 'position': {'x': -632.3, 'y': -75.0, 'z': -8.9}}, + 33028: {'can_slip_through': False, + 'name': 'Grassy Plateaus West Wreck - Data Terminal', + 'need_laser_cutter': False, + 'position': {'x': -664.4, 'y': -97.8, 'z': -8.0}}, + 33029: {'can_slip_through': False, + 'name': 'Grassy Plateaus West Wreck - Databox', + 'need_laser_cutter': True, + 'position': {'x': -421.4, 'y': -107.8, 'z': -266.5}}, + 33030: {'can_slip_through': False, + 'name': 'Safe Shallows Wreck - PDA', + 'need_laser_cutter': False, + 'position': {'x': -44.0, 'y': -29.1, 'z': -403.6}}, + 33031: {'can_slip_through': False, + 'name': 'Kelp Forest Wreck - Databox', + 'need_laser_cutter': False, + 'position': {'x': -317.6, 'y': -78.8, 'z': 247.4}}, + 33032: {'can_slip_through': False, + 'name': 'Kelp Forest Wreck - PDA', + 'need_laser_cutter': False, + 'position': {'x': 63.2, 'y': -38.5, 'z': 382.9}}, + 33033: {'can_slip_through': False, + 'name': 'Mountains West Wreck - Outside Databox', + 'need_laser_cutter': False, + 'position': {'x': 740.3, 'y': -389.2, 'z': 1179.8}}, + 33034: {'can_slip_through': False, + 'name': 'Mountains West Wreck - Data Terminal', + 'need_laser_cutter': True, + 'position': {'x': 703.7, 'y': -365.9, 'z': 1199.3}}, + 33035: {'can_slip_through': False, + 'name': 'Mountains West Wreck - Hangar Databox', + 'need_laser_cutter': True, + 'position': {'x': 698.2, 'y': -350.8, 'z': 1186.9}}, + 33036: {'can_slip_through': False, + 'name': 'Mountains West Wreck - Office Databox', + 'need_laser_cutter': False, + 'position': {'x': 676.3, 'y': -343.6, 'z': 1204.6}}, + 33037: {'can_slip_through': False, + 'name': 'Mountains East Wreck - Comms Databox', + 'need_laser_cutter': False, + 'position': {'x': 1068.5, 'y': -283.4, 'z': 1345.3}}, + 33038: {'can_slip_through': False, + 'name': 'Mountains East Wreck - Outside Databox', + 'need_laser_cutter': False, + 'position': {'x': 1075.7, 'y': -288.9, 'z': 1321.8}}, + 33039: {'can_slip_through': False, + 'name': 'Northwestern Mushroom Forest Wreck - Cargo Databox', + 'need_laser_cutter': True, + 'position': {'x': -655.1, 'y': -109.6, 'z': 791.0}}, + 33040: {'can_slip_through': False, + 'name': 'Northwestern Mushroom Forest Wreck - Office Databox', + 'need_laser_cutter': False, + 'position': {'x': -663.4, 'y': -111.9, 'z': 777.9}}, + 33041: {'can_slip_through': False, + 'name': 'Northwestern Mushroom Forest Wreck - PDA', + 'need_laser_cutter': False, + 'position': {'x': -662.2, 'y': -113.4, 'z': 777.7}}, + 33042: {'can_slip_through': False, + 'name': "Sea Treader's Path Wreck - Outside Databox", + 'need_laser_cutter': False, + 'position': {'x': -1161.1, 'y': -191.7, 'z': -758.3}}, + 33043: {'can_slip_through': False, + 'name': "Sea Treader's Path Wreck - Hangar Databox", + 'need_laser_cutter': True, + 'position': {'x': -1129.5, 'y': -155.2, 'z': -729.3}}, + 33044: {'can_slip_through': False, + 'name': "Sea Treader's Path Wreck - Lobby Databox", + 'need_laser_cutter': False, + 'position': {'x': -1115.9, 'y': -175.3, 'z': -724.5}}, + 33045: {'can_slip_through': False, + 'name': "Sea Treader's Path Wreck - PDA", + 'need_laser_cutter': False, + 'position': {'x': -1136.8, 'y': -157.0, 'z': -734.6}}, + 33046: {'can_slip_through': False, + 'name': 'Sparse Reef Wreck - Locker Databox', + 'need_laser_cutter': True, + 'position': {'x': -789.8, 'y': -216.1, 'z': -711.0}}, + 33047: {'can_slip_through': False, + 'name': 'Sparse Reef Wreck - Outside Databox', + 'need_laser_cutter': False, + 'position': {'x': -810.7, 'y': -209.3, 'z': -685.5}}, + 33048: {'can_slip_through': False, + 'name': 'Sparse Reef Wreck - Lab Databox', + 'need_laser_cutter': True, + 'position': {'x': -795.5, 'y': -204.1, 'z': -774.7}}, + 33049: {'can_slip_through': False, + 'name': 'Underwater Islands Wreck - Outside Databox', + 'need_laser_cutter': False, + 'position': {'x': -170.8, 'y': -187.6, 'z': 880.7}}, + 33050: {'can_slip_through': False, + 'name': 'Underwater Islands Wreck - Hangar Databox', + 'need_laser_cutter': True, + 'position': {'x': -138.4, 'y': -193.6, 'z': 888.7}}, + 33051: {'can_slip_through': False, + 'name': 'Underwater Islands Wreck - Data Terminal', + 'need_laser_cutter': True, + 'position': {'x': -130.7, 'y': -193.2, 'z': 883.3}}, + 33052: {'can_slip_through': False, + 'name': 'Underwater Islands Wreck - Cable Databox', + 'need_laser_cutter': False, + 'position': {'x': -137.8, 'y': -193.4, 'z': 879.4}}, + 33053: {'can_slip_through': False, + 'name': 'Underwater Islands Wreck - Pipes Databox 1', + 'need_laser_cutter': False, + 'need_propulsion_cannon': True, + 'position': {'x': -124.4, 'y': -200.7, 'z': 853.0}}, + 33054: {'can_slip_through': False, + 'name': 'Underwater Islands Wreck - Pipes Databox 2', + 'need_laser_cutter': False, + 'need_propulsion_cannon': True, + 'position': {'x': -126.8, 'y': -201.1, 'z': 852.1}}, + 33055: {'can_slip_through': False, + 'name': 'Degasi Seabase - Deep Grand Reef - Bedroom Databox', + 'need_laser_cutter': False, + 'position': {'x': -643.8, 'y': -509.9, 'z': -941.9}}, + 33056: {'can_slip_through': False, + 'name': 'Degasi Seabase - Deep Grand Reef - Observatory Databox', + 'need_laser_cutter': False, + 'position': {'x': -635.1, 'y': -502.7, 'z': -951.4}}, + 33057: {'can_slip_through': False, + 'name': 'Degasi Seabase - Deep Grand Reef - Bedroom PDA', + 'need_laser_cutter': False, + 'position': {'x': -645.8, 'y': -508.7, 'z': -943.0}}, + 33058: {'can_slip_through': False, + 'name': 'Degasi Seabase - Deep Grand Reef - Outside PDA', + 'need_laser_cutter': False, + 'position': {'x': -630.5, 'y': -511.1, 'z': -936.1}}, + 33059: {'can_slip_through': False, + 'name': 'Degasi Seabase - Deep Grand Reef - Observatory PDA', + 'need_laser_cutter': False, + 'position': {'x': -647.7, 'y': -502.6, 'z': -935.8}}, + 33060: {'can_slip_through': False, + 'name': 'Degasi Seabase - Deep Grand Reef - Lab PDA', + 'need_laser_cutter': False, + 'position': {'x': -639.6, 'y': -505.9, 'z': -946.6}}, + 33061: {'can_slip_through': False, + 'name': 'Floating Island - Lake PDA', + 'need_laser_cutter': False, + 'position': {'x': -707.2, 'y': 0.5, 'z': -1096.7}}, + 33062: {'can_slip_through': False, + 'name': 'Degasi Seabase - Floating Island - Databox', + 'need_laser_cutter': False, + 'position': {'x': -765.7, 'y': 17.6, 'z': -1116.4}}, + 33063: {'can_slip_through': False, + 'name': 'Degasi Seabase - Floating Island - Room PDA', + 'need_laser_cutter': False, + 'position': {'x': -754.9, 'y': 14.6, 'z': -1108.9}}, + 33064: {'can_slip_through': False, + 'name': 'Degasi Seabase - Floating Island - Green Wall PDA', + 'need_laser_cutter': False, + 'position': {'x': -765.3, 'y': 14.1, 'z': -1115.0}}, + 33065: {'can_slip_through': False, + 'name': 'Degasi Seabase - Floating Island - Corridor PDA', + 'need_laser_cutter': False, + 'position': {'x': -758.6, 'y': 14.1, 'z': -1111.3}}, + 33066: {'can_slip_through': False, + 'name': 'Degasi Seabase - Floating Island - North Observatory PDA', + 'need_laser_cutter': False, + 'position': {'x': -805.4, 'y': 76.9, 'z': -1055.7}}, + 33067: {'can_slip_through': False, + 'name': 'Degasi Seabase - Floating Island - South Observatory PDA', + 'need_laser_cutter': False, + 'position': {'x': -715.9, 'y': 75.4, 'z': -1168.8}}, + 33068: {'can_slip_through': False, + 'name': 'Jellyshroom Cave - PDA', + 'need_laser_cutter': False, + 'position': {'x': -540.5, 'y': -250.8, 'z': -83.4}}, + 33069: {'can_slip_through': False, + 'name': 'Degasi Seabase - Jellyshroom Cave - Bedroom Databox', + 'need_laser_cutter': False, + 'position': {'x': 110.6, 'y': -264.9, 'z': -369.0}}, + 33070: {'can_slip_through': False, + 'name': 'Degasi Seabase - Jellyshroom Cave - Detached PDA', + 'need_laser_cutter': False, + 'position': {'x': 80.6, 'y': -268.6, 'z': -358.3}}, + 33071: {'can_slip_through': False, + 'name': 'Degasi Seabase - Jellyshroom Cave - Office PDA', + 'need_laser_cutter': False, + 'position': {'x': 78.2, 'y': -265.0, 'z': -373.4}}, + 33072: {'can_slip_through': False, + 'name': 'Degasi Seabase - Jellyshroom Cave - Locker PDA', + 'need_laser_cutter': False, + 'position': {'x': 85.1, 'y': -264.1, 'z': -372.8}}, + 33073: {'can_slip_through': False, + 'name': 'Degasi Seabase - Jellyshroom Cave - Bedroom PDA', + 'need_laser_cutter': False, + 'position': {'x': 112.3, 'y': -264.9, 'z': -369.3}}, + 33074: {'can_slip_through': False, + 'name': 'Degasi Seabase - Jellyshroom Cave - Observatory PDA', + 'need_laser_cutter': False, + 'position': {'x': 95.5, 'y': -258.9, 'z': -366.5}}, + 33075: {'can_slip_through': False, + 'name': 'Lifepod 2 - Databox', + 'need_laser_cutter': False, + 'position': {'x': -483.6, 'y': -504.7, 'z': 1326.6}}, + 33076: {'can_slip_through': False, + 'name': 'Lifepod 2 - PDA', + 'need_laser_cutter': False, + 'position': {'x': -481.4, 'y': -503.6, 'z': 1324.1}}, + 33077: {'can_slip_through': False, + 'name': 'Lifepod 3 - Databox', + 'need_laser_cutter': False, + 'position': {'x': -34.2, 'y': -22.4, 'z': 410.5}}, + 33078: {'can_slip_through': False, + 'name': 'Lifepod 3 - PDA', + 'need_laser_cutter': False, + 'position': {'x': -33.8, 'y': -22.5, 'z': 408.8}}, + 33079: {'can_slip_through': False, + 'name': 'Lifepod 4 - Databox', + 'need_laser_cutter': False, + 'position': {'x': 712.4, 'y': -3.4, 'z': 160.8}}, + 33080: {'can_slip_through': False, + 'name': 'Lifepod 4 - PDA', + 'need_laser_cutter': False, + 'position': {'x': 712.0, 'y': -3.5, 'z': 161.5}}, + 33081: {'can_slip_through': False, + 'name': 'Lifepod 6 - Databox', + 'need_laser_cutter': False, + 'position': {'x': 358.7, 'y': -117.1, 'z': 306.8}}, + 33082: {'can_slip_through': False, + 'name': 'Lifepod 6 - Inside PDA', + 'need_laser_cutter': False, + 'position': {'x': 361.8, 'y': -116.2, 'z': 309.5}}, + 33083: {'can_slip_through': False, + 'name': 'Lifepod 6 - Outside PDA', + 'need_laser_cutter': False, + 'position': {'x': 359.9, 'y': -117.0, 'z': 312.1}}, + 33084: {'can_slip_through': False, + 'name': 'Lifepod 7 - PDA', + 'need_laser_cutter': False, + 'position': {'x': -56.0, 'y': -182.0, 'z': -1039.0}}, + 33085: {'can_slip_through': False, + 'name': 'Lifepod 12 - Databox', + 'need_laser_cutter': False, + 'position': {'x': 1119.5, 'y': -271.7, 'z': 561.7}}, + 33086: {'can_slip_through': False, + 'name': 'Lifepod 12 - PDA', + 'need_laser_cutter': False, + 'position': {'x': 1116.1, 'y': -271.3, 'z': 566.9}}, + 33087: {'can_slip_through': False, + 'name': 'Lifepod 13 - Databox', + 'need_laser_cutter': False, + 'position': {'x': -926.4, 'y': -185.2, 'z': 501.8}}, + 33088: {'can_slip_through': False, + 'name': 'Lifepod 13 - PDA', + 'need_laser_cutter': False, + 'position': {'x': -926.8, 'y': -184.4, 'z': 506.6}}, + 33089: {'can_slip_through': False, + 'name': 'Lifepod 17 - PDA', + 'need_laser_cutter': False, + 'position': {'x': -514.5, 'y': -98.1, 'z': -56.5}}, + 33090: {'can_slip_through': False, + 'name': 'Lifepod 19 - Databox', + 'need_laser_cutter': False, + 'position': {'x': -809.8, 'y': -302.2, 'z': -876.9}}, + 33091: {'can_slip_through': False, + 'name': 'Lifepod 19 - Outside PDA', + 'need_laser_cutter': False, + 'position': {'x': -806.1, 'y': -294.1, 'z': -866.0}}, + 33092: {'can_slip_through': False, + 'name': 'Lifepod 19 - Inside PDA', + 'need_laser_cutter': False, + 'position': {'x': -810.5, 'y': -299.4, 'z': -873.1}}, + 33093: {'can_slip_through': False, + 'name': 'Aurora Seamoth Bay - Upgrade Console', + 'need_laser_cutter': False, + 'need_propulsion_cannon': True, + 'position': {'x': 903.5, 'y': -0.2, 'z': 16.1}}, + 33094: {'can_slip_through': False, + 'name': 'Aurora Drive Room - Upgrade Console', + 'need_laser_cutter': False, + 'need_propulsion_cannon': True, + 'position': {'x': 872.5, 'y': 2.7, 'z': -0.7}}, + 33095: {'can_slip_through': False, + 'name': 'Aurora Prawn Suit Bay - Upgrade Console', + 'need_laser_cutter': True, + 'need_propulsion_cannon': True, + 'position': {'x': 991.6, 'y': 3.2, 'z': -31.0}}, + 33096: {'can_slip_through': False, + 'name': 'Aurora - Office PDA', + 'need_laser_cutter': False, + 'position': {'x': 952.1, 'y': 41.2, 'z': 113.9}}, + 33097: {'can_slip_through': False, + 'name': 'Aurora - Corridor PDA', + 'need_laser_cutter': False, + 'position': {'x': 977.2, 'y': 39.1, 'z': 83.0}}, + 33098: {'can_slip_through': False, + 'name': 'Aurora - Cargo Bay PDA', + 'need_laser_cutter': False, + 'need_propulsion_cannon': True, + 'position': {'x': 954.9, 'y': 11.2, 'z': 3.4}}, + 33099: {'can_slip_through': False, + 'name': 'Aurora - Seamoth Bay PDA', + 'need_laser_cutter': False, + 'need_propulsion_cannon': True, + 'position': {'x': 907.1, 'y': -1.5, 'z': 15.3}}, + 33100: {'can_slip_through': False, + 'name': 'Aurora - Medkit Locker PDA', + 'need_laser_cutter': True, + 'need_propulsion_cannon': True, + 'position': {'x': 951.8, 'y': -2.3, 'z': -34.7}}, + 33101: {'can_slip_through': False, + 'name': 'Aurora - Locker PDA', + 'need_laser_cutter': True, + 'need_propulsion_cannon': True, + 'position': {'x': 952.0, 'y': -3.7, 'z': -23.4}}, + 33102: {'can_slip_through': False, + 'name': 'Aurora - Canteen PDA', + 'need_laser_cutter': True, + 'need_propulsion_cannon': True, + 'position': {'x': 986.5, 'y': 9.6, 'z': -48.6}}, + 33103: {'can_slip_through': False, + 'name': 'Aurora - Cabin 4 PDA', + 'need_laser_cutter': True, + 'need_propulsion_cannon': True, + 'position': {'x': 951.3, 'y': 11.2, 'z': -51.0}}, + 33104: {'can_slip_through': False, + 'name': 'Aurora - Cabin 7 PDA', + 'need_laser_cutter': True, + 'need_propulsion_cannon': True, + 'position': {'x': 967.1, 'y': 10.4, 'z': -47.4}}, + 33105: {'can_slip_through': False, + 'name': 'Aurora - Cabin 1 PDA', + 'need_laser_cutter': True, + 'need_propulsion_cannon': True, + 'position': {'x': 964.1, 'y': 11.1, 'z': -61.9}}, + 33106: {'can_slip_through': False, + 'name': 'Aurora - Captain PDA', + 'need_laser_cutter': True, + 'need_propulsion_cannon': True, + 'position': {'x': 971.2, 'y': 10.8, 'z': -70.4}}, + 33107: {'can_slip_through': False, + 'name': 'Aurora - Ring PDA', + 'need_laser_cutter': False, + 'need_propulsion_cannon': True, + 'position': {'x': 1033.6, 'y': -8.5, 'z': 16.2}}, + 33108: {'can_slip_through': False, + 'name': 'Aurora - Lab PDA', + 'need_laser_cutter': False, + 'need_propulsion_cannon': True, + 'position': {'x': 1032.5, 'y': -7.8, 'z': 32.4}}, + 33109: {'can_slip_through': False, + 'name': 'Aurora - Office Data Terminal', + 'need_laser_cutter': False, + 'position': {'x': 945.8, 'y': 40.8, 'z': 115.1}}, + 33110: {'can_slip_through': False, + 'name': 'Aurora - Captain Data Terminal', + 'need_laser_cutter': True, + 'need_propulsion_cannon': True, + 'position': {'x': 974.8, 'y': 10.0, 'z': -77.0}}, + 33111: {'can_slip_through': False, + 'name': 'Aurora - Battery Room Data Terminal', + 'need_laser_cutter': True, + 'need_propulsion_cannon': True, + 'position': {'x': 1040.8, 'y': -11.4, 'z': -3.4}}, + 33112: {'can_slip_through': False, + 'name': 'Aurora - Lab Data Terminal', + 'need_laser_cutter': False, + 'need_propulsion_cannon': True, + 'position': {'x': 1029.5, 'y': -8.7, 'z': 35.9}}, + 33113: {'can_slip_through': False, + 'name': "Quarantine Enforcement Platform's - Upper Alien Data " + 'Terminal', + 'need_laser_cutter': False, + 'position': {'x': 432.2, 'y': 3.0, 'z': 1193.2}}, + 33114: {'can_slip_through': False, + 'name': "Quarantine Enforcement Platform's - Mid Alien Data Terminal", + 'need_laser_cutter': False, + 'position': {'x': 474.4, 'y': -4.5, 'z': 1224.4}}, + 33115: {'can_slip_through': False, + 'name': 'Dunes Sanctuary - Alien Data Terminal', + 'need_laser_cutter': False, + 'position': {'x': -1224.2, 'y': -400.4, 'z': 1057.9}}, + 33116: {'can_slip_through': False, + 'name': 'Deep Sparse Reef Sanctuary - Alien Data Terminal', + 'need_laser_cutter': False, + 'position': {'x': -895.5, 'y': -311.6, 'z': -838.1}}, + 33117: {'can_slip_through': False, + 'name': 'Northern Blood Kelp Zone Sanctuary - Alien Data Terminal', + 'need_laser_cutter': False, + 'position': {'x': -642.9, 'y': -563.5, 'z': 1485.5}}, + 33118: {'can_slip_through': False, + 'name': 'Lost River Laboratory Cache - Alien Data Terminal', + 'need_laser_cutter': False, + 'position': {'x': -1112.3, 'y': -687.3, 'z': -695.5}}, + 33119: {'can_slip_through': False, + 'name': 'Disease Research Facility - Upper Alien Data Terminal', + 'need_laser_cutter': False, + 'position': {'x': -280.2, 'y': -804.3, 'z': 305.1}}, + 33120: {'can_slip_through': False, + 'name': 'Disease Research Facility - Mid Alien Data Terminal', + 'need_laser_cutter': False, + 'position': {'x': -267.9, 'y': -806.6, 'z': 250.0}}, + 33121: {'can_slip_through': False, + 'name': 'Disease Research Facility - Lower Alien Data Terminal', + 'need_laser_cutter': False, + 'position': {'x': -286.2, 'y': -815.6, 'z': 297.8}}, + 33122: {'can_slip_through': False, + 'name': 'Alien Thermal Plant - Entrance Alien Data Terminal', + 'need_laser_cutter': False, + 'position': {'x': -71.3, 'y': -1227.2, 'z': 104.8}}, + 33123: {'can_slip_through': False, + 'name': 'Alien Thermal Plant - Green Alien Data Terminal', + 'need_laser_cutter': False, + 'position': {'x': -38.7, 'y': -1226.6, 'z': 111.8}}, + 33124: {'can_slip_through': False, + 'name': 'Alien Thermal Plant - Yellow Alien Data Terminal', + 'need_laser_cutter': False, + 'position': {'x': -30.4, 'y': -1220.3, 'z': 111.8}}, + 33125: {'can_slip_through': False, + 'name': "Primary Containment Facility's Antechamber - Alien Data " + 'Terminal', + 'need_laser_cutter': False, + 'position': {'x': 245.8, 'y': -1430.6, 'z': -311.5}}, + 33126: {'can_slip_through': False, + 'name': "Primary Containment Facility's Egg Laboratory - Alien Data " + 'Terminal', + 'need_laser_cutter': False, + 'position': {'x': 165.5, 'y': -1442.4, 'z': -385.8}}, + 33127: {'can_slip_through': False, + 'name': "Primary Containment Facility's Pipe Room - Alien Data " + 'Terminal', + 'need_laser_cutter': False, + 'position': {'x': 348.7, 'y': -1443.5, 'z': -291.9}}, + 33128: {'can_slip_through': False, + 'name': 'Grassy Plateaus West Wreck - Beam PDA', + 'need_laser_cutter': True, + 'position': {'x': -641.8, 'y': -111.3, 'z': -19.7}}, + 33129: {'can_slip_through': False, + 'name': 'Floating Island - Cave Entrance PDA', + 'need_laser_cutter': False, + 'position': {'x': -748.9, 'y': 14.4, 'z': -1179.5}}} + +if False: # turn to True to export for Subnautica mod + payload = {location_id: location_data["position"] for location_id, location_data in location_table.items()} + import json + + with open("locations.json", "w") as f: + json.dump(payload, f) diff --git a/worlds/subnautica/Options.py b/worlds/subnautica/Options.py index 4189aecb..cae7ba6c 100644 --- a/worlds/subnautica/Options.py +++ b/worlds/subnautica/Options.py @@ -2,13 +2,36 @@ from Options import Choice class ItemPool(Choice): - """Valuable item pool moves all not progression relevant items to starting inventory and - creates random duplicates of important items in their place.""" + """Valuable item pool leaves all filler items in their vanilla locations and + creates random duplicates of important items into freed spots.""" display_name = "Item Pool" option_standard = 0 option_valuable = 1 +class Goal(Choice): + """Goal to complete. + Launch: Leave the planet. + Free: Disable quarantine. + Infected: Reach maximum infection level. + Drive: Repair the Aurora's Drive Core""" + auto_display_name = True + display_name = "Goal" + option_launch = 0 + option_free = 1 + option_infected = 2 + option_drive = 3 + + def get_event_name(self) -> str: + return { + self.option_launch: "Neptune Launch", + self.option_infected: "Full Infection", + self.option_free: "Disable Quarantine", + self.option_drive: "Repair Aurora Drive" + }[self.value] + + options = { - "item_pool": ItemPool + "item_pool": ItemPool, + "goal": Goal, } diff --git a/worlds/subnautica/Regions.py b/worlds/subnautica/Regions.py deleted file mode 100644 index 1eb0e12f..00000000 --- a/worlds/subnautica/Regions.py +++ /dev/null @@ -1,8 +0,0 @@ -def create_regions(world, player: int): - from . import create_region - from .Locations import lookup_name_to_id as location_lookup_name_to_id - - world.regions += [ - create_region(world, player, 'Menu', None, ['Lifepod 5']), - create_region(world, player, 'Planet 4546B', [location for location in location_lookup_name_to_id]) - ] diff --git a/worlds/subnautica/Rules.py b/worlds/subnautica/Rules.py index 8d5bcae4..131a537f 100644 --- a/worlds/subnautica/Rules.py +++ b/worlds/subnautica/Rules.py @@ -1,6 +1,5 @@ -from ..generic.Rules import set_rule -from .Locations import location_table -import logging +from worlds.generic.Rules import set_rule +from .Locations import location_table, LocationDict import math @@ -197,32 +196,32 @@ def get_max_depth(state, player): get_prawn_max_depth(state, player)) -def can_access_location(state, player, loc): - pos_x = loc.get("position").get("x") - pos_y = loc.get("position").get("y") - pos_z = loc.get("position").get("z") - depth = -pos_y # y-up - map_center_dist = math.sqrt(pos_x ** 2 + pos_z ** 2) - aurora_dist = math.sqrt((pos_x - 1038.0) ** 2 + (pos_y - -3.4) ** 2 + (pos_z - -163.1) ** 2) - - need_radiation_suit = aurora_dist < 950 +def can_access_location(state, player: int, loc: LocationDict): need_laser_cutter = loc.get("need_laser_cutter", False) - need_propulsion_cannon = loc.get("need_propulsion_cannon", False) - if need_laser_cutter and not has_laser_cutter(state, player): return False - if need_radiation_suit and not state.has("Radiation Suit", player): + need_propulsion_cannon = loc.get("need_propulsion_cannon", False) + if need_propulsion_cannon and not has_propulsion_cannon(state, player): return False - if need_propulsion_cannon and not has_propulsion_cannon(state, player): + pos = loc["position"] + pos_x = pos["x"] + pos_y = pos["y"] + pos_z = pos["z"] + + aurora_dist = math.sqrt((pos_x - 1038.0) ** 2 + (pos_y - -3.4) ** 2 + (pos_z - -163.1) ** 2) + need_radiation_suit = aurora_dist < 950 + if need_radiation_suit and not state.has("Radiation Suit", player): return False # Seaglide doesn't unlock anything specific, but just allows for faster movement. # Otherwise the game is painfully slow. + map_center_dist = math.sqrt(pos_x ** 2 + pos_z ** 2) if (map_center_dist > 800 or pos_y < -200) and not has_seaglide(state, player): return False + depth = -pos_y # y-up return get_max_depth(state, player) >= depth @@ -230,21 +229,33 @@ def set_location_rule(world, player, loc): set_rule(world.get_location(loc["name"], player), lambda state: can_access_location(state, player, loc)) -def set_rules(world, player): - for loc in location_table: +def set_rules(subnautica_world): + player = subnautica_world.player + world = subnautica_world.world + + for loc in location_table.values(): set_location_rule(world, player, loc) - # Victory location - set_rule(world.get_location("Neptune Launch", player), lambda state: \ - get_max_depth(state, player) >= 1444 and \ - has_mobile_vehicle_bay(state, player) and \ - state.has('Neptune Launch Platform', player) and \ - state.has('Neptune Gantry', player) and \ - state.has('Neptune Boosters', player) and \ - state.has('Neptune Fuel Reserve', player) and \ - state.has('Neptune Cockpit', player) and \ - state.has('Ion Power Cell', player) and \ - state.has('Ion Battery', player) and \ + # Victory locations + set_rule(world.get_location("Neptune Launch", player), lambda state: + get_max_depth(state, player) >= 1444 and + has_mobile_vehicle_bay(state, player) and + state.has("Neptune Launch Platform", player) and + state.has("Neptune Gantry", player) and + state.has("Neptune Boosters", player) and + state.has("Neptune Fuel Reserve", player) and + state.has("Neptune Cockpit", player) and + state.has("Ion Power Cell", player) and + state.has("Ion Battery", player) and has_cyclops_shield(state, player)) - world.completion_condition[player] = lambda state: state.has('Victory', player) + set_rule(world.get_location("Disable Quarantine", player), lambda state: + get_max_depth(state, player) >= 1444) + + set_rule(world.get_location("Full Infection", player), lambda state: + get_max_depth(state, player) >= 900) + + room = world.get_location("Aurora Drive Room - Upgrade Console", player) + set_rule(world.get_location("Repair Aurora Drive", player), lambda state: room.can_reach(state)) + + world.completion_condition[player] = lambda state: state.has("Victory", player) diff --git a/worlds/subnautica/__init__.py b/worlds/subnautica/__init__.py index ae923318..f2fa5497 100644 --- a/worlds/subnautica/__init__.py +++ b/worlds/subnautica/__init__.py @@ -1,18 +1,16 @@ import logging +from typing import List, Dict, Any + +from BaseClasses import Region, Entrance, Location, Item, Tutorial, ItemClassification, RegionType +from worlds.AutoWorld import World, WebWorld +from . import Items +from . import Locations +from . import Options +from .Items import item_table +from .Rules import set_rules logger = logging.getLogger("Subnautica") -from .Locations import lookup_name_to_id as locations_lookup_name_to_id -from .Items import item_table, lookup_name_to_item, advancement_item_names -from .Items import lookup_name_to_id as items_lookup_name_to_id - -from .Regions import create_regions -from .Rules import set_rules -from .Options import options - -from BaseClasses import Region, Entrance, Location, MultiWorld, Item, Tutorial, ItemClassification, RegionType -from ..AutoWorld import World, WebWorld - class SubnaticaWeb(WebWorld): tutorials = [Tutorial( @@ -34,34 +32,51 @@ class SubnauticaWorld(World): game: str = "Subnautica" web = SubnaticaWeb() - item_name_to_id = items_lookup_name_to_id - location_name_to_id = locations_lookup_name_to_id - options = options + item_name_to_id = {data["name"]: item_id for item_id, data in Items.item_table.items()} + location_name_to_id = {data["name"]: loc_id for loc_id, data in Locations.location_table.items()} + options = Options.options data_version = 2 - required_client_version = (0, 1, 9) + required_client_version = (0, 3, 3) + + prefill_items: List[Item] + + def generate_early(self) -> None: + self.prefill_items = [ + self.create_item("Seaglide Fragment"), + self.create_item("Seaglide Fragment") + ] + + def create_regions(self): + self.world.regions += [ + self.create_region("Menu", None, ["Lifepod 5"]), + self.create_region("Planet 4546B", + Locations.events + [location["name"] for location in Locations.location_table.values()]) + ] + + # refer to Rules.py + set_rules = set_rules def generate_basic(self): # Link regions - self.world.get_entrance('Lifepod 5', self.player).connect(self.world.get_region('Planet 4546B', self.player)) + self.world.get_entrance("Lifepod 5", self.player).connect(self.world.get_region("Planet 4546B", self.player)) # Generate item pool pool = [] neptune_launch_platform = None extras = 0 - valuable = self.world.item_pool[self.player] == "valuable" - for item in item_table: + valuable = self.world.item_pool[self.player] == Options.ItemPool.option_valuable + for item in item_table.values(): for i in range(item["count"]): subnautica_item = self.create_item(item["name"]) if item["name"] == "Neptune Launch Platform": neptune_launch_platform = subnautica_item - elif valuable and not item["progression"]: - self.world.push_precollected(subnautica_item) + elif valuable and ItemClassification.filler == item["classification"]: extras += 1 else: pool.append(subnautica_item) - for item_name in self.world.random.choices(sorted(advancement_item_names - {"Neptune Launch Platform"}), + for item_name in self.world.random.choices(sorted(Items.advancement_item_names - {"Neptune Launch Platform"}), k=extras): item = self.create_item(item_name) item.classification = ItemClassification.filler # as it's an extra, just fast-fill it somewhere @@ -72,39 +87,57 @@ class SubnauticaWorld(World): # Victory item self.world.get_location("Aurora - Captain Data Terminal", self.player).place_locked_item( neptune_launch_platform) - self.world.get_location("Neptune Launch", self.player).place_locked_item( - SubnauticaItem("Victory", ItemClassification.progression, None, player=self.player)) + for event in Locations.events: + self.world.get_location(event, self.player).place_locked_item( + SubnauticaItem(event, ItemClassification.progression, None, player=self.player)) + # make the goal event the victory "item" + self.world.get_location(self.world.goal[self.player].get_event_name(), self.player).item.name = "Victory" - def set_rules(self): - set_rules(self.world, self.player) + def fill_slot_data(self) -> Dict[str, Any]: + goal: Options.Goal = self.world.goal[self.player] + item_pool: Options.ItemPool = self.world.item_pool[self.player] + vanilla_tech: List[str] = [] + if item_pool == Options.ItemPool.option_valuable: + for item in Items.item_table.values(): + if item["classification"] == ItemClassification.filler: + vanilla_tech.append(item["tech_type"]) - def create_regions(self): - create_regions(self.world, self.player) + slot_data: Dict[str, Any] = { + "goal": goal.current_key, + "vanilla_tech": vanilla_tech, + } - def fill_slot_data(self): - slot_data = {} return slot_data def create_item(self, name: str) -> Item: - item = lookup_name_to_item[name] + item_id: int = self.item_name_to_id[name] + return SubnauticaItem(name, - ItemClassification.progression if item["progression"] else ItemClassification.filler, - item["id"], player=self.player) + item_table[item_id]["classification"], + item_id, player=self.player) + def create_region(self, name: str, locations=None, exits=None): + ret = Region(name, RegionType.Generic, name, self.player) + ret.world = self.world + if locations: + for location in locations: + loc_id = self.location_name_to_id.get(location, None) + location = SubnauticaLocation(self.player, location, loc_id, ret) + ret.locations.append(location) + if exits: + for region_exit in exits: + ret.exits.append(Entrance(self.player, region_exit, ret)) + return ret -def create_region(world: MultiWorld, player: int, name: str, locations=None, exits=None): - ret = Region(name, RegionType.Generic, name, player) - ret.world = world - if locations: - for location in locations: - loc_id = locations_lookup_name_to_id.get(location, 0) - location = SubnauticaLocation(player, location, loc_id, ret) - ret.locations.append(location) - if exits: - for exit in exits: - ret.exits.append(Entrance(player, exit, ret)) + def get_pre_fill_items(self) -> List[Item]: + return self.prefill_items - return ret + def pre_fill(self) -> None: + reachable = self.world.get_reachable_locations(player=self.player) + self.world.random.shuffle(reachable) + items = self.prefill_items.copy() + for item in items: + reachable.pop().place_locked_item(item) class SubnauticaLocation(Location): @@ -112,4 +145,4 @@ class SubnauticaLocation(Location): class SubnauticaItem(Item): - game = "Subnautica" + game: str = "Subnautica" diff --git a/worlds/subnautica/items.json b/worlds/subnautica/items.json deleted file mode 100644 index 2dc4b225..00000000 --- a/worlds/subnautica/items.json +++ /dev/null @@ -1,83 +0,0 @@ -[ - { "id": 35000, "count": 1, "progression": false, "tech_type": "Compass", "name": "Compass" }, - { "id": 35001, "count": 1, "progression": true, "tech_type": "PlasteelTank", "name": "Lightweight High Capacity Tank" }, - { "id": 35002, "count": 1, "progression": true, "tech_type": "BaseUpgradeConsole", "name": "Vehicle Upgrade Console" }, - { "id": 35003, "count": 1, "progression": true, "tech_type": "UltraGlideFins", "name": "Ultra Glide Fins" }, - { "id": 35004, "count": 1, "progression": false, "tech_type": "CyclopsSonarModule", "name": "Cyclops Sonar Upgrade" }, - { "id": 35005, "count": 1, "progression": false, "tech_type": "ReinforcedDiveSuit", "name": "Reinforced Dive Suit" }, - { "id": 35006, "count": 1, "progression": false, "tech_type": "CyclopsThermalReactorModule", "name": "Cyclops Thermal Reactor Module" }, - { "id": 35007, "count": 1, "progression": false, "tech_type": "Stillsuit", "name": "Stillsuit" }, - { "id": 35008, "count": 2, "progression": false, "tech_type": "BaseWaterParkFragment", "name": "Alien Containment Fragment" }, - { "id": 35009, "count": 1, "progression": false, "tech_type": "CyclopsDecoy", "name": "Creature Decoy" }, - { "id": 35010, "count": 1, "progression": false, "tech_type": "CyclopsFireSuppressionModule", "name": "Cyclops Fire Suppression System" }, - { "id": 35011, "count": 1, "progression": false, "tech_type": "SwimChargeFins", "name": "Swim Charge Fins" }, - { "id": 35012, "count": 1, "progression": false, "tech_type": "RepulsionCannon", "name": "Repulsion Cannon" }, - { "id": 35013, "count": 1, "progression": false, "tech_type": "CyclopsDecoyModule", "name": "Cyclops Decoy Tube Upgrade" }, - { "id": 35014, "count": 1, "progression": true, "tech_type": "CyclopsShieldModule", "name": "Cyclops Shield Generator" }, - { "id": 35015, "count": 1, "progression": true, "tech_type": "CyclopsHullModule1", "name": "Cyclops Depth Module MK1" }, - { "id": 35016, "count": 1, "progression": false, "tech_type": "CyclopsSeamothRepairModule", "name": "Cyclops Docking Bay Repair Module" }, - { "id": 35017, "count": 2, "progression": false, "tech_type": "BatteryChargerFragment", "name": "Battery Charger fragment" }, - { "id": 35018, "count": 2, "progression": false, "tech_type": "BeaconFragment", "name": "Beacon Fragment" }, - { "id": 35019, "count": 2, "progression": false, "tech_type": "BaseBioReactorFragment", "name": "Bioreactor Fragment" }, - { "id": 35020, "count": 3, "progression": true, "tech_type": "CyclopsBridgeFragment", "name": "Cyclops Bridge Fragment" }, - { "id": 35021, "count": 3, "progression": true, "tech_type": "CyclopsEngineFragment", "name": "Cyclops Engine Fragment" }, - { "id": 35022, "count": 3, "progression": true, "tech_type": "CyclopsHullFragment", "name": "Cyclops Hull Fragment" }, - { "id": 35023, "count": 2, "progression": false, "tech_type": "GravSphereFragment", "name": "Grav Trap Fragment" }, - { "id": 35024, "count": 3, "progression": true, "tech_type": "LaserCutterFragment", "name": "Laser Cutter Fragment" }, - { "id": 35025, "count": 1, "progression": false, "tech_type": "TechlightFragment", "name": "Light Stick Fragment" }, - { "id": 35026, "count": 3, "progression": true, "tech_type": "ConstructorFragment", "name": "Mobile Vehicle Bay Fragment" }, - { "id": 35027, "count": 3, "progression": true, "tech_type": "WorkbenchFragment", "name": "Modification Station Fragment" }, - { "id": 35028, "count": 2, "progression": true, "tech_type": "MoonpoolFragment", "name": "Moonpool Fragment" }, - { "id": 35029, "count": 3, "progression": false, "tech_type": "BaseNuclearReactorFragment", "name": "Nuclear Reactor Fragment" }, - { "id": 35030, "count": 2, "progression": false, "tech_type": "PowerCellChargerFragment", "name": "Power Cell Charger Fragment" }, - { "id": 35031, "count": 1, "progression": false, "tech_type": "PowerTransmitterFragment", "name": "Power Transmitter Fragment" }, - { "id": 35032, "count": 4, "progression": true, "tech_type": "ExosuitFragment", "name": "Prawn Suit Fragment" }, - { "id": 35033, "count": 2, "progression": false, "tech_type": "ExosuitDrillArmFragment", "name": "Prawn Suit Drill Arm Fragment" }, - { "id": 35034, "count": 2, "progression": false, "tech_type": "ExosuitGrapplingArmFragment", "name": "Prawn Suit Grappling Arm Fragment" }, - { "id": 35035, "count": 2, "progression": false, "tech_type": "ExosuitPropulsionArmFragment", "name": "Prawn Suit Propulsion Cannon Fragment" }, - { "id": 35036, "count": 2, "progression": false, "tech_type": "ExosuitTorpedoArmFragment", "name": "Prawn Suit Torpedo Arm Fragment" }, - { "id": 35037, "count": 3, "progression": false, "tech_type": "BaseMapRoomFragment", "name": "Scanner Room Fragment" }, - { "id": 35038, "count": 5, "progression": true, "tech_type": "SeamothFragment", "name": "Seamoth Fragment" }, - { "id": 35039, "count": 2, "progression": false, "tech_type": "StasisRifleFragment", "name": "Stasis Rifle Fragment" }, - { "id": 35040, "count": 2, "progression": false, "tech_type": "ThermalPlantFragment", "name": "Thermal Plant Fragment" }, - { "id": 35041, "count": 4, "progression": true, "tech_type": "SeaglideFragment", "name": "Seaglide Fragment" }, - { "id": 35042, "count": 1, "progression": true, "tech_type": "RadiationSuit", "name": "Radiation Suit" }, - { "id": 35043, "count": 2, "progression": true, "tech_type": "PropulsionCannonFragment", "name": "Propulsion Cannon Fragment" }, - { "id": 35044, "count": 1, "progression": true, "tech_type": "RocketBase", "name": "Neptune Launch Platform" }, - { "id": 35045, "count": 1, "progression": true, "tech_type": "PrecursorIonPowerCell", "name": "Ion Power Cell" }, - { "id": 35046, "count": 2, "progression": false, "tech_type": "FarmingTrayFragment", "name": "Exterior Growbed Fragment" }, - { "id": 35047, "count": 1, "progression": false, "tech_type": "PictureFrameFragment", "name": "Picture Frame" }, - { "id": 35048, "count": 2, "progression": false, "tech_type": "BenchFragment", "name": "Bench Fragment" }, - { "id": 35049, "count": 1, "progression": false, "tech_type": "PlanterPotFragment", "name": "Basic Plant Pot" }, - { "id": 35050, "count": 1, "progression": false, "tech_type": "PlanterBoxFragment", "name": "Interior Growbed" }, - { "id": 35051, "count": 1, "progression": false, "tech_type": "PlanterShelfFragment", "name": "Plant Shelf" }, - { "id": 35052, "count": 2, "progression": false, "tech_type": "BaseObservatoryFragment", "name": "Observatory Fragment" }, - { "id": 35053, "count": 2, "progression": false, "tech_type": "BaseRoomFragment", "name": "Multipurpose Room Fragment" }, - { "id": 35054, "count": 2, "progression": false, "tech_type": "BaseBulkheadFragment", "name": "Bulkhead Fragment" }, - { "id": 35055, "count": 1, "progression": false, "tech_type": "Spotlight", "name": "Spotlight" }, - { "id": 35056, "count": 2, "progression": false, "tech_type": "StarshipDesk", "name": "Desk" }, - { "id": 35057, "count": 1, "progression": false, "tech_type": "StarshipChair", "name": "Swivel Chair" }, - { "id": 35058, "count": 1, "progression": false, "tech_type": "StarshipChair2", "name": "Office Chair" }, - { "id": 35059, "count": 1, "progression": false, "tech_type": "StarshipChair3", "name": "Command Chair" }, - { "id": 35060, "count": 2, "progression": false, "tech_type": "LabCounter", "name": "Counter" }, - { "id": 35061, "count": 1, "progression": false, "tech_type": "NarrowBed", "name": "Single Bed" }, - { "id": 35062, "count": 1, "progression": false, "tech_type": "Bed1", "name": "Basic Double Bed" }, - { "id": 35063, "count": 1, "progression": false, "tech_type": "Bed2", "name": "Quilted Double Bed" }, - { "id": 35064, "count": 2, "progression": false, "tech_type": "CoffeeVendingMachine", "name": "Coffee Vending Machine" }, - { "id": 35065, "count": 2, "progression": false, "tech_type": "Trashcans", "name": "Trash Can" }, - { "id": 35066, "count": 1, "progression": false, "tech_type": "Techlight", "name": "Floodlight" }, - { "id": 35067, "count": 1, "progression": false, "tech_type": "BarTable", "name": "Bar Table" }, - { "id": 35068, "count": 1, "progression": false, "tech_type": "VendingMachine", "name": "Vending Machine" }, - { "id": 35069, "count": 1, "progression": false, "tech_type": "SingleWallShelf", "name": "Single Wall Shelf" }, - { "id": 35070, "count": 1, "progression": false, "tech_type": "WallShelves", "name": "Wall Shelves" }, - { "id": 35071, "count": 1, "progression": false, "tech_type": "PlanterPot2", "name": "Round Plant Pot" }, - { "id": 35072, "count": 1, "progression": false, "tech_type": "PlanterPot3", "name": "Chic Plant Pot" }, - { "id": 35073, "count": 1, "progression": false, "tech_type": "LabTrashcan", "name": "Nuclear Waste Disposal" }, - { "id": 35074, "count": 1, "progression": false, "tech_type": "BasePlanter", "name": "Wall Planter" }, - { "id": 35075, "count": 1, "progression": true, "tech_type": "PrecursorIonBattery", "name": "Ion Battery" }, - { "id": 35076, "count": 1, "progression": true, "tech_type": "RocketBaseLadder", "name": "Neptune Gantry" }, - { "id": 35077, "count": 1, "progression": true, "tech_type": "RocketStage1", "name": "Neptune Boosters" }, - { "id": 35078, "count": 1, "progression": true, "tech_type": "RocketStage2", "name": "Neptune Fuel Reserve" }, - { "id": 35079, "count": 1, "progression": true, "tech_type": "RocketStage3", "name": "Neptune Cockpit" }, - { "id": 35080, "count": 1, "progression": false, "tech_type": "BaseFiltrationMachine", "name": "Water Filtration Machine" } -] diff --git a/worlds/subnautica/locations.json b/worlds/subnautica/locations.json deleted file mode 100644 index f39e453e..00000000 --- a/worlds/subnautica/locations.json +++ /dev/null @@ -1,521 +0,0 @@ -[ - { "id": 33000, "position": { "x": -1234.3, "y": -349.7, "z": -396.0}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Blood Kelp Trench Wreck - Outside Databox" }, - - { "id": 33001, "position": { "x": -1208.0, "y": -349.6, "z": -383.0}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Blood Kelp Trench Wreck - Inside Databox" }, - - { "id": 33002, "position": { "x": -1210.6, "y": -340.7, "z": -393.4}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Blood Kelp Trench Wreck - PDA" }, - - { "id": 33003, "position": { "x": 903.8, "y": -220.3, "z": 590.9}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Bulb Zone West Wreck - Outside Databox" }, - - { "id": 33004, "position": { "x": 910.9, "y": -201.8, "z": 623.5}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Bulb Zone West Wreck - Under Databox" }, - - { "id": 33005, "position": { "x": 914.9, "y": -202.1, "z": 611.8}, - "need_laser_cutter": true, "can_slip_through": false, - "name": "Bulb Zone West Wreck - Inside Databox" }, - - { "id": 33006, "position": { "x": 912.6, "y": -202.0, "z": 609.5}, - "need_laser_cutter": true, "can_slip_through": false, - "name": "Bulb Zone West Wreck - PDA" }, - - { "id": 33007, "position": { "x": 1327.1, "y": -234.9, "z": 575.8}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Bulb Zone East Wreck - Databox" }, - - { "id": 33008, "position": { "x": -1407.7, "y": -344.2, "z": 721.5}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Dunes North Wreck - Outside Databox" }, - - { "id": 33009, "position": { "x": -1393.9, "y": -329.7, "z": 733.5}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Dunes North Wreck - Office Databox" }, - - { "id": 33010, "position": { "x": -1396.3, "y": -330.8, "z": 730.0}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Dunes North Wreck - PDA" }, - - { "id": 33011, "position": { "x": -1409.8, "y": -332.4, "z": 706.9}, - "need_laser_cutter": true, "can_slip_through": false, - "name": "Dunes North Wreck - Cargo Databox" }, - - { "id": 33012, "position": { "x": -1626.2, "y": -357.5, "z": 99.5}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Dunes West Wreck - Databox" }, - - { "id": 33013, "position": { "x": -1196.3, "y": -223.0, "z": 12.5}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Dunes East Wreck - Outside Databox" }, - - { "id": 33014, "position": { "x": -1206.4, "y": -225.6, "z": 4.0}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Dunes East Wreck - Inside Databox" }, - - { "id": 33015, "position": { "x": -269.7, "y": -262.8, "z": -764.3}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Grand Reef North Wreck - Outside Databox" }, - - { "id": 33016, "position": { "x": -285.8, "y": -240.2, "z": -786.5}, - "need_laser_cutter": true, "can_slip_through": false, - "name": "Grand Reef North Wreck - Elevator Databox" }, - - { "id": 33017, "position": { "x": -285.2, "y": -262.4, "z": -788.4}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Grand Reef North Wreck - Bottom Databox" }, - - { "id": 33018, "position": { "x": -272.5, "y": -254.7, "z": -788.5}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Grand Reef North Wreck - Hangar PDA" }, - - { "id": 33019, "position": { "x": -850.9, "y": -473.2, "z": -1414.6}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Grand Reef South Wreck - Trench Databox" }, - - { "id": 33020, "position": { "x": -889.4, "y": -433.8, "z": -1424.8}, - "need_laser_cutter": true, "can_slip_through": false, - "name": "Grand Reef South Wreck - Comms Databox" }, - - { "id": 33021, "position": { "x": -862.4, "y": -437.5, "z": -1444.1}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Grand Reef South Wreck - Outside Databox" }, - - { "id": 33022, "position": { "x": -887.9, "y": -446.0, "z": -1422.7}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Grand Reef South Wreck - PDA" }, - - { "id": 33023, "position": { "x": -23.3, "y": -105.8, "z": -604.2}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Grassy Plateaus South Wreck - Databox" }, - - { "id": 33024, "position": { "x": -27.3, "y": -106.8, "z": -607.2}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Grassy Plateaus South Wreck - PDA" }, - - { "id": 33025, "position": { "x": 313.9, "y": -91.8, "z": 432.6}, - "need_laser_cutter": true, "can_slip_through": true, - "name": "Grassy Plateaus East Wreck - Breach Databox" }, - - { "id": 33026, "position": { "x": 319.4, "y": -104.3, "z": 441.5}, - "need_laser_cutter": true, "can_slip_through": true, - "name": "Grassy Plateaus East Wreck - Hangar Databox" }, - - { "id": 33027, "position": { "x": -632.3, "y": -75.0, "z": -8.9}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Grassy Plateaus West Wreck - Locker PDA" }, - - { "id": 33028, "position": { "x": -664.4, "y": -97.8, "z": -8.0}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Grassy Plateaus West Wreck - Data Terminal" }, - - { "id": 33029, "position": { "x": -421.4, "y": -107.8, "z": -266.5}, - "need_laser_cutter": true, "can_slip_through": false, - "name": "Grassy Plateaus West Wreck - Databox" }, - - { "id": 33030, "position": { "x": -44.0, "y": -29.1, "z": -403.6}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Safe Shallows Wreck - PDA" }, - - { "id": 33031, "position": { "x": -317.1, "y": -79.0, "z": 248.5}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Kelp Forest Wreck - Databox" }, - - { "id": 33032, "position": { "x": 63.2, "y": -38.5, "z": 382.9}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Kelp Forest Wreck - PDA" }, - - { "id": 33033, "position": { "x": 740.3, "y": -389.2, "z": 1179.8}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Mountains West Wreck - Outside Databox" }, - - { "id": 33034, "position": { "x": 703.7, "y": -365.9, "z": 1199.3}, - "need_laser_cutter": true, "can_slip_through": false, - "name": "Mountains West Wreck - Data Terminal" }, - - { "id": 33035, "position": { "x": 698.2, "y": -350.8, "z": 1186.9}, - "need_laser_cutter": true, "can_slip_through": false, - "name": "Mountains West Wreck - Hangar Databox" }, - - { "id": 33036, "position": { "x": 676.3, "y": -343.6, "z": 1204.6}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Mountains West Wreck - Office Databox" }, - - { "id": 33037, "position": { "x": 1068.5, "y": -283.4, "z": 1345.3}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Mountains East Wreck - Comms Databox" }, - - { "id": 33038, "position": { "x": 1075.7, "y": -288.9, "z": 1321.8}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Mountains East Wreck - Outside Databox" }, - - { "id": 33039, "position": { "x": -655.1, "y": -109.6, "z": 791.0}, - "need_laser_cutter": true, "can_slip_through": false, - "name": "Northwestern Mushroom Forest Wreck - Cargo Databox" }, - - { "id": 33040, "position": { "x": -663.4, "y": -111.9, "z": 777.9}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Northwestern Mushroom Forest Wreck - Office Databox" }, - - { "id": 33041, "position": { "x": -662.2, "y": -113.4, "z": 777.7}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Northwestern Mushroom Forest Wreck - PDA" }, - - { "id": 33042, "position": { "x": -1161.1, "y": -191.7, "z": -758.3}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Sea Treader's Path Wreck - Outside Databox" }, - - { "id": 33043, "position": { "x": -1129.5, "y": -155.2, "z": -729.3}, - "need_laser_cutter": true, "can_slip_through": false, - "name": "Sea Treader's Path Wreck - Hangar Databox" }, - - { "id": 33044, "position": { "x": -1115.9, "y": -175.3, "z": -724.5}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Sea Treader's Path Wreck - Lobby Databox" }, - - { "id": 33045, "position": { "x": -1136.8, "y": -157.0, "z": -734.6}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Sea Treader's Path Wreck - PDA" }, - - { "id": 33046, "position": { "x": -789.8, "y": -216.1, "z": -711.0}, - "need_laser_cutter": true, "can_slip_through": false, - "name": "Sparse Reef Wreck - Locker Databox" }, - - { "id": 33047, "position": { "x": -810.7, "y": -209.3, "z": -685.5}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Sparse Reef Wreck - Outside Databox" }, - - { "id": 33048, "position": { "x": -795.5, "y": -204.1, "z": -774.7}, - "need_laser_cutter": true, "can_slip_through": false, - "name": "Sparse Reef Wreck - Lab Databox" }, - - { "id": 33049, "position": { "x": -170.8, "y": -187.6, "z": 880.7}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Underwater Islands Wreck - Outside Databox" }, - - { "id": 33050, "position": { "x": -138.4, "y": -193.6, "z": 888.7}, - "need_laser_cutter": true, "can_slip_through": false, - "name": "Underwater Islands Wreck - Hangar Databox" }, - - { "id": 33051, "position": { "x": -130.7, "y": -193.2, "z": 883.3}, - "need_laser_cutter": true, "can_slip_through": false, - "name": "Underwater Islands Wreck - Data Terminal" }, - - { "id": 33052, "position": { "x": -137.8, "y": -193.4, "z": 879.4}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Underwater Islands Wreck - Cable Databox" }, - - { "id": 33053, "position": { "x": -124.4, "y": -200.7, "z": 853.0}, - "need_laser_cutter": false, "can_slip_through": false, "need_propulsion_cannon": true, - "name": "Underwater Islands Wreck - Pipes Databox 1" }, - - { "id": 33054, "position": { "x": -126.8, "y": -201.1, "z": 852.1}, - "need_laser_cutter": false, "can_slip_through": false, "need_propulsion_cannon": true, - "name": "Underwater Islands Wreck - Pipes Databox 2" }, - - { "id": 33055, "position": { "x": -643.8, "y": -509.9, "z": -941.9}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Degasi Seabase - Deep Grand Reef - Bedroom Databox" }, - - { "id": 33056, "position": { "x": -635.1, "y": -502.7, "z": -951.4}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Degasi Seabase - Deep Grand Reef - Observatory Databox" }, - - { "id": 33057, "position": { "x": -645.8, "y": -508.7, "z": -943.0}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Degasi Seabase - Deep Grand Reef - Bedroom PDA" }, - - { "id": 33058, "position": { "x": -630.5, "y": -511.1, "z": -936.1}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Degasi Seabase - Deep Grand Reef - Outside PDA" }, - - { "id": 33059, "position": { "x": -647.7, "y": -502.6, "z": -935.8}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Degasi Seabase - Deep Grand Reef - Observatory PDA" }, - - { "id": 33060, "position": { "x": -639.6, "y": -505.9, "z": -946.6}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Degasi Seabase - Deep Grand Reef - Lab PDA" }, - - { "id": 33061, "position": { "x": -707.2, "y": 0.5, "z": -1096.7}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Floating Island - Lake PDA" }, - - { "id": 33062, "position": { "x": -765.7, "y": 17.6, "z": -1116.4}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Degasi Seabase - Floating Island - Databox" }, - - { "id": 33063, "position": { "x": -754.9, "y": 14.6, "z": -1108.9}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Degasi Seabase - Floating Island - Room PDA" }, - - { "id": 33064, "position": { "x": -765.3, "y": 14.1, "z": -1115.0}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Degasi Seabase - Floating Island - Green Wall PDA" }, - - { "id": 33065, "position": { "x": -758.6, "y": 14.1, "z": -1111.3}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Degasi Seabase - Floating Island - Corridor PDA" }, - - { "id": 33066, "position": { "x": -805.4, "y": 76.9, "z": -1055.7}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Degasi Seabase - Floating Island - North Observatory PDA" }, - - { "id": 33067, "position": { "x": -715.9, "y": 75.4, "z": -1168.8}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Degasi Seabase - Floating Island - South Observatory PDA" }, - - { "id": 33068, "position": { "x": -540.5, "y": -250.8, "z": -83.4}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Jellyshroom Cave - PDA" }, - - { "id": 33069, "position": { "x": 110.6, "y": -264.9, "z": -369.0}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Degasi Seabase - Jellyshroom Cave - Bedroom Databox" }, - - { "id": 33070, "position": { "x": 80.6, "y": -268.6, "z": -358.3}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Degasi Seabase - Jellyshroom Cave - Detached PDA" }, - - { "id": 33071, "position": { "x": 78.2, "y": -265.0, "z": -373.4}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Degasi Seabase - Jellyshroom Cave - Office PDA" }, - - { "id": 33072, "position": { "x": 85.1, "y": -264.1, "z": -372.8}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Degasi Seabase - Jellyshroom Cave - Locker PDA" }, - - { "id": 33073, "position": { "x": 112.3, "y": -264.9, "z": -369.3}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Degasi Seabase - Jellyshroom Cave - Bedroom PDA" }, - - { "id": 33074, "position": { "x": 95.5, "y": -258.9, "z": -366.5}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Degasi Seabase - Jellyshroom Cave - Observatory PDA" }, - - { "id": 33075, "position": { "x": -483.6, "y": -504.7, "z": 1326.6}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Lifepod 2 - Databox" }, - - { "id": 33076, "position": { "x": -481.4, "y": -503.6, "z": 1324.1}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Lifepod 2 - PDA" }, - - { "id": 33077, "position": { "x": -34.2, "y": -22.4, "z": 410.5}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Lifepod 3 - Databox" }, - - { "id": 33078, "position": { "x": -33.8, "y": -22.5, "z": 408.8}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Lifepod 3 - PDA" }, - - { "id": 33079, "position": { "x": 712.4, "y": -3.4, "z": 160.8}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Lifepod 4 - Databox" }, - - { "id": 33080, "position": { "x": 712.0, "y": -3.5, "z": 161.5}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Lifepod 4 - PDA" }, - - { "id": 33081, "position": { "x": 358.7, "y": -117.1, "z": 306.8}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Lifepod 6 - Databox" }, - - { "id": 33082, "position": { "x": 361.8, "y": -116.2, "z": 309.5}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Lifepod 6 - Inside PDA" }, - - { "id": 33083, "position": { "x": 359.9, "y": -117.0, "z": 312.1}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Lifepod 6 - Outside PDA" }, - - { "id": 33084, "position": { "x": -56.0, "y": -182.0, "z": -1039.0}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Lifepod 7 - PDA" }, - - { "id": 33085, "position": { "x": 1119.5, "y": -271.7, "z": 561.7}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Lifepod 12 - Databox" }, - - { "id": 33086, "position": { "x": 1116.1, "y": -271.3, "z": 566.9}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Lifepod 12 - PDA" }, - - { "id": 33087, "position": { "x": -926.4, "y": -185.2, "z": 501.8}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Lifepod 13 - Databox" }, - - { "id": 33088, "position": { "x": -926.8, "y": -184.4, "z": 506.6}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Lifepod 13 - PDA" }, - - { "id": 33089, "position": { "x": -514.5, "y": -98.1, "z": -56.5}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Lifepod 17 - PDA" }, - - { "id": 33090, "position": { "x": -809.8, "y": -302.2, "z": -876.9}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Lifepod 19 - Databox" }, - - { "id": 33091, "position": { "x": -806.1, "y": -294.1, "z": -866.0}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Lifepod 19 - Outside PDA" }, - - { "id": 33092, "position": { "x": -810.5, "y": -299.4, "z": -873.1}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Lifepod 19 - Inside PDA" }, - - { "id": 33093, "position": { "x": 903.5, "y": -0.2, "z": 16.1}, - "need_laser_cutter": false, "can_slip_through": false, "need_propulsion_cannon": true, - "name": "Aurora Seamoth Bay - Upgrade Console" }, - - { "id": 33094, "position": { "x": 872.5, "y": 2.7, "z": -0.7}, - "need_laser_cutter": false, "can_slip_through": false, "need_propulsion_cannon": true, - "name": "Aurora Drive Room - Upgrade Console" }, - - { "id": 33095, "position": { "x": 991.6, "y": 3.2, "z": -31.0}, - "need_laser_cutter": true, "can_slip_through": false, "need_propulsion_cannon": true, - "name": "Aurora Prawn Suit Bay - Upgrade Console" }, - - { "id": 33096, "position": { "x": 952.1, "y": 41.2, "z": 113.9}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Aurora - Office PDA" }, - - { "id": 33097, "position": { "x": 977.2, "y": 39.1, "z": 83.0}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Aurora - Corridor PDA" }, - - { "id": 33098, "position": { "x": 954.9, "y": 11.2, "z": 3.4}, - "need_laser_cutter": false, "can_slip_through": false, "need_propulsion_cannon": true, - "name": "Aurora - Cargo Bay PDA" }, - - { "id": 33099, "position": { "x": 907.1, "y": -1.5, "z": 15.3}, - "need_laser_cutter": false, "can_slip_through": false, "need_propulsion_cannon": true, - "name": "Aurora - Seamoth Bay PDA" }, - - { "id": 33100, "position": { "x": 951.8, "y": -2.3, "z": -34.7}, - "need_laser_cutter": true, "can_slip_through": false, "need_propulsion_cannon": true, - "name": "Aurora - Medkit Locker PDA" }, - - { "id": 33101, "position": { "x": 952.0, "y": -3.7, "z": -23.4}, - "need_laser_cutter": true, "can_slip_through": false, "need_propulsion_cannon": true, - "name": "Aurora - Locker PDA" }, - - { "id": 33102, "position": { "x": 986.5, "y": 9.6, "z": -48.6}, - "need_laser_cutter": true, "can_slip_through": false, "need_propulsion_cannon": true, - "name": "Aurora - Canteen PDA" }, - - { "id": 33103, "position": { "x": 951.3, "y": 11.2, "z": -51.0}, - "need_laser_cutter": true, "can_slip_through": false, "need_propulsion_cannon": true, - "name": "Aurora - Cabin 4 PDA" }, - - { "id": 33104, "position": { "x": 967.1, "y": 10.4, "z": -47.4}, - "need_laser_cutter": true, "can_slip_through": false, "need_propulsion_cannon": true, - "name": "Aurora - Cabin 7 PDA" }, - - { "id": 33105, "position": { "x": 964.1, "y": 11.1, "z": -61.9}, - "need_laser_cutter": true, "can_slip_through": false, "need_propulsion_cannon": true, - "name": "Aurora - Cabin 1 PDA" }, - - { "id": 33106, "position": { "x": 971.2, "y": 10.8, "z": -70.4}, - "need_laser_cutter": true, "can_slip_through": false, "need_propulsion_cannon": true, - "name": "Aurora - Captain PDA" }, - - { "id": 33107, "position": { "x": 1033.6, "y": -8.5, "z": 16.2}, - "need_laser_cutter": false, "can_slip_through": false, "need_propulsion_cannon": true, - "name": "Aurora - Ring PDA" }, - - { "id": 33108, "position": { "x": 1032.5, "y": -7.8, "z": 32.4}, - "need_laser_cutter": false, "can_slip_through": false, "need_propulsion_cannon": true, - "name": "Aurora - Lab PDA" }, - - { "id": 33109, "position": { "x": 945.8, "y": 40.8, "z": 115.1}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Aurora - Office Data Terminal" }, - - { "id": 33110, "position": { "x": 974.8, "y": 10.0, "z": -77.0}, - "need_laser_cutter": true, "can_slip_through": false, "need_propulsion_cannon": true, - "name": "Aurora - Captain Data Terminal" }, - - { "id": 33111, "position": { "x": 1040.8, "y": -11.4, "z": -3.4}, - "need_laser_cutter": true, "can_slip_through": false, "need_propulsion_cannon": true, - "name": "Aurora - Battery Room Data Terminal" }, - - { "id": 33112, "position": { "x": 1029.5, "y": -8.7, "z": 35.9}, - "need_laser_cutter": false, "can_slip_through": false, "need_propulsion_cannon": true, - "name": "Aurora - Lab Data Terminal" }, - - { "id": 33113, "position": { "x": 432.2, "y": 3.0, "z": 1193.2}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Quarantine Enforcement Platform's - Upper Alien Data Terminal" }, - - { "id": 33114, "position": { "x": 474.4, "y": -4.5, "z": 1224.4}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Quarantine Enforcement Platform's - Mid Alien Data Terminal" }, - - { "id": 33115, "position": { "x": -1224.2, "y": -400.4, "z": 1057.9}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Dunes Sanctuary - Alien Data Terminal" }, - - { "id": 33116, "position": { "x": -895.5, "y": -311.6, "z": -838.1}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Deep Sparse Reef Sanctuary - Alien Data Terminal" }, - - { "id": 33117, "position": { "x": -642.9, "y": -563.5, "z": 1485.5}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Northern Blood Kelp Zone Sanctuary - Alien Data Terminal" }, - - { "id": 33118, "position": { "x": -1112.3, "y": -687.3, "z": -695.5}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Lost River Laboratory Cache - Alien Data Terminal" }, - - { "id": 33119, "position": { "x": -280.2, "y": -804.3, "z": 305.1}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Disease Research Facility - Upper Alien Data Terminal" }, - - { "id": 33120, "position": { "x": -267.9, "y": -806.6, "z": 250.0}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Disease Research Facility - Mid Alien Data Terminal" }, - - { "id": 33121, "position": { "x": -286.2, "y": -815.6, "z": 297.8}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Disease Research Facility - Lower Alien Data Terminal" }, - - { "id": 33122, "position": { "x": -71.3, "y": -1227.2, "z": 104.8}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Alien Thermal Plant - Entrance Alien Data Terminal" }, - - { "id": 33123, "position": { "x": -38.7, "y": -1226.6, "z": 111.8}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Alien Thermal Plant - Green Alien Data Terminal" }, - - { "id": 33124, "position": { "x": -30.4, "y": -1220.3, "z": 111.8}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Alien Thermal Plant - Yellow Alien Data Terminal" }, - - { "id": 33125, "position": { "x": 245.8, "y": -1430.6, "z": -311.5}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Primary Containment Facility's Antechamber - Alien Data Terminal" }, - - { "id": 33126, "position": { "x": 165.5, "y": -1442.4, "z": -385.8}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Primary Containment Facility's Egg Laboratory - Alien Data Terminal" }, - - { "id": 33127, "position": { "x": 348.7, "y": -1443.5, "z": -291.9}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Primary Containment Facility's Pipe Room - Alien Data Terminal" }, - - { "id": 33128, "position": { "x": -641.8, "y": -111.3, "z": -19.7}, - "need_laser_cutter": true, "can_slip_through": false, - "name": "Grassy Plateaus West Wreck - Beam PDA" }, - - { "id": 33129, "position": { "x": -748.9, "y": 14.4, "z": -1179.5}, - "need_laser_cutter": false, "can_slip_through": false, - "name": "Floating Island - Cave Entrance PDA" } -]