def _setup(skip_qtbot):
    parent = QtWidgets.QWidget()
    skip_qtbot.addWidget(parent)
    tool = QtWidgets.QToolButton(parent)
    label = QtWidgets.QLabel(parent)

    result = GameConnectionSetup(parent, label,
                                 GameConnection(DolphinExecutor()),
                                 MagicMock())
    result.setup_tool_button_menu(tool)

    return result
    def __init__(self, game_connection: GameConnection, options: Options):
        super().__init__()
        self.setupUi(self)
        self.game_connection = game_connection
        self.options = options
        common_qt_lib.set_default_window_icon(self)

        self._action_to_theme = {
            self.action_theme_2d_style: TrackerTheme.CLASSIC,
            self.action_theme_game_icons: TrackerTheme.GAME,
        }

        theme_group = QActionGroup(self)
        for action, theme in self._action_to_theme.items():
            theme_group.addAction(action)
            action.setChecked(theme == options.tracker_theme)
            action.triggered.connect(self._on_action_theme)

        self._tracker_elements: List[Element] = []
        self.create_tracker(RandovaniaGame.PRIME2)

        self.game_connection_setup = GameConnectionSetup(
            self, self.game_connection_tool, self.connection_status_label,
            self.game_connection, options)
        self.force_update_button.clicked.connect(self.on_force_update_button)

        self._update_timer = QTimer(self)
        self._update_timer.setInterval(100)
        self._update_timer.timeout.connect(self._on_timer_update)
        self._update_timer.setSingleShot(True)
Example #3
0
def _setup(skip_qtbot):
    parent = QtWidgets.QWidget()
    skip_qtbot.addWidget(parent)
    tool = QtWidgets.QToolButton(parent)
    label = QtWidgets.QLabel(parent)

    return GameConnectionSetup(parent, tool, label, GameConnection(DolphinBackend()), MagicMock())
Example #4
0
    def __init__(self, game_connection: GameConnection, options: Options):
        super().__init__()
        self.setupUi(self)
        self.game_connection = game_connection
        common_qt_lib.set_default_window_icon(self)

        self.game_data = data_reader.decode_data(
            default_data.decode_default_prime2())
        self._energy_tank_item = find_resource_info_with_long_name(
            self.game_data.resource_database.item, "Energy Tank")

        self._item_to_label: Dict[ItemResourceInfo, ClickableLabel] = {}
        self._labels_for_keys = []
        self.create_tracker()

        self.game_connection_setup = GameConnectionSetup(
            self, self.game_connection_tool, self.connection_status_label,
            self.game_connection, options)
        self.force_update_button.setEnabled(not options.tracking_inventory)
        self.force_update_button.clicked.connect(self.on_force_update_button)

        self._update_timer = QTimer(self)
        self._update_timer.setInterval(100)
        self._update_timer.timeout.connect(self._on_timer_update)
        self._update_timer.setSingleShot(True)
    def __init__(self, game_connection: GameConnection, options: Options):
        super().__init__()
        self.setupUi(self)
        self.game_connection = game_connection
        self.options = options
        common_qt_lib.set_default_window_icon(self)

        with get_data_path().joinpath(f"gui_assets/tracker/trackers.json"
                                      ).open("r") as trackers_file:
            self.trackers = json.load(trackers_file)["trackers"]

        self._action_to_name = {}
        theme_group = QtGui.QActionGroup(self)
        for name in self.trackers.keys():
            action = QtGui.QAction(self.menu_tracker)
            action.setText(name)
            action.setCheckable(True)
            action.setChecked(name == options.selected_tracker)
            action.triggered.connect(self._on_action_select_tracker)
            self.menu_tracker.addAction(action)
            self._action_to_name[action] = name
            theme_group.addAction(action)

        self._tracker_elements: List[Element] = []
        self.create_tracker()

        self.game_connection_setup = GameConnectionSetup(
            self, self.connection_status_label, self.game_connection, options)
        self.game_connection_setup.create_backend_entries(self.menu_backend)
        self.game_connection_setup.create_upload_nintendont_action(
            self.menu_options)
        self.game_connection_setup.refresh_backend()

        self.action_force_update.triggered.connect(self.on_force_update_button)

        self._update_timer = QtCore.QTimer(self)
        self._update_timer.setInterval(100)
        self._update_timer.timeout.connect(self._on_timer_update)
        self._update_timer.setSingleShot(True)
Example #6
0
    def __init__(self, game_connection: GameConnection, options: Options):
        super().__init__()
        self.setupUi(self)
        self.game_connection = game_connection
        common_qt_lib.set_default_window_icon(self)

        self._tracker_elements: List[Element] = []
        self.create_tracker()

        self.game_connection_setup = GameConnectionSetup(self, self.game_connection_tool, self.connection_status_label,
                                                         self.game_connection, options)
        self.force_update_button.clicked.connect(self.on_force_update_button)

        self._update_timer = QTimer(self)
        self._update_timer.setInterval(100)
        self._update_timer.timeout.connect(self._on_timer_update)
        self._update_timer.setSingleShot(True)
class AutoTrackerWindow(QtWidgets.QMainWindow, Ui_AutoTrackerWindow):
    _hooked = False
    _base_address: int
    trackers: Dict[str, str]
    _current_tracker_game: RandovaniaGame = None
    _current_tracker_name: str = None
    give_item_signal = QtCore.Signal(PickupEntry)

    def __init__(self, game_connection: GameConnection, options: Options):
        super().__init__()
        self.setupUi(self)
        self.game_connection = game_connection
        self.options = options
        common_qt_lib.set_default_window_icon(self)

        with get_data_path().joinpath(f"gui_assets/tracker/trackers.json"
                                      ).open("r") as trackers_file:
            self.trackers = json.load(trackers_file)["trackers"]

        self._action_to_name = {}
        theme_group = QtGui.QActionGroup(self)
        for name in self.trackers.keys():
            action = QtGui.QAction(self.menu_tracker)
            action.setText(name)
            action.setCheckable(True)
            action.setChecked(name == options.selected_tracker)
            action.triggered.connect(self._on_action_select_tracker)
            self.menu_tracker.addAction(action)
            self._action_to_name[action] = name
            theme_group.addAction(action)

        self._tracker_elements: List[Element] = []
        self.create_tracker()

        self.game_connection_setup = GameConnectionSetup(
            self, self.connection_status_label, self.game_connection, options)
        self.game_connection_setup.create_backend_entries(self.menu_backend)
        self.game_connection_setup.create_upload_nintendont_action(
            self.menu_options)
        self.game_connection_setup.refresh_backend()

        self.action_force_update.triggered.connect(self.on_force_update_button)

        self._update_timer = QtCore.QTimer(self)
        self._update_timer.setInterval(100)
        self._update_timer.timeout.connect(self._on_timer_update)
        self._update_timer.setSingleShot(True)

    def showEvent(self, event: QtGui.QShowEvent):
        self._update_timer.start()
        super().showEvent(event)

    def hideEvent(self, event: QtGui.QHideEvent):
        self._update_timer.stop()
        super().hideEvent(event)

    @property
    def selected_tracker(self) -> Optional[str]:
        for action, name in self._action_to_name.items():
            if action.isChecked():
                return name

    def _update_tracker_from_hook(self, inventory: Dict[ItemResourceInfo,
                                                        InventoryItem]):
        for element in self._tracker_elements:
            if len(element.labels) > 1:
                satisfied = False
                for i, resource in reversed(list(enumerate(
                        element.resources))):
                    current = inventory.get(resource, InventoryItem(0, 0))
                    fields = {
                        "amount": current.amount,
                        "capacity": current.capacity,
                        "max_capacity": resource.max_capacity
                    }

                    if satisfied:
                        element.labels[i].setVisible(False)

                    elif fields[element.field_to_check.
                                value] >= element.minimum_to_check:
                        # This tier is satisfied
                        satisfied = True
                        element.labels[i].setVisible(True)
                        element.labels[i].set_checked(True)
                    else:
                        element.labels[i].setVisible(False)

                if not satisfied:
                    element.labels[0].setVisible(True)
                    element.labels[0].set_checked(False)

            else:
                label = element.labels[0]

                amount = 0
                capacity = 0
                max_capacity = 0
                for resource in element.resources:
                    current = inventory.get(resource, InventoryItem(0, 0))
                    amount += current.amount
                    capacity += current.capacity
                    max_capacity += resource.max_capacity

                if isinstance(label, ClickableLabel):
                    fields = {
                        "amount": amount,
                        "capacity": capacity,
                        "max_capacity": max_capacity
                    }
                    value_target = element.minimum_to_check
                    value = fields[element.field_to_check.value]
                    label.set_checked(max_capacity == 0
                                      or value >= value_target)
                else:
                    label.setText(
                        element.text_template.format(
                            amount=amount,
                            capacity=capacity,
                            max_capacity=max_capacity,
                        ))

    def _on_action_select_tracker(self):
        with self.options as options:
            options.selected_tracker = self.selected_tracker
        self.create_tracker()

    @asyncSlot()
    async def _on_timer_update(self):
        await self._on_timer_update_raw()

    async def _on_timer_update_raw(self):
        try:
            current_status = self.game_connection.current_status
            if current_status not in {
                    GameConnectionStatus.Disconnected,
                    GameConnectionStatus.UnknownGame,
                    GameConnectionStatus.WrongGame
            }:
                self.action_force_update.setEnabled(True)
            else:
                self.action_force_update.setEnabled(False)

            if current_status == GameConnectionStatus.InGame or current_status == GameConnectionStatus.TrackerOnly:
                if self.game_connection.connector.game_enum == self._current_tracker_game:
                    inventory = self.game_connection.get_current_inventory()
                    self._update_tracker_from_hook(inventory)
                    self.game_connection_setup.on_game_connection_updated()
                else:
                    self.connection_status_label.setText(
                        "{}: Wrong Game ({})".format(
                            self.game_connection.backend_choice.pretty_text,
                            self.game_connection.current_game_name,
                        ))
        finally:
            self._update_timer.start()

    def delete_tracker(self):
        for element in self._tracker_elements:
            for l in element.labels:
                l.deleteLater()

        self._tracker_elements.clear()

    def create_tracker(self):
        tracker_name = self.selected_tracker
        if tracker_name == self._current_tracker_name or tracker_name is None:
            return

        self.delete_tracker()

        with path_for(
                self.trackers[tracker_name]).open("r") as tracker_details_file:
            tracker_details = json.load(tracker_details_file)

        game_enum = RandovaniaGame(tracker_details["game"])
        resource_database = default_database.resource_database_for(game_enum)

        for element in tracker_details["elements"]:
            text_template = ""
            minimum_to_check = element.get("minimum_to_check", 1)
            field_to_check = FieldToCheck(
                element.get("field_to_check", FieldToCheck.CAPACITY.value))

            labels = []
            if "image_path" in element:
                paths = element["image_path"]
                if not isinstance(paths, list):
                    paths = [paths]

                visible = True
                for path in paths:
                    image_path = get_data_path().joinpath(path)
                    if not image_path.exists():
                        logging.error("Tracker asset not found: %s",
                                      image_path)
                    pixmap = QtGui.QPixmap(str(image_path))

                    label = ClickableLabel(self.inventory_group,
                                           paint_with_opacity(pixmap, 0.3),
                                           paint_with_opacity(pixmap, 1.0))
                    label.set_checked(False)
                    label.set_ignore_mouse_events(True)
                    label.setVisible(visible)
                    visible = False
                    labels.append(label)

            elif "label" in element:
                label = QtWidgets.QLabel(self.inventory_group)
                label.setAlignment(QtCore.Qt.AlignCenter)
                text_template = element["label"]
                labels.append(label)

            else:
                raise ValueError(f"Invalid element: {element}")

            resources = [
                find_resource_info_with_long_name(resource_database.item,
                                                  resource_name)
                for resource_name in element["resources"]
            ]
            for resource, label in zip(resources, labels):
                label.setToolTip(resource.long_name)

            self._tracker_elements.append(
                Element(labels, resources, text_template, minimum_to_check,
                        field_to_check))
            for label in labels:
                self.inventory_layout.addWidget(label, element["row"],
                                                element["column"])

        self.inventory_spacer = QtWidgets.QSpacerItem(
            5, 5, QtWidgets.QSizePolicy.Expanding,
            QtWidgets.QSizePolicy.Expanding)
        self.inventory_layout.addItem(self.inventory_spacer,
                                      self.inventory_layout.rowCount(),
                                      self.inventory_layout.columnCount())

        self._current_tracker_game = game_enum
        self._update_tracker_from_hook({})

        self._current_tracker_name = tracker_name

    @asyncSlot()
    async def on_force_update_button(self):
        await self.game_connection.update_current_inventory()
        inventory = self.game_connection.get_current_inventory()
        logging.info("Inventory:" + "\n".join(
            f"{item.long_name}: {inv_item.amount}/{inv_item.capacity}"
            for item, inv_item in sorted(inventory.items(),
                                         key=lambda it: it[0].long_name)))