mirror of
https://github.com/magefree/mage.git
synced 2025-12-26 21:42:07 -08:00
* Commander: added support of lands as commander (#5795);
This commit is contained in:
parent
b3e7c4f136
commit
42ed14df52
18 changed files with 441 additions and 201 deletions
|
|
@ -1,15 +1,13 @@
|
|||
package mage.abilities.common;
|
||||
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.abilities.costs.CostsImpl;
|
||||
import mage.abilities.costs.common.CommanderAdditionalCost;
|
||||
import mage.cards.Card;
|
||||
import mage.constants.SpellAbilityType;
|
||||
import mage.constants.TimingRule;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
|
||||
/**
|
||||
* @author Plopman
|
||||
* @author Plopman, JayDi85
|
||||
*/
|
||||
public class CastCommanderAbility extends SpellAbility {
|
||||
|
||||
|
|
@ -20,9 +18,11 @@ public class CastCommanderAbility extends SpellAbility {
|
|||
this.getEffects().addAll(card.getSpellAbility().getEffects().copy());
|
||||
this.getTargets().addAll(card.getSpellAbility().getTargets().copy());
|
||||
this.timing = card.getSpellAbility().getTiming();
|
||||
|
||||
// extra cost
|
||||
this.addCost(new CommanderAdditionalCost());
|
||||
} else {
|
||||
this.costs = new CostsImpl<>();
|
||||
this.timing = TimingRule.SORCERY;
|
||||
throw new IllegalStateException("Cast commander ability must be used with spell ability only: " + card.getName());
|
||||
}
|
||||
this.usesStack = true;
|
||||
this.controllerId = card.getOwnerId();
|
||||
|
|
@ -33,22 +33,6 @@ public class CastCommanderAbility extends SpellAbility {
|
|||
super(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean activate(Game game, boolean noMana) {
|
||||
if (super.activate(game, noMana)) {
|
||||
// save amount of times commander was cast
|
||||
Integer castCount = (Integer) game.getState().getValue(sourceId + "_castCount");
|
||||
if (castCount == null) {
|
||||
castCount = 1;
|
||||
} else {
|
||||
castCount++;
|
||||
}
|
||||
game.getState().setValue(sourceId + "_castCount", castCount);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CastCommanderAbility copy() {
|
||||
return new CastCommanderAbility(this);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
package mage.abilities.common;
|
||||
|
||||
import mage.abilities.PlayLandAbility;
|
||||
import mage.abilities.costs.common.CommanderAdditionalCost;
|
||||
import mage.constants.Zone;
|
||||
|
||||
/**
|
||||
* @author JayDi85
|
||||
*/
|
||||
public class PlayLandAsCommanderAbility extends PlayLandAbility {
|
||||
|
||||
public PlayLandAsCommanderAbility(PlayLandAbility originalAbility) {
|
||||
super(originalAbility);
|
||||
zone = Zone.COMMAND;
|
||||
|
||||
// extra cost
|
||||
this.addCost(new CommanderAdditionalCost());
|
||||
}
|
||||
|
||||
private PlayLandAsCommanderAbility(PlayLandAsCommanderAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlayLandAsCommanderAbility copy() {
|
||||
return new PlayLandAsCommanderAbility(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
package mage.abilities.costs.common;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.dynamicvalue.common.CommanderPlaysCount;
|
||||
import mage.game.Game;
|
||||
|
||||
/**
|
||||
* @author JayDi85
|
||||
*/
|
||||
public class CommanderAdditionalCost extends DynamicValueGenericManaCost {
|
||||
|
||||
/*
|
||||
903.8. A player may cast a commander they own from the command zone. A commander cast from the
|
||||
command zone costs an additional {2} for each previous time the player casting it has cast it from
|
||||
the command zone that game. This additional cost is informally known as the “commander tax.”
|
||||
*/
|
||||
|
||||
public CommanderAdditionalCost() {
|
||||
super(new CommanderPlaysCount(2), "{2} for each previous time the player casting it has cast it from the command zone");
|
||||
}
|
||||
|
||||
public CommanderAdditionalCost(final CommanderAdditionalCost cost) {
|
||||
super(cost);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommanderAdditionalCost copy() {
|
||||
return new CommanderAdditionalCost(this);
|
||||
}
|
||||
|
||||
public boolean isEmptyPay(Ability ability, Game game) {
|
||||
return amount.calculate(game, ability, null) == 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
package mage.abilities.costs.common;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.costs.Cost;
|
||||
import mage.abilities.costs.CostImpl;
|
||||
import mage.abilities.costs.mana.GenericManaCost;
|
||||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
import mage.game.Game;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class DynamicValueGenericManaCost extends CostImpl {
|
||||
|
||||
DynamicValue amount;
|
||||
|
||||
public DynamicValueGenericManaCost(DynamicValue amount, String text) {
|
||||
this.amount = amount;
|
||||
setText(text);
|
||||
}
|
||||
|
||||
public DynamicValueGenericManaCost(DynamicValueGenericManaCost cost) {
|
||||
super(cost);
|
||||
this.amount = cost.amount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) {
|
||||
int convertedCost = amount.calculate(game, ability, null);
|
||||
Cost cost = new GenericManaCost(convertedCost);
|
||||
return cost.canPay(ability, sourceId, controllerId, game);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana, Cost costToPay) {
|
||||
int convertedCost = amount.calculate(game, ability, null);
|
||||
Cost cost = new GenericManaCost(convertedCost);
|
||||
paid = cost.pay(ability, game, sourceId, controllerId, noMana);
|
||||
return paid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DynamicValueGenericManaCost copy() {
|
||||
return new DynamicValueGenericManaCost(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
package mage.abilities.dynamicvalue.common;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.game.Game;
|
||||
import mage.watchers.common.CommanderPlaysCountWatcher;
|
||||
|
||||
/**
|
||||
* @author JayDi85
|
||||
*/
|
||||
public class CommanderPlaysCount implements DynamicValue {
|
||||
|
||||
private Integer multiplier;
|
||||
|
||||
public CommanderPlaysCount() {
|
||||
this(1);
|
||||
}
|
||||
|
||||
public CommanderPlaysCount(Integer multiplier) {
|
||||
this.multiplier = multiplier;
|
||||
}
|
||||
|
||||
public CommanderPlaysCount(final CommanderPlaysCount dynamicValue) {
|
||||
this.multiplier = dynamicValue.multiplier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int calculate(Game game, Ability sourceAbility, Effect effect) {
|
||||
CommanderPlaysCountWatcher watcher = game.getState().getWatcher(CommanderPlaysCountWatcher.class);
|
||||
int value = 0;
|
||||
if (watcher != null) {
|
||||
value = watcher.getPlaysCount(sourceAbility.getSourceId());
|
||||
}
|
||||
return value * multiplier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommanderPlaysCount copy() {
|
||||
return new CommanderPlaysCount(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "X";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
|
||||
package mage.abilities.effects.common.cost;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.CastCommanderAbility;
|
||||
import mage.abilities.costs.mana.GenericManaCost;
|
||||
import mage.constants.CostModificationType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.game.Game;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Plopman
|
||||
*/
|
||||
//20130711
|
||||
/*903.10. A player may cast a commander he or she owns from the command zone.
|
||||
* Doing so costs that player an additional {2} for each previous time he or she cast that commander from the command zone that game.
|
||||
* */
|
||||
public class CommanderCostModification extends CostModificationEffectImpl {
|
||||
|
||||
private final UUID commanderId;
|
||||
|
||||
public CommanderCostModification(UUID commanderId) {
|
||||
super(Duration.Custom, Outcome.Neutral, CostModificationType.INCREASE_COST);
|
||||
this.commanderId = commanderId;
|
||||
}
|
||||
|
||||
public CommanderCostModification(final CommanderCostModification effect) {
|
||||
super(effect);
|
||||
this.commanderId = effect.commanderId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source, Ability abilityToModify) {
|
||||
Integer castCount = (Integer) game.getState().getValue(commanderId + "_castCount");
|
||||
if (castCount > 0) {
|
||||
abilityToModify.getManaCostsToPay().add(new GenericManaCost(2 * castCount));
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(Ability abilityToModify, Ability source, Game game) {
|
||||
return abilityToModify instanceof CastCommanderAbility && abilityToModify.getSourceId().equals(commanderId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommanderCostModification copy() {
|
||||
return new CommanderCostModification(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -13,9 +13,9 @@ import mage.game.events.GameEvent.EventType;
|
|||
import mage.game.stack.Spell;
|
||||
import mage.game.stack.StackObject;
|
||||
import mage.players.Player;
|
||||
import mage.watchers.common.CommanderPlaysCountWatcher;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Plopman
|
||||
*/
|
||||
public class CommanderStormAbility extends TriggeredAbilityImpl {
|
||||
|
|
@ -83,9 +83,9 @@ class CommanderStormEffect extends OneShotEffect {
|
|||
if (player == null) {
|
||||
return false;
|
||||
}
|
||||
stormCount = player.getCommandersIds().stream().map(
|
||||
(commanderId) -> (Integer) game.getState().getValue(commanderId + "_castCount")
|
||||
).map((castCount) -> castCount).reduce(stormCount, Integer::sum);
|
||||
stormCount = player.getCommandersIds().stream()
|
||||
.map((commanderId) -> game.getState().getWatcher(CommanderPlaysCountWatcher.class).getPlaysCount(commanderId))
|
||||
.reduce(stormCount, Integer::sum);
|
||||
if (stormCount == 0) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import mage.abilities.Ability;
|
|||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.common.InfoEffect;
|
||||
import mage.abilities.effects.common.continuous.CommanderReplacementEffect;
|
||||
import mage.abilities.effects.common.cost.CommanderCostModification;
|
||||
import mage.cards.Card;
|
||||
import mage.constants.MultiplayerAttackOption;
|
||||
import mage.constants.PhaseStep;
|
||||
|
|
@ -14,6 +13,7 @@ import mage.game.mulligan.Mulligan;
|
|||
import mage.game.turn.TurnMod;
|
||||
import mage.players.Player;
|
||||
import mage.watchers.common.CommanderInfoWatcher;
|
||||
import mage.watchers.common.CommanderPlaysCountWatcher;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
|
@ -40,7 +40,11 @@ public abstract class GameCommanderImpl extends GameImpl {
|
|||
|
||||
@Override
|
||||
protected void init(UUID choosingPlayerId) {
|
||||
//Move commander to command zone
|
||||
|
||||
// plays watcher
|
||||
state.addWatcher(new CommanderPlaysCountWatcher());
|
||||
|
||||
// move commanders to command zone
|
||||
for (UUID playerId : state.getPlayerList(startingPlayerId)) {
|
||||
Player player = getPlayer(playerId);
|
||||
if (player != null) {
|
||||
|
|
@ -62,6 +66,7 @@ public abstract class GameCommanderImpl extends GameImpl {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
super.init(choosingPlayerId);
|
||||
if (startingPlayerSkipsDraw) {
|
||||
state.getTurnMods().add(new TurnMod(startingPlayerId, PhaseStep.DRAW));
|
||||
|
|
@ -73,8 +78,6 @@ public abstract class GameCommanderImpl extends GameImpl {
|
|||
commander.moveToZone(Zone.COMMAND, null, this, true);
|
||||
commander.getAbilities().setControllerId(player.getId());
|
||||
ability.addEffect(new CommanderReplacementEffect(commander.getId(), alsoHand, alsoLibrary));
|
||||
ability.addEffect(new CommanderCostModification(commander.getId()));
|
||||
getState().setValue(commander.getId() + "_castCount", 0);
|
||||
CommanderInfoWatcher watcher = new CommanderInfoWatcher(commander.getId(), checkCommanderDamage);
|
||||
getState().addWatcher(watcher);
|
||||
watcher.addCardInfoToCommander(this);
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import mage.abilities.Ability;
|
|||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.common.InfoEffect;
|
||||
import mage.abilities.effects.common.continuous.CommanderReplacementEffect;
|
||||
import mage.abilities.effects.common.cost.CommanderCostModification;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
|
|
@ -16,6 +15,7 @@ import mage.game.mulligan.Mulligan;
|
|||
import mage.game.turn.TurnMod;
|
||||
import mage.players.Player;
|
||||
import mage.watchers.common.CommanderInfoWatcher;
|
||||
import mage.watchers.common.CommanderPlaysCountWatcher;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
|
@ -42,7 +42,10 @@ public abstract class GameTinyLeadersImpl extends GameImpl {
|
|||
|
||||
@Override
|
||||
protected void init(UUID choosingPlayerId) {
|
||||
//Move tiny leader to command zone
|
||||
// plays watcher
|
||||
state.addWatcher(new CommanderPlaysCountWatcher());
|
||||
|
||||
// move tiny leader to command zone
|
||||
for (UUID playerId : state.getPlayerList(startingPlayerId)) {
|
||||
Player player = getPlayer(playerId);
|
||||
if (player != null) {
|
||||
|
|
@ -55,10 +58,8 @@ public abstract class GameTinyLeadersImpl extends GameImpl {
|
|||
commander.moveToZone(Zone.COMMAND, null, this, true);
|
||||
Ability ability = new SimpleStaticAbility(Zone.COMMAND, new InfoEffect("Commander effects"));
|
||||
ability.addEffect(new CommanderReplacementEffect(commander.getId(), alsoHand, alsoLibrary));
|
||||
ability.addEffect(new CommanderCostModification(commander.getId()));
|
||||
// Commander rule #4 was removed Jan. 18, 2016
|
||||
// ability.addEffect(new CommanderManaReplacementEffect(player.getId(), CardUtil.getColorIdentity(commander)));
|
||||
getState().setValue(commander.getId() + "_castCount", 0);
|
||||
CommanderInfoWatcher watcher = new CommanderInfoWatcher(commander.getId(), false);
|
||||
getState().addWatcher(watcher);
|
||||
watcher.addCardInfoToCommander(this);
|
||||
|
|
|
|||
|
|
@ -3,11 +3,9 @@ package mage.game.command;
|
|||
import mage.MageInt;
|
||||
import mage.MageObject;
|
||||
import mage.ObjectColor;
|
||||
import mage.abilities.Abilities;
|
||||
import mage.abilities.AbilitiesImpl;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.abilities.*;
|
||||
import mage.abilities.common.CastCommanderAbility;
|
||||
import mage.abilities.common.PlayLandAsCommanderAbility;
|
||||
import mage.abilities.costs.mana.ManaCost;
|
||||
import mage.abilities.costs.mana.ManaCosts;
|
||||
import mage.abilities.text.TextPart;
|
||||
|
|
@ -34,9 +32,23 @@ public class Commander implements CommandObject {
|
|||
|
||||
public Commander(Card card) {
|
||||
this.sourceObject = card;
|
||||
abilities.add(new CastCommanderAbility(card));
|
||||
|
||||
// replace spell ability by commander cast spell (to cast from command zone)
|
||||
if (card.getSpellAbility() != null) {
|
||||
abilities.add(new CastCommanderAbility(card));
|
||||
}
|
||||
|
||||
// replace play land with commander play land (to play from command zone)
|
||||
for (Ability ability : card.getAbilities()) {
|
||||
if (!(ability instanceof SpellAbility)) {
|
||||
if (ability instanceof PlayLandAbility) {
|
||||
Ability newAbility = new PlayLandAsCommanderAbility((PlayLandAbility) ability);
|
||||
abilities.add(newAbility);
|
||||
}
|
||||
}
|
||||
|
||||
// other abilities
|
||||
for (Ability ability : card.getAbilities()) {
|
||||
if (!(ability instanceof SpellAbility) && !(ability instanceof PlayLandAbility)) {
|
||||
Ability newAbility = ability.copy();
|
||||
abilities.add(newAbility);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,9 +8,11 @@ import mage.Mana;
|
|||
import mage.abilities.*;
|
||||
import mage.abilities.ActivatedAbility.ActivationStatus;
|
||||
import mage.abilities.common.PassAbility;
|
||||
import mage.abilities.common.PlayLandAsCommanderAbility;
|
||||
import mage.abilities.common.WhileSearchingPlayFromLibraryAbility;
|
||||
import mage.abilities.common.delayed.AtTheEndOfTurnStepPostDelayedTriggeredAbility;
|
||||
import mage.abilities.costs.*;
|
||||
import mage.abilities.costs.common.CommanderAdditionalCost;
|
||||
import mage.abilities.costs.mana.ManaCost;
|
||||
import mage.abilities.costs.mana.ManaCosts;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
|
|
@ -1145,10 +1147,13 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
}
|
||||
}
|
||||
|
||||
// warning, if you change code here then fix it in activateAbility too (play commander as land)
|
||||
|
||||
//20091005 - 305.1
|
||||
if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.PLAY_LAND, card.getId(), card.getId(), playerId, activationStatus.getPermittingObject()))) {
|
||||
// int bookmark = game.bookmarkState();
|
||||
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.PLAY_LAND, card.getId(), card.getId(), playerId, activationStatus.getPermittingObject()));
|
||||
|
||||
if (moveCards(card, Zone.BATTLEFIELD, playLandAbility, game, false, false, false, null)) {
|
||||
landsPlayed++;
|
||||
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.LAND_PLAYED, card.getId(), card.getId(), playerId, activationStatus.getPermittingObject()));
|
||||
|
|
@ -1252,10 +1257,60 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
pass(game);
|
||||
return true;
|
||||
}
|
||||
if (ability instanceof PlayLandAbility) {
|
||||
Card card = game.getCard(ability.getSourceId());
|
||||
|
||||
Card card = game.getCard(ability.getSourceId());
|
||||
if (ability instanceof PlayLandAsCommanderAbility) {
|
||||
// LAND as commander:
|
||||
// * first time - play without cost as land
|
||||
// * second+ times -- cast as spell with cost and stack
|
||||
|
||||
// code from playLand
|
||||
|
||||
ActivationStatus activationStatus = ability.canActivate(this.playerId, game);
|
||||
if (!activationStatus.canActivate() || !this.canPlayLand()) {
|
||||
return false;
|
||||
}
|
||||
if (card == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// workaround to find out empty pay in commander land
|
||||
boolean isEmptyPay = true;
|
||||
Costs<Cost> costs = ability.getCosts().copy();
|
||||
for (Cost cost : costs) {
|
||||
if (!(cost instanceof CommanderAdditionalCost) || !((CommanderAdditionalCost) cost).isEmptyPay(ability, game)) {
|
||||
isEmptyPay = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (isEmptyPay) {
|
||||
// play as land
|
||||
result = playLand(card, game, false);
|
||||
} else {
|
||||
// cast as spell with cost, but with all land's restrictions and events like Damping Engine
|
||||
// look at code in playLand
|
||||
if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.PLAY_LAND, card.getId(), card.getId(), playerId, activationStatus.getPermittingObject()))) {
|
||||
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.PLAY_LAND, card.getId(), card.getId(), playerId, activationStatus.getPermittingObject()));
|
||||
|
||||
SpellAbility spellAbility = new SpellAbility(null, card.getName(), game.getState().getZone(card.getId()));
|
||||
spellAbility.addCost(costs);
|
||||
spellAbility.setControllerId(this.getId());
|
||||
spellAbility.setSourceId(card.getId());
|
||||
result = cast(spellAbility, game, false, activationStatus.getPermittingObject());
|
||||
|
||||
if (result) {
|
||||
landsPlayed++;
|
||||
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.LAND_PLAYED, card.getId(), card.getId(), playerId, activationStatus.getPermittingObject()));
|
||||
}
|
||||
} else {
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
} else if (ability instanceof PlayLandAbility) {
|
||||
// LAND as normal card: without cost and stack
|
||||
result = playLand(card, game, false);
|
||||
} else {
|
||||
// ABILITY
|
||||
ActivationStatus activationStatus = ability.canActivate(this.playerId, game);
|
||||
if (!activationStatus.canActivate()) {
|
||||
return false;
|
||||
|
|
@ -3030,6 +3085,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
for (ConditionalMana conditionalMana : manaPool.getConditionalMana()) {
|
||||
availableMana.addMana(conditionalMana);
|
||||
}
|
||||
|
||||
if (hidden) {
|
||||
for (Card card : hand.getUniqueCards(game)) {
|
||||
for (Ability ability : card.getAbilities(game)) { // gets this activated ability from hand? (Morph?)
|
||||
|
|
@ -3058,6 +3114,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (Card card : graveyard.getUniqueCards(game)) {
|
||||
// Handle split cards in graveyard to support Aftermath
|
||||
if (card instanceof SplitCard) {
|
||||
|
|
@ -3074,6 +3131,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
getOtherUseableActivatedAbilities(card, Zone.GRAVEYARD, game, useable);
|
||||
playable.addAll(useable.values());
|
||||
}
|
||||
|
||||
for (ExileZone exile : game.getExile().getExileZones()) {
|
||||
for (Card card : exile.getCards(game)) {
|
||||
if (null != game.getContinuousEffects().asThough(card.getId(), AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, null, this.getId(), game)) {
|
||||
|
|
@ -3091,7 +3149,8 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
}
|
||||
}
|
||||
}
|
||||
// Check to play revealed cards
|
||||
|
||||
// check to play revealed cards
|
||||
for (Cards cards : game.getState().getRevealed().values()) {
|
||||
for (Card card : cards.getCards(game)) {
|
||||
if (null != game.getContinuousEffects().asThough(card.getId(), AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, null, this.getId(), game)) {
|
||||
|
|
@ -3103,6 +3162,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check if it's possible to play the top card of a library
|
||||
for (UUID playerInRangeId : game.getState().getPlayersInRange(getId(), game)) {
|
||||
Player player = game.getPlayer(playerInRangeId);
|
||||
|
|
@ -3119,6 +3179,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// eliminate duplicate activated abilities
|
||||
Map<String, Ability> playableActivated = new HashMap<>();
|
||||
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(playerId)) {
|
||||
|
|
@ -3127,6 +3188,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
playableActivated.putIfAbsent(ability.toString(), ability);
|
||||
}
|
||||
}
|
||||
|
||||
// activated abilities from stack objects
|
||||
for (StackObject stackObject : game.getState().getStack()) {
|
||||
for (ActivatedAbility ability : stackObject.getAbilities().getActivatedAbilities(Zone.STACK)) {
|
||||
|
|
@ -3136,15 +3198,16 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
|
||||
}
|
||||
}
|
||||
|
||||
// activated abilities from objects in the command zone (emblems or commanders)
|
||||
for (CommandObject commandObject : game.getState().getCommand()) {
|
||||
for (ActivatedAbility ability : commandObject.getAbilities().getActivatedAbilities(Zone.COMMAND)) {
|
||||
if (ability.isControlledBy(getId()) && canPlay(ability, availableMana, game.getObject(ability.getSourceId()), game)) {
|
||||
playableActivated.put(ability.toString(), ability);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
playable.addAll(playableActivated.values());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,5 @@
|
|||
|
||||
package mage.watchers.common;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
import mage.cards.Card;
|
||||
import mage.constants.WatcherScope;
|
||||
|
|
@ -15,6 +11,10 @@ import mage.game.permanent.Permanent;
|
|||
import mage.players.Player;
|
||||
import mage.watchers.Watcher;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/* 20130711
|
||||
*903.14a A player that's been dealt 21 or more combat damage by the same commander
|
||||
* over the course of the game loses the game. (This is a state-based action. See rule 704.)
|
||||
|
|
@ -79,11 +79,13 @@ public class CommanderInfoWatcher extends Watcher {
|
|||
if (object != null) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("<b>Commander</b>");
|
||||
Integer castCount = (Integer) game.getState().getValue(sourceId + "_castCount");
|
||||
if (castCount != null) {
|
||||
sb.append(' ').append(castCount).append(castCount == 1 ? " time" : " times").append(" casted from the command zone.");
|
||||
CommanderPlaysCountWatcher watcher = game.getState().getWatcher(CommanderPlaysCountWatcher.class);
|
||||
int playsCount = watcher.getPlaysCount(sourceId);
|
||||
if (playsCount > 0) {
|
||||
sb.append(' ').append(playsCount).append(playsCount == 1 ? " time" : " times").append(" played from the command zone.");
|
||||
}
|
||||
this.addInfo(object, "Commander", sb.toString(), game);
|
||||
|
||||
if (checkCommanderDamage) {
|
||||
for (Map.Entry<UUID, Integer> entry : damageToPlayer.entrySet()) {
|
||||
Player damagedPlayer = game.getPlayer(entry.getKey());
|
||||
|
|
|
|||
|
|
@ -0,0 +1,62 @@
|
|||
package mage.watchers.common;
|
||||
|
||||
import mage.constants.WatcherScope;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.GameEvent.EventType;
|
||||
import mage.players.Player;
|
||||
import mage.watchers.Watcher;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Calcs commanders play count (spell or land)
|
||||
*
|
||||
* @author JayDi85
|
||||
*/
|
||||
public class CommanderPlaysCountWatcher extends Watcher {
|
||||
|
||||
private final Map<UUID, Integer> playsCount = new HashMap<>();
|
||||
|
||||
public CommanderPlaysCountWatcher() {
|
||||
super(WatcherScope.GAME);
|
||||
}
|
||||
|
||||
public CommanderPlaysCountWatcher(final CommanderPlaysCountWatcher watcher) {
|
||||
super(watcher);
|
||||
this.playsCount.putAll(watcher.playsCount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommanderPlaysCountWatcher copy() {
|
||||
return new CommanderPlaysCountWatcher(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void watch(GameEvent event, Game game) {
|
||||
if (event.getType() != EventType.LAND_PLAYED && event.getType() != EventType.SPELL_CAST) {
|
||||
return;
|
||||
}
|
||||
|
||||
UUID possibleCommanderId = event.getSourceId();
|
||||
boolean isCommanderObject = false;
|
||||
for (Player player : game.getPlayers().values()) {
|
||||
if (player.getCommandersIds().contains(possibleCommanderId)) {
|
||||
isCommanderObject = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isCommanderObject) {
|
||||
int count = playsCount.getOrDefault(possibleCommanderId, 0);
|
||||
count++;
|
||||
playsCount.put(possibleCommanderId, count);
|
||||
}
|
||||
}
|
||||
|
||||
public int getPlaysCount(UUID commanderId) {
|
||||
return this.playsCount.getOrDefault(commanderId, 0);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue