mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-17 19:28:01 +00:00
Attached: combine Enchant+Equip+Fortify
This commit is contained in:
@@ -767,7 +767,7 @@ public class AiController {
|
||||
// will need actual logic that determines if the enchantment is able
|
||||
// to disable the permanent or it's still functional and a duplicate is unneeded.
|
||||
boolean disabledByEnemy = false;
|
||||
for (Card card2 : card.getEnchantedBy(false)) {
|
||||
for (Card card2 : card.getEnchantedBy()) {
|
||||
if (card2.getOwner() != player) {
|
||||
disabledByEnemy = true;
|
||||
}
|
||||
|
||||
@@ -823,7 +823,7 @@ public class ComputerUtil {
|
||||
|
||||
if (c != null && c.isEnchanted()) {
|
||||
// TODO: choose "worst" controlled enchanting Aura
|
||||
for (Card aura : c.getEnchantedBy(false)) {
|
||||
for (Card aura : c.getEnchantedBy()) {
|
||||
if (aura.getController().equals(c.getController()) && remaining.contains(aura)) {
|
||||
return aura;
|
||||
}
|
||||
@@ -2924,7 +2924,7 @@ public class ComputerUtil {
|
||||
if (sa.getParam("AITgts").equals("BetterThanSource")) {
|
||||
int value = ComputerUtilCard.evaluateCreature(source);
|
||||
if (source.isEnchanted()) {
|
||||
for (Card enc : source.getEnchantedBy(false)) {
|
||||
for (Card enc : source.getEnchantedBy()) {
|
||||
if (enc.getController().equals(ai)) {
|
||||
value += 100; // is 100 per AI's own aura enough?
|
||||
}
|
||||
|
||||
@@ -585,7 +585,7 @@ public class ComputerUtilCard {
|
||||
|
||||
// Add all cost of all auras with the same controller
|
||||
if (card.isEnchanted()) {
|
||||
final List<Card> auras = CardLists.filterControlledBy(card.getEnchantedBy(false), card.getController());
|
||||
final List<Card> auras = CardLists.filterControlledBy(card.getEnchantedBy(), card.getController());
|
||||
curCMC += Aggregates.sum(auras, CardPredicates.Accessors.fnGetCmc) + auras.size();
|
||||
}
|
||||
|
||||
@@ -833,7 +833,7 @@ public class ComputerUtilCard {
|
||||
int score = tmp.isTapped() ? 2 : 0;
|
||||
score += tmp.isBasicLand() ? 1 : 0;
|
||||
score -= tmp.isCreature() ? 4 : 0;
|
||||
for (Card aura : tmp.getEnchantedBy(false)) {
|
||||
for (Card aura : tmp.getEnchantedBy()) {
|
||||
if (aura.getController().isOpponentOf(tmp.getController())) {
|
||||
score += 5;
|
||||
} else {
|
||||
@@ -857,7 +857,7 @@ public class ComputerUtilCard {
|
||||
int score = tmp.isTapped() ? 0 : 2;
|
||||
score += tmp.isBasicLand() ? 2 : 0;
|
||||
score -= tmp.isCreature() ? 4 : 0;
|
||||
score -= 5 * tmp.getEnchantedBy(false).size();
|
||||
score -= 5 * tmp.getEnchantedBy().size();
|
||||
|
||||
if (score >= maxScore) {
|
||||
land = tmp;
|
||||
@@ -1033,7 +1033,7 @@ public class ComputerUtilCard {
|
||||
// interrupt 3: two for one = good
|
||||
if (c.isEnchanted()) {
|
||||
boolean myEnchants = false;
|
||||
for (Card enc : c.getEnchantedBy(false)) {
|
||||
for (Card enc : c.getEnchantedBy()) {
|
||||
if (enc.getOwner().equals(ai)) {
|
||||
myEnchants = true;
|
||||
break;
|
||||
|
||||
@@ -300,7 +300,7 @@ public class ComputerUtilCost {
|
||||
if (!important) {
|
||||
return false;
|
||||
}
|
||||
if (!CardLists.filterControlledBy(source.getEnchantedBy(false), source.getController()).isEmpty()) {
|
||||
if (!CardLists.filterControlledBy(source.getEnchantedBy(), source.getController()).isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
|
||||
@@ -196,9 +196,7 @@ public abstract class GameState {
|
||||
cardsReferencedByID.add(card.getExiledWith());
|
||||
}
|
||||
if (zone == ZoneType.Battlefield) {
|
||||
if (!card.getEnchantedBy(false).isEmpty()
|
||||
|| !card.getEquippedBy(false).isEmpty()
|
||||
|| !card.getFortifiedBy(false).isEmpty()) {
|
||||
if (!card.getAttachedBy().isEmpty()) {
|
||||
// Remember the ID of cards that have attachments
|
||||
cardsReferencedByID.add(card);
|
||||
}
|
||||
@@ -290,12 +288,8 @@ public abstract class GameState {
|
||||
} else if (c.getCurrentStateName().equals(CardStateName.Meld)) {
|
||||
newText.append("|Meld");
|
||||
}
|
||||
if (c.getEquipping() != null) {
|
||||
newText.append("|Attaching:").append(c.getEquipping().getId());
|
||||
} else if (c.getFortifying() != null) {
|
||||
newText.append("|Attaching:").append(c.getFortifying().getId());
|
||||
} else if (c.getEnchantingCard() != null) {
|
||||
newText.append("|Attaching:").append(c.getEnchantingCard().getId());
|
||||
if (c.isAttaching()) {
|
||||
newText.append("|Attaching:").append(c.getAttaching().getId());
|
||||
}
|
||||
if (c.getEnchantingPlayer() != null) {
|
||||
// TODO: improve this for game states with more than two players
|
||||
@@ -959,25 +953,15 @@ public abstract class GameState {
|
||||
// Unattach all permanents first
|
||||
for(Entry<Card, Integer> entry : cardToAttachId.entrySet()) {
|
||||
Card attachedTo = idToCard.get(entry.getValue());
|
||||
|
||||
attachedTo.unEnchantAllCards();
|
||||
attachedTo.unEquipAllCards();
|
||||
for (Card c : attachedTo.getFortifiedBy(true)) {
|
||||
attachedTo.unFortifyCard(c);
|
||||
}
|
||||
attachedTo.unAttachAllCards();
|
||||
}
|
||||
|
||||
// Attach permanents by ID
|
||||
for(Entry<Card, Integer> entry : cardToAttachId.entrySet()) {
|
||||
Card attachedTo = idToCard.get(entry.getValue());
|
||||
Card attacher = entry.getKey();
|
||||
|
||||
if (attacher.isEquipment()) {
|
||||
attacher.equipCard(attachedTo);
|
||||
} else if (attacher.isAura()) {
|
||||
attacher.enchantEntity(attachedTo);
|
||||
} else if (attacher.isFortified()) {
|
||||
attacher.fortifyCard(attachedTo);
|
||||
if (attacher.isAttachment()) {
|
||||
attacher.attachEntity(attachedTo);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -988,7 +972,7 @@ public abstract class GameState {
|
||||
Game game = attacher.getGame();
|
||||
Player attachedTo = entry.getValue() == TARGET_AI ? game.getPlayers().get(1) : game.getPlayers().get(0);
|
||||
|
||||
attacher.enchantEntity(attachedTo);
|
||||
attacher.attachEntity(attachedTo);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1043,7 +1027,9 @@ public abstract class GameState {
|
||||
if (c.isAura()) {
|
||||
// dummy "enchanting" to indicate that the card will be force-attached elsewhere
|
||||
// (will be overridden later, so the actual value shouldn't matter)
|
||||
c.setEnchanting(c);
|
||||
|
||||
//FIXME it shouldn't be able to attach itself
|
||||
c.setAttaching(c);
|
||||
}
|
||||
|
||||
if (cardsWithoutETBTrigs.contains(c)) {
|
||||
|
||||
@@ -408,7 +408,7 @@ public class AttachAi extends SpellAbilityAi {
|
||||
return true;
|
||||
}
|
||||
|
||||
final Iterable<Card> auras = c.getEnchantedBy(false);
|
||||
final Iterable<Card> auras = c.getEnchantedBy();
|
||||
final Iterator<Card> itr = auras.iterator();
|
||||
while (itr.hasNext()) {
|
||||
final Card aura = itr.next();
|
||||
@@ -1276,7 +1276,7 @@ public class AttachAi extends SpellAbilityAi {
|
||||
return null;
|
||||
}
|
||||
// Don't fortify if already fortifying
|
||||
if (attachSource.getFortifying() != null && attachSource.getFortifying().getController() == aiPlayer) {
|
||||
if (attachSource.getAttachingCard() != null && attachSource.getAttachingCard().getController() == aiPlayer) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1491,7 +1491,7 @@ public class AttachAi extends SpellAbilityAi {
|
||||
return false;
|
||||
}
|
||||
// Also don't play if it would destroy own Aura
|
||||
for (Card c : card.getEnchantedBy(false)) {
|
||||
for (Card c : card.getEnchantedBy()) {
|
||||
if ((c.getController().equals(ai)) && (c.isOfColor(cc))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -159,7 +159,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
|
||||
return true; // debuffed by opponent's auras to the level that it becomes useless
|
||||
}
|
||||
int delta = 0;
|
||||
for (Card enc : sa.getHostCard().getEnchantedBy(false)) {
|
||||
for (Card enc : sa.getHostCard().getEnchantedBy()) {
|
||||
if (enc.getController().isOpponentOf(aiPlayer)) {
|
||||
delta--;
|
||||
} else {
|
||||
@@ -961,7 +961,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
|
||||
list = CardLists.filter(list, new Predicate<Card>() {
|
||||
@Override
|
||||
public boolean apply(final Card c) {
|
||||
for (Card aura : c.getEnchantedBy(false)) {
|
||||
for (Card aura : c.getEnchantedBy()) {
|
||||
if (aura.getController().isOpponentOf(ai)) {
|
||||
return true;
|
||||
} else {
|
||||
@@ -1054,7 +1054,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
|
||||
list = CardLists.filter(list, new Predicate<Card>() {
|
||||
@Override
|
||||
public boolean apply(final Card c) {
|
||||
for (Card aura : c.getEnchantedBy(false)) {
|
||||
for (Card aura : c.getEnchantedBy()) {
|
||||
if (c.getOwner().isOpponentOf(ai) && aura.getController().equals(ai)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ public class CountersPutAi extends SpellAbilityAi {
|
||||
if (sa.hasParam("LevelUp")) {
|
||||
// creatures enchanted by curse auras have low priority
|
||||
if (ph.getPhase().isBefore(PhaseType.MAIN2)) {
|
||||
for (Card aura : source.getEnchantedBy(false)) {
|
||||
for (Card aura : source.getEnchantedBy()) {
|
||||
if (aura.getController().isOpponentOf(ai)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ public abstract class DamageAiBase extends SpellAbilityAi {
|
||||
Card hostcard = sa.getHostCard();
|
||||
boolean lifelink = hostcard.hasKeyword(Keyword.LIFELINK);
|
||||
if (!lifelink) {
|
||||
for (Card ench : hostcard.getEnchantedBy(false)) {
|
||||
for (Card ench : hostcard.getEnchantedBy()) {
|
||||
// Treat cards enchanted by older cards with "when enchanted creature deals damage, gain life" as if they had lifelink.
|
||||
if (ench.hasSVar("LikeLifeLink")) {
|
||||
if ("True".equals(ench.getSVar("LikeLifeLink"))) {
|
||||
|
||||
@@ -273,7 +273,7 @@ public class DestroyAi extends SpellAbilityAi {
|
||||
} else {
|
||||
// Don't destroy stolen permanents when the stealing aura can be destroyed
|
||||
if (choice.getOwner() == ai) {
|
||||
for (Card aura : choice.getEnchantedBy(false)) {
|
||||
for (Card aura : choice.getEnchantedBy()) {
|
||||
SpellAbility sp = aura.getFirstSpellAbility();
|
||||
if (sp != null && "GainControl".equals(sp.getParam("AILogic"))
|
||||
&& aura.getController() != ai && sa.canTarget(aura)) {
|
||||
|
||||
@@ -192,10 +192,10 @@ public class PermanentAi extends SpellAbilityAi {
|
||||
// be better to have a pristine copy of the card - might not always be a correct assumption, but sounds
|
||||
// like a reasonable default for some cards).
|
||||
for (Card c : ctrld) {
|
||||
if (c.getEnchantedBy(false).isEmpty()) {
|
||||
if (c.getEnchantedBy().isEmpty()) {
|
||||
numControlled++;
|
||||
} else {
|
||||
for (Card att : c.getEnchantedBy(false)) {
|
||||
for (Card att : c.getEnchantedBy()) {
|
||||
if (!att.getController().isOpponentOf(ai)) {
|
||||
numControlled++;
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import forge.LobbyPlayer;
|
||||
import forge.ai.LobbyPlayerAi;
|
||||
import forge.card.CardStateName;
|
||||
import forge.game.Game;
|
||||
import forge.game.GameEntity;
|
||||
import forge.game.GameObject;
|
||||
import forge.game.GameObjectMap;
|
||||
import forge.game.GameRules;
|
||||
@@ -204,19 +205,16 @@ public class GameCopier {
|
||||
}
|
||||
}
|
||||
gameObjectMap = new CopiedGameObjectMap(newGame);
|
||||
|
||||
for (Card card : origGame.getCardsIn(ZoneType.Battlefield)) {
|
||||
Card otherCard = cardMap.get(card);
|
||||
otherCard.setTimestamp(card.getTimestamp());
|
||||
otherCard.setSickness(card.hasSickness());
|
||||
otherCard.setState(card.getCurrentStateName(), false);
|
||||
if (card.isEnchanting()) {
|
||||
otherCard.setEnchanting(gameObjectMap.map(card.getEnchanting()));
|
||||
}
|
||||
if (card.isEquipping()) {
|
||||
otherCard.equipCard(cardMap.get(card.getEquipping()));
|
||||
}
|
||||
if (card.isFortifying()) {
|
||||
otherCard.setFortifying(cardMap.get(card.getFortifying()));
|
||||
if (card.isAttaching()) {
|
||||
GameEntity ge = gameObjectMap.map(card.getAttaching());
|
||||
otherCard.setAttaching(ge);
|
||||
ge.addAttachedBy(otherCard);
|
||||
}
|
||||
if (card.getCloneOrigin() != null) {
|
||||
otherCard.setCloneOrigin(cardMap.get(card.getCloneOrigin()));
|
||||
|
||||
@@ -36,7 +36,6 @@ import forge.game.replacement.ReplacementResult;
|
||||
import forge.game.spellability.AbilitySub;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.spellability.SpellAbilityPredicates;
|
||||
import forge.game.spellability.TargetRestrictions;
|
||||
import forge.game.staticability.StaticAbility;
|
||||
import forge.game.staticability.StaticAbilityLayer;
|
||||
import forge.game.trigger.Trigger;
|
||||
@@ -504,45 +503,12 @@ public class GameAction {
|
||||
}
|
||||
|
||||
private static void unattachCardLeavingBattlefield(final Card copied) {
|
||||
// Handle unequipping creatures
|
||||
if (copied.isEquipped()) {
|
||||
for (final Card equipment : copied.getEquippedBy(true)) {
|
||||
if (equipment.isInPlay()) {
|
||||
equipment.unEquipCard(copied);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Handle unfortifying lands
|
||||
if (copied.isFortified()) {
|
||||
for (final Card f : copied.getFortifiedBy(true)) {
|
||||
if (f.isInPlay()) {
|
||||
f.unFortifyCard(copied);
|
||||
}
|
||||
}
|
||||
}
|
||||
// equipment moving off battlefield
|
||||
if (copied.isEquipping()) {
|
||||
final Card equippedCreature = copied.getEquipping();
|
||||
if (equippedCreature.isInPlay()) {
|
||||
copied.unEquipCard(equippedCreature);
|
||||
}
|
||||
}
|
||||
// fortifications moving off battlefield
|
||||
if (copied.isFortifying()) {
|
||||
final Card fortifiedLand = copied.getFortifying();
|
||||
if (fortifiedLand.isInPlay()) {
|
||||
copied.unFortifyCard(fortifiedLand);
|
||||
}
|
||||
}
|
||||
// remove enchantments from creatures
|
||||
if (copied.isEnchanted()) {
|
||||
for (final Card aura : copied.getEnchantedBy(true)) {
|
||||
aura.unEnchantEntity(copied);
|
||||
}
|
||||
}
|
||||
// remove attachments from creatures
|
||||
copied.unAttachAllCards();
|
||||
|
||||
// unenchant creature if moving aura
|
||||
if (copied.isEnchanting()) {
|
||||
copied.unEnchantEntity(copied.getEnchanting());
|
||||
if (copied.isAttaching()) {
|
||||
copied.unAttachEntity(copied.getAttaching());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1006,11 +972,10 @@ public class GameAction {
|
||||
}
|
||||
|
||||
checkAgain |= stateBasedAction_Saga(c);
|
||||
checkAgain |= stateBasedAction704_5n(c); // Auras attached to illegal or not attached go to graveyard
|
||||
checkAgain |= stateBasedAction704_5p(c); // Equipment and Fortifications
|
||||
checkAgain |= stateBasedAction704_attach(c); // Attachment
|
||||
|
||||
if (c.isCreature() && c.isEnchanting()) { // Rule 704.5q - Creature attached to an object or player, becomes unattached
|
||||
c.unEnchantEntity(c.getEnchanting());
|
||||
if (c.isCreature() && c.isAttaching()) { // Rule 704.5q - Creature attached to an object or player, becomes unattached
|
||||
c.unAttachEntity(c.getAttaching());
|
||||
checkAgain = true;
|
||||
}
|
||||
|
||||
@@ -1124,107 +1089,31 @@ public class GameAction {
|
||||
return checkAgain;
|
||||
}
|
||||
|
||||
private boolean stateBasedAction704_5n(Card c) {
|
||||
private boolean stateBasedAction704_attach(Card c) {
|
||||
boolean checkAgain = false;
|
||||
if (!c.isAura()) {
|
||||
return false;
|
||||
|
||||
if (c.isAttaching()) {
|
||||
final GameEntity ge = c.getAttaching();
|
||||
if (!ge.canBeAttachedBy(c)) {
|
||||
c.unAttachEntity(ge);
|
||||
checkAgain = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if Card Aura is attached to is a legal target
|
||||
final GameEntity entity = c.getEnchanting();
|
||||
SpellAbility sa = c.getFirstAttachSpell();
|
||||
|
||||
TargetRestrictions tgt = null;
|
||||
if (sa != null) {
|
||||
tgt = sa.getTargetRestrictions();
|
||||
if (c.isAttachedBy()) {
|
||||
for (final Card attach : Lists.newArrayList(c.getAttachedBy())) {
|
||||
if (!attach.isInPlay()) {
|
||||
attach.unAttachEntity(c);
|
||||
checkAgain = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (entity instanceof Card) {
|
||||
final Card perm = (Card) entity;
|
||||
final ZoneType tgtZone = tgt.getZone().get(0);
|
||||
|
||||
if (!perm.isInZone(tgtZone) || !perm.canBeEnchantedBy(c, true) || (perm.isPhasedOut() && !c.isPhasedOut())) {
|
||||
c.unEnchantEntity(perm);
|
||||
// cleanup aura
|
||||
if (c.isAura() && c.isInPlay() && !c.isEnchanting()) {
|
||||
moveToGraveyard(c, null, null);
|
||||
checkAgain = true;
|
||||
}
|
||||
} else if (entity instanceof Player) {
|
||||
final Player pl = (Player) entity;
|
||||
boolean invalid = false;
|
||||
|
||||
if (!game.getPlayers().contains(pl)) {
|
||||
// lost player can't have Aura on it
|
||||
invalid = true;
|
||||
} else if (tgt.canOnlyTgtOpponent() && !c.getController().isOpponentOf(pl)) {
|
||||
invalid = true;
|
||||
}
|
||||
else if (pl.hasProtectionFrom(c)) {
|
||||
invalid = true;
|
||||
}
|
||||
if (invalid) {
|
||||
c.unEnchantEntity(pl);
|
||||
moveToGraveyard(c, null, null);
|
||||
checkAgain = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (c.isInPlay() && !c.isEnchanting()) {
|
||||
moveToGraveyard(c, null, null);
|
||||
checkAgain = true;
|
||||
}
|
||||
return checkAgain;
|
||||
}
|
||||
|
||||
private boolean stateBasedAction704_5p(Card c) {
|
||||
boolean checkAgain = false;
|
||||
if (c.isEquipped()) {
|
||||
for (final Card equipment : c.getEquippedBy(true)) {
|
||||
if (!equipment.isInPlay()) {
|
||||
equipment.unEquipCard(c);
|
||||
checkAgain = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (c.isFortified()) {
|
||||
for (final Card f : c.getFortifiedBy(true)) {
|
||||
if (!f.isInPlay()) {
|
||||
f.unFortifyCard(c);
|
||||
checkAgain = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (c.isEquipping()) {
|
||||
final Card equippedCreature = c.getEquipping();
|
||||
if (!equippedCreature.isCreature() || !equippedCreature.isInPlay()
|
||||
|| !equippedCreature.canBeEquippedBy(c)
|
||||
|| (equippedCreature.isPhasedOut() && !c.isPhasedOut())
|
||||
|| !c.isEquipment()) {
|
||||
c.unEquipCard(equippedCreature);
|
||||
checkAgain = true;
|
||||
}
|
||||
// make sure any equipment that has become a creature stops equipping
|
||||
if (c.isCreature()) {
|
||||
c.unEquipCard(equippedCreature);
|
||||
checkAgain = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (c.isFortifying()) {
|
||||
final Card fortifiedLand = c.getFortifying();
|
||||
if (!fortifiedLand.isLand() || !fortifiedLand.isInPlay()
|
||||
|| (fortifiedLand.isPhasedOut() && !c.isPhasedOut())
|
||||
|| !c.isFortification()) {
|
||||
c.unFortifyCard(fortifiedLand);
|
||||
checkAgain = true;
|
||||
}
|
||||
// make sure any fortification that has become a creature stops fortifying
|
||||
if (c.isCreature()) {
|
||||
c.unFortifyCard(fortifiedLand);
|
||||
checkAgain = true;
|
||||
}
|
||||
}
|
||||
return checkAgain;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,9 +21,10 @@ import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardCollectionView;
|
||||
import forge.game.card.CardDamageMap;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.card.CardPredicates;
|
||||
import forge.game.card.CounterType;
|
||||
import forge.game.event.GameEventCardAttachment;
|
||||
import forge.game.event.GameEventCardAttachment.AttachMethod;
|
||||
import forge.game.keyword.Keyword;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
@@ -33,6 +34,7 @@ import forge.util.collect.FCollection;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
|
||||
@@ -40,7 +42,7 @@ public abstract class GameEntity extends GameObject implements IIdentifiable {
|
||||
protected final int id;
|
||||
private String name = "";
|
||||
private int preventNextDamage = 0;
|
||||
private CardCollection enchantedBy;
|
||||
protected CardCollection attachedBy;
|
||||
private Map<Card, Map<String, String>> preventionShieldsWithEffects = Maps.newTreeMap();
|
||||
protected Map<CounterType, Integer> counters = Maps.newEnumMap(CounterType.class);
|
||||
|
||||
@@ -280,77 +282,140 @@ public abstract class GameEntity extends GameObject implements IIdentifiable {
|
||||
public abstract boolean hasKeyword(final String keyword);
|
||||
public abstract boolean hasKeyword(final Keyword keyword);
|
||||
|
||||
// GameEntities can now be Enchanted
|
||||
public final CardCollectionView getEnchantedBy(boolean allowModify) {
|
||||
return CardCollection.getView(enchantedBy, allowModify);
|
||||
public final CardCollectionView getEnchantedBy() {
|
||||
if (attachedBy == null) {
|
||||
return CardCollection.EMPTY;
|
||||
}
|
||||
public final void setEnchantedBy(final CardCollection cards) {
|
||||
enchantedBy = cards;
|
||||
getView().updateEnchantedBy(this);
|
||||
// enchanted means attached by Aura
|
||||
return CardLists.filter(attachedBy, CardPredicates.Presets.AURA);
|
||||
}
|
||||
public final void setEnchantedBy(final Iterable<Card> cards) {
|
||||
|
||||
public final CardCollectionView getAttachedBy() {
|
||||
return CardCollection.getView(attachedBy);
|
||||
}
|
||||
|
||||
public final void setAttachedBy(final Iterable<Card> cards) {
|
||||
if (cards == null) {
|
||||
enchantedBy = null;
|
||||
attachedBy = null;
|
||||
}
|
||||
else {
|
||||
enchantedBy = new CardCollection(cards);
|
||||
attachedBy = new CardCollection(cards);
|
||||
}
|
||||
getView().updateEnchantedBy(this);
|
||||
|
||||
getView().updateAttachedBy(this);
|
||||
}
|
||||
|
||||
public final boolean isAttachedBy() {
|
||||
return FCollection.hasElements(attachedBy);
|
||||
}
|
||||
|
||||
public final boolean isEnchanted() {
|
||||
return FCollection.hasElements(enchantedBy);
|
||||
}
|
||||
public final boolean isEnchantedBy(Card c) {
|
||||
return FCollection.hasElement(enchantedBy, c);
|
||||
}
|
||||
public final boolean isEnchantedBy(final String cardName) {
|
||||
for (final Card aura : getEnchantedBy(false)) {
|
||||
if (aura.getName().equals(cardName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (attachedBy == null) {
|
||||
return false;
|
||||
}
|
||||
public final void addEnchantedBy(final Card c) {
|
||||
if (enchantedBy == null) {
|
||||
enchantedBy = new CardCollection();
|
||||
}
|
||||
if (enchantedBy.add(c)) {
|
||||
getView().updateEnchantedBy(this);
|
||||
getGame().fireEvent(new GameEventCardAttachment(c, null, this, AttachMethod.Enchant));
|
||||
}
|
||||
}
|
||||
public final void removeEnchantedBy(final Card c) {
|
||||
if (enchantedBy == null) { return; }
|
||||
|
||||
if (enchantedBy.remove(c)) {
|
||||
if (enchantedBy.isEmpty()) {
|
||||
enchantedBy = null;
|
||||
// enchanted means attached by Aura
|
||||
return CardLists.count(attachedBy, CardPredicates.Presets.AURA) > 0;
|
||||
}
|
||||
getView().updateEnchantedBy(this);
|
||||
getGame().fireEvent(new GameEventCardAttachment(c, this, null, AttachMethod.Enchant));
|
||||
|
||||
public final boolean isAttachedBy(Card c) {
|
||||
return FCollection.hasElement(attachedBy, c);
|
||||
}
|
||||
public final boolean isEnchantedBy(Card c) {
|
||||
// Rule 303.4k Even if c is no Aura it still counts
|
||||
return isAttachedBy(c);
|
||||
}
|
||||
public final void unEnchantAllCards() {
|
||||
if (isEnchanted()) {
|
||||
for (Card c : getEnchantedBy(true)) {
|
||||
c.unEnchantEntity(this);
|
||||
|
||||
public final boolean isAttachedBy(final String cardName) {
|
||||
if (attachedBy == null) {
|
||||
return false;
|
||||
}
|
||||
return CardLists.count(getAttachedBy(), CardPredicates.nameEquals(cardName)) > 0;
|
||||
}
|
||||
public final boolean isEnchantedBy(final String cardName) {
|
||||
// Rule 303.4k Even if c is no Aura it still counts
|
||||
return isAttachedBy(cardName);
|
||||
}
|
||||
|
||||
public final void addAttachedBy(final Card c) {
|
||||
if (attachedBy == null) {
|
||||
attachedBy = new CardCollection();
|
||||
}
|
||||
|
||||
if (attachedBy.add(c)) {
|
||||
getView().updateAttachedBy(this);
|
||||
getGame().fireEvent(new GameEventCardAttachment(c, null, this));
|
||||
}
|
||||
}
|
||||
|
||||
public boolean canBeEnchantedBy(final Card aura) {
|
||||
public final void removeAttachedBy(final Card c) {
|
||||
if (attachedBy == null) { return; }
|
||||
|
||||
if (attachedBy.remove(c)) {
|
||||
if (attachedBy.isEmpty()) {
|
||||
attachedBy = null;
|
||||
}
|
||||
getView().updateAttachedBy(this);
|
||||
getGame().fireEvent(new GameEventCardAttachment(c, this, null));
|
||||
}
|
||||
}
|
||||
|
||||
public final void unAttachAllCards() {
|
||||
for (Card c : Lists.newArrayList(getAttachedBy())) {
|
||||
c.unAttachEntity(this);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean canBeAttachedBy(final Card attach) {
|
||||
return canBeAttachedBy(attach, false);
|
||||
}
|
||||
|
||||
public boolean canBeAttachedBy(final Card attach, boolean checkSBA) {
|
||||
// master mode
|
||||
if (!attach.isAttachment()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (attach.isAura() && !canBeEnchantedBy(attach, checkSBA)) {
|
||||
return false;
|
||||
}
|
||||
if (attach.isEquipment() && !canBeEquippedBy(attach)) {
|
||||
return false;
|
||||
}
|
||||
if (attach.isFortification() && !canBeFortifiedBy(attach)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean canBeEquippedBy(final Card aura) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean canBeFortifiedBy(final Card aura) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean canBeEnchantedBy(final Card aura, final boolean checkSBA) {
|
||||
if (!aura.isAura()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SpellAbility sa = aura.getFirstAttachSpell();
|
||||
TargetRestrictions tgt = null;
|
||||
if (sa != null) {
|
||||
tgt = sa.getTargetRestrictions();
|
||||
}
|
||||
|
||||
return !(hasProtectionFrom(aura)
|
||||
return !(hasProtectionFrom(aura, checkSBA)
|
||||
|| ((tgt != null) && !isValid(tgt.getValidTgts(), aura.getController(), aura, sa)));
|
||||
}
|
||||
|
||||
public abstract boolean hasProtectionFrom(final Card source);
|
||||
public boolean hasProtectionFrom(final Card source) {
|
||||
return hasProtectionFrom(source, false);
|
||||
}
|
||||
|
||||
public abstract boolean hasProtectionFrom(final Card source, final boolean checkSBA);
|
||||
|
||||
// Counters!
|
||||
public boolean hasCounters() {
|
||||
|
||||
@@ -42,18 +42,19 @@ public abstract class GameEntityView extends TrackableObject {
|
||||
set(TrackableProperty.PreventNextDamage, e.getPreventNextDamageTotalShields());
|
||||
}
|
||||
|
||||
public Iterable<CardView> getEnchantedBy() {
|
||||
return get(TrackableProperty.EnchantedBy);
|
||||
public Iterable<CardView> getAttachedBy() {
|
||||
return get(TrackableProperty.AttachedBy);
|
||||
}
|
||||
protected void updateEnchantedBy(GameEntity e) {
|
||||
if (e.isEnchanted()) {
|
||||
set(TrackableProperty.EnchantedBy, CardView.getCollection(e.getEnchantedBy(false)));
|
||||
public boolean isAttached() {
|
||||
return getAttachedBy() != null;
|
||||
}
|
||||
|
||||
protected void updateAttachedBy(GameEntity e) {
|
||||
if (e.isAttachedBy()) {
|
||||
set(TrackableProperty.AttachedBy, CardView.getCollection(e.getAttachedBy()));
|
||||
}
|
||||
else {
|
||||
set(TrackableProperty.EnchantedBy, null);
|
||||
set(TrackableProperty.AttachedBy, null);
|
||||
}
|
||||
}
|
||||
public boolean isEnchanted() {
|
||||
return getEnchantedBy() != null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,12 +104,8 @@ public class AttachEffect extends SpellAbilityEffect {
|
||||
if (c.canBeEnchantedBy(card)) {
|
||||
handleAura(card, c);
|
||||
}
|
||||
} else if (card.isEquipment()) {
|
||||
if(c.canBeEquippedBy(card)) {
|
||||
card.equipCard(c);
|
||||
}
|
||||
} else if (card.isFortification()) {
|
||||
card.fortifyCard(c);
|
||||
} else {
|
||||
card.attachEntity(c);
|
||||
}
|
||||
} else if (o instanceof Player) {
|
||||
// Currently, a few cards can enchant players
|
||||
@@ -131,30 +127,22 @@ public class AttachEffect extends SpellAbilityEffect {
|
||||
* the tgt
|
||||
*/
|
||||
public static void handleAura(final Card card, final GameEntity tgt) {
|
||||
if (card.isEnchanting()) {
|
||||
// If this Card is already Enchanting something
|
||||
// Need to unenchant it, then clear out the commands
|
||||
final GameEntity oldEnchanted = card.getEnchanting();
|
||||
oldEnchanted.removeEnchantedBy(card);
|
||||
card.removeEnchanting(oldEnchanted);
|
||||
}
|
||||
|
||||
final GameCommand onLeavesPlay = new GameCommand() {
|
||||
private static final long serialVersionUID = -639204333673364477L;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
final GameEntity entity = card.getEnchanting();
|
||||
final GameEntity entity = card.getAttaching();
|
||||
if (entity == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
card.unEnchantEntity(entity);
|
||||
card.unAttachEntity(entity);
|
||||
}
|
||||
}; // Command
|
||||
|
||||
card.addLeavesPlayCommand(onLeavesPlay);
|
||||
card.enchantEntity(tgt);
|
||||
card.attachEntity(tgt);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -504,29 +504,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
|
||||
}
|
||||
if (!list.isEmpty()) {
|
||||
Card attachedTo = player.getController().chooseSingleEntityForEffect(list, sa, tgtC + " - Select a card to attach to.");
|
||||
if (tgtC.isAura()) {
|
||||
if (tgtC.isEnchanting()) {
|
||||
// If this Card is already Enchanting something, need
|
||||
// to unenchant it, then clear out the commands
|
||||
final GameEntity oldEnchanted = tgtC.getEnchanting();
|
||||
tgtC.removeEnchanting(oldEnchanted);
|
||||
}
|
||||
tgtC.enchantEntity(attachedTo);
|
||||
} else if (tgtC.isEquipment()) { //Equipment
|
||||
if (tgtC.isEquipping()) {
|
||||
final Card oldEquiped = tgtC.getEquipping();
|
||||
if ( null != oldEquiped )
|
||||
tgtC.unEquipCard(oldEquiped);
|
||||
}
|
||||
tgtC.equipCard(attachedTo);
|
||||
} else { // fortification
|
||||
if (tgtC.isFortifying()) {
|
||||
final Card oldFortified = tgtC.getFortifying();
|
||||
if( oldFortified != null )
|
||||
tgtC.unFortifyCard(oldFortified);
|
||||
}
|
||||
tgtC.fortifyCard(attachedTo);
|
||||
}
|
||||
tgtC.attachEntity(attachedTo);
|
||||
} else { // When it should enter the battlefield attached to an illegal permanent it fails
|
||||
continue;
|
||||
}
|
||||
@@ -536,15 +514,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
|
||||
FCollectionView<Player> list = AbilityUtils.getDefinedPlayers(hostCard, sa.getParam("AttachedToPlayer"), sa);
|
||||
if (!list.isEmpty()) {
|
||||
Player attachedTo = player.getController().chooseSingleEntityForEffect(list, sa, tgtC + " - Select a player to attach to.");
|
||||
if (tgtC.isAura()) {
|
||||
if (tgtC.isEnchanting()) {
|
||||
// If this Card is already Enchanting something, need
|
||||
// to unenchant it, then clear out the commands
|
||||
final GameEntity oldEnchanted = tgtC.getEnchanting();
|
||||
tgtC.removeEnchanting(oldEnchanted);
|
||||
}
|
||||
tgtC.enchantEntity(attachedTo);
|
||||
}
|
||||
tgtC.attachEntity(attachedTo);
|
||||
}
|
||||
else { // When it should enter the battlefield attached to an illegal player it fails
|
||||
continue;
|
||||
@@ -1022,42 +992,9 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
|
||||
else {
|
||||
attachedTo = list.get(0);
|
||||
}
|
||||
if (c.isAura()) {
|
||||
if (c.isEnchanting()) {
|
||||
// If this Card is already Enchanting something, need
|
||||
// to unenchant it, then clear out the commands
|
||||
final GameEntity oldEnchanted = c.getEnchanting();
|
||||
c.removeEnchanting(oldEnchanted);
|
||||
}
|
||||
// TODO: this should ideally be handled with !attachedTo.canBeEnchantedBy(c), but the relevant function is not adapted
|
||||
// for corner cases tested here and modifying it to accomodate these situations (e.g. Boonweaver Giant + Animate Dead)
|
||||
// tends to break other things.
|
||||
if (!checkCanIndirectlyAttachTo(c, attachedTo)) {
|
||||
// if an aura can't enchant the source, it shouldn't move (303.4i, 303.4j)
|
||||
continue;
|
||||
}
|
||||
if ( ((c.hasKeyword("Enchant creature card in a graveyard") || c.hasKeyword("Enchant instant card in a graveyard")) && !attachedTo.getZone().is(ZoneType.Graveyard))
|
||||
|| !attachedTo.getZone().is(ZoneType.Battlefield)) {
|
||||
// if the source of the effect is no longer in the zone where it can be enchanted, aura does not move
|
||||
continue;
|
||||
}
|
||||
c.enchantEntity(attachedTo);
|
||||
}
|
||||
else if (c.isEquipment()) { //Equipment
|
||||
if (c.isEquipping()) {
|
||||
final Card oldEquiped = c.getEquipping();
|
||||
if ( null != oldEquiped )
|
||||
c.unEquipCard(oldEquiped);
|
||||
}
|
||||
c.equipCard(attachedTo);
|
||||
}
|
||||
else {
|
||||
if (c.isFortifying()) {
|
||||
final Card oldFortified = c.getFortifying();
|
||||
if ( null != oldFortified )
|
||||
c.unFortifyCard(oldFortified);
|
||||
}
|
||||
c.fortifyCard(attachedTo);
|
||||
|
||||
if (c.isAttachment()) {
|
||||
c.attachEntity(attachedTo);
|
||||
}
|
||||
}
|
||||
else { // When it should enter the battlefield attached to an illegal permanent it fails
|
||||
@@ -1069,15 +1006,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
|
||||
FCollectionView<Player> list = AbilityUtils.getDefinedPlayers(source, sa.getParam("AttachedToPlayer"), sa);
|
||||
if (!list.isEmpty()) {
|
||||
Player attachedTo = player.getController().chooseSingleEntityForEffect(list, sa, c + " - Select a player to attach to.");
|
||||
if (c.isAura()) {
|
||||
if (c.isEnchanting()) {
|
||||
// If this Card is already Enchanting something, need
|
||||
// to unenchant it, then clear out the commands
|
||||
final GameEntity oldEnchanted = c.getEnchanting();
|
||||
c.removeEnchanting(oldEnchanted);
|
||||
}
|
||||
c.enchantEntity(attachedTo);
|
||||
}
|
||||
c.attachEntity(attachedTo);
|
||||
}
|
||||
else { // When it should enter the battlefield attached to an illegal permanent it fails
|
||||
continue;
|
||||
|
||||
@@ -238,21 +238,8 @@ public class CopyPermanentEffect extends SpellAbilityEffect {
|
||||
}
|
||||
if (!list.isEmpty()) {
|
||||
Card attachedTo = activator.getController().chooseSingleEntityForEffect(list, sa, copyInPlay + " - Select a card to attach to.");
|
||||
if (copyInPlay.isAura()) {
|
||||
if (attachedTo.canBeEnchantedBy(copyInPlay)) {
|
||||
copyInPlay.enchantEntity(attachedTo);
|
||||
} else {//can't enchant
|
||||
continue;
|
||||
}
|
||||
} else if (copyInPlay.isEquipment()) { //Equipment
|
||||
if (attachedTo.canBeEquippedBy(copyInPlay)) {
|
||||
copyInPlay.equipCard(attachedTo);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
} else { // Fortification
|
||||
copyInPlay.fortifyCard(attachedTo);
|
||||
}
|
||||
|
||||
copyInPlay.attachEntity(attachedTo);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -95,9 +95,7 @@ public class DestroyEffect extends SpellAbilityEffect {
|
||||
boolean destroyed = false;
|
||||
final Card lki = CardUtil.getLKICopy(tgtC);
|
||||
if (remAttached) {
|
||||
card.addRemembered(tgtC.getEnchantedBy(false));
|
||||
card.addRemembered(tgtC.getEquippedBy(false));
|
||||
card.addRemembered(tgtC.getFortifiedBy(false));
|
||||
card.addRemembered(tgtC.getAttachedBy());
|
||||
}
|
||||
if (sac) {
|
||||
destroyed = game.getAction().sacrifice(tgtC, sa) != null;
|
||||
|
||||
@@ -495,33 +495,11 @@ public class TokenEffect extends SpellAbilityEffect {
|
||||
game.getAction().checkStaticAbilities(false, Sets.newHashSet(lki), preList);
|
||||
|
||||
// TODO update when doing Attach Update
|
||||
boolean canAttach = lki.isAura() || lki.isEquipment() || lki.isFortification();
|
||||
boolean canAttach = lki.isAttachment();
|
||||
|
||||
if (lki.isAura()) {
|
||||
if (!ge.canBeEnchantedBy(lki)) {
|
||||
if (canAttach && ge.canBeAttachedBy(lki)) {
|
||||
canAttach = false;
|
||||
}
|
||||
}
|
||||
if (lki.isEquipment()) {
|
||||
if (ge instanceof Card) {
|
||||
Card gc = (Card) ge;
|
||||
if (!gc.canBeEquippedBy(lki)) {
|
||||
canAttach = false;
|
||||
}
|
||||
} else {
|
||||
canAttach = false;
|
||||
}
|
||||
}
|
||||
if (lki.isFortification()) {
|
||||
if (ge instanceof Card) {
|
||||
Card gc = (Card) ge;
|
||||
if (!gc.isLand()) {
|
||||
canAttach = false;
|
||||
}
|
||||
} else {
|
||||
canAttach = false;
|
||||
}
|
||||
}
|
||||
|
||||
// reset static abilities
|
||||
game.getAction().checkStaticAbilities(false);
|
||||
@@ -531,20 +509,7 @@ public class TokenEffect extends SpellAbilityEffect {
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO update when doing Attach Update
|
||||
if (lki.isAura()) {
|
||||
tok.enchantEntity(ge);
|
||||
} else if (lki.isEquipment()) {
|
||||
if (ge instanceof Card) {
|
||||
Card gc = (Card) ge;
|
||||
tok.equipCard(gc);
|
||||
}
|
||||
} else if (lki.isFortification()) {
|
||||
if (ge instanceof Card) {
|
||||
Card gc = (Card) ge;
|
||||
tok.fortifyCard(gc);
|
||||
}
|
||||
}
|
||||
tok.attachEntity(ge);
|
||||
return true;
|
||||
} else {
|
||||
// not a GameEntity, cant be attach
|
||||
|
||||
@@ -17,25 +17,8 @@ import java.util.List;
|
||||
|
||||
public class UnattachAllEffect extends SpellAbilityEffect {
|
||||
private static void handleUnattachment(final GameEntity o, final Card cardToUnattach) {
|
||||
if (o instanceof Card) {
|
||||
final Card c = (Card) o;
|
||||
if (cardToUnattach.isAura()) {
|
||||
//final boolean gainControl = "GainControl".equals(af.parseParams().get("AILogic"));
|
||||
//AbilityFactoryAttach.handleUnattachAura(cardToUnattach, c, gainControl);
|
||||
} else if (cardToUnattach.isEquipment()) {
|
||||
if (cardToUnattach.isEquipping() && c.isEquippedBy(cardToUnattach)) {
|
||||
cardToUnattach.unEquipCard(cardToUnattach.getEquipping());
|
||||
}
|
||||
} else if (cardToUnattach.isFortification()) {
|
||||
if (cardToUnattach.isFortifying() && c.isFortifiedBy(cardToUnattach)) {
|
||||
cardToUnattach.unFortifyCard(cardToUnattach.getFortifying());
|
||||
}
|
||||
}
|
||||
} else if (o instanceof Player) {
|
||||
final Player p = (Player) o;
|
||||
if (cardToUnattach.isAura() && p.isEnchantedBy(cardToUnattach)) {
|
||||
//AbilityFactoryAttach.handleUnattachAura(cardToUnattach, p, false);
|
||||
}
|
||||
if (cardToUnattach.isAttachment() && o.isAttachedBy(cardToUnattach)) {
|
||||
cardToUnattach.unAttachEntity(cardToUnattach.getAttaching());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,13 +31,9 @@ public class UnattachEffect extends SpellAbilityEffect {
|
||||
if (cardToUnattach.isAura()) {
|
||||
//final boolean gainControl = "GainControl".equals(af.parseParams().get("AILogic"));
|
||||
//AbilityFactoryAttach.handleUnattachAura(cardToUnattach, c, gainControl);
|
||||
} else if (cardToUnattach.isEquipment()) {
|
||||
if (cardToUnattach.isEquipping()) {
|
||||
cardToUnattach.unEquipCard(cardToUnattach.getEquipping());
|
||||
}
|
||||
} else if (cardToUnattach.isFortification()) {
|
||||
if (cardToUnattach.isFortifying()) {
|
||||
cardToUnattach.unFortifyCard(cardToUnattach.getFortifying());
|
||||
} else if (cardToUnattach.isAttachment()) {
|
||||
if (cardToUnattach.isAttaching()) {
|
||||
cardToUnattach.unAttachEntity(cardToUnattach.getAttaching());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,8 +83,8 @@ public class ZoneExchangeEffect extends SpellAbilityEffect {
|
||||
}
|
||||
// Enchant first
|
||||
if (c != null) {
|
||||
object1.unEnchantEntity(c);
|
||||
object2.enchantEntity(c);
|
||||
object1.unAttachEntity(c);
|
||||
object2.attachEntity(c);
|
||||
}
|
||||
// Exchange Zone
|
||||
game.getAction().moveTo(zone2, object1, sa);
|
||||
|
||||
@@ -37,7 +37,6 @@ import forge.game.combat.Combat;
|
||||
import forge.game.cost.Cost;
|
||||
import forge.game.cost.CostSacrifice;
|
||||
import forge.game.event.*;
|
||||
import forge.game.event.GameEventCardAttachment.AttachMethod;
|
||||
import forge.game.event.GameEventCardDamaged.DamageType;
|
||||
import forge.game.keyword.Keyword;
|
||||
import forge.game.keyword.KeywordCollection;
|
||||
@@ -98,14 +97,13 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
private final KeywordCollection hiddenExtrinsicKeyword = new KeywordCollection();
|
||||
|
||||
// cards attached or otherwise linked to this card
|
||||
private CardCollection equippedBy, fortifiedBy, hauntedBy, devouredCards, delvedCards, convokedCards, imprintedCards, encodedCards;
|
||||
private CardCollection hauntedBy, devouredCards, delvedCards, convokedCards, imprintedCards, encodedCards;
|
||||
private CardCollection mustBlockCards, clones, gainControlTargets, chosenCards, blockedThisTurn, blockedByThisTurn;
|
||||
|
||||
// if this card is attached or linked to something, what card is it currently attached to
|
||||
private Card equipping, encoding, fortifying, cloneOrigin, haunting, effectSource, pairedWith, meldedWith;
|
||||
private Card encoding, cloneOrigin, haunting, effectSource, pairedWith, meldedWith;
|
||||
|
||||
// if this card is an Aura, what Entity is it enchanting?
|
||||
private GameEntity enchanting = null;
|
||||
private GameEntity attaching = null;
|
||||
|
||||
private GameEntity mustAttackEntity = null;
|
||||
private GameEntity mustAttackEntityThisTurn = null;
|
||||
@@ -2585,186 +2583,126 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
}
|
||||
}
|
||||
|
||||
public final CardCollectionView getEquippedBy(boolean allowModify) {
|
||||
return CardCollection.getView(equippedBy, allowModify);
|
||||
public final CardCollectionView getEquippedBy() {
|
||||
if (this.attachedBy == null) {
|
||||
return CardCollection.EMPTY;
|
||||
}
|
||||
public final void setEquippedBy(final CardCollection cards) {
|
||||
equippedBy = view.setCards(equippedBy, cards, TrackableProperty.EquippedBy);
|
||||
}
|
||||
public final void setEquippedBy(final Iterable<Card> cards) {
|
||||
equippedBy = view.setCards(equippedBy, cards, TrackableProperty.EquippedBy);
|
||||
|
||||
return CardLists.filter(attachedBy, CardPredicates.Presets.EQUIPMENT);
|
||||
}
|
||||
|
||||
public final boolean isEquipped() {
|
||||
return FCollection.hasElements(equippedBy);
|
||||
}
|
||||
public final boolean isEquippedBy(Card c) {
|
||||
return FCollection.hasElement(equippedBy, c);
|
||||
}
|
||||
public final boolean isEquippedBy(final String cardName) {
|
||||
for (final Card card : getEquippedBy(false)) {
|
||||
if (card.getName().equals(cardName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (this.attachedBy == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public final CardCollectionView getFortifiedBy(boolean allowModify) {
|
||||
return CardCollection.getView(fortifiedBy, allowModify);
|
||||
return CardLists.count(attachedBy, CardPredicates.Presets.EQUIPMENT) > 0;
|
||||
}
|
||||
public final void setFortifiedBy(final CardCollection cards) {
|
||||
fortifiedBy = view.setCards(fortifiedBy, cards, TrackableProperty.FortifiedBy);
|
||||
public final boolean isEquippedBy(Card c) {
|
||||
return this.isAttachedBy(c);
|
||||
}
|
||||
public final void setFortifiedBy(final Iterable<Card> cards) {
|
||||
fortifiedBy = view.setCards(fortifiedBy, cards, TrackableProperty.FortifiedBy);
|
||||
public final boolean isEquippedBy(final String cardName) {
|
||||
return this.isAttachedBy(cardName);
|
||||
}
|
||||
|
||||
public final CardCollectionView getFortifiedBy() {
|
||||
if (this.attachedBy == null) {
|
||||
return CardCollection.EMPTY;
|
||||
}
|
||||
|
||||
return CardLists.filter(attachedBy, CardPredicates.Presets.FORTIFICATION);
|
||||
}
|
||||
|
||||
public final boolean isFortified() {
|
||||
return FCollection.hasElements(fortifiedBy);
|
||||
if (this.attachedBy == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return CardLists.count(attachedBy, CardPredicates.Presets.FORTIFICATION) > 0;
|
||||
}
|
||||
public final boolean isFortifiedBy(Card c) {
|
||||
return FCollection.hasElement(fortifiedBy, c);
|
||||
// 301.5e + 301.6
|
||||
return isAttachedBy(c);
|
||||
}
|
||||
|
||||
public final Card getEquipping() {
|
||||
return equipping;
|
||||
}
|
||||
public final void setEquipping(final Card card) {
|
||||
equipping = view.setCard(equipping, card, TrackableProperty.Equipping);
|
||||
return this.getAttachingCard();
|
||||
}
|
||||
public final boolean isEquipping() {
|
||||
return equipping != null;
|
||||
return this.isAttaching();
|
||||
}
|
||||
|
||||
public final Card getFortifying() {
|
||||
return fortifying;
|
||||
}
|
||||
public final void setFortifying(final Card card) {
|
||||
fortifying = view.setCard(fortifying, card, TrackableProperty.Fortifying);
|
||||
}
|
||||
public final boolean isFortifying() {
|
||||
return fortifying != null;
|
||||
return this.isAttaching();
|
||||
}
|
||||
|
||||
public final void equipCard(final Card c) {
|
||||
if (c.hasKeyword("CARDNAME can't be equipped.")) {
|
||||
getGame().getGameLog().add(GameLogEntryType.STACK_RESOLVE, "Trying to equip " + c.getName() + " but it can't be equipped.");
|
||||
if (!isEquipment()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for(KeywordInterface inst : c.getKeywords()) {
|
||||
String kw = inst.getOriginal();
|
||||
if (!kw.startsWith("CantEquip")) {
|
||||
continue;
|
||||
}
|
||||
final String[] k = kw.split(" ", 2);
|
||||
final String[] restrictions = k[1].split(",");
|
||||
if (c.isValid(restrictions, getController(), this, null)) {
|
||||
getGame().getGameLog().add(GameLogEntryType.STACK_RESOLVE, "Trying to equip " + c.getName() + " but it can't be equipped.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Card oldTarget = null;
|
||||
if (isEquipping()) {
|
||||
oldTarget = equipping;
|
||||
if (oldTarget.equals(c)) {
|
||||
// If attempting to reattach to the same object, don't do anything.
|
||||
return;
|
||||
}
|
||||
unEquipCard(oldTarget);
|
||||
}
|
||||
|
||||
// They use double links... it's doubtful
|
||||
setEquipping(c);
|
||||
setTimestamp(getGame().getNextTimestamp());
|
||||
c.equippedBy = c.view.addCard(c.equippedBy, this, TrackableProperty.EquippedBy);
|
||||
|
||||
// Play the Equip sound
|
||||
getGame().fireEvent(new GameEventCardAttachment(this, oldTarget, c, AttachMethod.Equip));
|
||||
|
||||
// run trigger
|
||||
final Map<String, Object> runParams = Maps.newHashMap();
|
||||
runParams.put("AttachSource", this);
|
||||
runParams.put("AttachTarget", c);
|
||||
getController().getGame().getTriggerHandler().runTrigger(TriggerType.Attached, runParams, false);
|
||||
this.attachEntity(c);
|
||||
}
|
||||
|
||||
public final void fortifyCard(final Card c) {
|
||||
Card oldTarget = null;
|
||||
if (isFortifying()) {
|
||||
oldTarget = fortifying;
|
||||
unFortifyCard(oldTarget);
|
||||
if (!isFortification()) {
|
||||
return;
|
||||
}
|
||||
|
||||
setFortifying(c);
|
||||
setTimestamp(getGame().getNextTimestamp());
|
||||
c.fortifiedBy = c.view.addCard(c.fortifiedBy, this, TrackableProperty.FortifiedBy);
|
||||
|
||||
// Play the Equip sound
|
||||
getGame().fireEvent(new GameEventCardAttachment(this, oldTarget, c, AttachMethod.Fortify));
|
||||
// run trigger
|
||||
final Map<String, Object> runParams = Maps.newHashMap();
|
||||
runParams.put("AttachSource", this);
|
||||
runParams.put("AttachTarget", c);
|
||||
getController().getGame().getTriggerHandler().runTrigger(TriggerType.Attached, runParams, false);
|
||||
this.attachEntity(c);
|
||||
}
|
||||
|
||||
public final void unEquipCard(final Card c) { // equipment.unEquipCard(equippedCard);
|
||||
if (equipping != null && equipping.getId() == c.getId()) {
|
||||
setEquipping(null);
|
||||
}
|
||||
c.equippedBy = c.view.removeCard(c.equippedBy, this, TrackableProperty.EquippedBy);
|
||||
|
||||
getGame().fireEvent(new GameEventCardAttachment(this, c, null, AttachMethod.Equip));
|
||||
|
||||
// Run triggers
|
||||
final Map<String, Object> runParams = Maps.newTreeMap();
|
||||
runParams.put("Equipment", this);
|
||||
runParams.put("Card", c);
|
||||
getGame().getTriggerHandler().runTrigger(TriggerType.Unequip, runParams, false);
|
||||
runUnattachCommands();
|
||||
}
|
||||
|
||||
public final void unFortifyCard(final Card c) { // fortification.unEquipCard(fortifiedCard);
|
||||
if (fortifying == c) {
|
||||
setFortifying(null);
|
||||
}
|
||||
c.fortifiedBy = c.view.removeCard(c.fortifiedBy, this, TrackableProperty.FortifiedBy);
|
||||
|
||||
getGame().fireEvent(new GameEventCardAttachment(this, c, null, AttachMethod.Fortify));
|
||||
runUnattachCommands();
|
||||
this.unAttachEntity(c);
|
||||
}
|
||||
|
||||
public final void unEquipAllCards() {
|
||||
if (isEquipped()) {
|
||||
for (Card c : getEquippedBy(true)) {
|
||||
c.unEquipCard(this);
|
||||
for (Card c : Lists.newArrayList(getEquippedBy())) {
|
||||
c.unAttachEntity(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public final GameEntity getEnchanting() {
|
||||
return enchanting;
|
||||
public final GameEntity getAttaching() {
|
||||
return attaching;
|
||||
}
|
||||
public final void setEnchanting(final GameEntity e) {
|
||||
if (enchanting == e) { return; }
|
||||
enchanting = e;
|
||||
view.updateEnchanting(this);
|
||||
public final void setAttaching(final GameEntity e) {
|
||||
if (attaching == e) { return; }
|
||||
attaching = e;
|
||||
view.updateAttaching(this);
|
||||
}
|
||||
public final Card getEnchantingCard() {
|
||||
if (enchanting instanceof Card) {
|
||||
return (Card) enchanting;
|
||||
public final void removeAttaching(final GameEntity e) {
|
||||
if (attaching == e) {
|
||||
setAttaching(null);
|
||||
}
|
||||
}
|
||||
public final boolean isAttaching() {
|
||||
return attaching != null;
|
||||
}
|
||||
|
||||
public final Card getAttachingCard() {
|
||||
if (attaching instanceof Card) {
|
||||
return (Card) attaching;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public final GameEntity getEnchanting() {
|
||||
return getAttaching();
|
||||
}
|
||||
|
||||
public final Card getEnchantingCard() {
|
||||
return getAttachingCard();
|
||||
}
|
||||
public final Player getEnchantingPlayer() {
|
||||
if (enchanting instanceof Player) {
|
||||
return (Player) enchanting;
|
||||
if (attaching instanceof Player) {
|
||||
return (Player) attaching;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public final boolean isEnchanting() {
|
||||
return enchanting != null;
|
||||
return isAttaching();
|
||||
}
|
||||
public final boolean isEnchantingCard() {
|
||||
return getEnchantingCard() != null;
|
||||
@@ -2773,43 +2711,63 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
return getEnchantingPlayer() != null;
|
||||
}
|
||||
|
||||
public final void removeEnchanting(final GameEntity e) {
|
||||
if (enchanting == e) {
|
||||
setEnchanting(null);
|
||||
}
|
||||
}
|
||||
|
||||
public final void enchantEntity(final GameEntity entity) {
|
||||
if (entity.hasKeyword("CARDNAME can't be enchanted.")
|
||||
|| entity.hasKeyword("CARDNAME can't be enchanted in the future.")) {
|
||||
getGame().getGameLog().add(GameLogEntryType.STACK_RESOLVE, "Trying to enchant " + entity.getName()
|
||||
+ " but it can't be enchanted.");
|
||||
public final void attachEntity(final GameEntity entity) {
|
||||
if (!entity.canBeAttachedBy(this)) {
|
||||
return;
|
||||
}
|
||||
setEnchanting(entity);
|
||||
setTimestamp(getGame().getNextTimestamp());
|
||||
entity.addEnchantedBy(this);
|
||||
|
||||
getGame().fireEvent(new GameEventCardAttachment(this, null, entity, AttachMethod.Enchant));
|
||||
GameEntity oldTarget = null;
|
||||
if (isAttaching()) {
|
||||
oldTarget = getAttaching();
|
||||
// If attempting to reattach to the same object, don't do anything.
|
||||
if (oldTarget.equals(entity)) {
|
||||
return;
|
||||
}
|
||||
unAttachEntity(oldTarget);
|
||||
}
|
||||
|
||||
// They use double links... it's doubtful
|
||||
setAttaching(entity);
|
||||
setTimestamp(getGame().getNextTimestamp());
|
||||
entity.addAttachedBy(this);
|
||||
|
||||
// Play the Equip sound
|
||||
getGame().fireEvent(new GameEventCardAttachment(this, oldTarget, entity));
|
||||
|
||||
// run trigger
|
||||
final Map<String, Object> runParams = Maps.newHashMap();
|
||||
runParams.put("AttachSource", this);
|
||||
runParams.put("AttachTarget", entity);
|
||||
getController().getGame().getTriggerHandler().runTrigger(TriggerType.Attached, runParams, false);
|
||||
|
||||
}
|
||||
|
||||
public final void unEnchantEntity(final GameEntity entity) {
|
||||
if (enchanting == null || !enchanting.equals(entity)) {
|
||||
public final void enchantEntity(final GameEntity entity) {
|
||||
if (!isAura()) {
|
||||
return;
|
||||
}
|
||||
this.attachEntity(entity);
|
||||
}
|
||||
|
||||
public final void unAttachEntity(final GameEntity entity) {
|
||||
if (attaching == null || !attaching.equals(entity)) {
|
||||
return;
|
||||
}
|
||||
|
||||
setEnchanting(null);
|
||||
entity.removeEnchantedBy(this);
|
||||
setAttaching(null);
|
||||
entity.removeAttachedBy(this);
|
||||
|
||||
// Handle Bestowed Aura part
|
||||
if (isBestowed()) {
|
||||
unanimateBestow();
|
||||
}
|
||||
getGame().fireEvent(new GameEventCardAttachment(this, entity, null, AttachMethod.Enchant));
|
||||
getGame().fireEvent(new GameEventCardAttachment(this, entity, null));
|
||||
|
||||
// Run triggers
|
||||
final Map<String, Object> runParams = Maps.newTreeMap();
|
||||
runParams.put("Attach", this);
|
||||
runParams.put("Object", entity);
|
||||
getGame().getTriggerHandler().runTrigger(TriggerType.Unattach, runParams, false);
|
||||
runUnattachCommands();
|
||||
}
|
||||
|
||||
@@ -3820,7 +3778,9 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
public final boolean isPlaneswalker() { return getType().isPlaneswalker(); }
|
||||
public final boolean isEnchantment() { return getType().isEnchantment(); }
|
||||
public final boolean isAura() { return getType().hasSubtype("Aura"); }
|
||||
public final boolean isHistoric() {return getType().isLegendary() || getType().isArtifact() || getType().hasSubtype("Saga");}
|
||||
|
||||
public final boolean isAttachment() { return isAura() || isEquipment() || isFortification(); }
|
||||
public final boolean isHistoric() {return getType().isLegendary() || isArtifact() || getType().hasSubtype("Saga");}
|
||||
|
||||
public final boolean isScheme() { return getType().isScheme(); }
|
||||
public final boolean isPhenomenon() { return getType().isPhenomenon(); }
|
||||
@@ -3886,27 +3846,13 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
setDirectlyPhasedOut(direct);
|
||||
}
|
||||
|
||||
if (isEquipped()) {
|
||||
for (final Card eq : getEquippedBy(false)) {
|
||||
if (isAttachedBy()) {
|
||||
for (final Card eq : getAttachedBy()) {
|
||||
if (eq.isPhasedOut() == phasingIn) {
|
||||
eq.phase(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isFortified()) {
|
||||
for (final Card f : getFortifiedBy(false)) {
|
||||
if (f.isPhasedOut() == phasingIn) {
|
||||
f.phase(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isEnchanted()) {
|
||||
for (final Card aura : getEnchantedBy(false)) {
|
||||
if (aura.isPhasedOut() == phasingIn) {
|
||||
aura.phase(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getGame().fireEvent(new GameEventCardPhased(this, isPhasedOut()));
|
||||
}
|
||||
@@ -4997,7 +4943,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
return sum;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
public boolean hasProtectionFrom(final Card source) {
|
||||
return hasProtectionFrom(source, false, false);
|
||||
}
|
||||
@@ -5006,6 +4952,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
return hasProtectionFrom(source, false, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasProtectionFrom(final Card source, final boolean checkSBA) {
|
||||
return hasProtectionFrom(source, checkSBA, false);
|
||||
}
|
||||
@@ -5019,6 +4966,11 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Protection only works on the Battlefield
|
||||
if (isInZone(ZoneType.Battlefield)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final boolean colorlessDamage = damageSource && source.hasKeyword("Colorless Damage Source");
|
||||
|
||||
for (final KeywordInterface inst : getKeywords()) {
|
||||
@@ -5221,14 +5173,50 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
tgt = sa.getTargetRestrictions();
|
||||
}
|
||||
|
||||
if (aura.isCreature()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// phase check there
|
||||
if (isPhasedOut() && !aura.isPhasedOut()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (tgt != null) {
|
||||
boolean zoneValid = false;
|
||||
// check the zone types
|
||||
for (final ZoneType zt : tgt.getZone()) {
|
||||
if (isInZone(zt)) {
|
||||
zoneValid = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!zoneValid) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// check valid
|
||||
if (!isValid(tgt.getValidTgts(), aura.getController(), aura, sa)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return !(hasProtectionFrom(aura, checkSBA)
|
||||
|| (hasKeyword("CARDNAME can't be enchanted in the future.") && !isEnchantedBy(aura))
|
||||
|| (hasKeyword("CARDNAME can't be enchanted.") && !aura.getName().equals("Anti-Magic Aura")
|
||||
&& !(aura.getName().equals("Consecrate Land") && aura.isInZone(ZoneType.Battlefield)))
|
||||
|| ((tgt != null) && !isValid(tgt.getValidTgts(), aura.getController(), aura, sa)));
|
||||
&& !(aura.getName().equals("Consecrate Land") && aura.isInZone(ZoneType.Battlefield))));
|
||||
}
|
||||
|
||||
public final boolean canBeEquippedBy(final Card equip) {
|
||||
if (!isCreature() || !isInPlay() || equip.isCreature()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// phase check there
|
||||
if (isPhasedOut() && !equip.isPhasedOut()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for(KeywordInterface inst : equip.getKeywords()) {
|
||||
String kw = inst.getOriginal();
|
||||
if(!kw.startsWith("CantEquip")) {
|
||||
@@ -5241,8 +5229,19 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
}
|
||||
}
|
||||
return !(hasProtectionFrom(equip)
|
||||
|| hasKeyword("CARDNAME can't be equipped.")
|
||||
|| !isValid("Creature", equip.getController(), equip, null));
|
||||
|| hasKeyword("CARDNAME can't be equipped."));
|
||||
}
|
||||
|
||||
public boolean canBeFortifiedBy(final Card fort) {
|
||||
if (!isLand() || !isInPlay() || fort.isCreature() || fort.isLand()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// phase check there
|
||||
if (isPhasedOut() && !fort.isPhasedOut()) {
|
||||
return false;
|
||||
}
|
||||
return !hasProtectionFrom(fort);
|
||||
}
|
||||
|
||||
public FCollectionView<ReplacementEffect> getReplacementEffects() {
|
||||
|
||||
@@ -92,12 +92,8 @@ public class CardFactory {
|
||||
out.setState(in.getCurrentStateName(), true);
|
||||
|
||||
// this's necessary for forge.game.GameAction.unattachCardLeavingBattlefield(Card)
|
||||
out.setEquipping(in.getEquipping());
|
||||
out.setEquippedBy(in.getEquippedBy(false));
|
||||
out.setFortifying(in.getFortifying());
|
||||
out.setFortifiedBy(in.getFortifiedBy(false));
|
||||
out.setEnchantedBy(in.getEnchantedBy(false));
|
||||
out.setEnchanting(in.getEnchanting());
|
||||
out.setAttachedBy(in.getAttachedBy());
|
||||
out.setAttaching(in.getAttaching());
|
||||
|
||||
out.setClones(in.getClones());
|
||||
out.setCastSA(in.getCastSA());
|
||||
|
||||
@@ -470,6 +470,15 @@ public final class CardPredicates {
|
||||
return c.isEnchantment();
|
||||
}
|
||||
};
|
||||
/**
|
||||
* a Predicate<Card> to get all aura.
|
||||
*/
|
||||
public static final Predicate<Card> AURA = new Predicate<Card>() {
|
||||
@Override
|
||||
public boolean apply(Card c) {
|
||||
return c.isAura();
|
||||
}
|
||||
};
|
||||
/**
|
||||
* a Predicate<Card> to get all equipment.
|
||||
*/
|
||||
@@ -482,7 +491,7 @@ public final class CardPredicates {
|
||||
/**
|
||||
* a Predicate<Card> to get all fortification.
|
||||
*/
|
||||
public static final Predicate<Card> Fortification = new Predicate<Card>() {
|
||||
public static final Predicate<Card> FORTIFICATION = new Predicate<Card>() {
|
||||
@Override
|
||||
public boolean apply(Card c) {
|
||||
return c.isFortification();
|
||||
|
||||
@@ -405,7 +405,7 @@ public class CardProperty {
|
||||
return false;
|
||||
}
|
||||
} else if (property.equals("Attached")) {
|
||||
if (card.getEquipping() != source && !source.equals(card.getEnchanting()) && card.getFortifying() != source) {
|
||||
if (card.getEquipping() != source && !source.equals(card.getAttaching())) {
|
||||
return false;
|
||||
}
|
||||
} else if (property.startsWith("AttachedTo")) {
|
||||
@@ -433,9 +433,8 @@ public class CardProperty {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if ((card.getEnchanting() == null || !card.getEnchanting().isValid(restriction, sourceController, source, spellAbility))
|
||||
&& (card.getEquipping() == null || !card.getEquipping().isValid(restriction, sourceController, source, spellAbility))
|
||||
&& (card.getFortifying() == null || !card.getFortifying().isValid(restriction, sourceController, source, spellAbility))) {
|
||||
if ((card.getAttaching() == null || !card.getAttaching().isValid(restriction, sourceController, source, spellAbility))
|
||||
&& (card.getEquipping() == null || !card.getEquipping().isValid(restriction, sourceController, source, spellAbility))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -445,7 +444,7 @@ public class CardProperty {
|
||||
return false;
|
||||
}
|
||||
} else if (property.equals("NotAttachedTo")) {
|
||||
if (card.getEquipping() == source || source.equals(card.getEnchanting()) || card.getFortifying() == source) {
|
||||
if (card.getEquipping() == source || source.equals(card.getAttaching())) {
|
||||
return false;
|
||||
}
|
||||
} else if (property.startsWith("EnchantedBy")) {
|
||||
@@ -476,7 +475,7 @@ public class CardProperty {
|
||||
}
|
||||
break;
|
||||
default: // EnchantedBy Aura.Other
|
||||
for (final Card aura : card.getEnchantedBy(false)) {
|
||||
for (final Card aura : card.getEnchantedBy()) {
|
||||
if (aura.isValid(restriction, sourceController, source, spellAbility)) {
|
||||
return true;
|
||||
}
|
||||
@@ -572,11 +571,12 @@ public class CardProperty {
|
||||
return false;
|
||||
}
|
||||
} else if (property.startsWith("Equipped")) {
|
||||
if (card.getEquipping() != source) {
|
||||
if (!source.isAttachedBy(card)) {
|
||||
return false;
|
||||
}
|
||||
} else if (property.startsWith("Fortified")) {
|
||||
if (card.getFortifying() != source) {
|
||||
// FIXME TODO what property has this?
|
||||
if (!source.isAttachedBy(card)) {
|
||||
return false;
|
||||
}
|
||||
} else if (property.startsWith("HauntedBy")) {
|
||||
|
||||
@@ -264,12 +264,10 @@ public final class CardUtil {
|
||||
newCopy.setReceivedDamageFromThisTurn(in.getReceivedDamageFromThisTurn());
|
||||
newCopy.setReceivedDamageFromPlayerThisTurn(in.getReceivedDamageFromPlayerThisTurn());
|
||||
newCopy.getDamageHistory().setCreatureGotBlockedThisTurn(in.getDamageHistory().getCreatureGotBlockedThisTurn());
|
||||
newCopy.setEnchanting(in.getEnchanting());
|
||||
newCopy.setEnchantedBy(in.getEnchantedBy(false));
|
||||
newCopy.setEquipping(in.getEquipping());
|
||||
newCopy.setEquippedBy(in.getEquippedBy(false));
|
||||
newCopy.setFortifying(in.getFortifying());
|
||||
newCopy.setFortifiedBy(in.getFortifiedBy(false));
|
||||
|
||||
newCopy.setAttachedBy(in.getAttachedBy());
|
||||
newCopy.setAttaching(in.getAttaching());
|
||||
|
||||
newCopy.setClones(in.getClones());
|
||||
newCopy.setHaunting(in.getHaunting());
|
||||
newCopy.setCopiedPermanent(in.getCopiedPermanent());
|
||||
|
||||
@@ -438,56 +438,32 @@ public class CardView extends GameEntityView {
|
||||
return false;
|
||||
}
|
||||
|
||||
public CardView getEquipping() {
|
||||
return get(TrackableProperty.Equipping);
|
||||
}
|
||||
|
||||
public FCollectionView<CardView> getEquippedBy() {
|
||||
return get(TrackableProperty.EquippedBy);
|
||||
}
|
||||
|
||||
public boolean isEquipped() {
|
||||
return getEquippedBy() != null; //isEmpty check not needed since we won't keep an empty collection around
|
||||
}
|
||||
|
||||
public FCollectionView<CardView> getEncodedCards() {
|
||||
return get(TrackableProperty.EncodedCards);
|
||||
}
|
||||
|
||||
public GameEntityView getEnchanting() {
|
||||
return get(TrackableProperty.Enchanting);
|
||||
public GameEntityView getAttaching() {
|
||||
return get(TrackableProperty.Attaching);
|
||||
}
|
||||
void updateEnchanting(Card c) {
|
||||
set(TrackableProperty.Enchanting, GameEntityView.get(c.getEnchanting()));
|
||||
void updateAttaching(Card c) {
|
||||
set(TrackableProperty.Attaching, GameEntityView.get(c.getAttaching()));
|
||||
}
|
||||
|
||||
public CardView getEnchantingCard() {
|
||||
GameEntityView enchanting = getEnchanting();
|
||||
public CardView getAttachingCard() {
|
||||
GameEntityView enchanting = getAttaching();
|
||||
if (enchanting instanceof CardView) {
|
||||
return (CardView) enchanting;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public PlayerView getEnchantingPlayer() {
|
||||
GameEntityView enchanting = getEnchanting();
|
||||
public PlayerView getAttachingPlayer() {
|
||||
GameEntityView enchanting = getAttaching();
|
||||
if (enchanting instanceof PlayerView) {
|
||||
return (PlayerView) enchanting;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public CardView getFortifying() {
|
||||
return get(TrackableProperty.Fortifying);
|
||||
}
|
||||
|
||||
public FCollectionView<CardView> getFortifiedBy() {
|
||||
return get(TrackableProperty.FortifiedBy);
|
||||
}
|
||||
|
||||
public boolean isFortified() {
|
||||
return getFortifiedBy() != null;
|
||||
}
|
||||
|
||||
public FCollectionView<CardView> getGainControlTargets() {
|
||||
return get(TrackableProperty.GainControlTargets);
|
||||
}
|
||||
|
||||
@@ -424,15 +424,12 @@ public class Combat {
|
||||
|
||||
public Player getDefendingPlayerRelatedTo(final Card source) {
|
||||
Card attacker = source;
|
||||
if (source.isAura()) {
|
||||
if (source.isAura() || source.isFortification()) {
|
||||
attacker = source.getEnchantingCard();
|
||||
}
|
||||
else if (source.isEquipment()) {
|
||||
attacker = source.getEquipping();
|
||||
}
|
||||
else if (source.isFortification()) {
|
||||
attacker = source.getFortifying();
|
||||
}
|
||||
|
||||
// return the corresponding defender
|
||||
return getDefenderPlayerByAttacker(attacker);
|
||||
|
||||
@@ -83,7 +83,7 @@ public class CostUnattach extends CostPartWithList {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
if (CardLists.getValidCards(source.getEquippedBy(false), type, payer, source).size() > 0) {
|
||||
if (CardLists.getValidCards(source.getEquippedBy(), type, payer, source).size() > 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -102,7 +102,7 @@ public class CostUnattach extends CostPartWithList {
|
||||
return originalEquipment;
|
||||
}
|
||||
} else {
|
||||
List<Card> attachees = CardLists.getValidCards(source.getEquippedBy(false), this.getType(), activator, source);
|
||||
List<Card> attachees = CardLists.getValidCards(source.getEquippedBy(), this.getType(), activator, source);
|
||||
if (attachees.size() > 0) {
|
||||
// Just pick the first one, although maybe give a dialog
|
||||
return attachees.get(0);
|
||||
@@ -116,7 +116,7 @@ public class CostUnattach extends CostPartWithList {
|
||||
*/
|
||||
@Override
|
||||
protected Card doPayment(SpellAbility ability, Card targetCard) {
|
||||
targetCard.unEquipCard(targetCard.getEquipping());
|
||||
targetCard.unAttachEntity(targetCard.getAttaching());
|
||||
return targetCard;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,23 +4,15 @@ import forge.game.GameEntity;
|
||||
import forge.game.card.Card;
|
||||
|
||||
public class GameEventCardAttachment extends GameEvent {
|
||||
public enum AttachMethod {
|
||||
Equip,
|
||||
Fortify,
|
||||
Enchant;
|
||||
}
|
||||
|
||||
|
||||
public final Card equipment;
|
||||
public final GameEntity newTarget; // can enchant player, I'm ssaving a class to enchants - it could be incorrect.
|
||||
public final GameEntity oldEntiy;
|
||||
public final AttachMethod method;
|
||||
|
||||
public GameEventCardAttachment(Card attachment, GameEntity formerEntity, GameEntity newEntity, AttachMethod method) {
|
||||
public GameEventCardAttachment(Card attachment, GameEntity formerEntity, GameEntity newEntity) {
|
||||
this.equipment = attachment;
|
||||
this.newTarget = newEntity;
|
||||
this.oldEntiy = formerEntity;
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -272,20 +272,15 @@ public class Untap extends Phase {
|
||||
} else if (c.hasKeyword(Keyword.PHASING)) {
|
||||
// 702.23g If an object would simultaneously phase out directly
|
||||
// and indirectly, it just phases out indirectly.
|
||||
if (c.isAura()) {
|
||||
final GameEntity ent = c.getEnchanting();
|
||||
|
||||
if ((ent instanceof Card) && list.contains(ent)) {
|
||||
if (c.isAura() || c.isFortification()) {
|
||||
final Card ent = c.getAttachingCard();
|
||||
if (ent != null && list.contains(ent)) {
|
||||
continue;
|
||||
}
|
||||
} else if (c.isEquipment() && c.isEquipping()) {
|
||||
if (list.contains(c.getEquipping())) {
|
||||
continue;
|
||||
}
|
||||
} else if (c.isFortification() && c.isFortifying()) {
|
||||
if (list.contains(c.getFortifying())) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
c.phase();
|
||||
}
|
||||
|
||||
@@ -624,7 +624,7 @@ public class Player extends GameEntity implements Comparable<Player> {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (hasProtectionFrom(source, true)) {
|
||||
if (hasProtectionFromDamage(source)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1012,7 +1012,6 @@ public class Player extends GameEntity implements Comparable<Player> {
|
||||
if (changedKeywords.containsKey(timestamp)) {
|
||||
final KeywordsChange cks = changedKeywords.get(timestamp);
|
||||
|
||||
;
|
||||
changedKeywords.put(timestamp, cks.merge(addKeywords, removeKeywords,
|
||||
cks.isRemoveAllKeywords(), cks.isRemoveIntrinsicKeywords()));
|
||||
updateKeywords();
|
||||
@@ -1195,12 +1194,17 @@ public class Player extends GameEntity implements Comparable<Player> {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasProtectionFrom(final Card source) {
|
||||
return hasProtectionFrom(source, false);
|
||||
|
||||
public boolean hasProtectionFromDamage(final Card source) {
|
||||
return hasProtectionFrom(source, false, false);
|
||||
}
|
||||
|
||||
public boolean hasProtectionFrom(final Card source, final boolean damageSource) {
|
||||
@Override
|
||||
public boolean hasProtectionFrom(final Card source, final boolean checkSBA) {
|
||||
return hasProtectionFrom(source, checkSBA, false);
|
||||
}
|
||||
|
||||
public boolean hasProtectionFrom(final Card source, final boolean checkSBA, final boolean damageSource) {
|
||||
for (String kw : keywords) {
|
||||
if (kw.startsWith("Protection")) {
|
||||
if (kw.startsWith("Protection:")) { // uses isValid
|
||||
|
||||
@@ -11,7 +11,7 @@ public enum TrackableProperty {
|
||||
//Shared
|
||||
Text(TrackableTypes.StringType),
|
||||
PreventNextDamage(TrackableTypes.IntegerType),
|
||||
EnchantedBy(TrackableTypes.CardViewCollectionType),
|
||||
AttachedBy(TrackableTypes.CardViewCollectionType),
|
||||
Counters(TrackableTypes.CounterMapType),
|
||||
CurrentPlane(TrackableTypes.StringType),
|
||||
PlanarPlayer(TrackableTypes.PlayerViewType),
|
||||
@@ -43,11 +43,7 @@ public enum TrackableProperty {
|
||||
NamedCard(TrackableTypes.StringType),
|
||||
PlayerMayLook(TrackableTypes.PlayerViewCollectionType, FreezeMode.IgnoresFreeze),
|
||||
PlayerMayLookTemp(TrackableTypes.PlayerViewCollectionType, FreezeMode.IgnoresFreeze),
|
||||
Equipping(TrackableTypes.CardViewType),
|
||||
EquippedBy(TrackableTypes.CardViewCollectionType),
|
||||
Enchanting(TrackableTypes.GameEntityViewType),
|
||||
Fortifying(TrackableTypes.CardViewType),
|
||||
FortifiedBy(TrackableTypes.CardViewCollectionType),
|
||||
Attaching(TrackableTypes.GameEntityViewType),
|
||||
EncodedCards(TrackableTypes.CardViewCollectionType),
|
||||
GainControlTargets(TrackableTypes.CardViewCollectionType),
|
||||
CloneOrigin(TrackableTypes.CardViewType),
|
||||
|
||||
@@ -404,56 +404,24 @@ public class TargetingOverlay {
|
||||
return; //don't add arcs for cards if card already visualized
|
||||
}
|
||||
|
||||
final CardView enchanting = c.getEnchantingCard();
|
||||
final CardView equipping = c.getEquipping();
|
||||
final CardView fortifying = c.getFortifying();
|
||||
final Iterable<CardView> enchantedBy = c.getEnchantedBy();
|
||||
final Iterable<CardView> equippedBy = c.getEquippedBy();
|
||||
final Iterable<CardView> fortifiedBy = c.getFortifiedBy();
|
||||
final CardView attaching = c.getAttachingCard();
|
||||
final Iterable<CardView> attachedBy = c.getAttachedBy();
|
||||
final CardView paired = c.getPairedWith();
|
||||
|
||||
if (null != enchanting) {
|
||||
if (enchanting.getController() != null && !enchanting.getController().equals(c.getController())) {
|
||||
addArc(endpoints.get(enchanting.getId()), endpoints.get(c.getId()), ArcConnection.Friends);
|
||||
cardsVisualized.add(enchanting);
|
||||
if (null != attaching) {
|
||||
if (attaching.getController() != null && !attaching.getController().equals(c.getController())) {
|
||||
addArc(endpoints.get(attaching.getId()), endpoints.get(c.getId()), ArcConnection.Friends);
|
||||
cardsVisualized.add(attaching);
|
||||
}
|
||||
}
|
||||
if (null != equipping) {
|
||||
if (equipping.getController() != null && !equipping.getController().equals(c.getController())) {
|
||||
addArc(endpoints.get(equipping.getId()), endpoints.get(c.getId()), ArcConnection.Friends);
|
||||
cardsVisualized.add(equipping);
|
||||
}
|
||||
}
|
||||
if (null != fortifying) {
|
||||
if (fortifying.getController() != null && !fortifying.getController().equals(c.getController())) {
|
||||
addArc(endpoints.get(fortifying.getId()), endpoints.get(c.getId()), ArcConnection.Friends);
|
||||
cardsVisualized.add(fortifying);
|
||||
}
|
||||
}
|
||||
if (null != enchantedBy) {
|
||||
for (final CardView enc : enchantedBy) {
|
||||
if (null != attachedBy) {
|
||||
for (final CardView enc : attachedBy) {
|
||||
if (enc.getController() != null && !enc.getController().equals(c.getController())) {
|
||||
addArc(endpoints.get(c.getId()), endpoints.get(enc.getId()), ArcConnection.Friends);
|
||||
cardsVisualized.add(enc);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (null != equippedBy) {
|
||||
for (final CardView eq : equippedBy) {
|
||||
if (eq.getController() != null && !eq.getController().equals(c.getController())) {
|
||||
addArc(endpoints.get(c.getId()), endpoints.get(eq.getId()), ArcConnection.Friends);
|
||||
cardsVisualized.add(eq);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (null != fortifiedBy) {
|
||||
for (final CardView eq : fortifiedBy) {
|
||||
if (eq.getController() != null && !eq.getController().equals(c.getController())) {
|
||||
addArc(endpoints.get(c.getId()), endpoints.get(eq.getId()), ArcConnection.Friends);
|
||||
cardsVisualized.add(eq);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (null != paired) {
|
||||
addArc(endpoints.get(paired.getId()), endpoints.get(c.getId()), ArcConnection.Friends);
|
||||
cardsVisualized.add(paired);
|
||||
|
||||
@@ -106,7 +106,7 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen
|
||||
final CardStack stack = allLands.get(i);
|
||||
final CardPanel firstPanel = stack.get(0);
|
||||
if (firstPanel.getCard().getCurrentState().getName().equals(state.getName())) {
|
||||
if (!firstPanel.getAttachedPanels().isEmpty() || firstPanel.getCard().isEnchanted()) {
|
||||
if (!firstPanel.getAttachedPanels().isEmpty() || firstPanel.getCard().isAttached()) {
|
||||
// Put this land to the left of lands with the same name
|
||||
// and attachments.
|
||||
insertIndex = i;
|
||||
@@ -114,7 +114,7 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen
|
||||
}
|
||||
if (!panel.getAttachedPanels().isEmpty()
|
||||
|| !panel.getCard().hasSameCounters(firstPanel.getCard())
|
||||
|| firstPanel.getCard().isEnchanted() || (stack.size() == this.landStackMax)) {
|
||||
|| firstPanel.getCard().isAttached() || (stack.size() == this.landStackMax)) {
|
||||
// If this land has attachments or the stack is full,
|
||||
// put it to the right.
|
||||
insertIndex = i + 1;
|
||||
@@ -683,8 +683,8 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen
|
||||
}
|
||||
toPanel.getAttachedPanels().clear();
|
||||
|
||||
if (card.isEnchanted()) {
|
||||
final Iterable<CardView> enchants = card.getEnchantedBy();
|
||||
if (card.isAttached()) {
|
||||
final Iterable<CardView> enchants = card.getAttachedBy();
|
||||
for (final CardView e : enchants) {
|
||||
final CardPanel cardE = getCardPanel(e.getId());
|
||||
if (cardE != null) {
|
||||
@@ -697,43 +697,9 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen
|
||||
}
|
||||
}
|
||||
|
||||
if (card.isEquipped()) {
|
||||
final Iterable<CardView> equips = card.getEquippedBy();
|
||||
for (final CardView e : equips) {
|
||||
final CardPanel cardE = getCardPanel(e.getId());
|
||||
if (cardE != null) {
|
||||
if (cardE.getAttachedToPanel() != toPanel) {
|
||||
cardE.setAttachedToPanel(toPanel);
|
||||
needLayoutRefresh = true; //ensure layout refreshed if any attachments change
|
||||
}
|
||||
toPanel.getAttachedPanels().add(cardE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (card.isFortified()) {
|
||||
final Iterable<CardView> fortifications = card.getFortifiedBy();
|
||||
for (final CardView f : fortifications) {
|
||||
final CardPanel cardE = getCardPanel(f.getId());
|
||||
if (cardE != null) {
|
||||
if (cardE.getAttachedToPanel() != toPanel) {
|
||||
cardE.setAttachedToPanel(toPanel);
|
||||
needLayoutRefresh = true; //ensure layout refreshed if any attachments change
|
||||
}
|
||||
toPanel.getAttachedPanels().add(cardE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CardPanel attachedToPanel;
|
||||
if (card.getEnchantingCard() != null) {
|
||||
attachedToPanel = getCardPanel(card.getEnchantingCard().getId());
|
||||
}
|
||||
else if (card.getEquipping() != null) {
|
||||
attachedToPanel = getCardPanel(card.getEquipping().getId());
|
||||
}
|
||||
else if (card.getFortifying() != null) {
|
||||
attachedToPanel = getCardPanel(card.getFortifying().getId());
|
||||
if (card.getAttachingCard() != null) {
|
||||
attachedToPanel = getCardPanel(card.getAttachingCard().getId());
|
||||
}
|
||||
else {
|
||||
attachedToPanel = null;
|
||||
|
||||
@@ -115,7 +115,7 @@ public class GameSimulatorTest extends SimulationTestCase {
|
||||
Card bear = addCard(bearCardName, p);
|
||||
bear.setSickness(false);
|
||||
Card cloak = addCard("Whispersilk Cloak", p);
|
||||
cloak.equipCard(bear);
|
||||
cloak.attachEntity(bear);
|
||||
game.getPhaseHandler().devModeSet(PhaseType.MAIN1, p);
|
||||
game.getAction().checkStateEffects(true);
|
||||
assertEquals(1, bear.getAmountOfKeyword("Unblockable"));
|
||||
@@ -133,7 +133,7 @@ public class GameSimulatorTest extends SimulationTestCase {
|
||||
Card bear = addCard(bearCardName, p);
|
||||
bear.setSickness(false);
|
||||
Card lifelink = addCard("Lifelink", p);
|
||||
lifelink.enchantEntity(bear);
|
||||
lifelink.attachEntity(bear);
|
||||
game.getPhaseHandler().devModeSet(PhaseType.MAIN1, p);
|
||||
game.getAction().checkStateEffects(true);
|
||||
assertEquals(1, bear.getAmountOfKeyword("Lifelink"));
|
||||
@@ -661,7 +661,7 @@ public class GameSimulatorTest extends SimulationTestCase {
|
||||
Card pridemate = addCard(pridemateName, p1);
|
||||
Card indestructibility = addCard(indestructibilityName, p1);
|
||||
|
||||
indestructibility.enchantEntity(pridemate);
|
||||
indestructibility.attachEntity(pridemate);
|
||||
|
||||
Card ignition = addCardToZone(ignitionName, p1, ZoneType.Hand);
|
||||
SpellAbility ignitionSA = ignition.getFirstSpellAbility();
|
||||
@@ -681,6 +681,7 @@ public class GameSimulatorTest extends SimulationTestCase {
|
||||
|
||||
// because it was destroyed
|
||||
assertNull(simBrood);
|
||||
assertNotNull(simPridemate);
|
||||
|
||||
assertEquals(0, simKalitas.getDamage());
|
||||
assertEquals(3, simPridemate.getDamage());
|
||||
@@ -774,7 +775,7 @@ public class GameSimulatorTest extends SimulationTestCase {
|
||||
Card pridemate = addCard(pridemateName, p1);
|
||||
Card indestructibility = addCard(indestructibilityName, p1);
|
||||
|
||||
indestructibility.enchantEntity(pridemate);
|
||||
indestructibility.attachEntity(pridemate);
|
||||
|
||||
Card ignition = addCardToZone(ignitionName, p1, ZoneType.Hand);
|
||||
SpellAbility ignitionSA = ignition.getFirstSpellAbility();
|
||||
@@ -800,6 +801,7 @@ public class GameSimulatorTest extends SimulationTestCase {
|
||||
|
||||
//destoryed because of to much redirected damage
|
||||
assertNull(simPalisade);
|
||||
assertNotNull(simPridemate);
|
||||
|
||||
assertEquals(0, simKalitas.getDamage());
|
||||
assertEquals(3, simPridemate.getDamage());
|
||||
|
||||
@@ -103,17 +103,11 @@ public class GameWrapper {
|
||||
|
||||
if( card.getTarget() != null ) {
|
||||
Card target = CardSpecificationHandler.INSTANCE.find( game, card.getTarget() );
|
||||
if( actualCard.isEnchantment() ) {
|
||||
if( target.canBeEnchantedBy( actualCard ) ) {
|
||||
actualCard.enchantEntity( target );
|
||||
if (actualCard.isAttachment()) {
|
||||
if (target.canBeAttachedBy(actualCard)) {
|
||||
actualCard.attachEntity(target);
|
||||
} else {
|
||||
throw new IllegalStateException( actualCard + " can't enchant " + target );
|
||||
}
|
||||
} else if( actualCard.isEquipment() ) {
|
||||
if( target.canBeEquippedBy( actualCard ) ) {
|
||||
actualCard.equipCard( target );
|
||||
} else {
|
||||
throw new IllegalStateException( actualCard + " can't equip " + target );
|
||||
throw new IllegalStateException( actualCard + " can't attach " + target );
|
||||
}
|
||||
} else {
|
||||
throw new IllegalStateException( "Don't know how to make " + actualCard + " target anything" );
|
||||
|
||||
@@ -441,48 +441,28 @@ public class CardDetailUtil {
|
||||
area.append(")");
|
||||
}
|
||||
|
||||
// equipping
|
||||
if (card.getEquipping() != null) {
|
||||
// attached by
|
||||
if (card.isAttached()) {
|
||||
if (area.length() != 0) {
|
||||
area.append("\n");
|
||||
}
|
||||
area.append("=Equipping ");
|
||||
area.append(card.getEquipping());
|
||||
area.append("=Attached by ");
|
||||
area.append(StringUtils.join(card.getAttachedBy(), ", "));
|
||||
area.append("=");
|
||||
}
|
||||
|
||||
// equipped by
|
||||
if (card.isEquipped()) {
|
||||
// attaching
|
||||
if (card.getAttachingCard() != null) {
|
||||
if (area.length() != 0) {
|
||||
area.append("\n");
|
||||
}
|
||||
area.append("=Equipped by ");
|
||||
area.append(StringUtils.join(card.getEquippedBy(), ", "));
|
||||
area.append("=");
|
||||
area.append("*Attaching ").append(card.getAttachingCard()).append("*");
|
||||
}
|
||||
|
||||
// enchanting
|
||||
if (card.getEnchantingCard() != null) {
|
||||
if (card.getAttachingPlayer() != null) {
|
||||
if (area.length() != 0) {
|
||||
area.append("\n");
|
||||
}
|
||||
area.append("*Enchanting ").append(card.getEnchantingCard()).append("*");
|
||||
}
|
||||
if (card.getEnchantingPlayer() != null) {
|
||||
if (area.length() != 0) {
|
||||
area.append("\n");
|
||||
}
|
||||
area.append("*Enchanting ").append(card.getEnchantingPlayer()).append("*");
|
||||
}
|
||||
|
||||
// enchanted by
|
||||
if (card.isEnchanted()) {
|
||||
if (area.length() != 0) {
|
||||
area.append("\n");
|
||||
}
|
||||
area.append("*Enchanted by ");
|
||||
area.append(StringUtils.join(card.getEnchantedBy(), ", "));
|
||||
area.append("*");
|
||||
area.append("*Enchanting ").append(card.getAttachingPlayer()).append("*");
|
||||
}
|
||||
|
||||
// controlling
|
||||
|
||||
@@ -595,7 +595,7 @@ public class QuestUtil {
|
||||
rules.setManaBurn(FModel.getPreferences().getPrefBoolean(FPref.UI_MANABURN));
|
||||
rules.setCanCloneUseTargetsImage(FModel.getPreferences().getPrefBoolean(FPref.UI_CLONE_MODE_SOURCE));
|
||||
|
||||
TreeSet<GameType> variant = new TreeSet();
|
||||
final TreeSet<GameType> variant = new TreeSet<>();
|
||||
if(FModel.getQuest().getDeckConstructionRules() == DeckConstructionRules.Commander){
|
||||
variant.add(GameType.Commander);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user