Cards compatibility with oathbreaker format;

This commit is contained in:
Oleg Agafonov 2019-05-27 17:21:17 +04:00
parent e1259d0dd6
commit 913ee65f36
22 changed files with 99 additions and 46 deletions

View file

@ -8,6 +8,7 @@ import mage.abilities.condition.common.OathbreakerOnBattlefieldCondition;
import mage.abilities.effects.common.InfoEffect;
import mage.abilities.hint.ConditionHint;
import mage.cards.Card;
import mage.constants.CommanderCardType;
import mage.constants.MultiplayerAttackOption;
import mage.constants.RangeOfInfluence;
import mage.game.match.MatchType;
@ -138,4 +139,33 @@ public class OathbreakerFreeForAll extends GameCommanderImpl {
public OathbreakerFreeForAll copy() {
return new OathbreakerFreeForAll(this);
}
@Override
public Set<UUID> getCommandersIds(Player player, CommanderCardType commanderCardType) {
Set<UUID> res = new HashSet<>();
if (player != null) {
List<UUID> commanders = this.playerCommanders.getOrDefault(player.getId(), new ArrayList<>());
UUID spell = this.playerSignatureSpell.getOrDefault(player.getId(), null);
for (UUID id : player.getCommandersIds()) {
switch (commanderCardType) {
case ANY:
res.add(id);
break;
case COMMANDER_OR_OATHBREAKER:
if (commanders.contains(id)) {
res.add(id);
}
break;
case SIGNATURE_SPELL:
if (id.equals(spell)) {
res.add(id);
}
break;
default:
throw new IllegalStateException("Unknown commander type " + commanderCardType);
}
}
}
return res;
}
}

View file

@ -93,7 +93,7 @@ class ConspyEffect extends ContinuousEffectImpl {
}
}
// commander in command zone
for (UUID commanderId : controller.getCommandersIds()) {
for (UUID commanderId : game.getCommandersIds(controller)) {
if (game.getState().getZone(commanderId) == Zone.COMMAND) {
Card card = game.getCard(commanderId);
if (card != null && card.isCreature() && !card.hasSubtype(subType, game)) {

View file

@ -1,9 +1,5 @@
package mage.cards.c;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.SacrificeSourceCost;
@ -14,19 +10,23 @@ import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.CommanderCardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
/**
*
* @author emerald000
*/
public final class CommandBeacon extends CardImpl {
public CommandBeacon(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.LAND},"");
super(ownerId, setInfo, new CardType[]{CardType.LAND}, "");
// {T}: Add {C}.
this.addAbility(new ColorlessManaAbility());
@ -67,7 +67,7 @@ class CommandBeaconEffect extends OneShotEffect {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
List<Card> commandersInCommandZone = new ArrayList<>(1);
for (UUID commanderId : controller.getCommandersIds()) {
for (UUID commanderId : game.getCommandersIds(controller, CommanderCardType.COMMANDER_OR_OATHBREAKER)) {
Card commander = game.getCard(commanderId);
if (commander != null && game.getState().getZone(commander.getId()) == Zone.COMMAND) {
commandersInCommandZone.add(commander);
@ -75,14 +75,12 @@ class CommandBeaconEffect extends OneShotEffect {
}
if (commandersInCommandZone.size() == 1) {
controller.moveCards(commandersInCommandZone.get(0), Zone.HAND, source, game);
}
else if (commandersInCommandZone.size() == 2) {
} else if (commandersInCommandZone.size() == 2) {
Card firstCommander = commandersInCommandZone.get(0);
Card secondCommander = commandersInCommandZone.get(1);
if (controller.chooseUse(Outcome.ReturnToHand, "Return which commander to hand?", null, firstCommander.getName(), secondCommander.getName(), source, game)) {
controller.moveCards(firstCommander, Zone.HAND, source, game);
}
else {
} else {
controller.moveCards(secondCommander, Zone.HAND, source, game);
}
}

View file

@ -95,7 +95,7 @@ class ConspiracyEffect extends ContinuousEffectImpl {
}
}
// commander in command zone
for (UUID commanderId : controller.getCommandersIds()) {
for (UUID commanderId : game.getCommandersIds(controller)) {
if (game.getState().getZone(commanderId) == Zone.COMMAND) {
Card card = game.getCard(commanderId);
if (card != null && card.isCreature()) {

View file

@ -109,8 +109,9 @@ class KarnLiberatedEffect extends OneShotEffect {
if (card.isOwnedBy(player.getId()) && !card.isCopy() // no copies
&& !player.getSideboard().contains(card.getId())
&& !cards.contains(card)) { // not the exiled cards
if (player.getCommandersIds().contains(card.getId())) {
game.addCommander(new Commander(card));
if (game.getCommandersIds(player).contains(card.getId())) {
game.addCommander(new Commander(card)); // TODO: check restart and init
// no needs in initCommander call -- it's uses on game startup (init)
game.setZone(card.getId(), Zone.COMMAND);
} else {
player.getLibrary().putOnTop(card, game);

View file

@ -95,7 +95,7 @@ class MythUnboundCostReductionEffect extends CostModificationEffectImpl {
if (abilityToModify instanceof SpellAbility || abilityToModify instanceof PlayLandAbility) {
if (abilityToModify.isControlledBy(source.getControllerId())) {
return player.getCommandersIds().contains(abilityToModify.getSourceId());
return game.getCommandersIds(player).contains(abilityToModify.getSourceId());
}
}
return false;

View file

@ -93,7 +93,7 @@ class OpalPalaceWatcher extends Watcher {
for (UUID playerId : game.getPlayerList()) {
Player player = game.getPlayer(playerId);
if (player != null) {
if (player.getCommandersIds().contains(card.getId())) {
if (game.getCommandersIds(player).contains(card.getId())) {
commanderId.add(card.getId());
break;
}

View file

@ -1,7 +1,5 @@
package mage.cards.p;
import java.util.Iterator;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
@ -22,8 +20,11 @@ import mage.game.permanent.Permanent;
import mage.game.stack.Spell;
import mage.players.Player;
import java.util.Iterator;
import java.util.Set;
import java.util.UUID;
/**
*
* @author TheElk801
*/
public final class PathOfAncestry extends CardImpl {
@ -88,9 +89,10 @@ class PathOfAncestryTriggeredAbility extends TriggeredAbilityImpl {
Spell spell = game.getStack().getSpell(event.getTargetId());
if (spell != null && spell.isCreature()) {
Player controller = game.getPlayer(getControllerId());
if (controller != null && controller.getCommandersIds() != null && !controller.getCommandersIds().isEmpty()) {
Set<UUID> commanders = game.getCommandersIds(controller);
if (controller != null && commanders != null && !commanders.isEmpty()) {
if (spell.getAbilities().contains(ChangelingAbility.getInstance())) {
for (UUID cmdr : controller.getCommandersIds()) {
for (UUID cmdr : commanders) {
MageObject commander = game.getObject(cmdr);
if (commander != null) {
if (commander.getAbilities().contains(ChangelingAbility.getInstance())) {
@ -110,7 +112,7 @@ class PathOfAncestryTriggeredAbility extends TriggeredAbilityImpl {
while (spellSubs.hasNext()) {
SubType sType = spellSubs.next();
if (sType.getSubTypeSet() == SubTypeSet.CreatureType) {
for (UUID cmdr : controller.getCommandersIds()) {
for (UUID cmdr : commanders) {
MageObject commander = game.getObject(cmdr);
if (commander != null && (commander.hasSubtype(sType, game) || commander.getAbilities().contains(ChangelingAbility.getInstance()))) {
return true;

View file

@ -99,7 +99,7 @@ class TeferiMageOfZhalfirAddFlashEffect extends ContinuousEffectImpl {
}
}
// commander in command zone
for (UUID commanderId : controller.getCommandersIds()) {
for (UUID commanderId : game.getCommandersIds(controller)) {
if (game.getState().getZone(commanderId) == Zone.COMMAND) {
Card card = game.getCard(commanderId);
if (card != null && card.isCreature()) {

View file

@ -750,7 +750,7 @@ public class TestPlayer implements Player {
// show command
if (params[0].equals(SHOW_COMMAND_COMMAND) && params.length == 1) {
printStart(action.getActionName());
CardsImpl cards = new CardsImpl(computerPlayer.getCommandersIds());
CardsImpl cards = new CardsImpl(game.getCommandersIds(computerPlayer));
printCards(cards.getCards(game));
printEnd();
actions.remove(action);

View file

@ -1,8 +1,8 @@
package mage.abilities.condition.common;
import mage.abilities.Ability;
import mage.abilities.condition.Condition;
import mage.constants.CommanderCardType;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
@ -22,7 +22,7 @@ public enum CommanderInPlayCondition implements Condition {
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
for (UUID commanderId : controller.getCommandersIds()) {
for (UUID commanderId : game.getCommandersIds(controller, CommanderCardType.COMMANDER_OR_OATHBREAKER)) {
Permanent commander = game.getPermanent(commanderId);
if (commander != null && commander.isControlledBy(source.getControllerId())) {
return true;

View file

@ -5,6 +5,7 @@ import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.constants.CommanderCardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
@ -83,7 +84,7 @@ class CommanderStormEffect extends OneShotEffect {
if (player == null) {
return false;
}
stormCount = player.getCommandersIds().stream()
stormCount = game.getCommandersIds(player, CommanderCardType.COMMANDER_OR_OATHBREAKER).stream()
.map((commanderId) -> game.getState().getWatcher(CommanderPlaysCountWatcher.class).getPlaysCount(commanderId))
.reduce(stormCount, Integer::sum);
if (stormCount == 0) {

View file

@ -1,6 +1,5 @@
package mage.abilities.keyword;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.ActivatedAbilityImpl;
import mage.abilities.costs.Cost;
@ -21,24 +20,25 @@ import mage.players.Player;
import mage.target.common.TargetControlledCreaturePermanent;
import mage.target.common.TargetControlledPermanent;
import java.util.UUID;
/**
* 702.47. Ninjutsu
*
* <p>
* 702.47a Ninjutsu is an activated ability that functions only while the card
* with ninjutsu is in a player's hand. "Ninjutsu [cost]" means "[Cost], Reveal
* this card from your hand, Return an unblocked attacking creature you control
* to its owner's hand: Put this card onto the battlefield from your hand tapped
* and attacking."
*
* <p>
* 702.47b The card with ninjutsu remains revealed from the time the ability is
* announced until the ability leaves the stack.
*
* <p>
* 702.47c A ninjutsu ability may be activated only while a creature on the
* battlefield is unblocked (see rule 509.1h). The creature with ninjutsu is put
* onto the battlefield unblocked. It will be attacking the same player or
* planeswalker as the creature that was returned to its owner's hand.
*
*
* @author LevelX2
*/
public class NinjutsuAbility extends ActivatedAbilityImpl {
@ -51,7 +51,6 @@ public class NinjutsuAbility extends ActivatedAbilityImpl {
}
/**
*
* @param manaCost ninjutsu mana cost
*/
public NinjutsuAbility(ManaCost manaCost) {
@ -195,7 +194,7 @@ class RevealNinjutsuCardCost extends CostImpl {
Card card = player.getHand().get(ability.getSourceId(), game);
if (card == null && commander
&& player.getCommandersIds().contains(ability.getSourceId())) {
&& game.getCommandersIds(player).contains(ability.getSourceId())) {
for (CommandObject coj : game.getState().getCommand()) {
if (coj != null && coj.getId().equals(ability.getSourceId())) {
card = game.getCard(ability.getSourceId());

View file

@ -1,8 +1,5 @@
package mage.abilities.mana;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import mage.Mana;
import mage.abilities.Ability;
import mage.abilities.costs.Cost;
@ -17,8 +14,11 @@ import mage.filter.FilterMana;
import mage.game.Game;
import mage.players.Player;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
/**
*
* @author LevelX2
*/
public class CommanderColorIdentityManaAbility extends ActivatedManaAbilityImpl {
@ -46,7 +46,7 @@ public class CommanderColorIdentityManaAbility extends ActivatedManaAbilityImpl
if (netMana.isEmpty() && game != null) {
Player controller = game.getPlayer(getControllerId());
if (controller != null) {
for (UUID commanderId : controller.getCommandersIds()) {
for (UUID commanderId : game.getCommandersIds(controller)) {
Card commander = game.getCard(commanderId);
if (commander != null) {
FilterMana commanderMana = commander.getColorIdentity();
@ -114,7 +114,7 @@ class CommanderIdentityManaEffect extends ManaEffect {
if (controller != null) {
Choice choice = new ChoiceImpl();
choice.setMessage("Pick a mana color");
for (UUID commanderId : controller.getCommandersIds()) {
for (UUID commanderId : game.getCommandersIds(controller)) {
Card commander = game.getCard(commanderId);
if (commander != null) {
FilterMana commanderMana = commander.getColorIdentity();

View file

@ -0,0 +1,10 @@
package mage.constants;
/**
* @author JayDi85
*/
public enum CommanderCardType {
ANY,
COMMANDER_OR_OATHBREAKER,
SIGNATURE_SPELL
}

View file

@ -20,7 +20,7 @@ public enum CommanderPredicate implements Predicate<Permanent> {
public boolean apply(Permanent input, Game game) {
Player owner = game.getPlayer(input.getOwnerId());
return owner != null
&& owner.getCommandersIds().contains(input.getId());
&& game.getCommandersIds(owner).contains(input.getId());
}
@Override

View file

@ -476,4 +476,9 @@ public interface Game extends MageItem, Serializable {
Mulligan getMulligan();
Set<UUID> getCommandersIds(Player player, CommanderCardType commanderCardType);
default Set<UUID> getCommandersIds(Player player) {
return getCommandersIds(player, CommanderCardType.ANY);
}
}

View file

@ -59,7 +59,7 @@ public abstract class GameCommanderImpl extends GameImpl {
}
// init commanders
for (UUID commanderId : player.getCommandersIds()) {
for (UUID commanderId : this.getCommandersIds(player)) {
Card commander = this.getCard(commanderId);
if (commander != null) {
initCommander(commander, player);
@ -183,7 +183,7 @@ public abstract class GameCommanderImpl extends GameImpl {
@Override
protected boolean checkStateBasedActions() {
for (Player player : getPlayers().values()) {
for (UUID commanderId : player.getCommandersIds()) {
for (UUID commanderId : this.getCommandersIds(player)) {
CommanderInfoWatcher damageWatcher = getState().getWatcher(CommanderInfoWatcher.class, commanderId);
if (damageWatcher == null) {
continue;

View file

@ -3193,4 +3193,9 @@ public abstract class GameImpl implements Game, Serializable {
return mulligan;
}
@Override
public Set<UUID> getCommandersIds(Player player, CommanderCardType commanderCardType) {
return player.getCommandersIds();
}
}

View file

@ -696,9 +696,11 @@ public interface Player extends MageItem, Copyable<Player> {
/**
* Get the commanderIds of the player
* Deprecated, use game.getCommandersIds(xxx) instead
*
* @return
*/
@Deprecated
Set<UUID> getCommandersIds();
/**

View file

@ -302,7 +302,7 @@ public abstract class PlayerImpl implements Player, Serializable {
this.sideboard = player.getSideboard().copy();
this.hand = player.getHand().copy();
this.graveyard = player.getGraveyard().copy();
this.commandersIds = player.getCommandersIds();
this.commandersIds = new HashSet<>(player.getCommandersIds());
this.abilities = player.getAbilities().copy();
this.counters = player.getCounters().copy();

View file

@ -43,7 +43,7 @@ public class CommanderPlaysCountWatcher extends Watcher {
UUID possibleCommanderId = event.getSourceId();
boolean isCommanderObject = false;
for (Player player : game.getPlayers().values()) {
if (player.getCommandersIds().contains(possibleCommanderId)) {
if (game.getCommandersIds(player).contains(possibleCommanderId)) {
isCommanderObject = true;
break;
}