1
0
Fork 0
mirror of https://github.com/correl/mage.git synced 2025-04-08 17:00:07 -09:00

Some improvements to split card handling. Better display of tooltip of split cards, also added handling if not cast from hand.

This commit is contained in:
LevelX2 2013-05-09 21:26:15 +02:00
parent a29dc6cb18
commit b352217e17
11 changed files with 256 additions and 66 deletions
Mage.Client/src/main/java
mage/client/components
org/mage/plugins/card/info
Mage.Common/src/mage/view
Mage.Server.Plugins
Mage.Player.AI/src/main/java/mage/player/ai
Mage.Player.Human/src/mage/player/human
Mage.Server/src/main/java/mage/server/util
Mage/src/mage

View file

@ -40,7 +40,7 @@ public class MageTextArea extends JEditorPane {
buffer.append("pt;margin:3px 3px 3px 3px;color: #FFFFFF'><b><center>");
text = text.replaceAll("#([^#]+)#", "<i>$1</i>");
text = text.replaceAll("\\s*//\\s*", "<hr width='50%'>");
//text = text.replaceAll("\\s*//\\s*", "<hr width='50%'>");
text = text.replace("\r\n", "<div style='font-size:5pt'></div>");
//text += "<br>";

View file

@ -117,11 +117,13 @@ public class CardInfoPaneImpl extends JEditorPane implements CardInfoPane {
buffer.append("pt;margin:0px 1px 0px 1px'>");
buffer.append("<table cellspacing=0 cellpadding=0 border=0 width='100%'>");
buffer.append("<tr><td valign='top'><b>");
buffer.append(card.getName());
buffer.append(card.getDisplayName());
buffer.append("</b></td><td align='right' valign='top' style='width:");
buffer.append(symbolCount * 11 + 1);
buffer.append("px'>");
buffer.append(castingCost);
if (!card.isSplitCard()) {
buffer.append(castingCost);
}
buffer.append("</td></tr></table>");
buffer.append("<table cellspacing=0 cellpadding=0 border=0 width='100%'><tr><td style='margin-left: 1px'>");
buffer.append(getTypes(card));
@ -160,24 +162,49 @@ public class CardInfoPaneImpl extends JEditorPane implements CardInfoPane {
buffer.append("</td></tr></table>");
}
String legal = "";
if (rulings.size() > 0) {
legal = legal.replaceAll("#([^#]+)#", "<i>$1</i>");
legal = legal.replaceAll("\\s*//\\s*", "<hr width='50%'>");
legal = legal.replace("\r\n", "<div style='font-size:5pt'></div>");
legal += "<br>";
for (String ruling : rulings) {
StringBuilder rule = new StringBuilder("<br/>");
if (card.isSplitCard()) {
rule.append("<table cellspacing=0 cellpadding=0 border=0 width='100%'>");
rule.append("<tr><td valign='top'><b>");
rule.append(card.getLeftSplitName());
rule.append("</b></td><td align='right' valign='top' style='width:");
rule.append(card.getLeftSplitCosts().getSymbols().size() * 11 + 1);
rule.append("px'>");
rule.append(card.getLeftSplitCosts().getText());
rule.append("</td></tr></table>");
for (String ruling : card.getLeftSplitRules()) {
if (ruling != null && !ruling.replace(".", "").trim().isEmpty()) {
legal += "<p style='margin: 2px'>";
legal += ruling;
legal += "</p>";
rule.append("<p style='margin: 2px'>").append(ruling).append("</p>");
}
}
rule.append("<table cellspacing=0 cellpadding=0 border=0 width='100%'>");
rule.append("<tr><td valign='top'><b>");
rule.append(card.getRightSplitName());
rule.append("</b></td><td align='right' valign='top' style='width:");
rule.append(card.getRightSplitCosts().getSymbols().size() * 11 + 1);
rule.append("px'>");
rule.append(card.getRightSplitCosts().getText());
rule.append("</td></tr></table>");
for (String ruling : card.getRightSplitRules()) {
if (ruling != null && !ruling.replace(".", "").trim().isEmpty()) {
rule.append("<p style='margin: 2px'>").append(ruling).append("</p>");
}
}
}
if (rulings.size() > 0) {
for (String ruling : rulings) {
if (ruling != null && !ruling.replace(".", "").trim().isEmpty()) {
rule.append("<p style='margin: 2px'>").append(ruling).append("</p>");
}
}
}
String legal = rule.toString();
if (legal.length() > 0) {
//buffer.append("<br>");
// this 2 replaces were only done with the empty string, is it any longer needed? (LevelX2)
// legal = legal.replaceAll("#([^#]+)#", "<i>$1</i>");
// legal = legal.replaceAll("\\s*//\\s*", "<hr width='50%'>");
// legal = legal.replace("\r\n", "<div style='font-size:5pt'></div>");
legal = legal.replaceAll("\\{this\\}", card.getName());
legal = legal.replaceAll("\\{source\\}", card.getName());
buffer.append(ManaSymbols.replaceSymbolsWithHTML(legal, ManaSymbols.Type.CARD));

View file

@ -33,14 +33,11 @@ import mage.Constants.CardType;
import mage.Constants.Rarity;
import mage.MageObject;
import mage.ObjectColor;
import mage.abilities.Mode;
import mage.cards.Card;
import mage.counters.Counter;
import mage.counters.CounterType;
import mage.game.permanent.Permanent;
import mage.game.permanent.PermanentToken;
import mage.game.permanent.token.Token;
import mage.game.stack.Spell;
import mage.game.stack.StackAbility;
import mage.target.Target;
import mage.target.Targets;
@ -48,6 +45,11 @@ import mage.target.Targets;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import mage.abilities.Mode;
import mage.abilities.costs.mana.ManaCosts;
import mage.cards.SplitCard;
import mage.counters.Counter;
import mage.game.stack.Spell;
/**
* @author BetaSteward_at_googlemail.com
@ -57,6 +59,7 @@ public class CardView extends SimpleCardView {
protected UUID parentId;
protected String name;
protected String displayName;
protected List<String> rules;
protected String power;
protected String toughness;
@ -76,6 +79,14 @@ public class CardView extends SimpleCardView {
protected CardView secondCardFace;
protected boolean transformed;
protected boolean isSplitCard;
protected String leftSplitName;
protected ManaCosts leftSplitCosts;
protected List<String> leftSplitRules;
protected String rightSplitName;
protected ManaCosts rightSplitCosts;
protected List<String> rightSplitRules;
protected List<UUID> targets;
protected UUID pairedCard;
@ -95,9 +106,44 @@ public class CardView extends SimpleCardView {
fillEmpty();
return;
}
Card cardHalf = null;
SplitCard splitCard = null;
this.isSplitCard = card.isSplitCard();
if (card instanceof Spell) {
if (((Spell) card).getSpellAbility().getSpellAbilityType().equals(Constants.SpellAbilityType.SPLIT_LEFT)) {
splitCard = (SplitCard) ((Spell) card).getCard();
cardHalf = ((SplitCard) splitCard).getLeftHalfCard();
} else if (((Spell) card).getSpellAbility().getSpellAbilityType().equals(Constants.SpellAbilityType.SPLIT_RIGHT)) {
splitCard = (SplitCard) ((Spell) card).getCard();
cardHalf = ((SplitCard) splitCard).getRightHalfCard();
} else if (((Spell) card).getSpellAbility().getSpellAbilityType().equals(Constants.SpellAbilityType.SPLIT_FUSED)) {
isSplitCard = true;
splitCard = (SplitCard) ((Spell) card).getCard();
}
} else if (card.isSplitCard()) {
splitCard = (SplitCard) card;
}
if (this.isSplitCard && splitCard != null) {
leftSplitName = splitCard.getLeftHalfCard().getName();
leftSplitCosts = splitCard.getLeftHalfCard().getManaCost();
leftSplitRules = splitCard.getLeftHalfCard().getRules();
rightSplitName = splitCard.getRightHalfCard().getName();
rightSplitCosts = splitCard.getRightHalfCard().getManaCost();
rightSplitRules = splitCard.getRightHalfCard().getRules();
}
this.name = card.getName();
this.rules = card.getRules();
if (cardHalf != null) {
this.displayName = cardHalf.getName();
this.rules = cardHalf.getRules();
this.manaCost = cardHalf.getManaCost().getSymbols();
this.convertedManaCost = cardHalf.getManaCost().convertedManaCost();
} else {
this.displayName = card.getName();
this.rules = card.getRules();
this.manaCost = card.getManaCost().getSymbols();
this.convertedManaCost = card.getManaCost().convertedManaCost();
}
if (card instanceof Permanent) {
Permanent permanent = (Permanent)card;
this.power = Integer.toString(card.getPower().getValue());
@ -113,9 +159,9 @@ public class CardView extends SimpleCardView {
this.subTypes = card.getSubtype();
this.superTypes = card.getSupertype();
this.color = card.getColor();
this.manaCost = card.getManaCost().getSymbols();
this.convertedManaCost = card.getManaCost().convertedManaCost();
this.canTransform = card.canTransform();
if (card instanceof PermanentToken) {
this.rarity = Rarity.COMMON;
this.expansionSetCode = ((PermanentToken) card).getExpansionSetCode();
@ -152,7 +198,6 @@ public class CardView extends SimpleCardView {
public CardView(MageObject card) {
super(card.getId(), "", 0, false, false);
this.name = card.getName();
if (card instanceof Permanent) {
this.power = Integer.toString(card.getPower().getValue());
@ -256,6 +301,10 @@ public class CardView extends SimpleCardView {
return name;
}
public String getDisplayName() {
return displayName;
}
public List<String> getRules() {
return rules;
}
@ -381,6 +430,34 @@ public class CardView extends SimpleCardView {
return this.canTransform;
}
public boolean isSplitCard() {
return this.isSplitCard;
}
public String getLeftSplitName() {
return leftSplitName;
}
public ManaCosts getLeftSplitCosts() {
return leftSplitCosts;
}
public List<String> getLeftSplitRules() {
return leftSplitRules;
}
public String getRightSplitName() {
return rightSplitName;
}
public ManaCosts getRightSplitCosts() {
return rightSplitCosts;
}
public List<String> getRightSplitRules() {
return rightSplitRules;
}
public CardView getSecondCardFace() {
return this.secondCardFace;
}

View file

@ -80,6 +80,8 @@ import java.io.IOException;
import java.io.Serializable;
import java.util.*;
import java.util.Map.Entry;
import static mage.Constants.SpellAbilityType.SPLIT;
import static mage.Constants.SpellAbilityType.SPLIT_FUSED;
@ -1204,6 +1206,26 @@ public class ComputerPlayer<T extends ComputerPlayer<T>> extends PlayerImpl<T> i
return 0;
}
@Override
public SpellAbility chooseSpellAbilityForCast(SpellAbility ability, Game game, boolean noMana) {
switch(ability.getSpellAbilityType()) {
case SPLIT:
case SPLIT_FUSED:
MageObject object = game.getObject(ability.getSourceId());
if (object != null) {
LinkedHashMap<UUID, ActivatedAbility> useableAbilities = getSpellAbilities(object, game.getState().getZone(object.getId()), game);
if (useableAbilities != null && useableAbilities.size() > 0) {
game.fireGetChoiceEvent(playerId, name, new ArrayList<ActivatedAbility>(useableAbilities.values()));
// TODO: Improve this
return (SpellAbility) useableAbilities.values().iterator().next();
}
}
return null;
default:
return ability;
}
}
@Override
public Mode chooseMode(Modes modes, Ability source, Game game) {
log.debug("chooseMode");

View file

@ -32,6 +32,8 @@ import java.io.Serializable;
import java.util.*;
import mage.Constants.Outcome;
import mage.Constants.RangeOfInfluence;
import static mage.Constants.SpellAbilityType.SPLIT;
import static mage.Constants.SpellAbilityType.SPLIT_FUSED;
import mage.Constants.Zone;
import mage.MageObject;
import mage.abilities.*;
@ -741,6 +743,32 @@ public class HumanPlayer extends PlayerImpl<HumanPlayer> {
}
}
@Override
public SpellAbility chooseSpellAbilityForCast(SpellAbility ability, Game game, boolean noMana) {
switch(ability.getSpellAbilityType()) {
case SPLIT:
case SPLIT_FUSED:
MageObject object = game.getObject(ability.getSourceId());
if (object != null) {
LinkedHashMap<UUID, ActivatedAbility> useableAbilities = getSpellAbilities(object, game.getState().getZone(object.getId()), game);
if (useableAbilities != null && useableAbilities.size() == 1) {
return (SpellAbility) useableAbilities.values().iterator().next();
} else if (useableAbilities != null && useableAbilities.size() > 0) {
game.fireGetChoiceEvent(playerId, name, new ArrayList<ActivatedAbility>(useableAbilities.values()));
waitForResponse();
if (response.getUUID() != null) {
if (useableAbilities.containsKey(response.getUUID())) {
return (SpellAbility) useableAbilities.get(response.getUUID());
}
}
}
}
return null;
default:
return ability;
}
}
@Override
public Mode chooseMode(Modes modes, Ability source, Game game) {
updateGameStatePriority("chooseMode", game);

View file

@ -39,7 +39,7 @@ public class SystemUtil {
public static void addCardsForTesting(Game game) {
try {
File f = new File(INIT_FILE_PATH);
Pattern pattern = Pattern.compile("([a-zA-Z]*):([\\w]*):([a-zA-Z ,\\-.!'\\d]*):([\\d]*)");
Pattern pattern = Pattern.compile("([a-zA-Z]*):([\\w]*):([a-zA-Z ,\\/\\-.!'\\d]*):([\\d]*)");
if (!f.exists()) {
logger.warn("Couldn't find init file: " + INIT_FILE_PATH);
return;

View file

@ -33,9 +33,7 @@ import mage.Constants.AsThoughEffectType;
import mage.Constants.CardType;
import mage.Constants.Zone;
import mage.MageObject;
import mage.abilities.costs.Cost;
import mage.abilities.costs.mana.ManaCost;
import mage.abilities.effects.Effect;
import mage.abilities.keyword.FlashAbility;
import mage.game.Game;
@ -90,7 +88,9 @@ public class SpellAbility extends ActivatedAbilityImpl<SpellAbility> {
object.getAbilities().containsKey(FlashAbility.getInstance().getId()) ||
game.getContinuousEffects().asThough(sourceId, AsThoughEffectType.CAST, game) ||
game.canPlaySorcery(playerId))) {
if (spellAbilityType.equals(SpellAbilityType.SPLIT)) {
return false;
}
// fix for Gitaxian Probe and casting opponent's spells
if (!controllerId.equals(playerId)) {
return false;

View file

@ -38,8 +38,6 @@ import mage.abilities.Abilities;
import mage.abilities.AbilitiesImpl;
import mage.abilities.Ability;
import mage.abilities.SpellAbility;
import mage.abilities.costs.mana.ManaCosts;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.watchers.Watcher;
/**
@ -108,11 +106,10 @@ public abstract class SplitCard<T extends SplitCard<T>> extends CardImpl<T> {
@Override
public List<String> getRules() {
List<String> rules = new ArrayList<String>();
rules.addAll(leftHalfCard.getRules());
rules.addAll(rightHalfCard.getRules());
// rules.addAll(leftHalfCard.getRules());
// rules.addAll(rightHalfCard.getRules());
if (getSpellAbility().getSpellAbilityType().equals(SpellAbilityType.SPLIT_FUSED)) {
rules.add("--------------------------------------------------------------------------");
rules.add("Fuse (You may cast one or both halves of this card from your hand.)");
rules.add("--------------------------------------------------------------------------\nFuse (You may cast one or both halves of this card from your hand.)");
}
return rules;
}
@ -163,23 +160,24 @@ class LeftHalfCard extends CardImpl<LeftHalfCard> {
return new LeftHalfCard(this);
}
@Override
public List<String> getRules() {
List<String> rules = new ArrayList<String>();
// TODO: Move formatting to client CardInfoPaneImpl.java
StringBuilder buffer = new StringBuilder();
buffer.append("<table cellspacing=0 cellpadding=0 border=0 width='100%'>");
buffer.append("<tr><td valign='top'><b>");
buffer.append(this.getName());
buffer.append("</b></td><td align='right' valign='top' style='width:");
buffer.append(getSpellAbility().getManaCosts().getSymbols().size() * 11 + 1);
buffer.append("px'>");
buffer.append(getSpellAbility().getManaCosts().getText());
buffer.append("</td></tr></table>");
rules.add(buffer.toString());
rules.addAll(super.getRules());
return rules;
}
// @Override
// public List<String> getRules() {
// List<String> rules = new ArrayList<String>();
// // TODO: Move formatting to client CardInfoPaneImpl.java
// StringBuilder buffer = new StringBuilder();
// buffer.append("<table cellspacing=0 cellpadding=0 border=0 width='100%'>");
// buffer.append("<tr><td valign='top'><b>");
// buffer.append(this.getName());
// buffer.append("</b></td><td align='right' valign='top' style='width:");
// buffer.append(getSpellAbility().getManaCosts().getSymbols().size() * 11 + 1);
// buffer.append("px'>");
// buffer.append(getSpellAbility().getManaCosts().getText());
// buffer.append("</td></tr></table>");
//
// rules.add(buffer.toString());
// rules.addAll(super.getRules());
// return rules;
// }
}
@ -202,21 +200,21 @@ class RightHalfCard extends CardImpl<RightHalfCard> {
return new RightHalfCard(this);
}
@Override
public List<String> getRules() {
List<String> rules = new ArrayList<String>();
// TODO: Move formatting to client CardInfoPaneImpl.java
StringBuilder buffer = new StringBuilder();
buffer.append("<table cellspacing=0 cellpadding=0 border=0 width='100%'>");
buffer.append("<tr><td valign='top'><b>");
buffer.append(this.getName());
buffer.append("</b></td><td align='right' valign='top' style='width:");
buffer.append(getSpellAbility().getManaCosts().getSymbols().size() * 11 + 1);
buffer.append("px'>");
buffer.append(getSpellAbility().getManaCosts().getText());
buffer.append("</td></tr></table>");
rules.add(buffer.toString());
rules.addAll(super.getRules());
return rules;
}
// @Override
// public List<String> getRules() {
// List<String> rules = new ArrayList<String>();
// // TODO: Move formatting to client CardInfoPaneImpl.java
// StringBuilder buffer = new StringBuilder();
// buffer.append("<table cellspacing=0 cellpadding=0 border=0 width='100%'>");
// buffer.append("<tr><td valign='top'><b>");
// buffer.append(this.getName());
// buffer.append("</b></td><td align='right' valign='top' style='width:");
// buffer.append(getSpellAbility().getManaCosts().getSymbols().size() * 11 + 1);
// buffer.append("px'>");
// buffer.append(getSpellAbility().getManaCosts().getText());
// buffer.append("</td></tr></table>");
// rules.add(buffer.toString());
// rules.addAll(super.getRules());
// return rules;
// }
}

View file

@ -591,4 +591,8 @@ public class Spell<T extends Spell<T>> implements StackObject, Card {
@Override
public void removeCounters(Counter counter, Game game) {}
public Card getCard() {
return card;
}
}

View file

@ -167,6 +167,7 @@ public interface Player extends MageItem, Copyable<Player> {
int drawCards(int num, Game game);
int drawCards(int num, Game game, ArrayList<UUID> appliedEffects);
boolean cast(SpellAbility ability, Game game, boolean noMana);
SpellAbility chooseSpellAbilityForCast(SpellAbility ability, Game game, boolean noMana);
boolean putInHand(Card card, Game game);
boolean removeFromHand(Card card, Game game);
boolean removeFromBattlefield(Permanent permanent, Game game);

View file

@ -595,6 +595,9 @@ public abstract class PlayerImpl<T extends PlayerImpl<T>> implements Player, Ser
@Override
public boolean cast(SpellAbility ability, Game game, boolean noMana) {
if (!ability.getSpellAbilityType().equals(SpellAbilityType.BASE)) {
ability = chooseSpellAbilityForCast(ability, game, noMana);
}
//20091005 - 601.2a
Card card = game.getCard(ability.getSourceId());
if (card != null) {
@ -618,6 +621,11 @@ public abstract class PlayerImpl<T extends PlayerImpl<T>> implements Player, Ser
return false;
}
@Override
public SpellAbility chooseSpellAbilityForCast(SpellAbility ability, Game game, boolean noMana) {
return ability;
}
@Override
public boolean playLand(Card card, Game game) {
//20091005 - 305.1
@ -775,6 +783,31 @@ public abstract class PlayerImpl<T extends PlayerImpl<T>> implements Player, Ser
return false;
}
protected LinkedHashMap<UUID, ActivatedAbility> getSpellAbilities(MageObject object, Zone zone, Game game) {
LinkedHashMap<UUID, ActivatedAbility> useable = new LinkedHashMap<UUID, ActivatedAbility>();
for (Ability ability: object.getAbilities()) {
if (ability instanceof SpellAbility) {
if (((SpellAbility) ability).getSpellAbilityType().equals(SpellAbilityType.SPLIT_FUSED)) {
if (zone.equals(Zone.HAND)) {
// Fix so you don't need to choose Fuse twice
useable.clear();
useable.put(ability.getId(), (SpellAbility) ability);
return useable;
} else {
// Fuse only allowed from hand
continue;
}
}
if (((SpellAbility) ability).getSpellAbilityType().equals(SpellAbilityType.SPLIT)) {
continue;
}
useable.put(ability.getId(), (SpellAbility) ability);
}
}
return useable;
}
protected LinkedHashMap<UUID, ActivatedAbility> getUseableActivatedAbilities(MageObject object, Zone zone, Game game) {
LinkedHashMap<UUID, ActivatedAbility> useable = new LinkedHashMap<UUID, ActivatedAbility>();
for (ActivatedAbility ability: object.getAbilities().getActivatedAbilities(zone)) {