extends Control class_name LobbyShopScreen signal back_pressed signal card_unlocked(card, token_cost) signal lobby_shop_visibility_changed(isvisible) signal hand_size_increased # Node references @onready var card_carousel = $MainContainer/CardCarouselContainer/CardCarousel @onready var token_label = $TopBar/TokenContainer/TokenLabel @onready var buy_button = $BuyButton @onready var back_button = $BackButton @onready var card_preview = $CardPreviewPanel @onready var left_button = $MainContainer/CardCarouselContainer/LeftButton @onready var right_button = $MainContainer/CardCarouselContainer/RightButton @onready var hand_size_label = $HandSizeContainer/HandSizeLabel @onready var hand_size_cost_label = $HandSizeContainer/CostLabel @onready var increase_hand_size_button = $HandSizeContainer/IncreaseButton var available_cards = [] var player_tokens = 0 var selected_card = null var selected_index = 0 var carousel_page = 0 var cards_per_page = 3 var card_instance_map = {} var hovering_card_index = -1 var mouse_over_any_card = false var game: ChessGame var player: Player var card_costs = Utils.TokenCosts var fibonacci = [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144] func _ready(): if back_button: back_button.connect("pressed", Callable(self, "_on_back_button_pressed")) if buy_button: buy_button.connect("pressed", Callable(self, "_on_buy_button_pressed")) if increase_hand_size_button: increase_hand_size_button.connect("pressed", Callable(self, "_on_increase_hand_size_pressed")) if left_button: left_button.pressed.connect(_on_left_button_pressed) if right_button: right_button.pressed.connect(_on_right_button_pressed) # Initialize with empty shop if card_preview: card_preview.visible = false update_token_display() update_buy_button() update_navigation_buttons() update_hand_size_display() func initialize(options = null): carousel_page = 0 selected_index = 0 game = get_node_or_null("/root/Board") as ChessGame if game and "player" in game: player = game.player player_tokens = player.tokens # Generate shop cards if not provided if available_cards.is_empty() and game and "deckManager" in game: var deck_manager = game.deckManager available_cards = generate_shop_cards(deck_manager) # Update display update_token_display() update_hand_size_display() populate_carousel() update_navigation_buttons() if not available_cards.is_empty(): select_card(0) # Select the first card by default func generate_shop_cards(deck_manager): var shop_cards = [] var all_available_cards = [] for rank in player.cards_by_rank: for card in player.cards_by_rank[rank]: var is_unlocked = false for unlocked_card in player.unlocked_cards: if unlocked_card.cardName == card.cardName: is_unlocked = true break if not is_unlocked: var card_instance = card.duplicate() all_available_cards.append(card_instance) if all_available_cards.is_empty(): print("No new cards available for the shop") return [] all_available_cards.shuffle() var num_shop_cards = min(randi_range(5, 7), all_available_cards.size()) for i in range(num_shop_cards): shop_cards.append(all_available_cards[i]) print("Generated shop with " + str(shop_cards.size()) + " cards") return shop_cards func populate_carousel(): if card_carousel: for child in card_carousel.get_children(): child.queue_free() card_instance_map.clear() var start_index = carousel_page * cards_per_page var end_index = min(start_index + cards_per_page, available_cards.size()) card_carousel.add_theme_constant_override("separation", 20) for i in range(start_index, end_index): var card = available_cards[i] var card_visual = preload("res://card_visual.tscn").instantiate() card_carousel.add_child(card_visual) card_visual.set_card(card) var token_cost = get_card_cost(card) card_visual.set_price(token_cost) card_visual.set_string("tokens") var instance_id = card_visual.get_instance_id() card_instance_map[instance_id] = { "card_index": i, "card": card } update_navigation_buttons() func update_navigation_buttons(): if left_button: left_button.disabled = (carousel_page <= 0) if right_button: var max_page = ceil(float(available_cards.size()) / cards_per_page) - 1 right_button.disabled = (carousel_page >= max_page or available_cards.size() <= cards_per_page) func select_card(index): if index < 0 or index >= available_cards.size(): return var page_for_index = int(index / cards_per_page) if page_for_index != carousel_page: carousel_page = page_for_index populate_carousel() selected_index = index selected_card = available_cards[index] var visual_index = index % cards_per_page for i in range(card_carousel.get_child_count()): var card_visual = card_carousel.get_child(i) card_visual.set_selected(i == visual_index) if card_preview and selected_card: card_preview.preview_card(selected_card) card_preview.visible = true update_buy_button() func update_buy_button(): if not buy_button or not selected_card: return var cost = get_card_cost(selected_card) buy_button.text = "BUY (" + str(cost) + " tokens)" buy_button.disabled = cost > player_tokens func get_card_cost(card): if not card: return 0 if card.rank in card_costs: return card_costs[card.rank] return 10 func update_token_display(): if token_label: token_label.text = str(player_tokens) + " TOKENS" func update_hand_size_display(): if not player or not hand_size_label or not hand_size_cost_label: return hand_size_label.text = "HAND SIZE: " + str(player.hand_size) # Calculate cost using Fibonacci sequence var fib_index = max(player.hand_size - 2, 1) + 2 # Start at index 2 (which is 1) if fib_index >= fibonacci.size(): fib_index = fibonacci.size() - 1 var cost = fibonacci[fib_index] hand_size_cost_label.text = "Cost: " + str(cost) + " tokens" if increase_hand_size_button: increase_hand_size_button.disabled = cost > player_tokens func purchase_selected_card(): if not selected_card or not player: return false var cost = get_card_cost(selected_card) if player_tokens < cost: print("Not enough tokens") return false player_tokens -= cost player.tokens = player_tokens var purchased_card = selected_card.duplicate() available_cards.remove_at(selected_index) emit_signal("card_unlocked", purchased_card, cost) update_token_display() var max_page = max(0, ceil(float(available_cards.size()) / cards_per_page) - 1) if carousel_page > max_page: carousel_page = max_page populate_carousel() if not available_cards.is_empty(): var new_index = min(selected_index, available_cards.size() - 1) select_card(new_index) else: selected_card = null selected_index = -1 if card_preview: card_preview.hide_preview() buy_button.disabled = true update_buy_button() return true func increase_hand_size(): if not player: return false # Calculate cost using Fibonacci sequence var fib_index = max(player.hand_size - 2, 1) + 2 if fib_index >= fibonacci.size(): fib_index = fibonacci.size() - 1 var cost = fibonacci[fib_index] if player_tokens < cost: print("Not enough tokens for hand size increase") return false if player.hand_size >= player.MAX_HAND_SIZE: print("Hand reached max size") return false player_tokens -= cost player.tokens = player_tokens player.set_hand_size(player.hand_size + 1) update_token_display() update_hand_size_display() update_buy_button() emit_signal("hand_size_increased") return true # Signal handlers func _on_back_button_pressed(): emit_signal("back_pressed") visible = false func _on_buy_button_pressed(): purchase_selected_card() func _on_increase_hand_size_pressed(): increase_hand_size() func _on_left_button_pressed(): if carousel_page > 0: carousel_page -= 1 var new_index = carousel_page * cards_per_page populate_carousel() select_card(new_index) func _on_right_button_pressed(): var max_page = ceil(float(available_cards.size()) / cards_per_page) - 1 if carousel_page < max_page: carousel_page += 1 var new_index = carousel_page * cards_per_page populate_carousel() select_card(new_index) func _on_card_visual_pressed(index): select_card(index) func _on_card_visual_hover(card, index): if card_preview and card: card_preview.preview_card(card) card_preview.visible = true select_card(index) func _on_card_visual_exit(): if card_preview and selected_card: card_preview.preview_card(selected_card) elif card_preview: card_preview.hide_preview() func _process(delta): if not visible: return var mouse_pos = get_viewport().get_mouse_position() # Reset tracking var old_hovering_index = hovering_card_index hovering_card_index = -1 mouse_over_any_card = false var mouse_clicked = Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT) for i in range(card_carousel.get_child_count()): var card_visual = card_carousel.get_child(i) var card_rect = card_visual.get_global_rect() if card_rect.has_point(mouse_pos) and mouse_clicked: # Get data from instance map var instance_id = card_visual.get_instance_id() if card_instance_map.has(instance_id): var data = card_instance_map[instance_id] hovering_card_index = data.card_index mouse_over_any_card = true # If we just started hovering this card if old_hovering_index != hovering_card_index: _on_card_visual_hover(data.card, data.card_index) # Also trigger the card's own hover effect card_visual._on_mouse_entered() break # If we were hovering a card before but not now, trigger exit if old_hovering_index != -1 and hovering_card_index == -1: _on_card_visual_exit() # Find the previously hovered card by index for i in range(card_carousel.get_child_count()): var card_visual = card_carousel.get_child(i) var instance_id = card_visual.get_instance_id() if card_instance_map.has(instance_id) and card_instance_map[instance_id].card_index == old_hovering_index: card_visual._on_mouse_exited() break # Notification func _notification(what): if what == NOTIFICATION_VISIBILITY_CHANGED: _on_visibility_changed(visible) func _on_visibility_changed(is_visible): print("LobbyShop visibility changed to: ", is_visible) if is_visible: update_token_display() update_hand_size_display() update_buy_button() else: print("LobbyShop is now invisible") emit_signal("lobby_shop_visibility_changed", is_visible)