Add additional ability icons (#10549)

* Slightly revamped basic card icons

All icon classes which were just static text have been removed, and instead replaced with a static instance.

A new icon for reach has been added

Some icons have been reused for new abilities (hexproof for shroud and ward, infect for toxic)

When a card would have two icons of the same type, the icons are instead combines into one with a combined hover tooltip.

* Fixed missing capitalization on ward, hexproof
This commit is contained in:
Alexander Novotny 2023-07-03 14:22:07 -07:00 committed by GitHub
parent 9e63858db6
commit fae63d9d4b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
42 changed files with 167 additions and 522 deletions

View file

@ -175,7 +175,32 @@ public class CardIconsPanel extends JPanel {
this.removeAll();
if (newIcons != null) {
this.icons.clear();
this.icons.addAll(newIcons);
TreeMap<CardIconType, List<CardIcon>> cardIconMap = new TreeMap<>();
newIcons.forEach(icon -> cardIconMap.computeIfAbsent(icon.getIconType(), k -> new ArrayList<>()).add(icon));
for (Map.Entry<CardIconType, List<CardIcon>> entry : cardIconMap.entrySet()) {
List<CardIcon> combined = entry.getValue()
.stream()
.filter(icon -> icon != null && icon.canBeCombined())
.sorted(CardIconComparator.instance)
.collect(Collectors.toList());
if (combined.size() > 1) {
entry.getValue().removeAll(combined);
String combinedHint = combined.stream()
.map(CardIcon::getCombinedInfo)
.collect(Collectors.joining("<br>"));
CardIcon combinedIcon = new CardIconImpl(entry.getKey(), combinedHint);
this.icons.add(combinedIcon);
this.icons.addAll(entry.getValue());
} else {
this.icons.addAll(entry.getValue());
}
}
}
// auto-hide panel on empty icons

View file

@ -1,7 +1,7 @@
package org.mage.card.arcane;
import mage.abilities.icon.CardIconColor;
import mage.abilities.icon.abilities.FlyingAbilityIcon;
import mage.abilities.icon.CardIconImpl;
import mage.utils.StreamUtils;
import org.apache.batik.anim.dom.SVGDOMImplementation;
import org.apache.batik.transcoder.TranscoderInput;
@ -217,7 +217,8 @@ public class SvgUtils {
public static boolean checkSvgSupport() {
// usa sample icon for svg support testing
// direct call, no needs in cache
BufferedImage sampleImage = ImageManagerImpl.instance.getCardIcon(FlyingAbilityIcon.instance.getIconType().getResourceName(), 32, CardIconColor.DEFAULT);
BufferedImage sampleImage = ImageManagerImpl.instance
.getCardIcon(CardIconImpl.ABILITY_FLYING.getIconType().getResourceName(), 32, CardIconColor.DEFAULT);
haveSvgSupport = (sampleImage != null && sampleImage.getWidth() > 0);
if (!haveSvgSupport) {
logger.warn("WARNING, your system doesn't support svg images, so card icons will be disabled. Please, make a bug report in the github.");

View file

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" height="1em" viewBox="0 0 384 512"> <!--! Font Awesome Free 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. -->
<path d="M256 64A64 64 0 1 0 128 64a64 64 0 1 0 128 0zM152.9 169.3c-23.7-8.4-44.5-24.3-58.8-45.8L74.6 94.2C64.8 79.5 45 75.6 30.2 85.4s-18.7 29.7-8.9 44.4L40.9 159c18.1 27.1 42.8 48.4 71.1 62.4V480c0 17.7 14.3 32 32 32s32-14.3 32-32V384h32v96c0 17.7 14.3 32 32 32s32-14.3 32-32V221.6c29.1-14.2 54.4-36.2 72.7-64.2l18.2-27.9c9.6-14.8 5.4-34.6-9.4-44.3s-34.6-5.5-44.3 9.4L291 122.4c-21.8 33.4-58.9 53.6-98.8 53.6c-12.6 0-24.9-2-36.6-5.8c-.9-.3-1.8-.7-2.7-.9z"/>
</svg>

After

Width:  |  Height:  |  Size: 719 B

View file

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" height="1em" viewBox="0 0 384 512"> <!--! Font Awesome Free 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. -->
<path d="M256 64A64 64 0 1 0 128 64a64 64 0 1 0 128 0zM152.9 169.3c-23.7-8.4-44.5-24.3-58.8-45.8L74.6 94.2C64.8 79.5 45 75.6 30.2 85.4s-18.7 29.7-8.9 44.4L40.9 159c18.1 27.1 42.8 48.4 71.1 62.4V480c0 17.7 14.3 32 32 32s32-14.3 32-32V384h32v96c0 17.7 14.3 32 32 32s32-14.3 32-32V221.6c29.1-14.2 54.4-36.2 72.7-64.2l18.2-27.9c9.6-14.8 5.4-34.6-9.4-44.3s-34.6-5.5-44.3 9.4L291 122.4c-21.8 33.4-58.9 53.6-98.8 53.6c-12.6 0-24.9-2-36.6-5.8c-.9-.3-1.8-.7-2.7-.9z"/>
</svg>

After

Width:  |  Height:  |  Size: 719 B

View file

@ -11,9 +11,7 @@ import mage.abilities.dynamicvalue.common.ManacostVariableValue;
import mage.abilities.effects.Effect;
import mage.abilities.effects.Effects;
import mage.abilities.icon.CardIcon;
import mage.abilities.icon.other.CommanderCardIcon;
import mage.abilities.icon.other.FaceDownCardIcon;
import mage.abilities.icon.other.VariableCostCardIcon;
import mage.abilities.icon.CardIconImpl;
import mage.abilities.keyword.AftermathAbility;
import mage.cards.*;
import mage.cards.mock.MockCard;
@ -435,13 +433,13 @@ public class CardView extends SimpleCardView {
});
// face down
if (permanent.isFaceDown(game)) {
this.cardIcons.add(FaceDownCardIcon.instance);
this.cardIcons.add(CardIconImpl.FACE_DOWN);
}
// commander
if (game != null) {
Player owner = game.getPlayer(game.getOwnerId(permanent));
if (owner != null && game.isCommanderObject(owner, permanent)) {
this.cardIcons.add(CommanderCardIcon.instance);
this.cardIcons.add(CardIconImpl.COMMANDER);
}
}
} else {
@ -475,7 +473,7 @@ public class CardView extends SimpleCardView {
// other like Stack (can show x icon on stack only, so use normal source)
costX = ManacostVariableValue.REGULAR.calculate(game, card.getSpellAbility(), null);
}
this.cardIcons.add(new VariableCostCardIcon(costX));
this.cardIcons.add(CardIconImpl.variableCost(costX));
}
}

View file

@ -7,7 +7,7 @@ import mage.abilities.dynamicvalue.common.ManacostVariableValue;
import mage.abilities.effects.Effect;
import mage.abilities.hint.Hint;
import mage.abilities.hint.HintUtils;
import mage.abilities.icon.other.VariableCostCardIcon;
import mage.abilities.icon.CardIconImpl;
import mage.cards.Card;
import mage.constants.AbilityType;
import mage.constants.CardType;
@ -83,7 +83,7 @@ public class StackAbilityView extends CardView {
// cost x
if (ability.getManaCostsToPay().containsX()) {
int costX = ManacostVariableValue.END_GAME.calculate(game, ability, null);
this.cardIcons.add(new VariableCostCardIcon(costX));
this.cardIcons.add(CardIconImpl.variableCost(costX));
}
}

View file

@ -2,7 +2,7 @@ package mage.abilities.effects.common;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.Effect;
import mage.abilities.icon.abilities.CrewAbilityIcon;
import mage.abilities.icon.CardIconImpl;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
@ -12,7 +12,7 @@ public class CrewsVehicleSourceTriggeredAbility extends TriggeredAbilityImpl {
public CrewsVehicleSourceTriggeredAbility(Effect effect) {
super(Zone.BATTLEFIELD, effect, false);
this.addIcon(CrewAbilityIcon.instance);
this.addIcon(CardIconImpl.ABILITY_CREW);
setTriggerPhrase("Whenever {this} crews a Vehicle, ");
}

View file

@ -18,6 +18,13 @@ public interface CardIcon extends Copyable<CardIcon> {
*/
String getHint();
/**
* Whether or not this icon can be combined with others with the same icon type
*/
default boolean canBeCombined() {
return getText().isEmpty();
}
/**
* Combined info (text + hint)
*

View file

@ -11,6 +11,32 @@ public class CardIconImpl implements CardIcon, Serializable {
private final String text;
private final String hint;
// Utility Icons
public static final CardIconImpl FACE_DOWN = new CardIconImpl(CardIconType.OTHER_FACEDOWN, "Card is face down");
public static final CardIconImpl COMMANDER = new CardIconImpl(CardIconType.COMMANDER, "Card is commander");
// Ability Icons
public static final CardIconImpl ABILITY_CREW = new CardIconImpl(CardIconType.ABILITY_CREW,
"Crew");
public static final CardIconImpl ABILITY_DEATHTOUCH = new CardIconImpl(CardIconType.ABILITY_DEATHTOUCH,
"Deathtouch");
public static final CardIconImpl ABILITY_DEFENDER = new CardIconImpl(CardIconType.ABILITY_DEFENDER, "Defender");
public static final CardIconImpl ABILITY_DOUBLE_STRIKE = new CardIconImpl(CardIconType.ABILITY_DOUBLE_STRIKE,
"Double Strike");
public static final CardIconImpl ABILITY_FIRST_STRIKE = new CardIconImpl(CardIconType.ABILITY_FIRST_STRIKE,
"First Strike");
public static final CardIconImpl ABILITY_FLYING = new CardIconImpl(CardIconType.ABILITY_FLYING, "Flying");
public static final CardIconImpl ABILITY_INDESTRUCTIBLE = new CardIconImpl(CardIconType.ABILITY_INDESTRUCTIBLE,
"Indestructible");
public static final CardIconImpl ABILITY_INFECT = new CardIconImpl(CardIconType.ABILITY_INFECT, "Infect");
public static final CardIconImpl ABILITY_LIFELINK = new CardIconImpl(CardIconType.ABILITY_LIFELINK, "Lifelink");
public static final CardIconImpl ABILITY_TRAMPLE = new CardIconImpl(CardIconType.ABILITY_TRAMPLE, "Trample");
public static final CardIconImpl ABILITY_VIGILANCE = new CardIconImpl(CardIconType.ABILITY_VIGILANCE, "Vigilance");
// "Target protection" abilities
public static final CardIconImpl ABILITY_HEXPROOF = new CardIconImpl(CardIconType.ABILITY_HEXPROOF, "Hexproof");
public static final CardIconImpl ABILITY_SHROUD = new CardIconImpl(CardIconType.ABILITY_HEXPROOF, "Shroud");
public CardIconImpl(CardIconType cardIconType, String hint) {
this(cardIconType, hint, "");
}
@ -46,4 +72,8 @@ public class CardIconImpl implements CardIcon, Serializable {
public CardIcon copy() {
return new CardIconImpl(this);
}
public static CardIconImpl variableCost(int costX) {
return new CardIconImpl(CardIconType.OTHER_COST_X, "Announced X = " + costX, "x=" + costX);
}
}

View file

@ -30,6 +30,7 @@ public enum CardIconType {
ABILITY_INDESTRUCTIBLE("prepared/ankh.svg", CardIconCategory.ABILITY, 100),
ABILITY_VIGILANCE("prepared/eye.svg", CardIconCategory.ABILITY, 100),
ABILITY_CLASS_LEVEL("prepared/hexagon-fill.svg", CardIconCategory.ABILITY, 100),
ABILITY_REACH("prepared/child-reaching.svg", CardIconCategory.ABILITY, 100),
//
OTHER_FACEDOWN("prepared/reply-fill.svg", CardIconCategory.ABILITY, 100),
OTHER_COST_X("prepared/square-fill.svg", CardIconCategory.ABILITY, 100),

View file

@ -1,31 +0,0 @@
package mage.abilities.icon.abilities;
import mage.abilities.icon.CardIcon;
import mage.abilities.icon.CardIconType;
/**
* @author JayDi85
*/
public enum CrewAbilityIcon implements CardIcon {
instance;
@Override
public CardIconType getIconType() {
return CardIconType.ABILITY_CREW;
}
@Override
public String getText() {
return "";
}
@Override
public String getHint() {
return "Crew ability";
}
@Override
public CardIcon copy() {
return instance;
}
}

View file

@ -1,31 +0,0 @@
package mage.abilities.icon.abilities;
import mage.abilities.icon.CardIcon;
import mage.abilities.icon.CardIconType;
/**
* @author JayDi85
*/
public enum DeathtouchAbilityIcon implements CardIcon {
instance;
@Override
public CardIconType getIconType() {
return CardIconType.ABILITY_DEATHTOUCH;
}
@Override
public String getText() {
return "";
}
@Override
public String getHint() {
return "Deathtouch ability";
}
@Override
public CardIcon copy() {
return instance;
}
}

View file

@ -1,31 +0,0 @@
package mage.abilities.icon.abilities;
import mage.abilities.icon.CardIcon;
import mage.abilities.icon.CardIconType;
/**
* @author JayDi85
*/
public enum DefenderAbilityIcon implements CardIcon {
instance;
@Override
public CardIconType getIconType() {
return CardIconType.ABILITY_DEFENDER;
}
@Override
public String getText() {
return "";
}
@Override
public String getHint() {
return "Defender ability";
}
@Override
public CardIcon copy() {
return instance;
}
}

View file

@ -1,31 +0,0 @@
package mage.abilities.icon.abilities;
import mage.abilities.icon.CardIcon;
import mage.abilities.icon.CardIconType;
/**
* @author JayDi85
*/
public enum DoubleStrikeAbilityIcon implements CardIcon {
instance;
@Override
public CardIconType getIconType() {
return CardIconType.ABILITY_DOUBLE_STRIKE;
}
@Override
public String getText() {
return "";
}
@Override
public String getHint() {
return "Double strike ability";
}
@Override
public CardIcon copy() {
return instance;
}
}

View file

@ -1,31 +0,0 @@
package mage.abilities.icon.abilities;
import mage.abilities.icon.CardIcon;
import mage.abilities.icon.CardIconType;
/**
* @author JayDi85
*/
public enum FirstStrikeAbilityIcon implements CardIcon {
instance;
@Override
public CardIconType getIconType() {
return CardIconType.ABILITY_FIRST_STRIKE;
}
@Override
public String getText() {
return "";
}
@Override
public String getHint() {
return "First strike ability";
}
@Override
public CardIcon copy() {
return instance;
}
}

View file

@ -1,31 +0,0 @@
package mage.abilities.icon.abilities;
import mage.abilities.icon.CardIcon;
import mage.abilities.icon.CardIconType;
/**
* @author JayDi85
*/
public enum FlyingAbilityIcon implements CardIcon {
instance;
@Override
public CardIconType getIconType() {
return CardIconType.ABILITY_FLYING;
}
@Override
public String getText() {
return "";
}
@Override
public String getHint() {
return "Flying ability";
}
@Override
public CardIcon copy() {
return instance;
}
}

View file

@ -1,37 +0,0 @@
package mage.abilities.icon.abilities;
import mage.abilities.icon.CardIcon;
import mage.abilities.icon.CardIconImpl;
import mage.abilities.icon.CardIconType;
import mage.util.CardUtil;
/**
* @author JayDi85
*/
public enum HexproofAbilityIcon implements CardIcon {
instance;
@Override
public CardIconType getIconType() {
return CardIconType.ABILITY_HEXPROOF;
}
@Override
public String getText() {
return "";
}
@Override
public String getHint() {
return "Hexproof ability";
}
@Override
public CardIcon copy() {
return instance;
}
public static CardIconImpl createDynamicCardIcon(String hint) {
return new CardIconImpl(CardIconType.ABILITY_HEXPROOF, CardUtil.getTextWithFirstCharUpperCase(hint));
}
}

View file

@ -1,31 +0,0 @@
package mage.abilities.icon.abilities;
import mage.abilities.icon.CardIcon;
import mage.abilities.icon.CardIconType;
/**
* @author JayDi85
*/
public enum IndestructibleAbilityIcon implements CardIcon {
instance;
@Override
public CardIconType getIconType() {
return CardIconType.ABILITY_INDESTRUCTIBLE;
}
@Override
public String getText() {
return "";
}
@Override
public String getHint() {
return "Indestructible ability";
}
@Override
public CardIcon copy() {
return instance;
}
}

View file

@ -1,31 +0,0 @@
package mage.abilities.icon.abilities;
import mage.abilities.icon.CardIcon;
import mage.abilities.icon.CardIconType;
/**
* @author JayDi85
*/
public enum InfectAbilityIcon implements CardIcon {
instance;
@Override
public CardIconType getIconType() {
return CardIconType.ABILITY_INFECT;
}
@Override
public String getText() {
return "";
}
@Override
public String getHint() {
return "Infect ability";
}
@Override
public CardIcon copy() {
return instance;
}
}

View file

@ -1,31 +0,0 @@
package mage.abilities.icon.abilities;
import mage.abilities.icon.CardIcon;
import mage.abilities.icon.CardIconType;
/**
* @author JayDi85
*/
public enum LifelinkAbilityIcon implements CardIcon {
instance;
@Override
public CardIconType getIconType() {
return CardIconType.ABILITY_LIFELINK;
}
@Override
public String getText() {
return "";
}
@Override
public String getHint() {
return "Lifelink ability";
}
@Override
public CardIcon copy() {
return instance;
}
}

View file

@ -1,31 +0,0 @@
package mage.abilities.icon.abilities;
import mage.abilities.icon.CardIcon;
import mage.abilities.icon.CardIconType;
/**
* @author JayDi85
*/
public enum TrampleAbilityIcon implements CardIcon {
instance;
@Override
public CardIconType getIconType() {
return CardIconType.ABILITY_TRAMPLE;
}
@Override
public String getText() {
return "";
}
@Override
public String getHint() {
return "Trample ability";
}
@Override
public CardIcon copy() {
return instance;
}
}

View file

@ -1,31 +0,0 @@
package mage.abilities.icon.abilities;
import mage.abilities.icon.CardIcon;
import mage.abilities.icon.CardIconType;
/**
* @author JayDi85
*/
public enum VigilanceAbilityIcon implements CardIcon {
instance;
@Override
public CardIconType getIconType() {
return CardIconType.ABILITY_VIGILANCE;
}
@Override
public String getText() {
return "";
}
@Override
public String getHint() {
return "Vigilance ability";
}
@Override
public CardIcon copy() {
return instance;
}
}

View file

@ -1,31 +0,0 @@
package mage.abilities.icon.other;
import mage.abilities.icon.CardIcon;
import mage.abilities.icon.CardIconType;
/**
* @author JayDi85
*/
public enum CommanderCardIcon implements CardIcon {
instance;
@Override
public CardIconType getIconType() {
return CardIconType.COMMANDER;
}
@Override
public String getText() {
return "";
}
@Override
public String getHint() {
return "Card is commander";
}
@Override
public CardIcon copy() {
return instance;
}
}

View file

@ -1,31 +0,0 @@
package mage.abilities.icon.other;
import mage.abilities.icon.CardIcon;
import mage.abilities.icon.CardIconType;
/**
* @author JayDi85
*/
public enum FaceDownCardIcon implements CardIcon {
instance;
@Override
public CardIconType getIconType() {
return CardIconType.OTHER_FACEDOWN;
}
@Override
public String getText() {
return "";
}
@Override
public String getHint() {
return "Card is face down";
}
@Override
public CardIcon copy() {
return instance;
}
}

View file

@ -1,16 +0,0 @@
package mage.abilities.icon.other;
import mage.abilities.icon.CardIconImpl;
import mage.abilities.icon.CardIconType;
/**
* Showing x cost value
*
* @author JayDi85
*/
public class VariableCostCardIcon extends CardIconImpl {
public VariableCostCardIcon(int costX) {
super(CardIconType.OTHER_COST_X, "Announced X = " + costX, "x=" + costX);
}
}

View file

@ -11,7 +11,8 @@ import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.InfoEffect;
import mage.abilities.effects.common.continuous.AddCardTypeSourceEffect;
import mage.abilities.hint.HintUtils;
import mage.abilities.icon.abilities.CrewAbilityIcon;
import mage.abilities.icon.CardIconImpl;
import mage.abilities.icon.CardIconType;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
@ -47,7 +48,7 @@ public class CrewAbility extends SimpleActivatedAbility {
Duration.EndOfTurn, CardType.ARTIFACT, CardType.CREATURE
), new CrewCost(value, altCost));
this.addEffect(new CrewEventEffect());
this.addIcon(CrewAbilityIcon.instance);
this.addIcon(new CardIconImpl(CardIconType.ABILITY_CREW, "Crew " + value));
this.value = value;
if (altCost != null) {
this.addSubAbility(new SimpleStaticAbility(Zone.ALL, new InfoEffect(

View file

@ -2,7 +2,7 @@ package mage.abilities.keyword;
import mage.abilities.MageSingleton;
import mage.abilities.StaticAbility;
import mage.abilities.icon.abilities.DeathtouchAbilityIcon;
import mage.abilities.icon.CardIconImpl;
import mage.constants.Zone;
import java.io.ObjectStreamException;
@ -16,7 +16,7 @@ public class DeathtouchAbility extends StaticAbility implements MageSingleton {
static {
instance = new DeathtouchAbility();
instance.addIcon(DeathtouchAbilityIcon.instance);
instance.addIcon(CardIconImpl.ABILITY_DEATHTOUCH);
}
private Object readResolve() throws ObjectStreamException {

View file

@ -2,7 +2,7 @@ package mage.abilities.keyword;
import mage.abilities.MageSingleton;
import mage.abilities.StaticAbility;
import mage.abilities.icon.abilities.DefenderAbilityIcon;
import mage.abilities.icon.CardIconImpl;
import mage.constants.Zone;
import java.io.ObjectStreamException;
@ -16,7 +16,7 @@ public class DefenderAbility extends StaticAbility implements MageSingleton {
static {
instance = new DefenderAbility();
instance.addIcon(DefenderAbilityIcon.instance);
instance.addIcon(CardIconImpl.ABILITY_DEFENDER);
}
private Object readResolve() throws ObjectStreamException {

View file

@ -2,7 +2,7 @@ package mage.abilities.keyword;
import mage.abilities.MageSingleton;
import mage.abilities.StaticAbility;
import mage.abilities.icon.abilities.DoubleStrikeAbilityIcon;
import mage.abilities.icon.CardIconImpl;
import mage.constants.Zone;
import java.io.ObjectStreamException;
@ -16,7 +16,7 @@ public class DoubleStrikeAbility extends StaticAbility implements MageSingleton
static {
instance = new DoubleStrikeAbility();
instance.addIcon(DoubleStrikeAbilityIcon.instance);
instance.addIcon(CardIconImpl.ABILITY_DOUBLE_STRIKE);
}
private Object readResolve() throws ObjectStreamException {

View file

@ -2,7 +2,7 @@ package mage.abilities.keyword;
import mage.abilities.MageSingleton;
import mage.abilities.StaticAbility;
import mage.abilities.icon.abilities.FirstStrikeAbilityIcon;
import mage.abilities.icon.CardIconImpl;
import mage.constants.Zone;
import java.io.ObjectStreamException;
@ -16,7 +16,7 @@ public class FirstStrikeAbility extends StaticAbility implements MageSingleton {
static {
instance = new FirstStrikeAbility();
instance.addIcon(FirstStrikeAbilityIcon.instance);
instance.addIcon(CardIconImpl.ABILITY_FIRST_STRIKE);
}
private Object readResolve() throws ObjectStreamException {

View file

@ -4,7 +4,7 @@ import mage.abilities.Ability;
import mage.abilities.EvasionAbility;
import mage.abilities.MageSingleton;
import mage.abilities.effects.RestrictionEffect;
import mage.abilities.icon.abilities.FlyingAbilityIcon;
import mage.abilities.icon.CardIconImpl;
import mage.constants.AsThoughEffectType;
import mage.constants.Duration;
import mage.constants.SubType;
@ -22,7 +22,7 @@ public class FlyingAbility extends EvasionAbility implements MageSingleton {
static {
instance = new FlyingAbility();
instance.addIcon(FlyingAbilityIcon.instance);
instance.addIcon(CardIconImpl.ABILITY_FLYING);
}
private Object readResolve() throws ObjectStreamException {

View file

@ -7,10 +7,10 @@ import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.icon.CardIcon;
import mage.abilities.icon.CardIconImpl;
import mage.abilities.icon.CardIconType;
import mage.abilities.icon.abilities.HexproofAbilityIcon;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.util.CardUtil;
import java.util.*;
@ -68,14 +68,11 @@ public abstract class HexproofBaseAbility extends SimpleStaticAbility implements
@Override
public List<CardIcon> getIcons(Game game) {
if (game == null) {
return new ArrayList<>(Collections.singletonList(
HexproofAbilityIcon.instance
));
return Collections.singletonList(CardIconImpl.ABILITY_HEXPROOF);
}
// dynamic icon (example: colored hexproof)
return new ArrayList<>(Collections.singletonList(
HexproofAbilityIcon.createDynamicCardIcon(getCardIconHint(game))
));
return Collections.singletonList(new CardIconImpl(CardIconType.ABILITY_HEXPROOF,
CardUtil.getTextWithFirstCharUpperCase(getCardIconHint(game))));
}
}

View file

@ -2,7 +2,7 @@ package mage.abilities.keyword;
import mage.abilities.MageSingleton;
import mage.abilities.StaticAbility;
import mage.abilities.icon.abilities.IndestructibleAbilityIcon;
import mage.abilities.icon.CardIconImpl;
import mage.constants.Zone;
import java.io.ObjectStreamException;
@ -28,7 +28,7 @@ public class IndestructibleAbility extends StaticAbility implements MageSingleto
static {
instance = new IndestructibleAbility();
instance.addIcon(IndestructibleAbilityIcon.instance);
instance.addIcon(CardIconImpl.ABILITY_INDESTRUCTIBLE);
}
private Object readResolve() throws ObjectStreamException {

View file

@ -2,7 +2,7 @@ package mage.abilities.keyword;
import mage.abilities.MageSingleton;
import mage.abilities.StaticAbility;
import mage.abilities.icon.abilities.InfectAbilityIcon;
import mage.abilities.icon.CardIconImpl;
import mage.constants.Zone;
import java.io.ObjectStreamException;
@ -36,7 +36,7 @@ public class InfectAbility extends StaticAbility implements MageSingleton {
static {
instance = new InfectAbility();
instance.addIcon(InfectAbilityIcon.instance);
instance.addIcon(CardIconImpl.ABILITY_INFECT);
}
private Object readResolve() throws ObjectStreamException {

View file

@ -2,7 +2,7 @@ package mage.abilities.keyword;
import mage.abilities.MageSingleton;
import mage.abilities.StaticAbility;
import mage.abilities.icon.abilities.LifelinkAbilityIcon;
import mage.abilities.icon.CardIconImpl;
import mage.constants.Zone;
import java.io.ObjectStreamException;
@ -16,7 +16,7 @@ public class LifelinkAbility extends StaticAbility implements MageSingleton {
static {
instance = new LifelinkAbility();
instance.addIcon(LifelinkAbilityIcon.instance);
instance.addIcon(CardIconImpl.ABILITY_LIFELINK);
}
private Object readResolve() throws ObjectStreamException {

View file

@ -4,6 +4,8 @@ package mage.abilities.keyword;
import mage.constants.Zone;
import mage.abilities.MageSingleton;
import mage.abilities.StaticAbility;
import mage.abilities.icon.CardIconImpl;
import mage.abilities.icon.CardIconType;
import java.io.ObjectStreamException;
@ -13,7 +15,13 @@ import java.io.ObjectStreamException;
*/
public class ReachAbility extends StaticAbility implements MageSingleton {
private static final ReachAbility instance = new ReachAbility();
private static final ReachAbility instance;
static {
instance = new ReachAbility();
instance.addIcon(
new CardIconImpl(CardIconType.ABILITY_REACH, "Reach"));
}
private Object readResolve() throws ObjectStreamException {
return instance;

View file

@ -5,6 +5,8 @@ package mage.abilities.keyword;
import mage.constants.Zone;
import mage.abilities.MageSingleton;
import mage.abilities.StaticAbility;
import mage.abilities.icon.CardIconImpl;
import mage.abilities.icon.CardIconType;
import java.io.ObjectStreamException;
@ -14,7 +16,13 @@ import java.io.ObjectStreamException;
*/
public class ShroudAbility extends StaticAbility implements MageSingleton {
private static final ShroudAbility instance = new ShroudAbility();
private static final ShroudAbility instance;
static {
instance = new ShroudAbility();
instance.addIcon(
new CardIconImpl(CardIconType.ABILITY_HEXPROOF, "Shroud"));
}
private Object readResolve() throws ObjectStreamException {
return instance;

View file

@ -1,13 +1,11 @@
package mage.abilities.keyword;
import mage.abilities.MageSingleton;
import mage.abilities.StaticAbility;
import mage.abilities.icon.abilities.InfectAbilityIcon;
import mage.abilities.icon.CardIconImpl;
import mage.abilities.icon.CardIconType;
import mage.constants.Zone;
import mage.util.CardUtil;
import java.io.ObjectStreamException;
/**
* @author TheElk801
*/
@ -18,6 +16,8 @@ public class ToxicAbility extends StaticAbility {
public ToxicAbility(int amount) {
super(Zone.BATTLEFIELD, null);
this.amount = amount;
this.addIcon(new CardIconImpl(CardIconType.ABILITY_INFECT, "Toxic " + amount));
}
private ToxicAbility(final ToxicAbility ability) {

View file

@ -2,7 +2,7 @@ package mage.abilities.keyword;
import mage.abilities.MageSingleton;
import mage.abilities.StaticAbility;
import mage.abilities.icon.abilities.TrampleAbilityIcon;
import mage.abilities.icon.CardIconImpl;
import mage.constants.Zone;
import java.io.ObjectStreamException;
@ -16,7 +16,7 @@ public class TrampleAbility extends StaticAbility implements MageSingleton {
static {
instance = new TrampleAbility();
instance.addIcon(TrampleAbilityIcon.instance);
instance.addIcon(CardIconImpl.ABILITY_TRAMPLE);
}
private Object readResolve() throws ObjectStreamException {

View file

@ -2,7 +2,8 @@ package mage.abilities.keyword;
import mage.abilities.MageSingleton;
import mage.abilities.StaticAbility;
import mage.abilities.icon.abilities.TrampleAbilityIcon;
import mage.abilities.icon.CardIconImpl;
import mage.abilities.icon.CardIconType;
import mage.constants.Zone;
import java.io.ObjectStreamException;
@ -16,6 +17,7 @@ public class TrampleOverPlaneswalkersAbility extends StaticAbility implements Ma
static {
instance = new TrampleOverPlaneswalkersAbility();
instance.addIcon(new CardIconImpl(CardIconType.ABILITY_TRAMPLE, "Trample over planeswalkers"));
}
private Object readResolve() throws ObjectStreamException {

View file

@ -2,7 +2,7 @@ package mage.abilities.keyword;
import mage.abilities.MageSingleton;
import mage.abilities.StaticAbility;
import mage.abilities.icon.abilities.VigilanceAbilityIcon;
import mage.abilities.icon.CardIconImpl;
import mage.constants.Zone;
import java.io.ObjectStreamException;
@ -16,7 +16,7 @@ public class VigilanceAbility extends StaticAbility implements MageSingleton {
static {
instance = new VigilanceAbility();
instance.addIcon(VigilanceAbilityIcon.instance);
instance.addIcon(CardIconImpl.ABILITY_VIGILANCE);
}
private Object readResolve() throws ObjectStreamException {

View file

@ -5,6 +5,8 @@ import mage.abilities.costs.Cost;
import mage.abilities.costs.mana.ManaCost;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.effects.common.CounterUnlessPaysEffect;
import mage.abilities.icon.CardIconImpl;
import mage.abilities.icon.CardIconType;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
@ -34,6 +36,9 @@ public class WardAbility extends TriggeredAbilityImpl {
this.genericMana = null;
this.showAbilityHint = showAbilityHint;
this.whereXIs = null;
this.addIcon(new CardIconImpl(CardIconType.ABILITY_HEXPROOF,
CardUtil.getTextWithFirstCharUpperCase(getRuleWithoutHint())));
}
public WardAbility(DynamicValue genericMana) {
@ -46,6 +51,9 @@ public class WardAbility extends TriggeredAbilityImpl {
this.whereXIs = whereXIs;
this.cost = null;
this.showAbilityHint = false;
this.addIcon(new CardIconImpl(CardIconType.ABILITY_HEXPROOF,
CardUtil.getTextWithFirstCharUpperCase(getRuleWithoutHint())));
}
private WardAbility(final WardAbility ability) {
@ -97,8 +105,7 @@ public class WardAbility extends TriggeredAbilityImpl {
return new WardAbility(this);
}
@Override
public String getRule() {
public String getRuleWithoutHint() {
StringBuilder sb = new StringBuilder("ward");
if (cost != null) {
if (cost instanceof ManaCost) {
@ -113,7 +120,18 @@ public class WardAbility extends TriggeredAbilityImpl {
}
}
if (showAbilityHint) {
return sb.toString();
}
@Override
public String getRule() {
String rule = getRuleWithoutHint();
if (!showAbilityHint) {
return rule;
}
StringBuilder sb = new StringBuilder(rule);
sb.append(" <i>(Whenever this creature becomes the target of a spell or ability an opponent controls, " +
"counter it unless that player ");
if (cost != null) {
@ -130,7 +148,6 @@ public class WardAbility extends TriggeredAbilityImpl {
}
sb.append(".)</i>");
}
}
return sb.toString();
}