mirror of
https://github.com/correl/mage.git
synced 2024-11-15 11:09:30 +00:00
Reworking effects that allow controlling combat (WIP) (#8159)
* reworked effects that allow controlling combat * [AFC] Implemented Berserker's Frenzy * [AFC] updated Berserker's Frenzy to roll correctly
This commit is contained in:
parent
f5177097cd
commit
f7e821be2f
12 changed files with 366 additions and 492 deletions
107
Mage.Sets/src/mage/cards/b/BerserkersFrenzy.java
Normal file
107
Mage.Sets/src/mage/cards/b/BerserkersFrenzy.java
Normal file
|
@ -0,0 +1,107 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.CastOnlyDuringPhaseStepSourceAbility;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.abilities.dynamicvalue.common.StaticValue;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.RollDieWithResultTableEffect;
|
||||
import mage.abilities.effects.common.combat.BlocksIfAbleTargetEffect;
|
||||
import mage.abilities.effects.common.combat.ChooseBlockersEffect;
|
||||
import mage.abilities.hint.ConditionHint;
|
||||
import mage.abilities.hint.Hint;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.cards.CardsImpl;
|
||||
import mage.constants.*;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetPermanent;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
import mage.target.targetpointer.FixedTargets;
|
||||
import mage.watchers.common.ControlCombatRedundancyWatcher;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class BerserkersFrenzy extends CardImpl {
|
||||
|
||||
private static final Hint hint = new ConditionHint(BerserkersFrenzyCondition.instance, "Can be cast");
|
||||
|
||||
public BerserkersFrenzy(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{R}");
|
||||
|
||||
// Cast this spell only before combat or during combat before blockers are declared.
|
||||
this.addAbility(new CastOnlyDuringPhaseStepSourceAbility(
|
||||
null, null, BerserkersFrenzyCondition.instance,
|
||||
"Cast this spell only before combat or during combat before blockers are declared"
|
||||
).addHint(hint));
|
||||
|
||||
// Roll two d20 and ignore the lower roll.
|
||||
RollDieWithResultTableEffect effect = new RollDieWithResultTableEffect(
|
||||
20, "roll two d20 and ignore the lower roll", StaticValue.get(0), 1
|
||||
);
|
||||
|
||||
// 1-14 | Choose any number of creatures. They block this turn if able.
|
||||
effect.addTableEntry(1, 14, new BerserkersFrenzyEffect());
|
||||
|
||||
// 15-20 | You choose which creatures block this turn and how those creatures block.
|
||||
effect.addTableEntry(15, 20, new ChooseBlockersEffect(Duration.EndOfTurn));
|
||||
this.getSpellAbility().addEffect(effect);
|
||||
this.getSpellAbility().addWatcher(new ControlCombatRedundancyWatcher());
|
||||
}
|
||||
|
||||
private BerserkersFrenzy(final BerserkersFrenzy card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BerserkersFrenzy copy() {
|
||||
return new BerserkersFrenzy(this);
|
||||
}
|
||||
}
|
||||
|
||||
enum BerserkersFrenzyCondition implements Condition {
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
if (game.getPhase().getType() == TurnPhase.COMBAT) {
|
||||
return game.getStep().getType().isBefore(PhaseStep.DECLARE_BLOCKERS);
|
||||
}
|
||||
return !game.getTurn().isDeclareAttackersStepStarted();
|
||||
}
|
||||
}
|
||||
|
||||
class BerserkersFrenzyEffect extends OneShotEffect {
|
||||
|
||||
BerserkersFrenzyEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "choose any number of creatures. They block this turn if able";
|
||||
}
|
||||
|
||||
private BerserkersFrenzyEffect(final BerserkersFrenzyEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BerserkersFrenzyEffect copy() {
|
||||
return new BerserkersFrenzyEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
if (player == null) {
|
||||
return false;
|
||||
}
|
||||
TargetPermanent target = new TargetCreaturePermanent(0, Integer.MAX_VALUE);
|
||||
target.setNotTarget(true);
|
||||
player.choose(outcome, target, source.getSourceId(), game);
|
||||
game.addEffect(new BlocksIfAbleTargetEffect(Duration.EndOfTurn)
|
||||
.setTargetPointer(new FixedTargets(new CardsImpl(target.getTargets()), game)), source);
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -1,17 +1,14 @@
|
|||
|
||||
package mage.cards.b;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.GainLifeEffect;
|
||||
import mage.abilities.effects.common.LoseLifeTargetEffect;
|
||||
import mage.abilities.effects.common.combat.BlocksIfAbleAllEffect;
|
||||
import mage.abilities.effects.common.combat.ChooseBlockersEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
|
@ -19,12 +16,12 @@ import mage.filter.common.FilterCreaturePermanent;
|
|||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
import mage.watchers.common.ChooseBlockersRedundancyWatcher;
|
||||
import mage.watchers.common.ControlCombatRedundancyWatcher;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public final class BrutalHordechief extends CardImpl {
|
||||
|
@ -36,7 +33,7 @@ public final class BrutalHordechief extends CardImpl {
|
|||
}
|
||||
|
||||
public BrutalHordechief(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{B}");
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}");
|
||||
this.subtype.add(SubType.ORC, SubType.WARRIOR);
|
||||
this.power = new MageInt(3);
|
||||
this.toughness = new MageInt(3);
|
||||
|
@ -45,10 +42,11 @@ public final class BrutalHordechief extends CardImpl {
|
|||
this.addAbility(new BrutalHordechiefTriggeredAbility());
|
||||
|
||||
// {3}{R/W}{R/W}: Creatures your opponents control block this turn if able, and you choose how those creatures block.
|
||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BlocksIfAbleAllEffect(filter, Duration.EndOfTurn), new ManaCostsImpl("{3}{R/W}{R/W}"));
|
||||
ability.addEffect(new BrutalHordechiefChooseBlockersEffect());
|
||||
ability.addWatcher(new ChooseBlockersRedundancyWatcher());
|
||||
ability.addEffect(new ChooseBlockersRedundancyWatcherIncrementEffect());
|
||||
Ability ability = new SimpleActivatedAbility(
|
||||
new BlocksIfAbleAllEffect(filter, Duration.EndOfTurn), new ManaCostsImpl<>("{3}{R/W}{R/W}")
|
||||
);
|
||||
ability.addEffect(new ChooseBlockersEffect(Duration.EndOfTurn).setText("and you choose how those creatures block"));
|
||||
ability.addWatcher(new ControlCombatRedundancyWatcher());
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
|
@ -60,32 +58,6 @@ public final class BrutalHordechief extends CardImpl {
|
|||
public BrutalHordechief copy() {
|
||||
return new BrutalHordechief(this);
|
||||
}
|
||||
|
||||
private class ChooseBlockersRedundancyWatcherIncrementEffect extends OneShotEffect {
|
||||
|
||||
ChooseBlockersRedundancyWatcherIncrementEffect() {
|
||||
super(Outcome.Neutral);
|
||||
}
|
||||
|
||||
ChooseBlockersRedundancyWatcherIncrementEffect(final ChooseBlockersRedundancyWatcherIncrementEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
ChooseBlockersRedundancyWatcher watcher = game.getState().getWatcher(ChooseBlockersRedundancyWatcher.class);
|
||||
if (watcher != null) {
|
||||
watcher.increment();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChooseBlockersRedundancyWatcherIncrementEffect copy() {
|
||||
return new ChooseBlockersRedundancyWatcherIncrementEffect(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class BrutalHordechiefTriggeredAbility extends TriggeredAbilityImpl {
|
||||
|
@ -112,9 +84,9 @@ class BrutalHordechiefTriggeredAbility extends TriggeredAbilityImpl {
|
|||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
Permanent source = game.getPermanent(event.getSourceId());
|
||||
if (source != null && source.isControlledBy(controllerId)) {
|
||||
if (source != null && source.isControlledBy(getControllerId())) {
|
||||
UUID defendingPlayerId = game.getCombat().getDefendingPlayerId(event.getSourceId(), game);
|
||||
this.getEffects().get(0).setTargetPointer(new FixedTarget(defendingPlayerId));
|
||||
this.getEffects().setTargetPointer(new FixedTarget(defendingPlayerId));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -125,50 +97,3 @@ class BrutalHordechiefTriggeredAbility extends TriggeredAbilityImpl {
|
|||
return "Whenever a creature you control attacks, defending player loses 1 life and you gain 1 life.";
|
||||
}
|
||||
}
|
||||
|
||||
class BrutalHordechiefChooseBlockersEffect extends ContinuousRuleModifyingEffectImpl {
|
||||
|
||||
public BrutalHordechiefChooseBlockersEffect() {
|
||||
super(Duration.EndOfTurn, Outcome.Benefit, false, false);
|
||||
staticText = "You choose which creatures block this turn and how those creatures block";
|
||||
}
|
||||
|
||||
public BrutalHordechiefChooseBlockersEffect(final BrutalHordechiefChooseBlockersEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BrutalHordechiefChooseBlockersEffect copy() {
|
||||
return new BrutalHordechiefChooseBlockersEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.DECLARING_BLOCKERS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
ChooseBlockersRedundancyWatcher watcher = game.getState().getWatcher(ChooseBlockersRedundancyWatcher.class);
|
||||
if(watcher == null){
|
||||
return false;
|
||||
}
|
||||
watcher.decrement();
|
||||
if (watcher.copyCountApply > 0) {
|
||||
game.informPlayers(source.getSourceObject(game).getIdName() + " didn't apply");
|
||||
return false;
|
||||
}
|
||||
watcher.copyCountApply = watcher.copyCount;
|
||||
Player blockController = game.getPlayer(source.getControllerId());
|
||||
if (blockController != null) {
|
||||
game.getCombat().selectBlockers(blockController, source, game);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ public final class DivinersPortent extends CardImpl {
|
|||
// Roll a d20 and add the number of cards in your hand.
|
||||
RollDieWithResultTableEffect effect = new RollDieWithResultTableEffect(
|
||||
20, "roll a d20 and add the number " +
|
||||
"of cards in your hand", CardsInControllerHandCount.instance
|
||||
"of cards in your hand", CardsInControllerHandCount.instance, 0
|
||||
);
|
||||
this.getSpellAbility().addEffect(effect);
|
||||
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
|
||||
package mage.cards.m;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.CastOnlyDuringPhaseStepSourceAbility;
|
||||
import mage.abilities.condition.common.BeforeAttackersAreDeclaredCondition;
|
||||
import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.RequirementEffect;
|
||||
import mage.abilities.effects.RestrictionEffect;
|
||||
import mage.abilities.effects.common.combat.AttacksIfAbleTargetEffect;
|
||||
import mage.abilities.effects.common.combat.CantAttackTargetEffect;
|
||||
import mage.abilities.effects.common.combat.ChooseBlockersEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.TargetController;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
|
@ -23,11 +23,13 @@ import mage.players.Player;
|
|||
import mage.target.Target;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
import mage.watchers.Watcher;
|
||||
import mage.watchers.common.ChooseBlockersRedundancyWatcher;
|
||||
import mage.watchers.common.ControlCombatRedundancyWatcher;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author L_J
|
||||
*/
|
||||
public final class MasterWarcraft extends CardImpl {
|
||||
|
@ -36,20 +38,19 @@ public final class MasterWarcraft extends CardImpl {
|
|||
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{R/W}{R/W}");
|
||||
|
||||
// Cast Master Warcraft only before attackers are declared.
|
||||
this.addAbility(new CastOnlyDuringPhaseStepSourceAbility(null, null, BeforeAttackersAreDeclaredCondition.instance, "Cast this spell only before attackers are declared"));
|
||||
this.addAbility(new CastOnlyDuringPhaseStepSourceAbility(
|
||||
null, null, BeforeAttackersAreDeclaredCondition.instance,
|
||||
"Cast this spell only before attackers are declared"
|
||||
));
|
||||
|
||||
// You choose which creatures attack this turn.
|
||||
this.getSpellAbility().addEffect(new MasterWarcraftChooseAttackersEffect());
|
||||
|
||||
// You choose which creatures block this turn and how those creatures block.
|
||||
this.getSpellAbility().addEffect(new MasterWarcraftChooseBlockersEffect());
|
||||
|
||||
this.getSpellAbility().addEffect(new ChooseBlockersEffect(Duration.EndOfTurn).concatBy("<br>"));
|
||||
|
||||
// (only the last resolved Master Warcraft spell's effects apply)
|
||||
this.getSpellAbility().addWatcher(new MasterWarcraftCastWatcher());
|
||||
this.getSpellAbility().addEffect(new MasterWarcraftCastWatcherIncrementEffect());
|
||||
this.getSpellAbility().addWatcher(new ChooseBlockersRedundancyWatcher());
|
||||
this.getSpellAbility().addEffect(new ChooseBlockersRedundancyWatcherIncrementEffect());
|
||||
this.getSpellAbility().addWatcher(new ControlCombatRedundancyWatcher());
|
||||
}
|
||||
|
||||
private MasterWarcraft(final MasterWarcraft card) {
|
||||
|
@ -60,73 +61,22 @@ public final class MasterWarcraft extends CardImpl {
|
|||
public MasterWarcraft copy() {
|
||||
return new MasterWarcraft(this);
|
||||
}
|
||||
|
||||
private class MasterWarcraftCastWatcherIncrementEffect extends OneShotEffect {
|
||||
|
||||
MasterWarcraftCastWatcherIncrementEffect() {
|
||||
super(Outcome.Neutral);
|
||||
}
|
||||
|
||||
MasterWarcraftCastWatcherIncrementEffect(final MasterWarcraftCastWatcherIncrementEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
MasterWarcraftCastWatcher watcher = game.getState().getWatcher(MasterWarcraftCastWatcher.class);
|
||||
if (watcher != null) {
|
||||
watcher.increment();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MasterWarcraftCastWatcherIncrementEffect copy() {
|
||||
return new MasterWarcraftCastWatcherIncrementEffect(this);
|
||||
}
|
||||
}
|
||||
|
||||
private class ChooseBlockersRedundancyWatcherIncrementEffect extends OneShotEffect {
|
||||
|
||||
ChooseBlockersRedundancyWatcherIncrementEffect() {
|
||||
super(Outcome.Neutral);
|
||||
}
|
||||
|
||||
ChooseBlockersRedundancyWatcherIncrementEffect(final ChooseBlockersRedundancyWatcherIncrementEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
ChooseBlockersRedundancyWatcher watcher = game.getState().getWatcher(ChooseBlockersRedundancyWatcher.class);
|
||||
if (watcher != null) {
|
||||
watcher.increment();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChooseBlockersRedundancyWatcherIncrementEffect copy() {
|
||||
return new ChooseBlockersRedundancyWatcherIncrementEffect(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class MasterWarcraftChooseAttackersEffect extends ContinuousRuleModifyingEffectImpl {
|
||||
|
||||
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creatures that will attack this combat (creatures not chosen won't attack this combat)");
|
||||
|
||||
static {
|
||||
filter.add(TargetController.ACTIVE.getControllerPredicate());
|
||||
}
|
||||
|
||||
public MasterWarcraftChooseAttackersEffect() {
|
||||
MasterWarcraftChooseAttackersEffect() {
|
||||
super(Duration.EndOfTurn, Outcome.Benefit, false, false);
|
||||
staticText = "You choose which creatures attack this turn";
|
||||
}
|
||||
|
||||
public MasterWarcraftChooseAttackersEffect(final MasterWarcraftChooseAttackersEffect effect) {
|
||||
private MasterWarcraftChooseAttackersEffect(final MasterWarcraftChooseAttackersEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
|
@ -145,131 +95,54 @@ class MasterWarcraftChooseAttackersEffect extends ContinuousRuleModifyingEffectI
|
|||
return event.getType() == GameEvent.EventType.DECLARING_ATTACKERS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Ability source, Game game) {
|
||||
super.init(source, game);
|
||||
ControlCombatRedundancyWatcher.addAttackingController(source.getControllerId(), duration, game);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
MasterWarcraftCastWatcher watcher = game.getState().getWatcher(MasterWarcraftCastWatcher.class);
|
||||
if(watcher == null){
|
||||
return false;
|
||||
}
|
||||
watcher.decrement();
|
||||
if (watcher.copyCountApply > 0) {
|
||||
if (!ControlCombatRedundancyWatcher.checkAttackingController(source.getControllerId(), game)) {
|
||||
game.informPlayers(source.getSourceObject(game).getIdName() + " didn't apply");
|
||||
return false;
|
||||
}
|
||||
watcher.copyCountApply = watcher.copyCount;
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
Player attackingPlayer = game.getPlayer(game.getCombat().getAttackingPlayerId());
|
||||
if (controller != null && attackingPlayer != null && !attackingPlayer.getAvailableAttackers(game).isEmpty()) {
|
||||
Target target = new TargetCreaturePermanent(0, Integer.MAX_VALUE, filter, true);
|
||||
if (controller.chooseTarget(Outcome.Benefit, target, source, game)) {
|
||||
for (Permanent permanent : game.getBattlefield().getActivePermanents(new FilterCreaturePermanent(), source.getControllerId(), source.getSourceId(), game)) {
|
||||
|
||||
// Choose creatures that will be attacking this combat
|
||||
if (target.getTargets().contains(permanent.getId())) {
|
||||
RequirementEffect effect = new AttacksIfAbleTargetEffect(Duration.EndOfCombat);
|
||||
effect.setText("");
|
||||
effect.setTargetPointer(new FixedTarget(permanent, game));
|
||||
game.addEffect(effect, source);
|
||||
game.informPlayers(controller.getLogName() + " has decided that " + permanent.getLogName() + " attacks this combat if able");
|
||||
|
||||
// All other creatures can't attack (unless they must attack)
|
||||
} else {
|
||||
boolean hasToAttack = false;
|
||||
for (Map.Entry<RequirementEffect, Set<Ability>> entry : game.getContinuousEffects().getApplicableRequirementEffects(permanent, false, game).entrySet()) {
|
||||
RequirementEffect effect2 = entry.getKey();
|
||||
if (effect2.mustAttack(game)) {
|
||||
hasToAttack = true;
|
||||
}
|
||||
}
|
||||
if (!hasToAttack) {
|
||||
RestrictionEffect effect = new CantAttackTargetEffect(Duration.EndOfCombat);
|
||||
effect.setText("");
|
||||
effect.setTargetPointer(new FixedTarget(permanent, game));
|
||||
game.addEffect(effect, source);
|
||||
}
|
||||
if (controller == null || attackingPlayer == null || attackingPlayer.getAvailableAttackers(game).isEmpty()) {
|
||||
return false; // the attack declaration resumes for the active player as normal
|
||||
}
|
||||
Target target = new TargetCreaturePermanent(0, Integer.MAX_VALUE, filter, true);
|
||||
if (!controller.chooseTarget(Outcome.Benefit, target, source, game)) {
|
||||
return false; // the attack declaration resumes for the active player as normal
|
||||
}
|
||||
for (Permanent permanent : game.getBattlefield().getActivePermanents(new FilterCreaturePermanent(), source.getControllerId(), source.getSourceId(), game)) {
|
||||
|
||||
// Choose creatures that will be attacking this combat
|
||||
if (target.getTargets().contains(permanent.getId())) {
|
||||
RequirementEffect effect = new AttacksIfAbleTargetEffect(Duration.EndOfCombat);
|
||||
effect.setText("");
|
||||
effect.setTargetPointer(new FixedTarget(permanent, game));
|
||||
game.addEffect(effect, source);
|
||||
game.informPlayers(controller.getLogName() + " has decided that " + permanent.getLogName() + " attacks this combat if able");
|
||||
|
||||
// All other creatures can't attack (unless they must attack)
|
||||
} else {
|
||||
boolean hasToAttack = false;
|
||||
for (Map.Entry<RequirementEffect, Set<Ability>> entry : game.getContinuousEffects().getApplicableRequirementEffects(permanent, false, game).entrySet()) {
|
||||
RequirementEffect effect2 = entry.getKey();
|
||||
if (effect2.mustAttack(game)) {
|
||||
hasToAttack = true;
|
||||
}
|
||||
}
|
||||
if (!hasToAttack) {
|
||||
RestrictionEffect effect = new CantAttackTargetEffect(Duration.EndOfCombat);
|
||||
effect.setText("");
|
||||
effect.setTargetPointer(new FixedTarget(permanent, game));
|
||||
game.addEffect(effect, source);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false; // the attack declaration resumes for the active player as normal
|
||||
}
|
||||
}
|
||||
|
||||
class MasterWarcraftChooseBlockersEffect extends ContinuousRuleModifyingEffectImpl {
|
||||
|
||||
public MasterWarcraftChooseBlockersEffect() {
|
||||
super(Duration.EndOfTurn, Outcome.Benefit, false, false);
|
||||
staticText = "You choose which creatures block this turn and how those creatures block";
|
||||
}
|
||||
|
||||
public MasterWarcraftChooseBlockersEffect(final MasterWarcraftChooseBlockersEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MasterWarcraftChooseBlockersEffect copy() {
|
||||
return new MasterWarcraftChooseBlockersEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.DECLARING_BLOCKERS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
ChooseBlockersRedundancyWatcher watcher = game.getState().getWatcher(ChooseBlockersRedundancyWatcher.class);
|
||||
if(watcher == null){
|
||||
return false;
|
||||
}
|
||||
watcher.decrement();
|
||||
if (watcher.copyCountApply > 0) {
|
||||
game.informPlayers(source.getSourceObject(game).getIdName() + " didn't apply");
|
||||
return false;
|
||||
}
|
||||
watcher.copyCountApply = watcher.copyCount;
|
||||
Player blockController = game.getPlayer(source.getControllerId());
|
||||
if (blockController != null) {
|
||||
game.getCombat().selectBlockers(blockController, source, game);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class MasterWarcraftCastWatcher extends Watcher {
|
||||
|
||||
public int copyCount = 0;
|
||||
public int copyCountApply = 0;
|
||||
|
||||
public MasterWarcraftCastWatcher() {
|
||||
super(WatcherScope.GAME);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
copyCount = 0;
|
||||
copyCountApply = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void watch(GameEvent event, Game game) {
|
||||
}
|
||||
|
||||
public void increment() {
|
||||
copyCount++;
|
||||
copyCountApply = copyCount;
|
||||
}
|
||||
|
||||
public void decrement() {
|
||||
if (copyCountApply > 0) {
|
||||
copyCountApply--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package mage.cards.m;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.DelayedTriggeredAbility;
|
||||
import mage.abilities.common.CastOnlyDuringPhaseStepSourceAbility;
|
||||
import mage.abilities.condition.CompoundCondition;
|
||||
|
@ -8,25 +7,23 @@ import mage.abilities.condition.Condition;
|
|||
import mage.abilities.condition.common.BeforeBlockersAreDeclaredCondition;
|
||||
import mage.abilities.condition.common.IsPhaseCondition;
|
||||
import mage.abilities.condition.common.MyTurnCondition;
|
||||
import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
|
||||
import mage.abilities.effects.common.RemoveFromCombatTargetEffect;
|
||||
import mage.abilities.effects.common.UntapTargetEffect;
|
||||
import mage.abilities.effects.common.combat.ChooseBlockersEffect;
|
||||
import mage.abilities.hint.ConditionHint;
|
||||
import mage.abilities.hint.Hint;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.TurnPhase;
|
||||
import mage.game.Game;
|
||||
import mage.game.combat.CombatGroup;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
import mage.watchers.common.ChooseBlockersRedundancyWatcher;
|
||||
import mage.watchers.common.ControlCombatRedundancyWatcher;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
@ -35,21 +32,26 @@ import java.util.UUID;
|
|||
*/
|
||||
public final class Melee extends CardImpl {
|
||||
|
||||
private static final Condition condition = new CompoundCondition(
|
||||
BeforeBlockersAreDeclaredCondition.instance,
|
||||
new IsPhaseCondition(TurnPhase.COMBAT),
|
||||
MyTurnCondition.instance
|
||||
);
|
||||
private static final Hint hint = new ConditionHint(condition, "Can be cast");
|
||||
|
||||
public Melee(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{4}{R}");
|
||||
|
||||
// Cast Melee only during your turn and only during combat before blockers are declared.
|
||||
Condition condition = new CompoundCondition(BeforeBlockersAreDeclaredCondition.instance,
|
||||
new IsPhaseCondition(TurnPhase.COMBAT),
|
||||
MyTurnCondition.instance);
|
||||
this.addAbility(new CastOnlyDuringPhaseStepSourceAbility(null, null, condition, "Cast this spell only during your turn and only during combat before blockers are declared")
|
||||
.addHint(new ConditionHint(condition, "Can cast melee (it's combat phase on your turn)")));
|
||||
this.addAbility(new CastOnlyDuringPhaseStepSourceAbility(
|
||||
null, null, condition,
|
||||
"Cast this spell only during your turn and only during combat before blockers are declared"
|
||||
).addHint(hint));
|
||||
|
||||
// You choose which creatures block this combat and how those creatures block.
|
||||
// (only the last resolved Melee spell's blocking effect applies)
|
||||
this.getSpellAbility().addEffect(new MeleeChooseBlockersEffect());
|
||||
this.getSpellAbility().addWatcher(new ChooseBlockersRedundancyWatcher());
|
||||
this.getSpellAbility().addEffect(new ChooseBlockersRedundancyWatcherIncrementEffect());
|
||||
this.getSpellAbility().addEffect(new ChooseBlockersEffect(Duration.EndOfCombat));
|
||||
this.getSpellAbility().addWatcher(new ControlCombatRedundancyWatcher());
|
||||
|
||||
// Whenever a creature attacks and isn't blocked this combat, untap it and remove it from combat.
|
||||
this.getSpellAbility().addEffect(new CreateDelayedTriggeredAbilityEffect(new MeleeTriggeredAbility()));
|
||||
|
@ -63,82 +65,6 @@ public final class Melee extends CardImpl {
|
|||
public Melee copy() {
|
||||
return new Melee(this);
|
||||
}
|
||||
|
||||
private class ChooseBlockersRedundancyWatcherIncrementEffect extends OneShotEffect {
|
||||
|
||||
ChooseBlockersRedundancyWatcherIncrementEffect() {
|
||||
super(Outcome.Neutral);
|
||||
}
|
||||
|
||||
ChooseBlockersRedundancyWatcherIncrementEffect(final ChooseBlockersRedundancyWatcherIncrementEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
ChooseBlockersRedundancyWatcher watcher = game.getState().getWatcher(ChooseBlockersRedundancyWatcher.class);
|
||||
if (watcher != null) {
|
||||
watcher.increment();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChooseBlockersRedundancyWatcherIncrementEffect copy() {
|
||||
return new ChooseBlockersRedundancyWatcherIncrementEffect(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class MeleeChooseBlockersEffect extends ContinuousRuleModifyingEffectImpl {
|
||||
|
||||
public MeleeChooseBlockersEffect() {
|
||||
super(Duration.EndOfCombat, Outcome.Benefit, false, false);
|
||||
staticText = "You choose which creatures block this combat and how those creatures block";
|
||||
}
|
||||
|
||||
public MeleeChooseBlockersEffect(final MeleeChooseBlockersEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MeleeChooseBlockersEffect copy() {
|
||||
return new MeleeChooseBlockersEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.DECLARING_BLOCKERS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
ChooseBlockersRedundancyWatcher watcher = game.getState().getWatcher(ChooseBlockersRedundancyWatcher.class);
|
||||
if (watcher == null) {
|
||||
return false;
|
||||
}
|
||||
watcher.decrement();
|
||||
watcher.copyCount--;
|
||||
if (watcher.copyCountApply > 0) {
|
||||
game.informPlayers(source.getSourceObject(game).getIdName() + " didn't apply");
|
||||
this.discard();
|
||||
return false;
|
||||
}
|
||||
watcher.copyCountApply = watcher.copyCount;
|
||||
Player blockController = game.getPlayer(source.getControllerId());
|
||||
if (blockController != null) {
|
||||
game.getCombat().selectBlockers(blockController, source, game);
|
||||
return true;
|
||||
}
|
||||
this.discard();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class MeleeTriggeredAbility extends DelayedTriggeredAbility {
|
||||
|
|
|
@ -1,19 +1,17 @@
|
|||
package mage.cards.o;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.combat.ChooseBlockersEffect;
|
||||
import mage.abilities.keyword.FirstStrikeAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.players.Player;
|
||||
import mage.watchers.common.ChooseBlockersRedundancyWatcher;
|
||||
import mage.watchers.common.ControlCombatRedundancyWatcher;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author noxx
|
||||
|
@ -49,9 +47,8 @@ public final class OdricMasterTactician extends CardImpl {
|
|||
class OdricMasterTacticianTriggeredAbility extends TriggeredAbilityImpl {
|
||||
|
||||
public OdricMasterTacticianTriggeredAbility() {
|
||||
super(Zone.BATTLEFIELD, new OdricMasterTacticianChooseBlockersEffect());
|
||||
this.addWatcher(new ChooseBlockersRedundancyWatcher());
|
||||
this.addEffect(new ChooseBlockersRedundancyWatcherIncrementEffect());
|
||||
super(Zone.BATTLEFIELD, new ChooseBlockersEffect(Duration.EndOfCombat));
|
||||
this.addWatcher(new ControlCombatRedundancyWatcher());
|
||||
}
|
||||
|
||||
public OdricMasterTacticianTriggeredAbility(final OdricMasterTacticianTriggeredAbility ability) {
|
||||
|
@ -72,80 +69,4 @@ class OdricMasterTacticianTriggeredAbility extends TriggeredAbilityImpl {
|
|||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
return game.getCombat().getAttackers().size() >= 4 && game.getCombat().getAttackers().contains(this.sourceId);
|
||||
}
|
||||
|
||||
private class ChooseBlockersRedundancyWatcherIncrementEffect extends OneShotEffect {
|
||||
|
||||
ChooseBlockersRedundancyWatcherIncrementEffect() {
|
||||
super(Outcome.Neutral);
|
||||
}
|
||||
|
||||
ChooseBlockersRedundancyWatcherIncrementEffect(final ChooseBlockersRedundancyWatcherIncrementEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
ChooseBlockersRedundancyWatcher watcher = game.getState().getWatcher(ChooseBlockersRedundancyWatcher.class);
|
||||
if (watcher != null) {
|
||||
watcher.increment();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChooseBlockersRedundancyWatcherIncrementEffect copy() {
|
||||
return new ChooseBlockersRedundancyWatcherIncrementEffect(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class OdricMasterTacticianChooseBlockersEffect extends ContinuousRuleModifyingEffectImpl {
|
||||
|
||||
public OdricMasterTacticianChooseBlockersEffect() {
|
||||
super(Duration.EndOfCombat, Outcome.Benefit, false, false);
|
||||
staticText = "Whenever {this} and at least three other creatures attack, you choose which creatures block this combat and how those creatures block";
|
||||
}
|
||||
|
||||
public OdricMasterTacticianChooseBlockersEffect(final OdricMasterTacticianChooseBlockersEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OdricMasterTacticianChooseBlockersEffect copy() {
|
||||
return new OdricMasterTacticianChooseBlockersEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.DECLARING_BLOCKERS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
ChooseBlockersRedundancyWatcher watcher = game.getState().getWatcher(ChooseBlockersRedundancyWatcher.class);
|
||||
if (watcher == null) {
|
||||
return false;
|
||||
}
|
||||
watcher.decrement();
|
||||
watcher.copyCount--;
|
||||
if (watcher.copyCountApply > 0) {
|
||||
game.informPlayers(source.getSourceObject(game).getIdName() + " didn't apply");
|
||||
this.discard();
|
||||
return false;
|
||||
}
|
||||
watcher.copyCountApply = watcher.copyCount;
|
||||
Player blockController = game.getPlayer(source.getControllerId());
|
||||
if (blockController != null) {
|
||||
game.getCombat().selectBlockers(blockController, source, game);
|
||||
return true;
|
||||
}
|
||||
this.discard();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ public final class Revivify extends CardImpl {
|
|||
// Roll a d20 and add the number of creature cards in your graveyard that were put there from the battlefield this turn.
|
||||
RollDieWithResultTableEffect effect = new RollDieWithResultTableEffect(
|
||||
20, "roll a d20 and add the number of creature cards " +
|
||||
"in your graveyard that were put there from the battlefield this turn", xValue
|
||||
"in your graveyard that were put there from the battlefield this turn", xValue, 0
|
||||
);
|
||||
this.getSpellAbility().addEffect(effect);
|
||||
this.getSpellAbility().addWatcher(new CardsPutIntoGraveyardWatcher());
|
||||
|
|
|
@ -42,6 +42,7 @@ public final class ForgottenRealmsCommander extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Bedevil", 179, Rarity.RARE, mage.cards.b.Bedevil.class));
|
||||
cards.add(new SetCardInfo("Behemoth Sledge", 180, Rarity.UNCOMMON, mage.cards.b.BehemothSledge.class));
|
||||
cards.add(new SetCardInfo("Belt of Giant Strength", 38, Rarity.RARE, mage.cards.b.BeltOfGiantStrength.class));
|
||||
cards.add(new SetCardInfo("Berserker's Frenzy", 29, Rarity.RARE, mage.cards.b.BerserkersFrenzy.class));
|
||||
cards.add(new SetCardInfo("Bituminous Blast", 181, Rarity.UNCOMMON, mage.cards.b.BituminousBlast.class));
|
||||
cards.add(new SetCardInfo("Bogardan Hellkite", 115, Rarity.MYTHIC, mage.cards.b.BogardanHellkite.class));
|
||||
cards.add(new SetCardInfo("Bojuka Bog", 226, Rarity.COMMON, mage.cards.b.BojukaBog.class));
|
||||
|
|
|
@ -27,6 +27,7 @@ public class RollDieWithResultTableEffect extends OneShotEffect {
|
|||
private final String prefixText;
|
||||
private final List<TableEntry> resultsTable = new ArrayList<>();
|
||||
private final DynamicValue modifier;
|
||||
private final int toIgnore;
|
||||
|
||||
public RollDieWithResultTableEffect() {
|
||||
this(20);
|
||||
|
@ -37,14 +38,15 @@ public class RollDieWithResultTableEffect extends OneShotEffect {
|
|||
}
|
||||
|
||||
public RollDieWithResultTableEffect(int sides, String prefixText) {
|
||||
this(sides, prefixText, StaticValue.get(0));
|
||||
this(sides, prefixText, StaticValue.get(0), 0);
|
||||
}
|
||||
|
||||
public RollDieWithResultTableEffect(int sides, String prefixText, DynamicValue modifier) {
|
||||
public RollDieWithResultTableEffect(int sides, String prefixText, DynamicValue modifier, int toIgnore) {
|
||||
super(Outcome.Benefit);
|
||||
this.sides = sides;
|
||||
this.prefixText = prefixText;
|
||||
this.modifier = modifier;
|
||||
this.toIgnore = toIgnore;
|
||||
}
|
||||
|
||||
protected RollDieWithResultTableEffect(final RollDieWithResultTableEffect effect) {
|
||||
|
@ -55,6 +57,7 @@ public class RollDieWithResultTableEffect extends OneShotEffect {
|
|||
this.resultsTable.add(tableEntry.copy());
|
||||
}
|
||||
this.modifier = effect.modifier.copy();
|
||||
this.toIgnore = effect.toIgnore;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -68,7 +71,9 @@ public class RollDieWithResultTableEffect extends OneShotEffect {
|
|||
if (player == null) {
|
||||
return false;
|
||||
}
|
||||
int result = player.rollDice(outcome, source, game, sides) + modifier.calculate(game, source, this);
|
||||
int result = player.rollDice(
|
||||
outcome, source, game, sides, 1 + toIgnore, toIgnore
|
||||
).get(0) + modifier.calculate(game, source, this);
|
||||
this.applyResult(result, game, source);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
package mage.abilities.effects.common.combat;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.Mode;
|
||||
import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.players.Player;
|
||||
import mage.watchers.common.ControlCombatRedundancyWatcher;
|
||||
|
||||
/**
|
||||
* @author L_J, TheElk801
|
||||
*/
|
||||
public class ChooseBlockersEffect extends ContinuousRuleModifyingEffectImpl {
|
||||
|
||||
public ChooseBlockersEffect(Duration duration) {
|
||||
super(duration, Outcome.Benefit, false, false);
|
||||
}
|
||||
|
||||
private ChooseBlockersEffect(final ChooseBlockersEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChooseBlockersEffect copy() {
|
||||
return new ChooseBlockersEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.DECLARING_BLOCKERS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Ability source, Game game) {
|
||||
super.init(source, game);
|
||||
ControlCombatRedundancyWatcher.addBlockingController(source.getControllerId(), this.duration, game);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
if (!ControlCombatRedundancyWatcher.checkBlockingController(source.getControllerId(), game)) {
|
||||
game.informPlayers(source.getSourceObject(game).getIdName() + " didn't apply");
|
||||
return false;
|
||||
}
|
||||
Player blockController = game.getPlayer(source.getControllerId());
|
||||
if (blockController != null) {
|
||||
game.getCombat().selectBlockers(blockController, source, game);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText(Mode mode) {
|
||||
if (staticText != null && !staticText.isEmpty()) {
|
||||
return staticText;
|
||||
}
|
||||
StringBuilder sb = new StringBuilder("you choose which creatures block this ");
|
||||
switch (duration) {
|
||||
case EndOfTurn:
|
||||
sb.append("turn");
|
||||
break;
|
||||
case EndOfCombat:
|
||||
sb.append("combat");
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("duration type not supported");
|
||||
}
|
||||
sb.append(" and how those creatures block");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
package mage.watchers.common;
|
||||
|
||||
import mage.constants.WatcherScope;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.watchers.Watcher;
|
||||
|
||||
/**
|
||||
* @author L_J
|
||||
*/
|
||||
|
||||
public class ChooseBlockersRedundancyWatcher extends Watcher { // workaround for solving timestamp issues regarding "you choose which creatures block and how those creatures block" effects
|
||||
|
||||
public int copyCount = 0;
|
||||
public int copyCountApply = 0;
|
||||
|
||||
public ChooseBlockersRedundancyWatcher() {
|
||||
super(WatcherScope.GAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
super.reset();
|
||||
copyCount = 0;
|
||||
copyCountApply = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void watch(GameEvent event, Game game) {
|
||||
}
|
||||
|
||||
public void increment() {
|
||||
copyCount++;
|
||||
copyCountApply = copyCount;
|
||||
}
|
||||
|
||||
public void decrement() {
|
||||
if (copyCountApply > 0) {
|
||||
copyCountApply--;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
package mage.watchers.common;
|
||||
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.WatcherScope;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.watchers.Watcher;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author L_J
|
||||
*/
|
||||
public class ControlCombatRedundancyWatcher extends Watcher { // workaround for solving timestamp issues regarding "you choose which creatures block and how those creatures block" effects
|
||||
|
||||
private static final class PlayerDuration {
|
||||
|
||||
private final Duration duration;
|
||||
private final UUID playerId;
|
||||
|
||||
private PlayerDuration(Duration duration, UUID playerId) {
|
||||
this.duration = duration;
|
||||
this.playerId = playerId;
|
||||
}
|
||||
|
||||
private boolean isCombat() {
|
||||
return duration == Duration.EndOfCombat;
|
||||
}
|
||||
|
||||
private boolean isPlayer(UUID playerId) {
|
||||
return playerId.equals(this.playerId);
|
||||
}
|
||||
}
|
||||
|
||||
private final List<PlayerDuration> attackingControllers = new ArrayList<>();
|
||||
private final List<PlayerDuration> blockingControllers = new ArrayList<>();
|
||||
|
||||
public ControlCombatRedundancyWatcher() {
|
||||
super(WatcherScope.GAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
super.reset();
|
||||
attackingControllers.clear();
|
||||
blockingControllers.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void watch(GameEvent event, Game game) {
|
||||
if (event.getType() == GameEvent.EventType.END_COMBAT_STEP_POST) {
|
||||
attackingControllers.removeIf(PlayerDuration::isCombat);
|
||||
blockingControllers.removeIf(PlayerDuration::isCombat);
|
||||
}
|
||||
}
|
||||
|
||||
public static void addAttackingController(UUID playerId, Duration duration, Game game) {
|
||||
ControlCombatRedundancyWatcher watcher = game.getState().getWatcher(ControlCombatRedundancyWatcher.class);
|
||||
watcher.attackingControllers.add(0, new PlayerDuration(duration, playerId));
|
||||
}
|
||||
|
||||
public static void addBlockingController(UUID playerId, Duration duration, Game game) {
|
||||
ControlCombatRedundancyWatcher watcher = game.getState().getWatcher(ControlCombatRedundancyWatcher.class);
|
||||
watcher.blockingControllers.add(0, new PlayerDuration(duration, playerId));
|
||||
}
|
||||
|
||||
public static boolean checkAttackingController(UUID playerId, Game game) {
|
||||
ControlCombatRedundancyWatcher watcher = game.getState().getWatcher(ControlCombatRedundancyWatcher.class);
|
||||
return !watcher.attackingControllers.isEmpty() && watcher.attackingControllers.get(0).isPlayer(playerId);
|
||||
}
|
||||
|
||||
public static boolean checkBlockingController(UUID playerId, Game game) {
|
||||
ControlCombatRedundancyWatcher watcher = game.getState().getWatcher(ControlCombatRedundancyWatcher.class);
|
||||
return !watcher.blockingControllers.isEmpty() && watcher.blockingControllers.get(0).isPlayer(playerId);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue