init game files

This commit is contained in:
2026-01-24 16:29:11 -05:00
commit ea2028cf13
171 changed files with 191733 additions and 0 deletions

View File

@@ -0,0 +1,286 @@
extends Node
## GameManager - Main game coordinator singleton
## Bridges game state, visuals, and UI
signal game_ready
signal game_started
signal game_ended(winner_name: String)
signal turn_changed(player_name: String, turn_number: int)
signal phase_changed(phase_name: String)
signal card_played(card_data: Dictionary)
signal damage_dealt(player_name: String, amount: int)
signal message(text: String)
# Game state
var game_state: GameState = null
# State flags
var is_initialized: bool = false
var is_game_active: bool = false
# Current input mode
enum InputMode {
NONE,
SELECT_CARD_TO_PLAY,
SELECT_CP_SOURCE,
SELECT_ATTACKER,
SELECT_BLOCKER,
SELECT_TARGET
}
var input_mode: InputMode = InputMode.NONE
# Selection tracking
var selected_card: CardInstance = null
var pending_action: Callable = func(): pass
func _ready() -> void:
# Wait for CardDatabase to load
if CardDatabase.get_all_cards().size() == 0:
CardDatabase.database_loaded.connect(_on_database_loaded)
else:
_on_database_loaded()
func _on_database_loaded() -> void:
is_initialized = true
game_ready.emit()
print("GameManager: Ready")
## Start a new game
func start_new_game() -> void:
if not is_initialized:
push_error("GameManager not initialized")
return
# Create new game state
game_state = GameState.new()
# Connect signals
_connect_game_signals()
# Create test decks
var deck1 = CardDatabase.create_test_deck(0)
var deck2 = CardDatabase.create_test_deck(1)
# Setup and start
game_state.setup_game(deck1, deck2)
game_state.start_game()
is_game_active = true
game_started.emit()
message.emit("Game started!")
## Connect to game state signals
func _connect_game_signals() -> void:
game_state.game_ended.connect(_on_game_ended)
game_state.card_played.connect(_on_card_played)
game_state.damage_dealt.connect(_on_damage_dealt)
game_state.forward_broken.connect(_on_forward_broken)
game_state.attack_declared.connect(_on_attack_declared)
game_state.block_declared.connect(_on_block_declared)
game_state.combat_resolved.connect(_on_combat_resolved)
game_state.turn_manager.turn_changed.connect(_on_turn_changed)
game_state.turn_manager.phase_changed.connect(_on_phase_changed)
## Get current player
func get_current_player() -> Player:
if game_state:
return game_state.get_current_player()
return null
## Get opponent
func get_opponent() -> Player:
if game_state:
return game_state.get_opponent()
return null
## Check if it's a specific player's turn
func is_player_turn(player_index: int) -> bool:
if game_state:
return game_state.turn_manager.current_player_index == player_index
return false
## Get current phase
func get_current_phase() -> Enums.TurnPhase:
if game_state:
return game_state.turn_manager.current_phase
return Enums.TurnPhase.ACTIVE
## Try to play a card
func try_play_card(card: CardInstance) -> bool:
if not game_state or not is_game_active:
return false
var player_index = card.controller_index
if not is_player_turn(player_index):
message.emit("Not your turn!")
return false
if not game_state.turn_manager.is_main_phase():
message.emit("Can only play cards during Main Phase!")
return false
var player = game_state.get_player(player_index)
# Check if we can afford the card
if not player.cp_pool.can_afford_card(card.card_data):
message.emit("Not enough CP!")
# Enter CP generation mode
input_mode = InputMode.SELECT_CP_SOURCE
selected_card = card
return false
# Try to play
if game_state.play_card(player_index, card):
message.emit("Played " + card.get_display_name())
return true
else:
message.emit("Cannot play that card!")
return false
## Discard a card to generate CP
func discard_card_for_cp(card: CardInstance) -> bool:
if not game_state or not is_game_active:
return false
var player_index = card.owner_index
if game_state.discard_for_cp(player_index, card):
message.emit("Discarded " + card.get_display_name() + " for 2 CP")
_check_pending_action()
return true
return false
## Dull a backup to generate CP
func dull_backup_for_cp(card: CardInstance) -> bool:
if not game_state or not is_game_active:
return false
var player_index = card.controller_index
if game_state.dull_backup_for_cp(player_index, card):
message.emit("Dulled " + card.get_display_name() + " for 1 CP")
_check_pending_action()
return true
return false
## Check if we can now afford the pending card
func _check_pending_action() -> void:
if input_mode == InputMode.SELECT_CP_SOURCE and selected_card:
var player = game_state.get_player(selected_card.controller_index)
if player.cp_pool.can_afford_card(selected_card.card_data):
# Can now afford - try to play
try_play_card(selected_card)
clear_selection()
## Declare an attack
func declare_attack(card: CardInstance) -> bool:
if not game_state or not is_game_active:
return false
if game_state.declare_attack(card):
input_mode = InputMode.SELECT_BLOCKER
return true
return false
## Declare a block
func declare_block(card: CardInstance) -> bool:
if not game_state or not is_game_active:
return false
if game_state.declare_block(card):
game_state.resolve_combat()
input_mode = InputMode.SELECT_ATTACKER
return true
return false
## Skip blocking
func skip_block() -> bool:
if not game_state or not is_game_active:
return false
if game_state.skip_block():
game_state.resolve_combat()
input_mode = InputMode.SELECT_ATTACKER
return true
return false
## Pass priority / end current phase
func pass_priority() -> void:
if not game_state or not is_game_active:
return
var phase = game_state.turn_manager.current_phase
match phase:
Enums.TurnPhase.MAIN_1, Enums.TurnPhase.MAIN_2:
game_state.end_main_phase()
Enums.TurnPhase.ATTACK:
if game_state.turn_manager.attack_step == Enums.AttackStep.DECLARATION:
game_state.end_attack_phase()
elif game_state.turn_manager.attack_step == Enums.AttackStep.BLOCK_DECLARATION:
skip_block()
clear_selection()
## Clear current selection
func clear_selection() -> void:
input_mode = InputMode.NONE
selected_card = null
pending_action = func(): pass
## Signal handlers
func _on_game_ended(winner_index: int) -> void:
is_game_active = false
var winner_name = game_state.get_player(winner_index).player_name
game_ended.emit(winner_name)
message.emit(winner_name + " wins!")
func _on_card_played(card: CardInstance, _player_index: int) -> void:
card_played.emit({
"name": card.get_display_name(),
"type": Enums.card_type_to_string(card.card_data.type)
})
func _on_damage_dealt(player_index: int, amount: int, _cards: Array) -> void:
var player_name = game_state.get_player(player_index).player_name
damage_dealt.emit(player_name, amount)
message.emit(player_name + " takes " + str(amount) + " damage!")
func _on_forward_broken(card: CardInstance) -> void:
message.emit(card.get_display_name() + " was broken!")
func _on_attack_declared(attacker: CardInstance) -> void:
message.emit(attacker.get_display_name() + " attacks!")
func _on_block_declared(blocker: CardInstance) -> void:
message.emit(blocker.get_display_name() + " blocks!")
func _on_combat_resolved(_attacker: CardInstance, blocker: CardInstance) -> void:
if blocker == null:
message.emit("Attack hits!")
else:
message.emit("Combat resolved!")
func _on_turn_changed(player_index: int) -> void:
var player = game_state.get_player(player_index)
turn_changed.emit(player.player_name, game_state.turn_manager.turn_number)
message.emit(player.player_name + "'s turn")
func _on_phase_changed(phase: Enums.TurnPhase) -> void:
var phase_name = Enums.phase_to_string(phase)
phase_changed.emit(phase_name)
# Set appropriate input mode
match phase:
Enums.TurnPhase.MAIN_1, Enums.TurnPhase.MAIN_2:
input_mode = InputMode.SELECT_CARD_TO_PLAY
Enums.TurnPhase.ATTACK:
input_mode = InputMode.SELECT_ATTACKER
_:
input_mode = InputMode.NONE