images: added The Ring image support (part of #12274, #12899);

images: fixed miss dungeon image in choose dungeon dialog (part of #12274);
This commit is contained in:
Oleg Agafonov 2024-09-21 18:41:53 +04:00
parent 7d1ab71092
commit f7d702d5df
9 changed files with 50 additions and 23 deletions

View file

@ -313,7 +313,7 @@ public class PickChoiceDialog extends MageDialog {
// as card name // as card name
cardInfo.init(item.getHint(), this.bigCard, this.gameId); cardInfo.init(item.getHint(), this.bigCard, this.gameId);
} else if (item.getHintType() == ChoiceHintType.CARD_DUNGEON) { } else if (item.getHintType() == ChoiceHintType.CARD_DUNGEON) {
// as card name // as dungeon name
CardView cardView = new CardView(new DungeonView(Dungeon.createDungeon(item.getHint(), true))); CardView cardView = new CardView(new DungeonView(Dungeon.createDungeon(item.getHint(), true)));
cardInfo.init(cardView, this.bigCard, this.gameId); cardInfo.init(cardView, this.bigCard, this.gameId);
} else if (item.getHintType() == ChoiceHintType.GAME_OBJECT) { } else if (item.getHintType() == ChoiceHintType.GAME_OBJECT) {

View file

@ -33,6 +33,7 @@ public enum TokenRepository {
public static final String XMAGE_IMAGE_NAME_NIGHT = "Night"; public static final String XMAGE_IMAGE_NAME_NIGHT = "Night";
public static final String XMAGE_IMAGE_NAME_THE_MONARCH = "The Monarch"; public static final String XMAGE_IMAGE_NAME_THE_MONARCH = "The Monarch";
public static final String XMAGE_IMAGE_NAME_RADIATION = "Radiation"; public static final String XMAGE_IMAGE_NAME_RADIATION = "Radiation";
public static final String XMAGE_IMAGE_NAME_THE_RING = "The Ring";
public static final String XMAGE_IMAGE_NAME_HELPER_EMBLEM = "Helper Emblem"; public static final String XMAGE_IMAGE_NAME_HELPER_EMBLEM = "Helper Emblem";
private static final Logger logger = Logger.getLogger(TokenRepository.class); private static final Logger logger = Logger.getLogger(TokenRepository.class);
@ -306,6 +307,9 @@ public enum TokenRepository {
// Radiation (for trigger) // Radiation (for trigger)
res.add(createXmageToken(XMAGE_IMAGE_NAME_RADIATION, 1, "https://api.scryfall.com/cards/tpip/22/en?format=image")); res.add(createXmageToken(XMAGE_IMAGE_NAME_RADIATION, 1, "https://api.scryfall.com/cards/tpip/22/en?format=image"));
// The Ring
res.add(createXmageToken(XMAGE_IMAGE_NAME_THE_RING, 1, "https://api.scryfall.com/cards/tltr/H13/en?format=image"));
// Helper emblem (for global card hints) // Helper emblem (for global card hints)
// use backface for it // use backface for it
res.add(createXmageToken(XMAGE_IMAGE_NAME_HELPER_EMBLEM, 1, "https://upload.wikimedia.org/wikipedia/en/a/aa/Magic_the_gathering-card_back.jpg")); res.add(createXmageToken(XMAGE_IMAGE_NAME_HELPER_EMBLEM, 1, "https://upload.wikimedia.org/wikipedia/en/a/aa/Magic_the_gathering-card_back.jpg"));

View file

@ -583,11 +583,10 @@ public abstract class GameImpl implements Game {
if (emblem != null) { if (emblem != null) {
return emblem; return emblem;
} }
TheRingEmblem newEmblem = new TheRingEmblem(playerId); TheRingEmblem newEmblem = new TheRingEmblem(playerId);
// TODO: add image info
state.addCommandObject(newEmblem); state.addCommandObject(newEmblem);
return newEmblem; return newEmblem;
} }
@ -1966,16 +1965,13 @@ public abstract class GameImpl implements Game {
@Override @Override
public void addEmblem(Emblem emblem, MageObject sourceObject, UUID toPlayerId) { public void addEmblem(Emblem emblem, MageObject sourceObject, UUID toPlayerId) {
Emblem newEmblem = emblem.copy(); Emblem newEmblem = emblem.copy();
newEmblem.setSourceObject(sourceObject); newEmblem.setSourceObjectAndInitImage(sourceObject);
newEmblem.setControllerId(toPlayerId); newEmblem.setControllerId(toPlayerId);
newEmblem.assignNewId(); newEmblem.assignNewId();
newEmblem.getAbilities().newId(); newEmblem.getAbilities().newId();
for (Ability ability : newEmblem.getAbilities()) { for (Ability ability : newEmblem.getAbilities()) {
ability.setSourceId(newEmblem.getId()); ability.setSourceId(newEmblem.getId());
} }
// image info setup in setSourceObject
state.addCommandObject(newEmblem); state.addCommandObject(newEmblem);
} }
@ -1997,17 +1993,15 @@ public abstract class GameImpl implements Game {
} }
} }
Plane newPlane = plane.copy(); Plane newPlane = plane.copy();
newPlane.setSourceObject(); newPlane.setSourceObjectAndInitImage();
newPlane.setControllerId(toPlayerId); newPlane.setControllerId(toPlayerId);
newPlane.assignNewId(); newPlane.assignNewId();
newPlane.getAbilities().newId(); newPlane.getAbilities().newId();
for (Ability ability : newPlane.getAbilities()) { for (Ability ability : newPlane.getAbilities()) {
ability.setSourceId(newPlane.getId()); ability.setSourceId(newPlane.getId());
} }
// image info setup in setSourceObject
state.addCommandObject(newPlane); state.addCommandObject(newPlane);
informPlayers("You have planeswalked to " + newPlane.getLogName()); informPlayers("You have planeswalked to " + newPlane.getLogName());
// Fire off the planeswalked event // Fire off the planeswalked event
@ -2028,7 +2022,6 @@ public abstract class GameImpl implements Game {
@Override @Override
public Dungeon addDungeon(Dungeon dungeon, UUID playerId) { public Dungeon addDungeon(Dungeon dungeon, UUID playerId) {
dungeon.setControllerId(playerId); dungeon.setControllerId(playerId);
dungeon.setSourceObject();
state.addCommandObject(dungeon); state.addCommandObject(dungeon);
return dungeon; return dungeon;
} }

View file

@ -1239,6 +1239,11 @@ public class GameState implements Serializable, Copyable<GameState> {
this.isPlaneChase = isPlaneChase; this.isPlaneChase = isPlaneChase;
} }
/**
* Add object to command zone.
* <p>
* Warning, all object data must be initialized before adding, including image info
*/
public void addCommandObject(CommandObject commandObject) { public void addCommandObject(CommandObject commandObject) {
getCommand().add(commandObject); getCommand().add(commandObject);
setZone(commandObject.getId(), Zone.COMMAND); setZone(commandObject.getId(), Zone.COMMAND);

View file

@ -154,24 +154,35 @@ public class Dungeon extends CommandObjectImpl {
} }
public static Dungeon createDungeon(String name, boolean isNameMustExists) { public static Dungeon createDungeon(String name, boolean isNameMustExists) {
Dungeon res;
switch (name) { switch (name) {
case "Tomb of Annihilation": case "Tomb of Annihilation":
return new TombOfAnnihilationDungeon(); res = new TombOfAnnihilationDungeon();
break;
case "Lost Mine of Phandelver": case "Lost Mine of Phandelver":
return new LostMineOfPhandelverDungeon(); res = new LostMineOfPhandelverDungeon();
break;
case "Dungeon of the Mad Mage": case "Dungeon of the Mad Mage":
return new DungeonOfTheMadMageDungeon(); res = new DungeonOfTheMadMageDungeon();
break;
default: default:
if (isNameMustExists) { if (isNameMustExists) {
throw new UnsupportedOperationException("A dungeon should have been chosen"); throw new UnsupportedOperationException("A dungeon should have been chosen");
} else { } else {
return null; res = null;
} }
} }
// source don't have source, so image data can be initialized immediately
if (res != null) {
res.setSourceObjectAndInitImage();
}
return res;
} }
public void setSourceObject() { public void setSourceObjectAndInitImage() {
// choose set code due source // image
TokenInfo foundInfo = TokenRepository.instance.findPreferredTokenInfoForClass(this.getClass().getName(), null); TokenInfo foundInfo = TokenRepository.instance.findPreferredTokenInfoForClass(this.getClass().getName(), null);
if (foundInfo != null) { if (foundInfo != null) {
this.setExpansionSetCode(foundInfo.getSetCode()); this.setExpansionSetCode(foundInfo.getSetCode());

View file

@ -19,7 +19,6 @@ import mage.constants.SubType;
import mage.constants.SuperType; import mage.constants.SuperType;
import mage.game.Game; import mage.game.Game;
import mage.game.events.ZoneChangeEvent; import mage.game.events.ZoneChangeEvent;
import mage.util.CardUtil;
import mage.util.SubTypes; import mage.util.SubTypes;
import java.util.Collections; import java.util.Collections;
@ -59,7 +58,7 @@ public abstract class Emblem extends CommandObjectImpl {
return frameStyle; return frameStyle;
} }
public void setSourceObject(MageObject sourceObject) { public void setSourceObjectAndInitImage(MageObject sourceObject) {
this.sourceObject = sourceObject; this.sourceObject = sourceObject;
// choose set code due source // choose set code due source

View file

@ -65,7 +65,7 @@ public abstract class Plane extends CommandObjectImpl {
return frameStyle; return frameStyle;
} }
public void setSourceObject() { public void setSourceObjectAndInitImage() {
this.sourceObject = null; this.sourceObject = null;
// choose set code due source // choose set code due source

View file

@ -94,7 +94,7 @@ public final class EmblemOfCard extends Emblem {
} }
@Override @Override
public void setSourceObject(MageObject sourceObject) { public void setSourceObjectAndInitImage(MageObject sourceObject) {
this.sourceObject = sourceObject; this.sourceObject = sourceObject;
// super method would try and fail to find the emblem image here // super method would try and fail to find the emblem image here
// (not sure why that would be setSoureObject's job; we get our image during construction) // (not sure why that would be setSoureObject's job; we get our image during construction)

View file

@ -12,6 +12,8 @@ import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
import mage.abilities.effects.common.DrawDiscardControllerEffect; import mage.abilities.effects.common.DrawDiscardControllerEffect;
import mage.abilities.effects.common.LoseLifeOpponentsEffect; import mage.abilities.effects.common.LoseLifeOpponentsEffect;
import mage.abilities.effects.common.SacrificeTargetEffect; import mage.abilities.effects.common.SacrificeTargetEffect;
import mage.cards.repository.TokenInfo;
import mage.cards.repository.TokenRepository;
import mage.constants.*; import mage.constants.*;
import mage.filter.FilterPermanent; import mage.filter.FilterPermanent;
import mage.filter.common.FilterControlledPermanent; import mage.filter.common.FilterControlledPermanent;
@ -41,6 +43,19 @@ public final class TheRingEmblem extends Emblem {
public TheRingEmblem(UUID controllerId) { public TheRingEmblem(UUID controllerId) {
super("The Ring"); super("The Ring");
this.setControllerId(controllerId); this.setControllerId(controllerId);
// ring don't have source, so image can be initialized immediately
TokenInfo foundInfo = TokenRepository.instance.findPreferredTokenInfoForXmage(TokenRepository.XMAGE_IMAGE_NAME_THE_RING, null);
if (foundInfo != null) {
this.setExpansionSetCode(foundInfo.getSetCode());
this.setUsesVariousArt(false);
this.setCardNumber("");
this.setImageFileName(""); // use default
this.setImageNumber(foundInfo.getImageNumber());
} else {
// how-to fix: add emblem to the tokens-database TokenRepository->loadXmageTokens
throw new IllegalArgumentException("Wrong code usage: can't find xmage token info for: " + TokenRepository.XMAGE_IMAGE_NAME_THE_RING);
}
} }
private TheRingEmblem(final TheRingEmblem card) { private TheRingEmblem(final TheRingEmblem card) {