Files
forge/src/forge/SpellAbility.java
jendave a43b5a619c - Cards discarded as a cost will now be recorded in the SA and cleared at resolution.
- Altered DealDamage to use AF.calculateAmount()
- Added Pyromancy and Stormscale Anarch
2011-08-06 11:16:28 +00:00

482 lines
13 KiB
Java

package forge;
import java.util.ArrayList;
//only SpellAbility can go on the stack
//override any methods as needed
public abstract class SpellAbility {
public Object[] choices_made; //open ended Casting choice storage
//choices for constructor isPermanent argument
public static final int Spell = 0;
public static final int Ability = 1;
public static final int Ability_Tap = 2;
private String description = "";
private Player targetPlayer = null;
private String stackDescription = "";
private String manaCost = "";
private String additionalManaCost = "";
private String multiKickerManaCost= "";
private String xManaCost = "";
private Player activatingPlayer = null;
private String type = "Intrinsic"; //set to Intrinsic by default
private Card targetCard;
private Card sourceCard;
private CardList targetList;
private boolean spell;
private boolean tapAbility;
private boolean untapAbility;
private boolean buyBackAbility = false; //false by default
private boolean flashBackAbility = false;
private boolean multiKicker = false;
private boolean xCost = false;
private boolean kickerAbility = false;
private boolean kothThirdAbility = false;
private boolean cycling = false;
private Input beforePayMana;
private Input afterResolve;
private Input afterPayMana;
protected Ability_Cost payCosts = null;
protected Target chosenTarget = null;
private SpellAbility_Restriction restrictions = new SpellAbility_Restriction();
private Ability_Sub subAbility = null;
private CardList sacrificedCards = null;
private CardList discardedCards = null;
private Command cancelCommand = Command.Blank;
private Command beforePayManaAI = Command.Blank;
private CommandArgs randomTarget = new CommandArgs() {
private static final long serialVersionUID = 1795025064923737374L;
public void execute(Object o) {}
};
public SpellAbility(int spellOrAbility, Card i_sourceCard) {
if(spellOrAbility == Spell) spell = true;
else if(spellOrAbility == Ability) spell = false;
else if(spellOrAbility == Ability_Tap) {
spell = false;
tapAbility = true;
}
else throw new RuntimeException("SpellAbility : constructor error, invalid spellOrAbility argument = "
+ spellOrAbility);
sourceCard = i_sourceCard;
}
//Spell, and Ability, and other Ability objects override this method
abstract public boolean canPlay();
//all Spell's and Abilities must override this method
abstract public void resolve();
/*
public boolean canPlayAI()
{
return true;
}
public void chooseTargetAI()
{
}
*/
public boolean canPlayAI() {
return true;
}
public void chooseTargetAI() {
randomTarget.execute(this);
}
public void setChooseTargetAI(CommandArgs c) {
randomTarget = c;
}
public CommandArgs getChooseTargetAI() {
return randomTarget;
}
public String getManaCost() {
return manaCost;
}
public void setManaCost(String cost) {
manaCost = cost;
}
public String getAdditionalManaCost() {
return additionalManaCost;
}
public void setAdditionalManaCost(String cost) {
additionalManaCost = cost;
}
public String getMultiKickerManaCost() {
return multiKickerManaCost;
}
public void setMultiKickerManaCost(String cost) {
multiKickerManaCost = cost;
}
public String getXManaCost()
{
return xManaCost;
}
public void setXManaCost(String cost)
{
xManaCost = cost;
}
public Player getActivatingPlayer()
{
return activatingPlayer;
}
public void setActivatingPlayer(Player player)
{
activatingPlayer = player;
}
public boolean isSpell() {
return spell;
}
public boolean isAbility() {
return !isSpell();
}
public boolean isTapAbility() {
return tapAbility;
}
public boolean isUntapAbility() {
return untapAbility;
}
public void makeUntapAbility()
{
untapAbility = true;
tapAbility = false;
}
public void setIsBuyBackAbility(boolean b) {
buyBackAbility = b;
}
public boolean isBuyBackAbility() {
return buyBackAbility;
}
public void setIsMultiKicker(boolean b){
multiKicker = b;
}
public boolean isMultiKicker() {
return multiKicker;
}
public void setIsXCost(boolean b) {
xCost = b;
}
public boolean isXCost(){
return xCost;
}
public void setIsCycling(boolean b) {
cycling = b;
}
public boolean isCycling(){
return cycling;
}
public void setSourceCard(Card c) {
sourceCard = c;
}
public Card getSourceCard() {
return sourceCard;
}
public Command getBeforePayManaAI() {
return beforePayManaAI;
}
public void setBeforePayManaAI(Command c) {
beforePayManaAI = c;
}
//begin - Input methods
public Input getBeforePayMana() {
return beforePayMana;
}
public void setBeforePayMana(Input in) {
beforePayMana = in;
}
public Input getAfterPayMana() {
return afterPayMana;
}
public void setAfterPayMana(Input in) {
afterPayMana = in;
}
public Ability_Cost getPayCosts() {
return payCosts;
}
public void setPayCosts(Ability_Cost abCost) {
payCosts = abCost;
}
public Target getTarget() {
return chosenTarget;
}
public void setTarget(Target tgt) {
chosenTarget = tgt;
}
public void setRestrictions(SpellAbility_Restriction restrict){
restrictions = restrict;
}
public SpellAbility_Restriction getRestrictions(){
return restrictions;
}
public void addSacrificedCost(Card c){
if (sacrificedCards == null)
sacrificedCards = new CardList();
sacrificedCards.add(c);
}
public CardList getSacrificedCost(){
return sacrificedCards;
}
public void resetSacrificedCost(){
sacrificedCards = null;
}
public void addDiscardedCost(Card c){
if (discardedCards == null)
discardedCards = new CardList();
discardedCards.add(c);
}
public CardList getDiscardedCost(){
return discardedCards;
}
public void resetDiscardedCost(){
discardedCards = null;
}
public Input getAfterResolve() {
return afterResolve;
}
public void setAfterResolve(Input in) {
afterResolve = in;
}
public void setStackDescription(String s) {
stackDescription = s;
}
public String getStackDescription() {
if(stackDescription.equals(getSourceCard().getText().trim())) return getSourceCard().getName() + " - "
+ getSourceCard().getText();
return stackDescription.replaceAll("CARDNAME", this.getSourceCard().getName());
}
public boolean isIntrinsic() {
return type.equals("Intrinsic");
}
public boolean isExtrinsic() {
return type.equals("Extrinsic");
}
public void setType(String s) //Extrinsic or Intrinsic:
{
type = s;
}
//setDescription() includes mana cost and everything like
//"G, tap: put target creature from your hand into play"
public void setDescription(String s) {
description = s;
}
@Override
public String toString() {
if (description.contains("CARDNAME"))
description = description.replace("CARDNAME", this.getSourceCard().getName());
return description;
}
public void setSubAbility(Ability_Sub subAbility) {
this.subAbility = subAbility;
}
public Ability_Sub getSubAbility() {
return this.subAbility;
}
public Card getTargetCard() {
if(targetCard == null){
Target tgt = this.getTarget();
if (tgt != null){
ArrayList<Card> list = tgt.getTargetCards();
if (!list.isEmpty())
return list.get(0);
}
return null;
}
return targetCard;
}
public void setTargetCard(Card card) {
if (card == null){
System.out.println(getSourceCard()+" - SpellAbility.setTargetCard() called with null for target card.");
return;
}
Target tgt = this.getTarget();
if (tgt != null){
tgt.addTarget(card);
}
else{
targetPlayer = null;//reset setTargetPlayer()
targetCard = card;
}
String desc = "";
if(null != card) {
if(!card.isFaceDown()) desc = getSourceCard().getName() + " - targeting " + card;
else desc = getSourceCard().getName() + " - targeting Morph(" + card.getUniqueNumber() + ")";
setStackDescription(desc);
}
}
public CardList getTargetList() {
return targetList;
}
public void setTargetList(CardList list) {
// The line below started to create a null error at forge.CardFactoryUtil.canTarget(CardFactoryUtil.java:3329)
// after ForgeSVN r2699. I hope that commenting out the line below will not result in other bugs. :)
// targetPlayer = null;//reset setTargetPlayer()
targetList = list;
StringBuilder sb = new StringBuilder();
sb.append(getSourceCard().getName()).append(" - targeting ");
for (int i = 0; i < targetList.size(); i++) {
if (!targetList.get(i).isFaceDown()) sb.append(targetList.get(i));
else sb.append("Morph(").append(targetList.get(i).getUniqueNumber()).append(")");
if (i < targetList.size() - 1) sb.append(", ");
}
setStackDescription(sb.toString());
}
public void setTargetPlayer(Player p) {
if(p == null || (!(p.isHuman() || p.isComputer()))) throw new RuntimeException(
"SpellAbility : setTargetPlayer() error, argument is " + p + " source card is " + getSourceCard());
Target tgt = this.getTarget();
if (tgt != null){
tgt.addTarget(p);
}
else{
targetCard = null;//reset setTargetCard()
targetPlayer = p;
}
setStackDescription(getSourceCard().getName() + " - targeting " + p);
}
public Player getTargetPlayer() {
if(targetPlayer == null){
Target tgt = this.getTarget();
if (tgt != null){
ArrayList<Player> list = tgt.getTargetPlayers();
if (!list.isEmpty())
return list.get(0);
}
return null;
}
return targetPlayer;
}
public Command getCancelCommand() {
return cancelCommand;
}
public void setCancelCommand(Command cancelCommand) {
this.cancelCommand = cancelCommand;
}
public void setFlashBackAbility(boolean flashBackAbility) {
this.flashBackAbility = flashBackAbility;
}
public boolean isFlashBackAbility() {
return flashBackAbility;
}
public void setKickerAbility(boolean kab) {
this.kickerAbility=kab;
}
public boolean isKickerAbility() {
return kickerAbility;
}
// Only used by Ability_Reflected_Mana, because the user has an option to cancel the input.
// Most spell abilities and even most mana abilities do not need to use this.
public boolean wasCancelled() {
return false;
}
public SpellAbility copy()
{
SpellAbility clone = null;
try {
clone = (SpellAbility)this.clone();
} catch (CloneNotSupportedException e) {
System.err.println(e);
}
return clone;
}
public void setKothThirdAbility(boolean kothThirdAbility) {
this.kothThirdAbility = kothThirdAbility;
}
public boolean isKothThirdAbility() {
return kothThirdAbility;
}
}