From aad8edd8cc9297a71453b4af76f84a58ca362e16 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Thu, 12 Mar 2015 01:11:31 +0100 Subject: [PATCH] * Tiny Leader - The commander cast X times is shown now, you can use deck name "Sultai" as default commander for UBG, check that the commander card can't be again in the deck or sideboard, sideboard can also be empty now, sideboard may not include the commander. --- Mage.Common/src/mage/view/CardView.java | 2 +- Mage.Common/src/mage/view/CommanderView.java | 12 +- Mage.Common/src/mage/view/PlayerView.java | 2 +- .../src/mage/deck/TinyLeaders.java | 19 ++-- Mage/src/mage/game/GameCommanderImpl.java | 8 +- Mage/src/mage/game/GameTinyLeadersImpl.java | 104 +++++++++++++++--- ...Watcher.java => CommanderInfoWatcher.java} | 38 ++++--- 7 files changed, 128 insertions(+), 57 deletions(-) rename Mage/src/mage/watchers/common/{CommanderCombatDamageWatcher.java => CommanderInfoWatcher.java} (75%) diff --git a/Mage.Common/src/mage/view/CardView.java b/Mage.Common/src/mage/view/CardView.java index 9648daba66d..1211594b2e1 100644 --- a/Mage.Common/src/mage/view/CardView.java +++ b/Mage.Common/src/mage/view/CardView.java @@ -134,7 +134,7 @@ public class CardView extends SimpleCardView { * * @param card * @param game - * @param cardId + * @param cardId not used? * @param controlled is the card view created for the card controller - used for morph / face down cards to know which player may see information for the card */ public CardView(Card card, Game game, UUID cardId, boolean controlled) { diff --git a/Mage.Common/src/mage/view/CommanderView.java b/Mage.Common/src/mage/view/CommanderView.java index b104d9a4962..46e012b374c 100644 --- a/Mage.Common/src/mage/view/CommanderView.java +++ b/Mage.Common/src/mage/view/CommanderView.java @@ -27,22 +27,20 @@ */ package mage.view; +import java.io.Serializable; import mage.cards.Card; import mage.constants.MageObjectType; +import mage.game.Game; import mage.game.command.Commander; -import java.io.Serializable; - /** * * @author Plopman */ public class CommanderView extends CardView implements CommandObjectView, Serializable{ - public CommanderView(Commander commander, Card sourceCard) { - super(sourceCard); + public CommanderView(Commander commander, Card sourceCard, Game game) { + super(sourceCard, game, null, false); this.mageObjectType = MageObjectType.COMMANDER; - } - - + } } diff --git a/Mage.Common/src/mage/view/PlayerView.java b/Mage.Common/src/mage/view/PlayerView.java index 67379692644..b843c768231 100644 --- a/Mage.Common/src/mage/view/PlayerView.java +++ b/Mage.Common/src/mage/view/PlayerView.java @@ -132,7 +132,7 @@ public class PlayerView implements Serializable { if(commander.getControllerId().equals(this.playerId)){ Card sourceCard = game.getCard(commander.getSourceId()); if(sourceCard != null){ - commandList.add(new CommanderView(commander, sourceCard)); + commandList.add(new CommanderView(commander, sourceCard, game)); } } } diff --git a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/TinyLeaders.java b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/TinyLeaders.java index d425a8bf318..471ccaedf2f 100644 --- a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/TinyLeaders.java +++ b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/TinyLeaders.java @@ -38,6 +38,7 @@ import mage.cards.decks.Deck; import mage.cards.decks.DeckValidator; import mage.constants.CardType; import mage.filter.FilterMana; +import mage.game.GameTinyLeadersImpl; import mage.util.CardUtil; /** @@ -121,6 +122,7 @@ public class TinyLeaders extends DeckValidator { List basicLandNames = new ArrayList<>(Arrays.asList("Forest", "Island", "Mountain", "Swamp", "Plains", "Snow-Covered Forest", "Snow-Covered Island", "Snow-Covered Mountain", "Snow-Covered Swamp", "Snow-Covered Plains")); Map counts = new HashMap<>(); + counts.put(deck.getName(), 1); // add the commander to the counts, so it can't be in the deck or sideboard again countCards(counts, deck.getCards()); countCards(counts, deck.getSideboard()); for (Map.Entry entry : counts.entrySet()) { @@ -139,15 +141,8 @@ public class TinyLeaders extends DeckValidator { } } - if (deck.getSideboard().size() <= 11) { - Card commander = null; - - for (Card card : deck.getSideboard()) { - if (card.getName().equalsIgnoreCase(deck.getName())) { - commander = card; - } - } - + if (deck.getSideboard().size() <= 10) { + Card commander = GameTinyLeadersImpl.getCommanderCard(deck.getName(), null); /** * 905.5b - Each card must have a converted mana cost of three of less. * Cards with {X} in their mana cost count X as zero. @@ -156,10 +151,10 @@ public class TinyLeaders extends DeckValidator { if (commander == null || commander.getManaCost().convertedManaCost() > 3) { if (commander == null) { - invalid.put("Leader", "Please be sure to set your leader in the NAME field in the DECK EDITOR"); + invalid.put("Leader", "Please be sure to set your leader in the NAME field in the DECK EDITOR (use the names Mardu, Sultai or Jeskai as default Commanders)"); } if (commander != null && commander.getManaCost().convertedManaCost() > 3) { - invalid.put("Leader", "Commander CMC is Greater than 3"); + invalid.put("Leader", "Commanders converted mana cost is greater than 3"); } return false; } @@ -188,7 +183,7 @@ public class TinyLeaders extends DeckValidator { valid = false; } } else { - invalid.put("Commander", "Sideboard must contain only the commander and a maximum of 10 sideboard cards"); + invalid.put("Commander", "Sideboard must contain only a maximum of 10 sideboard cards (the Tiny Leader name must be written to the deck name)"); valid = false; } diff --git a/Mage/src/mage/game/GameCommanderImpl.java b/Mage/src/mage/game/GameCommanderImpl.java index accb5d52c2b..19541ff2ee0 100644 --- a/Mage/src/mage/game/GameCommanderImpl.java +++ b/Mage/src/mage/game/GameCommanderImpl.java @@ -52,12 +52,12 @@ import mage.game.turn.TurnMod; import mage.players.Player; import mage.target.common.TargetCardInHand; import mage.util.CardUtil; -import mage.watchers.common.CommanderCombatDamageWatcher; +import mage.watchers.common.CommanderInfoWatcher; public abstract class GameCommanderImpl extends GameImpl { private final Map mulliganedCards = new HashMap<>(); - private final Set commanderCombatWatcher = new HashSet<>(); + private final Set commanderCombatWatcher = new HashSet<>(); protected boolean alsoLibrary; // replace also commander going to library protected boolean startingPlayerSkipsDraw = true; @@ -88,7 +88,7 @@ public abstract class GameCommanderImpl extends GameImpl { ability.addEffect(new CommanderCostModification(commander.getId())); ability.addEffect(new CommanderManaReplacementEffect(player.getId(), CardUtil.getColorIdentity(commander))); getState().setValue(commander.getId() + "_castCount", 0); - CommanderCombatDamageWatcher watcher = new CommanderCombatDamageWatcher(commander.getId()); + CommanderInfoWatcher watcher = new CommanderInfoWatcher(commander.getId(), true); getState().getWatchers().add(watcher); this.commanderCombatWatcher.add(watcher); watcher.addCardInfoToCommander(this); @@ -182,7 +182,7 @@ public abstract class GameCommanderImpl extends GameImpl { */ @Override protected boolean checkStateBasedActions() { - for (CommanderCombatDamageWatcher damageWatcher: commanderCombatWatcher) { + for (CommanderInfoWatcher damageWatcher: commanderCombatWatcher) { for(Map.Entry entrySet : damageWatcher.getDamageToPlayer().entrySet()){ if (entrySet.getValue() > 20) { Player player = getPlayer(entrySet.getKey()); diff --git a/Mage/src/mage/game/GameTinyLeadersImpl.java b/Mage/src/mage/game/GameTinyLeadersImpl.java index 809d7fb7d24..095d9f0141d 100644 --- a/Mage/src/mage/game/GameTinyLeadersImpl.java +++ b/Mage/src/mage/game/GameTinyLeadersImpl.java @@ -31,6 +31,7 @@ package mage.game; import java.util.HashSet; import java.util.Set; import java.util.UUID; +import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.common.InfoEffect; @@ -38,15 +39,19 @@ import mage.abilities.effects.common.continuous.CommanderManaReplacementEffect; 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.repository.CardInfo; import mage.cards.repository.CardRepository; +import mage.constants.CardType; import mage.constants.MultiplayerAttackOption; import mage.constants.PhaseStep; import mage.constants.RangeOfInfluence; +import mage.constants.Rarity; import mage.constants.Zone; import mage.game.turn.TurnMod; import mage.players.Player; import mage.util.CardUtil; +import mage.watchers.common.CommanderInfoWatcher; /** * @@ -74,22 +79,22 @@ public abstract class GameTinyLeadersImpl extends GameImpl{ for (UUID playerId: state.getPlayerList(startingPlayerId)) { Player player = getPlayer(playerId); if (player != null){ - if (player.getSideboard().size() > 0){ - CardInfo cardInfo = CardRepository.instance.findCard(player.getMatchPlayer().getDeck().getName()); - if (cardInfo != null) { - Card commander = cardInfo.getCard(); - Set cards = new HashSet<>(); - cards.add(commander); - this.loadCards(cards, playerId); - if (commander != null) { - player.setCommanderId(commander.getId()); - commander.moveToZone(Zone.COMMAND, null, this, true); - ability.addEffect(new CommanderReplacementEffect(commander.getId(), alsoLibrary)); - ability.addEffect(new CommanderCostModification(commander.getId())); - ability.addEffect(new CommanderManaReplacementEffect(player.getId(), CardUtil.getColorIdentity(commander))); - getState().setValue(commander.getId() + "_castCount", 0); - } - } + Card commander = getCommanderCard(player.getMatchPlayer().getDeck().getName(), player.getId()); + if (commander != null) { + Set cards = new HashSet<>(); + cards.add(commander); + this.loadCards(cards, playerId); + player.setCommanderId(commander.getId()); + commander.moveToZone(Zone.COMMAND, null, this, true); + ability.addEffect(new CommanderReplacementEffect(commander.getId(), alsoLibrary)); + ability.addEffect(new CommanderCostModification(commander.getId())); + ability.addEffect(new CommanderManaReplacementEffect(player.getId(), CardUtil.getColorIdentity(commander))); + getState().setValue(commander.getId() + "_castCount", 0); + CommanderInfoWatcher watcher = new CommanderInfoWatcher(commander.getId(), false); + getState().getWatchers().add(watcher); + watcher.addCardInfoToCommander(this); + } else { + throw new UnknownError("Commander card could not be created"); } } @@ -101,6 +106,34 @@ public abstract class GameTinyLeadersImpl extends GameImpl{ } } + /** + * Name of Tiny Leader comes from the deck name (it's not in the sideboard) + * Additionally, it was taken into account that WOTC had missed a few color combinations + * when making Legendary Creatures at 3 CMC. There are three Commanders available to use + * for the missing color identities: + * Mardu [WBR 2/2], + * Sultai [UBG 2/2], and + * Jeskai [WUR 2/2]. + * + * @param commanderName + * @param ownerId + * @return + */ + public static Card getCommanderCard(String commanderName, UUID ownerId) { + Card commander = null; + switch (commanderName) { + case "Sultai": + commander = new DefaultCommander(ownerId, commanderName, "{U}{B}{G}"); + break; + default: + CardInfo cardInfo = CardRepository.instance.findCard(commanderName); + if (cardInfo != null) { + commander = cardInfo.getCard(); + } + } + return commander; + } + @Override public Set getOpponents(UUID playerId) { Set opponents = new HashSet<>(); @@ -122,3 +155,42 @@ public abstract class GameTinyLeadersImpl extends GameImpl{ } } + +class DefaultCommander extends CardImpl { + + public DefaultCommander(UUID ownerId, String commanderName, String manaString) { + super(ownerId, 999, commanderName, Rarity.RARE, new CardType[]{CardType.CREATURE}, manaString); + this.expansionSetCode = ""; + this.supertype.add("Legendary"); + //this.subtype.add("Human"); + this.subtype.add("Soldier"); + + if (manaString.contains("{G}")) { + this.color.setGreen(true); + } + if (manaString.contains("{W}")) { + this.color.setWhite(true); + } + if (manaString.contains("{U}")) { + this.color.setBlue(true); + } + if (manaString.contains("{B}")) { + this.color.setBlack(true); + } + if (manaString.contains("{R}")) { + this.color.setRed(true); + } + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + } + + public DefaultCommander(final DefaultCommander card) { + super(card); + } + + @Override + public DefaultCommander copy() { + return new DefaultCommander(this); + } +} diff --git a/Mage/src/mage/watchers/common/CommanderCombatDamageWatcher.java b/Mage/src/mage/watchers/common/CommanderInfoWatcher.java similarity index 75% rename from Mage/src/mage/watchers/common/CommanderCombatDamageWatcher.java rename to Mage/src/mage/watchers/common/CommanderInfoWatcher.java index f0a0f5c9aee..eccce0af197 100644 --- a/Mage/src/mage/watchers/common/CommanderCombatDamageWatcher.java +++ b/Mage/src/mage/watchers/common/CommanderInfoWatcher.java @@ -48,29 +48,33 @@ import mage.watchers.Watcher; * * @author Plopman */ -public class CommanderCombatDamageWatcher extends Watcher { - public Map damageToPlayer = new HashMap(); +public class CommanderInfoWatcher extends Watcher { - public CommanderCombatDamageWatcher(UUID commander) { + public Map damageToPlayer = new HashMap<>(); + public boolean checkCommanderDamage; + + public CommanderInfoWatcher(UUID commander, boolean checkCommanderDamage) { super("CommanderCombatDamageWatcher", WatcherScope.CARD); this.sourceId = commander; + this.checkCommanderDamage = checkCommanderDamage; } - public CommanderCombatDamageWatcher(final CommanderCombatDamageWatcher watcher) { + public CommanderInfoWatcher(final CommanderInfoWatcher watcher) { super(watcher); this.damageToPlayer.putAll(watcher.damageToPlayer); + this.checkCommanderDamage = watcher.checkCommanderDamage; } @Override - public CommanderCombatDamageWatcher copy() { - return new CommanderCombatDamageWatcher(this); + public CommanderInfoWatcher copy() { + return new CommanderInfoWatcher(this); } @Override public void watch(GameEvent event, Game game) { - if (event.getType() == EventType.DAMAGED_PLAYER && event instanceof DamagedPlayerEvent) { + if (checkCommanderDamage && event.getType() == EventType.DAMAGED_PLAYER && event instanceof DamagedPlayerEvent) { if (sourceId.equals(event.getSourceId())) { DamagedPlayerEvent damageEvent = (DamagedPlayerEvent)event; if (damageEvent.isCombatDamage()) { @@ -106,22 +110,24 @@ public class CommanderCombatDamageWatcher extends Watcher { sb.append("Commander"); Integer castCount = (Integer)game.getState().getValue(sourceId + "_castCount"); if (castCount != null) { - sb.append(" ").append(castCount).append(castCount.intValue() == 1 ? " time":" times").append(" casted from the command zone."); + sb.append(" ").append(castCount).append(castCount == 1 ? " time":" times").append(" casted from the command zone."); } this.addInfo(object, "Commander",sb.toString(), game); - for (Map.Entry entry : damageToPlayer.entrySet()) { - Player damagedPlayer = game.getPlayer(entry.getKey()); - sb.setLength(0); - sb.append("Commander did ").append(entry.getValue()).append(" combat damage to player ").append(damagedPlayer.getName()).append("."); - this.addInfo(object, new StringBuilder("Commander").append(entry.getKey()).toString(),sb.toString(), game); + + if (checkCommanderDamage) { + for (Map.Entry entry : damageToPlayer.entrySet()) { + Player damagedPlayer = game.getPlayer(entry.getKey()); + sb.setLength(0); + sb.append("Commander did ").append(entry.getValue()).append(" combat damage to player ").append(damagedPlayer.getName()).append("."); + this.addInfo(object, new StringBuilder("Commander").append(entry.getKey()).toString(),sb.toString(), game); + } } } } private void addInfo(MageObject object, String key, String value, Game game) { - if (object instanceof Card) { - ((Card) object).addInfo(key, value, game); - } else if (object instanceof Permanent) { + ((Card) object).addInfo(key, value, game); + if (object instanceof Permanent) { ((Permanent) object).addInfo(key, value, game); } }