feature updates
This commit is contained in:
174
scripts/game/abilities/TargetSelector.gd
Normal file
174
scripts/game/abilities/TargetSelector.gd
Normal file
@@ -0,0 +1,174 @@
|
||||
class_name TargetSelector
|
||||
extends RefCounted
|
||||
|
||||
## TargetSelector - Validates and provides target options for effects
|
||||
|
||||
|
||||
## Get all valid targets for an effect's target specification
|
||||
func get_valid_targets(
|
||||
target_spec: Dictionary,
|
||||
source: CardInstance,
|
||||
game_state
|
||||
) -> Array:
|
||||
if target_spec.is_empty():
|
||||
return []
|
||||
|
||||
var candidates: Array = []
|
||||
|
||||
var zone = str(target_spec.get("zone", "FIELD")).to_upper()
|
||||
var owner = str(target_spec.get("owner", "ANY")).to_upper()
|
||||
var filter = target_spec.get("filter", {})
|
||||
var target_type = str(target_spec.get("type", "CHOOSE")).to_upper()
|
||||
|
||||
# Handle SELF and ALL targets specially
|
||||
if target_type == "SELF":
|
||||
return [source]
|
||||
elif target_type == "ALL":
|
||||
return _get_all_matching(owner, zone, filter, source, game_state)
|
||||
|
||||
# Collect candidates from appropriate zones
|
||||
match zone:
|
||||
"FIELD":
|
||||
candidates = _get_field_cards(owner, source, game_state)
|
||||
"HAND":
|
||||
candidates = _get_hand_cards(owner, source, game_state)
|
||||
"BREAK_ZONE", "BREAK":
|
||||
candidates = _get_break_zone_cards(owner, source, game_state)
|
||||
"DECK":
|
||||
candidates = _get_deck_cards(owner, source, game_state)
|
||||
_:
|
||||
# Default to field
|
||||
candidates = _get_field_cards(owner, source, game_state)
|
||||
|
||||
# Apply filters using CardFilter utility
|
||||
return CardFilter.get_matching(candidates, filter, source)
|
||||
|
||||
|
||||
## Get all cards matching filter (for "ALL" target type)
|
||||
func _get_all_matching(
|
||||
owner: String,
|
||||
zone: String,
|
||||
filter: Dictionary,
|
||||
source: CardInstance,
|
||||
game_state
|
||||
) -> Array:
|
||||
var candidates = _get_field_cards(owner, source, game_state)
|
||||
return CardFilter.get_matching(candidates, filter, source)
|
||||
|
||||
|
||||
## Get cards from field
|
||||
func _get_field_cards(
|
||||
owner: String,
|
||||
source: CardInstance,
|
||||
game_state
|
||||
) -> Array:
|
||||
var cards: Array = []
|
||||
|
||||
match owner:
|
||||
"CONTROLLER":
|
||||
var player = game_state.get_player(source.controller_index)
|
||||
if player:
|
||||
cards.append_array(_get_player_field_cards(player))
|
||||
"OPPONENT":
|
||||
var opponent = game_state.get_player(1 - source.controller_index)
|
||||
if opponent:
|
||||
cards.append_array(_get_player_field_cards(opponent))
|
||||
"ANY", _:
|
||||
for player in game_state.players:
|
||||
cards.append_array(_get_player_field_cards(player))
|
||||
|
||||
return cards
|
||||
|
||||
|
||||
## Get all field cards for a player
|
||||
func _get_player_field_cards(player) -> Array:
|
||||
var cards: Array = []
|
||||
cards.append_array(player.field_forwards.get_cards())
|
||||
cards.append_array(player.field_backups.get_cards())
|
||||
return cards
|
||||
|
||||
|
||||
## Get cards from hand
|
||||
func _get_hand_cards(
|
||||
owner: String,
|
||||
source: CardInstance,
|
||||
game_state
|
||||
) -> Array:
|
||||
var cards: Array = []
|
||||
var player_index = source.controller_index
|
||||
|
||||
if owner == "OPPONENT":
|
||||
player_index = 1 - player_index
|
||||
|
||||
var player = game_state.get_player(player_index)
|
||||
if player:
|
||||
cards.append_array(player.hand.get_cards())
|
||||
|
||||
return cards
|
||||
|
||||
|
||||
## Get cards from break zone
|
||||
func _get_break_zone_cards(
|
||||
owner: String,
|
||||
source: CardInstance,
|
||||
game_state
|
||||
) -> Array:
|
||||
var cards: Array = []
|
||||
var player_index = source.controller_index
|
||||
|
||||
if owner == "OPPONENT":
|
||||
player_index = 1 - player_index
|
||||
|
||||
var player = game_state.get_player(player_index)
|
||||
if player:
|
||||
cards.append_array(player.break_zone.get_cards())
|
||||
|
||||
return cards
|
||||
|
||||
|
||||
## Get cards from deck
|
||||
func _get_deck_cards(
|
||||
owner: String,
|
||||
source: CardInstance,
|
||||
game_state
|
||||
) -> Array:
|
||||
# Usually not directly targetable, used for search effects
|
||||
var cards: Array = []
|
||||
var player_index = source.controller_index
|
||||
|
||||
if owner == "OPPONENT":
|
||||
player_index = 1 - player_index
|
||||
|
||||
var player = game_state.get_player(player_index)
|
||||
if player:
|
||||
cards.append_array(player.deck.get_cards())
|
||||
|
||||
return cards
|
||||
|
||||
|
||||
## Validate that a set of targets meets the target specification requirements
|
||||
func validate_targets(
|
||||
targets: Array,
|
||||
target_spec: Dictionary,
|
||||
source: CardInstance,
|
||||
game_state
|
||||
) -> bool:
|
||||
var target_type = str(target_spec.get("type", "CHOOSE")).to_upper()
|
||||
|
||||
# Check count requirements
|
||||
if target_spec.has("count"):
|
||||
var required = int(target_spec.count)
|
||||
if targets.size() != required:
|
||||
return false
|
||||
elif target_spec.has("count_up_to"):
|
||||
var max_count = int(target_spec.count_up_to)
|
||||
if targets.size() > max_count:
|
||||
return false
|
||||
|
||||
# Validate each target is valid
|
||||
var valid_targets = get_valid_targets(target_spec, source, game_state)
|
||||
for target in targets:
|
||||
if target not in valid_targets:
|
||||
return false
|
||||
|
||||
return true
|
||||
Reference in New Issue
Block a user