Beispiel #1
0
 def create_from_dock(cls, dock: DockNode) -> DockLockNode:
     lock_identifier = dock.get_lock_node_identifier_from_identifier(dock.identifier)
     return DockLockNode(
         identifier=lock_identifier,
         heal=False,
         location=None,
         description="",
         layers=dock.layers,
         extra={},
         dock_identifier=dock.identifier,
     )
Beispiel #2
0
def test_connections_from_dock_blast_shield(empty_patches):
    # Setup
    trivial = Requirement.trivial()
    req_1 = ResourceRequirement.simple(
        SimpleResourceInfo(0, "Ev1", "Ev1", ResourceType.EVENT))
    req_2 = ResourceRequirement.simple(
        SimpleResourceInfo(1, "Ev2", "Ev2", ResourceType.EVENT))
    dock_type = DockType("Type", "Type", frozendict())
    weak_1 = DockWeakness(0, "Weak 1", frozendict(), req_1, None)
    weak_2 = DockWeakness(1, "Weak 2", frozendict(), trivial,
                          DockLock(DockLockType.FRONT_BLAST_BACK_BLAST, req_2))

    node_1_identifier = NodeIdentifier.create("W", "Area 1", "Node 1")
    node_2_identifier = NodeIdentifier.create("W", "Area 2", "Node 2")

    node_1 = DockNode(node_1_identifier, 0, False, None, "", ("default", ), {},
                      dock_type, node_2_identifier, weak_1, None, None)
    node_1_lock = DockLockNode.create_from_dock(node_1, 1)
    node_2 = DockNode(node_2_identifier, 2, False, None, "", ("default", ), {},
                      dock_type, node_1_identifier, weak_2, None, None)
    node_2_lock = DockLockNode.create_from_dock(node_2, 3)

    area_1 = Area("Area 1", None, True, [node_1, node_1_lock], {}, {})
    area_2 = Area("Area 2", None, True, [node_2, node_2_lock], {}, {})

    world = World("W", [area_1, area_2], {})
    world_list = WorldList([world])
    world_list.ensure_has_node_cache()

    game_mock = MagicMock()
    game_mock.world_list = world_list
    patches = dataclasses.replace(empty_patches, game=game_mock)

    context = NodeContext(
        patches=patches,
        current_resources=ResourceCollection(),
        database=patches.game.resource_database,
        node_provider=world_list,
    )

    # Run
    result_1 = list(node_1.connections_from(context))
    result_2 = list(node_2.connections_from(context))

    # Assert
    simple = ResourceRequirement.simple

    assert result_1 == [
        (node_2,
         RequirementAnd(
             [req_1,
              simple(NodeResourceInfo.from_node(node_2, context))])),
        (node_1_lock, RequirementAnd([trivial, req_2])),
    ]
    assert result_2 == [
        (node_1, simple(NodeResourceInfo.from_node(node_2, context))),
        (node_2_lock, req_2),
    ]
Beispiel #3
0
def test_connections_from_dock_blast_shield(empty_patches):
    # Setup
    trivial = Requirement.trivial()
    req_1 = ResourceRequirement(
        SimpleResourceInfo("Ev1", "Ev1", ResourceType.EVENT), 1, False)
    req_2 = ResourceRequirement(
        SimpleResourceInfo("Ev2", "Ev2", ResourceType.EVENT), 1, False)
    dock_type = DockType("Type", "Type", frozendict())
    weak_1 = DockWeakness("Weak 1", frozendict(), req_1, None)
    weak_2 = DockWeakness("Weak 2", frozendict(), trivial,
                          DockLock(DockLockType.FRONT_BLAST_BACK_BLAST, req_2))

    node_1_identifier = NodeIdentifier.create("W", "Area 1", "Node 1")
    node_2_identifier = NodeIdentifier.create("W", "Area 2", "Node 2")

    node_1 = DockNode(node_1_identifier, False, None, "", ("default", ), {},
                      dock_type, node_2_identifier, weak_1, None, None)
    node_1_lock = DockLockNode.create_from_dock(node_1)
    node_2 = DockNode(node_2_identifier, False, None, "", ("default", ), {},
                      dock_type, node_1_identifier, weak_2, None, None)
    node_2_lock = DockLockNode.create_from_dock(node_2)

    area_1 = Area("Area 1", None, True, [node_1, node_1_lock], {}, {})
    area_2 = Area("Area 2", None, True, [node_2, node_2_lock], {}, {})

    world = World("W", [area_1, area_2], {})
    world_list = WorldList([world])

    context = NodeContext(
        patches=empty_patches,
        current_resources={},
        database=None,
        node_provider=world_list,
    )

    # Run
    result_1 = list(node_1.connections_from(context))
    result_2 = list(node_2.connections_from(context))

    # Assert
    assert result_1 == [
        (node_2,
         RequirementAnd([req_1,
                         ResourceRequirement.simple(node_2_identifier)])),
        (node_1_lock, RequirementAnd([trivial, req_2])),
    ]
    assert result_2 == [
        (node_1, ResourceRequirement.simple(node_2_identifier)),
        (node_2_lock, req_2),
    ]
Beispiel #4
0
    def read_node(self, name: str, data: Dict) -> Node:
        try:
            location = None
            if data["coordinates"] is not None:
                location = location_from_json(data["coordinates"])

            generic_args = {
                "identifier":
                NodeIdentifier.create(self.current_world_name,
                                      self.current_area_name, name),
                "heal":
                data["heal"],
                "location":
                location,
                "description":
                data["description"],
                "layers":
                tuple(data["layers"]),
                "extra":
                frozen_lib.wrap(data["extra"]),
            }
            node_type: int = data["node_type"]

            if node_type == "generic":
                return GenericNode(**generic_args)

            elif node_type == "dock":
                return DockNode(
                    **generic_args,
                    dock_type=self.dock_weakness_database.find_type(
                        data["dock_type"]),
                    default_connection=NodeIdentifier.from_json(
                        data["default_connection"]),
                    default_dock_weakness=self.dock_weakness_database.
                    get_by_weakness(
                        data["dock_type"],
                        data["default_dock_weakness"],
                    ),
                    override_default_open_requirement=read_optional_requirement(
                        data["override_default_open_requirement"],
                        self.resource_database),
                    override_default_lock_requirement=read_optional_requirement(
                        data["override_default_lock_requirement"],
                        self.resource_database),
                )

            elif node_type == "pickup":
                return PickupNode(
                    **generic_args,
                    pickup_index=PickupIndex(data["pickup_index"]),
                    major_location=data["major_location"],
                )

            elif node_type == "teleporter":
                return TeleporterNode(
                    **generic_args,
                    default_connection=AreaIdentifier.from_json(
                        data["destination"]),
                    keep_name_when_vanilla=data["keep_name_when_vanilla"],
                    editable=data["editable"],
                )

            elif node_type == "event":
                return EventNode(
                    **generic_args,
                    event=self.resource_database.get_by_type_and_index(
                        ResourceType.EVENT, data["event_name"]))

            elif node_type == "configurable_node":
                return ConfigurableNode(**generic_args, )

            elif node_type == "logbook":
                lore_type = LoreType(data["lore_type"])

                if lore_type == LoreType.REQUIRES_ITEM:
                    required_translator = self.resource_database.get_item(
                        data["extra"]["translator"])
                else:
                    required_translator = None

                if lore_type in {
                        LoreType.SPECIFIC_PICKUP, LoreType.SKY_TEMPLE_KEY_HINT
                }:
                    hint_index = data["extra"]["hint_index"]
                else:
                    hint_index = None

                return LogbookNode(
                    **generic_args,
                    string_asset_id=data["string_asset_id"],
                    scan_visor=self._get_scan_visor(),
                    lore_type=lore_type,
                    required_translator=required_translator,
                    hint_index=hint_index,
                )

            elif node_type == "player_ship":
                return PlayerShipNode(
                    **generic_args,
                    is_unlocked=read_requirement(data["is_unlocked"],
                                                 self.resource_database),
                    item_to_summon=self._get_command_visor(),
                )

            else:
                raise Exception(f"Unknown type: {node_type}")

        except Exception as e:
            raise Exception(f"In node {name}, got error: {e}")
Beispiel #5
0
    def create_new_node(self) -> Node:
        node_type = self.node_type_combo.currentData()
        identifier = dataclasses.replace(self.node.identifier, node_name=self.name_edit.text())
        heal = self.heals_check.isChecked()
        location = None
        if self.location_group.isChecked():
            location = NodeLocation(self.location_x_spin.value(),
                                    self.location_y_spin.value(),
                                    self.location_z_spin.value())
        description = self.description_edit.toMarkdown()
        extra = json.loads(self.extra_edit.toPlainText())
        layers = (self.layers_combo.currentText(),)

        if node_type == GenericNode:
            return GenericNode(identifier, heal, location, description, layers, extra)

        elif node_type == DockNode:
            connection_node: Node = self.dock_connection_node_combo.currentData()

            return DockNode(
                identifier, heal, location, description, layers, extra,
                self.dock_type_combo.currentData(),
                self.game.world_list.identifier_for_node(connection_node),
                self.dock_weakness_combo.currentData(),
                None, None,
            )

        elif node_type == PickupNode:
            return PickupNode(
                identifier, heal, location, description, layers, extra,
                PickupIndex(self.pickup_index_spin.value()),
                self.major_location_check.isChecked(),
            )

        elif node_type == TeleporterNode:
            dest_world: World = self.teleporter_destination_world_combo.currentData()
            dest_area: Area = self.teleporter_destination_area_combo.currentData()

            return TeleporterNode(
                identifier, heal, location, description, layers, extra,
                AreaIdentifier(
                    world_name=dest_world.name,
                    area_name=dest_area.name,
                ),
                self.teleporter_vanilla_name_edit.isChecked(),
                self.teleporter_editable_check.isChecked(),
            )

        elif node_type == EventNode:
            event = self.event_resource_combo.currentData()
            if event is None:
                raise ValueError("There are no events in the database, unable to create EventNode.")
            return EventNode(
                identifier, heal, location, description, layers, extra,
                event,
            )

        elif node_type == ConfigurableNode:
            return ConfigurableNode(
                identifier, heal, location, description, layers, extra,
            )

        elif node_type == LogbookNode:
            lore_type: LoreType = self.lore_type_combo.currentData()
            if lore_type == LoreType.REQUIRES_ITEM:
                required_translator = self.logbook_extra_combo.currentData()
                if required_translator is None:
                    raise ValueError("Missing required translator.")
            else:
                required_translator = None

            if lore_type == LoreType.SPECIFIC_PICKUP:
                hint_index = self.logbook_extra_combo.currentData()
            else:
                hint_index = None

            return LogbookNode(
                identifier, heal, location, description, layers, extra,
                int(self.logbook_string_asset_id_edit.text(), 0),
                self._get_scan_visor(),
                lore_type,
                required_translator,
                hint_index
            )

        elif node_type == PlayerShipNode:
            return PlayerShipNode(
                identifier, heal, location, description, layers, extra,
                self._unlocked_by_requirement,
                self._get_command_visor()
            )

        else:
            raise RuntimeError(f"Unknown node type: {node_type}")
Beispiel #6
0
    def _create_new_dock(self, location: NodeLocation, target_area: Area):
        current_area = self.current_area
        target_identifier = self.world_list.identifier_for_area(target_area)
        source_identifier = self.world_list.identifier_for_area(current_area)

        dock_weakness = self.game_description.dock_weakness_database.default_weakness
        source_name_base = integrity_check.base_dock_name_raw(
            dock_weakness[0], dock_weakness[1], target_identifier)
        target_name_base = integrity_check.base_dock_name_raw(
            dock_weakness[0], dock_weakness[1], source_identifier)

        source_count = len(
            integrity_check.docks_with_same_base_name(current_area,
                                                      source_name_base))
        if source_count != len(
                integrity_check.docks_with_same_base_name(
                    target_area, target_name_base)):
            raise ValueError(
                f"Expected {target_area.name} to also have {source_count} "
                f"docks with name {target_name_base}")

        if source_count > 0:
            source_name = f"{source_name_base} ({source_count + 1})"
            target_name = f"{target_name_base} ({source_count + 1})"
        else:
            source_name = source_name_base
            target_name = target_name_base

        new_node_this_area_identifier = NodeIdentifier(
            self.world_list.identifier_for_area(current_area), source_name)
        new_node_other_area_identifier = NodeIdentifier(
            self.world_list.identifier_for_area(target_area), target_name)

        new_node_this_area = DockNode(
            identifier=new_node_this_area_identifier,
            node_index=self.editor.new_node_index(),
            heal=False,
            location=location,
            description="",
            layers=("default", ),
            extra={},
            dock_type=dock_weakness[0],
            default_connection=new_node_other_area_identifier,
            default_dock_weakness=dock_weakness[1],
            override_default_open_requirement=None,
            override_default_lock_requirement=None,
        )

        new_node_other_area = DockNode(
            identifier=new_node_other_area_identifier,
            node_index=self.editor.new_node_index(),
            heal=False,
            location=location,
            description="",
            layers=("default", ),
            extra={},
            dock_type=dock_weakness[0],
            default_connection=new_node_this_area_identifier,
            default_dock_weakness=dock_weakness[1],
            override_default_open_requirement=None,
            override_default_lock_requirement=None,
        )

        self.editor.add_node(current_area, new_node_this_area)
        self.editor.add_node(target_area, new_node_other_area)
        if source_count == 1:
            self.editor.rename_node(
                current_area,
                current_area.node_with_name(source_name_base),
                f"{source_name_base} (1)",
            )
            self.editor.rename_node(
                target_area,
                target_area.node_with_name(target_name_base),
                f"{target_name_base} (1)",
            )
        self.on_select_area(new_node_this_area)