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
|
// 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.
|
// to disable the permanent or it's still functional and a duplicate is unneeded.
|
||||||
boolean disabledByEnemy = false;
|
boolean disabledByEnemy = false;
|
||||||
for (Card card2 : card.getEnchantedBy(false)) {
|
for (Card card2 : card.getEnchantedBy()) {
|
||||||
if (card2.getOwner() != player) {
|
if (card2.getOwner() != player) {
|
||||||
disabledByEnemy = true;
|
disabledByEnemy = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -823,7 +823,7 @@ public class ComputerUtil {
|
|||||||
|
|
||||||
if (c != null && c.isEnchanted()) {
|
if (c != null && c.isEnchanted()) {
|
||||||
// TODO: choose "worst" controlled enchanting Aura
|
// 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)) {
|
if (aura.getController().equals(c.getController()) && remaining.contains(aura)) {
|
||||||
return aura;
|
return aura;
|
||||||
}
|
}
|
||||||
@@ -2924,7 +2924,7 @@ public class ComputerUtil {
|
|||||||
if (sa.getParam("AITgts").equals("BetterThanSource")) {
|
if (sa.getParam("AITgts").equals("BetterThanSource")) {
|
||||||
int value = ComputerUtilCard.evaluateCreature(source);
|
int value = ComputerUtilCard.evaluateCreature(source);
|
||||||
if (source.isEnchanted()) {
|
if (source.isEnchanted()) {
|
||||||
for (Card enc : source.getEnchantedBy(false)) {
|
for (Card enc : source.getEnchantedBy()) {
|
||||||
if (enc.getController().equals(ai)) {
|
if (enc.getController().equals(ai)) {
|
||||||
value += 100; // is 100 per AI's own aura enough?
|
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
|
// Add all cost of all auras with the same controller
|
||||||
if (card.isEnchanted()) {
|
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();
|
curCMC += Aggregates.sum(auras, CardPredicates.Accessors.fnGetCmc) + auras.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -833,7 +833,7 @@ public class ComputerUtilCard {
|
|||||||
int score = tmp.isTapped() ? 2 : 0;
|
int score = tmp.isTapped() ? 2 : 0;
|
||||||
score += tmp.isBasicLand() ? 1 : 0;
|
score += tmp.isBasicLand() ? 1 : 0;
|
||||||
score -= tmp.isCreature() ? 4 : 0;
|
score -= tmp.isCreature() ? 4 : 0;
|
||||||
for (Card aura : tmp.getEnchantedBy(false)) {
|
for (Card aura : tmp.getEnchantedBy()) {
|
||||||
if (aura.getController().isOpponentOf(tmp.getController())) {
|
if (aura.getController().isOpponentOf(tmp.getController())) {
|
||||||
score += 5;
|
score += 5;
|
||||||
} else {
|
} else {
|
||||||
@@ -857,7 +857,7 @@ public class ComputerUtilCard {
|
|||||||
int score = tmp.isTapped() ? 0 : 2;
|
int score = tmp.isTapped() ? 0 : 2;
|
||||||
score += tmp.isBasicLand() ? 2 : 0;
|
score += tmp.isBasicLand() ? 2 : 0;
|
||||||
score -= tmp.isCreature() ? 4 : 0;
|
score -= tmp.isCreature() ? 4 : 0;
|
||||||
score -= 5 * tmp.getEnchantedBy(false).size();
|
score -= 5 * tmp.getEnchantedBy().size();
|
||||||
|
|
||||||
if (score >= maxScore) {
|
if (score >= maxScore) {
|
||||||
land = tmp;
|
land = tmp;
|
||||||
@@ -1033,7 +1033,7 @@ public class ComputerUtilCard {
|
|||||||
// interrupt 3: two for one = good
|
// interrupt 3: two for one = good
|
||||||
if (c.isEnchanted()) {
|
if (c.isEnchanted()) {
|
||||||
boolean myEnchants = false;
|
boolean myEnchants = false;
|
||||||
for (Card enc : c.getEnchantedBy(false)) {
|
for (Card enc : c.getEnchantedBy()) {
|
||||||
if (enc.getOwner().equals(ai)) {
|
if (enc.getOwner().equals(ai)) {
|
||||||
myEnchants = true;
|
myEnchants = true;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -300,7 +300,7 @@ public class ComputerUtilCost {
|
|||||||
if (!important) {
|
if (!important) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!CardLists.filterControlledBy(source.getEnchantedBy(false), source.getController()).isEmpty()) {
|
if (!CardLists.filterControlledBy(source.getEnchantedBy(), source.getController()).isEmpty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -196,9 +196,7 @@ public abstract class GameState {
|
|||||||
cardsReferencedByID.add(card.getExiledWith());
|
cardsReferencedByID.add(card.getExiledWith());
|
||||||
}
|
}
|
||||||
if (zone == ZoneType.Battlefield) {
|
if (zone == ZoneType.Battlefield) {
|
||||||
if (!card.getEnchantedBy(false).isEmpty()
|
if (!card.getAttachedBy().isEmpty()) {
|
||||||
|| !card.getEquippedBy(false).isEmpty()
|
|
||||||
|| !card.getFortifiedBy(false).isEmpty()) {
|
|
||||||
// Remember the ID of cards that have attachments
|
// Remember the ID of cards that have attachments
|
||||||
cardsReferencedByID.add(card);
|
cardsReferencedByID.add(card);
|
||||||
}
|
}
|
||||||
@@ -290,12 +288,8 @@ public abstract class GameState {
|
|||||||
} else if (c.getCurrentStateName().equals(CardStateName.Meld)) {
|
} else if (c.getCurrentStateName().equals(CardStateName.Meld)) {
|
||||||
newText.append("|Meld");
|
newText.append("|Meld");
|
||||||
}
|
}
|
||||||
if (c.getEquipping() != null) {
|
if (c.isAttaching()) {
|
||||||
newText.append("|Attaching:").append(c.getEquipping().getId());
|
newText.append("|Attaching:").append(c.getAttaching().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.getEnchantingPlayer() != null) {
|
if (c.getEnchantingPlayer() != null) {
|
||||||
// TODO: improve this for game states with more than two players
|
// TODO: improve this for game states with more than two players
|
||||||
@@ -959,25 +953,15 @@ public abstract class GameState {
|
|||||||
// Unattach all permanents first
|
// Unattach all permanents first
|
||||||
for(Entry<Card, Integer> entry : cardToAttachId.entrySet()) {
|
for(Entry<Card, Integer> entry : cardToAttachId.entrySet()) {
|
||||||
Card attachedTo = idToCard.get(entry.getValue());
|
Card attachedTo = idToCard.get(entry.getValue());
|
||||||
|
attachedTo.unAttachAllCards();
|
||||||
attachedTo.unEnchantAllCards();
|
|
||||||
attachedTo.unEquipAllCards();
|
|
||||||
for (Card c : attachedTo.getFortifiedBy(true)) {
|
|
||||||
attachedTo.unFortifyCard(c);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attach permanents by ID
|
// Attach permanents by ID
|
||||||
for(Entry<Card, Integer> entry : cardToAttachId.entrySet()) {
|
for(Entry<Card, Integer> entry : cardToAttachId.entrySet()) {
|
||||||
Card attachedTo = idToCard.get(entry.getValue());
|
Card attachedTo = idToCard.get(entry.getValue());
|
||||||
Card attacher = entry.getKey();
|
Card attacher = entry.getKey();
|
||||||
|
if (attacher.isAttachment()) {
|
||||||
if (attacher.isEquipment()) {
|
attacher.attachEntity(attachedTo);
|
||||||
attacher.equipCard(attachedTo);
|
|
||||||
} else if (attacher.isAura()) {
|
|
||||||
attacher.enchantEntity(attachedTo);
|
|
||||||
} else if (attacher.isFortified()) {
|
|
||||||
attacher.fortifyCard(attachedTo);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -988,7 +972,7 @@ public abstract class GameState {
|
|||||||
Game game = attacher.getGame();
|
Game game = attacher.getGame();
|
||||||
Player attachedTo = entry.getValue() == TARGET_AI ? game.getPlayers().get(1) : game.getPlayers().get(0);
|
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()) {
|
if (c.isAura()) {
|
||||||
// dummy "enchanting" to indicate that the card will be force-attached elsewhere
|
// dummy "enchanting" to indicate that the card will be force-attached elsewhere
|
||||||
// (will be overridden later, so the actual value shouldn't matter)
|
// (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)) {
|
if (cardsWithoutETBTrigs.contains(c)) {
|
||||||
|
|||||||
@@ -408,7 +408,7 @@ public class AttachAi extends SpellAbilityAi {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
final Iterable<Card> auras = c.getEnchantedBy(false);
|
final Iterable<Card> auras = c.getEnchantedBy();
|
||||||
final Iterator<Card> itr = auras.iterator();
|
final Iterator<Card> itr = auras.iterator();
|
||||||
while (itr.hasNext()) {
|
while (itr.hasNext()) {
|
||||||
final Card aura = itr.next();
|
final Card aura = itr.next();
|
||||||
@@ -1276,7 +1276,7 @@ public class AttachAi extends SpellAbilityAi {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// Don't fortify if already fortifying
|
// Don't fortify if already fortifying
|
||||||
if (attachSource.getFortifying() != null && attachSource.getFortifying().getController() == aiPlayer) {
|
if (attachSource.getAttachingCard() != null && attachSource.getAttachingCard().getController() == aiPlayer) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1491,7 +1491,7 @@ public class AttachAi extends SpellAbilityAi {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Also don't play if it would destroy own Aura
|
// 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))) {
|
if ((c.getController().equals(ai)) && (c.isOfColor(cc))) {
|
||||||
return false;
|
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
|
return true; // debuffed by opponent's auras to the level that it becomes useless
|
||||||
}
|
}
|
||||||
int delta = 0;
|
int delta = 0;
|
||||||
for (Card enc : sa.getHostCard().getEnchantedBy(false)) {
|
for (Card enc : sa.getHostCard().getEnchantedBy()) {
|
||||||
if (enc.getController().isOpponentOf(aiPlayer)) {
|
if (enc.getController().isOpponentOf(aiPlayer)) {
|
||||||
delta--;
|
delta--;
|
||||||
} else {
|
} else {
|
||||||
@@ -961,7 +961,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
|
|||||||
list = CardLists.filter(list, new Predicate<Card>() {
|
list = CardLists.filter(list, new Predicate<Card>() {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(final Card c) {
|
public boolean apply(final Card c) {
|
||||||
for (Card aura : c.getEnchantedBy(false)) {
|
for (Card aura : c.getEnchantedBy()) {
|
||||||
if (aura.getController().isOpponentOf(ai)) {
|
if (aura.getController().isOpponentOf(ai)) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
@@ -1054,7 +1054,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
|
|||||||
list = CardLists.filter(list, new Predicate<Card>() {
|
list = CardLists.filter(list, new Predicate<Card>() {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(final Card c) {
|
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)) {
|
if (c.getOwner().isOpponentOf(ai) && aura.getController().equals(ai)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ public class CountersPutAi extends SpellAbilityAi {
|
|||||||
if (sa.hasParam("LevelUp")) {
|
if (sa.hasParam("LevelUp")) {
|
||||||
// creatures enchanted by curse auras have low priority
|
// creatures enchanted by curse auras have low priority
|
||||||
if (ph.getPhase().isBefore(PhaseType.MAIN2)) {
|
if (ph.getPhase().isBefore(PhaseType.MAIN2)) {
|
||||||
for (Card aura : source.getEnchantedBy(false)) {
|
for (Card aura : source.getEnchantedBy()) {
|
||||||
if (aura.getController().isOpponentOf(ai)) {
|
if (aura.getController().isOpponentOf(ai)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ public abstract class DamageAiBase extends SpellAbilityAi {
|
|||||||
Card hostcard = sa.getHostCard();
|
Card hostcard = sa.getHostCard();
|
||||||
boolean lifelink = hostcard.hasKeyword(Keyword.LIFELINK);
|
boolean lifelink = hostcard.hasKeyword(Keyword.LIFELINK);
|
||||||
if (!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.
|
// Treat cards enchanted by older cards with "when enchanted creature deals damage, gain life" as if they had lifelink.
|
||||||
if (ench.hasSVar("LikeLifeLink")) {
|
if (ench.hasSVar("LikeLifeLink")) {
|
||||||
if ("True".equals(ench.getSVar("LikeLifeLink"))) {
|
if ("True".equals(ench.getSVar("LikeLifeLink"))) {
|
||||||
|
|||||||
@@ -273,7 +273,7 @@ public class DestroyAi extends SpellAbilityAi {
|
|||||||
} else {
|
} else {
|
||||||
// Don't destroy stolen permanents when the stealing aura can be destroyed
|
// Don't destroy stolen permanents when the stealing aura can be destroyed
|
||||||
if (choice.getOwner() == ai) {
|
if (choice.getOwner() == ai) {
|
||||||
for (Card aura : choice.getEnchantedBy(false)) {
|
for (Card aura : choice.getEnchantedBy()) {
|
||||||
SpellAbility sp = aura.getFirstSpellAbility();
|
SpellAbility sp = aura.getFirstSpellAbility();
|
||||||
if (sp != null && "GainControl".equals(sp.getParam("AILogic"))
|
if (sp != null && "GainControl".equals(sp.getParam("AILogic"))
|
||||||
&& aura.getController() != ai && sa.canTarget(aura)) {
|
&& 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
|
// 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).
|
// like a reasonable default for some cards).
|
||||||
for (Card c : ctrld) {
|
for (Card c : ctrld) {
|
||||||
if (c.getEnchantedBy(false).isEmpty()) {
|
if (c.getEnchantedBy().isEmpty()) {
|
||||||
numControlled++;
|
numControlled++;
|
||||||
} else {
|
} else {
|
||||||
for (Card att : c.getEnchantedBy(false)) {
|
for (Card att : c.getEnchantedBy()) {
|
||||||
if (!att.getController().isOpponentOf(ai)) {
|
if (!att.getController().isOpponentOf(ai)) {
|
||||||
numControlled++;
|
numControlled++;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import forge.LobbyPlayer;
|
|||||||
import forge.ai.LobbyPlayerAi;
|
import forge.ai.LobbyPlayerAi;
|
||||||
import forge.card.CardStateName;
|
import forge.card.CardStateName;
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
|
import forge.game.GameEntity;
|
||||||
import forge.game.GameObject;
|
import forge.game.GameObject;
|
||||||
import forge.game.GameObjectMap;
|
import forge.game.GameObjectMap;
|
||||||
import forge.game.GameRules;
|
import forge.game.GameRules;
|
||||||
@@ -204,19 +205,16 @@ public class GameCopier {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
gameObjectMap = new CopiedGameObjectMap(newGame);
|
gameObjectMap = new CopiedGameObjectMap(newGame);
|
||||||
|
|
||||||
for (Card card : origGame.getCardsIn(ZoneType.Battlefield)) {
|
for (Card card : origGame.getCardsIn(ZoneType.Battlefield)) {
|
||||||
Card otherCard = cardMap.get(card);
|
Card otherCard = cardMap.get(card);
|
||||||
otherCard.setTimestamp(card.getTimestamp());
|
otherCard.setTimestamp(card.getTimestamp());
|
||||||
otherCard.setSickness(card.hasSickness());
|
otherCard.setSickness(card.hasSickness());
|
||||||
otherCard.setState(card.getCurrentStateName(), false);
|
otherCard.setState(card.getCurrentStateName(), false);
|
||||||
if (card.isEnchanting()) {
|
if (card.isAttaching()) {
|
||||||
otherCard.setEnchanting(gameObjectMap.map(card.getEnchanting()));
|
GameEntity ge = gameObjectMap.map(card.getAttaching());
|
||||||
}
|
otherCard.setAttaching(ge);
|
||||||
if (card.isEquipping()) {
|
ge.addAttachedBy(otherCard);
|
||||||
otherCard.equipCard(cardMap.get(card.getEquipping()));
|
|
||||||
}
|
|
||||||
if (card.isFortifying()) {
|
|
||||||
otherCard.setFortifying(cardMap.get(card.getFortifying()));
|
|
||||||
}
|
}
|
||||||
if (card.getCloneOrigin() != null) {
|
if (card.getCloneOrigin() != null) {
|
||||||
otherCard.setCloneOrigin(cardMap.get(card.getCloneOrigin()));
|
otherCard.setCloneOrigin(cardMap.get(card.getCloneOrigin()));
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ import forge.game.replacement.ReplacementResult;
|
|||||||
import forge.game.spellability.AbilitySub;
|
import forge.game.spellability.AbilitySub;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
import forge.game.spellability.SpellAbilityPredicates;
|
import forge.game.spellability.SpellAbilityPredicates;
|
||||||
import forge.game.spellability.TargetRestrictions;
|
|
||||||
import forge.game.staticability.StaticAbility;
|
import forge.game.staticability.StaticAbility;
|
||||||
import forge.game.staticability.StaticAbilityLayer;
|
import forge.game.staticability.StaticAbilityLayer;
|
||||||
import forge.game.trigger.Trigger;
|
import forge.game.trigger.Trigger;
|
||||||
@@ -504,45 +503,12 @@ public class GameAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void unattachCardLeavingBattlefield(final Card copied) {
|
private static void unattachCardLeavingBattlefield(final Card copied) {
|
||||||
// Handle unequipping creatures
|
// remove attachments from creatures
|
||||||
if (copied.isEquipped()) {
|
copied.unAttachAllCards();
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// unenchant creature if moving aura
|
// unenchant creature if moving aura
|
||||||
if (copied.isEnchanting()) {
|
if (copied.isAttaching()) {
|
||||||
copied.unEnchantEntity(copied.getEnchanting());
|
copied.unAttachEntity(copied.getAttaching());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1006,11 +972,10 @@ public class GameAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
checkAgain |= stateBasedAction_Saga(c);
|
checkAgain |= stateBasedAction_Saga(c);
|
||||||
checkAgain |= stateBasedAction704_5n(c); // Auras attached to illegal or not attached go to graveyard
|
checkAgain |= stateBasedAction704_attach(c); // Attachment
|
||||||
checkAgain |= stateBasedAction704_5p(c); // Equipment and Fortifications
|
|
||||||
|
|
||||||
if (c.isCreature() && c.isEnchanting()) { // Rule 704.5q - Creature attached to an object or player, becomes unattached
|
if (c.isCreature() && c.isAttaching()) { // Rule 704.5q - Creature attached to an object or player, becomes unattached
|
||||||
c.unEnchantEntity(c.getEnchanting());
|
c.unAttachEntity(c.getAttaching());
|
||||||
checkAgain = true;
|
checkAgain = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1124,110 +1089,34 @@ public class GameAction {
|
|||||||
return checkAgain;
|
return checkAgain;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean stateBasedAction704_5n(Card c) {
|
private boolean stateBasedAction704_attach(Card c) {
|
||||||
boolean checkAgain = false;
|
boolean checkAgain = false;
|
||||||
if (!c.isAura()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if Card Aura is attached to is a legal target
|
if (c.isAttaching()) {
|
||||||
final GameEntity entity = c.getEnchanting();
|
final GameEntity ge = c.getAttaching();
|
||||||
SpellAbility sa = c.getFirstAttachSpell();
|
if (!ge.canBeAttachedBy(c)) {
|
||||||
|
c.unAttachEntity(ge);
|
||||||
TargetRestrictions tgt = null;
|
|
||||||
if (sa != null) {
|
|
||||||
tgt = sa.getTargetRestrictions();
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
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;
|
checkAgain = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c.isInPlay() && !c.isEnchanting()) {
|
if (c.isAttachedBy()) {
|
||||||
|
for (final Card attach : Lists.newArrayList(c.getAttachedBy())) {
|
||||||
|
if (!attach.isInPlay()) {
|
||||||
|
attach.unAttachEntity(c);
|
||||||
|
checkAgain = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// cleanup aura
|
||||||
|
if (c.isAura() && c.isInPlay() && !c.isEnchanting()) {
|
||||||
moveToGraveyard(c, null, null);
|
moveToGraveyard(c, null, null);
|
||||||
checkAgain = true;
|
checkAgain = true;
|
||||||
}
|
}
|
||||||
return checkAgain;
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean stateBasedAction704_5r(Card c) {
|
private boolean stateBasedAction704_5r(Card c) {
|
||||||
boolean checkAgain = false;
|
boolean checkAgain = false;
|
||||||
int plusOneCounters = c.getCounters(CounterType.P1P1);
|
int plusOneCounters = c.getCounters(CounterType.P1P1);
|
||||||
|
|||||||
@@ -6,12 +6,12 @@
|
|||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
@@ -21,9 +21,10 @@ import forge.game.card.Card;
|
|||||||
import forge.game.card.CardCollection;
|
import forge.game.card.CardCollection;
|
||||||
import forge.game.card.CardCollectionView;
|
import forge.game.card.CardCollectionView;
|
||||||
import forge.game.card.CardDamageMap;
|
import forge.game.card.CardDamageMap;
|
||||||
|
import forge.game.card.CardLists;
|
||||||
|
import forge.game.card.CardPredicates;
|
||||||
import forge.game.card.CounterType;
|
import forge.game.card.CounterType;
|
||||||
import forge.game.event.GameEventCardAttachment;
|
import forge.game.event.GameEventCardAttachment;
|
||||||
import forge.game.event.GameEventCardAttachment.AttachMethod;
|
|
||||||
import forge.game.keyword.Keyword;
|
import forge.game.keyword.Keyword;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
@@ -33,6 +34,7 @@ import forge.util.collect.FCollection;
|
|||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
|
|
||||||
|
|
||||||
@@ -40,7 +42,7 @@ public abstract class GameEntity extends GameObject implements IIdentifiable {
|
|||||||
protected final int id;
|
protected final int id;
|
||||||
private String name = "";
|
private String name = "";
|
||||||
private int preventNextDamage = 0;
|
private int preventNextDamage = 0;
|
||||||
private CardCollection enchantedBy;
|
protected CardCollection attachedBy;
|
||||||
private Map<Card, Map<String, String>> preventionShieldsWithEffects = Maps.newTreeMap();
|
private Map<Card, Map<String, String>> preventionShieldsWithEffects = Maps.newTreeMap();
|
||||||
protected Map<CounterType, Integer> counters = Maps.newEnumMap(CounterType.class);
|
protected Map<CounterType, Integer> counters = Maps.newEnumMap(CounterType.class);
|
||||||
|
|
||||||
@@ -93,7 +95,7 @@ public abstract class GameEntity extends GameObject implements IIdentifiable {
|
|||||||
source.getDamageHistory().registerCombatDamage(this);
|
source.getDamageHistory().registerCombatDamage(this);
|
||||||
}
|
}
|
||||||
// damage prevention is already checked
|
// damage prevention is already checked
|
||||||
return addCombatDamageBase(damageToDo, source, damageMap);
|
return addCombatDamageBase(damageToDo, source, damageMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected int addCombatDamageBase(final int damage, final Card source, CardDamageMap damageMap) {
|
protected int addCombatDamageBase(final int damage, final Card source, CardDamageMap damageMap) {
|
||||||
@@ -204,17 +206,17 @@ public abstract class GameEntity extends GameObject implements IIdentifiable {
|
|||||||
restDamage = 0;
|
restDamage = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if damage is greater than restDamage, damage was prevented
|
// if damage is greater than restDamage, damage was prevented
|
||||||
if (damage > restDamage) {
|
if (damage > restDamage) {
|
||||||
int prevent = damage - restDamage;
|
int prevent = damage - restDamage;
|
||||||
preventMap.put(source, this, damage - restDamage);
|
preventMap.put(source, this, damage - restDamage);
|
||||||
|
|
||||||
final Map<String, Object> runParams = Maps.newHashMap();
|
final Map<String, Object> runParams = Maps.newHashMap();
|
||||||
runParams.put("DamageTarget", this);
|
runParams.put("DamageTarget", this);
|
||||||
runParams.put("DamageAmount", prevent);
|
runParams.put("DamageAmount", prevent);
|
||||||
runParams.put("DamageSource", source);
|
runParams.put("DamageSource", source);
|
||||||
runParams.put("IsCombatDamage", isCombat);
|
runParams.put("IsCombatDamage", isCombat);
|
||||||
|
|
||||||
getGame().getTriggerHandler().runTrigger(TriggerType.DamagePrevented, runParams, false);
|
getGame().getTriggerHandler().runTrigger(TriggerType.DamagePrevented, runParams, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -280,77 +282,140 @@ public abstract class GameEntity extends GameObject implements IIdentifiable {
|
|||||||
public abstract boolean hasKeyword(final String keyword);
|
public abstract boolean hasKeyword(final String keyword);
|
||||||
public abstract boolean hasKeyword(final Keyword keyword);
|
public abstract boolean hasKeyword(final Keyword keyword);
|
||||||
|
|
||||||
// GameEntities can now be Enchanted
|
public final CardCollectionView getEnchantedBy() {
|
||||||
public final CardCollectionView getEnchantedBy(boolean allowModify) {
|
if (attachedBy == null) {
|
||||||
return CardCollection.getView(enchantedBy, allowModify);
|
return CardCollection.EMPTY;
|
||||||
|
}
|
||||||
|
// enchanted means attached by Aura
|
||||||
|
return CardLists.filter(attachedBy, CardPredicates.Presets.AURA);
|
||||||
}
|
}
|
||||||
public final void setEnchantedBy(final CardCollection cards) {
|
|
||||||
enchantedBy = cards;
|
public final CardCollectionView getAttachedBy() {
|
||||||
getView().updateEnchantedBy(this);
|
return CardCollection.getView(attachedBy);
|
||||||
}
|
}
|
||||||
public final void setEnchantedBy(final Iterable<Card> cards) {
|
|
||||||
|
public final void setAttachedBy(final Iterable<Card> cards) {
|
||||||
if (cards == null) {
|
if (cards == null) {
|
||||||
enchantedBy = null;
|
attachedBy = null;
|
||||||
}
|
}
|
||||||
else {
|
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() {
|
public final boolean isEnchanted() {
|
||||||
return FCollection.hasElements(enchantedBy);
|
if (attachedBy == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// enchanted means attached by Aura
|
||||||
|
return CardLists.count(attachedBy, CardPredicates.Presets.AURA) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final boolean isAttachedBy(Card c) {
|
||||||
|
return FCollection.hasElement(attachedBy, c);
|
||||||
}
|
}
|
||||||
public final boolean isEnchantedBy(Card c) {
|
public final boolean isEnchantedBy(Card c) {
|
||||||
return FCollection.hasElement(enchantedBy, c);
|
// Rule 303.4k Even if c is no Aura it still counts
|
||||||
|
return isAttachedBy(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
public final boolean isEnchantedBy(final String cardName) {
|
||||||
for (final Card aura : getEnchantedBy(false)) {
|
// Rule 303.4k Even if c is no Aura it still counts
|
||||||
if (aura.getName().equals(cardName)) {
|
return isAttachedBy(cardName);
|
||||||
return true;
|
}
|
||||||
}
|
|
||||||
|
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 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;
|
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)) {
|
public boolean canBeFortifiedBy(final Card aura) {
|
||||||
if (enchantedBy.isEmpty()) {
|
return false;
|
||||||
enchantedBy = null;
|
|
||||||
}
|
|
||||||
getView().updateEnchantedBy(this);
|
|
||||||
getGame().fireEvent(new GameEventCardAttachment(c, this, null, AttachMethod.Enchant));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public final void unEnchantAllCards() {
|
|
||||||
if (isEnchanted()) {
|
|
||||||
for (Card c : getEnchantedBy(true)) {
|
|
||||||
c.unEnchantEntity(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean canBeEnchantedBy(final Card aura) {
|
public boolean canBeEnchantedBy(final Card aura, final boolean checkSBA) {
|
||||||
|
if (!aura.isAura()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
SpellAbility sa = aura.getFirstAttachSpell();
|
SpellAbility sa = aura.getFirstAttachSpell();
|
||||||
TargetRestrictions tgt = null;
|
TargetRestrictions tgt = null;
|
||||||
if (sa != null) {
|
if (sa != null) {
|
||||||
tgt = sa.getTargetRestrictions();
|
tgt = sa.getTargetRestrictions();
|
||||||
}
|
}
|
||||||
|
|
||||||
return !(hasProtectionFrom(aura)
|
return !(hasProtectionFrom(aura, checkSBA)
|
||||||
|| ((tgt != null) && !isValid(tgt.getValidTgts(), aura.getController(), aura, sa)));
|
|| ((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!
|
// Counters!
|
||||||
public boolean hasCounters() {
|
public boolean hasCounters() {
|
||||||
|
|||||||
@@ -42,18 +42,19 @@ public abstract class GameEntityView extends TrackableObject {
|
|||||||
set(TrackableProperty.PreventNextDamage, e.getPreventNextDamageTotalShields());
|
set(TrackableProperty.PreventNextDamage, e.getPreventNextDamageTotalShields());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Iterable<CardView> getEnchantedBy() {
|
public Iterable<CardView> getAttachedBy() {
|
||||||
return get(TrackableProperty.EnchantedBy);
|
return get(TrackableProperty.AttachedBy);
|
||||||
}
|
}
|
||||||
protected void updateEnchantedBy(GameEntity e) {
|
public boolean isAttached() {
|
||||||
if (e.isEnchanted()) {
|
return getAttachedBy() != null;
|
||||||
set(TrackableProperty.EnchantedBy, CardView.getCollection(e.getEnchantedBy(false)));
|
}
|
||||||
|
|
||||||
|
protected void updateAttachedBy(GameEntity e) {
|
||||||
|
if (e.isAttachedBy()) {
|
||||||
|
set(TrackableProperty.AttachedBy, CardView.getCollection(e.getAttachedBy()));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
set(TrackableProperty.EnchantedBy, null);
|
set(TrackableProperty.AttachedBy, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public boolean isEnchanted() {
|
|
||||||
return getEnchantedBy() != null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ public class AttachEffect extends SpellAbilityEffect {
|
|||||||
final Player ap = sa.getActivatingPlayer();
|
final Player ap = sa.getActivatingPlayer();
|
||||||
// The Spell_Permanent (Auras) version of this AF needs to
|
// The Spell_Permanent (Auras) version of this AF needs to
|
||||||
// move the card into play before Attaching
|
// move the card into play before Attaching
|
||||||
|
|
||||||
sa.getHostCard().setController(ap, 0);
|
sa.getHostCard().setController(ap, 0);
|
||||||
final Card c = ap.getGame().getAction().moveTo(ap.getZone(ZoneType.Battlefield), sa.getHostCard(), sa);
|
final Card c = ap.getGame().getAction().moveTo(ap.getZone(ZoneType.Battlefield), sa.getHostCard(), sa);
|
||||||
sa.setHostCard(c);
|
sa.setHostCard(c);
|
||||||
@@ -82,7 +82,7 @@ public class AttachEffect extends SpellAbilityEffect {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle attachment.
|
* Handle attachment.
|
||||||
*
|
*
|
||||||
* @param card
|
* @param card
|
||||||
* the card
|
* the card
|
||||||
* @param o
|
* @param o
|
||||||
@@ -104,12 +104,8 @@ public class AttachEffect extends SpellAbilityEffect {
|
|||||||
if (c.canBeEnchantedBy(card)) {
|
if (c.canBeEnchantedBy(card)) {
|
||||||
handleAura(card, c);
|
handleAura(card, c);
|
||||||
}
|
}
|
||||||
} else if (card.isEquipment()) {
|
} else {
|
||||||
if(c.canBeEquippedBy(card)) {
|
card.attachEntity(c);
|
||||||
card.equipCard(c);
|
|
||||||
}
|
|
||||||
} else if (card.isFortification()) {
|
|
||||||
card.fortifyCard(c);
|
|
||||||
}
|
}
|
||||||
} else if (o instanceof Player) {
|
} else if (o instanceof Player) {
|
||||||
// Currently, a few cards can enchant players
|
// Currently, a few cards can enchant players
|
||||||
@@ -124,42 +120,34 @@ public class AttachEffect extends SpellAbilityEffect {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle aura.
|
* Handle aura.
|
||||||
*
|
*
|
||||||
* @param card
|
* @param card
|
||||||
* the card
|
* the card
|
||||||
* @param tgt
|
* @param tgt
|
||||||
* the tgt
|
* the tgt
|
||||||
*/
|
*/
|
||||||
public static void handleAura(final Card card, final GameEntity 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() {
|
final GameCommand onLeavesPlay = new GameCommand() {
|
||||||
private static final long serialVersionUID = -639204333673364477L;
|
private static final long serialVersionUID = -639204333673364477L;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
final GameEntity entity = card.getEnchanting();
|
final GameEntity entity = card.getAttaching();
|
||||||
if (entity == null) {
|
if (entity == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
card.unEnchantEntity(entity);
|
card.unAttachEntity(entity);
|
||||||
}
|
}
|
||||||
}; // Command
|
}; // Command
|
||||||
|
|
||||||
card.addLeavesPlayCommand(onLeavesPlay);
|
card.addLeavesPlayCommand(onLeavesPlay);
|
||||||
card.enchantEntity(tgt);
|
card.attachEntity(tgt);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attach aura on indirect enter battlefield.
|
* Attach aura on indirect enter battlefield.
|
||||||
*
|
*
|
||||||
* @param source
|
* @param source
|
||||||
* the source
|
* the source
|
||||||
* @return true, if successful
|
* @return true, if successful
|
||||||
|
|||||||
@@ -504,29 +504,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
|
|||||||
}
|
}
|
||||||
if (!list.isEmpty()) {
|
if (!list.isEmpty()) {
|
||||||
Card attachedTo = player.getController().chooseSingleEntityForEffect(list, sa, tgtC + " - Select a card to attach to.");
|
Card attachedTo = player.getController().chooseSingleEntityForEffect(list, sa, tgtC + " - Select a card to attach to.");
|
||||||
if (tgtC.isAura()) {
|
tgtC.attachEntity(attachedTo);
|
||||||
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);
|
|
||||||
}
|
|
||||||
} else { // When it should enter the battlefield attached to an illegal permanent it fails
|
} else { // When it should enter the battlefield attached to an illegal permanent it fails
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -536,15 +514,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
|
|||||||
FCollectionView<Player> list = AbilityUtils.getDefinedPlayers(hostCard, sa.getParam("AttachedToPlayer"), sa);
|
FCollectionView<Player> list = AbilityUtils.getDefinedPlayers(hostCard, sa.getParam("AttachedToPlayer"), sa);
|
||||||
if (!list.isEmpty()) {
|
if (!list.isEmpty()) {
|
||||||
Player attachedTo = player.getController().chooseSingleEntityForEffect(list, sa, tgtC + " - Select a player to attach to.");
|
Player attachedTo = player.getController().chooseSingleEntityForEffect(list, sa, tgtC + " - Select a player to attach to.");
|
||||||
if (tgtC.isAura()) {
|
tgtC.attachEntity(attachedTo);
|
||||||
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 { // When it should enter the battlefield attached to an illegal player it fails
|
else { // When it should enter the battlefield attached to an illegal player it fails
|
||||||
continue;
|
continue;
|
||||||
@@ -1022,42 +992,9 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
|
|||||||
else {
|
else {
|
||||||
attachedTo = list.get(0);
|
attachedTo = list.get(0);
|
||||||
}
|
}
|
||||||
if (c.isAura()) {
|
|
||||||
if (c.isEnchanting()) {
|
if (c.isAttachment()) {
|
||||||
// If this Card is already Enchanting something, need
|
c.attachEntity(attachedTo);
|
||||||
// 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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else { // When it should enter the battlefield attached to an illegal permanent it fails
|
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);
|
FCollectionView<Player> list = AbilityUtils.getDefinedPlayers(source, sa.getParam("AttachedToPlayer"), sa);
|
||||||
if (!list.isEmpty()) {
|
if (!list.isEmpty()) {
|
||||||
Player attachedTo = player.getController().chooseSingleEntityForEffect(list, sa, c + " - Select a player to attach to.");
|
Player attachedTo = player.getController().chooseSingleEntityForEffect(list, sa, c + " - Select a player to attach to.");
|
||||||
if (c.isAura()) {
|
c.attachEntity(attachedTo);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else { // When it should enter the battlefield attached to an illegal permanent it fails
|
else { // When it should enter the battlefield attached to an illegal permanent it fails
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -154,9 +154,9 @@ public class CopyPermanentEffect extends SpellAbilityEffect {
|
|||||||
choices = CardLists.getValidCards(choices, sa.getParam("Choices"), activator, host);
|
choices = CardLists.getValidCards(choices, sa.getParam("Choices"), activator, host);
|
||||||
if (!choices.isEmpty()) {
|
if (!choices.isEmpty()) {
|
||||||
String title = sa.hasParam("ChoiceTitle") ? sa.getParam("ChoiceTitle") : "Choose a card ";
|
String title = sa.hasParam("ChoiceTitle") ? sa.getParam("ChoiceTitle") : "Choose a card ";
|
||||||
|
|
||||||
Card choosen = chooser.getController().chooseSingleEntityForEffect(choices, sa, title, false);
|
Card choosen = chooser.getController().chooseSingleEntityForEffect(choices, sa, title, false);
|
||||||
|
|
||||||
if (choosen != null) {
|
if (choosen != null) {
|
||||||
tgtCards.add(choosen);
|
tgtCards.add(choosen);
|
||||||
}
|
}
|
||||||
@@ -238,21 +238,8 @@ public class CopyPermanentEffect extends SpellAbilityEffect {
|
|||||||
}
|
}
|
||||||
if (!list.isEmpty()) {
|
if (!list.isEmpty()) {
|
||||||
Card attachedTo = activator.getController().chooseSingleEntityForEffect(list, sa, copyInPlay + " - Select a card to attach to.");
|
Card attachedTo = activator.getController().chooseSingleEntityForEffect(list, sa, copyInPlay + " - Select a card to attach to.");
|
||||||
if (copyInPlay.isAura()) {
|
|
||||||
if (attachedTo.canBeEnchantedBy(copyInPlay)) {
|
copyInPlay.attachEntity(attachedTo);
|
||||||
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);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -95,9 +95,7 @@ public class DestroyEffect extends SpellAbilityEffect {
|
|||||||
boolean destroyed = false;
|
boolean destroyed = false;
|
||||||
final Card lki = CardUtil.getLKICopy(tgtC);
|
final Card lki = CardUtil.getLKICopy(tgtC);
|
||||||
if (remAttached) {
|
if (remAttached) {
|
||||||
card.addRemembered(tgtC.getEnchantedBy(false));
|
card.addRemembered(tgtC.getAttachedBy());
|
||||||
card.addRemembered(tgtC.getEquippedBy(false));
|
|
||||||
card.addRemembered(tgtC.getFortifiedBy(false));
|
|
||||||
}
|
}
|
||||||
if (sac) {
|
if (sac) {
|
||||||
destroyed = game.getAction().sacrifice(tgtC, sa) != null;
|
destroyed = game.getAction().sacrifice(tgtC, sa) != null;
|
||||||
|
|||||||
@@ -495,32 +495,10 @@ public class TokenEffect extends SpellAbilityEffect {
|
|||||||
game.getAction().checkStaticAbilities(false, Sets.newHashSet(lki), preList);
|
game.getAction().checkStaticAbilities(false, Sets.newHashSet(lki), preList);
|
||||||
|
|
||||||
// TODO update when doing Attach Update
|
// TODO update when doing Attach Update
|
||||||
boolean canAttach = lki.isAura() || lki.isEquipment() || lki.isFortification();
|
boolean canAttach = lki.isAttachment();
|
||||||
|
|
||||||
if (lki.isAura()) {
|
if (canAttach && ge.canBeAttachedBy(lki)) {
|
||||||
if (!ge.canBeEnchantedBy(lki)) {
|
canAttach = false;
|
||||||
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
|
// reset static abilities
|
||||||
@@ -531,20 +509,7 @@ public class TokenEffect extends SpellAbilityEffect {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO update when doing Attach Update
|
tok.attachEntity(ge);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
// not a GameEntity, cant be attach
|
// not a GameEntity, cant be attach
|
||||||
|
|||||||
@@ -17,25 +17,8 @@ import java.util.List;
|
|||||||
|
|
||||||
public class UnattachAllEffect extends SpellAbilityEffect {
|
public class UnattachAllEffect extends SpellAbilityEffect {
|
||||||
private static void handleUnattachment(final GameEntity o, final Card cardToUnattach) {
|
private static void handleUnattachment(final GameEntity o, final Card cardToUnattach) {
|
||||||
if (o instanceof Card) {
|
if (cardToUnattach.isAttachment() && o.isAttachedBy(cardToUnattach)) {
|
||||||
final Card c = (Card) o;
|
cardToUnattach.unAttachEntity(cardToUnattach.getAttaching());
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,13 +31,9 @@ public class UnattachEffect extends SpellAbilityEffect {
|
|||||||
if (cardToUnattach.isAura()) {
|
if (cardToUnattach.isAura()) {
|
||||||
//final boolean gainControl = "GainControl".equals(af.parseParams().get("AILogic"));
|
//final boolean gainControl = "GainControl".equals(af.parseParams().get("AILogic"));
|
||||||
//AbilityFactoryAttach.handleUnattachAura(cardToUnattach, c, gainControl);
|
//AbilityFactoryAttach.handleUnattachAura(cardToUnattach, c, gainControl);
|
||||||
} else if (cardToUnattach.isEquipment()) {
|
} else if (cardToUnattach.isAttachment()) {
|
||||||
if (cardToUnattach.isEquipping()) {
|
if (cardToUnattach.isAttaching()) {
|
||||||
cardToUnattach.unEquipCard(cardToUnattach.getEquipping());
|
cardToUnattach.unAttachEntity(cardToUnattach.getAttaching());
|
||||||
}
|
|
||||||
} else if (cardToUnattach.isFortification()) {
|
|
||||||
if (cardToUnattach.isFortifying()) {
|
|
||||||
cardToUnattach.unFortifyCard(cardToUnattach.getFortifying());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,8 +83,8 @@ public class ZoneExchangeEffect extends SpellAbilityEffect {
|
|||||||
}
|
}
|
||||||
// Enchant first
|
// Enchant first
|
||||||
if (c != null) {
|
if (c != null) {
|
||||||
object1.unEnchantEntity(c);
|
object1.unAttachEntity(c);
|
||||||
object2.enchantEntity(c);
|
object2.attachEntity(c);
|
||||||
}
|
}
|
||||||
// Exchange Zone
|
// Exchange Zone
|
||||||
game.getAction().moveTo(zone2, object1, sa);
|
game.getAction().moveTo(zone2, object1, sa);
|
||||||
|
|||||||
@@ -37,7 +37,6 @@ import forge.game.combat.Combat;
|
|||||||
import forge.game.cost.Cost;
|
import forge.game.cost.Cost;
|
||||||
import forge.game.cost.CostSacrifice;
|
import forge.game.cost.CostSacrifice;
|
||||||
import forge.game.event.*;
|
import forge.game.event.*;
|
||||||
import forge.game.event.GameEventCardAttachment.AttachMethod;
|
|
||||||
import forge.game.event.GameEventCardDamaged.DamageType;
|
import forge.game.event.GameEventCardDamaged.DamageType;
|
||||||
import forge.game.keyword.Keyword;
|
import forge.game.keyword.Keyword;
|
||||||
import forge.game.keyword.KeywordCollection;
|
import forge.game.keyword.KeywordCollection;
|
||||||
@@ -98,14 +97,13 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
private final KeywordCollection hiddenExtrinsicKeyword = new KeywordCollection();
|
private final KeywordCollection hiddenExtrinsicKeyword = new KeywordCollection();
|
||||||
|
|
||||||
// cards attached or otherwise linked to this card
|
// 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;
|
private CardCollection mustBlockCards, clones, gainControlTargets, chosenCards, blockedThisTurn, blockedByThisTurn;
|
||||||
|
|
||||||
// if this card is attached or linked to something, what card is it currently attached to
|
// 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 attaching = null;
|
||||||
private GameEntity enchanting = null;
|
|
||||||
|
|
||||||
private GameEntity mustAttackEntity = null;
|
private GameEntity mustAttackEntity = null;
|
||||||
private GameEntity mustAttackEntityThisTurn = null;
|
private GameEntity mustAttackEntityThisTurn = null;
|
||||||
@@ -176,7 +174,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
|
|
||||||
// for Vanguard / Manapool / Emblems etc.
|
// for Vanguard / Manapool / Emblems etc.
|
||||||
private boolean isImmutable = false;
|
private boolean isImmutable = false;
|
||||||
|
|
||||||
private int exertThisTurn = 0;
|
private int exertThisTurn = 0;
|
||||||
private PlayerCollection exertedByPlayer = new PlayerCollection();
|
private PlayerCollection exertedByPlayer = new PlayerCollection();
|
||||||
|
|
||||||
@@ -413,7 +411,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
if (!changedCardKeywords.isEmpty()) {
|
if (!changedCardKeywords.isEmpty()) {
|
||||||
currentState.getView().updateKeywords(this, currentState);
|
currentState.getView().updateKeywords(this, currentState);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state == CardStateName.FaceDown) {
|
if (state == CardStateName.FaceDown) {
|
||||||
view.updateHiddenId(game.nextHiddenCardId());
|
view.updateHiddenId(game.nextHiddenCardId());
|
||||||
}
|
}
|
||||||
@@ -902,7 +900,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
public final void clearTriggersNew() {
|
public final void clearTriggersNew() {
|
||||||
currentState.clearTriggers();
|
currentState.clearTriggers();
|
||||||
}
|
}
|
||||||
|
|
||||||
public final boolean hasTrigger(final Trigger t) {
|
public final boolean hasTrigger(final Trigger t) {
|
||||||
return currentState.hasTrigger(t);
|
return currentState.hasTrigger(t);
|
||||||
}
|
}
|
||||||
@@ -1064,7 +1062,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
public final boolean hasSecondStrike() {
|
public final boolean hasSecondStrike() {
|
||||||
return hasDoubleStrike() || !hasFirstStrike();
|
return hasDoubleStrike() || !hasFirstStrike();
|
||||||
}
|
}
|
||||||
|
|
||||||
public final boolean hasConverge() {
|
public final boolean hasConverge() {
|
||||||
return "Count$Converge".equals(getSVar("X")) || "Count$Converge".equals(getSVar("Y")) || hasKeyword("Sunburst");
|
return "Count$Converge".equals(getSVar("X")) || "Count$Converge".equals(getSVar("Y")) || hasKeyword("Sunburst");
|
||||||
}
|
}
|
||||||
@@ -1290,7 +1288,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
public final void removeSVar(final String var) {
|
public final void removeSVar(final String var) {
|
||||||
currentState.removeSVar(var);
|
currentState.removeSVar(var);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final int sumAllCounters() {
|
public final int sumAllCounters() {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (final Integer value2 : counters.values()) {
|
for (final Integer value2 : counters.values()) {
|
||||||
@@ -1519,7 +1517,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
sbLong.append(parts[0]).append(" ").append(ManaCostParser.parse(parts[1])).append("\r\n");
|
sbLong.append(parts[0]).append(" ").append(ManaCostParser.parse(parts[1])).append("\r\n");
|
||||||
}
|
}
|
||||||
} else if (keyword.startsWith("Morph") || keyword.startsWith("Megamorph")) {
|
} else if (keyword.startsWith("Morph") || keyword.startsWith("Megamorph")) {
|
||||||
String[] k = keyword.split(":");
|
String[] k = keyword.split(":");
|
||||||
sbLong.append(k[0]);
|
sbLong.append(k[0]);
|
||||||
if (k.length > 1) {
|
if (k.length > 1) {
|
||||||
final Cost mCost = new Cost(k[1], true);
|
final Cost mCost = new Cost(k[1], true);
|
||||||
@@ -1704,7 +1702,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
if (sbLong.length() > 0) {
|
if (sbLong.length() > 0) {
|
||||||
sbLong.append("\r\n");
|
sbLong.append("\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
if (sb.length() > 0) {
|
if (sb.length() > 0) {
|
||||||
@@ -2223,7 +2221,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
public final FCollectionView<SpellAbility> getNonManaAbilities() {
|
public final FCollectionView<SpellAbility> getNonManaAbilities() {
|
||||||
return currentState.getNonManaAbilities();
|
return currentState.getNonManaAbilities();
|
||||||
}
|
}
|
||||||
|
|
||||||
public final boolean hasSpellAbility(final SpellAbility sa) {
|
public final boolean hasSpellAbility(final SpellAbility sa) {
|
||||||
return currentState.hasSpellAbility(sa);
|
return currentState.hasSpellAbility(sa);
|
||||||
}
|
}
|
||||||
@@ -2410,7 +2408,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
public final void addUntapCommand(final GameCommand c) {
|
public final void addUntapCommand(final GameCommand c) {
|
||||||
untapCommandList.add(c);
|
untapCommandList.add(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void addUnattachCommand(final GameCommand c) {
|
public final void addUnattachCommand(final GameCommand c) {
|
||||||
unattachCommandList.add(c);
|
unattachCommandList.add(c);
|
||||||
}
|
}
|
||||||
@@ -2472,7 +2470,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
public void setStartedTheTurnUntapped(boolean untapped) {
|
public void setStartedTheTurnUntapped(boolean untapped) {
|
||||||
startedTheTurnUntapped = untapped;
|
startedTheTurnUntapped = untapped;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean cameUnderControlSinceLastUpkeep() {
|
public boolean cameUnderControlSinceLastUpkeep() {
|
||||||
return cameUnderControlSinceLastUpkeep;
|
return cameUnderControlSinceLastUpkeep;
|
||||||
}
|
}
|
||||||
@@ -2585,186 +2583,126 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public final CardCollectionView getEquippedBy(boolean allowModify) {
|
public final CardCollectionView getEquippedBy() {
|
||||||
return CardCollection.getView(equippedBy, allowModify);
|
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);
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
|
return CardLists.filter(attachedBy, CardPredicates.Presets.EQUIPMENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final CardCollectionView getFortifiedBy(boolean allowModify) {
|
public final boolean isEquipped() {
|
||||||
return CardCollection.getView(fortifiedBy, allowModify);
|
if (this.attachedBy == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CardLists.count(attachedBy, CardPredicates.Presets.EQUIPMENT) > 0;
|
||||||
}
|
}
|
||||||
public final void setFortifiedBy(final CardCollection cards) {
|
public final boolean isEquippedBy(Card c) {
|
||||||
fortifiedBy = view.setCards(fortifiedBy, cards, TrackableProperty.FortifiedBy);
|
return this.isAttachedBy(c);
|
||||||
}
|
}
|
||||||
public final void setFortifiedBy(final Iterable<Card> cards) {
|
public final boolean isEquippedBy(final String cardName) {
|
||||||
fortifiedBy = view.setCards(fortifiedBy, cards, TrackableProperty.FortifiedBy);
|
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() {
|
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) {
|
public final boolean isFortifiedBy(Card c) {
|
||||||
return FCollection.hasElement(fortifiedBy, c);
|
// 301.5e + 301.6
|
||||||
|
return isAttachedBy(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final Card getEquipping() {
|
public final Card getEquipping() {
|
||||||
return equipping;
|
return this.getAttachingCard();
|
||||||
}
|
|
||||||
public final void setEquipping(final Card card) {
|
|
||||||
equipping = view.setCard(equipping, card, TrackableProperty.Equipping);
|
|
||||||
}
|
}
|
||||||
public final boolean isEquipping() {
|
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() {
|
public final boolean isFortifying() {
|
||||||
return fortifying != null;
|
return this.isAttaching();
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void equipCard(final Card c) {
|
public final void equipCard(final Card c) {
|
||||||
if (c.hasKeyword("CARDNAME can't be equipped.")) {
|
if (!isEquipment()) {
|
||||||
getGame().getGameLog().add(GameLogEntryType.STACK_RESOLVE, "Trying to equip " + c.getName() + " but it can't be equipped.");
|
|
||||||
return;
|
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;
|
this.attachEntity(c);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void fortifyCard(final Card c) {
|
public final void fortifyCard(final Card c) {
|
||||||
Card oldTarget = null;
|
if (!isFortification()) {
|
||||||
if (isFortifying()) {
|
return;
|
||||||
oldTarget = fortifying;
|
|
||||||
unFortifyCard(oldTarget);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setFortifying(c);
|
this.attachEntity(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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void unEquipCard(final Card c) { // equipment.unEquipCard(equippedCard);
|
public final void unEquipCard(final Card c) { // equipment.unEquipCard(equippedCard);
|
||||||
if (equipping != null && equipping.getId() == c.getId()) {
|
this.unAttachEntity(c);
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void unEquipAllCards() {
|
public final void unEquipAllCards() {
|
||||||
if (isEquipped()) {
|
if (isEquipped()) {
|
||||||
for (Card c : getEquippedBy(true)) {
|
for (Card c : Lists.newArrayList(getEquippedBy())) {
|
||||||
c.unEquipCard(this);
|
c.unAttachEntity(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public final GameEntity getEnchanting() {
|
public final GameEntity getAttaching() {
|
||||||
return enchanting;
|
return attaching;
|
||||||
}
|
}
|
||||||
public final void setEnchanting(final GameEntity e) {
|
public final void setAttaching(final GameEntity e) {
|
||||||
if (enchanting == e) { return; }
|
if (attaching == e) { return; }
|
||||||
enchanting = e;
|
attaching = e;
|
||||||
view.updateEnchanting(this);
|
view.updateAttaching(this);
|
||||||
}
|
}
|
||||||
public final Card getEnchantingCard() {
|
public final void removeAttaching(final GameEntity e) {
|
||||||
if (enchanting instanceof Card) {
|
if (attaching == e) {
|
||||||
return (Card) enchanting;
|
setAttaching(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public final boolean isAttaching() {
|
||||||
|
return attaching != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final Card getAttachingCard() {
|
||||||
|
if (attaching instanceof Card) {
|
||||||
|
return (Card) attaching;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final GameEntity getEnchanting() {
|
||||||
|
return getAttaching();
|
||||||
|
}
|
||||||
|
|
||||||
|
public final Card getEnchantingCard() {
|
||||||
|
return getAttachingCard();
|
||||||
|
}
|
||||||
public final Player getEnchantingPlayer() {
|
public final Player getEnchantingPlayer() {
|
||||||
if (enchanting instanceof Player) {
|
if (attaching instanceof Player) {
|
||||||
return (Player) enchanting;
|
return (Player) attaching;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
public final boolean isEnchanting() {
|
public final boolean isEnchanting() {
|
||||||
return enchanting != null;
|
return isAttaching();
|
||||||
}
|
}
|
||||||
public final boolean isEnchantingCard() {
|
public final boolean isEnchantingCard() {
|
||||||
return getEnchantingCard() != null;
|
return getEnchantingCard() != null;
|
||||||
@@ -2773,43 +2711,63 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
return getEnchantingPlayer() != null;
|
return getEnchantingPlayer() != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void removeEnchanting(final GameEntity e) {
|
public final void attachEntity(final GameEntity entity) {
|
||||||
if (enchanting == e) {
|
if (!entity.canBeAttachedBy(this)) {
|
||||||
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.");
|
|
||||||
return;
|
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
|
// run trigger
|
||||||
final Map<String, Object> runParams = Maps.newHashMap();
|
final Map<String, Object> runParams = Maps.newHashMap();
|
||||||
runParams.put("AttachSource", this);
|
runParams.put("AttachSource", this);
|
||||||
runParams.put("AttachTarget", entity);
|
runParams.put("AttachTarget", entity);
|
||||||
getController().getGame().getTriggerHandler().runTrigger(TriggerType.Attached, runParams, false);
|
getController().getGame().getTriggerHandler().runTrigger(TriggerType.Attached, runParams, false);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void unEnchantEntity(final GameEntity entity) {
|
public final void enchantEntity(final GameEntity entity) {
|
||||||
if (enchanting == null || !enchanting.equals(entity)) {
|
if (!isAura()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.attachEntity(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void unAttachEntity(final GameEntity entity) {
|
||||||
|
if (attaching == null || !attaching.equals(entity)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
setEnchanting(null);
|
setAttaching(null);
|
||||||
entity.removeEnchantedBy(this);
|
entity.removeAttachedBy(this);
|
||||||
|
|
||||||
|
// Handle Bestowed Aura part
|
||||||
if (isBestowed()) {
|
if (isBestowed()) {
|
||||||
unanimateBestow();
|
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();
|
runUnattachCommands();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2820,11 +2778,11 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
public final void addType(final String type0) {
|
public final void addType(final String type0) {
|
||||||
currentState.addType(type0);
|
currentState.addType(type0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void removeType(final CardType.Supertype st) {
|
public final void removeType(final CardType.Supertype st) {
|
||||||
currentState.removeType(st);
|
currentState.removeType(st);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void setCreatureTypes(Collection<String> ctypes) {
|
public final void setCreatureTypes(Collection<String> ctypes) {
|
||||||
currentState.setCreatureTypes(ctypes);
|
currentState.setCreatureTypes(ctypes);
|
||||||
}
|
}
|
||||||
@@ -2832,7 +2790,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
public final CardTypeView getType() {
|
public final CardTypeView getType() {
|
||||||
return getType(currentState);
|
return getType(currentState);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final CardTypeView getType(CardState state) {
|
public final CardTypeView getType(CardState state) {
|
||||||
if (changedCardTypes.isEmpty()) {
|
if (changedCardTypes.isEmpty()) {
|
||||||
return state.getType();
|
return state.getType();
|
||||||
@@ -2843,7 +2801,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
public Iterable<CardChangedType> getChangedCardTypes() {
|
public Iterable<CardChangedType> getChangedCardTypes() {
|
||||||
return Iterables.unmodifiableIterable(changedCardTypes.values());
|
return Iterables.unmodifiableIterable(changedCardTypes.values());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<Long, CardChangedType> getChangedCardTypesMap() {
|
public Map<Long, CardChangedType> getChangedCardTypesMap() {
|
||||||
return Collections.unmodifiableMap(changedCardTypes);
|
return Collections.unmodifiableMap(changedCardTypes);
|
||||||
}
|
}
|
||||||
@@ -3050,7 +3008,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
public final void addNewPT(final Integer power, final Integer toughness, final long timestamp) {
|
public final void addNewPT(final Integer power, final Integer toughness, final long timestamp) {
|
||||||
addNewPT(power, toughness, timestamp, false);
|
addNewPT(power, toughness, timestamp, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void addNewPT(final Integer power, final Integer toughness, final long timestamp, final boolean cda) {
|
public final void addNewPT(final Integer power, final Integer toughness, final long timestamp, final boolean cda) {
|
||||||
if (cda) {
|
if (cda) {
|
||||||
newPTCharacterDefining.put(timestamp, Pair.of(power, toughness));
|
newPTCharacterDefining.put(timestamp, Pair.of(power, toughness));
|
||||||
@@ -3063,10 +3021,10 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
|
|
||||||
public final void removeNewPT(final long timestamp) {
|
public final void removeNewPT(final long timestamp) {
|
||||||
boolean removed = false;
|
boolean removed = false;
|
||||||
|
|
||||||
removed |= newPT.remove(timestamp) != null;
|
removed |= newPT.remove(timestamp) != null;
|
||||||
removed |= newPTCharacterDefining.remove(timestamp) != null;
|
removed |= newPTCharacterDefining.remove(timestamp) != null;
|
||||||
|
|
||||||
if (removed) {
|
if (removed) {
|
||||||
currentState.getView().updatePower(this);
|
currentState.getView().updatePower(this);
|
||||||
currentState.getView().updateToughness(this);
|
currentState.getView().updateToughness(this);
|
||||||
@@ -3358,7 +3316,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
final boolean removeAllKeywords, final boolean removeIntrinsicKeywords, final long timestamp) {
|
final boolean removeAllKeywords, final boolean removeIntrinsicKeywords, final long timestamp) {
|
||||||
addChangedCardKeywords(keywords, removeKeywords, removeAllKeywords, removeIntrinsicKeywords, timestamp, true);
|
addChangedCardKeywords(keywords, removeKeywords, removeAllKeywords, removeIntrinsicKeywords, timestamp, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public final void addChangedCardKeywords(final List<String> keywords, final List<String> removeKeywords,
|
public final void addChangedCardKeywords(final List<String> keywords, final List<String> removeKeywords,
|
||||||
final boolean removeAllKeywords, final boolean removeIntrinsicKeywords, final long timestamp, final boolean updateView) {
|
final boolean removeAllKeywords, final boolean removeIntrinsicKeywords, final long timestamp, final boolean updateView) {
|
||||||
@@ -3377,12 +3335,12 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
newCks.addKeywordsToCard(this);
|
newCks.addKeywordsToCard(this);
|
||||||
changedCardKeywords.put(timestamp, newCks);
|
changedCardKeywords.put(timestamp, newCks);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (updateView) {
|
if (updateView) {
|
||||||
updateKeywords();
|
updateKeywords();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void addChangedCardKeywordsInternal(
|
public final void addChangedCardKeywordsInternal(
|
||||||
final List<KeywordInterface> keywords, final List<KeywordInterface> removeKeywords,
|
final List<KeywordInterface> keywords, final List<KeywordInterface> removeKeywords,
|
||||||
final boolean removeAllKeywords, final boolean removeIntrinsicKeywords,
|
final boolean removeAllKeywords, final boolean removeIntrinsicKeywords,
|
||||||
@@ -3404,7 +3362,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
newCks.addKeywordsToCard(this);
|
newCks.addKeywordsToCard(this);
|
||||||
changedCardKeywords.put(timestamp, newCks);
|
changedCardKeywords.put(timestamp, newCks);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (updateView) {
|
if (updateView) {
|
||||||
updateKeywords();
|
updateKeywords();
|
||||||
}
|
}
|
||||||
@@ -3432,7 +3390,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
|
|
||||||
public final KeywordsChange removeChangedCardKeywords(final long timestamp, final boolean updateView) {
|
public final KeywordsChange removeChangedCardKeywords(final long timestamp, final boolean updateView) {
|
||||||
KeywordsChange change = changedCardKeywords.remove(timestamp);
|
KeywordsChange change = changedCardKeywords.remove(timestamp);
|
||||||
if (change != null && updateView) {
|
if (change != null && updateView) {
|
||||||
updateKeywords();
|
updateKeywords();
|
||||||
}
|
}
|
||||||
return change;
|
return change;
|
||||||
@@ -3445,10 +3403,10 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
public final Collection<KeywordInterface> getUnhiddenKeywords(CardState state) {
|
public final Collection<KeywordInterface> getUnhiddenKeywords(CardState state) {
|
||||||
return state.getCachedKeywords();
|
return state.getCachedKeywords();
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void updateKeywordsCache(final CardState state) {
|
public final void updateKeywordsCache(final CardState state) {
|
||||||
KeywordCollection keywords = new KeywordCollection();
|
KeywordCollection keywords = new KeywordCollection();
|
||||||
|
|
||||||
//final List<KeywordInterface> keywords = Lists.newArrayList();
|
//final List<KeywordInterface> keywords = Lists.newArrayList();
|
||||||
boolean removeIntrinsic = false;
|
boolean removeIntrinsic = false;
|
||||||
for (final KeywordsChange ck : changedCardKeywords.values()) {
|
for (final KeywordsChange ck : changedCardKeywords.values()) {
|
||||||
@@ -3568,7 +3526,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
String oldtxt = kw.getOriginal();
|
String oldtxt = kw.getOriginal();
|
||||||
final String newtxt = AbilityUtils.applyKeywordTextChangeEffects(oldtxt, this);
|
final String newtxt = AbilityUtils.applyKeywordTextChangeEffects(oldtxt, this);
|
||||||
if (!newtxt.equals(oldtxt)) {
|
if (!newtxt.equals(oldtxt)) {
|
||||||
KeywordInterface newKw = Keyword.getInstance(newtxt);
|
KeywordInterface newKw = Keyword.getInstance(newtxt);
|
||||||
addKeywords.add(newKw);
|
addKeywords.add(newKw);
|
||||||
removeKeywords.add(kw);
|
removeKeywords.add(kw);
|
||||||
keywordsGrantedByTextChanges.add(newKw);
|
keywordsGrantedByTextChanges.add(newKw);
|
||||||
@@ -3733,7 +3691,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
currentState.getView().updateKeywords(this, currentState);
|
currentState.getView().updateKeywords(this, currentState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void addHiddenExtrinsicKeyword(KeywordInterface k) {
|
public final void addHiddenExtrinsicKeyword(KeywordInterface k) {
|
||||||
if (hiddenExtrinsicKeyword.insert(k)) {
|
if (hiddenExtrinsicKeyword.insert(k)) {
|
||||||
view.updateNonAbilityText(this);
|
view.updateNonAbilityText(this);
|
||||||
@@ -3788,7 +3746,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
public final void removeStaticAbility(StaticAbility stAb) {
|
public final void removeStaticAbility(StaticAbility stAb) {
|
||||||
currentState.removeStaticAbility(stAb);
|
currentState.removeStaticAbility(stAb);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateStaticAbilities(List<StaticAbility> list, CardState state) {
|
public void updateStaticAbilities(List<StaticAbility> list, CardState state) {
|
||||||
for (KeywordInterface kw : getUnhiddenKeywords(state)) {
|
for (KeywordInterface kw : getUnhiddenKeywords(state)) {
|
||||||
list.addAll(kw.getStaticAbilities());
|
list.addAll(kw.getStaticAbilities());
|
||||||
@@ -3820,7 +3778,9 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
public final boolean isPlaneswalker() { return getType().isPlaneswalker(); }
|
public final boolean isPlaneswalker() { return getType().isPlaneswalker(); }
|
||||||
public final boolean isEnchantment() { return getType().isEnchantment(); }
|
public final boolean isEnchantment() { return getType().isEnchantment(); }
|
||||||
public final boolean isAura() { return getType().hasSubtype("Aura"); }
|
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 isScheme() { return getType().isScheme(); }
|
||||||
public final boolean isPhenomenon() { return getType().isPhenomenon(); }
|
public final boolean isPhenomenon() { return getType().isPhenomenon(); }
|
||||||
@@ -3886,27 +3846,13 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
setDirectlyPhasedOut(direct);
|
setDirectlyPhasedOut(direct);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isEquipped()) {
|
if (isAttachedBy()) {
|
||||||
for (final Card eq : getEquippedBy(false)) {
|
for (final Card eq : getAttachedBy()) {
|
||||||
if (eq.isPhasedOut() == phasingIn) {
|
if (eq.isPhasedOut() == phasingIn) {
|
||||||
eq.phase(false);
|
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()));
|
getGame().fireEvent(new GameEventCardPhased(this, isPhasedOut()));
|
||||||
}
|
}
|
||||||
@@ -4181,7 +4127,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
//do not check for SplitCard anymore
|
//do not check for SplitCard anymore
|
||||||
return host.getCMC() == n;
|
return host.getCMC() == n;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final boolean sharesCMCWith(final Card c1) {
|
public final boolean sharesCMCWith(final Card c1) {
|
||||||
//need to get GameState for Discarded Cards
|
//need to get GameState for Discarded Cards
|
||||||
final Card host = game.getCardState(this);
|
final Card host = game.getCardState(this);
|
||||||
@@ -4784,7 +4730,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
return (c != null ? c.getImageKey() : "");
|
return (c != null ? c.getImageKey() : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public final boolean isTributed() { return tributed; }
|
public final boolean isTributed() { return tributed; }
|
||||||
|
|
||||||
public final void setTributed(final boolean b) {
|
public final void setTributed(final boolean b) {
|
||||||
@@ -4808,7 +4754,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
public final int getExertedThisTurn() {
|
public final int getExertedThisTurn() {
|
||||||
return exertThisTurn;
|
return exertThisTurn;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void exert() {
|
public void exert() {
|
||||||
exertedByPlayer.add(getController());
|
exertedByPlayer.add(getController());
|
||||||
exertThisTurn++;
|
exertThisTurn++;
|
||||||
@@ -4818,16 +4764,16 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
runParams.put("Player", getController());
|
runParams.put("Player", getController());
|
||||||
game.getTriggerHandler().runTrigger(TriggerType.Exerted, runParams, false);
|
game.getTriggerHandler().runTrigger(TriggerType.Exerted, runParams, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isExertedBy(final Player player) {
|
public boolean isExertedBy(final Player player) {
|
||||||
return exertedByPlayer.contains(player);
|
return exertedByPlayer.contains(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeExertedBy(final Player player) {
|
public void removeExertedBy(final Player player) {
|
||||||
exertedByPlayer.remove(player);
|
exertedByPlayer.remove(player);
|
||||||
view.updateExertedThisTurn(this, getExertedThisTurn() > 0);
|
view.updateExertedThisTurn(this, getExertedThisTurn() > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void resetExtertedThisTurn() {
|
protected void resetExtertedThisTurn() {
|
||||||
exertThisTurn = 0;
|
exertThisTurn = 0;
|
||||||
view.updateExertedThisTurn(this, false);
|
view.updateExertedThisTurn(this, false);
|
||||||
@@ -4917,8 +4863,8 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
|
|
||||||
public final CardCollectionView getDevouredCards() {
|
public final CardCollectionView getDevouredCards() {
|
||||||
return CardCollection.getView(devouredCards);
|
return CardCollection.getView(devouredCards);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final CardCollectionView getHauntedBy() {
|
public final CardCollectionView getHauntedBy() {
|
||||||
return CardCollection.getView(hauntedBy);
|
return CardCollection.getView(hauntedBy);
|
||||||
}
|
}
|
||||||
@@ -4997,7 +4943,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasProtectionFrom(final Card source) {
|
public boolean hasProtectionFrom(final Card source) {
|
||||||
return hasProtectionFrom(source, false, false);
|
return hasProtectionFrom(source, false, false);
|
||||||
}
|
}
|
||||||
@@ -5006,6 +4952,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
return hasProtectionFrom(source, false, true);
|
return hasProtectionFrom(source, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean hasProtectionFrom(final Card source, final boolean checkSBA) {
|
public boolean hasProtectionFrom(final Card source, final boolean checkSBA) {
|
||||||
return hasProtectionFrom(source, checkSBA, false);
|
return hasProtectionFrom(source, checkSBA, false);
|
||||||
}
|
}
|
||||||
@@ -5019,6 +4966,11 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Protection only works on the Battlefield
|
||||||
|
if (isInZone(ZoneType.Battlefield)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
final boolean colorlessDamage = damageSource && source.hasKeyword("Colorless Damage Source");
|
final boolean colorlessDamage = damageSource && source.hasKeyword("Colorless Damage Source");
|
||||||
|
|
||||||
for (final KeywordInterface inst : getKeywords()) {
|
for (final KeywordInterface inst : getKeywords()) {
|
||||||
@@ -5078,11 +5030,11 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
|
|
||||||
// if colorlessDamage then it does only check damage color..
|
// if colorlessDamage then it does only check damage color..
|
||||||
if (colorlessDamage) {
|
if (colorlessDamage) {
|
||||||
if (characteristic.endsWith("White") || characteristic.endsWith("Blue")
|
if (characteristic.endsWith("White") || characteristic.endsWith("Blue")
|
||||||
|| characteristic.endsWith("Black") || characteristic.endsWith("Red")
|
|| characteristic.endsWith("Black") || characteristic.endsWith("Red")
|
||||||
|| characteristic.endsWith("Green") || characteristic.endsWith("Colorless")
|
|| characteristic.endsWith("Green") || characteristic.endsWith("Colorless")
|
||||||
|| characteristic.endsWith("ChosenColor")) {
|
|| characteristic.endsWith("ChosenColor")) {
|
||||||
characteristic += "Source";
|
characteristic += "Source";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5221,14 +5173,50 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
tgt = sa.getTargetRestrictions();
|
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)
|
return !(hasProtectionFrom(aura, checkSBA)
|
||||||
|| (hasKeyword("CARDNAME can't be enchanted in the future.") && !isEnchantedBy(aura))
|
|| (hasKeyword("CARDNAME can't be enchanted in the future.") && !isEnchantedBy(aura))
|
||||||
|| (hasKeyword("CARDNAME can't be enchanted.") && !aura.getName().equals("Anti-Magic Aura")
|
|| (hasKeyword("CARDNAME can't be enchanted.") && !aura.getName().equals("Anti-Magic Aura")
|
||||||
&& !(aura.getName().equals("Consecrate Land") && aura.isInZone(ZoneType.Battlefield)))
|
&& !(aura.getName().equals("Consecrate Land") && aura.isInZone(ZoneType.Battlefield))));
|
||||||
|| ((tgt != null) && !isValid(tgt.getValidTgts(), aura.getController(), aura, sa)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public final boolean canBeEquippedBy(final Card equip) {
|
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()) {
|
for(KeywordInterface inst : equip.getKeywords()) {
|
||||||
String kw = inst.getOriginal();
|
String kw = inst.getOriginal();
|
||||||
if(!kw.startsWith("CantEquip")) {
|
if(!kw.startsWith("CantEquip")) {
|
||||||
@@ -5241,8 +5229,19 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return !(hasProtectionFrom(equip)
|
return !(hasProtectionFrom(equip)
|
||||||
|| hasKeyword("CARDNAME can't be equipped.")
|
|| hasKeyword("CARDNAME can't be equipped."));
|
||||||
|| !isValid("Creature", equip.getController(), equip, null));
|
}
|
||||||
|
|
||||||
|
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() {
|
public FCollectionView<ReplacementEffect> getReplacementEffects() {
|
||||||
@@ -5265,7 +5264,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
public void removeReplacementEffect(ReplacementEffect replacementEffect) {
|
public void removeReplacementEffect(ReplacementEffect replacementEffect) {
|
||||||
currentState.removeReplacementEffect(replacementEffect);
|
currentState.removeReplacementEffect(replacementEffect);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateReplacementEffects(List<ReplacementEffect> list, CardState state) {
|
public void updateReplacementEffects(List<ReplacementEffect> list, CardState state) {
|
||||||
for (KeywordInterface kw : getUnhiddenKeywords(state)) {
|
for (KeywordInterface kw : getUnhiddenKeywords(state)) {
|
||||||
list.addAll(kw.getReplacements());
|
list.addAll(kw.getReplacements());
|
||||||
@@ -5449,7 +5448,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
public final void setLKICMC(final int cmc) {
|
public final void setLKICMC(final int cmc) {
|
||||||
this.lkiCMC = cmc;
|
this.lkiCMC = cmc;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final boolean isLKI() {
|
public final boolean isLKI() {
|
||||||
return this.lkiCMC >= 0;
|
return this.lkiCMC >= 0;
|
||||||
}
|
}
|
||||||
@@ -5758,7 +5757,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
public final void addGoad(Long timestamp, final Player p) {
|
public final void addGoad(Long timestamp, final Player p) {
|
||||||
goad.put(timestamp, p);
|
goad.put(timestamp, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void removeGoad(Long timestamp) {
|
public final void removeGoad(Long timestamp) {
|
||||||
goad.remove(timestamp);
|
goad.remove(timestamp);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -92,12 +92,8 @@ public class CardFactory {
|
|||||||
out.setState(in.getCurrentStateName(), true);
|
out.setState(in.getCurrentStateName(), true);
|
||||||
|
|
||||||
// this's necessary for forge.game.GameAction.unattachCardLeavingBattlefield(Card)
|
// this's necessary for forge.game.GameAction.unattachCardLeavingBattlefield(Card)
|
||||||
out.setEquipping(in.getEquipping());
|
out.setAttachedBy(in.getAttachedBy());
|
||||||
out.setEquippedBy(in.getEquippedBy(false));
|
out.setAttaching(in.getAttaching());
|
||||||
out.setFortifying(in.getFortifying());
|
|
||||||
out.setFortifiedBy(in.getFortifiedBy(false));
|
|
||||||
out.setEnchantedBy(in.getEnchantedBy(false));
|
|
||||||
out.setEnchanting(in.getEnchanting());
|
|
||||||
|
|
||||||
out.setClones(in.getClones());
|
out.setClones(in.getClones());
|
||||||
out.setCastSA(in.getCastSA());
|
out.setCastSA(in.getCastSA());
|
||||||
|
|||||||
@@ -470,6 +470,15 @@ public final class CardPredicates {
|
|||||||
return c.isEnchantment();
|
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.
|
* a Predicate<Card> to get all equipment.
|
||||||
*/
|
*/
|
||||||
@@ -482,7 +491,7 @@ public final class CardPredicates {
|
|||||||
/**
|
/**
|
||||||
* a Predicate<Card> to get all fortification.
|
* 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
|
@Override
|
||||||
public boolean apply(Card c) {
|
public boolean apply(Card c) {
|
||||||
return c.isFortification();
|
return c.isFortification();
|
||||||
|
|||||||
@@ -405,7 +405,7 @@ public class CardProperty {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (property.equals("Attached")) {
|
} 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;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (property.startsWith("AttachedTo")) {
|
} else if (property.startsWith("AttachedTo")) {
|
||||||
@@ -433,9 +433,8 @@ public class CardProperty {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if ((card.getEnchanting() == null || !card.getEnchanting().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))
|
&& (card.getEquipping() == null || !card.getEquipping().isValid(restriction, sourceController, source, spellAbility))) {
|
||||||
&& (card.getFortifying() == null || !card.getFortifying().isValid(restriction, sourceController, source, spellAbility))) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -445,7 +444,7 @@ public class CardProperty {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (property.equals("NotAttachedTo")) {
|
} 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;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (property.startsWith("EnchantedBy")) {
|
} else if (property.startsWith("EnchantedBy")) {
|
||||||
@@ -476,7 +475,7 @@ public class CardProperty {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default: // EnchantedBy Aura.Other
|
default: // EnchantedBy Aura.Other
|
||||||
for (final Card aura : card.getEnchantedBy(false)) {
|
for (final Card aura : card.getEnchantedBy()) {
|
||||||
if (aura.isValid(restriction, sourceController, source, spellAbility)) {
|
if (aura.isValid(restriction, sourceController, source, spellAbility)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -572,11 +571,12 @@ public class CardProperty {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (property.startsWith("Equipped")) {
|
} else if (property.startsWith("Equipped")) {
|
||||||
if (card.getEquipping() != source) {
|
if (!source.isAttachedBy(card)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (property.startsWith("Fortified")) {
|
} else if (property.startsWith("Fortified")) {
|
||||||
if (card.getFortifying() != source) {
|
// FIXME TODO what property has this?
|
||||||
|
if (!source.isAttachedBy(card)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (property.startsWith("HauntedBy")) {
|
} else if (property.startsWith("HauntedBy")) {
|
||||||
|
|||||||
@@ -6,12 +6,12 @@
|
|||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
@@ -93,8 +93,8 @@ public final class CardUtil {
|
|||||||
if (kw.startsWith("HIDDEN")) {
|
if (kw.startsWith("HIDDEN")) {
|
||||||
kw = kw.substring(7);
|
kw = kw.substring(7);
|
||||||
}
|
}
|
||||||
|
|
||||||
return !kw.startsWith("Protection") && !kw.startsWith("CantBeBlockedBy")
|
return !kw.startsWith("Protection") && !kw.startsWith("CantBeBlockedBy")
|
||||||
&& !NON_STACKING_LIST.contains(kw);
|
&& !NON_STACKING_LIST.contains(kw);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,7 +108,7 @@ public final class CardUtil {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* getThisTurnEntered.
|
* getThisTurnEntered.
|
||||||
*
|
*
|
||||||
* @param to zone going to
|
* @param to zone going to
|
||||||
* @param from zone coming from
|
* @param from zone coming from
|
||||||
* @param valid a isValid expression
|
* @param valid a isValid expression
|
||||||
@@ -121,7 +121,7 @@ public final class CardUtil {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* getThisTurnEntered.
|
* getThisTurnEntered.
|
||||||
*
|
*
|
||||||
* @param to zone going to
|
* @param to zone going to
|
||||||
* @param from zone coming from
|
* @param from zone coming from
|
||||||
* @param valid a isValid expression
|
* @param valid a isValid expression
|
||||||
@@ -146,7 +146,7 @@ public final class CardUtil {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* getLastTurnEntered.
|
* getLastTurnEntered.
|
||||||
*
|
*
|
||||||
* @param to zone going to
|
* @param to zone going to
|
||||||
* @param from zone coming from
|
* @param from zone coming from
|
||||||
* @param valid a isValid expression
|
* @param valid a isValid expression
|
||||||
@@ -159,7 +159,7 @@ public final class CardUtil {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* getLastTurnEntered.
|
* getLastTurnEntered.
|
||||||
*
|
*
|
||||||
* @param to zone going to
|
* @param to zone going to
|
||||||
* @param from zone coming from
|
* @param from zone coming from
|
||||||
* @param valid a isValid expression
|
* @param valid a isValid expression
|
||||||
@@ -222,7 +222,7 @@ public final class CardUtil {
|
|||||||
|
|
||||||
// needed to ensure that the LKI object has correct CMC info no matter what state the original card was in
|
// needed to ensure that the LKI object has correct CMC info no matter what state the original card was in
|
||||||
// (e.g. Scrap Trawler + transformed Harvest Hand)
|
// (e.g. Scrap Trawler + transformed Harvest Hand)
|
||||||
newCopy.setLKICMC(in.getCMC());
|
newCopy.setLKICMC(in.getCMC());
|
||||||
// used for the purpose of cards that care about the zone the card was known to be in last
|
// used for the purpose of cards that care about the zone the card was known to be in last
|
||||||
newCopy.setLastKnownZone(in.getLastKnownZone());
|
newCopy.setLastKnownZone(in.getLastKnownZone());
|
||||||
|
|
||||||
@@ -264,12 +264,10 @@ public final class CardUtil {
|
|||||||
newCopy.setReceivedDamageFromThisTurn(in.getReceivedDamageFromThisTurn());
|
newCopy.setReceivedDamageFromThisTurn(in.getReceivedDamageFromThisTurn());
|
||||||
newCopy.setReceivedDamageFromPlayerThisTurn(in.getReceivedDamageFromPlayerThisTurn());
|
newCopy.setReceivedDamageFromPlayerThisTurn(in.getReceivedDamageFromPlayerThisTurn());
|
||||||
newCopy.getDamageHistory().setCreatureGotBlockedThisTurn(in.getDamageHistory().getCreatureGotBlockedThisTurn());
|
newCopy.getDamageHistory().setCreatureGotBlockedThisTurn(in.getDamageHistory().getCreatureGotBlockedThisTurn());
|
||||||
newCopy.setEnchanting(in.getEnchanting());
|
|
||||||
newCopy.setEnchantedBy(in.getEnchantedBy(false));
|
newCopy.setAttachedBy(in.getAttachedBy());
|
||||||
newCopy.setEquipping(in.getEquipping());
|
newCopy.setAttaching(in.getAttaching());
|
||||||
newCopy.setEquippedBy(in.getEquippedBy(false));
|
|
||||||
newCopy.setFortifying(in.getFortifying());
|
|
||||||
newCopy.setFortifiedBy(in.getFortifiedBy(false));
|
|
||||||
newCopy.setClones(in.getClones());
|
newCopy.setClones(in.getClones());
|
||||||
newCopy.setHaunting(in.getHaunting());
|
newCopy.setHaunting(in.getHaunting());
|
||||||
newCopy.setCopiedPermanent(in.getCopiedPermanent());
|
newCopy.setCopiedPermanent(in.getCopiedPermanent());
|
||||||
@@ -313,9 +311,9 @@ public final class CardUtil {
|
|||||||
final Game game = source.getGame();
|
final Game game = source.getGame();
|
||||||
ColorSet cs = CardUtil.getColors(origin);
|
ColorSet cs = CardUtil.getColors(origin);
|
||||||
for (byte color : MagicColor.WUBRG) {
|
for (byte color : MagicColor.WUBRG) {
|
||||||
if(!cs.hasAnyColor(color))
|
if(!cs.hasAnyColor(color))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for(final Card c : game.getColoredCardsInPlay(MagicColor.toLongString(color))) {
|
for(final Card c : game.getColoredCardsInPlay(MagicColor.toLongString(color))) {
|
||||||
if (!res.contains(c) && c.isValid(valid, source.getController(), source, null) && !c.equals(origin)) {
|
if (!res.contains(c) && c.isValid(valid, source.getController(), source, null) && !c.equals(origin)) {
|
||||||
res.add(c);
|
res.add(c);
|
||||||
@@ -344,7 +342,7 @@ public final class CardUtil {
|
|||||||
public static Set<String> getReflectableManaColors(final SpellAbility sa) {
|
public static Set<String> getReflectableManaColors(final SpellAbility sa) {
|
||||||
return getReflectableManaColors(sa, sa, Sets.<String>newHashSet(), new CardCollection());
|
return getReflectableManaColors(sa, sa, Sets.<String>newHashSet(), new CardCollection());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Set<String> getReflectableManaColors(final SpellAbility abMana, final SpellAbility sa,
|
private static Set<String> getReflectableManaColors(final SpellAbility abMana, final SpellAbility sa,
|
||||||
Set<String> colors, final CardCollection parents) {
|
Set<String> colors, final CardCollection parents) {
|
||||||
// Here's the problem with reflectable Mana. If more than one is out,
|
// Here's the problem with reflectable Mana. If more than one is out,
|
||||||
@@ -352,7 +350,7 @@ public final class CardUtil {
|
|||||||
// so we basically need to have a recursive list that send the parents
|
// so we basically need to have a recursive list that send the parents
|
||||||
// so we don't infinite recurse.
|
// so we don't infinite recurse.
|
||||||
final Card card = abMana.getHostCard();
|
final Card card = abMana.getHostCard();
|
||||||
|
|
||||||
if (abMana.getApi() != ApiType.ManaReflected) {
|
if (abMana.getApi() != ApiType.ManaReflected) {
|
||||||
return colors;
|
return colors;
|
||||||
}
|
}
|
||||||
@@ -361,7 +359,7 @@ public final class CardUtil {
|
|||||||
parents.add(card);
|
parents.add(card);
|
||||||
}
|
}
|
||||||
|
|
||||||
final String colorOrType = sa.getParam("ColorOrType");
|
final String colorOrType = sa.getParam("ColorOrType");
|
||||||
// currently Color or Type, Type is colors + colorless
|
// currently Color or Type, Type is colors + colorless
|
||||||
final String validCard = sa.getParam("Valid");
|
final String validCard = sa.getParam("Valid");
|
||||||
final String reflectProperty = sa.getParam("ReflectProperty");
|
final String reflectProperty = sa.getParam("ReflectProperty");
|
||||||
@@ -459,7 +457,7 @@ public final class CardUtil {
|
|||||||
}
|
}
|
||||||
return colors;
|
return colors;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Set<String> canProduce(final int maxChoices, final AbilityManaPart ab,
|
public static Set<String> canProduce(final int maxChoices, final AbilityManaPart ab,
|
||||||
final Set<String> colors) {
|
final Set<String> colors) {
|
||||||
if (ab == null) {
|
if (ab == null) {
|
||||||
@@ -512,7 +510,7 @@ public final class CardUtil {
|
|||||||
if (ability.hasParam("MaxTotalTargetCMC")) {
|
if (ability.hasParam("MaxTotalTargetCMC")) {
|
||||||
int totalCMCTargeted = 0;
|
int totalCMCTargeted = 0;
|
||||||
for (final Card c : targeted) {
|
for (final Card c : targeted) {
|
||||||
totalCMCTargeted += c.getCMC();
|
totalCMCTargeted += c.getCMC();
|
||||||
}
|
}
|
||||||
|
|
||||||
final List<Card> choicesCopy = Lists.newArrayList(choices);
|
final List<Card> choicesCopy = Lists.newArrayList(choices);
|
||||||
|
|||||||
@@ -438,56 +438,32 @@ public class CardView extends GameEntityView {
|
|||||||
return false;
|
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() {
|
public FCollectionView<CardView> getEncodedCards() {
|
||||||
return get(TrackableProperty.EncodedCards);
|
return get(TrackableProperty.EncodedCards);
|
||||||
}
|
}
|
||||||
|
|
||||||
public GameEntityView getEnchanting() {
|
public GameEntityView getAttaching() {
|
||||||
return get(TrackableProperty.Enchanting);
|
return get(TrackableProperty.Attaching);
|
||||||
}
|
}
|
||||||
void updateEnchanting(Card c) {
|
void updateAttaching(Card c) {
|
||||||
set(TrackableProperty.Enchanting, GameEntityView.get(c.getEnchanting()));
|
set(TrackableProperty.Attaching, GameEntityView.get(c.getAttaching()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public CardView getEnchantingCard() {
|
public CardView getAttachingCard() {
|
||||||
GameEntityView enchanting = getEnchanting();
|
GameEntityView enchanting = getAttaching();
|
||||||
if (enchanting instanceof CardView) {
|
if (enchanting instanceof CardView) {
|
||||||
return (CardView) enchanting;
|
return (CardView) enchanting;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
public PlayerView getEnchantingPlayer() {
|
public PlayerView getAttachingPlayer() {
|
||||||
GameEntityView enchanting = getEnchanting();
|
GameEntityView enchanting = getAttaching();
|
||||||
if (enchanting instanceof PlayerView) {
|
if (enchanting instanceof PlayerView) {
|
||||||
return (PlayerView) enchanting;
|
return (PlayerView) enchanting;
|
||||||
}
|
}
|
||||||
return null;
|
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() {
|
public FCollectionView<CardView> getGainControlTargets() {
|
||||||
return get(TrackableProperty.GainControlTargets);
|
return get(TrackableProperty.GainControlTargets);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -424,15 +424,12 @@ public class Combat {
|
|||||||
|
|
||||||
public Player getDefendingPlayerRelatedTo(final Card source) {
|
public Player getDefendingPlayerRelatedTo(final Card source) {
|
||||||
Card attacker = source;
|
Card attacker = source;
|
||||||
if (source.isAura()) {
|
if (source.isAura() || source.isFortification()) {
|
||||||
attacker = source.getEnchantingCard();
|
attacker = source.getEnchantingCard();
|
||||||
}
|
}
|
||||||
else if (source.isEquipment()) {
|
else if (source.isEquipment()) {
|
||||||
attacker = source.getEquipping();
|
attacker = source.getEquipping();
|
||||||
}
|
}
|
||||||
else if (source.isFortification()) {
|
|
||||||
attacker = source.getFortifying();
|
|
||||||
}
|
|
||||||
|
|
||||||
// return the corresponding defender
|
// return the corresponding defender
|
||||||
return getDefenderPlayerByAttacker(attacker);
|
return getDefenderPlayerByAttacker(attacker);
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ public class CostUnattach extends CostPartWithList {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (CardLists.getValidCards(source.getEquippedBy(false), type, payer, source).size() > 0) {
|
if (CardLists.getValidCards(source.getEquippedBy(), type, payer, source).size() > 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -102,7 +102,7 @@ public class CostUnattach extends CostPartWithList {
|
|||||||
return originalEquipment;
|
return originalEquipment;
|
||||||
}
|
}
|
||||||
} else {
|
} 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) {
|
if (attachees.size() > 0) {
|
||||||
// Just pick the first one, although maybe give a dialog
|
// Just pick the first one, although maybe give a dialog
|
||||||
return attachees.get(0);
|
return attachees.get(0);
|
||||||
@@ -116,7 +116,7 @@ public class CostUnattach extends CostPartWithList {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected Card doPayment(SpellAbility ability, Card targetCard) {
|
protected Card doPayment(SpellAbility ability, Card targetCard) {
|
||||||
targetCard.unEquipCard(targetCard.getEquipping());
|
targetCard.unAttachEntity(targetCard.getAttaching());
|
||||||
return targetCard;
|
return targetCard;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,23 +4,15 @@ import forge.game.GameEntity;
|
|||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
|
|
||||||
public class GameEventCardAttachment extends GameEvent {
|
public class GameEventCardAttachment extends GameEvent {
|
||||||
public enum AttachMethod {
|
|
||||||
Equip,
|
|
||||||
Fortify,
|
|
||||||
Enchant;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public final Card equipment;
|
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 newTarget; // can enchant player, I'm ssaving a class to enchants - it could be incorrect.
|
||||||
public final GameEntity oldEntiy;
|
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.equipment = attachment;
|
||||||
this.newTarget = newEntity;
|
this.newTarget = newEntity;
|
||||||
this.oldEntiy = formerEntity;
|
this.oldEntiy = formerEntity;
|
||||||
this.method = method;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -272,20 +272,15 @@ public class Untap extends Phase {
|
|||||||
} else if (c.hasKeyword(Keyword.PHASING)) {
|
} else if (c.hasKeyword(Keyword.PHASING)) {
|
||||||
// 702.23g If an object would simultaneously phase out directly
|
// 702.23g If an object would simultaneously phase out directly
|
||||||
// and indirectly, it just phases out indirectly.
|
// and indirectly, it just phases out indirectly.
|
||||||
if (c.isAura()) {
|
if (c.isAura() || c.isFortification()) {
|
||||||
final GameEntity ent = c.getEnchanting();
|
final Card ent = c.getAttachingCard();
|
||||||
|
if (ent != null && list.contains(ent)) {
|
||||||
if ((ent instanceof Card) && list.contains(ent)) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else if (c.isEquipment() && c.isEquipping()) {
|
} else if (c.isEquipment() && c.isEquipping()) {
|
||||||
if (list.contains(c.getEquipping())) {
|
if (list.contains(c.getEquipping())) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else if (c.isFortification() && c.isFortifying()) {
|
|
||||||
if (list.contains(c.getFortifying())) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
c.phase();
|
c.phase();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,12 +6,12 @@
|
|||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
@@ -67,7 +67,7 @@ import java.util.concurrent.ConcurrentSkipListMap;
|
|||||||
* <p>
|
* <p>
|
||||||
* Abstract Player class.
|
* Abstract Player class.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @author Forge
|
* @author Forge
|
||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
@@ -109,7 +109,7 @@ public class Player extends GameEntity implements Comparable<Player> {
|
|||||||
private CardCollection sacrificedThisTurn = new CardCollection();
|
private CardCollection sacrificedThisTurn = new CardCollection();
|
||||||
|
|
||||||
private Map<CounterType, Integer> countersAddedtoPermThisTurn = Maps.newEnumMap(CounterType.class);
|
private Map<CounterType, Integer> countersAddedtoPermThisTurn = Maps.newEnumMap(CounterType.class);
|
||||||
|
|
||||||
/** A list of tokens not in play, but on their way.
|
/** A list of tokens not in play, but on their way.
|
||||||
* This list is kept in order to not break ETB-replacement
|
* This list is kept in order to not break ETB-replacement
|
||||||
* on tokens. */
|
* on tokens. */
|
||||||
@@ -293,7 +293,7 @@ public class Player extends GameEntity implements Comparable<Player> {
|
|||||||
public final int getOpponentsGreatestLifeTotal() {
|
public final int getOpponentsGreatestLifeTotal() {
|
||||||
return Aggregates.max(getOpponents(), Accessors.FN_GET_LIFE_TOTAL);
|
return Aggregates.max(getOpponents(), Accessors.FN_GET_LIFE_TOTAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the total number of poison counters amongst this player's opponents.
|
* Get the total number of poison counters amongst this player's opponents.
|
||||||
*/
|
*/
|
||||||
@@ -382,7 +382,7 @@ public class Player extends GameEntity implements Comparable<Player> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final boolean gainLife(int lifeGain, final Card source, final SpellAbility sa) {
|
public final boolean gainLife(int lifeGain, final Card source, final SpellAbility sa) {
|
||||||
|
|
||||||
// Run any applicable replacement effects.
|
// Run any applicable replacement effects.
|
||||||
final Map<String, Object> repParams = Maps.newHashMap();
|
final Map<String, Object> repParams = Maps.newHashMap();
|
||||||
repParams.put("Event", "GainLife");
|
repParams.put("Event", "GainLife");
|
||||||
@@ -410,7 +410,7 @@ public class Player extends GameEntity implements Comparable<Player> {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -509,10 +509,10 @@ public class Player extends GameEntity implements Comparable<Player> {
|
|||||||
if (!canPayLife(lifePayment)) {
|
if (!canPayLife(lifePayment)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lifePayment <= 0)
|
if (lifePayment <= 0)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// rule 118.8
|
// rule 118.8
|
||||||
if (life >= lifePayment) {
|
if (life >= lifePayment) {
|
||||||
return (loseLife(lifePayment) > 0);
|
return (loseLife(lifePayment) > 0);
|
||||||
@@ -624,7 +624,7 @@ public class Player extends GameEntity implements Comparable<Player> {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasProtectionFrom(source, true)) {
|
if (hasProtectionFromDamage(source)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -826,7 +826,7 @@ public class Player extends GameEntity implements Comparable<Player> {
|
|||||||
}
|
}
|
||||||
return num;
|
return num;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final int getAssignedCombatDamage() {
|
public final int getAssignedCombatDamage() {
|
||||||
int num = 0;
|
int num = 0;
|
||||||
for (final Integer value : assignedCombatDamage.values()) {
|
for (final Integer value : assignedCombatDamage.values()) {
|
||||||
@@ -852,14 +852,14 @@ public class Player extends GameEntity implements Comparable<Player> {
|
|||||||
}
|
}
|
||||||
return num;
|
return num;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the total damage assigned to this player's opponents this turn.
|
* Get the total damage assigned to this player's opponents this turn.
|
||||||
*/
|
*/
|
||||||
public final int getOpponentsAssignedDamage() {
|
public final int getOpponentsAssignedDamage() {
|
||||||
return Aggregates.sum(getOpponents(), Accessors.FN_GET_ASSIGNED_DAMAGE);
|
return Aggregates.sum(getOpponents(), Accessors.FN_GET_ASSIGNED_DAMAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the greatest amount of damage assigned to a single opponent this turn.
|
* Get the greatest amount of damage assigned to a single opponent this turn.
|
||||||
*/
|
*/
|
||||||
@@ -1011,8 +1011,7 @@ public class Player extends GameEntity implements Comparable<Player> {
|
|||||||
// if the key already exists - merge entries
|
// if the key already exists - merge entries
|
||||||
if (changedKeywords.containsKey(timestamp)) {
|
if (changedKeywords.containsKey(timestamp)) {
|
||||||
final KeywordsChange cks = changedKeywords.get(timestamp);
|
final KeywordsChange cks = changedKeywords.get(timestamp);
|
||||||
|
|
||||||
;
|
|
||||||
changedKeywords.put(timestamp, cks.merge(addKeywords, removeKeywords,
|
changedKeywords.put(timestamp, cks.merge(addKeywords, removeKeywords,
|
||||||
cks.isRemoveAllKeywords(), cks.isRemoveIntrinsicKeywords()));
|
cks.isRemoveAllKeywords(), cks.isRemoveIntrinsicKeywords()));
|
||||||
updateKeywords();
|
updateKeywords();
|
||||||
@@ -1061,14 +1060,14 @@ public class Player extends GameEntity implements Comparable<Player> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove all keyword changes which grant this {@link Player} the specified
|
* Remove all keyword changes which grant this {@link Player} the specified
|
||||||
* keyword.
|
* keyword.
|
||||||
* @param keyword the keyword to remove.
|
* @param keyword the keyword to remove.
|
||||||
*/
|
*/
|
||||||
public final void removeKeyword(final String keyword) {
|
public final void removeKeyword(final String keyword) {
|
||||||
removeKeyword(keyword, true);
|
removeKeyword(keyword, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public final void removeKeyword(final String keyword, final boolean allInstances) {
|
public final void removeKeyword(final String keyword, final boolean allInstances) {
|
||||||
boolean keywordRemoved = false;
|
boolean keywordRemoved = false;
|
||||||
|
|
||||||
@@ -1134,7 +1133,7 @@ public class Player extends GameEntity implements Comparable<Player> {
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final StaticAbility addStaticAbility(final Card host, final String s) {
|
public final StaticAbility addStaticAbility(final Card host, final String s) {
|
||||||
PlayerZone com = getZone(ZoneType.Command);
|
PlayerZone com = getZone(ZoneType.Command);
|
||||||
|
|
||||||
@@ -1195,12 +1194,17 @@ public class Player extends GameEntity implements Comparable<Player> {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasProtectionFrom(final Card source) {
|
public boolean hasProtectionFromDamage(final Card source) {
|
||||||
return hasProtectionFrom(source, false);
|
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) {
|
for (String kw : keywords) {
|
||||||
if (kw.startsWith("Protection")) {
|
if (kw.startsWith("Protection")) {
|
||||||
if (kw.startsWith("Protection:")) { // uses isValid
|
if (kw.startsWith("Protection:")) { // uses isValid
|
||||||
@@ -1418,7 +1422,7 @@ public class Player extends GameEntity implements Comparable<Player> {
|
|||||||
|
|
||||||
if (topCardRevealed) {
|
if (topCardRevealed) {
|
||||||
revealed.add(c);
|
revealed.add(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (numDrawnThisTurn == 0) {
|
if (numDrawnThisTurn == 0) {
|
||||||
boolean reveal = false;
|
boolean reveal = false;
|
||||||
@@ -1436,7 +1440,7 @@ public class Player extends GameEntity implements Comparable<Player> {
|
|||||||
revealed.remove(c);
|
revealed.remove(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setLastDrawnCard(c);
|
setLastDrawnCard(c);
|
||||||
c.setDrawnThisTurn(true);
|
c.setDrawnThisTurn(true);
|
||||||
@@ -1654,7 +1658,7 @@ public class Player extends GameEntity implements Comparable<Player> {
|
|||||||
public final CardCollectionView mill(final int n) {
|
public final CardCollectionView mill(final int n) {
|
||||||
return mill(n, ZoneType.Graveyard, false);
|
return mill(n, ZoneType.Graveyard, false);
|
||||||
}
|
}
|
||||||
public final CardCollectionView mill(final int n, final ZoneType zone,
|
public final CardCollectionView mill(final int n, final ZoneType zone,
|
||||||
final boolean bottom) {
|
final boolean bottom) {
|
||||||
final CardCollectionView lib = getCardsIn(ZoneType.Library);
|
final CardCollectionView lib = getCardsIn(ZoneType.Library);
|
||||||
final CardCollection milled = new CardCollection();
|
final CardCollection milled = new CardCollection();
|
||||||
@@ -2204,7 +2208,7 @@ public class Player extends GameEntity implements Comparable<Player> {
|
|||||||
public final void resetSacrificedThisTurn() {
|
public final void resetSacrificedThisTurn() {
|
||||||
sacrificedThisTurn.clear();
|
sacrificedThisTurn.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void addCounterToPermThisTurn(final CounterType type, final int x) {
|
public final void addCounterToPermThisTurn(final CounterType type, final int x) {
|
||||||
countersAddedtoPermThisTurn.put(type, getCounterToPermThisTurn(type) + x);
|
countersAddedtoPermThisTurn.put(type, getCounterToPermThisTurn(type) + x);
|
||||||
}
|
}
|
||||||
@@ -2270,7 +2274,7 @@ public class Player extends GameEntity implements Comparable<Player> {
|
|||||||
/**
|
/**
|
||||||
* get the Player object or Card (Planeswalker) object that this Player must
|
* get the Player object or Card (Planeswalker) object that this Player must
|
||||||
* attack this combat.
|
* attack this combat.
|
||||||
*
|
*
|
||||||
* @return the Player or Card (Planeswalker)
|
* @return the Player or Card (Planeswalker)
|
||||||
* @since 1.1.01
|
* @since 1.1.01
|
||||||
*/
|
*/
|
||||||
@@ -2625,7 +2629,7 @@ public class Player extends GameEntity implements Comparable<Player> {
|
|||||||
public CardCollectionView getInboundTokens() {
|
public CardCollectionView getInboundTokens() {
|
||||||
return inboundTokens;
|
return inboundTokens;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addInboundToken(Card c) {
|
public void addInboundToken(Card c) {
|
||||||
inboundTokens.add(c);
|
inboundTokens.add(c);
|
||||||
}
|
}
|
||||||
@@ -2710,7 +2714,7 @@ public class Player extends GameEntity implements Comparable<Player> {
|
|||||||
com.add(Card.fromPaperCard(avatar, this));
|
com.add(Card.fromPaperCard(avatar, this));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Schemes
|
// Schemes
|
||||||
CardCollection sd = new CardCollection();
|
CardCollection sd = new CardCollection();
|
||||||
for (IPaperCard cp : registeredPlayer.getSchemes()) {
|
for (IPaperCard cp : registeredPlayer.getSchemes()) {
|
||||||
@@ -2773,7 +2777,7 @@ public class Player extends GameEntity implements Comparable<Player> {
|
|||||||
|
|
||||||
eff.setSVar("CommanderMoveReplacement", "DB$ ChangeZone | Origin$ Battlefield,Graveyard,Exile,Library,Hand | Destination$ Command | Defined$ ReplacedCard");
|
eff.setSVar("CommanderMoveReplacement", "DB$ ChangeZone | Origin$ Battlefield,Graveyard,Exile,Library,Hand | Destination$ Command | Defined$ ReplacedCard");
|
||||||
|
|
||||||
String moved = "Event$ Moved | ValidCard$ Card.EffectSource+YouOwn | Secondary$ True | Optional$ True | OptionalDecider$ You | ReplaceWith$ CommanderMoveReplacement ";
|
String moved = "Event$ Moved | ValidCard$ Card.EffectSource+YouOwn | Secondary$ True | Optional$ True | OptionalDecider$ You | ReplaceWith$ CommanderMoveReplacement ";
|
||||||
if (game.getRules().hasAppliedVariant(GameType.TinyLeaders)) {
|
if (game.getRules().hasAppliedVariant(GameType.TinyLeaders)) {
|
||||||
moved += " | Destination$ Graveyard,Exile | Description$ If a commander would be put into its owner's graveyard or exile from anywhere, that player may put it into the command zone instead.";
|
moved += " | Destination$ Graveyard,Exile | Description$ If a commander would be put into its owner's graveyard or exile from anywhere, that player may put it into the command zone instead.";
|
||||||
} else {
|
} else {
|
||||||
@@ -2837,7 +2841,7 @@ public class Player extends GameEntity implements Comparable<Player> {
|
|||||||
monarchEffect.addType("Effect");
|
monarchEffect.addType("Effect");
|
||||||
|
|
||||||
{
|
{
|
||||||
final String drawTrig = "Mode$ Phase | Phase$ End of Turn | TriggerZones$ Command | " +
|
final String drawTrig = "Mode$ Phase | Phase$ End of Turn | TriggerZones$ Command | " +
|
||||||
"ValidPlayer$ You | TriggerDescription$ At the beginning of your end step, draw a card.";
|
"ValidPlayer$ You | TriggerDescription$ At the beginning of your end step, draw a card.";
|
||||||
final String drawEff = "AB$Draw | Cost$ 0 | Defined$ You | NumCards$ 1";
|
final String drawEff = "AB$Draw | Cost$ 0 | Defined$ You | NumCards$ 1";
|
||||||
|
|
||||||
@@ -2870,11 +2874,11 @@ public class Player extends GameEntity implements Comparable<Player> {
|
|||||||
this.updateZoneForView(com);
|
this.updateZoneForView(com);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasBlessing() {
|
public boolean hasBlessing() {
|
||||||
return blessingEffect != null;
|
return blessingEffect != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setBlessing(boolean bless) {
|
public void setBlessing(boolean bless) {
|
||||||
// no need to to change
|
// no need to to change
|
||||||
if ((blessingEffect != null) == bless) {
|
if ((blessingEffect != null) == bless) {
|
||||||
@@ -2882,14 +2886,14 @@ public class Player extends GameEntity implements Comparable<Player> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final PlayerZone com = getZone(ZoneType.Command);
|
final PlayerZone com = getZone(ZoneType.Command);
|
||||||
|
|
||||||
if(bless) {
|
if(bless) {
|
||||||
blessingEffect = new Card(-1, game);
|
blessingEffect = new Card(-1, game);
|
||||||
blessingEffect.setOwner(this);
|
blessingEffect.setOwner(this);
|
||||||
blessingEffect.setImageKey("t:blessing");
|
blessingEffect.setImageKey("t:blessing");
|
||||||
blessingEffect.setName("City's Blessing");
|
blessingEffect.setName("City's Blessing");
|
||||||
blessingEffect.addType("Effect");
|
blessingEffect.addType("Effect");
|
||||||
|
|
||||||
|
|
||||||
blessingEffect.updateStateForView();
|
blessingEffect.updateStateForView();
|
||||||
|
|
||||||
@@ -2898,7 +2902,7 @@ public class Player extends GameEntity implements Comparable<Player> {
|
|||||||
com.remove(blessingEffect);
|
com.remove(blessingEffect);
|
||||||
blessingEffect = null;
|
blessingEffect = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.updateZoneForView(com);
|
this.updateZoneForView(com);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ public enum TrackableProperty {
|
|||||||
//Shared
|
//Shared
|
||||||
Text(TrackableTypes.StringType),
|
Text(TrackableTypes.StringType),
|
||||||
PreventNextDamage(TrackableTypes.IntegerType),
|
PreventNextDamage(TrackableTypes.IntegerType),
|
||||||
EnchantedBy(TrackableTypes.CardViewCollectionType),
|
AttachedBy(TrackableTypes.CardViewCollectionType),
|
||||||
Counters(TrackableTypes.CounterMapType),
|
Counters(TrackableTypes.CounterMapType),
|
||||||
CurrentPlane(TrackableTypes.StringType),
|
CurrentPlane(TrackableTypes.StringType),
|
||||||
PlanarPlayer(TrackableTypes.PlayerViewType),
|
PlanarPlayer(TrackableTypes.PlayerViewType),
|
||||||
@@ -43,11 +43,7 @@ public enum TrackableProperty {
|
|||||||
NamedCard(TrackableTypes.StringType),
|
NamedCard(TrackableTypes.StringType),
|
||||||
PlayerMayLook(TrackableTypes.PlayerViewCollectionType, FreezeMode.IgnoresFreeze),
|
PlayerMayLook(TrackableTypes.PlayerViewCollectionType, FreezeMode.IgnoresFreeze),
|
||||||
PlayerMayLookTemp(TrackableTypes.PlayerViewCollectionType, FreezeMode.IgnoresFreeze),
|
PlayerMayLookTemp(TrackableTypes.PlayerViewCollectionType, FreezeMode.IgnoresFreeze),
|
||||||
Equipping(TrackableTypes.CardViewType),
|
Attaching(TrackableTypes.GameEntityViewType),
|
||||||
EquippedBy(TrackableTypes.CardViewCollectionType),
|
|
||||||
Enchanting(TrackableTypes.GameEntityViewType),
|
|
||||||
Fortifying(TrackableTypes.CardViewType),
|
|
||||||
FortifiedBy(TrackableTypes.CardViewCollectionType),
|
|
||||||
EncodedCards(TrackableTypes.CardViewCollectionType),
|
EncodedCards(TrackableTypes.CardViewCollectionType),
|
||||||
GainControlTargets(TrackableTypes.CardViewCollectionType),
|
GainControlTargets(TrackableTypes.CardViewCollectionType),
|
||||||
CloneOrigin(TrackableTypes.CardViewType),
|
CloneOrigin(TrackableTypes.CardViewType),
|
||||||
|
|||||||
@@ -404,56 +404,24 @@ public class TargetingOverlay {
|
|||||||
return; //don't add arcs for cards if card already visualized
|
return; //don't add arcs for cards if card already visualized
|
||||||
}
|
}
|
||||||
|
|
||||||
final CardView enchanting = c.getEnchantingCard();
|
final CardView attaching = c.getAttachingCard();
|
||||||
final CardView equipping = c.getEquipping();
|
final Iterable<CardView> attachedBy = c.getAttachedBy();
|
||||||
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 paired = c.getPairedWith();
|
final CardView paired = c.getPairedWith();
|
||||||
|
|
||||||
if (null != enchanting) {
|
if (null != attaching) {
|
||||||
if (enchanting.getController() != null && !enchanting.getController().equals(c.getController())) {
|
if (attaching.getController() != null && !attaching.getController().equals(c.getController())) {
|
||||||
addArc(endpoints.get(enchanting.getId()), endpoints.get(c.getId()), ArcConnection.Friends);
|
addArc(endpoints.get(attaching.getId()), endpoints.get(c.getId()), ArcConnection.Friends);
|
||||||
cardsVisualized.add(enchanting);
|
cardsVisualized.add(attaching);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (null != equipping) {
|
if (null != attachedBy) {
|
||||||
if (equipping.getController() != null && !equipping.getController().equals(c.getController())) {
|
for (final CardView enc : attachedBy) {
|
||||||
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 (enc.getController() != null && !enc.getController().equals(c.getController())) {
|
if (enc.getController() != null && !enc.getController().equals(c.getController())) {
|
||||||
addArc(endpoints.get(c.getId()), endpoints.get(enc.getId()), ArcConnection.Friends);
|
addArc(endpoints.get(c.getId()), endpoints.get(enc.getId()), ArcConnection.Friends);
|
||||||
cardsVisualized.add(enc);
|
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) {
|
if (null != paired) {
|
||||||
addArc(endpoints.get(paired.getId()), endpoints.get(c.getId()), ArcConnection.Friends);
|
addArc(endpoints.get(paired.getId()), endpoints.get(c.getId()), ArcConnection.Friends);
|
||||||
cardsVisualized.add(paired);
|
cardsVisualized.add(paired);
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen
|
|||||||
final CardStack stack = allLands.get(i);
|
final CardStack stack = allLands.get(i);
|
||||||
final CardPanel firstPanel = stack.get(0);
|
final CardPanel firstPanel = stack.get(0);
|
||||||
if (firstPanel.getCard().getCurrentState().getName().equals(state.getName())) {
|
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
|
// Put this land to the left of lands with the same name
|
||||||
// and attachments.
|
// and attachments.
|
||||||
insertIndex = i;
|
insertIndex = i;
|
||||||
@@ -114,7 +114,7 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen
|
|||||||
}
|
}
|
||||||
if (!panel.getAttachedPanels().isEmpty()
|
if (!panel.getAttachedPanels().isEmpty()
|
||||||
|| !panel.getCard().hasSameCounters(firstPanel.getCard())
|
|| !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,
|
// If this land has attachments or the stack is full,
|
||||||
// put it to the right.
|
// put it to the right.
|
||||||
insertIndex = i + 1;
|
insertIndex = i + 1;
|
||||||
@@ -683,8 +683,8 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen
|
|||||||
}
|
}
|
||||||
toPanel.getAttachedPanels().clear();
|
toPanel.getAttachedPanels().clear();
|
||||||
|
|
||||||
if (card.isEnchanted()) {
|
if (card.isAttached()) {
|
||||||
final Iterable<CardView> enchants = card.getEnchantedBy();
|
final Iterable<CardView> enchants = card.getAttachedBy();
|
||||||
for (final CardView e : enchants) {
|
for (final CardView e : enchants) {
|
||||||
final CardPanel cardE = getCardPanel(e.getId());
|
final CardPanel cardE = getCardPanel(e.getId());
|
||||||
if (cardE != null) {
|
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;
|
CardPanel attachedToPanel;
|
||||||
if (card.getEnchantingCard() != null) {
|
if (card.getAttachingCard() != null) {
|
||||||
attachedToPanel = getCardPanel(card.getEnchantingCard().getId());
|
attachedToPanel = getCardPanel(card.getAttachingCard().getId());
|
||||||
}
|
|
||||||
else if (card.getEquipping() != null) {
|
|
||||||
attachedToPanel = getCardPanel(card.getEquipping().getId());
|
|
||||||
}
|
|
||||||
else if (card.getFortifying() != null) {
|
|
||||||
attachedToPanel = getCardPanel(card.getFortifying().getId());
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
attachedToPanel = null;
|
attachedToPanel = null;
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ public class GameSimulatorTest extends SimulationTestCase {
|
|||||||
Card bear = addCard(bearCardName, p);
|
Card bear = addCard(bearCardName, p);
|
||||||
bear.setSickness(false);
|
bear.setSickness(false);
|
||||||
Card cloak = addCard("Whispersilk Cloak", p);
|
Card cloak = addCard("Whispersilk Cloak", p);
|
||||||
cloak.equipCard(bear);
|
cloak.attachEntity(bear);
|
||||||
game.getPhaseHandler().devModeSet(PhaseType.MAIN1, p);
|
game.getPhaseHandler().devModeSet(PhaseType.MAIN1, p);
|
||||||
game.getAction().checkStateEffects(true);
|
game.getAction().checkStateEffects(true);
|
||||||
assertEquals(1, bear.getAmountOfKeyword("Unblockable"));
|
assertEquals(1, bear.getAmountOfKeyword("Unblockable"));
|
||||||
@@ -133,7 +133,7 @@ public class GameSimulatorTest extends SimulationTestCase {
|
|||||||
Card bear = addCard(bearCardName, p);
|
Card bear = addCard(bearCardName, p);
|
||||||
bear.setSickness(false);
|
bear.setSickness(false);
|
||||||
Card lifelink = addCard("Lifelink", p);
|
Card lifelink = addCard("Lifelink", p);
|
||||||
lifelink.enchantEntity(bear);
|
lifelink.attachEntity(bear);
|
||||||
game.getPhaseHandler().devModeSet(PhaseType.MAIN1, p);
|
game.getPhaseHandler().devModeSet(PhaseType.MAIN1, p);
|
||||||
game.getAction().checkStateEffects(true);
|
game.getAction().checkStateEffects(true);
|
||||||
assertEquals(1, bear.getAmountOfKeyword("Lifelink"));
|
assertEquals(1, bear.getAmountOfKeyword("Lifelink"));
|
||||||
@@ -661,7 +661,7 @@ public class GameSimulatorTest extends SimulationTestCase {
|
|||||||
Card pridemate = addCard(pridemateName, p1);
|
Card pridemate = addCard(pridemateName, p1);
|
||||||
Card indestructibility = addCard(indestructibilityName, p1);
|
Card indestructibility = addCard(indestructibilityName, p1);
|
||||||
|
|
||||||
indestructibility.enchantEntity(pridemate);
|
indestructibility.attachEntity(pridemate);
|
||||||
|
|
||||||
Card ignition = addCardToZone(ignitionName, p1, ZoneType.Hand);
|
Card ignition = addCardToZone(ignitionName, p1, ZoneType.Hand);
|
||||||
SpellAbility ignitionSA = ignition.getFirstSpellAbility();
|
SpellAbility ignitionSA = ignition.getFirstSpellAbility();
|
||||||
@@ -681,6 +681,7 @@ public class GameSimulatorTest extends SimulationTestCase {
|
|||||||
|
|
||||||
// because it was destroyed
|
// because it was destroyed
|
||||||
assertNull(simBrood);
|
assertNull(simBrood);
|
||||||
|
assertNotNull(simPridemate);
|
||||||
|
|
||||||
assertEquals(0, simKalitas.getDamage());
|
assertEquals(0, simKalitas.getDamage());
|
||||||
assertEquals(3, simPridemate.getDamage());
|
assertEquals(3, simPridemate.getDamage());
|
||||||
@@ -774,7 +775,7 @@ public class GameSimulatorTest extends SimulationTestCase {
|
|||||||
Card pridemate = addCard(pridemateName, p1);
|
Card pridemate = addCard(pridemateName, p1);
|
||||||
Card indestructibility = addCard(indestructibilityName, p1);
|
Card indestructibility = addCard(indestructibilityName, p1);
|
||||||
|
|
||||||
indestructibility.enchantEntity(pridemate);
|
indestructibility.attachEntity(pridemate);
|
||||||
|
|
||||||
Card ignition = addCardToZone(ignitionName, p1, ZoneType.Hand);
|
Card ignition = addCardToZone(ignitionName, p1, ZoneType.Hand);
|
||||||
SpellAbility ignitionSA = ignition.getFirstSpellAbility();
|
SpellAbility ignitionSA = ignition.getFirstSpellAbility();
|
||||||
@@ -800,6 +801,7 @@ public class GameSimulatorTest extends SimulationTestCase {
|
|||||||
|
|
||||||
//destoryed because of to much redirected damage
|
//destoryed because of to much redirected damage
|
||||||
assertNull(simPalisade);
|
assertNull(simPalisade);
|
||||||
|
assertNotNull(simPridemate);
|
||||||
|
|
||||||
assertEquals(0, simKalitas.getDamage());
|
assertEquals(0, simKalitas.getDamage());
|
||||||
assertEquals(3, simPridemate.getDamage());
|
assertEquals(3, simPridemate.getDamage());
|
||||||
|
|||||||
@@ -102,22 +102,16 @@ public class GameWrapper {
|
|||||||
actualController.getZone( zoneType ).add( actualCard );
|
actualController.getZone( zoneType ).add( actualCard );
|
||||||
|
|
||||||
if( card.getTarget() != null ) {
|
if( card.getTarget() != null ) {
|
||||||
Card target = CardSpecificationHandler.INSTANCE.find( game, card.getTarget() );
|
Card target = CardSpecificationHandler.INSTANCE.find( game, card.getTarget() );
|
||||||
if( actualCard.isEnchantment() ) {
|
if (actualCard.isAttachment()) {
|
||||||
if( target.canBeEnchantedBy( actualCard ) ) {
|
if (target.canBeAttachedBy(actualCard)) {
|
||||||
actualCard.enchantEntity( target );
|
actualCard.attachEntity(target);
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalStateException( actualCard + " can't enchant " + target );
|
throw new IllegalStateException( actualCard + " can't attach " + target );
|
||||||
}
|
}
|
||||||
} else if( actualCard.isEquipment() ) {
|
} else {
|
||||||
if( target.canBeEquippedBy( actualCard ) ) {
|
throw new IllegalStateException( "Don't know how to make " + actualCard + " target anything" );
|
||||||
actualCard.equipCard( target );
|
}
|
||||||
} else {
|
|
||||||
throw new IllegalStateException( actualCard + " can't equip " + target );
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw new IllegalStateException( "Don't know how to make " + actualCard + " target anything" );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -441,48 +441,28 @@ public class CardDetailUtil {
|
|||||||
area.append(")");
|
area.append(")");
|
||||||
}
|
}
|
||||||
|
|
||||||
// equipping
|
// attached by
|
||||||
if (card.getEquipping() != null) {
|
if (card.isAttached()) {
|
||||||
if (area.length() != 0) {
|
if (area.length() != 0) {
|
||||||
area.append("\n");
|
area.append("\n");
|
||||||
}
|
}
|
||||||
area.append("=Equipping ");
|
area.append("=Attached by ");
|
||||||
area.append(card.getEquipping());
|
area.append(StringUtils.join(card.getAttachedBy(), ", "));
|
||||||
area.append("=");
|
area.append("=");
|
||||||
}
|
}
|
||||||
|
|
||||||
// equipped by
|
// attaching
|
||||||
if (card.isEquipped()) {
|
if (card.getAttachingCard() != null) {
|
||||||
if (area.length() != 0) {
|
if (area.length() != 0) {
|
||||||
area.append("\n");
|
area.append("\n");
|
||||||
}
|
}
|
||||||
area.append("=Equipped by ");
|
area.append("*Attaching ").append(card.getAttachingCard()).append("*");
|
||||||
area.append(StringUtils.join(card.getEquippedBy(), ", "));
|
|
||||||
area.append("=");
|
|
||||||
}
|
}
|
||||||
|
if (card.getAttachingPlayer() != null) {
|
||||||
// enchanting
|
|
||||||
if (card.getEnchantingCard() != null) {
|
|
||||||
if (area.length() != 0) {
|
if (area.length() != 0) {
|
||||||
area.append("\n");
|
area.append("\n");
|
||||||
}
|
}
|
||||||
area.append("*Enchanting ").append(card.getEnchantingCard()).append("*");
|
area.append("*Enchanting ").append(card.getAttachingPlayer()).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("*");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// controlling
|
// controlling
|
||||||
|
|||||||
@@ -595,7 +595,7 @@ public class QuestUtil {
|
|||||||
rules.setManaBurn(FModel.getPreferences().getPrefBoolean(FPref.UI_MANABURN));
|
rules.setManaBurn(FModel.getPreferences().getPrefBoolean(FPref.UI_MANABURN));
|
||||||
rules.setCanCloneUseTargetsImage(FModel.getPreferences().getPrefBoolean(FPref.UI_CLONE_MODE_SOURCE));
|
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){
|
if(FModel.getQuest().getDeckConstructionRules() == DeckConstructionRules.Commander){
|
||||||
variant.add(GameType.Commander);
|
variant.add(GameType.Commander);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user