bastd.ui.purchase

UI related to purchasing items.

  1# Released under the MIT License. See LICENSE for details.
  2#
  3"""UI related to purchasing items."""
  4
  5from __future__ import annotations
  6
  7from typing import TYPE_CHECKING
  8
  9import ba
 10import ba.internal
 11
 12if TYPE_CHECKING:
 13    from typing import Any
 14
 15
 16class PurchaseWindow(ba.Window):
 17    """Window for purchasing one or more items."""
 18
 19    def __init__(
 20        self,
 21        items: list[str],
 22        transition: str = 'in_right',
 23        header_text: ba.Lstr | None = None,
 24    ):
 25        from ba.internal import get_store_item_display_size
 26        from bastd.ui.store import item as storeitemui
 27
 28        if header_text is None:
 29            header_text = ba.Lstr(
 30                resource='unlockThisText',
 31                fallback_resource='unlockThisInTheStoreText',
 32            )
 33        if len(items) != 1:
 34            raise ValueError('expected exactly 1 item')
 35        self._items = list(items)
 36        self._width = 580
 37        self._height = 520
 38        uiscale = ba.app.ui.uiscale
 39        super().__init__(
 40            root_widget=ba.containerwidget(
 41                size=(self._width, self._height),
 42                transition=transition,
 43                toolbar_visibility='menu_currency',
 44                scale=(
 45                    1.2
 46                    if uiscale is ba.UIScale.SMALL
 47                    else 1.1
 48                    if uiscale is ba.UIScale.MEDIUM
 49                    else 1.0
 50                ),
 51                stack_offset=(0, -15)
 52                if uiscale is ba.UIScale.SMALL
 53                else (0, 0),
 54            )
 55        )
 56        self._is_double = False
 57        self._title_text = ba.textwidget(
 58            parent=self._root_widget,
 59            position=(self._width * 0.5, self._height - 30),
 60            size=(0, 0),
 61            text=header_text,
 62            h_align='center',
 63            v_align='center',
 64            maxwidth=self._width * 0.9 - 120,
 65            scale=1.2,
 66            color=(1, 0.8, 0.3, 1),
 67        )
 68        size = get_store_item_display_size(items[0])
 69        display: dict[str, Any] = {}
 70        storeitemui.instantiate_store_item_display(
 71            items[0],
 72            display,
 73            parent_widget=self._root_widget,
 74            b_pos=(
 75                self._width * 0.5
 76                - size[0] * 0.5
 77                + 10
 78                - ((size[0] * 0.5 + 30) if self._is_double else 0),
 79                self._height * 0.5
 80                - size[1] * 0.5
 81                + 30
 82                + (20 if self._is_double else 0),
 83            ),
 84            b_width=size[0],
 85            b_height=size[1],
 86            button=False,
 87        )
 88
 89        # Wire up the parts we need.
 90        if self._is_double:
 91            pass  # not working
 92        else:
 93            if self._items == ['pro']:
 94                price_str = ba.internal.get_price(self._items[0])
 95                pyoffs = -15
 96            else:
 97                pyoffs = 0
 98                price = self._price = ba.internal.get_v1_account_misc_read_val(
 99                    'price.' + str(items[0]), -1
100                )
101                price_str = ba.charstr(ba.SpecialChar.TICKET) + str(price)
102            self._price_text = ba.textwidget(
103                parent=self._root_widget,
104                position=(self._width * 0.5, 150 + pyoffs),
105                size=(0, 0),
106                text=price_str,
107                h_align='center',
108                v_align='center',
109                maxwidth=self._width * 0.9,
110                scale=1.4,
111                color=(0.2, 1, 0.2),
112            )
113
114        self._update_timer = ba.Timer(
115            1.0,
116            ba.WeakCall(self._update),
117            timetype=ba.TimeType.REAL,
118            repeat=True,
119        )
120
121        self._cancel_button = ba.buttonwidget(
122            parent=self._root_widget,
123            position=(50, 40),
124            size=(150, 60),
125            scale=1.0,
126            on_activate_call=self._cancel,
127            autoselect=True,
128            label=ba.Lstr(resource='cancelText'),
129        )
130        self._purchase_button = ba.buttonwidget(
131            parent=self._root_widget,
132            position=(self._width - 200, 40),
133            size=(150, 60),
134            scale=1.0,
135            on_activate_call=self._purchase,
136            autoselect=True,
137            label=ba.Lstr(resource='store.purchaseText'),
138        )
139
140        ba.containerwidget(
141            edit=self._root_widget,
142            cancel_button=self._cancel_button,
143            start_button=self._purchase_button,
144            selected_child=self._purchase_button,
145        )
146
147    def _update(self) -> None:
148        can_die = False
149
150        # We go away if we see that our target item is owned.
151        if self._items == ['pro']:
152            if ba.app.accounts_v1.have_pro():
153                can_die = True
154        else:
155            if ba.internal.get_purchased(self._items[0]):
156                can_die = True
157
158        if can_die:
159            ba.containerwidget(edit=self._root_widget, transition='out_left')
160
161    def _purchase(self) -> None:
162        from bastd.ui import getcurrency
163
164        if self._items == ['pro']:
165            ba.internal.purchase('pro')
166        else:
167            ticket_count: int | None
168            try:
169                ticket_count = ba.internal.get_v1_account_ticket_count()
170            except Exception:
171                ticket_count = None
172            if ticket_count is not None and ticket_count < self._price:
173                getcurrency.show_get_tickets_prompt()
174                ba.playsound(ba.getsound('error'))
175                return
176
177            def do_it() -> None:
178                ba.internal.in_game_purchase(self._items[0], self._price)
179
180            ba.playsound(ba.getsound('swish'))
181            do_it()
182
183    def _cancel(self) -> None:
184        ba.containerwidget(edit=self._root_widget, transition='out_right')
class PurchaseWindow(ba.ui.Window):
 17class PurchaseWindow(ba.Window):
 18    """Window for purchasing one or more items."""
 19
 20    def __init__(
 21        self,
 22        items: list[str],
 23        transition: str = 'in_right',
 24        header_text: ba.Lstr | None = None,
 25    ):
 26        from ba.internal import get_store_item_display_size
 27        from bastd.ui.store import item as storeitemui
 28
 29        if header_text is None:
 30            header_text = ba.Lstr(
 31                resource='unlockThisText',
 32                fallback_resource='unlockThisInTheStoreText',
 33            )
 34        if len(items) != 1:
 35            raise ValueError('expected exactly 1 item')
 36        self._items = list(items)
 37        self._width = 580
 38        self._height = 520
 39        uiscale = ba.app.ui.uiscale
 40        super().__init__(
 41            root_widget=ba.containerwidget(
 42                size=(self._width, self._height),
 43                transition=transition,
 44                toolbar_visibility='menu_currency',
 45                scale=(
 46                    1.2
 47                    if uiscale is ba.UIScale.SMALL
 48                    else 1.1
 49                    if uiscale is ba.UIScale.MEDIUM
 50                    else 1.0
 51                ),
 52                stack_offset=(0, -15)
 53                if uiscale is ba.UIScale.SMALL
 54                else (0, 0),
 55            )
 56        )
 57        self._is_double = False
 58        self._title_text = ba.textwidget(
 59            parent=self._root_widget,
 60            position=(self._width * 0.5, self._height - 30),
 61            size=(0, 0),
 62            text=header_text,
 63            h_align='center',
 64            v_align='center',
 65            maxwidth=self._width * 0.9 - 120,
 66            scale=1.2,
 67            color=(1, 0.8, 0.3, 1),
 68        )
 69        size = get_store_item_display_size(items[0])
 70        display: dict[str, Any] = {}
 71        storeitemui.instantiate_store_item_display(
 72            items[0],
 73            display,
 74            parent_widget=self._root_widget,
 75            b_pos=(
 76                self._width * 0.5
 77                - size[0] * 0.5
 78                + 10
 79                - ((size[0] * 0.5 + 30) if self._is_double else 0),
 80                self._height * 0.5
 81                - size[1] * 0.5
 82                + 30
 83                + (20 if self._is_double else 0),
 84            ),
 85            b_width=size[0],
 86            b_height=size[1],
 87            button=False,
 88        )
 89
 90        # Wire up the parts we need.
 91        if self._is_double:
 92            pass  # not working
 93        else:
 94            if self._items == ['pro']:
 95                price_str = ba.internal.get_price(self._items[0])
 96                pyoffs = -15
 97            else:
 98                pyoffs = 0
 99                price = self._price = ba.internal.get_v1_account_misc_read_val(
100                    'price.' + str(items[0]), -1
101                )
102                price_str = ba.charstr(ba.SpecialChar.TICKET) + str(price)
103            self._price_text = ba.textwidget(
104                parent=self._root_widget,
105                position=(self._width * 0.5, 150 + pyoffs),
106                size=(0, 0),
107                text=price_str,
108                h_align='center',
109                v_align='center',
110                maxwidth=self._width * 0.9,
111                scale=1.4,
112                color=(0.2, 1, 0.2),
113            )
114
115        self._update_timer = ba.Timer(
116            1.0,
117            ba.WeakCall(self._update),
118            timetype=ba.TimeType.REAL,
119            repeat=True,
120        )
121
122        self._cancel_button = ba.buttonwidget(
123            parent=self._root_widget,
124            position=(50, 40),
125            size=(150, 60),
126            scale=1.0,
127            on_activate_call=self._cancel,
128            autoselect=True,
129            label=ba.Lstr(resource='cancelText'),
130        )
131        self._purchase_button = ba.buttonwidget(
132            parent=self._root_widget,
133            position=(self._width - 200, 40),
134            size=(150, 60),
135            scale=1.0,
136            on_activate_call=self._purchase,
137            autoselect=True,
138            label=ba.Lstr(resource='store.purchaseText'),
139        )
140
141        ba.containerwidget(
142            edit=self._root_widget,
143            cancel_button=self._cancel_button,
144            start_button=self._purchase_button,
145            selected_child=self._purchase_button,
146        )
147
148    def _update(self) -> None:
149        can_die = False
150
151        # We go away if we see that our target item is owned.
152        if self._items == ['pro']:
153            if ba.app.accounts_v1.have_pro():
154                can_die = True
155        else:
156            if ba.internal.get_purchased(self._items[0]):
157                can_die = True
158
159        if can_die:
160            ba.containerwidget(edit=self._root_widget, transition='out_left')
161
162    def _purchase(self) -> None:
163        from bastd.ui import getcurrency
164
165        if self._items == ['pro']:
166            ba.internal.purchase('pro')
167        else:
168            ticket_count: int | None
169            try:
170                ticket_count = ba.internal.get_v1_account_ticket_count()
171            except Exception:
172                ticket_count = None
173            if ticket_count is not None and ticket_count < self._price:
174                getcurrency.show_get_tickets_prompt()
175                ba.playsound(ba.getsound('error'))
176                return
177
178            def do_it() -> None:
179                ba.internal.in_game_purchase(self._items[0], self._price)
180
181            ba.playsound(ba.getsound('swish'))
182            do_it()
183
184    def _cancel(self) -> None:
185        ba.containerwidget(edit=self._root_widget, transition='out_right')

Window for purchasing one or more items.

PurchaseWindow( items: list[str], transition: str = 'in_right', header_text: ba._language.Lstr | None = None)
 20    def __init__(
 21        self,
 22        items: list[str],
 23        transition: str = 'in_right',
 24        header_text: ba.Lstr | None = None,
 25    ):
 26        from ba.internal import get_store_item_display_size
 27        from bastd.ui.store import item as storeitemui
 28
 29        if header_text is None:
 30            header_text = ba.Lstr(
 31                resource='unlockThisText',
 32                fallback_resource='unlockThisInTheStoreText',
 33            )
 34        if len(items) != 1:
 35            raise ValueError('expected exactly 1 item')
 36        self._items = list(items)
 37        self._width = 580
 38        self._height = 520
 39        uiscale = ba.app.ui.uiscale
 40        super().__init__(
 41            root_widget=ba.containerwidget(
 42                size=(self._width, self._height),
 43                transition=transition,
 44                toolbar_visibility='menu_currency',
 45                scale=(
 46                    1.2
 47                    if uiscale is ba.UIScale.SMALL
 48                    else 1.1
 49                    if uiscale is ba.UIScale.MEDIUM
 50                    else 1.0
 51                ),
 52                stack_offset=(0, -15)
 53                if uiscale is ba.UIScale.SMALL
 54                else (0, 0),
 55            )
 56        )
 57        self._is_double = False
 58        self._title_text = ba.textwidget(
 59            parent=self._root_widget,
 60            position=(self._width * 0.5, self._height - 30),
 61            size=(0, 0),
 62            text=header_text,
 63            h_align='center',
 64            v_align='center',
 65            maxwidth=self._width * 0.9 - 120,
 66            scale=1.2,
 67            color=(1, 0.8, 0.3, 1),
 68        )
 69        size = get_store_item_display_size(items[0])
 70        display: dict[str, Any] = {}
 71        storeitemui.instantiate_store_item_display(
 72            items[0],
 73            display,
 74            parent_widget=self._root_widget,
 75            b_pos=(
 76                self._width * 0.5
 77                - size[0] * 0.5
 78                + 10
 79                - ((size[0] * 0.5 + 30) if self._is_double else 0),
 80                self._height * 0.5
 81                - size[1] * 0.5
 82                + 30
 83                + (20 if self._is_double else 0),
 84            ),
 85            b_width=size[0],
 86            b_height=size[1],
 87            button=False,
 88        )
 89
 90        # Wire up the parts we need.
 91        if self._is_double:
 92            pass  # not working
 93        else:
 94            if self._items == ['pro']:
 95                price_str = ba.internal.get_price(self._items[0])
 96                pyoffs = -15
 97            else:
 98                pyoffs = 0
 99                price = self._price = ba.internal.get_v1_account_misc_read_val(
100                    'price.' + str(items[0]), -1
101                )
102                price_str = ba.charstr(ba.SpecialChar.TICKET) + str(price)
103            self._price_text = ba.textwidget(
104                parent=self._root_widget,
105                position=(self._width * 0.5, 150 + pyoffs),
106                size=(0, 0),
107                text=price_str,
108                h_align='center',
109                v_align='center',
110                maxwidth=self._width * 0.9,
111                scale=1.4,
112                color=(0.2, 1, 0.2),
113            )
114
115        self._update_timer = ba.Timer(
116            1.0,
117            ba.WeakCall(self._update),
118            timetype=ba.TimeType.REAL,
119            repeat=True,
120        )
121
122        self._cancel_button = ba.buttonwidget(
123            parent=self._root_widget,
124            position=(50, 40),
125            size=(150, 60),
126            scale=1.0,
127            on_activate_call=self._cancel,
128            autoselect=True,
129            label=ba.Lstr(resource='cancelText'),
130        )
131        self._purchase_button = ba.buttonwidget(
132            parent=self._root_widget,
133            position=(self._width - 200, 40),
134            size=(150, 60),
135            scale=1.0,
136            on_activate_call=self._purchase,
137            autoselect=True,
138            label=ba.Lstr(resource='store.purchaseText'),
139        )
140
141        ba.containerwidget(
142            edit=self._root_widget,
143            cancel_button=self._cancel_button,
144            start_button=self._purchase_button,
145            selected_child=self._purchase_button,
146        )
Inherited Members
ba.ui.Window
get_root_widget