init game files
This commit is contained in:
263
scripts/game/Player.gd
Normal file
263
scripts/game/Player.gd
Normal file
@@ -0,0 +1,263 @@
|
||||
class_name Player
|
||||
extends RefCounted
|
||||
|
||||
## Player - Represents a player's game state
|
||||
|
||||
var player_index: int = 0
|
||||
var player_name: String = "Player"
|
||||
|
||||
# Zones
|
||||
var deck: Zone
|
||||
var hand: Zone
|
||||
var field_forwards: Zone
|
||||
var field_backups: Zone
|
||||
var damage_zone: Zone
|
||||
var break_zone: Zone
|
||||
|
||||
# Resources
|
||||
var cp_pool: CPPool
|
||||
|
||||
# Game state
|
||||
var is_first_player: bool = false
|
||||
var has_mulliganed: bool = false
|
||||
|
||||
# Constants
|
||||
const MAX_HAND_SIZE: int = 5
|
||||
const MAX_BACKUPS: int = 5
|
||||
const DAMAGE_TO_LOSE: int = 7
|
||||
|
||||
func _init(index: int, name: String = "") -> void:
|
||||
player_index = index
|
||||
player_name = name if name != "" else "Player %d" % (index + 1)
|
||||
|
||||
# Initialize zones
|
||||
deck = Zone.new(Enums.ZoneType.DECK, index)
|
||||
hand = Zone.new(Enums.ZoneType.HAND, index)
|
||||
field_forwards = Zone.new(Enums.ZoneType.FIELD_FORWARDS, index)
|
||||
field_backups = Zone.new(Enums.ZoneType.FIELD_BACKUPS, index)
|
||||
damage_zone = Zone.new(Enums.ZoneType.DAMAGE, index)
|
||||
break_zone = Zone.new(Enums.ZoneType.BREAK, index)
|
||||
|
||||
# Initialize CP pool
|
||||
cp_pool = CPPool.new()
|
||||
|
||||
## Setup the player's deck from a list of card IDs
|
||||
func setup_deck(card_ids: Array[String]) -> void:
|
||||
for card_id in card_ids:
|
||||
var card_data = CardDatabase.get_card(card_id)
|
||||
if card_data:
|
||||
var card = CardInstance.new(card_data, player_index)
|
||||
deck.add_card(card)
|
||||
|
||||
# Shuffle the deck
|
||||
deck.shuffle()
|
||||
|
||||
## Draw cards from deck to hand
|
||||
func draw_cards(count: int) -> Array[CardInstance]:
|
||||
var drawn: Array[CardInstance] = []
|
||||
|
||||
for i in range(count):
|
||||
if deck.is_empty():
|
||||
break # Can't draw from empty deck
|
||||
var card = deck.pop_top_card()
|
||||
if card:
|
||||
hand.add_card(card)
|
||||
drawn.append(card)
|
||||
|
||||
return drawn
|
||||
|
||||
## Check if player can draw (deck not empty)
|
||||
func can_draw() -> bool:
|
||||
return not deck.is_empty()
|
||||
|
||||
## Get current damage count
|
||||
func get_damage_count() -> int:
|
||||
return damage_zone.get_count()
|
||||
|
||||
## Check if player has lost (7+ damage)
|
||||
func has_lost() -> bool:
|
||||
return get_damage_count() >= DAMAGE_TO_LOSE
|
||||
|
||||
## Take damage (move cards from deck to damage zone)
|
||||
func take_damage(amount: int) -> Array[CardInstance]:
|
||||
var damage_cards: Array[CardInstance] = []
|
||||
|
||||
for i in range(amount):
|
||||
if deck.is_empty():
|
||||
break
|
||||
var card = deck.pop_top_card()
|
||||
if card:
|
||||
damage_zone.add_card(card)
|
||||
damage_cards.append(card)
|
||||
|
||||
return damage_cards
|
||||
|
||||
## Discard a card from hand to generate CP
|
||||
func discard_for_cp(card: CardInstance) -> bool:
|
||||
if not hand.has_card(card):
|
||||
return false
|
||||
|
||||
# Light/Dark cards cannot be discarded for CP
|
||||
if card.is_light_or_dark():
|
||||
return false
|
||||
|
||||
hand.remove_card(card)
|
||||
break_zone.add_card(card)
|
||||
|
||||
# Generate 2 CP of the card's element
|
||||
var element = card.get_element()
|
||||
cp_pool.add_cp(element, 2)
|
||||
|
||||
return true
|
||||
|
||||
## Dull a backup to generate CP
|
||||
func dull_backup_for_cp(card: CardInstance) -> bool:
|
||||
if not field_backups.has_card(card):
|
||||
return false
|
||||
|
||||
if not card.is_backup():
|
||||
return false
|
||||
|
||||
if card.is_dull():
|
||||
return false
|
||||
|
||||
card.dull()
|
||||
|
||||
# Generate 1 CP of the backup's element
|
||||
var element = card.get_element()
|
||||
cp_pool.add_cp(element, 1)
|
||||
|
||||
return true
|
||||
|
||||
## Play a card from hand to field
|
||||
func play_card(card: CardInstance) -> bool:
|
||||
if not hand.has_card(card):
|
||||
return false
|
||||
|
||||
# Check if we can afford it
|
||||
if not cp_pool.can_afford_card(card.card_data):
|
||||
return false
|
||||
|
||||
# Check field restrictions
|
||||
if card.is_backup():
|
||||
if field_backups.get_count() >= MAX_BACKUPS:
|
||||
return false
|
||||
|
||||
# Check unique name restriction
|
||||
if not card.card_data.is_generic:
|
||||
if card.is_forward() and field_forwards.has_card_with_name(card.card_data.name):
|
||||
return false
|
||||
if card.is_backup() and field_backups.has_card_with_name(card.card_data.name):
|
||||
return false
|
||||
|
||||
# Check Light/Dark restriction
|
||||
if card.is_light_or_dark():
|
||||
if field_forwards.has_light_or_dark() or field_backups.has_light_or_dark():
|
||||
return false
|
||||
|
||||
# Pay the cost
|
||||
if not cp_pool.spend_for_card(card.card_data):
|
||||
return false
|
||||
|
||||
# Move to field
|
||||
hand.remove_card(card)
|
||||
|
||||
if card.is_forward():
|
||||
field_forwards.add_card(card)
|
||||
card.state = Enums.CardState.ACTIVE
|
||||
elif card.is_backup():
|
||||
field_backups.add_card(card)
|
||||
card.state = Enums.CardState.DULL # Backups enter dull
|
||||
|
||||
card.entered_field()
|
||||
|
||||
return true
|
||||
|
||||
## Break a card (move from field to break zone)
|
||||
func break_card(card: CardInstance) -> bool:
|
||||
var removed = false
|
||||
|
||||
if field_forwards.has_card(card):
|
||||
field_forwards.remove_card(card)
|
||||
removed = true
|
||||
elif field_backups.has_card(card):
|
||||
field_backups.remove_card(card)
|
||||
removed = true
|
||||
|
||||
if removed:
|
||||
break_zone.add_card(card)
|
||||
return true
|
||||
|
||||
return false
|
||||
|
||||
## Activate all dull cards (Active Phase)
|
||||
func activate_all() -> void:
|
||||
for card in field_forwards.get_dull_cards():
|
||||
card.activate()
|
||||
for card in field_backups.get_dull_cards():
|
||||
card.activate()
|
||||
|
||||
## Discard down to hand size (End Phase)
|
||||
func discard_to_hand_limit() -> Array[CardInstance]:
|
||||
var discarded: Array[CardInstance] = []
|
||||
|
||||
while hand.get_count() > MAX_HAND_SIZE:
|
||||
# For now, just discard the last card
|
||||
# In actual game, player would choose
|
||||
var card = hand.pop_top_card()
|
||||
if card:
|
||||
break_zone.add_card(card)
|
||||
discarded.append(card)
|
||||
|
||||
return discarded
|
||||
|
||||
## End of turn cleanup
|
||||
func end_turn_cleanup() -> void:
|
||||
# Clear CP pool
|
||||
cp_pool.clear()
|
||||
|
||||
# Reset temporary effects on field cards
|
||||
for card in field_forwards.get_cards():
|
||||
card.end_turn_cleanup()
|
||||
for card in field_backups.get_cards():
|
||||
card.end_turn_cleanup()
|
||||
|
||||
## Start of turn setup
|
||||
func start_turn() -> void:
|
||||
# Increment turn counter for field cards
|
||||
for card in field_forwards.get_cards():
|
||||
card.start_turn()
|
||||
for card in field_backups.get_cards():
|
||||
card.start_turn()
|
||||
|
||||
## Get all cards on field
|
||||
func get_all_field_cards() -> Array[CardInstance]:
|
||||
var cards: Array[CardInstance] = []
|
||||
cards.append_array(field_forwards.get_cards())
|
||||
cards.append_array(field_backups.get_cards())
|
||||
return cards
|
||||
|
||||
## Get forwards that can attack
|
||||
func get_attackable_forwards() -> Array[CardInstance]:
|
||||
var attackers: Array[CardInstance] = []
|
||||
for card in field_forwards.get_cards():
|
||||
if card.can_attack():
|
||||
attackers.append(card)
|
||||
return attackers
|
||||
|
||||
## Get forwards that can block
|
||||
func get_blockable_forwards() -> Array[CardInstance]:
|
||||
var blockers: Array[CardInstance] = []
|
||||
for card in field_forwards.get_cards():
|
||||
if card.can_block():
|
||||
blockers.append(card)
|
||||
return blockers
|
||||
|
||||
func _to_string() -> String:
|
||||
return "[Player: %s, Hand: %d, Forwards: %d, Backups: %d, Damage: %d]" % [
|
||||
player_name,
|
||||
hand.get_count(),
|
||||
field_forwards.get_count(),
|
||||
field_backups.get_count(),
|
||||
damage_zone.get_count()
|
||||
]
|
||||
Reference in New Issue
Block a user