Implemented Bands With Other

This commit is contained in:
L_J 2018-10-21 16:59:10 +02:00 committed by GitHub
parent 4e640dc8ab
commit 5a08632d59
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 727 additions and 43 deletions

View file

@ -0,0 +1,47 @@
package mage.cards.a;
import java.util.UUID;
import mage.ObjectColor;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
import mage.abilities.keyword.BandsWithOtherAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SuperType;
import mage.constants.Zone;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.mageobject.ColorPredicate;
import mage.filter.predicate.mageobject.SupertypePredicate;
/**
*
* @author L_J
*/
public final class AdventurersGuildhouse extends CardImpl {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Green legendary creatures");
static {
filter.add(new ColorPredicate(ObjectColor.GREEN));
filter.add(new SupertypePredicate(SuperType.LEGENDARY));
}
public AdventurersGuildhouse(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.LAND}, "");
// Green legendary creatures you control have "bands with other legendary creatures."
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityControlledEffect(new BandsWithOtherAbility(SuperType.LEGENDARY), Duration.WhileOnBattlefield, filter)));
}
public AdventurersGuildhouse(final AdventurersGuildhouse card) {
super(card);
}
@Override
public AdventurersGuildhouse copy() {
return new AdventurersGuildhouse(this);
}
}

View file

@ -0,0 +1,47 @@
package mage.cards.c;
import java.util.UUID;
import mage.ObjectColor;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
import mage.abilities.keyword.BandsWithOtherAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SuperType;
import mage.constants.Zone;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.mageobject.ColorPredicate;
import mage.filter.predicate.mageobject.SupertypePredicate;
/**
*
* @author L_J
*/
public final class CathedralOfSerra extends CardImpl {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("White legendary creatures");
static {
filter.add(new ColorPredicate(ObjectColor.WHITE));
filter.add(new SupertypePredicate(SuperType.LEGENDARY));
}
public CathedralOfSerra(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.LAND}, "");
// White legendary creatures you control have "bands with other legendary creatures."
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityControlledEffect(new BandsWithOtherAbility(SuperType.LEGENDARY), Duration.WhileOnBattlefield, filter)));
}
public CathedralOfSerra(final CathedralOfSerra card) {
super(card);
}
@Override
public CathedralOfSerra copy() {
return new CathedralOfSerra(this);
}
}

View file

@ -0,0 +1,40 @@
package mage.cards.m;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.game.permanent.token.WolvesOfTheHuntToken;
/**
* @author L_J
*/
public final class MasterOfTheHunt extends CardImpl {
public MasterOfTheHunt(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{G}{G}");
this.subtype.add(SubType.HUMAN);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
// Create a 1/1 green Wolf creature token named Wolves of the Hunt. It has bands with other creatures named Wolves of the Hunt.
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new CreateTokenEffect(new WolvesOfTheHuntToken()), new ManaCostsImpl("{2}{G}{G}")));
}
public MasterOfTheHunt(final MasterOfTheHunt card) {
super(card);
}
@Override
public MasterOfTheHunt copy() {
return new MasterOfTheHunt(this);
}
}

View file

@ -0,0 +1,47 @@
package mage.cards.m;
import java.util.UUID;
import mage.ObjectColor;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
import mage.abilities.keyword.BandsWithOtherAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SuperType;
import mage.constants.Zone;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.mageobject.ColorPredicate;
import mage.filter.predicate.mageobject.SupertypePredicate;
/**
*
* @author L_J
*/
public final class MountainStronghold extends CardImpl {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Red legendary creatures");
static {
filter.add(new ColorPredicate(ObjectColor.RED));
filter.add(new SupertypePredicate(SuperType.LEGENDARY));
}
public MountainStronghold(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.LAND}, "");
// Red legendary creatures you control have "bands with other legendary creatures."
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityControlledEffect(new BandsWithOtherAbility(SuperType.LEGENDARY), Duration.WhileOnBattlefield, filter)));
}
public MountainStronghold(final MountainStronghold card) {
super(card);
}
@Override
public MountainStronghold copy() {
return new MountainStronghold(this);
}
}

View file

@ -0,0 +1,75 @@
package mage.cards.o;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.keyword.BandsWithOtherAbility;
import mage.abilities.keyword.CumulativeUpkeepAbility;
import mage.abilities.keyword.EchoAbility;
import mage.abilities.keyword.FadingAbility;
import mage.abilities.keyword.FlankingAbility;
import mage.abilities.keyword.LandwalkAbility;
import mage.abilities.keyword.PhasingAbility;
import mage.abilities.keyword.ProtectionAbility;
import mage.abilities.keyword.RampageAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.filter.FilterCard;
import mage.filter.common.FilterLandPermanent;
import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.filter.predicate.mageobject.SupertypePredicate;
/**
*
* @author L_J
*/
public final class OldFogey extends CardImpl {
private static final FilterCard filter = new FilterCard("Homarids");
private static final FilterLandPermanent filter2 = new FilterLandPermanent("snow-covered plains");
static {
filter.add(new SubtypePredicate(SubType.HOMARID));
filter2.add(new SupertypePredicate(SuperType.SNOW));
filter2.add(new SubtypePredicate(SubType.PLAINS));
}
public OldFogey(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{G}{G}");
this.subtype.add(SubType.DINOSAUR);
this.power = new MageInt(7);
this.toughness = new MageInt(7);
// Phasing
this.addAbility(PhasingAbility.getInstance());
// Cumulative upkeep {1}
this.addAbility(new CumulativeUpkeepAbility(new ManaCostsImpl("{1}")));
// Echo {G}{G}
this.addAbility(new EchoAbility("{G}{G}"));
// Fading 3
this.addAbility(new FadingAbility(3, this));
// Bands with other Dinosaurs
this.addAbility(new BandsWithOtherAbility(SubType.DINOSAUR));
// Protection from Homarids
this.addAbility(new ProtectionAbility(filter));
// Snow-covered plainswalk
this.addAbility(new LandwalkAbility(filter2));
// Flanking
this.addAbility(new FlankingAbility());
// Rampage 2
this.addAbility(new RampageAbility(2));
}
public OldFogey(final OldFogey card) {
super(card);
}
@Override
public OldFogey copy() {
return new OldFogey(this);
}
}

View file

@ -0,0 +1,47 @@
package mage.cards.s;
import java.util.UUID;
import mage.ObjectColor;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
import mage.abilities.keyword.BandsWithOtherAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SuperType;
import mage.constants.Zone;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.mageobject.ColorPredicate;
import mage.filter.predicate.mageobject.SupertypePredicate;
/**
*
* @author L_J
*/
public final class SeafarersQuay extends CardImpl {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Blue legendary creatures");
static {
filter.add(new ColorPredicate(ObjectColor.BLUE));
filter.add(new SupertypePredicate(SuperType.LEGENDARY));
}
public SeafarersQuay(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.LAND}, "");
// Blue legendary creatures you control have "bands with other legendary creatures."
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityControlledEffect(new BandsWithOtherAbility(SuperType.LEGENDARY), Duration.WhileOnBattlefield, filter)));
}
public SeafarersQuay(final SeafarersQuay card) {
super(card);
}
@Override
public SeafarersQuay copy() {
return new SeafarersQuay(this);
}
}

View file

@ -0,0 +1,45 @@
package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.effects.common.continuous.LoseAbilityTargetEffect;
import mage.abilities.keyword.BandsWithOtherAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.Zone;
import mage.target.common.TargetCreaturePermanent;
/**
*
* @author L_J
*/
public final class ShelkinBrownie extends CardImpl {
public ShelkinBrownie(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{G}");
this.subtype.add(SubType.OUPHE);
this.power = new MageInt(1);
this.toughness = new MageInt(1);
// {T}: Target creature loses all "bands with other" abilities until end of turn.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new LoseAbilityTargetEffect(new BandsWithOtherAbility(), Duration.EndOfTurn), new TapSourceCost());
ability.addTarget(new TargetCreaturePermanent());
this.addAbility(ability);
}
public ShelkinBrownie(final ShelkinBrownie card) {
super(card);
}
@Override
public ShelkinBrownie copy() {
return new ShelkinBrownie(this);
}
}

View file

@ -0,0 +1,52 @@
package mage.cards.t;
import java.util.UUID;
import mage.abilities.ActivatedAbilityImpl;
import mage.abilities.condition.common.IsStepCondition;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.decorator.ConditionalActivatedAbility;
import mage.abilities.effects.common.continuous.LoseAbilityTargetEffect;
import mage.abilities.keyword.BandingAbility;
import mage.abilities.keyword.BandsWithOtherAbility;
import mage.abilities.mana.BlueManaAbility;
import mage.constants.SuperType;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import mage.target.common.TargetCreaturePermanent;
/**
*
* @author L_J
*/
public final class Tolaria extends CardImpl {
public Tolaria(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.LAND}, "");
this.addSuperType(SuperType.LEGENDARY);
// {T}: Add {U}.
this.addAbility(new BlueManaAbility());
// {T}: Target creature loses banding and all "bands with other" abilities until end of turn. Activate this ability only during any upkeep step.
ActivatedAbilityImpl ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD,
new LoseAbilityTargetEffect(BandingAbility.getInstance(), Duration.EndOfTurn), new TapSourceCost(), new IsStepCondition(PhaseStep.UPKEEP, false),
"{T}: Target creature loses banding and all \"bands with other\" abilities until end of turn. Activate this ability only during any upkeep step.");
ability.addEffect(new LoseAbilityTargetEffect(new BandsWithOtherAbility(), Duration.EndOfTurn));
ability.addTarget(new TargetCreaturePermanent());
this.addAbility(ability);
}
public Tolaria(final Tolaria card) {
super(card);
}
@Override
public Tolaria copy() {
return new Tolaria(this);
}
}

View file

@ -0,0 +1,47 @@
package mage.cards.u;
import java.util.UUID;
import mage.ObjectColor;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
import mage.abilities.keyword.BandsWithOtherAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SuperType;
import mage.constants.Zone;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.mageobject.ColorPredicate;
import mage.filter.predicate.mageobject.SupertypePredicate;
/**
*
* @author L_J
*/
public final class UnholyCitadel extends CardImpl {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Black legendary creatures");
static {
filter.add(new ColorPredicate(ObjectColor.BLACK));
filter.add(new SupertypePredicate(SuperType.LEGENDARY));
}
public UnholyCitadel(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.LAND}, "");
// Black legendary creatures you control have "bands with other legendary creatures."
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityControlledEffect(new BandsWithOtherAbility(SuperType.LEGENDARY), Duration.WhileOnBattlefield, filter)));
}
public UnholyCitadel(final UnholyCitadel card) {
super(card);
}
@Override
public UnholyCitadel copy() {
return new UnholyCitadel(this);
}
}

View file

@ -39,6 +39,7 @@ public final class Unhinged extends ExpansionSet {
cards.add(new SetCardInfo("Mountain", 139, Rarity.LAND, mage.cards.basiclands.Mountain.class, new CardGraphicInfo(FrameStyle.UNH_FULL_ART_BASIC, false))); cards.add(new SetCardInfo("Mountain", 139, Rarity.LAND, mage.cards.basiclands.Mountain.class, new CardGraphicInfo(FrameStyle.UNH_FULL_ART_BASIC, false)));
cards.add(new SetCardInfo("Mox Lotus", 124, Rarity.RARE, mage.cards.m.MoxLotus.class)); cards.add(new SetCardInfo("Mox Lotus", 124, Rarity.RARE, mage.cards.m.MoxLotus.class));
cards.add(new SetCardInfo("Now I Know My ABC's", 41, Rarity.RARE, mage.cards.n.NowIKnowMyABCs.class)); cards.add(new SetCardInfo("Now I Know My ABC's", 41, Rarity.RARE, mage.cards.n.NowIKnowMyABCs.class));
cards.add(new SetCardInfo("Old Fogey", 106, Rarity.RARE, mage.cards.o.OldFogey.class));
cards.add(new SetCardInfo("Plains", 136, Rarity.LAND, mage.cards.basiclands.Plains.class, new CardGraphicInfo(FrameStyle.UNH_FULL_ART_BASIC, false))); cards.add(new SetCardInfo("Plains", 136, Rarity.LAND, mage.cards.basiclands.Plains.class, new CardGraphicInfo(FrameStyle.UNH_FULL_ART_BASIC, false)));
cards.add(new SetCardInfo("Rare-B-Gone", 119, Rarity.RARE, mage.cards.r.RareBGone.class)); cards.add(new SetCardInfo("Rare-B-Gone", 119, Rarity.RARE, mage.cards.r.RareBGone.class));
cards.add(new SetCardInfo("Six-y Beast", 89, Rarity.UNCOMMON, mage.cards.s.SixyBeast.class)); cards.add(new SetCardInfo("Six-y Beast", 89, Rarity.UNCOMMON, mage.cards.s.SixyBeast.class));

View file

@ -0,0 +1,79 @@
package mage.abilities.keyword;
import mage.abilities.StaticAbility;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.constants.Zone;
/**
*
* @author L_J
*/
public class BandsWithOtherAbility extends StaticAbility {
private SubType subtype;
private SuperType supertype;
private String bandingName;
public BandsWithOtherAbility() {
this(null, null, null);
}
public BandsWithOtherAbility(SubType subtype) {
this(subtype, null, null);
}
public BandsWithOtherAbility(SuperType supertype) {
this(null, supertype, null);
}
public BandsWithOtherAbility(String bandingName) {
this(null, null, bandingName);
}
public BandsWithOtherAbility(SubType subtype, SuperType supertype, String bandingName) {
super(Zone.ALL, null);
this.subtype = subtype;
this.supertype = supertype;
this.bandingName = bandingName;
}
public BandsWithOtherAbility(BandsWithOtherAbility ability) {
super(ability);
this.subtype = ability.subtype;
this.supertype = ability.supertype;
this.bandingName = ability.bandingName;
}
@Override
public BandsWithOtherAbility copy() {
return new BandsWithOtherAbility(this);
}
public SubType getSubtype() {
return subtype;
}
public SuperType getSupertype() {
return supertype;
}
public String getName() {
return bandingName;
}
@Override
public String getRule() {
StringBuilder sb = new StringBuilder("bands with other");
if (subtype != null) {
return sb.append(' ').append(subtype.getDescription()).append('s').toString();
} else if (supertype != null) {
return sb.append(' ').append(supertype.toString()).append(" creatures").toString();
} else if (bandingName != null) {
return sb.append(" creatures named ").append(bandingName).toString();
}
return "all \"" + sb.toString() + "\" abilities";
}
}

View file

@ -6,6 +6,7 @@ import mage.abilities.Ability;
import mage.abilities.effects.RequirementEffect; import mage.abilities.effects.RequirementEffect;
import mage.abilities.effects.RestrictionEffect; import mage.abilities.effects.RestrictionEffect;
import mage.abilities.keyword.BandingAbility; import mage.abilities.keyword.BandingAbility;
import mage.abilities.keyword.BandsWithOtherAbility;
import mage.abilities.keyword.VigilanceAbility; import mage.abilities.keyword.VigilanceAbility;
import mage.abilities.keyword.special.JohanVigilanceAbility; import mage.abilities.keyword.special.JohanVigilanceAbility;
import mage.constants.Outcome; import mage.constants.Outcome;
@ -14,8 +15,12 @@ import mage.filter.StaticFilters;
import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.common.FilterCreatureForCombatBlock; import mage.filter.common.FilterCreatureForCombatBlock;
import mage.filter.common.FilterCreaturePermanent; import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.Predicate;
import mage.filter.predicate.Predicates; import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.AbilityPredicate; import mage.filter.predicate.mageobject.AbilityPredicate;
import mage.filter.predicate.mageobject.NamePredicate;
import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.filter.predicate.mageobject.SupertypePredicate;
import mage.filter.predicate.permanent.AttackingSameNotBandedPredicate; import mage.filter.predicate.permanent.AttackingSameNotBandedPredicate;
import mage.filter.predicate.permanent.PermanentIdPredicate; import mage.filter.predicate.permanent.PermanentIdPredicate;
import mage.game.Game; import mage.game.Game;
@ -293,53 +298,115 @@ public class Combat implements Serializable, Copyable<Combat> {
Permanent attacker = game.getPermanent(creatureId); Permanent attacker = game.getPermanent(creatureId);
if (attacker != null && player != null) { if (attacker != null && player != null) {
CombatGroup combatGroup = findGroup(attacker.getId()); CombatGroup combatGroup = findGroup(attacker.getId());
if (combatGroup != null && attacker.getAbilities().containsKey(BandingAbility.getInstance().getId()) && attacker.getBandedCards().isEmpty() && getAttackers().size() > 1) { if (combatGroup != null && attacker.getBandedCards().isEmpty() && getAttackers().size() > 1) {
boolean isBanded = false; boolean canBand = attacker.getAbilities().containsKey(BandingAbility.getInstance().getId());
FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("attacking creature to band with " + attacker.getLogName()); List<Ability> bandsWithOther = new ArrayList<>();
filter.add(Predicates.not(new PermanentIdPredicate(creatureId))); for (Ability ability : attacker.getAbilities()) {
filter.add(new AttackingSameNotBandedPredicate(combatGroup.getDefenderId())); // creature that isn't already banded, and is attacking the same player or planeswalker if (ability.getClass().equals(BandsWithOtherAbility.class)) {
while (player.canRespond()) { bandsWithOther.add(ability);
TargetControlledPermanent target = new TargetControlledPermanent(1, 1, filter, true);
target.setRequired(false);
if (!target.canChoose(attackingPlayerId, game)
|| game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.DECLARING_ATTACKERS, attackingPlayerId, attackingPlayerId))
|| !player.chooseUse(Outcome.Benefit, "Do you wish to " + (isBanded ? "band " + attacker.getLogName() + " with another " : "form a band with " + attacker.getLogName() + " and an ") + "attacking creature?", null, game)) {
break;
}
if (target.choose(Outcome.Benefit, attackingPlayerId, null, game)) {
isBanded = true;
for (UUID targetId : target.getTargets()) {
Permanent permanent = game.getPermanent(targetId);
if (permanent != null) {
for (UUID bandedId : attacker.getBandedCards()) {
permanent.addBandedCard(bandedId);
Permanent banded = game.getPermanent(bandedId);
if (banded != null) {
banded.addBandedCard(targetId);
}
}
permanent.addBandedCard(creatureId);
attacker.addBandedCard(targetId);
if (!permanent.getAbilities().containsKey(BandingAbility.getInstance().getId())) {
filter.add(new AbilityPredicate(BandingAbility.class));
}
}
}
} }
} }
if (isBanded) { boolean canBandWithOther = !bandsWithOther.isEmpty();
StringBuilder sb = new StringBuilder(player.getLogName()).append(" formed a band with ").append((attacker.getBandedCards().size() + 1) + " creatures: "); if (canBand || canBandWithOther) {
sb.append(attacker.getLogName()); boolean isBanded = false;
for (UUID id : attacker.getBandedCards()) { FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("attacking creature to band with " + attacker.getLogName());
sb.append(", "); filter.add(Predicates.not(new PermanentIdPredicate(creatureId)));
Permanent permanent = game.getPermanent(id); filter.add(new AttackingSameNotBandedPredicate(combatGroup.getDefenderId())); // creature that isn't already banded, and is attacking the same player or planeswalker
if (permanent != null) { List<Predicate<MageObject>> predicates = new ArrayList<>();
sb.append(permanent.getLogName()); if (!canBand && canBandWithOther) {
for (Ability ab : bandsWithOther) {
BandsWithOtherAbility ability = (BandsWithOtherAbility) ab;
if (ability.getSubtype() != null) {
predicates.add(new SubtypePredicate(ability.getSubtype()));
}
if (ability.getSupertype() != null) {
predicates.add(new SupertypePredicate(ability.getSupertype()));
}
if (ability.getName() != null) {
predicates.add(new NamePredicate(ability.getName()));
}
}
filter.add(Predicates.or(predicates));
}
while (player.canRespond()) {
TargetControlledPermanent target = new TargetControlledPermanent(1, 1, filter, true);
target.setRequired(false);
canBand &= target.canChoose(attackingPlayerId, game);
canBandWithOther &= target.canChoose(attackingPlayerId, game);
if (game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.DECLARING_ATTACKERS, attackingPlayerId, attackingPlayerId))
|| (!canBand && !canBandWithOther)
|| !player.chooseUse(Outcome.Benefit, "Do you wish to " + (isBanded ? "band " + attacker.getLogName() + " with another " : "form a band with " + attacker.getLogName() + " and an ") + "attacking creature?", null, game)) {
break;
}
if (canBand && canBandWithOther) {
if (player.chooseUse(Outcome.Detriment, "Choose type of banding ability to apply:", attacker.getLogName(), "Banding", "Bands with other", null, game)) {
canBandWithOther = false;
} else {
canBand = false;
for (Ability ab : bandsWithOther) {
BandsWithOtherAbility ability = (BandsWithOtherAbility) ab;
if (ability.getSubtype() != null) {
predicates.add(new SubtypePredicate(ability.getSubtype()));
}
if (ability.getSupertype() != null) {
predicates.add(new SupertypePredicate(ability.getSupertype()));
}
if (ability.getName() != null) {
predicates.add(new NamePredicate(ability.getName()));
}
}
filter.add(Predicates.or(predicates));
}
}
if (target.choose(Outcome.Benefit, attackingPlayerId, null, game)) {
isBanded = true;
for (UUID targetId : target.getTargets()) {
Permanent permanent = game.getPermanent(targetId);
if (permanent != null) {
for (UUID bandedId : attacker.getBandedCards()) {
permanent.addBandedCard(bandedId);
Permanent banded = game.getPermanent(bandedId);
if (banded != null) {
banded.addBandedCard(targetId);
}
}
permanent.addBandedCard(creatureId);
attacker.addBandedCard(targetId);
if (canBand) {
if (!permanent.getAbilities().containsKey(BandingAbility.getInstance().getId())) {
filter.add(new AbilityPredicate(BandingAbility.class));
canBandWithOther = false;
}
} else if (canBandWithOther) {
List<Predicate<MageObject>> newPredicates = new ArrayList<>();
for (Predicate<MageObject> predicate : predicates) {
if (predicate.apply(permanent, game)) {
newPredicates.add(predicate);
}
}
filter.add(Predicates.or(newPredicates));
canBand = false;
}
}
}
} }
} }
game.informPlayers(sb.toString()); if (isBanded) {
StringBuilder sb = new StringBuilder(player.getLogName()).append(" formed a band with ").append((attacker.getBandedCards().size() + 1) + " creatures: ");
sb.append(attacker.getLogName());
for (UUID id : attacker.getBandedCards()) {
sb.append(", ");
Permanent permanent = game.getPermanent(id);
if (permanent != null) {
sb.append(permanent.getLogName());
}
}
game.informPlayers(sb.toString());
}
} }
} }
} }

View file

@ -5,10 +5,12 @@ import java.io.Serializable;
import java.util.*; import java.util.*;
import java.util.stream.Stream; import java.util.stream.Stream;
import mage.abilities.Ability;
import mage.abilities.common.ControllerAssignCombatDamageToBlockersAbility; import mage.abilities.common.ControllerAssignCombatDamageToBlockersAbility;
import mage.abilities.common.ControllerDivideCombatDamageAbility; import mage.abilities.common.ControllerDivideCombatDamageAbility;
import mage.abilities.common.DamageAsThoughNotBlockedAbility; import mage.abilities.common.DamageAsThoughNotBlockedAbility;
import mage.abilities.keyword.BandingAbility; import mage.abilities.keyword.BandingAbility;
import mage.abilities.keyword.BandsWithOtherAbility;
import mage.abilities.keyword.CantBlockAloneAbility; import mage.abilities.keyword.CantBlockAloneAbility;
import mage.abilities.keyword.DeathtouchAbility; import mage.abilities.keyword.DeathtouchAbility;
import mage.abilities.keyword.DoubleStrikeAbility; import mage.abilities.keyword.DoubleStrikeAbility;
@ -110,6 +112,56 @@ public class CombatGroup implements Serializable, Copyable<CombatGroup> {
return perm.getAbilities().containsKey(BandingAbility.getInstance().getId()); return perm.getAbilities().containsKey(BandingAbility.getInstance().getId());
} }
private boolean appliesBandsWithOther(List<UUID> creatureIds, Game game) {
for (UUID creatureId : creatureIds) {
Permanent perm = game.getPermanent(creatureId);
if (perm != null && perm.getBandedCards() != null) {
for (Ability ab : perm.getAbilities()) {
if (ab.getClass().equals(BandsWithOtherAbility.class)) {
BandsWithOtherAbility ability = (BandsWithOtherAbility) ab;
if (ability.getSubtype() != null) {
if (perm.hasSubtype(ability.getSubtype(), game)) {
for (UUID bandedId : creatureIds) {
if (!bandedId.equals(creatureId)) {
Permanent banded = game.getPermanent(bandedId);
if (banded != null && banded.hasSubtype(ability.getSubtype(), game)) {
return true;
}
}
}
}
}
if (ability.getSupertype() != null) {
if (perm.getSuperType().contains(ability.getSupertype())) {
for (UUID bandedId : creatureIds) {
if (!bandedId.equals(creatureId)) {
Permanent banded = game.getPermanent(bandedId);
if (banded != null && banded.getSuperType().contains(ability.getSupertype())) {
return true;
}
}
}
}
}
if (ability.getName() != null) {
if (perm.getName().equals(ability.getName())) {
for (UUID bandedId : creatureIds) {
if (!bandedId.equals(creatureId)) {
Permanent banded = game.getPermanent(bandedId);
if (banded != null && banded.getName().equals(ability.getName())) {
return true;
}
}
}
}
}
}
}
}
}
return false;
}
public void assignDamageToBlockers(boolean first, Game game) { public void assignDamageToBlockers(boolean first, Game game) {
if (!attackers.isEmpty() && (!first || hasFirstOrDoubleStrike(game))) { if (!attackers.isEmpty() && (!first || hasFirstOrDoubleStrike(game))) {
Permanent attacker = game.getPermanent(attackers.get(0)); Permanent attacker = game.getPermanent(attackers.get(0));
@ -837,6 +889,9 @@ public class CombatGroup implements Serializable, Copyable<CombatGroup> {
} }
} }
} }
if (appliesBandsWithOther(attackers, game)) { // 702.21k - both a [quality] creature with bands with other [quality] and another [quality] creature (...)
return true;
}
return false; return false;
} }
@ -855,6 +910,9 @@ public class CombatGroup implements Serializable, Copyable<CombatGroup> {
} }
} }
} }
if (appliesBandsWithOther(blockers, game)) { // 702.21j - both a [quality] creature with bands with other [quality] and another [quality] creature (...)
return true;
}
for (Permanent defensiveFormation : game.getBattlefield().getAllActivePermanents(defendingPlayerId)) { for (Permanent defensiveFormation : game.getBattlefield().getAllActivePermanents(defendingPlayerId)) {
if (defensiveFormation.getAbilities().containsKey(ControllerAssignCombatDamageToBlockersAbility.getInstance().getId())) { if (defensiveFormation.getAbilities().containsKey(ControllerAssignCombatDamageToBlockersAbility.getInstance().getId())) {
return true; return true;

View file

@ -0,0 +1,32 @@
package mage.game.permanent.token;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.MageInt;
import mage.abilities.keyword.BandsWithOtherAbility;
/**
*
* @author L_J
*/
public final class WolvesOfTheHuntToken extends TokenImpl {
public WolvesOfTheHuntToken() {
super("Wolves of the Hunt", "1/1 green Wolf creature token named Wolves of the Hunt");
cardType.add(CardType.CREATURE);
subtype.add(SubType.WOLF);
color.setGreen(true);
power = new MageInt(1);
toughness = new MageInt(1);
this.addAbility(new BandsWithOtherAbility("Wolves of the Hunt"));
}
public WolvesOfTheHuntToken(final WolvesOfTheHuntToken token) {
super(token);
}
public WolvesOfTheHuntToken copy() {
return new WolvesOfTheHuntToken(this);
}
}