Merge branch 'exchangeControlTrickster' into 'master'

ExchangeControl: add Optional and two Targets also TargetsWithSameCardType

See merge request core-developers/forge!3705
This commit is contained in:
Michael Kamensky
2021-02-02 17:06:19 +00:00
20 changed files with 163 additions and 54 deletions

View File

@@ -352,6 +352,9 @@ public final class AbilityFactory {
if (mapParams.containsKey("TargetsWithSameCreatureType")) {
abTgt.setWithSameCreatureType(true);
}
if (mapParams.containsKey("TargetsWithSameCardType")) {
abTgt.setWithSameCardType(true);
}
if (mapParams.containsKey("TargetsWithSameController")) {
abTgt.setSameController(true);
}

View File

@@ -1,14 +1,16 @@
package forge.game.ability.effects;
import com.google.common.collect.Lists;
import forge.game.Game;
import forge.game.ability.AbilityUtils;
import forge.game.ability.SpellAbilityEffect;
import forge.game.card.Card;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetRestrictions;
import forge.util.CardTranslation;
import forge.util.Localizer;
import java.util.ArrayList;
import java.util.List;
@@ -21,21 +23,27 @@ public class ControlExchangeEffect extends SpellAbilityEffect {
protected String getStackDescription(SpellAbility sa) {
Card object1 = null;
Card object2 = null;
final TargetRestrictions tgt = sa.getTargetRestrictions();
List<Card> tgts = tgt == null ? new ArrayList<>() : Lists.newArrayList(sa.getTargets().getTargetCards());
if (tgts.size() > 0) {
object1 = tgts.get(0);
List<Card> tgts = null;
if (sa.usesTargeting()) {
tgts = Lists.newArrayList(sa.getTargets().getTargetCards());
if (tgts.size() > 0) {
object1 = tgts.get(0);
}
}
if (sa.hasParam("Defined")) {
List<Card> cards = AbilityUtils.getDefinedCards(sa.getHostCard(), sa.getParam("Defined"), sa);
object2 = cards.isEmpty() ? null : cards.get(0);
if (cards.size() > 1 && sa.hasParam("BothDefined")) {
if (cards.size() > 1 && !sa.usesTargeting()) {
object1 = cards.get(1);
}
} else if (tgts.size() > 1) {
object2 = tgts.get(1);
}
if (object1 == null || object2 == null) {
return "";
}
return object1 + " exchanges controller with " + object2;
}
@@ -44,17 +52,22 @@ public class ControlExchangeEffect extends SpellAbilityEffect {
*/
@Override
public void resolve(SpellAbility sa) {
Card host = sa.getHostCard();
Game game = host.getGame();
Card object1 = null;
Card object2 = null;
final TargetRestrictions tgt = sa.getTargetRestrictions();
List<Card> tgts = tgt == null ? new ArrayList<>() : Lists.newArrayList(sa.getTargets().getTargetCards());
if (tgts.size() > 0) {
object1 = tgts.get(0);
List<Card> tgts = null;
if (sa.usesTargeting()) {
tgts = Lists.newArrayList(sa.getTargets().getTargetCards());
if (tgts.size() > 0) {
object1 = tgts.get(0);
}
}
if (sa.hasParam("Defined")) {
final List<Card> cards = AbilityUtils.getDefinedCards(sa.getHostCard(), sa.getParam("Defined"), sa);
final List<Card> cards = AbilityUtils.getDefinedCards(host, sa.getParam("Defined"), sa);
object2 = cards.isEmpty() ? null : cards.get(0);
if (cards.size() > 1 && sa.hasParam("BothDefined")) {
if (cards.size() > 1 && !sa.usesTargeting()) {
object1 = cards.get(1);
}
} else if (tgts.size() > 1) {
@@ -73,7 +86,16 @@ public class ControlExchangeEffect extends SpellAbilityEffect {
return;
}
final long tStamp = sa.getActivatingPlayer().getGame().getNextTimestamp();
if (sa.hasParam("Optional")) {
if (!sa.getActivatingPlayer().getController().confirmAction(sa, null,
Localizer.getInstance().getMessage("lblExchangeControl",
CardTranslation.getTranslatedName(object1.getName()),
CardTranslation.getTranslatedName(object2.getName())))) {
return;
}
}
final long tStamp = game.getNextTimestamp();
object2.setController(player1, tStamp);
object1.setController(player2, tStamp);
if (sa.hasParam("RememberExchanged")) {

View File

@@ -1056,29 +1056,26 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
final Card c = (Card) entity;
CardCollection pl = AbilityUtils.getDefinedCards(getHostCard(), getParam("TargetsWithSharedCardType"), this);
for (final Card crd : pl) {
if (!c.sharesCardTypeWith(crd)) {
return false;
// one of those types
if (hasParam("TargetsWithSharedTypes")) {
boolean flag = false;
for (final String type : getParam("TargetsWithSharedTypes").split(",")) {
if (c.getType().hasStringType(type) && crd.getType().hasStringType(type)) {
flag = true;
break;
}
}
if (!flag) {
return false;
}
} else {
if (!c.sharesCardTypeWith(crd)) {
return false;
}
}
}
}
if (hasParam("TargetsWithSharedTypes") && entity instanceof Card) {
final Card c = (Card) entity;
final SpellAbility parent = getParentTargetingCard();
final Card parentTargeted = parent != null ? parent.getTargetCard() : null;
if (parentTargeted == null) {
return false;
}
boolean flag = false;
for (final String type : getParam("TargetsWithSharedTypes").split(",")) {
if (c.getType().hasStringType(type) && parentTargeted.getType().hasStringType(type)) {
flag = true;
break;
}
}
if (!flag) {
return false;
}
}
if (hasParam("TargetsWithControllerProperty") && entity instanceof Card) {
final String prop = getParam("TargetsWithControllerProperty");
final Card c = (Card) entity;
@@ -1172,6 +1169,16 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
}
}
if (tr.isWithSameCardType()) {
if (entity instanceof Card) {
for (final Card c : targetChosen.getTargetCards()) {
if (entity != c && !c.sharesCardTypeWith((Card) entity)) {
return false;
}
}
}
}
String[] validTgt = tr.getValidTgts();
if (entity instanceof GameEntity) {
GameEntity e = (GameEntity)entity;

View File

@@ -65,6 +65,7 @@ public class TargetRestrictions {
private boolean sameController = false;
private boolean withoutSameCreatureType = false;
private boolean withSameCreatureType = false;
private boolean withSameCardType = false;
private boolean singleTarget = false;
private boolean randomTarget = false;
@@ -108,6 +109,7 @@ public class TargetRestrictions {
this.sameController = target.isSameController();
this.withoutSameCreatureType = target.isWithoutSameCreatureType();
this.withSameCreatureType = target.isWithSameCreatureType();
this.withSameCardType = target.isWithSameCardType();
this.singleTarget = target.isSingleTarget();
this.randomTarget = target.isRandomTarget();
}
@@ -622,6 +624,20 @@ public class TargetRestrictions {
this.withSameCreatureType = b;
}
/**
* @return the withSameCardType
*/
public boolean isWithSameCardType() {
return withSameCardType;
}
/**
* @param b the withSameCardType to set
*/
public void setWithSameCardType(boolean b) {
this.withSameCardType = b;
}
/**
* <p>
* copy.