mirror of
https://github.com/magefree/mage.git
synced 2025-12-20 10:40:06 -08:00
GUI: added restriction card icon to permanent (contains all applied restrictions and requirements, #7471)
This commit is contained in:
parent
ebaa92c537
commit
eaa510b265
7 changed files with 87 additions and 14 deletions
|
|
@ -199,7 +199,6 @@ public class CardIconsPanel extends JPanel {
|
||||||
} else {
|
} else {
|
||||||
this.icons.addAll(entry.getValue());
|
this.icons.addAll(entry.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,10 @@ import mage.abilities.SpellAbility;
|
||||||
import mage.abilities.dynamicvalue.common.ManacostVariableValue;
|
import mage.abilities.dynamicvalue.common.ManacostVariableValue;
|
||||||
import mage.abilities.effects.Effect;
|
import mage.abilities.effects.Effect;
|
||||||
import mage.abilities.effects.Effects;
|
import mage.abilities.effects.Effects;
|
||||||
|
import mage.abilities.hint.HintUtils;
|
||||||
import mage.abilities.icon.CardIcon;
|
import mage.abilities.icon.CardIcon;
|
||||||
import mage.abilities.icon.CardIconImpl;
|
import mage.abilities.icon.CardIconImpl;
|
||||||
|
import mage.abilities.icon.CardIconType;
|
||||||
import mage.abilities.keyword.AftermathAbility;
|
import mage.abilities.keyword.AftermathAbility;
|
||||||
import mage.cards.*;
|
import mage.cards.*;
|
||||||
import mage.cards.mock.MockCard;
|
import mage.cards.mock.MockCard;
|
||||||
|
|
@ -441,25 +443,46 @@ public class CardView extends SimpleCardView {
|
||||||
}
|
}
|
||||||
|
|
||||||
// card icons for permanents on battlefield
|
// card icons for permanents on battlefield
|
||||||
// abilities
|
|
||||||
|
// icon - all from abilities
|
||||||
permanent.getAbilities(game).forEach(ability -> {
|
permanent.getAbilities(game).forEach(ability -> {
|
||||||
this.cardIcons.addAll(ability.getIcons(game));
|
this.cardIcons.addAll(ability.getIcons(game));
|
||||||
});
|
});
|
||||||
// face down
|
|
||||||
|
// icon - face down
|
||||||
if (permanent.isFaceDown(game)) {
|
if (permanent.isFaceDown(game)) {
|
||||||
this.cardIcons.add(CardIconImpl.FACE_DOWN);
|
this.cardIcons.add(CardIconImpl.FACE_DOWN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// icon - commander
|
||||||
if (game != null) {
|
if (game != null) {
|
||||||
Player owner = game.getPlayer(game.getOwnerId(permanent));
|
Player owner = game.getPlayer(game.getOwnerId(permanent));
|
||||||
// commander
|
|
||||||
if (owner != null && game.isCommanderObject(owner, permanent)) {
|
if (owner != null && game.isCommanderObject(owner, permanent)) {
|
||||||
this.cardIcons.add(CardIconImpl.COMMANDER);
|
this.cardIcons.add(CardIconImpl.COMMANDER);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Ring-bearer
|
|
||||||
|
// icon - ring-bearer
|
||||||
if (permanent.isRingBearer()) {
|
if (permanent.isRingBearer()) {
|
||||||
this.cardIcons.add(CardIconImpl.RINGBEARER);
|
this.cardIcons.add(CardIconImpl.RINGBEARER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// icon - restrictions (search it in card hints)
|
||||||
|
List<String> restricts = new ArrayList<>();
|
||||||
|
this.rules.forEach(r -> {
|
||||||
|
if (r.startsWith(HintUtils.HINT_ICON_RESTRICT)
|
||||||
|
|| r.startsWith(HintUtils.HINT_ICON_REQUIRE)) {
|
||||||
|
restricts.add(r
|
||||||
|
.replace(HintUtils.HINT_ICON_RESTRICT, "")
|
||||||
|
.replace(HintUtils.HINT_ICON_REQUIRE, "")
|
||||||
|
.trim()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (!restricts.isEmpty()) {
|
||||||
|
restricts.sort(String::compareTo);
|
||||||
|
this.cardIcons.add(new CardIconImpl(CardIconType.OTHER_HAS_RESTRICTIONS, String.join("<br>", restricts)));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (card.isCopy()) {
|
if (card.isCopy()) {
|
||||||
this.mageObjectType = MageObjectType.COPY_CARD;
|
this.mageObjectType = MageObjectType.COPY_CARD;
|
||||||
|
|
@ -493,6 +516,9 @@ public class CardView extends SimpleCardView {
|
||||||
}
|
}
|
||||||
this.cardIcons.add(CardIconImpl.variableCost(costX));
|
this.cardIcons.add(CardIconImpl.variableCost(costX));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// restrictions
|
||||||
|
//card.getRules()
|
||||||
}
|
}
|
||||||
|
|
||||||
this.power = Integer.toString(card.getPower().getValue());
|
this.power = Integer.toString(card.getPower().getValue());
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
package org.mage.test.serverside;
|
package org.mage.test.serverside;
|
||||||
|
|
||||||
|
import mage.abilities.hint.HintUtils;
|
||||||
|
import mage.abilities.icon.CardIconType;
|
||||||
import mage.constants.PhaseStep;
|
import mage.constants.PhaseStep;
|
||||||
import mage.constants.Zone;
|
import mage.constants.Zone;
|
||||||
import mage.view.CardView;
|
import mage.view.CardView;
|
||||||
|
|
@ -338,4 +340,46 @@ public class CardIconsTest extends CardTestPlayerBase {
|
||||||
setStopAt(1, PhaseStep.END_TURN);
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
execute();
|
execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_RestrictionsIcon() {
|
||||||
|
// Felhide Brawler can't block unless you control another Minotaur.
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Felhide Brawler", 1);
|
||||||
|
//
|
||||||
|
addCard(Zone.HAND, playerA, "Felhide Brawler", 1); // {1}{B}
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2);
|
||||||
|
|
||||||
|
// active restriction
|
||||||
|
runCode("has restrictions", 1, PhaseStep.PRECOMBAT_MAIN, playerA, (info, player, game) -> {
|
||||||
|
GameView gameView = getGameView(player);
|
||||||
|
PlayerView playerView = gameView.getPlayers().get(0);
|
||||||
|
Assert.assertEquals("player", player.getName(), playerView.getName());
|
||||||
|
CardView cardView = playerView.getBattlefield().values().stream().filter(p -> p.getName().equals("Felhide Brawler")).findFirst().orElse(null);
|
||||||
|
Assert.assertNotNull("must have 1 creature in battlefield", cardView);
|
||||||
|
Assert.assertTrue("creature must have restriction hint", cardView.getRules().stream().anyMatch(s -> s.startsWith(HintUtils.HINT_ICON_RESTRICT)));
|
||||||
|
Assert.assertTrue("creature must have restriction icon", cardView.getCardIcons().stream().anyMatch(icon -> icon.getIconType().equals(CardIconType.OTHER_HAS_RESTRICTIONS)));
|
||||||
|
});
|
||||||
|
|
||||||
|
// cast another creature and disable restriction
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Felhide Brawler");
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
runCode("no restrictions", 1, PhaseStep.PRECOMBAT_MAIN, playerA, (info, player, game) -> {
|
||||||
|
GameView gameView = getGameView(player);
|
||||||
|
PlayerView playerView = gameView.getPlayers().get(0);
|
||||||
|
Assert.assertEquals("player", player.getName(), playerView.getName());
|
||||||
|
Assert.assertEquals("must have 2 creature in battlefield", 2, playerView.getBattlefield().values()
|
||||||
|
.stream()
|
||||||
|
.filter(p -> p.getName().equals("Felhide Brawler"))
|
||||||
|
.count()
|
||||||
|
);
|
||||||
|
CardView cardView = playerView.getBattlefield().values().stream().filter(p -> p.getName().equals("Felhide Brawler")).findFirst().orElse(null);
|
||||||
|
Assert.assertNotNull("can't find creature", cardView);
|
||||||
|
Assert.assertFalse("creature must not have restriction hint", cardView.getRules().stream().anyMatch(s -> s.startsWith(HintUtils.HINT_ICON_RESTRICT)));
|
||||||
|
Assert.assertFalse("creature must not have restriction icon", cardView.getCardIcons().stream().anyMatch(icon -> icon.getIconType().equals(CardIconType.OTHER_HAS_RESTRICTIONS)));
|
||||||
|
});
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
execute();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,8 @@ public class HintUtils {
|
||||||
// icons changes to real files on client side (see mana icons replacement)
|
// icons changes to real files on client side (see mana icons replacement)
|
||||||
public static final String HINT_ICON_GOOD = "ICON_GOOD";
|
public static final String HINT_ICON_GOOD = "ICON_GOOD";
|
||||||
public static final String HINT_ICON_BAD = "ICON_BAD";
|
public static final String HINT_ICON_BAD = "ICON_BAD";
|
||||||
public static final String HINT_ICON_RESTRICT = "ICON_RESTRICT";
|
public static final String HINT_ICON_RESTRICT = "ICON_RESTRICT"; // used for restrict card icon too
|
||||||
public static final String HINT_ICON_REQUIRE = "ICON_REQUIRE";
|
public static final String HINT_ICON_REQUIRE = "ICON_REQUIRE"; // used for restrict card icon too
|
||||||
public static final String HINT_ICON_DUNGEON_ROOM_CURRENT = "ICON_DUNGEON_ROOM_CURRENT";
|
public static final String HINT_ICON_DUNGEON_ROOM_CURRENT = "ICON_DUNGEON_ROOM_CURRENT";
|
||||||
public static final String HINT_ICON_DUNGEON_ROOM_NEXT = "ICON_DUNGEON_ROOM_NEXT";
|
public static final String HINT_ICON_DUNGEON_ROOM_NEXT = "ICON_DUNGEON_ROOM_NEXT";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,9 @@ import java.io.Serializable;
|
||||||
*/
|
*/
|
||||||
public class CardIconImpl implements CardIcon, Serializable {
|
public class CardIconImpl implements CardIcon, Serializable {
|
||||||
|
|
||||||
private final CardIconType cardIconType;
|
private final CardIconType cardIconType; // icon image
|
||||||
private final String text;
|
private final String text; // drawing text instead over icon (example: x value or level)
|
||||||
private final String hint;
|
private final String hint; // popup text hint on mouse move over icon
|
||||||
|
|
||||||
// Utility Icons
|
// Utility Icons
|
||||||
public static final CardIconImpl FACE_DOWN = new CardIconImpl(CardIconType.OTHER_FACEDOWN, "Card is face down");
|
public static final CardIconImpl FACE_DOWN = new CardIconImpl(CardIconType.OTHER_FACEDOWN, "Card is face down");
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ public enum CardIconType {
|
||||||
//
|
//
|
||||||
OTHER_FACEDOWN("prepared/reply-fill.svg", CardIconCategory.ABILITY, 100),
|
OTHER_FACEDOWN("prepared/reply-fill.svg", CardIconCategory.ABILITY, 100),
|
||||||
OTHER_COST_X("prepared/square-fill.svg", CardIconCategory.ABILITY, 100),
|
OTHER_COST_X("prepared/square-fill.svg", CardIconCategory.ABILITY, 100),
|
||||||
|
OTHER_HAS_RESTRICTIONS("prepared/exclamation-triangle-fill.svg", CardIconCategory.ABILITY, 100),
|
||||||
//
|
//
|
||||||
RINGBEARER("prepared/ring.svg", CardIconCategory.COMMANDER, 100),
|
RINGBEARER("prepared/ring.svg", CardIconCategory.COMMANDER, 100),
|
||||||
COMMANDER("prepared/crown.svg", CardIconCategory.COMMANDER, 100), // TODO: fix big size, see CardIconsPanel
|
COMMANDER("prepared/crown.svg", CardIconCategory.COMMANDER, 100), // TODO: fix big size, see CardIconsPanel
|
||||||
|
|
|
||||||
|
|
@ -259,7 +259,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public List<String> getRules(Game game) {
|
final public List<String> getRules(Game game) {
|
||||||
try {
|
try {
|
||||||
List<String> rules = super.getRules(game);
|
List<String> rules = super.getRules(game);
|
||||||
|
|
||||||
|
|
@ -277,6 +277,9 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
||||||
|
|
||||||
// ability hints already collected in super call
|
// ability hints already collected in super call
|
||||||
|
|
||||||
|
// warning, if you add new icon type for restriction or requirement then don't forget
|
||||||
|
// to add it for card icon too (search CardIconType.OTHER_HAS_RESTRICTIONS)
|
||||||
|
|
||||||
// restrict hints
|
// restrict hints
|
||||||
List<String> restrictHints = new ArrayList<>();
|
List<String> restrictHints = new ArrayList<>();
|
||||||
if (HintUtils.RESTRICT_HINTS_ENABLE) {
|
if (HintUtils.RESTRICT_HINTS_ENABLE) {
|
||||||
|
|
@ -301,7 +304,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// requirement
|
// requirement hints
|
||||||
for (Map.Entry<RequirementEffect, Set<Ability>> entry : game.getContinuousEffects().getApplicableRequirementEffects(this, false, game).entrySet()) {
|
for (Map.Entry<RequirementEffect, Set<Ability>> entry : game.getContinuousEffects().getApplicableRequirementEffects(this, false, game).entrySet()) {
|
||||||
for (Ability ability : entry.getValue()) {
|
for (Ability ability : entry.getValue()) {
|
||||||
if (entry.getKey().mustAttack(game)) {
|
if (entry.getKey().mustAttack(game)) {
|
||||||
|
|
@ -338,11 +341,11 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Goaded hints.
|
// goaded hints
|
||||||
for (UUID playerId : getGoadingPlayers()) {
|
for (UUID playerId : getGoadingPlayers()) {
|
||||||
Player player = game.getPlayer(playerId);
|
Player player = game.getPlayer(playerId);
|
||||||
if (player != null) {
|
if (player != null) {
|
||||||
restrictHints.add(HintUtils.prepareText("Goaded by " + player.getLogName(), null, HintUtils.HINT_ICON_REQUIRE));
|
restrictHints.add(HintUtils.prepareText("Goaded by " + player.getLogName() + " (must attack)", null, HintUtils.HINT_ICON_REQUIRE));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue