Refactoring Enchanting and GameEntities

Added support for Enchanting Players in AF_Attach
Added Psychic Possession
This commit is contained in:
Sol
2011-09-17 20:49:55 +00:00
parent ea35ddd564
commit f71567c0f8
15 changed files with 254 additions and 160 deletions

1
.gitattributes vendored
View File

@@ -5776,6 +5776,7 @@ res/cardsfolder/p/psychic_barrier.txt svneol=native#text/plain
res/cardsfolder/p/psychic_drain.txt svneol=native#text/plain
res/cardsfolder/p/psychic_membrane.txt svneol=native#text/plain
res/cardsfolder/p/psychic_overload.txt svneol=native#text/plain
res/cardsfolder/p/psychic_possession.txt -text
res/cardsfolder/p/psychic_purge.txt svneol=native#text/plain
res/cardsfolder/p/psychic_spear.txt svneol=native#text/plain
res/cardsfolder/p/psychic_surgery.txt svneol=native#text/plain

View File

@@ -0,0 +1,11 @@
Name:Psychic Possession
ManaCost:2 U U
Types:Enchantment Aura
Text:Skip your draw step.
A:SP$ Attach | Cost$ 2 U U | ValidTgts$ Opponent | AILogic$ Curse
T:Mode$ Drawn | ValidCard$ Card.YouDontOwn | TriggerZones$ Battlefield | Execute$ TrigDraw | OptionalDecider$ You | TriggerDescription$ Whenever an opponent draws a card, you may draw a card.
SVar:TrigDraw:DB$Draw | NumCards$ 1
SVar:RemAIDeck:True
SVar:Rarity:Rare
SVar:Picture:http://www.wizards.com/global/images/magic/general/psychic_possession.jpg
End

View File

@@ -55,10 +55,9 @@ public class Card extends GameEntity implements Comparable<Card> {
//if this card is of the type equipment, what card is it currently equipping?
private ArrayList<Card> equipping = new ArrayList<Card>();
//which auras enchanted this card?
private ArrayList<Card> enchantedBy = new ArrayList<Card>();
//enchanting size will always be 0 or 1
//if this card is an Aura, what card is it enchanting?
private ArrayList<Card> enchanting = new ArrayList<Card>();
//if this card is an Aura, what Entity is it enchanting?
private GameEntity enchanting = null;
private ArrayList<String> type = new ArrayList<String>();
private ArrayList<String> prevType = new ArrayList<String>();
private ArrayList<String> choicesMade = new ArrayList<String>();
@@ -3036,30 +3035,12 @@ public class Card extends GameEntity implements Comparable<Card> {
}
}
/**
* <p>Getter for the field <code>enchantedBy</code>.</p>
*
* @return a {@link java.util.ArrayList} object.
*/
public final ArrayList<Card> getEnchantedBy() {
return enchantedBy;
}
/**
* <p>Setter for the field <code>enchantedBy</code>.</p>
*
* @param list a {@link java.util.ArrayList} object.
*/
public final void setEnchantedBy(final ArrayList<Card> list) {
enchantedBy = list;
}
/**
* <p>Getter for the field <code>enchanting</code>.</p>
*
* @return a {@link java.util.ArrayList} object.
* @return a {@link forge.enchanting} object.
*/
public final ArrayList<Card> getEnchanting() {
public final GameEntity getEnchanting() {
return enchanting;
}
@@ -3069,10 +3050,22 @@ public class Card extends GameEntity implements Comparable<Card> {
* @return a {@link forge.Card} object.
*/
public final Card getEnchantingCard() {
if (enchanting.size() == 0) {
if (enchanting != null && enchanting instanceof Card){
return (Card)enchanting;
}
return null;
}
return enchanting.get(0);
/**
* <p>getEnchantingPlayer.</p>
*
* @return a {@link forge.Player} object.
*/
public final Player getEnchantingPlayer() {
if (enchanting != null && enchanting instanceof Player){
return (Player)enchanting;
}
return null;
}
/**
@@ -3080,17 +3073,8 @@ public class Card extends GameEntity implements Comparable<Card> {
*
* @param list a {@link java.util.ArrayList} object.
*/
public final void setEnchanting(final ArrayList<Card> list) {
enchanting = list;
}
/**
* <p>isEnchanted.</p>
*
* @return a boolean.
*/
public final boolean isEnchanted() {
return enchantedBy.size() != 0;
public final void setEnchanting(GameEntity e) {
enchanting = e;
}
/**
@@ -3099,27 +3083,25 @@ public class Card extends GameEntity implements Comparable<Card> {
* @return a boolean.
*/
public final boolean isEnchanting() {
return enchanting.size() != 0;
return enchanting != null;
}
/**
* <p>addEnchantedBy.</p>
* <p>isEnchanting.</p>
*
* @param c a {@link forge.Card} object.
* @return a boolean.
*/
public final void addEnchantedBy(final Card c) {
enchantedBy.add(c);
this.updateObservers();
public final boolean isEnchantingCard() {
return getEnchantingCard() != null;
}
/**
* <p>removeEnchantedBy.</p>
* <p>isEnchanting.</p>
*
* @param c a {@link forge.Card} object.
* @return a boolean.
*/
public final void removeEnchantedBy(final Card c) {
enchantedBy.remove(c);
this.updateObservers();
public final boolean isEnchantingPlayer() {
return getEnchantingPlayer() != null;
}
/**
@@ -3141,10 +3123,10 @@ public class Card extends GameEntity implements Comparable<Card> {
/**
* <p>addEnchanting.</p>
*
* @param c a {@link forge.Card} object.
* @param e a {@link forge.GameEntity} object.
*/
public final void addEnchanting(final Card c) {
enchanting.add(c);
public final void addEnchanting(final GameEntity e) {
enchanting = e;
setTimestamp(AllZone.getNextTimestamp());
this.updateObservers();
}
@@ -3152,41 +3134,36 @@ public class Card extends GameEntity implements Comparable<Card> {
/**
* <p>removeEnchanting.</p>
*
* @param c a {@link forge.Card} object.
* @param e a {@link forge.GameEntity} object.
*/
public final void removeEnchanting(final Card c) {
enchanting.remove(c);
public final void removeEnchanting(final GameEntity e) {
if (enchanting.equals(e)){
enchanting = null;
this.updateObservers();
}
}
/**
* <p>enchantCard.</p>
* <p>enchant</p>
*
* @param c a {@link forge.Card} object.
* @param entity a {@link forge.GameEntity} object.
*/
public final void enchantCard(final Card c) {
addEnchanting(c);
c.addEnchantedBy(this);
public final void enchantEntity(final GameEntity entity) {
addEnchanting(entity);
entity.addEnchantedBy(this);
this.enchant();
}
/**
* <p>unEnchantCard.</p>
* <p>unEnchant.</p>
*
* @param c a {@link forge.Card} object.
* @param gameEntity a {@link forge.GameEntity} object.
*/
public final void unEnchantCard(final Card c) {
public final void unEnchantEntity(final GameEntity gameEntity) {
if (enchanting != null && enchanting.equals(gameEntity)){
this.unEnchant();
enchanting.remove(c);
c.removeEnchantedBy(this);
}
/**
* <p>unEnchantAllCards.</p>
*/
public final void unEnchantAllCards() {
for (int i = 0; i < enchantedBy.size(); i++) {
enchantedBy.get(i).unEnchantCard(this);
enchanting = null;
gameEntity.removeEnchantedBy(this);
}
}
@@ -4979,11 +4956,11 @@ public class Card extends GameEntity implements Comparable<Card> {
} else if (Property.startsWith("AttachedBy")) {
if (!equippedBy.contains(source) && !enchantedBy.contains(source)) return false;
} else if (Property.startsWith("Attached")) {
if (!equipping.contains(source) && !enchanting.contains(source)) return false;
if (!equipping.contains(source) && !source.equals(enchanting)) return false;
} else if (Property.startsWith("EnchantedBy")) {
if (!enchantedBy.contains(source)) return false;
} else if (Property.startsWith("Enchanted")) {
if (!enchanting.contains(source)) return false;
if (!source.equals(enchanting)) return false;
} else if (Property.startsWith("EquippedBy")) {
if (!equippedBy.contains(source)) return false;
} else if (Property.startsWith("Equipped")) {

View File

@@ -351,7 +351,7 @@ public final class CardUtil {
if (relation.equals("CARDNAME")) {
return c;
} else if (relation.startsWith("enchanted ")) {
return c.getEnchanting().get(0);
return c.getEnchantingCard();
} else if (relation.startsWith("equipped ")) {
return c.getEquipping().get(0);
//else if(relation.startsWith("target ")) return c.getTargetCard();

View File

@@ -1712,7 +1712,7 @@ public class CombatUtil {
if (obj != null) {
Card target = (Card) obj;
if (AllZoneUtil.isCardInPlay(target)) {
crd.enchantCard(target);
crd.enchantEntity(target);
}
}
}
@@ -2090,7 +2090,7 @@ public class CombatUtil {
if (Enchantment != null && AllZoneUtil.isCardInPlay(attacker)) {
GameAction.changeZone(AllZone.getZone(Enchantment),
AllZone.getZone(Constant.Zone.Battlefield, Enchantment.getOwner()), Enchantment);
Enchantment.enchantCard(attacker);
Enchantment.enchantEntity(attacker);
}
attacker.getController().shuffle();
}//resolve

View File

@@ -738,29 +738,44 @@ public class GameAction {
if (c.isAura()) {
// Check if Card Aura is attached to is a legal target
for (int i = 0; i < c.getEnchanting().size(); i++) {
Card perm = c.getEnchanting().get(i);
GameEntity entity = c.getEnchanting();
SpellAbility sa = c.getSpellPermanent();
Target tgt = null;
if (sa != null) {
tgt = sa.getTarget();
}
if (entity instanceof Card){
Card perm = (Card)entity;
// I think the Keyword checks might be superfluous with the isValidCard check
if (!AllZoneUtil.isCardInPlay(perm)
|| CardFactoryUtil.hasProtectionFrom(c, perm)
|| ((c.hasKeyword("Enchant creature") || c.hasKeyword("Enchant tapped creature"))
&& !perm.isCreature())
|| (c.hasKeyword("Enchant tapped creature") && perm.isUntapped())
|| (tgt != null && !perm.isValidCard(tgt.getValidTgts(), c.getController(), c)))
{
c.unEnchantCard(perm);
|| (tgt != null && !perm.isValidCard(tgt.getValidTgts(), c.getController(), c))){
c.unEnchantEntity(perm);
moveToGraveyard(c);
checkAgain = true;
}
}
else{
Player pl = (Player)entity;
boolean invalid = false;
if (tgt.canOnlyTgtOpponent() && !c.getController().getOpponent().isPlayer(pl)){
invalid = true;
}
else{
// TODO: Check Player Protection once it's added.
}
if (invalid){
c.unEnchantEntity(pl);
moveToGraveyard(c);
checkAgain = true;
}
}
} //if isAura
if (c.isCreature()) {

View File

@@ -2818,8 +2818,9 @@ public final class GameActionUtil {
} else if (range.equals("All")) {
affected.addAll(AllZoneUtil.getCardsInPlay());
} else if (range.equals("Enchanted")) {
if (source.getEnchanting().size() > 0) {
affected.addAll(source.getEnchanting().toArray());
Card en = source.getEnchantingCard();
if (en != null) {
affected.add(en);
}
}
affected = affected.getValidCards(specific, source.getController(), source);

View File

@@ -1,5 +1,7 @@
package forge;
import java.util.ArrayList;
import forge.card.spellability.SpellAbility;
@@ -12,6 +14,7 @@ import forge.card.spellability.SpellAbility;
public abstract class GameEntity extends MyObservable {
private String name = "";
private int preventNextDamage = 0;
protected ArrayList<Card> enchantedBy = new ArrayList<Card>();
/**
* <p>Getter for the field <code>name</code>.</p>
@@ -247,6 +250,65 @@ public abstract class GameEntity extends MyObservable {
return true;
}
// GameEntities can now be Enchanted
/**
* <p>Getter for the field <code>enchantedBy</code>.</p>
*
* @return a {@link java.util.ArrayList} object.
*/
public final ArrayList<Card> getEnchantedBy() {
return enchantedBy;
}
/**
* <p>Setter for the field <code>enchantedBy</code>.</p>
*
* @param list a {@link java.util.ArrayList} object.
*/
public final void setEnchantedBy(final ArrayList<Card> list) {
enchantedBy = list;
}
/**
* <p>isEnchanted.</p>
*
* @return a boolean.
*/
public final boolean isEnchanted() {
return enchantedBy.size() != 0;
}
/**
* <p>addEnchantedBy.</p>
*
* @param c a {@link forge.Card} object.
*/
public final void addEnchantedBy(final Card c) {
enchantedBy.add(c);
this.updateObservers();
}
/**
* <p>removeEnchantedBy.</p>
*
* @param c a {@link forge.Card} object.
*/
public final void removeEnchantedBy(final Card c) {
enchantedBy.remove(c);
this.updateObservers();
}
/**
* <p>unEnchantAllCards.</p>
*/
public final void unEnchantAllCards() {
for (int i = 0; i < enchantedBy.size(); i++) {
enchantedBy.get(i).unEnchantEntity(this);
}
}
////////////////////////////////
//
// generic Object overrides

View File

@@ -1129,8 +1129,8 @@ public final class GuiDisplayUtil implements NewConstants {
}
}
if (card.isEnchanting()) {
toPanel.attachedToPanel = p.getCardPanel(card.getEnchanting().get(0).getUniqueNumber());
if (card.isEnchantingCard()) {
toPanel.attachedToPanel = p.getCardPanel(card.getEnchantingCard().getUniqueNumber());
} else if (card.isEquipping()) {
toPanel.attachedToPanel = p.getCardPanel(card.getEquipping().get(0).getUniqueNumber());
} else {

View File

@@ -15,6 +15,7 @@ import forge.CombatUtil;
import forge.Command;
import forge.ComputerUtil;
import forge.Constant;
import forge.GameEntity;
import forge.MyRandom;
import forge.Player;
@@ -534,7 +535,7 @@ public class AbilityFactory_Attach {
return null;
}
if (af.isCurse())
if ("Curse".equals(af.getMapParams().get("AILogic")))
p = AllZone.getHumanPlayer();
else
p = AllZone.getComputerPlayer();
@@ -650,18 +651,19 @@ public class AbilityFactory_Attach {
}
else if (o instanceof Player){
// Currently, a few cards can enchant players
// Psychic Possession, Paradox Haze, Wheel of Sun and Moon
// Player p = (Player)o;
//if (card.isAura())
// card.enchantPlayer(p);
// Psychic Possession, Paradox Haze, Wheel of Sun and Moon, New Curse cards
Player p = (Player)o;
if (card.isAura()){
handleAura(card, p, false);
}
}
}
public static void handleAura(final Card card, final Card tgt, boolean gainControl){
public static void handleAura(final Card card, final GameEntity tgt, boolean gainControl){
if (card.isEnchanting()){
// If this Card is already Enchanting something
// Need to unenchant it, then clear out the commands
Card oldEnchanted = card.getEnchantingCard();
GameEntity oldEnchanted = card.getEnchanting();
card.removeEnchanting(oldEnchanted);
card.clearEnchantCommand();
card.clearUnEnchantCommand();
@@ -671,19 +673,27 @@ public class AbilityFactory_Attach {
if (gainControl){
// Handle GainControl Auras
final Player[] pl = new Player[1];
pl[0] = tgt.getController();
if (tgt instanceof Card){
pl[0] = ((Card)tgt).getController();
}
else{
pl[0] = (Player)tgt;
}
Command onEnchant = new Command() {
private static final long serialVersionUID = -2519887209491512000L;
public void execute() {
if(card.isEnchanting()) {
Card crd = card.getEnchanting().get(0);
Card crd = card.getEnchantingCard();
if (crd == null){
return;
}
pl[0] = crd.getController();
crd.addController(card);
//AllZone.getGameAction().changeController(new CardList(crd), pl[0], card.getController());
}
}//execute()
};//Command
@@ -691,12 +701,13 @@ public class AbilityFactory_Attach {
private static final long serialVersionUID = 3426441132121179288L;
public void execute() {
if(card.isEnchanting()) {
Card crd = card.getEnchanting().get(0);
Card crd = card.getEnchantingCard();
if (crd == null){
return;
}
if(AllZoneUtil.isCardInPlay(crd)) {
crd.removeController(card);
//AllZone.getGameAction().changeController(new CardList(crd), crd.getController(), pl[0]);
}
}
}//execute()
@@ -707,17 +718,16 @@ public class AbilityFactory_Attach {
private static final long serialVersionUID = -65903786170234039L;
public void execute() {
if(card.isEnchanting()) {
Card crd = card.getEnchanting().get(0);
Card crd = card.getEnchantingCard();
if (crd == null){
return;
}
crd.removeController(card); //This looks odd, but will simply refresh controller
crd.addController(card);
//AllZone.getGameAction().changeController(new CardList(crd), crd.getController(),card.getController());
}
}//execute()
};//Command
// Add Enchant Commands
// Add Enchant Commands for Control changers
card.addEnchantCommand(onEnchant);
card.addUnEnchantCommand(onUnEnchant);
card.addChangeControllerCommand(onChangesControl);
@@ -727,15 +737,17 @@ public class AbilityFactory_Attach {
private static final long serialVersionUID = -639204333673364477L;
public void execute() {
if(card.isEnchanting()) {
Card crd = card.getEnchanting().get(0);
card.unEnchantCard(crd);
GameEntity entity = card.getEnchanting();
if (entity == null){
return;
}
card.unEnchantEntity(entity);
}
};//Command
card.addLeavesPlayCommand(onLeavesPlay);
card.enchantCard(tgt);
card.enchantEntity(tgt);
}
public static SpellAbility getAttachSpellAbility(Card source){
@@ -767,7 +779,7 @@ public class AbilityFactory_Attach {
Object o = GuiUtils.getChoice(source + " - Select a card to attach to.", list.toArray());
if (o instanceof Card){
source.enchantCard((Card)o);
source.enchantEntity((Card)o);
return true;
}
}
@@ -775,7 +787,7 @@ public class AbilityFactory_Attach {
else if (AbilityFactory_Attach.attachPreference(af, aura, af.getMapParams(), tgt, true)){
Object o = aura.getTarget().getTargets().get(0);
if (o instanceof Card){
source.enchantCard((Card)o);
source.enchantEntity((Card)o);
return true;
}
else if (o instanceof Player)

View File

@@ -2850,8 +2850,9 @@ public class CardFactoryUtil {
// count total number of aura enchanting card that aura is attached to
if (l[0].contains("AllAurasEnchanting")) {
int numAuras = 0;
if (c.getEnchanting().size() != 0) {
numAuras = c.getEnchantingCard().getEnchantedBy().size();
Card aura = c.getEnchantingCard();
if (aura != null){
numAuras = aura.getEnchantedBy().size();
}
return doXMath(numAuras, m, c);
}

View File

@@ -150,7 +150,7 @@ class CardFactory_Auras {
if (AllZoneUtil.isCardInPlay(c)
&& CardFactoryUtil.canTarget(card, c))
{
card.enchantCard(c);
card.enchantEntity(c);
}
} //resolve()
@@ -171,7 +171,7 @@ class CardFactory_Auras {
public void execute() {
if (card.isEnchanting()) {
Card crd = card.getEnchanting().get(0);
Card crd = card.getEnchantingCard();
ArrayList<Card> seas = crd.getEnchantedBy();
int count = 0;
for (int i = 0; i < seas.size(); i++) {
@@ -210,7 +210,7 @@ class CardFactory_Auras {
public void execute() {
if (card.isEnchanting()) {
Card crd = card.getEnchanting().get(0);
Card crd = card.getEnchantingCard();
ArrayList<Card> seas = crd.getEnchantedBy();
int count = 0;
for (int i = 0; i < seas.size(); i++) {
@@ -250,8 +250,8 @@ class CardFactory_Auras {
public void execute() {
if (card.isEnchanting()) {
Card crd = card.getEnchanting().get(0);
card.unEnchantCard(crd);
Card crd = card.getEnchantingCard();
card.unEnchantEntity(crd);
}
}
};
@@ -319,7 +319,7 @@ class CardFactory_Auras {
if (AllZoneUtil.isCardInPlay(c)
&& CardFactoryUtil.canTarget(card, c))
{
card.enchantCard(c);
card.enchantEntity(c);
Log.debug("Enchanted: " + getTargetCard());
}
} //resolve()
@@ -334,7 +334,7 @@ class CardFactory_Auras {
public void execute() {
if (card.isEnchanting()) {
Card crd = card.getEnchanting().get(0);
Card crd = card.getEnchantingCard();
if (crd.hasKeyword("Flying")) {
badTarget[0] = false;
crd.addDamage(2, card);
@@ -355,7 +355,7 @@ class CardFactory_Auras {
if (card.isEnchanting()
&& !badTarget[0])
{
Card crd = card.getEnchanting().get(0);
Card crd = card.getEnchantingCard();
crd.addIntrinsicKeyword("Flying");
}
} //execute()
@@ -367,8 +367,8 @@ class CardFactory_Auras {
public void execute() {
if (card.isEnchanting()) {
Card crd = card.getEnchanting().get(0);
card.unEnchantCard(crd);
Card crd = card.getEnchantingCard();
card.unEnchantEntity(crd);
}
}
};
@@ -429,7 +429,7 @@ class CardFactory_Auras {
if (AllZoneUtil.isCardInPlay(c)
&& CardFactoryUtil.canTarget(aura, c))
{
aura.enchantCard(c);
aura.enchantEntity(c);
}
} //resolve()
}; //SpellAbility
@@ -523,7 +523,7 @@ class CardFactory_Auras {
if (cardName.equals("Dance of the Dead")) {
animated.tap();
}
card.enchantCard(animated); // Attach before Targeting so detach Command will trigger
card.enchantEntity(animated); // Attach before Targeting so detach Command will trigger
if (CardFactoryUtil.hasProtectionFrom(card, animated)) {
// Animated a creature with protection

View File

@@ -1744,7 +1744,7 @@ public class CardFactory_Creatures {
if (choices.contains(card)) {
if (AllZoneUtil.isCardInPlay(card)) {
c.enchantCard(card);
c.enchantEntity(card);
stop();
}
}

View File

@@ -1383,10 +1383,16 @@ public class CardFactory_Instants {
CardList ens = AllZoneUtil.getTypeInPlay("Enchantment");
CardList toReturn = ens.filter(new CardListFilter() {
public boolean addCard(final Card c) {
return (c.getOwner().isPlayer(you) && c.getController().isPlayer(you))
|| (c.isAura() && c.getEnchanting().get(0).getController().isPlayer(you))
|| (c.isAura() && c.getEnchanting().get(0).isAttacking()
&& c.getEnchanting().get(0).getController().isPlayer(you.getOpponent()));
Card enchanting = c.getEnchantingCard();
if (enchanting != null){
if ((enchanting.isAttacking() && enchanting.getController().isPlayer(you.getOpponent())) ||
enchanting.getController().isPlayer(you)){
return true;
}
}
return (c.getOwner().isPlayer(you) && c.getController().isPlayer(you));
}
});
for (Card c : toReturn) {

View File

@@ -266,16 +266,24 @@ public class CardDetailPanel extends JPanel implements CardContainer {
}
//enchanting
if (card.getEnchanting().size() > 0) {
GameEntity entity = card.getEnchanting();
if (entity != null){
if (area.length() != 0) area.append("\n");
area.append("*Enchanting ");
if (card.getEnchanting().get(0).isFaceDown()
&& card.getEnchanting().get(0).getController().isComputer()) {
if (entity instanceof Card){
Card c = (Card)entity;
if (c.isFaceDown() && c.getController().isComputer()){
area.append("Morph (");
area.append(card.getEnchanting().get(0).getUniqueNumber());
area.append(card.getUniqueNumber());
area.append(")");
} else {
area.append(card.getEnchanting().get(0));
}
else{
area.append(entity);
}
}
else{
area.append(entity);
}
area.append("*");
}