*Added Haunt keyword

*Added
	Absolver Thrull
	Belfry Spirit
	Benediction of Moons
	Blind Hunter
	Cry of Contrition
	Exhumer Thrull
	Graven Dominator
	Orzhov Euthanist
	Seize the Soul
This commit is contained in:
Hellfish
2011-09-20 16:16:52 +00:00
parent 7bf5ccc6e9
commit 75221cacbb
14 changed files with 376 additions and 4 deletions

View File

@@ -184,6 +184,9 @@ public class Card extends GameEntity implements Comparable<Card> {
private Map<Counters, Integer> counters = new TreeMap<Counters, Integer>();
private Map<String, String> sVars = new TreeMap<String, String>();
private static String[] storableSVars = {"ChosenX"};
private ArrayList<Card> hauntedBy = new ArrayList<Card>();
private Card haunting = null;
/**
*
@@ -1615,7 +1618,7 @@ public class Card extends GameEntity implements Comparable<Card> {
sbLong.append(" (When this enters the battlefield, sacrifice it unless you exile another ");
sbLong.append(types);
sbLong.append(" you control. When this leaves the battlefield, that card returns to the battlefield.)\r\n");
} else if (keyword.get(i).endsWith(".")) {
} else if (keyword.get(i).endsWith(".") && !keyword.get(i).startsWith("Haunt")) {
sbLong.append(keyword.get(i).toString()).append("\r\n");
} else if (keyword.get(i).contains("At the beginning of your upkeep, ")
&& keyword.get(i).contains(" unless you pay"))
@@ -1645,6 +1648,17 @@ public class Card extends GameEntity implements Comparable<Card> {
sbLong.append(" +1/+1 counters on it. When it's put into a graveyard, you may put its +1/+1 counters on target artifact creature.)");
} else if (keyword.get(i).startsWith("MayEffectFromOpeningHand")) {
continue;
} else if (keyword.get(i).contains("Haunt")) {
sb.append("\r\nHaunt (");
if(isCreature()) {
sb.append("When this creature dies, exile it haunting target creature.");
}
else
{
sb.append("When this spell card is put into a graveyard after resolving, exile it haunting target creature.");
}
sb.append(")");
continue;
} else {
if (i != 0 && sb.length() != 0) {
sb.append(", ");
@@ -1760,10 +1774,31 @@ public class Card extends GameEntity implements Comparable<Card> {
sb.append(")\r\n");
}
}
for(String keyw : kw) {
if(keyw.startsWith("Haunt")) {
if (sb.toString().endsWith("\r\n\r\n")) {
sb.delete(sb.lastIndexOf("\r\n"), sb.lastIndexOf("\r\n") + 3);
}
sb.append("Haunt (");
if(isCreature()) {
sb.append("When this creature dies, exile it haunting target creature.");
}
else {
sb.append("When this spell card is put into a graveyard after resolving, exile it haunting target creature.");
}
sb.append(")\r\n");
}
}
if(haunting != null) {
sb.append("Haunting: ").append(haunting);
sb.append("\r\n");
}
while (sb.toString().endsWith("\r\n")) {
sb.delete(sb.lastIndexOf("\r\n"), sb.lastIndexOf("\r\n") + 3);
}
}
return sb.toString().replaceAll("CARDNAME", getName());
}
@@ -1870,6 +1905,20 @@ public class Card extends GameEntity implements Comparable<Card> {
sb.append("\r\n");
}
}
if(hauntedBy.size() != 0) {
sb.append("Haunted by: ");
for(Card c : hauntedBy) {
sb.append(c).append(",");
}
sb.deleteCharAt(sb.length()-1);
sb.append("\r\n");
}
if(haunting != null) {
sb.append("Haunting: ").append(haunting);
sb.append("\r\n");
}
/*
sb.append("\r\nOwner: ").append(owner).append("\r\n");
@@ -4957,6 +5006,8 @@ public class Card extends GameEntity implements Comparable<Card> {
if (!equippedBy.contains(source)) return false;
} else if (Property.startsWith("Equipped")) {
if (!equipping.contains(source)) return false;
} else if (Property.startsWith("HauntedBy")) {
if (!hauntedBy.contains(source)) return false;
} else if (Property.startsWith("Above")){ // "Are Above" Source
CardList list = this.getOwner().getCardsIn(Zone.Graveyard);
if (!list.getAbove(source, this))
@@ -6129,5 +6180,28 @@ public class Card extends GameEntity implements Comparable<Card> {
public final void setFoil(final int f) {
sVars.put("Foil", Integer.toString(f));
}
public final void addHauntedBy(final Card c) {
hauntedBy.add(c);
if(c != null) {
c.setHaunting(this);
}
}
public final ArrayList<Card> getHauntedBy() {
return hauntedBy;
}
public final void removeHauntedBy(final Card c) {
hauntedBy.remove(c);
}
public final Card getHaunting() {
return haunting;
}
public final void setHaunting(final Card c) {
haunting = c;
}
} //end Card class

View File

@@ -692,6 +692,10 @@ public final class CardUtil {
res.setChangedCardTypes(c.getChangedCardTypes());
res.setNewPT(c.getNewPT());
res.setReceivedDamageFromThisTurn(c.getReceivedDamageFromThisTurn());
res.setHaunting(c.getHaunting());
for(Card haunter : c.getHauntedBy()) {
res.addHauntedBy(haunter);
}
return res;
}

View File

@@ -820,7 +820,7 @@ public class MagicStack extends MyObservable {
SpellAbility sa = AllZone.getStack().pop();
AllZone.getPhase().resetPriority(); // ActivePlayer gains priority first after Resolve
Card source = sa.getSourceCard();
final Card source = sa.getSourceCard();
if (hasFizzled(sa, source)) { //Fizzle
// TODO: Spell fizzles, what's the best way to alert player?
@@ -833,6 +833,67 @@ public class MagicStack extends MyObservable {
sa.resolve();
finishResolving(sa, false);
}
if(source.hasStartOfKeyword("Haunt") && !source.isCreature() && AllZone.getZoneOf(source).is(Constant.Zone.Graveyard)) {
CardList creats = AllZoneUtil.getCreaturesInPlay();
if(creats.size() != 0)
{
final Ability haunterDies_Work = new Ability(source,"0") {
@Override
public void resolve() {
AllZone.getGameAction().exile(source);
getTargetCard().addHauntedBy(source);
}
};
haunterDies_Work.setDescription("");
final Input target = new Input() {
private static final long serialVersionUID = 1981791992623774490L;
@Override
public void showMessage() {
AllZone.getDisplay().showMessage("Choose target creature to haunt.");
ButtonUtil.disableAll();
}
@Override
public void selectCard(final Card c, final PlayerZone zone) {
if(!zone.is(Constant.Zone.Battlefield)) {
return;
}
if(CardFactoryUtil.canTarget(source,c))
{
haunterDies_Work.setTargetCard(c);
add(haunterDies_Work);
stop();
}
else
{
AllZone.getDisplay().showMessage("Cannot target this card (Shroud? Protection?).");
}
}
};
if(source.getController().isHuman())
{
AllZone.getInputControl().setInput(target);
}
else
{
//AI choosing what to haunt
CardList oppCreats = creats.getController(AllZone.getHumanPlayer());
if(oppCreats.size() != 0)
{
haunterDies_Work.setTargetCard(CardFactoryUtil.AI_getWorstCreature(oppCreats));
}
else
{
haunterDies_Work.setTargetCard(CardFactoryUtil.AI_getWorstCreature(creats));
}
add(haunterDies_Work);
}
}
}
}

View File

@@ -3,6 +3,7 @@ package forge.card.cardFactory;
import com.esotericsoftware.minlog.Log;
import forge.*;
import forge.Constant.Zone;
import forge.card.abilityFactory.AbilityFactory;
import forge.card.cost.Cost;
import forge.card.mana.ManaCost;
import forge.card.spellability.*;
@@ -4770,6 +4771,137 @@ public class CardFactoryUtil {
card.addSpellAbility(altCostSA);
}
}
if(card.hasStartOfKeyword("Haunt")) {
int hauntPos = card.getKeywordPosition("Haunt");
String[] splitKeyword = card.getKeyword().get(hauntPos).split(":");
String hauntSVarName = splitKeyword[1];
String abilityDescription = splitKeyword[2];
String hauntAbilityDescription = abilityDescription.substring(0,1).toLowerCase() + abilityDescription.substring(1);
String hauntDescription;
if(card.isCreature())
{
hauntDescription = "When " + card.getName() + " enters the battlefield or the creature it haunts dies, " + hauntAbilityDescription;
}
else
{
hauntDescription = "When the creature " + card.getName() + " haunts dies, " + hauntAbilityDescription;
}
card.getKeyword().remove(hauntPos);
//First, create trigger that runs when the haunter dies (if it's a creature)
Trigger haunterDies = forge.card.trigger.TriggerHandler.parseTrigger("Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Static$ True | Secondary$ True | TriggerDescription$ Blank", card, true);
final Ability haunterDies_Work = new Ability(card,"0") {
@Override
public void resolve() {
getTargetCard().addHauntedBy(card);
AllZone.getGameAction().exile(card);
}
};
haunterDies_Work.setDescription(hauntDescription);
final Input target = new Input() {
private static final long serialVersionUID = 1981791992623774490L;
@Override
public void showMessage() {
AllZone.getDisplay().showMessage("Choose target creature to haunt.");
ButtonUtil.disableAll();
}
@Override
public void selectCard(final Card c, final PlayerZone zone) {
if(!zone.is(Constant.Zone.Battlefield)) {
return;
}
if(canTarget(card,c))
{
haunterDies_Work.setTargetCard(c);
AllZone.getStack().add(haunterDies_Work);
stop();
}
else
{
AllZone.getDisplay().showMessage("Cannot target this card (Shroud? Protection?).");
}
}
};
Ability haunterDies_Setup = new Ability(card,"0") {
@Override
public void resolve() {
CardList creats = AllZoneUtil.getCreaturesInPlay();
if(creats.size() == 0)
{
return;
}
//need to do it this way because I don't know quite how to make TriggerHandler respect BeforePayMana.
if(card.getController().isHuman())
{
AllZone.getInputControl().setInput(target);
}
else
{
//AI choosing what to haunt
CardList oppCreats = creats.getController(AllZone.getHumanPlayer());
if(oppCreats.size() != 0)
{
haunterDies_Work.setTargetCard(CardFactoryUtil.AI_getWorstCreature(oppCreats));
}
else
{
haunterDies_Work.setTargetCard(CardFactoryUtil.AI_getWorstCreature(creats));
}
AllZone.getStack().add(haunterDies_Work);
}
}
};
haunterDies.setOverridingAbility(haunterDies_Setup);
//Second, create the trigger that runs when the haunted creature dies
Trigger hauntedDies = forge.card.trigger.TriggerHandler.parseTrigger("Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Creature.HauntedBy | Execute$ " + hauntSVarName + " | TriggerDescription$ " + hauntDescription, card, true);
//Third, create the trigger that runs when the haunting creature enters the battlefield
Trigger haunterETB = forge.card.trigger.TriggerHandler.parseTrigger("Mode$ ChangesZone | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ " + hauntSVarName + " | Secondary$ True | TriggerDescription$ " + hauntDescription, card, true);
//Fourth, create a trigger that removes the haunting status if the haunter leaves the exile
Trigger haunterUnExiled = forge.card.trigger.TriggerHandler.parseTrigger("Mode$ ChangesZone | Origin$ Exile | ValidCard$ Card.Self | Static$ True | Secondary$ True | TriggerDescription$ Blank", card, true);
Ability haunterUnExiled_Work = new Ability(card,"0") {
@Override
public void resolve() {
if(card.getHaunting() != null)
{
card.getHaunting().removeHauntedBy(card);
card.setHaunting(null);
}
}
};
haunterUnExiled.setOverridingAbility(haunterUnExiled_Work);
//Fifth, add all triggers and abilities to the card.
if(card.isCreature()) {
card.addTrigger(haunterETB);
card.addTrigger(haunterDies);
}
else {
AbilityFactory af = new AbilityFactory();
String abString = card.getSVar(hauntSVarName).replace("AB$", "SP$").replace("Cost$ 0", "Cost$ " + card.getManaCost()) + " | SpellDescription$ " + abilityDescription;
SpellAbility sa = af.getAbility(abString, card);
card.addSpellAbility(sa);
}
card.addTrigger(hauntedDies);
card.addTrigger(haunterUnExiled);
}
return card;
}