From 6c1b4c57baa1a452f7e501d905ed035e68e7b154 Mon Sep 17 00:00:00 2001 From: 2ManyProjects Date: Fri, 14 Mar 2025 00:51:53 -0500 Subject: [PATCH] added progression --- .../fairy-chess-server/variants.js | 87 +++++ Systems/CardDisplay.gd | 2 +- Systems/DeckManager.gd | 46 +-- Systems/Game/ChessGame.gd | 4 +- Systems/Game/DeckManagerScreen.gd | 2 +- Systems/Game/GameMenuScreen.gd | 25 +- Systems/Game/Lobby/LobbyScreen.gd | 67 ++++ Systems/Game/Lobby/LobbyScreen.gd.uid | 1 + Systems/Game/Lobby/LobbyShop.gd.uid | 1 + Systems/Game/Lobby/LobbyShopScreen.gd | 368 ++++++++++++++++++ Systems/Game/Lobby/LobbyShopScreen.gd.uid | 1 + Systems/Game/Map/MapGenerator.gd | 131 ++++++- Systems/Game/Map/MapScreen.gd | 15 +- Systems/Game/Menu/MenuContainer.gd | 151 ++++++- Systems/Game/Player/Player.gd | 26 +- Systems/Game/ProgressionScreen.gd | 35 +- Systems/Game/Shop/RewardScreen.gd | 11 +- Systems/Game/Shop/ShopScreen.gd | 7 +- Utils/Utils.gd | 33 +- board.tscn | 22 +- card_preview_panel.tscn | 2 +- deck_manager_screen.tscn | 2 +- lobby_screen.tscn | 161 ++++++++ lobby_shop_screen.tscn | 188 +++++++++ progression_screen.tscn | 2 +- reward_screen.tscn | 2 +- shop_screen.tscn | 2 +- 27 files changed, 1286 insertions(+), 108 deletions(-) create mode 100644 Assets/ChessEngines/fairy-chess-server/variants.js create mode 100644 Systems/Game/Lobby/LobbyScreen.gd create mode 100644 Systems/Game/Lobby/LobbyScreen.gd.uid create mode 100644 Systems/Game/Lobby/LobbyShop.gd.uid create mode 100644 Systems/Game/Lobby/LobbyShopScreen.gd create mode 100644 Systems/Game/Lobby/LobbyShopScreen.gd.uid create mode 100644 lobby_screen.tscn create mode 100644 lobby_shop_screen.tscn diff --git a/Assets/ChessEngines/fairy-chess-server/variants.js b/Assets/ChessEngines/fairy-chess-server/variants.js new file mode 100644 index 0000000..af4f42d --- /dev/null +++ b/Assets/ChessEngines/fairy-chess-server/variants.js @@ -0,0 +1,87 @@ +import fs from 'fs' + +const pieceSetups = [ + "nk", // 2 cells + "nkr", // 3 cells + "nkbr", // 4 cells + "rnkbr", // 5 cells + "rbnkqr", // 6 cells + "rnbkqnr", // 7 cells + "rnbqkbnr", // 8 cells (standard chess) + "rbnqknbnr", // 9 cells + "rnbnqknbnr", // 10 cells + "rnbnqknbnnr", // 11 cells + "rnnbnqknbnnr" // 12 cells +]; + +const files = "abcdefghijkl"; + +function generateVariant(width, height) { + if (width < 2 || width > 12) { + console.error("Width must be between 2 and 12"); + return ""; + } + + if (height < 6 || height > 12) { + console.error("Height must be between 6 and 12"); + return ""; + } + + const pieceSetup = pieceSetups[width - 2]; + + + const emptyRanks = height - 4; + + + const whitePieces = pieceSetup.toUpperCase(); + const blackPieces = pieceSetup.toLowerCase(); + + const whitePawns = "P".repeat(width); + const blackPawns = "p".repeat(width); + const emptyRank = width.toString(); + + let fenParts = [blackPieces, blackPawns]; + + for (let i = 0; i < emptyRanks; i++) { + fenParts.push(emptyRank); + } + + fenParts.push(whitePawns, whitePieces); + const fen = fenParts.join("/") + " w - - 0 1"; + + const maxFile = files[width - 1]; + + return `[chessbuilder${width}x${height}:chess] +pieceToCharTable = PNBRQK..*@...........pnbrqk..*@........... +maxRank = ${height} +maxFile = ${maxFile} +startFen = ${fen} + +walltype = * # Duck wall +walltype = @ # Stone wall + +wallingRule = static +wallOrMove = false +mobilityRegion = *:@ +prohibitedMove = *@ +`; +} +function generateAllVariants() { + let allVariants = ""; + let count = 0; + + for (let height = 6; height <= 12; height++) { + for (let width = 2; width <= 12; width++) { + const variant = generateVariant(width, height); + allVariants += variant + "\n"; + count++; + } + } + + fs.writeFileSync('chessbuilder_variants.ini', allVariants); + console.log(`Generated ${count} variants and saved to chessbuilder_variants.ini`); + + return allVariants; +} + +generateAllVariants(); \ No newline at end of file diff --git a/Systems/CardDisplay.gd b/Systems/CardDisplay.gd index 80c6681..41bfaa2 100644 --- a/Systems/CardDisplay.gd +++ b/Systems/CardDisplay.gd @@ -103,7 +103,7 @@ func _on_card_clicked(event: InputEvent, card: Card): selectedCard = null highlight_selectedCard(selectedCard) -func _on_card_mouse_entered(card: Card): +func _on_card_mouse_entered( card: Card): # Show card preview when hovering # print("_on_card_mouse_entered") currently_hovered_card = card diff --git a/Systems/DeckManager.gd b/Systems/DeckManager.gd index 95cdd50..26a73a6 100644 --- a/Systems/DeckManager.gd +++ b/Systems/DeckManager.gd @@ -10,13 +10,6 @@ var attached_effects: Dictionary = {} # piece_id: [card] var hand_size: int = 5 # Card costs for shop -const CARD_BASE_COSTS = { - Card.Rank.RANK_0: 100, - Card.Rank.RANK_1: 75, - Card.Rank.RANK_2: 50, - Card.Rank.RANK_3: 25 -} - func _init(): print("************************DECK INIT*****************") initializeStartingDeck() @@ -28,14 +21,14 @@ func set_hand_size(size: int): func initializeStartingDeck(): deck.clear(); # for i in range(2): - # deck.append(DoubleTimeCard.new()) - # deck.append(HopscotchCard.new()) - # deck.append(FieryCapeCard.new()) - # deck.append(FieryTrailCard.new()) - deck.append(ExplosiveBootsCard.new()) - deck.append(DoubleTimeCard.new()) - # deck.append(DrunkDrivingCard.new()) - deck.append(SupernovaCard.new()) + # addCardToDeck(DoubleTimeCard.new()) + # addCardToDeck(HopscotchCard.new()) + # addCardToDeck(FieryCapeCard.new()) + # addCardToDeck(FieryTrailCard.new()) + addCardToDeck(ExplosiveBootsCard.new()) + addCardToDeck(DoubleTimeCard.new()) + # addCardToDeck(DrunkDrivingCard.new()) + addCardToDeck(SupernovaCard.new()) func initializeStartingBank(): # sample @@ -73,6 +66,9 @@ func drawCard(): signal hand_updated +func addCardToDeck(card: Card): + deck.insert(0, card) + func playCard(card: Card, target_piece: Pawn, board_flow = null, game_state = null, avoidHand = false): if !avoidHand and !hand.has(card): @@ -87,22 +83,6 @@ func playCard(card: Card, target_piece: Pawn, board_flow = null, game_state = nu hand.erase(card) emit_signal("hand_updated", hand) - # match card.rank: - # Card.Rank.RANK_0: - # print("Rank 3 Burned permanently") - # pass - # Card.Rank.RANK_1: - # print("Rank 3 Burned until next match") - # pass - # Card.Rank.RANK_2: - # print("Rank 2 add to Discard") - # discard.append(card) - # pass - # Card.Rank.RANK_3: - # deck.append(card) - # print("Rank 3 add to Deck") - # pass - return true # print("Failed Play Card 2") @@ -187,7 +167,7 @@ func updateCardDurations(): discard.append(card) pass Card.Rank.RANK_3: - deck.append(card) + addCardToDeck(card) print("Rank 3 add to Deck") pass else: @@ -215,7 +195,7 @@ func getShopCards(num_cards: int = 3) -> Array: return shop_cards func calculateCardCost(card: Card) -> int: - var base_cost = CARD_BASE_COSTS[card.rank] + var base_cost = Utils.CardPrices[card.rank] # Add modifiers based on card effects return base_cost diff --git a/Systems/Game/ChessGame.gd b/Systems/Game/ChessGame.gd index d4abc32..b70793d 100644 --- a/Systems/Game/ChessGame.gd +++ b/Systems/Game/ChessGame.gd @@ -869,10 +869,10 @@ func recover_cards_from_player_piece(piece: Pawn): match card.rank: Card.Rank.RANK_2: - deckManager.deck.append(card) + deckManager.addCardToDeck(card) print("Recovered Rank 2 card pile: ", card.cardName) Card.Rank.RANK_3: - deckManager.deck.append(card) + deckManager.addCardToDeck(card) print("Recovered Rank 3 card to deck: ", card.cardName) deckManager.attached_cards.erase(piece_id) diff --git a/Systems/Game/DeckManagerScreen.gd b/Systems/Game/DeckManagerScreen.gd index b09a5f3..079e0b6 100644 --- a/Systems/Game/DeckManagerScreen.gd +++ b/Systems/Game/DeckManagerScreen.gd @@ -149,7 +149,7 @@ func _on_bank_card_selected(card_item, card): bankCards.remove_at(bank_index) # Add to deck - currentDeck.append(card) + currentDeck.addCardToDeck(card) # Update UI deckGrid.get_child(empty_slot_index).set_card(card) diff --git a/Systems/Game/GameMenuScreen.gd b/Systems/Game/GameMenuScreen.gd index 6e9b368..f6c0aa8 100644 --- a/Systems/Game/GameMenuScreen.gd +++ b/Systems/Game/GameMenuScreen.gd @@ -6,7 +6,7 @@ signal shop_open_requested(options) signal deckmanager_open_requested(options) signal map_open_requested(options) signal new_game_requested(options) - +signal lobby_open_requested(options) # @onready var newGameButton = $HBoxContainer/VBoxContainer/MenuOptions/NewGameText # @onready var continueButton = $HBoxContainer/VBoxContainer/MenuOptions/Continue @@ -17,7 +17,7 @@ signal new_game_requested(options) # Node references @onready var shopButton = $HBoxContainer/VBoxContainer/GameOptions/ShopText -@onready var deckButton = $HBoxContainer/VBoxContainer/GameOptions/ManageDeckText +@onready var lobbyButton = $HBoxContainer/VBoxContainer/GameOptions/LobbyText @onready var mapButton = $HBoxContainer/VBoxContainer/GameOptions/MapText @onready var startButton = $HBoxContainer/VBoxContainer/GameOptions/StartText @onready var backButton = $HBoxContainer/VBoxContainer/GameOptions/BackText @@ -31,11 +31,11 @@ func _ready(): shopButton.visible = false; shopButton.connect("pressed", Callable(self, "_on_shop_button_pressed")) - if deckButton: - deckButton.visible = false; - deckButton.connect("pressed", Callable(self, "_on_deck_button_pressed")) + if lobbyButton: + lobbyButton.connect("pressed", Callable(self, "_on_lobby_button_pressed")) if mapButton: + mapButton.visible = false; mapButton.connect("pressed", Callable(self, "_on_map_button_pressed")) if startButton: @@ -46,6 +46,7 @@ func _ready(): backButton.connect("pressed", Callable(self, "_on_back_button_pressed")) connect("map_open_requested", Callable(self, "_on_map_button_pressed")) + func setup(menu_container): @@ -63,6 +64,7 @@ func _on_deck_button_pressed(): func _on_map_button_pressed(): print("Map button pressed") + # ignore error, keeping the null prevents infinit recursion emit_signal("map_open_requested", null) visible = false @@ -84,4 +86,15 @@ func _on_back_button_pressed(): self.visible = false func show_menu(): - self.visible = true \ No newline at end of file + self.visible = true + +func _on_lobby_open_requested(options): + print("Lobby button pressed") + emit_signal("lobby_open_requested", options) + visible = false + + +func _on_lobby_button_pressed(): + print("Lobby button pressed") + emit_signal("lobby_open_requested", null) + visible = false diff --git a/Systems/Game/Lobby/LobbyScreen.gd b/Systems/Game/Lobby/LobbyScreen.gd new file mode 100644 index 0000000..c0f9da4 --- /dev/null +++ b/Systems/Game/Lobby/LobbyScreen.gd @@ -0,0 +1,67 @@ +extends Control +class_name LobbyScreen + +signal vanilla_selected +signal shop_selected +signal deeper_selected +signal back_pressed + +# Node references +@onready var vanilla_button = $BottomContainer/VanillaButton +@onready var shop_button = $CenterContainer/ShopButton +@onready var deeper_button = $BottomContainer/DeeperButton +@onready var back_button = $BackButton +@onready var run_count_label = $TopBar/RunCountLabel +@onready var token_label = $TopBar/TokenContainer/TokenLabel + +var game: ChessGame +var player: Player + +func _ready(): + # Connect button signals + if vanilla_button: + vanilla_button.connect("pressed", Callable(self, "_on_vanilla_button_pressed")) + + if shop_button: + shop_button.connect("pressed", Callable(self, "_on_shop_button_pressed")) + + if deeper_button: + deeper_button.connect("pressed", Callable(self, "_on_deeper_button_pressed")) + + if back_button: + back_button.connect("pressed", Callable(self, "_on_back_button_pressed")) + +func initialize(options = null): + game = get_node_or_null("/root/Board") as ChessGame + if game and "player" in game: + player = game.player + update_display() + +func update_display(): + if player: + if run_count_label: + run_count_label.text = "RUN #" + str(player.get_run_count() + 1) + + + if token_label: + token_label.text = str(player.tokens) + " TOKENS" + +func _on_vanilla_button_pressed(): + emit_signal("vanilla_selected") + self.visible = false + +func _on_shop_button_pressed(): + emit_signal("shop_selected") + self.visible = false + +func _on_deeper_button_pressed(): + emit_signal("deeper_selected") + self.visible = false + +func _on_back_button_pressed(): + emit_signal("back_pressed") + # self.visible = false + +func show_screen(): + initialize() + self.visible = true \ No newline at end of file diff --git a/Systems/Game/Lobby/LobbyScreen.gd.uid b/Systems/Game/Lobby/LobbyScreen.gd.uid new file mode 100644 index 0000000..6a5900e --- /dev/null +++ b/Systems/Game/Lobby/LobbyScreen.gd.uid @@ -0,0 +1 @@ +uid://dkk0eu4fj7q5j diff --git a/Systems/Game/Lobby/LobbyShop.gd.uid b/Systems/Game/Lobby/LobbyShop.gd.uid new file mode 100644 index 0000000..ff4a522 --- /dev/null +++ b/Systems/Game/Lobby/LobbyShop.gd.uid @@ -0,0 +1 @@ +uid://dlnqj0b1622gq diff --git a/Systems/Game/Lobby/LobbyShopScreen.gd b/Systems/Game/Lobby/LobbyShopScreen.gd new file mode 100644 index 0000000..4f0fcc5 --- /dev/null +++ b/Systems/Game/Lobby/LobbyShopScreen.gd @@ -0,0 +1,368 @@ +extends Control +class_name LobbyShopScreen + +signal back_pressed +signal card_purchased(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) + + 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 = player.run_count + 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_purchased", 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 = player.run_count + 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 \ No newline at end of file diff --git a/Systems/Game/Lobby/LobbyShopScreen.gd.uid b/Systems/Game/Lobby/LobbyShopScreen.gd.uid new file mode 100644 index 0000000..015b84f --- /dev/null +++ b/Systems/Game/Lobby/LobbyShopScreen.gd.uid @@ -0,0 +1 @@ +uid://nrd5mq0tfmur diff --git a/Systems/Game/Map/MapGenerator.gd b/Systems/Game/Map/MapGenerator.gd index 43b8a87..d5e4687 100644 --- a/Systems/Game/Map/MapGenerator.gd +++ b/Systems/Game/Map/MapGenerator.gd @@ -3,18 +3,21 @@ class_name ChessMapGenerator -var min_levels = 10 -var max_levels = 20 +var min_levels = 5 +var max_levels = 6 var max_connections_per_node = 4 var min_nodes_per_level = 1 var max_nodes_per_level = 4 -var positions_per_level = 6 +var positions_per_level = 4 var starting_elo = 1000 var final_elo = 2100 var current_max_level = 0; # var level_unit_distribution = ["", "", "", "nkr", "rnkr", "rnkbr", "rnqkbr", "rnqkbnr", "rnbqkbnr", "rbnqknbnr", "rnbnqknbnr", "rnbnqknbnbr", "rbnbnqknbnbr"] -var level_unit_distribution = ["", "nk", "nkr", "rnkr", "rnkr", "rnkbr", "rnqkbr", "rnqkbnr", "rnbqkbnr", "rbnqknbnr", "rnbnqknbnr"] +# var level_unit_distribution = ["", "nk", "nkr", "rnkr", "rnkr", "rnkbr", "rnqkbr", "rnqkbnr", "rnbqkbnr"] + +var level_unit_distribution = ["", "nk", "nkr", "rnkr", "rnkbr", "rnqkbr", "rnqkbnr", "rnbqkbnr"] +# ["", "nk", "nkr", "rnkr", "rnkbr", "rnqkbr", "rnqkbnr", "rnbqkbnr", "rbnqknbnr", "rnbnqknbnr", "rnbnqknbnnr", "rnnbnqknbnnr"] # ["", "", "nkr", "rnkr", "rnkr", "rnkbr", "rnqkbr", "rnqkbnr", "rnbqkbnr", "rbnqknbnr", "rnbnqknbnr", "rnbnqknbnbr", "rbnbnqknbnbr"] var _rng = RandomNumberGenerator.new() var _next_id = 0 @@ -26,7 +29,39 @@ func _init(seed_value = null): else: _rng.randomize() -func generate_map(): +func change_preset_mode(mode, player): + # var game = get_node_or_null("/root/Board") as ChessGame + # var player = game.player + var run_count = player.run_count + + match mode: + "vanilla": + min_levels = 5 + max_levels = 6 + var elo_step = Utils.VANILLA_ELO_STEP + var base_elo = Utils.MIN_ELO + run_count * elo_step + starting_elo = clamp(base_elo, Utils.MIN_ELO, Utils.MAX_ELO) + final_elo = starting_elo + elo_step + "deeper": + min_levels = 10 + max_levels = 16 + var elo_step = Utils.DEEPER_ELO_STEP + var base_elo = Utils.MIN_ELO + run_count * elo_step + starting_elo = clamp(base_elo, Utils.MIN_ELO, Utils.MAX_ELO) + final_elo = starting_elo + elo_step + _: + min_levels = 5 + max_levels = 6 + var elo_step = Utils.VANILLA_ELO_STEP + var base_elo = Utils.MIN_ELO + run_count * elo_step + starting_elo = clamp(base_elo, Utils.MIN_ELO, Utils.MAX_ELO) + final_elo = starting_elo + elo_step + + + +func generate_map(mode, player): + var isVanilla = mode == "vanilla" + change_preset_mode(mode, player) var nodes = [] var connections = [] _next_id = 0 @@ -53,11 +88,12 @@ func generate_map(): "type": Utils.RoomType.FINAL, "level": num_levels - 1, "position": Vector2(3, num_levels - 1), - "metadata": { - "is_escape": true, - }, + "metadata": {}, "elo": final_elo } + # final_node.metadata = generate_final_data(final_node) + final_node = generate_node_data(final_node) + # print("final_node ====", final_node) nodes.append(final_node) var levels_nodes = {0: [start_node], (num_levels - 1): [final_node]} @@ -170,8 +206,7 @@ func generate_map(): var isLeaf = true; for connection in valid_connections: # if theres outgoing connection we arent at a dead end - # dont change final node colour - if connection.from == valid_node.id || valid_node.id == 1: + if connection.from == valid_node.id: isLeaf = false break; valid_node.metadata.is_escape = isLeaf @@ -252,7 +287,7 @@ func generate_node_data(node): Utils.RoomType.BOSS: data.metadata = generate_boss_data(data) Utils.RoomType.FINAL: - data.metadata = generate_chess_data(data) + data.metadata = generate_final_data(data) Utils.RoomType.SHOP: data.metadata = generate_shop_data(data) Utils.RoomType.EVENT: @@ -277,6 +312,8 @@ func generate_boss_data(node): if game_type == Utils.BossType.ZERG: index = 7 height = 7 + # if index > 7: + unit_string = level_unit_distribution[index] elif game_type == Utils.BossType.DOUBLETROUBLE: index = 9 height = 9 @@ -295,10 +332,10 @@ func generate_boss_data(node): var fen = ""; # "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR" if node.level >= 7 and node.level <= 10: - height = node.level + # height = node.level enemy_unit_depth = 3 elif node.level > 10: - height = 10 + # height = 10 enemy_unit_depth = 4 for x in height - enemy_unit_depth: if x == 0: @@ -440,12 +477,78 @@ func generate_event_data(node): }, } # "rnbqkbnr1/pppppppp1/9/9/9/9/9/PPPPPPPP1/RNBQKBNR1 w KQkq - 0 1" + +func generate_final_data(node): + # level_unit_distribution + # current_max_level + var rng = float(node.level) / int(current_max_level) + # print(node.level, " ", 2, " ", current_max_level - 2, " ", 1, " ", level_unit_distribution.size() - 1) + var index = map_to_array_index(node.level, 2, current_max_level - 2, 1, level_unit_distribution.size() - 1); + # print("generate_chess_data ", index) + var unit_string = level_unit_distribution[index] + var pawn_string = "" + + for x in unit_string.length(): + pawn_string += "p" + + var height = 6; +# "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR" + var fen = ""; + if node.level > 8 and node.level <= 10: + height = node.level + elif node.level > 10: + height = 10 + for x in height - 2: + if x == 0: + fen += unit_string + "/" + elif x == 1: + fen += pawn_string + "/" + # elif x == height - 3: + # fen += "u" + # # for y in unit_string.length() - 1: + # # fen += "*" + # fen += "u/" + else: + fen += str(unit_string.length()) + "/" + + fen += pawn_string.to_upper() + "/" + unit_string.to_upper() + var fen_ending = " w KQkq - 0 1" + # print("generate_chess_data ", fen + fen_ending) + var win_condition = Utils.WinConditionType.CAPTURE_UNIT # Default + var loss_condition = Utils.LossConditionType.UNIT_LOST # Default + + # Randomly select a win condition with increasing variety at higher levels + var rng_val = _rng.randf() + var conditions_pool = [Utils.WinConditionType.CAPTURE_UNIT] # Default pool + + var additional_metadata = {} + var result = { + "is_escape": true, + "fen": fen + fen_ending, + "game_type": "chess", + "win_condition": win_condition, + "loss_condition": loss_condition, + "has_opponent": true, + "elo": node.elo, + "reward": { + "gold": 50 * node.level + } + } + # Merge additional metadata + for key in additional_metadata: + result[key] = additional_metadata[key] + + # print("final_node ", result) + return result + + func generate_chess_data(node): # level_unit_distribution # current_max_level var rng = float(node.level) / int(current_max_level) - # (current_value, min_value, max_value, min_index, max_index) + # print(node.level, " ", 2, " ", current_max_level - 2, " ", 1, " ", level_unit_distribution.size() - 1) var index = map_to_array_index(node.level, 2, current_max_level - 2, 1, level_unit_distribution.size() - 1); + # print("generate_chess_data ", index) var unit_string = level_unit_distribution[index] var pawn_string = "" diff --git a/Systems/Game/Map/MapScreen.gd b/Systems/Game/Map/MapScreen.gd index 0a9a409..b39acb7 100644 --- a/Systems/Game/Map/MapScreen.gd +++ b/Systems/Game/Map/MapScreen.gd @@ -63,14 +63,15 @@ var selected_node_panel: NodePopup = null func _ready(): # Connect back button if back_button: + back_button.visible = false; back_button.connect("pressed", Callable(self, "_on_back_button_pressed")) if deck_manager_button: deck_manager_button.connect("pressed", Callable(self, "_on_deck_button_pressed")) # Create legend create_legend() - generate_map() - display_map() + # generate_map() + # display_map() selected_node_panel = node_popup_scene.instantiate() selected_node_panel.visible = false add_child(selected_node_panel) @@ -109,13 +110,17 @@ func create_legend(): hbox.add_child(text) legend_container.add_child(hbox) -func generate_map(): +func generate_map(options): + # {"mode": options.mode} # Clear existing map + + var game = get_node_or_null("/root/Board") as ChessGame + var player = game.player map_nodes.clear() map_connections.clear() connection_lines.clear() traversed_map.clear() - var mapGen = MapGenerator.new().generate_map() + var mapGen = MapGenerator.new().generate_map(options.mode, player) # Create starting node # var start_node = { # "id": 0, @@ -184,7 +189,6 @@ func display_map(): var max_y = 0 var min_x = 9999 var max_x = 0 - # Find boundaries of the map for node_data in map_nodes: var x_pos = node_data.position.x * NODE_SPACING_X @@ -343,6 +347,7 @@ func highlight_current_node(button): button.add_theme_stylebox_override("normal", style) func _on_node_pressed(node_data): + print("SELECTED NODE", node_data) if is_node_accessible(node_data) || is_node_path_accessible(node_data): # Get node type description var node_name = get_node_type_name(node_data.type) diff --git a/Systems/Game/Menu/MenuContainer.gd b/Systems/Game/Menu/MenuContainer.gd index 9b62cb9..a9465a4 100644 --- a/Systems/Game/Menu/MenuContainer.gd +++ b/Systems/Game/Menu/MenuContainer.gd @@ -4,7 +4,7 @@ class_name MenuContainer const VERSION_FILE_PATH = "res://Game.json" # Signal to notify parent when a new game is requested # signal new_game_requested -signal reward_closed +signal reward_closed(node) signal new_game_requested(options) signal shop_open_requested(options) signal reward_open_requested(options) @@ -13,6 +13,10 @@ signal map_open_requested(options) signal node_completed(options) signal shop_closed signal card_purchased(card, price) +signal lobby_open_requested(options) +signal lobby_shop_open_requested(options) +signal vanilla_mode_selected +signal deeper_mode_selected @onready var newGameButton = $HBoxContainer/VBoxContainer/MenuOptions/NewGameText @onready var continueButton = $HBoxContainer/VBoxContainer/MenuOptions/Continue @onready var optionsButton = $HBoxContainer/VBoxContainer/MenuOptions/Options @@ -24,10 +28,14 @@ signal card_purchased(card, price) @onready var mapScreen = get_node("/root/Board/MapScreen") @onready var stateMachine = get_node("/root/Board/StateMachine") @onready var shopScreen = get_node("/root/Board/ShopScreen") -# @onready var progressionScreen = get_node("/root/Board/ProgressionScreen") +@onready var progressionScreen = get_node("/root/Board/ProgressionScreen") @onready var rewardScreen = get_node("/root/Board/RewardScreen") @onready var game = get_node_or_null("/root/Board") as ChessGame -# back up if game isn't loaded yet? +@onready var lobbyScreen = get_node_or_null("/root/Board/LobbyScreen") +@onready var lobbyShopScreen = get_node_or_null("/root/Board/LobbyShopScreen") + + + var player_gold = 10 var back_to_map = false var winConditionManager: WinConditionManager @@ -47,17 +55,20 @@ func _ready(): gameMenuScreen.connect("map_open_requested", Callable(self, "_on_map_open_requested")) gameMenuScreen.connect("new_game_requested", Callable(self, "_on_start_game_pressed")) gameMenuScreen.connect("reward_open_requested", Callable(self, "_on_reward_open_requested")) + gameMenuScreen.connect("lobby_open_requested", Callable(self, "_on_lobby_open_requested")) gameMenuScreen.visible = false else: connect("map_open_requested", Callable(self, "_on_map_open_requested")) + connect("reward_closed", Callable(self, "_on_reward_completed")) + game.connect("node_completed", Callable(self, "_on_node_completed")) if deckManagerScreen: deckManagerScreen.connect("back_pressed", Callable(self, "_on_deck_manager_back_pressed")) deckManagerScreen.visible = false - # if progressionScreen: - # progressionScreen.connect("save_pressed", Callable(self, "_on_progression_save_pressed")) - # progressionScreen.visible = false + if progressionScreen: + progressionScreen.connect("save_pressed", Callable(self, "_on_progression_save_pressed")) + progressionScreen.visible = false if mapScreen: mapScreen.connect("back_pressed", Callable(self, "_on_map_back_pressed")) mapScreen.connect("deckmanager_open_requested", Callable(self, "_on_deckmanager_open_requested_from_map")) @@ -72,6 +83,19 @@ func _ready(): rewardScreen.connect("back_pressed", Callable(self, "_on_reward_back_pressed")) rewardScreen.connect("card_purchased", Callable(self, "_on_reward_card")) rewardScreen.visible = false + if lobbyScreen: + lobbyScreen.connect("vanilla_selected", Callable(self, "_on_vanilla_selected")) + lobbyScreen.connect("shop_selected", Callable(self, "_on_lobby_shop_open_requested")) + lobbyScreen.connect("deeper_selected", Callable(self, "_on_deeper_selected")) + lobbyScreen.connect("back_pressed", Callable(self, "_on_lobby_back_pressed")) + # lobbyScreen.connect("map_open_requested", Callable(self, "_on_map_open_requested")) + lobbyScreen.visible = false + + if lobbyShopScreen: + lobbyShopScreen.connect("back_pressed", Callable(self, "_on_lobby_shop_back_pressed")) + lobbyShopScreen.connect("card_purchased", Callable(self, "_on_lobby_shop_card_purchased")) + lobbyShopScreen.connect("hand_size_increased", Callable(self, "_on_hand_size_increased")) + lobbyShopScreen.visible = false load_version() @@ -118,10 +142,66 @@ func _on_new_game_pressed(): self.visible = false if gameMenuScreen: gameMenuScreen.visible = true - # self.visible = false + # _on_map_open_requested({}) # emit_signal("new_game_requested") + + +func _on_lobby_open_requested(options): + print("Lobby requested with options:", options) + if gameMenuScreen: + gameMenuScreen.visible = false + if lobbyScreen: + lobbyScreen.visible = true + lobbyScreen.initialize(options) + lobbyScreen.show_screen() + print("_on_lobby_open_requested" ) + +func _on_lobby_back_pressed(): + if lobbyScreen: + lobbyScreen.visible = false + self.visible = true + +func _on_vanilla_selected(): + print("Vanilla mode selected") + if gameMenuScreen: + gameMenuScreen.visible = true + _on_map_open_requested({"mode": "vanilla", "hand_size": 2, }) + # emit_signal("vanilla_mode_selected") + +func _on_deeper_selected(): + print("Deeper mode selected") + if gameMenuScreen: + gameMenuScreen.visible = true + _on_map_open_requested({"mode": "deeper", "hand_size": game.player.hand_size,}) + +func _on_lobby_shop_open_requested(options): + print("Lobby Shop requested with options:", options) + if lobbyScreen: + lobbyScreen.visible = false + if lobbyShopScreen: + lobbyShopScreen.visible = true + lobbyShopScreen.initialize(options) + emit_signal("lobby_shop_open_requested", options) + +func _on_lobby_shop_back_pressed(): + if lobbyShopScreen: + lobbyShopScreen.visible = false + if lobbyScreen: + lobbyScreen.visible = true + +func _on_lobby_shop_card_purchased(card, token_cost): + # Add the card to the player's bank + if game and "deckManager" in game: + var deck_manager = game.deckManager + deck_manager.bank.append(card) + print("Added purchased card to bank:", card.cardName) + +func _on_hand_size_increased(): + print("Hand size increased") + + # Handle Continue button press func _on_continue_pressed(): print("Continue pressed") @@ -188,15 +268,15 @@ func _on_reward_open_requested(options): options = {} - if "gold" in options: - options["gold"] = game.player.get_gold() + if "gold" in options.metadata: + options.metadata["gold"] = game.player.get_gold() if rewardScreen: rewardScreen.visible = true rewardScreen.initialize(options) emit_signal("reward_open_requested", options) -func _on_reward_back_pressed(): +func _on_reward_back_pressed(completed_node): if rewardScreen: rewardScreen.visible = false @@ -204,8 +284,9 @@ func _on_reward_back_pressed(): gameMenuScreen.visible = true if back_to_map: mapScreen.visible = true - # Emit signal that shop was closed - emit_signal("reward_closed") + print("DONE: ", completed_node) + var is_escape = completed_node.metadata.is_escape + emit_signal("reward_closed", completed_node) func _on_reward_card(card, price): # Forward the signal @@ -218,6 +299,24 @@ func _on_reward_card(card, price): print("Added reward card to bank:", card.cardName) +func _on_reward_completed(completed_node): + var is_escape = completed_node.metadata.is_escape + if progressionScreen and is_escape: + progressionScreen.initialize({"max_deck_size": 10, "node": completed_node}) + if completed_node.type == Utils.RoomType.FINAL: + game.player.add_tokens(1) + progressionScreen.visible = true + + + +func _on_progression_save_pressed(): + print("_on_progression_save_pressed") + progressionScreen.visible = false + gameMenuScreen.visible = false + _on_lobby_open_requested(null) + + + func _on_deckmanager_open_requested_from_map(options): print("Deck Manager requested with options:", options) @@ -257,17 +356,15 @@ func _on_deck_manager_back_pressed(): else: mapScreen.visible = true - -# func _on_progression_save_pressed(): -# progressionScreen.visible = false -# gameMenuScreen.visible = true - - - +# _on_map_open_requested({"mode": "deep", "hand_size": game.player.hand_size,}) func _on_map_open_requested(options): print("Map requested with options:", options) gameMenuScreen.visible = false + if "hand_size" in options: + game.player.update_deck_hand_size(options.hand_size) if mapScreen: + mapScreen.generate_map({"mode": options.mode}) + mapScreen.display_map() mapScreen.visible = true emit_signal("map_open_requested", options) @@ -284,9 +381,21 @@ func _on_map_back_pressed(): func _on_map_node_selected(node_data): print("Selected map node: ", node_data) if node_data.type == Utils.RoomType.SHOP: + print("Utils.RoomType.SHOP") back_to_map = true _on_shop_open_requested(node_data.metadata) + elif node_data.type == Utils.RoomType.FINAL: + print("Utils.RoomType.FINAL") + if gameMenuScreen: + gameMenuScreen.visible = false + if deckManagerScreen: + deckManagerScreen.visible = false + if mapScreen: + mapScreen.visible = false + back_to_map = true + _on_start_game_pressed(node_data) elif node_data.type == Utils.RoomType.NORMAL: + print("Utils.RoomType.NORMAL") if gameMenuScreen: gameMenuScreen.visible = false if deckManagerScreen: @@ -296,6 +405,7 @@ func _on_map_node_selected(node_data): back_to_map = true _on_start_game_pressed(node_data) elif node_data.type == Utils.RoomType.BOSS: + print("Utils.RoomType.BOSS") if gameMenuScreen: gameMenuScreen.visible = false if deckManagerScreen: @@ -305,6 +415,7 @@ func _on_map_node_selected(node_data): back_to_map = true _on_start_game_pressed(node_data) elif node_data.type == Utils.RoomType.EVENT: + print("Utils.RoomType.EVENT") if gameMenuScreen: gameMenuScreen.visible = false if deckManagerScreen: @@ -319,7 +430,7 @@ func _on_node_completed(options): var completed = options.completed var success = options.success if success: - _on_reward_open_requested(node_data.metadata) + _on_reward_open_requested(node_data) print("**********************************") print("**********************************") print("**********************************") diff --git a/Systems/Game/Player/Player.gd b/Systems/Game/Player/Player.gd index a50410a..320878f 100644 --- a/Systems/Game/Player/Player.gd +++ b/Systems/Game/Player/Player.gd @@ -7,6 +7,8 @@ var hand_size: int = 2 var gold: int = 70 var tokens: int = 0 var game: ChessGame +var run_count: int = 0 +const MAX_HAND_SIZE = 5 func _init(g: int, size: int, tok: int, gm: ChessGame): @@ -14,14 +16,34 @@ func _init(g: int, size: int, tok: int, gm: ChessGame): gold = g tokens = tok game = gm + hand_size = size update_deck_hand_size(size) func update_deck_hand_size(size: int): - hand_size = size if "deckManager" in game: game.deckManager.set_hand_size(hand_size) +func set_hand_size(size: int): + hand_size = size + +func get_tokens() -> int: + return tokens + +func set_tokens(amount: int) -> void: + tokens = amount + +func remove_tokens(amount: int) -> void: + tokens = max(0, tokens - amount) + +func add_tokens(t: int) -> void : + tokens += t + +func increment_runs() -> void : + run_count += 1 + +func get_run_count() -> int : + return run_count func get_gold() -> int : return gold @@ -33,4 +55,4 @@ func remove_gold(g: int) -> void : gold -= g func set_gold(g: int) -> void : - gold = g \ No newline at end of file + gold = g diff --git a/Systems/Game/ProgressionScreen.gd b/Systems/Game/ProgressionScreen.gd index 2409dd4..8b97d7b 100644 --- a/Systems/Game/ProgressionScreen.gd +++ b/Systems/Game/ProgressionScreen.gd @@ -11,6 +11,7 @@ signal deck_manager_visibility_changed(isvisible) var maxDeckSize = 10 var deckManager = null +var game = null var bankCards = [] # All Users card # The current deck @@ -34,6 +35,7 @@ func initialize(options = null): # Find the DeckManager instance var board = get_node_or_null("/root/Board") as ChessGame + game = board if board and "deckManager" in board: deckManager = board.deckManager print("Found deck manager:", deckManager) @@ -60,7 +62,8 @@ func loadCards(): if deckManager: # Clone the deck to work with currentDeck = [] - bankCards = deckManager.bank.duplicate().append_array(deckManager.deck.duplicate()) + bankCards = deckManager.bank.duplicate() + bankCards.append_array(deckManager.deck.duplicate()) else: # Fallback with empty collections if deck manager not found currentDeck = [] @@ -185,17 +188,41 @@ func hide_card_preview(): current_preview_card = null card_preview.hide_preview() -func saveDeck(): +func save_deck(): + sell_remaining_cards() if deckManager: # Save the current deck to the deck manager deckManager.deck = currentDeck.duplicate() deckManager.bank = [] print("Deck saved with ", currentDeck.size(), " cards") + if game.player: + game.player.increment_runs() + +func sell_remaining_cards(): + for card in bankCards: + sell_selected_card(card) + bankCards.clear() + +func get_card_price(card): + if not card: + return 0 + if card.rank in Utils.CardPrices: + return Utils.CardPrices[card.rank] + return 50 + + +func sell_selected_card(selected_card): + + var price = get_card_price(selected_card) + + game.player.add_gold(price) + + return true func _on_save_button_pressed(): # Save changes before returning - saveDeck() + save_deck() # Emit signal to go back emit_signal("save_pressed") @@ -220,4 +247,4 @@ func _on_visibility_changed(is_visible): else: print("DeckManager is now invisible") - emit_signal("deck_manager_visibility_changed", is_visible) \ No newline at end of file + emit_signal("deck_manager_visibility_changed", is_visible) diff --git a/Systems/Game/Shop/RewardScreen.gd b/Systems/Game/Shop/RewardScreen.gd index 27e722e..997e047 100644 --- a/Systems/Game/Shop/RewardScreen.gd +++ b/Systems/Game/Shop/RewardScreen.gd @@ -1,7 +1,7 @@ extends Control class_name RewardScreen -signal back_pressed +signal back_pressed(node) signal card_purchased(card, price) # Node references @@ -62,14 +62,15 @@ func _ready(): update_select_button() update_navigation_buttons() -func initialize(options = null): - print("RewardScreen ", options) +func initialize(node_data = null): + print("RewardScreen ", node_data) carousel_page = 0 selected_index = 0 var board = get_node_or_null("/root/Board") as ChessGame if board and "deckManager" in board: deckManager = board.deckManager - + var options = node_data.metadata + selected_node = node_data # Process options if provided if options: if options.has("gold") and options.gold is int: @@ -221,7 +222,7 @@ func get_selected_card(): # Signal handlers func _on_back_button_pressed(): - emit_signal("back_pressed") + emit_signal("back_pressed", selected_node) visible = false func _on_select_button_pressed(): diff --git a/Systems/Game/Shop/ShopScreen.gd b/Systems/Game/Shop/ShopScreen.gd index 6351870..47f852d 100644 --- a/Systems/Game/Shop/ShopScreen.gd +++ b/Systems/Game/Shop/ShopScreen.gd @@ -25,12 +25,7 @@ var card_instance_map = {} var hovering_card_index = -1 var mouse_over_any_card = false # Card prices by rank -var card_prices = { - Card.Rank.RANK_0: 200, # Legendary (Rank 0) - Card.Rank.RANK_1: 100, # Rare (Rank 1) - Card.Rank.RANK_2: 50, # Uncommon (Rank 2) - Card.Rank.RANK_3: 25 # Common (Rank 3) -} +var card_prices = Utils.CardPrices func _ready(): if back_button: diff --git a/Utils/Utils.gd b/Utils/Utils.gd index 5f7dbf4..3433bf0 100644 --- a/Utils/Utils.gd +++ b/Utils/Utils.gd @@ -52,6 +52,13 @@ static func location_to_algebraic(location: String, maxRank: int) -> String: return file + rank +static var MAX_ELO = 2300 +static var MIN_ELO = 500 + +static var VANILLA_ELO_STEP = 100 +static var DEEPER_ELO_STEP = 250 + + static var LIGHT_CELL = Color(0.5, 0.5, 0.5, 1) static var DARK_CELL = Color(0.2, 0.2, 0.2, 1) static var GREEN_CELL = Color(0.36, 0.62, 0.43, 1) @@ -94,4 +101,28 @@ static var CardTypes = [ DoubleTimeCard, DrunkDrivingCard, SupernovaCard -] \ No newline at end of file +] + +static var CardPrices = { + Card.Rank.RANK_0: 200, # Legendary (Rank 0) + Card.Rank.RANK_1: 100, # Rare (Rank 1) + Card.Rank.RANK_2: 50, # Uncommon (Rank 2) + Card.Rank.RANK_3: 25 # Common (Rank 3) +} + +static var TokenCosts = { + 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) +} + +static var Fibonacci = [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144] + +# Calculate the token cost for increasing hand size +static func calculate_hand_size_cost(run_count: int) -> int: + var fib_index = run_count + 3 + if fib_index >= Fibonacci.size(): + fib_index = Fibonacci.size() - 1 + + return Fibonacci[fib_index] \ No newline at end of file diff --git a/board.tscn b/board.tscn index 3fbb612..8a76c31 100644 --- a/board.tscn +++ b/board.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=32 format=3 uid="uid://d0qyk6v20uief"] +[gd_scene load_steps=35 format=3 uid="uid://d0qyk6v20uief"] [ext_resource type="Script" uid="uid://cbcu68o863pfp" path="res://Systems/Game/ChessGame.gd" id="1_fkb2r"] [ext_resource type="Script" uid="uid://d2bfw6edgkhfa" path="res://Systems/StateMachine/GameStates/WhiteTurn.gd" id="3_276ip"] @@ -31,6 +31,9 @@ [ext_resource type="PackedScene" uid="uid://dxiw67f3rrwue" path="res://map_screen.tscn" id="29_y7cv2"] [ext_resource type="PackedScene" uid="uid://djw7jhwtnycxq" path="res://shop_screen.tscn" id="30_5rfmq"] [ext_resource type="PackedScene" uid="uid://tmrvgfwodpno" path="res://reward_screen.tscn" id="31_d2oob"] +[ext_resource type="PackedScene" uid="uid://c6cgcs22ox0no" path="res://progression_screen.tscn" id="32_eq1pg"] +[ext_resource type="PackedScene" uid="uid://depsrpx00pnl5" path="res://lobby_shop_screen.tscn" id="33_ccaoj"] +[ext_resource type="PackedScene" uid="uid://c1u88sbx0am7b" path="res://lobby_screen.tscn" id="34_yqcr4"] [node name="Board" type="Control"] layout_mode = 3 @@ -328,10 +331,11 @@ deselect_on_focus_loss_enabled = false drag_and_drop_selection_enabled = false script = ExtResource("26_t2e38") -[node name="ManageDeckText" type="RichTextLabel" parent="GameMenuScreen/HBoxContainer/VBoxContainer/GameOptions"] +[node name="LobbyText" type="RichTextLabel" parent="GameMenuScreen/HBoxContainer/VBoxContainer/GameOptions"] layout_mode = 2 theme = ExtResource("24_4y4dr") -text = "Manage Deck" +text = "Lobby +" fit_content = true scroll_active = false autowrap_mode = 0 @@ -409,3 +413,15 @@ anchors_preset = 0 [node name="RewardScreen" parent="." instance=ExtResource("31_d2oob")] visible = false layout_mode = 1 + +[node name="ProgressionScreen" parent="." instance=ExtResource("32_eq1pg")] +visible = false +layout_mode = 1 + +[node name="LobbyShopScreen" parent="." instance=ExtResource("33_ccaoj")] +visible = false +layout_mode = 1 + +[node name="LobbyScreen" parent="." instance=ExtResource("34_yqcr4")] +visible = false +layout_mode = 1 diff --git a/card_preview_panel.tscn b/card_preview_panel.tscn index ab232d7..50ca27a 100644 --- a/card_preview_panel.tscn +++ b/card_preview_panel.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=3 format=3 uid="uid://xxxxadwawdxxxx"] +[gd_scene load_steps=3 format=3 uid="uid://xxxxxxxx"] [ext_resource type="Script" uid="uid://2xcreiq6lhe2" path="res://Systems/CardPreviewPanel.gd" id="1_ykslh"] diff --git a/deck_manager_screen.tscn b/deck_manager_screen.tscn index a6b0155..3a06098 100644 --- a/deck_manager_screen.tscn +++ b/deck_manager_screen.tscn @@ -1,7 +1,7 @@ [gd_scene load_steps=4 format=3 uid="uid://c7uqbcxdjoais"] [ext_resource type="Script" uid="uid://vxufsih5pgeu" path="res://Systems/Game/DeckManagerScreen.gd" id="1_gokg4"] -[ext_resource type="PackedScene" uid="uid://xxxxadwawdxxxx" path="res://card_preview_panel.tscn" id="3_abcde"] +[ext_resource type="PackedScene" uid="uid://b128n53ivvwcv" path="res://card_preview_panel.tscn" id="3_abcde"] [ext_resource type="Script" uid="uid://bfjmon81nckns" path="res://Systems/Game/GameMenuButton.gd" id="4_gokg4"] [node name="DeckManagerScreen" type="Control"] diff --git a/lobby_screen.tscn b/lobby_screen.tscn new file mode 100644 index 0000000..cc63a2e --- /dev/null +++ b/lobby_screen.tscn @@ -0,0 +1,161 @@ +[gd_scene load_steps=5 format=3 uid="uid://c1u88sbx0am7b"] + +[ext_resource type="Script" uid="uid://dkk0eu4fj7q5j" path="res://Systems/Game/Lobby/LobbyScreen.gd" id="1_pmnho"] +[ext_resource type="Script" uid="uid://bfjmon81nckns" path="res://Systems/Game/GameMenuButton.gd" id="2_uhnf6"] + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_kvmw1"] +bg_color = Color(0.14902, 0.14902, 0.2, 1) +border_width_left = 2 +border_width_top = 2 +border_width_right = 2 +border_width_bottom = 2 +border_color = Color(0.2, 0.2, 0.3, 1) +corner_radius_top_left = 10 +corner_radius_top_right = 10 +corner_radius_bottom_right = 10 +corner_radius_bottom_left = 10 + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_bmpt2"] +bg_color = Color(0.14902, 0.14902, 0.2, 1) +corner_radius_top_left = 5 +corner_radius_top_right = 5 +corner_radius_bottom_right = 5 +corner_radius_bottom_left = 5 + +[node name="LobbyScreen" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_pmnho") + +[node name="Background" type="ColorRect" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +color = Color(0.08, 0.08, 0.12, 1) + +[node name="TopBar" type="HBoxContainer" parent="."] +layout_mode = 1 +anchors_preset = 10 +anchor_right = 1.0 +offset_top = 20.0 +offset_bottom = 80.0 +grow_horizontal = 2 + +[node name="RunCountLabel" type="Label" parent="TopBar"] +layout_mode = 2 +size_flags_horizontal = 3 +theme_override_font_sizes/font_size = 36 +text = "RUN #1" +horizontal_alignment = 1 + +[node name="TokenContainer" type="HBoxContainer" parent="TopBar"] +layout_mode = 2 +size_flags_horizontal = 3 +alignment = 2 + +[node name="TokenLabel" type="Label" parent="TopBar/TokenContainer"] +layout_mode = 2 +theme_override_font_sizes/font_size = 24 +text = "0 TOKENS" + +[node name="Spacer" type="Control" parent="TopBar/TokenContainer"] +custom_minimum_size = Vector2(20, 0) +layout_mode = 2 + +[node name="CenterContainer" type="Control" parent="."] +layout_mode = 1 +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -150.0 +offset_top = -150.0 +offset_right = 150.0 +offset_bottom = 150.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="ShopPanel" type="Panel" parent="CenterContainer"] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +theme_override_styles/panel = SubResource("StyleBoxFlat_kvmw1") + +[node name="ShopButton" type="Button" parent="CenterContainer"] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +flat = true + +[node name="Label" type="Label" parent="CenterContainer"] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +theme_override_font_sizes/font_size = 48 +text = "SHOP" +horizontal_alignment = 1 +vertical_alignment = 1 + +[node name="BottomContainer" type="HBoxContainer" parent="."] +layout_mode = 1 +anchors_preset = 12 +anchor_top = 1.0 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_top = -100.0 +offset_bottom = -20.0 +grow_horizontal = 2 +grow_vertical = 0 +theme_override_constants/separation = 20 +alignment = 1 + +[node name="VanillaButton" type="Button" parent="BottomContainer"] +custom_minimum_size = Vector2(300, 80) +layout_mode = 2 +size_flags_horizontal = 3 +theme_override_font_sizes/font_size = 24 +theme_override_styles/normal = SubResource("StyleBoxFlat_bmpt2") +text = "VANILLA" + +[node name="Spacer" type="Control" parent="BottomContainer"] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="DeeperButton" type="Button" parent="BottomContainer"] +custom_minimum_size = Vector2(300, 80) +layout_mode = 2 +size_flags_horizontal = 3 +theme_override_font_sizes/font_size = 24 +theme_override_styles/normal = SubResource("StyleBoxFlat_bmpt2") +text = "DEEPER" + +[node name="BackButton" type="RichTextLabel" parent="."] +custom_minimum_size = Vector2(100, 40) +layout_mode = 2 +offset_left = 10.0 +offset_top = 488.0 +offset_right = 110.0 +offset_bottom = 528.0 +size_flags_horizontal = 0 +size_flags_vertical = 4 +text = "BACK" +horizontal_alignment = 1 +vertical_alignment = 2 +script = ExtResource("2_uhnf6") diff --git a/lobby_shop_screen.tscn b/lobby_shop_screen.tscn new file mode 100644 index 0000000..b85847b --- /dev/null +++ b/lobby_shop_screen.tscn @@ -0,0 +1,188 @@ +[gd_scene load_steps=6 format=3 uid="uid://depsrpx00pnl5"] + +[ext_resource type="Script" uid="uid://nrd5mq0tfmur" path="res://Systems/Game/Lobby/LobbyShopScreen.gd" id="1_bdrsx"] +[ext_resource type="Script" uid="uid://bfjmon81nckns" path="res://Systems/Game/GameMenuButton.gd" id="2_pq3rv"] +[ext_resource type="PackedScene" uid="uid://xxxxxxxx" path="res://card_preview_panel.tscn" id="3_cuwn5"] + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_xsd3f"] +bg_color = Color(0.14902, 0.14902, 0.2, 1) +border_width_left = 2 +border_width_top = 2 +border_width_right = 2 +border_width_bottom = 2 +border_color = Color(0.2, 0.2, 0.25, 1) +corner_radius_top_left = 8 +corner_radius_top_right = 8 +corner_radius_bottom_right = 8 +corner_radius_bottom_left = 8 + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_jk2fb"] +bg_color = Color(0.14902, 0.14902, 0.2, 1) +corner_radius_top_left = 5 +corner_radius_top_right = 5 +corner_radius_bottom_right = 5 +corner_radius_bottom_left = 5 + +[node name="LobbyShop" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_bdrsx") + +[node name="Background" type="ColorRect" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +color = Color(0.08, 0.08, 0.12, 1) + +[node name="TopBar" type="HBoxContainer" parent="."] +layout_mode = 1 +anchors_preset = 10 +anchor_right = 1.0 +offset_top = 20.0 +offset_bottom = 80.0 +grow_horizontal = 2 + +[node name="TitleLabel" type="Label" parent="TopBar"] +layout_mode = 2 +size_flags_horizontal = 3 +theme_override_font_sizes/font_size = 36 +text = "LOBBY SHOP" +horizontal_alignment = 1 + +[node name="TokenContainer" type="HBoxContainer" parent="TopBar"] +layout_mode = 2 +size_flags_horizontal = 3 +alignment = 2 + +[node name="TokenLabel" type="Label" parent="TopBar/TokenContainer"] +layout_mode = 2 +theme_override_font_sizes/font_size = 24 +text = "10 TOKENS" + +[node name="Spacer" type="Control" parent="TopBar/TokenContainer"] +custom_minimum_size = Vector2(20, 0) +layout_mode = 2 + +[node name="CardPreviewPanel" parent="." instance=ExtResource("3_cuwn5")] +layout_mode = 1 +anchors_preset = 4 +anchor_top = 0.5 +anchor_right = 0.0 +anchor_bottom = 0.5 +offset_left = 20.0 +offset_top = -200.0 +offset_right = 320.0 +offset_bottom = 200.0 +grow_horizontal = 1 + +[node name="MainContainer" type="VBoxContainer" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_left = 340.0 +offset_top = 100.0 +offset_right = -20.0 +offset_bottom = -100.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="CardCarouselContainer" type="HBoxContainer" parent="MainContainer"] +layout_mode = 2 +size_flags_vertical = 3 +alignment = 1 + +[node name="LeftButton" type="Button" parent="MainContainer/CardCarouselContainer"] +custom_minimum_size = Vector2(40, 0) +layout_mode = 2 +size_flags_vertical = 4 +theme_override_font_sizes/font_size = 24 +text = "←" + +[node name="CardCarousel" type="HBoxContainer" parent="MainContainer/CardCarouselContainer"] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 +theme_override_constants/separation = 20 +alignment = 1 + +[node name="RightButton" type="Button" parent="MainContainer/CardCarouselContainer"] +custom_minimum_size = Vector2(40, 0) +layout_mode = 2 +size_flags_vertical = 4 +theme_override_font_sizes/font_size = 24 +text = "→" + +[node name="HandSizeContainer" type="HBoxContainer" parent="."] +layout_mode = 1 +anchors_preset = 12 +anchor_top = 1.0 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_left = 340.0 +offset_top = -170.0 +offset_right = -20.0 +offset_bottom = -110.0 +grow_horizontal = 2 +grow_vertical = 0 +alignment = 1 + +[node name="Panel" type="Panel" parent="HandSizeContainer"] +layout_mode = 2 +size_flags_horizontal = 3 +theme_override_styles/panel = SubResource("StyleBoxFlat_xsd3f") + +[node name="HandSizeLabel" type="Label" parent="HandSizeContainer"] +layout_mode = 2 +size_flags_horizontal = 3 +theme_override_font_sizes/font_size = 24 +text = "HAND SIZE: 2" +horizontal_alignment = 1 +vertical_alignment = 1 + +[node name="CostLabel" type="Label" parent="HandSizeContainer"] +layout_mode = 2 +size_flags_horizontal = 3 +theme_override_font_sizes/font_size = 20 +text = "Cost: 3 tokens" +horizontal_alignment = 1 +vertical_alignment = 1 + +[node name="IncreaseButton" type="Button" parent="HandSizeContainer"] +custom_minimum_size = Vector2(60, 60) +layout_mode = 2 +theme_override_font_sizes/font_size = 36 +text = "+" + +[node name="BackButton" type="RichTextLabel" parent="."] +custom_minimum_size = Vector2(100, 40) +layout_mode = 2 +offset_top = 578.0 +offset_right = 100.0 +offset_bottom = 618.0 +size_flags_horizontal = 0 +size_flags_vertical = 4 +text = "BACK" +horizontal_alignment = 1 +vertical_alignment = 2 +script = ExtResource("2_pq3rv") + +[node name="BuyButton" type="Button" parent="."] +custom_minimum_size = Vector2(200, 50) +layout_mode = 2 +offset_left = 952.0 +offset_top = 533.0 +offset_right = 1152.0 +offset_bottom = 583.0 +size_flags_horizontal = 8 +size_flags_vertical = 4 +theme_override_font_sizes/font_size = 18 +theme_override_styles/normal = SubResource("StyleBoxFlat_jk2fb") +text = "BUY (3 tokens)" diff --git a/progression_screen.tscn b/progression_screen.tscn index a32a89b..156d8e8 100644 --- a/progression_screen.tscn +++ b/progression_screen.tscn @@ -1,7 +1,7 @@ [gd_scene load_steps=4 format=3 uid="uid://c6cgcs22ox0no"] [ext_resource type="Script" uid="uid://dbohdt174pual" path="res://Systems/Game/ProgressionScreen.gd" id="1_gokg4"] -[ext_resource type="PackedScene" uid="uid://b128n53ivvwcv" path="res://card_preview_panel.tscn" id="2_srvl8"] +[ext_resource type="PackedScene" uid="uid://xxxxxxxx" path="res://card_preview_panel.tscn" id="2_srvl8"] [ext_resource type="Script" uid="uid://bfjmon81nckns" path="res://Systems/Game/GameMenuButton.gd" id="4_gokg4"] [node name="ProgressionScreen" type="Control"] diff --git a/reward_screen.tscn b/reward_screen.tscn index 9664c3f..2de0960 100644 --- a/reward_screen.tscn +++ b/reward_screen.tscn @@ -1,7 +1,7 @@ [gd_scene load_steps=5 format=3 uid="uid://tmrvgfwodpno"] [ext_resource type="Script" uid="uid://ccy6bx6kiejjy" path="res://Systems/Game/Shop/RewardScreen.gd" id="1_c5sfe"] -[ext_resource type="PackedScene" uid="uid://b128n53ivvwcv" path="res://card_preview_panel.tscn" id="2_1dq2e"] +[ext_resource type="PackedScene" uid="uid://xxxxxxxx" path="res://card_preview_panel.tscn" id="2_1dq2e"] [ext_resource type="Script" uid="uid://bfjmon81nckns" path="res://Systems/Game/GameMenuButton.gd" id="3_2qq52"] [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_jk2fb"] diff --git a/shop_screen.tscn b/shop_screen.tscn index 9786892..bc7efef 100644 --- a/shop_screen.tscn +++ b/shop_screen.tscn @@ -2,7 +2,7 @@ [ext_resource type="Script" uid="uid://rqkucvk8au68" path="res://Systems/Game/Shop/ShopScreen.gd" id="1_aoepi"] [ext_resource type="Script" uid="uid://bfjmon81nckns" path="res://Systems/Game/GameMenuButton.gd" id="2_mkl0p"] -[ext_resource type="PackedScene" uid="uid://b128n53ivvwcv" path="res://card_preview_panel.tscn" id="3_yh3xu"] +[ext_resource type="PackedScene" uid="uid://xxxxxxxx" path="res://card_preview_panel.tscn" id="3_yh3xu"] [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_jk2fb"] bg_color = Color(0.14902, 0.14902, 0.2, 1)