Face down images and cards rework (#11873)

Face down changes:
* GUI: added visible face down type and real card name for controller/owner (opponent can see it after game ends);
* GUI: added day/night button to view real card for controller/owner (opponent can see it after game ends);
* game: fixed that faced-down card can render symbols, abilities and other hidden data from a real card;
* images: added image support for normal faced-down cards;
* images: added image support for morph and megamorph faced-down cards;
* images: added image support for foretell faced-down cards;

Other changes:
* images: fixed missing tokens from DDD set;
* images: no more client restart to apply newly downloaded images or render settings;
* images: improved backface image quality (use main menu -> symbols to download it);
This commit is contained in:
Oleg Agafonov 2024-02-29 01:14:54 +04:00 committed by GitHub
parent 4901de12c1
commit e38a79f231
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
104 changed files with 2178 additions and 1495 deletions

View file

@ -1,12 +1,18 @@
package mage.constants;
import mage.abilities.SpellAbility;
import mage.abilities.effects.common.continuous.BecomesFaceDownCreatureEffect;
import mage.abilities.keyword.BestowAbility;
import mage.abilities.keyword.PrototypeAbility;
import mage.cards.Card;
import mage.abilities.keyword.MorphAbility;
import mage.game.Game;
import mage.game.stack.Spell;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
* @author LevelX2
*/
@ -16,16 +22,24 @@ public enum SpellAbilityCastMode {
FLASHBACK("Flashback"),
BESTOW("Bestow"),
PROTOTYPE("Prototype"),
MORPH("Morph"),
MORPH("Morph", false, SpellAbilityCastMode.MORPH_ADDITIONAL_RULE),
MEGAMORPH("Megamorph", false, SpellAbilityCastMode.MORPH_ADDITIONAL_RULE),
TRANSFORMED("Transformed", true),
DISTURB("Disturb", true),
MORE_THAN_MEETS_THE_EYE("More than Meets the Eye", true);
private static final String MORPH_ADDITIONAL_RULE = "You may cast this card as a 2/2 face-down creature, with no text,"
+ " no name, no subtypes, and no mana cost by paying {3} rather than paying its mana cost.";
private final String text;
// Should the cast mode use the second face?
// should the cast mode use the second face?
private final boolean isTransformed;
// use it to add additional info in stack object cause face down has nothing
// TODO: is it possible to use InfoEffect or CardHint instead that?
private final List<String> additionalRulesOnStack;
public boolean isTransformed() {
return this.isTransformed;
}
@ -35,8 +49,17 @@ public enum SpellAbilityCastMode {
}
SpellAbilityCastMode(String text, boolean isTransformed) {
this(text, isTransformed, null);
}
SpellAbilityCastMode(String text, boolean isTransformed, String additionalRulesOnStack) {
this.text = text;
this.isTransformed = isTransformed;
this.additionalRulesOnStack = additionalRulesOnStack == null ? null : Collections.singletonList(additionalRulesOnStack);
}
public List<String> getAdditionalRulesOnStack() {
return additionalRulesOnStack;
}
@Override
@ -44,27 +67,46 @@ public enum SpellAbilityCastMode {
return text;
}
public Card getTypeModifiedCardObjectCopy(Card card, SpellAbility spellAbility) {
public Card getTypeModifiedCardObjectCopy(Card card, SpellAbility spellAbility, Game game) {
Card cardCopy = card.copy();
if (this.equals(BESTOW)) {
BestowAbility.becomeAura(cardCopy);
}
if (this.isTransformed) {
Card tmp = card.getSecondCardFace();
if (tmp != null) {
cardCopy = tmp.copy();
}
}
if (this.equals(PROTOTYPE)) {
cardCopy = ((PrototypeAbility) spellAbility).prototypeCardSpell(cardCopy);
}
if (this.equals(MORPH)) {
if (cardCopy instanceof Spell) {
//Spell doesn't support setName, so make a copy of the card (we're blowing it away anyway)
cardCopy = ((Spell) cardCopy).getCard().copy();
}
MorphAbility.setCardToFaceDownCreature(cardCopy);
switch (this) {
case BESTOW:
BestowAbility.becomeAura(cardCopy);
break;
case PROTOTYPE:
cardCopy = ((PrototypeAbility) spellAbility).prototypeCardSpell(cardCopy);
break;
case MORPH:
case MEGAMORPH:
if (cardCopy instanceof Spell) {
//Spell doesn't support setName, so make a copy of the card (we're blowing it away anyway)
// TODO: research - is it possible to apply face down code to spell instead workaround with card
cardCopy = ((Spell) cardCopy).getCard().copy();
}
BecomesFaceDownCreatureEffect.makeFaceDownObject(game, null, cardCopy, BecomesFaceDownCreatureEffect.FaceDownType.MORPHED, null);
break;
case NORMAL:
case MADNESS:
case FLASHBACK:
case DISTURB:
case MORE_THAN_MEETS_THE_EYE:
// it changes only cost, so keep other characteristics
// TODO: research - why TRANSFORMED here - is it used in this.isTransformed code?!
break;
case TRANSFORMED:
// TODO: research - why TRANSFORMED here - is it used in this.isTransformed code?!
break;
default:
throw new IllegalArgumentException("Un-supported ability cast mode: " + this);
}
return cardCopy;
}
}