|
//EndTurn |
|
//remove if (game_data.phase != GamePhase.Main) |
|
//remove return; |
|
|
|
if (game_data.response_phase == ResponsePhase.Response) |
|
{ |
|
game_data.GetPlayer(game_data.response_player).resolve = true; |
|
|
|
if (!game_data.GetOpponentPlayer(game_data.response_player).resolve) |
|
{ |
|
game_data.response_player = game_data.GetOpponentPlayer(game_data.response_player).player_id; |
|
RefreshData(); |
|
return; |
|
} |
|
else |
|
{ |
|
game_data.response_phase = ResponsePhase.None; |
|
game_data.response_player = game_data.GetOpponentPlayer(game_data.response_player).player_id; |
|
resolve_queue.ResolveAll(true); |
|
RefreshData(); |
|
return; |
|
} |
|
} |
|
//End |
|
|
|
public virtual void PlayCard(Card card, Slot slot, bool skip_cost = false) |
|
{ |
|
if (game_data.CanPlayCard(card, slot, skip_cost)) |
|
{ |
|
Player player = game_data.GetPlayer(card.player_id); |
|
|
|
//Cost |
|
if (!skip_cost) |
|
player.PayMana(card); |
|
|
|
//Play card |
|
player.RemoveCardFromAllGroups(card); |
|
|
|
if (card.CardData.skip_stack || skip_cost) |
|
{ |
|
TriggerCard(card, player, slot); |
|
} |
|
else |
|
{ |
|
resolve_queue.AddCard(card, player, slot, TriggerCard); |
|
|
|
ActionHistory order = new ActionHistory(); |
|
order.type = GameAction.PlayCard; |
|
order.card_id = card.card_id; |
|
order.card_uid = card.uid; |
|
game_data.history_list.Add(order); |
|
|
|
Player responseOp = game_data.GetOpponentPlayer(game_data.response_phase == ResponsePhase.None ? player.player_id : game_data.response_player); |
|
Player resposePl = game_data.GetOpponentPlayer(responseOp.player_id); |
|
if (game_data.response_phase == ResponsePhase.None || (!resposePl.resolve || !responseOp.resolve)) |
|
{ |
|
game_data.response_phase = ResponsePhase.Response; |
|
game_data.response_timer = GameplayData.Get().turn_duration; // you can a different amout for response timer, just add on GameplayData and setup as you want |
|
resposePl.resolve = true; |
|
responseOp.resolve = false; |
|
game_data.response_player = responseOp.player_id; |
|
RefreshData(); |
|
return; |
|
} |
|
|
|
game_data.response_phase = ResponsePhase.None; |
|
} |
|
|
|
RefreshData(); |
|
|
|
onCardPlayed?.Invoke(card, slot); |
|
resolve_queue.ResolveAll(0.3f); |
|
} |
|
} |
|
|
|
public virtual void TriggerCard(Card card, Player player, Slot slot) |
|
{ |
|
//Add to board |
|
CardData icard = card.CardData; |
|
if (icard.IsBoardCard() || icard.IsLandCard()) |
|
{ |
|
player.cards_board.Add(card); |
|
card.slot = slot; |
|
card.exhausted = true; //Cant attack first turn |
|
} |
|
else if (icard.IsEquipment()) |
|
{ |
|
Card bearer = game_data.GetSlotCard(slot); |
|
EquipCard(bearer, card); |
|
card.exhausted = true; |
|
} |
|
else if (icard.IsSecret()) |
|
{ |
|
player.cards_secret.Add(card); |
|
} |
|
else |
|
{ |
|
player.cards_discard.Add(card); |
|
card.slot = slot; //Save slot in case spell has PlayTarget |
|
} |
|
|
|
var history_card = game_data.history_list.Find(item => item.card_uid == card.uid); |
|
game_data.history_list.Remove(history_card); |
|
|
|
//History |
|
if (!is_ai_predict && !icard.IsSecret()) |
|
player.AddHistory(GameAction.PlayCard, card); |
|
|
|
//Update ongoing effects |
|
game_data.last_played = card.uid; |
|
UpdateOngoing(); |
|
|
|
//Trigger abilities |
|
if (card.CardData.IsDynamicManaCost()) |
|
{ |
|
GoToSelectorCost(card); |
|
} |
|
else |
|
{ |
|
TriggerSecrets(AbilityTrigger.OnPlayOther, card); //After playing card |
|
TriggerCardAbilityType(AbilityTrigger.OnPlay, card); |
|
TriggerOtherCardsAbilityType(AbilityTrigger.OnPlayOther, card); |
|
} |
|
} |
|
|
|
// This method will solve the selectors that aren't cancelable, choosing the first valid option, you could remove this logic, adapt, pick random, is in your hands to choose. |
|
public virtual void CancelSelection() |
|
{ |
|
if (game_data.selector != SelectorType.None) |
|
{ |
|
if (!game_data.selector_cancelable) |
|
{ |
|
if (game_data.selector == SelectorType.SelectorCard) |
|
{ |
|
var iability = AbilityData.Get(game_data.selector_ability_id); |
|
var icard = game_data.GetCard(game_data.selector_caster_uid); |
|
var options = iability.GetCardTargets(game_data, icard); |
|
|
|
if (options.Count > 0 && options?.First() != null) |
|
{ |
|
Card target = game_data.GetCard(options.First().uid); |
|
SelectCard(target); |
|
} |
|
} |
|
else if (game_data.selector == SelectorType.SelectorChoice) |
|
{ |
|
var icard = game_data.GetCard(game_data.selector_caster_uid); |
|
var iability = AbilityData.Get(game_data.selector_ability_id); |
|
if (iability != null && iability.chain_abilities.Length > 0) |
|
{ |
|
int i = 0; |
|
foreach (var chain_ability in iability.chain_abilities) |
|
{ |
|
if (game_data.CanSelectAbility(icard, chain_ability)) |
|
{ |
|
SelectChoice(i); |
|
break; |
|
} |
|
i++; |
|
} |
|
} |
|
|
|
} |
|
else if (game_data.selector == SelectorType.SelectTarget) |
|
{ |
|
var icard = game_data.GetCard(game_data.selector_caster_uid); |
|
AbilityData iability = AbilityData.Get(game_data.selector_ability_id); |
|
|
|
var found = false; |
|
foreach (var player in game_data.players) |
|
{ |
|
for (var i = 0; i < player.cards_board.Count; i++) |
|
{ |
|
if (found) break; |
|
var target = player.cards_board[i]; |
|
|
|
if (iability.CanTarget(game_data, icard, target)) |
|
{ |
|
SelectCard(target); |
|
found = true; |
|
} |
|
|
|
} |
|
|
|
if (found) break; |
|
} |
|
|
|
} |
|
} |
|
|
|
//End selection |
|
game_data.selector = SelectorType.None; |
|
|
|
RefreshData(); |
|
} |
|
} |
|
|
|
// This method triggers a ResponseSelector, unlike Response, we will finish the response of this kind after an action is made |
|
protected virtual void CheckResponseSelector(AbilityData iability, Card caster) |
|
{ |
|
game_data.selector_player_id = iability.selector_owner ? caster.player_id : game_data.GetOpponentPlayer(caster.player_id).player_id; |
|
|
|
if (iability.selector_owner != (game_data.GetActivePlayer().player_id == caster.player_id) && game_data.response_phase == ResponsePhase.None) |
|
{ |
|
game_data.response_timer = GameplayData.Get().turn_duration; |
|
game_data.response_phase = ResponsePhase.ResponseSelector; |
|
} |
|
} |