Merge branch 'definedPlayerValid' into 'master'

AbilityUtils.getDefinedPlayer use valid like with getDefinedCards

See merge request core-developers/forge!6067
This commit is contained in:
Hans Mackowiak
2022-01-23 10:19:56 +00:00
7 changed files with 59 additions and 54 deletions

View File

@@ -992,12 +992,17 @@ public class AbilityUtils {
*/ */
public static PlayerCollection getDefinedPlayers(final Card card, final String def, final CardTraitBase sa) { public static PlayerCollection getDefinedPlayers(final Card card, final String def, final CardTraitBase sa) {
final PlayerCollection players = new PlayerCollection(); final PlayerCollection players = new PlayerCollection();
final String defined = (def == null) ? "You" : applyAbilityTextChangeEffects(def, sa); String changedDef = (def == null) ? "You" : applyAbilityTextChangeEffects(def, sa); // default to Self
final String[] incR = changedDef.split("\\.", 2);
String defined = incR[0];
final Game game = card == null ? null : card.getGame(); final Game game = card == null ? null : card.getGame();
final Player player = sa instanceof SpellAbility ? ((SpellAbility)sa).getActivatingPlayer() : card.getController(); final Player player = sa instanceof SpellAbility ? ((SpellAbility)sa).getActivatingPlayer() : card.getController();
if (defined.equals("TargetedOrController")) { if (defined.equals("Self")) {
// do nothing, Self is for Cards, not Players
} else if (defined.equals("TargetedOrController")) {
players.addAll(getDefinedPlayers(card, "Targeted", sa)); players.addAll(getDefinedPlayers(card, "Targeted", sa));
players.addAll(getDefinedPlayers(card, "TargetedController", sa)); players.addAll(getDefinedPlayers(card, "TargetedController", sa));
} }
@@ -1056,6 +1061,15 @@ public class AbilityUtils {
else if (defined.startsWith("Remembered")) { else if (defined.startsWith("Remembered")) {
addPlayer(card.getRemembered(), defined, players); addPlayer(card.getRemembered(), defined, players);
} }
else if (defined.startsWith("Imprinted")) {
addPlayer(Lists.newArrayList(card.getImprintedCards()), defined, players);
}
else if (defined.startsWith("EffectSource")) {
Card root = findEffectRoot(card);
if (root != null) {
addPlayer(Lists.newArrayList(root), defined, players);
}
}
else if (defined.startsWith("DelayTriggerRemembered") && sa instanceof SpellAbility) { else if (defined.startsWith("DelayTriggerRemembered") && sa instanceof SpellAbility) {
SpellAbility root = ((SpellAbility)sa).getRootAbility(); SpellAbility root = ((SpellAbility)sa).getRootAbility();
if (root != null) { if (root != null) {
@@ -1064,16 +1078,6 @@ public class AbilityUtils {
System.err.println("Warning: couldn't find trigger SA in the chain of SpellAbility " + sa); System.err.println("Warning: couldn't find trigger SA in the chain of SpellAbility " + sa);
} }
} }
else if (defined.equals("ImprintedController")) {
for (final Card rem : card.getImprintedCards()) {
players.add(rem.getController());
}
}
else if (defined.equals("ImprintedOwner")) {
for (final Card rem : card.getImprintedCards()) {
players.add(rem.getOwner());
}
}
else if (defined.startsWith("Triggered") && sa instanceof SpellAbility) { else if (defined.startsWith("Triggered") && sa instanceof SpellAbility) {
String defParsed = defined.endsWith("AndYou") ? defined.substring(0, defined.indexOf("AndYou")) : defined; String defParsed = defined.endsWith("AndYou") ? defined.substring(0, defined.indexOf("AndYou")) : defined;
if (defined.endsWith("AndYou")) { if (defined.endsWith("AndYou")) {
@@ -1096,7 +1100,7 @@ public class AbilityUtils {
o = ((CardCollection) c).get(0).getController(); o = ((CardCollection) c).get(0).getController();
} }
} }
else if (defParsed.endsWith("Opponent") && !defParsed.endsWith("IfOpponent")) { else if (defParsed.endsWith("Opponent")) {
String triggeringType = defParsed.substring(9); String triggeringType = defParsed.substring(9);
triggeringType = triggeringType.substring(0, triggeringType.length() - 8); triggeringType = triggeringType.substring(0, triggeringType.length() - 8);
final Object c = root.getTriggeringObject(AbilityKey.fromString(triggeringType)); final Object c = root.getTriggeringObject(AbilityKey.fromString(triggeringType));
@@ -1125,21 +1129,7 @@ public class AbilityUtils {
} }
else { else {
String triggeringType = defParsed.substring(9); String triggeringType = defParsed.substring(9);
String filter = null;
if (triggeringType.contains("=")) {
filter = triggeringType.split("If")[1];
triggeringType = triggeringType.split("If")[0];
}
o = root.getTriggeringObject(AbilityKey.fromString(triggeringType)); o = root.getTriggeringObject(AbilityKey.fromString(triggeringType));
if (filter != null) {
if (filter.equals("Opponent")) {
if (!((Player)o).isOpponentOf(((SpellAbility) sa).getActivatingPlayer())) {
o = null;
}
} else {
System.err.println("getDefinedPlayers needs additional code for =Filter");
}
}
} }
if (o != null) { if (o != null) {
if (o instanceof Player) { if (o instanceof Player) {
@@ -1190,29 +1180,26 @@ public class AbilityUtils {
players.addAll(game.getPlayersInTurnOrder()); players.addAll(game.getPlayersInTurnOrder());
players.removeAll((FCollectionView<Player>)getDefinedPlayers(card, defined.substring(3), sa)); players.removeAll((FCollectionView<Player>)getDefinedPlayers(card, defined.substring(3), sa));
} }
else if (defined.equals("EnchantedController")) {
if (card.getEnchantingCard() == null) {
return players;
}
players.add(card.getEnchantingCard().getController());
}
else if (defined.equals("EnchantedOwner")) {
if (card.getEnchantingCard() == null) {
return players;
}
players.add(card.getEnchantingCard().getOwner());
}
else if (defined.equals("EnchantedPlayer")) { else if (defined.equals("EnchantedPlayer")) {
final Object o = sa.getHostCard().getEntityAttachedTo(); final Object o = sa.getHostCard().getEntityAttachedTo();
if (o instanceof Player) { if (o instanceof Player) {
players.add((Player) o); players.add((Player) o);
} }
} }
else if (defined.equals("AttackingPlayer")) { else if (defined.startsWith("Enchanted")) {
if (!game.getPhaseHandler().inCombat()) { if (card.getEntityAttachedTo() != null) {
return players; addPlayer(Lists.newArrayList(card.getEntityAttachedTo()), defined, players);
}
}
else if (defined.startsWith("Equipped")) {
if (card.getEquipping() != null) {
addPlayer(Lists.newArrayList(card.getEquipping()), defined, players);
}
}
else if (defined.equals("AttackingPlayer")) {
if (game.getPhaseHandler().inCombat()) {
players.add(game.getCombat().getAttackingPlayer());
} }
players.add(game.getCombat().getAttackingPlayer());
} }
else if (defined.equals("DefendingPlayer")) { else if (defined.equals("DefendingPlayer")) {
players.add(game.getCombat().getDefendingPlayerRelatedTo(card)); players.add(game.getCombat().getDefendingPlayerRelatedTo(card));
@@ -1264,8 +1251,10 @@ public class AbilityUtils {
} }
} }
} }
else if (defined.equals("Caster") && sa.getHostCard().wasCast()) { else if (defined.equals("Caster")) {
players.add((sa.getHostCard().getCastSA().getActivatingPlayer())); if (sa.getHostCard().wasCast()) {
players.add((sa.getHostCard().getCastSA().getActivatingPlayer()));
}
} }
else if (defined.equals("ActivePlayer")) { else if (defined.equals("ActivePlayer")) {
players.add(game.getPhaseHandler().getPlayerTurn()); players.add(game.getPhaseHandler().getPlayerTurn());
@@ -1281,11 +1270,17 @@ public class AbilityUtils {
players.add(game.getNextPlayerAfter(player, dir)); players.add(game.getNextPlayerAfter(player, dir));
} }
else { else {
for (Player p : game.getPlayersInTurnOrder()) { // will be filtered below
if (p.isValid(defined, player, card, sa)) { players.addAll(game.getPlayersInTurnOrder());
players.add(p); }
}
if (incR.length > 1 && !players.isEmpty()) {
String[] valids = incR[1].split(",");
// need to add valids onto all of them
for (int i = 0; i < valids.length; i++) {
valids[i] = "Player." + valids[i];
} }
return players.filter(PlayerPredicates.restriction(valids, player, card, sa));
} }
return players; return players;
} }

View File

@@ -5,6 +5,7 @@ import java.util.Comparator;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.base.Predicates; import com.google.common.base.Predicates;
import forge.game.CardTraitBase;
import forge.game.card.Card; import forge.game.card.Card;
import forge.game.card.CardLists; import forge.game.card.CardLists;
import forge.game.card.CounterEnumType; import forge.game.card.CounterEnumType;
@@ -129,6 +130,15 @@ public final class PlayerPredicates {
}; };
} }
public static final Predicate<Player> restriction(final String[] restrictions, final Player sourceController, final Card source, final CardTraitBase spellAbility) {
return new Predicate<Player>() {
@Override
public boolean apply(final Player c) {
return c != null && c.isValid(restrictions, sourceController, source, spellAbility);
}
};
}
public static final Comparator<Player> compareByZoneSize(final ZoneType zone) { public static final Comparator<Player> compareByZoneSize(final ZoneType zone) {
return new Comparator<Player>() { return new Comparator<Player>() {
@Override @Override

View File

@@ -5,5 +5,5 @@ K:Enchant player
A:SP$ Attach | ValidTgts$ Player | AILogic$ Curse A:SP$ Attach | ValidTgts$ Player | AILogic$ Curse
T:Mode$ AttackersDeclared | ValidCard$ Creature | AttackedTarget$ Player.EnchantedBy | Execute$ TrigUntap | TriggerZones$ Battlefield | TriggerDescription$ Whenever enchanted player is attacked, untap all nonland permanents you control. Each opponent attacking that player untaps all nonland permanents they control. T:Mode$ AttackersDeclared | ValidCard$ Creature | AttackedTarget$ Player.EnchantedBy | Execute$ TrigUntap | TriggerZones$ Battlefield | TriggerDescription$ Whenever enchanted player is attacked, untap all nonland permanents you control. Each opponent attacking that player untaps all nonland permanents they control.
SVar:TrigUntap:DB$ UntapAll | Defined$ You | ValidCards$ Permanent.nonLand | SubAbility$ DBUntap SVar:TrigUntap:DB$ UntapAll | Defined$ You | ValidCards$ Permanent.nonLand | SubAbility$ DBUntap
SVar:DBUntap:DB$ UntapAll | Defined$ TriggeredAttackingPlayerIfOpponent | ValidCards$ Permanent.nonLand SVar:DBUntap:DB$ UntapAll | Defined$ TriggeredAttackingPlayer.Opponent | ValidCards$ Permanent.nonLand
Oracle:Enchant player\nWhenever enchanted player is attacked, untap all nonland permanents you control. Each opponent attacking that player untaps all nonland permanents they control. Oracle:Enchant player\nWhenever enchanted player is attacked, untap all nonland permanents you control. Each opponent attacking that player untaps all nonland permanents they control.

View File

@@ -5,5 +5,5 @@ K:Enchant player
A:SP$ Attach | ValidTgts$ Player | AILogic$ Curse A:SP$ Attach | ValidTgts$ Player | AILogic$ Curse
T:Mode$ AttackersDeclared | ValidCard$ Creature | AttackedTarget$ Player.EnchantedBy | Execute$ TrigToken | TriggerZones$ Battlefield | TriggerDescription$ Whenever enchanted player is attacked, create a 2/2 black Zombie creature token. Each opponent attacking that player does the same. T:Mode$ AttackersDeclared | ValidCard$ Creature | AttackedTarget$ Player.EnchantedBy | Execute$ TrigToken | TriggerZones$ Battlefield | TriggerDescription$ Whenever enchanted player is attacked, create a 2/2 black Zombie creature token. Each opponent attacking that player does the same.
SVar:TrigToken:DB$ Token | TokenScript$ b_2_2_zombie | SubAbility$ DBToken SVar:TrigToken:DB$ Token | TokenScript$ b_2_2_zombie | SubAbility$ DBToken
SVar:DBToken:DB$ Token | TokenOwner$ TriggeredAttackingPlayerIfOpponent | TokenScript$ b_2_2_zombie SVar:DBToken:DB$ Token | TokenOwner$ TriggeredAttackingPlayer.Opponent | TokenScript$ b_2_2_zombie
Oracle:Enchant player\nWhenever enchanted player is attacked, create a 2/2 black Zombie creature token. Each opponent attacking that player does the same. Oracle:Enchant player\nWhenever enchanted player is attacked, create a 2/2 black Zombie creature token. Each opponent attacking that player does the same.

View File

@@ -5,5 +5,5 @@ K:Enchant player
A:SP$ Attach | ValidTgts$ Player | AILogic$ Curse A:SP$ Attach | ValidTgts$ Player | AILogic$ Curse
T:Mode$ AttackersDeclared | ValidCard$ Creature | AttackedTarget$ Player.EnchantedBy | Execute$ TrigToken | TriggerZones$ Battlefield | TriggerDescription$ Whenever enchanted player is attacked, create a Gold token. Each opponent attacking that player does the same. (A Gold token is an artifact with "Sacrifice this artifact: Add one mana of any color.") T:Mode$ AttackersDeclared | ValidCard$ Creature | AttackedTarget$ Player.EnchantedBy | Execute$ TrigToken | TriggerZones$ Battlefield | TriggerDescription$ Whenever enchanted player is attacked, create a Gold token. Each opponent attacking that player does the same. (A Gold token is an artifact with "Sacrifice this artifact: Add one mana of any color.")
SVar:TrigToken:DB$ Token | TokenScript$ c_a_gold_draw | SubAbility$ DBToken SVar:TrigToken:DB$ Token | TokenScript$ c_a_gold_draw | SubAbility$ DBToken
SVar:DBToken:DB$ Token | TokenOwner$ TriggeredAttackingPlayerIfOpponent | TokenScript$ c_a_gold_draw SVar:DBToken:DB$ Token | TokenOwner$ TriggeredAttackingPlayer.Opponent | TokenScript$ c_a_gold_draw
Oracle:Enchant player\nWhenever enchanted player is attacked, create a Gold token. Each opponent attacking that player does the same. (A Gold token is an artifact with "Sacrifice this artifact: Add one mana of any color.") Oracle:Enchant player\nWhenever enchanted player is attacked, create a Gold token. Each opponent attacking that player does the same. (A Gold token is an artifact with "Sacrifice this artifact: Add one mana of any color.")

View File

@@ -5,5 +5,5 @@ K:Enchant player
A:SP$ Attach | ValidTgts$ Player | AILogic$ Curse A:SP$ Attach | ValidTgts$ Player | AILogic$ Curse
T:Mode$ AttackersDeclared | ValidCard$ Creature | AttackedTarget$ Player.EnchantedBy | Execute$ TrigRepeat | TriggerZones$ Battlefield | TriggerDescription$ Whenever enchanted player is attacked, draw a card. Each opponent attacking that player does the same. T:Mode$ AttackersDeclared | ValidCard$ Creature | AttackedTarget$ Player.EnchantedBy | Execute$ TrigRepeat | TriggerZones$ Battlefield | TriggerDescription$ Whenever enchanted player is attacked, draw a card. Each opponent attacking that player does the same.
SVar:TrigDraw:DB$ Draw | NumCards$ 1 | Defined$ You SVar:TrigDraw:DB$ Draw | NumCards$ 1 | Defined$ You
SVar:DBDraw:DB$ Draw | NumCards$ 1 | Defined$ TriggeredAttackingPlayerIfOpponent SVar:DBDraw:DB$ Draw | NumCards$ 1 | Defined$ TriggeredAttackingPlayer.Opponent
Oracle:Enchant player\nWhenever enchanted player is attacked, you draw a card. Each opponent attacking that player does the same. Oracle:Enchant player\nWhenever enchanted player is attacked, you draw a card. Each opponent attacking that player does the same.

View File

@@ -5,6 +5,6 @@ K:Enchant player
A:SP$ Attach | ValidTgts$ Player | AILogic$ Curse A:SP$ Attach | ValidTgts$ Player | AILogic$ Curse
T:Mode$ AttackersDeclared | ValidCard$ Creature | AttackedTarget$ Player.EnchantedBy | Execute$ TrigGainLife | TriggerZones$ Battlefield | TriggerDescription$ Whenever enchanted player is attacked, you gain 2 life. Each opponent attacking that player does the same. T:Mode$ AttackersDeclared | ValidCard$ Creature | AttackedTarget$ Player.EnchantedBy | Execute$ TrigGainLife | TriggerZones$ Battlefield | TriggerDescription$ Whenever enchanted player is attacked, you gain 2 life. Each opponent attacking that player does the same.
SVar:TrigGainLife:DB$ GainLife | Defined$ You | LifeAmount$ 2 | SubAbility$ DBGainLife SVar:TrigGainLife:DB$ GainLife | Defined$ You | LifeAmount$ 2 | SubAbility$ DBGainLife
SVar:DBGainLife:DB$ GainLife | Defined$ TriggeredAttackingPlayerIfOpponent | LifeAmount$ 2 SVar:DBGainLife:DB$ GainLife | Defined$ TriggeredAttackingPlayer.Opponent | LifeAmount$ 2
DeckHas:Ability$LifeGain DeckHas:Ability$LifeGain
Oracle:Enchant player\nWhenever enchanted player is attacked, you gain 2 life. Each opponent attacking that player does the same. Oracle:Enchant player\nWhenever enchanted player is attacked, you gain 2 life. Each opponent attacking that player does the same.