From aad8edd8cc9297a71453b4af76f84a58ca362e16 Mon Sep 17 00:00:00 2001 From: LevelX2 <ludwig.hirth@online.de> 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 9648daba66..1211594b2e 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 b104d9a496..46e012b374 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 6737969264..b843c76823 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 d425a8bf31..471ccaedf2 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<String> 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<String, Integer> 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<String, Integer> 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 accb5d52c2..19541ff2ee 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<UUID, Cards> mulliganedCards = new HashMap<>(); - private final Set<CommanderCombatDamageWatcher> commanderCombatWatcher = new HashSet<>(); + private final Set<CommanderInfoWatcher> 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<UUID, Integer> 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 809d7fb7d2..095d9f0141 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<Card> 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<Card> 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<UUID> getOpponents(UUID playerId) { Set<UUID> 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 f0a0f5c9ae..eccce0af19 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<UUID, Integer> damageToPlayer = new HashMap<UUID, Integer>(); +public class CommanderInfoWatcher extends Watcher { - public CommanderCombatDamageWatcher(UUID commander) { + public Map<UUID, Integer> 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("<b>Commander</b>"); 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<UUID, Integer> entry : damageToPlayer.entrySet()) { - Player damagedPlayer = game.getPlayer(entry.getKey()); - sb.setLength(0); - sb.append("<b>Commander</b> 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<UUID, Integer> entry : damageToPlayer.entrySet()) { + Player damagedPlayer = game.getPlayer(entry.getKey()); + sb.setLength(0); + sb.append("<b>Commander</b> 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); } }