mirror of
https://github.com/correl/mage.git
synced 2024-11-28 19:19:55 +00:00
[ZNR] Improved modal double faces cards in GUI (#7012)
This commit is contained in:
parent
02e19f0a3f
commit
4893c5b1ac
11 changed files with 156 additions and 87 deletions
|
@ -204,15 +204,32 @@ public class TestCardRenderDialog extends MageDialog {
|
|||
game.addPlayer(playerOpponent, deck);
|
||||
|
||||
List<CardView> cardViews = new ArrayList<>();
|
||||
///*
|
||||
/* // test morphed
|
||||
cardViews.add(createPermanentCard(game, playerYou.getId(), "RNA", "263", 0, 0, 0, false)); // mountain
|
||||
cardViews.add(createPermanentCard(game, playerYou.getId(), "RNA", "185", 0, 0, 0, true)); // Judith, the Scourge Diva
|
||||
//*/
|
||||
cardViews.add(createHandCard(game, playerYou.getId(), "DIS", "153")); // Odds // Ends (split card)
|
||||
cardViews.add(createHandCard(game, playerYou.getId(), "ELD", "38")); // Animating Faerie (adventure card)
|
||||
cardViews.add(createFaceDownCard(game, playerOpponent.getId(), "ELD", "38", false, false, false)); // face down
|
||||
cardViews.add(createFaceDownCard(game, playerOpponent.getId(), "ELD", "38", true, false, true)); // morphed
|
||||
cardViews.add(createFaceDownCard(game, playerOpponent.getId(), "ELD", "38", false, true, false)); // manifested
|
||||
//*/
|
||||
|
||||
/* //test emblems
|
||||
cardViews.add(createPermanentCard(game, playerYou.getId(), "RNA", "78", 125, 89, 0, false)); // Noxious Groodion
|
||||
cardViews.add(createPermanentCard(game, playerYou.getId(), "RNA", "14", 3, 5, 2, false)); // Knight of Sorrows
|
||||
cardViews.add(createPermanentCard(game, playerYou.getId(), "DKA", "140", 5, 2, 2, false)); // Huntmaster of the Fells, transforms
|
||||
cardViews.add(createPermanentCard(game, playerYou.getId(), "RNA", "221", 0, 0, 0, false)); // Bedeck // Bedazzle
|
||||
cardViews.add(createPermanentCard(game, playerYou.getId(), "XLN", "234", 0, 0, 0, false)); // Conqueror's Galleon
|
||||
cardViews.add(createEmblem(new AjaniAdversaryOfTyrantsEmblem())); // Emblem Ajani
|
||||
cardViews.add(createPlane(new AkoumPlane())); // Plane - Akoum
|
||||
//*/
|
||||
|
||||
//* //test split, transform and mdf in hands
|
||||
cardViews.add(createHandCard(game, playerYou.getId(), "SOI", "97")); // Accursed Witch
|
||||
cardViews.add(createHandCard(game, playerYou.getId(), "UMA", "225")); // Fire // Ice
|
||||
cardViews.add(createHandCard(game, playerYou.getId(), "ELD", "14")); // Giant Killer
|
||||
cardViews.add(createHandCard(game, playerYou.getId(), "ZNR", "134")); // Akoum Warrior
|
||||
//*/
|
||||
|
||||
// duplicate cards
|
||||
if (checkBoxGenerateManyCards.isSelected()) {
|
||||
|
@ -226,17 +243,6 @@ public class TestCardRenderDialog extends MageDialog {
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
cardViews.add(createPermanentCard(game, playerYou.getId(), "RNA", "78", 125, 89, 0, false)); // Noxious Groodion
|
||||
|
||||
cardViews.add(createPermanentCard(game, playerYou.getId(), "RNA", "14", 3, 5, 2, false)); // Knight of Sorrows
|
||||
cardViews.add(createPermanentCard(game, playerYou.getId(), "DKA", "140", 5, 2, 2, false)); // Huntmaster of the Fells, transforms
|
||||
cardViews.add(createPermanentCard(game, playerYou.getId(), "RNA", "221", 0, 0, 0, false)); // Bedeck // Bedazzle
|
||||
cardViews.add(createPermanentCard(game, playerYou.getId(), "XLN", "234", 0, 0, 0, false)); // Conqueror's Galleon
|
||||
cardViews.add(createEmblem(new AjaniAdversaryOfTyrantsEmblem())); // Emblem Ajani
|
||||
cardViews.add(createPlane(new AkoumPlane())); // Plane - Akoum
|
||||
//*/
|
||||
|
||||
BigCard big = new BigCard();
|
||||
CardsView view = new CardsView(cardViews);
|
||||
cardsPanel.loadCards(view, big, game.getId());
|
||||
|
|
|
@ -417,7 +417,6 @@ public class CardView extends SimpleCardView {
|
|||
this.subTypes = card.getSubtype(game);
|
||||
this.superTypes = card.getSuperType();
|
||||
this.color = card.getColor(game);
|
||||
this.transformable = card.isTransformable();
|
||||
this.flipCard = card.isFlipCard();
|
||||
this.faceDown = !showFaceUp;
|
||||
|
||||
|
@ -436,7 +435,7 @@ public class CardView extends SimpleCardView {
|
|||
this.tokenDescriptor = card.getTokenDescriptor();
|
||||
}
|
||||
//
|
||||
// set code und card number for token copies to get the image
|
||||
// set code and card number for token copies to get the image
|
||||
this.rules = card.getRules(game);
|
||||
this.type = ((PermanentToken) card).getToken().getTokenType();
|
||||
} else {
|
||||
|
@ -445,6 +444,8 @@ public class CardView extends SimpleCardView {
|
|||
}
|
||||
|
||||
// transformable, double faces cards
|
||||
this.transformable = card.isTransformable();
|
||||
|
||||
Card secondSideCard = card.getSecondCardFace();
|
||||
if (secondSideCard != null) {
|
||||
this.secondCardFace = new CardView(secondSideCard);
|
||||
|
@ -458,14 +459,13 @@ public class CardView extends SimpleCardView {
|
|||
this.originalName = card.getName();
|
||||
}
|
||||
|
||||
/*
|
||||
if (card instanceof ModalDoubleFacesCard) {
|
||||
this.transformable = true; // enable GUI day/night button
|
||||
ModalDoubleFacesCard mdfCard = (ModalDoubleFacesCard) card;
|
||||
this.secondCardFace = new CardView(mdfCard.getRightHalfCard());
|
||||
this.alternateName = mdfCard.getRightHalfCard().getName();
|
||||
this.originalName = card.getName();
|
||||
}
|
||||
*/
|
||||
|
||||
if (card instanceof Spell) {
|
||||
this.mageObjectType = MageObjectType.SPELL;
|
||||
|
|
|
@ -1,13 +1,10 @@
|
|||
package mage.cards;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import mage.MageObject;
|
||||
import mage.MageObjectImpl;
|
||||
import mage.Mana;
|
||||
import mage.ObjectColor;
|
||||
import mage.abilities.*;
|
||||
import mage.abilities.hint.Hint;
|
||||
import mage.abilities.hint.HintUtils;
|
||||
import mage.abilities.keyword.FlashbackAbility;
|
||||
import mage.abilities.mana.ActivatedManaAbilityImpl;
|
||||
import mage.cards.repository.PluginClassloaderRegistery;
|
||||
|
@ -22,6 +19,7 @@ import mage.game.events.ZoneChangeEvent;
|
|||
import mage.game.permanent.Permanent;
|
||||
import mage.game.stack.Spell;
|
||||
import mage.game.stack.StackObject;
|
||||
import mage.util.CardUtil;
|
||||
import mage.util.GameLog;
|
||||
import mage.util.SubTypeList;
|
||||
import mage.watchers.Watcher;
|
||||
|
@ -218,52 +216,16 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
|
|||
game.getState().getCardState(objectId).addInfo(key, value);
|
||||
}
|
||||
|
||||
protected static final List<String> rulesError = ImmutableList.of("Exception occurred in rules generation");
|
||||
|
||||
@Override
|
||||
public List<String> getRules() {
|
||||
try {
|
||||
return getAbilities().getRules(this.getName());
|
||||
} catch (Exception e) {
|
||||
logger.info("Exception in rules generation for card: " + this.getName(), e);
|
||||
}
|
||||
return rulesError;
|
||||
Abilities<Ability> sourceAbilities = this.getAbilities();
|
||||
return CardUtil.getCardRulesWithAdditionalInfo(this.getId(), this.getName(), sourceAbilities, sourceAbilities);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getRules(Game game) {
|
||||
try {
|
||||
List<String> rules = getAbilities(game).getRules(getName());
|
||||
if (game != null) {
|
||||
// debug state
|
||||
for (String data : game.getState().getCardState(objectId).getInfo().values()) {
|
||||
rules.add(data);
|
||||
}
|
||||
// ability hints
|
||||
List<String> abilityHints = new ArrayList<>();
|
||||
if (HintUtils.ABILITY_HINTS_ENABLE) {
|
||||
for (Ability ability : abilities) {
|
||||
for (Hint hint : ability.getHints()) {
|
||||
String s = hint.getText(game, ability);
|
||||
if (s != null && !s.isEmpty()) {
|
||||
abilityHints.add(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// restrict hints only for permanents, not cards
|
||||
// total hints
|
||||
if (!abilityHints.isEmpty()) {
|
||||
rules.add(HintUtils.HINT_START_MARK);
|
||||
HintUtils.appendHints(rules, abilityHints);
|
||||
}
|
||||
}
|
||||
return rules;
|
||||
} catch (Exception e) {
|
||||
logger.error("Exception in rules generation for card: " + this.getName(), e);
|
||||
}
|
||||
return rulesError;
|
||||
Abilities<Ability> sourceAbilities = this.getAbilities(game);
|
||||
return CardUtil.getCardRulesWithAdditionalInfo(game, this.getId(), this.getName(), sourceAbilities, sourceAbilities);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -12,6 +12,7 @@ import mage.abilities.costs.mana.ManaCosts;
|
|||
import mage.constants.*;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.ZoneChangeEvent;
|
||||
import mage.util.CardUtil;
|
||||
import mage.util.SubTypeList;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -157,20 +158,7 @@ public abstract class ModalDoubleFacesCard extends CardImpl {
|
|||
|
||||
@Override
|
||||
public Abilities<Ability> getAbilities() {
|
||||
Abilities<Ability> allAbilites = new AbilitiesImpl<>();
|
||||
|
||||
// ignore default spell ability from main card (only halfes are actual)
|
||||
for (Ability ability : super.getAbilities()) {
|
||||
if (ability instanceof SpellAbility && ((SpellAbility) ability).getSpellAbilityType() == SpellAbilityType.MODAL) {
|
||||
continue;
|
||||
}
|
||||
allAbilites.add(ability);
|
||||
}
|
||||
|
||||
allAbilites.addAll(super.getAbilities());
|
||||
allAbilites.addAll(leftHalfCard.getAbilities());
|
||||
allAbilites.addAll(rightHalfCard.getAbilities());
|
||||
return allAbilites;
|
||||
return getInnerAbilities(false);
|
||||
}
|
||||
|
||||
public Abilities<Ability> getSharedAbilities(Game game) {
|
||||
|
@ -180,6 +168,10 @@ public abstract class ModalDoubleFacesCard extends CardImpl {
|
|||
|
||||
@Override
|
||||
public Abilities<Ability> getAbilities(Game game) {
|
||||
return getInnerAbilities(game, false);
|
||||
}
|
||||
|
||||
private Abilities<Ability> getInnerAbilities(Game game, boolean showOnlyMainSide) {
|
||||
Abilities<Ability> allAbilites = new AbilitiesImpl<>();
|
||||
|
||||
// ignore default spell ability from main card (only halfes are actual)
|
||||
|
@ -191,10 +183,50 @@ public abstract class ModalDoubleFacesCard extends CardImpl {
|
|||
}
|
||||
|
||||
allAbilites.addAll(leftHalfCard.getAbilities(game));
|
||||
if (!showOnlyMainSide) {
|
||||
allAbilites.addAll(rightHalfCard.getAbilities(game));
|
||||
}
|
||||
|
||||
return allAbilites;
|
||||
}
|
||||
|
||||
private Abilities<Ability> getInnerAbilities(boolean showOnlyMainSide) {
|
||||
Abilities<Ability> allAbilites = new AbilitiesImpl<>();
|
||||
|
||||
// ignore default spell ability from main card (only halfes are actual)
|
||||
for (Ability ability : super.getAbilities()) {
|
||||
if (ability instanceof SpellAbility && ((SpellAbility) ability).getSpellAbilityType() == SpellAbilityType.MODAL) {
|
||||
continue;
|
||||
}
|
||||
allAbilites.add(ability);
|
||||
}
|
||||
|
||||
allAbilites.addAll(leftHalfCard.getAbilities());
|
||||
if (!showOnlyMainSide) {
|
||||
allAbilites.addAll(rightHalfCard.getAbilities());
|
||||
}
|
||||
|
||||
return allAbilites;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getRules() {
|
||||
// rules must show only main side (another side visible by toggle/transform button in GUI)
|
||||
// card hints from both sides
|
||||
return CardUtil.getCardRulesWithAdditionalInfo(this.getId(), this.getName(),
|
||||
this.getInnerAbilities(true), this.getInnerAbilities(false)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getRules(Game game) {
|
||||
// rules must show only main side (another side visible by toggle/transform button in GUI)
|
||||
// card hints from both sides
|
||||
return CardUtil.getCardRulesWithAdditionalInfo(game, this.getId(), this.getName(),
|
||||
this.getInnerAbilities(game, true), this.getInnerAbilities(game, false)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasAbility(Ability ability, Game game) {
|
||||
return super.hasAbility(ability, game);
|
||||
|
|
|
@ -100,4 +100,10 @@ public class ModalDoubleFacesCardHalfImpl extends CardImpl implements ModalDoubl
|
|||
this.power = power;
|
||||
this.toughness = toughness;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIdName() {
|
||||
// id must send to main card (popup card hint in game logs)
|
||||
return getName() + " [" + parentCard.getId().toString().substring(0, 3) + ']';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,7 +78,6 @@ public class MockCard extends CardImpl {
|
|||
if (this.isPlaneswalker()) {
|
||||
String startingLoyaltyString = card.getStartingLoyalty();
|
||||
if (startingLoyaltyString.isEmpty()) {
|
||||
//Logger.getLogger(MockCard.class).warn("Planeswalker `" + this.name + "` has empty starting loyalty.");
|
||||
} else {
|
||||
try {
|
||||
this.startingLoyalty = Integer.parseInt(startingLoyaltyString);
|
||||
|
|
|
@ -198,14 +198,7 @@ public class CardInfo {
|
|||
rulesList.add(rule);
|
||||
}
|
||||
} else if (card instanceof ModalDoubleFacesCard) {
|
||||
for (String rule : ((ModalDoubleFacesCard) card).getLeftHalfCard().getRules()) {
|
||||
length += rule.length();
|
||||
rulesList.add(rule);
|
||||
}
|
||||
for (String rule : ((ModalDoubleFacesCard) card).getRightHalfCard().getRules()) {
|
||||
length += rule.length();
|
||||
rulesList.add(rule);
|
||||
}
|
||||
// mdf card return main side's rules only (GUI can toggle it to another side)
|
||||
for (String rule : card.getRules()) {
|
||||
length += rule.length();
|
||||
rulesList.add(rule);
|
||||
|
|
|
@ -264,7 +264,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
// ability hints
|
||||
List<String> abilityHints = new ArrayList<>();
|
||||
if (HintUtils.ABILITY_HINTS_ENABLE) {
|
||||
for (Ability ability : abilities) {
|
||||
for (Ability ability : getAbilities(game)) {
|
||||
for (Hint hint : ability.getHints()) {
|
||||
String s = hint.getText(game, ability);
|
||||
if (s != null && !s.isEmpty()) {
|
||||
|
@ -341,7 +341,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
|
||||
return rules;
|
||||
} catch (Exception e) {
|
||||
return rulesError;
|
||||
return CardUtil.RULES_ERROR_INFO;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -178,6 +178,12 @@ public class Spell extends StackObjImpl implements Card {
|
|||
+ " as Adventure spell of " + GameLog.getColoredObjectIdName(adventureCard);
|
||||
}
|
||||
|
||||
if (card instanceof ModalDoubleFacesCardHalf) {
|
||||
ModalDoubleFacesCard mdfCard = (ModalDoubleFacesCard) card.getMainCard();
|
||||
return GameLog.replaceNameByColoredName(card, getSpellAbility().toString(), mdfCard)
|
||||
+ " as mdf side of " + GameLog.getColoredObjectIdName(mdfCard);
|
||||
}
|
||||
|
||||
return GameLog.replaceNameByColoredName(card, getSpellAbility().toString());
|
||||
}
|
||||
|
||||
|
|
|
@ -1309,7 +1309,14 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
card.getId(), card.getId(), playerId, activationStatus.getApprovingObject());
|
||||
landEventAfter.setZone(cardZoneBefore);
|
||||
game.fireEvent(landEventAfter);
|
||||
game.fireInformEvent(getLogName() + " plays " + card.getLogName());
|
||||
|
||||
String playText = getLogName() + " plays " + card.getLogName();
|
||||
if (card instanceof ModalDoubleFacesCardHalf) {
|
||||
ModalDoubleFacesCard mdfCard = (ModalDoubleFacesCard) card.getMainCard();
|
||||
playText = getLogName() + " plays " + GameLog.replaceNameByColoredName(card, card.getName(), mdfCard)
|
||||
+ " as MDF side of " + GameLog.getColoredObjectIdName(mdfCard);
|
||||
}
|
||||
game.fireInformEvent(playText);
|
||||
// game.removeBookmark(bookmark);
|
||||
resetStoredBookmark(game); // prevent undo after playing a land
|
||||
return true;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package mage.util;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import mage.MageObject;
|
||||
import mage.Mana;
|
||||
import mage.abilities.Abilities;
|
||||
|
@ -9,6 +10,8 @@ import mage.abilities.SpellAbility;
|
|||
import mage.abilities.costs.VariableCost;
|
||||
import mage.abilities.costs.mana.*;
|
||||
import mage.abilities.effects.ContinuousEffect;
|
||||
import mage.abilities.hint.Hint;
|
||||
import mage.abilities.hint.HintUtils;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.MeldCard;
|
||||
import mage.cards.ModalDoubleFacesCard;
|
||||
|
@ -26,6 +29,7 @@ import mage.game.stack.Spell;
|
|||
import mage.players.Player;
|
||||
import mage.target.Target;
|
||||
import mage.util.functions.CopyTokenFunction;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
|
@ -39,6 +43,10 @@ import java.util.stream.Collectors;
|
|||
*/
|
||||
public final class CardUtil {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(CardUtil.class);
|
||||
|
||||
public static final List<String> RULES_ERROR_INFO = ImmutableList.of("Exception occurred in rules generation");
|
||||
|
||||
private static final String SOURCE_EXILE_ZONE_TEXT = "SourceExileZone";
|
||||
|
||||
static final String[] numberStrings = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine",
|
||||
|
@ -897,4 +905,54 @@ public final class CardUtil {
|
|||
return card.getName();
|
||||
}
|
||||
}
|
||||
|
||||
public static List<String> getCardRulesWithAdditionalInfo(UUID cardId, String cardName,
|
||||
Abilities<Ability> rulesSource, Abilities<Ability> hintAbilities) {
|
||||
return getCardRulesWithAdditionalInfo(null, cardId, cardName, rulesSource, hintAbilities);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare rules list from abilities
|
||||
*
|
||||
* @param rulesSource abilities list to show as rules
|
||||
* @param hintsSource abilities list to show as card hints only (you can add additional hints here; exameple: from second or transformed side)
|
||||
*/
|
||||
public static List<String> getCardRulesWithAdditionalInfo(Game game, UUID cardId, String cardName,
|
||||
Abilities<Ability> rulesSource, Abilities<Ability> hintsSource) {
|
||||
try {
|
||||
List<String> rules = rulesSource.getRules(cardName);
|
||||
|
||||
if (game != null) {
|
||||
|
||||
// debug state
|
||||
for (String data : game.getState().getCardState(cardId).getInfo().values()) {
|
||||
rules.add(data);
|
||||
}
|
||||
|
||||
// ability hints
|
||||
List<String> abilityHints = new ArrayList<>();
|
||||
if (HintUtils.ABILITY_HINTS_ENABLE) {
|
||||
for (Ability ability : hintsSource) {
|
||||
for (Hint hint : ability.getHints()) {
|
||||
String s = hint.getText(game, ability);
|
||||
if (s != null && !s.isEmpty()) {
|
||||
abilityHints.add(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// restrict hints only for permanents, not cards
|
||||
// total hints
|
||||
if (!abilityHints.isEmpty()) {
|
||||
rules.add(HintUtils.HINT_START_MARK);
|
||||
HintUtils.appendHints(rules, abilityHints);
|
||||
}
|
||||
}
|
||||
return rules;
|
||||
} catch (Exception e) {
|
||||
logger.error("Exception in rules generation for card: " + cardName, e);
|
||||
}
|
||||
return RULES_ERROR_INFO;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue