public bool CanSelectMoreTargets() { if (selectableTargetDescriptions != null) { ITargettingDescription desc = selectableTargetDescriptions[allSelectedTargets.Count]; if (desc.targettingType == TargettingType.EXCEPT) { ExceptTargetDescription exceptDesc = (ExceptTargetDescription)desc; desc = exceptDesc.targetDescription; } switch (desc.targettingType) { case TargettingType.TARGET: case TargettingType.TARGET_ALLY: case TargettingType.TARGET_ENEMY: TargetXDescription targetDesc = (TargetXDescription)desc; return(selectedTargets.Count < targetDesc.amount); case TargettingType.UP_TO_TARGET: case TargettingType.UP_TO_TARGET_ALLY: case TargettingType.UP_TO_TARGET_ENEMY: UpToXTargetDescription upToTargetDesc = (UpToXTargetDescription)desc; return(selectedTargets.Count < upToTargetDesc.amount); } } return(false); }
public bool HasValidSelectedTargets() { if (selectableTargetDescriptions != null && allSelectedTargets.Count < selectableTargetDescriptions.Count) { ITargettingDescription desc = selectableTargetDescriptions[allSelectedTargets.Count]; if (desc.targettingType == TargettingType.EXCEPT) { ExceptTargetDescription exceptDesc = (ExceptTargetDescription)desc; desc = exceptDesc.targetDescription; } switch (desc.targettingType) { case TargettingType.TARGET: case TargettingType.TARGET_ALLY: case TargettingType.TARGET_ENEMY: TargetXDescription targetDesc = (TargetXDescription)desc; return(selectedTargets.Count == targetDesc.amount); case TargettingType.UP_TO_TARGET: case TargettingType.UP_TO_TARGET_ALLY: case TargettingType.UP_TO_TARGET_ENEMY: // 0 is valid for up to so selected targets is always valid return(true); } } return(false); }
public override bool IsTargettable(TargettingQuery targetQuery) { bool valid = false; if (!creatureState.IsDead()) { ITargettingDescription desc = targetQuery.targettingDesc; if (desc.targettingType == TargettingType.EXCEPT) { ExceptTargetDescription exceptDesc = (ExceptTargetDescription)desc; desc = exceptDesc.targetDescription; } switch (desc.targetType) { case TargetType.CREATURES: case TargetType.PERMANENT: case TargetType.DAMAGEABLE: valid = true; break; } if (!targetQuery.ignoreUntouchable && HasKeyword(KeywordAttribute.UNTOUCHABLE)) { valid = false; } if (valid) { IQualifiableTargettingDescription qualifiableDesc = (IQualifiableTargettingDescription)desc; if (qualifiableDesc != null) { valid = qualifiableDesc.GetPlayerAlignment() == Alignment.NEUTRAL || (qualifiableDesc.GetPlayerAlignment() == GetAlignmentToPlayer(targetQuery.requestingPlayer)); IQualifierDescription qualifier = qualifiableDesc.qualifier; if (valid && qualifier != null) { switch (qualifier.qualifierType) { case QualifierType.NONE: break; case QualifierType.CREATURE_TYPE: { CreatureTypeQualifierDescription creatureQualifier = (CreatureTypeQualifierDescription)qualifier; valid = creatureQualifier.creatureType == card.cardData.GetCreatureType(); } break; default: valid = false; break; } } } } } return(valid); }
public bool HasValidTargets(List <ITargettingDescription> targets) { List <Targettable> potentialTargets = FindObjectOfType <GameSession>().GetPotentialTargets(); foreach (ITargettingDescription desc in targets) { ITargettingDescription descToCheck = desc; if (desc.targettingType == TargettingType.EXCEPT) { ExceptTargetDescription exceptDesc = (ExceptTargetDescription)desc; descToCheck = exceptDesc.targetDescription; } int targetsNeeded = 0; switch (descToCheck.targettingType) { case TargettingType.TARGET: case TargettingType.TARGET_ALLY: case TargettingType.TARGET_ENEMY: { TargetXDescription targetDesc = (TargetXDescription)descToCheck; targetsNeeded = targetDesc.amount; } break; case TargettingType.UP_TO_TARGET: case TargettingType.UP_TO_TARGET_ALLY: case TargettingType.UP_TO_TARGET_ENEMY: // Up to is valid for 0 so we can skip uneccessary checks continue; } TargettingQuery query = new TargettingQuery(desc, controller); foreach (Targettable t in potentialTargets) { if (t.IsTargettable(query)) { targetsNeeded -= 1; if (targetsNeeded <= 0) { break; } } } if (targetsNeeded > 0) { return(false); } } return(true); }
public void SetTargettingQuery(ITargettingDescription desc) { TargettingQuery query = new TargettingQuery(desc, this); if (gameSession.GetPendingActionType() == GameSession.PendingType.REPLACE_CREATURE) { query.ignoreUntouchable = true; } foreach (Targettable t in gameSession.GetPotentialTargets()) { t.SetTargettingQuery(query); } }
public override bool IsTargettable(TargettingQuery targetQuery) { bool valid = false; ITargettingDescription desc = targetQuery.targettingDesc; if (desc.targettingType == TargettingType.EXCEPT) { ExceptTargetDescription exceptDesc = (ExceptTargetDescription)desc; desc = exceptDesc.targetDescription; } switch (desc.targetType) { case TargetType.PLAYERS: case TargetType.DAMAGEABLE: valid = true; break; } if (valid) { IQualifiableTargettingDescription qualifiableDesc = (IQualifiableTargettingDescription)desc; if (qualifiableDesc != null) { valid = qualifiableDesc.GetPlayerAlignment() == Alignment.NEUTRAL || (qualifiableDesc.GetPlayerAlignment() == GetAlignmentToPlayer(targetQuery.requestingPlayer)); IQualifierDescription qualifier = qualifiableDesc.qualifier; if (valid && qualifier != null) { switch (qualifier.qualifierType) { case QualifierType.NONE: break; default: valid = false; break; } } } } return(valid); }
public static CardTags GetCardTagsFromTargetType(ITargettingDescription targettingDesc) { switch (targettingDesc.targettingType) { case TargettingType.TARGET: if (targettingDesc is TargetXDescription targetDesc) { if (targetDesc.amount == 1) { return(CardTags.SINGLE_TARGET); } else { return(CardTags.MULTI_TARGET); } } break; case TargettingType.UP_TO_TARGET: if (targettingDesc is UpToXTargetDescription upToTargetDesc) { if (upToTargetDesc.amount == 1) { return(CardTags.SINGLE_TARGET); } else { return(CardTags.MULTI_TARGET); } } break; case TargettingType.ALL: return(CardTags.AOE); } return(CardTags.NONE); }
public TargettingQuery(ITargettingDescription desc, PlayerController player, bool targets = true) { targettingDesc = desc; requestingPlayer = player; ignoreUntouchable = !targets; }
private void HandleTargetEvent(TargetSelectionEvent targetEvent) { // Validate all targets Card card = gameSession.GetPendingCard(targetEvent.playerId.GetComponent <PlayerController>()); bool isValid = false; if (card != null && targetEvent.playerId == gameSession.GetWaitingOnPlayer().netIdentity) { PlayerController player = gameSession.GetWaitingOnPlayer(); TriggerCondition triggerCondition = gameSession.GetPendingTriggerCondition(); NetworkIdentity[][] targets = targetEvent.ReconstructTargets(); List <ITargettingDescription> selectableTargetDescriptions = null; GameSession.PendingType pendingType = gameSession.GetPendingActionType(); if (pendingType == GameSession.PendingType.REPLACE_CREATURE) { selectableTargetDescriptions = GameUtils.ReplaceCreatureTargetDescriptions(); } else { switch (card.cardData.GetCardType()) { case CardType.CREATURE: selectableTargetDescriptions = card.cardData.GetSelectableTargets(triggerCondition); break; case CardType.SPELL: case CardType.TRAP: selectableTargetDescriptions = card.cardData.GetSelectableTargets(TriggerCondition.NONE); break; } } if (selectableTargetDescriptions != null && selectableTargetDescriptions.Count == targets.Length) { isValid = true; for (int i = 0; i < selectableTargetDescriptions.Count; i++) { ITargettingDescription desc = selectableTargetDescriptions[i]; if (desc.targettingType == TargettingType.EXCEPT) { ExceptTargetDescription exceptDesc = (ExceptTargetDescription)desc; desc = exceptDesc.targetDescription; } switch (desc.targettingType) { case TargettingType.TARGET: { TargetXDescription targetDesc = (TargetXDescription)desc; if (targetDesc.amount == targets[i].Length) { TargettingQuery query = new TargettingQuery(targetDesc, player, pendingType != GameSession.PendingType.REPLACE_CREATURE); for (int j = 0; j < targets[i].Length; j++) { Targettable targettable = targets[i][j].GetComponent <Targettable>(); if (!targettable.IsTargettable(query)) { isValid = false; break; } } } else { isValid = false; } break; } case TargettingType.UP_TO_TARGET: { UpToXTargetDescription targetDesc = (UpToXTargetDescription)desc; if (targetDesc.amount >= targets[i].Length) { TargettingQuery query = new TargettingQuery(targetDesc, player, pendingType != GameSession.PendingType.REPLACE_CREATURE); for (int j = 0; j < targets[i].Length; j++) { Targettable targettable = targets[i][j].GetComponent <Targettable>(); if (!targettable.IsTargettable(query)) { isValid = false; break; } } } else { isValid = false; } break; } } if (!isValid) { break; } } } if (isValid) { switch (pendingType) { case GameSession.PendingType.PLAY_CARD: PlayCardEvent playCardEvent = new PlayCardEvent(player, card, targetEvent.flattenedTargets, targetEvent.indexes); gameSession.HandleEvent(playCardEvent); gameSession.ServerPopState(); break; case GameSession.PendingType.TRIGGER_EFFECT: gameSession.ServerAddEffectToStack(gameSession.GetPendingCreature(player), card, triggerCondition, targetEvent.flattenedTargets, targetEvent.indexes); gameSession.ResetPendingCreature(); gameSession.ServerPopState(); break; case GameSession.PendingType.USE_TRAP: UseTrapEvent trapEvent = new UseTrapEvent(player, card, targetEvent.flattenedTargets, targetEvent.indexes); gameSession.HandleEvent(trapEvent); gameSession.ServerPopState(); break; case GameSession.PendingType.REPLACE_CREATURE: // Replace creature should only have one target Creature creatureToReplace = targets[0][0].GetComponent <Creature>(); // Destroying the creature makes it so we can't target it for the on enter effect of the replacing creature which is what we want creatureToReplace.GetCreatureState().ServerDestroyCard(); gameSession.SetPendingCreature(creatureToReplace); PlayCardEvent playReplaceCreatureEvent = new PlayCardEvent(player, card); gameSession.HandleEvent(playReplaceCreatureEvent); gameSession.ServerPopState(); break; } } else { CancelPlayCard(); } } }
private bool IsTargettableCard(TargettingQuery targetQuery) { bool valid = false; ITargettingDescription desc = targetQuery.targettingDesc; if (desc.targettingType == TargettingType.EXCEPT) { ExceptTargetDescription exceptDesc = (ExceptTargetDescription)desc; desc = exceptDesc.targetDescription; } switch (desc.targetType) { case TargetType.CARDS: valid = true; break; case TargetType.CREATURE_CARDS: valid = cardData.GetCardType() == CardType.CREATURE; break; case TargetType.SPELL_CARDS: valid = cardData.GetCardType() == CardType.SPELL; break; case TargetType.TRAP_CARDS: valid = cardData.GetCardType() == CardType.TRAP; break; } if (valid) { IQualifiableTargettingDescription qualifiableDesc = (IQualifiableTargettingDescription)desc; if (qualifiableDesc != null) { valid = qualifiableDesc.GetPlayerAlignment() == Alignment.NEUTRAL || (qualifiableDesc.GetPlayerAlignment() == GetAlignmentToPlayer(targetQuery.requestingPlayer)); IQualifierDescription qualifier = qualifiableDesc.qualifier; if (valid && qualifier != null) { switch (qualifier.qualifierType) { case QualifierType.NONE: break; case QualifierType.CREATURE_TYPE: { CreatureTypeQualifierDescription creatureQualifier = (CreatureTypeQualifierDescription)qualifier; valid = creatureQualifier.creatureType == cardData.GetCreatureType(); } break; case QualifierType.CARD_TYPE: { CardTypeQualifierDescription cardTypeQualifier = (CardTypeQualifierDescription)qualifier; valid = cardTypeQualifier.cardType == cardData.GetCardType(); } break; default: valid = false; break; } } } } return(valid); }