mirror of
https://github.com/magefree/mage.git
synced 2025-12-22 11:32:00 -08:00
Combat.getAttackers and Combat.getBlockers now return a Set instead of a List, so that two-headed blockers aren't included twice
This commit is contained in:
parent
efaccf8564
commit
a6c5209a2a
20 changed files with 192 additions and 354 deletions
|
|
@ -844,7 +844,7 @@ public class ComputerPlayer6 extends ComputerPlayer /*implements Player*/ {
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Permanent> getAttackers(Game game) {
|
private List<Permanent> getAttackers(Game game) {
|
||||||
List<UUID> attackersUUID = game.getCombat().getAttackers();
|
Set<UUID> attackersUUID = game.getCombat().getAttackers();
|
||||||
if (attackersUUID.isEmpty()) {
|
if (attackersUUID.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2815,7 +2815,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
|
||||||
log.debug(sb.toString());
|
log.debug(sb.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void playRemoval(List<UUID> creatures, Game game) {
|
private void playRemoval(Set<UUID> creatures, Game game) {
|
||||||
for (UUID creatureId : creatures) {
|
for (UUID creatureId : creatures) {
|
||||||
for (Card card : this.playableInstant) {
|
for (Card card : this.playableInstant) {
|
||||||
if (card.getSpellAbility().canActivate(playerId, game).canActivate()) {
|
if (card.getSpellAbility().canActivate(playerId, game).canActivate()) {
|
||||||
|
|
@ -2833,7 +2833,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void playDamage(List<UUID> creatures, Game game) {
|
private void playDamage(Set<UUID> creatures, Game game) {
|
||||||
for (UUID creatureId : creatures) {
|
for (UUID creatureId : creatures) {
|
||||||
Permanent creature = game.getPermanent(creatureId);
|
Permanent creature = game.getPermanent(creatureId);
|
||||||
for (Card card : this.playableInstant) {
|
for (Card card : this.playableInstant) {
|
||||||
|
|
|
||||||
|
|
@ -2,25 +2,19 @@ package mage.cards.f;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.TriggeredAbilityImpl;
|
import mage.abilities.common.AttacksAloneControlledTriggeredAbility;
|
||||||
import mage.abilities.effects.Effect;
|
import mage.abilities.condition.common.FirstCombatPhaseCondition;
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
|
||||||
|
import mage.abilities.effects.common.UntapTargetEffect;
|
||||||
|
import mage.abilities.effects.common.AdditionalCombatPhaseEffect;
|
||||||
import mage.abilities.keyword.ExaltedAbility;
|
import mage.abilities.keyword.ExaltedAbility;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Outcome;
|
|
||||||
import mage.constants.TurnPhase;
|
|
||||||
import mage.constants.Zone;
|
|
||||||
import mage.game.Game;
|
|
||||||
import mage.game.events.GameEvent;
|
|
||||||
import mage.game.permanent.Permanent;
|
|
||||||
import mage.game.turn.TurnMod;
|
|
||||||
import mage.target.targetpointer.FixedTarget;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author BetaSteward_at_googlemail.com
|
* @author awjackson
|
||||||
*/
|
*/
|
||||||
public final class FinestHour extends CardImpl {
|
public final class FinestHour extends CardImpl {
|
||||||
|
|
||||||
|
|
@ -32,7 +26,14 @@ public final class FinestHour extends CardImpl {
|
||||||
|
|
||||||
// Whenever a creature you control attacks alone, if it's the first combat phase of the turn, untap that
|
// Whenever a creature you control attacks alone, if it's the first combat phase of the turn, untap that
|
||||||
// creature. After this phase, there is an additional combat phase.
|
// creature. After this phase, there is an additional combat phase.
|
||||||
this.addAbility(new FinestHourAbility());
|
Ability ability = new ConditionalInterveningIfTriggeredAbility(
|
||||||
|
new AttacksAloneControlledTriggeredAbility(new UntapTargetEffect("untap that creature"), true, false),
|
||||||
|
FirstCombatPhaseCondition.instance,
|
||||||
|
"Whenever a creature you control attacks alone, if it's the first combat phase of the turn, " +
|
||||||
|
"untap that creature. After this phase, there is an additional combat phase."
|
||||||
|
);
|
||||||
|
ability.addEffect(new AdditionalCombatPhaseEffect());
|
||||||
|
this.addAbility(ability);
|
||||||
}
|
}
|
||||||
|
|
||||||
private FinestHour(final FinestHour card) {
|
private FinestHour(final FinestHour card) {
|
||||||
|
|
@ -43,78 +44,4 @@ public final class FinestHour extends CardImpl {
|
||||||
public FinestHour copy() {
|
public FinestHour copy() {
|
||||||
return new FinestHour(this);
|
return new FinestHour(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class FinestHourAbility extends TriggeredAbilityImpl {
|
|
||||||
|
|
||||||
public FinestHourAbility() {
|
|
||||||
super(Zone.BATTLEFIELD, new FinestHourEffect());
|
|
||||||
}
|
|
||||||
|
|
||||||
public FinestHourAbility(final FinestHourAbility ability) {
|
|
||||||
super(ability);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public FinestHourAbility copy() {
|
|
||||||
return new FinestHourAbility(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean checkEventType(GameEvent event, Game game) {
|
|
||||||
return event.getType() == GameEvent.EventType.DECLARED_ATTACKERS;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean checkTrigger(GameEvent event, Game game) {
|
|
||||||
if (game.isActivePlayer(this.controllerId)) {
|
|
||||||
if (game.getCombat().attacksAlone()) {
|
|
||||||
for (Effect effect : this.getEffects()) {
|
|
||||||
effect.setTargetPointer(new FixedTarget(game.getCombat().getAttackers().get(0), game));
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean checkInterveningIfClause(Game game) {
|
|
||||||
return game.getTurn().getPhase(TurnPhase.COMBAT).getCount() == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getRule() {
|
|
||||||
return "Whenever a creature you control attacks alone, if it's the first combat phase of the turn, untap that creature. After this phase, there is an additional combat phase.";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class FinestHourEffect extends OneShotEffect {
|
|
||||||
|
|
||||||
public FinestHourEffect() {
|
|
||||||
super(Outcome.Benefit);
|
|
||||||
}
|
|
||||||
|
|
||||||
public FinestHourEffect(final FinestHourEffect effect) {
|
|
||||||
super(effect);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public FinestHourEffect copy() {
|
|
||||||
return new FinestHourEffect(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean apply(Game game, Ability source) {
|
|
||||||
Permanent permanent = game.getPermanent(this.getTargetPointer().getFirst(game, source));
|
|
||||||
if (permanent != null) {
|
|
||||||
permanent.untap(game);
|
|
||||||
game.getState().getTurnMods().add(new TurnMod(source.getControllerId(), TurnPhase.COMBAT, null, false));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,10 +8,7 @@ import mage.abilities.effects.OneShotEffect;
|
||||||
import mage.abilities.keyword.EquipAbility;
|
import mage.abilities.keyword.EquipAbility;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.AttachmentType;
|
import mage.constants.*;
|
||||||
import mage.constants.CardType;
|
|
||||||
import mage.constants.Outcome;
|
|
||||||
import mage.constants.SubType;
|
|
||||||
import mage.counters.CounterType;
|
import mage.counters.CounterType;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
|
|
@ -37,7 +34,7 @@ public final class FractalHarness extends CardImpl {
|
||||||
|
|
||||||
// Whenever equipped creature attacks, double the number of +1/+1 counters on it.
|
// Whenever equipped creature attacks, double the number of +1/+1 counters on it.
|
||||||
this.addAbility(new AttacksAttachedTriggeredAbility(
|
this.addAbility(new AttacksAttachedTriggeredAbility(
|
||||||
new FractalHarnessDoubleEffect(), AttachmentType.EQUIPMENT, false, true
|
new FractalHarnessDoubleEffect(), AttachmentType.EQUIPMENT, false, SetTargetPointer.PERMANENT
|
||||||
));
|
));
|
||||||
|
|
||||||
// Equip {2}
|
// Equip {2}
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ import mage.game.permanent.Permanent;
|
||||||
import mage.game.turn.Phase;
|
import mage.game.turn.Phase;
|
||||||
import mage.game.turn.TurnMod;
|
import mage.game.turn.TurnMod;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.Set;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
|
@ -62,7 +62,7 @@ class IllusionistsGambitRemoveFromCombatEffect extends OneShotEffect {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
List<UUID> attackers = game.getCombat().getAttackers();
|
Set<UUID> attackers = game.getCombat().getAttackers();
|
||||||
for (UUID attackerId : attackers) {
|
for (UUID attackerId : attackers) {
|
||||||
Permanent creature = game.getPermanent(attackerId);
|
Permanent creature = game.getPermanent(attackerId);
|
||||||
if (creature != null) {
|
if (creature != null) {
|
||||||
|
|
@ -85,10 +85,10 @@ class IllusionistsGambitRemoveFromCombatEffect extends OneShotEffect {
|
||||||
|
|
||||||
class IllusionistsGambitRequirementEffect extends RequirementEffect {
|
class IllusionistsGambitRequirementEffect extends RequirementEffect {
|
||||||
|
|
||||||
private List attackers;
|
private Set<UUID> attackers;
|
||||||
private Phase phase;
|
private Phase phase;
|
||||||
|
|
||||||
public IllusionistsGambitRequirementEffect(List attackers, Phase phase) {
|
public IllusionistsGambitRequirementEffect(Set<UUID> attackers, Phase phase) {
|
||||||
super(Duration.Custom);
|
super(Duration.Custom);
|
||||||
this.attackers = attackers;
|
this.attackers = attackers;
|
||||||
this.phase = phase;
|
this.phase = phase;
|
||||||
|
|
@ -135,10 +135,10 @@ class IllusionistsGambitRequirementEffect extends RequirementEffect {
|
||||||
|
|
||||||
class IllusionistsGambitRestrictionEffect extends RestrictionEffect {
|
class IllusionistsGambitRestrictionEffect extends RestrictionEffect {
|
||||||
|
|
||||||
private final List attackers;
|
private final Set<UUID> attackers;
|
||||||
private final Phase phase;
|
private final Phase phase;
|
||||||
|
|
||||||
public IllusionistsGambitRestrictionEffect(List attackers, Phase phase) {
|
public IllusionistsGambitRestrictionEffect(Set<UUID> attackers, Phase phase) {
|
||||||
super(Duration.Custom, Outcome.Benefit);
|
super(Duration.Custom, Outcome.Benefit);
|
||||||
this.attackers = attackers;
|
this.attackers = attackers;
|
||||||
this.phase = phase;
|
this.phase = phase;
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import mage.MageInt;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.common.AttacksWithCreaturesTriggeredAbility;
|
import mage.abilities.common.AttacksWithCreaturesTriggeredAbility;
|
||||||
import mage.abilities.common.ChooseABackgroundAbility;
|
import mage.abilities.common.ChooseABackgroundAbility;
|
||||||
import mage.abilities.condition.Condition;
|
import mage.abilities.condition.common.FirstCombatPhaseCondition;
|
||||||
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
|
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
|
||||||
import mage.abilities.effects.common.AdditionalCombatPhaseEffect;
|
import mage.abilities.effects.common.AdditionalCombatPhaseEffect;
|
||||||
import mage.abilities.effects.common.UntapAllEffect;
|
import mage.abilities.effects.common.UntapAllEffect;
|
||||||
|
|
@ -32,11 +32,11 @@ public final class KarlachFuryOfAvernus extends CardImpl {
|
||||||
this.power = new MageInt(5);
|
this.power = new MageInt(5);
|
||||||
this.toughness = new MageInt(4);
|
this.toughness = new MageInt(4);
|
||||||
|
|
||||||
// Whenever you attack, if its the first combat phase of the turn, untap all attacking creatures. They gain first strike until end of turn. After this phase, there is an additional combat phase.
|
// Whenever you attack, if it's the first combat phase of the turn, untap all attacking creatures. They gain first strike until end of turn. After this phase, there is an additional combat phase.
|
||||||
Ability ability = new ConditionalInterveningIfTriggeredAbility(
|
Ability ability = new ConditionalInterveningIfTriggeredAbility(
|
||||||
new AttacksWithCreaturesTriggeredAbility(
|
new AttacksWithCreaturesTriggeredAbility(
|
||||||
new UntapAllEffect(StaticFilters.FILTER_ATTACKING_CREATURES), 1
|
new UntapAllEffect(StaticFilters.FILTER_ATTACKING_CREATURES), 1
|
||||||
), KarlachFuryOfAvernusCondition.instance, "Whenever you attack, if its the first " +
|
), FirstCombatPhaseCondition.instance, "Whenever you attack, if it's the first " +
|
||||||
"combat phase of the turn, untap all attacking creatures. They gain first strike " +
|
"combat phase of the turn, untap all attacking creatures. They gain first strike " +
|
||||||
"until end of turn. After this phase, there is an additional combat phase."
|
"until end of turn. After this phase, there is an additional combat phase."
|
||||||
);
|
);
|
||||||
|
|
@ -60,12 +60,3 @@ public final class KarlachFuryOfAvernus extends CardImpl {
|
||||||
return new KarlachFuryOfAvernus(this);
|
return new KarlachFuryOfAvernus(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum KarlachFuryOfAvernusCondition implements Condition {
|
|
||||||
instance;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean apply(Game game, Ability source) {
|
|
||||||
return game.getTurn().getPhase(TurnPhase.COMBAT).getCount() == 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,7 @@
|
||||||
|
|
||||||
package mage.cards.l;
|
package mage.cards.l;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import mage.MageObjectReference;
|
import mage.MageObjectReference;
|
||||||
|
|
@ -99,10 +97,9 @@ class LightmineFieldEffect extends OneShotEffect {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
List<UUID> attackers = game.getCombat().getAttackers();
|
int damage = game.getCombat().getAttackers().size();
|
||||||
int damage = attackers.size();
|
|
||||||
Set<MageObjectReference> attackSet = (Set<MageObjectReference>) getValue("Lightmine Field");
|
Set<MageObjectReference> attackSet = (Set<MageObjectReference>) getValue("Lightmine Field");
|
||||||
if (!attackers.isEmpty()) {
|
if (damage > 0) {
|
||||||
for (Iterator<MageObjectReference> it = attackSet.iterator(); it.hasNext();) {
|
for (Iterator<MageObjectReference> it = attackSet.iterator(); it.hasNext();) {
|
||||||
MageObjectReference attacker = it.next();
|
MageObjectReference attacker = it.next();
|
||||||
Permanent creature = attacker.getPermanent(game);
|
Permanent creature = attacker.getPermanent(game);
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,19 @@
|
||||||
|
|
||||||
package mage.cards.m;
|
package mage.cards.m;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.common.AttacksAttachedTriggeredAbility;
|
import mage.abilities.common.AttacksAttachedTriggeredAbility;
|
||||||
import mage.abilities.costs.mana.GenericManaCost;
|
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.OneShotEffect;
|
||||||
import mage.abilities.keyword.EquipAbility;
|
import mage.abilities.keyword.EquipAbility;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.*;
|
||||||
import mage.constants.SubType;
|
|
||||||
import mage.constants.Outcome;
|
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
import mage.target.common.TargetControlledCreaturePermanent;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author jeffwadsworth
|
* @author awjackson
|
||||||
*/
|
*/
|
||||||
public final class MageSlayer extends CardImpl {
|
public final class MageSlayer extends CardImpl {
|
||||||
|
|
||||||
|
|
@ -26,11 +21,13 @@ public final class MageSlayer extends CardImpl {
|
||||||
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}{R}{G}");
|
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}{R}{G}");
|
||||||
this.subtype.add(SubType.EQUIPMENT);
|
this.subtype.add(SubType.EQUIPMENT);
|
||||||
|
|
||||||
// Whenever equipped creature attacks, it deals damage equal to its power to defending player.
|
// Whenever equipped creature attacks, it deals damage equal to its power to the player or planeswalker it's attacking
|
||||||
this.addAbility(new AttacksAttachedTriggeredAbility(new MageSlayerEffect(), false));
|
this.addAbility(new AttacksAttachedTriggeredAbility(
|
||||||
|
new MageSlayerEffect(), AttachmentType.EQUIPMENT, false, SetTargetPointer.PERMANENT
|
||||||
|
));
|
||||||
|
|
||||||
// Equip {3}
|
// Equip {3}
|
||||||
this.addAbility(new EquipAbility(Outcome.Benefit, new GenericManaCost(3), new TargetControlledCreaturePermanent(), false));
|
this.addAbility(new EquipAbility(3, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
private MageSlayer(final MageSlayer card) {
|
private MageSlayer(final MageSlayer card) {
|
||||||
|
|
@ -61,18 +58,19 @@ class MageSlayerEffect extends OneShotEffect {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Permanent equipment = game.getPermanent(source.getSourceId());
|
Permanent attacker = getTargetPointer().getFirstTargetPermanentOrLKI(game, source);
|
||||||
if (equipment != null && equipment.getAttachedTo() != null) {
|
if (attacker == null) {
|
||||||
int power = game.getPermanent(equipment.getAttachedTo()).getPower().getValue();
|
|
||||||
UUID defenderId = game.getCombat().getDefenderId(equipment.getAttachedTo());
|
|
||||||
if (power > 0 && defenderId != null) {
|
|
||||||
UUID sourceId = (UUID) this.getValue("sourceId");
|
|
||||||
if (sourceId != null) {
|
|
||||||
game.damagePlayerOrPlaneswalker(defenderId, power, source.getSourceId(), source, game, false, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
game.damagePlayerOrPlaneswalker(
|
||||||
|
game.getCombat().getDefenderId(attacker.getId()),
|
||||||
|
attacker.getPower().getValue(),
|
||||||
|
attacker.getId(),
|
||||||
|
source,
|
||||||
|
game,
|
||||||
|
false,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package mage.cards.m;
|
package mage.cards.m;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
|
@ -108,8 +108,8 @@ class MandateOfPeaceEndCombatEffect extends OneShotEffect {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Combat combat = game.getCombat();
|
Combat combat = game.getCombat();
|
||||||
List<UUID> attackerIds = combat.getAttackers();
|
Set<UUID> attackerIds = combat.getAttackers();
|
||||||
List<UUID> blockerIds = combat.getBlockers();
|
Set<UUID> blockerIds = combat.getBlockers();
|
||||||
Stream.concat(blockerIds.stream(), attackerIds.stream())
|
Stream.concat(blockerIds.stream(), attackerIds.stream())
|
||||||
.map(id -> game.getPermanent(id))
|
.map(id -> game.getPermanent(id))
|
||||||
.filter(e -> e != null)
|
.filter(e -> e != null)
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,9 @@ package mage.cards.r;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import mage.abilities.TriggeredAbilityImpl;
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.common.AttacksAloneAttachedTriggeredAbility;
|
||||||
import mage.abilities.common.AttacksAttachedTriggeredAbility;
|
import mage.abilities.common.AttacksAttachedTriggeredAbility;
|
||||||
import mage.abilities.effects.Effect;
|
|
||||||
import mage.abilities.effects.common.GainLifeEffect;
|
import mage.abilities.effects.common.GainLifeEffect;
|
||||||
import mage.abilities.effects.common.LoseLifeTargetEffect;
|
import mage.abilities.effects.common.LoseLifeTargetEffect;
|
||||||
import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect;
|
import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect;
|
||||||
|
|
@ -13,14 +13,10 @@ import mage.abilities.keyword.EquipAbility;
|
||||||
import mage.constants.*;
|
import mage.constants.*;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.game.Game;
|
|
||||||
import mage.game.events.GameEvent;
|
|
||||||
import mage.game.permanent.Permanent;
|
|
||||||
import mage.target.targetpointer.FixedTarget;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author weirddan455
|
* @author awjackson
|
||||||
*/
|
*/
|
||||||
public final class ReapersTalisman extends CardImpl {
|
public final class ReapersTalisman extends CardImpl {
|
||||||
|
|
||||||
|
|
@ -38,7 +34,12 @@ public final class ReapersTalisman extends CardImpl {
|
||||||
)));
|
)));
|
||||||
|
|
||||||
// Whenever equipped creature attacks alone, defending player loses 2 life and you gain 2 life.
|
// Whenever equipped creature attacks alone, defending player loses 2 life and you gain 2 life.
|
||||||
this.addAbility(new ReapersTalismanAttacksLoneTriggeredAbility());
|
Ability ability = new AttacksAloneAttachedTriggeredAbility(
|
||||||
|
new LoseLifeTargetEffect(2).setText("defending player loses 2 life"),
|
||||||
|
AttachmentType.EQUIPMENT, false, SetTargetPointer.PLAYER
|
||||||
|
);
|
||||||
|
ability.addEffect(new GainLifeEffect(2).concatBy("and"));
|
||||||
|
this.addAbility(ability);
|
||||||
|
|
||||||
// Equip {2}
|
// Equip {2}
|
||||||
this.addAbility(new EquipAbility(2));
|
this.addAbility(new EquipAbility(2));
|
||||||
|
|
@ -53,48 +54,3 @@ public final class ReapersTalisman extends CardImpl {
|
||||||
return new ReapersTalisman(this);
|
return new ReapersTalisman(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ReapersTalismanAttacksLoneTriggeredAbility extends TriggeredAbilityImpl {
|
|
||||||
|
|
||||||
public ReapersTalismanAttacksLoneTriggeredAbility() {
|
|
||||||
super(Zone.BATTLEFIELD, new LoseLifeTargetEffect(2));
|
|
||||||
this.addEffect(new GainLifeEffect(2));
|
|
||||||
}
|
|
||||||
|
|
||||||
private ReapersTalismanAttacksLoneTriggeredAbility(final ReapersTalismanAttacksLoneTriggeredAbility ability) {
|
|
||||||
super(ability);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ReapersTalismanAttacksLoneTriggeredAbility copy() {
|
|
||||||
return new ReapersTalismanAttacksLoneTriggeredAbility(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean checkEventType(GameEvent event, Game game) {
|
|
||||||
return event.getType() == GameEvent.EventType.DECLARED_ATTACKERS;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean checkTrigger(GameEvent event, Game game) {
|
|
||||||
if (game.isActivePlayer(this.controllerId) && game.getCombat().attacksAlone()) {
|
|
||||||
Permanent equipment = game.getPermanent(this.sourceId);
|
|
||||||
UUID attackerId = game.getCombat().getAttackers().get(0);
|
|
||||||
if (equipment != null && equipment.isAttachedTo(attackerId)) {
|
|
||||||
UUID defender = game.getCombat().getDefendingPlayerId(attackerId, game);
|
|
||||||
if (defender != null) {
|
|
||||||
for (Effect effect : this.getEffects()) {
|
|
||||||
effect.setTargetPointer(new FixedTarget(defender));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getRule() {
|
|
||||||
return "Whenever equipped creature attacks alone, defending player loses 2 life and you gain 2 life.";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
package mage.cards.s;
|
package mage.cards.s;
|
||||||
|
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.TriggeredAbilityImpl;
|
import mage.abilities.common.AttacksAloneAttachedTriggeredAbility;
|
||||||
import mage.abilities.costs.mana.GenericManaCost;
|
|
||||||
import mage.abilities.dynamicvalue.DynamicValue;
|
import mage.abilities.dynamicvalue.DynamicValue;
|
||||||
import mage.abilities.effects.Effect;
|
import mage.abilities.effects.Effect;
|
||||||
import mage.abilities.effects.common.continuous.BoostTargetEffect;
|
import mage.abilities.effects.common.continuous.BoostTargetEffect;
|
||||||
|
|
@ -10,19 +9,15 @@ import mage.abilities.keyword.EquipAbility;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.*;
|
import mage.constants.*;
|
||||||
import mage.filter.FilterPermanent;
|
|
||||||
import mage.filter.common.FilterControlledCreaturePermanent;
|
import mage.filter.common.FilterControlledCreaturePermanent;
|
||||||
import mage.filter.predicate.Predicates;
|
import mage.filter.predicate.Predicates;
|
||||||
import mage.filter.predicate.mageobject.CardIdPredicate;
|
import mage.filter.predicate.mageobject.CardIdPredicate;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.events.GameEvent;
|
|
||||||
import mage.game.permanent.Permanent;
|
|
||||||
import mage.target.targetpointer.FixedTarget;
|
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author LevelX2
|
* @author awjackson
|
||||||
*/
|
*/
|
||||||
public final class SigilOfValor extends CardImpl {
|
public final class SigilOfValor extends CardImpl {
|
||||||
|
|
||||||
|
|
@ -31,10 +26,13 @@ public final class SigilOfValor extends CardImpl {
|
||||||
this.subtype.add(SubType.EQUIPMENT);
|
this.subtype.add(SubType.EQUIPMENT);
|
||||||
|
|
||||||
// Whenever equipped creature attacks alone, it gets +1/+1 until end of turn for each other creature you control.
|
// Whenever equipped creature attacks alone, it gets +1/+1 until end of turn for each other creature you control.
|
||||||
this.addAbility(new SigilOfValorTriggeredAbility(new SigilOfValorCount()));
|
this.addAbility(new AttacksAloneAttachedTriggeredAbility(
|
||||||
|
new BoostTargetEffect(SigilOfValorCount.instance, SigilOfValorCount.instance, Duration.EndOfTurn),
|
||||||
|
AttachmentType.EQUIPMENT, false, SetTargetPointer.PERMANENT
|
||||||
|
));
|
||||||
|
|
||||||
// Equip {1}
|
// Equip {1}
|
||||||
this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(1)));
|
this.addAbility(new EquipAbility(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
private SigilOfValor(final SigilOfValor card) {
|
private SigilOfValor(final SigilOfValor card) {
|
||||||
|
|
@ -47,81 +45,32 @@ public final class SigilOfValor extends CardImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SigilOfValorTriggeredAbility extends TriggeredAbilityImpl {
|
enum SigilOfValorCount implements DynamicValue {
|
||||||
|
instance;
|
||||||
public SigilOfValorTriggeredAbility(DynamicValue boostValue) {
|
|
||||||
super(Zone.BATTLEFIELD, new BoostTargetEffect(boostValue, boostValue, Duration.EndOfTurn));
|
|
||||||
}
|
|
||||||
|
|
||||||
public SigilOfValorTriggeredAbility(final SigilOfValorTriggeredAbility ability) {
|
|
||||||
super(ability);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SigilOfValorTriggeredAbility copy() {
|
|
||||||
return new SigilOfValorTriggeredAbility(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean checkEventType(GameEvent event, Game game) {
|
|
||||||
return event.getType() == GameEvent.EventType.DECLARED_ATTACKERS;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean checkTrigger(GameEvent event, Game game) {
|
|
||||||
if (game.isActivePlayer(getControllerId())) {
|
|
||||||
if (game.getCombat().attacksAlone()) {
|
|
||||||
Permanent equipment = game.getPermanent(getSourceId());
|
|
||||||
UUID attackerId = game.getCombat().getAttackers().get(0);
|
|
||||||
if (equipment != null
|
|
||||||
&& equipment.isAttachedTo(attackerId)) {
|
|
||||||
this.getEffects().get(0).setTargetPointer(new FixedTarget(attackerId, game));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getRule() {
|
|
||||||
return "Whenever equipped creature attacks alone, it gets +1/+1 until end of turn for each other creature you control.";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class SigilOfValorCount implements DynamicValue {
|
|
||||||
|
|
||||||
public SigilOfValorCount() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public SigilOfValorCount(final SigilOfValorCount dynamicValue) {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int calculate(Game game, Ability sourceAbility, Effect effect) {
|
public int calculate(Game game, Ability sourceAbility, Effect effect) {
|
||||||
Permanent equipment = game.getPermanent(sourceAbility.getSourceId());
|
UUID attackerId = effect.getTargetPointer().getFirst(game, sourceAbility);
|
||||||
if (equipment != null && equipment.getAttachedTo() != null) {
|
if (attackerId != null) {
|
||||||
FilterPermanent filterPermanent = new FilterControlledCreaturePermanent();
|
FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent();
|
||||||
filterPermanent.add(Predicates.not(new CardIdPredicate(equipment.getAttachedTo())));
|
filter.add(Predicates.not(new CardIdPredicate(attackerId)));
|
||||||
return game.getBattlefield().count(filterPermanent, sourceAbility.getControllerId(), sourceAbility, game);
|
return game.getBattlefield().count(filter, sourceAbility.getControllerId(), sourceAbility, game);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DynamicValue copy() {
|
public DynamicValue copy() {
|
||||||
return new SigilOfValorCount(this);
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "X";
|
return "1";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getMessage() {
|
public String getMessage() {
|
||||||
return "";
|
return "other creature you control";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import mage.abilities.keyword.EquipAbility;
|
||||||
import mage.abilities.keyword.TrampleAbility;
|
import mage.abilities.keyword.TrampleAbility;
|
||||||
import mage.constants.AttachmentType;
|
import mage.constants.AttachmentType;
|
||||||
import mage.constants.Duration;
|
import mage.constants.Duration;
|
||||||
|
import mage.constants.SetTargetPointer;
|
||||||
import mage.constants.SubType;
|
import mage.constants.SubType;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
|
|
@ -37,7 +38,7 @@ public final class SpikedRipsaw extends CardImpl {
|
||||||
// Whenever equipped creature attacks, you may sacrifice a Forest. If you do, that creature gains trample until end of turn.
|
// Whenever equipped creature attacks, you may sacrifice a Forest. If you do, that creature gains trample until end of turn.
|
||||||
this.addAbility(new AttacksAttachedTriggeredAbility(
|
this.addAbility(new AttacksAttachedTriggeredAbility(
|
||||||
new DoIfCostPaid(new GainAbilityTargetEffect(TrampleAbility.getInstance(), Duration.EndOfTurn, "that creature gains trample until end of turn"), new SacrificeTargetCost(filter)),
|
new DoIfCostPaid(new GainAbilityTargetEffect(TrampleAbility.getInstance(), Duration.EndOfTurn, "that creature gains trample until end of turn"), new SacrificeTargetCost(filter)),
|
||||||
AttachmentType.EQUIPMENT, false, true
|
AttachmentType.EQUIPMENT, false, SetTargetPointer.PERMANENT
|
||||||
));
|
));
|
||||||
|
|
||||||
// Equip {3}
|
// Equip {3}
|
||||||
|
|
|
||||||
|
|
@ -10,10 +10,7 @@ import mage.abilities.keyword.DoubleStrikeAbility;
|
||||||
import mage.abilities.keyword.EquipAbility;
|
import mage.abilities.keyword.EquipAbility;
|
||||||
import mage.cards.AdventureCard;
|
import mage.cards.AdventureCard;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.AttachmentType;
|
import mage.constants.*;
|
||||||
import mage.constants.CardType;
|
|
||||||
import mage.constants.Outcome;
|
|
||||||
import mage.constants.SubType;
|
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
import mage.target.common.TargetControlledCreaturePermanent;
|
import mage.target.common.TargetControlledCreaturePermanent;
|
||||||
|
|
@ -33,7 +30,7 @@ public final class TwoHandedAxe extends AdventureCard {
|
||||||
|
|
||||||
// Whenever equipped creature attacks, double its power until end of turn.
|
// Whenever equipped creature attacks, double its power until end of turn.
|
||||||
this.addAbility(new AttacksAttachedTriggeredAbility(
|
this.addAbility(new AttacksAttachedTriggeredAbility(
|
||||||
new TwoHandedAxeEffect(), AttachmentType.EQUIPMENT, false, true
|
new TwoHandedAxeEffect(), AttachmentType.EQUIPMENT, false, SetTargetPointer.PERMANENT
|
||||||
));
|
));
|
||||||
|
|
||||||
// Equip {1}{R}
|
// Equip {1}{R}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
package mage.abilities.common;
|
||||||
|
|
||||||
|
import mage.abilities.effects.Effect;
|
||||||
|
import mage.constants.AttachmentType;
|
||||||
|
import mage.constants.SetTargetPointer;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.game.events.GameEvent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author awjackson
|
||||||
|
*/
|
||||||
|
public class AttacksAloneAttachedTriggeredAbility extends AttacksAttachedTriggeredAbility {
|
||||||
|
|
||||||
|
public AttacksAloneAttachedTriggeredAbility(Effect effect) {
|
||||||
|
this(effect, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AttacksAloneAttachedTriggeredAbility(Effect effect, boolean optional) {
|
||||||
|
this(effect, AttachmentType.EQUIPMENT, optional);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AttacksAloneAttachedTriggeredAbility(Effect effect, AttachmentType attachmentType, boolean optional) {
|
||||||
|
this(effect, attachmentType, optional, SetTargetPointer.NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AttacksAloneAttachedTriggeredAbility(Effect effect, AttachmentType attachmentType, boolean optional, SetTargetPointer setTargetPointer) {
|
||||||
|
super(effect, attachmentType, optional, setTargetPointer);
|
||||||
|
setTriggerPhrase("Whenever " + attachmentType.verb().toLowerCase() + " creature attacks alone, ");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected AttacksAloneAttachedTriggeredAbility(final AttacksAloneAttachedTriggeredAbility ability) {
|
||||||
|
super(ability);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AttacksAloneAttachedTriggeredAbility copy() {
|
||||||
|
return new AttacksAloneAttachedTriggeredAbility(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean checkTrigger(GameEvent event, Game game) {
|
||||||
|
return game.getCombat().attacksAlone() && super.checkTrigger(event, game);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -10,7 +10,6 @@ import mage.game.events.GameEvent;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
import mage.target.targetpointer.FixedTarget;
|
import mage.target.targetpointer.FixedTarget;
|
||||||
import mage.util.CardUtil;
|
import mage.util.CardUtil;
|
||||||
import mage.util.CardUtil;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author TheElk801
|
* @author TheElk801
|
||||||
|
|
@ -39,7 +38,7 @@ public class AttacksAloneControlledTriggeredAbility extends TriggeredAbilityImpl
|
||||||
setTriggerPhrase("Whenever " + CardUtil.addArticle(filter.getMessage()) + " attacks alone, ");
|
setTriggerPhrase("Whenever " + CardUtil.addArticle(filter.getMessage()) + " attacks alone, ");
|
||||||
}
|
}
|
||||||
|
|
||||||
private AttacksAloneControlledTriggeredAbility(final AttacksAloneControlledTriggeredAbility ability) {
|
protected AttacksAloneControlledTriggeredAbility(final AttacksAloneControlledTriggeredAbility ability) {
|
||||||
super(ability);
|
super(ability);
|
||||||
this.filter = ability.filter;
|
this.filter = ability.filter;
|
||||||
this.setTargetPointer = ability.setTargetPointer;
|
this.setTargetPointer = ability.setTargetPointer;
|
||||||
|
|
@ -52,7 +51,7 @@ public class AttacksAloneControlledTriggeredAbility extends TriggeredAbilityImpl
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean checkEventType(GameEvent event, Game game) {
|
public boolean checkEventType(GameEvent event, Game game) {
|
||||||
return event.getType() == GameEvent.EventType.DECLARED_ATTACKERS;
|
return event.getType() == GameEvent.EventType.ATTACKER_DECLARED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -60,7 +59,7 @@ public class AttacksAloneControlledTriggeredAbility extends TriggeredAbilityImpl
|
||||||
if (!game.getCombat().attacksAlone()) {
|
if (!game.getCombat().attacksAlone()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Permanent permanent = game.getPermanent(game.getCombat().getAttackers().get(0));
|
Permanent permanent = game.getPermanent(event.getSourceId());
|
||||||
if (permanent == null || !filter.match(permanent, getControllerId(), this, game)) {
|
if (permanent == null || !filter.match(permanent, getControllerId(), this, game)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,5 @@
|
||||||
|
|
||||||
package mage.abilities.common;
|
package mage.abilities.common;
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.UUID;
|
|
||||||
import mage.abilities.TriggeredAbilityImpl;
|
import mage.abilities.TriggeredAbilityImpl;
|
||||||
import mage.abilities.effects.Effect;
|
import mage.abilities.effects.Effect;
|
||||||
import mage.constants.Zone;
|
import mage.constants.Zone;
|
||||||
|
|
@ -21,7 +18,7 @@ public class AttacksAloneSourceTriggeredAbility extends TriggeredAbilityImpl {
|
||||||
setTriggerPhrase("Whenever {this} attacks alone, ");
|
setTriggerPhrase("Whenever {this} attacks alone, ");
|
||||||
}
|
}
|
||||||
|
|
||||||
public AttacksAloneSourceTriggeredAbility(final AttacksAloneSourceTriggeredAbility ability) {
|
protected AttacksAloneSourceTriggeredAbility(final AttacksAloneSourceTriggeredAbility ability) {
|
||||||
super(ability);
|
super(ability);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -32,25 +29,15 @@ public class AttacksAloneSourceTriggeredAbility extends TriggeredAbilityImpl {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean checkEventType(GameEvent event, Game game) {
|
public boolean checkEventType(GameEvent event, Game game) {
|
||||||
return event.getType() == GameEvent.EventType.DECLARED_ATTACKERS;
|
return event.getType() == GameEvent.EventType.ATTACKER_DECLARED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean checkTrigger(GameEvent event, Game game) {
|
public boolean checkTrigger(GameEvent event, Game game) {
|
||||||
if(game.isActivePlayer(this.controllerId) ) {
|
if (!getSourceId().equals(event.getSourceId()) || !game.getCombat().attacksAlone()) {
|
||||||
UUID creatureId = this.getSourceId();
|
|
||||||
if(creatureId != null) {
|
|
||||||
if(game.getCombat().attacksAlone() && Objects.equals(creatureId, game.getCombat().getAttackers().get(0))) {
|
|
||||||
UUID defender = game.getCombat().getDefenderId(creatureId);
|
|
||||||
if(defender != null) {
|
|
||||||
for(Effect effect: getEffects()) {
|
|
||||||
effect.setTargetPointer(new FixedTarget(defender));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
getEffects().setTargetPointer(new FixedTarget(game.getCombat().getDefendingPlayerId(getSourceId(), game)));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,16 @@
|
||||||
|
|
||||||
package mage.abilities.common;
|
package mage.abilities.common;
|
||||||
|
|
||||||
import mage.abilities.TriggeredAbilityImpl;
|
import mage.abilities.TriggeredAbilityImpl;
|
||||||
import mage.abilities.effects.Effect;
|
import mage.abilities.effects.Effect;
|
||||||
import mage.constants.AttachmentType;
|
import mage.constants.AttachmentType;
|
||||||
|
import mage.constants.SetTargetPointer;
|
||||||
import mage.constants.Zone;
|
import mage.constants.Zone;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.events.GameEvent;
|
import mage.game.events.GameEvent;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
import mage.target.targetpointer.FixedTarget;
|
import mage.target.targetpointer.FixedTarget;
|
||||||
|
|
||||||
import java.util.Locale;
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* "When enchanted/equipped creature attacks " triggered ability
|
* "When enchanted/equipped creature attacks " triggered ability
|
||||||
|
|
@ -20,7 +20,7 @@ import java.util.Locale;
|
||||||
public class AttacksAttachedTriggeredAbility extends TriggeredAbilityImpl {
|
public class AttacksAttachedTriggeredAbility extends TriggeredAbilityImpl {
|
||||||
|
|
||||||
private final AttachmentType attachmentType;
|
private final AttachmentType attachmentType;
|
||||||
private final boolean setTargetPointer;
|
private final SetTargetPointer setTargetPointer;
|
||||||
|
|
||||||
public AttacksAttachedTriggeredAbility(Effect effect) {
|
public AttacksAttachedTriggeredAbility(Effect effect) {
|
||||||
this(effect, false);
|
this(effect, false);
|
||||||
|
|
@ -31,20 +31,20 @@ public class AttacksAttachedTriggeredAbility extends TriggeredAbilityImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
public AttacksAttachedTriggeredAbility(Effect effect, AttachmentType attachmentType, boolean optional) {
|
public AttacksAttachedTriggeredAbility(Effect effect, AttachmentType attachmentType, boolean optional) {
|
||||||
this(effect, attachmentType, optional, false);
|
this(effect, attachmentType, optional, SetTargetPointer.NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public AttacksAttachedTriggeredAbility(Effect effect, AttachmentType attachmentType, boolean optional, boolean setTargetPointer) {
|
public AttacksAttachedTriggeredAbility(Effect effect, AttachmentType attachmentType, boolean optional, SetTargetPointer setTargetPointer) {
|
||||||
super(Zone.BATTLEFIELD, effect, optional);
|
super(Zone.BATTLEFIELD, effect, optional);
|
||||||
this.attachmentType = attachmentType;
|
this.attachmentType = attachmentType;
|
||||||
this.setTargetPointer = setTargetPointer;
|
this.setTargetPointer = setTargetPointer;
|
||||||
setTriggerPhrase("Whenever " + attachmentType.verb().toLowerCase(Locale.ENGLISH) + " creature attacks, ");
|
setTriggerPhrase("Whenever " + attachmentType.verb().toLowerCase() + " creature attacks, ");
|
||||||
}
|
}
|
||||||
|
|
||||||
public AttacksAttachedTriggeredAbility(final AttacksAttachedTriggeredAbility abiltity) {
|
protected AttacksAttachedTriggeredAbility(final AttacksAttachedTriggeredAbility ability) {
|
||||||
super(abiltity);
|
super(ability);
|
||||||
this.attachmentType = abiltity.attachmentType;
|
this.attachmentType = ability.attachmentType;
|
||||||
this.setTargetPointer = abiltity.setTargetPointer;
|
this.setTargetPointer = ability.setTargetPointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -59,20 +59,19 @@ public class AttacksAttachedTriggeredAbility extends TriggeredAbilityImpl {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean checkTrigger(GameEvent event, Game game) {
|
public boolean checkTrigger(GameEvent event, Game game) {
|
||||||
Permanent equipment = game.getPermanent(this.sourceId);
|
Permanent attachment = getSourcePermanentOrLKI(game);
|
||||||
if (equipment != null && equipment.getAttachedTo() != null
|
UUID attackerId = event.getSourceId();
|
||||||
&& event.getSourceId().equals(equipment.getAttachedTo())) {
|
if (attachment == null || !attackerId.equals(attachment.getAttachedTo())) {
|
||||||
getEffects().setValue("sourceId", event.getSourceId());
|
return false;
|
||||||
// TODO: Passing a permanent object like this can cause bugs. May need refactoring to use UUID instead.
|
}
|
||||||
// See https://github.com/magefree/mage/issues/8377
|
switch (setTargetPointer) {
|
||||||
// 11-08-2021: Added a new constructor to set target pointer. Should probably be using this instead.
|
case PERMANENT:
|
||||||
Permanent attachedPermanent = game.getPermanent(event.getSourceId());
|
getEffects().setTargetPointer(new FixedTarget(attackerId, game));
|
||||||
getEffects().setValue("attachedPermanent", attachedPermanent);
|
break;
|
||||||
if (setTargetPointer && attachedPermanent != null) {
|
case PLAYER:
|
||||||
getEffects().setTargetPointer(new FixedTarget(attachedPermanent, game));
|
getEffects().setTargetPointer(new FixedTarget(game.getCombat().getDefendingPlayerId(attackerId, game)));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
package mage.abilities.condition.common;
|
||||||
|
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.condition.Condition;
|
||||||
|
import mage.constants.TurnPhase;
|
||||||
|
import mage.game.Game;
|
||||||
|
|
||||||
|
public enum FirstCombatPhaseCondition implements Condition {
|
||||||
|
instance;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Game game, Ability source) {
|
||||||
|
return game.getTurn().getPhase(TurnPhase.COMBAT).getCount() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "it's the first combat phase of the turn";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,25 +1,19 @@
|
||||||
|
|
||||||
package mage.abilities.keyword;
|
package mage.abilities.keyword;
|
||||||
|
|
||||||
import mage.abilities.TriggeredAbilityImpl;
|
import mage.abilities.common.AttacksAloneControlledTriggeredAbility;
|
||||||
import mage.abilities.effects.common.continuous.BoostTargetEffect;
|
import mage.abilities.effects.common.continuous.BoostTargetEffect;
|
||||||
import mage.constants.Duration;
|
|
||||||
import mage.constants.Zone;
|
|
||||||
import mage.game.Game;
|
|
||||||
import mage.game.events.GameEvent;
|
|
||||||
import mage.target.targetpointer.FixedTarget;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author BetaSteward_at_googlemail.com
|
* @author awjackson
|
||||||
*/
|
*/
|
||||||
public class ExaltedAbility extends TriggeredAbilityImpl {
|
public class ExaltedAbility extends AttacksAloneControlledTriggeredAbility {
|
||||||
|
|
||||||
public ExaltedAbility() {
|
public ExaltedAbility() {
|
||||||
super(Zone.BATTLEFIELD, new BoostTargetEffect(1, 1, Duration.EndOfTurn));
|
super(new BoostTargetEffect(1, 1), true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ExaltedAbility(final ExaltedAbility ability) {
|
private ExaltedAbility(final ExaltedAbility ability) {
|
||||||
super(ability);
|
super(ability);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -28,25 +22,8 @@ public class ExaltedAbility extends TriggeredAbilityImpl {
|
||||||
return new ExaltedAbility(this);
|
return new ExaltedAbility(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean checkEventType(GameEvent event, Game game) {
|
|
||||||
return event.getType() == GameEvent.EventType.DECLARED_ATTACKERS;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean checkTrigger(GameEvent event, Game game) {
|
|
||||||
if (game.isActivePlayer(this.controllerId)) {
|
|
||||||
if (game.getCombat().attacksAlone()) {
|
|
||||||
this.getEffects().get(0).setTargetPointer(new FixedTarget(game.getCombat().getAttackers().get(0)));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getRule() {
|
public String getRule() {
|
||||||
return "exalted <i>(Whenever a creature you control attacks alone, that creature gets +1/+1 until end of turn.)</i>";
|
return "Exalted <i>(Whenever a creature you control attacks alone, that creature gets +1/+1 until end of turn.)</i>";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -115,16 +115,16 @@ public class Combat implements Serializable, Copyable<Combat> {
|
||||||
return defenders;
|
return defenders;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<UUID> getAttackers() {
|
public Set<UUID> getAttackers() {
|
||||||
List<UUID> attackers = new ArrayList<>();
|
Set<UUID> attackers = new HashSet<>();
|
||||||
for (CombatGroup group : groups) {
|
for (CombatGroup group : groups) {
|
||||||
attackers.addAll(group.attackers);
|
attackers.addAll(group.attackers);
|
||||||
}
|
}
|
||||||
return attackers;
|
return attackers;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<UUID> getBlockers() {
|
public Set<UUID> getBlockers() {
|
||||||
List<UUID> blockers = new ArrayList<>();
|
Set<UUID> blockers = new HashSet<>();
|
||||||
for (CombatGroup group : groups) {
|
for (CombatGroup group : groups) {
|
||||||
blockers.addAll(group.blockers);
|
blockers.addAll(group.blockers);
|
||||||
}
|
}
|
||||||
|
|
@ -1160,14 +1160,13 @@ public class Combat implements Serializable, Copyable<Combat> {
|
||||||
Set<UUID> blockedSet = mustBeBlockedByAtLeastX.get(blockedAttackerId);
|
Set<UUID> blockedSet = mustBeBlockedByAtLeastX.get(blockedAttackerId);
|
||||||
Set<UUID> toBlockSet = mustBeBlockedByAtLeastX.get(toBeBlockedCreatureId);
|
Set<UUID> toBlockSet = mustBeBlockedByAtLeastX.get(toBeBlockedCreatureId);
|
||||||
if (toBlockSet == null) {
|
if (toBlockSet == null) {
|
||||||
// This should never happen.
|
// This should never happen.
|
||||||
return null;
|
return null;
|
||||||
} else if (toBlockSet.containsAll(blockedSet)) {
|
} else if (toBlockSet.containsAll(blockedSet)) {
|
||||||
// the creature already blocks alone a creature that has to be blocked by at least one
|
// the creature already blocks alone a creature that has to be blocked by at least one
|
||||||
// and has more possible blockers, so this is ok
|
// and has more possible blockers, so this is ok
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
// TODO: Check if the attacker is already blocked by another creature
|
// TODO: Check if the attacker is already blocked by another creature
|
||||||
// and despite there is need that this attacker blocks this attacker also
|
// and despite there is need that this attacker blocks this attacker also
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue