388 lines
No EOL
12 KiB
GDScript
388 lines
No EOL
12 KiB
GDScript
extends Control
|
|
class_name LobbyShopScreen
|
|
|
|
signal back_pressed
|
|
signal card_unlocked(card, token_cost)
|
|
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 = {
|
|
Card.Rank.RANK_0: 15, # Most expensive (one-time use)
|
|
Card.Rank.RANK_1: 10, # Expensive (once per match)
|
|
Card.Rank.RANK_2: 5, # Medium (multiple uses)
|
|
Card.Rank.RANK_3: 3 # Cheapest (basic cards)
|
|
}
|
|
|
|
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_cards = []
|
|
var card_classes = [
|
|
HopscotchCard,
|
|
FieryCapeCard,
|
|
FieryTrailCard,
|
|
ExplosiveBootsCard,
|
|
DoubleTimeCard,
|
|
DrunkDrivingCard,
|
|
SupernovaCard
|
|
]
|
|
|
|
for card_class in card_classes:
|
|
var card = card_class.new()
|
|
all_cards.append(card)
|
|
|
|
all_cards.shuffle()
|
|
|
|
var num_shop_cards = min(randi_range(5, 7), all_cards.size())
|
|
|
|
for i in range(num_shop_cards):
|
|
shop_cards.append(all_cards[i % card_classes.size()])
|
|
|
|
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) |