mirror of
https://github.com/magefree/mage.git
synced 2025-12-23 03:51:58 -08:00
* Fixed some corner cases for Worl Enchantment State-Based actions (704.5k).
This commit is contained in:
parent
fdae577cef
commit
a2ae232b43
7 changed files with 161 additions and 54 deletions
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
package mage.cards.l;
|
package mage.cards.l;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
@ -11,8 +10,8 @@ import mage.abilities.effects.common.CreateTokenEffect;
|
||||||
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.SubType;
|
|
||||||
import mage.constants.Outcome;
|
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;
|
||||||
|
|
@ -33,7 +32,9 @@ public final class LieutenantsOfTheGuard extends CardImpl {
|
||||||
this.power = new MageInt(2);
|
this.power = new MageInt(2);
|
||||||
this.toughness = new MageInt(2);
|
this.toughness = new MageInt(2);
|
||||||
|
|
||||||
// <i>Council's dilemma</i> — When Lieutenants of the Guard enters the battlefield, starting with you, each player votes for strength or numbers. Put a +1/+1 counter on Lieutenants of the Guard for each strength vote and put a 1/1 white Soldier creature token onto the battlefield for each numbers vote.
|
// <i>Council's dilemma</i> — When Lieutenants of the Guard enters the battlefield, starting with you,
|
||||||
|
// each player votes for strength or numbers. Put a +1/+1 counter on Lieutenants of the Guard for each
|
||||||
|
// strength vote and put a 1/1 white Soldier creature token onto the battlefield for each numbers vote.
|
||||||
this.addAbility(new EntersBattlefieldTriggeredAbility(new LieutenantsOfTheGuardDilemmaEffect(), false, "<i>Council's dilemma</i> — "));
|
this.addAbility(new EntersBattlefieldTriggeredAbility(new LieutenantsOfTheGuardDilemmaEffect(), false, "<i>Council's dilemma</i> — "));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -48,6 +49,7 @@ public final class LieutenantsOfTheGuard extends CardImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
class LieutenantsOfTheGuardDilemmaEffect extends CouncilsDilemmaVoteEffect {
|
class LieutenantsOfTheGuardDilemmaEffect extends CouncilsDilemmaVoteEffect {
|
||||||
|
|
||||||
public LieutenantsOfTheGuardDilemmaEffect() {
|
public LieutenantsOfTheGuardDilemmaEffect() {
|
||||||
super(Outcome.Benefit);
|
super(Outcome.Benefit);
|
||||||
this.staticText = "starting with you, each player votes for strength or numbers. Put a +1/+1 counter on {this} for each strength vote and put a 1/1 white Soldier creature token onto the battlefield for each numbers vote.";
|
this.staticText = "starting with you, each player votes for strength or numbers. Put a +1/+1 counter on {this} for each strength vote and put a 1/1 white Soldier creature token onto the battlefield for each numbers vote.";
|
||||||
|
|
@ -62,7 +64,9 @@ class LieutenantsOfTheGuardDilemmaEffect extends CouncilsDilemmaVoteEffect {
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
|
|
||||||
//If no controller, exit out here and do not vote.
|
//If no controller, exit out here and do not vote.
|
||||||
if (controller == null) return false;
|
if (controller == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
this.vote("strength", "numbers", controller, game, source);
|
this.vote("strength", "numbers", controller, game, source);
|
||||||
|
|
||||||
|
|
@ -70,8 +74,9 @@ class LieutenantsOfTheGuardDilemmaEffect extends CouncilsDilemmaVoteEffect {
|
||||||
|
|
||||||
//Strength Votes
|
//Strength Votes
|
||||||
//If strength received zero votes or the permanent is no longer on the battlefield, do not attempt to put P1P1 counters on it.
|
//If strength received zero votes or the permanent is no longer on the battlefield, do not attempt to put P1P1 counters on it.
|
||||||
if (voteOneCount > 0 && permanent != null)
|
if (voteOneCount > 0 && permanent != null) {
|
||||||
permanent.addCounters(CounterType.P1P1.createInstance(voteOneCount), source, game);
|
permanent.addCounters(CounterType.P1P1.createInstance(voteOneCount), source, game);
|
||||||
|
}
|
||||||
|
|
||||||
//Numbers Votes
|
//Numbers Votes
|
||||||
if (voteTwoCount > 0) {
|
if (voteTwoCount > 0) {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
package org.mage.test.cards.rules;
|
package org.mage.test.cards.rules;
|
||||||
|
|
||||||
import mage.constants.PhaseStep;
|
import mage.constants.PhaseStep;
|
||||||
|
|
@ -10,14 +9,14 @@ import org.mage.test.serverside.base.CardTestMultiPlayerBase;
|
||||||
*
|
*
|
||||||
* @author LevelX2
|
* @author LevelX2
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class WorldEnchantmentsRuleTest extends CardTestMultiPlayerBase {
|
public class WorldEnchantmentsRuleTest extends CardTestMultiPlayerBase {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 704.5m If two or more permanents have the supertype world, all except the one that has had
|
* 704.5m If two or more permanents have the supertype world, all except the
|
||||||
* the world supertype for the shortest amount of time are put into their owners' graveyards.
|
* one that has had the world supertype for the shortest amount of time are
|
||||||
* In the event of a tie for the shortest amount of time, all are put into their owners' graveyards.
|
* put into their owners' graveyards. In the event of a tie for the shortest
|
||||||
* This is called the “world rule.
|
* amount of time, all are put into their owners' graveyards. This is called
|
||||||
|
* the “world rule.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
|
|
@ -64,4 +63,83 @@ public class WorldEnchantmentsRuleTest extends CardTestMultiPlayerBase {
|
||||||
assertPermanentCount(playerA, "Nether Void", 1);
|
assertPermanentCount(playerA, "Nether Void", 1);
|
||||||
assertPermanentCount(playerC, "Nether Void", 1);
|
assertPermanentCount(playerC, "Nether Void", 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 704.5 In the event of a tie for the shortest amount of time, all are put into their owners’ graveyards. This is called the “world rule.”
|
||||||
|
// In this example the execution order of the leaves the battlefield triggers of the two Oblivion Rings decide, which World Enchnatment may stay
|
||||||
|
// Player order: A -> D -> C -> B
|
||||||
|
@Test
|
||||||
|
public void TestTwoWorldEnchantmentsFromTriggers() {
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
// When Oblivion Ring enters the battlefield, exile another target nonland permanent.
|
||||||
|
// When Oblivion Ring leaves the battlefield, return the exiled card to the battlefield under its owner's control.
|
||||||
|
addCard(Zone.HAND, playerA, "Oblivion Ring", 1);
|
||||||
|
// All creatures have haste.
|
||||||
|
addCard(Zone.HAND, playerA, "Concordant Crossroads", 1);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Forest", 3);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Plains", 1);
|
||||||
|
|
||||||
|
// When Oblivion Ring enters the battlefield, exile another target nonland permanent.
|
||||||
|
// When Oblivion Ring leaves the battlefield, return the exiled card to the battlefield under its owner's control.
|
||||||
|
addCard(Zone.HAND, playerD, "Oblivion Ring", 1); // Enchantment {2}{W}
|
||||||
|
// Destroy all white permanents.
|
||||||
|
addCard(Zone.HAND, playerD, "Anarchy", 1); // Sorcery {2}{R}{R}
|
||||||
|
|
||||||
|
// All creatures have haste.
|
||||||
|
addCard(Zone.BATTLEFIELD, playerD, "Concordant Crossroads", 1); // World Enchantment {G}
|
||||||
|
addCard(Zone.BATTLEFIELD, playerD, "Plains", 1);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerD, "Mountain", 6);
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Oblivion Ring");
|
||||||
|
addTarget(playerA, "Concordant Crossroads");
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Concordant Crossroads");
|
||||||
|
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerD, "Oblivion Ring");
|
||||||
|
addTarget(playerD, "Concordant Crossroads");
|
||||||
|
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerD, "Anarchy"); // Both World Enchantments return at the same time and go to grave
|
||||||
|
|
||||||
|
setStopAt(2, PhaseStep.BEGIN_COMBAT);
|
||||||
|
execute();
|
||||||
|
assertAllCommandsUsed();
|
||||||
|
|
||||||
|
assertPermanentCount(playerD, "Concordant Crossroads", 0);
|
||||||
|
assertPermanentCount(playerA, "Concordant Crossroads", 1);
|
||||||
|
|
||||||
|
assertGraveyardCount(playerA, "Oblivion Ring", 1);
|
||||||
|
assertGraveyardCount(playerA, "Concordant Crossroads", 0);
|
||||||
|
assertGraveyardCount(playerD, "Oblivion Ring", 1);
|
||||||
|
assertGraveyardCount(playerD, "Concordant Crossroads", 1);
|
||||||
|
assertGraveyardCount(playerD, "Anarchy", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void TestTwoWorldEnchantmentsWithSameOrder() {
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
// When Charmed Griffin enters the battlefield, each other player may put an artifact or enchantment card onto the battlefield from their hand.
|
||||||
|
addCard(Zone.HAND, playerA, "Charmed Griffin", 1);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Plains", 4);
|
||||||
|
|
||||||
|
// All creatures have haste.
|
||||||
|
addCard(Zone.HAND, playerD, "Concordant Crossroads", 1);
|
||||||
|
addCard(Zone.HAND, playerB, "Concordant Crossroads", 1);
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Charmed Griffin");
|
||||||
|
|
||||||
|
setChoice(playerD, "Yes"); // Put an artifact or enchantment card from your hand onto the battlefield?
|
||||||
|
setChoice(playerD, "Concordant Crossroads");
|
||||||
|
|
||||||
|
setChoice(playerB, "Yes"); // Put an artifact or enchantment card from your hand onto the battlefield?
|
||||||
|
setChoice(playerB, "Concordant Crossroads");
|
||||||
|
|
||||||
|
concede(1, PhaseStep.PRECOMBAT_MAIN, playerC); // World Enchantments come into range
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||||
|
execute();
|
||||||
|
assertAllCommandsUsed();
|
||||||
|
|
||||||
|
assertPermanentCount(playerA, "Charmed Griffin", 1);
|
||||||
|
assertPermanentCount(playerD, "Concordant Crossroads", 0);
|
||||||
|
assertPermanentCount(playerB, "Concordant Crossroads", 0);
|
||||||
|
|
||||||
|
assertGraveyardCount(playerB, "Concordant Crossroads", 1);
|
||||||
|
assertGraveyardCount(playerD, "Concordant Crossroads", 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package mage.abilities.effects;
|
package mage.abilities.effects;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
import mage.MageObject;
|
import mage.MageObject;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.SpellAbility;
|
import mage.abilities.SpellAbility;
|
||||||
|
|
@ -17,8 +18,6 @@ import mage.players.Player;
|
||||||
import mage.target.Target;
|
import mage.target.Target;
|
||||||
import mage.target.common.TargetCardInGraveyard;
|
import mage.target.common.TargetCardInGraveyard;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cards with the Aura subtype don't change the zone they are in, if there is no
|
* Cards with the Aura subtype don't change the zone they are in, if there is no
|
||||||
* valid target on the battlefield. Also, when entering the battlefield and it
|
* valid target on the battlefield. Also, when entering the battlefield and it
|
||||||
|
|
@ -163,7 +162,7 @@ public class AuraReplacementEffect extends ReplacementEffectImpl {
|
||||||
PermanentCard permanent = new PermanentCard(card, (controllingPlayer == null ? card.getOwnerId() : controllingPlayer.getId()), game);
|
PermanentCard permanent = new PermanentCard(card, (controllingPlayer == null ? card.getOwnerId() : controllingPlayer.getId()), game);
|
||||||
ZoneChangeEvent zoneChangeEvent = new ZoneChangeEvent(permanent, controllerId, fromZone, Zone.BATTLEFIELD);
|
ZoneChangeEvent zoneChangeEvent = new ZoneChangeEvent(permanent, controllerId, fromZone, Zone.BATTLEFIELD);
|
||||||
permanent.updateZoneChangeCounter(game, zoneChangeEvent);
|
permanent.updateZoneChangeCounter(game, zoneChangeEvent);
|
||||||
game.getBattlefield().addPermanent(permanent);
|
game.addPermanent(permanent, 0);
|
||||||
card.setZone(Zone.BATTLEFIELD, game);
|
card.setZone(Zone.BATTLEFIELD, game);
|
||||||
if (permanent.entersBattlefield(event.getSourceId(), game, fromZone, true)) {
|
if (permanent.entersBattlefield(event.getSourceId(), game, fromZone, true)) {
|
||||||
if (targetCard != null) {
|
if (targetCard != null) {
|
||||||
|
|
@ -196,9 +195,9 @@ public class AuraReplacementEffect extends ReplacementEffectImpl {
|
||||||
return card != null && (card.isEnchantment() && card.hasSubtype(SubType.AURA, game)
|
return card != null && (card.isEnchantment() && card.hasSubtype(SubType.AURA, game)
|
||||||
|| // in case of transformable enchantments
|
|| // in case of transformable enchantments
|
||||||
(game.getState().getValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + card.getId()) != null
|
(game.getState().getValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + card.getId()) != null
|
||||||
&& card.getSecondCardFace() != null
|
&& card.getSecondCardFace() != null
|
||||||
&& card.getSecondCardFace().isEnchantment()
|
&& card.getSecondCardFace().isEnchantment()
|
||||||
&& card.getSecondCardFace().hasSubtype(SubType.AURA, game)));
|
&& card.getSecondCardFace().hasSubtype(SubType.AURA, game)));
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -373,7 +373,16 @@ public interface Game extends MageItem, Serializable {
|
||||||
|
|
||||||
void addCommander(Commander commander);
|
void addCommander(Commander commander);
|
||||||
|
|
||||||
void addPermanent(Permanent permanent);
|
/**
|
||||||
|
* Adds a permanent to the battlefield
|
||||||
|
*
|
||||||
|
* @param permanent
|
||||||
|
* @param createOrder upcounting number from state about the create order of
|
||||||
|
* all permanents. Can equal for multiple permanents, if
|
||||||
|
* they go to battlefield at the same time. If the value
|
||||||
|
* is set to 0, a next number will be set automatically.
|
||||||
|
*/
|
||||||
|
void addPermanent(Permanent permanent, int createOrder);
|
||||||
|
|
||||||
// priority method
|
// priority method
|
||||||
void sendPlayerAction(PlayerAction playerAction, UUID playerId, Object data);
|
void sendPlayerAction(PlayerAction playerAction, UUID playerId, Object data);
|
||||||
|
|
|
||||||
|
|
@ -187,6 +187,7 @@ public abstract class GameImpl implements Game, Serializable {
|
||||||
this.startLife = game.startLife;
|
this.startLife = game.startLife;
|
||||||
this.enterWithCounters.putAll(game.enterWithCounters);
|
this.enterWithCounters.putAll(game.enterWithCounters);
|
||||||
this.startingSize = game.startingSize;
|
this.startingSize = game.startingSize;
|
||||||
|
this.gameStopped = game.gameStopped;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -1419,7 +1420,7 @@ public abstract class GameImpl implements Game, Serializable {
|
||||||
if (spell != null) {
|
if (spell != null) {
|
||||||
if (spell.getCommandedBy() != null) {
|
if (spell.getCommandedBy() != null) {
|
||||||
UUID commandedBy = spell.getCommandedBy();
|
UUID commandedBy = spell.getCommandedBy();
|
||||||
UUID spellControllerId = null;
|
UUID spellControllerId;
|
||||||
if (commandedBy.equals(spell.getControllerId())) {
|
if (commandedBy.equals(spell.getControllerId())) {
|
||||||
spellControllerId = spell.getSpellAbility().getFirstTarget(); // i.e. resolved spell is Word of Command
|
spellControllerId = spell.getSpellAbility().getFirstTarget(); // i.e. resolved spell is Word of Command
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1605,9 +1606,12 @@ public abstract class GameImpl implements Game, Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addPermanent(Permanent permanent) {
|
public void addPermanent(Permanent permanent, int createOrder) {
|
||||||
|
if (createOrder == 0) {
|
||||||
|
createOrder = getState().getNextPermanentOrderNumber();
|
||||||
|
}
|
||||||
|
permanent.setCreateOrder(createOrder);
|
||||||
getBattlefield().addPermanent(permanent);
|
getBattlefield().addPermanent(permanent);
|
||||||
permanent.setCreateOrder(getState().getNextPermanentOrderNumber());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -2254,30 +2258,38 @@ public abstract class GameImpl implements Game, Serializable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//704.5m - World Enchantments
|
//704.5k - World Enchantments
|
||||||
if (worldEnchantment.size() > 1) {
|
if (worldEnchantment.size() > 1) {
|
||||||
int newestCard = -1;
|
int newestCard = -1;
|
||||||
|
Set<UUID> controllerIdOfNewest = new HashSet<>();
|
||||||
Permanent newestPermanent = null;
|
Permanent newestPermanent = null;
|
||||||
for (Permanent permanent : worldEnchantment) {
|
for (Permanent permanent : worldEnchantment) {
|
||||||
if (newestCard == -1) {
|
if (newestCard == -1) {
|
||||||
newestCard = permanent.getCreateOrder();
|
newestCard = permanent.getCreateOrder();
|
||||||
newestPermanent = permanent;
|
newestPermanent = permanent;
|
||||||
|
controllerIdOfNewest.clear();
|
||||||
|
controllerIdOfNewest.add(permanent.getControllerId());
|
||||||
} else if (newestCard < permanent.getCreateOrder()) {
|
} else if (newestCard < permanent.getCreateOrder()) {
|
||||||
newestCard = permanent.getCreateOrder();
|
newestCard = permanent.getCreateOrder();
|
||||||
newestPermanent = permanent;
|
newestPermanent = permanent;
|
||||||
|
controllerIdOfNewest.clear();
|
||||||
|
controllerIdOfNewest.add(permanent.getControllerId());
|
||||||
} else if (newestCard == permanent.getCreateOrder()) {
|
} else if (newestCard == permanent.getCreateOrder()) {
|
||||||
|
// In the event of a tie for the shortest amount of time, all are put into their owners’ graveyards. This is called the “world rule.”
|
||||||
newestPermanent = null;
|
newestPermanent = null;
|
||||||
|
controllerIdOfNewest.add(permanent.getControllerId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (UUID controllerId : controllerIdOfNewest) {
|
||||||
|
PlayerList newestPermanentControllerRange = state.getPlayersInRange(controllerId, this);
|
||||||
|
|
||||||
PlayerList newestPermanentControllerRange = state.getPlayersInRange(newestPermanent.getControllerId(), this);
|
// 801.12 The "world rule" applies to a permanent only if other world permanents are within its controller's range of influence.
|
||||||
|
for (Permanent permanent : worldEnchantment) {
|
||||||
// 801.12 The "world rule" applies to a permanent only if other world permanents are within its controller's range of influence.
|
if (newestPermanentControllerRange.contains(permanent.getControllerId())
|
||||||
for (Permanent permanent : worldEnchantment) {
|
&& !Objects.equals(newestPermanent, permanent)) {
|
||||||
if (newestPermanentControllerRange.contains(permanent.getControllerId())
|
movePermanentToGraveyardWithInfo(permanent);
|
||||||
&& !Objects.equals(newestPermanent, permanent)) {
|
somethingHappened = true;
|
||||||
movePermanentToGraveyardWithInfo(permanent);
|
}
|
||||||
somethingHappened = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2788,7 +2800,7 @@ public abstract class GameImpl implements Game, Serializable {
|
||||||
}
|
}
|
||||||
if (amountToPrevent != Integer.MAX_VALUE) {
|
if (amountToPrevent != Integer.MAX_VALUE) {
|
||||||
// set remaining amount
|
// set remaining amount
|
||||||
result.setRemainingAmount(amountToPrevent -= result.getPreventedDamage());
|
result.setRemainingAmount(amountToPrevent - result.getPreventedDamage());
|
||||||
}
|
}
|
||||||
MageObject damageSource = game.getObject(damageEvent.getSourceId());
|
MageObject damageSource = game.getObject(damageEvent.getSourceId());
|
||||||
MageObject preventionSource = game.getObject(source.getSourceId());
|
MageObject preventionSource = game.getObject(source.getSourceId());
|
||||||
|
|
@ -3058,7 +3070,7 @@ public abstract class GameImpl implements Game, Serializable {
|
||||||
PermanentCard newPermanent = new PermanentCard(permanentCard.getCard(), ownerId, this);
|
PermanentCard newPermanent = new PermanentCard(permanentCard.getCard(), ownerId, this);
|
||||||
getPermanentsEntering().put(newPermanent.getId(), newPermanent);
|
getPermanentsEntering().put(newPermanent.getId(), newPermanent);
|
||||||
newPermanent.entersBattlefield(newPermanent.getId(), this, Zone.OUTSIDE, false);
|
newPermanent.entersBattlefield(newPermanent.getId(), this, Zone.OUTSIDE, false);
|
||||||
getBattlefield().addPermanent(newPermanent);
|
addPermanent(newPermanent, getState().getNextPermanentOrderNumber());
|
||||||
getPermanentsEntering().remove(newPermanent.getId());
|
getPermanentsEntering().remove(newPermanent.getId());
|
||||||
newPermanent.removeSummoningSickness();
|
newPermanent.removeSummoningSickness();
|
||||||
if (permanentCard.isTapped()) {
|
if (permanentCard.isTapped()) {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package mage.game;
|
package mage.game;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
import mage.cards.Card;
|
import mage.cards.Card;
|
||||||
import mage.cards.Cards;
|
import mage.cards.Cards;
|
||||||
import mage.cards.CardsImpl;
|
import mage.cards.CardsImpl;
|
||||||
|
|
@ -18,8 +19,6 @@ import mage.game.stack.Spell;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
import mage.target.TargetCard;
|
import mage.target.TargetCard;
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by samuelsandeen on 9/6/16.
|
* Created by samuelsandeen on 9/6/16.
|
||||||
*/
|
*/
|
||||||
|
|
@ -27,7 +26,7 @@ public final class ZonesHandler {
|
||||||
|
|
||||||
public static boolean cast(ZoneChangeInfo info, Game game) {
|
public static boolean cast(ZoneChangeInfo info, Game game) {
|
||||||
if (maybeRemoveFromSourceZone(info, game)) {
|
if (maybeRemoveFromSourceZone(info, game)) {
|
||||||
placeInDestinationZone(info, game);
|
placeInDestinationZone(info, game, 0);
|
||||||
// create a group zone change event if a card is moved to stack for casting (it's always only one card, but some effects check for group events (one or more xxx))
|
// create a group zone change event if a card is moved to stack for casting (it's always only one card, but some effects check for group events (one or more xxx))
|
||||||
Set<Card> cards = new HashSet<>();
|
Set<Card> cards = new HashSet<>();
|
||||||
Set<PermanentToken> tokens = new HashSet<>();
|
Set<PermanentToken> tokens = new HashSet<>();
|
||||||
|
|
@ -53,7 +52,7 @@ public final class ZonesHandler {
|
||||||
|
|
||||||
public static List<ZoneChangeInfo> moveCards(List<ZoneChangeInfo> zoneChangeInfos, Game game) {
|
public static List<ZoneChangeInfo> moveCards(List<ZoneChangeInfo> zoneChangeInfos, Game game) {
|
||||||
// Handle Unmelded Meld Cards
|
// Handle Unmelded Meld Cards
|
||||||
for (ListIterator<ZoneChangeInfo> itr = zoneChangeInfos.listIterator(); itr.hasNext(); ) {
|
for (ListIterator<ZoneChangeInfo> itr = zoneChangeInfos.listIterator(); itr.hasNext();) {
|
||||||
ZoneChangeInfo info = itr.next();
|
ZoneChangeInfo info = itr.next();
|
||||||
MeldCard card = game.getMeldCard(info.event.getTargetId());
|
MeldCard card = game.getMeldCard(info.event.getTargetId());
|
||||||
// Copies should be handled as normal cards.
|
// Copies should be handled as normal cards.
|
||||||
|
|
@ -67,8 +66,13 @@ public final class ZonesHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
zoneChangeInfos.removeIf(zoneChangeInfo -> !maybeRemoveFromSourceZone(zoneChangeInfo, game));
|
zoneChangeInfos.removeIf(zoneChangeInfo -> !maybeRemoveFromSourceZone(zoneChangeInfo, game));
|
||||||
|
int createOrder = 0;
|
||||||
for (ZoneChangeInfo zoneChangeInfo : zoneChangeInfos) {
|
for (ZoneChangeInfo zoneChangeInfo : zoneChangeInfos) {
|
||||||
placeInDestinationZone(zoneChangeInfo, game);
|
if (createOrder == 0 && Zone.BATTLEFIELD.equals(zoneChangeInfo.event.getToZone())) {
|
||||||
|
// All permanents go to battlefield at the same time (=create order)
|
||||||
|
createOrder = game.getState().getNextPermanentOrderNumber();
|
||||||
|
}
|
||||||
|
placeInDestinationZone(zoneChangeInfo, game, createOrder);
|
||||||
if (game.getPhase() != null) { // moving cards to zones before game started does not need events
|
if (game.getPhase() != null) { // moving cards to zones before game started does not need events
|
||||||
game.addSimultaneousEvent(zoneChangeInfo.event);
|
game.addSimultaneousEvent(zoneChangeInfo.event);
|
||||||
}
|
}
|
||||||
|
|
@ -76,14 +80,14 @@ public final class ZonesHandler {
|
||||||
return zoneChangeInfos;
|
return zoneChangeInfos;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void placeInDestinationZone(ZoneChangeInfo info, Game game) {
|
private static void placeInDestinationZone(ZoneChangeInfo info, Game game, int createOrder) {
|
||||||
// Handle unmelded cards
|
// Handle unmelded cards
|
||||||
if (info instanceof ZoneChangeInfo.Unmelded) {
|
if (info instanceof ZoneChangeInfo.Unmelded) {
|
||||||
ZoneChangeInfo.Unmelded unmelded = (ZoneChangeInfo.Unmelded) info;
|
ZoneChangeInfo.Unmelded unmelded = (ZoneChangeInfo.Unmelded) info;
|
||||||
Zone toZone = null;
|
Zone toZone = null;
|
||||||
for (ZoneChangeInfo subInfo : unmelded.subInfo) {
|
for (ZoneChangeInfo subInfo : unmelded.subInfo) {
|
||||||
toZone = subInfo.event.getToZone();
|
toZone = subInfo.event.getToZone();
|
||||||
placeInDestinationZone(subInfo, game);
|
placeInDestinationZone(subInfo, game, createOrder);
|
||||||
}
|
}
|
||||||
// We arbitrarily prefer the bottom half card. This should never be relevant.
|
// We arbitrarily prefer the bottom half card. This should never be relevant.
|
||||||
if (toZone != null) {
|
if (toZone != null) {
|
||||||
|
|
@ -161,7 +165,7 @@ public final class ZonesHandler {
|
||||||
break;
|
break;
|
||||||
case BATTLEFIELD:
|
case BATTLEFIELD:
|
||||||
Permanent permanent = event.getTarget();
|
Permanent permanent = event.getTarget();
|
||||||
game.addPermanent(permanent);
|
game.addPermanent(permanent, createOrder);
|
||||||
game.getPermanentsEntering().remove(permanent.getId());
|
game.getPermanentsEntering().remove(permanent.getId());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
@ -197,7 +201,7 @@ public final class ZonesHandler {
|
||||||
if (info instanceof ZoneChangeInfo.Unmelded) {
|
if (info instanceof ZoneChangeInfo.Unmelded) {
|
||||||
ZoneChangeInfo.Unmelded unmelded = (ZoneChangeInfo.Unmelded) info;
|
ZoneChangeInfo.Unmelded unmelded = (ZoneChangeInfo.Unmelded) info;
|
||||||
MeldCard meld = game.getMeldCard(info.event.getTargetId());
|
MeldCard meld = game.getMeldCard(info.event.getTargetId());
|
||||||
for (Iterator<ZoneChangeInfo> itr = unmelded.subInfo.iterator(); itr.hasNext(); ) {
|
for (Iterator<ZoneChangeInfo> itr = unmelded.subInfo.iterator(); itr.hasNext();) {
|
||||||
ZoneChangeInfo subInfo = itr.next();
|
ZoneChangeInfo subInfo = itr.next();
|
||||||
if (!maybeRemoveFromSourceZone(subInfo, game)) {
|
if (!maybeRemoveFromSourceZone(subInfo, game)) {
|
||||||
itr.remove();
|
itr.remove();
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,9 @@
|
||||||
package mage.game.permanent.token;
|
package mage.game.permanent.token;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.UUID;
|
||||||
import mage.MageObject;
|
import mage.MageObject;
|
||||||
import mage.MageObjectImpl;
|
import mage.MageObjectImpl;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
|
|
@ -14,11 +18,6 @@ import mage.game.permanent.PermanentToken;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
import mage.util.RandomUtil;
|
import mage.util.RandomUtil;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
public abstract class TokenImpl extends MageObjectImpl implements Token {
|
public abstract class TokenImpl extends MageObjectImpl implements Token {
|
||||||
|
|
||||||
protected String description;
|
protected String description;
|
||||||
|
|
@ -202,8 +201,9 @@ public abstract class TokenImpl extends MageObjectImpl implements Token {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
game.setScopeRelevant(false);
|
game.setScopeRelevant(false);
|
||||||
|
int createOrder = game.getState().getNextPermanentOrderNumber();
|
||||||
for (Permanent permanent : permanentsEntered) {
|
for (Permanent permanent : permanentsEntered) {
|
||||||
game.addPermanent(permanent);
|
game.addPermanent(permanent, createOrder);
|
||||||
permanent.setZone(Zone.BATTLEFIELD, game);
|
permanent.setZone(Zone.BATTLEFIELD, game);
|
||||||
game.getPermanentsEntering().remove(permanent.getId());
|
game.getPermanentsEntering().remove(permanent.getId());
|
||||||
|
|
||||||
|
|
@ -242,8 +242,8 @@ public abstract class TokenImpl extends MageObjectImpl implements Token {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set token index to search in card-pictures-tok.txt (if set have multiple tokens with same name)
|
* Set token index to search in card-pictures-tok.txt (if set have multiple
|
||||||
* Default is 1
|
* tokens with same name) Default is 1
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void setTokenType(int tokenType) {
|
public void setTokenType(int tokenType) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue