mirror of
https://github.com/correl/mage.git
synced 2025-03-26 17:00:08 -09:00
* 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.
This commit is contained in:
parent
2307e851db
commit
aad8edd8cc
7 changed files with 128 additions and 57 deletions
Mage.Common/src/mage/view
Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck
Mage/src/mage
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue