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

@ -1117,7 +1117,7 @@ public final class CardUtil {
// put onto battlefield with possible counters without ETB
game.getPermanentsEntering().put(permanent.getId(), permanent);
permCard.checkForCountersToAdd(permanent, source, game);
permCard.applyEnterWithCounters(permanent, source, game);
permanent.entersBattlefield(source, game, Zone.OUTSIDE, false);
game.addPermanent(permanent, game.getState().getNextPermanentOrderNumber());
game.getPermanentsEntering().remove(permanent.getId());
@ -2141,43 +2141,63 @@ public final class CardUtil {
/**
* Copy image related data from one object to another (set code, card number, image number)
* Copy image related data from one object to another (set code, card number, image number, file name)
* Use it in copy/transform effects
*/
public static void copySetAndCardNumber(MageObject targetObject, MageObject copyFromObject) {
String needSetCode;
String needCardNumber;
String needImageFileName;
int needImageNumber;
boolean needUsesVariousArt = false;
if (copyFromObject instanceof Card) {
needUsesVariousArt = ((Card) copyFromObject).getUsesVariousArt();
}
needSetCode = copyFromObject.getExpansionSetCode();
needCardNumber = copyFromObject.getCardNumber();
needImageFileName = copyFromObject.getImageFileName();
needImageNumber = copyFromObject.getImageNumber();
if (targetObject instanceof Permanent) {
copySetAndCardNumber((Permanent) targetObject, needSetCode, needCardNumber, needImageNumber);
copySetAndCardNumber((Permanent) targetObject, needSetCode, needCardNumber, needImageFileName, needImageNumber, needUsesVariousArt);
} else if (targetObject instanceof Token) {
copySetAndCardNumber((Token) targetObject, needSetCode, needCardNumber, needImageNumber);
copySetAndCardNumber((Token) targetObject, needSetCode, needCardNumber, needImageFileName, needImageNumber);
} else if (targetObject instanceof Card) {
copySetAndCardNumber((Card) targetObject, needSetCode, needCardNumber, needImageFileName, needImageNumber, needUsesVariousArt);
} else {
throw new IllegalStateException("Unsupported target object class: " + targetObject.getClass().getSimpleName());
}
}
private static void copySetAndCardNumber(Permanent targetPermanent, String newSetCode, String newCardNumber, Integer newImageNumber) {
private static void copySetAndCardNumber(Permanent targetPermanent, String newSetCode, String newCardNumber, String newImageFileName, Integer newImageNumber, boolean usesVariousArt) {
if (targetPermanent instanceof PermanentCard
|| targetPermanent instanceof PermanentToken) {
targetPermanent.setExpansionSetCode(newSetCode);
targetPermanent.setCardNumber(newCardNumber);
targetPermanent.setImageFileName(newImageFileName);
targetPermanent.setImageNumber(newImageNumber);
targetPermanent.setUsesVariousArt(usesVariousArt);
} else {
throw new IllegalArgumentException("Wrong code usage: un-supported target permanent type: " + targetPermanent.getClass().getSimpleName());
}
}
private static void copySetAndCardNumber(Token targetToken, String newSetCode, String newCardNumber, Integer newImageNumber) {
private static void copySetAndCardNumber(Token targetToken, String newSetCode, String newCardNumber, String newImageFileName, Integer newImageNumber) {
targetToken.setExpansionSetCode(newSetCode);
targetToken.setCardNumber(newCardNumber);
targetToken.setImageFileName(newImageFileName);
targetToken.setImageNumber(newImageNumber);
}
private static void copySetAndCardNumber(Card targetCard, String newSetCode, String newCardNumber, String newImageFileName, Integer newImageNumber, boolean usesVariousArt) {
targetCard.setExpansionSetCode(newSetCode);
targetCard.setCardNumber(newCardNumber);
targetCard.setImageFileName(newImageFileName);
targetCard.setImageNumber(newImageNumber);
targetCard.setUsesVariousArt(usesVariousArt);
}
/**
* One single event can be a batch (contain multiple events)
*
@ -2193,4 +2213,26 @@ public final class CardUtil {
}
return res;
}
/**
* Prepare card name for render in card panels, popups, etc. Can show face down status and real card name instead empty string
*
* @param imageFileName face down status or another inner image name like Morph, Copy, etc
*/
public static String getCardNameForGUI(String name, String imageFileName) {
if (imageFileName.isEmpty()) {
// normal name
return name;
} else {
// face down or inner name
return imageFileName + (name.isEmpty() ? "" : ": " + name);
}
}
/**
* GUI related: show real name and day/night button for face down card
*/
public static boolean canShowAsControlled(Card card, UUID createdForPlayer) {
return card.getControllerOrOwnerId().equals(createdForPlayer);
}
}